FileDocCategorySizeDatePackage
InterceptorInfoRepository.javaAPI DocJBoss 4.2.136356Fri Jul 13 20:53:52 BST 2007org.jboss.ejb3.interceptor

InterceptorInfoRepository

public class InterceptorInfoRepository extends Object
A repository of interceptor details shared amongst all containers in this deployment. Interceptors differ from other ejb 3 artifacts in that we can have annotations on the interceptor classes which are not the ejb container, so we cannot use annotation overrides on the interceptors themselves.

The xml structures get added on deployment.
Interceptors only declared by using @Interceptors on the bean class get added on demand.
author
Kabir Khan
version
$Revision: 63298 $

Fields Summary
private static Logger
log
private Set
beanClasses
private org.jboss.ejb3.metamodel.Interceptors
interceptorsXml
private List
bindingsXml
private ConcurrentMap
infos
private ConcurrentMap
ejbInfos
private LinkedHashSet
defaultInterceptors
private InterceptorSorter
sorter
Constructors Summary
public InterceptorInfoRepository()


    
   
   
Methods Summary
public voidaddBeanClass(java.lang.String classname)

      beanClasses.add(classname);
   
private static booleancheckExceptions(java.lang.Class[] allowedExceptions, java.lang.reflect.Method method)

      for(Class<?> exception : method.getExceptionTypes())
      {
         boolean isAllowed = false;
         for(Class<?> allowed : allowedExceptions)
         {
            if(allowed.isAssignableFrom(exception))
               isAllowed = true;
         }
         if(!isAllowed)
         {
            log.warn("Illegal exception '" + exception.getName() + "' in lifecycle signature (EJB3 12.4.2): " + method);
            return false;
         }
      }
      return true;
   
public static booleancheckValidBeanLifecycleSignature(java.lang.reflect.Method method)
EJB3 12.4 Lifecycle methods may throw runtime exceptions, but not application exceptions. Note that for 2.1 beans CreateException (on ejbCreate) and RemoteException should pass.

param
method
return

      int modifiers = method.getModifiers();
      if (method.getName().equals("ejbCreate"))
      {
         // for public void ejbCreate(...) throws javax.ejb.CreateException
         if (!Modifier.isStatic(modifiers) && method.getReturnType().equals(Void.TYPE)
               && method.getExceptionTypes().length <= 1)
         {
            if(!checkExceptions(new Class<?>[] { RuntimeException.class, CreateException.class, RemoteException.class }, method))
               return false;
            return true;
         }
      }
      else if (!Modifier.isStatic(modifiers) && method.getReturnType().equals(Void.TYPE)
            && method.getParameterTypes().length == 0)
      {
         if(!checkExceptions(new Class<?>[] { RuntimeException.class, RemoteException.class }, method))
            return false;
         return true;
      }
      return false;
   
public static booleancheckValidBusinessSignature(java.lang.reflect.Method method)

      int modifiers = method.getModifiers();

      if (!Modifier.isStatic(modifiers))
      {
         if (method.getReturnType().equals(Object.class))
         {
            Class[] params = method.getParameterTypes();
            if (params.length == 1 && params[0].equals(InvocationContext.class))
            {
               Class[] exceptions = method.getExceptionTypes();
               if (exceptions.length == 1 && exceptions[0].equals(Exception.class))
               {
                  return true;
               }
            }
         }
      }
      return false;
   
public static booleancheckValidLifecycleSignature(java.lang.reflect.Method method)

      int modifiers = method.getModifiers();

      if (!Modifier.isStatic(modifiers))
      {
         if (method.getReturnType().equals(Void.TYPE))
         {
            Class[] params = method.getParameterTypes();
            if (params.length == 1 && params[0].equals(InvocationContext.class))
            {
               return true;
            }
         }
      }
      return false;
   
public java.lang.reflect.Method[]getBeanClassAroundInvokes(org.jboss.ejb3.EJBContainer container)

      return getBeanClassInterceptors(container, AroundInvoke.class);
   
private java.lang.reflect.Method[]getBeanClassInterceptors(org.jboss.ejb3.EJBContainer container, java.lang.Class type)

      InterceptorInfo info = getOrInitialiseFromAnnotations(container);
      return getMethodsForEvent(info, type);
   
public java.lang.reflect.Method[]getBeanClassPostActivates(org.jboss.ejb3.EJBContainer container)

      return getBeanClassInterceptors(container, PostActivate.class);
   
public java.lang.reflect.Method[]getBeanClassPostConstructs(org.jboss.ejb3.EJBContainer container)

      return getBeanClassInterceptors(container, PostConstruct.class);
   
public java.lang.reflect.Method[]getBeanClassPreDestroys(org.jboss.ejb3.EJBContainer container)

      return getBeanClassInterceptors(container, PreDestroy.class);
   
public java.lang.reflect.Method[]getBeanClassPrePassivates(org.jboss.ejb3.EJBContainer container)

      return getBeanClassInterceptors(container, PrePassivate.class);
   
public InterceptorInfo[]getBusinessInterceptors(org.jboss.ejb3.EJBContainer container, java.lang.reflect.Method method)

      return getInterceptors(container, AroundInvoke.class, method);
   
public java.util.ArrayListgetClassInterceptors(org.jboss.ejb3.EJBContainer container)

      javax.interceptor.Interceptors interceptors = (javax.interceptor.Interceptors) container
            .resolveAnnotation(javax.interceptor.Interceptors.class);
      ArrayList<InterceptorInfo> infos = getInterceptorsFromAnnotation(container, interceptors);

      return infos;
   
public java.util.HashSetgetDefaultInterceptors()

      return defaultInterceptors;
   
public InterceptorInfogetInterceptorInfo(java.lang.Class clazz)

      initialiseInfosFromXml();
      return infos.get(clazz);
   
private InterceptorInfo[]getInterceptors(org.jboss.ejb3.EJBContainer container, java.lang.Class type, java.lang.reflect.Method method)

      ArrayList<InterceptorInfo> interceptors = new ArrayList<InterceptorInfo>();

      if (!hasAnnotation(container, ExcludeDefaultInterceptors.class, method))
      {
         HashSet<InterceptorInfo> infos = getDefaultInterceptors();
         if (infos != null)
         {
            interceptors.addAll(trimUnwanted(infos, type));
         }
         sorter.sortDefaultInterceptors(container, interceptors);
      }

      
      if (!hasAnnotation(container, ExcludeClassInterceptors.class, method))
      {
         List<InterceptorInfo> infos = container.getClassInterceptors();
         if (infos != null)
         {
            interceptors.addAll(trimUnwanted(infos, type));
         }
         
         if (type != AroundInvoke.class)
         {
            List<InterceptorInfo> methodOnlyInterceptors = getMethodOnlyInterceptorsForLifecycle(container, type, interceptors);
            if (infos != null)
               interceptors.addAll(methodOnlyInterceptors);
         }
         sorter.sortClassInterceptors(container, interceptors);
      }

      if (type == AroundInvoke.class)
      {
         List<InterceptorInfo> infos = getMethodInterceptors(container, method);
         if (infos != null)
            interceptors.addAll(trimUnwanted(infos, type));
         sorter.sortMethodInterceptors(container, method, interceptors);
      }

      InterceptorInfo[] ints = interceptors.toArray(new InterceptorInfo[interceptors.size()]);
      return ints;
   
private java.util.ArrayListgetInterceptorsFromAnnotation(org.jboss.ejb3.EJBContainer container, javax.interceptor.Interceptors interceptors)

      ArrayList<InterceptorInfo> inters = new ArrayList<InterceptorInfo>();
      if (interceptors == null)
         return inters;

      for (Class clazz : interceptors.value())
      {
         InterceptorInfo info = getOrInitialiseFromAnnotations(clazz);
         validateInterceptorForContainer(container, info.getClazz());
         inters.add(info);
      }

      return inters;
   
public java.util.ArrayListgetMethodInterceptors(org.jboss.ejb3.EJBContainer container, java.lang.reflect.Method m)

      javax.interceptor.Interceptors interceptors = (javax.interceptor.Interceptors) container.resolveAnnotation(m,
            javax.interceptor.Interceptors.class);
      ArrayList<InterceptorInfo> infos = getInterceptorsFromAnnotation(container, interceptors);

      return infos;
   
private java.util.ListgetMethodOnlyInterceptorsForLifecycle(org.jboss.ejb3.EJBContainer container, java.lang.Class type, java.util.List infos)

      HashSet<InterceptorInfo> methodLevelInterceptors = (HashSet<InterceptorInfo>)container.getApplicableInterceptors().clone();
      
      for (InterceptorInfo info : infos)
      {
         if (methodLevelInterceptors.contains(info))
         {
            methodLevelInterceptors.remove(info);
         }
      }
      
      if (defaultInterceptors != null)
      {
         for (InterceptorInfo info : defaultInterceptors)
         {
            if (methodLevelInterceptors.contains(info))
            {
               methodLevelInterceptors.remove(info);
            }
         }
      }
      
      List<InterceptorInfo> trimmedInfos = trimUnwanted(methodLevelInterceptors, type); 
      return trimmedInfos;
   
private java.lang.reflect.Method[]getMethodsForEvent(InterceptorInfo info, java.lang.Class type)

      if (type == AroundInvoke.class)
         return info.getAroundInvokes();
      else if (type == PostConstruct.class)
         return info.getPostConstructs();
      else if (type == PostActivate.class)
         return info.getPostActivates();
      else if (type == PrePassivate.class)
         return info.getPrePassivates();
      else if (type == PreDestroy.class)
         return info.getPreDestroys();
      return null;
   
private InterceptorInfogetOrInitialiseFromAnnotations(java.lang.String classname)

      Class clazz = loadClass(classname);
      return getOrInitialiseFromAnnotations(clazz);
   
private InterceptorInfogetOrInitialiseFromAnnotations(java.lang.Class clazz)

      InterceptorInfo info = infos.get(clazz);

      if (info == null)
      {
         synchronized (this)
         {
            info = infos.get(clazz);
            if (info == null)
            {
               info = initialiseFromAnnotations(clazz);
               infos.put(clazz, info);
            }
         }
      }

      return info;
   
private InterceptorInfogetOrInitialiseFromAnnotations(org.jboss.ejb3.EJBContainer container)

      InterceptorInfo info = ejbInfos.get(container.getEjbName());

      if (info == null)
      {
         synchronized (this)
         {
            info = ejbInfos.get(container.getEjbName());
            if (info == null)
            {
               info = initialiseFromAnnotations(container);
               ejbInfos.put(container.getEjbName(), info);
            }
         }
      }

      return info;
   
public InterceptorInfo[]getPostActivateInterceptors(org.jboss.ejb3.EJBContainer container)

      return getInterceptors(container, PostActivate.class, null);
   
public InterceptorInfo[]getPostConstructInterceptors(org.jboss.ejb3.EJBContainer container)

      return getInterceptors(container, PostConstruct.class, null);
   
public InterceptorInfo[]getPreDestroyInterceptors(org.jboss.ejb3.EJBContainer container)

      return getInterceptors(container, PreDestroy.class, null);
   
public InterceptorInfo[]getPrePassivateInterceptors(org.jboss.ejb3.EJBContainer container)

      return getInterceptors(container, PrePassivate.class, null);
   
private booleanhasAnnotation(org.jboss.ejb3.EJBContainer container, java.lang.Class annotation, java.lang.reflect.Method method)

      if (container.resolveAnnotation(annotation) != null)
      {
         return true;
      }

      if (method != null)
      {
         return container.resolveAnnotation(method, annotation) != null;
      }

      return false;
   
public booleanhasDefaultInterceptors()

      return defaultInterceptors.size() > 0;
   
private booleanhasMethodsForEvent(InterceptorInfo info, java.lang.Class type)

      return getMethodsForEvent(info, type) != null;
   
public voidinitialise(org.jboss.ejb3.metamodel.EjbJarDD dd)

      this.interceptorsXml = dd.getInterceptors();

      if (dd.getAssemblyDescriptor() != null)
      {
         this.bindingsXml = dd.getAssemblyDescriptor().getInterceptorBindings();
      }
      
      initialiseInfosFromXml();
      initialiseDefaultInterceptors();
   
private InterceptorInfoinitialiseContainerSuperClassFromAnnotationsOnly(java.lang.Class clazz)

      InterceptorInfo superInfo = null;
      if (clazz != Object.class)
      {
         superInfo = initialiseContainerSuperClassFromAnnotationsOnly(clazz.getSuperclass());
      }

      AnnotationInitialiser init = new AnnotationInitialiser(clazz, BeanSignatureValidator.instance);
      InterceptorInfo info = init.getInfo();
      info.calculateHierarchy(superInfo);
      return info;
   
private voidinitialiseDefaultInterceptors()

      defaultInterceptors = new LinkedHashSet<InterceptorInfo>();

      if (bindingsXml != null)
      {
         for (InterceptorBinding bindingXml : bindingsXml)
         {
            if (bindingXml.getEjbName().equals("*")
                  && (bindingXml.getMethodName() == null || bindingXml.getMethodName().length() == 0))
            {
               for (String classname : bindingXml.getInterceptorClasses())
               {
                  if (beanClasses.contains(classname))
                  {
                     throw new RuntimeException("Bean class defined in default binding " + classname);
                  }
                  InterceptorInfo info = getOrInitialiseFromAnnotations(classname);
                  defaultInterceptors.add(info);
               }
            }
         }
      }
   
private InterceptorInfoinitialiseFromAnnotations(java.lang.Class clazz)

      InterceptorInfo superInfo = null;
      if (clazz.getSuperclass() != Object.class)
      {
         superInfo = getOrInitialiseFromAnnotations(clazz.getSuperclass());
      }

      AnnotationInitialiser init = new AnnotationInitialiser(clazz, InterceptorSignatureValidator.instance);
      InterceptorInfo info = init.getInfo();
      info.calculateHierarchy(superInfo);
      return info;
   
private InterceptorInfoinitialiseFromAnnotations(org.jboss.ejb3.EJBContainer container)

      //Currently I see no way in spec for specifying interceptors of an ejb super class using xml,
      //use annotations only to initialise super classes, and don't store these
      InterceptorInfo superInfo = initialiseContainerSuperClassFromAnnotationsOnly(container.getClazz().getSuperclass());
      AnnotationInitialiser init = new ContainerInitialiser(container);
      InterceptorInfo info = init.getInfo();
      info.calculateHierarchy(superInfo);
      return info;
   
private voidinitialiseInfosFromXml()

      if (interceptorsXml != null)
      {
         //Initialise all interceptor entries so we know which classes we have xml for
         HashMap<String, AnnotationInitialiser> initialisers = new HashMap<String, AnnotationInitialiser>();
         for (Interceptor xml : interceptorsXml.getInterceptors())
         {
            XmlInitialiser init = new XmlInitialiser(xml);
            initialisers.put(xml.getInterceptorClass(), init);
         }

         //Create entries recursively, top classes first so we get the method hierarchies         
         for (Interceptor xml : interceptorsXml.getInterceptors())
         {
            String clazz = xml.getInterceptorClass();
            initialiseSuperClassesFirstFromXmlOrAnnotations(initialisers, clazz);
         }

      }
   
private InterceptorInfoinitialiseSuperClassesFirstFromXmlOrAnnotations(java.util.HashMap initialisers, java.lang.String superClassName)

      if ("java.lang.Object".equals(superClassName))
      {
         return null;
      }

      AnnotationInitialiser initialiser = initialisers.get(superClassName);
      if (initialiser == null)
      {
         initialiser = new AnnotationInitialiser(superClassName, InterceptorSignatureValidator.instance);
         initialisers.put(initialiser.getClazz().getName(), initialiser);
      }
      InterceptorInfo superInfo = initialiseSuperClassesFirstFromXmlOrAnnotations(
            initialisers, initialiser.getClazz().getSuperclass().getName());

      InterceptorInfo info = initialiser.getInfo();
      info.calculateHierarchy(superInfo);
      infos.put(info.getClazz(), info);
      return info;
   
private java.lang.ClassloadClass(java.lang.String name)

      try
      {
         return Thread.currentThread().getContextClassLoader().loadClass(name);
      }
      catch (Exception e)
      {
         throw new RuntimeException("Interceptor class not found: " + name);
      }
   
public static java.lang.StringsimpleType(java.lang.Class type)

      Class ret = type;
      if (ret.isArray())
      {
         Class arr = ret;
         String array = "";
         while (arr.isArray())
         {
            array += "[]";
            arr = arr.getComponentType();
         }
         return arr.getName() + array;
      }
      return ret.getName();
   
private java.util.ListtrimUnwanted(java.util.Collection interceptors, java.lang.Class type)

      ArrayList<InterceptorInfo> ints = new ArrayList<InterceptorInfo>(interceptors.size());
      ints.addAll(interceptors);

      for (Iterator<InterceptorInfo> it = ints.iterator(); it.hasNext();)
      {
         InterceptorInfo info = it.next();
         if (!hasMethodsForEvent(info, type))
         {
            it.remove();
         }
      }

      return ints;
   
private voidvalidateInterceptorForContainer(org.jboss.ejb3.EJBContainer container, java.lang.Class interceptor)

      if (beanClasses.contains(interceptor.getName()))
      {
         if (!interceptor.equals(container.getClazz()))
         {
            throw new RuntimeException("Bean class " + interceptor.getName() + " cannot be used as an interceptor for "
                  + container.getEjbName());
         }
      }