KickJava   Java API By Example, From Geeks To Geeks.

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


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 gnu.trove.TLongObjectHashMap;
25
26 import java.lang.ref.WeakReference JavaDoc;
27 import java.lang.reflect.Constructor JavaDoc;
28 import java.lang.reflect.Field JavaDoc;
29 import java.lang.reflect.Method JavaDoc;
30 import java.security.AccessController JavaDoc;
31 import java.security.PrivilegedActionException JavaDoc;
32 import java.security.PrivilegedExceptionAction JavaDoc;
33 import java.util.ArrayList JavaDoc;
34 import java.util.HashMap JavaDoc;
35 import java.util.HashSet JavaDoc;
36 import java.util.List JavaDoc;
37 import java.util.Map JavaDoc;
38 import java.util.Set JavaDoc;
39
40 import javassist.CtClass;
41 import javassist.CtConstructor;
42 import javassist.CtField;
43 import javassist.CtMethod;
44
45 import org.jboss.aop.ClassAdvisor.RebuildInterceptorsAction;
46 import org.jboss.aop.advice.AdviceBinding;
47 import org.jboss.aop.advice.AspectDefinition;
48 import org.jboss.aop.advice.CFlowInterceptor;
49 import org.jboss.aop.advice.GeneratedOnly;
50 import org.jboss.aop.advice.Interceptor;
51 import org.jboss.aop.advice.InterceptorFactory;
52 import org.jboss.aop.advice.PrecedenceSorter;
53 import org.jboss.aop.annotation.AnnotationElement;
54 import org.jboss.aop.annotation.AnnotationRepository;
55 import org.jboss.aop.instrument.ConstructionTransformer;
56 import org.jboss.aop.instrument.ConstructorExecutionTransformer;
57 import org.jboss.aop.instrument.FieldAccessTransformer;
58 import org.jboss.aop.introduction.AnnotationIntroduction;
59 import org.jboss.aop.introduction.InterfaceIntroduction;
60 import org.jboss.aop.joinpoint.ConstructorJoinpoint;
61 import org.jboss.aop.joinpoint.Invocation;
62 import org.jboss.aop.joinpoint.InvocationResponse;
63 import org.jboss.aop.joinpoint.Joinpoint;
64 import org.jboss.aop.joinpoint.MethodInvocation;
65 import org.jboss.aop.joinpoint.MethodJoinpoint;
66 import org.jboss.aop.metadata.ClassMetaDataBinding;
67 import org.jboss.aop.metadata.ConstructorMetaData;
68 import org.jboss.aop.metadata.FieldMetaData;
69 import org.jboss.aop.metadata.MethodMetaData;
70 import org.jboss.aop.metadata.SimpleMetaData;
71 import org.jboss.aop.pointcut.PointcutMethodMatch;
72 import org.jboss.repository.spi.MetaDataContext;
73 import org.jboss.util.NestedRuntimeException;
74
75 import EDU.oswego.cs.dl.util.concurrent.ConcurrentReaderHashMap;
76 import EDU.oswego.cs.dl.util.concurrent.CopyOnWriteArraySet;
77
78 /**
79  * @author <a HREF="mailto:bill@jboss.org">Bill Burke</a>
80  * @version $Revision: 57019 $
81  */

82 public abstract class Advisor
83 {
84    public MethodInfo getMethodInfo(long hash)
85    {
86       return (MethodInfo)methodInterceptors.get(hash);
87    }
88    
89    private class AdviceInterceptorKey
90    {
91       private String JavaDoc adviceName;
92       private Joinpoint joinpoint;
93       private int hash;
94
95       public AdviceInterceptorKey(String JavaDoc adviceName, Joinpoint joinpoint)
96       {
97          this.adviceName = adviceName;
98          this.joinpoint = joinpoint;
99          hash = adviceName.hashCode();
100          hash = 29 * hash + (joinpoint != null ? joinpoint.hashCode() : 0);
101       }
102
103       public boolean equals(Object JavaDoc o)
104       {
105          if (this == o) return true;
106          if (!(o instanceof AdviceInterceptorKey)) return false;
107
108          final AdviceInterceptorKey adviceInterceptorKey = (AdviceInterceptorKey) o;
109
110          if (!adviceName.equals(adviceInterceptorKey.adviceName)) return false;
111          if (joinpoint != null ? !joinpoint.equals(adviceInterceptorKey.joinpoint) : adviceInterceptorKey.joinpoint != null) return false;
112
113          return true;
114       }
115
116       public int hashCode()
117       {
118          return hash;
119       }
120    }
121
122
123    protected HashSet JavaDoc adviceBindings = new HashSet JavaDoc();
124    protected ArrayList JavaDoc interfaceIntroductions = new ArrayList JavaDoc();
125    protected ArrayList JavaDoc classMetaDataBindings = new ArrayList JavaDoc();
126    protected SimpleMetaData defaultMetaData = new SimpleMetaData();
127    protected MethodMetaData methodMetaData = new MethodMetaData();
128    protected FieldMetaData fieldMetaData = new FieldMetaData();
129    protected SimpleMetaData classMetaData = new SimpleMetaData();
130    protected ConstructorMetaData constructorMetaData = new ConstructorMetaData();
131    protected HashMap classAnnotations = new HashMap();
132    protected AnnotationRepository annotations = new AnnotationRepository();
133    protected boolean doesHaveAspects = false;
134
135    protected String JavaDoc name;
136    protected ConcurrentReaderHashMap aspects = new ConcurrentReaderHashMap();
137    protected HashMap adviceInterceptors = new HashMap();
138    protected CopyOnWriteArraySet perInstanceAspectDefinitions = new CopyOnWriteArraySet();
139    protected ConcurrentReaderHashMap perInstanceJoinpointAspectDefinitions = new ConcurrentReaderHashMap();
140
141    static Class JavaDoc cl = java.lang.String JavaDoc.class;
142    protected TLongObjectHashMap advisedMethods = new TLongObjectHashMap();
143    // The method signatures are sorted at transformation and load time to
144
// make sure the tables line up.
145
protected TLongObjectHashMap methodInterceptors = new TLongObjectHashMap();
146    protected AspectManager manager;
147    protected Class JavaDoc clazz = null;
148    protected Constructor JavaDoc[] constructors;
149
150    /** @deprecated Use constructorInfos instead */
151    protected Interceptor[][] constructorInterceptors;
152    protected ConstructorInfo[] constructorInfos; //This should replace constructorInterceptors
153

154    /** @deprecated Use constructorInfos instead */
155    protected Interceptor[][] constructionInterceptors;
156    protected ConstructionInfo[] constructionInfos;
157    
158    
159    //FIXME - make metaDataContext a MetaDataContext once MC 2.0 is released
160
MetaDataContext metadataContext;
161
162    public Advisor(String JavaDoc name, AspectManager manager)
163    {
164       this.name = name;
165       this.manager = manager;
166    }
167
168    public Constructor JavaDoc[] getConstructors()
169    {
170       return constructors;
171    }
172
173    /** @deprecated Use getConstructorInfos instead*/
174    public Interceptor[][] getConstructorInterceptors()
175    {
176       return constructorInterceptors;
177    }
178
179    public ConstructorInfo[] getConstructorInfos()
180    {
181       return constructorInfos;
182    }
183
184    /** @deprecated Use getConstructionInfos instead*/
185    public Interceptor[][] getConstructionInterceptors()
186    {
187       return constructionInterceptors;
188    }
189
190    public ConstructionInfo[] getConstructionInfos()
191    {
192       return constructionInfos;
193    }
194
195    /**
196     * @deprecated Need a better mechanism to override the
197     * methods seen by pointcuts, e.g. those provided
198     * by a "proxy advisor"
199     */

200    public Method JavaDoc[] getAllMethods()
201    {
202       return null;
203    }
204
205    public AspectManager getManager()
206    {
207       return manager;
208    }
209    
210    /**
211     * For use by generated advisors. They will explicitly set the manager
212     * @param name
213     */

214    protected void setManager(AspectManager manager)
215    {
216       this.manager = manager;
217    }
218
219
220    public List JavaDoc getClassMetadataBindings()
221    {
222       return classMetaDataBindings;
223    }
224
225    public SimpleMetaData getClassMetaData()
226    {
227       return classMetaData;
228    }
229
230    public SimpleMetaData getDefaultMetaData()
231    {
232       return defaultMetaData;
233    }
234
235    public MethodMetaData getMethodMetaData()
236    {
237       return methodMetaData;
238    }
239    
240    public FieldMetaData getFieldMetaData()
241    {
242       return fieldMetaData;
243    }
244
245    public ConstructorMetaData getConstructorMetaData()
246    {
247       return constructorMetaData;
248    }
249
250    /* (non-Javadoc)
251     * @see org.jboss.aop.AdvisorIF#deployAnnotationOverrides()
252     */

253    public void deployAnnotationOverrides()
254    {
255       List JavaDoc annotationOverrides = getManager().getAnnotationOverrides();
256       if (annotationOverrides != null)
257       {
258          for (int i = 0; i < annotationOverrides.size(); ++i)
259          {
260             AnnotationIntroduction introduction = (AnnotationIntroduction) annotationOverrides.get(i);
261             deployAnnotationOverride(introduction);
262          }
263       }
264    }
265    
266    public void deployAnnotationOverride(AnnotationIntroduction introduction)
267    {
268       if (System.getSecurityManager() == null)
269       {
270          DeployAnnotationOverrideAction.NON_PRIVILEGED.deploy(this, introduction);
271       }
272       else
273       {
274          DeployAnnotationOverrideAction.PRIVILEGED.deploy(this, introduction);
275       }
276    }
277
278    public void doDeployAnnotationOverride(AnnotationIntroduction introduction)
279    {
280       if (introduction.matches(this, clazz))
281       {
282          annotations.addClassAnnotation(introduction.getAnnotation().getIdentifier(), introduction.getOriginalAnnotationExpr());
283       }
284
285       Class JavaDoc theClass = clazz;
286
287       deployMethodAnnotationOverrides(theClass, introduction);
288       Field JavaDoc[] fields = theClass.getDeclaredFields();
289       for (int i = 0; i < fields.length; i++)
290       {
291          if (introduction.matches(this, fields[i]))
292          {
293             annotations.addAnnotation(fields[i], introduction.getAnnotation().getIdentifier(), introduction.getOriginalAnnotationExpr());
294          }
295       }
296       Constructor JavaDoc[] cons = theClass.getDeclaredConstructors();
297       for (int i = 0; i < cons.length; i++)
298       {
299          if (introduction.matches(this, cons[i]))
300          {
301             annotations.addAnnotation(cons[i], introduction.getAnnotation().getIdentifier(), introduction.getOriginalAnnotationExpr());
302          }
303       }
304    }
305
306    protected void initializeInterfaceIntroductions(Class JavaDoc theClass)
307    {
308       manager.applyInterfaceIntroductions(this, theClass);
309    }
310    
311    protected void deployMethodAnnotationOverrides(Class JavaDoc theClass, AnnotationIntroduction introduction)
312    {
313       if (theClass.getSuperclass() != null)
314       {
315          deployMethodAnnotationOverrides(theClass.getSuperclass(), introduction);
316       }
317       Method JavaDoc[] methods = theClass.getDeclaredMethods();
318       for (int i = 0; i < methods.length; i++)
319       {
320          if (introduction.matches(this, methods[i]))
321          {
322             annotations.addAnnotation(methods[i], introduction.getAnnotation().getIdentifier(), introduction.getOriginalAnnotationExpr());
323          }
324       }
325    }
326
327
328    public AnnotationRepository getAnnotations()
329    {
330       return annotations;
331    }
332
333    public Object JavaDoc resolveAnnotation(Class JavaDoc annotation)
334    {
335       if (metadataContext != null)
336       {
337          Object JavaDoc value = metadataContext.getAnnotation(annotation);
338          if (value != null) return value;
339       }
340       
341       if (annotations.isDisabled(annotation))
342          return null;
343       
344       Object JavaDoc value = annotations.resolveClassAnnotation(annotation);
345       if (clazz == null) return null;
346       if (value == null) value = AnnotationElement.getVisibleAnnotation(clazz, annotation);
347       return value;
348    }
349
350    public boolean hasAnnotation(String JavaDoc annotation)
351    {
352       return hasAnnotation(clazz, annotation);
353    }
354
355    public boolean hasAnnotation(Class JavaDoc tgt, String JavaDoc annotation)
356    {
357       if (metadataContext != null)
358       {
359          if (metadataContext.hasAnnotation(annotation)) return true;
360       }
361       if (annotations.hasClassAnnotation(annotation)) return true;
362       if (tgt == null) return false;
363       try
364       {
365          return AnnotationElement.isAnyAnnotationPresent(tgt, annotation);
366       }
367       catch (Exception JavaDoc e)
368       {
369          throw new RuntimeException JavaDoc(e); //To change body of catch statement use Options | File Templates.
370
}
371    }
372
373    public Object JavaDoc resolveAnnotation(Method JavaDoc m, Class JavaDoc annotation)
374    {
375       if (metadataContext != null)
376       {
377          Object JavaDoc val = metadataContext.getAnnotation(m, annotation);
378          if (val != null) return val;
379       }
380       
381       if (annotations.isDisabled(m,annotation))
382          return null;
383       
384       Object JavaDoc value = annotations.resolveAnnotation(m, annotation);
385       if (value == null) value = AnnotationElement.getVisibleAnnotation(m, annotation);
386       return value;
387    }
388    
389    public Object JavaDoc resolveAnnotation(Method JavaDoc m, Class JavaDoc[] annotationChoices)
390    {
391       Object JavaDoc value = null;
392       int i = 0;
393       while (value == null && i < annotationChoices.length){
394          value = annotations.resolveAnnotation(m, annotationChoices[i++]);
395       }
396       
397       i = 0;
398       while (value == null && i < annotationChoices.length){
399          value = AnnotationElement.getVisibleAnnotation(m, annotationChoices[i++]);
400       }
401       return value;
402    }
403
404    public Object JavaDoc resolveAnnotation(Field JavaDoc f, Class JavaDoc annotation)
405    {
406       Object JavaDoc value = annotations.resolveAnnotation(f, annotation);
407       if (value == null) value = AnnotationElement.getVisibleAnnotation(f, annotation);
408       return value;
409    }
410
411    public Object JavaDoc resolveAnnotation(Constructor JavaDoc c, Class JavaDoc annotation)
412    {
413       Object JavaDoc value = annotations.resolveAnnotation(c, annotation);
414       if (value == null) value = AnnotationElement.getVisibleAnnotation(c, annotation);
415       return value;
416    }
417
418    public boolean hasAnnotation(Method JavaDoc m, String JavaDoc annotation)
419    {
420       if (metadataContext != null)
421       {
422          if (metadataContext.hasAnnotation(m, annotation)) return true;
423       }
424       
425       if (annotations.hasAnnotation(m, annotation)) return true;
426       try
427       {
428          return AnnotationElement.isAnyAnnotationPresent(m, annotation);
429       }
430       catch (Exception JavaDoc e)
431       {
432          throw new RuntimeException JavaDoc(e); //To change body of catch statement use Options | File Templates.
433
}
434    }
435
436    public boolean hasAnnotation(Field JavaDoc m, String JavaDoc annotation)
437    {
438       if (annotations.hasAnnotation(m, annotation)) return true;
439       try
440       {
441          return AnnotationElement.isAnyAnnotationPresent(m, annotation);
442       }
443       catch (Exception JavaDoc e)
444       {
445          throw new RuntimeException JavaDoc(e); //To change body of catch statement use Options | File Templates.
446
}
447    }
448
449    public boolean hasAnnotation(Constructor JavaDoc m, String JavaDoc annotation)
450    {
451       if (annotations.hasAnnotation(m, annotation)) return true;
452       try
453       {
454          return AnnotationElement.isAnyAnnotationPresent(m, annotation);
455       }
456       catch (Exception JavaDoc e)
457       {
458          throw new RuntimeException JavaDoc(e); //To change body of catch statement use Options | File Templates.
459
}
460    }
461
462    public boolean hasAnnotation(CtClass clazz, String JavaDoc annotation)
463    {
464       if (annotations.hasClassAnnotation(annotation)) return true;
465       try
466       {
467          return AnnotationElement.isAnyAnnotationPresent(clazz, annotation);
468       }
469       catch (Exception JavaDoc e)
470       {
471          throw new RuntimeException JavaDoc(e); //To change body of catch statement use Options | File Templates.
472
}
473    }
474
475    public boolean hasAnnotation(CtMethod member, String JavaDoc annotation)
476    {
477       // todo these are here so that we can chain configuration domains
478
if (annotations.hasAnnotation(member, annotation)) return true;
479       return AnnotationElement.isAnyAnnotationPresent(member, annotation);
480    }
481
482    public boolean hasAnnotation(CtField member, String JavaDoc annotation)
483    {
484       // todo these are here so that we can chain configuration domains
485
if (annotations.hasAnnotation(member, annotation)) return true;
486       return AnnotationElement.isAnyAnnotationPresent(member, annotation);
487    }
488
489    public boolean hasAnnotation(CtConstructor member, String JavaDoc annotation)
490    {
491       // todo these are here so that we can chain configuration domains
492
if (annotations.hasAnnotation(member, annotation)) return true;
493       return AnnotationElement.isAnyAnnotationPresent(member, annotation);
494    }
495    
496    public MetaDataContext getMetadataContext()
497    {
498       return metadataContext;
499    }
500
501    public void setMetadataContext(/*MetaDataContext*/ Object JavaDoc metadataContext)
502    {
503       this.metadataContext = (MetaDataContext)metadataContext;
504    }
505
506    public String JavaDoc getName()
507    {
508       return name;
509    }
510
511    public final boolean hasAspects()
512    {
513       return doesHaveAspects;
514    }
515    
516    public synchronized void removeAdviceBinding(AdviceBinding binding)
517    {
518       adviceBindings.remove(binding);
519       rebuildInterceptors();
520       doesHaveAspects = adviceBindings.size() > 0;
521    }
522
523    public synchronized void removeAdviceBindings(ArrayList JavaDoc bindings)
524    {
525       adviceBindings.removeAll(bindings);
526       rebuildInterceptors();
527       doesHaveAspects = adviceBindings.size() > 0;
528    }
529
530    /**
531     * a new binding has been added to the AspectManager, recalculate interceptors
532     */

533    public synchronized void newBindingAdded()
534    {
535       rebuildInterceptors();
536       doesHaveAspects = adviceBindings.size() > 0;
537    }
538
539    public ArrayList JavaDoc getInterfaceIntroductions()
540    {
541       return interfaceIntroductions;
542    }
543
544    public synchronized void addInterfaceIntroduction(InterfaceIntroduction pointcut)
545    {
546       interfaceIntroductions.add(pointcut);
547    }
548
549    public synchronized void removeInterfaceIntroduction(InterfaceIntroduction pointcut)
550    {
551       interfaceIntroductions.remove(pointcut);
552    }
553
554    protected abstract void rebuildInterceptors();
555
556    ////////////////////////////////
557
// Metadata. Metadata will be used for things like Transaction attributes (Required, RequiresNew, etc...)
558
//
559

560    public abstract void addClassMetaData(ClassMetaDataBinding data);
561
562    public abstract void removeClassMetaData(ClassMetaDataBinding data);
563
564    // This is aspect stuff. Aspect again, is a class that encapsulates advices
565

566    public void addPerInstanceAspect(AspectDefinition def)
567    {
568       perInstanceAspectDefinitions.add(def);
569    }
570
571    public void removePerInstanceAspect(AspectDefinition def)
572    {
573       perInstanceAspectDefinitions.remove(def);
574    }
575
576    public Set JavaDoc getPerInstanceAspectDefinitions()
577    {
578       return perInstanceAspectDefinitions;
579    }
580
581    // This is aspect stuff. Aspect again, is a class that encapsulates advices
582

583    public void addPerInstanceJoinpointAspect(Joinpoint joinpoint, AspectDefinition def)
584    {
585       Set JavaDoc joinpoints = (Set JavaDoc) perInstanceJoinpointAspectDefinitions.get(def);
586       if (joinpoints == null)
587       {
588          joinpoints = new CopyOnWriteArraySet();
589          perInstanceJoinpointAspectDefinitions.put(def, joinpoints);
590       }
591       joinpoints.add(joinpoint);
592    }
593   
594    public void removePerInstanceJoinpointAspect(AspectDefinition def)
595    {
596       perInstanceJoinpointAspectDefinitions.remove(def);
597    }
598
599    public Map getPerInstanceJoinpointAspectDefinitions()
600    {
601       return perInstanceJoinpointAspectDefinitions;
602    }
603
604    public Object JavaDoc getPerClassAspect(AspectDefinition def)
605    {
606       return aspects.get(def.getName());
607    }
608
609    public Object JavaDoc getPerClassAspect(String JavaDoc def)
610    {
611       return aspects.get(def);
612    }
613
614    public void addPerClassAspect(AspectDefinition def)
615    {
616       if (aspects.containsKey(def.getName())) return;
617       Object JavaDoc aspect = def.getFactory().createPerClass(this);
618       aspects.put(def.getName(), aspect);
619    }
620
621    public void removePerClassAspect(AspectDefinition def)
622    {
623       aspects.remove(def.getName());
624       adviceInterceptors.remove(def);
625    }
626
627    public Interceptor getAdviceInterceptor(AspectDefinition def, String JavaDoc adviceName, Joinpoint joinpoint)
628    {
629       AdviceInterceptorKey key = new AdviceInterceptorKey(adviceName, joinpoint);
630       synchronized (adviceInterceptors)
631       {
632          Map map = null;
633          map = (Map) adviceInterceptors.get(def);
634          if (map != null)
635          {
636             return (Interceptor) map.get(key);
637          }
638       }
639       return null;
640    }
641
642    public void addAdviceInterceptor(AspectDefinition def, String JavaDoc adviceName, Interceptor interceptor, Joinpoint joinpoint)
643    {
644       synchronized (adviceInterceptors)
645       {
646          Map map = (Map) adviceInterceptors.get(def);
647          if (map == null)
648          {
649             map = new HashMap();
650             adviceInterceptors.put(def, map);
651          }
652          map.put(adviceName, interceptor);
653       }
654    }
655
656
657    protected void createInterceptorChain(InterceptorFactory[] factories, ArrayList JavaDoc newinterceptors, Joinpoint joinpoint)
658    {
659       for (int i = 0; i < factories.length; i++)
660       {
661          if (factories[i] instanceof GeneratedOnly)
662          {
663             throw new RuntimeException JavaDoc("Before/After/Throwing is only supported for Generated Advisors");
664          }
665          if (factories[i].isDeployed()) newinterceptors.add(factories[i].create(this, joinpoint));
666       }
667    }
668
669    protected void resolveMethodPointcut(MethodInterceptors newMethodInterceptors, AdviceBinding binding)
670    {
671       long[] keys = advisedMethods.keys();
672       for (int i = 0; i < keys.length; i++)
673       {
674          Method JavaDoc method = (Method JavaDoc) advisedMethods.get(keys[i]);
675          PointcutMethodMatch match = binding.getPointcut().matchesExecution(this, method);
676          
677          if (match != null && match.isMatch())
678          {
679             adviceBindings.add(binding);
680             if (AspectManager.verbose)
681             {
682                /*
683                RepositoryClassLoader loader = (RepositoryClassLoader)clazz.getClassLoader();
684                try
685                {
686                   System.err.println("method matched binding " + binding.getPointcut().getExpr() + " " + method.toString() + " " + loader.getObjectName());
687                }
688                catch (MalformedObjectNameException e)
689                {
690                   throw new RuntimeException(e);
691                }
692                */

693                System.err.println("method matched binding " + binding.getPointcut().getExpr() + " " + method.toString());
694
695             }
696             binding.addAdvisor(this);
697             MethodMatchInfo info = newMethodInterceptors.getMatchInfo(keys[i]);
698             info.addMatchedBinding(binding, match);
699          }
700       }
701    }
702    
703    protected void finalizeMethodChain(MethodInterceptors newMethodInterceptors)
704    {
705       TLongObjectHashMap newMethodInfos = new TLongObjectHashMap();
706       
707       long[] keys = newMethodInterceptors.keys();
708       for (int i = 0; i < keys.length; i++)
709       {
710          MethodMatchInfo matchInfo = newMethodInterceptors.getMatchInfo(keys[i]);
711          matchInfo.populateBindings();
712
713          MethodInfo info = matchInfo.getInfo();
714          newMethodInfos.put(keys[i], info);
715          
716          ArrayList JavaDoc list = info.getInterceptorChain();
717          Interceptor[] interceptors = null;
718          if (list.size() > 0)
719          {
720             interceptors = applyPrecedence((Interceptor[]) list.toArray(new Interceptor[list.size()]));
721          }
722          info.setInterceptors(interceptors);
723       }
724       methodInterceptors = newMethodInfos;
725    }
726
727    public InvocationResponse dynamicInvoke(Object JavaDoc target, Invocation invocation)
728    throws Throwable JavaDoc
729    {
730       // Only need to set Method because fields will already have been set.
731
if (invocation instanceof MethodInvocation)
732       {
733          Interceptor[] aspects = null;
734          MethodInvocation methodInvocation = (MethodInvocation) invocation;
735          long hash = methodInvocation.getMethodHash();
736          MethodInfo info = (MethodInfo) methodInterceptors.get(hash);
737          aspects = info.getInterceptors();
738          if (aspects == null) aspects = new Interceptor[0];
739          if (target != null && target instanceof Advised)
740          {
741             InstanceAdvised advised = (InstanceAdvised) target;
742             aspects = advised._getInstanceAdvisor().getInterceptors(aspects);
743          }
744          MethodInvocation nextInvocation = new MethodInvocation(info, aspects);
745          nextInvocation.setMetaData(invocation.getMetaData());
746          nextInvocation.setTargetObject(target);
747          nextInvocation.setArguments(methodInvocation.getArguments());
748          nextInvocation.setAdvisor(this);
749          InvocationResponse response = new InvocationResponse(nextInvocation.invokeNext());
750          response.setContextInfo(nextInvocation.getResponseContextInfo());
751          return response;
752       }
753       throw new RuntimeException JavaDoc("dynamic field invocations not supported yet!");
754    }
755
756    public Class JavaDoc getClazz()
757    {
758       return clazz;
759    }
760
761    void setClazz(Class JavaDoc clazz)
762    {
763       this.clazz = clazz;
764    }
765
766    public static String JavaDoc getSimpleName(Class JavaDoc clazz)
767    {
768       String JavaDoc name = clazz.getName();
769       int lastIndex = name.lastIndexOf('.');
770       if (lastIndex < 0)
771       {
772          return name;
773       }
774       
775       return name.substring(lastIndex + 1);
776    }
777    
778    protected ArrayList JavaDoc initializeConstructorChain()
779    {
780       if (clazz != null && constructors == null)
781       {
782           constructors = clazz.getDeclaredConstructors();
783       }
784       
785       ArrayList JavaDoc newInfos = new ArrayList JavaDoc(constructors.length);
786       for (int i = 0; i < constructors.length; i++)
787       {
788          final ConstructorInfo info = new ConstructorInfo();
789          info.setConstructor(constructors[i]);
790          info.setIndex(i);
791          try
792          {
793             final String JavaDoc name = ConstructorExecutionTransformer.constructorFactory(getSimpleName(clazz));
794             final Class JavaDoc[] types = constructors[i].getParameterTypes();
795             Method JavaDoc method = (Method JavaDoc) AccessController.doPrivileged(new PrivilegedExceptionAction JavaDoc()
796             {
797                public Object JavaDoc run() throws Exception JavaDoc
798                {
799                   return clazz.getDeclaredMethod(name, types);
800                }
801             });
802             info.setWrapper(method);
803          }
804          catch (PrivilegedActionException JavaDoc e1)
805          {
806             Exception JavaDoc e = e1.getException();
807             if (e instanceof NoSuchMethodException JavaDoc == false)
808                throw new NestedRuntimeException(e);
809          }
810
811          info.setAdvisor(this);
812          newInfos.add(info);
813          
814          try
815          {
816             final String JavaDoc name = ConstructorExecutionTransformer.getConstructorInfoFieldName(getSimpleName(clazz), i);
817             AccessController.doPrivileged(new PrivilegedExceptionAction JavaDoc()
818             {
819                public Object JavaDoc run() throws Exception JavaDoc
820                {
821                   Field JavaDoc infoField = clazz.getDeclaredField(name);
822                   infoField.setAccessible(true);
823                   infoField.set(null, new WeakReference JavaDoc(info));
824                   return null;
825                }
826             });
827          }
828          catch (PrivilegedActionException JavaDoc e1)
829          {
830             Exception JavaDoc e = e1.getException();
831             if (e instanceof NoSuchFieldException JavaDoc == false)
832                throw new NestedRuntimeException(e);
833          }
834       }
835       
836       return newInfos;
837    }
838
839    protected ArrayList JavaDoc initializeConstructionChain()
840    {
841       ArrayList JavaDoc newInfos = new ArrayList JavaDoc(constructors.length);
842       for (int i = 0; i < constructors.length; i++)
843       {
844          ConstructionInfo info = new ConstructionInfo();
845          info.setConstructor(constructors[i]);
846          info.setIndex(i);
847          info.setAdvisor(this);
848          newInfos.add(info);
849          
850          try
851          {
852             Field JavaDoc infoField = clazz.getDeclaredField(ConstructionTransformer.getConstructionInfoFieldName(getSimpleName(clazz), i));
853             infoField.setAccessible(true);
854             infoField.set(null, new WeakReference JavaDoc(info));
855          }
856          catch (NoSuchFieldException JavaDoc e)
857          {
858             // ignore, method may not be advised.
859
}
860          catch (IllegalAccessException JavaDoc e)
861          {
862             throw new RuntimeException JavaDoc(e);
863          }
864          
865       }
866       return newInfos;
867    }
868
869    protected void finalizeConstructorChain(ArrayList JavaDoc newConstructorInfos)
870    {
871       for (int i = 0; i < newConstructorInfos.size(); i++)
872       {
873          ConstructorInfo info = (ConstructorInfo) newConstructorInfos.get(i);
874          ArrayList JavaDoc list = info.getInterceptorChain();
875          Interceptor[] interceptors = null;
876          if (list.size() > 0)
877          {
878           interceptors = applyPrecedence((Interceptor[]) list.toArray(new Interceptor[list.size()]));
879          }
880          info.setInterceptors(interceptors);
881       }
882    }
883
884    protected void finalizeConstructionChain(ArrayList JavaDoc newConstructionInfos)
885    {
886       for (int i = 0; i < newConstructionInfos.size(); i++)
887       {
888          ConstructionInfo info = (ConstructionInfo) newConstructionInfos.get(i);
889          ArrayList JavaDoc list = info.getInterceptorChain();
890          Interceptor[] interceptors = null;
891          if (list.size() > 0)
892          {
893           interceptors = applyPrecedence((Interceptor[]) list.toArray(new Interceptor[list.size()]));
894          }
895          info.setInterceptors(interceptors);
896       }
897    }
898
899    protected void resolveConstructorPointcut(ArrayList JavaDoc newConstructorInfos, AdviceBinding binding)
900    {
901       for (int i = 0; i < constructors.length; i++)
902       {
903          Constructor JavaDoc constructor = constructors[i];
904          if (binding.getPointcut().matchesExecution(this, constructor))
905          {
906             if (AspectManager.verbose) System.err.println(constructor + " matched binding " + binding.getName() + " " + binding.getPointcut().getExpr());
907             adviceBindings.add(binding);
908             binding.addAdvisor(this);
909             ConstructorInfo info = (ConstructorInfo)newConstructorInfos.get(i);
910             pointcutResolved(info, binding, new ConstructorJoinpoint(constructor));
911          }
912       }
913    }
914
915    protected void resolveConstructionPointcut(ArrayList JavaDoc newConstructionInfos, AdviceBinding binding)
916    {
917       for (int i = 0; i < constructors.length; i++)
918       {
919          Constructor JavaDoc constructor = constructors[i];
920          if (binding.getPointcut().matchesConstruction(this, constructor))
921          {
922             if (AspectManager.verbose) System.err.println(constructor + " matched binding " + binding.getName() + " " + binding.getPointcut().getExpr());
923             adviceBindings.add(binding);
924             binding.addAdvisor(this);
925             ConstructionInfo info = (ConstructionInfo) newConstructionInfos.get(i);
926             pointcutResolved(info, binding, new ConstructorJoinpoint(constructor));
927          }
928       }
929    }
930
931    /** @deprecated We should just be using xxxxInfos */
932    protected void populateInterceptorsFromInfos()
933    {
934       constructorInterceptors = new Interceptor[constructorInfos.length][];
935       for (int i = 0 ; i < constructorInfos.length ; i++)
936       {
937          constructorInterceptors[i] = constructorInfos[i].getInterceptors();
938       }
939    }
940  
941    /**
942     * Default implementation adds interceptorChain directly to the info.
943     * GeneratedClassAdvisor overrides this
944     */

945    protected void pointcutResolved(JoinPointInfo info, AdviceBinding binding, Joinpoint joinpoint)
946    {
947       ArrayList JavaDoc curr = info.getInterceptorChain();
948       if (binding.getCFlow() != null)
949       {
950          ArrayList JavaDoc cflowChain = new ArrayList JavaDoc();
951          createInterceptorChain(binding.getInterceptorFactories(), cflowChain, joinpoint);
952          Interceptor[] cflowInterceptors = (Interceptor[]) cflowChain.toArray(new Interceptor[cflowChain.size()]);
953          curr.add(new CFlowInterceptor(binding.getCFlowString(), binding.getCFlow(), cflowInterceptors));
954       }
955       else
956       {
957          createInterceptorChain(binding.getInterceptorFactories(), curr, joinpoint);
958       }
959    }
960   
961    Interceptor[] applyPrecedence(Interceptor[] interceptors)
962    {
963       return PrecedenceSorter.applyPrecedence(interceptors, manager);
964    }
965    
966    /**
967     * Whether the type of advisor supports matching on pointcut expression, where the method is defined in a superclass only,
968     * while the pointcut expression class matches the subclass. This is currently only supported for generated advisors, due to
969     * the new weaving model. So (with generated advisors) if we have<BR/>
970     * <code><BR/>
971     * public class Super {<BR/>
972     * &nbsp;&nbsp;void method(){}<BR/>
973     * }<BR/>
974     * <BR/>
975     * public class Sub etxends Super {<BR/>
976     * }<BR/>
977     * </code>
978     * and<BR/>
979     * <code>
980     * &lt;bind pointcut="execution(* Super->method())"&gt;<BR/>
981     * &nbsp;&nbsp;&lt;interceptor class="A"/&gt;<BR/>
982     * &lt;/bind&gt;<BR/>
983     * &lt;bind pointcut="execution(* sub->method())"&gt;<BR/>
984     * &nbsp;&nbsp;&lt;interceptor class="B"/&gt;<BR/>
985     * &lt;/bind&gt;<BR/>
986     * </code><BR/>
987     * Super.method() will be intercepted by A only<BR/>
988     * Sub.method() will be intercepted by A and B
989     *
990     */

991    public boolean chainOverridingForInheritedMethods()
992    {
993       return false;
994    }
995    
996    interface DeployAnnotationOverrideAction
997    {
998       void deploy(Advisor advisor, AnnotationIntroduction introduction);
999       
1000      DeployAnnotationOverrideAction PRIVILEGED = new DeployAnnotationOverrideAction()
1001      {
1002         public void deploy(final Advisor advisor, final AnnotationIntroduction introduction)
1003         {
1004            try
1005            {
1006               AccessController.doPrivileged(new PrivilegedExceptionAction JavaDoc()
1007               {
1008                  public Object JavaDoc run()
1009                  {
1010                     advisor.doDeployAnnotationOverride(introduction);
1011                     return null;
1012                  }
1013               });
1014            }
1015            catch (PrivilegedActionException JavaDoc e)
1016            {
1017               Exception JavaDoc ex = e.getException();
1018               if (ex instanceof RuntimeException JavaDoc)
1019               {
1020                  throw (RuntimeException JavaDoc)ex;
1021               }
1022               throw new RuntimeException JavaDoc(ex);
1023            }
1024         }
1025      };
1026
1027      DeployAnnotationOverrideAction NON_PRIVILEGED = new DeployAnnotationOverrideAction()
1028      {
1029         public void deploy(Advisor advisor, AnnotationIntroduction introduction)
1030         {
1031            advisor.doDeployAnnotationOverride(introduction);
1032         }
1033      };
1034   }
1035}
Popular Tags