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.MethodVisitor; 9 import com.tc.asm.Opcodes; 10 import com.tc.asm.Type; 11 12 import java.util.HashMap ; 13 import java.util.Map ; 14 15 18 public abstract class ChangeClassNameHierarchyAdapter extends ClassAdapter implements Opcodes { 19 public final static char DOT_DELIMITER = '.'; 20 public final static char SLASH_DELIMITER = '/'; 21 final static String CLASS_DELIMITER = ";"; 22 final static String CLASS_START_CHAR = "L"; 23 final static String CLASS_START_DESC_CHAR = "(L"; 24 final static String CLASS_RETURN_DESC_CHAR = ")L"; 25 final static String CLASS_ARRAY_DESC_CHAR = "[L"; 26 27 ChangeContext addNewContextIfNotExist(String fullClassNameSlashes, String convertedFullClassNameSlashes, Map instrumentedContext) { 28 ChangeContext changeContext = (ChangeContext)instrumentedContext.get(fullClassNameSlashes); 29 if (changeContext == null) { 30 changeContext = new ChangeContext(fullClassNameSlashes, convertedFullClassNameSlashes); 31 instrumentedContext.put(fullClassNameSlashes, changeContext); 32 } else if (!convertedFullClassNameSlashes.equals(fullClassNameSlashes) && 33 !convertedFullClassNameSlashes.equals(changeContext.convertedClassNameSlashes)) { 34 changeContext.convertedClassNameSlashes = convertedFullClassNameSlashes; 35 } 36 return changeContext; 37 } 38 39 ChangeContext addNewContext(String fullClassNameSlashes, String convertedFullClassNameSlashes, Map instrumentedContext) { 40 ChangeContext changeContext = new ChangeContext(fullClassNameSlashes, convertedFullClassNameSlashes); 41 instrumentedContext.put(fullClassNameSlashes, changeContext); 42 43 return changeContext; 44 } 45 46 ModifiedMethodInfo getModifiedMethodInfo(ChangeContext changeContext, String methodName, String desc) { 47 if (changeContext == null) { return null; } 48 49 ModifiedMethodInfo methodInfo = (ModifiedMethodInfo)changeContext.modifiedMethodInfo.get(methodName+desc); 50 if (methodInfo != null && methodName.equals(methodInfo.methodName) && desc.equals(methodInfo.originalMethodDesc)) { return methodInfo; } 51 return null; 52 } 53 54 String getConvertedMethodDesc(Map instrumentedContext, String fullClassNameSlashes, String methodName, String methodDesc) { 55 ChangeContext context = (ChangeContext)instrumentedContext.get(fullClassNameSlashes); 56 while (context != null) { 57 ModifiedMethodInfo methodInfo = getModifiedMethodInfo(context, methodName, methodDesc); 58 if (methodInfo != null) { 59 return methodInfo.convertedMethodDesc; 60 } 61 String superClassName = context.originalSuperClassNameSlashes; 62 if (superClassName != null) { 63 context = (ChangeContext)instrumentedContext.get(superClassName); 64 } else { 65 context = null; 66 } 67 } 68 return null; 69 } 70 71 static class ChangeContext { 72 final String originalClassNameSlashes; 73 String convertedClassNameSlashes; 74 String originalSuperClassNameSlashes; 75 76 final Map modifiedMethodInfo = new HashMap (); 77 final Map modifiedFieldInfo = new HashMap (); 78 79 public ChangeContext(String originalClassNameSlashes, String convertedClassNameSlashes) { 80 this.originalClassNameSlashes = originalClassNameSlashes; 81 this.convertedClassNameSlashes = convertedClassNameSlashes; 82 } 83 84 public void setOriginalSuperClass(String superClassNameSlashes) { 85 this.originalSuperClassNameSlashes = superClassNameSlashes; 86 } 87 88 void addModifiedMethodInfo(String name, String originalDesc, String convertedDesc, String signature, 89 String convertedSignature) { 90 ModifiedMethodInfo methodInfo = (ModifiedMethodInfo)modifiedMethodInfo.get(name+originalDesc); 91 if (methodInfo == null) { 92 modifiedMethodInfo.put(name+originalDesc, new ModifiedMethodInfo(name, originalDesc, convertedDesc, signature, convertedSignature)); 93 } else { 94 if (!convertedDesc.equals(methodInfo.convertedMethodDesc)) { 95 methodInfo.convertedMethodDesc = convertedDesc; 96 } 97 if (signature != null && !signature.equals(methodInfo.originalSignature)) { 98 methodInfo.originalSignature = signature; 99 } 100 if (convertedSignature != null && !convertedSignature.equals(methodInfo.convertedSignature)) { 101 methodInfo.convertedSignature = signature; 102 } 103 } 104 } 105 106 void addModifiedFieldInfo(String name, String originalDesc, String convertedDesc, String signature, 107 String convertedSignature) { 108 modifiedFieldInfo.put(name+originalDesc, new ModifiedFieldInfo(name, originalDesc, convertedDesc, signature, convertedSignature)); 109 } 110 111 public String toString() { 112 StringBuffer buf = new StringBuffer (); 113 buf.append(super.toString()); 114 buf.append(" ChangeContext :- "); 115 buf.append("originalClassNameSlashes: "); 116 buf.append(originalClassNameSlashes); 117 buf.append(", convertedClassNameSlashes: "); 118 buf.append(convertedClassNameSlashes); 119 buf.append(", modifiedMethodInfo size: "); 120 buf.append(modifiedMethodInfo.size()); 121 buf.append(modifiedMethodInfo); 122 return buf.toString(); 123 } 124 } 125 126 static class ModifiedFieldInfo { 127 final String fieldName; 128 final String originalFieldDesc; 129 String convertedFieldDesc; 130 String originalSignature; 131 String convertedSignature; 132 133 ModifiedFieldInfo(String name, String originalDesc, String convertedDesc, String signature, 134 String convertedSignature) { 135 this.fieldName = name; 136 this.originalFieldDesc = originalDesc; 137 this.convertedFieldDesc = convertedDesc; 138 this.originalSignature = signature; 139 this.convertedSignature = convertedSignature; 140 } 141 142 public boolean equals(Object obj) { 143 ModifiedFieldInfo fieldInfo = (ModifiedFieldInfo) obj; 144 boolean match = this.fieldName != null && this.fieldName.equals(fieldInfo.fieldName); 145 match = match && this.originalFieldDesc != null && this.originalFieldDesc.equals(fieldInfo.originalFieldDesc); 146 match = match && this.convertedFieldDesc != null && this.convertedFieldDesc.equals(fieldInfo.convertedFieldDesc); 147 match = match 148 && ((this.originalSignature == null && fieldInfo.originalSignature == null) || (this.originalSignature != null && this.originalSignature 149 .equals(fieldInfo.originalSignature))); 150 match = match 151 && ((this.convertedSignature == null && fieldInfo.convertedSignature == null) || (this.convertedSignature != null && this.convertedSignature 152 .equals(fieldInfo.convertedSignature))); 153 return match; 154 } 155 156 public String toString() { 157 return super.toString() + ", name: " +fieldName + ", desc: " + originalFieldDesc + ", convertedDesc: " + convertedFieldDesc; 158 } 159 } 160 161 static class ModifiedMethodInfo { 162 final String methodName; 163 final String originalMethodDesc; 164 String convertedMethodDesc; 165 String originalSignature; 166 String convertedSignature; 167 168 ModifiedMethodInfo(String name, String originalDesc, String convertedDesc, String signature, 169 String convertedSignature) { 170 this.methodName = name; 171 this.originalMethodDesc = originalDesc; 172 this.convertedMethodDesc = convertedDesc; 173 this.originalSignature = signature; 174 this.convertedSignature = convertedSignature; 175 } 176 177 public boolean equals(Object obj) { 178 ModifiedMethodInfo methodInfo = (ModifiedMethodInfo) obj; 179 boolean match = this.methodName != null && this.methodName.equals(methodInfo.methodName); 180 match = match && this.originalMethodDesc != null && this.originalMethodDesc.equals(methodInfo.originalMethodDesc); 181 match = match && this.convertedMethodDesc != null 182 && this.convertedMethodDesc.equals(methodInfo.convertedMethodDesc); 183 match = match 184 && ((this.originalSignature == null && methodInfo.originalSignature == null) || (this.originalSignature != null && this.originalSignature 185 .equals(methodInfo.originalSignature))); 186 match = match 187 && ((this.convertedSignature == null && methodInfo.convertedSignature == null) || (this.convertedSignature != null && this.convertedSignature 188 .equals(methodInfo.convertedSignature))); 189 return match; 190 } 191 192 public String toString() { 193 return super.toString() + ", name: " + methodName + ", desc: " + originalMethodDesc + ", convertedDesc: " + convertedMethodDesc; 194 } 195 } 196 197 public ChangeClassNameHierarchyAdapter(ClassVisitor cv) { 198 super(cv); 199 } 200 201 public MethodVisitor invokeSuperVisitMethod(int access, String name, String desc, String signature, String [] exceptions, 202 Map instrumentedContext, String fullClassSlashes) { 203 ChangeContext context = (ChangeContext)instrumentedContext.get(fullClassSlashes); 204 String origSuperClassName = context.originalSuperClassNameSlashes; 205 String convertedSuperClassName = context.convertedClassNameSlashes; 207 208 Type returnType = Type.getReturnType(desc); 209 MethodVisitor mv = cv.visitMethod(access, name, desc, signature, exceptions); 210 mv.visitCode(); 211 mv.visitVarInsn(ALOAD, 0); 212 ByteCodeUtil.pushMethodArguments(access, desc, mv); 213 mv.visitMethodInsn(INVOKESPECIAL, origSuperClassName, name, desc); 214 mv.visitInsn(returnType.getOpcode(IRETURN)); 215 mv.visitMaxs(0, 0); 216 mv.visitEnd(); 217 return mv; 218 } 219 220 } 221 | Popular Tags |