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