1 22 package org.jboss.aop; 23 24 import javassist.bytecode.AnnotationsAttribute; 25 import javassist.bytecode.ClassFile; 26 import javassist.bytecode.FieldInfo; 27 import javassist.bytecode.MethodInfo; 28 import javassist.bytecode.annotation.ArrayMemberValue; 29 import javassist.bytecode.annotation.BooleanMemberValue; 30 import javassist.bytecode.annotation.ClassMemberValue; 31 import javassist.bytecode.annotation.MemberValue; 32 import javassist.bytecode.annotation.StringMemberValue; 33 34 import org.jboss.aop.advice.AdviceBinding; 35 import org.jboss.aop.advice.AdviceFactory; 36 import org.jboss.aop.advice.AspectDefinition; 37 import org.jboss.aop.advice.AspectFactory; 38 import org.jboss.aop.advice.AspectFactoryDelegator; 39 import org.jboss.aop.advice.DynamicCFlowDefinition; 40 import org.jboss.aop.advice.GenericAspectFactory; 41 import org.jboss.aop.advice.Interceptor; 42 import org.jboss.aop.advice.InterceptorFactory; 43 import org.jboss.aop.advice.PrecedenceDef; 44 import org.jboss.aop.advice.PrecedenceDefEntry; 45 import org.jboss.aop.advice.Scope; 46 import org.jboss.aop.advice.ScopedInterceptorFactory; 47 import org.jboss.aop.annotation.factory.duplicate.javassist.AnnotationProxy; 48 import org.jboss.aop.introduction.AnnotationIntroduction; 49 import org.jboss.aop.introduction.InterfaceIntroduction; 50 import org.jboss.aop.pointcut.CFlow; 51 import org.jboss.aop.pointcut.CFlowStack; 52 import org.jboss.aop.pointcut.DeclareDef; 53 import org.jboss.aop.pointcut.DynamicCFlow; 54 import org.jboss.aop.pointcut.Pointcut; 55 import org.jboss.aop.pointcut.PointcutExpression; 56 import org.jboss.aop.pointcut.Typedef; 57 import org.jboss.aop.pointcut.TypedefExpression; 58 import org.jboss.aop.pointcut.ast.ASTCFlowExpression; 59 import org.jboss.aop.pointcut.ast.ASTStart; 60 import org.jboss.aop.pointcut.ast.PointcutExpressionParser; 61 import org.jboss.aop.pointcut.ast.TypeExpressionParser; 62 import org.jboss.aop.util.MethodHashing; 63 64 import java.io.DataInputStream ; 65 import java.io.InputStream ; 66 import java.io.StringReader ; 67 import java.util.ArrayList ; 68 import java.util.Iterator ; 69 70 76 public class AspectAnnotationLoader 77 { 78 80 protected AspectManager manager; 81 82 public AspectAnnotationLoader(AspectManager manager) 83 { 84 this.manager = manager; 85 } 86 87 public void deployInputStreamIterator(Iterator it) throws Exception 88 { 89 while (it.hasNext()) 90 { 91 InputStream stream = (InputStream ) it.next(); 92 DataInputStream dstream = new DataInputStream (stream); 93 ClassFile cf = null; 94 try 95 { 96 cf = new ClassFile(dstream); 97 } 98 finally 99 { 100 dstream.close(); 101 stream.close(); 102 } 103 deployClassFile(cf); 104 } 105 } 106 107 public void deployClassFile(ClassFile cf) throws Exception 108 { 109 if (AspectManager.verbose) System.out.println("[debug] Looking for aspects in: " + cf.getName()); 110 AnnotationsAttribute visible = (AnnotationsAttribute) cf.getAttribute(AnnotationsAttribute.visibleTag); 111 if (visible != null) 112 { 113 AspectDefinition def = deployAspect(visible, cf); 114 115 if (def == null) 116 { 117 def = deployInterceptor(visible, cf); 118 } 119 120 if (def == null) 121 { 122 deployDynamicCFlow(visible, cf); 123 } 124 125 if (def == null) 126 { 127 if (!deployPreparedClass(visible, cf)) 128 { 129 deployPrecedence(visible, cf); 130 } 131 } 132 else 133 { 134 deployPointcuts(cf); 135 deployMixins(cf); 136 deployIntroductions(cf); 137 deployTypedefs(cf); 138 deployCFlowStackDefs(cf); 139 deployPrepares(cf); 140 deployAnnotationIntroductions(cf); 141 deployDeclares(cf); 142 } 143 } 144 } 145 146 public void undeployInputStreamIterator(Iterator it) throws Exception 147 { 148 while (it.hasNext()) 149 { 150 InputStream stream = (InputStream ) it.next(); 151 DataInputStream dstream = new DataInputStream (stream); 152 ClassFile cf = null; 153 try 154 { 155 cf = new ClassFile(dstream); 156 } 157 finally 158 { 159 dstream.close(); 160 stream.close(); 161 } 162 undeployClassFile(cf); 163 } 164 } 165 166 public void undeployClassFile(ClassFile cf) throws Exception 167 { 168 if (AspectManager.verbose) System.out.println("[debug] Looking for aspects in: " + cf.getName()); 169 AnnotationsAttribute visible = (AnnotationsAttribute) cf.getAttribute(AnnotationsAttribute.visibleTag); 170 if (visible != null) 171 { 172 undeployAspect(visible, cf); 173 undeployInterceptor(visible, cf); 174 undeployDynamicCFlow(visible, cf); 175 undeployPreparedClass(visible, cf); 176 undeployPrecedence(visible, cf); 177 undeployPointcuts(cf); 178 undeployMixins(cf); 179 undeployIntroductions(cf); 180 undeployTypedefs(cf); 181 undeployCFlowStackDefs(cf); 182 undeployPrepares(cf); 183 undeployAnnotationIntroductions(cf); 184 } 185 } 186 187 private AspectDefinition deployAspect(AnnotationsAttribute visible, ClassFile cf) throws Exception 188 { 189 javassist.bytecode.annotation.Annotation info = visible.getAnnotation(Aspect.class.getName()); 191 if (info != null) 192 { 193 if (AspectManager.verbose) System.out.println("[debug] Found @Aspect in: " + cf.getName()); 194 Aspect aspect = (Aspect) AnnotationProxy.createProxy(info, Aspect.class); 195 Scope scope = aspect.scope(); 196 197 String [] interfaces = cf.getInterfaces(); 198 boolean isFactory = false; 199 for (int i = 0; i < interfaces.length; i++) 200 { 201 if (interfaces[i].equals(AspectFactory.class.getName())) 202 { 203 isFactory = true; 204 break; 205 } 206 } 207 AspectFactory factory = null; 208 if (isFactory) 209 { 210 factory = new AspectFactoryDelegator(cf.getName(), null); 211 } 212 else 213 { 214 factory = new GenericAspectFactory(cf.getName(), null); 215 } 216 AspectDefinition def = new AspectDefinition(cf.getName(), scope, factory); 217 manager.addAspectDefinition(def); 218 if (!isFactory) 219 { 220 deployAspectMethodBindings(cf, def); 221 } 222 223 return def; 224 } 225 return null; 226 } 227 228 private void undeployAspect(AnnotationsAttribute visible, ClassFile cf) throws Exception 229 { 230 javassist.bytecode.annotation.Annotation info = visible.getAnnotation(Aspect.class.getName()); 232 if (info != null) 233 { 234 if (AspectManager.verbose) System.out.println("[debug] Undeploying @Aspect in: " + cf.getName()); 235 manager.removeAspectDefinition(cf.getName()); 236 237 undeployAspectMethodBindings(cf); 238 } 239 } 240 241 private AspectDefinition deployInterceptor(AnnotationsAttribute visible, ClassFile cf) throws Exception 242 { 243 javassist.bytecode.annotation.Annotation info = visible.getAnnotation(InterceptorDef.class.getName()); 245 if (info != null) 246 { 247 if (AspectManager.verbose) System.out.println("[debug] Found @InterceptorDef in: " + cf.getName()); 248 Aspect aspect = (Aspect) AnnotationProxy.createProxy(info, Aspect.class); 249 Scope scope = aspect.scope(); 250 251 String [] interfaces = cf.getInterfaces(); 252 boolean isFactory = false; 253 for (int i = 0; i < interfaces.length; i++) 254 { 255 if (interfaces[i].equals(AspectFactory.class.getName())) 256 { 257 isFactory = true; 258 break; 259 } 260 else if (interfaces[i].equals(Interceptor.class.getName())) 261 { 262 break; 263 } 264 } 265 266 AspectFactory aspectFactory; 267 if (isFactory) 268 { 269 aspectFactory = new AspectFactoryDelegator(cf.getName(), null); 270 } 271 else 272 { 273 aspectFactory = new GenericAspectFactory(cf.getName(), null); 274 } 275 276 AspectDefinition def = new AspectDefinition(cf.getName(), scope, aspectFactory); 277 manager.addAspectDefinition(def); 278 ScopedInterceptorFactory factory = new ScopedInterceptorFactory(def); 279 manager.addInterceptorFactory(factory.getName(), factory); 280 281 deployInterceptorBindings(visible, cf, factory); 282 283 return def; 284 } 285 286 return null; 287 } 288 289 private void undeployInterceptor(AnnotationsAttribute visible, ClassFile cf) throws Exception 290 { 291 javassist.bytecode.annotation.Annotation info = visible.getAnnotation(InterceptorDef.class.getName()); 293 if (info != null) 294 { 295 if (AspectManager.verbose) System.out.println("[debug] Undeploying @InterceptorDef in: " + cf.getName()); 296 AnnotationProxy.createProxy(info, Aspect.class); 297 298 manager.removeAspectDefinition(cf.getName()); 299 manager.removeInterceptorFactory(cf.getName()); 300 undeployInterceptorBindings(visible, cf); 301 } 302 303 } 304 305 private void deployDynamicCFlow(AnnotationsAttribute visible, ClassFile cf) throws Exception 306 { 307 javassist.bytecode.annotation.Annotation info = visible.getAnnotation(DynamicCFlowDef.class.getName()); 308 if (info != null) 309 { 310 if (AspectManager.verbose) System.out.println("[debug] Found @DynamicCFlowDef in: " + cf.getName()); 311 AnnotationProxy.createProxy(info, DynamicCFlowDef.class); 312 313 String name = cf.getName(); 314 String clazz = cf.getName(); 315 316 String [] interfaces = cf.getInterfaces(); 317 boolean foundDCFlow = false; 318 for (int i = 0; i < interfaces.length; i++) 319 { 320 if (interfaces[i].equals(DynamicCFlow.class.getName())) 321 { 322 foundDCFlow = true; 323 break; 324 } 325 } 326 if (!foundDCFlow) throw new RuntimeException ("@DynamicCFlow annotated class: " + clazz + " must implement " + DynamicCFlow.class.getName()); 327 328 manager.addDynamicCFlow(name, new DynamicCFlowDefinition(null, clazz, name)); 329 } 330 } 331 332 private void undeployDynamicCFlow(AnnotationsAttribute visible, ClassFile cf) throws Exception 333 { 334 javassist.bytecode.annotation.Annotation info = visible.getAnnotation(DynamicCFlowDef.class.getName()); 335 if (info != null) 336 { 337 if (AspectManager.verbose) System.out.println("[debug] Undeploying @DynamicCFlowDef in: " + cf.getName()); 338 String name = cf.getName(); 339 manager.removeDynamicCFlow(name); 340 } 341 } 342 343 private boolean deployPreparedClass(AnnotationsAttribute visible, ClassFile cf) throws Exception 344 { 345 javassist.bytecode.annotation.Annotation info = visible.getAnnotation(Prepare.class.getName()); 347 if (info != null) 348 { 349 if (AspectManager.verbose) System.out.println("[debug] Found top-level @Prepare in: " + cf.getName()); 350 Prepare prepare = (Prepare) AnnotationProxy.createProxy(info, Prepare.class); 351 352 String name = cf.getName() + "." + visible.getName(); 353 String expr = replaceThisInExpr(prepare.value(), cf.getName()); 354 Pointcut p = new PointcutExpression(name, expr); 355 manager.addPointcut(p); 356 return true; 357 } 358 359 return false; 360 } 361 362 private void undeployPreparedClass(AnnotationsAttribute visible, ClassFile cf) throws Exception 363 { 364 javassist.bytecode.annotation.Annotation info = visible.getAnnotation(Prepare.class.getName()); 366 if (info != null) 367 { 368 String name = cf.getName() + "." + visible.getName(); 369 manager.removePointcut(name); 370 } 371 } 372 373 private void deployPrecedence(AnnotationsAttribute visible, ClassFile cf)throws Exception 374 { 375 javassist.bytecode.annotation.Annotation info = visible.getAnnotation(Precedence.class.getName()); 376 if (info != null) 377 { 378 if (AspectManager.verbose) System.out.println("[debug] Found top-level @Precedence in: " + cf.getName()); 379 380 ArrayList entries = new ArrayList (); 381 Iterator fields = cf.getFields().iterator(); 382 while (fields.hasNext()) 383 { 384 FieldInfo finfo = (javassist.bytecode.FieldInfo) fields.next(); 385 AnnotationsAttribute mgroup = (AnnotationsAttribute) finfo.getAttribute(AnnotationsAttribute.visibleTag); 386 if (mgroup == null) continue; 387 javassist.bytecode.annotation.Annotation binfo = mgroup.getAnnotation(PrecedenceInterceptor.class.getName()); 388 if (binfo != null) 389 { 390 entries.add(new PrecedenceDefEntry(getFieldType(finfo), null)); 392 } 393 else 394 { 395 binfo = mgroup.getAnnotation(PrecedenceAdvice.class.getName()); 396 if (binfo != null) 397 { 398 PrecedenceAdvice advice = (PrecedenceAdvice) AnnotationProxy.createProxy(binfo, PrecedenceAdvice.class); 399 String method = advice.value(); 400 entries.add(new PrecedenceDefEntry(getFieldType(finfo), method)); 401 } 402 } 403 } 404 PrecedenceDefEntry[] pentries = (PrecedenceDefEntry[])entries.toArray(new PrecedenceDefEntry[entries.size()]); 405 PrecedenceDef precedenceDef = new PrecedenceDef(cf.getName(), pentries); 406 manager.addPrecedence(precedenceDef); 407 } 408 } 409 410 private void undeployPrecedence(AnnotationsAttribute visible, ClassFile cf)throws Exception 411 { 412 javassist.bytecode.annotation.Annotation info = visible.getAnnotation(Precedence.class.getName()); 413 if (info != null) 414 { 415 manager.removePrecedence(cf.getName()); 416 } 417 } 418 419 private void deployAspectMethodBindings(ClassFile cf, AspectDefinition def) 420 throws Exception 421 { 422 Iterator methods = cf.getMethods().iterator(); 423 while (methods.hasNext()) 424 { 425 javassist.bytecode.MethodInfo minfo = (javassist.bytecode.MethodInfo) methods.next(); 426 AnnotationsAttribute mgroup = (AnnotationsAttribute) minfo.getAttribute(AnnotationsAttribute.visibleTag); 427 if (mgroup == null) continue; 428 javassist.bytecode.annotation.Annotation binfo = mgroup.getAnnotation(Bind.class.getName()); 429 if (binfo == null) continue; 430 Bind binding = (Bind) AnnotationProxy.createProxy(binfo, Bind.class); 431 String pointcutString = binding.pointcut(); 432 String cflow = binding.cflow(); 433 if (cflow == null || cflow.trim().equals("")) cflow = null; 434 ASTCFlowExpression cflowExpression = null; 435 if (cflow != null) 436 { 437 cflowExpression = new PointcutExpressionParser(new StringReader (cflow)).CFlowExpression(); 438 439 } 440 AdviceFactory factory = new AdviceFactory(def, minfo.getName()); 441 manager.addInterceptorFactory(factory.getName(), factory); 442 InterceptorFactory[] fact = {factory}; 443 String name = getAspectMethodBindingName(cf, minfo); 444 PointcutExpression pointcut = new PointcutExpression(name, pointcutString); 445 AdviceBinding abinding = new AdviceBinding(name, pointcut, cflowExpression, cflow, fact); 446 manager.addBinding(abinding); 447 } 448 } 449 450 451 private void undeployAspectMethodBindings(ClassFile cf) 452 throws Exception 453 { 454 Iterator methods = cf.getMethods().iterator(); 455 while (methods.hasNext()) 456 { 457 javassist.bytecode.MethodInfo minfo = (javassist.bytecode.MethodInfo) methods.next(); 458 AnnotationsAttribute mgroup = (AnnotationsAttribute) minfo.getAttribute(AnnotationsAttribute.visibleTag); 459 if (mgroup == null) continue; 460 javassist.bytecode.annotation.Annotation binfo = mgroup.getAnnotation(Bind.class.getName()); 461 if (binfo == null) continue; 462 463 String adviceName = cf.getName() + "." + minfo.getName(); 464 manager.removeInterceptorFactory(adviceName); 465 String name = getAspectMethodBindingName(cf, minfo); 466 manager.removePointcut(name); 467 manager.removeBinding(name); 468 } 469 } 470 471 private String getAspectMethodBindingName(ClassFile cf, MethodInfo minfo)throws Exception 472 { 473 String method = cf.getName() + "." + minfo.getName(); 474 String fullMethod = method + minfo.getDescriptor(); 475 return method + " " + MethodHashing.createHash(fullMethod); 476 } 477 478 private void deployInterceptorBindings(AnnotationsAttribute visible, ClassFile cf, InterceptorFactory factory) 479 throws Exception 480 { 481 javassist.bytecode.annotation.Annotation binfo = visible.getAnnotation(Bind.class.getName()); 482 if (binfo == null) return; 483 Bind bind = (Bind) AnnotationProxy.createProxy(binfo, Bind.class); 484 String pointcutString = bind.pointcut(); 485 String cflow = bind.cflow(); 486 if (cflow == null || cflow.trim().equals("")) cflow = null; 487 ASTCFlowExpression cflowExpression = null; 488 if (cflow != null) 489 { 490 cflowExpression = new PointcutExpressionParser(new StringReader (cflow)).CFlowExpression(); 491 492 } 493 494 String name = cf.getName(); 495 InterceptorFactory[] inters = {factory}; 496 Pointcut p = null; 497 p = new PointcutExpression(name, pointcutString); 498 AdviceBinding binding = new AdviceBinding(name, p, cflowExpression, cflow, inters); 499 manager.addBinding(binding); 500 } 501 502 private void undeployInterceptorBindings(AnnotationsAttribute visible, ClassFile cf) 503 throws Exception 504 { 505 javassist.bytecode.annotation.Annotation binfo = visible.getAnnotation(Bind.class.getName()); 506 if (binfo == null) return; 507 508 String name = cf.getName(); 509 manager.removePointcut(name); 510 manager.removeBinding(name); 511 } 512 513 514 private void deployPointcuts(ClassFile cf) 515 throws Exception 516 { 517 Iterator fields = cf.getFields().iterator(); 518 while (fields.hasNext()) 519 { 520 javassist.bytecode.FieldInfo finfo = (javassist.bytecode.FieldInfo) fields.next(); 521 AnnotationsAttribute mgroup = (AnnotationsAttribute) finfo.getAttribute(AnnotationsAttribute.visibleTag); 522 if (mgroup == null) continue; 523 javassist.bytecode.annotation.Annotation binfo = mgroup.getAnnotation(PointcutDef.class.getName()); 524 if (binfo == null) continue; 525 PointcutDef pdef = (PointcutDef) AnnotationProxy.createProxy(binfo, PointcutDef.class); 526 527 PointcutExpression pointcut = new PointcutExpression(getPointcutName(cf, finfo), pdef.value()); 528 529 manager.addPointcut(pointcut); 530 } 531 } 532 533 private void undeployPointcuts(ClassFile cf) 534 throws Exception 535 { 536 Iterator fields = cf.getFields().iterator(); 537 while (fields.hasNext()) 538 { 539 javassist.bytecode.FieldInfo finfo = (javassist.bytecode.FieldInfo) fields.next(); 540 AnnotationsAttribute mgroup = (AnnotationsAttribute) finfo.getAttribute(AnnotationsAttribute.visibleTag); 541 if (mgroup == null) continue; 542 javassist.bytecode.annotation.Annotation binfo = mgroup.getAnnotation(PointcutDef.class.getName()); 543 if (binfo == null) continue; 544 manager.removePointcut(getPointcutName(cf, finfo)); 545 } 546 } 547 548 private String getPointcutName(ClassFile cf, FieldInfo finfo) 549 { 550 return cf.getName() + "." + finfo.getName(); 551 } 552 553 private void deployMixins(ClassFile cf) 554 throws Exception 555 { 556 Iterator methods = cf.getMethods().iterator(); 557 while (methods.hasNext()) 558 { 559 javassist.bytecode.MethodInfo minfo = (javassist.bytecode.MethodInfo) methods.next(); 560 AnnotationsAttribute mgroup = (AnnotationsAttribute) minfo.getAttribute(AnnotationsAttribute.visibleTag); 561 if (mgroup == null) continue; 562 javassist.bytecode.annotation.Annotation binfo = mgroup.getAnnotation(Mixin.class.getName()); 563 if (binfo == null) continue; 564 565 570 576 MemberValue mv = binfo.getMemberValue("target"); 577 String target = (mv != null) ? ((ClassMemberValue) mv).getValue() : "java.lang.Class"; 579 mv = binfo.getMemberValue("typeExpression"); 580 String typeExpression = (mv != null) ? ((StringMemberValue) mv).getValue() : ""; 582 mv = binfo.getMemberValue("interfaces"); 583 MemberValue[] values = ((ArrayMemberValue) mv).getValue(); 584 String [] interfaces = new String [values.length]; 585 for (int i = 0; i < values.length; i++) interfaces[i] = ((ClassMemberValue) values[i]).getValue(); 586 587 mv = binfo.getMemberValue("isTransient"); 588 boolean isTransient = (mv != null) ? ((BooleanMemberValue) mv).getValue() : true; 590 String name = cf.getName() + "." + minfo.getName(); 592 InterfaceIntroduction intro = createIntroduction(name, target, typeExpression, null); 593 594 595 String construction = name + "(this)"; 596 597 String classname = getReturnType(minfo); 599 intro.getMixins().add(new InterfaceIntroduction.Mixin(classname, interfaces, construction, isTransient)); 600 601 manager.addInterfaceIntroduction(intro); 602 } 603 } 604 605 private void undeployMixins(ClassFile cf) 606 throws Exception 607 { 608 Iterator methods = cf.getMethods().iterator(); 609 while (methods.hasNext()) 610 { 611 javassist.bytecode.MethodInfo minfo = (javassist.bytecode.MethodInfo) methods.next(); 612 AnnotationsAttribute mgroup = (AnnotationsAttribute) minfo.getAttribute(AnnotationsAttribute.visibleTag); 613 if (mgroup == null) continue; 614 javassist.bytecode.annotation.Annotation binfo = mgroup.getAnnotation(Mixin.class.getName()); 615 if (binfo == null) continue; 616 617 String name = cf.getName() + "." + minfo.getName(); manager.removeInterfaceIntroduction(name); 619 } 620 } 621 622 private void deployIntroductions(ClassFile cf) 623 throws Exception 624 { 625 Iterator fields = cf.getFields().iterator(); 626 while (fields.hasNext()) 627 { 628 FieldInfo finfo = (javassist.bytecode.FieldInfo) fields.next(); 629 AnnotationsAttribute mgroup = (AnnotationsAttribute) finfo.getAttribute(AnnotationsAttribute.visibleTag); 630 if (mgroup == null) continue; 631 javassist.bytecode.annotation.Annotation binfo = mgroup.getAnnotation(Introduction.class.getName()); 632 if (binfo == null) continue; 633 634 639 644 MemberValue mv = binfo.getMemberValue("target"); 645 String target = (mv != null) ? ((ClassMemberValue) mv).getValue() : "java.lang.Class"; 647 mv = binfo.getMemberValue("typeExpression"); 648 String typeExpression = (mv != null) ? ((StringMemberValue) mv).getValue() : ""; 650 mv = binfo.getMemberValue("interfaces"); 651 MemberValue[] values = ((ArrayMemberValue) mv).getValue(); 652 String [] interfaces = new String [values.length]; 653 for (int i = 0; i < values.length; i++) interfaces[i] = ((ClassMemberValue) values[i]).getValue(); 654 655 String name = cf.getName() + "." + finfo.getName(); 657 InterfaceIntroduction interfaceIntro = createIntroduction(name, target, typeExpression, interfaces); 658 manager.addInterfaceIntroduction(interfaceIntro); 659 } 660 } 661 662 private void undeployIntroductions(ClassFile cf) 663 throws Exception 664 { 665 Iterator fields = cf.getFields().iterator(); 666 while (fields.hasNext()) 667 { 668 FieldInfo finfo = (javassist.bytecode.FieldInfo) fields.next(); 669 AnnotationsAttribute mgroup = (AnnotationsAttribute) finfo.getAttribute(AnnotationsAttribute.visibleTag); 670 if (mgroup == null) continue; 671 javassist.bytecode.annotation.Annotation binfo = mgroup.getAnnotation(Introduction.class.getName()); 672 if (binfo == null) continue; 673 674 String name = cf.getName() + "." + finfo.getName(); 676 manager.removeInterfaceIntroduction(name); 677 } 678 } 679 680 private void deployTypedefs(ClassFile cf) throws Exception 681 { 682 Iterator fields = cf.getFields().iterator(); 683 while (fields.hasNext()) 684 { 685 FieldInfo finfo = (javassist.bytecode.FieldInfo) fields.next(); 686 AnnotationsAttribute mgroup = (AnnotationsAttribute) finfo.getAttribute(AnnotationsAttribute.visibleTag); 687 if (mgroup == null) continue; 688 javassist.bytecode.annotation.Annotation binfo = mgroup.getAnnotation(TypeDef.class.getName()); 689 if (binfo == null) continue; 690 TypeDef typeDefinition = (TypeDef) AnnotationProxy.createProxy(binfo, TypeDef.class); 691 692 String name = getTypedefName(cf, finfo); 693 String expr = typeDefinition.value(); 694 Typedef typedef = new TypedefExpression(name, expr); 695 manager.addTypedef(typedef); 696 697 } 698 } 699 700 private void undeployTypedefs(ClassFile cf) throws Exception 701 { 702 Iterator fields = cf.getFields().iterator(); 703 while (fields.hasNext()) 704 { 705 FieldInfo finfo = (javassist.bytecode.FieldInfo) fields.next(); 706 AnnotationsAttribute mgroup = (AnnotationsAttribute) finfo.getAttribute(AnnotationsAttribute.visibleTag); 707 if (mgroup == null) continue; 708 javassist.bytecode.annotation.Annotation binfo = mgroup.getAnnotation(TypeDef.class.getName()); 709 if (binfo == null) continue; 710 711 AnnotationProxy.createProxy(binfo, TypeDef.class); 712 713 manager.removeTypedef(getTypedefName(cf, finfo)); 714 715 } 716 } 717 718 private String getTypedefName(ClassFile cf, FieldInfo finfo) 719 { 720 return cf.getName() + "." + finfo.getName(); 721 } 722 723 private void deployCFlowStackDefs(ClassFile cf) throws Exception 724 { 725 Iterator fields = cf.getFields().iterator(); 726 while (fields.hasNext()) 727 { 728 FieldInfo finfo = (javassist.bytecode.FieldInfo) fields.next(); 729 AnnotationsAttribute mgroup = (AnnotationsAttribute) finfo.getAttribute(AnnotationsAttribute.visibleTag); 730 if (mgroup == null) continue; 731 javassist.bytecode.annotation.Annotation binfo = mgroup.getAnnotation(CFlowStackDef.class.getName()); 732 if (binfo == null) continue; 733 CFlowStackDef stackDef = (CFlowStackDef) AnnotationProxy.createProxy(binfo, CFlowStackDef.class); 734 735 String name = getStackDefName(cf, finfo); 736 CFlowDef[] cflows = stackDef.cflows(); 737 CFlowStack stack = new CFlowStack(name); 738 739 for (int i = 0; i < cflows.length; i++) 740 { 741 CFlowDef cflow = cflows[i]; 742 boolean not = !cflow.called(); 743 stack.addCFlow(new CFlow(cflow.expr(), not)); 744 } 745 746 manager.addCFlowStack(stack); 747 } 748 } 749 750 private void undeployCFlowStackDefs(ClassFile cf) throws Exception 751 { 752 Iterator fields = cf.getFields().iterator(); 753 while (fields.hasNext()) 754 { 755 FieldInfo finfo = (javassist.bytecode.FieldInfo) fields.next(); 756 AnnotationsAttribute mgroup = (AnnotationsAttribute) finfo.getAttribute(AnnotationsAttribute.visibleTag); 757 if (mgroup == null) continue; 758 javassist.bytecode.annotation.Annotation binfo = mgroup.getAnnotation(CFlowStackDef.class.getName()); 759 if (binfo == null) continue; 760 AnnotationProxy.createProxy(binfo, CFlowStackDef.class); 761 762 manager.removeCFlowStack(getStackDefName(cf, finfo)); 763 } 764 } 765 766 private String getStackDefName(ClassFile cf, FieldInfo finfo) 767 { 768 return cf.getName() + "." + finfo.getName(); 769 } 770 771 private void deployPrepares(ClassFile cf) throws Exception 772 { 773 Iterator fields = cf.getFields().iterator(); 774 while (fields.hasNext()) 775 { 776 FieldInfo finfo = (javassist.bytecode.FieldInfo) fields.next(); 777 AnnotationsAttribute mgroup = (AnnotationsAttribute) finfo.getAttribute(AnnotationsAttribute.visibleTag); 778 if (mgroup == null) continue; 779 javassist.bytecode.annotation.Annotation binfo = mgroup.getAnnotation(Prepare.class.getName()); 780 if (binfo == null) continue; 781 Prepare prepare = (Prepare) AnnotationProxy.createProxy(binfo, Prepare.class); 782 783 String name = getPrepareName(cf, finfo); 784 String expr = prepare.value(); 785 Pointcut p = new PointcutExpression(name, expr); 786 manager.addPointcut(p); 787 } 788 } 789 790 private void undeployPrepares(ClassFile cf) throws Exception 791 { 792 Iterator fields = cf.getFields().iterator(); 793 while (fields.hasNext()) 794 { 795 FieldInfo finfo = (javassist.bytecode.FieldInfo) fields.next(); 796 AnnotationsAttribute mgroup = (AnnotationsAttribute) finfo.getAttribute(AnnotationsAttribute.visibleTag); 797 if (mgroup == null) continue; 798 javassist.bytecode.annotation.Annotation binfo = mgroup.getAnnotation(Prepare.class.getName()); 799 if (binfo == null) continue; 800 AnnotationProxy.createProxy(binfo, Prepare.class); 801 802 manager.removePointcut(getPrepareName(cf, finfo)); 803 } 804 } 805 806 private String getPrepareName(ClassFile cf, FieldInfo finfo) 807 { 808 return cf.getName() + "." + finfo.getName(); 809 } 810 811 private void deployAnnotationIntroductions(ClassFile cf) throws Exception 812 { 813 Iterator fields = cf.getFields().iterator(); 814 while (fields.hasNext()) 815 { 816 FieldInfo finfo = (javassist.bytecode.FieldInfo) fields.next(); 817 AnnotationsAttribute mgroup = (AnnotationsAttribute) finfo.getAttribute(AnnotationsAttribute.visibleTag); 818 if (mgroup == null) continue; 819 javassist.bytecode.annotation.Annotation binfo = mgroup.getAnnotation(AnnotationIntroductionDef.class.getName()); 820 if (binfo == null) continue; 821 AnnotationIntroductionDef intro = (AnnotationIntroductionDef) AnnotationProxy.createProxy(binfo, AnnotationIntroductionDef.class); 822 823 String expr = intro.expr(); 824 boolean invisible = intro.invisible(); 825 String annotation = intro.annotation(); 826 827 annotation = annotation.replace('\'', '"'); 828 829 AnnotationIntroduction annIntro = AnnotationIntroduction.createComplexAnnotationIntroduction(expr, annotation, invisible); 830 manager.addAnnotationIntroduction(annIntro); 831 } 832 } 833 834 private void undeployAnnotationIntroductions(ClassFile cf) throws Exception 835 { 836 Iterator fields = cf.getFields().iterator(); 837 while (fields.hasNext()) 838 { 839 FieldInfo finfo = (javassist.bytecode.FieldInfo) fields.next(); 840 AnnotationsAttribute mgroup = (AnnotationsAttribute) finfo.getAttribute(AnnotationsAttribute.visibleTag); 841 if (mgroup == null) continue; 842 javassist.bytecode.annotation.Annotation binfo = mgroup.getAnnotation(AnnotationIntroductionDef.class.getName()); 843 if (binfo == null) continue; 844 AnnotationIntroductionDef intro = (AnnotationIntroductionDef) AnnotationProxy.createProxy(binfo, AnnotationIntroductionDef.class); 845 846 String expr = intro.expr(); 847 boolean invisible = intro.invisible(); 848 String annotation = intro.annotation(); 849 850 annotation = annotation.replace('\'', '"'); 851 852 AnnotationIntroduction annIntro = AnnotationIntroduction.createComplexAnnotationIntroduction(expr, annotation, invisible); 853 manager.removeAnnotationIntroduction(annIntro); 854 } 855 } 856 857 private void deployDeclares(ClassFile cf) throws Exception 858 { 859 Iterator fields = cf.getFields().iterator(); 860 while (fields.hasNext()) 861 { 862 FieldInfo finfo = (javassist.bytecode.FieldInfo) fields.next(); 863 AnnotationsAttribute mgroup = (AnnotationsAttribute) finfo.getAttribute(AnnotationsAttribute.visibleTag); 864 if (mgroup == null) continue; 865 javassist.bytecode.annotation.Annotation dwinfo = mgroup.getAnnotation(DeclareWarning.class.getName()); 866 javassist.bytecode.annotation.Annotation deinfo = mgroup.getAnnotation(DeclareError.class.getName()); 867 868 if (dwinfo == null && deinfo == null) continue; 869 String name = getDeclareName(cf, finfo); 870 if (dwinfo != null && deinfo != null) throw new RuntimeException ("Cannot annotate " + name + " field with both DeclareError and DeclareWarning"); 871 872 String expr = null; 873 String msg = null; 874 boolean warning = false; 875 if (deinfo != null) 876 { 877 DeclareError derror = (DeclareError) AnnotationProxy.createProxy(deinfo, DeclareError.class); 878 expr = derror.expr(); 879 msg = derror.msg(); 880 } 881 else 882 { 883 DeclareWarning dwarning = (DeclareWarning) AnnotationProxy.createProxy(dwinfo, DeclareWarning.class); 884 expr = dwarning.expr(); 885 msg = dwarning.msg(); 886 warning = true; 887 } 888 DeclareDef def = new DeclareDef(name, expr, warning, msg); 889 890 manager.addDeclare(def); 891 } 892 } 893 894 private String getDeclareName(ClassFile cf, FieldInfo finfo) 895 { 896 return cf.getName() + "." + finfo.getName(); 897 } 898 899 private InterfaceIntroduction createIntroduction(String name, String target, String typeExpression, String [] interfaces) 900 throws Exception 901 { 902 if (typeExpression != null && typeExpression.trim().equals("")) 903 { 904 typeExpression = null; 905 } 906 907 if (typeExpression != null && target != null && target.equals("java.lang.Class")) 908 { 909 target = null; 910 } 911 912 if (target == null && typeExpression == null) 913 { 914 throw new RuntimeException ("No target nor a typeExpression attribute is defined for this @Mixin"); 915 } 916 917 if (target == null && typeExpression == null) 918 { 919 throw new RuntimeException ("You cannot define both a target and typeExpression attribute in the same @Mixin"); 920 } 921 922 923 InterfaceIntroduction intro = null; 924 925 if (target != null) 926 { 927 intro = new InterfaceIntroduction(name, target, interfaces); 928 } 929 else 930 { 931 ASTStart start = new TypeExpressionParser(new StringReader (typeExpression)).Start(); 932 intro = new InterfaceIntroduction(name, start, interfaces); 933 } 934 935 return intro; 936 } 937 938 private String getReturnType(MethodInfo minfo) 939 { 940 String descriptor = minfo.getDescriptor(); 941 int paramsEnd = descriptor.indexOf(";)"); 942 String classname = descriptor.substring(paramsEnd + 3, descriptor.length() - 1); 943 classname = classname.replace('/', '.'); 944 return classname; 945 } 946 947 private String getFieldType(FieldInfo finfo) 948 { 949 String descriptor = finfo.getDescriptor(); 951 String classname = descriptor.substring(1, descriptor.length() - 1); 952 classname = classname.replace('/', '.'); 953 return classname; 954 } 955 956 967 private static String replaceThisInExpr(String expr, String classname) 968 { 969 final String THIS = "this"; 970 971 StringBuffer buf = new StringBuffer (); 972 int index = expr.indexOf(THIS); 973 if (index == -1) 974 { 975 return expr; 976 } 977 978 int lastindex = 0; 979 while (index != -1) 980 { 981 boolean isPartOfWord = false; 982 if (index > 0) 983 { 984 char before = expr.charAt(index - 1); 985 isPartOfWord = Character.isJavaIdentifierPart(before); 986 } 987 988 if (!isPartOfWord && index + THIS.length() < expr.length() - 1) 989 { 990 char after = expr.charAt(index + THIS.length()); 991 isPartOfWord = Character.isJavaIdentifierPart(after); 992 } 993 994 buf.append(expr.substring(lastindex, index)); 995 996 if (isPartOfWord) 997 { 998 buf.append(THIS); 999 } 1000 else 1001 { 1002 buf.append(classname); 1003 } 1004 1005 lastindex = index + THIS.length(); 1006 index = expr.indexOf(THIS, lastindex); 1007 } 1008 buf.append(expr.substring(lastindex)); 1009 return buf.toString(); 1010 } 1011} 1012 | Popular Tags |