KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > aop > AspectAnnotationLoader


1 /*
2   * JBoss, Home of Professional Open Source
3   * Copyright 2005, JBoss Inc., and individual contributors as indicated
4   * by the @authors tag. See the copyright.txt in the distribution for a
5   * full listing of individual contributors.
6   *
7   * This is free software; you can redistribute it and/or modify it
8   * under the terms of the GNU Lesser General Public License as
9   * published by the Free Software Foundation; either version 2.1 of
10   * the License, or (at your option) any later version.
11   *
12   * This software is distributed in the hope that it will be useful,
13   * but WITHOUT ANY WARRANTY; without even the implied warranty of
14   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15   * Lesser General Public License for more details.
16   *
17   * You should have received a copy of the GNU Lesser General Public
18   * License along with this software; if not, write to the Free
19   * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20   * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21   */

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 JavaDoc;
65 import java.io.InputStream JavaDoc;
66 import java.io.StringReader JavaDoc;
67 import java.util.ArrayList JavaDoc;
68 import java.util.Iterator JavaDoc;
69
70 /**
71  * Comment
72  *
73  * @author <a HREF="mailto:bill@jboss.org">Bill Burke</a>
74  * @version $Revision: 57019 $
75  */

76 public class AspectAnnotationLoader
77 {
78    //TODO: We need something to undeploy everything...
79

80    protected AspectManager manager;
81
82    public AspectAnnotationLoader(AspectManager manager)
83    {
84       this.manager = manager;
85    }
86
87    public void deployInputStreamIterator(Iterator JavaDoc it) throws Exception JavaDoc
88    {
89       while (it.hasNext())
90       {
91          InputStream JavaDoc stream = (InputStream JavaDoc) it.next();
92          DataInputStream JavaDoc dstream = new DataInputStream JavaDoc(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 JavaDoc
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 JavaDoc it) throws Exception JavaDoc
147    {
148       while (it.hasNext())
149       {
150          InputStream JavaDoc stream = (InputStream JavaDoc) it.next();
151          DataInputStream JavaDoc dstream = new DataInputStream JavaDoc(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 JavaDoc
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 JavaDoc
188    {
189       //Check for Aspect
190
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 JavaDoc[] 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 JavaDoc
229    {
230       //Check for Aspect
231
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 JavaDoc
242    {
243       //Check for InterceptorDef
244
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 JavaDoc[] 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 JavaDoc
290    {
291       //Check for InterceptorDef
292
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 JavaDoc
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 JavaDoc name = cf.getName();
314          String JavaDoc clazz = cf.getName();
315
316          String JavaDoc[] 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 JavaDoc("@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 JavaDoc
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 JavaDoc name = cf.getName();
339          manager.removeDynamicCFlow(name);
340       }
341    }
342
343    private boolean deployPreparedClass(AnnotationsAttribute visible, ClassFile cf) throws Exception JavaDoc
344    {
345       //Check for Aspect
346
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 JavaDoc name = cf.getName() + "." + visible.getName();
353          String JavaDoc 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 JavaDoc
363    {
364       //Check for Aspect
365
javassist.bytecode.annotation.Annotation info = visible.getAnnotation(Prepare.class.getName());
366       if (info != null)
367       {
368          String JavaDoc name = cf.getName() + "." + visible.getName();
369          manager.removePointcut(name);
370       }
371    }
372    
373    private void deployPrecedence(AnnotationsAttribute visible, ClassFile cf)throws Exception JavaDoc
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 JavaDoc entries = new ArrayList JavaDoc();
381          Iterator JavaDoc 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                //TODO Make sure it is an interceptor
391
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 JavaDoc 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 JavaDoc
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 JavaDoc
421    {
422       Iterator JavaDoc 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 JavaDoc pointcutString = binding.pointcut();
432          String JavaDoc 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 JavaDoc(cflow)).CFlowExpression();
438
439          }
440          AdviceFactory factory = new AdviceFactory(def, minfo.getName());
441          manager.addInterceptorFactory(factory.getName(), factory);
442          InterceptorFactory[] fact = {factory};
443          String JavaDoc 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 JavaDoc
453    {
454       Iterator JavaDoc 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 JavaDoc adviceName = cf.getName() + "." + minfo.getName();
464          manager.removeInterceptorFactory(adviceName);
465          String JavaDoc name = getAspectMethodBindingName(cf, minfo);
466          manager.removePointcut(name);
467          manager.removeBinding(name);
468       }
469    }
470
471    private String JavaDoc getAspectMethodBindingName(ClassFile cf, MethodInfo minfo)throws Exception JavaDoc
472    {
473       String JavaDoc method = cf.getName() + "." + minfo.getName();
474       String JavaDoc 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 JavaDoc
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 JavaDoc pointcutString = bind.pointcut();
485       String JavaDoc 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 JavaDoc(cflow)).CFlowExpression();
491
492       }
493
494       String JavaDoc 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 JavaDoc
504    {
505       javassist.bytecode.annotation.Annotation binfo = visible.getAnnotation(Bind.class.getName());
506       if (binfo == null) return;
507
508       String JavaDoc name = cf.getName();
509       manager.removePointcut(name);
510       manager.removeBinding(name);
511    }
512
513
514    private void deployPointcuts(ClassFile cf)
515    throws Exception JavaDoc
516    {
517       Iterator JavaDoc 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 JavaDoc
535    {
536       Iterator JavaDoc 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 JavaDoc getPointcutName(ClassFile cf, FieldInfo finfo)
549    {
550       return cf.getName() + "." + finfo.getName();
551    }
552
553    private void deployMixins(ClassFile cf)
554    throws Exception JavaDoc
555    {
556       Iterator JavaDoc 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          //Since some of the values are of type Class, and method gets called by the system classloader (via Agent)
566
// for loadtime aop in jdk 1.5 the classes we try to look at might not yet have been loaded. We're
567
//only after the names anyway, so we bypass the AnnotationProxy/ProxyMapCreator which tries to validate
568
//class names by loading the (so far) non-existent class.
569

570          //Mixin mixin = (Mixin) AnnotationProxy.createProxy(binfo, Mixin.class);
571
//String target = mixin.target();
572
//String typeExpression = mixin.typeExpression();
573
//String[] interfaces = mixin.interfaces();
574
//boolean isTransient = mixin.isTransient();
575

576          MemberValue mv = binfo.getMemberValue("target");
577          String JavaDoc target = (mv != null) ? ((ClassMemberValue) mv).getValue() : "java.lang.Class";//Note! this should be the same as the default in @Mixin
578

579          mv = binfo.getMemberValue("typeExpression");
580          String JavaDoc typeExpression = (mv != null) ? ((StringMemberValue) mv).getValue() : "";//Note! this should be the same as the default in @Mixin
581

582          mv = binfo.getMemberValue("interfaces");
583          MemberValue[] values = ((ArrayMemberValue) mv).getValue();
584          String JavaDoc[] interfaces = new String JavaDoc[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;//Note! this should be the same as the default in @Mixin
589

590          String JavaDoc name = cf.getName() + "." + minfo.getName(); //Name of the method defined on
591

592          InterfaceIntroduction intro = createIntroduction(name, target, typeExpression, null);
593
594
595          String JavaDoc construction = name + "(this)";
596          
597          //Parse the descriptor to get the returntype of the method.
598
String JavaDoc 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 JavaDoc
607    {
608       Iterator JavaDoc 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 JavaDoc name = cf.getName() + "." + minfo.getName(); //Name of the method defined on
618
manager.removeInterfaceIntroduction(name);
619       }
620    }
621
622    private void deployIntroductions(ClassFile cf)
623    throws Exception JavaDoc
624    {
625       Iterator JavaDoc 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          //Since some of the values are of type Class, and method gets called by the system classloader (via Agent)
635
// for loadtime aop in jdk 1.5 the classes we try to look at might not yet have been loaded. We're
636
//only after the names anyway, so we bypass the AnnotationProxy/ProxyMapCreator which tries to validate
637
//class names by loading the (so far) non-existent class.
638

639          //Introduction introduction = (Introduction) AnnotationProxy.createProxy(binfo, Introduction.class);
640
//String target = introduction.target();
641
//String typeExpression = introduction.typeExpression();
642
//String[] interfaces = introduction.interfaces();
643

644          MemberValue mv = binfo.getMemberValue("target");
645          String JavaDoc target = (mv != null) ? ((ClassMemberValue) mv).getValue() : "java.lang.Class";//Note! this should be the same as the default in @Interceptor
646

647          mv = binfo.getMemberValue("typeExpression");
648          String JavaDoc typeExpression = (mv != null) ? ((StringMemberValue) mv).getValue() : "";//Note! this should be the same as the default in @Interceptor
649

650          mv = binfo.getMemberValue("interfaces");
651          MemberValue[] values = ((ArrayMemberValue) mv).getValue();
652          String JavaDoc[] interfaces = new String JavaDoc[values.length];
653          for (int i = 0; i < values.length; i++) interfaces[i] = ((ClassMemberValue) values[i]).getValue();
654
655          String JavaDoc name = cf.getName() + "." + finfo.getName(); //Name of the field defined on
656

657          InterfaceIntroduction interfaceIntro = createIntroduction(name, target, typeExpression, interfaces);
658          manager.addInterfaceIntroduction(interfaceIntro);
659       }
660    }
661
662    private void undeployIntroductions(ClassFile cf)
663    throws Exception JavaDoc
664    {
665       Iterator JavaDoc 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 JavaDoc name = cf.getName() + "." + finfo.getName(); //Name of the field defined on
675

676          manager.removeInterfaceIntroduction(name);
677       }
678    }
679
680    private void deployTypedefs(ClassFile cf) throws Exception JavaDoc
681    {
682       Iterator JavaDoc 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 JavaDoc name = getTypedefName(cf, finfo);
693          String JavaDoc 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 JavaDoc
701    {
702       Iterator JavaDoc 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 JavaDoc getTypedefName(ClassFile cf, FieldInfo finfo)
719    {
720       return cf.getName() + "." + finfo.getName();
721    }
722
723    private void deployCFlowStackDefs(ClassFile cf) throws Exception JavaDoc
724    {
725       Iterator JavaDoc 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 JavaDoc 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 JavaDoc
751    {
752       Iterator JavaDoc 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 JavaDoc getStackDefName(ClassFile cf, FieldInfo finfo)
767    {
768       return cf.getName() + "." + finfo.getName();
769    }
770
771    private void deployPrepares(ClassFile cf) throws Exception JavaDoc
772    {
773       Iterator JavaDoc 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 JavaDoc name = getPrepareName(cf, finfo);
784          String JavaDoc 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 JavaDoc
791    {
792       Iterator JavaDoc 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 JavaDoc getPrepareName(ClassFile cf, FieldInfo finfo)
807    {
808       return cf.getName() + "." + finfo.getName();
809    }
810    
811    private void deployAnnotationIntroductions(ClassFile cf) throws Exception JavaDoc
812    {
813       Iterator JavaDoc 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 JavaDoc expr = intro.expr();
824          boolean invisible = intro.invisible();
825          String JavaDoc 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 JavaDoc
835    {
836       Iterator JavaDoc 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 JavaDoc expr = intro.expr();
847          boolean invisible = intro.invisible();
848          String JavaDoc 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 JavaDoc
858    {
859       Iterator JavaDoc 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 JavaDoc name = getDeclareName(cf, finfo);
870          if (dwinfo != null && deinfo != null) throw new RuntimeException JavaDoc("Cannot annotate " + name + " field with both DeclareError and DeclareWarning");
871          
872          String JavaDoc expr = null;
873          String JavaDoc 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 JavaDoc getDeclareName(ClassFile cf, FieldInfo finfo)
895    {
896       return cf.getName() + "." + finfo.getName();
897    }
898
899    private InterfaceIntroduction createIntroduction(String JavaDoc name, String JavaDoc target, String JavaDoc typeExpression, String JavaDoc[] interfaces)
900    throws Exception JavaDoc
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 JavaDoc("No target nor a typeExpression attribute is defined for this @Mixin");
915       }
916
917       if (target == null && typeExpression == null)
918       {
919          throw new RuntimeException JavaDoc("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 JavaDoc(typeExpression)).Start();
932          intro = new InterfaceIntroduction(name, start, interfaces);
933       }
934
935       return intro;
936    }
937
938    private String JavaDoc getReturnType(MethodInfo minfo)
939    {
940       String JavaDoc descriptor = minfo.getDescriptor();
941       int paramsEnd = descriptor.indexOf(";)");
942       String JavaDoc classname = descriptor.substring(paramsEnd + 3, descriptor.length() - 1);
943       classname = classname.replace('/', '.');
944       return classname;
945    }
946    
947    private String JavaDoc getFieldType(FieldInfo finfo)
948    {
949       //This will be of the form: Lorg/jboss/test/aop/annotated/AspectPerClass;
950
String JavaDoc descriptor = finfo.getDescriptor();
951       String JavaDoc classname = descriptor.substring(1, descriptor.length() - 1);
952       classname = classname.replace('/', '.');
953       return classname;
954    }
955
956    /**
957     * Replace all occurrences of 'this' unless it happens to be part of
958     * another word. For example (if class name is org.acme.Foo:
959     * "all(this)" -> "all(org.acme.Foo)"
960     * "all(org.Forthis)" -> "all(org.Forthis)"
961     * "all(org.thisthing.Foo)" -> "all(org.thisthing.Foo)"
962     *
963     * @param s
964     * @param classname
965     * @return
966     */

967    private static String JavaDoc replaceThisInExpr(String JavaDoc expr, String JavaDoc classname)
968    {
969       final String JavaDoc THIS = "this";
970
971       StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
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