KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb3 > interceptor > InterceptorInfoRepository


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.ejb3.interceptor;
23
24 import org.jboss.ejb3.EJBContainer;
25 import org.jboss.ejb3.metamodel.EjbJarDD;
26 import org.jboss.ejb3.metamodel.Interceptor;
27 import org.jboss.ejb3.metamodel.InterceptorBinding;
28 import org.jboss.ejb3.metamodel.Interceptors;
29 import org.jboss.logging.Logger;
30
31 import javax.annotation.PostConstruct;
32 import javax.annotation.PreDestroy;
33 import javax.ejb.PostActivate JavaDoc;
34 import javax.ejb.PrePassivate JavaDoc;
35 import javax.interceptor.AroundInvoke;
36 import javax.interceptor.ExcludeClassInterceptors;
37 import javax.interceptor.ExcludeDefaultInterceptors;
38 import javax.interceptor.InvocationContext;
39 import java.lang.annotation.Annotation JavaDoc;
40 import java.lang.reflect.Method JavaDoc;
41 import java.lang.reflect.Modifier JavaDoc;
42 import java.util.*;
43 import java.util.concurrent.ConcurrentHashMap JavaDoc;
44 import java.util.concurrent.ConcurrentMap JavaDoc;
45
46 /**
47  * A repository of interceptor details shared amongst all containers in this deployment.
48  * Interceptors differ from other ejb 3 artifacts in that we can have annotations on the
49  * interceptor classes which are not the ejb container, so we cannot use annotation overrides
50  * on the interceptors themselves.<BR/>
51  * <BR/>
52  * The xml structures get added on deployment.<BR/>
53  * Interceptors only declared by using @Interceptors on the bean class get added on demand.<BR/>
54  *
55  * @author <a HREF="kabir.khan@jboss.com">Kabir Khan</a>
56  * @version $Revision: 56971 $
57  */

58 public class InterceptorInfoRepository
59 {
60    private static Logger log = Logger.getLogger(InterceptorInfoRepository.class);
61
62    private Set<String JavaDoc> beanClasses = new HashSet<String JavaDoc>();
63
64    private Interceptors interceptorsXml;
65
66    private List<InterceptorBinding> bindingsXml;
67
68    private ConcurrentMap JavaDoc<Class JavaDoc, InterceptorInfo> infos = new ConcurrentHashMap JavaDoc<Class JavaDoc, InterceptorInfo>();
69
70    private ConcurrentMap JavaDoc<String JavaDoc, InterceptorInfo> ejbInfos = new ConcurrentHashMap JavaDoc<String JavaDoc, InterceptorInfo>();
71
72    private LinkedHashSet<InterceptorInfo> defaultInterceptors = null;
73    
74    private InterceptorSorter sorter = new InterceptorSorter();
75
76    public InterceptorInfoRepository()
77    {
78    }
79
80    public void initialise(EjbJarDD dd)
81    {
82       this.interceptorsXml = dd.getInterceptors();
83
84       if (dd.getAssemblyDescriptor() != null)
85       {
86          this.bindingsXml = dd.getAssemblyDescriptor().getInterceptorBindings();
87       }
88       
89       initialiseInfosFromXml();
90       initialiseDefaultInterceptors();
91    }
92
93    public void addBeanClass(String JavaDoc classname)
94    {
95       beanClasses.add(classname);
96    }
97
98    public InterceptorInfo getInterceptorInfo(Class JavaDoc clazz)
99    {
100       initialiseInfosFromXml();
101       return infos.get(clazz);
102    }
103
104    public HashSet<InterceptorInfo> getDefaultInterceptors()
105    {
106       return defaultInterceptors;
107    }
108
109    public boolean hasDefaultInterceptors()
110    {
111       return defaultInterceptors.size() > 0;
112    }
113
114    public ArrayList<InterceptorInfo> getClassInterceptors(EJBContainer container)
115    {
116       javax.interceptor.Interceptors interceptors = (javax.interceptor.Interceptors) container
117             .resolveAnnotation(javax.interceptor.Interceptors.class);
118       ArrayList<InterceptorInfo> infos = getInterceptorsFromAnnotation(container, interceptors);
119
120       return infos;
121    }
122
123    public ArrayList<InterceptorInfo> getMethodInterceptors(EJBContainer container, Method JavaDoc m)
124    {
125       javax.interceptor.Interceptors interceptors = (javax.interceptor.Interceptors) container.resolveAnnotation(m,
126             javax.interceptor.Interceptors.class);
127       ArrayList<InterceptorInfo> infos = getInterceptorsFromAnnotation(container, interceptors);
128
129       return infos;
130    }
131
132    public Method JavaDoc[] getBeanClassAroundInvokes(EJBContainer container)
133    {
134       return getBeanClassInterceptors(container, AroundInvoke.class);
135    }
136
137    public Method JavaDoc[] getBeanClassPostConstructs(EJBContainer container)
138    {
139       return getBeanClassInterceptors(container, PostConstruct.class);
140    }
141
142    public Method JavaDoc[] getBeanClassPostActivates(EJBContainer container)
143    {
144       return getBeanClassInterceptors(container, PostActivate JavaDoc.class);
145    }
146
147    public Method JavaDoc[] getBeanClassPrePassivates(EJBContainer container)
148    {
149       return getBeanClassInterceptors(container, PrePassivate JavaDoc.class);
150    }
151
152    public Method JavaDoc[] getBeanClassPreDestroys(EJBContainer container)
153    {
154       return getBeanClassInterceptors(container, PreDestroy.class);
155    }
156
157    private Method JavaDoc[] getBeanClassInterceptors(EJBContainer container, Class JavaDoc type)
158    {
159       InterceptorInfo info = getOrInitialiseFromAnnotations(container);
160       return getMethodsForEvent(info, type);
161    }
162
163    public InterceptorInfo[] getBusinessInterceptors(EJBContainer container, Method JavaDoc method)
164    {
165       return getInterceptors(container, AroundInvoke.class, method);
166    }
167
168    public InterceptorInfo[] getPostConstructInterceptors(EJBContainer container)
169    {
170       return getInterceptors(container, PostConstruct.class, null);
171    }
172
173    public InterceptorInfo[] getPostActivateInterceptors(EJBContainer container)
174    {
175       return getInterceptors(container, PostActivate JavaDoc.class, null);
176    }
177
178    public InterceptorInfo[] getPrePassivateInterceptors(EJBContainer container)
179    {
180       return getInterceptors(container, PrePassivate JavaDoc.class, null);
181    }
182
183    public InterceptorInfo[] getPreDestroyInterceptors(EJBContainer container)
184    {
185       return getInterceptors(container, PreDestroy.class, null);
186    }
187
188    private InterceptorInfo[] getInterceptors(EJBContainer container, Class JavaDoc type, Method JavaDoc method)
189    {
190       ArrayList<InterceptorInfo> interceptors = new ArrayList<InterceptorInfo>();
191
192       if (!hasAnnotation(container, ExcludeDefaultInterceptors.class, method))
193       {
194          HashSet<InterceptorInfo> infos = getDefaultInterceptors();
195          if (infos != null)
196          {
197             interceptors.addAll(trimUnwanted(infos, type));
198          }
199          sorter.sortDefaultInterceptors(container, interceptors);
200       }
201
202       
203       if (!hasAnnotation(container, ExcludeClassInterceptors.class, method))
204       {
205          List<InterceptorInfo> infos = container.getClassInterceptors();
206          if (infos != null)
207          {
208             interceptors.addAll(trimUnwanted(infos, type));
209          }
210          
211          if (type != AroundInvoke.class)
212          {
213             List<InterceptorInfo> methodOnlyInterceptors = getMethodOnlyInterceptorsForLifecycle(container, type, interceptors);
214             if (infos != null)
215                interceptors.addAll(methodOnlyInterceptors);
216          }
217          sorter.sortClassInterceptors(container, interceptors);
218       }
219
220       if (type == AroundInvoke.class)
221       {
222          List<InterceptorInfo> infos = getMethodInterceptors(container, method);
223          if (infos != null)
224             interceptors.addAll(trimUnwanted(infos, type));
225          sorter.sortMethodInterceptors(container, method, interceptors);
226       }
227
228       InterceptorInfo[] ints = interceptors.toArray(new InterceptorInfo[interceptors.size()]);
229       return ints;
230    }
231
232    private List<InterceptorInfo> getMethodOnlyInterceptorsForLifecycle(EJBContainer container, Class JavaDoc type, List<InterceptorInfo> infos)
233    {
234       HashSet<InterceptorInfo> methodLevelInterceptors = (HashSet<InterceptorInfo>)container.getApplicableInterceptors().clone();
235       
236       for (InterceptorInfo info : infos)
237       {
238          if (methodLevelInterceptors.contains(info))
239          {
240             methodLevelInterceptors.remove(info);
241          }
242       }
243       
244       if (defaultInterceptors != null)
245       {
246          for (InterceptorInfo info : defaultInterceptors)
247          {
248             if (methodLevelInterceptors.contains(info))
249             {
250                methodLevelInterceptors.remove(info);
251             }
252          }
253       }
254       
255       List<InterceptorInfo> trimmedInfos = trimUnwanted(methodLevelInterceptors, type);
256       return trimmedInfos;
257    }
258    
259    private boolean hasAnnotation(EJBContainer container, Class JavaDoc annotation, Method JavaDoc method)
260    {
261       if (container.resolveAnnotation(annotation) != null)
262       {
263          return true;
264       }
265
266       if (method != null)
267       {
268          return container.resolveAnnotation(method, annotation) != null;
269       }
270
271       return false;
272    }
273
274    private List<InterceptorInfo> trimUnwanted(Collection<InterceptorInfo> interceptors, Class JavaDoc type)
275    {
276       ArrayList<InterceptorInfo> ints = new ArrayList<InterceptorInfo>(interceptors.size());
277       ints.addAll(interceptors);
278
279       for (Iterator<InterceptorInfo> it = ints.iterator(); it.hasNext();)
280       {
281          InterceptorInfo info = it.next();
282          if (!hasMethodsForEvent(info, type))
283          {
284             it.remove();
285          }
286       }
287
288       return ints;
289    }
290
291    private boolean hasMethodsForEvent(InterceptorInfo info, Class JavaDoc type)
292    {
293       return getMethodsForEvent(info, type) != null;
294    }
295    
296    private Method JavaDoc[] getMethodsForEvent(InterceptorInfo info, Class JavaDoc type)
297    {
298       if (type == AroundInvoke.class)
299          return info.getAroundInvokes();
300       else if (type == PostConstruct.class)
301          return info.getPostConstructs();
302       else if (type == PostActivate JavaDoc.class)
303          return info.getPostActivates();
304       else if (type == PrePassivate JavaDoc.class)
305          return info.getPrePassivates();
306       else if (type == PreDestroy.class)
307          return info.getPreDestroys();
308       return null;
309    }
310
311    private ArrayList<InterceptorInfo> getInterceptorsFromAnnotation(EJBContainer container,
312          javax.interceptor.Interceptors interceptors)
313    {
314       ArrayList<InterceptorInfo> inters = new ArrayList<InterceptorInfo>();
315       if (interceptors == null)
316          return inters;
317
318       for (Class JavaDoc clazz : interceptors.value())
319       {
320          InterceptorInfo info = getOrInitialiseFromAnnotations(clazz);
321          validateInterceptorForContainer(container, info.getClazz());
322          inters.add(info);
323       }
324
325       return inters;
326    }
327
328    private void validateInterceptorForContainer(EJBContainer container, Class JavaDoc interceptor)
329    {
330       if (beanClasses.contains(interceptor.getName()))
331       {
332          if (!interceptor.equals(container.getClazz()))
333          {
334             throw new RuntimeException JavaDoc("Bean class " + interceptor.getName() + " cannot be used as an interceptor for "
335                   + container.getEjbName());
336          }
337       }
338    }
339
340    private void initialiseInfosFromXml()
341    {
342       if (interceptorsXml != null)
343       {
344          //Initialise all interceptor entries so we know which classes we have xml for
345
HashMap JavaDoc<String JavaDoc, AnnotationInitialiser> initialisers = new HashMap JavaDoc<String JavaDoc, AnnotationInitialiser>();
346          for (Interceptor xml : interceptorsXml.getInterceptors())
347          {
348             XmlInitialiser init = new XmlInitialiser(xml);
349             initialisers.put(xml.getInterceptorClass(), init);
350          }
351
352          //Create entries recursively, top classes first so we get the method hierarchies
353
for (Interceptor xml : interceptorsXml.getInterceptors())
354          {
355             String JavaDoc clazz = xml.getInterceptorClass();
356             initialiseSuperClassesFirstFromXmlOrAnnotations(initialisers, clazz);
357          }
358
359       }
360    }
361
362    private InterceptorInfo initialiseSuperClassesFirstFromXmlOrAnnotations(
363          HashMap JavaDoc<String JavaDoc, AnnotationInitialiser> initialisers, String JavaDoc superClassName)
364    {
365       if ("java.lang.Object".equals(superClassName))
366       {
367          return null;
368       }
369
370       AnnotationInitialiser initialiser = initialisers.get(superClassName);
371       if (initialiser == null)
372       {
373          initialiser = new AnnotationInitialiser(superClassName, InterceptorSignatureValidator.instance);
374          initialisers.put(initialiser.getClazz().getName(), initialiser);
375       }
376       InterceptorInfo superInfo = initialiseSuperClassesFirstFromXmlOrAnnotations(
377             initialisers, initialiser.getClazz().getSuperclass().getName());
378
379       InterceptorInfo info = initialiser.getInfo();
380       info.calculateHierarchy(superInfo);
381       infos.put(info.getClazz(), info);
382       return info;
383    }
384
385    /*
386     * Default interceptors are defined using xml only
387     */

388    private void initialiseDefaultInterceptors()
389    {
390       defaultInterceptors = new LinkedHashSet<InterceptorInfo>();
391
392       if (bindingsXml != null)
393       {
394          for (InterceptorBinding bindingXml : bindingsXml)
395          {
396             if (bindingXml.getEjbName().equals("*")
397                   && (bindingXml.getMethodName() == null || bindingXml.getMethodName().length() == 0))
398             {
399                for (String JavaDoc classname : bindingXml.getInterceptorClasses())
400                {
401                   if (beanClasses.contains(classname))
402                   {
403                      throw new RuntimeException JavaDoc("Bean class defined in default binding " + classname);
404                   }
405                   InterceptorInfo info = getOrInitialiseFromAnnotations(classname);
406                   defaultInterceptors.add(info);
407                }
408             }
409          }
410       }
411    }
412
413    private InterceptorInfo getOrInitialiseFromAnnotations(String JavaDoc classname)
414    {
415       Class JavaDoc clazz = loadClass(classname);
416       return getOrInitialiseFromAnnotations(clazz);
417    }
418
419    private InterceptorInfo getOrInitialiseFromAnnotations(Class JavaDoc clazz)
420    {
421       InterceptorInfo info = infos.get(clazz);
422
423       if (info == null)
424       {
425          synchronized (this)
426          {
427             info = infos.get(clazz);
428             if (info == null)
429             {
430                info = initialiseFromAnnotations(clazz);
431                infos.put(clazz, info);
432             }
433          }
434       }
435
436       return info;
437    }
438
439    private InterceptorInfo initialiseFromAnnotations(Class JavaDoc clazz)
440    {
441       InterceptorInfo superInfo = null;
442       if (clazz.getSuperclass() != Object JavaDoc.class)
443       {
444          superInfo = getOrInitialiseFromAnnotations(clazz.getSuperclass());
445       }
446
447       AnnotationInitialiser init = new AnnotationInitialiser(clazz, InterceptorSignatureValidator.instance);
448       InterceptorInfo info = init.getInfo();
449       info.calculateHierarchy(superInfo);
450       return info;
451    }
452
453    private InterceptorInfo getOrInitialiseFromAnnotations(EJBContainer container)
454    {
455       InterceptorInfo info = ejbInfos.get(container.getEjbName());
456
457       if (info == null)
458       {
459          synchronized (this)
460          {
461             info = ejbInfos.get(container.getEjbName());
462             if (info == null)
463             {
464                info = initialiseFromAnnotations(container);
465                ejbInfos.put(container.getEjbName(), info);
466             }
467          }
468       }
469
470       return info;
471    }
472
473    private InterceptorInfo initialiseFromAnnotations(EJBContainer container)
474    {
475       //Currently I see no way in spec for specifying interceptors of an ejb super class using xml,
476
//use annotations only to initialise super classes, and don't store these
477
InterceptorInfo superInfo = initialiseContainerSuperClassFromAnnotationsOnly(container.getClazz().getSuperclass());
478       AnnotationInitialiser init = new ContainerInitialiser(container);
479       InterceptorInfo info = init.getInfo();
480       info.calculateHierarchy(superInfo);
481       return info;
482    }
483
484    private InterceptorInfo initialiseContainerSuperClassFromAnnotationsOnly(Class JavaDoc clazz)
485    {
486       InterceptorInfo superInfo = null;
487       if (clazz != Object JavaDoc.class)
488       {
489          superInfo = initialiseContainerSuperClassFromAnnotationsOnly(clazz.getSuperclass());
490       }
491
492       AnnotationInitialiser init = new AnnotationInitialiser(clazz, BeanSignatureValidator.instance);
493       InterceptorInfo info = init.getInfo();
494       info.calculateHierarchy(superInfo);
495       return info;
496    }
497    
498    
499    private Class JavaDoc loadClass(String JavaDoc name)
500    {
501       try
502       {
503          return Thread.currentThread().getContextClassLoader().loadClass(name);
504       }
505       catch (Exception JavaDoc e)
506       {
507          throw new RuntimeException JavaDoc("Interceptor class not found: " + name);
508       }
509    }
510
511    public static boolean checkValidBusinessSignature(Method JavaDoc method)
512    {
513       int modifiers = method.getModifiers();
514
515       if (!Modifier.isStatic(modifiers))
516       {
517          if (method.getReturnType().equals(Object JavaDoc.class))
518          {
519             Class JavaDoc[] params = method.getParameterTypes();
520             if (params.length == 1 && params[0].equals(InvocationContext.class))
521             {
522                Class JavaDoc[] exceptions = method.getExceptionTypes();
523                if (exceptions.length == 1 && exceptions[0].equals(Exception JavaDoc.class))
524                {
525                   return true;
526                }
527             }
528          }
529       }
530       return false;
531    }
532
533    public static boolean checkValidLifecycleSignature(Method JavaDoc method)
534    {
535       int modifiers = method.getModifiers();
536
537       if (!Modifier.isStatic(modifiers))
538       {
539          if (method.getReturnType().equals(Void.TYPE))
540          {
541             Class JavaDoc[] params = method.getParameterTypes();
542             if (params.length == 1 && params[0].equals(InvocationContext.class))
543             {
544                return true;
545             }
546          }
547       }
548       return false;
549    }
550
551    public static boolean checkValidBeanLifecycleSignature(Method JavaDoc method)
552    {
553       int modifiers = method.getModifiers();
554       if (method.getName().equals("ejbCreate"))
555       {
556          // for public void ejbCreate() throws javax.ejb.CreateException
557
if (!Modifier.isStatic(modifiers) && method.getReturnType().equals(Void.TYPE)
558                && method.getParameterTypes().length == 0 && method.getExceptionTypes().length <= 1)
559             return true;
560       }
561       else if (!Modifier.isStatic(modifiers) && method.getReturnType().equals(Void.TYPE)
562             && method.getParameterTypes().length == 0 && method.getExceptionTypes().length == 0)
563       {
564          return true;
565       }
566       return false;
567    }
568
569    public static String JavaDoc simpleType(Class JavaDoc type)
570    {
571       Class JavaDoc ret = type;
572       if (ret.isArray())
573       {
574          Class JavaDoc arr = ret;
575          String JavaDoc array = "";
576          while (arr.isArray())
577          {
578             array += "[]";
579             arr = arr.getComponentType();
580          }
581          return arr.getName() + array;
582       }
583       return ret.getName();
584    }
585    
586
587    private interface SignatureValidator
588    {
589       boolean checkValidLifecycle(Method JavaDoc m);
590       boolean checkValidAround(Method JavaDoc m);
591    }
592
593    private static class InterceptorSignatureValidator implements SignatureValidator
594    {
595       static SignatureValidator instance = new InterceptorSignatureValidator();
596       public boolean checkValidAround(Method JavaDoc m)
597       {
598          return checkValidBusinessSignature(m);
599       }
600
601       public boolean checkValidLifecycle(Method JavaDoc m)
602       {
603          return checkValidLifecycleSignature(m);
604       }
605    }
606
607    private static class BeanSignatureValidator implements SignatureValidator
608    {
609       static SignatureValidator instance = new BeanSignatureValidator();
610       public boolean checkValidAround(Method JavaDoc m)
611       {
612          return checkValidBusinessSignature(m);
613       }
614
615       public boolean checkValidLifecycle(Method JavaDoc m)
616       {
617          return checkValidBeanLifecycleSignature(m);
618       }
619    }
620    
621    
622    private class AnnotationInitialiser
623    {
624       SignatureValidator signatureValidator;
625       Class JavaDoc clazz;
626
627       InterceptorInfo info;
628
629       AnnotationInitialiser(String JavaDoc classname, SignatureValidator signatureValidator)
630       {
631          clazz = loadClass(classname);
632          this.signatureValidator = signatureValidator;
633          info = new InterceptorInfo(clazz);
634       }
635
636       AnnotationInitialiser(Class JavaDoc clazz, SignatureValidator signatureValidator)
637       {
638          this.clazz = clazz;
639          this.signatureValidator = signatureValidator;
640          info = new InterceptorInfo(clazz);
641       }
642
643       public Class JavaDoc getClazz()
644       {
645          return clazz;
646       }
647
648       InterceptorInfo getInfo()
649       {
650          for (Method JavaDoc method : clazz.getDeclaredMethods())
651          {
652             info.setAroundInvoke(resolveAroundInvoke(method));
653             info.setPostConstruct(resolvePostConstruct(method));
654             info.setPostActivate(resolvePostActivate(method));
655             info.setPreDestroy(resolvePreDestroy(method));
656             info.setPrePassivate(resolvePrePassivate(method));
657          }
658          return info;
659       }
660
661       Method JavaDoc resolveAroundInvoke(Method JavaDoc method)
662       {
663          AroundInvoke ann = (AroundInvoke) getAnnotation(method, AroundInvoke.class);
664          if (ann != null)
665          {
666             if (!signatureValidator.checkValidAround(method))
667             {
668                throw new RuntimeException JavaDoc("@" + ((Annotation JavaDoc) ann).annotationType().getName()
669                      + " annotated method in has the wrong signature - " + method);
670             }
671             return method;
672          }
673          return null;
674       }
675
676       Method JavaDoc resolvePostConstruct(Method JavaDoc method)
677       {
678          PostConstruct ann = (PostConstruct) getAnnotation(method, PostConstruct.class);
679          return resolveLifecycleMethod(method, ann);
680       }
681
682       Method JavaDoc resolvePostActivate(Method JavaDoc method)
683       {
684          PostActivate JavaDoc ann = (PostActivate JavaDoc) getAnnotation(method, PostActivate JavaDoc.class);
685          return resolveLifecycleMethod(method, ann);
686       }
687
688       Method JavaDoc resolvePreDestroy(Method JavaDoc method)
689       {
690          PreDestroy ann = (PreDestroy) getAnnotation(method, PreDestroy.class);
691          return resolveLifecycleMethod(method, ann);
692       }
693
694       Method JavaDoc resolvePrePassivate(Method JavaDoc method)
695       {
696          PrePassivate JavaDoc ann = (PrePassivate JavaDoc) getAnnotation(method, PrePassivate JavaDoc.class);
697          return resolveLifecycleMethod(method, ann);
698       }
699
700       Method JavaDoc resolveLifecycleMethod(Method JavaDoc method, Annotation JavaDoc ann)
701       {
702          if (ann != null)
703          {
704             if (!signatureValidator.checkValidLifecycle(method))
705             {
706                throw new RuntimeException JavaDoc("@" + ((Annotation JavaDoc) ann).annotationType().getName()
707                      + " annotated method has the wrong signature - " + method);
708             }
709             return method;
710          }
711          return null;
712       }
713
714       Object JavaDoc getAnnotation(Method JavaDoc method, Class JavaDoc annotation)
715       {
716          return method.getAnnotation(annotation);
717       }
718
719    }
720
721    private class ContainerInitialiser extends AnnotationInitialiser
722    {
723       EJBContainer container;
724
725       public ContainerInitialiser(EJBContainer container)
726       {
727          // FIXME ContainerInitialiser constructor
728
super(container.getBeanClass(), BeanSignatureValidator.instance);
729          this.container = container;
730       }
731
732       Object JavaDoc getAnnotation(Method JavaDoc method, Class JavaDoc annotation)
733       {
734          return container.resolveAnnotation(method, annotation);
735       }
736
737       /*
738        * Lifecycle methods on bean class have a different signature from those defined on
739        *
740        */

741       Method JavaDoc resolveLifecycleMethod(Method JavaDoc method, Annotation JavaDoc ann)
742       {
743          if (ann != null)
744          {
745             if (!signatureValidator.checkValidLifecycle(method))
746             {
747                // FIXME: JBCTS-322
748
// This is just a hack that prevents the RTE below. Please fix appropriately.
749
if (ann.annotationType() == PostConstruct.class && method.getName().equals("ejbCreate"))
750                {
751                    return method;
752                }
753                
754                throw new RuntimeException JavaDoc("@" + ann.annotationType().getName()
755                        + " annotated method has the wrong signature - " + method);
756             }
757             return method;
758          }
759          return null;
760       }
761    }
762
763    private class XmlInitialiser extends AnnotationInitialiser
764    {
765       Interceptor xml;
766
767       XmlInitialiser(Interceptor xml)
768       {
769          super(xml.getInterceptorClass(), InterceptorSignatureValidator.instance);
770          this.xml = xml;
771       }
772
773       InterceptorInfo getInfo()
774       {
775          info.setAroundInvoke(findInterceptorMethodFromXml(clazz, "around-invoke-method", xml.getAroundInvoke()));
776          info.setPostConstruct(findInterceptorMethodFromXml(clazz, "post-construct-method", xml.getPostConstruct()));
777          info.setPostActivate(findInterceptorMethodFromXml(clazz, "post-activate-method", xml.getPostActivate()));
778          info.setPreDestroy(findInterceptorMethodFromXml(clazz, "pre-destroy-method", xml.getPreDestroy()));
779          info.setPrePassivate(findInterceptorMethodFromXml(clazz, "pre-passivate-method", xml.getPrePassivate()));
780          super.getInfo();
781          info.setXml(xml);
782          return info;
783       }
784
785       java.lang.reflect.Method JavaDoc findInterceptorMethodFromXml(Class JavaDoc clazz, String JavaDoc lookingFor, org.jboss.ejb3.metamodel.Method xml)
786       {
787          if (xml == null)
788             return null;
789          if (xml.getMethodName() == null || xml.getMethodName().trim().equals(""))
790          {
791             throw new RuntimeException JavaDoc(lookingFor + " must contain a valid method name for interceptor "
792                   + clazz.getName());
793          }
794          if (xml.getMethodParams() != null)
795          {
796             log.debug("Ignoring method parameters for " + lookingFor + " in interceptor " + clazz.getName());
797          }
798
799          ArrayList<Method JavaDoc> possible = new ArrayList<Method JavaDoc>();
800          for (java.lang.reflect.Method JavaDoc method : clazz.getDeclaredMethods())
801          {
802             if (xml.getMethodName().equals(method.getName()))
803             {
804                possible.add(method);
805             }
806          }
807
808          if (possible.size() == 0)
809          {
810             throw new RuntimeException JavaDoc(lookingFor + " must contain a valid method name for interceptor "
811                   + clazz.getName());
812          }
813
814          Method JavaDoc found = null;
815
816          for (Method JavaDoc method : possible)
817          {
818             if (lookingFor.equals("around-invoke-method"))
819             {
820                if (signatureValidator.checkValidAround(method))
821                {
822                   found = method;
823                }
824             }
825             else
826             {
827                if (signatureValidator.checkValidLifecycle(method))
828                {
829                   found = method;
830                }
831             }
832          }
833
834          if (found == null)
835          {
836             throw new RuntimeException JavaDoc(lookingFor + " has the wrong method signature for interceptor "
837                   + clazz.getName());
838          }
839
840          return found;
841       }
842    }
843
844    private class InterceptorSorter
845    {
846       boolean initialised;
847       List<InterceptorBinding> orderedBindings;
848       
849       void initialise()
850       {
851          if (!initialised)
852          {
853             synchronized(this)
854             {
855                if (bindingsXml != null)
856                {
857                   for (InterceptorBinding binding : bindingsXml)
858                   {
859                      if (binding.isOrdered())
860                      {
861                         //Validate each interceptor only occurs once
862
HashSet names = new HashSet();
863                         for (Iterator it = binding.getInterceptorClasses().iterator() ; it.hasNext() ; )
864                         {
865                            String JavaDoc className = (String JavaDoc)it.next();
866                            if (names.contains(className))
867                            {
868                               throw new RuntimeException JavaDoc(className + " occurs more than once in ordered binding " +
869                                     getInterceptorBindingString(binding));
870                            }
871                            names.add(className);
872                         }
873                         
874                         if (orderedBindings == null)
875                         {
876                            orderedBindings = new ArrayList<InterceptorBinding>();
877                         }
878                         orderedBindings.add(binding);
879                      }
880                   }
881                }
882             }
883             initialised = true;
884          }
885       }
886       
887       void sortDefaultInterceptors(EJBContainer container, ArrayList<InterceptorInfo> infos)
888       {
889          initialise();
890          if (orderedBindings == null) return;
891          ArrayList<String JavaDoc> bindingOrder = null;
892          for (InterceptorBinding binding : orderedBindings)
893          {
894             if (binding.getEjbName().equals("*"))
895             {
896                if (bindingOrder != null)
897                {
898                   throw new RuntimeException JavaDoc("There should only be one interceptor-binding specifying " +
899                         "the order of default interceptors " + getInterceptorBindingString(binding));
900                }
901                bindingOrder = binding.getInterceptorClasses();
902             }
903          }
904          sortInterceptors(infos, bindingOrder);
905       }
906       
907       void sortClassInterceptors(EJBContainer container, ArrayList<InterceptorInfo> infos)
908       {
909          initialise();
910          if (orderedBindings == null) return;
911          ArrayList<String JavaDoc> bindingOrder = null;
912          for (InterceptorBinding binding : orderedBindings)
913          {
914             if (binding.getMethodName() != null && binding.getMethodName().trim().length() > 0)
915             {
916                continue;
917             }
918             if (binding.getEjbName().equals(container.getEjbName()))
919             {
920                if (bindingOrder != null)
921                {
922                   throw new RuntimeException JavaDoc("There should only be one interceptor-binding specifying " +
923                         "the order of class interceptors: " + getInterceptorBindingString(binding));
924                }
925                bindingOrder = binding.getInterceptorClasses();
926             }
927          }
928          sortInterceptors(infos, bindingOrder);
929       }
930       
931       void sortMethodInterceptors(EJBContainer container, Method JavaDoc method, ArrayList<InterceptorInfo> infos)
932       {
933          initialise();
934          if (orderedBindings == null) return;
935          ArrayList<String JavaDoc> methodNoParamsOrder = null;
936          ArrayList<String JavaDoc> methodParamsOrder = null;
937          for (InterceptorBinding binding : orderedBindings)
938          {
939             if (binding.getEjbName().equals(container.getEjbName()))
940             {
941                if (binding.getMethodName() != null && binding.getMethodName().equals(method.getName()))
942                {
943                   if (binding.getMethodParams() == null)
944                   {
945                      if (methodNoParamsOrder != null)
946                      {
947                         throw new RuntimeException JavaDoc("There should only be one interceptor-binding specifying " +
948                               "the order of method interceptors: " + getInterceptorBindingString(binding));
949                      }
950                      methodNoParamsOrder = binding.getInterceptorClasses();
951                   }
952                   else
953                   {
954                      Class JavaDoc[] params = method.getParameterTypes();
955                      List<String JavaDoc> methodParams = binding.getMethodParams();
956                      if (methodParams.size() == params.length)
957                      {
958                         boolean matches = true;
959                         for (int i = 0 ; i < params.length ; i++)
960                         {
961                            if (!simpleType(params[i]).equals(methodParams.get(i)))
962                            {
963                               matches = false;
964                               break;
965                            }
966                         }
967                         
968                         if (matches)
969                         {
970                            if (methodParamsOrder != null)
971                            {
972                               boolean first = false;
973                               StringBuffer JavaDoc paramBuf = new StringBuffer JavaDoc();
974                               paramBuf.append("(");
975                               for (String JavaDoc par : methodParams)
976                               {
977                                  if (!first) paramBuf.append(",");
978                                  paramBuf.append(par);
979                               }
980                               paramBuf.append(")");
981                               throw new RuntimeException JavaDoc("There should only be one interceptor-binding specifying " +
982                                     "the order of method interceptors: " + getInterceptorBindingString(binding));
983                            }
984                            
985                            methodParamsOrder = binding.getInterceptorClasses();
986                         }
987                      }
988                   }
989                }
990             }
991          }
992          
993          if (methodParamsOrder != null)
994          {
995             sortInterceptors(infos, methodParamsOrder);
996             
997          }
998          else
999          {
1000            sortInterceptors(infos, methodNoParamsOrder);
1001         }
1002      }
1003      
1004      void sortInterceptors(ArrayList<InterceptorInfo> infos, ArrayList<String JavaDoc> interceptorOrder)
1005      {
1006         if (interceptorOrder == null) return;
1007         Collections.sort(infos, new InterceptorComparator(interceptorOrder));
1008      }
1009
1010      String JavaDoc getInterceptorBindingString(InterceptorBinding binding)
1011      {
1012         StringBuffer JavaDoc buf = new StringBuffer JavaDoc();
1013         List methodParams = binding.getMethodParams();
1014         
1015         buf.append(binding.getEjbName());
1016         if (binding.getMethodName() != null)
1017         {
1018            buf.append("." + binding.getMethodName());
1019            if (methodParams != null)
1020            {
1021               buf.append("(");
1022               for (int i = 0 ; i < methodParams.size() ; )
1023               {
1024                  if (i == 0) buf.append(",");
1025                  buf.append((String JavaDoc)methodParams.get(i));
1026               }
1027               buf.append(")");
1028            }
1029         }
1030         
1031         return buf.toString();
1032      }
1033   }
1034   
1035   private class InterceptorComparator implements Comparator<InterceptorInfo>
1036   {
1037      ArrayList<String JavaDoc> ordered;
1038
1039      InterceptorComparator(ArrayList<String JavaDoc> ordered)
1040      {
1041         this.ordered = ordered;
1042      }
1043      
1044      public int compare(InterceptorInfo o1, InterceptorInfo o2)
1045      {
1046         int pos1 = ordered.indexOf(o1.getClazz().getName());
1047         int pos2 = ordered.indexOf(o2.getClazz().getName());
1048         
1049         //Make anything not specified in the order come last
1050
if (pos1 < 0) pos1 = Integer.MAX_VALUE;
1051         if (pos2 < 0) pos2 = Integer.MAX_VALUE;
1052         
1053         if (pos1 < pos2)
1054         {
1055            return -1;
1056         }
1057         else if (pos1 > pos2)
1058         {
1059            return 1;
1060         }
1061         else
1062         {
1063            return 0;
1064         }
1065      }
1066      
1067      
1068   }
1069   
1070}
1071
Popular Tags