1 4 package com.tc.objectserver.managedobject.bytecode; 5 6 import com.tc.asm.ClassWriter; 7 import com.tc.asm.FieldVisitor; 8 import com.tc.asm.Label; 9 import com.tc.asm.MethodVisitor; 10 import com.tc.asm.Opcodes; 11 import com.tc.exception.TCRuntimeException; 12 import com.tc.object.LiteralValues; 13 import com.tc.object.ObjectID; 14 import com.tc.util.AdaptedClassDumper; 15 16 import java.util.ArrayList ; 17 import java.util.Collections ; 18 import java.util.HashMap ; 19 import java.util.Iterator ; 20 import java.util.List ; 21 import java.util.Map ; 22 23 public class PhysicalStateClassLoader extends ClassLoader implements Opcodes { 24 25 public static class MethodDetail { 26 27 private final String methodName; 28 private final String methodDesc; 29 30 public MethodDetail(String methodName, String methodDesc) { 31 this.methodName = methodName; 32 this.methodDesc = methodDesc; 33 } 34 35 public String getMethodDescriptor() { 36 return methodDesc; 37 } 38 39 public String getMethodName() { 40 return methodName; 41 } 42 43 } 44 45 private static final String PARENT_ID_FIELD = "parentId"; 46 47 private static final Map OBJECT_OUTPUT_METHODS = Collections.synchronizedMap(new HashMap ()); 48 private static final Map OBJECT_INPUT_METHODS = Collections.synchronizedMap(new HashMap ()); 49 50 static { 51 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.INTEGER, "writeInt", "(I)V"); 52 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.LONG, "writeLong", "(J)V"); 53 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.CHARACTER, "writeChar", "(I)V"); 54 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.BYTE, "writeByte", "(I)V"); 55 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.SHORT, "writeShort", "(I)V"); 56 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.FLOAT, "writeFloat", "(F)V"); 57 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.DOUBLE, "writeDouble", "(D)V"); 58 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.BOOLEAN, "writeBoolean", "(Z)V"); 59 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.OBJECT, "writeObject", "(Ljava/lang/Object;)V"); 61 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.OBJECT_ID, "writeObject", "(Ljava/lang/Object;)V"); 62 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.ARRAY, "writeObject", "(Ljava/lang/Object;)V"); 63 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.JAVA_LANG_CLASS, "writeObject", "(Ljava/lang/Object;)V"); 64 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.JAVA_LANG_CLASS_HOLDER, "writeObject", "(Ljava/lang/Object;)V"); 65 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.STACK_TRACE_ELEMENT, "writeObject", "(Ljava/lang/Object;)V"); 66 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.STRING, "writeObject", "(Ljava/lang/Object;)V"); 67 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.STRING_BYTES, "writeObject", "(Ljava/lang/Object;)V"); 68 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.BIG_INTEGER, "writeObject", "(Ljava/lang/Object;)V"); 69 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.BIG_DECIMAL, "writeObject", "(Ljava/lang/Object;)V"); 70 71 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.JAVA_LANG_CLASSLOADER, "writeObject", "(Ljava/lang/Object;)V"); 72 addMapping(OBJECT_OUTPUT_METHODS, LiteralValues.JAVA_LANG_CLASSLOADER_HOLDER, "writeObject", "(Ljava/lang/Object;)V"); 73 74 75 addMapping(OBJECT_INPUT_METHODS, LiteralValues.INTEGER, "readInt", "()I"); 76 addMapping(OBJECT_INPUT_METHODS, LiteralValues.LONG, "readLong", "()J"); 77 addMapping(OBJECT_INPUT_METHODS, LiteralValues.CHARACTER, "readChar", "()C"); 78 addMapping(OBJECT_INPUT_METHODS, LiteralValues.BYTE, "readByte", "()B"); 79 addMapping(OBJECT_INPUT_METHODS, LiteralValues.SHORT, "readShort", "()S"); 80 addMapping(OBJECT_INPUT_METHODS, LiteralValues.FLOAT, "readFloat", "()F"); 81 addMapping(OBJECT_INPUT_METHODS, LiteralValues.DOUBLE, "readDouble", "()D"); 82 addMapping(OBJECT_INPUT_METHODS, LiteralValues.BOOLEAN, "readBoolean", "()Z"); 83 addMapping(OBJECT_INPUT_METHODS, LiteralValues.OBJECT, "readObject", "()Ljava/lang/Object;"); 85 addMapping(OBJECT_INPUT_METHODS, LiteralValues.OBJECT_ID, "readObject", "()Ljava/lang/Object;"); 86 addMapping(OBJECT_INPUT_METHODS, LiteralValues.ARRAY, "readObject", "()Ljava/lang/Object;"); 87 addMapping(OBJECT_INPUT_METHODS, LiteralValues.JAVA_LANG_CLASS, "readObject", "()Ljava/lang/Object;"); 88 addMapping(OBJECT_INPUT_METHODS, LiteralValues.JAVA_LANG_CLASS_HOLDER, "readObject", "()Ljava/lang/Object;"); 89 addMapping(OBJECT_INPUT_METHODS, LiteralValues.STACK_TRACE_ELEMENT, "readObject", "()Ljava/lang/Object;"); 90 addMapping(OBJECT_INPUT_METHODS, LiteralValues.STRING, "readObject", "()Ljava/lang/Object;"); 91 addMapping(OBJECT_INPUT_METHODS, LiteralValues.STRING_BYTES, "readObject", "()Ljava/lang/Object;"); 92 addMapping(OBJECT_INPUT_METHODS, LiteralValues.BIG_INTEGER, "readObject", "()Ljava/lang/Object;"); 93 addMapping(OBJECT_INPUT_METHODS, LiteralValues.BIG_DECIMAL, "readObject", "()Ljava/lang/Object;"); 94 95 addMapping(OBJECT_INPUT_METHODS, LiteralValues.JAVA_LANG_CLASSLOADER, "readObject", "()Ljava/lang/Object;"); 96 addMapping(OBJECT_INPUT_METHODS, LiteralValues.JAVA_LANG_CLASSLOADER_HOLDER, "readObject", "()Ljava/lang/Object;"); 97 98 99 } 100 101 public PhysicalStateClassLoader(ClassLoader parent) { 102 super(parent); 103 } 104 105 private static void addMapping(Map map, int type, String methodName, String methodDesc) { 106 map.put(new Integer (type), new MethodDetail(methodName, methodDesc)); 107 } 108 109 private static MethodDetail get(Map map, int type) { 110 MethodDetail md = (MethodDetail) map.get(new Integer (type)); 111 if (md == null) { throw new TCRuntimeException("Unknown Type : " + type + " Map = " + map); } 112 return md; 113 } 114 115 public PhysicalStateClassLoader() { 116 super(); 117 } 118 119 public byte[] createClassBytes(ClassSpec cs, ObjectID parentID, List fields) { 120 byte data[] = basicCreateClassBytes(cs, parentID, fields); 121 AdaptedClassDumper.write(cs.getGeneratedClassName(), data); 122 return data; 123 } 124 125 public Class defineClassFromBytes(String className, int classId, byte[] clazzBytes, int offset, int length) { 126 Class clazz = defineClass(className, clazzBytes, offset, length); 127 return clazz; 128 } 129 130 private byte[] basicCreateClassBytes(ClassSpec cs, ObjectID parentID, List fields) { 131 String classNameSlash = cs.getGeneratedClassName().replace('.', '/'); 132 String superClassNameSlash = cs.getSuperClassName().replace('.', '/'); 133 ClassWriter cw = new ClassWriter(false); 134 135 cw.visit(V1_2, ACC_PUBLIC | ACC_SUPER, classNameSlash, null, superClassNameSlash, null); 136 137 createConstructor(cw, superClassNameSlash); 138 if (!parentID.isNull()) { 139 createParentIDField(cw); 140 createGetParentIDMethod(cw, classNameSlash); 141 createSetParentIDMethod(cw, classNameSlash); 142 } 143 144 createFields(cw, fields); 145 createGetClassNameMethod(cw, classNameSlash, cs); 146 createGetLoaderDescriptionMethod(cw, classNameSlash, cs); 147 createGetObjectReferencesMethod(cw, classNameSlash, parentID, cs, superClassNameSlash, fields); 148 createBasicSetMethod(cw, classNameSlash, cs, superClassNameSlash, fields); 149 createBasicDehydrateMethod(cw, classNameSlash, cs, superClassNameSlash, fields); 150 createAddValuesMethod(cw, classNameSlash, cs, superClassNameSlash, fields); 151 createWriteObjectMethod(cw, classNameSlash, cs, superClassNameSlash, fields); 152 createReadObjectMethod(cw, classNameSlash, cs, superClassNameSlash, fields); 153 154 createGetClassIdMethod(cw, classNameSlash, cs); 155 156 cw.visitEnd(); 157 return cw.toByteArray(); 158 } 159 160 private void createGetLoaderDescriptionMethod(ClassWriter cw, String classNameSlash, ClassSpec cs) { 168 if (!cs.isDirectSubClassOfPhysicalMOState()) { 169 return; 171 } 172 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "getLoaderDescription", "()Ljava/lang/String;", null, null); 173 mv.visitCode(); 174 mv.visitLdcInsn(cs.getLoaderDesc()); 175 mv.visitInsn(ARETURN); 176 mv.visitMaxs(1, 1); 177 mv.visitEnd(); 178 } 179 180 private void createGetClassNameMethod(ClassWriter cw, String classNameSlash, ClassSpec cs) { 188 if (!cs.isDirectSubClassOfPhysicalMOState()) { 189 return; 191 } 192 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "getClassName", "()Ljava/lang/String;", null, null); 193 mv.visitCode(); 194 mv.visitLdcInsn(cs.getClassName()); 195 mv.visitInsn(ARETURN); 196 mv.visitMaxs(1, 1); 197 mv.visitEnd(); 198 } 199 200 private void createGetClassIdMethod(ClassWriter cw, String classNameSlash, ClassSpec cs) { 208 MethodVisitor mv = cw.visitMethod(ACC_PROTECTED, "getClassId", "()I", null, null); 209 mv.visitLdcInsn(new Integer (cs.getClassID())); 210 mv.visitInsn(IRETURN); 211 mv.visitMaxs(1, 1); 212 mv.visitEnd(); 213 } 214 215 private void createWriteObjectMethod(ClassWriter cw, String classNameSlash, ClassSpec cs, String superClassNameSlash, List fields) { 228 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "writeObject", "(Ljava/io/ObjectOutput;)V", null, 229 new String [] { "java/io/IOException" }); 230 mv.visitCode(); 231 232 if (!cs.isDirectSubClassOfPhysicalMOState()) { 233 mv.visitVarInsn(ALOAD, 0); 234 mv.visitVarInsn(ALOAD, 1); 235 mv.visitMethodInsn(INVOKESPECIAL, superClassNameSlash, "writeObject", "(Ljava/io/ObjectOutput;)V"); 236 } 237 238 for (Iterator i = fields.iterator(); i.hasNext();) { 239 FieldType f = (FieldType) i.next(); 240 mv.visitVarInsn(ALOAD, 1); 241 mv.visitVarInsn(ALOAD, 0); 242 mv.visitFieldInsn(GETFIELD, classNameSlash, f.getLocalFieldName(), getFieldTypeDesc(f.getType())); 243 MethodDetail md = get(OBJECT_OUTPUT_METHODS, f.getType()); 244 mv.visitMethodInsn(INVOKEINTERFACE, "java/io/ObjectOutput", md.getMethodName(), md.getMethodDescriptor()); 245 } 246 mv.visitInsn(RETURN); 247 mv.visitMaxs(3, 2); 248 mv.visitEnd(); 249 } 250 251 private void createReadObjectMethod(ClassWriter cw, String classNameSlash, ClassSpec cs, String superClassNameSlash, List fields) { 265 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "readObject", "(Ljava/io/ObjectInput;)V", null, new String [] { 266 "java/io/IOException", "java/lang/ClassNotFoundException" }); 267 mv.visitCode(); 268 269 if (!cs.isDirectSubClassOfPhysicalMOState()) { 270 mv.visitVarInsn(ALOAD, 0); 271 mv.visitVarInsn(ALOAD, 1); 272 mv.visitMethodInsn(INVOKESPECIAL, superClassNameSlash, "readObject", "(Ljava/io/ObjectInput;)V"); 273 } 274 275 for (Iterator i = fields.iterator(); i.hasNext();) { 276 FieldType f = (FieldType) i.next(); 277 mv.visitVarInsn(ALOAD, 0); 278 mv.visitVarInsn(ALOAD, 1); 279 MethodDetail md = get(OBJECT_INPUT_METHODS, f.getType()); 280 mv.visitMethodInsn(INVOKEINTERFACE, "java/io/ObjectInput", md.getMethodName(), md.getMethodDescriptor()); 281 mv.visitFieldInsn(PUTFIELD, classNameSlash, f.getLocalFieldName(), getFieldTypeDesc(f.getType())); 282 } 283 mv.visitInsn(RETURN); 284 mv.visitMaxs(3, 2); 285 mv.visitEnd(); 286 } 287 288 private void createAddValuesMethod(ClassWriter cw, String classNameSlash, ClassSpec cs, String superClassNameSlash, 300 List fields) { 301 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "addValues", "(Ljava/util/Map;)Ljava/util/Map;", null, null); 302 mv.visitCode(); 303 304 if (!cs.isDirectSubClassOfPhysicalMOState()) { 305 mv.visitVarInsn(ALOAD, 0); 306 mv.visitVarInsn(ALOAD, 1); 307 mv.visitMethodInsn(INVOKESPECIAL, superClassNameSlash, "addValues", "(Ljava/util/Map;)Ljava/util/Map;"); 308 mv.visitInsn(POP); 309 } 310 311 for (Iterator i = fields.iterator(); i.hasNext();) { 312 FieldType f = (FieldType) i.next(); 313 mv.visitVarInsn(ALOAD, 1); 314 mv.visitLdcInsn(f.getQualifiedName()); 315 getObjectFor(mv, classNameSlash, f); 316 mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Map", "put", 317 "(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;"); 318 mv.visitInsn(POP); 319 } 320 mv.visitVarInsn(ALOAD, 1); 321 mv.visitInsn(ARETURN); 322 323 mv.visitMaxs(6, 2); 324 mv.visitEnd(); 325 326 } 327 328 private void createBasicDehydrateMethod(ClassWriter cw, String classNameSlash, ClassSpec cs, 339 String superClassNameSlash, List fields) { 340 MethodVisitor mv = cw.visitMethod(ACC_PROTECTED, "basicDehydrate", "(Lcom/tc/object/dna/api/DNAWriter;)V", null, 341 null); 342 mv.visitCode(); 343 344 if (!cs.isDirectSubClassOfPhysicalMOState()) { 345 mv.visitVarInsn(ALOAD, 0); 346 mv.visitVarInsn(ALOAD, 1); 347 mv.visitMethodInsn(INVOKESPECIAL, superClassNameSlash, "basicDehydrate", "(Lcom/tc/object/dna/api/DNAWriter;)V"); 348 } 349 350 for (Iterator i = fields.iterator(); i.hasNext();) { 351 FieldType f = (FieldType) i.next(); 352 mv.visitVarInsn(ALOAD, 1); 353 mv.visitLdcInsn(f.getQualifiedName()); 354 getObjectFor(mv, classNameSlash, f); 355 mv.visitMethodInsn(INVOKEINTERFACE, "com/tc/object/dna/api/DNAWriter", "addPhysicalAction", 357 "(Ljava/lang/String;Ljava/lang/Object;)V"); 358 } 359 mv.visitInsn(RETURN); 360 361 mv.visitMaxs(6, 2); 362 mv.visitEnd(); 363 } 364 365 private void createBasicSetMethod(ClassWriter cw, String classNameSlash, ClassSpec cs, String superClassNameSlash, 385 List fields) { 386 MethodVisitor mv = cw.visitMethod(ACC_PROTECTED, "basicSet", 387 "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;", null, null); 388 mv.visitCode(); 389 390 for (Iterator i = fields.iterator(); i.hasNext();) { 391 FieldType f = (FieldType) i.next(); 392 mv.visitLdcInsn(f.getQualifiedName()); 393 mv.visitVarInsn(ALOAD, 1); 394 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "equals", "(Ljava/lang/Object;)Z"); 395 Label l1 = new Label(); 396 mv.visitJumpInsn(IFEQ, l1); 397 getObjectFor(mv, classNameSlash, f); 398 mv.visitVarInsn(ASTORE, 3); 399 mv.visitVarInsn(ALOAD, 0); 400 mv.visitVarInsn(ALOAD, 2); 401 getValueFrom(mv, classNameSlash, f); 402 mv.visitFieldInsn(PUTFIELD, classNameSlash, f.getLocalFieldName(), getFieldTypeDesc(f.getType())); 403 mv.visitVarInsn(ALOAD, 3); 404 mv.visitInsn(ARETURN); 405 mv.visitLabel(l1); 406 } 407 408 if (cs.isDirectSubClassOfPhysicalMOState()) { 409 mv.visitTypeInsn(NEW, "com/tc/objectserver/managedobject/bytecode/ClassNotCompatableException"); 411 mv.visitInsn(DUP); 412 mv.visitTypeInsn(NEW, "java/lang/StringBuffer"); 413 mv.visitInsn(DUP); 414 mv.visitLdcInsn("Not found ! field = "); 415 mv.visitMethodInsn(INVOKESPECIAL, "java/lang/StringBuffer", "<init>", "(Ljava/lang/String;)V"); 416 mv.visitVarInsn(ALOAD, 1); 417 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "append", 418 "(Ljava/lang/String;)Ljava/lang/StringBuffer;"); 419 mv.visitLdcInsn(" value = "); 420 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "append", 421 "(Ljava/lang/String;)Ljava/lang/StringBuffer;"); 422 mv.visitVarInsn(ALOAD, 2); 423 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "append", 424 "(Ljava/lang/Object;)Ljava/lang/StringBuffer;"); 425 mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/StringBuffer", "toString", "()Ljava/lang/String;"); 426 mv.visitMethodInsn(INVOKESPECIAL, "com/tc/objectserver/managedobject/bytecode/ClassNotCompatableException", 427 "<init>", "(Ljava/lang/String;)V"); 428 mv.visitInsn(ATHROW); 429 } else { 430 mv.visitVarInsn(ALOAD, 0); 432 mv.visitVarInsn(ALOAD, 1); 433 mv.visitVarInsn(ALOAD, 2); 434 mv.visitMethodInsn(INVOKESPECIAL, superClassNameSlash, "basicSet", 435 "(Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;"); 436 mv.visitInsn(ARETURN); 437 } 438 439 mv.visitMaxs(5, 4); 440 mv.visitEnd(); 441 } 442 443 447 private void getValueFrom(MethodVisitor mv, String classNameSlash, FieldType f) { 448 String classOnStack = getClassNameFor(f.getType()); 449 if ("java/lang/Object".equals(classOnStack)) { return; } 450 mv.visitTypeInsn(CHECKCAST, classOnStack); 451 mv.visitMethodInsn(INVOKEVIRTUAL, classOnStack, getMethodNameForPrimitives(f.getType()), "()" 452 + getFieldTypeDesc((f 453 .getType()))); 454 455 } 456 457 460 private void getObjectFor(MethodVisitor mv, String classNameSlash, FieldType f) { 461 String classToReturn = getClassNameFor(f.getType()); 462 if ("java/lang/Object".equals(classToReturn)) { 463 mv.visitVarInsn(ALOAD, 0); 464 mv.visitFieldInsn(GETFIELD, classNameSlash, f.getLocalFieldName(), getFieldTypeDesc(f.getType())); 465 return; 466 } 467 String fieldTypeDesc = getFieldTypeDesc(f.getType()); 468 String constructorDesc = "(" + fieldTypeDesc + ")V"; 469 mv.visitTypeInsn(NEW, classToReturn); 470 mv.visitInsn(DUP); 471 mv.visitVarInsn(ALOAD, 0); 472 mv.visitFieldInsn(GETFIELD, classNameSlash, f.getLocalFieldName(), fieldTypeDesc); 473 mv.visitMethodInsn(INVOKESPECIAL, classToReturn, "<init>", constructorDesc); 474 475 } 476 477 private void createGetObjectReferencesMethod(ClassWriter cw, String classNameSlash, ObjectID parentID, ClassSpec cs, 490 String superClassNameSlash, List fields) { 491 List referenceFields = new ArrayList (fields.size()); 492 for (Iterator i = fields.iterator(); i.hasNext();) { 493 FieldType f = (FieldType) i.next(); 494 if (f.getType() == LiteralValues.OBJECT_ID) { 495 referenceFields.add(f); 496 } 497 } 498 499 if (referenceFields.size() == 0 && parentID.isNull() && !cs.isDirectSubClassOfPhysicalMOState()) { 501 return; 503 } 504 505 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "getObjectReferences", "()Ljava/util/Set;", null, null); 506 mv.visitCode(); 507 508 if (referenceFields.size() == 0 && parentID.isNull()) { 510 mv.visitFieldInsn(GETSTATIC, "java/util/Collections", "EMPTY_SET", "Ljava/util/Set;"); 511 mv.visitInsn(ARETURN); 512 mv.visitMaxs(1, 1); 513 mv.visitEnd(); 514 return; 515 } 516 517 int size = referenceFields.size(); 518 if (!parentID.isNull() && cs.isDirectSubClassOfPhysicalMOState()) { 519 size++; 520 } 521 522 mv.visitTypeInsn(NEW, "gnu/trove/THashSet"); 523 mv.visitInsn(DUP); 524 mv.visitIntInsn(BIPUSH, size); 525 mv.visitMethodInsn(INVOKESPECIAL, "gnu/trove/THashSet", "<init>", "(I)V"); 526 mv.visitVarInsn(ASTORE, 1); 527 528 if (!cs.isDirectSubClassOfPhysicalMOState()) { 529 mv.visitVarInsn(ALOAD, 0); 530 mv.visitMethodInsn(INVOKESPECIAL, superClassNameSlash, "getObjectReferences", "()Ljava/util/Set;"); 531 mv.visitVarInsn(ASTORE, 2); 532 mv.visitVarInsn(ALOAD, 1); 533 mv.visitVarInsn(ALOAD, 2); 534 mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Set", "addAll", "(Ljava/util/Collection;)Z"); 535 mv.visitInsn(POP); 536 } 537 538 for (Iterator i = referenceFields.iterator(); i.hasNext();) { 539 FieldType f = (FieldType) i.next(); 540 mv.visitVarInsn(ALOAD, 0); 541 mv.visitFieldInsn(GETFIELD, classNameSlash, f.getLocalFieldName(), getFieldTypeDesc(f.getType())); 542 mv.visitTypeInsn(INSTANCEOF, "com/tc/object/ObjectID"); 543 Label l2 = new Label(); 544 mv.visitJumpInsn(IFEQ, l2); 545 mv.visitVarInsn(ALOAD, 0); 546 mv.visitFieldInsn(GETFIELD, classNameSlash, f.getLocalFieldName(), getFieldTypeDesc(f.getType())); 547 mv.visitTypeInsn(CHECKCAST, "com/tc/object/ObjectID"); 548 mv.visitMethodInsn(INVOKEVIRTUAL, "com/tc/object/ObjectID", "isNull", "()Z"); 549 mv.visitJumpInsn(IFNE, l2); 550 mv.visitVarInsn(ALOAD, 1); 551 mv.visitVarInsn(ALOAD, 0); 552 mv.visitFieldInsn(GETFIELD, classNameSlash, f.getLocalFieldName(), getFieldTypeDesc(f.getType())); 553 mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Set", "add", "(Ljava/lang/Object;)Z"); 554 mv.visitInsn(POP); 555 mv.visitLabel(l2); 556 } 557 if (!parentID.isNull() && cs.isDirectSubClassOfPhysicalMOState()) { 558 mv.visitVarInsn(ALOAD, 1); 560 mv.visitVarInsn(ALOAD, 0); 561 mv.visitFieldInsn(GETFIELD, classNameSlash, PARENT_ID_FIELD, "Lcom/tc/object/ObjectID;"); 562 mv.visitMethodInsn(INVOKEINTERFACE, "java/util/Set", "add", "(Ljava/lang/Object;)Z"); 563 mv.visitInsn(POP); 564 } 565 mv.visitVarInsn(ALOAD, 1); 566 mv.visitInsn(ARETURN); 567 mv.visitMaxs(3, 3); 568 mv.visitEnd(); 569 } 570 571 private void createFields(ClassWriter cw, List fields) { 572 for (Iterator i = fields.iterator(); i.hasNext();) { 573 FieldType f = (FieldType) i.next(); 574 FieldVisitor fv = cw.visitField(ACC_PRIVATE, f.getLocalFieldName(), getFieldTypeDesc(f.getType()), null, null); 575 fv.visitEnd(); 576 } 577 } 578 579 private String getFieldTypeDesc(int type) { 580 switch (type) { 581 case LiteralValues.INTEGER: 582 return "I"; 583 case LiteralValues.LONG: 584 return "J"; 585 case LiteralValues.CHARACTER: 586 return "C"; 587 case LiteralValues.FLOAT: 588 return "F"; 589 case LiteralValues.DOUBLE: 590 return "D"; 591 case LiteralValues.BYTE: 592 return "B"; 593 case LiteralValues.SHORT: 594 return "S"; 595 case LiteralValues.BOOLEAN: 596 return "Z"; 597 case LiteralValues.OBJECT_ID: 598 return "Ljava/lang/Object;"; default: 600 return "Ljava/lang/Object;"; } 602 } 603 604 private String getMethodNameForPrimitives(int type) { 606 switch (type) { 607 case LiteralValues.INTEGER: 608 return "intValue"; 609 case LiteralValues.LONG: 610 return "longValue"; 611 case LiteralValues.CHARACTER: 612 return "charValue"; 613 case LiteralValues.FLOAT: 614 return "floatValue"; 615 case LiteralValues.DOUBLE: 616 return "doubleValue"; 617 case LiteralValues.BYTE: 618 return "byteValue"; 619 case LiteralValues.SHORT: 620 return "shortValue"; 621 case LiteralValues.BOOLEAN: 622 return "booleanValue"; 623 default: 627 throw new AssertionError ("This type is invalid : " + type); 628 } 629 } 630 631 private String getClassNameFor(int type) { 632 switch (type) { 633 case LiteralValues.INTEGER: 634 return "java/lang/Integer"; 635 case LiteralValues.LONG: 636 return "java/lang/Long"; 637 case LiteralValues.CHARACTER: 638 return "java/lang/Character"; 639 case LiteralValues.FLOAT: 640 return "java/lang/Float"; 641 case LiteralValues.DOUBLE: 642 return "java/lang/Double"; 643 case LiteralValues.BYTE: 644 return "java/lang/Byte"; 645 case LiteralValues.SHORT: 646 return "java/lang/Short"; 647 case LiteralValues.BOOLEAN: 648 return "java/lang/Boolean"; 649 case LiteralValues.OBJECT_ID: 650 return "java/lang/Object"; default: 652 return "java/lang/Object"; } 654 } 655 656 private void createParentIDField(ClassWriter cw) { 657 FieldVisitor fv = cw.visitField(ACC_PRIVATE, PARENT_ID_FIELD, "Lcom/tc/object/ObjectID;", null, null); 658 fv.visitEnd(); 659 } 660 661 private void createGetParentIDMethod(ClassWriter cw, String classNameSlash) { 670 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "getParentID", "()Lcom/tc/object/ObjectID;", null, null); 671 mv.visitCode(); 672 mv.visitVarInsn(ALOAD, 0); 673 mv.visitFieldInsn(GETFIELD, classNameSlash, PARENT_ID_FIELD, "Lcom/tc/object/ObjectID;"); 674 mv.visitInsn(ARETURN); 675 mv.visitMaxs(2, 1); 676 mv.visitEnd(); 677 } 678 679 private void createSetParentIDMethod(ClassWriter cw, String classNameSlash) { 688 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "setParentID", "(Lcom/tc/object/ObjectID;)V", null, null); 689 mv.visitCode(); 690 mv.visitVarInsn(ALOAD, 0); 691 mv.visitVarInsn(ALOAD, 1); 692 mv.visitFieldInsn(PUTFIELD, classNameSlash, PARENT_ID_FIELD, "Lcom/tc/object/ObjectID;"); 693 mv.visitInsn(RETURN); 694 mv.visitMaxs(3, 2); 695 mv.visitEnd(); 696 } 697 698 private void createConstructor(ClassWriter cw, String superClassNameSlash) { 699 MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null, null); 700 mv.visitCode(); 701 mv.visitVarInsn(ALOAD, 0); 702 mv.visitMethodInsn(INVOKESPECIAL, superClassNameSlash, "<init>", "()V"); 703 mv.visitInsn(RETURN); 704 mv.visitMaxs(2, 2); 705 mv.visitEnd(); 706 } 707 708 } 709 | Popular Tags |