[jboss-cvs] JBossAS SVN: r110168 - in trunk/weld-int/deployer: src/main/java/org/jboss/weld/integration/deployer/metadata and 1 other directory.

jboss-cvs-commits at lists.jboss.org jboss-cvs-commits at lists.jboss.org
Wed Dec 22 21:04:49 EST 2010


Author: marius.bogoevici
Date: 2010-12-22 21:04:49 -0500 (Wed, 22 Dec 2010)
New Revision: 110168

Modified:
   trunk/weld-int/deployer/pom.xml
   trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/metadata/WeldEjbInterceptorMetadataDeployer.java
Log:
JBAS-8768,JBAS-8769 Manipulate interceptor metadata to work around exclusions (if any) and to ensure the right placement of the JSR299 bindings interceptor

Modified: trunk/weld-int/deployer/pom.xml
===================================================================
--- trunk/weld-int/deployer/pom.xml	2010-12-22 23:22:42 UTC (rev 110167)
+++ trunk/weld-int/deployer/pom.xml	2010-12-23 02:04:49 UTC (rev 110168)
@@ -522,6 +522,11 @@
         <groupId>org.jboss.spec.javax.annotation</groupId>
         <artifactId>jboss-annotations-api_1.1_spec</artifactId>
     </dependency>
+
+     <dependency>
+        <groupId>org.jboss.scanning</groupId>
+        <artifactId>scanning-plugins</artifactId>
+    </dependency>
     
    </dependencies>
 

Modified: trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/metadata/WeldEjbInterceptorMetadataDeployer.java
===================================================================
--- trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/metadata/WeldEjbInterceptorMetadataDeployer.java	2010-12-22 23:22:42 UTC (rev 110167)
+++ trunk/weld-int/deployer/src/main/java/org/jboss/weld/integration/deployer/metadata/WeldEjbInterceptorMetadataDeployer.java	2010-12-23 02:04:49 UTC (rev 110168)
@@ -22,16 +22,30 @@
 package org.jboss.weld.integration.deployer.metadata;
 
 import java.lang.reflect.AnnotatedElement;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
 
+import javax.interceptor.ExcludeClassInterceptors;
+import javax.interceptor.ExcludeDefaultInterceptors;
+
 import org.jboss.deployers.spi.DeploymentException;
 import org.jboss.deployers.spi.deployer.DeploymentStages;
+import org.jboss.deployers.structure.spi.DeploymentUnit;
 import org.jboss.deployers.vfs.spi.structure.VFSDeploymentUnit;
+import org.jboss.metadata.annotation.creator.EjbProcessorUtils;
 import org.jboss.metadata.annotation.creator.ejb.InterceptorMetaDataCreator;
+import org.jboss.metadata.annotation.finder.AnnotationFinder;
 import org.jboss.metadata.annotation.finder.DefaultAnnotationFinder;
 import org.jboss.metadata.ejb.jboss.JBossAssemblyDescriptorMetaData;
+import org.jboss.metadata.ejb.jboss.JBossEnterpriseBeanMetaData;
+import org.jboss.metadata.ejb.jboss.JBossEnterpriseBeansMetaData;
 import org.jboss.metadata.ejb.jboss.JBossMetaData;
 import org.jboss.metadata.ejb.spec.AroundInvokeMetaData;
 import org.jboss.metadata.ejb.spec.AroundInvokesMetaData;
@@ -41,7 +55,12 @@
 import org.jboss.metadata.ejb.spec.InterceptorBindingsMetaData;
 import org.jboss.metadata.ejb.spec.InterceptorClassesMetaData;
 import org.jboss.metadata.ejb.spec.InterceptorMetaData;
+import org.jboss.metadata.ejb.spec.InterceptorOrderMetaData;
 import org.jboss.metadata.ejb.spec.InterceptorsMetaData;
+import org.jboss.metadata.ejb.spec.MethodParametersMetaData;
+import org.jboss.metadata.ejb.spec.NamedMethodMetaData;
+import org.jboss.scanning.annotations.spi.AnnotationIndex;
+import org.jboss.scanning.annotations.spi.Element;
 import org.jboss.vfs.VirtualFile;
 
 import org.jboss.weld.integration.ejb.SessionBeanInterceptor;
@@ -66,8 +85,8 @@
    private InterceptorMetaData injectionIMD;
    private InterceptorMetaData bindingsIMD;
    private InterceptorMetaData contextIMD;
+
    private InterceptorBindingMetaData injectionIBMD;
-   private InterceptorBindingMetaData bindingsIBMD;
    private InterceptorBindingMetaData contextIBMD;
 
    private InterceptorMetaDataCreator interceptorMetaDataCreator;
@@ -104,7 +123,6 @@
 
       // create interceptor binding metadata instance
       injectionIBMD = createInterceptorBindingMetadata(INJECTION_INTERCEPTOR_CLASS_NAME);
-      bindingsIBMD = createInterceptorBindingMetadata(BINDINGS_INTERCEPTOR_CLASS_NAME);
       contextIBMD = createInterceptorBindingMetadata(CONTEXT_INTERCEPTOR_CLASS_NAME);
 
    }
@@ -146,13 +164,11 @@
          interceptorBindings = new InterceptorBindingsMetaData();
          assemblyDescriptor.setInterceptorBindings(interceptorBindings);
       }
-      // Add this as the first binding in the list so that it is called first...
-      interceptorBindings.add(contextIBMD);
-      interceptorBindings.add(0, injectionIBMD);
 
-      // Add JSR-299 binding interceptor as the last (all others have to be
-      // called first)
-      interceptorBindings.add(bindingsIBMD);
+      if (jbmd.isEJB3x() && jbmd.getEnterpriseBeans() != null)
+      {
+         processEjbInterceptorMetadata(jbmd.getEnterpriseBeans(), interceptorBindings, unit);
+      }
 
       // Check to see there is a defined order; if we aren't first, warn
       for (InterceptorBindingMetaData interceptorBinding : interceptorBindings)
@@ -171,11 +187,233 @@
                lastInterceptorClassName = iterator.next();
             }
             while (iterator.hasNext());
-            if (!BINDINGS_INTERCEPTOR_CLASS_NAME.equals(lastInterceptorClassName))
+         }
+      }
+   }
+
+   private InterceptorBindingMetaData createBinding(String className, String ejbName, NamedMethodMetaData method, boolean excludeClassInterceptors)
+   {
+      InterceptorClassesMetaData interceptorClasses = new InterceptorClassesMetaData();
+      interceptorClasses.add(className);
+      return createBinding(interceptorClasses, null, ejbName, method);
+   }
+
+   private InterceptorBindingMetaData createBinding(InterceptorClassesMetaData classesMetaData, InterceptorOrderMetaData orderMetaData, String ejbName, NamedMethodMetaData method)
+   {
+      InterceptorBindingMetaData ibmd = new InterceptorBindingMetaData();
+      ibmd.setInterceptorClasses(classesMetaData);
+      ibmd.setEjbName(ejbName);
+      if (orderMetaData != null)
+      {
+         ibmd.setInterceptorOrder(orderMetaData);
+      }
+      if (method != null)
+      {
+         ibmd.setMethod(method);
+      }
+      return ibmd;
+   }
+
+   /**
+    * Process EJB interceptors metadata and make sure that the JSR 299 bindings interceptor is added after the EJB3 ones
+    * There are 3 possibilities
+    * - there are no EJB3 interceptor definitions or all the existing ones are defaults: set a default binding
+    * - there are EJB3 interceptors bound on classes, case in which we need to:
+    *     - bind the JSR299 interceptor after the class interceptors
+    *     - verify if the existing EJB3 interceptors exclude defaults; if the latter is the case then we need to add
+    *       CDI bindings (context and injection) at the class level, otherwise EJB3 handling won't happen correctly;
+    * - there are EJB3 interceptors bound on methods, case in which we need to:
+    *     - verify if the existing EJB3 interceptors exclude defaults; if the latter is the case then we need to add
+    *       CDI bindings (context and injection) at the class level, otherwise EJB3 handling won't happen correctly;
+    *     - in order to add the JSR299interceptor *last*, we will exclude the class level interceptors for this particular
+    *       method and re-add the class level interceptors before the mapped method-level interceptors, leaving the
+    *       JSR299 interceptor last
+    * @param jBossEnterpriseBeansMetaData
+    * @param interceptorBindings
+    * @param deploymentUnit
+    */
+   private void processEjbInterceptorMetadata(JBossEnterpriseBeansMetaData jBossEnterpriseBeansMetaData, InterceptorBindingsMetaData interceptorBindings, DeploymentUnit deploymentUnit)
+   {
+      // we need to figure out whether there are class-level or method-level bindings
+      List<InterceptorBindingMetaData> classInterceptorBindings = new ArrayList<InterceptorBindingMetaData>();
+      List<InterceptorBindingMetaData> methodInterceptorBindings = new ArrayList<InterceptorBindingMetaData>();
+
+
+      for (InterceptorBindingMetaData interceptorBinding : interceptorBindings)
+      {
+         if (!"*".equals(interceptorBinding.getEjbName())
+               && null != interceptorBinding.getEjbName()
+               && !interceptorBinding.getEjbName().trim().equals(""))
+         {
+            //record class-level bindings may need them later
+            if (interceptorBinding.getMethod() == null)
             {
-               log.warn("The Web Beans Jsr299BindingsInterceptor is not the outer most EJB interceptor in this deployment. JSR299 requires that @InterceptorBinding-bound interceptors should execute after @Interceptors-registered interceptors. Specify " + BINDINGS_INTERCEPTOR_CLASS_NAME + " as the last interceptor in the interceptor ordering for " + interceptorBinding.getEjbName());
+               classInterceptorBindings.add(interceptorBinding);
             }
          }
+
+         // record method level interceptor bindings
+         if (null != interceptorBinding.getMethod())
+         {
+            methodInterceptorBindings.add(interceptorBinding);
+         }
+
       }
+      Set<NamedMethodMetaData> processedMethodMetadatas = new HashSet<NamedMethodMetaData>();
+
+      if (!excludeClassLevelInterceptorsExist(deploymentUnit)
+            && methodInterceptorBindings.isEmpty()
+            && classInterceptorBindings.isEmpty()
+            && getMethodsWithExcludedClasses(deploymentUnit).isEmpty()
+            && getMethodsWithExcludedDefaults(deploymentUnit).isEmpty())
+      {
+         // there are no class or method level EJB3 interceptor bindings, nor are there any exclusions:
+         // we can simply set up defaults
+         interceptorBindings.add(0, createBinding(INJECTION_INTERCEPTOR_CLASS_NAME, "*", null, false));
+         interceptorBindings.add(0, createBinding(CONTEXT_INTERCEPTOR_CLASS_NAME, "*", null, false));
+         interceptorBindings.add(createBinding(BINDINGS_INTERCEPTOR_CLASS_NAME, "*", null, false));
+      }
+      else
+      {
+
+         for (JBossEnterpriseBeanMetaData enterpriseBeanMetaData : jBossEnterpriseBeansMetaData)
+         {
+            // add a bindings for EJB interceptors - they need to be added after class level interceptors, so we can't add a default
+            String ejbName = enterpriseBeanMetaData.getEjbName();
+            interceptorBindings.add(0, createBinding(INJECTION_INTERCEPTOR_CLASS_NAME, ejbName, null, false));
+            interceptorBindings.add(0, createBinding(CONTEXT_INTERCEPTOR_CLASS_NAME, ejbName, null, false));
+            interceptorBindings.add(createBinding(BINDINGS_INTERCEPTOR_CLASS_NAME, ejbName, null, false));
+         }
+
+
+         // if there are method level bindings, then we need to execute the JSR299 interceptor last, but it has been
+         // already added at the class level (we must do so, otherwise lifecycle interception won't happen. As well, we
+         // don't have access to all the methods so we can't add bindings directly. But if we keep things this way,
+         // then the JSR299 interceptor will execute before EJB3 method-level interceptors, which is not right, so will
+         // exclude all the class-level bindings and add the original bindings on the method before the current bindings
+         if (!methodInterceptorBindings.isEmpty())
+         {
+            for (InterceptorBindingMetaData methodInterceptorBinding : methodInterceptorBindings)
+            {
+
+               // re-add class level interceptors in their original order
+               if (!methodInterceptorBinding.isExcludeClassInterceptors())
+               {
+                  // create a local list to preserve the original ordering of the class-level interceptors
+                  List<InterceptorBindingMetaData> replacementInterceptorBindings = new ArrayList<InterceptorBindingMetaData>();
+                  for (InterceptorBindingMetaData classInterceptorBinding : classInterceptorBindings)
+                  {
+                     if (methodInterceptorBinding.getEjbName().equals(classInterceptorBinding.getEjbName()))
+                     {
+                        replacementInterceptorBindings.add(0, createBinding(classInterceptorBinding.getInterceptorClasses(), classInterceptorBinding.getInterceptorOrder(), methodInterceptorBinding.getEjbName(), methodInterceptorBinding.getMethod()));
+                     }
+                  }
+                  // add new bindings at the beginning of the list so that they will be mapped first on the method
+                  interceptorBindings.addAll(0, replacementInterceptorBindings);
+               }
+               interceptorBindings.add(createBinding(BINDINGS_INTERCEPTOR_CLASS_NAME, methodInterceptorBinding.getEjbName(), methodInterceptorBinding.getMethod(), methodInterceptorBinding.isExcludeClassInterceptors()));
+               // exclude class level interceptors so that our new bindings won't be executed twice
+               processedMethodMetadatas.add(methodInterceptorBinding.getMethod());
+               methodInterceptorBinding.setExcludeClassInterceptors(true);
+            }
+         }
+
+
+         for (Element<ExcludeDefaultInterceptors, Method> element : getMethodsWithExcludedDefaults(deploymentUnit))
+         {
+            //re-add CDI support defaults if they would be otherwise excluded
+            for (JBossEnterpriseBeanMetaData enterpriseBeanMetaData : jBossEnterpriseBeansMetaData)
+            {
+
+               if (enterpriseBeanMetaData.getEjbClass().equals(element.getOwnerClassName()))
+               {
+                  String ejbName = enterpriseBeanMetaData.getEjbName();
+                  NamedMethodMetaData namedMethod = new NamedMethodMetaData();
+                  namedMethod.setMethodName(element.getAnnotatedElement().getName());
+                  MethodParametersMetaData methodParams = EjbProcessorUtils.getMethodParameters(element.getAnnotatedElement());
+                  namedMethod.setMethodParams(methodParams);
+                  if (!processedMethodMetadatas.contains(namedMethod))
+                  {
+                     interceptorBindings.add(0, createBinding(INJECTION_INTERCEPTOR_CLASS_NAME, ejbName, namedMethod, false));
+                     interceptorBindings.add(0, createBinding(CONTEXT_INTERCEPTOR_CLASS_NAME, ejbName, namedMethod, false));
+                     processedMethodMetadatas.add(namedMethod);
+                  }
+               }
+            }
+         }
+
+         for (Element<ExcludeClassInterceptors, Method> element : getMethodsWithExcludedClasses(deploymentUnit))
+         {
+            //re-add CDI support defaults if they would be otherwise excluded
+            for (JBossEnterpriseBeanMetaData enterpriseBeanMetaData : jBossEnterpriseBeansMetaData)
+            {
+
+               if (enterpriseBeanMetaData.getEjbClass().equals(element.getOwnerClassName()))
+               {
+                  String ejbName = enterpriseBeanMetaData.getEjbName();
+                  NamedMethodMetaData namedMethod = new NamedMethodMetaData();
+                  namedMethod.setMethodName(element.getAnnotatedElement().getName());
+                  MethodParametersMetaData methodParams = EjbProcessorUtils.getMethodParameters(element.getAnnotatedElement());
+                  namedMethod.setMethodParams(methodParams);
+                  interceptorBindings.add(0, createBinding(INJECTION_INTERCEPTOR_CLASS_NAME, ejbName, namedMethod, false));
+                  interceptorBindings.add(0, createBinding(CONTEXT_INTERCEPTOR_CLASS_NAME, ejbName, namedMethod, false));
+                  if (!processedMethodMetadatas.contains(namedMethod))
+                  {
+                     interceptorBindings.add(0, createBinding(INJECTION_INTERCEPTOR_CLASS_NAME, ejbName, namedMethod, false));
+                     interceptorBindings.add(0, createBinding(CONTEXT_INTERCEPTOR_CLASS_NAME, ejbName, namedMethod, false));
+                     interceptorBindings.add(createBinding(BINDINGS_INTERCEPTOR_CLASS_NAME, ejbName, namedMethod, false));
+                     processedMethodMetadatas.add(namedMethod);
+                  }
+               }
+            }
+         }
+
+      }
    }
+
+   private boolean excludeClassLevelInterceptorsExist(DeploymentUnit unit)
+   {
+      AnnotationIndex annotationRepository = unit.getAttachment(AnnotationIndex.class);
+      if (annotationRepository != null)
+      {
+         return !annotationRepository.classIsAnnotatedWith(ExcludeDefaultInterceptors.class).isEmpty();
+      }
+      else
+      {
+         // if annotations are not scanned we won't bother checking each EJB class
+         // let interceptors just go at the class level
+         return true;
+      }
+   }
+
+   private Set<Element<ExcludeDefaultInterceptors,Method>> getMethodsWithExcludedDefaults(DeploymentUnit unit)
+   {
+      AnnotationIndex annotationRepository = unit.getAttachment(AnnotationIndex.class);
+
+      if (annotationRepository != null)
+      {
+         return annotationRepository.classHasMethodAnnotatedWith(ExcludeDefaultInterceptors.class);
+
+      }
+      else
+      {
+         // no scanning info, ignore those methods
+         return Collections.emptySet();
+      }
+   }
+
+   private Set<Element<ExcludeClassInterceptors,Method>> getMethodsWithExcludedClasses(DeploymentUnit unit)
+   {
+      AnnotationIndex annotationRepository = unit.getAttachment(AnnotationIndex.class);
+
+      if (annotationRepository != null)
+      {
+         return annotationRepository.classHasMethodAnnotatedWith(ExcludeClassInterceptors.class);
+      }
+      else
+      {
+         // no scanning info, ignore those methods
+         return Collections.emptySet();
+      }
+   }
 }
\ No newline at end of file



More information about the jboss-cvs-commits mailing list