1 22 package org.jboss.aop.instrument; 23 24 import java.util.ArrayList ; 25 import java.util.Collection ; 26 import java.util.Collections ; 27 import java.util.HashMap ; 28 import java.util.HashSet ; 29 import java.util.Iterator ; 30 import java.util.List ; 31 import java.util.Map ; 32 import org.jboss.aop.Advised; 33 import org.jboss.aop.Advisor; 34 import org.jboss.aop.AspectManager; 35 import org.jboss.aop.ClassAdvisor; 36 import org.jboss.aop.annotation.compiler.AnnotationInfoCreator; 37 import org.jboss.aop.classpool.AOPClassPool; 38 import org.jboss.aop.classpool.AOPClassPoolRepository; 39 import org.jboss.aop.introduction.AnnotationIntroduction; 40 import org.jboss.aop.introduction.InterfaceIntroduction; 41 import org.jboss.aop.util.Advisable; 42 import org.jboss.aop.util.CtConstructorComparator; 43 import org.jboss.aop.util.CtFieldComparator; 44 import org.jboss.aop.util.JavassistMethodHashing; 45 import javassist.CannotCompileException; 46 import javassist.ClassPool; 47 import javassist.CodeConverter; 48 import javassist.CtClass; 49 import javassist.CtConstructor; 50 import javassist.CtField; 51 import javassist.CtMethod; 52 import javassist.CtNewMethod; 53 import javassist.Modifier; 54 import javassist.NotFoundException; 55 import javassist.SerialVersionUID; 56 import javassist.bytecode.AnnotationsAttribute; 57 import javassist.bytecode.FieldInfo; 58 import javassist.bytecode.MethodInfo; 59 60 78 public abstract class Instrumentor 79 { 80 83 public static final String AOP_PACKAGE = 84 Advised.class.getPackage().getName(); 85 86 89 public static final String ASPECT_MANAGER_CLASS_NAME = 90 AOP_PACKAGE + ".AspectManager"; 91 92 95 public static final String HELPER_FIELD_NAME = "aop$classAdvisor" + ClassAdvisor.NOT_TRANSFORMABLE_SUFFIX; 96 97 protected AOPClassPool classPool; 98 protected boolean basicsSet = false; 99 100 101 protected CodeConverter converter; 102 protected AspectManager manager; 103 protected JoinpointClassifier joinpointClassifier; 104 protected static Collection processedClasses = new ArrayList (); 105 106 MethodExecutionTransformer methodExecutionTransformer; 108 ConstructorExecutionTransformer constructorExecutionTransformer; 109 ConstructionTransformer constructionTransformer; 110 FieldAccessTransformer fieldAccessTransformer; 111 CallerTransformer callerTransformer; 112 DynamicTransformationObserver dynamicTransformationObserver; 113 114 120 protected Instrumentor(AOPClassPool pool, 121 AspectManager manager, 122 JoinpointClassifier joinpointClassifier, 123 DynamicTransformationObserver observer) 124 { 125 this.classPool = pool; 126 this.converter = new CodeConverter(); 127 this.manager = manager; 128 this.joinpointClassifier = joinpointClassifier; 129 this.dynamicTransformationObserver = observer; 130 intitialiseTransformers(); 131 } 132 133 protected Instrumentor(AspectManager manager, 134 JoinpointClassifier joinpointClassifier) 135 { 136 this(null, 137 manager, 138 joinpointClassifier, 139 null); 140 } 141 142 protected abstract void intitialiseTransformers(); 143 144 public ClassPool getClassPool() 145 { 146 return classPool; 147 } 148 149 CodeConverter getCodeConverter() 150 { 151 return converter; 152 } 153 154 public boolean isAdvised(CtClass clazz) throws NotFoundException 155 { 156 CtClass[] interfaces = clazz.getInterfaces(); 157 CtClass advised = forName(AOP_PACKAGE + ".Advised"); 158 for (int i = 0; i < interfaces.length; i++) 159 { 160 if (interfaces[i].equals(advised)) return true; 161 if (interfaces[i].getName().equals(AOP_PACKAGE + ".Advised")) return true; 162 } 163 return false; 164 } 165 166 public static boolean implementsAdvised(CtClass clazz) throws NotFoundException 167 { 168 CtClass[] interfaces = clazz.getInterfaces(); 169 for (int i = 0; i < interfaces.length; i++) 170 { 171 if (interfaces[i].getName().equals(AOP_PACKAGE + ".Advised")) return true; 172 } 173 return false; 174 } 175 176 177 public static boolean isTransformable(CtClass clazz) throws NotFoundException 178 { 179 CtClass[] interfaces = clazz.getInterfaces(); 180 for (int i = 0; i < interfaces.length; i++) 182 { 183 if (interfaces[i].getName().equals(AOP_PACKAGE + ".instrument.Untransformable")) return false; 185 } 186 return true; 187 } 188 189 protected boolean isBaseClass(CtClass clazz) 190 throws NotFoundException 191 { 192 if (clazz.getSuperclass() != null) 193 { 194 return !isAdvised(clazz.getSuperclass()); 195 } 196 return true; 197 } 198 199 200 protected static String mixinFieldName(CtClass mixinClass) 201 { 202 StringBuffer buf = new StringBuffer ("_"); 203 buf.append(mixinClass.getName().replace('.', '$')); 204 buf.append("$aop$mixin"); 205 return buf.toString(); 206 } 207 208 private void addMixinMethod(Advisor advisor, CtMethod method, CtClass clazz, CtMethod delegate, long hash) throws Exception 209 { 210 CtClass[] exceptions = method.getExceptionTypes(); 211 212 CtMethod newMethod = CtNewMethod.wrapped(method.getReturnType(), 214 method.getName(), 215 method.getParameterTypes(), 216 exceptions, 217 delegate, 218 CtMethod.ConstParameter.integer(hash), 219 clazz); 220 newMethod.setModifiers(Modifier.PUBLIC); 221 clazz.addMethod(newMethod); 222 } 223 224 private void addMixin(CtClass clazz, InterfaceIntroduction pointcut, InterfaceIntroduction.Mixin mixin, HashMap baseMethods) throws Exception 225 { 226 CtClass mixinClass = classPool.get(mixin.getClassName()); 233 String initializer = (mixin.getConstruction() == null) ? ("new " + mixinClass.getName() + "()") : mixin.getConstruction(); 234 CtClass type = forName(mixinClass.getName()); 235 CtField field = new CtField(type, mixinFieldName(mixinClass), clazz); 236 int modifiers = Modifier.PRIVATE; 237 if (mixin.isTransient()) modifiers = modifiers | Modifier.TRANSIENT; 238 field.setModifiers(modifiers); 239 clazz.addField(field, CtField.Initializer.byExpr(initializer)); 240 HashSet addedMethods = new HashSet (); 241 242 String [] interfaces = mixin.getInterfaces(); 243 for (int i = 0; i < interfaces.length; i++) 244 { 245 CtClass intf = classPool.get(interfaces[i]); 246 if (clazz.subtypeOf(intf)) continue; 247 clazz.addInterface(intf); 248 HashMap intfMap = JavassistMethodHashing.getMethodMap(intf); 249 Iterator entries = intfMap.entrySet().iterator(); 250 while (entries.hasNext()) 251 { 252 Map.Entry entry = (Map.Entry ) entries.next(); 253 Long hash = (Long ) entry.getKey(); 254 CtMethod method = (CtMethod) entry.getValue(); 255 CtMethod baseMethod = (CtMethod)baseMethods.get(hash); 256 if (baseMethod != null && !addedMethods.contains(hash)) 257 { 258 String msg = "Mixin " + mixinClass.getName() + 259 " of pointcut " + pointcut.getName() + 260 " is trying to apply an already existing method" + method.getName() + " for class " + clazz.getName(); 261 262 if (baseMethod.getDeclaringClass().equals(clazz)) 263 { 264 throw new RuntimeException (msg); 265 } 266 else 267 { 268 if (AspectManager.verbose)System.out.println("[warn] " + msg); 269 } 270 } 271 if (addedMethods.contains(hash)) continue; 273 createMixinInvokeMethod(clazz, mixinClass, initializer, method, hash.longValue()); 274 baseMethods.put(hash, method); 275 addedMethods.add(hash); 276 } 277 } 278 } 279 280 private void addIntroductionPointcutInterface(CtClass clazz, Advisor advisor, String intf, HashMap baseMethods) throws Exception 281 { 282 CtClass iface = classPool.get(intf); 283 if (clazz.subtypeOf(iface)) return; 284 if (clazz.subclassOf(iface)) return; 285 286 clazz.addInterface(iface); 287 288 CtMethod mixinInvokeMethod = createInvokeMethod(clazz); 289 HashMap intfMap = JavassistMethodHashing.getMethodMap(iface); 290 Iterator entries = intfMap.entrySet().iterator(); 291 while (entries.hasNext()) 292 { 293 Map.Entry entry = (Map.Entry ) entries.next(); 294 Long hash = (Long ) entry.getKey(); 295 if (baseMethods.containsKey(hash)) continue; 296 CtMethod method = (CtMethod) entry.getValue(); 297 addMixinMethod(advisor, method, clazz, mixinInvokeMethod, hash.longValue()); 298 baseMethods.put(hash, method); 299 } 300 } 301 302 private void instrumentIntroductions(CtClass clazz, Advisor advisor) 303 throws Exception 304 { 305 ArrayList pointcuts = advisor.getInterfaceIntroductions(); 306 if (pointcuts.size() == 0) return; 307 HashMap baseMethods = JavassistMethodHashing.getMethodMap(clazz); 308 Iterator it = pointcuts.iterator(); 309 if (it.hasNext()) setupBasics(clazz); 310 while (it.hasNext()) 311 { 312 313 InterfaceIntroduction pointcut = (InterfaceIntroduction) it.next(); 314 ArrayList mixins = pointcut.getMixins(); 315 for (int i = 0; i < mixins.size(); i++) 316 { 317 InterfaceIntroduction.Mixin mixin = (InterfaceIntroduction.Mixin) mixins.get(i); 318 addMixin(clazz, pointcut, mixin, baseMethods); 319 } 320 } 321 322 it = pointcuts.iterator(); 325 while (it.hasNext()) 326 { 327 InterfaceIntroduction pointcut = (InterfaceIntroduction) it.next(); 328 String [] interfaces = pointcut.getInterfaces(); 329 if (interfaces == null) continue; 330 for (int i = 0; i < interfaces.length; i++) 331 { 332 addIntroductionPointcutInterface(clazz, advisor, interfaces[i], baseMethods); 333 } 334 } 335 } 336 337 private boolean instrumentAnnotationIntroductions(CtClass clazz, ClassAdvisor advisor) 338 throws Exception 339 { 340 boolean changed = false; 341 Iterator it = advisor.getManager().getAnnotationIntroductions().iterator(); 342 while (it.hasNext()) 343 { 344 AnnotationIntroduction introduction = (AnnotationIntroduction) it.next(); 345 if (AspectManager.verbose) System.out.println("**** " + introduction.getOriginalAnnotationExpr() + " invisible: " + introduction.isInvisible() + " expr: " + introduction.getOriginalExpression()); 346 if (introduction.matches(advisor, clazz)) 347 { 348 if (AspectManager.verbose) System.out.println(introduction.getAnnotation() + " binds to " + clazz.getName()); 349 javassist.bytecode.annotation.Annotation info = AnnotationInfoCreator.createAnnotationInfo(classPool, clazz.getClassFile2().getConstPool(), introduction.getAnnotation()); 350 if (introduction.isInvisible()) 351 { 352 AnnotationsAttribute invisible = (AnnotationsAttribute) clazz.getClassFile2().getAttribute(AnnotationsAttribute.invisibleTag); 353 if (invisible == null) 354 { 355 invisible = new AnnotationsAttribute(clazz.getClassFile2().getConstPool(), AnnotationsAttribute.invisibleTag); 356 clazz.getClassFile2().addAttribute(invisible); 357 } 358 changed = true; 359 invisible.addAnnotation(info); 360 } 361 else 362 { 363 AnnotationsAttribute visible = (AnnotationsAttribute) clazz.getClassFile2().getAttribute(AnnotationsAttribute.visibleTag); 364 if (visible == null) 365 { 366 visible = new AnnotationsAttribute(clazz.getClassFile2().getConstPool(), AnnotationsAttribute.visibleTag); 367 clazz.getClassFile2().addAttribute(visible); 368 } 369 changed = true; 370 visible.addAnnotation(info); 371 } 372 } 373 374 CtMethod[] methods = clazz.getDeclaredMethods(); 375 for (int i = 0; i < methods.length; i++) 376 { 377 if (introduction.matches(advisor, methods[i])) 378 { 379 javassist.bytecode.annotation.Annotation info = AnnotationInfoCreator.createAnnotationInfo(classPool, methods[i].getMethodInfo2().getConstPool(), introduction.getAnnotation()); 380 MethodInfo mi = methods[i].getMethodInfo2(); 381 if (introduction.isInvisible()) 382 { 383 AnnotationsAttribute invisible = (AnnotationsAttribute) mi.getAttribute(AnnotationsAttribute.invisibleTag); 384 if (invisible == null) 385 { 386 invisible = new AnnotationsAttribute(mi.getConstPool(), AnnotationsAttribute.invisibleTag); 387 mi.addAttribute(invisible); 388 } 389 changed = true; 390 invisible.addAnnotation(info); 391 } 392 else 393 { 394 AnnotationsAttribute visible = (AnnotationsAttribute) mi.getAttribute(AnnotationsAttribute.visibleTag); 395 if (visible == null) 396 { 397 visible = new AnnotationsAttribute(mi.getConstPool(), AnnotationsAttribute.visibleTag); 398 mi.addAttribute(visible); 399 } 400 changed = true; 401 visible.addAnnotation(info); 402 } 403 } 404 405 } 406 407 CtConstructor[] cons = clazz.getDeclaredConstructors(); 408 for (int i = 0; i < cons.length; i++) 409 { 410 if (introduction.matches(advisor, cons[i])) 411 { 412 javassist.bytecode.annotation.Annotation info = AnnotationInfoCreator.createAnnotationInfo(classPool, cons[i].getMethodInfo2().getConstPool(), introduction.getAnnotation()); 413 MethodInfo mi = cons[i].getMethodInfo2(); 414 if (introduction.isInvisible()) 415 { 416 AnnotationsAttribute invisible = (AnnotationsAttribute) mi.getAttribute(AnnotationsAttribute.invisibleTag); 417 if (invisible == null) 418 { 419 invisible = new AnnotationsAttribute(mi.getConstPool(), AnnotationsAttribute.invisibleTag); 420 mi.addAttribute(invisible); 421 } 422 changed = true; 423 invisible.addAnnotation(info); 424 } 425 else 426 { 427 AnnotationsAttribute visible = (AnnotationsAttribute) mi.getAttribute(AnnotationsAttribute.visibleTag); 428 if (visible == null) 429 { 430 visible = new AnnotationsAttribute(mi.getConstPool(), AnnotationsAttribute.visibleTag); 431 mi.addAttribute(visible); 432 } 433 changed = true; 434 visible.addAnnotation(info); 435 } 436 } 437 } 438 439 CtField[] fields = clazz.getDeclaredFields(); 440 for (int i = 0; i < fields.length; i++) 441 { 442 if (introduction.matches(advisor, fields[i])) 443 { 444 javassist.bytecode.annotation.Annotation info = AnnotationInfoCreator.createAnnotationInfo(classPool, fields[i].getFieldInfo2().getConstPool(), introduction.getAnnotation()); 445 FieldInfo mi = fields[i].getFieldInfo2(); 446 if (introduction.isInvisible()) 447 { 448 AnnotationsAttribute invisible = (AnnotationsAttribute) mi.getAttribute(AnnotationsAttribute.invisibleTag); 449 if (invisible == null) 450 { 451 invisible = new AnnotationsAttribute(mi.getConstPool(), AnnotationsAttribute.invisibleTag); 452 mi.addAttribute(invisible); 453 } 454 changed = true; 455 invisible.addAnnotation(info); 456 } 457 else 458 { 459 AnnotationsAttribute visible = (AnnotationsAttribute) mi.getAttribute(AnnotationsAttribute.visibleTag); 460 if (visible == null) 461 { 462 visible = new AnnotationsAttribute(mi.getConstPool(), AnnotationsAttribute.visibleTag); 463 mi.addAttribute(visible); 464 } 465 changed = true; 466 visible.addAnnotation(info); 467 } 468 } 469 } 470 } 471 return changed; 472 } 473 474 private boolean instrumentAnnotationOverrides(CtClass clazz, ClassAdvisor advisor) 475 throws Exception 476 { 477 boolean changed = false; 478 Iterator it = advisor.getManager().getAnnotationOverrides().iterator(); 479 while (it.hasNext()) 480 { 481 AnnotationIntroduction introduction = (AnnotationIntroduction) it.next(); 482 if (introduction.matches(advisor, clazz)) 483 { 484 advisor.getAnnotations().addClassAnnotation(introduction.getAnnotation().getIdentifier(), introduction.getOriginalAnnotationExpr()); 485 } 486 487 CtMethod[] methods = clazz.getDeclaredMethods(); 488 for (int i = 0; i < methods.length; i++) 489 { 490 if (introduction.matches(advisor, methods[i])) 491 { 492 advisor.getAnnotations().addAnnotation(methods[i], introduction.getAnnotation().getIdentifier()); 493 } 494 } 495 496 CtConstructor[] cons = clazz.getDeclaredConstructors(); 497 for (int i = 0; i < cons.length; i++) 498 { 499 if (introduction.matches(advisor, cons[i])) 500 { 501 advisor.getAnnotations().addAnnotation(cons[i], introduction.getAnnotation().getIdentifier()); 502 } 503 } 504 505 CtField[] fields = clazz.getDeclaredFields(); 506 for (int i = 0; i < fields.length; i++) 507 { 508 if (introduction.matches(advisor, fields[i])) 509 { 510 advisor.getAnnotations().addAnnotation(fields[i], introduction.getAnnotation().getIdentifier()); 511 } 512 } 513 } 514 return changed; 515 } 516 517 public boolean applyCallerPointcuts(CtClass clazz, ClassAdvisor advisor) throws CannotCompileException 518 { 519 return callerTransformer.applyCallerPointcuts(clazz, advisor); 520 } 521 522 526 protected boolean convertReferences(CtClass clazz) throws Exception 527 { 528 boolean converted = false; 529 String ref = null; 530 try 531 { 532 AOPClassPool pool = AOPClassPool.createAOPClassPool(clazz.getClassPool(), AOPClassPoolRepository.getInstance()); 533 534 Iterator it = clazz.getRefClasses().iterator(); 541 while (it.hasNext()) 542 { 543 ref = (String ) it.next(); 544 if (!manager.convertReference(ref) 545 || manager.isNonAdvisableClassName(ref) 546 || ref.startsWith("java.") 547 || ref.startsWith("javax.") 548 || ref.startsWith("[")) continue; 549 CtClass ctRef = null; 551 try 552 { 553 ctRef = pool.get(ref); 554 } 555 catch (NotFoundException e) 556 { 557 if (AspectManager.suppressReferenceErrors) 558 { 559 System.err.println("[warn] Could not find class " + ref + " that " + clazz.getName() + " references. It may not be in your classpath and you may not be getting field and constructor weaving for this class."); 560 if (AspectManager.verbose) e.printStackTrace(); 561 continue; 562 } 563 else 564 { 565 throw e; 566 } 567 } 568 if (!isTransformable(ctRef)) continue; 569 570 ClassAdvisor advisor = manager.getTempClassAdvisor(ctRef); 571 572 579 if (!manager.shouldSkipFieldAccess(ref) && !ref.equals(clazz.getName())) 580 { 581 List fields = getAdvisableFields(ctRef); 582 if (fieldAccessTransformer.replaceFieldAccess(fields, ctRef, advisor)) 583 { 584 manager.addFieldInterceptionMarker(ref); 586 converted = true; 587 } 588 else 589 { 590 manager.skipFieldAccess(ref); 591 } 592 } 593 if (!manager.shouldSkipConstruction(ref)) 594 { 595 if (constructorExecutionTransformer.replaceConstructorAccess(advisor, ctRef)) 596 { 597 manager.addConstructionInterceptionMarker(ref); 598 converted = true; 599 } 600 else 601 { 602 manager.skipConstruction(ref); 603 } 604 } 605 606 if (!converted) 607 { 608 manager.skipReference(ref); 609 } 610 ref = null; 611 } 612 } 613 catch (Exception ex) 614 { 615 if (ref != null) 616 { 617 throw new TransformationException("Failed to aspectize class " + clazz.getName() + ". Could not find class it references " + ref + " It may not be in your classpath and you may not be getting field and constructor weaving for this class."); 618 } 619 throw ex; 620 } 621 return converted; 622 } 623 624 protected boolean shouldNotTransform(CtClass clazz)throws NotFoundException 625 { 626 return (clazz.isInterface() || 627 clazz.isFrozen() || 628 clazz.isArray() || 629 clazz.getName().startsWith("org.jboss.aop") || 630 isAdvised(clazz) || 631 !isTransformable(clazz)); 632 } 633 634 637 public boolean transform(CtClass clazz, 638 ClassAdvisor advisor) 639 { 640 synchronized(this.processedClasses) 641 { 642 processedClasses.add(clazz); 643 } 644 try 645 { 646 if (shouldNotTransform(clazz)) return false; 647 if (AspectManager.verbose) System.out.println("[trying to transform] " + clazz.getName()); 648 649 DeclareChecker.checkDeclares(manager, clazz, advisor); 650 651 boolean converted = instrumentAnnotationIntroductions(clazz, advisor); 652 converted = instrumentAnnotationOverrides(clazz, advisor) || converted; 653 boolean constructorAccessConverted = false; 654 converted = applyCallerPointcuts(clazz, advisor) || converted; 655 methodExecutionTransformer.instrument(clazz, advisor); 656 boolean constructionTransformation = constructionTransformer.insertConstructionInterception(clazz, advisor); 657 constructorAccessConverted = constructorExecutionTransformer.transform(clazz, advisor); 658 String classname = clazz.getName(); 659 if (constructorAccessConverted) 660 { 661 manager.addConstructionInterceptionMarker(classname); 662 } 663 else 664 { 665 manager.skipConstruction(classname); 666 } 667 converted = converted || constructorAccessConverted; 668 669 instrumentIntroductions(clazz, advisor); 670 671 converted = convertReferences(clazz) || converted; 672 if (converted || basicsSet) 676 { 677 clazz.instrument(converter); 678 } 679 680 fieldAccessTransformer.buildFieldWrappers(clazz, advisor); 683 if (constructorAccessConverted) 684 { 685 constructorExecutionTransformer.codeConverted(); 686 } 687 else 688 { 689 if (manager.shouldSkipFieldAccess(classname)) 690 { 691 manager.skipReference(classname); 692 } 693 } 694 695 696 dynamicTransformationObserver.transformationFinished(clazz, converter); 698 699 if (AspectManager.verbose) System.out.println("[debug] was " + clazz.getName() + " converted: " + (basicsSet || converted)); 700 701 if (basicsSet || converted) 702 { 703 return true; 704 } 705 else 706 { 707 return false; 709 } 710 711 } 712 catch (Throwable e) 713 { 714 if (AspectManager.suppressTransformationErrors) 715 { 716 System.err.println("[warn] AOP Instrumentor failed to transform " + clazz.getName()); 717 e.printStackTrace(); 718 return false; 719 } 720 else 721 { 722 if (e instanceof TransformationException) 723 { 724 throw ((TransformationException) e); 725 } 726 else 727 { 728 e.printStackTrace(); 729 throw new RuntimeException ("failed to transform: " + clazz.getName(), e); 730 } 731 } 732 733 } 734 } 735 736 737 public List getConstructors(CtClass clazz) 738 { 739 List list = new ArrayList (); 740 741 CtConstructor[] constructors = clazz.getDeclaredConstructors(); 742 743 for (int i = 0; i < constructors.length; i++) 744 { 745 list.add(constructors[i]); 746 } 747 Collections.sort(list, CtConstructorComparator.INSTANCE); 748 749 return list; 750 } 751 752 755 public static List getAdvisableFields(CtClass clazz) throws NotFoundException 756 { 757 List list = new ArrayList (); 758 CtField[] fields = clazz.getDeclaredFields(); 759 for (int i = 0; i < fields.length; i++) 760 { 761 if (Advisable.isAdvisable(fields[i])) 762 { 763 list.add(fields[i]); 764 } 765 } 766 Collections.sort(list, CtFieldComparator.INSTANCE); 767 768 return list; 769 } 770 771 774 private CtMethod createInvokeMethod(CtClass clazz) 775 throws CannotCompileException 776 { 777 return CtNewMethod.make("public java.lang.Object invoke(java.lang.Object[] args, long i)" + 778 " throws java.lang.Throwable {" + 779 " return ((org.jboss.aop.ClassAdvisor)this._getAdvisor()).invokeMethod(this, i, args);" + 780 "}", 781 clazz); 782 } 783 784 787 public CtClass forName(String name) throws NotFoundException 788 { 789 return this.classPool.get(name); 790 } 791 792 795 public CtClass forName(ClassPool pool, String name) throws NotFoundException 796 { 797 return pool.get(name); 798 } 799 800 801 804 protected CtField addStaticField(CtClass clazz, String name, String typeName, 805 CtField.Initializer initializer) 806 throws CannotCompileException, NotFoundException 807 { 808 CtClass type = forName(typeName); 809 CtField field = new CtField(type, name, clazz); 810 field.setModifiers(Modifier.PRIVATE | Modifier.STATIC); 811 clazz.addField(field, initializer); 812 813 return field; 814 } 815 816 819 protected CtField addProtectedField(CtClass clazz, String name, String typeName, 820 CtField.Initializer initializer) 821 throws CannotCompileException, NotFoundException 822 { 823 CtClass type = forName(typeName); 824 CtField field = new CtField(type, name, clazz); 825 field.setModifiers(Modifier.PROTECTED | Modifier.TRANSIENT); 826 if (initializer != null) 827 { 828 clazz.addField(field, initializer); 829 } 830 else 831 { 832 clazz.addField(field); 833 } 834 return field; 835 } 836 837 public void setupBasics(CtClass clazz) throws CannotCompileException, NotFoundException 838 { 839 if (basicsSet) return; 840 basicsSet = true; 841 SerialVersionUID.setSerialVersionUID(clazz); 843 844 clazz.addInterface(forName(AOP_PACKAGE + ".Advised")); 846 847 doSetupBasics(clazz); 848 } 849 850 856 public synchronized void interceptorChainsUpdated(Collection joinpointUpdates, HotSwapper hotSwapper) { 857 this.converter = new CodeConverter(); 859 Collection classes = new HashSet (); 861 try { 862 for (Iterator iterator = joinpointUpdates.iterator(); iterator.hasNext(); ) 864 { 865 JoinpointStatusUpdate update = (JoinpointStatusUpdate) iterator.next(); 866 CtClass clazz = update.clazz; 867 JoinpointStatusUpdate.ClassJoinpoints wrapTargets = update.newlyAdvisedJoinpoints; 868 JoinpointStatusUpdate.ClassJoinpoints unwrapTargets = update.newlyUnadvisedJoinpoints; 869 870 clazz.defrost(); 871 fieldAccessTransformer.wrap(clazz, wrapTargets.fieldReads, wrapTargets.fieldWrites); 872 fieldAccessTransformer.unwrap(clazz, unwrapTargets.fieldReads, unwrapTargets.fieldWrites); 873 constructorExecutionTransformer.wrap(clazz, wrapTargets.constructorExecutions); 874 constructorExecutionTransformer.unwrap(clazz, unwrapTargets.constructorExecutions); 875 methodExecutionTransformer.wrap(clazz, wrapTargets.methodExecutions); 876 methodExecutionTransformer.unwrap(clazz, unwrapTargets.methodExecutions); 877 if (!update.isEmpty()) 878 { 879 clazz.instrument(converter); 880 classes.add(clazz); 881 } 882 } 883 Collection classPools = manager.getRegisteredCLs().values(); 886 Collection conversionsRegistered = new HashSet (); 887 synchronized(this.processedClasses) 888 { 889 for (Iterator iterator2 = processedClasses.iterator(); iterator2.hasNext(); ) { 890 891 CtClass clazz = (CtClass) iterator2.next(); 892 if (manager.isNonAdvisableClassName(clazz.getName()) || ! isTransformable(clazz)) 893 { 894 continue; 895 } 896 if (classes.contains(clazz)) 898 { 899 continue; 900 } 901 clazz.defrost(); 903 byte[] previousByteCode = clazz.toBytecode(); 904 clazz.defrost(); 905 clazz.instrument(converter); 906 if (!java.util.Arrays.equals(clazz.toBytecode(), previousByteCode)) 907 { 908 classes.add(clazz); 909 } 910 clazz.defrost(); 911 } 912 } 913 fieldAccessTransformer.codeConverted(); 915 constructorExecutionTransformer.codeConverted(); 916 917 for (Iterator iterator = classes.iterator(); iterator.hasNext(); ) 919 { 920 CtClass clazz = (CtClass) iterator.next(); 921 AOPClassPool classPool = (AOPClassPool) clazz.getClassPool(); 922 clazz.defrost(); 923 hotSwapper.registerChange(classPool.getClassLoader().loadClass(clazz.getName()), 924 clazz.toBytecode()); 925 } 926 hotSwapper.hotSwap(); 928 } 929 catch (Exception e) { 930 e.printStackTrace(); 931 if (AspectManager.suppressTransformationErrors) 932 { 933 System.err.println("[warn] AOP Instrumentor failed to updated wrapping status."); 934 e.printStackTrace(); 935 } 936 else 937 { 938 if (e instanceof TransformationException) 939 { 940 throw ((TransformationException) e); 941 } 942 else 943 { 944 throw new RuntimeException ("failed to update wrapping status", e); 945 } 946 } 947 } 948 } 949 950 951 964 public void convertProcessedClasses(HotSwapper hotSwapper, CtClass clazz, 965 Collection fieldReads, Collection fieldWrites, boolean constructor) 966 { 967 AOPClassPool classPool = (AOPClassPool) clazz.getClassPool(); 968 CodeConverter codeConverter = new CodeConverter(); 969 for (Iterator iterator = fieldReads.iterator(); iterator.hasNext(); ) 970 { 971 CtField field = (CtField) iterator.next(); 972 codeConverter.replaceFieldRead(field, clazz, fieldAccessTransformer.fieldRead(field.getName())); 973 } 974 for (Iterator iterator = fieldReads.iterator(); iterator.hasNext(); ) 975 { 976 CtField field = (CtField) iterator.next(); 977 codeConverter.replaceFieldWrite(field, clazz, fieldAccessTransformer.fieldWrite(field.getName())); 978 } 979 if (constructor) 980 { 981 codeConverter.replaceNew(clazz, clazz, ConstructorExecutionTransformer.constructorFactory(clazz.getSimpleName())); 982 } 983 984 synchronized(processedClasses) 985 { 986 for (Iterator iterator = processedClasses.iterator(); iterator.hasNext();) 987 { 988 CtClass processedClass = (CtClass) iterator.next(); 989 if (processedClass == clazz) 990 continue; 991 if (processedClass.getRefClasses() == null || 992 ! clazz.getRefClasses().contains(clazz.getName())) 993 { 994 continue; 995 } 996 try 997 { 998 processedClass.defrost(); 999 byte[] previousByteCode = processedClass.toBytecode(); 1000 processedClass.defrost(); 1001 processedClass.instrument(codeConverter); 1002 byte[] updatedByteCode = processedClass.toBytecode(); 1003 if (!java.util.Arrays.equals(updatedByteCode, previousByteCode)) 1004 { 1005 hotSwapper.registerChange(classPool.getClassLoader().loadClass(processedClass.getName()), updatedByteCode); 1006 } 1007 processedClass.defrost(); 1008 } 1009 catch (Exception e) 1010 { 1011 e.printStackTrace(); 1012 if (AspectManager.suppressTransformationErrors) 1013 { 1014 System.err.println("[warn] AOP Instrumentor failed to updated wrapping status."); 1015 e.printStackTrace(); 1016 } 1017 else if (e instanceof TransformationException) 1018 { 1019 throw ((TransformationException) e); 1020 } 1021 else 1022 { 1023 throw new RuntimeException ("failed to update wrapping status", e); 1024 } 1025 } 1026 1027 } 1028 } 1029 hotSwapper.hotSwap(); 1030 } 1031 1032 protected abstract void doSetupBasics(CtClass clazz) throws CannotCompileException, NotFoundException; 1033 1034 1037 protected abstract CtMethod createMixinInvokeMethod(CtClass clazz, CtClass mixinClass, String initializer, CtMethod method, long hash) 1038 throws CannotCompileException, NotFoundException, Exception ; 1039 1040} | Popular Tags |