1 22 package org.jboss.aop.instrument; 23 24 import java.util.Collection ; 25 import java.util.Iterator ; 26 import java.util.List ; 27 28 import javassist.CannotCompileException; 29 import javassist.CtClass; 30 import javassist.CtConstructor; 31 import javassist.CtField; 32 import javassist.CtMember; 33 import javassist.CtMethod; 34 import javassist.CtNewMethod; 35 import javassist.Modifier; 36 import javassist.NotFoundException; 37 38 import org.jboss.aop.ClassAdvisor; 39 import org.jboss.aop.pointcut.Pointcut; 40 41 47 public abstract class ConstructorExecutionTransformer implements CodeConversionObserver 48 { 49 protected static final String CONSTRUCTOR_INFO_CLASS_NAME = "org.jboss.aop.ConstructorInfo"; 50 51 protected Instrumentor instrumentor; 52 protected Codifier codifier; 53 private JoinpointClassifier classifier; 54 private static final WrapperTransformer wrapper = 56 new WrapperTransformer(new String []{"wrapperStatus", "constructorsWrapped"}); 57 protected static final int CONSTRUCTOR_STATUS = 0; 58 private static final int ALL_CONSTRUCTORS_STATUS = 1; 59 60 protected ConstructorExecutionTransformer(Instrumentor instrumentor) 61 { 62 this.instrumentor = instrumentor; 63 this.codifier = new Codifier(); 64 this.classifier = instrumentor.joinpointClassifier; 65 } 67 68 protected Instrumentor getInstrumentor() 69 { 70 return instrumentor; 71 } 72 73 protected WrapperTransformer getWrapper() 74 { 75 return wrapper; 76 } 77 78 public static String constructorFactory(String className) 79 { 80 if (className.indexOf('.') >= 0)throw new RuntimeException ("constructorFactory() takes a simple class name: " + className); 81 return className + "_new_" + ClassAdvisor.NOT_TRANSFORMABLE_SUFFIX; 82 } 83 84 87 protected String addConstructorInfoField(int modifiers, CtClass addTo, String infoName) throws NotFoundException, CannotCompileException 88 { 89 return addConstructorInfoField(modifiers, addTo, infoName, null); 90 } 91 92 95 protected String addConstructorInfoField(int modifiers, CtClass addTo, String infoName, CtField.Initializer init) throws NotFoundException, CannotCompileException 96 { 97 if (instrumentor.getClassPool() != null) 100 { 101 try 102 { 103 addTo.getDeclaredField(infoName); 104 return infoName; 105 } 106 catch(NotFoundException e) 107 { 108 } 109 TransformerCommon.addInfoField(instrumentor, CONSTRUCTOR_INFO_CLASS_NAME, infoName, modifiers, addTo, addInfoAsWeakReference(), init); 110 111 } 112 return infoName; 113 } 114 115 protected boolean addInfoAsWeakReference() 116 { 117 return true; 118 } 119 120 public static String getConstructorInfoFieldName(String classname, int index) 121 { 122 if (classname.indexOf('.') >= 0)throw new RuntimeException ("Simple name should be used: " + classname); 123 return "aop$constructorInfo_" + index; 124 } 125 126 protected static String constructorInfoFromWeakReference(String localName, String ctorInfoName) 127 { 128 return TransformerCommon.infoFromWeakReference(CONSTRUCTOR_INFO_CLASS_NAME, localName, ctorInfoName); 129 } 130 131 138 public boolean transform(CtClass clazz, ClassAdvisor classAdvisor) throws Exception 139 { 140 List constructors = instrumentor.getConstructors(clazz); 141 JoinpointClassification[] classification = classifyConstructor(constructors, classAdvisor); 142 boolean wrappersGenerated = false; 143 boolean oneOrMoreWrapped = false; 144 int i = 0; 145 boolean dynamicallyWrapped = false; 146 boolean notDynamicallyWrapped = false; 147 CtConstructor firstConstructor = null; 148 if (!constructors.isEmpty()) 149 { 150 firstConstructor = (CtConstructor) constructors.get(0); 151 } 152 for (Iterator iterator = constructors.iterator(); iterator.hasNext(); i++) 153 { 154 CtConstructor constructor = (CtConstructor) iterator.next(); 155 if (classification[i] == JoinpointClassification.NOT_INSTRUMENTED 156 && !oneOrMoreWrapped) 157 { 158 continue; 159 } 160 else if (!wrappersGenerated) 161 { 162 buildConstructorWrappers(clazz, classAdvisor); 164 wrappersGenerated = true; 165 wrapper.prepareForWrapping(firstConstructor, ALL_CONSTRUCTORS_STATUS); 166 } 167 168 if (classification[i].equals(JoinpointClassification.WRAPPED)) 169 { 170 if (!oneOrMoreWrapped) 171 { 172 for (int j = 0; j < i; j++) 173 { 174 this.setEmptyWrapperCodeLater((CtConstructor) constructors.get(j)); 175 } 176 oneOrMoreWrapped = true; 177 } 178 wrap(clazz, constructor, i); 179 dynamicallyWrapped = dynamicallyWrapped || classification[i].equals(JoinpointClassification.DYNAMICALY_WRAPPED); 180 notDynamicallyWrapped = notDynamicallyWrapped || !classification[i].equals(JoinpointClassification.DYNAMICALY_WRAPPED); 181 } 182 else if (oneOrMoreWrapped) 183 { 184 this.setEmptyWrapperCodeLater(constructor); 185 } 186 } 187 188 if (oneOrMoreWrapped) 189 { 190 wrapAllConstructors(clazz, firstConstructor, null); 191 } 192 if (dynamicallyWrapped && !notDynamicallyWrapped) 193 { 194 instrumentor.dynamicTransformationObserver.constructorDynamicalyWrapped(); 195 } 196 return wrappersGenerated; 197 } 198 199 200 214 private void wrapAllConstructors(final CtClass clazz, CtConstructor firstConstructor, List constructors) throws NotFoundException, CannotCompileException 215 { 216 wrapper.wrap(firstConstructor, ALL_CONSTRUCTORS_STATUS); 217 if (constructors == null) 218 { 219 return; 220 } 221 for (Iterator i = constructors.iterator(); i.hasNext();) 222 { 223 CtConstructor constructor = (CtConstructor) i.next(); 224 if (!wrapper.isWrapped(constructor, CONSTRUCTOR_STATUS)) 225 { 226 setEmptyWrapperCodeLater(constructor); 227 } 228 } 229 instrumentor.converter.replaceNew(clazz, clazz, constructorFactory(clazz.getSimpleName())); 230 } 231 232 238 public void wrap(CtClass clazz, Collection constructorIndexes) throws Exception 239 { 240 List constructors = instrumentor.getConstructors(clazz); 241 CtConstructor firstConstructor = (CtConstructor) constructors.get(0); 243 if (wrapper.isNotPrepared(firstConstructor , ALL_CONSTRUCTORS_STATUS)) 244 { 245 return; 246 } 247 for (Iterator iterator = constructorIndexes.iterator(); iterator.hasNext(); ) 249 { 250 int constructorIndex = ((Integer ) iterator.next()).intValue(); 251 CtConstructor constructor = (CtConstructor) constructors.get(constructorIndex); 252 wrap(clazz, constructor, constructorIndex); 253 } 254 if (!wrapper.isWrapped(firstConstructor, ALL_CONSTRUCTORS_STATUS)) 257 { 258 wrapAllConstructors(clazz, firstConstructor, constructors); 259 } 260 } 261 262 268 private void wrap(CtClass clazz, CtConstructor constructor, int constructorIndex) throws NotFoundException, Exception , CannotCompileException 269 { 270 if (wrapper.isNotPrepared(constructor, CONSTRUCTOR_STATUS)) 272 { 273 return; 274 } 275 wrapper.wrap(constructor, CONSTRUCTOR_STATUS); 277 CtMethod wrapperMethod = clazz.getDeclaredMethod(constructorFactory(clazz.getSimpleName()), constructor.getParameterTypes()); 279 setTemporaryWrapperCode(constructor.getDeclaringClass(), wrapperMethod); 280 ConstructorTransformation trans = new ConstructorTransformation(clazz, constructor, wrapperMethod, constructorIndex); 281 createWrapper(trans); 282 } 283 284 290 public void unwrap(CtClass clazz, Collection constructorIndexes) throws NotFoundException 291 { 292 List constructors = instrumentor.getConstructors(clazz); 293 if (wrapper.isNotPrepared((CtMember) constructors.get(0), ALL_CONSTRUCTORS_STATUS)) 295 { 296 return; 297 } 298 for (Iterator iterator = constructorIndexes.iterator(); iterator.hasNext(); ) 299 { 300 int constructorIndex = ((Integer ) iterator.next()).intValue(); 301 CtConstructor constructor = (CtConstructor) constructors.get(constructorIndex); 302 if (wrapper.isNotPrepared(constructor, CONSTRUCTOR_STATUS)) 303 { 304 continue; 305 } 306 wrapper.unwrap(constructor, CONSTRUCTOR_STATUS); 308 310 setEmptyWrapperCode(constructor); 311 } 312 } 313 314 317 public void codeConverted() throws CannotCompileException 318 { 319 this.codifier.codifyPending(); 320 } 321 322 public boolean replaceConstructorAccess(ClassAdvisor sourceAdvisor, CtClass source) throws NotFoundException 323 { 324 if (!isAnyConstructorAdvised(source, sourceAdvisor)) 325 { 326 return false; 327 } 328 instrumentor.converter.replaceNew(source, source, constructorFactory(source.getSimpleName())); 329 return true; 330 } 331 332 protected void buildConstructorWrappers(CtClass clazz, ClassAdvisor advisor) 334 throws Exception 335 { 336 instrumentor.setupBasics(clazz); 337 List constructors = instrumentor.getConstructors(clazz); 338 339 Iterator it = constructors.iterator(); 340 for (int index = 0; it.hasNext(); index++) 341 { 342 CtConstructor constructor = (CtConstructor) it.next(); 344 int mod = Modifier.STATIC; 345 if ((constructor.getModifiers() & Modifier.PUBLIC) != 0) 346 { 347 mod |= Modifier.PUBLIC; 348 } 349 else if ((constructor.getModifiers() & Modifier.PROTECTED) != 0) 350 { 351 mod |= Modifier.PROTECTED; 352 } 353 else if ((constructor.getModifiers() & Modifier.PRIVATE) != 0) 354 { 355 mod |= Modifier.PRIVATE; 356 } 357 else 358 { 359 mod |= Modifier.PUBLIC; 360 } 361 362 initialiseWrapper(mod, constructor, index); 363 generateConstructorInfoField(clazz, constructor, index); 364 } 365 } 366 367 protected void generateConstructorInfoField(CtClass clazz, CtConstructor constructor, int index) throws CannotCompileException, NotFoundException 368 { 369 String name = getConstructorInfoFieldName(clazz.getSimpleName(), index); 370 addConstructorInfoField(Modifier.PRIVATE | Modifier.STATIC, clazz, name); 371 } 372 373 379 protected void setTemporaryWrapperCode(CtClass type, CtMethod wrapperMethod) 380 { 381 String code = "{" + 382 " return null;" + 383 "}"; 384 try 385 { 386 wrapperMethod.setBody(code); 387 } 388 catch (CannotCompileException e) 389 { 390 System.out.println(code); 391 throw new RuntimeException (e); } 393 } 394 395 401 protected void setEmptyWrapperCode(CtConstructor constructor)throws NotFoundException 402 { 403 CtMethod wrapperMethod = getWrapperMethod(constructor); 404 String code = 405 "{ " + 406 " return new " + constructor.getDeclaringClass().getName() + "($$); " + 407 "}"; 408 try 409 { 410 wrapperMethod.setBody(code); 411 } 412 catch (CannotCompileException e) 413 { 414 System.out.println(code); 415 throw new RuntimeException (e); } 417 } 418 419 426 protected void setEmptyWrapperCodeLater(CtConstructor constructor) throws NotFoundException 427 { 428 CtMethod wrapperMethod = getWrapperMethod(constructor); 429 String code = 430 "{ " + 431 " return new " + constructor.getDeclaringClass().getName() + "($$); " + 432 "}"; 433 this.codifier.addPendingCode(wrapperMethod, code); 434 } 435 436 437 444 protected boolean isAnyConstructorAdvised(CtClass clazz, ClassAdvisor advisor) throws NotFoundException 445 { 446 CtConstructor[] constructors = clazz.getDeclaredConstructors(); 447 for (int i = 0; i < constructors.length; i++) 448 { 449 JoinpointClassification classification = classifier.classifyConstructorExecution(constructors[i], advisor); 450 if (classification.equals(JoinpointClassification.WRAPPED)) 451 return true; 452 } 453 return false; 454 } 455 456 public static boolean isAdvisableConstructor(CtConstructor con, ClassAdvisor advisor) throws NotFoundException 458 { 459 Iterator pointcuts = advisor.getManager().getPointcuts().values().iterator(); 460 while (pointcuts.hasNext()) 461 { 462 Pointcut pointcut = (Pointcut) pointcuts.next(); 463 if (pointcut.matchesExecution(advisor, con)) 464 { 465 return true; 466 } 467 } 468 return false; 469 } 470 471 477 protected JoinpointClassification[] classifyConstructor(List constructors, ClassAdvisor advisor) throws NotFoundException 478 { 479 JoinpointClassification[] classification = new JoinpointClassification[constructors.size()]; 480 int index = 0; 481 for (Iterator iterator = constructors.iterator(); iterator.hasNext(); index++) 482 { 483 CtConstructor constructor = (CtConstructor) iterator.next(); 484 classification[index] = classifier.classifyConstructorExecution(constructor, advisor); 485 } 486 return classification; 487 } 488 489 protected abstract void createWrapper(ConstructorTransformation trans) throws CannotCompileException, NotFoundException; 490 491 protected void initialiseWrapper(int mod, CtConstructor constructor, int index) throws NotFoundException, CannotCompileException 492 { 493 CtClass clazz = constructor.getDeclaringClass(); 494 CtClass[] exceptions = constructor.getExceptionTypes(); 495 String name = clazz.getSimpleName(); 496 CtClass type = constructor.getDeclaringClass(); 497 498 CtMethod wmethod = CtNewMethod.make(type, constructorFactory(name), constructor.getParameterTypes(), exceptions, null, clazz); 499 wmethod.setModifiers(mod); 500 setTemporaryWrapperCode(type, wmethod); 501 clazz.addMethod(wmethod); 502 503 getWrapper().prepareForWrapping(constructor, CONSTRUCTOR_STATUS); 505 } 506 507 protected CtMethod getWrapperMethod(CtConstructor constructor) throws NotFoundException 508 { 509 CtClass clazz = constructor.getDeclaringClass(); 510 return clazz.getDeclaredMethod( 511 constructorFactory(clazz.getSimpleName()), 512 constructor.getParameterTypes()); 513 } 514 515 protected class ConstructorTransformation 516 { 517 CtClass clazz; 518 CtConstructor constructor; 519 CtMethod wrapperMethod; 520 int index; 521 522 public ConstructorTransformation(CtClass clazz, CtConstructor constructor, CtMethod wrapper, int index) 523 { 524 this.clazz = clazz; 525 this.constructor = constructor; 526 this.wrapperMethod = wrapper; 527 this.index = index; 528 } 529 530 public CtMethod getWrapperMethod() 531 { 532 return wrapperMethod; 533 } 534 535 public void setWrapperMethod(CtMethod wrapperMethod) 536 { 537 this.wrapperMethod = wrapperMethod; 538 } 539 540 public CtClass getClazz() 541 { 542 return clazz; 543 } 544 545 public CtConstructor getConstructor() 546 { 547 return constructor; 548 } 549 550 public int getIndex() 551 { 552 return index; 553 } 554 555 public String getClassName() 556 { 557 return clazz.getName(); 558 } 559 560 public String getSimpleName() 561 { 562 return clazz.getSimpleName(); 563 } 564 } 565 } | Popular Tags |