1 22 package org.jboss.aop.instrument; 23 24 import java.lang.reflect.Method ; 25 import java.util.Collection ; 26 import java.util.HashMap ; 27 import java.util.Iterator ; 28 import org.jboss.aop.ClassAdvisor; 29 import org.jboss.aop.classpool.AOPClassPool; 30 import org.jboss.aop.util.JavassistMethodHashing; 31 32 import javassist.CannotCompileException; 33 import javassist.CtClass; 34 import javassist.CtField; 35 import javassist.CtMethod; 36 import javassist.Modifier; 37 import javassist.NotFoundException; 38 import javassist.bytecode.AnnotationsAttribute; 39 import javassist.bytecode.MethodInfo; 40 41 47 public abstract class MethodExecutionTransformer 48 { 49 public static final String METHOD_INFO_CLASS_NAME = "org.jboss.aop.MethodInfo"; 50 private static final WrapperTransformer wrapper = new WrapperTransformer(WrapperTransformer.SINGLE_TRANSFORMATION); 51 protected Instrumentor instrumentor; 52 private JoinpointClassifier classifier; 53 54 protected MethodExecutionTransformer(Instrumentor instrumentor) 55 { 56 this.instrumentor = instrumentor; 57 this.classifier = instrumentor.joinpointClassifier; 58 } 59 60 protected static WrapperTransformer getWrapper() 61 { 62 return wrapper; 63 } 64 65 protected JoinpointClassifier getClassifier() 66 { 67 return classifier; 68 } 69 70 73 protected String addMethodInfoField(int modifiers, CtClass addTo, MethodTransformation trans) throws NotFoundException, CannotCompileException 74 { 75 return addMethodInfoField(modifiers, addTo, trans, null); 76 } 77 78 81 protected String addMethodInfoField(int modifiers, CtClass addTo, MethodTransformation trans, CtField.Initializer init) throws NotFoundException, CannotCompileException 82 { 83 String name = getMethodInfoFieldName(trans.getOriginalName(), trans.getHash()); 84 TransformerCommon.addInfoField(instrumentor, METHOD_INFO_CLASS_NAME, name, modifiers, addTo, addInfoAsWeakReference(), init); 85 86 return name; 87 } 88 89 protected boolean addInfoAsWeakReference() 90 { 91 return true; 92 } 93 94 public static String getMethodNameHash(String methodName, long methodHash) 95 { 96 String hash; 97 if (methodHash < 0) 98 hash = "_N_" + (-1 * methodHash); 99 else 100 hash = "" + methodHash; 101 return methodName + hash; 102 } 103 104 public static String getMethodInfoFieldName(String methodName, long methodHash) 105 { 106 String name = "aop$MethodInfo_" + getMethodNameHash(methodName, methodHash); 107 return name; 108 } 109 110 protected static String methodInfoFromWeakReference(String localName, String methodInfoName) 111 { 112 return TransformerCommon.infoFromWeakReference(METHOD_INFO_CLASS_NAME, localName, methodInfoName); 113 } 114 115 122 protected JoinpointClassification[] classifyMethods(CtClass clazz, ClassAdvisor advisor) throws NotFoundException 123 { 124 CtMethod[] methods = clazz.getDeclaredMethods(); 125 JoinpointClassification[] classification = new JoinpointClassification[methods.length]; 126 for (int i = 0; i < methods.length; i++) 127 { 128 classification[i] = classifier.classifyMethodExecution(methods[i], advisor); 129 } 130 return classification; 131 } 132 133 public void instrument(CtClass clazz, ClassAdvisor advisor)throws NotFoundException, CannotCompileException 134 { 135 JoinpointClassification[] classification = classifyMethods(clazz, advisor); 136 CtMethod[] methods = clazz.getDeclaredMethods(); 137 for (int i = 0; i < methods.length; i++) 138 { 139 if (classification[i] == JoinpointClassification.NOT_INSTRUMENTED) 140 { 141 continue; 142 } 143 instrumentor.setupBasics(clazz); 144 MethodTransformation trans = new MethodTransformation(instrumentor, clazz, methods[i]); 145 boolean wrap = (classification[i].equals(JoinpointClassification.WRAPPED)); 146 transformMethod(trans, wrap); 147 148 int modifier = trans.getWMethod().getModifiers(); 149 if (Modifier.isNative(modifier)) 150 { 151 modifier &=~Modifier.NATIVE; 152 trans.getWMethod().setModifiers(modifier); 153 } 154 } 155 } 156 157 164 public void wrap(CtClass clazz, Collection methodInfos) throws Exception 165 { 166 for (Iterator iterator = methodInfos.iterator(); iterator.hasNext();) 167 { 168 org.jboss.aop.MethodInfo methodInfo = (org.jboss.aop.MethodInfo) iterator.next(); 169 Method method = methodInfo.getAdvisedMethod(); 170 AOPClassPool classPool = (AOPClassPool) clazz.getClassPool(); 171 Class [] parameterTypes = method.getParameterTypes(); 172 CtClass[] javassistParameterTypes = new CtClass[parameterTypes.length]; 173 for (int i = 0; i < parameterTypes.length; i++) 174 { 175 classPool.getLocally(parameterTypes[i].getName()); 176 } 177 if (method.getName().indexOf("access$") >= 0) 178 { 179 continue; 180 } 181 182 String wrappedName = ClassAdvisor.notAdvisedMethodName(clazz.getName(), method.getName()); 183 CtMethod wmethod = clazz.getDeclaredMethod(method.getName(), javassistParameterTypes); 184 if (wrapper.isNotPrepared(wmethod, WrapperTransformer.SINGLE_TRANSFORMATION_INDEX)) 185 { 186 continue; 187 } 188 MethodTransformation trans = new MethodTransformation( 189 instrumentor, 190 clazz, 191 clazz.getDeclaredMethod(wrappedName, javassistParameterTypes), 192 method.getName(), 193 clazz.getDeclaredMethod(method.getName(), javassistParameterTypes), 194 wrappedName); 195 196 wrapper.wrap(trans.getWMethod(), WrapperTransformer.SINGLE_TRANSFORMATION_INDEX); 198 String methodInfoFieldName = getMethodInfoFieldName(trans.getOriginalName(), trans.getHash()); 200 doWrap(trans, methodInfoFieldName); 201 } 202 } 203 204 211 public void unwrap(CtClass clazz, Collection methodInfos) throws Exception 212 { 213 for (Iterator iterator = methodInfos.iterator(); iterator.hasNext();) 214 { 215 org.jboss.aop.MethodInfo methodInfo = (org.jboss.aop.MethodInfo) iterator.next(); 216 Method method = methodInfo.getAdvisedMethod(); 217 AOPClassPool classPool = (AOPClassPool) clazz.getClassPool(); 218 Class [] parameterTypes = method.getParameterTypes(); 219 CtClass[] javassistParameterTypes = new CtClass[parameterTypes.length]; 220 for (int i = 0; i < parameterTypes.length; i++) 221 { 222 classPool.getLocally(parameterTypes[i].getName()); 223 } 224 CtMethod javassistWMethod = clazz.getDeclaredMethod(method.getName(), javassistParameterTypes); 225 if (wrapper.isNotPrepared(javassistWMethod, WrapperTransformer.SINGLE_TRANSFORMATION_INDEX)) 226 { 227 continue; 228 } 229 CtMethod javassistMethod = clazz.getDeclaredMethod(ClassAdvisor.notAdvisedMethodName(clazz.getName(), method.getName()), 230 javassistParameterTypes); 231 wrapper.unwrap(javassistWMethod, WrapperTransformer.SINGLE_TRANSFORMATION_INDEX); 233 javassistWMethod.setBody(javassistMethod, null); 235 } 236 } 237 238 protected void copyAnnotations(CtMethod src, CtMethod dest) 239 { 240 MethodInfo mi = src.getMethodInfo2(); 241 MethodInfo wmi = dest.getMethodInfo2(); 242 AnnotationsAttribute invisible = (AnnotationsAttribute) mi.getAttribute(AnnotationsAttribute.invisibleTag); 243 if (invisible != null) 244 { 245 wmi.addAttribute(invisible.copy(wmi.getConstPool(), new HashMap ())); 246 } 247 AnnotationsAttribute visible = (AnnotationsAttribute) mi.getAttribute(AnnotationsAttribute.visibleTag); 248 if (visible != null) 249 { 250 wmi.addAttribute(visible.copy(wmi.getConstPool(), new HashMap ())); 251 } 252 } 253 254 protected static String getAopReturnStr(CtMethod method)throws NotFoundException 255 { 256 return getAopReturnStr(method.getReturnType().equals(CtClass.voidType)); 257 } 258 259 protected static String getAopReturnStr(boolean isVoid)throws NotFoundException 260 { 261 return isVoid ? "" : "return ($r)"; 262 } 263 264 protected static String getReturnStr(CtMethod method)throws NotFoundException 265 { 266 return getReturnStr(method.getReturnType().equals(CtClass.voidType)); 267 } 268 269 protected static String getReturnStr(boolean isVoid)throws NotFoundException 270 { 271 return isVoid ? "" : "return "; 272 } 273 274 protected abstract void transformMethod(MethodTransformation trans, boolean wrap) throws CannotCompileException, NotFoundException; 275 protected abstract void doWrap(MethodTransformation trans, String methodInfoFieldName)throws NotFoundException, Exception ; 276 277 protected class MethodTransformation 278 { 279 Instrumentor instrumentor; 280 CtClass clazz; 281 CtMethod method; 282 String originalName; 283 CtMethod wmethod; 284 String wrappedName; 285 long hash; 286 287 public MethodTransformation(Instrumentor instrumentor, CtClass clazz, CtMethod method) 288 { 289 this.instrumentor = instrumentor; 290 this.clazz = clazz; 291 this.method = method; 292 this.originalName = method.getName(); 293 hash = JavassistMethodHashing.methodHash(method); 294 } 295 296 public MethodTransformation(Instrumentor instrumentor, 297 CtClass clazz, 298 CtMethod method, 299 String originalName, 300 CtMethod wmethod, 301 String wrappedName) 302 { 303 this.instrumentor = instrumentor; 304 this.clazz = clazz; 305 this.method = method; 306 this.originalName = originalName; 307 this.wmethod = wmethod; 308 this.wrappedName = wrappedName; 309 hash = JavassistMethodHashing.methodHash(wmethod); 310 } 311 312 public MethodTransformation(Instrumentor instrumentor, 313 CtClass clazz, 314 CtMethod method, 315 String originalName, 316 CtMethod wmethod, 317 String wrappedName, 318 long hash) 319 { 320 this.instrumentor = instrumentor; 321 this.clazz = clazz; 322 this.method = method; 323 this.originalName = originalName; 324 this.wmethod = wmethod; 325 this.wrappedName = wrappedName; 326 this.hash = hash; 327 } 328 329 330 public void setWMethod(CtMethod wmethod, String wrappedName) 331 { 332 this.wmethod = wmethod; 333 this.wrappedName = wrappedName; 334 } 335 336 public void setWMethodBody(String code)throws CannotCompileException 337 { 338 wmethod.setBody(code); 339 } 340 341 public String getOriginalName() 342 { 343 return originalName; 344 } 345 346 public String getWrappedName() 347 { 348 return wrappedName; 349 } 350 351 public CtClass getClazz() 352 { 353 return clazz; 354 } 355 356 public String getClazzName() 357 { 358 return clazz.getName(); 359 } 360 361 public CtMethod getMethod() 362 { 363 return method; 364 } 365 366 public CtMethod getWMethod() 367 { 368 return wmethod; 369 } 370 371 public long getHash() 372 { 373 return hash; 374 } 375 376 public Instrumentor getInstrumentor() 377 { 378 return instrumentor; 379 } 380 } 381 } | Popular Tags |