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