[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