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.Advisor; 37 import org.jboss.aop.ConstructorInfo; 38 import org.jboss.aop.GeneratedClassAdvisor; 39 import org.jboss.aop.JoinPointInfo; 40 import org.jboss.aop.advice.AdviceMethodProperties; 41 import org.jboss.aop.joinpoint.ConstructorInvocation; 42 import org.jboss.aop.util.ReflectToJavassist; 43 44 49 public class ConstructorJoinPointGenerator extends JoinPointGenerator 50 { 51 public static final String GENERATOR_PREFIX = JoinPointGenerator.GENERATOR_PREFIX + "constructor_"; 52 public static final String JOINPOINT_CLASS_PREFIX = JoinPointGenerator.JOINPOINT_CLASS_PREFIX + "constructor_"; 53 public static final String JOINPOINT_FIELD_PREFIX = JoinPointGenerator.JOINPOINT_FIELD_PREFIX + "constructor_"; 54 private static final Class INVOCATION_TYPE = ConstructorInvocation.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 69 public ConstructorJoinPointGenerator(GeneratedClassAdvisor advisor, JoinPointInfo info) 70 { 71 super(advisor, info); 72 } 73 74 75 protected void initialiseJoinPointNames() 76 { 77 joinpointClassName = getInfoClassName( 78 classSimpleName(), 79 index()); 80 81 joinpointFieldName = getInfoFieldName( 82 classSimpleName(), 83 index()); 84 } 85 86 private String classSimpleName() 87 { 88 Constructor ctor = ((ConstructorInfo)info).getConstructor(); 89 return Advisor.getSimpleName(ctor.getDeclaringClass()); 90 } 91 92 private int index() 93 { 94 return ((ConstructorInfo)info).getIndex(); 95 } 96 97 protected boolean isVoid() 98 { 99 return false; 100 } 101 102 protected Class getReturnType() 103 { 104 return ((ConstructorInfo)super.info).getConstructor().getDeclaringClass(); 105 } 106 107 protected AdviceMethodProperties getAdviceMethodProperties(AdviceSetup setup) 108 { 109 Constructor ctor = ((ConstructorInfo)info).getConstructor(); 110 return new AdviceMethodProperties( 111 setup.getAspectClass(), 112 setup.getAdviceName(), 113 info.getClass(), 114 INVOCATION_TYPE, 115 ctor.getDeclaringClass(), 116 ctor.getParameterTypes(), 117 ctor.getExceptionTypes()); 118 } 119 120 protected boolean hasTargetObject() 121 { 122 return false; 123 } 124 125 protected static CtClass createJoinpointBaseClass( 126 GeneratedAdvisorInstrumentor instrumentor, 127 CtClass advisedClass, 128 CtConstructor advisedCtor, 129 String ciname, 130 int index)throws NotFoundException, CannotCompileException 131 { 132 instrumentor.addJoinPointGeneratorFieldToGenAdvisor( 133 getJoinPointGeneratorFieldName(advisedClass.getSimpleName(), index)); 134 135 BaseClassGenerator generator = new BaseClassGenerator(instrumentor, advisedClass, advisedCtor, ciname, index); 136 return generator.generate(); 137 } 138 139 protected String getJoinPointGeneratorFieldName() 140 { 141 return getJoinPointGeneratorFieldName(classSimpleName(), index()); 142 } 143 144 protected static String getInfoFieldName(String className, int index) 145 { 146 return JOINPOINT_FIELD_PREFIX + className + "_" + index; 147 } 148 149 private static String getInfoClassName(String className, int index) 150 { 151 return JOINPOINT_CLASS_PREFIX + className + "_" + index; 152 } 153 154 protected static String getJoinPointGeneratorFieldName(String className, int index) 155 { 156 return GENERATOR_PREFIX + className + "_" + index; 157 } 158 159 private static class BaseClassGenerator 160 { 161 GeneratedAdvisorInstrumentor instrumentor; 162 CtClass advisedClass; 163 CtConstructor advisedCtor; 164 String ciname; 165 int index; 166 167 CtClass jp; 168 CtMethod invokeJoinpointMethod; 169 CtConstructor publicConstructor; 170 CtConstructor protectedConstructor; 171 CtField targetField; 172 CtClass[] params; 173 CtClass constructorInfoClass; 174 175 BaseClassGenerator( 176 GeneratedAdvisorInstrumentor instrumentor, 177 CtClass advisedClass, 178 CtConstructor advisedCtor, 179 String ciname, 180 int index) throws NotFoundException 181 { 182 this.instrumentor = instrumentor; 183 this.advisedClass = advisedClass; 184 this.advisedCtor = advisedCtor; 185 this.ciname = ciname; 186 this.index = index; 187 this.params = advisedCtor.getParameterTypes(); 188 constructorInfoClass = instrumentor.forName(ConstructorExecutionTransformer.CONSTRUCTOR_INFO_CLASS_NAME); 189 } 190 191 protected CtClass generate() throws CannotCompileException, NotFoundException 192 { 193 jp = setupClass(); 194 addArgumentsFieldsAndAccessors(); 195 addInvokeJoinpointMethod(); 196 addMethodInfoField(); 197 addPublicConstructor(); 198 addProtectedConstructor(); 199 addDispatchMethods(); 200 201 TransformerCommon.compileOrLoadClass(advisedClass, jp); 202 return jp; 203 } 204 205 206 private CtClass setupClass()throws NotFoundException, CannotCompileException 207 { 208 String className = getInfoClassName(advisedClass.getSimpleName(), index); 209 210 jp = TransformerCommon.makeNestedClass(advisedClass, className, true, Modifier.PUBLIC | Modifier.STATIC, INVOCATION_CT_TYPE); 212 addUntransformableInterface(instrumentor, jp); 213 return jp; 214 } 215 216 private void addArgumentsFieldsAndAccessors() throws NotFoundException, CannotCompileException 217 { 218 OptimizedBehaviourInvocations.addArgumentFieldsToInvocation(jp, params); 219 OptimizedBehaviourInvocations.addSetArguments(instrumentor.getClassPool(), jp, params); 220 OptimizedBehaviourInvocations.addGetArguments(instrumentor.getClassPool(), jp, params); 221 } 222 223 228 private void addPublicConstructor() throws CannotCompileException 229 { 230 publicConstructor = CtNewConstructor.make( 231 new CtClass[] {constructorInfoClass}, 232 new CtClass[0], 233 "{super($1, $1.getInterceptors()); this." + INFO_FIELD + " = $1;}", 234 jp); 235 236 jp.addConstructor(publicConstructor); 237 } 238 239 243 protected void addProtectedConstructor() throws CannotCompileException 244 { 245 CtClass[] ctorParams = new CtClass[params.length + 1]; 246 ctorParams[0] = jp; 247 System.arraycopy(params, 0, ctorParams, 1, params.length); 248 249 StringBuffer body = new StringBuffer (); 250 body.append("{"); 251 body.append(" this($1." + INFO_FIELD + ");"); 252 253 int offset = 1; 254 for (int i = offset ; i < ctorParams.length ; i++) 255 { 256 body.append(" arg" + (i - offset) + " = $" + (i + 1) + ";"); 257 } 258 259 body.append("}"); 260 protectedConstructor = CtNewConstructor.make( 261 ctorParams, 262 new CtClass[0], 263 body.toString(), 264 jp); 265 protectedConstructor.setModifiers(Modifier.PROTECTED); 266 jp.addConstructor(protectedConstructor); 267 268 } 269 270 274 private CtMethod addInvokeJoinpointMethod() throws CannotCompileException, NotFoundException 275 { 276 invokeJoinpointMethod = CtNewMethod.make( 277 advisedClass, 278 INVOKE_JOINPOINT, 279 params, 280 advisedCtor.getExceptionTypes(), 281 null, 282 jp); 283 invokeJoinpointMethod.setModifiers(Modifier.PROTECTED); 284 jp.addMethod(invokeJoinpointMethod); 285 return invokeJoinpointMethod; 286 } 287 288 private void addMethodInfoField()throws CannotCompileException 289 { 290 CtField infoField = new CtField(constructorInfoClass, INFO_FIELD, jp); 291 infoField.setModifiers(javassist.Modifier.PROTECTED); jp.addField(infoField); 293 } 294 295 private void addDispatchMethods() throws CannotCompileException, NotFoundException 296 { 297 addInvokeNextDispatchMethod(); 298 299 if (params.length > 0) 300 { 301 addInvokeJoinPointDispatchMethod(); 302 } 303 304 addInvokeTargetMethod(); 305 } 306 307 private void addInvokeNextDispatchMethod() throws CannotCompileException, NotFoundException 308 { 309 StringBuffer parameters = new StringBuffer ("("); 311 for (int i = 0 ; i < params.length ; i++) 312 { 313 if (i > 0)parameters.append(", "); 314 parameters.append("arg" + i); 315 } 316 parameters.append(")"); 317 318 String body = 319 "{" + 320 " " + advisedClass.getName() + " obj = new " + advisedClass.getName() + parameters + ";" + 321 " setTargetObject(obj);" + 322 " return obj;" + 323 "}"; 324 325 try 326 { 327 CtMethod dispatch = CtNewMethod.make( 328 advisedClass, 329 JoinPointGenerator.DISPATCH, 330 new CtClass[0], 331 advisedCtor.getExceptionTypes(), 332 body, 333 jp); 334 dispatch.setModifiers(Modifier.PROTECTED); 335 jp.addMethod(dispatch); 336 } 337 catch (CannotCompileException e) 338 { 339 throw new RuntimeException ("Could not compile code " + body + " for method " + getMethodString(jp, JoinPointGenerator.DISPATCH, params), e); 340 } 341 } 342 343 private void addInvokeJoinPointDispatchMethod() throws CannotCompileException, NotFoundException 344 { 345 347 String body = 348 "{" + 349 " " + advisedClass.getName() + " obj = new " + advisedClass.getName() + "($$);" + 350 " setTargetObject(obj);" + 351 " return obj;" + 352 "}"; 353 354 try 355 { 356 CtMethod dispatch = CtNewMethod.make( 357 advisedClass, 358 JoinPointGenerator.DISPATCH, 359 params, 360 advisedCtor.getExceptionTypes(), 361 body, 362 jp); 363 dispatch.setModifiers(Modifier.PROTECTED); 364 jp.addMethod(dispatch); 365 } 366 catch (CannotCompileException e) 367 { 368 throw new RuntimeException ("Could not compile code " + body + " for method " + getMethodString(jp, JoinPointGenerator.DISPATCH, params), e); 369 } 370 } 371 372 private void addInvokeTargetMethod() throws CannotCompileException, NotFoundException 373 { 374 CtMethod template = INVOCATION_CT_TYPE.getDeclaredMethod(INVOKE_TARGET); 375 376 String body = "{return dispatch();}"; 377 378 CtMethod invokeTarget = CtNewMethod.make( 379 template.getReturnType(), 380 template.getName(), 381 template.getParameterTypes(), 382 template.getExceptionTypes(), 383 body, 384 jp); 385 jp.addMethod(invokeTarget); 386 } 387 388 } 389 } 390 | Popular Tags |