1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.jdo.impl.enhancer.core;
18
19 import java.util.HashMap;
20 import java.util.ArrayList;
21 import java.util.Iterator;
22 import java.util.Enumeration;
23
24 import org.apache.jdo.impl.enhancer.classfile.AttributeVector;
25 import org.apache.jdo.impl.enhancer.classfile.ClassField;
26 import org.apache.jdo.impl.enhancer.classfile.ClassFile;
27 import org.apache.jdo.impl.enhancer.classfile.CodeAttribute;
28 import org.apache.jdo.impl.enhancer.classfile.ConstClass;
29 import org.apache.jdo.impl.enhancer.classfile.ConstFieldRef;
30 import org.apache.jdo.impl.enhancer.classfile.ConstNameAndType;
31 import org.apache.jdo.impl.enhancer.classfile.ConstUtf8;
32 import org.apache.jdo.impl.enhancer.classfile.ConstantPool;
33 import org.apache.jdo.impl.enhancer.classfile.Descriptor;
34 import org.apache.jdo.impl.enhancer.classfile.ExceptionRange;
35 import org.apache.jdo.impl.enhancer.classfile.ExceptionTable;
36 import org.apache.jdo.impl.enhancer.classfile.ExceptionsAttribute;
37 import org.apache.jdo.impl.enhancer.classfile.Insn;
38 import org.apache.jdo.impl.enhancer.classfile.InsnIInc;
39 import org.apache.jdo.impl.enhancer.classfile.InsnInterfaceInvoke;
40 import org.apache.jdo.impl.enhancer.classfile.InsnLookupSwitch;
41 import org.apache.jdo.impl.enhancer.classfile.InsnTableSwitch;
42 import org.apache.jdo.impl.enhancer.classfile.InsnTarget;
43 import org.apache.jdo.impl.enhancer.classfile.InsnUtils;
44 import org.apache.jdo.impl.enhancer.classfile.VMConstants;
45 import org.apache.jdo.impl.enhancer.util.InternalError;
46 import org.apache.jdo.impl.enhancer.util.Support;
47
48 /***
49 * Helper object to create the generic JDO methods for a class.
50 */
51 class Builder
52 extends Support
53 implements VMConstants, JDOConstants, EnhancerConstants
54 {
55 /***
56 * The augmentation controller for this class.
57 */
58 private final Augmenter augmenter;
59
60 /***
61 * The class analyzer for this class.
62 */
63 private final Analyzer analyzer;
64
65 /***
66 * The classfile to be annotated.
67 */
68 private final ClassFile classFile;
69
70 /***
71 * The class name in VM form.
72 */
73 private final String className;
74
75 /***
76 * The class name in user ('.' delimited) form.
77 */
78 private final String userClassName;
79
80 /***
81 * The classfile's constant pool.
82 */
83 private final ConstantPool pool;
84
85 /***
86 * Repository for the enhancement options.
87 */
88 private final Environment env;
89
90 /***
91 * The constant utf8 string for the CodeAttribute.
92 */
93 private ConstUtf8 codeAttributeUtf8;
94 /***
95
96 * The constant field ref for the jdoStateManager field.
97 */
98 private ConstFieldRef jdoStateManagerFieldRef;
99
100 /***
101 * The constant field ref for the jdoFlags field.
102 */
103 private ConstFieldRef jdoFlagsFieldRef;
104
105 /***
106 * The constant field ref for the jdoFieldNames field.
107 */
108 private ConstFieldRef jdoFieldNamesFieldRef;
109
110 /***
111 * The constant field ref for the jdoFieldTypes field.
112 */
113 private ConstFieldRef jdoFieldTypesFieldRef;
114
115 /***
116 * The constant field ref for the jdoFieldFlags field.
117 */
118 private ConstFieldRef jdoFieldFlagsFieldRef;
119
120 /***
121 * The constant field ref for the jdoPersistenceCapableSuperclass field.
122 */
123 private ConstFieldRef jdoPersistenceCapableSuperclassFieldRef;
124
125 /***
126 * The constant field refs for the annotated fields sorted by their
127 * relative field index.
128 */
129 private ConstFieldRef[] annotatedFieldRefs;
130
131 /***
132 * The constant field refs for the key fields sorted by
133 * ascending relative field index.
134 */
135 private ConstFieldRef[] keyFieldRefs;
136
137 /***
138 * The constant field refs on the key class for the key fields sorted by
139 * ascending relative field index.
140 */
141 private ConstFieldRef[] keyClassKeyFieldRefs;
142
143 /***
144 * Constructor.
145 */
146 public Builder(Analyzer analyzer,
147 Augmenter augmenter,
148 Environment env)
149 {
150 affirm(analyzer != null);
151 affirm(augmenter != null);
152 affirm(env != null);
153
154 this.analyzer = analyzer;
155 this.augmenter = augmenter;
156 this.classFile = analyzer.getClassFile();
157 this.className = classFile.classNameString();
158 this.userClassName = classFile.userClassName();
159 this.pool = classFile.pool();
160 this.env = env;
161
162 affirm(classFile != null);
163 affirm(className != null);
164 affirm(userClassName != null);
165 affirm(pool != null);
166 }
167
168
169
170
171
172 /***
173 * Holder object for returning a size info from a code generation method.
174 */
175 static private class SizeHolder
176 {
177 int size;
178 }
179
180 /***
181 * Returns the minimum of two numbers.
182 */
183 static private int min(int i, int j) {
184 return (i < j ? i : j);
185 }
186
187 /***
188 * Returns the maximum of two numbers.
189 */
190 static private int max(int i, int j) {
191 return (i < j ? j : i);
192 }
193
194 /***
195 * Count the size of the arguments to an invokevirtual method call.
196 */
197 static private int countMethodArgWords(String sig)
198 {
199
200 return Descriptor.countMethodArgWords(sig) + 1;
201 }
202
203 /***
204 * Returns the utf8 string for the CodeAttribute.
205 */
206 private ConstUtf8 getCodeAttributeUtf8()
207 {
208
209 if (codeAttributeUtf8 == null) {
210 codeAttributeUtf8 = pool.addUtf8(CodeAttribute.expectedAttrName);
211 }
212 return codeAttributeUtf8;
213 }
214
215 /***
216 * Returns the constant field ref for the jdoStateManager field.
217 */
218 private ConstFieldRef getjdoStateManagerFieldRef()
219 {
220
221 final String pcRootName = analyzer.getPCRootClassName();
222 affirm(pcRootName != null);
223
224
225 if (jdoStateManagerFieldRef == null) {
226 jdoStateManagerFieldRef
227 = pool.addFieldRef(pcRootName,
228 JDO_PC_jdoStateManager_Name,
229 JDO_PC_jdoStateManager_Sig);
230 }
231 return jdoStateManagerFieldRef;
232 }
233
234 /***
235 * Returns the constant field ref for the jdoFlags field.
236 */
237 private ConstFieldRef getjdoFlagsFieldRef()
238 {
239
240 final String pcRootName = analyzer.getPCRootClassName();
241 affirm(pcRootName != null);
242
243
244 if (jdoFlagsFieldRef == null) {
245 jdoFlagsFieldRef
246 = pool.addFieldRef(pcRootName,
247 JDO_PC_jdoFlags_Name,
248 JDO_PC_jdoFlags_Sig);
249 }
250 return jdoFlagsFieldRef;
251 }
252
253 /***
254 * Returns the constant field ref for the jdoFieldNames field.
255 */
256 private ConstFieldRef getjdoFieldNamesFieldRef()
257 {
258
259 if (jdoFieldNamesFieldRef == null) {
260 jdoFieldNamesFieldRef
261 = pool.addFieldRef(className,
262 JDO_PC_jdoFieldNames_Name,
263 JDO_PC_jdoFieldNames_Sig);
264 }
265 return jdoFieldNamesFieldRef;
266 }
267
268 /***
269 * Returns the constant field ref for the jdoFieldTypes field.
270 */
271 private ConstFieldRef getjdoFieldTypesFieldRef()
272 {
273
274 if (jdoFieldTypesFieldRef == null) {
275 jdoFieldTypesFieldRef
276 = pool.addFieldRef(className,
277 JDO_PC_jdoFieldTypes_Name,
278 JDO_PC_jdoFieldTypes_Sig);
279 }
280 return jdoFieldTypesFieldRef;
281 }
282
283 /***
284 * Returns the constant field ref for the jdoFieldFlags field.
285 */
286 private ConstFieldRef getjdoFieldFlagsFieldRef()
287 {
288
289 if (jdoFieldFlagsFieldRef == null) {
290 jdoFieldFlagsFieldRef
291 = pool.addFieldRef(className,
292 JDO_PC_jdoFieldFlags_Name,
293 JDO_PC_jdoFieldFlags_Sig);
294 }
295 return jdoFieldFlagsFieldRef;
296 }
297
298 /***
299 * Returns the constant field ref for the jdoPersistenceCapableSuperclass field.
300 */
301 private ConstFieldRef getjdoPersistenceCapableSuperclassFieldRef()
302 {
303
304 if (jdoPersistenceCapableSuperclassFieldRef == null) {
305 jdoPersistenceCapableSuperclassFieldRef
306 = pool.addFieldRef(className,
307 JDO_PC_jdoPersistenceCapableSuperclass_Name,
308 JDO_PC_jdoPersistenceCapableSuperclass_Sig);
309 }
310 return jdoPersistenceCapableSuperclassFieldRef;
311 }
312
313 /***
314 * Returns the constant field refs for the annotated fields.
315 */
316 private ConstFieldRef[] getAnnotatedFieldRefs()
317 {
318
319 if (annotatedFieldRefs == null) {
320 final int annotatedFieldCount = analyzer.getAnnotatedFieldCount();
321 final String[] annotatedFieldNames
322 = analyzer.getAnnotatedFieldNames();
323 final String[] annotatedFieldSigs
324 = analyzer.getAnnotatedFieldSigs();
325 affirm(annotatedFieldNames.length == annotatedFieldCount);
326 affirm(annotatedFieldSigs.length == annotatedFieldCount);
327
328
329 annotatedFieldRefs = new ConstFieldRef[annotatedFieldCount];
330 for (int i = 0; i < annotatedFieldCount; i++) {
331 final String name = annotatedFieldNames[i];
332 final String sig = annotatedFieldSigs[i];
333 annotatedFieldRefs[i] = pool.addFieldRef(className, name, sig);
334 affirm(annotatedFieldRefs[i] != null);
335 }
336 }
337 affirm(annotatedFieldRefs != null);
338 return annotatedFieldRefs;
339 }
340
341 /***
342 * Returns the constant field refs for the key fields.
343 */
344 private ConstFieldRef[] getKeyFieldRefs()
345 {
346
347 if (keyFieldRefs == null) {
348 final ConstFieldRef[] annotatedFieldRefs = getAnnotatedFieldRefs();
349 final int keyFieldCount = analyzer.getKeyFieldCount();
350 final int[] keyFieldIndexes = analyzer.getKeyFieldIndexes();
351 affirm(keyFieldIndexes.length == keyFieldCount);
352
353
354 keyFieldRefs = new ConstFieldRef[keyFieldCount];
355 for (int i = 0; i < keyFieldCount; i++) {
356 keyFieldRefs[i] = annotatedFieldRefs[keyFieldIndexes[i]];
357 affirm(keyFieldRefs[i] != null);
358 }
359 }
360 affirm(keyFieldRefs != null);
361 return keyFieldRefs;
362 }
363
364 /***
365 * Returns the constant field refs for the key fields of the key class.
366 */
367 private ConstFieldRef[] getKeyClassKeyFieldRefs()
368 {
369
370 if (keyClassKeyFieldRefs == null) {
371 final String keyClassName = analyzer.getKeyClassName();
372 affirm(keyClassName != null);
373 final int keyFieldCount = analyzer.getKeyFieldCount();
374 final ConstFieldRef[] keyFieldRefs = getKeyFieldRefs();
375 affirm(keyFieldRefs.length == keyFieldCount);
376
377
378 keyClassKeyFieldRefs = new ConstFieldRef[keyFieldCount];
379 for (int i = 0; i < keyFieldCount; i++) {
380 final ConstNameAndType nt = keyFieldRefs[i].nameAndType();
381 final String name = nt.name().asString();
382 final String sig = nt.signature().asString();
383 keyClassKeyFieldRefs[i]
384 = pool.addFieldRef(keyClassName, name, sig);
385 affirm(keyClassKeyFieldRefs[i] != null);
386 }
387 }
388 affirm(keyClassKeyFieldRefs != null);
389 return keyClassKeyFieldRefs;
390 }
391
392 /***
393 * Adds the code for throwing a IllegalArgumentException.
394 */
395 private Insn appendThrowJavaException(Insn insn,
396 String exceptionName,
397 String exceptionText)
398 {
399 affirm(insn != null);
400 affirm(exceptionName != null);
401 affirm(exceptionText != null);
402
403
404 final String exceptionCtorName
405 = NameHelper.constructorName();
406 final String exceptionCtorSig
407 = NameHelper.constructorSig(JAVA_String_Sig);
408 insn = insn.append(
409 Insn.create(opc_new,
410 pool.addClass(exceptionName)));
411 insn = insn.append(Insn.create(opc_dup));
412 insn = insn.append(
413 InsnUtils.stringConstant(
414 exceptionText, pool));
415 insn = insn.append(
416 Insn.create(opc_invokespecial,
417 pool.addMethodRef(
418 exceptionName,
419 exceptionCtorName,
420 exceptionCtorSig)));
421 insn = insn.append(Insn.create(opc_athrow));
422
423 affirm(insn != null);
424 return insn;
425 }
426
427 /***
428 * Adds the code for handling if jdoStateManager field is null.
429 */
430 private Insn appendCheckStateManager(Insn insn,
431 int argStart,
432 String exceptionName,
433 String exceptionText)
434 {
435 affirm(insn != null);
436 affirm(exceptionName != null);
437 affirm(exceptionText != null);
438
439
440 final InsnTarget body = new InsnTarget();
441 insn = insn.append(InsnUtils.aLoad(argStart, pool));
442 insn = insn.append(
443 Insn.create(
444 opc_getfield,
445 getjdoStateManagerFieldRef()));
446 insn = insn.append(Insn.create(opc_ifnonnull, body));
447 insn = appendThrowJavaException(insn, exceptionName, exceptionText);
448 insn = insn.append(body);
449
450 affirm(insn != null);
451 return insn;
452 }
453
454 /***
455 * Adds the code for handling if an argument is null.
456 */
457 private Insn appendCheckVarNonNull(Insn insn,
458 int argStart,
459 String exceptionName,
460 String exceptionText)
461 {
462 affirm(insn != null);
463 affirm(exceptionName != null);
464 affirm(exceptionText != null);
465
466
467 final InsnTarget body = new InsnTarget();
468 insn = insn.append(InsnUtils.aLoad(argStart, pool));
469 insn = insn.append(Insn.create(opc_ifnonnull, body));
470 insn = appendThrowJavaException(insn, exceptionName, exceptionText);
471 insn = insn.append(body);
472
473 affirm(insn != null);
474 return insn;
475 }
476
477 /***
478 * Adds the code for handling if an argument is instance of a class.
479 */
480 private Insn appendCheckVarInstanceOf(Insn insn,
481 int argStart,
482 ConstClass constClass,
483 String exceptionName,
484 String exceptionText)
485 {
486 affirm(insn != null);
487 affirm(constClass != null);
488 affirm(exceptionName != null);
489 affirm(exceptionText != null);
490
491
492 final InsnTarget body = new InsnTarget();
493 insn = insn.append(InsnUtils.aLoad(argStart, pool));
494 insn = insn.append(Insn.create(opc_instanceof, constClass));
495 insn = insn.append(Insn.create(opc_ifne, body));
496 insn = appendThrowJavaException(insn, exceptionName, exceptionText);
497 insn = insn.append(body);
498
499 affirm(insn != null);
500 return insn;
501 }
502
503
504
505 /***
506 * Builds an empty method (for debugging).
507 *
508 * public void XXX() {
509 * }
510 */
511 public void addNullMethod(final String methodName,
512 final String methodSig,
513 final int accessFlags)
514 {
515
516 affirm((accessFlags & ACCStatic) == 0);
517 final ExceptionsAttribute exceptAttr = null;
518
519
520 final InsnTarget begin = new InsnTarget();
521 Insn insn = begin;
522
523
524 insn = insn.append(Insn.create(opc_return));
525
526 final CodeAttribute codeAttr
527 = new CodeAttribute(getCodeAttributeUtf8(),
528 0,
529 countMethodArgWords(methodSig),
530 begin,
531 new ExceptionTable(),
532 new AttributeVector());
533 augmenter.addMethod(methodName, methodSig, accessFlags,
534 codeAttr, exceptAttr);
535 }
536
537
538
539
540
541 /***
542 * Build the jdoSetStateManager method for the class.
543 *
544 * public final synchronized void jdoReplaceStateManager(javax.jdo.StateManager sm)
545 * {
546 * final javax.jdo.StateManager s = this.jdoStateManager;
547 * if (s != null) {
548 * this.jdoStateManager = s.replacingStateManager(this, sm);
549 * return;
550 * }
551 * // throws exception if not authorized
552 * JDOImplHelper.checkAuthorizedStateManager(sm);
553 * this.jdoStateManager = sm;
554 * this.jdoFlags = LOAD_REQUIRED;
555 * }
556 */
557 public void addJDOReplaceStateManager()
558 {
559 final String methodName = JDO_PC_jdoReplaceStateManager_Name;
560 final String methodSig = JDO_PC_jdoReplaceStateManager_Sig;
561 final int accessFlags = JDO_PC_jdoReplaceStateManager_Mods;
562 final ExceptionsAttribute exceptAttr = null;
563
564
565
566
567 final InsnTarget begin = new InsnTarget();
568 Insn insn = begin;
569
570
571 insn = insn.append(Insn.create(opc_aload_0));
572 insn = insn.append(
573 Insn.create(
574 opc_getfield,
575 getjdoStateManagerFieldRef()));
576 insn = insn.append(Insn.create(opc_astore_2));
577
578
579 final InsnTarget check = new InsnTarget();
580 insn = insn.append(Insn.create(opc_aload_2));
581 insn = insn.append(Insn.create(opc_ifnull, check));
582
583
584 insn = insn.append(Insn.create(opc_aload_0));
585
586
587 insn = insn.append(Insn.create(opc_aload_2));
588 insn = insn.append(Insn.create(opc_aload_0));
589 insn = insn.append(Insn.create(opc_aload_1));
590 insn = insn.append(
591 new InsnInterfaceInvoke(
592 pool.addInterfaceMethodRef(
593 JDO_StateManager_Path,
594 JDO_SM_replacingStateManager_Name,
595 JDO_SM_replacingStateManager_Sig),
596 countMethodArgWords(JDO_SM_replacingStateManager_Sig)));
597
598
599 insn = insn.append(
600 Insn.create(opc_putfield,
601 getjdoStateManagerFieldRef()));
602 insn = insn.append(Insn.create(opc_return));
603
604
605 insn = insn.append(check);
606 insn = insn.append(Insn.create(opc_aload_1));
607 insn = insn.append(
608 Insn.create(opc_invokestatic,
609 pool.addMethodRef(
610 JDO_JDOImplHelper_Path,
611 JDO_JDOImplHelper_checkAuthorizedStateManager_Name,
612 JDO_JDOImplHelper_checkAuthorizedStateManager_Sig)));
613
614
615 insn = insn.append(Insn.create(opc_aload_0));
616 insn = insn.append(Insn.create(opc_aload_1));
617 insn = insn.append(
618 Insn.create(opc_putfield,
619 getjdoStateManagerFieldRef()));
620
621
622 insn = insn.append(Insn.create(opc_aload_0));
623 insn = insn.append(Insn.create(opc_iconst_1));
624 insn = insn.append(
625 Insn.create(opc_putfield,
626 getjdoFlagsFieldRef()));
627
628
629 insn = insn.append(Insn.create(opc_return));
630
631 final CodeAttribute codeAttr
632 = new CodeAttribute(getCodeAttributeUtf8(),
633 4,
634 3,
635 begin,
636 new ExceptionTable(),
637 new AttributeVector());
638 augmenter.addMethod(methodName, methodSig, accessFlags,
639 codeAttr, exceptAttr);
640 }
641
642
643
644 /***
645 * Build the jdoReplaceFlags method for the class.
646 *
647 * public final void jdoReplaceFlags()
648 * {
649 * final StateManager sm = this.jdoStateManager;
650 * if (sm != null) {
651 * this.jdoFlags = sm.replacingFlags(this);
652 * }
653 * }
654 */
655 public void addJDOReplaceFlags()
656 {
657 final String methodName = JDO_PC_jdoReplaceFlags_Name;
658 final String methodSig = JDO_PC_jdoReplaceFlags_Sig;
659 final int accessFlags = JDO_PC_jdoReplaceFlags_Mods;
660 final ExceptionsAttribute exceptAttr = null;
661
662
663 final InsnTarget begin = new InsnTarget();
664 Insn insn = begin;
665
666
667 insn = insn.append(Insn.create(opc_aload_0));
668 insn = insn.append(
669 Insn.create(
670 opc_getfield,
671 getjdoStateManagerFieldRef()));
672 insn = insn.append(Insn.create(opc_astore_1));
673
674
675 final InsnTarget end = new InsnTarget();
676 insn = insn.append(Insn.create(opc_aload_1));
677 insn = insn.append(Insn.create(opc_ifnull, end));
678
679
680 insn = insn.append(Insn.create(opc_aload_0));
681
682
683 insn = insn.append(Insn.create(opc_aload_1));
684 insn = insn.append(Insn.create(opc_aload_0));
685 insn = insn.append(
686 new InsnInterfaceInvoke(
687 pool.addInterfaceMethodRef(
688 JDO_StateManager_Path,
689 JDO_SM_replacingFlags_Name,
690 JDO_SM_replacingFlags_Sig),
691 countMethodArgWords(JDO_SM_replacingFlags_Sig)));
692
693
694 insn = insn.append(
695 Insn.create(opc_putfield,
696 getjdoFlagsFieldRef()));
697
698
699 insn = insn.append(end);
700 insn = insn.append(Insn.create(opc_return));
701
702 final CodeAttribute codeAttr
703 = new CodeAttribute(getCodeAttributeUtf8(),
704 3,
705 2,
706 begin,
707 new ExceptionTable(),
708 new AttributeVector());
709 augmenter.addMethod(methodName, methodSig, accessFlags,
710 codeAttr, exceptAttr);
711 }
712
713
714
715 /***
716 * Build the jdoMakeDirty method for the class.
717 *
718 * public final void jdoMakeDirty(java.lang.String fieldname)
719 * {
720 * final javax.jdo.StateManager sm = this.jdoStateManager;
721 * if (sm != null) {
722 * sm.makeDirty(this, fieldname);
723 * }
724 * }
725 */
726 public void addJDOMakeDirtyMethod()
727 {
728 final String methodName = JDO_PC_jdoMakeDirty_Name;
729 final String methodSig = JDO_PC_jdoMakeDirty_Sig;
730 final int accessFlags = JDO_PC_jdoMakeDirty_Mods;
731 final ExceptionsAttribute exceptAttr = null;
732
733
734 final InsnTarget begin = new InsnTarget();
735 Insn insn = begin;
736
737
738 insn = insn.append(Insn.create(opc_aload_0));
739 insn = insn.append(
740 Insn.create(
741 opc_getfield,
742 getjdoStateManagerFieldRef()));
743 insn = insn.append(Insn.create(opc_astore_2));
744
745
746 final InsnTarget end = new InsnTarget();
747 insn = insn.append(Insn.create(opc_aload_2));
748 insn = insn.append(Insn.create(opc_ifnull, end));
749
750
751 insn = insn.append(Insn.create(opc_aload_2));
752 insn = insn.append(Insn.create(opc_aload_0));
753 insn = insn.append(Insn.create(opc_aload_1));
754 insn = insn.append(
755 new InsnInterfaceInvoke(
756 pool.addInterfaceMethodRef(
757 JDO_StateManager_Path,
758 JDO_SM_makeDirty_Name,
759 JDO_SM_makeDirty_Sig),
760 countMethodArgWords(JDO_SM_makeDirty_Sig)));
761
762
763 insn = insn.append(end);
764 insn = insn.append(Insn.create(opc_return));
765
766 final CodeAttribute codeAttr
767 = new CodeAttribute(getCodeAttributeUtf8(),
768 3,
769 3,
770 begin,
771 new ExceptionTable(),
772 new AttributeVector());
773 augmenter.addMethod(methodName, methodSig, accessFlags,
774 codeAttr, exceptAttr);
775 }
776
777
778
779 /***
780 * Build the jdoPreSerialize method for the class.
781 *
782 * protected final void jdoPreSerialize()
783 * {
784 * final javax.jdo.StateManager sm = this.jdoStateManager;
785 * if (sm != null) {
786 * sm.preSerialize(this);
787 * }
788 * }
789 */
790 public void addJDOPreSerializeMethod()
791 {
792 final String methodName = JDO_PC_jdoPreSerialize_Name;
793 final String methodSig = JDO_PC_jdoPreSerialize_Sig;
794 final int accessFlags = JDO_PC_jdoPreSerialize_Mods;
795 final ExceptionsAttribute exceptAttr = null;
796
797
798 final InsnTarget begin = new InsnTarget();
799 Insn insn = begin;
800
801
802 insn = insn.append(Insn.create(opc_aload_0));
803 insn = insn.append(
804 Insn.create(
805 opc_getfield,
806 getjdoStateManagerFieldRef()));
807 insn = insn.append(Insn.create(opc_astore_1));
808
809
810 final InsnTarget end = new InsnTarget();
811 insn = insn.append(Insn.create(opc_aload_1));
812 insn = insn.append(Insn.create(opc_ifnull, end));
813
814
815 insn = insn.append(Insn.create(opc_aload_1));
816 insn = insn.append(Insn.create(opc_aload_0));
817 insn = insn.append(
818 new InsnInterfaceInvoke(
819 pool.addInterfaceMethodRef(
820 JDO_StateManager_Path,
821 JDO_SM_preSerialize_Name,
822 JDO_SM_preSerialize_Sig),
823 countMethodArgWords(JDO_SM_preSerialize_Sig)));
824
825
826 insn = insn.append(end);
827 insn = insn.append(Insn.create(opc_return));
828
829 final CodeAttribute codeAttr
830 = new CodeAttribute(getCodeAttributeUtf8(),
831 2,
832 2,
833 begin,
834 new ExceptionTable(),
835 new AttributeVector());
836 augmenter.addMethod(methodName, methodSig, accessFlags,
837 codeAttr, exceptAttr);
838 }
839
840
841
842 /***
843 * Build the writeObject method for the class.
844 *
845 * private void writeObject(java.io.ObjectOutputStream out)
846 * throws java.io.IOException
847 * {
848 * jdoPreSerialize();
849 * out.defaultWriteObject();
850 * }
851 */
852 public void addWriteObjectMethod()
853 {
854 final String methodName = JAVA_Object_writeObject_Name;
855 final String methodSig = JAVA_Object_writeObject_Sig;
856 final int accessFlags = JAVA_Object_writeObject_Mods;
857 final ExceptionsAttribute exceptAttr
858 = new ExceptionsAttribute(
859 pool.addUtf8(ExceptionsAttribute.expectedAttrName),
860 pool.addClass("java/io/IOException"));
861
862
863 final InsnTarget begin = new InsnTarget();
864 Insn insn = begin;
865
866
867 insn = insn.append(Insn.create(opc_aload_0));
868 insn = insn.append(
869 Insn.create(opc_invokevirtual,
870 pool.addMethodRef(
871 className,
872 JDO_PC_jdoPreSerialize_Name,
873 JDO_PC_jdoPreSerialize_Sig)));
874
875
876 insn = insn.append(Insn.create(opc_aload_1));
877 insn = insn.append(
878 Insn.create(opc_invokevirtual,
879 pool.addMethodRef(
880 JAVA_ObjectOutputStream_Path,
881 JAVA_ObjectOutputStream_defaultWriteObject_Name,
882 JDO_PC_jdoPreSerialize_Sig)));
883
884
885 insn = insn.append(Insn.create(opc_return));
886
887 final CodeAttribute codeAttr
888 = new CodeAttribute(getCodeAttributeUtf8(),
889 1,
890 2,
891 begin,
892 new ExceptionTable(),
893 new AttributeVector());
894 augmenter.addMethod(methodName, methodSig, accessFlags,
895 codeAttr, exceptAttr);
896
897 }
898
899
900
901 /***
902 * Adds a call to jdoPreSerialize as first statement to the existing method.
903 */
904 public void addJDOPreSerializeCall(String methodName, String methodSig)
905 {
906 final ExceptionsAttribute exceptAttr = null;
907
908
909 final InsnTarget begin = new InsnTarget();
910 Insn insn = begin;
911
912
913 insn = insn.append(Insn.create(opc_aload_0));
914 insn = insn.append(
915 Insn.create(opc_invokevirtual,
916 pool.addMethodRef(
917 className,
918 JDO_PC_jdoPreSerialize_Name,
919 JDO_PC_jdoPreSerialize_Sig)));
920
921
922 final CodeAttribute codeAttr
923 = new CodeAttribute(getCodeAttributeUtf8(),
924 1,
925 0,
926 begin,
927 new ExceptionTable(),
928 new AttributeVector());
929
930 augmenter.prependMethod(methodName, methodSig, codeAttr, exceptAttr);
931 }
932
933
934
935 /***
936 * Build an interrogative method for the class.
937 */
938 public void addJDOIsPersistentMethod()
939 {
940 addJDOInterrogativeMethod(JDO_PC_jdoIsPersistent_Name,
941 JDO_PC_jdoIsPersistent_Sig,
942 JDO_PC_jdoIsPersistent_Mods,
943 JDO_SM_isPersistent_Name,
944 JDO_SM_isPersistent_Sig);
945 }
946
947 /***
948 * Build an interrogative method for the class.
949 */
950 public void addJDOIsTransactionalMethod()
951 {
952 addJDOInterrogativeMethod(JDO_PC_jdoIsTransactional_Name,
953 JDO_PC_jdoIsTransactional_Sig,
954 JDO_PC_jdoIsTransactional_Mods,
955 JDO_SM_isTransactional_Name,
956 JDO_SM_isTransactional_Sig);
957 }
958
959 /***
960 * Build an interrogative method for the class.
961 */
962 public void addJDOIsNewMethod()
963 {
964 addJDOInterrogativeMethod(JDO_PC_jdoIsNew_Name,
965 JDO_PC_jdoIsNew_Sig,
966 JDO_PC_jdoIsNew_Mods,
967 JDO_SM_isNew_Name,
968 JDO_SM_isNew_Sig);
969 }
970
971 /***
972 * Build an interrogative method for the class.
973 */
974 public void addJDOIsDeletedMethod()
975 {
976 addJDOInterrogativeMethod(JDO_PC_jdoIsDeleted_Name,
977 JDO_PC_jdoIsDeleted_Sig,
978 JDO_PC_jdoIsDeleted_Mods,
979 JDO_SM_isDeleted_Name,
980 JDO_SM_isDeleted_Sig);
981 }
982
983 /***
984 * Build an interrogative method for the class.
985 */
986 public void addJDOIsDirtyMethod()
987 {
988 addJDOInterrogativeMethod(JDO_PC_jdoIsDirty_Name,
989 JDO_PC_jdoIsDirty_Sig,
990 JDO_PC_jdoIsDirty_Mods,
991 JDO_SM_isDirty_Name,
992 JDO_SM_isDirty_Sig);
993 }
994
995 /***
996 * Build an interrogative method for the class.
997 */
998 public void addJDOIsDetachedMethod()
999 {
1000
1001 addNotYetImplementedMethod(JDO_PC_jdoIsDetached_Name,
1002 JDO_PC_jdoIsDetached_Sig,
1003 JDO_PC_jdoIsDetached_Mods);
1004 }
1005
1006 /***
1007 * Build an interrogative method named methodName for the class.
1008 *
1009 * public boolean isXXX() {
1010 * final StateManager sm = this.jdoStateManager;
1011 * if (sm == null)
1012 * return false;
1013 * return sm.isXXXX(this);
1014 * }
1015 */
1016 private void addJDOInterrogativeMethod(final String methodName,
1017 final String methodSig,
1018 final int accessFlags,
1019 final String delegateName,
1020 final String delegateSig)
1021 {
1022 final ExceptionsAttribute exceptAttr = null;
1023
1024
1025 final InsnTarget begin = new InsnTarget();
1026 Insn insn = begin;
1027
1028
1029 insn = insn.append(Insn.create(opc_aload_0));
1030 insn = insn.append(
1031 Insn.create(
1032 opc_getfield,
1033 getjdoStateManagerFieldRef()));
1034 insn = insn.append(Insn.create(opc_astore_1));
1035
1036
1037 InsnTarget noncall = new InsnTarget();
1038 insn = insn.append(Insn.create(opc_aload_1));
1039 insn = insn.append(Insn.create(opc_ifnull, noncall));
1040
1041
1042 insn = insn.append(Insn.create(opc_aload_1));
1043 insn = insn.append(Insn.create(opc_aload_0));
1044 insn = insn.append(
1045 new InsnInterfaceInvoke(
1046 pool.addInterfaceMethodRef(
1047 JDO_StateManager_Path,
1048 delegateName,
1049 delegateSig),
1050 countMethodArgWords(delegateSig)));
1051 insn = insn.append(Insn.create(opc_ireturn));
1052
1053
1054 insn = insn.append(noncall);
1055 insn = insn.append(Insn.create(opc_iconst_0));
1056
1057
1058 insn = insn.append(Insn.create(opc_ireturn));
1059
1060 final CodeAttribute codeAttr
1061 = new CodeAttribute(getCodeAttributeUtf8(),
1062 2,
1063 2,
1064 begin,
1065 new ExceptionTable(),
1066 new AttributeVector());
1067 augmenter.addMethod(methodName, methodSig, accessFlags,
1068 codeAttr, exceptAttr);
1069 }
1070
1071
1072
1073 /***
1074 * Build an object query method for the class.
1075 */
1076 public void addJDOGetPersistenceManagerMethod()
1077 {
1078 addJDOObjectQueryMethod(JDO_PC_jdoGetPersistenceManager_Name,
1079 JDO_PC_jdoGetPersistenceManager_Sig,
1080 JDO_PC_jdoGetPersistenceManager_Mods,
1081 JDO_SM_getPersistenceManager_Name,
1082 JDO_SM_getPersistenceManager_Sig);
1083 }
1084
1085 /***
1086 * Build an object query method for the class.
1087 */
1088 public void addJDOGetObjectIdMethod()
1089 {
1090 addJDOObjectQueryMethod(JDO_PC_jdoGetObjectId_Name,
1091 JDO_PC_jdoGetObjectId_Sig,
1092 JDO_PC_jdoGetObjectId_Mods,
1093 JDO_SM_getObjectId_Name,
1094 JDO_SM_getObjectId_Sig);
1095 }
1096
1097 /***
1098 * Build an object query method for the class.
1099 */
1100 public void addJDOGetTransactionalObjectIdMethod()
1101 {
1102 addJDOObjectQueryMethod(JDO_PC_jdoGetTransactionalObjectId_Name,
1103 JDO_PC_jdoGetTransactionalObjectId_Sig,
1104 JDO_PC_jdoGetTransactionalObjectId_Mods,
1105 JDO_SM_getTransactionalObjectId_Name,
1106 JDO_SM_getTransactionalObjectId_Sig);
1107 }
1108
1109 /***
1110 * Build an object query method for the class.
1111 */
1112 public void addJDOGetVersionMethod()
1113 {
1114
1115 addNotYetImplementedMethod(JDO_PC_jdoGetVersion_Name,
1116 JDO_PC_jdoGetVersion_Sig,
1117 JDO_PC_jdoGetVersion_Mods);
1118 }
1119
1120 /***
1121 * Build an object query method for the class.
1122 *
1123 * public final XXX jdoGetYYY()
1124 * {
1125 * final javax.jdo.StateManager sm = this.jdoStateManager;
1126 * if (sm != null) {
1127 * return sm.getYYY(this);
1128 * }
1129 * return null;
1130 * }
1131 */
1132 private void addJDOObjectQueryMethod(final String methodName,
1133 final String methodSig,
1134 final int accessFlags,
1135 final String delegateName,
1136 final String delegateSig)
1137 {
1138 final ExceptionsAttribute exceptAttr = null;
1139
1140
1141 final InsnTarget begin = new InsnTarget();
1142 Insn insn = begin;
1143
1144
1145 insn = insn.append(Insn.create(opc_aload_0));
1146 insn = insn.append(
1147 Insn.create(
1148 opc_getfield,
1149 getjdoStateManagerFieldRef()));
1150 insn = insn.append(Insn.create(opc_astore_1));
1151
1152
1153 InsnTarget noncall = new InsnTarget();
1154 insn = insn.append(Insn.create(opc_aload_1));
1155 insn = insn.append(Insn.create(opc_ifnull, noncall));
1156
1157
1158 insn = insn.append(Insn.create(opc_aload_1));
1159 insn = insn.append(Insn.create(opc_aload_0));
1160 insn = insn.append(
1161 new InsnInterfaceInvoke(
1162 pool.addInterfaceMethodRef(
1163 JDO_StateManager_Path,
1164 delegateName,
1165 delegateSig),
1166 countMethodArgWords(delegateSig)));
1167 insn = insn.append(Insn.create(opc_areturn));
1168
1169
1170 insn = insn.append(noncall);
1171 insn = insn.append(Insn.create(opc_aconst_null));
1172
1173
1174 insn = insn.append(Insn.create(opc_areturn));
1175
1176 final CodeAttribute codeAttr
1177 = new CodeAttribute(getCodeAttributeUtf8(),
1178 2,
1179 2,
1180 begin,
1181 new ExceptionTable(),
1182 new AttributeVector());
1183 augmenter.addMethod(methodName, methodSig, accessFlags,
1184 codeAttr, exceptAttr);
1185 }
1186
1187
1188
1189 /***
1190 * Build the jdoArrayArgumentIteration method for the class.
1191 */
1192 public void addJDOProvideFieldsMethod()
1193 {
1194 addJDOArrayArgumentIterationMethod(JDO_PC_jdoProvideFields_Name,
1195 JDO_PC_jdoProvideFields_Sig,
1196 JDO_PC_jdoProvideFields_Mods,
1197 JDO_PC_jdoProvideField_Name,
1198 JDO_PC_jdoProvideField_Sig);
1199 }
1200
1201 /***
1202 * Build the jdoArrayArgumentIteration method for the class.
1203 */
1204 public void addJDOReplaceFieldsMethod()
1205 {
1206 addJDOArrayArgumentIterationMethod(JDO_PC_jdoReplaceFields_Name,
1207 JDO_PC_jdoReplaceFields_Sig,
1208 JDO_PC_jdoReplaceFields_Mods,
1209 JDO_PC_jdoReplaceField_Name,
1210 JDO_PC_jdoReplaceField_Sig);
1211 }
1212
1213 /***
1214 * Build the jdoArrayArgumentIteration method for the class.
1215 *
1216 * public final void jdoXXXFields(int[] fieldnumbers)
1217 * {
1218 * final int n = fieldnumbers.length;
1219 * for (int i = 0; i < n; i++) {
1220 * this.jdoXXXField(fieldnumbers[i]);
1221 * }
1222 * }
1223 */
1224 public void addJDOArrayArgumentIterationMethod(final String methodName,
1225 final String methodSig,
1226 final int accessFlags,
1227 final String delegateName,
1228 final String delegateSig)
1229 {
1230 final ExceptionsAttribute exceptAttr = null;
1231
1232
1233 final InsnTarget begin = new InsnTarget();
1234 Insn insn = begin;
1235
1236
1237 insn = appendCheckVarNonNull(insn, 1,
1238 JAVA_IllegalArgumentException_Path,
1239 "arg1");
1240
1241
1242 insn = insn.append(Insn.create(opc_aload_1));
1243 insn = insn.append(Insn.create(opc_arraylength));
1244 insn = insn.append(Insn.create(opc_istore_2));
1245
1246
1247 final InsnTarget loopcheck = new InsnTarget();
1248 insn = insn.append(Insn.create(opc_iconst_0));
1249 insn = insn.append(Insn.create(opc_istore_3));
1250 insn = insn.append(Insn.create(opc_goto, loopcheck));
1251
1252
1253 final InsnTarget loopbody = new InsnTarget();
1254 insn = insn.append(loopbody);
1255 insn = insn.append(Insn.create(opc_aload_0));
1256
1257
1258 insn = insn.append(Insn.create(opc_aload_1));
1259 insn = insn.append(Insn.create(opc_iload_3));
1260 insn = insn.append(Insn.create(opc_iaload));
1261
1262
1263 insn = insn.append(
1264 Insn.create(opc_invokevirtual,
1265 pool.addMethodRef(
1266 className,
1267 delegateName,
1268 delegateSig)));
1269
1270
1271 insn = insn.append(new InsnIInc(3, 1));
1272
1273
1274 insn = insn.append(loopcheck);
1275 insn = insn.append(Insn.create(opc_iload_3));
1276 insn = insn.append(Insn.create(opc_iload_2));
1277 insn = insn.append(Insn.create(opc_if_icmplt, loopbody));
1278
1279
1280 insn = insn.append(Insn.create(opc_return));
1281
1282 final CodeAttribute codeAttr
1283 = new CodeAttribute(getCodeAttributeUtf8(),
1284 3,
1285 4,
1286 begin,
1287 new ExceptionTable(),
1288 new AttributeVector());
1289 augmenter.addMethod(methodName, methodSig, accessFlags,
1290 codeAttr, exceptAttr);
1291 }
1292
1293
1294
1295 /***
1296 * Build the sunjdoClassForName method for the class.
1297 *
1298 * public final Class sunjdoClassForName(java.lang.String classname)
1299 * {
1300 * try {
1301 * return Class.forName(classname);
1302 * catch (ClassNotFoundException ex) {
1303 * throw new NoClassDefFoundError(ex.getMessage());
1304 * }
1305 * }
1306 */
1307 public void addSunJDOClassForNameMethod()
1308 {
1309 final String methodName = SUNJDO_PC_sunjdoClassForName_Name;
1310 final String methodSig = SUNJDO_PC_sunjdoClassForName_Sig;
1311 final int accessFlags = SUNJDO_PC_sunjdoClassForName_Mods;
1312 final ExceptionsAttribute exceptAttr = null;
1313
1314
1315 final InsnTarget begin = new InsnTarget();
1316 Insn insn = begin;
1317
1318
1319 insn = insn.append(Insn.create(opc_aload_0));
1320 insn = insn.append(
1321 Insn.create(opc_invokestatic,
1322 pool.addMethodRef(
1323 JAVA_Class_Path,
1324 JAVA_Class_forName_Name,
1325 JAVA_Class_forName_Sig)));
1326
1327
1328 insn = insn.append(Insn.create(opc_areturn));
1329
1330
1331 final InsnTarget end = new InsnTarget();
1332 final InsnTarget beginHandler = end;
1333 insn = insn.append(beginHandler);
1334
1335
1336 insn = insn.append(Insn.create(opc_astore_1));
1337 insn = insn.append(
1338 Insn.create(opc_new,
1339 pool.addClass(JAVA_NoClassDefFoundError_Path)));
1340 insn = insn.append(Insn.create(opc_dup));
1341 insn = insn.append(Insn.create(opc_aload_1));
1342 insn = insn.append(
1343 Insn.create(
1344 opc_invokevirtual,
1345 pool.addMethodRef(
1346 JAVA_Throwable_Path,
1347 JAVA_Throwable_getMessage_Name,
1348 JAVA_Throwable_getMessage_Sig)));
1349 insn = insn.append(
1350 Insn.create(
1351 opc_invokespecial,
1352 pool.addMethodRef(
1353 JAVA_NoClassDefFoundError_Path,
1354 JAVA_NoClassDefFoundError_NoClassDefFoundError_Name,
1355 JAVA_NoClassDefFoundError_NoClassDefFoundError_Sig)));
1356
1357
1358 insn = insn.append(Insn.create(opc_athrow));
1359
1360
1361 final ConstClass catchType
1362 = pool.addClass(JAVA_ClassNotFoundException_Path);
1363 final ExceptionRange exceptionRange
1364 = new ExceptionRange(begin, end, beginHandler, catchType);
1365 final ExceptionTable exceptionTable
1366 = new ExceptionTable();
1367 exceptionTable.addElement(exceptionRange);
1368
1369 final CodeAttribute codeAttr
1370 = new CodeAttribute(getCodeAttributeUtf8(),
1371 3,
1372 3,
1373 begin,
1374 exceptionTable,
1375 new AttributeVector());
1376 augmenter.addMethod(methodName, methodSig, accessFlags,
1377 codeAttr, exceptAttr);
1378 }
1379
1380
1381
1382
1383
1384 /***
1385 * Build the jdoGetManagedFieldCount method for the class.
1386 *
1387 * protected static int jdoGetManagedFieldCount()
1388 * {
1389 * return jdoInheritedFieldCount + X;
1390 * }
1391 */
1392 public void addJDOGetManagedFieldCountMethod()
1393 {
1394 final String methodName = JDO_PC_jdoGetManagedFieldCount_Name;
1395 final String methodSig = JDO_PC_jdoGetManagedFieldCount_Sig;
1396 final int accessFlags = JDO_PC_jdoGetManagedFieldCount_Mods;
1397 final ExceptionsAttribute exceptAttr = null;
1398
1399 final int managedFieldCount = analyzer.getManagedFieldCount();
1400 affirm(managedFieldCount >= 0);
1401
1402
1403 final InsnTarget begin = new InsnTarget();
1404 Insn insn = begin;
1405
1406
1407 final boolean isPCRoot = analyzer.isAugmentableAsRoot();
1408 if (isPCRoot) {
1409 insn = insn.append(InsnUtils.integerConstant(managedFieldCount, pool));
1410 }
1411 else {
1412 final ConstClass superConstClass = classFile.superName();
1413 affirm(superConstClass != null);
1414 final String superClassName = superConstClass.asString();
1415 affirm(superClassName != null);
1416
1417 insn = insn.append(
1418 Insn.create(opc_invokestatic,
1419 pool.addMethodRef(
1420 superClassName,
1421 JDO_PC_jdoGetManagedFieldCount_Name,
1422 JDO_PC_jdoGetManagedFieldCount_Sig)));
1423 insn = insn.append(InsnUtils.integerConstant(managedFieldCount, pool));
1424 insn = insn.append(Insn.create(opc_iadd));
1425 }
1426
1427
1428 insn = insn.append(Insn.create(opc_ireturn));
1429
1430 final CodeAttribute codeAttr
1431 = new CodeAttribute(getCodeAttributeUtf8(),
1432 isPCRoot ? 1 : 2,
1433 0,
1434 begin,
1435 new ExceptionTable(),
1436 new AttributeVector());
1437 augmenter.addMethod(methodName, methodSig, accessFlags,
1438 codeAttr, exceptAttr);
1439 }
1440
1441
1442
1443 /***
1444 * Adds the initialization code for the jdoInheritedFieldCount field.
1445 */
1446 private Insn initJdoInheritedFieldCount(Insn insn)
1447 {
1448 affirm(insn != null);
1449
1450
1451 final boolean isPCRoot = analyzer.isAugmentableAsRoot();
1452 if (isPCRoot) {
1453 insn = insn.append(Insn.create(opc_iconst_0));
1454 } else {
1455 final ConstClass superConstClass = classFile.superName();
1456 affirm(superConstClass != null);
1457 final String superClassName = superConstClass.asString();
1458 affirm(superClassName != null);
1459 insn = insn.append(
1460 Insn.create(opc_invokestatic,
1461 pool.addMethodRef(
1462 superClassName,
1463 JDO_PC_jdoGetManagedFieldCount_Name,
1464 JDO_PC_jdoGetManagedFieldCount_Sig)));
1465 }
1466
1467
1468 insn = insn.append(
1469 Insn.create(opc_putstatic,
1470 pool.addFieldRef(
1471 className,
1472 JDO_PC_jdoInheritedFieldCount_Name,
1473 JDO_PC_jdoInheritedFieldCount_Sig)));
1474
1475 affirm(insn != null);
1476 return insn;
1477 }
1478
1479 /***
1480 * Adds the initialization code for the jdoFieldNames field.
1481 */
1482 private Insn initJdoFieldNames(Insn insn)
1483 {
1484 affirm(insn != null);
1485
1486 final int managedFieldCount = analyzer.getManagedFieldCount();
1487 final String[] managedFieldNames = analyzer.getAnnotatedFieldNames();
1488 affirm(managedFieldNames.length >= managedFieldCount);
1489
1490
1491 affirm(NameHelper.elementPathForSig(JDO_PC_jdoFieldNames_Sig)
1492 .equals(JAVA_String_Path));
1493 insn = insn.append(InsnUtils.integerConstant(managedFieldCount, pool));
1494 insn = insn.append(
1495 Insn.create(opc_anewarray,
1496 pool.addClass(JAVA_String_Path)));
1497
1498
1499 for (int i = 0; i < managedFieldCount; i++) {
1500 insn = insn.append(Insn.create(opc_dup));
1501 insn = insn.append(InsnUtils.integerConstant(i, pool));
1502 final String name = managedFieldNames[i];
1503 affirm(name != null);
1504 insn = insn.append(
1505 InsnUtils.stringConstant(name, pool));
1506 insn = insn.append(Insn.create(opc_aastore));
1507 }
1508
1509
1510 insn = insn.append(
1511 Insn.create(opc_putstatic,
1512 getjdoFieldNamesFieldRef()));
1513
1514 affirm(insn != null);
1515 return insn;
1516 }
1517
1518 /***
1519 * Adds the initialization code for the jdoFieldTypes field.
1520 */
1521 private Insn initJdoFieldTypes(Insn insn)
1522 {
1523 affirm(insn != null);
1524
1525 final int managedFieldCount = analyzer.getManagedFieldCount();
1526 final String[] managedFieldSigs = analyzer.getAnnotatedFieldSigs();
1527 affirm(managedFieldSigs.length >= managedFieldCount);
1528
1529
1530 affirm(NameHelper.elementPathForSig(JDO_PC_jdoFieldTypes_Sig)
1531 .equals(JAVA_Class_Path));
1532 insn = insn.append(InsnUtils.integerConstant(managedFieldCount, pool));
1533 insn = insn.append(
1534 Insn.create(opc_anewarray,
1535 pool.addClass(JAVA_Class_Path)));
1536
1537
1538 for (int i = 0; i < managedFieldCount; i++) {
1539 insn = insn.append(Insn.create(opc_dup));
1540 insn = insn.append(InsnUtils.integerConstant(i, pool));
1541 final String sig = managedFieldSigs[i];
1542 affirm(sig != null && sig.length() > 0);
1543
1544
1545
1546
1547
1548 switch (sig.charAt(0)) {
1549 case 'Z':
1550
1551 insn = insn.append(
1552 Insn.create(opc_getstatic,
1553 pool.addFieldRef(
1554 JAVA_Boolean_Path,
1555 JAVA_Boolean_TYPE_Name,
1556 JAVA_Boolean_TYPE_Sig)));
1557 break;
1558 case 'C':
1559
1560 insn = insn.append(
1561 Insn.create(opc_getstatic,
1562 pool.addFieldRef(
1563 JAVA_Character_Path,
1564 JAVA_Character_TYPE_Name,
1565 JAVA_Character_TYPE_Sig)));
1566 break;
1567 case 'B':
1568
1569 insn = insn.append(
1570 Insn.create(opc_getstatic,
1571 pool.addFieldRef(
1572 JAVA_Byte_Path,
1573 JAVA_Byte_TYPE_Name,
1574 JAVA_Byte_TYPE_Sig)));
1575 break;
1576 case 'S':
1577
1578 insn = insn.append(
1579 Insn.create(opc_getstatic,
1580 pool.addFieldRef(
1581 JAVA_Short_Path,
1582 JAVA_Short_TYPE_Name,
1583 JAVA_Short_TYPE_Sig)));
1584 break;
1585 case 'I':
1586
1587 insn = insn.append(
1588 Insn.create(opc_getstatic,
1589 pool.addFieldRef(
1590 JAVA_Integer_Path,
1591 JAVA_Integer_TYPE_Name,
1592 JAVA_Integer_TYPE_Sig)));
1593 break;
1594 case 'J':
1595
1596 insn = insn.append(
1597 Insn.create(opc_getstatic,
1598 pool.addFieldRef(
1599 JAVA_Long_Path,
1600 JAVA_Long_TYPE_Name,
1601 JAVA_Long_TYPE_Sig)));
1602 break;
1603 case 'F':
1604
1605 insn = insn.append(
1606 Insn.create(opc_getstatic,
1607 pool.addFieldRef(
1608 JAVA_Float_Path,
1609 JAVA_Float_TYPE_Name,
1610 JAVA_Float_TYPE_Sig)));
1611 break;
1612 case 'D':
1613
1614 insn = insn.append(
1615 Insn.create(opc_getstatic,
1616 pool.addFieldRef(
1617 JAVA_Double_Path,
1618 JAVA_Double_TYPE_Name,
1619 JAVA_Double_TYPE_Sig)));
1620 break;
1621 case 'L':
1622
1623
1624
1625 insn = insn.append(
1626 InsnUtils.stringConstant(
1627 NameHelper.typeForSig(sig), pool));
1628
1629
1630 insn = insn.append(
1631 Insn.create(opc_invokestatic,
1632 pool.addMethodRef(
1633 className,
1634 SUNJDO_PC_sunjdoClassForName_Name,
1635 SUNJDO_PC_sunjdoClassForName_Sig)));
1636 break;
1637 case '[':
1638
1639
1640
1641
1642 insn = insn.append(
1643 InsnUtils.stringConstant(
1644 NameHelper.typeForPath(sig), pool));
1645
1646
1647 insn = insn.append(
1648 Insn.create(opc_invokestatic,
1649 pool.addMethodRef(
1650 className,
1651 SUNJDO_PC_sunjdoClassForName_Name,
1652 SUNJDO_PC_sunjdoClassForName_Sig)));
1653 break;
1654 default:
1655 affirm(false, "Illegal field type: " + sig);
1656 }
1657
1658 insn = insn.append(Insn.create(opc_aastore));
1659 }
1660
1661
1662 insn = insn.append(
1663 Insn.create(opc_putstatic,
1664 getjdoFieldTypesFieldRef()));
1665
1666 affirm(insn != null);
1667 return insn;
1668 }
1669
1670 /***
1671 * Adds the initialization code for the jdoFieldFlags field.
1672 */
1673 private Insn initJdoFieldFlags(Insn insn)
1674 {
1675 affirm(insn != null);
1676
1677 final int managedFieldCount = analyzer.getManagedFieldCount();
1678 final int[] managedFieldFlags = analyzer.getAnnotatedFieldFlags();
1679 affirm(managedFieldFlags.length >= managedFieldCount);
1680
1681
1682 affirm(NameHelper.elementSigForSig(JDO_PC_jdoFieldFlags_Sig)
1683 .equals("B"));
1684 insn = insn.append(InsnUtils.integerConstant(managedFieldCount, pool));
1685 insn = insn.append(
1686 Insn.create(opc_newarray, T_BYTE));
1687
1688
1689 for (int i = 0; i < managedFieldCount; i++) {
1690 insn = insn.append(Insn.create(opc_dup));
1691 insn = insn.append(InsnUtils.integerConstant(i, pool));
1692 final int flags = managedFieldFlags[i];
1693
1694
1695 affirm(-128 <= flags && flags < 128);
1696 insn = insn.append(InsnUtils.integerConstant(flags, pool));
1697 insn = insn.append(Insn.create(opc_bastore));
1698 }
1699
1700
1701 insn = insn.append(
1702 Insn.create(opc_putstatic,
1703 getjdoFieldFlagsFieldRef()));
1704
1705 affirm(insn != null);
1706 return insn;
1707 }
1708
1709 /***
1710 * Adds the initialization code for the jdoPersistenceCapableSuperclass
1711 * field.
1712 */
1713 private Insn initJdoPersistenceCapableSuperclass(Insn insn)
1714 {
1715 affirm(insn != null);
1716
1717 final String pcSuperName = analyzer.getPCSuperClassName();
1718 final String pcRootName = analyzer.getPCRootClassName();
1719 affirm(pcSuperName == null || pcRootName != null);
1720
1721
1722
1723
1724 if (pcSuperName == null) {
1725 insn = insn.append(Insn.create(opc_aconst_null));
1726 } else {
1727
1728
1729 insn = insn.append(
1730 InsnUtils.stringConstant(
1731 NameHelper.typeForPath(pcSuperName), pool));
1732
1733
1734
1735 insn = insn.append(
1736 Insn.create(opc_invokestatic,
1737 pool.addMethodRef(
1738 pcRootName,
1739 SUNJDO_PC_sunjdoClassForName_Name,
1740 SUNJDO_PC_sunjdoClassForName_Sig)));
1741 }
1742
1743
1744 insn = insn.append(
1745 Insn.create(opc_putstatic,
1746 getjdoPersistenceCapableSuperclassFieldRef()));
1747
1748 affirm(insn != null);
1749 return insn;
1750 }
1751
1752 /***
1753 * Adds the code for the jdoPersistenceCapableSuperclass
1754 * field.
1755 */
1756 private Insn registerClass(Insn insn)
1757 {
1758 affirm(insn != null);
1759
1760 final String pcRootName = analyzer.getPCRootClassName();
1761
1762
1763
1764
1765
1766
1767 insn = insn.append(
1768 InsnUtils.stringConstant(
1769 NameHelper.typeForPath(className), pool));
1770
1771
1772
1773 insn = insn.append(
1774 Insn.create(opc_invokestatic,
1775 pool.addMethodRef(
1776 pcRootName,
1777 SUNJDO_PC_sunjdoClassForName_Name,
1778 SUNJDO_PC_sunjdoClassForName_Sig)));
1779
1780
1781 insn = insn.append(
1782 Insn.create(opc_getstatic,
1783 getjdoFieldNamesFieldRef()));
1784
1785
1786 insn = insn.append(
1787 Insn.create(opc_getstatic,
1788 getjdoFieldTypesFieldRef()));
1789
1790
1791 insn = insn.append(
1792 Insn.create(opc_getstatic,
1793 getjdoFieldFlagsFieldRef()));
1794
1795
1796 insn = insn.append(
1797 Insn.create(opc_getstatic,
1798 getjdoPersistenceCapableSuperclassFieldRef()));
1799
1800
1801
1802 if (classFile.isAbstract()) {
1803 insn = insn.append(Insn.create(opc_aconst_null));
1804 } else {
1805 final ConstClass thisConstClass = classFile.className();
1806 affirm(thisConstClass != null);
1807 insn = insn.append(Insn.create(opc_new, thisConstClass));
1808 insn = insn.append(Insn.create(opc_dup));
1809 insn = insn.append(
1810 Insn.create(opc_invokespecial,
1811 pool.addMethodRef(
1812 className,
1813 NameHelper.constructorName(),
1814 NameHelper.constructorSig())));
1815 }
1816
1817
1818 insn = insn.append(
1819 Insn.create(opc_invokestatic,
1820 pool.addMethodRef(
1821 JDO_JDOImplHelper_Path,
1822 JDO_JDOImplHelper_registerClass_Name,
1823 JDO_JDOImplHelper_registerClass_Sig)));
1824
1825 affirm(insn != null);
1826 return insn;
1827 }
1828
1829 /***
1830 * Build the static initialization code for the class.
1831 *
1832 * static
1833 * {
1834 * jdoInheritedFieldCount = 0 | super.jdoGetManagedFieldCount();
1835 * jdoFieldNames = new String[]{ ... };
1836 * jdoFieldTypes = new Class[]{ ... };
1837 * jdoFieldFlags = new byte[]{ ... };
1838 * jdoPersistenceCapableSuperclass = ...;
1839 * javax.jdo.JDOImplHelper.registerClass(
1840 * XXX.class,
1841 * jdoFieldNames,
1842 * jdoFieldTypes,
1843 * jdoFieldFlags,
1844 * jdoPersistenceCapableSuperclass,
1845 * new XXX()
1846 * );
1847 * }
1848 */
1849 public void addStaticInitialization()
1850 {
1851 final String methodName = JAVA_clinit_Name;
1852 final String methodSig = JAVA_clinit_Sig;
1853 final int accessFlags = JAVA_clinit_Mods;
1854 final ExceptionsAttribute exceptAttr = null;
1855
1856
1857 final InsnTarget begin = new InsnTarget();
1858 Insn insn = begin;
1859
1860
1861 insn = initJdoInheritedFieldCount(insn);
1862 insn = initJdoFieldNames(insn);
1863 insn = initJdoFieldTypes(insn);
1864 insn = initJdoFieldFlags(insn);
1865 insn = initJdoPersistenceCapableSuperclass(insn);
1866
1867
1868 insn = registerClass(insn);
1869
1870
1871 final CodeAttribute codeAttr
1872 = new CodeAttribute(getCodeAttributeUtf8(),
1873 7,
1874 0,
1875 begin,
1876 new ExceptionTable(),
1877 new AttributeVector());
1878
1879 if (analyzer.hasStaticInitializer()) {
1880
1881 augmenter.prependMethod(methodName, methodSig,
1882 codeAttr, exceptAttr);
1883 } else {
1884
1885 insn = insn.append(Insn.create(opc_return));
1886 augmenter.addMethod(methodName, methodSig, accessFlags,
1887 codeAttr, exceptAttr);
1888 }
1889 }
1890
1891
1892
1893 /***
1894 * Build the jdoNewInstance method for the class.
1895 *
1896 * public PersistenceCapable jdoNewInstance(StateManager sm)
1897 * {
1898 * final XXX pc = new XXX();
1899 * pc.jdoFlags = 1; // == LOAD_REQUIRED
1900 * pc.jdoStateManager = sm;
1901 * return pc;
1902 * }
1903 */
1904 public void addJDONewInstanceMethod()
1905 {
1906 final String methodName = JDO_PC_jdoNewInstance_Name;
1907 final String methodSig = JDO_PC_jdoNewInstance_Sig;
1908 final int accessFlags = JDO_PC_jdoNewInstance_Mods;
1909 final ExceptionsAttribute exceptAttr = null;
1910
1911
1912 final InsnTarget begin = new InsnTarget();
1913 Insn insn = begin;
1914
1915
1916 final ConstClass thisConstClass = classFile.className();
1917 affirm(thisConstClass != null);
1918 insn = insn.append(Insn.create(opc_new, thisConstClass));
1919 insn = insn.append(Insn.create(opc_dup));
1920 insn = insn.append(
1921 Insn.create(opc_invokespecial,
1922 pool.addMethodRef(
1923 className,
1924 NameHelper.constructorName(),
1925 NameHelper.constructorSig())));
1926 insn = insn.append(Insn.create(opc_astore_2));
1927
1928
1929 insn = insn.append(Insn.create(opc_aload_2));
1930 insn = insn.append(Insn.create(opc_iconst_1));
1931 insn = insn.append(
1932 Insn.create(opc_putfield,
1933 getjdoFlagsFieldRef()));
1934 insn = insn.append(Insn.create(opc_aload_2));
1935 insn = insn.append(Insn.create(opc_aload_1));
1936 insn = insn.append(
1937 Insn.create(opc_putfield,
1938 getjdoStateManagerFieldRef()));
1939
1940
1941 insn = insn.append(Insn.create(opc_aload_2));
1942 insn = insn.append(Insn.create(opc_areturn));
1943
1944 final CodeAttribute codeAttr
1945 = new CodeAttribute(getCodeAttributeUtf8(),
1946 2,
1947 3,
1948 begin,
1949 new ExceptionTable(),
1950 new AttributeVector());
1951 augmenter.addMethod(methodName, methodSig, accessFlags,
1952 codeAttr, exceptAttr);
1953 }
1954
1955 /***
1956 * Build the jdoNewInstance method for the class.
1957 *
1958 * public PersistenceCapable jdoNewInstance(StateManager sm, Object oid)
1959 * {
1960 * final XXX pc = new XXX();
1961 * pc.jdoCopyKeyFieldsFromObjectId(oid);
1962 * pc.jdoFlags = 1; // == LOAD_REQUIRED
1963 * pc.jdoStateManager = sm;
1964 * return pc;
1965 * }
1966 */
1967 public void addJDONewInstanceOidMethod()
1968 {
1969 final String methodName = JDO_PC_jdoNewInstance_Object_Name;
1970 final String methodSig = JDO_PC_jdoNewInstance_Object_Sig;
1971 final int accessFlags = JDO_PC_jdoNewInstance_Object_Mods;
1972 final ExceptionsAttribute exceptAttr = null;
1973
1974
1975 final InsnTarget begin = new InsnTarget();
1976 Insn insn = begin;
1977
1978
1979 final ConstClass thisConstClass = classFile.className();
1980 affirm(thisConstClass != null);
1981 insn = insn.append(Insn.create(opc_new, thisConstClass));
1982 insn = insn.append(Insn.create(opc_dup));
1983 insn = insn.append(
1984 Insn.create(opc_invokespecial,
1985 pool.addMethodRef(
1986 className,
1987 NameHelper.constructorName(),
1988 NameHelper.constructorSig())));
1989 insn = insn.append(Insn.create(opc_astore_3));
1990
1991
1992
1993 final String pcKeyOwnerClassName = analyzer.getPCKeyOwnerClassName();
1994 affirm(pcKeyOwnerClassName != null);
1995 insn = insn.append(Insn.create(opc_aload_3));
1996 insn = insn.append(Insn.create(opc_aload_2));
1997 insn = insn.append(
1998 Insn.create(opc_invokevirtual,
1999 pool.addMethodRef(
2000 pcKeyOwnerClassName,
2001 JDO_PC_jdoCopyKeyFieldsFromObjectId_Name,
2002 JDO_PC_jdoCopyKeyFieldsFromObjectId_Sig)));
2003
2004
2005 insn = insn.append(Insn.create(opc_aload_3));
2006 insn = insn.append(Insn.create(opc_iconst_1));
2007 insn = insn.append(
2008 Insn.create(opc_putfield,
2009 getjdoFlagsFieldRef()));
2010 insn = insn.append(Insn.create(opc_aload_3));
2011 insn = insn.append(Insn.create(opc_aload_1));
2012 insn = insn.append(
2013 Insn.create(opc_putfield,
2014 getjdoStateManagerFieldRef()));
2015
2016
2017 insn = insn.append(Insn.create(opc_aload_3));
2018 insn = insn.append(Insn.create(opc_areturn));
2019
2020 final CodeAttribute codeAttr
2021 = new CodeAttribute(getCodeAttributeUtf8(),
2022 2,
2023 4,
2024 begin,
2025 new ExceptionTable(),
2026 new AttributeVector());
2027 augmenter.addMethod(methodName, methodSig, accessFlags,
2028 codeAttr, exceptAttr);
2029 }
2030
2031
2032
2033 /***
2034 * Adds the code for the begin of the jdoProvideField and
2035 * jdoReplaceField methods.
2036 */
2037 private Insn appendBeginProvideReplaceField(Insn insn)
2038 {
2039 affirm(insn != null);
2040
2041
2042 insn = insn.append(Insn.create(opc_aload_0));
2043 insn = insn.append(
2044 Insn.create(opc_getfield,
2045 getjdoStateManagerFieldRef()));
2046 insn = insn.append(Insn.create(opc_astore_2));
2047
2048
2049 insn = insn.append(Insn.create(opc_iload_1));
2050 insn = insn.append(
2051 Insn.create(opc_getstatic,
2052 pool.addFieldRef(
2053 className,
2054 JDO_PC_jdoInheritedFieldCount_Name,
2055 JDO_PC_jdoInheritedFieldCount_Sig)));
2056 insn = insn.append(Insn.create(opc_isub));
2057 affirm(insn != null);
2058 return insn;
2059 }
2060
2061 /***
2062 * Adds the default-branch code for the jdoProvideField and
2063 * jdoReplaceField methods.
2064 */
2065 private Insn appendEndProvideReplaceField(Insn insn,
2066 String provideReplaceField_Name,
2067 String provideReplaceField_Sig)
2068 {
2069 affirm(insn != null);
2070 affirm(provideReplaceField_Name);
2071 affirm(provideReplaceField_Sig);
2072
2073
2074 final boolean isPCRoot = analyzer.isAugmentableAsRoot();
2075 if (isPCRoot) {
2076 insn = appendThrowJavaException(insn,
2077 JAVA_IllegalArgumentException_Path,
2078 "arg1");
2079 } else {
2080
2081 final ConstClass superConstClass = classFile.superName();
2082 affirm(superConstClass != null);
2083 final String superClassName = superConstClass.asString();
2084 affirm(superClassName != null);
2085 insn = insn.append(Insn.create(opc_aload_0));
2086 insn = insn.append(Insn.create(opc_iload_1));
2087 insn = insn.append(
2088 Insn.create(opc_invokespecial,
2089 pool.addMethodRef(
2090 superClassName,
2091 provideReplaceField_Name,
2092 provideReplaceField_Sig)));
2093 insn = insn.append(Insn.create(opc_return));
2094 }
2095
2096 affirm(insn != null);
2097 return insn;
2098 }
2099
2100 /***
2101 * Adds the code for one case-branch in the jdoProvideField method.
2102 */
2103 private Insn appendCaseBranchForProvideField(Insn insn,
2104 String providedXXXField_Name,
2105 String providedXXXField_Sig,
2106 ConstFieldRef managedFieldRef)
2107 {
2108 affirm(insn != null);
2109 affirm(providedXXXField_Name != null);
2110 affirm(providedXXXField_Sig != null);
2111 affirm(managedFieldRef != null);
2112
2113
2114 insn = appendCheckVarNonNull(insn, 2,
2115 JAVA_IllegalStateException_Path,
2116 "arg0." + JDO_PC_jdoStateManager_Name);
2117
2118
2119 insn = insn.append(Insn.create(opc_aload_2));
2120 insn = insn.append(Insn.create(opc_aload_0));
2121 insn = insn.append(Insn.create(opc_iload_1));
2122 insn = insn.append(Insn.create(opc_aload_0));
2123 insn = insn.append(Insn.create(opc_getfield, managedFieldRef));
2124
2125
2126 insn = insn.append(
2127 new InsnInterfaceInvoke(
2128 pool.addInterfaceMethodRef(
2129 JDO_StateManager_Path,
2130 providedXXXField_Name,
2131 providedXXXField_Sig),
2132 countMethodArgWords(providedXXXField_Sig)));
2133
2134
2135 insn = insn.append(Insn.create(opc_return));
2136
2137 affirm(insn != null);
2138 return insn;
2139 }
2140
2141 /***
2142 * Adds the switch code for the jdoProvideField method.
2143 */
2144 private Insn appendSwitchForProvideField(Insn insn,
2145 SizeHolder sizeHolder)
2146 {
2147 affirm(insn != null);
2148 affirm(sizeHolder != null);
2149
2150
2151 final int managedFieldCount = analyzer.getManagedFieldCount();
2152
2153
2154
2155
2156
2157 final String[] managedFieldSigs = analyzer.getAnnotatedFieldSigs();
2158 final ConstFieldRef[] managedFieldRefs = getAnnotatedFieldRefs();
2159 affirm(managedFieldSigs.length >= managedFieldCount);
2160 affirm(managedFieldRefs.length >= managedFieldCount);
2161
2162
2163 final int lowOp = 0;
2164 final InsnTarget defaultOp = new InsnTarget();
2165 final InsnTarget[] targetsOp = new InsnTarget[managedFieldCount];
2166 for (int i = 0; i < managedFieldCount; i++) {
2167 targetsOp[i] = new InsnTarget();
2168 }
2169
2170
2171 if (managedFieldCount <= 1) {
2172 final int[] matchesOp
2173 = (managedFieldCount == 0 ? new int[]{} : new int[]{ lowOp });
2174 insn = insn.append(
2175 new InsnLookupSwitch(defaultOp, matchesOp, targetsOp));
2176 } else {
2177 insn = insn.append(
2178 new InsnTableSwitch(lowOp, defaultOp, targetsOp));
2179 }
2180
2181
2182 for (int i = 0; i < managedFieldCount; i++) {
2183
2184 insn = insn.append(targetsOp[i]);
2185
2186
2187 final String sig = managedFieldSigs[i];
2188 final ConstFieldRef ref = managedFieldRefs[i];
2189 affirm(sig != null && sig.length() > 0);
2190 affirm(ref != null);
2191
2192
2193 sizeHolder.size = max(sizeHolder.size,
2194 Descriptor.countFieldWords(sig));
2195
2196
2197 switch (sig.charAt(0)) {
2198 case 'Z':
2199 insn = appendCaseBranchForProvideField(
2200 insn,
2201 JDO_SM_providedBooleanField_Name,
2202 JDO_SM_providedBooleanField_Sig,
2203 ref);
2204 break;
2205 case 'C':
2206 insn = appendCaseBranchForProvideField(
2207 insn,
2208 JDO_SM_providedCharField_Name,
2209 JDO_SM_providedCharField_Sig,
2210 ref);
2211 break;
2212 case 'B':
2213 insn = appendCaseBranchForProvideField(
2214 insn,
2215 JDO_SM_providedByteField_Name,
2216 JDO_SM_providedByteField_Sig,
2217 ref);
2218 break;
2219 case 'S':
2220 insn = appendCaseBranchForProvideField(
2221 insn,
2222 JDO_SM_providedShortField_Name,
2223 JDO_SM_providedShortField_Sig,
2224 ref);
2225 break;
2226 case 'I':
2227 insn = appendCaseBranchForProvideField(
2228 insn,
2229 JDO_SM_providedIntField_Name,
2230 JDO_SM_providedIntField_Sig,
2231 ref);
2232 break;
2233 case 'J':
2234 insn = appendCaseBranchForProvideField(
2235 insn,
2236 JDO_SM_providedLongField_Name,
2237 JDO_SM_providedLongField_Sig,
2238 ref);
2239 break;
2240 case 'F':
2241 insn = appendCaseBranchForProvideField(
2242 insn,
2243 JDO_SM_providedFloatField_Name,
2244 JDO_SM_providedFloatField_Sig,
2245 ref);
2246 break;
2247 case 'D':
2248 insn = appendCaseBranchForProvideField(
2249 insn,
2250 JDO_SM_providedDoubleField_Name,
2251 JDO_SM_providedDoubleField_Sig,
2252 ref);
2253 break;
2254 case 'L':
2255 case '[':
2256 if (sig.equals(JAVA_String_Sig)) {
2257 insn = appendCaseBranchForProvideField(
2258 insn,
2259 JDO_SM_providedStringField_Name,
2260 JDO_SM_providedStringField_Sig,
2261 ref);
2262 } else {
2263 insn = appendCaseBranchForProvideField(
2264 insn,
2265 JDO_SM_providedObjectField_Name,
2266 JDO_SM_providedObjectField_Sig,
2267 ref);
2268 }
2269 break;
2270 default:
2271 affirm(false, "Illegal field type: " + sig);
2272 }
2273 }
2274
2275
2276 insn = insn.append(defaultOp);
2277
2278 affirm(insn != null);
2279 return insn;
2280 }
2281
2282 /***
2283 * Build the jdoProvideField method for the class.
2284 *
2285 * public void jdoProvideField(int fieldnumber)
2286 * {
2287 * final javax.jdo.StateManager sm = this.jdoStateManager;
2288 * switch(fieldnumber - jdoInheritedFieldCount) {
2289 * case 0:
2290 * sm.providedXXXField(this, fieldnumber, this.yyy);
2291 * return;
2292 * case 1:
2293 * ...
2294 * default:
2295 * <if (isPCRoot) {>
2296 * throw new javax.jdo.JDOFatalInternalException();
2297 * <} else {>
2298 * super.jdoProvideField(fieldnumber);
2299 * <}>
2300 * }
2301 * }
2302 */
2303 public void addJDOProvideFieldMethod()
2304 {
2305 final String methodName = JDO_PC_jdoProvideField_Name;
2306 final String methodSig = JDO_PC_jdoProvideField_Sig;
2307 final int accessFlags = JDO_PC_jdoProvideField_Mods;
2308 final ExceptionsAttribute exceptAttr = null;
2309
2310
2311 final InsnTarget begin = new InsnTarget();
2312 Insn insn = begin;
2313
2314
2315 insn = appendBeginProvideReplaceField(insn);
2316
2317
2318 final SizeHolder sizeHolder = new SizeHolder();
2319 insn = appendSwitchForProvideField(insn, sizeHolder);
2320
2321
2322 insn = appendEndProvideReplaceField(insn,
2323 JDO_PC_jdoProvideField_Name,
2324 JDO_PC_jdoProvideField_Sig);
2325
2326
2327 affirm(insn.opcode() == opc_athrow || insn.opcode() == opc_return);
2328
2329 affirm(0 <= sizeHolder.size && sizeHolder.size <= 2);
2330
2331 final int maxStack = (sizeHolder.size == 0
2332 ? 3 : (sizeHolder.size == 1 ? 4 : 5));
2333 final CodeAttribute codeAttr
2334 = new CodeAttribute(getCodeAttributeUtf8(),
2335 maxStack,
2336 3,
2337 begin,
2338 new ExceptionTable(),
2339 new AttributeVector());
2340 augmenter.addMethod(methodName, methodSig, accessFlags,
2341 codeAttr, exceptAttr);
2342 }
2343
2344 /***
2345 * Adds the code for one case-branch in the jdoReplaceField method.
2346 */
2347 private Insn appendCaseBranchForReplaceField(Insn insn,
2348 String replacingXXXField_Name,
2349 String replacingXXXField_Sig,
2350 ConstFieldRef managedFieldRef,
2351 String managedFieldSig)
2352 {
2353 affirm(insn != null);
2354 affirm(replacingXXXField_Name != null);
2355 affirm(replacingXXXField_Sig != null);
2356 affirm(managedFieldRef != null);
2357 affirm(managedFieldSig != null);
2358
2359
2360 insn = appendCheckVarNonNull(insn, 2,
2361 JAVA_IllegalStateException_Path,
2362 "arg0." + JDO_PC_jdoStateManager_Name);
2363
2364
2365 insn = insn.append(Insn.create(opc_aload_0));
2366 insn = insn.append(Insn.create(opc_aload_2));
2367 insn = insn.append(Insn.create(opc_aload_0));
2368 insn = insn.append(Insn.create(opc_iload_1));
2369
2370
2371 insn = insn.append(
2372 new InsnInterfaceInvoke(
2373 pool.addInterfaceMethodRef(
2374 JDO_StateManager_Path,
2375 replacingXXXField_Name,
2376 replacingXXXField_Sig),
2377 countMethodArgWords(replacingXXXField_Sig)));
2378
2379
2380 if (replacingXXXField_Name.equals(JDO_SM_replacingObjectField_Name)) {
2381 final String fieldType = NameHelper.pathForSig(managedFieldSig);
2382 insn = insn.append(
2383 Insn.create(opc_checkcast,
2384 pool.addClass(fieldType)));
2385 }
2386 insn = insn.append(Insn.create(opc_putfield, managedFieldRef));
2387
2388
2389 insn = insn.append(Insn.create(opc_return));
2390
2391 affirm(insn != null);
2392 return insn;
2393 }
2394
2395 /***
2396 * Adds the switch code for the jdoReplaceField method.
2397 */
2398 private Insn appendSwitchForReplaceField(Insn insn,
2399 SizeHolder sizeHolder)
2400 {
2401 affirm(insn != null);
2402 affirm(sizeHolder != null);
2403
2404
2405 final int managedFieldCount = analyzer.getManagedFieldCount();
2406
2407
2408
2409
2410
2411 final String[] managedFieldSigs = analyzer.getAnnotatedFieldSigs();
2412 final ConstFieldRef[] managedFieldRefs = getAnnotatedFieldRefs();
2413 affirm(managedFieldSigs.length >= managedFieldCount);
2414 affirm(managedFieldRefs.length >= managedFieldCount);
2415
2416
2417 final int lowOp = 0;
2418 final InsnTarget defaultOp = new InsnTarget();
2419 final InsnTarget[] targetsOp = new InsnTarget[managedFieldCount];
2420 for (int i = 0; i < managedFieldCount; i++) {
2421 targetsOp[i] = new InsnTarget();
2422 }
2423
2424
2425 if (managedFieldCount <= 1) {
2426 final int[] matchesOp
2427 = (managedFieldCount == 0 ? new int[]{} : new int[]{ lowOp });
2428 insn = insn.append(
2429 new InsnLookupSwitch(defaultOp, matchesOp, targetsOp));
2430 } else {
2431 insn = insn.append(
2432 new InsnTableSwitch(lowOp, defaultOp, targetsOp));
2433 }
2434
2435
2436 for (int i = 0; i < managedFieldCount; i++) {
2437
2438 insn = insn.append(targetsOp[i]);
2439
2440
2441 final String sig = managedFieldSigs[i];
2442 final ConstFieldRef ref = managedFieldRefs[i];
2443 affirm(sig != null && sig.length() > 0);
2444 affirm(ref != null);
2445
2446
2447 sizeHolder.size = max(sizeHolder.size,
2448 Descriptor.countFieldWords(sig));
2449
2450
2451 switch (sig.charAt(0)) {
2452 case 'Z':
2453 insn = appendCaseBranchForReplaceField(
2454 insn,
2455 JDO_SM_replacingBooleanField_Name,
2456 JDO_SM_replacingBooleanField_Sig,
2457 ref, sig);
2458 break;
2459 case 'C':
2460 insn = appendCaseBranchForReplaceField(
2461 insn,
2462 JDO_SM_replacingCharField_Name,
2463 JDO_SM_replacingCharField_Sig,
2464 ref, sig);
2465 break;
2466 case 'B':
2467 insn = appendCaseBranchForReplaceField(
2468 insn,
2469 JDO_SM_replacingByteField_Name,
2470 JDO_SM_replacingByteField_Sig,
2471 ref, sig);
2472 break;
2473 case 'S':
2474 insn = appendCaseBranchForReplaceField(
2475 insn,
2476 JDO_SM_replacingShortField_Name,
2477 JDO_SM_replacingShortField_Sig,
2478 ref, sig);
2479 break;
2480 case 'I':
2481 insn = appendCaseBranchForReplaceField(
2482 insn,
2483 JDO_SM_replacingIntField_Name,
2484 JDO_SM_replacingIntField_Sig,
2485 ref, sig);
2486 break;
2487 case 'J':
2488 insn = appendCaseBranchForReplaceField(
2489 insn,
2490 JDO_SM_replacingLongField_Name,
2491 JDO_SM_replacingLongField_Sig,
2492 ref, sig);
2493 break;
2494 case 'F':
2495 insn = appendCaseBranchForReplaceField(
2496 insn,
2497 JDO_SM_replacingFloatField_Name,
2498 JDO_SM_replacingFloatField_Sig,
2499 ref, sig);
2500 break;
2501 case 'D':
2502 insn = appendCaseBranchForReplaceField(
2503 insn,
2504 JDO_SM_replacingDoubleField_Name,
2505 JDO_SM_replacingDoubleField_Sig,
2506 ref, sig);
2507 break;
2508 case 'L':
2509 case '[':
2510 if (sig.equals(JAVA_String_Sig)) {
2511 insn = appendCaseBranchForReplaceField(
2512 insn,
2513 JDO_SM_replacingStringField_Name,
2514 JDO_SM_replacingStringField_Sig,
2515 ref, sig);
2516 } else {
2517 insn = appendCaseBranchForReplaceField(
2518 insn,
2519 JDO_SM_replacingObjectField_Name,
2520 JDO_SM_replacingObjectField_Sig,
2521 ref, sig);
2522 }
2523 break;
2524 default:
2525 affirm(false, "Illegal field type: " + sig);
2526 }
2527 }
2528
2529
2530 insn = insn.append(defaultOp);
2531
2532 affirm(insn != null);
2533 return insn;
2534 }
2535
2536 /***
2537 * Build the jdoReplaceField method for the class.
2538 *
2539 * public void jdoReplaceField(int fieldnumber)
2540 * {
2541 * final javax.jdo.StateManager sm = this.jdoStateManager;
2542 * switch(fieldnumber - jdoInheritedFieldCount) {
2543 * case 0:
2544 * this.yyy = (XXX)sm.replacingXXXField(this, fieldnumber);
2545 * return;
2546 * case 1:
2547 * ...
2548 * default:
2549 * <if (isPCRoot) {>
2550 * throw new javax.jdo.JDOFatalInternalException();
2551 * <} else {>
2552 * super.jdoReplaceField(fieldnumber);
2553 * <}>
2554 * }
2555 * }
2556 */
2557 public void addJDOReplaceFieldMethod()
2558 {
2559 final String methodName = JDO_PC_jdoReplaceField_Name;
2560 final String methodSig = JDO_PC_jdoReplaceField_Sig;
2561 final int accessFlags = JDO_PC_jdoReplaceField_Mods;
2562 final ExceptionsAttribute exceptAttr = null;
2563
2564
2565 final InsnTarget begin = new InsnTarget();
2566 Insn insn = begin;
2567
2568
2569 insn = appendBeginProvideReplaceField(insn);
2570
2571
2572 final SizeHolder sizeHolder = new SizeHolder();
2573 insn = appendSwitchForReplaceField(insn, sizeHolder);
2574
2575
2576 insn = appendEndProvideReplaceField(insn,
2577 JDO_PC_jdoReplaceField_Name,
2578 JDO_PC_jdoReplaceField_Sig);
2579
2580
2581 affirm(insn.opcode() == opc_athrow || insn.opcode() == opc_return);
2582
2583 affirm(0 <= sizeHolder.size && sizeHolder.size <= 2);
2584
2585 final int maxStack = (sizeHolder.size == 0 ? 3 : 4);
2586 final CodeAttribute codeAttr
2587 = new CodeAttribute(getCodeAttributeUtf8(),
2588 maxStack,
2589 3,
2590 begin,
2591 new ExceptionTable(),
2592 new AttributeVector());
2593 augmenter.addMethod(methodName, methodSig, accessFlags,
2594 codeAttr, exceptAttr);
2595 }
2596
2597
2598
2599 /***
2600 * Adds the code for the begin of the jdoCopyField method.
2601 */
2602 private Insn appendBeginCopyField(Insn insn)
2603 {
2604 affirm(insn != null);
2605
2606
2607 insn = insn.append(Insn.create(opc_iload_2));
2608 insn = insn.append(
2609 Insn.create(opc_getstatic,
2610 pool.addFieldRef(
2611 className,
2612 JDO_PC_jdoInheritedFieldCount_Name,
2613 JDO_PC_jdoInheritedFieldCount_Sig)));
2614 insn = insn.append(Insn.create(opc_isub));
2615
2616 affirm(insn != null);
2617 return insn;
2618 }
2619
2620 /***
2621 * Adds the default-branch code for the jdoCopyField method.
2622 */
2623 private Insn appendEndCopyField(Insn insn)
2624 {
2625 affirm(insn != null);
2626
2627
2628 final boolean isPCRoot = analyzer.isAugmentableAsRoot();
2629 if (isPCRoot) {
2630 insn = appendThrowJavaException(insn,
2631 JAVA_IllegalArgumentException_Path,
2632 "arg2");
2633 } else {
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644 final String superClassName = analyzer.getPCSuperClassName();
2645 affirm(superClassName != null);
2646 final String jdo_PC_jdoCopyField_Sig
2647 = JDONameHelper.getJDO_PC_jdoCopyField_Sig(superClassName);
2648 insn = insn.append(Insn.create(opc_aload_0));
2649 insn = insn.append(Insn.create(opc_aload_1));
2650 insn = insn.append(Insn.create(opc_iload_2));
2651 insn = insn.append(
2652 Insn.create(opc_invokespecial,
2653 pool.addMethodRef(
2654 superClassName,
2655 JDO_PC_jdoCopyField_Name,
2656 jdo_PC_jdoCopyField_Sig)));
2657 insn = insn.append(Insn.create(opc_return));
2658 }
2659
2660 affirm(insn != null);
2661 return insn;
2662 }
2663
2664 /***
2665 * Adds the code for one case-branch in the jdoCopyField method.
2666 */
2667 private Insn appendCaseBranchForCopyField(Insn insn,
2668 ConstFieldRef managedFieldRef)
2669 {
2670 affirm(insn != null);
2671 affirm(managedFieldRef != null);
2672
2673
2674 insn = appendCheckVarNonNull(insn, 1,
2675 JAVA_IllegalArgumentException_Path,
2676 "arg1");
2677
2678
2679 insn = insn.append(Insn.create(opc_aload_0));
2680 insn = insn.append(Insn.create(opc_aload_1));
2681 insn = insn.append(Insn.create(opc_getfield, managedFieldRef));
2682 insn = insn.append(Insn.create(opc_putfield, managedFieldRef));
2683
2684
2685 insn = insn.append(Insn.create(opc_return));
2686
2687 affirm(insn != null);
2688 return insn;
2689 }
2690
2691 /***
2692 * Adds the switch code for the jdoCopyField method.
2693 */
2694 private Insn appendSwitchForCopyField(Insn insn)
2695 {
2696 affirm(insn != null);
2697
2698
2699 final int managedFieldCount = analyzer.getManagedFieldCount();
2700
2701
2702
2703
2704
2705 final String[] managedFieldSigs = analyzer.getAnnotatedFieldSigs();
2706 final ConstFieldRef[] managedFieldRefs = getAnnotatedFieldRefs();
2707 affirm(managedFieldSigs.length >= managedFieldCount);
2708 affirm(managedFieldRefs.length >= managedFieldCount);
2709
2710
2711 final int lowOp = 0;
2712 final InsnTarget defaultOp = new InsnTarget();
2713 final InsnTarget[] targetsOp = new InsnTarget[managedFieldCount];
2714 for (int i = 0; i < managedFieldCount; i++) {
2715 targetsOp[i] = new InsnTarget();
2716 }
2717
2718
2719 if (managedFieldCount <= 1) {
2720 final int[] matchesOp
2721 = (managedFieldCount == 0 ? new int[]{} : new int[]{ lowOp });
2722 insn = insn.append(
2723 new InsnLookupSwitch(defaultOp, matchesOp, targetsOp));
2724 } else {
2725 insn = insn.append(
2726 new InsnTableSwitch(lowOp, defaultOp, targetsOp));
2727 }
2728
2729
2730 for (int i = 0; i < managedFieldCount; i++) {
2731
2732 insn = insn.append(targetsOp[i]);
2733
2734
2735 final String sig = managedFieldSigs[i];
2736 final ConstFieldRef ref = managedFieldRefs[i];
2737 affirm(sig != null && sig.length() > 0);
2738 affirm(ref != null);
2739
2740
2741 switch (sig.charAt(0)) {
2742 case 'Z':
2743 insn = appendCaseBranchForCopyField(insn, ref);
2744 break;
2745 case 'C':
2746 insn = appendCaseBranchForCopyField(insn, ref);
2747 break;
2748 case 'B':
2749 insn = appendCaseBranchForCopyField(insn, ref);
2750 break;
2751 case 'S':
2752 insn = appendCaseBranchForCopyField(insn, ref);
2753 break;
2754 case 'I':
2755 insn = appendCaseBranchForCopyField(insn, ref);
2756 break;
2757 case 'J':
2758 insn = appendCaseBranchForCopyField(insn, ref);
2759 break;
2760 case 'F':
2761 insn = appendCaseBranchForCopyField(insn, ref);
2762 break;
2763 case 'D':
2764 insn = appendCaseBranchForCopyField(insn, ref);
2765 break;
2766 case 'L':
2767 case '[':
2768 insn = appendCaseBranchForCopyField(insn, ref);
2769 break;
2770 default:
2771 affirm(false, "Illegal field type: " + sig);
2772 }
2773 }
2774
2775
2776 insn = insn.append(defaultOp);
2777
2778 affirm(insn != null);
2779 return insn;
2780 }
2781
2782 /***
2783 * Build the jdoCopyField method for the class.
2784 *
2785 * protected final void jdoCopyField(XXX pc, int fieldnumber)
2786 * {
2787 * switch(fieldnumber - jdoInheritedFieldCount) {
2788 * case 0:
2789 * this.yyy = pc.yyy;
2790 * return;
2791 * case 1:
2792 * ...
2793 * default:
2794 * <if (isPCRoot) {>
2795 * throw new javax.jdo.JDOFatalInternalException();
2796 * <} else {>
2797 * super.jdoCopyField(pc, fieldnumber);
2798 * <}>
2799 * }
2800 * }
2801 */
2802 public void addJDOCopyFieldMethod()
2803 {
2804 final String methodName = JDO_PC_jdoCopyField_Name;
2805 final String methodSig
2806 = JDONameHelper.getJDO_PC_jdoCopyField_Sig(className);
2807 final int accessFlags = JDO_PC_jdoCopyField_Mods;
2808 final ExceptionsAttribute exceptAttr = null;
2809
2810
2811 final InsnTarget begin = new InsnTarget();
2812 Insn insn = begin;
2813
2814
2815 insn = appendBeginCopyField(insn);
2816
2817
2818 insn = appendSwitchForCopyField(insn);
2819
2820
2821 insn = appendEndCopyField(insn);
2822
2823
2824 affirm(insn.opcode() == opc_athrow || insn.opcode() == opc_return);
2825
2826 final CodeAttribute codeAttr
2827 = new CodeAttribute(getCodeAttributeUtf8(),
2828 3,
2829 3,
2830 begin,
2831 new ExceptionTable(),
2832 new AttributeVector());
2833 augmenter.addMethod(methodName, methodSig, accessFlags,
2834 codeAttr, exceptAttr);
2835 }
2836
2837
2838
2839 /***
2840 * Build the jdoArrayArgumentIteration method for the class.
2841 *
2842 * public void jdoCopyFields(java.lang.Object pc, int[] fieldnumbers)
2843 * {
2844 * final XXX other = (XXX)pc;
2845 * if (other.jdoStateManager != this.jdoStateManager
2846 * || this.jdoStateManager == null) {
2847 * throw new javax.jdo.JDOFatalInternalException();
2848 * }
2849 * final int n = fieldnumbers.length;
2850 * for (int i = 0; i < n; i++) {
2851 * this.jdoCopyField(other, fieldnumbers[i]);
2852 * }
2853 * }
2854 */
2855 public void addJDOCopyFieldsMethod()
2856 {
2857 final String methodName = JDO_PC_jdoCopyFields_Name;
2858 final String methodSig = JDO_PC_jdoCopyFields_Sig;
2859 final int accessFlags = JDO_PC_jdoCopyFields_Mods;
2860 final ExceptionsAttribute exceptAttr = null;
2861
2862
2863 final InsnTarget begin = new InsnTarget();
2864 Insn insn = begin;
2865
2866
2867 insn = appendCheckStateManager(insn, 0,
2868 JAVA_IllegalStateException_Path,
2869 "arg0." + JDO_PC_jdoStateManager_Name);
2870
2871
2872 final ConstClass thisConstClass = classFile.className();
2873 affirm(thisConstClass != null);
2874 insn = appendCheckVarInstanceOf(insn, 1, thisConstClass,
2875 JAVA_IllegalArgumentException_Path,
2876 "arg1");
2877
2878
2879 insn = appendCheckVarNonNull(insn, 2,
2880 JAVA_IllegalArgumentException_Path,
2881 "arg2");
2882
2883
2884 insn = insn.append(Insn.create(opc_aload_1));
2885 insn = insn.append(Insn.create(opc_checkcast, thisConstClass));
2886 insn = insn.append(Insn.create(opc_astore_3));
2887
2888
2889 final InsnTarget endcheck = new InsnTarget();
2890 insn = insn.append(Insn.create(opc_aload_3));
2891 insn = insn.append(
2892 Insn.create(
2893 opc_getfield,
2894 getjdoStateManagerFieldRef()));
2895 insn = insn.append(Insn.create(opc_aload_0));
2896 insn = insn.append(
2897 Insn.create(
2898 opc_getfield,
2899 getjdoStateManagerFieldRef()));
2900 insn = insn.append(Insn.create(opc_if_acmpeq, endcheck));
2901 insn = appendThrowJavaException(insn,
2902 JAVA_IllegalArgumentException_Path,
2903 "arg1." + JDO_PC_jdoStateManager_Name);
2904
2905
2906 insn = insn.append(endcheck);
2907 insn = insn.append(Insn.create(opc_aload_2));
2908 insn = insn.append(Insn.create(opc_arraylength));
2909 insn = insn.append(Insn.create(opc_istore, 4));
2910
2911
2912 final InsnTarget loopcheck = new InsnTarget();
2913 insn = insn.append(Insn.create(opc_iconst_0));
2914 insn = insn.append(Insn.create(opc_istore, 5));
2915 insn = insn.append(Insn.create(opc_goto, loopcheck));
2916
2917
2918 final InsnTarget loopbody = new InsnTarget();
2919 insn = insn.append(loopbody);
2920 insn = insn.append(Insn.create(opc_aload_0));
2921 insn = insn.append(Insn.create(opc_aload_3));
2922
2923
2924 insn = insn.append(Insn.create(opc_aload_2));
2925 insn = insn.append(Insn.create(opc_iload, 5));
2926 insn = insn.append(Insn.create(opc_iaload));
2927
2928
2929 final String delegateName = JDO_PC_jdoCopyField_Name;
2930 final String delegateSig
2931 = JDONameHelper.getJDO_PC_jdoCopyField_Sig(className);
2932 insn = insn.append(
2933 Insn.create(opc_invokevirtual,
2934 pool.addMethodRef(
2935 className,
2936 delegateName,
2937 delegateSig)));
2938
2939
2940 insn = insn.append(new InsnIInc(5, 1));
2941
2942
2943 insn = insn.append(loopcheck);
2944 insn = insn.append(Insn.create(opc_iload, 5));
2945 insn = insn.append(Insn.create(opc_iload, 4));
2946 insn = insn.append(Insn.create(opc_if_icmplt, loopbody));
2947
2948
2949 insn = insn.append(Insn.create(opc_return));
2950
2951 final CodeAttribute codeAttr
2952 = new CodeAttribute(getCodeAttributeUtf8(),
2953 4,
2954 6,
2955 begin,
2956 new ExceptionTable(),
2957 new AttributeVector());
2958 augmenter.addMethod(methodName, methodSig, accessFlags,
2959 codeAttr, exceptAttr);
2960 }
2961
2962
2963
2964 /***
2965 * Build the jdoNewObjectIdInstance method for the class.
2966 *
2967 * public java.lang.Object jdoNewObjectIdInstance()
2968 * {
2969 * return new XXX();
2970 * }
2971 */
2972 public void addJDONewObjectIdInstanceMethod()
2973 {
2974 final String methodName = JDO_PC_jdoNewObjectIdInstance_Name;
2975 final String methodSig = JDO_PC_jdoNewObjectIdInstance_Sig;
2976 final int accessFlags = JDO_PC_jdoNewObjectIdInstance_Mods;
2977 final ExceptionsAttribute exceptAttr = null;
2978
2979
2980 final InsnTarget begin = new InsnTarget();
2981 Insn insn = begin;
2982
2983
2984 final String keyClassName = analyzer.getKeyClassName();
2985 if (keyClassName == null){
2986
2987 insn = insn.append(Insn.create(opc_aconst_null));
2988 insn = insn.append(Insn.create(opc_areturn));
2989
2990 final CodeAttribute codeAttr
2991 = new CodeAttribute(getCodeAttributeUtf8(),
2992 1,
2993 1,
2994 begin,
2995 new ExceptionTable(),
2996 new AttributeVector());
2997 augmenter.addMethod(methodName, methodSig, accessFlags,
2998 codeAttr, exceptAttr);
2999 return;
3000 }
3001 affirm(keyClassName != null);
3002
3003
3004 insn = insn.append(
3005 Insn.create(opc_new,
3006 pool.addClass(keyClassName)));
3007 insn = insn.append(Insn.create(opc_dup));
3008 insn = insn.append(
3009 Insn.create(opc_invokespecial,
3010 pool.addMethodRef(
3011 keyClassName,
3012 NameHelper.constructorName(),
3013 NameHelper.constructorSig())));
3014
3015
3016 insn = insn.append(Insn.create(opc_areturn));
3017
3018 final CodeAttribute codeAttr
3019 = new CodeAttribute(getCodeAttributeUtf8(),
3020 2,
3021 1,
3022 begin,
3023 new ExceptionTable(),
3024 new AttributeVector());
3025 augmenter.addMethod(methodName, methodSig, accessFlags,
3026 codeAttr, exceptAttr);
3027 }
3028
3029 /***
3030 * Build the jdoNewObjectIdInstance method for the class.
3031 *
3032 * public java.lang.Object jdoNewObjectIdInstance(Object o)
3033 * {
3034 * throw new UnsupportedOperationException(
3035 * "Method jdoNewObjectIdInstance not yet implemented");
3036 * }
3037 */
3038 public void addJDONewObjectIdInstanceObjectMethod()
3039 {
3040 final String methodName = JDO_PC_jdoNewObjectIdInstance_Object_Name;
3041 final String methodSig = JDO_PC_jdoNewObjectIdInstance_Object_Sig;
3042 final int accessFlags = JDO_PC_jdoNewObjectIdInstance_Object_Mods;
3043 final ExceptionsAttribute exceptAttr = null;
3044
3045
3046 final InsnTarget begin = new InsnTarget();
3047 Insn insn = begin;
3048
3049
3050 final String keyClassName = analyzer.getKeyClassName();
3051 if (keyClassName == null){
3052
3053 insn = insn.append(Insn.create(opc_aconst_null));
3054 insn = insn.append(Insn.create(opc_areturn));
3055
3056 final CodeAttribute codeAttr
3057 = new CodeAttribute(getCodeAttributeUtf8(),
3058 1,
3059 2,
3060 begin,
3061 new ExceptionTable(),
3062 new AttributeVector());
3063 augmenter.addMethod(methodName, methodSig, accessFlags,
3064 codeAttr, exceptAttr);
3065 return;
3066 }
3067 affirm(keyClassName != null);
3068
3069
3070
3071
3072 insn = insn.append(
3073 Insn.create(opc_new,
3074 pool.addClass(keyClassName)));
3075 insn = insn.append(Insn.create(opc_dup));
3076 insn = insn.append(Insn.create(opc_aload_1));
3077 insn = insn.append(Insn.create(opc_checkcast,
3078 pool.addClass(JAVA_String_Path)));
3079 insn = insn.append(
3080 Insn.create(opc_invokespecial,
3081 pool.addMethodRef(
3082 keyClassName,
3083 NameHelper.constructorName(),
3084 NameHelper.constructorSig(JAVA_String_Sig))));
3085
3086
3087 insn = insn.append(Insn.create(opc_areturn));
3088
3089 final CodeAttribute codeAttr
3090 = new CodeAttribute(getCodeAttributeUtf8(),
3091 3,
3092 2,
3093 begin,
3094 new ExceptionTable(),
3095 new AttributeVector());
3096 augmenter.addMethod(methodName, methodSig, accessFlags,
3097 codeAttr, exceptAttr);
3098 }
3099
3100
3101
3102 /***
3103 * Build the jdoCopyKeyFieldsToObjectId method for the class.
3104 */
3105 public void addJDOCopyKeyFieldsToObjectIdMethod()
3106 {
3107 addJDOCopyKeyFieldsToFromObjectIdMethod(true);
3108 }
3109
3110 /***
3111 * Build the jdoCopyKeyFieldsFromObjectId method for the class.
3112 */
3113 public void addJDOCopyKeyFieldsFromObjectIdMethod()
3114 {
3115 addJDOCopyKeyFieldsToFromObjectIdMethod(false);
3116 }
3117
3118 /***
3119 * Build the jdoCopyKeyFieldsTo/FromObjectId method for the class.
3120 *
3121 * public void jdoCopyKeyFieldsTo/FromObjectId(Object oid)
3122 * {
3123 * if (!(oid instanceof XXX)) {
3124 * throw new IllegalArgumentException("arg0");
3125 * }
3126 * final XXX _oid = (XXX)oid;
3127 * <if (superKeyClassname != null) {>
3128 * super.jdoCopyKeyFieldsToObjectId(oid);
3129 * <}>
3130 * _oid.yyy = this.yyy;
3131 * ...
3132 * }
3133 */
3134 private void addJDOCopyKeyFieldsToFromObjectIdMethod(boolean isToOid)
3135 {
3136 final String methodName;
3137 final String methodSig;
3138 final int accessFlags;
3139 if (isToOid) {
3140 methodName = JDO_PC_jdoCopyKeyFieldsToObjectId_Name;
3141 methodSig = JDO_PC_jdoCopyKeyFieldsToObjectId_Sig;
3142 accessFlags = JDO_PC_jdoCopyKeyFieldsToObjectId_Mods;
3143 } else {
3144 methodName = JDO_PC_jdoCopyKeyFieldsFromObjectId_Name;
3145 methodSig = JDO_PC_jdoCopyKeyFieldsFromObjectId_Sig;
3146 accessFlags = JDO_PC_jdoCopyKeyFieldsFromObjectId_Mods;
3147 }
3148 final ExceptionsAttribute exceptAttr = null;
3149
3150
3151 final InsnTarget begin = new InsnTarget();
3152 Insn insn = begin;
3153
3154
3155 final String keyClassName = analyzer.getKeyClassName();
3156 if (keyClassName == null){
3157
3158 insn = insn.append(Insn.create(opc_return));
3159
3160 final CodeAttribute codeAttr
3161 = new CodeAttribute(getCodeAttributeUtf8(),
3162 0,
3163 2,
3164 begin,
3165 new ExceptionTable(),
3166 new AttributeVector());
3167 augmenter.addMethod(methodName, methodSig, accessFlags,
3168 codeAttr, exceptAttr);
3169 return;
3170 }
3171 affirm(keyClassName != null);
3172
3173
3174 final ConstClass keyConstClass = pool.addClass(keyClassName);
3175 affirm(keyConstClass != null);
3176 insn = appendCheckVarInstanceOf(insn, 1, keyConstClass,
3177 JAVA_IllegalArgumentException_Path,
3178 "arg1");
3179
3180
3181 insn = insn.append(Insn.create(opc_aload_1));
3182 insn = insn.append(Insn.create(opc_checkcast, keyConstClass));
3183 insn = insn.append(Insn.create(opc_astore_2));
3184
3185
3186 final boolean isPCRoot = analyzer.isAugmentableAsRoot();
3187 if (!isPCRoot) {
3188
3189
3190
3191
3192
3193
3194
3195
3196 final String superClassName
3197 = analyzer.getPCSuperKeyOwnerClassName();
3198 affirm(superClassName != null);
3199 insn = insn.append(Insn.create(opc_aload_0));
3200 insn = insn.append(Insn.create(opc_aload_2));
3201 insn = insn.append(
3202 Insn.create(opc_invokespecial,
3203 pool.addMethodRef(
3204 superClassName,
3205 methodName,
3206 methodSig)));
3207 }
3208
3209
3210 final int keyFieldCount = analyzer.getKeyFieldCount();
3211 final ConstFieldRef[] keyFieldRefs = getKeyFieldRefs();
3212 final ConstFieldRef[] keyClassKeyFieldRefs = getKeyClassKeyFieldRefs();
3213 affirm(keyFieldRefs.length == keyFieldCount);
3214 affirm(keyClassKeyFieldRefs.length == keyFieldCount);
3215
3216
3217 int maxFieldSize = 0;
3218 for (int i = 0; i < keyFieldCount; i++) {
3219
3220 final ConstFieldRef thisClassKeyRef = keyFieldRefs[i];
3221 final ConstFieldRef keyClassKeyRef = keyClassKeyFieldRefs[i];
3222 affirm(thisClassKeyRef != null);
3223 affirm(keyClassKeyRef != null);
3224 if (isToOid) {
3225 insn = insn.append(Insn.create(opc_aload_2));
3226 insn = insn.append(Insn.create(opc_aload_0));
3227 insn = insn.append(Insn.create(opc_getfield, thisClassKeyRef));
3228 insn = insn.append(Insn.create(opc_putfield, keyClassKeyRef));
3229 } else {
3230 insn = insn.append(Insn.create(opc_aload_0));
3231 insn = insn.append(Insn.create(opc_aload_2));
3232 insn = insn.append(Insn.create(opc_getfield, keyClassKeyRef));
3233 insn = insn.append(Insn.create(opc_putfield, thisClassKeyRef));
3234 }
3235
3236
3237 final String sig
3238 = thisClassKeyRef.nameAndType().signature().asString();
3239 affirm(sig != null && sig.length() > 0);
3240 maxFieldSize = max(maxFieldSize, Descriptor.countFieldWords(sig));
3241 }
3242
3243
3244 insn = insn.append(Insn.create(opc_return));
3245
3246 final CodeAttribute codeAttr
3247 = new CodeAttribute(getCodeAttributeUtf8(),
3248 max(maxFieldSize + 1, 3),
3249 3,
3250 begin,
3251 new ExceptionTable(),
3252 new AttributeVector());
3253 augmenter.addMethod(methodName, methodSig, accessFlags,
3254 codeAttr, exceptAttr);
3255 }
3256
3257 /***
3258 * Adds the code for one case-branch in the jdoCopyKeyFieldsToObjectId.
3259 */
3260 private Insn appendCopyKeyFieldToOid(Insn insn,
3261 String fetchXXXField_Name,
3262 String fetchXXXField_Sig,
3263 int keyFieldNo,
3264 ConstFieldRef keyFieldRef,
3265 String keyFieldSig)
3266 {
3267 affirm(insn != null);
3268 affirm(fetchXXXField_Name != null);
3269 affirm(fetchXXXField_Sig != null);
3270 affirm(keyFieldNo >= 0);
3271 affirm(keyFieldRef != null);
3272 affirm(keyFieldSig != null && keyFieldSig.length() > 0);
3273
3274
3275 insn = insn.append(Insn.create(opc_aload_3));
3276 insn = insn.append(Insn.create(opc_aload_1));
3277
3278
3279 insn = insn.append(
3280 Insn.create(opc_getstatic,
3281 pool.addFieldRef(
3282 className,
3283 JDO_PC_jdoInheritedFieldCount_Name,
3284 JDO_PC_jdoInheritedFieldCount_Sig)));
3285 insn = insn.append(InsnUtils.integerConstant(keyFieldNo, pool));
3286 insn = insn.append(Insn.create(opc_iadd));
3287
3288
3289 insn = insn.append(
3290 new InsnInterfaceInvoke(
3291 pool.addInterfaceMethodRef(
3292 JDO_ObjectIdFieldSupplier_Path,
3293 fetchXXXField_Name,
3294 fetchXXXField_Sig),
3295 countMethodArgWords(fetchXXXField_Sig)));
3296
3297
3298 if (fetchXXXField_Name.equals(JDO_OIFS_fetchObjectField_Name)
3299 && !keyFieldSig.equals(JAVA_Object_Sig)) {
3300 final String fieldType = NameHelper.pathForSig(keyFieldSig);
3301 insn = insn.append(
3302 Insn.create(opc_checkcast,
3303 pool.addClass(fieldType)));
3304 }
3305
3306
3307 insn = insn.append(Insn.create(opc_putfield, keyFieldRef));
3308
3309 affirm(insn != null);
3310 return insn;
3311 }
3312
3313 /***
3314 * Adds the field assignment code for the jdoCopyKeyFieldsToObjectId.
3315 */
3316 private Insn appendStatementsForCopyKeyFieldsToOid(Insn insn,
3317 SizeHolder sizeHolder)
3318 {
3319 affirm(insn != null);
3320 affirm(sizeHolder != null);
3321
3322
3323 final int keyFieldCount = analyzer.getKeyFieldCount();
3324 final ConstFieldRef[] keyFieldRefs = getKeyClassKeyFieldRefs();
3325 final int[] keyFieldIndexes = analyzer.getKeyFieldIndexes();
3326 affirm(keyFieldRefs.length == keyFieldCount);
3327 affirm(keyFieldIndexes.length == keyFieldCount);
3328
3329
3330 for (int i = 0; i < keyFieldCount; i++) {
3331
3332 final int no = keyFieldIndexes[i];
3333 final ConstFieldRef ref = keyFieldRefs[i];
3334 affirm(ref != null);
3335 final String sig = ref.nameAndType().signature().asString();
3336 affirm(sig != null && sig.length() > 0);
3337
3338
3339 sizeHolder.size = max(sizeHolder.size,
3340 Descriptor.countFieldWords(sig));
3341
3342
3343 switch (sig.charAt(0)) {
3344 case 'Z':
3345 insn = appendCopyKeyFieldToOid(
3346 insn,
3347 JDO_OIFS_fetchBooleanField_Name,
3348 JDO_OIFS_fetchBooleanField_Sig,
3349 no, ref, sig);
3350 break;
3351 case 'C':
3352 insn = appendCopyKeyFieldToOid(
3353 insn,
3354 JDO_OIFS_fetchCharField_Name,
3355 JDO_OIFS_fetchCharField_Sig,
3356 no, ref, sig);
3357 break;
3358 case 'B':
3359 insn = appendCopyKeyFieldToOid(
3360 insn,
3361 JDO_OIFS_fetchByteField_Name,
3362 JDO_OIFS_fetchByteField_Sig,
3363 no, ref, sig);
3364 break;
3365 case 'S':
3366 insn = appendCopyKeyFieldToOid(
3367 insn,
3368 JDO_OIFS_fetchShortField_Name,
3369 JDO_OIFS_fetchShortField_Sig,
3370 no, ref, sig);
3371 break;
3372 case 'I':
3373 insn = appendCopyKeyFieldToOid(
3374 insn,
3375 JDO_OIFS_fetchIntField_Name,
3376 JDO_OIFS_fetchIntField_Sig,
3377 no, ref, sig);
3378 break;
3379 case 'J':
3380 insn = appendCopyKeyFieldToOid(
3381 insn,
3382 JDO_OIFS_fetchLongField_Name,
3383 JDO_OIFS_fetchLongField_Sig,
3384 no, ref, sig);
3385 break;
3386 case 'F':
3387 insn = appendCopyKeyFieldToOid(
3388 insn,
3389 JDO_OIFS_fetchFloatField_Name,
3390 JDO_OIFS_fetchFloatField_Sig,
3391 no, ref, sig);
3392 break;
3393 case 'D':
3394 insn = appendCopyKeyFieldToOid(
3395 insn,
3396 JDO_OIFS_fetchDoubleField_Name,
3397 JDO_OIFS_fetchDoubleField_Sig,
3398 no, ref, sig);
3399 break;
3400 case 'L':
3401 case '[':
3402 if (sig.equals(JAVA_String_Sig)) {
3403 insn = appendCopyKeyFieldToOid(
3404 insn,
3405 JDO_OIFS_fetchStringField_Name,
3406 JDO_OIFS_fetchStringField_Sig,
3407 no, ref, sig);
3408 } else {
3409 insn = appendCopyKeyFieldToOid(
3410 insn,
3411 JDO_OIFS_fetchObjectField_Name,
3412 JDO_OIFS_fetchObjectField_Sig,
3413 no, ref, sig);
3414 }
3415 break;
3416 default:
3417 affirm(false, "Illegal field type: " + sig);
3418 }
3419 }
3420
3421 affirm(insn != null);
3422 return insn;
3423 }
3424
3425 /***
3426 * Adds the code for one case-branch in the jdoCopyKeyFieldsFromObjectId.
3427 */
3428 private Insn appendCopyKeyFieldFromOid(Insn insn,
3429 String storeXXXField_Name,
3430 String storeXXXField_Sig,
3431 int keyFieldNo,
3432 ConstFieldRef keyFieldRef)
3433 {
3434 affirm(insn != null);
3435 affirm(storeXXXField_Name != null);
3436 affirm(storeXXXField_Sig != null);
3437 affirm(keyFieldNo >= 0);
3438 affirm(keyFieldRef != null);
3439
3440
3441 insn = insn.append(Insn.create(opc_aload_1));
3442
3443
3444 insn = insn.append(
3445 Insn.create(opc_getstatic,
3446 pool.addFieldRef(
3447 className,
3448 JDO_PC_jdoInheritedFieldCount_Name,
3449 JDO_PC_jdoInheritedFieldCount_Sig)));
3450 insn = insn.append(InsnUtils.integerConstant(keyFieldNo, pool));
3451 insn = insn.append(Insn.create(opc_iadd));
3452
3453
3454 insn = insn.append(Insn.create(opc_aload_3));
3455 insn = insn.append(Insn.create(opc_getfield, keyFieldRef));
3456
3457
3458 insn = insn.append(
3459 new InsnInterfaceInvoke(
3460 pool.addInterfaceMethodRef(
3461 JDO_ObjectIdFieldConsumer_Path,
3462 storeXXXField_Name,
3463 storeXXXField_Sig),
3464 countMethodArgWords(storeXXXField_Sig)));
3465
3466 affirm(insn != null);
3467 return insn;
3468 }
3469
3470 /***
3471 * Adds the field assignment code for the jdoCopyKeyFieldsFromObjectId.
3472 */
3473 private Insn appendStatementsForCopyKeyFieldsFromOid(Insn insn,
3474 SizeHolder sizeHolder)
3475 {
3476 affirm(insn != null);
3477 affirm(sizeHolder != null);
3478
3479
3480 final int keyFieldCount = analyzer.getKeyFieldCount();
3481 final ConstFieldRef[] keyFieldRefs = getKeyClassKeyFieldRefs();
3482 final int[] keyFieldIndexes = analyzer.getKeyFieldIndexes();
3483 affirm(keyFieldRefs.length == keyFieldCount);
3484 affirm(keyFieldIndexes.length == keyFieldCount);
3485
3486
3487 for (int i = 0; i < keyFieldCount; i++) {
3488
3489 final int no = keyFieldIndexes[i];
3490 final ConstFieldRef ref = keyFieldRefs[i];
3491 affirm(ref != null);
3492 final String sig = ref.nameAndType().signature().asString();
3493 affirm(sig != null && sig.length() > 0);
3494
3495
3496 sizeHolder.size = max(sizeHolder.size,
3497 Descriptor.countFieldWords(sig));
3498
3499
3500 switch (sig.charAt(0)) {
3501 case 'Z':
3502 insn = appendCopyKeyFieldFromOid(
3503 insn,
3504 JDO_OIFC_storeBooleanField_Name,
3505 JDO_OIFC_storeBooleanField_Sig,
3506 no, ref);
3507 break;
3508 case 'C':
3509 insn = appendCopyKeyFieldFromOid(
3510 insn,
3511 JDO_OIFC_storeCharField_Name,
3512 JDO_OIFC_storeCharField_Sig,
3513 no, ref);
3514 break;
3515 case 'B':
3516 insn = appendCopyKeyFieldFromOid(
3517 insn,
3518 JDO_OIFC_storeByteField_Name,
3519 JDO_OIFC_storeByteField_Sig,
3520 no, ref);
3521 break;
3522 case 'S':
3523 insn = appendCopyKeyFieldFromOid(
3524 insn,
3525 JDO_OIFC_storeShortField_Name,
3526 JDO_OIFC_storeShortField_Sig,
3527 no, ref);
3528 break;
3529 case 'I':
3530 insn = appendCopyKeyFieldFromOid(
3531 insn,
3532 JDO_OIFC_storeIntField_Name,
3533 JDO_OIFC_storeIntField_Sig,
3534 no, ref);
3535 break;
3536 case 'J':
3537 insn = appendCopyKeyFieldFromOid(
3538 insn,
3539 JDO_OIFC_storeLongField_Name,
3540 JDO_OIFC_storeLongField_Sig,
3541 no, ref);
3542 break;
3543 case 'F':
3544 insn = appendCopyKeyFieldFromOid(
3545 insn,
3546 JDO_OIFC_storeFloatField_Name,
3547 JDO_OIFC_storeFloatField_Sig,
3548 no, ref);
3549 break;
3550 case 'D':
3551 insn = appendCopyKeyFieldFromOid(
3552 insn,
3553 JDO_OIFC_storeDoubleField_Name,
3554 JDO_OIFC_storeDoubleField_Sig,
3555 no, ref);
3556 break;
3557 case 'L':
3558 case '[':
3559 if (sig.equals(JAVA_String_Sig)) {
3560 insn = appendCopyKeyFieldFromOid(
3561 insn,
3562 JDO_OIFC_storeStringField_Name,
3563 JDO_OIFC_storeStringField_Sig,
3564 no, ref);
3565 } else {
3566 insn = appendCopyKeyFieldFromOid(
3567 insn,
3568 JDO_OIFC_storeObjectField_Name,
3569 JDO_OIFC_storeObjectField_Sig,
3570 no, ref);
3571 }
3572 break;
3573 default:
3574 affirm(false, "Illegal field type: " + sig);
3575 }
3576 }
3577
3578 affirm(insn != null);
3579 return insn;
3580 }
3581
3582 /***
3583 * Build the jdoCopyKeyFieldsToObjectId method for the class.
3584 */
3585 public void addJDOCopyKeyFieldsToObjectIdOIFSMethod()
3586 {
3587 addJDOCopyKeyFieldsToFromObjectIdOIFSMethod(true);
3588 }
3589
3590 /***
3591 * Build the jdoCopyKeyFieldsFromObjectId method for the class.
3592 */
3593 public void addJDOCopyKeyFieldsFromObjectIdOIFCMethod()
3594 {
3595 addJDOCopyKeyFieldsToFromObjectIdOIFSMethod(false);
3596 }
3597
3598 /***
3599 * Build the jdoCopyKeyFieldsTo/FromObjectId method for the class.
3600 *
3601 * public void jdoCopyKeyFieldsTo/FromObjectId(
3602 * ObjectIdFieldSupplier/Consumer fm,
3603 * Object oid)
3604 * {
3605 * if (fm == null) {
3606 * throw new IllegalArgumentException("arg0");
3607 * }
3608 * if (!(oid instanceof XXX)) {
3609 * throw new IllegalArgumentException("arg1");
3610 * }
3611 * final XXX _oid = (XXX)oid;
3612 * <if (superKeyClassname != null) {>
3613 * super.jdoCopyKeyFieldsTo/FromObjectId(fm, _oid);
3614 * <}>
3615 * _oid.yyy = ofs.fetchIntField(jdoInheritedFieldCount + 0);
3616 * / ofc.storeIntField(jdoInheritedFieldCount + 0, _oid.yyy);
3617 * ...
3618 * }
3619 */
3620 private void addJDOCopyKeyFieldsToFromObjectIdOIFSMethod(boolean isToOid)
3621 {
3622 final String methodName;
3623 final String methodSig;
3624 final int accessFlags;
3625 if (isToOid) {
3626 methodName = JDO_PC_jdoCopyKeyFieldsToObjectId_OIFS_Name;
3627 methodSig = JDO_PC_jdoCopyKeyFieldsToObjectId_OIFS_Sig;
3628 accessFlags = JDO_PC_jdoCopyKeyFieldsToObjectId_OIFS_Mods;
3629 } else {
3630 methodName = JDO_PC_jdoCopyKeyFieldsFromObjectId_OIFC_Name;
3631 methodSig = JDO_PC_jdoCopyKeyFieldsFromObjectId_OIFC_Sig;
3632 accessFlags = JDO_PC_jdoCopyKeyFieldsFromObjectId_OIFC_Mods;
3633 }
3634 final ExceptionsAttribute exceptAttr = null;
3635
3636
3637 final InsnTarget begin = new InsnTarget();
3638 Insn insn = begin;
3639
3640
3641 final String keyClassName = analyzer.getKeyClassName();
3642 if (keyClassName == null){
3643
3644 insn = insn.append(Insn.create(opc_return));
3645
3646 final CodeAttribute codeAttr
3647 = new CodeAttribute(getCodeAttributeUtf8(),
3648 0,
3649 3,
3650 begin,
3651 new ExceptionTable(),
3652 new AttributeVector());
3653 augmenter.addMethod(methodName, methodSig, accessFlags,
3654 codeAttr, exceptAttr);
3655 return;
3656 }
3657 affirm(keyClassName != null);
3658
3659
3660 insn = appendCheckVarNonNull(insn, 1,
3661 JAVA_IllegalArgumentException_Path,
3662 "arg1");
3663
3664
3665 final ConstClass keyConstClass = pool.addClass(keyClassName);
3666 affirm(keyConstClass != null);
3667 insn = appendCheckVarInstanceOf(insn, 2, keyConstClass,
3668 JAVA_IllegalArgumentException_Path,
3669 "arg2");
3670
3671
3672 insn = insn.append(Insn.create(opc_aload_2));
3673 insn = insn.append(Insn.create(opc_checkcast, keyConstClass));
3674 insn = insn.append(Insn.create(opc_astore_3));
3675
3676
3677 final boolean isPCRoot = analyzer.isAugmentableAsRoot();
3678 if (!isPCRoot) {
3679
3680
3681
3682
3683
3684
3685
3686
3687 final String superClassName
3688 = analyzer.getPCSuperKeyOwnerClassName();
3689 insn = insn.append(Insn.create(opc_aload_0));
3690 insn = insn.append(Insn.create(opc_aload_1));
3691 insn = insn.append(Insn.create(opc_aload_3));
3692 insn = insn.append(
3693 Insn.create(opc_invokespecial,
3694 pool.addMethodRef(
3695 superClassName,
3696 methodName,
3697 methodSig)));
3698 }
3699
3700
3701 final int keyFieldCount = analyzer.getKeyFieldCount();
3702 final ConstFieldRef[] keyFieldRefs = getKeyFieldRefs();
3703 final ConstFieldRef[] keyClassKeyFieldRefs = getKeyClassKeyFieldRefs();
3704 affirm(keyFieldRefs.length == keyFieldCount);
3705 affirm(keyClassKeyFieldRefs.length == keyFieldCount);
3706
3707
3708 final SizeHolder sizeHolder = new SizeHolder();
3709 if (isToOid) {
3710 insn = appendStatementsForCopyKeyFieldsToOid(insn, sizeHolder);
3711 } else {
3712 insn = appendStatementsForCopyKeyFieldsFromOid(insn, sizeHolder);
3713 }
3714
3715
3716 insn = insn.append(Insn.create(opc_return));
3717
3718 final CodeAttribute codeAttr
3719 = new CodeAttribute(getCodeAttributeUtf8(),
3720 max(sizeHolder.size
3721 + (isToOid ? 3 : 2), 3),
3722 4,
3723 begin,
3724 new ExceptionTable(),
3725 new AttributeVector());
3726 augmenter.addMethod(methodName, methodSig, accessFlags,
3727 codeAttr, exceptAttr);
3728 }
3729
3730
3731
3732 /***
3733 * Append the code for returning the value from a direct read access.
3734 */
3735 private Insn appendDirectReadReturn(Insn insn,
3736 ConstFieldRef fieldRef)
3737 {
3738 affirm(insn != null);
3739 affirm(fieldRef != null);
3740
3741 final String sig = fieldRef.nameAndType().signature().asString();
3742 affirm(sig != null && sig.length() > 0);
3743
3744
3745 insn = insn.append(Insn.create(opc_aload_0));
3746 insn = insn.append(Insn.create(opc_getfield, fieldRef));
3747 switch (sig.charAt(0)) {
3748 case 'Z':
3749 case 'C':
3750 case 'B':
3751 case 'S':
3752 case 'I':
3753 insn = insn.append(Insn.create(opc_ireturn));
3754 break;
3755 case 'J':
3756 insn = insn.append(Insn.create(opc_lreturn));
3757 break;
3758 case 'F':
3759 insn = insn.append(Insn.create(opc_freturn));
3760 break;
3761 case 'D':
3762 insn = insn.append(Insn.create(opc_dreturn));
3763 break;
3764 case 'L':
3765 case '[':
3766 insn = insn.append(Insn.create(opc_areturn));
3767 break;
3768 default:
3769 affirm(false, "Illegal field type: " + sig);
3770 }
3771
3772 affirm(insn != null);
3773 return insn;
3774 }
3775
3776 /***
3777 * Build an accessor method for direct read access.
3778 *
3779 * static xxx final YYY jdoGetyyy(XXX instance)
3780 * {
3781 * // augmentation: grant direct read access
3782 * return instance.yyy;
3783 * }
3784 */
3785 public void addJDODirectReadAccessMethod(String methodName,
3786 String methodSig,
3787 int accessFlags,
3788 int fieldIndex)
3789 {
3790 affirm(methodName != null);
3791 affirm(methodSig != null);
3792 final ExceptionsAttribute exceptAttr = null;
3793
3794
3795 final InsnTarget begin = new InsnTarget();
3796 Insn insn = begin;
3797
3798 final ConstFieldRef fieldRef = getAnnotatedFieldRefs()[fieldIndex];
3799 affirm(fieldRef != null);
3800 final String sig = fieldRef.nameAndType().signature().asString();
3801 affirm(sig != null && sig.length() > 0);
3802 final int fieldSize = ((sig.equals("J") || sig.equals("D")) ? 2 : 1);
3803
3804
3805 insn = appendDirectReadReturn(insn, fieldRef);
3806
3807
3808
3809 final CodeAttribute codeAttr
3810 = new CodeAttribute(getCodeAttributeUtf8(),
3811 fieldSize,
3812 1,
3813 begin,
3814 new ExceptionTable(),
3815 new AttributeVector());
3816 augmenter.addMethod(methodName, methodSig, accessFlags,
3817 codeAttr, exceptAttr);
3818 }
3819
3820 /***
3821 * Append the code for mediated read access.
3822 */
3823 public Insn appendMediatedReadAccess(Insn insn,
3824 int fieldIndex,
3825 ConstFieldRef fieldRef,
3826 int varStart)
3827 {
3828 affirm(insn != null);
3829 affirm(fieldRef != null);
3830
3831 final String sig = fieldRef.nameAndType().signature().asString();
3832 affirm(sig != null && sig.length() > 0);
3833
3834
3835 insn = insn.append(Insn.create(opc_aload_0));
3836 insn = insn.append(
3837 Insn.create(
3838 opc_getfield,
3839 getjdoStateManagerFieldRef()));
3840 insn = insn.append(InsnUtils.aStore(varStart, pool));
3841
3842
3843 final InsnTarget callIsLoaded = new InsnTarget();
3844 insn = insn.append(InsnUtils.aLoad(varStart, pool));
3845 insn = insn.append(Insn.create(opc_ifnonnull, callIsLoaded));
3846 insn = appendDirectReadReturn(insn, fieldRef);
3847
3848
3849 insn = insn.append(callIsLoaded);
3850 insn = insn.append(InsnUtils.aLoad(varStart, pool));
3851
3852
3853 insn = insn.append(Insn.create(opc_aload_0));
3854
3855
3856 insn = insn.append(
3857 Insn.create(opc_getstatic,
3858 pool.addFieldRef(
3859 className,
3860 JDO_PC_jdoInheritedFieldCount_Name,
3861 JDO_PC_jdoInheritedFieldCount_Sig)));
3862 insn = insn.append(InsnUtils.integerConstant(fieldIndex, pool));
3863 insn = insn.append(Insn.create(opc_iadd));
3864
3865
3866 final InsnTarget mediate = new InsnTarget();
3867 insn = insn.append(
3868 new InsnInterfaceInvoke(
3869 pool.addInterfaceMethodRef(
3870 JDO_StateManager_Path,
3871 JDO_SM_isLoaded_Name,
3872 JDO_SM_isLoaded_Sig),
3873 countMethodArgWords(JDO_SM_isLoaded_Sig)));
3874 insn = insn.append(Insn.create(opc_ifeq, mediate));
3875 insn = appendDirectReadReturn(insn, fieldRef);
3876
3877
3878 insn = insn.append(mediate);
3879 insn = insn.append(InsnUtils.aLoad(varStart, pool));
3880
3881
3882 insn = insn.append(Insn.create(opc_aload_0));
3883
3884
3885 insn = insn.append(
3886 Insn.create(opc_getstatic,
3887 pool.addFieldRef(
3888 className,
3889 JDO_PC_jdoInheritedFieldCount_Name,
3890 JDO_PC_jdoInheritedFieldCount_Sig)));
3891 insn = insn.append(InsnUtils.integerConstant(fieldIndex, pool));
3892 insn = insn.append(Insn.create(opc_iadd));
3893
3894
3895 insn = insn.append(Insn.create(opc_aload_0));
3896 insn = insn.append(Insn.create(opc_getfield, fieldRef));
3897
3898
3899 switch (sig.charAt(0)) {
3900 case 'Z':
3901 insn = insn.append(
3902 new InsnInterfaceInvoke(
3903 pool.addInterfaceMethodRef(
3904 JDO_StateManager_Path,
3905 JDO_SM_getBooleanField_Name,
3906 JDO_SM_getBooleanField_Sig),
3907 countMethodArgWords(JDO_SM_getBooleanField_Sig)));
3908 insn = insn.append(Insn.create(opc_ireturn));
3909 break;
3910 case 'C':
3911 insn = insn.append(
3912 new InsnInterfaceInvoke(
3913 pool.addInterfaceMethodRef(
3914 JDO_StateManager_Path,
3915 JDO_SM_getCharField_Name,
3916 JDO_SM_getCharField_Sig),
3917 countMethodArgWords(JDO_SM_getCharField_Sig)));
3918 insn = insn.append(Insn.create(opc_ireturn));
3919 break;
3920 case 'B':
3921 insn = insn.append(
3922 new InsnInterfaceInvoke(
3923 pool.addInterfaceMethodRef(
3924 JDO_StateManager_Path,
3925 JDO_SM_getByteField_Name,
3926 JDO_SM_getByteField_Sig),
3927 countMethodArgWords(JDO_SM_getByteField_Sig)));
3928 insn = insn.append(Insn.create(opc_ireturn));
3929 break;
3930 case 'S':
3931 insn = insn.append(
3932 new InsnInterfaceInvoke(
3933 pool.addInterfaceMethodRef(
3934 JDO_StateManager_Path,
3935 JDO_SM_getShortField_Name,
3936 JDO_SM_getShortField_Sig),
3937 countMethodArgWords(JDO_SM_getShortField_Sig)));
3938 insn = insn.append(Insn.create(opc_ireturn));
3939 break;
3940 case 'I':
3941 insn = insn.append(
3942 new InsnInterfaceInvoke(
3943 pool.addInterfaceMethodRef(
3944 JDO_StateManager_Path,
3945 JDO_SM_getIntField_Name,
3946 JDO_SM_getIntField_Sig),
3947 countMethodArgWords(JDO_SM_getIntField_Sig)));
3948 insn = insn.append(Insn.create(opc_ireturn));
3949 break;
3950 case 'J':
3951 insn = insn.append(
3952 new InsnInterfaceInvoke(
3953 pool.addInterfaceMethodRef(
3954 JDO_StateManager_Path,
3955 JDO_SM_getLongField_Name,
3956 JDO_SM_getLongField_Sig),
3957 countMethodArgWords(JDO_SM_getLongField_Sig)));
3958 insn = insn.append(Insn.create(opc_lreturn));
3959 break;
3960 case 'F':
3961 insn = insn.append(
3962 new InsnInterfaceInvoke(
3963 pool.addInterfaceMethodRef(
3964 JDO_StateManager_Path,
3965 JDO_SM_getFloatField_Name,
3966 JDO_SM_getFloatField_Sig),
3967 countMethodArgWords(JDO_SM_getFloatField_Sig)));
3968 insn = insn.append(Insn.create(opc_freturn));
3969 break;
3970 case 'D':
3971 insn = insn.append(
3972 new InsnInterfaceInvoke(
3973 pool.addInterfaceMethodRef(
3974 JDO_StateManager_Path,
3975 JDO_SM_getDoubleField_Name,
3976 JDO_SM_getDoubleField_Sig),
3977 countMethodArgWords(JDO_SM_getDoubleField_Sig)));
3978 insn = insn.append(Insn.create(opc_dreturn));
3979 break;
3980 case 'L':
3981 case '[':
3982 if (sig.equals(JAVA_String_Sig)) {
3983 insn = insn.append(
3984 new InsnInterfaceInvoke(
3985 pool.addInterfaceMethodRef(
3986 JDO_StateManager_Path,
3987 JDO_SM_getStringField_Name,
3988 JDO_SM_getStringField_Sig),
3989 countMethodArgWords(JDO_SM_getStringField_Sig)));
3990 insn = insn.append(Insn.create(opc_areturn));
3991 } else {
3992 insn = insn.append(
3993 new InsnInterfaceInvoke(
3994 pool.addInterfaceMethodRef(
3995 JDO_StateManager_Path,
3996 JDO_SM_getObjectField_Name,
3997 JDO_SM_getObjectField_Sig),
3998 countMethodArgWords(JDO_SM_getObjectField_Sig)));
3999 if (!sig.equals(JAVA_Object_Sig)) {
4000 final String fieldType = NameHelper.pathForSig(sig);
4001 insn = insn.append(
4002 Insn.create(opc_checkcast,
4003 pool.addClass(fieldType)));
4004 }
4005 insn = insn.append(Insn.create(opc_areturn));
4006 }
4007 break;
4008 default:
4009 affirm(false, "Illegal field type: " + sig);
4010 }
4011
4012 affirm(insn != null);
4013 return insn;
4014 }
4015
4016 /***
4017 * Build an accessor method for mediated read access.
4018 *
4019 * static xxx final YYY jdoGetyyy(XXX instance)
4020 * {
4021 * // augmentation: mediate read access
4022 * final javax.jdo.StateManager sm = instance.jdoStateManager;
4023 * if (sm == null) {
4024 * return instance.yyy;
4025 * }
4026 * if (sm.isLoaded(instance, instance.jdoInheritedFieldCount + y)) {
4027 * return instance.yyy;
4028 * }
4029 * return (YYY)sm.getYYYField(instance,
4030 * instance.jdoInheritedFieldCount + x,
4031 * instance.yyy);
4032 * }
4033 */
4034 public void addJDOMediatedReadAccessMethod(String methodName,
4035 String methodSig,
4036 int accessFlags,
4037 int fieldIndex)
4038 {
4039 affirm(methodName != null);
4040 affirm(methodSig != null);
4041 final ExceptionsAttribute exceptAttr = null;
4042
4043
4044 final InsnTarget begin = new InsnTarget();
4045 Insn insn = begin;
4046
4047
4048 final ConstFieldRef fieldRef = getAnnotatedFieldRefs()[fieldIndex];
4049 affirm(fieldRef != null);
4050 final String sig = fieldRef.nameAndType().signature().asString();
4051 affirm(sig != null && sig.length() > 0);
4052 final int fieldSize = ((sig.equals("J") || sig.equals("D")) ? 2 : 1);
4053 final int varStart = 1;
4054
4055
4056 insn = appendMediatedReadAccess(insn, fieldIndex, fieldRef, varStart);
4057
4058
4059
4060 final CodeAttribute codeAttr
4061 = new CodeAttribute(getCodeAttributeUtf8(),
4062 fieldSize + 3,
4063 2,
4064 begin,
4065 new ExceptionTable(),
4066 new AttributeVector());
4067
4068 augmenter.addMethod(methodName, methodSig, accessFlags,
4069 codeAttr, exceptAttr);
4070 }
4071
4072 /***
4073 * Build an accessor method for checked read access.
4074 *
4075 * static xxx final YYY jdoGetyyy(XXX instance)
4076 * {
4077 * // augmentation: check read access
4078 * if (instance.jdoFlags <= 0) {
4079 * return instance.yyy;
4080 * }
4081 * final javax.jdo.StateManager sm = instance.jdoStateManager;
4082 * if (sm == null) {
4083 * return instance.yyy;
4084 * }
4085 * if (sm.isLoaded(instance, instance.jdoInheritedFieldCount + y)) {
4086 * return instance.yyy;
4087 * }
4088 * return (YYY)instance.jdoStateManager
4089 * .getYYYField(instance,
4090 * instance.jdoInheritedFieldCount + y,
4091 * instance.yyy);
4092 * }
4093 */
4094 public void addJDOCheckedReadAccessMethod(String methodName,
4095 String methodSig,
4096 int accessFlags,
4097 int fieldIndex)
4098 {
4099 affirm(methodName != null);
4100 affirm(methodSig != null);
4101 final ExceptionsAttribute exceptAttr = null;
4102
4103
4104 final InsnTarget begin = new InsnTarget();
4105 Insn insn = begin;
4106
4107
4108 final ConstFieldRef fieldRef = getAnnotatedFieldRefs()[fieldIndex];
4109 affirm(fieldRef != null);
4110 final String sig = fieldRef.nameAndType().signature().asString();
4111 affirm(sig != null && sig.length() > 0);
4112 final int fieldSize = ((sig.equals("J") || sig.equals("D")) ? 2 : 1);
4113 final int varStart = 1;
4114
4115
4116 final InsnTarget mediate = new InsnTarget();
4117 insn = insn.append(Insn.create(opc_aload_0));
4118 insn = insn.append(
4119 Insn.create(opc_getfield,
4120 getjdoFlagsFieldRef()));
4121 insn = insn.append(Insn.create(opc_ifgt, mediate));
4122 insn = appendDirectReadReturn(insn, fieldRef);
4123
4124
4125 insn = insn.append(mediate);
4126 insn = appendMediatedReadAccess(insn, fieldIndex, fieldRef, varStart);
4127
4128
4129
4130 final CodeAttribute codeAttr
4131 = new CodeAttribute(getCodeAttributeUtf8(),
4132 fieldSize + 3,
4133 2,
4134 begin,
4135 new ExceptionTable(),
4136 new AttributeVector());
4137 augmenter.addMethod(methodName, methodSig, accessFlags,
4138 codeAttr, exceptAttr);
4139 }
4140
4141 /***
4142 * Append the code for assigning the argument to the field and return.
4143 */
4144 private Insn appendDirectWriteReturn(Insn insn,
4145 ConstFieldRef fieldRef)
4146 {
4147 affirm(insn != null);
4148 affirm(fieldRef != null);
4149
4150 final String sig = fieldRef.nameAndType().signature().asString();
4151 affirm(sig != null && sig.length() > 0);
4152
4153
4154 insn = insn.append(Insn.create(opc_aload_0));
4155 switch (sig.charAt(0)) {
4156 case 'Z':
4157 case 'C':
4158 case 'B':
4159 case 'S':
4160 case 'I':
4161 insn = insn.append(Insn.create(opc_iload_1));
4162 break;
4163 case 'J':
4164 insn = insn.append(Insn.create(opc_lload_1));
4165 break;
4166 case 'F':
4167 insn = insn.append(Insn.create(opc_fload_1));
4168 break;
4169 case 'D':
4170 insn = insn.append(Insn.create(opc_dload_1));
4171 break;
4172 case 'L':
4173 case '[':
4174 insn = insn.append(Insn.create(opc_aload_1));
4175 break;
4176 default:
4177 affirm(false, "Illegal field type: " + sig);
4178 }
4179 insn = insn.append(Insn.create(opc_putfield, fieldRef));
4180 insn = insn.append(Insn.create(opc_return));
4181
4182 affirm(insn != null);
4183 return insn;
4184 }
4185
4186 /***
4187 * Build a mutator method for direct write access.
4188 *
4189 * static xxx void jdoSetyyy(XXX instance, YYY yyy)
4190 * {
4191 * // augmentation: grant direct write access
4192 * instance.yyy = yyy;
4193 * }
4194 */
4195 public void addJDODirectWriteAccessMethod(String methodName,
4196 String methodSig,
4197 int accessFlags,
4198 int fieldIndex)
4199 {
4200 affirm(methodName != null);
4201 affirm(methodSig != null);
4202 final ExceptionsAttribute exceptAttr = null;
4203
4204
4205 final InsnTarget begin = new InsnTarget();
4206 Insn insn = begin;
4207
4208 final ConstFieldRef fieldRef = getAnnotatedFieldRefs()[fieldIndex];
4209 affirm(fieldRef != null);
4210
4211
4212 insn = appendDirectWriteReturn(insn, fieldRef);
4213
4214 final CodeAttribute codeAttr
4215 = new CodeAttribute(getCodeAttributeUtf8(),
4216 3,
4217 3,
4218 begin,
4219 new ExceptionTable(),
4220 new AttributeVector());
4221 augmenter.addMethod(methodName, methodSig, accessFlags,
4222 codeAttr, exceptAttr);
4223 }
4224
4225 /***
4226 * Append the code for mediated write access.
4227 */
4228 private Insn appendMediatedWriteAccess(Insn insn,
4229 int fieldIndex,
4230 ConstFieldRef fieldRef,
4231 int varStart)
4232 {
4233 affirm(insn != null);
4234 affirm(fieldRef != null);
4235
4236 final String sig = fieldRef.nameAndType().signature().asString();
4237 affirm(sig != null && sig.length() > 0);
4238
4239
4240 insn = insn.append(Insn.create(opc_aload_0));
4241 insn = insn.append(
4242 Insn.create(
4243 opc_getfield,
4244 getjdoStateManagerFieldRef()));
4245 insn = insn.append(InsnUtils.aStore(varStart, pool));
4246
4247
4248 final InsnTarget mediate = new InsnTarget();
4249 insn = insn.append(InsnUtils.aLoad(varStart, pool));
4250 insn = insn.append(Insn.create(opc_ifnonnull, mediate));
4251
4252
4253 insn = appendDirectWriteReturn(insn, fieldRef);
4254
4255
4256 insn = insn.append(mediate);
4257 insn = insn.append(InsnUtils.aLoad(varStart, pool));
4258
4259
4260 insn = insn.append(Insn.create(opc_aload_0));
4261
4262
4263 insn = insn.append(
4264 Insn.create(opc_getstatic,
4265 pool.addFieldRef(
4266 className,
4267 JDO_PC_jdoInheritedFieldCount_Name,
4268 JDO_PC_jdoInheritedFieldCount_Sig)));
4269 insn = insn.append(InsnUtils.integerConstant(fieldIndex, pool));
4270 insn = insn.append(Insn.create(opc_iadd));
4271
4272
4273 insn = insn.append(Insn.create(opc_aload_0));
4274 insn = insn.append(Insn.create(opc_getfield, fieldRef));
4275
4276
4277 switch (sig.charAt(0)) {
4278 case 'Z':
4279 case 'C':
4280 case 'B':
4281 case 'S':
4282 case 'I':
4283 insn = insn.append(Insn.create(opc_iload_1));
4284 break;
4285 case 'J':
4286 insn = insn.append(Insn.create(opc_lload_1));
4287 break;
4288 case 'F':
4289 insn = insn.append(Insn.create(opc_fload_1));
4290 break;
4291 case 'D':
4292 insn = insn.append(Insn.create(opc_dload_1));
4293 break;
4294 case 'L':
4295 case '[':
4296 insn = insn.append(Insn.create(opc_aload_1));
4297 break;
4298 default:
4299 affirm(false, "Illegal field type: " + sig);
4300 }
4301
4302
4303 switch (sig.charAt(0)) {
4304 case 'Z':
4305 insn = insn.append(
4306 new InsnInterfaceInvoke(
4307 pool.addInterfaceMethodRef(
4308 JDO_StateManager_Path,
4309 JDO_SM_setBooleanField_Name,
4310 JDO_SM_setBooleanField_Sig),
4311 countMethodArgWords(JDO_SM_setBooleanField_Sig)));
4312 break;
4313 case 'C':
4314 insn = insn.append(
4315 new InsnInterfaceInvoke(
4316 pool.addInterfaceMethodRef(
4317 JDO_StateManager_Path,
4318 JDO_SM_setCharField_Name,
4319 JDO_SM_setCharField_Sig),
4320 countMethodArgWords(JDO_SM_setCharField_Sig)));
4321 break;
4322 case 'B':
4323 insn = insn.append(
4324 new InsnInterfaceInvoke(
4325 pool.addInterfaceMethodRef(
4326 JDO_StateManager_Path,
4327 JDO_SM_setByteField_Name,
4328 JDO_SM_setByteField_Sig),
4329 countMethodArgWords(JDO_SM_setByteField_Sig)));
4330 break;
4331 case 'S':
4332 insn = insn.append(
4333 new InsnInterfaceInvoke(
4334 pool.addInterfaceMethodRef(
4335 JDO_StateManager_Path,
4336 JDO_SM_setShortField_Name,
4337 JDO_SM_setShortField_Sig),
4338 countMethodArgWords(JDO_SM_setShortField_Sig)));
4339 break;
4340 case 'I':
4341 insn = insn.append(
4342 new InsnInterfaceInvoke(
4343 pool.addInterfaceMethodRef(
4344 JDO_StateManager_Path,
4345 JDO_SM_setIntField_Name,
4346 JDO_SM_setIntField_Sig),
4347 countMethodArgWords(JDO_SM_setIntField_Sig)));
4348 break;
4349 case 'J':
4350 insn = insn.append(
4351 new InsnInterfaceInvoke(
4352 pool.addInterfaceMethodRef(
4353 JDO_StateManager_Path,
4354 JDO_SM_setLongField_Name,
4355 JDO_SM_setLongField_Sig),
4356 countMethodArgWords(JDO_SM_setLongField_Sig)));
4357 break;
4358 case 'F':
4359 insn = insn.append(
4360 new InsnInterfaceInvoke(
4361 pool.addInterfaceMethodRef(
4362 JDO_StateManager_Path,
4363 JDO_SM_setFloatField_Name,
4364 JDO_SM_setFloatField_Sig),
4365 countMethodArgWords(JDO_SM_setFloatField_Sig)));
4366 break;
4367 case 'D':
4368 insn = insn.append(
4369 new InsnInterfaceInvoke(
4370 pool.addInterfaceMethodRef(
4371 JDO_StateManager_Path,
4372 JDO_SM_setDoubleField_Name,
4373 JDO_SM_setDoubleField_Sig),
4374 countMethodArgWords(JDO_SM_setDoubleField_Sig)));
4375 break;
4376 case 'L':
4377 case '[':
4378 if (sig.equals(JAVA_String_Sig)) {
4379 insn = insn.append(
4380 new InsnInterfaceInvoke(
4381 pool.addInterfaceMethodRef(
4382 JDO_StateManager_Path,
4383 JDO_SM_setStringField_Name,
4384 JDO_SM_setStringField_Sig),
4385 countMethodArgWords(JDO_SM_setStringField_Sig)));
4386 } else {
4387 insn = insn.append(
4388 new InsnInterfaceInvoke(
4389 pool.addInterfaceMethodRef(
4390 JDO_StateManager_Path,
4391 JDO_SM_setObjectField_Name,
4392 JDO_SM_setObjectField_Sig),
4393 countMethodArgWords(JDO_SM_setObjectField_Sig)));
4394 }
4395 break;
4396 default:
4397 affirm(false, "Illegal field type: " + sig);
4398 }
4399
4400 insn = insn.append(Insn.create(opc_return));
4401
4402 affirm(insn != null);
4403 return insn;
4404 }
4405
4406 /***
4407 * Build a mutator method for mediated write access.
4408 *
4409 * static xxx void jdoSetyyy(XXX instance, YYY yyy)
4410 * {
4411 * // augmentation: mediate write access
4412 * final javax.jdo.StateManager sm = instance.jdoStateManager;
4413 * if (sm == null) {
4414 * instance.yyy = yyy;
4415 * return;
4416 * }
4417 * sm.setYYYField(instance,
4418 * instance.jdoInheritedFieldCount + y,
4419 * instance.yyy,
4420 * yyy);
4421 * }
4422 */
4423 public void addJDOMediatedWriteAccessMethod(String methodName,
4424 String methodSig,
4425 int accessFlags,
4426 int fieldIndex)
4427 {
4428 affirm(methodName != null);
4429 affirm(methodSig != null);
4430 final ExceptionsAttribute exceptAttr = null;
4431
4432
4433 final InsnTarget begin = new InsnTarget();
4434 Insn insn = begin;
4435
4436
4437 final ConstFieldRef fieldRef = getAnnotatedFieldRefs()[fieldIndex];
4438 affirm(fieldRef != null);
4439 final String sig = fieldRef.nameAndType().signature().asString();
4440 affirm(sig != null && sig.length() > 0);
4441 final int fieldSize = ((sig.equals("J") || sig.equals("D")) ? 2 : 1);
4442 final int varStart = fieldSize + 1;
4443
4444
4445 insn = appendMediatedWriteAccess(insn, fieldIndex, fieldRef, varStart);
4446
4447
4448
4449 final CodeAttribute codeAttr
4450 = new CodeAttribute(getCodeAttributeUtf8(),
4451 (2 * fieldSize) + 3,
4452 fieldSize + 2,
4453 begin,
4454 new ExceptionTable(),
4455 new AttributeVector());
4456 augmenter.addMethod(methodName, methodSig, accessFlags,
4457 codeAttr, exceptAttr);
4458 }
4459
4460 /***
4461 * Build a mutator method for checked write access.
4462 *
4463 * static xxx void jdoSetyyy(XXX instance, YYY yyy)
4464 * {
4465 * // augmentation: check write access
4466 * if (instance.jdoFlags == 0) {
4467 * instance.yyy = yyy;
4468 * return;
4469 * }
4470 * instance.yyy = (YYY)instance.jdoStateManager
4471 * .setYYYField(instance,
4472 * instance.jdoInheritedFieldCount + y,
4473 * instance.yyy, yyy);
4474 * }
4475 */
4476 public void addJDOCheckedWriteAccessMethod(String methodName,
4477 String methodSig,
4478 int accessFlags,
4479 int fieldIndex)
4480 {
4481 affirm(methodName != null);
4482 affirm(methodSig != null);
4483 final ExceptionsAttribute exceptAttr = null;
4484
4485
4486 final InsnTarget begin = new InsnTarget();
4487 Insn insn = begin;
4488
4489
4490 final ConstFieldRef fieldRef = getAnnotatedFieldRefs()[fieldIndex];
4491 affirm(fieldRef != null);
4492 final String sig = fieldRef.nameAndType().signature().asString();
4493 affirm(sig != null && sig.length() > 0);
4494 final int fieldSize = ((sig.equals("J") || sig.equals("D")) ? 2 : 1);
4495 final int varStart = fieldSize + 1;
4496
4497
4498 final InsnTarget mediate = new InsnTarget();
4499 insn = insn.append(Insn.create(opc_aload_0));
4500 insn = insn.append(
4501 Insn.create(opc_getfield,
4502 getjdoFlagsFieldRef()));
4503 insn = insn.append(Insn.create(opc_ifne, mediate));
4504 insn = appendDirectWriteReturn(insn, fieldRef);
4505
4506
4507 insn = insn.append(mediate);
4508 insn = appendMediatedWriteAccess(insn, fieldIndex, fieldRef, varStart);
4509
4510
4511
4512 final CodeAttribute codeAttr
4513 = new CodeAttribute(getCodeAttributeUtf8(),
4514 (2 * fieldSize) + 3,
4515 fieldSize + 2,
4516 begin,
4517 new ExceptionTable(),
4518 new AttributeVector());
4519 augmenter.addMethod(methodName, methodSig, accessFlags,
4520 codeAttr, exceptAttr);
4521 }
4522
4523
4524
4525 /***
4526 * Build the jdoClear method for the class.
4527 *
4528 * public void jdoClear() {
4529 * ...
4530 * }
4531 */
4532 public void addJDOClearMethod()
4533 {
4534 final String methodName = "";
4535 final String methodSig = "()V";
4536 final int accessFlags = 0;
4537 final ExceptionsAttribute exceptAttr = null;
4538
4539
4540 final InsnTarget begin = new InsnTarget();
4541 Insn insn = begin;
4542
4543
4544 if (false) {
4545
4546 insn = insn.append(Insn.create(opc_aload_0));
4547 insn = insn.append(Insn.create(opc_iconst_1));
4548 insn = insn.append(
4549 Insn.create(opc_putfield,
4550 pool.addFieldRef(className,
4551 JDO_PC_jdoFlags_Name,
4552 JDO_PC_jdoFlags_Sig)));
4553 }
4554
4555
4556 final ClassField[] managedFields = null;
4557 final int managedFieldCount = managedFields.length;
4558 for (int i = 0; i < managedFieldCount; i++) {
4559 final ClassField field = managedFields[i];
4560 final String fieldName = field.name().asString();
4561 final String fieldSig = field.signature().asString();
4562
4563
4564
4565
4566
4567
4568
4569
4570
4571
4572
4573
4574
4575
4576
4577
4578
4579
4580
4581
4582
4583
4584
4585
4586
4587
4588
4589
4590
4591
4592
4593
4594
4595
4596
4597
4598
4599
4600
4601
4602
4603
4604
4605
4606
4607
4608
4609
4610
4611
4612
4613
4614
4615
4616
4617
4618
4619
4620
4621
4622
4623
4624
4625 insn = insn.append(Insn.create(opc_aload_0));
4626
4627
4628 switch (fieldSig.charAt(0)) {
4629 case 'D':
4630 insn = insn.append(Insn.create(opc_dconst_0));
4631 break;
4632 case 'F':
4633 insn = insn.append(Insn.create(opc_fconst_0));
4634 break;
4635 case 'J':
4636 insn = insn.append(Insn.create(opc_lconst_0));
4637 break;
4638 case 'Z':
4639 case 'C':
4640 case 'B':
4641 case 'S':
4642 case 'I':
4643 insn = insn.append(Insn.create(opc_iconst_0));
4644 break;
4645 case 'L':
4646 case '[':
4647 insn = insn.append(Insn.create(opc_aconst_null));
4648 break;
4649 default:
4650 throw new InternalError("Illegal field type: " + fieldSig);
4651 }
4652
4653
4654 insn = insn.append(
4655 Insn.create(opc_putfield,
4656 pool.addFieldRef(className,
4657 fieldName,
4658 fieldSig)));
4659 }
4660
4661
4662 insn = insn.append(Insn.create(opc_return));
4663
4664 final CodeAttribute codeAttr
4665 = new CodeAttribute(getCodeAttributeUtf8(),
4666 3,
4667 1,
4668 begin,
4669 new ExceptionTable(),
4670 new AttributeVector());
4671 augmenter.addMethod(methodName, methodSig, accessFlags,
4672 codeAttr, exceptAttr);
4673 }
4674
4675 /***
4676 * Build the clone method for the class.
4677 */
4678 public void addJDOClone()
4679 {
4680 final String methodName = "";
4681 final String methodSig = "()Ljava/lang/Object;";
4682 final int accessFlags = 0;
4683 final ExceptionsAttribute exceptAttr
4684 = new ExceptionsAttribute(
4685 pool.addUtf8(ExceptionsAttribute.expectedAttrName),
4686 pool.addClass("java/lang/CloneNotSupportedException"));
4687
4688
4689 final InsnTarget begin = new InsnTarget();
4690 Insn insn = begin;
4691
4692
4693 final ConstClass superConstClass = classFile.superName();
4694 final ConstClass thisConstClass = classFile.className();
4695 affirm(thisConstClass != null);
4696 insn = insn.append(Insn.create(opc_aload_0));
4697 insn = insn.append(
4698 Insn.create(opc_invokespecial,
4699 pool.addMethodRef(superConstClass.asString(),
4700 methodName,
4701 methodSig)));
4702 insn = insn.append(Insn.create(opc_checkcast, thisConstClass));
4703
4704
4705 if (false)
4706 {
4707 insn = insn.append(Insn.create(opc_dup));
4708 insn = insn.append(Insn.create(opc_aconst_null));
4709 insn = insn.append(
4710 Insn.create(opc_putfield,
4711 pool.addFieldRef(className,
4712 JDO_PC_jdoStateManager_Name,
4713 JDO_PC_jdoStateManager_Sig)));
4714 }
4715
4716
4717 if (false)
4718 {
4719 insn = insn.append(Insn.create(opc_dup));
4720 insn = insn.append(Insn.create(opc_iconst_0));
4721 insn = insn.append(
4722 Insn.create(opc_putfield,
4723 pool.addFieldRef(className,
4724 JDO_PC_jdoFlags_Name,
4725 JDO_PC_jdoFlags_Sig)));
4726 }
4727
4728
4729
4730
4731 insn = insn.append(Insn.create(opc_areturn));
4732
4733 final CodeAttribute codeAttr
4734 = new CodeAttribute(getCodeAttributeUtf8(),
4735 1,
4736 1,
4737 begin,
4738 new ExceptionTable(),
4739 new AttributeVector());
4740 augmenter.addMethod(methodName, methodSig, accessFlags,
4741 codeAttr, exceptAttr);
4742 }
4743
4744 /***
4745 * Builds a method throwing an UnsupportedOperationException.
4746 *
4747 * public void XXX() {
4748 * throw new UnsupportedOperationException(
4749 * "Method XXX not yet implemented");
4750 * }
4751 */
4752 public void addNotYetImplementedMethod(final String methodName,
4753 final String methodSig,
4754 final int accessFlags)
4755 {
4756
4757 affirm((accessFlags & ACCStatic) == 0);
4758 final ExceptionsAttribute exceptAttr = null;
4759
4760
4761 final InsnTarget begin = new InsnTarget();
4762 Insn insn = begin;
4763
4764 insn = appendThrowJavaException(
4765 insn, JAVA_UnsupportedOperationException_Path,
4766 "Method " + methodName + " not yet implemented");
4767
4768 final CodeAttribute codeAttr
4769 = new CodeAttribute(getCodeAttributeUtf8(),
4770 3,
4771 countMethodArgWords(methodSig),
4772 begin,
4773 new ExceptionTable(),
4774 new AttributeVector());
4775 augmenter.addMethod(methodName, methodSig, accessFlags,
4776 codeAttr, exceptAttr);
4777 }
4778
4779 }