KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > tc > object > bytecode > ClassAdapterBase


1 /*
2  * All content copyright (c) 2003-2006 Terracotta, Inc., except as may otherwise be noted in a separate copyright
3  * notice. All rights reserved.
4  */

5 package com.tc.object.bytecode;
6
7 import com.tc.asm.ClassAdapter;
8 import com.tc.asm.ClassVisitor;
9 import com.tc.asm.FieldVisitor;
10 import com.tc.asm.Label;
11 import com.tc.asm.MethodVisitor;
12 import com.tc.asm.Opcodes;
13 import com.tc.asm.Type;
14 import com.tc.asm.commons.LocalVariablesSorter;
15 import com.tc.aspectwerkz.reflect.ClassInfo;
16 import com.tc.object.Portability;
17 import com.tc.object.config.TransparencyClassSpec;
18
19 import java.lang.reflect.Method JavaDoc;
20 import java.lang.reflect.Modifier JavaDoc;
21 import java.util.Arrays JavaDoc;
22 import java.util.Collection JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.LinkedHashSet JavaDoc;
26 import java.util.Map JavaDoc;
27 import java.util.Set JavaDoc;
28
29 /**
30  * Common base class for Terracotta class adapters
31  */

32 public abstract class ClassAdapterBase extends ClassAdapter implements Opcodes {
33   public static final String JavaDoc MANAGED_FIELD_NAME = ByteCodeUtil.TC_FIELD_PREFIX
34                                                                                 + "MANAGED";
35   public static final String JavaDoc MANAGED_FIELD_TYPE = "Lcom/tc/object/TCObject;";
36   public static final String JavaDoc MANAGED_METHOD = ByteCodeUtil.TC_METHOD_PREFIX
37                                                                                 + "managed";
38   public static final String JavaDoc IS_MANAGED_METHOD = ByteCodeUtil.TC_METHOD_PREFIX
39                                                                                 + "isManaged";
40   public static final String JavaDoc IS_MANAGED_DESCRIPTION = "()Z";
41
42   public static final String JavaDoc VALUES_GETTER = ByteCodeUtil.VALUES_GETTER;
43   public static final String JavaDoc VALUES_GETTER_DESCRIPTION = ByteCodeUtil.VALUES_GETTER_DESCRIPTION;
44   public static final String JavaDoc VALUES_SETTER = ByteCodeUtil.VALUES_SETTER;
45   public static final String JavaDoc VALUES_SETTER_DESCRIPTION = ByteCodeUtil.VALUES_SETTER_DESCRIPTION;
46   public static final String JavaDoc MANAGED_VALUES_GETTER = ByteCodeUtil.MANAGED_VALUES_GETTER;
47   public static final String JavaDoc MANAGED_VALUES_GETTER_DESCRIPTION = ByteCodeUtil.MANAGED_VALUES_GETTER_DESCRIPTION;
48   public static final String JavaDoc MANAGED_VALUES_SETTER = ByteCodeUtil.MANAGED_VALUES_SETTER;
49
50   private static final String JavaDoc LOGICAL_TYPE_DELEGATE_FIELD_NAME_PREFIX = "__delegate_tc_";
51   private static final int LOGICAL_TYPE_DELEGATE_FIELD_MODIFIER = ACC_PRIVATE + ACC_TRANSIENT;
52
53   private final Map JavaDoc fields = new HashMap JavaDoc();
54   protected final InstrumentationSpec spec;
55   private final Portability portability;
56   private boolean hasVisitedDelegateField = false;
57
58   public static String JavaDoc getDelegateFieldName(String JavaDoc logicalExtendingClassName) {
59     return LOGICAL_TYPE_DELEGATE_FIELD_NAME_PREFIX
60            + logicalExtendingClassName.replace('.', '_').replace('/', '_').replace('$', '_');
61   }
62
63   public static boolean isDelegateFieldName(String JavaDoc fieldName) {
64     return fieldName.startsWith(LOGICAL_TYPE_DELEGATE_FIELD_NAME_PREFIX);
65   }
66
67   protected TransparencyClassSpec getTransparencyClassSpec() {
68     return spec.getTransparencyClassSpec();
69   }
70
71   protected InstrumentationSpec getInstrumentationSpec() {
72     return spec;
73   }
74
75   private boolean isRoot(String JavaDoc fieldName) {
76     return getTransparencyClassSpec().isRootInThisClass(fieldName);
77   }
78
79   public ClassAdapterBase(ClassInfo classInfo, TransparencyClassSpec spec, ClassVisitor delegate, ManagerHelper mgrHelper,
80                           ClassLoader JavaDoc caller, Portability p) {
81     super(delegate);
82     this.portability = p;
83     this.spec = new InstrumentationSpec(classInfo, spec, mgrHelper, caller);
84   }
85
86   public final void visit(int version, int access, String JavaDoc name, String JavaDoc signature, String JavaDoc superName, String JavaDoc[] interfaces) {
87     spec.initialize(version, access, name, signature, superName, interfaces, portability);
88
89     if (spec.isClassNotAdaptable()) {
90       super.visit(version, access, name, signature, superName, interfaces);
91       return;
92     }
93
94     if (spec.isClassPortable()) {
95       interfaces = getNewInterfacesForPortableObject(interfaces);
96     }
97
98     basicVisit(version, access, name, signature, superName, interfaces);
99   }
100
101   private void visitDelegateFieldIfNecessary() {
102     if (!hasVisitedDelegateField) {
103       hasVisitedDelegateField = true;
104       String JavaDoc superClassNameSlashes = spec.getSuperClassNameSlashes();
105       String JavaDoc delegateFieldName = getDelegateFieldName(superClassNameSlashes);
106       String JavaDoc delegateFieldType = "L" + superClassNameSlashes + ";";
107       visitField(LOGICAL_TYPE_DELEGATE_FIELD_MODIFIER, delegateFieldName, delegateFieldType, null, null);
108     }
109   }
110
111   private String JavaDoc[] getNewInterfacesForPortableObject(String JavaDoc[] interfaces) {
112     Set JavaDoc ifaces = new LinkedHashSet JavaDoc(Arrays.asList(interfaces));
113     if (!ifaces.contains(Manageable.CLASS)) {
114       ifaces.add(Manageable.CLASS);
115     }
116
117     if (!spec.isLogical() && !ifaces.contains(TransparentAccess.CLASS)) {
118       ifaces.add(TransparentAccess.CLASS);
119     }
120
121     return (String JavaDoc[]) ifaces.toArray(interfaces);
122   }
123
124   public final FieldVisitor visitField(int access, String JavaDoc name, String JavaDoc desc, String JavaDoc signature, Object JavaDoc value) {
125     spec.handleSubclassOfLogicalClassWithFieldsIfNecessary(access);
126     if (spec.needDelegateField()) {
127       visitDelegateFieldIfNecessary();
128     }
129
130     spec.recordExistingFields(name, desc, signature);
131
132     if (spec.isClassNotAdaptable() || name.startsWith(ByteCodeUtil.TC_FIELD_PREFIX)) { return super
133         .visitField(access, name, desc, signature, value); }
134     if (!Modifier.isStatic(access)) {
135       fields.put(name, desc);
136     }
137     return basicVisitField(access, name, desc, signature, value);
138   }
139
140   /**
141    * This MethodAdapter is to instrument the constructor for a subclass of Logical class which contains one or more
142    * field. In such situation, we need to instantiate the added delegate field in the constructor.
143    */

144   private class LogicalInitMethodAdapter extends LocalVariablesSorter implements Opcodes {
145     private boolean methodEnter = false;
146     private int[] localVariablesForMethodCall;
147
148     public LogicalInitMethodAdapter(int access, String JavaDoc methodDesc, MethodVisitor mv) {
149       super(access, methodDesc, mv);
150     }
151
152     private void storeStackValuesToLocalVariables(String JavaDoc methodInsnDesc) {
153       Type[] types = Type.getArgumentTypes(methodInsnDesc);
154       localVariablesForMethodCall = new int[types.length];
155       for (int i = 0; i < types.length; i++) {
156         localVariablesForMethodCall[i] = newLocal(types[i].getSize());
157       }
158       for (int i = types.length - 1; i >= 0; i--) {
159         super.visitVarInsn(types[i].getOpcode(ISTORE), localVariablesForMethodCall[i]);
160       }
161     }
162
163     private void loadLocalVariables(String JavaDoc methodInsnDesc) {
164       Type[] types = Type.getArgumentTypes(methodInsnDesc);
165       for (int i = 0; i < types.length; i++) {
166         super.visitVarInsn(types[i].getOpcode(ILOAD), localVariablesForMethodCall[i]);
167       }
168     }
169
170     public void visitMethodInsn(int opcode, String JavaDoc owner, String JavaDoc name, String JavaDoc desc) {
171       String JavaDoc superClassNameSlashes = spec.getSuperClassNameSlashes();
172       if (!methodEnter && INVOKESPECIAL == opcode && owner.equals(superClassNameSlashes) && "<init>".equals(name)) {
173         methodEnter = true;
174         storeStackValuesToLocalVariables(desc);
175         loadLocalVariables(desc);
176         super.visitMethodInsn(opcode, owner, name, desc);
177         super.visitVarInsn(ALOAD, 0);
178         super.visitTypeInsn(NEW, spec.getSuperClassNameSlashes());
179         super.visitInsn(DUP);
180         loadLocalVariables(desc);
181
182         String JavaDoc delegateFieldName = getDelegateFieldName(superClassNameSlashes);
183         super.visitMethodInsn(INVOKESPECIAL, superClassNameSlashes, "<init>", desc);
184         super.visitMethodInsn(INVOKESPECIAL, spec.getClassNameSlashes(),
185                            ByteCodeUtil.fieldSetterMethod(delegateFieldName), "(L" + superClassNameSlashes + ";)V");
186
187       } else {
188         super.visitMethodInsn(opcode, owner, name, desc);
189       }
190     }
191   }
192
193   public MethodVisitor visitMethod(int access, String JavaDoc name, String JavaDoc desc, String JavaDoc signature, String JavaDoc[] exceptions) {
194     spec.shouldProceedInstrumentation(access, name, desc);
195
196     if (spec.isClassNotAdaptable()) { return super.visitMethod(access, name, desc, signature, exceptions); }
197     MethodVisitor mv;
198
199     spec.recordExistingMethods(name, desc, signature);
200
201     if (spec.shouldVisitMethod(access, name)) {
202       mv = basicVisitMethod(access, name, desc, signature, exceptions);
203       if (spec.hasDelegatedToLogicalClass()) {
204         String JavaDoc logicalExtendingClassName = spec.getSuperClassNameSlashes();
205         mv = new LogicalClassSerializationAdapter.LogicalSubclassSerializationMethodAdapter(mv, name + desc, spec
206             .getClassNameSlashes(), logicalExtendingClassName, getDelegateFieldName(logicalExtendingClassName));
207       }
208     } else {
209       mv = super.visitMethod(access, name, desc, signature, exceptions);
210     }
211
212     if (spec.hasDelegatedToLogicalClass() && "<init>".equals(name)) {
213       mv = new LogicalInitMethodAdapter(access, desc, mv);
214     }
215
216     return mv;
217   }
218
219   private void revisitLogicalSubclassDefinition() {
220     spec.moveToLogicalIfNecessary();
221
222     String JavaDoc[] interfaces = spec.getClassInterfaces();
223     interfaces = getNewInterfacesForPortableObject(interfaces);
224
225     basicVisit(spec.getClassVersion(), spec.getClassAccess(), spec.getClassNameSlashes(), spec.getClassSignature(),
226                spec.getSuperClassNameSlashes(), interfaces);
227   }
228
229   public final void visitEnd() {
230     if (spec.isClassNotAdaptable()) {
231       super.visitEnd();
232       return;
233     }
234
235     if (spec.isSubclassofLogicalClass()) {
236       // If this is a subclass of a logical class, we need to determine if we need the
237
// TransparentAccess interface, depending if the subclass has defined any field or
238
// not.
239
revisitLogicalSubclassDefinition();
240     }
241
242     // We will add overriding method if there is any if this is a subclass of a logical
243
// class.
244
addOverridenLogicalMethods();
245
246     addRetrieveValuesMethod();
247     addSetValueMethod();
248     addRetrieveManagedValueMethod();
249     addSetManagedValueMethod();
250
251     // Condition for generating __tc_managed() method and $__tc_managed field should be the same.
252
if (spec.isManagedFieldNeeded() && spec.generateNonStaticTCFields()) {
253       addCachedManagedMethods();
254
255       visitField(ACC_PRIVATE | ACC_VOLATILE | ACC_TRANSIENT | ACC_SYNTHETIC, MANAGED_FIELD_NAME, MANAGED_FIELD_TYPE,
256                  null, null);
257     }
258
259     basicVisitEnd();
260   }
261
262   private void addOverridenLogicalMethods() {
263     Collection JavaDoc needToOverrideMethods = spec.getShouldOverrideMethods();
264     for (Iterator JavaDoc i = needToOverrideMethods.iterator(); i.hasNext();) {
265       Method JavaDoc m = (Method JavaDoc) i.next();
266       int modifier = m.getModifiers();
267       String JavaDoc methodName = m.getName();
268       if (!spec.shouldVisitMethod(modifier, methodName) || Modifier.isFinal(modifier)) {
269         continue;
270       }
271
272       String JavaDoc methodDesc = Type.getMethodDescriptor(m);
273       Type returnType = Type.getReturnType(m);
274
275       Class JavaDoc[] exceptionTypes = m.getExceptionTypes();
276       String JavaDoc[] exceptions = new String JavaDoc[exceptionTypes.length];
277       for (int j = 0; j < exceptionTypes.length; j++) {
278         exceptions[j] = Type.getInternalName(exceptionTypes[j]);
279       }
280
281       String JavaDoc logicalExtendingClassName = spec.getSuperClassNameSlashes();
282
283       MethodVisitor mv = cv.visitMethod(modifier & ~ACC_ABSTRACT, methodName, methodDesc, null, exceptions);
284       mv.visitVarInsn(ALOAD, 0);
285       mv.visitMethodInsn(INVOKESPECIAL, spec.getClassNameSlashes(), ByteCodeUtil
286           .fieldGetterMethod(getDelegateFieldName(logicalExtendingClassName)), "()L" + logicalExtendingClassName + ";");
287       ByteCodeUtil.pushMethodArguments(ACC_PUBLIC, methodDesc, mv);
288       mv.visitMethodInsn(INVOKEVIRTUAL, logicalExtendingClassName, methodName, methodDesc);
289
290       mv.visitInsn(returnType.getOpcode(IRETURN));
291       mv.visitMaxs(0, 0);
292       mv.visitEnd();
293     }
294     if (spec.hasDelegatedToLogicalClass()) {
295       addReadObjectMethod();
296       addWriteObjectMethod();
297       addSerializationOverrideMethod();
298     }
299   }
300
301   private void addSerializationOverrideMethod() {
302     LogicalClassSerializationAdapter.addCheckSerializationOverrideMethod(cv, true);
303   }
304
305   private void addWriteObjectMethod() {
306     if (!spec.isWriteObjectMethodNeeded()) { return; }
307     String JavaDoc logicalExtendingClassName = spec.getSuperClassNameSlashes();
308
309     MethodVisitor mv = cv.visitMethod(ACC_PRIVATE, "writeObject", "(Ljava/io/ObjectOutputStream;)V", null,
310                                       new String JavaDoc[] { "java/io/IOException" });
311     mv.visitCode();
312     LogicalClassSerializationAdapter.addDelegateFieldWriteObjectCode(mv, spec.getClassNameSlashes(),
313                                                                      logicalExtendingClassName,
314                                                                      getDelegateFieldName(logicalExtendingClassName));
315     mv.visitInsn(RETURN);
316     mv.visitMaxs(0, 0);
317     mv.visitEnd();
318   }
319
320   private void addReadObjectMethod() {
321     if (!spec.isReadObjectMethodNeeded()) { return; }
322     String JavaDoc logicalExtendingClassName = spec.getSuperClassNameSlashes();
323
324     MethodVisitor mv = cv.visitMethod(ACC_PRIVATE, "readObject", "(Ljava/io/ObjectInputStream;)V", null, new String JavaDoc[] {
325         "java/io/IOException", "java/lang/ClassNotFoundException" });
326     mv.visitCode();
327     LogicalClassSerializationAdapter.addDelegateFieldReadObjectCode(mv, spec.getClassNameSlashes(),
328                                                                     logicalExtendingClassName,
329                                                                     getDelegateFieldName(logicalExtendingClassName));
330     mv.visitInsn(RETURN);
331     mv.visitMaxs(0, 0);
332     mv.visitEnd();
333   }
334
335   private void addCachedManagedMethods() {
336     if (spec.isManagedMethodsNeeded()) {
337       // add getter
338
MethodVisitor mv = visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, MANAGED_METHOD, "()" + MANAGED_FIELD_TYPE, null, null);
339       if (spec.generateNonStaticTCFields()) {
340         mv.visitVarInsn(ALOAD, 0);
341         mv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(), MANAGED_FIELD_NAME, MANAGED_FIELD_TYPE);
342         mv.visitInsn(ARETURN);
343         mv.visitMaxs(0, 0);
344       } else {
345         mv.visitInsn(ACONST_NULL);
346         mv.visitInsn(ARETURN);
347         mv.visitMaxs(0, 0);
348       }
349
350       // add setter
351
mv = visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, MANAGED_METHOD, "(" + MANAGED_FIELD_TYPE + ")V", null, null);
352       if (spec.generateNonStaticTCFields()) {
353         mv.visitVarInsn(ALOAD, 0);
354         mv.visitVarInsn(ALOAD, 1);
355         mv.visitFieldInsn(PUTFIELD, spec.getClassNameSlashes(), MANAGED_FIELD_NAME, MANAGED_FIELD_TYPE);
356         mv.visitInsn(RETURN);
357         mv.visitMaxs(0, 0);
358       } else {
359         mv.visitInsn(RETURN);
360         mv.visitMaxs(0, 0);
361       }
362
363       // add isManaged() method
364
// XXX::FIXME:: This method need to handle TCClonableObjects and TCNonDistributableObjects
365
mv = visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, IS_MANAGED_METHOD, IS_MANAGED_DESCRIPTION, null, null);
366       if (spec.generateNonStaticTCFields()) {
367         mv.visitVarInsn(ALOAD, 0);
368         mv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(), MANAGED_FIELD_NAME, MANAGED_FIELD_TYPE);
369         Label l1 = new Label();
370         mv.visitJumpInsn(IFNULL, l1);
371         mv.visitInsn(ICONST_1);
372         mv.visitInsn(IRETURN);
373         mv.visitLabel(l1);
374         mv.visitInsn(ICONST_0);
375         mv.visitInsn(IRETURN);
376         mv.visitMaxs(1, 1);
377       } else {
378         mv.visitInsn(ICONST_0);
379         mv.visitInsn(IRETURN);
380         mv.visitMaxs(1, 1);
381       }
382     }
383   }
384
385   /**
386    * Creates a method that takes all of the fields in the class and the super classes and puts them into the passed in
387    * hashmap
388    */

389   private void addRetrieveValuesMethod() {
390     if (spec.isValuesGetterMethodNeeded()) {
391       MethodVisitor mv = visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, VALUES_GETTER, VALUES_GETTER_DESCRIPTION, null, null);
392       if (!portability.isInstrumentationNotNeeded(spec.getSuperClassNameDots())
393           && getTransparencyClassSpec().hasPhysicallyPortableSpecs(spec.getClassInfo().getSuperclass())) {
394         mv.visitVarInsn(ALOAD, 0);
395         mv.visitVarInsn(ALOAD, 1);
396         mv.visitMethodInsn(INVOKESPECIAL, spec.getSuperClassNameSlashes(), VALUES_GETTER, VALUES_GETTER_DESCRIPTION);
397       }
398
399       for (Iterator JavaDoc i = fields.keySet().iterator(); i.hasNext();) {
400         String JavaDoc fieldName = (String JavaDoc) i.next();
401         String JavaDoc fieldDescription = (String JavaDoc) fields.get(fieldName);
402
403         mv.visitVarInsn(ALOAD, 1);
404         mv.visitLdcInsn(spec.getClassNameDots() + "." + fieldName);
405         addValueToStackForField(mv, fieldName, fieldDescription);
406         mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "put",
407                            "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;");
408         mv.visitInsn(POP);
409       }
410       mv.visitInsn(RETURN);
411       mv.visitMaxs(0, 0);
412     }
413   }
414
415   private void addRetrieveManagedValueMethod() {
416     if (spec.isManagedValuesGetterMethodNeeded()) {
417       MethodVisitor mv = visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, MANAGED_VALUES_GETTER,
418                                      MANAGED_VALUES_GETTER_DESCRIPTION, null, null);
419
420       for (Iterator JavaDoc i = fields.keySet().iterator(); i.hasNext();) {
421         String JavaDoc fieldName = (String JavaDoc) i.next();
422         String JavaDoc fieldDescription = (String JavaDoc) fields.get(fieldName);
423         mv.visitVarInsn(ALOAD, 1);
424         mv.visitLdcInsn(spec.getClassNameDots() + "." + fieldName);
425         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z");
426         Label l1 = new Label();
427         mv.visitJumpInsn(IFEQ, l1);
428
429         if (ByteCodeUtil.isSynthetic(fieldName)) {
430           addValueToStackForField(mv, fieldName, fieldDescription);
431         } else {
432           addManagedValueToStackForField(mv, fieldName, fieldDescription);
433         }
434         mv.visitInsn(ARETURN);
435         mv.visitLabel(l1);
436       }
437
438       
439       if (!portability.isInstrumentationNotNeeded(spec.getSuperClassNameDots())
440           && getTransparencyClassSpec().hasPhysicallyPortableSpecs(spec.getClassInfo().getSuperclass())) {
441         mv.visitVarInsn(ALOAD, 0);
442         mv.visitVarInsn(ALOAD, 1);
443         mv.visitMethodInsn(INVOKESPECIAL, spec.getSuperClassNameSlashes(), MANAGED_VALUES_GETTER,
444                            MANAGED_VALUES_GETTER_DESCRIPTION);
445       } else {
446         mv.visitInsn(ACONST_NULL);
447       }
448       mv.visitInsn(ARETURN);
449       mv.visitMaxs(0, 0);
450     }
451   }
452
453   /**
454    * Creates a method that allows the setting of any field in this class or it's super classes.
455    */

456   private void addSetValueMethod() {
457     if (spec.isValuesSetterMethodNeeded()) {
458       MethodVisitor mv = visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, VALUES_SETTER, VALUES_SETTER_DESCRIPTION, null, null);
459       Label l1 = new Label();
460       for (Iterator JavaDoc i = fields.keySet().iterator(); i.hasNext();) {
461         String JavaDoc fieldName = (String JavaDoc) i.next();
462         if (ByteCodeUtil.isTCSynthetic(fieldName)) {
463           continue;
464         }
465
466         String JavaDoc fieldDescription = (String JavaDoc) fields.get(fieldName);
467         Type t = Type.getType(fieldDescription);
468         mv.visitVarInsn(ALOAD, 1);
469         mv.visitLdcInsn(spec.getClassNameDots() + "." + fieldName);
470         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z");
471         Label l2 = new Label();
472         mv.visitJumpInsn(IFEQ, l2);
473         mv.visitVarInsn(ALOAD, 0);
474         mv.visitVarInsn(ALOAD, 2);
475         if (t.getSort() != Type.OBJECT && t.getSort() != Type.ARRAY) {
476           mv.visitTypeInsn(CHECKCAST, ByteCodeUtil.sortToWrapperName(t.getSort()));
477           mv.visitMethodInsn(INVOKEVIRTUAL, ByteCodeUtil.sortToWrapperName(t.getSort()), ByteCodeUtil
478               .sortToPrimitiveMethodName(t.getSort()), "()" + fieldDescription);
479         } else {
480           mv.visitTypeInsn(CHECKCAST, convertToCheckCastDesc(fieldDescription));
481         }
482         mv.visitFieldInsn(PUTFIELD, spec.getClassNameSlashes(), fieldName, fieldDescription);
483         mv.visitJumpInsn(GOTO, l1);
484         mv.visitLabel(l2);
485       }
486       if (!portability.isInstrumentationNotNeeded(spec.getSuperClassNameDots())
487           && getTransparencyClassSpec().hasPhysicallyPortableSpecs(spec.getClassInfo().getSuperclass())) {
488         mv.visitVarInsn(ALOAD, 0);
489         mv.visitVarInsn(ALOAD, 1);
490         mv.visitVarInsn(ALOAD, 2);
491         mv.visitMethodInsn(INVOKESPECIAL, spec.getSuperClassNameSlashes(), VALUES_SETTER, VALUES_SETTER_DESCRIPTION);
492       }
493       mv.visitLabel(l1);
494
495       mv.visitInsn(RETURN);
496       mv.visitMaxs(0, 0);
497     }
498   }
499
500   private void addSetManagedValueMethod() {
501     if (spec.isManagedValuesSetterMethodNeeded()) {
502       MethodVisitor mv = visitMethod(ACC_PUBLIC | ACC_SYNTHETIC, MANAGED_VALUES_SETTER, VALUES_SETTER_DESCRIPTION,
503                                      null, null);
504
505       Label l1 = new Label();
506       for (Iterator JavaDoc i = fields.keySet().iterator(); i.hasNext();) {
507         String JavaDoc fieldName = (String JavaDoc) i.next();
508         if (ByteCodeUtil.isSynthetic(fieldName)) {
509           continue;
510         }
511
512         String JavaDoc fieldDescription = (String JavaDoc) fields.get(fieldName);
513         Type t = Type.getType(fieldDescription);
514         mv.visitVarInsn(ALOAD, 1);
515         mv.visitLdcInsn(spec.getClassNameDots() + "." + fieldName);
516         mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z");
517         Label l2 = new Label();
518         mv.visitJumpInsn(IFEQ, l2);
519         mv.visitVarInsn(ALOAD, 0);
520         mv.visitVarInsn(ALOAD, 2);
521         if (t.getSort() != Type.OBJECT && t.getSort() != Type.ARRAY) {
522           mv.visitTypeInsn(CHECKCAST, ByteCodeUtil.sortToWrapperName(t.getSort()));
523           mv.visitMethodInsn(INVOKEVIRTUAL, ByteCodeUtil.sortToWrapperName(t.getSort()), ByteCodeUtil
524               .sortToPrimitiveMethodName(t.getSort()), "()" + fieldDescription);
525         } else {
526           mv.visitTypeInsn(CHECKCAST, convertToCheckCastDesc(fieldDescription));
527         }
528         mv.visitMethodInsn(INVOKEVIRTUAL, spec.getClassNameSlashes(), ByteCodeUtil.fieldSetterMethod(fieldName),
529                            "(" + fieldDescription + ")V");
530         mv.visitJumpInsn(GOTO, l1);
531         mv.visitLabel(l2);
532       }
533
534       if (!portability.isInstrumentationNotNeeded(spec.getSuperClassNameDots())
535           && getTransparencyClassSpec().hasPhysicallyPortableSpecs(spec.getClassInfo().getSuperclass())) {
536         mv.visitVarInsn(ALOAD, 0);
537         mv.visitVarInsn(ALOAD, 1);
538         mv.visitVarInsn(ALOAD, 2);
539         mv.visitMethodInsn(INVOKESPECIAL, spec.getSuperClassNameSlashes(), MANAGED_VALUES_SETTER,
540                            VALUES_SETTER_DESCRIPTION);
541       }
542
543       mv.visitLabel(l1);
544       mv.visitInsn(RETURN);
545       mv.visitMaxs(0, 0);
546     }
547   }
548
549   protected String JavaDoc convertToCheckCastDesc(String JavaDoc desc) {
550     if (desc.startsWith("[")) return desc;
551     return desc.substring(1, desc.length() - 1);
552   }
553
554   private void addValueToStackForField(MethodVisitor mv, String JavaDoc fieldName, String JavaDoc fieldDescription) {
555     Type t = Type.getType(fieldDescription);
556
557     if (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY) {
558       ByteCodeUtil.pushThis(mv);
559       mv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(), fieldName, fieldDescription);
560     } else {
561       mv.visitTypeInsn(NEW, ByteCodeUtil.sortToWrapperName(t.getSort()));
562       mv.visitInsn(DUP);
563       ByteCodeUtil.pushThis(mv);
564       mv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(), fieldName, fieldDescription);
565       mv.visitMethodInsn(INVOKESPECIAL, ByteCodeUtil.sortToWrapperName(t.getSort()), "<init>", "(" + fieldDescription
566                                                                                                + ")V");
567     }
568   }
569
570   private void addManagedValueToStackForField(MethodVisitor mv, String JavaDoc fieldName, String JavaDoc fieldDescription) {
571     Type t = Type.getType(fieldDescription);
572     if (t.getSort() == Type.OBJECT || t.getSort() == Type.ARRAY) {
573       ByteCodeUtil.pushThis(mv);
574       mv.visitMethodInsn(INVOKESPECIAL, spec.getClassNameSlashes(), ByteCodeUtil.fieldGetterMethod(fieldName),
575                          "()" + fieldDescription);
576     } else {
577       mv.visitTypeInsn(NEW, ByteCodeUtil.sortToWrapperName(t.getSort()));
578       mv.visitInsn(DUP);
579       ByteCodeUtil.pushThis(mv);
580       if (isRoot(fieldName)) {
581         mv.visitMethodInsn(INVOKESPECIAL, spec.getClassNameSlashes(), ByteCodeUtil.fieldGetterMethod(fieldName),
582                            "()" + fieldDescription);
583       } else {
584         mv.visitFieldInsn(GETFIELD, spec.getClassNameSlashes(), fieldName, fieldDescription);
585       }
586       mv.visitMethodInsn(INVOKESPECIAL, ByteCodeUtil.sortToWrapperName(t.getSort()), "<init>", "(" + fieldDescription
587                                                                                                + ")V");
588     }
589   }
590
591   protected void basicVisit(int version, int access, String JavaDoc name, String JavaDoc signature, String JavaDoc superName,
592                             String JavaDoc[] interfaces) {
593     // override me if you need to access to the standard visit() method
594
cv.visit(version, access, name, signature, superName, interfaces);
595   }
596
597   protected FieldVisitor basicVisitField(int access, String JavaDoc name, String JavaDoc desc, String JavaDoc signature, Object JavaDoc value) {
598     // override me if you need to access to the standard visitField() method
599
return cv.visitField(access, name, desc, signature, value);
600   }
601
602   protected MethodVisitor basicVisitMethod(int access, String JavaDoc name, String JavaDoc desc, String JavaDoc signature, String JavaDoc[] exceptions) {
603     // override me if you need to access to the standard visitMethod() method
604
return cv.visitMethod(access, name, desc, signature, exceptions);
605   }
606
607   protected void basicVisitEnd() {
608     // override me if you need to access to the standard visitMethod() method
609
cv.visitEnd();
610   }
611
612 }
613
Popular Tags