1 4 package com.tc.object.bytecode; 5 6 import com.tc.asm.ClassAdapter; 7 import com.tc.asm.ClassVisitor; 8 import com.tc.asm.FieldVisitor; 9 import com.tc.asm.MethodAdapter; 10 import com.tc.asm.MethodVisitor; 11 import com.tc.asm.Opcodes; 12 import com.tc.asm.tree.ClassNode; 13 import com.tc.asm.tree.FieldNode; 14 import com.tc.asm.tree.InnerClassNode; 15 import com.tc.asm.tree.MethodNode; 16 17 import java.lang.reflect.Modifier ; 18 import java.util.ArrayList ; 19 import java.util.HashSet ; 20 import java.util.Iterator ; 21 import java.util.List ; 22 import java.util.Map ; 23 import java.util.Set ; 24 25 public class MergeTCToJavaClassAdapter extends ChangeClassNameHierarchyAdapter implements Opcodes { 26 private final ClassNode tcClassNode; 27 private final String jFullClassSlashes; 28 private final String tcFullClassSlashes; 29 private final Map instrumentedContext; 30 private final Set visitedMethods; 31 private String superName; 32 private TransparencyClassAdapter dsoAdapter; 33 34 public MergeTCToJavaClassAdapter(ClassVisitor cv, TransparencyClassAdapter dsoAdapter, String jFullClassDots, String tcFullClassDots, 35 ClassNode tcClassNode, Map instrumentedContext) { 36 super(cv); 37 this.tcClassNode = tcClassNode; 38 this.jFullClassSlashes = jFullClassDots.replace(DOT_DELIMITER, SLASH_DELIMITER); 39 this.tcFullClassSlashes = tcFullClassDots.replace(DOT_DELIMITER, SLASH_DELIMITER); 40 41 addNewContextIfNotExist(tcFullClassDots, jFullClassDots, instrumentedContext); 42 this.instrumentedContext = instrumentedContext; 43 this.visitedMethods = new HashSet (); 44 this.dsoAdapter = dsoAdapter; 45 } 46 47 public void visit(int version, int access, String name, String signature, String superName, String [] interfaces) { 48 this.superName = superName; 49 50 List tcInterfaces = tcClassNode.interfaces; 51 List jInterfaces = new ArrayList (); 52 for (int i = 0; i < interfaces.length; i++) { 53 if (!tcInterfaces.contains(interfaces[i])) { 54 jInterfaces.add(interfaces[i]); 55 } 56 } 57 for (Iterator i = tcInterfaces.iterator(); i.hasNext();) { 58 String intf = (String ) i.next(); 59 jInterfaces.add(intf); 60 } 61 interfaces = new String [jInterfaces.size()]; 62 jInterfaces.toArray(interfaces); 63 dsoAdapter.visit(version, access, name, signature, superName, interfaces); 65 } 66 67 private String getNewName(String methodName) { 68 if (isInitMethod(methodName)) { return methodName; } 69 return ByteCodeUtil.TC_METHOD_PREFIX + methodName; 70 } 71 72 public MethodVisitor visitMethod(int access, String name, String desc, String signature, String [] exceptions) { 73 String methodDesc = name + desc; 74 this.visitedMethods.add(methodDesc); 75 76 List tcMethods = tcClassNode.methods; 77 if (!isInitMethod(name)) { 78 for (Iterator i = tcMethods.iterator(); i.hasNext();) { 79 MethodNode mNode = (MethodNode) i.next(); 80 if (mNode.name.equals(name) && mNode.desc.equals(desc)) { return super 81 .visitMethod(ACC_PRIVATE, getNewName(name), desc, signature, exceptions); } 82 } 83 } 84 if (LogicalClassSerializationAdapter.WRITE_OBJECT_SIGNATURE.equals(methodDesc) 85 || LogicalClassSerializationAdapter.READ_OBJECT_SIGNATURE.equals(methodDesc)) { return new LogicalClassSerializationAdapter.LogicalClassSerializationMethodAdapter( 86 super 87 .visitMethod( 88 access, 89 name, 90 desc, 91 signature, 92 exceptions), 93 jFullClassSlashes); } 94 95 return super.visitMethod(access, name, desc, signature, exceptions); 96 } 97 98 public FieldVisitor visitField(int access, String name, String desc, String signature, Object value) { 99 List tcFields = tcClassNode.fields; 100 for (Iterator i = tcFields.iterator(); i.hasNext();) { 101 FieldNode fieldNode = (FieldNode) i.next(); 102 if (access == fieldNode.access && name.equals(fieldNode.name) && desc.equals(fieldNode.desc)) { 103 i.remove(); 104 break; 105 } 106 } 107 108 if ("java/util/LinkedHashMap".equals(jFullClassSlashes) && "accessOrder".equals(name)) { 110 access = ~Modifier.FINAL & access; 111 } 112 return super.visitField(access, name, desc, signature, value); 113 } 114 115 public void visitEnd() { 116 addTCFields(); 117 addTCMethods(); 118 addTCInnerClasses(); 119 super.visitEnd(); 120 } 121 122 private void addTCMethods() { 123 List tcMethods = tcClassNode.methods; 124 for (Iterator i = tcMethods.iterator(); i.hasNext();) { 125 MethodNode mNode = (MethodNode) i.next(); 126 if (isInitMethod(mNode.name)) { 127 continue; 128 } 129 mNode.accept(new TCSuperClassAdapter(cv)); 130 } 131 LogicalClassSerializationAdapter.addCheckSerializationOverrideMethod(cv, false); 132 } 133 134 private boolean isInitMethod(String methodName) { 135 return "<init>".equals(methodName); 136 } 137 138 private void addTCFields() { 139 List tcFields = tcClassNode.fields; 140 for (Iterator i = tcFields.iterator(); i.hasNext();) { 141 FieldNode fNode = (FieldNode) i.next(); 142 fNode.accept(cv); 143 } 144 } 145 146 private void addTCInnerClasses() { 147 List tcInnerClasses = tcClassNode.innerClasses; 148 for (Iterator i = tcInnerClasses.iterator(); i.hasNext();) { 149 InnerClassNode innerClass = (InnerClassNode) i.next(); 150 innerClass.accept(new TCSuperClassAdapter(cv)); 151 } 152 } 153 154 private class TCSuperClassAdapter extends ClassAdapter implements Opcodes { 155 public TCSuperClassAdapter(ClassVisitor cv) { 156 super(cv); 157 } 158 159 public void visit(int version, int access, String name, String signature, String superName, String [] interfaces) { 160 name = replaceClassName(name); 161 superName = replaceClassName(superName); 162 super.visit(version, access & ~ACC_ABSTRACT, name, signature, superName, interfaces); 163 } 164 165 public MethodVisitor visitMethod(int access, String name, String desc, String signature, String [] exceptions) { 166 desc = replaceClassName(desc); 167 signature = replaceClassName(signature); 168 return new TCSuperMethodAdapter(dsoAdapter.basicVisitMethod(access, name, desc, signature, exceptions)); 170 } 171 172 private String replaceClassName(String classNameDots) { 173 return replaceClassName(classNameDots, tcFullClassSlashes, jFullClassSlashes); 174 } 175 176 private String replaceClassName(String classNameDots, String srcClassNameDots, String targetClassNameDots) { 177 if (classNameDots == null || classNameDots.length() == 0) { return classNameDots; } 178 179 classNameDots = classNameDots.replace(DOT_DELIMITER, SLASH_DELIMITER); 180 srcClassNameDots = srcClassNameDots.replace(DOT_DELIMITER, SLASH_DELIMITER); 181 targetClassNameDots = targetClassNameDots.replace(DOT_DELIMITER, SLASH_DELIMITER); 182 183 int index = classNameDots.indexOf(srcClassNameDots); 184 if (index == -1) { return classNameDots; } 185 186 StringBuffer newClassName = new StringBuffer (); 187 while (index != -1) { 188 if (index > 0) { 189 newClassName.append(classNameDots.substring(0, index)); 190 } 191 newClassName.append(targetClassNameDots); 192 classNameDots = classNameDots.substring(index + srcClassNameDots.length()); 193 index = classNameDots.indexOf(srcClassNameDots); 194 } 195 newClassName.append(classNameDots); 196 return newClassName.toString(); 197 } 198 199 private class TCSuperMethodAdapter extends MethodAdapter implements Opcodes { 200 public TCSuperMethodAdapter(MethodVisitor mv) { 201 super(mv); 202 } 203 204 public void visitMethodInsn(int opcode, String owner, String name, String desc) { 205 int index = owner.indexOf(tcFullClassSlashes); 206 if (opcode == INVOKESPECIAL && index == -1) { 207 if (!visitedMethods.contains(name + desc) && !isInitMethod(name)) { 208 owner = superName; 209 } else { 210 ChangeContext context = (ChangeContext) instrumentedContext.get(owner); 211 if (context != null) { 212 owner = context.convertedClassNameSlashes; 213 } 214 name = getNewName(name); 215 } 216 super.visitMethodInsn(opcode, owner, name, desc); 217 } else { 218 owner = replaceClassName(owner); 219 desc = replaceClassName(desc); 220 super.visitMethodInsn(opcode, owner, name, desc); 221 } 222 } 223 224 public void visitFieldInsn(int opcode, String owner, String name, String desc) { 225 owner = replaceClassName(owner); 226 desc = replaceClassName(desc); 227 super.visitFieldInsn(opcode, owner, name, desc); 228 } 229 230 public void visitTypeInsn(int opcode, String desc) { 231 ChangeContext context = (ChangeContext) instrumentedContext.get(desc); 232 if (context != null) { 233 desc = context.convertedClassNameSlashes; 234 } else { 235 desc = replaceClassName(desc); 236 } 237 super.visitTypeInsn(opcode, desc); 238 } 239 240 } 241 } 242 } 243 | Popular Tags |