KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jdo > api > persistence > enhancer > impl > MethodBuilder


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24
25 package com.sun.jdo.api.persistence.enhancer.impl;
26
27 import java.util.HashMap JavaDoc;
28 import java.util.ArrayList JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.Enumeration JavaDoc;
31
32 import com.sun.jdo.api.persistence.enhancer.classfile.*;
33
34 import com.sun.jdo.api.persistence.enhancer.util.Support;
35 import com.sun.jdo.api.persistence.enhancer.util.InternalError;
36 import com.sun.jdo.api.persistence.enhancer.util.ClassFileSource;
37
38 //@olsen: added import
39
import com.sun.jdo.api.persistence.enhancer.meta.JDOMetaData;
40
41
42 //@olsen: cosmetics
43
//@olsen: moved: this class -> package impl
44
//@olsen: subst: (object)state -> flags
45
//@olsen: subst: JDOflags -> jdoFlags
46
//@olsen: subst: makeJDO[gs]etFlags -> makeJDO[GS]etFlags
47
//@olsen: subst: JDO[gs]etFlags -> jdo[GS]etFlags
48
//@olsen: subst: [Nn]eedsJDORefMethods -> [Nn]eedsJDOStateManagerMethods
49
//@olsen: subst: JDOref -> jdoStateManager
50
//@olsen: subst: makeJDO[gs]etRef -> makeJDO[GS]etStateManager
51
//@olsen: subst: JDO[gs]etRef -> jdo[GS]etStateManager
52
//@olsen: subst: [iI]Persistent -> [pP]ersistenceCapable
53
//@olsen: subst: PersistentAux -> StateManager
54
//@olsen: subst: jdo/ -> com/sun/forte4j/persistence/internal/
55
//@olsen: subst: jdo. -> com.sun.forte4j.persistence.internal.
56
//@olsen: subst: /* ... */ -> // ...
57
//@olsen: added: final modifiers on local variables
58
//@olsen: subst: FilterEnv -> Environment
59
//@olsen: made MethodBuilder's methods non-static
60
//@olsen: dropped parameter 'Environment env', use association instead
61
//@olsen: subst: Enumeration,... -> Iterator, hasNext(), next()
62
//@olsen: subst: myMethodName -> methodName
63
//@olsen: added: support for I18N
64
//@olsen: subst: FilterError -> UserException, affirm()
65
//@olsen: removed: proprietary support for ClassInfo
66
//@olsen: removed: proprietary support for FieldNote
67
//@olsen: removed: old, disabled ODI code
68

69
70 /**
71  * MethodBuilder is a collection of methods which
72  * create the persistence methods of a persistent class
73  */

74 class MethodBuilder
75     extends Support
76     implements VMConstants {
77
78     //@olsen: fix for bug 4467428:
79
// Debugging under jdk 1.3.1 shows the problem that any breakpoints
80
// in PC classes are ignored if the added jdo methods do NOT have a
81
// non-empty line number table attribute, no matter whether the
82
// 'Synthetic' attribute is given or not. However, this doesn't
83
// seem to comply with the JVM Spec (2nd edition), which states
84
// that the synthetic attribute _must_ be specified if no source
85
// code information is available for the member:
86
//
87
// 4.7.6 The Synthetic Attribute
88
// ... A class member that does not appear in the source code must
89
// be marked using a Synthetic attribute. ...
90
//
91
// 4.7.8 The LineNumberTable Attribute
92
// The LineNumberTable attribute is an optional variable-length
93
// attribute in the attributes table of a Code (see 4.7.3)
94
// attribute. It may be used by debuggers to determine which
95
// part of the Java virtual machine code array corresponds to a
96
// given line number in the original source file. ... Furthermore,
97
// multiple LineNumberTable attributes may together represent a
98
// given line of a source file; that is, LineNumberTable attributes
99
// need not be one-to-one with source lines.
100
//
101
// Unfortunately, if we do both, adding the synthetic attribute and
102
// a (dummy) line number table on generated methods, jdk's 1.3.1 javap
103
// fails to disassemble the classfile with an exception:
104
//
105
// sun.tools.java.CompilerError: checkOverride() synthetic
106
//
107
// So, to workaround these problems and to allow for both, debugging
108
// and disassembling with the jdk (1.3.1) tools, we pretend that the
109
// generated jdo methods have source code equivalents by
110
// - not adding the synthetic code attribute
111
// - providing a dummy line number table code attribute
112
static private final boolean addSyntheticAttr = false;
113     static private final boolean addLineNumberTableAttr = true;
114
115     /* Central repository for the options and classes */
116     //@olsen: added association
117
//@olsen: made final
118
private final Environment env;
119
120     /**
121      * Constructor.
122      */

123     //@olsen: added constructor
124
//@olsen: added parameter 'env' for association
125
public MethodBuilder(Environment env) {
126         this.env = env;
127     }
128
129     /**
130      * Build a null method named methodName for the class.
131      *
132      * public void methodName() {
133      * }
134      */

135     //@olsen: moved to beginning of this class
136
ClassMethod makeNullMethod(final ClassAction ca,
137                                final String JavaDoc methodName) {
138         //@olsen: added variable
139
final String JavaDoc methodSig = "()V";//NOI18N
140
env.message("adding "//NOI18N
141
+ ca.classControl().userClassName() +
142                     "." + methodName//NOI18N
143
+ Descriptor.userMethodArgs(methodSig));
144
145         final ConstantPool pool = ca.classFile().pool();
146         final ConstClass thisClass = ca.classFile().className();
147
148         final AttributeVector methodAttrs = new AttributeVector();
149         final ClassMethod nullMethod
150             = new ClassMethod(ACCPublic,
151                               pool.addUtf8(methodName),
152                               pool.addUtf8(methodSig),
153                               methodAttrs);
154
155         // begin of method body
156
//@olsen: fix 4467428, made 'begin' final InsnTarget
157
final InsnTarget begin = new InsnTarget();
158         Insn insn = begin;
159
160         // end of method body
161
insn = insn.append(Insn.create(opc_return));
162
163         final AttributeVector codeSpecificAttrs = new AttributeVector();
164
165         //@olsen: fix 4467428, added dummy, non-empty line number table
166
if (addLineNumberTableAttr) {
167             codeSpecificAttrs.addElement(
168                 new LineNumberTableAttribute(
169                     pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
170                     new short[]{ 0 }, new InsnTarget[]{ begin }));
171         }
172
173         methodAttrs.addElement(
174             new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
175                               0, // maxStack
176
1, // maxLocals
177
begin,
178                               new ExceptionTable(),
179                               codeSpecificAttrs));
180
181         //@olsen: fix 4467428, added synthetic attribute for generated method
182
if (addSyntheticAttr) {
183             methodAttrs.addElement(
184                 new SyntheticAttribute(
185                     pool.addUtf8(SyntheticAttribute.expectedAttrName)));
186         }
187
188         return nullMethod;
189     }
190
191     /**
192      * Build the initializeContents method for the class
193      */

194 //@olsen: dropped method
195
/*
196     ClassMethod makeInitializeContents(ClassAction ca) {
197         final ConstantPool pool = ca.classFile().pool();
198         final ConstClass thisClass = ca.classFile().className();
199
200         final AttributeVector methodAttrs = new AttributeVector();
201         ClassMethod initializeContentsMethod =
202             new ClassMethod(ACCPublic,
203                             pool.addUtf8("initializeContents"),
204                             pool.addUtf8("(Lcom/sun/forte4j/persistence/internal/ObjectContents;)V"),
205                             methodAttrs);
206
207         // begin of method body
208         Insn begin = new InsnTarget();
209         Insn insn = begin;
210
211         // Allocated reg 2 as cached ClassInfo*
212         insn = insn.append(
213             Insn.create(opc_getstatic,
214                         pool.addFieldRef(thisClass.asString(),
215                                          ca.getClassInfoMember(),
216                                          "Lcom/sun/forte4j/persistence/internal/ClassInfo;")));
217         insn = insn.append(Insn.create(opc_astore_2));
218
219         for (Iterator e = ca.fieldActions(); e.hasNext();) {
220             FieldAction act = (FieldAction)e.next();
221             if (act.isPersistent()) {
222                 int idx = act.index();
223                 // get this
224                 insn = insn.append(Insn.create(opc_aload_0));
225                 // get GenericObject
226                 insn = insn.append(Insn.create(opc_aload_1));
227                 // get field index
228                 insn = insn.append(InsnUtils.integerConstant(idx, pool));
229                 // get ClassInfo
230                 insn = insn.append(Insn.create(opc_aload_2));
231                 // call the get method
232                 insn = insn.append(Insn.create(opc_invokevirtual,
233                                                pool.addMethodRef("com/sun/forte4j/persistence/internal/ObjectContents",
234                                                                  act.getMethod(), act.getMethodSig())));
235
236                 switch(act.getMethodReturn()) {
237                 case T_DOUBLE:
238                 case T_LONG:
239                 case T_BOOLEAN:
240                 case T_CHAR:
241                 case T_FLOAT:
242                 case T_BYTE:
243                 case T_SHORT:
244                 case T_INT:
245                 case TC_STRING:
246                     // The above types are assumed to be accurate, with no
247                     // conversions required
248                     break;
249
250                 case TC_OBJECT:
251                 case TC_INTERFACE:
252                     if (!act.typeDescriptor().equals("Ljava/lang/Object;")) {
253                         ConstClass fieldType = pool.addClass(act.typeName());
254                         // Add a cast to the appropriate type
255                         insn = insn.append(Insn.create(opc_checkcast, fieldType));
256                     }
257                     break;
258                 default:
259                     throw new InternalError("Unexpected return type");
260                 }
261
262                 // finally, store the result
263                 insn = insn.append(Insn.create(opc_putfield,
264                                                pool.addFieldRef(thisClass.asString(), act.fieldName(),
265                                                                 act.typeDescriptor())));
266             }
267         }
268
269         ConstClass superClass = ca.classFile().superName();
270         if (!ca.getImplementsPersistence()) {
271             // Need to invoke initializeContents on super
272             // get this
273             insn = insn.append(Insn.create(opc_aload_0));
274             // get generic object
275             insn = insn.append(Insn.create(opc_aload_1));
276             // do the invoke
277             insn = insn.append(Insn.create(opc_invokespecial,
278                                            pool.addMethodRef(superClass.asString(),
279                                                              "initializeContents", "(Lcom/sun/forte4j/persistence/internal/ObjectContents;)V")));
280         }
281
282         // end of method body
283         insn = insn.append(Insn.create(opc_return));
284
285         methodAttrs.addElement(
286             new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
287                               4, // maxStack
288                               3, // maxLocals
289                               begin,
290                               new ExceptionTable(),
291                               new AttributeVector()));
292         return initializeContentsMethod;
293     }
294 */

295
296     /**
297      * Build the flushContents method for the class
298      */

299 //@olsen: dropped method
300
/*
301     ClassMethod makeFlushContents(ClassAction ca) {
302         final ConstantPool pool = ca.classFile().pool();
303         final ConstClass thisClass = ca.classFile().className();
304
305         final AttributeVector methodAttrs = new AttributeVector();
306         ClassMethod flushContentsMethod =
307             new ClassMethod(ACCPublic,
308                             pool.addUtf8("flushContents"),
309                             pool.addUtf8("(Lcom/sun/forte4j/persistence/internal/ObjectContents;)V"),
310                             methodAttrs);
311
312         // begin of method body
313         Insn begin = new InsnTarget();
314         Insn insn = begin;
315
316         // Allocated reg 2 as cached ClassInfo*
317         insn = insn.append(
318             Insn.create(opc_getstatic,
319                         pool.addFieldRef(thisClass.asString(),
320                                          ca.getClassInfoMember(),
321                                          "Lcom/sun/forte4j/persistence/internal/ClassInfo;")));
322         insn = insn.append(Insn.create(opc_astore_2));
323
324         for (Iterator e = ca.fieldActions(); e.hasNext();) {
325             FieldAction act = (FieldAction)e.next();
326             if (act.isPersistent()) {
327                 int idx = act.index();
328                 // get GenericObject
329                 insn = insn.append(Insn.create(opc_aload_1));
330                 // get field index
331                 insn = insn.append(InsnUtils.integerConstant(idx, pool));
332                 // get this
333                 insn = insn.append(Insn.create(opc_aload_0));
334                 // get the field value
335                 insn = insn = insn.append(Insn.create(opc_getfield,
336                                                       pool.addFieldRef(thisClass.asString(), act.fieldName(),
337                                                                        act.typeDescriptor())));
338                 // get ClassInfo
339                 insn = insn.append(Insn.create(opc_aload_2));
340
341                 // call the set method
342                 insn = insn.append(Insn.create(opc_invokevirtual,
343                                                pool.addMethodRef("com/sun/forte4j/persistence/internal/ObjectContents",
344                                                                  act.setMethod(), act.setMethodSig())));
345             }
346         }
347
348         ConstClass superClass = ca.classFile().superName();
349         if (!ca.getImplementsPersistence()) {
350             // Need to invoke flushContents on super
351             // get this
352             insn = insn.append(Insn.create(opc_aload_0));
353             // get generic object
354             insn = insn.append(Insn.create(opc_aload_1));
355             // do the invoke
356             insn = insn.append(Insn.create(opc_invokespecial,
357                                            pool.addMethodRef(superClass.asString(),
358                                                              "flushContents", "(Lcom/sun/forte4j/persistence/internal/ObjectContents;)V")));
359         }
360
361         // end of method body
362         insn = insn.append(Insn.create(opc_return));
363
364         methodAttrs.addElement(
365             new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
366                               6, // maxStack (might actually be 5, but ok)
367                               3, // maxLocals
368                               begin,
369                               new ExceptionTable(),
370                               new AttributeVector()));
371         return flushContentsMethod;
372     }
373 */

374
375     /**
376      * Build the clearContents method for the class
377      */

378 //@olsen: dropped method
379
/*
380     ClassMethod makeClearContents(ClassAction ca) {
381         final ConstantPool pool = ca.classFile().pool();
382         final ConstClass thisClass = ca.classFile().className();
383
384         final AttributeVector methodAttrs = new AttributeVector();
385         ClassMethod clearContentsMethod =
386             new ClassMethod(ACCPublic,
387                             pool.addUtf8("clearContents"),
388                             pool.addUtf8("()V"),
389                             methodAttrs);
390
391         // begin of method body
392         Insn begin = new InsnTarget();
393         Insn insn = begin;
394
395         for (Iterator e = ca.fieldActions(); e.hasNext();) {
396             FieldAction act = (FieldAction)e.next();
397             if (act.isPersistent()) {
398                 int idx = act.index();
399                 // get this
400                 insn = insn.append(Insn.create(opc_aload_0));
401
402                 // Use the getMethodReturn type to decide how to initialize
403                 switch(act.getMethodReturn()) {
404                 case T_DOUBLE:
405                     insn = insn.append(Insn.create(opc_dconst_0));
406                     break;
407                 case T_LONG:
408                     insn = insn.append(Insn.create(opc_lconst_0));
409                     break;
410                 case T_FLOAT:
411                     insn = insn.append(Insn.create(opc_fconst_0));
412                     break;
413                 case T_BOOLEAN:
414                 case T_CHAR:
415                 case T_BYTE:
416                 case T_SHORT:
417                 case T_INT:
418                     insn = insn.append(Insn.create(opc_iconst_0));
419                     break;
420                 case TC_STRING:
421                 case TC_OBJECT:
422                 case TC_INTERFACE:
423                     insn = insn.append(Insn.create(opc_aconst_null));
424                     break;
425                 default:
426                     throw new InternalError("Unexpected return type");
427                 }
428
429                 // finally, store the result
430                 insn = insn.append(Insn.create(opc_putfield,
431                                                pool.addFieldRef(thisClass.asString(), act.fieldName(),
432                                                                 act.typeDescriptor())));
433             }
434         }
435
436         ConstClass superClass = ca.classFile().superName();
437         if (!ca.getImplementsPersistence()) {
438             // Need to invoke clearContents on super
439             // get this
440             insn = insn.append(Insn.create(opc_aload_0));
441             // do the invoke
442             insn = insn.append(Insn.create(opc_invokespecial,
443                                            pool.addMethodRef(superClass.asString(),
444                                                              "clearContents", "()V")));
445         }
446
447         // end of method body
448         insn = insn.append(Insn.create(opc_return));
449
450         methodAttrs.addElement(
451             new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
452                               3, // maxStack (maybe only 2 - ok)
453                               1, // maxLocals
454                               begin,
455                               new ExceptionTable(),
456                               new AttributeVector()));
457         return clearContentsMethod;
458     }
459 */

460
461     /**
462      * Build an empty class initializer method for this class
463      */

464 //@olsen: dropped method
465
/*
466     ClassMethod makeClassInit(ClassAction ca) {
467         final ConstantPool pool = ca.classFile().pool();
468         final ConstClass thisClass = ca.classFile().className();
469
470         final AttributeVector methodAttrs = new AttributeVector();
471         ClassMethod classInitMethod =
472             new ClassMethod(ACCStatic,
473                             pool.addUtf8("<clinit>"),
474                             pool.addUtf8("()V"),
475                             methodAttrs);
476
477         // begin of method body
478         Insn begin = new InsnTarget();
479         Insn insn = begin;
480
481         // return from the initializer
482         // end of method body
483         insn = insn.append(Insn.create(opc_return));
484
485         methodAttrs.addElement(
486             new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
487                               0,
488                               0, // maxLocals
489                               begin,
490                               new ExceptionTable(),
491                               new AttributeVector()));
492         return classInitMethod;
493     }
494 */

495
496     /**
497      * Build the jdoGetStateManager method for the class.
498      *
499      * public StateManager jdoGetStateManager() {
500      * return this.jdoStateManager;
501      * }
502      */

503     //@olsen: cosmetics
504
ClassMethod makeJDOGetStateManager(final ClassAction ca,
505                                        final String JavaDoc methodName) {
506         //@olsen: added variable
507
final String JavaDoc methodSig = "()" + JDOMetaData.JDOStateManagerSig;//NOI18N
508
env.message("adding "//NOI18N
509
+ ca.classControl().userClassName() +
510                     "." + methodName//NOI18N
511
+ Descriptor.userMethodArgs(methodSig));
512
513         final ConstantPool pool = ca.classFile().pool();
514         final ConstClass theClass = ca.classFile().className();
515
516         final AttributeVector methodAttrs = new AttributeVector();
517
518         //@olsen: made method final
519
final ClassMethod jdoGetStateManagerMethod
520             = new ClassMethod(ACCPublic | ACCFinal,
521                               pool.addUtf8(methodName),
522                               pool.addUtf8(methodSig),
523                               methodAttrs);
524
525         // begin of method body
526
//@olsen: fix 4467428, made 'begin' final InsnTarget
527
final InsnTarget begin = new InsnTarget();
528         Insn insn = begin;
529
530         // get jdoStateManager field
531
insn = insn.append(Insn.create(opc_aload_0));
532         insn = insn.append(
533             Insn.create(opc_getfield,
534                         pool.addFieldRef(theClass.asString(),
535                                          JDOMetaData.JDOStateManagerFieldName,
536                                          JDOMetaData.JDOStateManagerFieldSig)));
537
538         // end of method body
539
insn = insn.append(Insn.create(opc_areturn));
540
541         final AttributeVector codeSpecificAttrs = new AttributeVector();
542
543         //@olsen: fix 4467428, added dummy, non-empty line number table
544
if (addLineNumberTableAttr) {
545             codeSpecificAttrs.addElement(
546                 new LineNumberTableAttribute(
547                     pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
548                     new short[]{ 0 }, new InsnTarget[]{ begin }));
549         }
550
551         methodAttrs.addElement(
552             new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
553                               1, // maxStack
554
1, // maxLocals
555
begin,
556                               new ExceptionTable(),
557                               codeSpecificAttrs));
558
559         //@olsen: fix 4467428, added synthetic attribute for generated method
560
if (addSyntheticAttr) {
561             methodAttrs.addElement(
562                 new SyntheticAttribute(
563                     pool.addUtf8(SyntheticAttribute.expectedAttrName)));
564         }
565
566         return jdoGetStateManagerMethod;
567     }
568
569     /**
570      * Build the jdoSetStateManager method for the class.
571      *
572      * public void jdoSetStateManager(StateManager sm) {
573      * this.jdoStateManager = sm;
574      * }
575      */

576     //@olsen: cosmetics
577
ClassMethod makeJDOSetStateManager(final ClassAction ca,
578                                        final String JavaDoc methodName) {
579         //@olsen: added variable
580
final String JavaDoc methodSig = "(" + JDOMetaData.JDOStateManagerSig + ")V";//NOI18N
581
env.message("adding "//NOI18N
582
+ ca.classControl().userClassName() +
583                     "." + methodName//NOI18N
584
+ Descriptor.userMethodArgs(methodSig));
585
586         final ConstantPool pool = ca.classFile().pool();
587         final ConstClass theClass = ca.classFile().className();
588
589         final AttributeVector methodAttrs = new AttributeVector();
590
591         //@olsen: made method final
592
final ClassMethod jdoSetStateManagerMethod
593             = new ClassMethod(ACCPublic | ACCFinal,
594                               pool.addUtf8(methodName),
595                               pool.addUtf8(methodSig),
596                               methodAttrs);
597
598         // begin of method body
599
//@olsen: fix 4467428, made 'begin' final InsnTarget
600
final InsnTarget begin = new InsnTarget();
601         Insn insn = begin;
602
603         // put argument value to jdoStateManager field
604
insn = insn.append(Insn.create(opc_aload_0));
605         insn = insn.append(Insn.create(opc_aload_1));
606         insn = insn.append(
607             Insn.create(opc_putfield,
608                         pool.addFieldRef(theClass.asString(),
609                                          JDOMetaData.JDOStateManagerFieldName,
610                                          JDOMetaData.JDOStateManagerFieldSig)));
611
612         // end of method body
613
insn = insn.append(Insn.create(opc_return));
614
615         final AttributeVector codeSpecificAttrs = new AttributeVector();
616
617         //@olsen: fix 4467428, added dummy, non-empty line number table
618
if (addLineNumberTableAttr) {
619             codeSpecificAttrs.addElement(
620                 new LineNumberTableAttribute(
621                     pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
622                     new short[]{ 0 }, new InsnTarget[]{ begin }));
623         }
624
625         methodAttrs.addElement(
626             new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
627                               2, // maxStack
628
2, // maxLocals
629
begin,
630                               new ExceptionTable(),
631                               codeSpecificAttrs));
632
633         //@olsen: fix 4467428, added synthetic attribute for generated method
634
if (addSyntheticAttr) {
635             methodAttrs.addElement(
636                 new SyntheticAttribute(
637                     pool.addUtf8(SyntheticAttribute.expectedAttrName)));
638         }
639
640         return jdoSetStateManagerMethod;
641     }
642
643     /**
644      * Build the jdoGetFlags method for the class.
645      *
646      * public byte jdoGetFlags() {
647      * return this.jdoFlags;
648      * }
649      */

650     //@olsen: cosmetics
651
ClassMethod makeJDOGetFlags(final ClassAction ca,
652                                 final String JavaDoc methodName) {
653         //@olsen: added variable
654
final String JavaDoc methodSig = "()B";//NOI18N
655
env.message("adding "//NOI18N
656
+ ca.classControl().userClassName() +
657                     "." + methodName//NOI18N
658
+ Descriptor.userMethodArgs(methodSig));
659
660         final ConstantPool pool = ca.classFile().pool();
661         final ConstClass theClass = ca.classFile().className();
662
663         final AttributeVector methodAttrs = new AttributeVector();
664
665         //@olsen: made method final
666
final ClassMethod jdoGetFlagsMethod
667             = new ClassMethod(ACCPublic | ACCFinal,
668                               pool.addUtf8(methodName),
669                               pool.addUtf8(methodSig),
670                               methodAttrs);
671
672         // begin of method body
673
//@olsen: fix 4467428, made 'begin' final InsnTarget
674
final InsnTarget begin = new InsnTarget();
675         Insn insn = begin;
676
677         // get jdoFlags field
678
insn = insn.append(Insn.create(opc_aload_0));
679         insn = insn.append(
680             Insn.create(opc_getfield,
681                         pool.addFieldRef(theClass.asString(),
682                                          JDOMetaData.JDOFlagsFieldName,
683                                          JDOMetaData.JDOFlagsFieldSig)));
684
685         // end of method body
686
insn = insn.append(Insn.create(opc_ireturn));
687
688         final AttributeVector codeSpecificAttrs = new AttributeVector();
689
690         //@olsen: fix 4467428, added dummy, non-empty line number table
691
if (addLineNumberTableAttr) {
692             codeSpecificAttrs.addElement(
693                 new LineNumberTableAttribute(
694                     pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
695                     new short[]{ 0 }, new InsnTarget[]{ begin }));
696         }
697
698         methodAttrs.addElement(
699             new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
700                               1, // maxStack
701
1, // maxLocals
702
begin,
703                               new ExceptionTable(),
704                               codeSpecificAttrs));
705
706         //@olsen: fix 4467428, added synthetic attribute for generated method
707
if (addSyntheticAttr) {
708             methodAttrs.addElement(
709                 new SyntheticAttribute(
710                     pool.addUtf8(SyntheticAttribute.expectedAttrName)));
711         }
712
713         return jdoGetFlagsMethod;
714     }
715
716     /**
717      * Build the jdoSetFlags method for the class.
718      *
719      * public void jdoSetFlags(byte flags) {
720      * this.jdoFlags = flags;
721      * }
722      */

723     //@olsen: cosmetics
724
ClassMethod makeJDOSetFlags(final ClassAction ca,
725                                 final String JavaDoc methodName) {
726         //@olsen: added variable
727
final String JavaDoc methodSig = "(B)V";//NOI18N
728
env.message("adding "//NOI18N
729
+ ca.classControl().userClassName() +
730                     "." + methodName//NOI18N
731
+ Descriptor.userMethodArgs(methodSig));
732
733         final ConstantPool pool = ca.classFile().pool();
734         final ConstClass theClass = ca.classFile().className();
735
736         final AttributeVector methodAttrs = new AttributeVector();
737
738         //@olsen: made method final
739
final ClassMethod jdoSetFlagsMethod
740             = new ClassMethod(ACCPublic | ACCFinal,
741                               pool.addUtf8(methodName),
742                               pool.addUtf8(methodSig),
743                               methodAttrs);
744
745         // begin of method body
746
//@olsen: fix 4467428, made 'begin' final InsnTarget
747
final InsnTarget begin = new InsnTarget();
748         Insn insn = begin;
749
750         // put argument value to jdoFlags field
751
insn = insn.append(Insn.create(opc_aload_0));
752         insn = insn.append(Insn.create(opc_iload_1));
753         insn = insn.append(
754             Insn.create(opc_putfield,
755                         pool.addFieldRef(theClass.asString(),
756                                          JDOMetaData.JDOFlagsFieldName,
757                                          JDOMetaData.JDOFlagsFieldSig)));
758
759         // end of method body
760
insn = insn.append(Insn.create(opc_return));
761
762         final AttributeVector codeSpecificAttrs = new AttributeVector();
763
764         //@olsen: fix 4467428, added dummy, non-empty line number table
765
if (addLineNumberTableAttr) {
766             codeSpecificAttrs.addElement(
767                 new LineNumberTableAttribute(
768                     pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
769                     new short[]{ 0 }, new InsnTarget[]{ begin }));
770         }
771
772         methodAttrs.addElement(
773             new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
774                               2, // maxStack
775
2, // maxLocals
776
begin,
777                               new ExceptionTable(),
778                               codeSpecificAttrs));
779
780         //@olsen: fix 4467428, added synthetic attribute for generated method
781
if (addSyntheticAttr) {
782             methodAttrs.addElement(
783                 new SyntheticAttribute(
784                     pool.addUtf8(SyntheticAttribute.expectedAttrName)));
785         }
786
787         return jdoSetFlagsMethod;
788     }
789
790     /**
791      * Build the jdoMakeDirty method for the class.
792      *
793      * public void makeDirty() {
794      * final StateManager sm = this.jdoStateManager;
795      * if (sm != null)
796      * sm.makeDirty(fieldName);
797      * }
798      */

799     //@olsen: added method for generating the jdoMakeDirty method
800
ClassMethod makeJDOMakeDirtyMethod(final ClassAction ca,
801                                        final String JavaDoc methodName) {
802         //@olsen: added variable
803
final String JavaDoc methodSig = "(Ljava/lang/String;)V";//NOI18N
804
env.message("adding "//NOI18N
805
+ ca.classControl().userClassName() +
806                     "." + methodName//NOI18N
807
+ Descriptor.userMethodArgs(methodSig));
808
809         final ConstantPool pool = ca.classFile().pool();
810         final ConstClass theClass = ca.classFile().className();
811
812         final AttributeVector methodAttrs = new AttributeVector();
813
814         //@olsen: made method final
815
final ClassMethod jdoMakeDirtyMethod
816             = new ClassMethod(ACCPublic | ACCFinal,
817                               pool.addUtf8(methodName),
818                               pool.addUtf8(methodSig),
819                               methodAttrs);
820
821         // begin of method body
822
//@olsen: fix 4467428, made 'begin' final InsnTarget
823
final InsnTarget begin = new InsnTarget();
824         Insn insn = begin;
825
826         // fetch the jdoStateManager field into local var
827
insn = insn.append(Insn.create(opc_aload_0));
828         insn = insn.append(
829             Insn.create(
830                 opc_getfield,
831                 pool.addFieldRef(theClass.asString(),
832                                  JDOMetaData.JDOStateManagerFieldName,
833                                  JDOMetaData.JDOStateManagerFieldSig)));
834         insn = insn.append(Insn.create(opc_astore_2));
835
836         // test the jdoStateManager field and goto end if null
837
InsnTarget end = new InsnTarget();
838         insn = insn.append(Insn.create(opc_aload_2));
839         insn = insn.append(Insn.create(opc_ifnull, end));
840
841         // call the jdoStateManager's makeDirty method with argument
842
insn = insn.append(Insn.create(opc_aload_2));
843         insn = insn.append(Insn.create(opc_aload_1));
844         insn = insn.append(
845             new InsnInterfaceInvoke(
846                 pool.addInterfaceMethodRef(
847                     JDOMetaData.JDOStateManagerPath,
848                     "makeDirty",//NOI18N
849
"(Ljava/lang/String;)V"),//NOI18N
850
2));
851
852         // end of method body
853
insn = insn.append(end);
854         insn = insn.append(Insn.create(opc_return));
855
856         final AttributeVector codeSpecificAttrs = new AttributeVector();
857
858         //@olsen: fix 4467428, added dummy, non-empty line number table
859
if (addLineNumberTableAttr) {
860             codeSpecificAttrs.addElement(
861                 new LineNumberTableAttribute(
862                     pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
863                     new short[]{ 0 }, new InsnTarget[]{ begin }));
864         }
865
866         methodAttrs.addElement(
867             new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
868                               2, // maxStack
869
3, // maxLocals
870
begin,
871                               new ExceptionTable(),
872                               codeSpecificAttrs));
873
874         //@olsen: fix 4467428, added synthetic attribute for generated method
875
if (addSyntheticAttr) {
876             methodAttrs.addElement(
877                 new SyntheticAttribute(
878                     pool.addUtf8(SyntheticAttribute.expectedAttrName)));
879         }
880
881         return jdoMakeDirtyMethod;
882     }
883
884     /**
885      * Build an interrogative method named methodName for the class.
886      *
887      * public boolean isXXX() {
888      * final StateManager sm = this.jdoStateManager;
889      * if (sm == null)
890      * return false;
891      * return sm.isXXXX();
892      * }
893      */

894     //@olsen: added method for generating an interrogative JDO method
895
ClassMethod makeJDOInterrogativeMethod(final ClassAction ca,
896                                            final String JavaDoc methodName) {
897         //@olsen: added variable
898
final String JavaDoc methodSig = "()Z";//NOI18N
899
env.message("adding "//NOI18N
900
+ ca.classControl().userClassName() +
901                     "." + methodName//NOI18N
902
+ Descriptor.userMethodArgs(methodSig));
903
904         final ConstantPool pool = ca.classFile().pool();
905         final ConstClass theClass = ca.classFile().className();
906
907         final AttributeVector methodAttrs = new AttributeVector();
908
909         //@olsen: made method final
910
final ClassMethod interrogativeMethod
911             = new ClassMethod(ACCPublic | ACCFinal,
912                               pool.addUtf8(methodName),
913                               pool.addUtf8(methodSig),
914                               methodAttrs);
915
916         // begin of method body
917
//@olsen: fix 4467428, made 'begin' final InsnTarget
918
final InsnTarget begin = new InsnTarget();
919         Insn insn = begin;
920
921         // fetch the jdoStateManager field into local var
922
insn = insn.append(Insn.create(opc_aload_0));
923         insn = insn.append(
924             Insn.create(
925                 opc_getfield,
926                 pool.addFieldRef(theClass.asString(),
927                                  JDOMetaData.JDOStateManagerFieldName,
928                                  JDOMetaData.JDOStateManagerFieldSig)));
929         insn = insn.append(Insn.create(opc_astore_1));
930
931         // test the jdoStateManager field and return false if null
932
InsnTarget call = new InsnTarget();
933         insn = insn.append(Insn.create(opc_aload_1));
934         insn = insn.append(Insn.create(opc_ifnonnull, call));
935         insn = insn.append(Insn.create(opc_iconst_0));
936         insn = insn.append(Insn.create(opc_ireturn));
937
938         // call the jdoStateManager's interrogative method (jdoIs... -> is...)
939
final String JavaDoc callName = "i" + methodName.substring(4);//NOI18N
940
insn = insn.append(call);
941         insn = insn.append(Insn.create(opc_aload_1));
942         insn = insn.append(
943             new InsnInterfaceInvoke(
944                 pool.addInterfaceMethodRef(
945                     JDOMetaData.JDOStateManagerPath,
946                     callName,
947                     "()Z"),//NOI18N
948
1));
949
950         // end of method body
951
insn = insn.append(Insn.create(opc_ireturn));
952
953         final AttributeVector codeSpecificAttrs = new AttributeVector();
954
955         //@olsen: fix 4467428, added dummy, non-empty line number table
956
if (addLineNumberTableAttr) {
957             codeSpecificAttrs.addElement(
958                 new LineNumberTableAttribute(
959                     pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
960                     new short[]{ 0 }, new InsnTarget[]{ begin }));
961         }
962
963         methodAttrs.addElement(
964             new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
965                               1, // maxStack
966
2, // maxLocals
967
begin,
968                               new ExceptionTable(),
969                               codeSpecificAttrs));
970
971         //@olsen: fix 4467428, added synthetic attribute for generated method
972
if (addSyntheticAttr) {
973             methodAttrs.addElement(
974                 new SyntheticAttribute(
975                     pool.addUtf8(SyntheticAttribute.expectedAttrName)));
976         }
977
978         return interrogativeMethod;
979     }
980
981     /**
982      * Build the jdoGetPersistenceManager method for the class.
983      *
984      * public PersistenceManager jdoGetPersistenceManager() {
985      * final StateManager sm = this.jdoStateManager;
986      * if (sm == null)
987      * return null;
988      * return sm.getPersistenceManager();
989      * }
990      */

991     //@olsen: added method for generating the jdoGetPersistenceManager method
992
ClassMethod makeJDOGetPersistenceManagerMethod(final ClassAction ca,
993                                                    final String JavaDoc methodName) {
994         //@olsen: added variable
995
final String JavaDoc methodSig = "()" + JDOMetaData.JDOPersistenceManagerSig;//NOI18N
996
env.message("adding "//NOI18N
997
+ ca.classControl().userClassName() +
998                     "." + methodName//NOI18N
999
+ Descriptor.userMethodArgs(methodSig));
1000
1001        final ConstantPool pool = ca.classFile().pool();
1002        final ConstClass theClass = ca.classFile().className();
1003
1004        final AttributeVector methodAttrs = new AttributeVector();
1005
1006        //@olsen: made method final
1007
final ClassMethod jdoGetPersistenceManagerMethod
1008            = new ClassMethod(ACCPublic | ACCFinal,
1009                              pool.addUtf8(methodName),
1010                              pool.addUtf8(methodSig),
1011                              methodAttrs);
1012
1013        // begin of method body
1014
//@olsen: fix 4467428, made 'begin' final InsnTarget
1015
final InsnTarget begin = new InsnTarget();
1016        Insn insn = begin;
1017
1018        // fetch the jdoStateManager field into local var
1019
insn = insn.append(Insn.create(opc_aload_0));
1020        insn = insn.append(
1021            Insn.create(
1022                opc_getfield,
1023                pool.addFieldRef(theClass.asString(),
1024                                 JDOMetaData.JDOStateManagerFieldName,
1025                                 JDOMetaData.JDOStateManagerFieldSig)));
1026        insn = insn.append(Insn.create(opc_astore_1));
1027
1028        // test the jdoStateManager field and return null if null
1029
InsnTarget call = new InsnTarget();
1030        insn = insn.append(Insn.create(opc_aload_1));
1031        insn = insn.append(Insn.create(opc_ifnonnull, call));
1032        insn = insn.append(Insn.create(opc_aconst_null));
1033        insn = insn.append(Insn.create(opc_areturn));
1034
1035        // call the jdoStateManager's getPersistenceManager method
1036
insn = insn.append(call);
1037        insn = insn.append(Insn.create(opc_aload_1));
1038        insn = insn.append(
1039            new InsnInterfaceInvoke(
1040                pool.addInterfaceMethodRef(
1041                    JDOMetaData.JDOStateManagerPath,
1042                    "getPersistenceManager",//NOI18N
1043
"()" + JDOMetaData.JDOPersistenceManagerSig),//NOI18N
1044
1));
1045
1046        // end of method body
1047
insn = insn.append(Insn.create(opc_areturn));
1048
1049        final AttributeVector codeSpecificAttrs = new AttributeVector();
1050
1051        //@olsen: fix 4467428, added dummy, non-empty line number table
1052
if (addLineNumberTableAttr) {
1053            codeSpecificAttrs.addElement(
1054                new LineNumberTableAttribute(
1055                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
1056                    new short[]{ 0 }, new InsnTarget[]{ begin }));
1057        }
1058
1059        methodAttrs.addElement(
1060            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
1061                              1, // maxStack
1062
2, // maxLocals
1063
begin,
1064                              new ExceptionTable(),
1065                              codeSpecificAttrs));
1066
1067        //@olsen: fix 4467428, added synthetic attribute for generated method
1068
if (addSyntheticAttr) {
1069            methodAttrs.addElement(
1070                new SyntheticAttribute(
1071                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
1072        }
1073
1074        return jdoGetPersistenceManagerMethod;
1075    }
1076
1077    /**
1078     * Build the jdoGetObjectId method for the class.
1079     *
1080     * public Object jdoGetObjectId() {
1081     * final StateManager sm = this.jdoStateManager;
1082     * if (sm == null)
1083     * return null;
1084     * return sm.getObjectId();
1085     * }
1086     */

1087    //@olsen: added method for generating the jdoGetObjectId method
1088
ClassMethod makeJDOGetObjectIdMethod(final ClassAction ca,
1089                                         final String JavaDoc methodName) {
1090        //@olsen: added variable
1091
final String JavaDoc methodSig = "()Ljava/lang/Object;";//NOI18N
1092
env.message("adding "//NOI18N
1093
+ ca.classControl().userClassName() +
1094                    "." + methodName//NOI18N
1095
+ Descriptor.userMethodArgs(methodSig));
1096
1097        final ConstantPool pool = ca.classFile().pool();
1098        final ConstClass theClass = ca.classFile().className();
1099
1100        final AttributeVector methodAttrs = new AttributeVector();
1101
1102        //@olsen: made method final
1103
final ClassMethod jdoGetObjectIdMethod
1104            = new ClassMethod(ACCPublic | ACCFinal,
1105                              pool.addUtf8(methodName),
1106                              pool.addUtf8(methodSig),
1107                              methodAttrs);
1108
1109        // begin of method body
1110
//@olsen: fix 4467428, made 'begin' final InsnTarget
1111
final InsnTarget begin = new InsnTarget();
1112        Insn insn = begin;
1113
1114        // fetch the jdoStateManager field into local var
1115
insn = insn.append(Insn.create(opc_aload_0));
1116        insn = insn.append(
1117            Insn.create(
1118                opc_getfield,
1119                pool.addFieldRef(theClass.asString(),
1120                                 JDOMetaData.JDOStateManagerFieldName,
1121                                 JDOMetaData.JDOStateManagerFieldSig)));
1122        insn = insn.append(Insn.create(opc_astore_1));
1123
1124        // test the jdoStateManager field and return null if null
1125
InsnTarget call = new InsnTarget();
1126        insn = insn.append(Insn.create(opc_aload_1));
1127        insn = insn.append(Insn.create(opc_ifnonnull, call));
1128        insn = insn.append(Insn.create(opc_aconst_null));
1129        insn = insn.append(Insn.create(opc_areturn));
1130
1131        // call the jdoStateManager's getObjectId method
1132
insn = insn.append(call);
1133        insn = insn.append(Insn.create(opc_aload_1));
1134        insn = insn.append(
1135            new InsnInterfaceInvoke(
1136                pool.addInterfaceMethodRef(
1137                    JDOMetaData.JDOStateManagerPath,
1138                    "getObjectId",//NOI18N
1139
"()Ljava/lang/Object;"),//NOI18N
1140
1));
1141
1142        // end of method body
1143
insn = insn.append(Insn.create(opc_areturn));
1144
1145        final AttributeVector codeSpecificAttrs = new AttributeVector();
1146
1147        //@olsen: fix 4467428, added dummy, non-empty line number table
1148
if (addLineNumberTableAttr) {
1149            codeSpecificAttrs.addElement(
1150                new LineNumberTableAttribute(
1151                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
1152                    new short[]{ 0 }, new InsnTarget[]{ begin }));
1153        }
1154
1155        methodAttrs.addElement(
1156            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
1157                              1, // maxStack
1158
2, // maxLocals
1159
begin,
1160                              new ExceptionTable(),
1161                              codeSpecificAttrs));
1162
1163        //@olsen: fix 4467428, added synthetic attribute for generated method
1164
if (addSyntheticAttr) {
1165            methodAttrs.addElement(
1166                new SyntheticAttribute(
1167                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
1168        }
1169
1170        return jdoGetObjectIdMethod;
1171    }
1172
1173    /**
1174     * Build the jdoGetJDOConstructor method for the class.
1175     *
1176     * public <init>(StateManager sm) {
1177     * this.jdoFlags = 1;
1178     * this.jdoStateManager = sm;
1179     * }
1180     */

1181    //@olsen: added method for generating the JDO constructor
1182
ClassMethod makeJDOConstructor(final ClassAction ca,
1183                                   final String JavaDoc methodName) {
1184        //@olsen: added variable
1185
final String JavaDoc methodSig = "(" + JDOMetaData.JDOStateManagerSig + ")V";//NOI18N
1186
env.message("adding "//NOI18N
1187
+ ca.classControl().userClassName() +
1188                    "." + methodName//NOI18N
1189
+ Descriptor.userMethodArgs(methodSig));
1190
1191        final ConstantPool pool = ca.classFile().pool();
1192        final ConstClass theClass = ca.classFile().className();
1193
1194        final AttributeVector methodAttrs = new AttributeVector();
1195        final ClassMethod jdoGetJDOConstructor
1196            = new ClassMethod(ACCPublic,
1197                              pool.addUtf8(methodName),
1198                              pool.addUtf8(methodSig),
1199                              methodAttrs);
1200
1201        // begin of method body
1202
//@olsen: fix 4467428, made 'begin' final InsnTarget
1203
final InsnTarget begin = new InsnTarget();
1204        Insn insn = begin;
1205
1206        // call the super-class' constructor
1207
final ConstClass superClass = ca.classFile().superName();
1208        insn = insn.append(Insn.create(opc_aload_0));
1209        insn = insn.append(
1210            Insn.create(opc_invokespecial,
1211                        pool.addMethodRef(superClass.asString(),
1212                                          "<init>",//NOI18N
1213
"()V")));//NOI18N
1214

1215        // put argument value to jdoFlags field
1216
insn = insn.append(Insn.create(opc_aload_0));
1217        insn = insn.append(Insn.create(opc_iconst_1));
1218        insn = insn.append(
1219            Insn.create(opc_putfield,
1220                        pool.addFieldRef(theClass.asString(),
1221                                         JDOMetaData.JDOFlagsFieldName,
1222                                         JDOMetaData.JDOFlagsFieldSig)));
1223
1224        // put argument value to jdoStateManager field
1225
insn = insn.append(Insn.create(opc_aload_0));
1226        insn = insn.append(Insn.create(opc_aload_1));
1227        insn = insn.append(
1228            Insn.create(
1229                opc_putfield,
1230                pool.addFieldRef(theClass.asString(),
1231                                 JDOMetaData.JDOStateManagerFieldName,
1232                                 JDOMetaData.JDOStateManagerFieldSig)));
1233
1234        // end of method body
1235
insn = insn.append(Insn.create(opc_return));
1236
1237        final AttributeVector codeSpecificAttrs = new AttributeVector();
1238
1239        //@olsen: fix 4467428, added dummy, non-empty line number table
1240
if (addLineNumberTableAttr) {
1241            codeSpecificAttrs.addElement(
1242                new LineNumberTableAttribute(
1243                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
1244                    new short[]{ 0 }, new InsnTarget[]{ begin }));
1245        }
1246
1247        methodAttrs.addElement(
1248            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
1249                              2, // maxStack
1250
2, // maxLocals
1251
begin,
1252                              new ExceptionTable(),
1253                              codeSpecificAttrs));
1254
1255        //@olsen: fix 4467428, added synthetic attribute for generated method
1256
if (addSyntheticAttr) {
1257            methodAttrs.addElement(
1258                new SyntheticAttribute(
1259                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
1260        }
1261
1262        return jdoGetJDOConstructor;
1263    }
1264
1265    /**
1266     * Build the jdoNewInstance method for the class.
1267     *
1268     * public Object jdoNewInstance(StateManager sm) {
1269     * return new <init>(sm);
1270     * }
1271     */

1272    //@olsen: added method for generating the getObjectId method
1273
ClassMethod makeJDONewInstanceMethod(final ClassAction ca,
1274                                         final String JavaDoc methodName) {
1275        //@olsen: added variable
1276
final String JavaDoc methodSig
1277            = "(" + JDOMetaData.JDOStateManagerSig + ")Ljava/lang/Object;";//NOI18N
1278
env.message("adding "//NOI18N
1279
+ ca.classControl().userClassName() +
1280                    "." + methodName//NOI18N
1281
+ Descriptor.userMethodArgs(methodSig));
1282
1283        final ConstantPool pool = ca.classFile().pool();
1284        final ConstClass theClass = ca.classFile().className();
1285
1286        final AttributeVector methodAttrs = new AttributeVector();
1287        final ClassMethod jdoNewInstanceMethod
1288            = new ClassMethod(ACCPublic,
1289                              pool.addUtf8(methodName),
1290                              pool.addUtf8(methodSig),
1291                              methodAttrs);
1292
1293        // begin of method body
1294
//@olsen: fix 4467428, made 'begin' final InsnTarget
1295
final InsnTarget begin = new InsnTarget();
1296        Insn insn = begin;
1297
1298        // create an instance of the class by JDO constructor
1299
insn = insn.append(Insn.create(opc_new, theClass));
1300        insn = insn.append(Insn.create(opc_dup));
1301        insn = insn.append(Insn.create(opc_aload_1));
1302        insn = insn.append(
1303            Insn.create(
1304                opc_invokespecial,
1305                pool.addMethodRef(
1306                    theClass.asString(),
1307                    "<init>",//NOI18N
1308
"(" + JDOMetaData.JDOStateManagerSig + ")V")));//NOI18N
1309

1310        // end of method body
1311
insn = insn.append(Insn.create(opc_areturn));
1312
1313        final AttributeVector codeSpecificAttrs = new AttributeVector();
1314
1315        //@olsen: fix 4467428, added dummy, non-empty line number table
1316
if (addLineNumberTableAttr) {
1317            codeSpecificAttrs.addElement(
1318                new LineNumberTableAttribute(
1319                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
1320                    new short[]{ 0 }, new InsnTarget[]{ begin }));
1321        }
1322
1323        methodAttrs.addElement(
1324            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
1325                              3, // maxStack
1326
2, // maxLocals
1327
begin,
1328                              new ExceptionTable(),
1329                              codeSpecificAttrs));
1330
1331        //@olsen: fix 4467428, added synthetic attribute for generated method
1332
if (addSyntheticAttr) {
1333            methodAttrs.addElement(
1334                new SyntheticAttribute(
1335                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
1336        }
1337
1338        return jdoNewInstanceMethod;
1339    }
1340
1341    /**
1342     * Build the jdoClear method for the class.
1343     *
1344     * public void jdoClear() {
1345     * ...
1346     * }
1347     */

1348    //@olsen: added method for generating the jdoClear method
1349
ClassMethod makeJDOClearMethod(final ClassAction ca,
1350                                   final String JavaDoc methodName) {
1351        //@olsen: added variable
1352
final String JavaDoc methodSig = "()V";//NOI18N
1353
env.message("adding "//NOI18N
1354
+ ca.classControl().userClassName() +
1355                    "." + methodName//NOI18N
1356
+ Descriptor.userMethodArgs(methodSig));
1357
1358        final ConstantPool pool = ca.classFile().pool();
1359        final ConstClass theClass = ca.classFile().className();
1360
1361        final AttributeVector methodAttrs = new AttributeVector();
1362        final ClassMethod jdoClearMethod
1363            = new ClassMethod(ACCPublic,
1364                              pool.addUtf8(methodName),
1365                              pool.addUtf8(methodSig),
1366                              methodAttrs);
1367
1368        // begin of method body
1369
//@olsen: fix 4467428, made 'begin' final InsnTarget
1370
final InsnTarget begin = new InsnTarget();
1371        Insn insn = begin;
1372
1373        //@olsen: disabled code
1374
if (false) {
1375            // reset jdoFlags = LOAD_REQUIRED
1376
insn = insn.append(Insn.create(opc_aload_0));
1377            insn = insn.append(Insn.create(opc_iconst_1));
1378            insn = insn.append(
1379                Insn.create(opc_putfield,
1380                            pool.addFieldRef(theClass.asString(),
1381                                             JDOMetaData.JDOFlagsFieldName,
1382                                             JDOMetaData.JDOFlagsFieldSig)));
1383        }
1384
1385        // iterate over all declared fields of the class
1386
for (Iterator JavaDoc e = ca.fieldActions(); e.hasNext();) {
1387            final FieldAction act = (FieldAction)e.next();
1388            //printFieldAction(act);
1389
//System.out.println();
1390

1391            // ignore non-persistent fields
1392
if (!act.isPersistent())
1393                continue;
1394
1395            // ignore primary key fields
1396
if (act.isPrimaryKey())
1397                continue;
1398
1399            //@olsen: disconnect mutable SCOs before clear
1400
if (act.isMutableSCO()) {
1401                // fetch field
1402
insn = insn.append(Insn.create(opc_aload_0));
1403                insn = insn.append(
1404                    Insn.create(opc_getfield,
1405                                pool.addFieldRef(
1406                                    theClass.asString(),
1407                                    act.fieldName(),
1408                                    act.typeDescriptor())));
1409
1410                // test whether instanceof SCO base type
1411
// skip disconnecting if == 0
1412
final ConstClass cc
1413                    = pool.addClass(JDOMetaData.JDOSecondClassObjectBasePath);
1414                InsnTarget disconnect = new InsnTarget();
1415                InsnTarget afterDisconnect = new InsnTarget();
1416                insn = insn.append(
1417                    Insn.create(opc_dup));
1418                insn = insn.append(
1419                    Insn.create(opc_instanceof,
1420                                cc));
1421                insn = insn.append(
1422                    Insn.create(opc_ifne,
1423                                disconnect));
1424
1425                // pop field and skip disconnecting
1426
insn = insn.append(
1427                    Insn.create(opc_pop));
1428                insn = insn.append(
1429                    Insn.create(opc_goto, afterDisconnect));
1430
1431                // disconnect SCO field's object
1432
insn = insn.append(disconnect);
1433
1434                // cast to SCO base type
1435
insn = insn.append(
1436                    Insn.create(opc_checkcast,
1437                                cc));
1438
1439                // call method: void unsetOwner();
1440
final int requiredStack = 1;
1441                insn = insn.append(
1442                    new InsnInterfaceInvoke(
1443                        pool.addInterfaceMethodRef(
1444                            JDOMetaData.JDOSecondClassObjectBasePath,
1445                            "unsetOwner",//NOI18N
1446
"()V"),//NOI18N
1447
requiredStack));
1448
1449                insn = insn.append(afterDisconnect);
1450            }
1451
1452            // get this
1453
insn = insn.append(Insn.create(opc_aload_0));
1454
1455            // use the getMethodReturn type to decide how to clear field
1456
switch(act.getMethodReturn()) {
1457            case T_DOUBLE:
1458                insn = insn.append(Insn.create(opc_dconst_0));
1459                break;
1460            case T_LONG:
1461                insn = insn.append(Insn.create(opc_lconst_0));
1462                break;
1463            case T_FLOAT:
1464                insn = insn.append(Insn.create(opc_fconst_0));
1465                break;
1466            case T_BOOLEAN:
1467            case T_CHAR:
1468            case T_BYTE:
1469            case T_SHORT:
1470            case T_INT:
1471                insn = insn.append(Insn.create(opc_iconst_0));
1472                break;
1473            case TC_STRING:
1474            case TC_OBJECT:
1475            case TC_INTERFACE:
1476                insn = insn.append(Insn.create(opc_aconst_null));
1477                break;
1478            default:
1479                throw new InternalError JavaDoc("Unexpected return type");//NOI18N
1480
}
1481
1482            // put default value to field
1483
insn = insn.append(
1484                Insn.create(opc_putfield,
1485                            pool.addFieldRef(theClass.asString(),
1486                                             act.fieldName(),
1487                                             act.typeDescriptor())));
1488        }
1489
1490        // end of method body
1491
insn = insn.append(Insn.create(opc_return));
1492
1493        final AttributeVector codeSpecificAttrs = new AttributeVector();
1494
1495        //@olsen: fix 4467428, added dummy, non-empty line number table
1496
if (addLineNumberTableAttr) {
1497            codeSpecificAttrs.addElement(
1498                new LineNumberTableAttribute(
1499                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
1500                    new short[]{ 0 }, new InsnTarget[]{ begin }));
1501        }
1502
1503        methodAttrs.addElement(
1504            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
1505                              3, // maxStack
1506
1, // maxLocals
1507
begin,
1508                              new ExceptionTable(),
1509                              codeSpecificAttrs));
1510
1511        //@olsen: fix 4467428, added synthetic attribute for generated method
1512
if (addSyntheticAttr) {
1513            methodAttrs.addElement(
1514                new SyntheticAttribute(
1515                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
1516        }
1517
1518        return jdoClearMethod;
1519    }
1520
1521    /**
1522     * Build the jdoCopy method for the class.
1523     *
1524     * public void jdoCopy(Object o, boolean cloneSCOs) {
1525     * ...
1526     * }
1527     */

1528//@lars, @olsen: disabled jdoCopy becuase of two problems with the
1529
// current code (this method hasn't been used by the runtime anyway):
1530
// 4388418: Generated jdoCopy() must ignore static fields
1531
// 4388367: Generated jdoCopy() can throw NPE if argument = 'true'
1532
/*
1533    //@olsen: added method for generating the jdoCopy method
1534    ClassMethod makeJDOCopyMethod(final ClassAction ca,
1535                                  final String methodName) {
1536
1537        //@olsen: added variable
1538        final String methodSig = "(Ljava/lang/Object;Z)V";//NOI18N
1539        env.message("adding "//NOI18N
1540                    + ca.classControl().userClassName() +
1541                    "." + methodName//NOI18N
1542                    + Descriptor.userMethodArgs(methodSig));
1543
1544        final ConstantPool pool = ca.classFile().pool();
1545        final ConstClass theClass = ca.classFile().className();
1546
1547        final AttributeVector methodAttrs = new AttributeVector();
1548        final ClassMethod jdoCopyMethod
1549            = new ClassMethod(ACCPublic,
1550                              pool.addUtf8(methodName),
1551                              pool.addUtf8(methodSig),
1552                              methodAttrs);
1553
1554        // begin of method body
1555        //@olsen: fix 4467428, made 'begin' final InsnTarget
1556        final InsnTarget begin = new InsnTarget();
1557        Insn insn = begin;
1558
1559        // get class object of this and of argument object
1560        insn = insn.append(Insn.create(opc_aload_1));
1561        insn = insn.append(
1562            Insn.create(opc_invokevirtual,
1563                        pool.addMethodRef(
1564                            "java/lang/Object",//NOI18N
1565                            "getClass",//NOI18N
1566                            "()Ljava/lang/Class;")));//NOI18N
1567        insn = insn.append(Insn.create(opc_aload_1));
1568        insn = insn.append(
1569            Insn.create(opc_invokevirtual,
1570                        pool.addMethodRef(
1571                            "java/lang/Object",//NOI18N
1572                            "getClass",//NOI18N
1573                            "()Ljava/lang/Class;")));//NOI18N
1574
1575        // test class objects for equality and throw exception if false
1576        insn = insn.append(
1577            Insn.create(opc_invokevirtual,
1578                        pool.addMethodRef(
1579                            "java/lang/Object",//NOI18N
1580                            "equals",//NOI18N
1581                            "(Ljava/lang/Object;)Z")));//NOI18N
1582        InsnTarget cast = new InsnTarget();
1583        insn = insn.append(Insn.create(opc_ifne, cast));
1584        final String exceptionClassName
1585            = "com/sun/forte4j/persistence/JDOFatalException";//NOI18N
1586        insn = insn.append(
1587            Insn.create(opc_new,
1588                        pool.addClass(exceptionClassName)));
1589        insn = insn.append(Insn.create(opc_dup));
1590        insn = insn.append(
1591            Insn.create(opc_invokespecial,
1592                        pool.addMethodRef(
1593                            exceptionClassName,
1594                            "<init>",//NOI18N
1595                            "()V")));//NOI18N
1596        insn = insn.append(Insn.create(opc_athrow));
1597
1598        // cast argument object to this class' type and store into local var
1599        insn = insn.append(cast);
1600        insn = insn.append(Insn.create(opc_aload_1));
1601        insn = insn.append(Insn.create(opc_checkcast, theClass));
1602        insn = insn.append(Insn.create(opc_astore_3));
1603
1604        // iterate over all declared fields of the class
1605        final ArrayList mscoFields = new ArrayList();
1606        final JDOMetaData jdoMetaData = env.getJDOMetaData();
1607        for (Iterator e = ca.fieldActions(); e.hasNext();) {
1608            final FieldAction act = (FieldAction)e.next();
1609            //printFieldAction(act);
1610            //System.out.println();
1611
1612            // remember fields of MSCO type for later processing
1613            if (act.isMutableSCO()) {
1614                mscoFields.add(act);
1615                continue;
1616            }
1617
1618            // get this object
1619            insn = insn.append(Insn.create(opc_aload_0));
1620
1621            // fetch arguments object's field
1622            insn = insn.append(Insn.create(opc_aload_3));
1623            insn = insn.append(
1624                Insn.create(opc_getfield,
1625                            pool.addFieldRef(
1626                                theClass.asString(),
1627                                act.fieldName(),
1628                                act.typeDescriptor())));
1629
1630            // store into this object's field
1631            insn = insn.append(
1632                Insn.create(opc_putfield,
1633                            pool.addFieldRef(
1634                                theClass.asString(),
1635                                act.fieldName(),
1636                                act.typeDescriptor())));
1637        }
1638
1639        if (mscoFields.size() > 0) {
1640            // test boolean argument value and clone msco fields if true
1641            insn = insn.append(Insn.create(opc_iload_2));
1642            InsnTarget shallow = new InsnTarget();
1643            insn = insn.append(Insn.create(opc_ifeq, shallow));
1644
1645            // clone fields
1646            for (Iterator i = mscoFields.iterator(); i.hasNext();) {
1647                final FieldAction act = (FieldAction)i.next();
1648
1649                // get this object
1650                insn = insn.append(Insn.create(opc_aload_0));
1651
1652                // fetch arguments object's field
1653                insn = insn.append(Insn.create(opc_aload_3));
1654                insn = insn.append(
1655                    Insn.create(opc_getfield,
1656                                pool.addFieldRef(
1657                                    theClass.asString(),
1658                                    act.fieldName(),
1659                                    act.typeDescriptor())));
1660
1661                // clone field value and cast to field's type
1662                insn = insn.append(
1663                    Insn.create(opc_invokevirtual,
1664                                pool.addMethodRef(
1665                                    act.typeName(),
1666                                    "clone",//NOI18N
1667                                    "()Ljava/lang/Object;")));//NOI18N
1668                insn = insn.append(
1669                    Insn.create(opc_checkcast,
1670                                pool.addClass(act.typeName())));
1671
1672                // store into this object's field
1673                insn = insn.append(
1674                    Insn.create(opc_putfield,
1675                                pool.addFieldRef(
1676                                    theClass.asString(),
1677                                    act.fieldName(),
1678                                    act.typeDescriptor())));
1679            }
1680            InsnTarget done = new InsnTarget();
1681            insn = insn.append(Insn.create(opc_goto, done));
1682
1683            // copy field values
1684            insn = insn.append(shallow);
1685            for (Iterator i = mscoFields.iterator(); i.hasNext();) {
1686                final FieldAction act = (FieldAction)i.next();
1687
1688                // get this object
1689                insn = insn.append(Insn.create(opc_aload_0));
1690
1691                // fetch arguments object's field
1692                insn = insn.append(Insn.create(opc_aload_3));
1693                insn = insn.append(
1694                    Insn.create(opc_getfield,
1695                                pool.addFieldRef(
1696                                    theClass.asString(),
1697                                    act.fieldName(),
1698                                    act.typeDescriptor())));
1699
1700                // store into this object's field
1701                insn = insn.append(
1702                    Insn.create(opc_putfield,
1703                                pool.addFieldRef(
1704                                    theClass.asString(),
1705                                    act.fieldName(),
1706                                    act.typeDescriptor())));
1707            }
1708
1709            insn = insn.append(done);
1710        }
1711
1712        // end of method body
1713        insn = insn.append(Insn.create(opc_return));
1714
1715        final AttributeVector codeSpecificAttrs = new AttributeVector();
1716
1717        //@olsen: fix 4467428, added dummy, non-empty line number table
1718        if (addLineNumberTableAttr) {
1719            codeSpecificAttrs.addElement(
1720                new LineNumberTableAttribute(
1721                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
1722                    new short[]{ 0 }, new InsnTarget[]{ begin }));
1723        }
1724
1725        methodAttrs.addElement(
1726            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
1727                              4, // maxStack
1728                              4, // maxLocals
1729                              begin,
1730                              new ExceptionTable(),
1731                              codeSpecificAttrs));
1732
1733        //@olsen: fix 4467428, added synthetic attribute for generated method
1734        if (addSyntheticAttr) {
1735            methodAttrs.addElement(
1736                new SyntheticAttribute(
1737                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
1738        }
1739
1740        return jdoCopyMethod;
1741    }
1742*/

1743
1744    /**
1745     * Build the jdoGetField method for the class.
1746     *
1747     * public Object jdoGetField(int fieldNumber) {
1748     * return ...
1749     * }
1750     */

1751    //@olsen: added method for generating the jdoGetField method
1752
ClassMethod makeJDOGetFieldMethod(final ClassAction ca,
1753                                      final String JavaDoc methodName) {
1754        //@olsen: added variable
1755
final String JavaDoc methodSig = "(I)Ljava/lang/Object;";//NOI18N
1756
env.message("adding "//NOI18N
1757
+ ca.classControl().userClassName() +
1758                    "." + methodName//NOI18N
1759
+ Descriptor.userMethodArgs(methodSig));
1760
1761        final ConstantPool pool = ca.classFile().pool();
1762        final ConstClass theClass = ca.classFile().className();
1763
1764        final AttributeVector methodAttrs = new AttributeVector();
1765        final ClassMethod jdoGetFieldMethod
1766            = new ClassMethod(ACCPublic,
1767                              pool.addUtf8(methodName),
1768                              pool.addUtf8(methodSig),
1769                              methodAttrs);
1770
1771        // begin of method body
1772
//@olsen: fix 4467428, made 'begin' final InsnTarget
1773
final InsnTarget begin = new InsnTarget();
1774        Insn insn = begin;
1775
1776        // get the declared, persistent fields from the JDOMetaData
1777
final String JavaDoc className = ca.className();
1778        //@lars: changed getPersistentFields() into getManagedFields()
1779
final String JavaDoc[] fieldNames
1780            = env.getJDOMetaData().getManagedFields(className);
1781        final int nofFields = fieldNames.length;
1782        //@olsen: added println() for debugging
1783
if (false) {
1784            System.out.print("MethodBuilder.makeJDOGetFieldMethod(): "//NOI18N
1785
+ " declared, persistent fields of class '"//NOI18N
1786
+ className + "' = {");//NOI18N
1787
for (int i = 0; i < nofFields; i++)
1788                System.out.print(" " + fieldNames[i]);//NOI18N
1789
System.out.println(" }");//NOI18N
1790
}
1791
1792        // generate the switch-statement only if more than zero fields
1793
final InsnTarget defaultOp = new InsnTarget();
1794        if (nofFields > 0) {
1795            // get the declared, persistent fields from the class
1796
final HashMap JavaDoc fieldsByName = new HashMap JavaDoc();
1797            for (Iterator JavaDoc e = ca.fieldActions(); e.hasNext();) {
1798                final FieldAction act = (FieldAction)e.next();
1799                fieldsByName.put(act.fieldName(), act);
1800            }
1801
1802            // do the tableswitch on argument
1803
insn = insn.append(Insn.create(opc_iload_1));
1804            final int lowOp = 0;
1805            final InsnTarget[] targetsOp = new InsnTarget[nofFields];
1806            for (int i = 0; i < nofFields; i++)
1807                targetsOp[i] = new InsnTarget();
1808            insn = insn.append(
1809                new InsnTableSwitch(lowOp, defaultOp, targetsOp));
1810
1811            // do the case-targets for field accesses
1812
for (int i = 0; i < nofFields; i++) {
1813                // target for accessing field [i]
1814
insn = insn.append(targetsOp[i]);
1815
1816                final FieldAction act
1817                    = (FieldAction)fieldsByName.get(fieldNames[i]);
1818                affirm(act,
1819                       ("Field '" + fieldNames[i]//NOI18N
1820
+ "' returned by JDOMetaData is not known by class '"//NOI18N
1821
+ className + "'."));//NOI18N
1822

1823                // use the getMethodReturn type to create the wrapper object
1824
final String JavaDoc wrapperClassName;
1825                final String JavaDoc wrapperSignature;
1826                switch(act.getMethodReturn()) {
1827                case T_DOUBLE:
1828                    wrapperClassName = "java/lang/Double";//NOI18N
1829
wrapperSignature = "(D)V";//NOI18N
1830
insn = insn.append(
1831                        Insn.create(opc_new, pool.addClass(wrapperClassName)));
1832                    insn = insn.append(Insn.create(opc_dup));
1833                    break;
1834                case T_LONG:
1835                    wrapperClassName = "java/lang/Long";//NOI18N
1836
wrapperSignature = "(J)V";//NOI18N
1837
insn = insn.append(
1838                        Insn.create(opc_new, pool.addClass(wrapperClassName)));
1839                    insn = insn.append(Insn.create(opc_dup));
1840                    break;
1841                case T_FLOAT:
1842                    wrapperClassName = "java/lang/Float";//NOI18N
1843
wrapperSignature = "(F)V";//NOI18N
1844
insn = insn.append(
1845                        Insn.create(opc_new, pool.addClass(wrapperClassName)));
1846                    insn = insn.append(Insn.create(opc_dup));
1847                    break;
1848                case T_BOOLEAN:
1849                    wrapperClassName = "java/lang/Boolean";//NOI18N
1850
wrapperSignature = "(Z)V";//NOI18N
1851
insn = insn.append(
1852                        Insn.create(opc_new, pool.addClass(wrapperClassName)));
1853                    insn = insn.append(Insn.create(opc_dup));
1854                    break;
1855                case T_CHAR:
1856                    wrapperClassName = "java/lang/Character";//NOI18N
1857
wrapperSignature = "(C)V";//NOI18N
1858
insn = insn.append(
1859                        Insn.create(opc_new, pool.addClass(wrapperClassName)));
1860                    insn = insn.append(Insn.create(opc_dup));
1861                    break;
1862                case T_BYTE:
1863                    wrapperClassName = "java/lang/Byte";//NOI18N
1864
wrapperSignature = "(B)V";//NOI18N
1865
insn = insn.append(
1866                        Insn.create(opc_new, pool.addClass(wrapperClassName)));
1867                    insn = insn.append(Insn.create(opc_dup));
1868                    break;
1869                case T_SHORT:
1870                    wrapperClassName = "java/lang/Short";//NOI18N
1871
wrapperSignature = "(S)V";//NOI18N
1872
insn = insn.append(
1873                        Insn.create(opc_new, pool.addClass(wrapperClassName)));
1874                    insn = insn.append(Insn.create(opc_dup));
1875                    break;
1876                case T_INT:
1877                    wrapperClassName = "java/lang/Integer";//NOI18N
1878
wrapperSignature = "(I)V";//NOI18N
1879
insn = insn.append(
1880                        Insn.create(opc_new, pool.addClass(wrapperClassName)));
1881                    insn = insn.append(Insn.create(opc_dup));
1882                    break;
1883                case TC_STRING:
1884                case TC_OBJECT:
1885                case TC_INTERFACE:
1886                    wrapperClassName = null;
1887                    wrapperSignature = null;
1888                    break;
1889                default:
1890                    throw new InternalError JavaDoc("Unexpected return type");//NOI18N
1891
}
1892
1893                // fetch this object's field
1894
insn = insn.append(Insn.create(opc_aload_0));
1895                insn = insn.append(
1896                    Insn.create(
1897                        opc_getfield,
1898                        pool.addFieldRef(
1899                            theClass.asString(),
1900                            act.fieldName(),
1901                            act.typeDescriptor())));
1902
1903                // wrap the field value if primitive
1904
switch(act.getMethodReturn()) {
1905                case T_DOUBLE:
1906                case T_LONG:
1907                case T_FLOAT:
1908                case T_BOOLEAN:
1909                case T_CHAR:
1910                case T_BYTE:
1911                case T_SHORT:
1912                case T_INT:
1913                    insn = insn.append(
1914                        Insn.create(
1915                            opc_invokespecial,
1916                            pool.addMethodRef(
1917                                wrapperClassName,
1918                                "<init>",//NOI18N
1919
wrapperSignature)));
1920                    break;
1921                case TC_STRING:
1922                case TC_OBJECT:
1923                case TC_INTERFACE:
1924                    break;
1925                default:
1926                    throw new InternalError JavaDoc("Unexpected return type");//NOI18N
1927
}
1928
1929                // return the object (break)
1930
insn = insn.append(Insn.create(opc_areturn));
1931            }
1932        }
1933
1934        // do the default branch target creating a fatal exception
1935
insn = insn.append(defaultOp);
1936        final String JavaDoc exceptionClassName
1937            = "com/sun/jdo/api/persistence/support/JDOFatalException";//NOI18N
1938
insn = insn.append(
1939            Insn.create(
1940                opc_new,
1941                pool.addClass(exceptionClassName)));
1942        insn = insn.append(Insn.create(opc_dup));
1943        insn = insn.append(
1944            Insn.create(
1945                opc_invokespecial,
1946                pool.addMethodRef(
1947                    exceptionClassName,
1948                    "<init>",//NOI18N
1949
"()V")));//NOI18N
1950

1951        // end of method body
1952
insn = insn.append(Insn.create(opc_athrow));
1953
1954        final AttributeVector codeSpecificAttrs = new AttributeVector();
1955
1956        //@olsen: fix 4467428, added dummy, non-empty line number table
1957
if (addLineNumberTableAttr) {
1958            codeSpecificAttrs.addElement(
1959                new LineNumberTableAttribute(
1960                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
1961                    new short[]{ 0 }, new InsnTarget[]{ begin }));
1962        }
1963
1964        methodAttrs.addElement(
1965            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
1966                              4, // maxStack
1967
2, // maxLocals
1968
begin,
1969                              new ExceptionTable(),
1970                              codeSpecificAttrs));
1971
1972        //@olsen: fix 4467428, added synthetic attribute for generated method
1973
if (addSyntheticAttr) {
1974            methodAttrs.addElement(
1975                new SyntheticAttribute(
1976                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
1977        }
1978
1979        return jdoGetFieldMethod;
1980    }
1981
1982    /**
1983     * Build the jdoSetField method for the class.
1984     *
1985     * public jdoSetField(int fieldNumber, Object value) {
1986     * ...
1987     * }
1988     */

1989    //@olsen: added method for generating the jdoSetField method
1990
ClassMethod makeJDOSetFieldMethod(final ClassAction ca,
1991                                      final String JavaDoc methodName) {
1992        //@olsen: added variable
1993
final String JavaDoc methodSig = "(ILjava/lang/Object;)V";//NOI18N
1994
env.message("adding "//NOI18N
1995
+ ca.classControl().userClassName() +
1996                    "." + methodName//NOI18N
1997
+ Descriptor.userMethodArgs(methodSig));
1998
1999        final ConstantPool pool = ca.classFile().pool();
2000        final ConstClass theClass = ca.classFile().className();
2001
2002        final AttributeVector methodAttrs = new AttributeVector();
2003        final ClassMethod jdoSetFieldMethod
2004            = new ClassMethod(ACCPublic,
2005                              pool.addUtf8(methodName),
2006                              pool.addUtf8(methodSig),
2007                              methodAttrs);
2008
2009        // begin of method body
2010
//@olsen: fix 4467428, made 'begin' final InsnTarget
2011
final InsnTarget begin = new InsnTarget();
2012        Insn insn = begin;
2013
2014        // get the declared, persistent fields from the JDOMetaData
2015
final String JavaDoc className = ca.className();
2016        //@lars: changed getPersistentFields() into getManagedFields()
2017
final String JavaDoc[] fieldNames
2018            = env.getJDOMetaData().getManagedFields(className);
2019        final int nofFields = fieldNames.length;
2020        //@olsen: added println() for debugging
2021
if (false) {
2022            System.out.print("MethodBuilder.makeJDOSetFieldMethod(): "//NOI18N
2023
+ " declared, persistent fields of class '"//NOI18N
2024
+ className + "' = {");//NOI18N
2025
for (int i = 0; i < nofFields; i++)
2026                System.out.print(" " + fieldNames[i]);//NOI18N
2027
System.out.println(" }");//NOI18N
2028
}
2029
2030        // generate the switch-statement only if more than zero fields
2031
final InsnTarget defaultOp = new InsnTarget();
2032        if (nofFields > 0) {
2033            // get the declared, persistent fields from the class
2034
final HashMap JavaDoc fieldsByName = new HashMap JavaDoc();
2035            for (Iterator JavaDoc e = ca.fieldActions(); e.hasNext();) {
2036                final FieldAction act = (FieldAction)e.next();
2037                fieldsByName.put(act.fieldName(), act);
2038            }
2039
2040            // do the tableswitch on argument
2041
insn = insn.append(Insn.create(opc_iload_1));
2042            final int lowOp = 0;
2043            final InsnTarget[] targetsOp = new InsnTarget[nofFields];
2044            for (int i = 0; i < nofFields; i++)
2045                targetsOp[i] = new InsnTarget();
2046            insn = insn.append(
2047                new InsnTableSwitch(lowOp, defaultOp, targetsOp));
2048
2049            // do the case-targets for field accesses
2050
for (int i = 0; i < nofFields; i++) {
2051                // target for accessing field [i]
2052
insn = insn.append(targetsOp[i]);
2053
2054                final FieldAction act
2055                    = (FieldAction)fieldsByName.get(fieldNames[i]);
2056                affirm(act,
2057                       ("Field '"//NOI18N
2058
+ fieldNames[i]
2059                        + "' returned by JDOMetaData is not known by class '"//NOI18N
2060
+ className + "'."));//NOI18N
2061

2062                // get object and value argument
2063
insn = insn.append(Insn.create(opc_aload_0));
2064                insn = insn.append(Insn.create(opc_aload_2));
2065
2066                // use the getMethodReturn type to downcast the Object argument
2067
final String JavaDoc wrapperClassName;
2068                final String JavaDoc unwrapperSignature;
2069                final String JavaDoc unwrapperName;
2070                switch(act.getMethodReturn()) {
2071                case T_DOUBLE:
2072                    wrapperClassName = "java/lang/Double";//NOI18N
2073
unwrapperSignature = "()D";//NOI18N
2074
unwrapperName = "doubleValue";//NOI18N
2075
insn = insn.append(
2076                        Insn.create(opc_checkcast,
2077                                    pool.addClass(wrapperClassName)));
2078                    break;
2079                case T_LONG:
2080                    wrapperClassName = "java/lang/Long";//NOI18N
2081
unwrapperSignature = "()J";//NOI18N
2082
unwrapperName = "longValue";//NOI18N
2083
insn = insn.append(
2084                        Insn.create(opc_checkcast,
2085                                    pool.addClass(wrapperClassName)));
2086                    break;
2087                case T_FLOAT:
2088                    wrapperClassName = "java/lang/Float";//NOI18N
2089
unwrapperSignature = "()F";//NOI18N
2090
unwrapperName = "floatValue";//NOI18N
2091
insn = insn.append(
2092                        Insn.create(opc_checkcast,
2093                                    pool.addClass(wrapperClassName)));
2094                    break;
2095                case T_BOOLEAN:
2096                    wrapperClassName = "java/lang/Boolean";//NOI18N
2097
unwrapperSignature = "()Z";//NOI18N
2098
unwrapperName = "booleanValue";//NOI18N
2099
insn = insn.append(
2100                        Insn.create(opc_checkcast,
2101                                    pool.addClass(wrapperClassName)));
2102                    break;
2103                case T_CHAR:
2104                    wrapperClassName = "java/lang/Character";//NOI18N
2105
unwrapperSignature = "()C";//NOI18N
2106
unwrapperName = "charValue";//NOI18N
2107
insn = insn.append(
2108                        Insn.create(opc_checkcast,
2109                                    pool.addClass(wrapperClassName)));
2110                    break;
2111                case T_BYTE:
2112                    wrapperClassName = "java/lang/Byte";//NOI18N
2113
unwrapperSignature = "()B";//NOI18N
2114
unwrapperName = "byteValue";//NOI18N
2115
insn = insn.append(
2116                        Insn.create(opc_checkcast,
2117                                    pool.addClass(wrapperClassName)));
2118                    break;
2119                case T_SHORT:
2120                    wrapperClassName = "java/lang/Short";//NOI18N
2121
unwrapperSignature = "()S";//NOI18N
2122
unwrapperName = "shortValue";//NOI18N
2123
insn = insn.append(
2124                        Insn.create(opc_checkcast,
2125                                    pool.addClass(wrapperClassName)));
2126                    break;
2127                case T_INT:
2128                    wrapperClassName = "java/lang/Integer";//NOI18N
2129
unwrapperSignature = "()I";//NOI18N
2130
unwrapperName = "intValue";//NOI18N
2131
insn = insn.append(
2132                        Insn.create(opc_checkcast,
2133                                    pool.addClass(wrapperClassName)));
2134                    break;
2135                case TC_STRING:
2136                case TC_OBJECT:
2137                case TC_INTERFACE:
2138                    wrapperClassName = null;
2139                    unwrapperSignature = null;
2140                    unwrapperName = null;
2141                    insn = insn.append(
2142                        Insn.create(opc_checkcast,
2143                                    pool.addClass(act.typeName())));
2144                    break;
2145                default:
2146                    throw new InternalError JavaDoc("Unexpected return type");//NOI18N
2147
}
2148
2149                // unwrap the object if primitive wrapper
2150
switch(act.getMethodReturn()) {
2151                case T_DOUBLE:
2152                case T_LONG:
2153                case T_FLOAT:
2154                case T_BOOLEAN:
2155                case T_CHAR:
2156                case T_BYTE:
2157                case T_SHORT:
2158                case T_INT:
2159                    insn = insn.append(
2160                        Insn.create(
2161                            opc_invokevirtual,
2162                            pool.addMethodRef(
2163                                wrapperClassName,
2164                                unwrapperName,
2165                                unwrapperSignature)));
2166                    break;
2167                case TC_STRING:
2168                case TC_OBJECT:
2169                case TC_INTERFACE:
2170                    break;
2171                default:
2172                    throw new InternalError JavaDoc("Unexpected return type");//NOI18N
2173
}
2174
2175                // store argument value in field
2176
insn = insn.append(
2177                    Insn.create(
2178                        opc_putfield,
2179                        pool.addFieldRef(
2180                            theClass.asString(),
2181                            act.fieldName(),
2182                            act.typeDescriptor())));
2183
2184                // return (break)
2185
insn = insn.append(Insn.create(opc_return));
2186            }
2187        }
2188
2189        // do the default branch target creating a fatal exception
2190
insn = insn.append(defaultOp);
2191        final String JavaDoc exceptionClassName
2192            = "com/sun/jdo/api/persistence/support/JDOFatalException";//NOI18N
2193
insn = insn.append(
2194            Insn.create(
2195                opc_new,
2196                pool.addClass(exceptionClassName)));
2197        insn = insn.append(Insn.create(opc_dup));
2198        insn = insn.append(
2199            Insn.create(
2200                opc_invokespecial,
2201                pool.addMethodRef(
2202                    exceptionClassName,
2203                    "<init>",//NOI18N
2204
"()V")));//NOI18N
2205

2206        // end of method body
2207
insn = insn.append(Insn.create(opc_athrow));
2208
2209        final AttributeVector codeSpecificAttrs = new AttributeVector();
2210
2211        //@olsen: fix 4467428, added dummy, non-empty line number table
2212
if (addLineNumberTableAttr) {
2213            codeSpecificAttrs.addElement(
2214                new LineNumberTableAttribute(
2215                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
2216                    new short[]{ 0 }, new InsnTarget[]{ begin }));
2217        }
2218
2219        methodAttrs.addElement(
2220            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
2221                              3, // maxStack
2222
3, // maxLocals
2223
begin,
2224                              new ExceptionTable(),
2225                              codeSpecificAttrs));
2226
2227        //@olsen: fix 4467428, added synthetic attribute for generated method
2228
if (addSyntheticAttr) {
2229            methodAttrs.addElement(
2230                new SyntheticAttribute(
2231                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
2232        }
2233
2234        return jdoSetFieldMethod;
2235    }
2236
2237    /**
2238     * Build the clone method for the class.
2239     */

2240    //@olsen: subst: makeClone -> makeJDOClone
2241
ClassMethod makeJDOClone(final ClassAction ca,
2242                             final String JavaDoc methodName) {
2243        //@olsen: added variable
2244
final String JavaDoc methodSig = "()Ljava/lang/Object;";//NOI18N
2245
env.message("adding "//NOI18N
2246
+ ca.classControl().userClassName() +
2247                    "." + methodName//NOI18N
2248
+ Descriptor.userMethodArgs(methodSig));
2249
2250        final ClassFile cFile = ca.classFile();
2251        final ConstantPool pool = cFile.pool();
2252        final ConstClass theClass = cFile.className();
2253        final ConstClass superClass = cFile.superName();
2254
2255        final AttributeVector methodAttrs = new AttributeVector();
2256        //@olsen: fixed bug: changed ACCProtected to ACCPublic to allow for
2257
// an inherited method clone() to be public!
2258
//@olsen: removed ACCSynchronized flag
2259
final ClassMethod cloneMethod
2260            = new ClassMethod(ACCPublic, //|ACCSynchronized,
2261
pool.addUtf8(methodName),
2262                              pool.addUtf8(methodSig),
2263                              methodAttrs);
2264
2265        // begin of method body
2266
//@olsen: fix 4467428, made 'begin' final InsnTarget
2267
final InsnTarget begin = new InsnTarget();
2268        Insn insn = begin;
2269
2270//@olsen: disabled feature
2271
/*
2272        // if (jdoFlags < 0)
2273        // Implementation.fetch(this);
2274
2275        InsnTarget cloneStart = new InsnTarget();
2276
2277        insn = insn.append(Insn.create(opc_aload_0));
2278        insn = insn.append(
2279            Insn.create(opc_getfield,
2280                        pool.addFieldRef(theClass.asString(),
2281                                         JDOMetaData.JDOFlagsFieldName,
2282                                         JDOMetaData.JDOFlagsFieldSig)));
2283        insn = insn.append(Insn.create(opc_ifge, cloneStart));
2284
2285        insn = insn.append(Insn.create(opc_aload_0));
2286        insn = insn.append(
2287            Insn.create(opc_invokestatic,
2288                        pool.addMethodRef("com/sun/forte4j/persistence/internal/Implementation", "fetch",
2289                                          "(" + JDOMetaData.JDOPersistenceCapableSig + ")V")));
2290
2291        insn = insn.append(cloneStart);
2292*/

2293
2294        // THISCLASS newObject = (THISCLASS) super.clone();
2295
{
2296            insn = insn.append(Insn.create(opc_aload_0));
2297            insn = insn.append(
2298                Insn.create(opc_invokespecial,
2299                            pool.addMethodRef(superClass.asString(),
2300// pool.addMethodRef("java/lang/Object",
2301
methodName,
2302                                              methodSig)));
2303
2304            // add cast to the appropriate type
2305
insn = insn.append(Insn.create(opc_checkcast, theClass));
2306        }
2307
2308//@olsen: disabled feature
2309
/*
2310        if (ca.getNeedsJDOStateManagerMethods()) {
2311*/

2312        // newObject.jdoStateManager = null;
2313
if (false)
2314        {
2315            insn = insn.append(Insn.create(opc_dup));
2316            insn = insn.append(Insn.create(opc_aconst_null));
2317            insn = insn.append(
2318                Insn.create(
2319                    opc_putfield,
2320                    pool.addFieldRef(theClass.asString(),
2321                                     JDOMetaData.JDOStateManagerFieldName,
2322                                     JDOMetaData.JDOStateManagerFieldSig)));
2323        }
2324
2325//@olsen: disabled feature
2326
/*
2327        if (ca.getNeedsJDOFlagsMethods()) {
2328*/

2329        // newObject.jdoFlags = 0;
2330
if (false)
2331        {
2332            insn = insn.append(Insn.create(opc_dup));
2333            insn = insn.append(Insn.create(opc_iconst_0));
2334            insn = insn.append(
2335                Insn.create(opc_putfield,
2336                            pool.addFieldRef(theClass.asString(),
2337                                             JDOMetaData.JDOFlagsFieldName,
2338                                             JDOMetaData.JDOFlagsFieldSig)));
2339        }
2340
2341        // return newObject;
2342

2343        // end of method body
2344
insn = insn.append(Insn.create(opc_areturn));
2345
2346        final AttributeVector codeSpecificAttrs = new AttributeVector();
2347
2348        //@olsen: fix 4467428, added dummy, non-empty line number table
2349
if (addLineNumberTableAttr) {
2350            codeSpecificAttrs.addElement(
2351                new LineNumberTableAttribute(
2352                    pool.addUtf8(LineNumberTableAttribute.expectedAttrName),
2353                    new short[]{ 0 }, new InsnTarget[]{ begin }));
2354        }
2355
2356        methodAttrs.addElement(
2357            new CodeAttribute(pool.addUtf8(CodeAttribute.expectedAttrName),
2358                              //@olsen: updated maxLocals
2359
1, //3, //3, // maxStack
2360
1, //2, // maxLocals
2361
begin,
2362                              new ExceptionTable(),
2363                              codeSpecificAttrs));
2364
2365        //@olsen: fix 4467428, added synthetic attribute for generated method
2366
if (addSyntheticAttr) {
2367            methodAttrs.addElement(
2368                new SyntheticAttribute(
2369                    pool.addUtf8(SyntheticAttribute.expectedAttrName)));
2370        }
2371
2372        methodAttrs.addElement(
2373            new ExceptionsAttribute(
2374                pool.addUtf8(ExceptionsAttribute.expectedAttrName),
2375                pool.addClass("java/lang/CloneNotSupportedException")));//NOI18N
2376

2377        return cloneMethod;
2378    }
2379
2380    // for debugging
2381
static private void printFieldAction(FieldAction act) {
2382        System.out.println("fieldName() = " + act.fieldName());//NOI18N
2383
System.out.println("userFieldName() = " + act.userFieldName());//NOI18N
2384
System.out.println("typeDescriptor() = " + act.typeDescriptor());//NOI18N
2385
System.out.println("typeName() = " + act.typeName());//NOI18N
2386
System.out.println("fieldClassName() = " + act.fieldClassName());//NOI18N
2387
System.out.println("isPersistent() = " + act.isPersistent());//NOI18N
2388
System.out.println("isPrimaryKey() = " + act.isPrimaryKey());//NOI18N
2389
System.out.println("isMutableSCO() = " + act.isMutableSCO());//NOI18N
2390
System.out.println("isSynthetic() = " + act.isSynthetic());//NOI18N
2391
//System.out.println("index() = " + act.index());
2392
System.out.println("nDims() = " + act.nDims());//NOI18N
2393
System.out.println("createMethod() = " + act.createMethod());//NOI18N
2394
System.out.println("createMethodSig() = " + act.createMethodSig());//NOI18N
2395
System.out.println("setMethod() = " + act.setMethod());//NOI18N
2396
System.out.println("setMethodSig() = " + act.setMethodSig());//NOI18N
2397
System.out.println("setMethodArg() = "//NOI18N
2398
+ typeToString(act.setMethodArg()));
2399        System.out.println("getMethod() = " + act.getMethod());//NOI18N
2400
System.out.println("getMethodSig() = " + act.getMethodSig());//NOI18N
2401
System.out.println("getMethodReturn() = "//NOI18N
2402
+ typeToString(act.getMethodReturn()));
2403    }
2404
2405    // for debugging
2406
static private String JavaDoc typeToString(int val) {
2407        switch(val) {
2408        case T_DOUBLE:
2409            return "T_DOUBLE";//NOI18N
2410
case T_LONG:
2411            return "T_LONG";//NOI18N
2412
case T_BOOLEAN:
2413            return "T_BOOLEAN";//NOI18N
2414
case T_CHAR:
2415            return "T_CHAR";//NOI18N
2416
case T_FLOAT:
2417            return "T_FLOAT";//NOI18N
2418
case T_BYTE:
2419            return "T_BYTE";//NOI18N
2420
case T_SHORT:
2421            return "T_SHORT";//NOI18N
2422
case T_INT:
2423            return "T_INT";//NOI18N
2424
case TC_STRING:
2425            return "TC_STRING";//NOI18N
2426
case TC_OBJECT:
2427            return "TC_OBJECT";//NOI18N
2428
case TC_INTERFACE:
2429            return "TC_INTERFACE";//NOI18N
2430
default:
2431            throw new InternalError JavaDoc("Unexpected return type");//NOI18N
2432
}
2433    }
2434}
2435
Popular Tags