1 22 package org.jboss.aop.instrument; 23 24 import java.lang.reflect.Constructor ; 25 26 import javassist.CannotCompileException; 27 import javassist.CtClass; 28 import javassist.CtConstructor; 29 import javassist.CtField; 30 import javassist.CtMethod; 31 import javassist.CtNewConstructor; 32 import javassist.CtNewMethod; 33 import javassist.Modifier; 34 import javassist.NotFoundException; 35 36 import org.jboss.aop.ConByMethodInfo; 37 import org.jboss.aop.GeneratedClassAdvisor; 38 import org.jboss.aop.JoinPointInfo; 39 import org.jboss.aop.advice.AdviceMethodProperties; 40 import org.jboss.aop.joinpoint.ConstructorCalledByMethodInvocation; 41 import org.jboss.aop.util.ReflectToJavassist; 42 43 48 public class ConByMethodJoinPointGenerator extends JoinPointGenerator 49 { 50 public static final String GENERATOR_PREFIX = JoinPointGenerator.GENERATOR_PREFIX + "CByM_"; 51 public static final String JOINPOINT_CLASS_PREFIX = JoinPointGenerator.JOINPOINT_CLASS_PREFIX + "CByM_"; 52 public static final String JOINPOINT_FIELD_PREFIX = JoinPointGenerator.JOINPOINT_FIELD_PREFIX + "CByM_"; 53 private static final Class INVOCATION_TYPE = ConstructorCalledByMethodInvocation.class; 54 private static final CtClass INVOCATION_CT_TYPE; 55 static 56 { 57 try 58 { 59 INVOCATION_CT_TYPE = ReflectToJavassist.classToJavassist(INVOCATION_TYPE); 60 } 61 catch (NotFoundException e) 62 { 63 throw new RuntimeException (e); 64 } 65 } 66 67 68 public ConByMethodJoinPointGenerator(GeneratedClassAdvisor advisor, JoinPointInfo info) 69 { 70 super(advisor, info); 71 } 72 73 protected void initialiseJoinPointNames() 74 { 75 joinpointClassName = getInfoClassName( 76 callingMethodHash(), 77 calledClass(), 78 calledConHash()); 79 80 joinpointFieldName = getInfoFieldName( 81 callingMethodHash(), 82 calledClass(), 83 calledConHash()); 84 85 } 86 87 private long callingMethodHash() 88 { 89 return ((ConByMethodInfo)info).getCallingMethodHash(); 90 } 91 92 private String calledClass() 93 { 94 return ((ConByMethodInfo)info).getCalledClass().getName(); 95 } 96 97 private long calledConHash() 98 { 99 return ((ConByMethodInfo)info).getCalledConHash(); 100 } 101 102 protected boolean isVoid() 103 { 104 return false; 105 } 106 107 protected Class getReturnType() 108 { 109 return ((ConByMethodInfo)info).getCalledClass(); 110 } 111 112 protected AdviceMethodProperties getAdviceMethodProperties(AdviceSetup setup) 113 { 114 Constructor ctor = ((ConByMethodInfo)info).getConstructor(); 115 return new AdviceMethodProperties( 116 setup.getAspectClass(), 117 setup.getAdviceName(), 118 info.getClass(), 119 INVOCATION_TYPE, 120 ctor.getDeclaringClass(), 121 ctor.getParameterTypes(), 122 ctor.getExceptionTypes()); 123 } 124 125 protected boolean isCaller() 126 { 127 return true; 128 } 129 130 protected boolean hasCallingObject() 131 { 132 return !java.lang.reflect.Modifier.isStatic(((ConByMethodInfo)info).getCallingMethod().getModifiers()); 133 } 134 135 protected boolean hasTargetObject() 136 { 137 return false; 138 } 139 140 protected void overrideDispatchMethods(CtClass superClass, CtClass clazz, JoinPointInfo newInfo) throws CannotCompileException, NotFoundException 141 { 142 super.overrideDispatchMethods(superClass, clazz, (ConByMethodInfo)newInfo); 143 } 144 145 protected static CtClass createJoinpointBaseClass( 146 GeneratedAdvisorInstrumentor instrumentor, 147 long callingHash, 148 boolean hasCallingObject, 149 CtClass callingClass, 150 CtConstructor targetCtor, 151 String classname, 152 long calledHash, 153 String ciname) throws NotFoundException, CannotCompileException 154 { 155 instrumentor.addJoinPointGeneratorFieldToGenAdvisor( 156 getJoinPointGeneratorFieldName(callingHash, classname, calledHash)); 157 158 BaseClassGenerator generator = new BaseClassGenerator(instrumentor, callingClass, callingHash, hasCallingObject, classname, targetCtor, calledHash, ciname); 159 return generator.generate(); 160 } 161 162 protected String getJoinPointGeneratorFieldName() 163 { 164 return getJoinPointGeneratorFieldName( 165 callingMethodHash(), 166 calledClass(), 167 calledConHash()); 168 } 169 170 protected static String getInfoClassName(long callingHash, String classname, long calledHash) 171 { 172 return JOINPOINT_CLASS_PREFIX + CallerTransformer.getUniqueInvocationFieldname(callingHash, classname, calledHash); 173 } 174 175 protected static String getInfoFieldName(long callingHash, String classname, long calledHash) 176 { 177 return JOINPOINT_FIELD_PREFIX + CallerTransformer.getUniqueInvocationFieldname(callingHash, classname, calledHash); 178 } 179 180 protected static String getJoinPointGeneratorFieldName(long callingHash, String classname, long calledHash) 181 { 182 return GENERATOR_PREFIX + CallerTransformer.getUniqueInvocationFieldname(callingHash, classname, calledHash); 183 } 184 185 private static class BaseClassGenerator 186 { 187 GeneratedAdvisorInstrumentor instrumentor; 188 CtClass callingClass; 189 long callingHash; 190 boolean hasCallingObject; 191 String classname; 192 CtClass targetClass; 193 CtConstructor targetCtor; 194 long calledHash; 195 String ciname; 196 197 CtClass jp; 198 CtMethod invokeJoinpointMethod; 199 CtConstructor publicConstructor; 200 CtConstructor protectedConstructor; 201 CtClass[] params; 202 CtClass constructorInfoClass; 203 204 BaseClassGenerator( 205 GeneratedAdvisorInstrumentor instrumentor, 206 CtClass callingClass, 207 long callingHash, 208 boolean hasCallingObject, 209 String classname, 210 CtConstructor targetCtor, 211 long calledHash, 212 String ciname) throws NotFoundException 213 { 214 this.instrumentor = instrumentor; 215 this.callingClass = callingClass; 216 this.callingHash = callingHash; 217 this.hasCallingObject = hasCallingObject; 218 this.classname = classname; 219 this.targetClass = instrumentor.forName(classname); 220 this.targetCtor = targetCtor; 221 this.calledHash = calledHash; 222 this.ciname = ciname; 223 this.params = targetCtor.getParameterTypes(); 224 constructorInfoClass = instrumentor.forName(CallerTransformer.CON_BY_METHOD_INFO_CLASS_NAME); 225 } 226 227 protected CtClass generate() throws CannotCompileException, NotFoundException 228 { 229 jp = setupClass(); 230 addArgumentsFieldsAndAccessors(); 231 addInvokeJoinpointMethod(); 232 addMethodInfoField(); 233 addPublicConstructor(); 234 addProtectedConstructor(); 235 addDispatchMethods(); 236 237 TransformerCommon.compileOrLoadClass(callingClass, jp); 238 return jp; 239 } 240 241 242 private CtClass setupClass()throws NotFoundException, CannotCompileException 243 { 244 String className = getInfoClassName(callingHash, targetClass.getName(), calledHash); 245 246 jp = TransformerCommon.makeNestedClass(callingClass, className, true, Modifier.PUBLIC | Modifier.STATIC, INVOCATION_CT_TYPE); 248 addUntransformableInterface(instrumentor, jp); 249 return jp; 250 } 251 252 private void addArgumentsFieldsAndAccessors() throws NotFoundException, CannotCompileException 253 { 254 OptimizedBehaviourInvocations.addArgumentFieldsToInvocation(jp, params); 255 OptimizedBehaviourInvocations.addSetArguments(instrumentor.getClassPool(), jp, params); 256 OptimizedBehaviourInvocations.addGetArguments(instrumentor.getClassPool(), jp, params); 257 } 258 259 264 private void addPublicConstructor() throws CannotCompileException 265 { 266 publicConstructor = CtNewConstructor.make( 267 new CtClass[] {constructorInfoClass}, 268 new CtClass[0], 269 "{super($1, null, $1.getInterceptors()); this." + INFO_FIELD + " = $1;}", 270 jp); 271 272 jp.addConstructor(publicConstructor); 273 } 274 275 279 protected void addProtectedConstructor() throws CannotCompileException 280 { 281 final int offset = (hasCallingObject) ? 2 : 1; 282 CtClass[] ctorParams = new CtClass[params.length + offset]; 283 ctorParams[0] = jp; 284 285 if (hasCallingObject) 286 { 287 ctorParams[1] = callingClass; 288 } 289 System.arraycopy(params, 0, ctorParams, offset, params.length); 290 291 StringBuffer body = new StringBuffer (); 292 body.append("{"); 293 body.append(" this($1." + INFO_FIELD + ");"); 294 295 if (hasCallingObject) 296 { 297 body.append(" super.callingObject=$" + offset + ";"); 298 } 299 300 for (int i = offset ; i < ctorParams.length ; i++) 301 { 302 body.append(" arg" + (i - offset) + " = $" + (i + 1) + ";"); 303 } 304 305 body.append("}"); 306 protectedConstructor = CtNewConstructor.make( 307 ctorParams, 308 new CtClass[0], 309 body.toString(), 310 jp); 311 protectedConstructor.setModifiers(Modifier.PROTECTED); 312 313 jp.addConstructor(protectedConstructor); 314 315 } 316 317 private CtClass[] getInvokeJoinPointParams() 318 { 319 if (hasCallingObject) 320 { 321 CtClass[] invokeParams = null; 322 invokeParams = new CtClass[params.length + 1]; 323 invokeParams[0] = callingClass; 324 System.arraycopy(params, 0, invokeParams, 1, params.length); 325 return invokeParams; 326 } 327 return params; 328 } 329 330 334 private CtMethod addInvokeJoinpointMethod() throws CannotCompileException, NotFoundException 335 { 336 invokeJoinpointMethod = CtNewMethod.make( 337 targetClass, 338 INVOKE_JOINPOINT, 339 getInvokeJoinPointParams(), 340 targetCtor.getExceptionTypes(), 341 null, 342 jp); 343 invokeJoinpointMethod.setModifiers(Modifier.PROTECTED); 344 jp.addMethod(invokeJoinpointMethod); 345 return invokeJoinpointMethod; 346 } 347 348 private void addMethodInfoField()throws CannotCompileException 349 { 350 CtField infoField = new CtField(constructorInfoClass, INFO_FIELD, jp); 351 infoField.setModifiers(javassist.Modifier.PROTECTED); jp.addField(infoField); 353 } 354 355 private void addDispatchMethods() throws CannotCompileException, NotFoundException 356 { 357 addInvokeNextDispatchMethod(); 358 359 if (hasCallingObject || params.length > 0) 360 { 361 addInvokeJoinPointDispatchMethod(); 362 } 363 364 addInvokeTargetMethod(); 365 } 366 367 private void addInvokeNextDispatchMethod() throws CannotCompileException, NotFoundException 368 { 369 371 StringBuffer parameters = new StringBuffer ("("); 372 for (int i = 0 ; i < params.length ; i++) 373 { 374 if (i > 0)parameters.append(", "); 375 parameters.append("arg" + i); 376 } 377 parameters.append(")"); 378 379 String body = 380 "{" + 381 " " + targetClass.getName() + " obj = new " + targetClass.getName() + parameters + ";" + 382 " setTargetObject(obj);" + 383 " return obj;" + 384 "}"; 385 386 try 387 { 388 CtMethod dispatch = CtNewMethod.make( 389 targetClass, 390 JoinPointGenerator.DISPATCH, 391 EMPTY_CTCLASS_ARRAY, 392 targetCtor.getExceptionTypes(), 393 body, 394 jp); 395 dispatch.setModifiers(Modifier.PROTECTED); 396 jp.addMethod(dispatch); 397 } 398 catch (CannotCompileException e) 399 { 400 throw new RuntimeException ("Could not compile code " + body + " for method " + getMethodString(jp, JoinPointGenerator.DISPATCH, EMPTY_CTCLASS_ARRAY), e); 401 } 402 } 403 404 private void addInvokeJoinPointDispatchMethod() throws CannotCompileException, NotFoundException 405 { 406 408 int offset = hasCallingObject ? 1 : 0; 409 StringBuffer parameters = new StringBuffer ("("); 410 for (int i = 0 ; i < params.length ; i++) 411 { 412 if (i > 0)parameters.append(", "); 413 parameters.append("$" + (i + offset + 1)); 414 } 415 parameters.append(")"); 416 417 String body = 418 "{" + 419 " " + targetClass.getName() + " obj = new " + targetClass.getName() + parameters + ";" + 420 " setTargetObject(obj);" + 421 " return obj;" + 422 "}"; 423 424 CtClass[] params = getInvokeJoinPointParams(); 425 try 426 { 427 CtMethod dispatch = CtNewMethod.make( 428 targetClass, 429 JoinPointGenerator.DISPATCH, 430 params, 431 targetCtor.getExceptionTypes(), 432 body, 433 jp); 434 dispatch.setModifiers(Modifier.PROTECTED); 435 jp.addMethod(dispatch); 436 } 437 catch (CannotCompileException e) 438 { 439 throw new RuntimeException ("Could not compile code " + body + " for method " + getMethodString(jp, JoinPointGenerator.DISPATCH, params), e); 440 } 441 } 442 443 private void addInvokeTargetMethod() throws CannotCompileException, NotFoundException 444 { 445 CtMethod template = INVOCATION_CT_TYPE.getDeclaredMethod(INVOKE_TARGET); 446 447 String body = "{return dispatch();}"; 448 449 CtMethod invokeTarget = CtNewMethod.make( 450 template.getReturnType(), 451 template.getName(), 452 template.getParameterTypes(), 453 template.getExceptionTypes(), 454 body, 455 jp); 456 jp.addMethod(invokeTarget); 457 } 458 459 } 460 461 } 462 463 | Popular Tags |