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