
org.apache.webbeans.intercept.WebBeansInterceptorConfig Maven / Gradle / Ivy
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.apache.webbeans.intercept;
import org.apache.webbeans.annotation.AnnotationManager;
import org.apache.webbeans.component.AbstractInjectionTargetBean;
import org.apache.webbeans.component.AbstractOwbBean;
import org.apache.webbeans.config.OWBLogConst;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.config.inheritance.IBeanInheritedMetaData;
import org.apache.webbeans.exception.WebBeansConfigurationException;
import org.apache.webbeans.intercept.webbeans.WebBeansInterceptor;
import org.apache.webbeans.logger.WebBeansLogger;
import org.apache.webbeans.plugins.OpenWebBeansEjbLCAPlugin;
import org.apache.webbeans.spi.BDABeansXmlScanner;
import org.apache.webbeans.spi.ScannerService;
import org.apache.webbeans.util.AnnotationUtil;
import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import javax.enterprise.context.Dependent;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.Interceptor;
import javax.interceptor.AroundInvoke;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* Configures the Web Beans related interceptors.
*
* @author Gurkan Erdogdu
* @version $Rev$ $Date$
* @see WebBeansInterceptor
*/
public final class WebBeansInterceptorConfig
{
/** Logger instance */
private static WebBeansLogger logger = WebBeansLogger.getLogger(WebBeansInterceptorConfig.class);
private WebBeansContext webBeansContext;
public WebBeansInterceptorConfig(WebBeansContext webBeansContext)
{
this.webBeansContext = webBeansContext;
}
/**
* Configures WebBeans specific interceptor class.
*
* @param interceptorBindingTypes interceptor class
*/
public void configureInterceptorClass(AbstractInjectionTargetBean delegate, Annotation[] interceptorBindingTypes)
{
if(delegate.getScope() != Dependent.class)
{
if(logger.wblWillLogWarn())
{
logger.warn(OWBLogConst.WARN_0005_1, delegate.getBeanClass().getName());
}
}
if(delegate.getName() != null)
{
if(logger.wblWillLogWarn())
{
logger.warn(OWBLogConst.WARN_0005_2, delegate.getBeanClass().getName());
}
}
if(delegate.isAlternative())
{
if(logger.wblWillLogWarn())
{
logger.warn(OWBLogConst.WARN_0005_3, delegate.getBeanClass().getName());
}
}
if (logger.wblWillLogDebug())
{
logger.debug("Configuring interceptor class : [{0}]", delegate.getReturnType());
}
WebBeansInterceptor interceptor = new WebBeansInterceptor(delegate);
List anns = Arrays.asList(interceptorBindingTypes);
for (Annotation ann : interceptorBindingTypes)
{
checkAnns(anns, ann, delegate);
interceptor.addInterceptorBinding(ann.annotationType(), ann);
}
delegate.getWebBeansContext().getBeanManagerImpl().addInterceptor(interceptor);
}
private void checkAnns(List list, Annotation ann, Bean> bean)
{
for(Annotation old : list)
{
if(old.annotationType().equals(ann.annotationType()))
{
if(!AnnotationUtil.isQualifierEqual(ann, old))
{
throw new WebBeansConfigurationException("Interceptor Binding types must be equal for interceptor : " + bean);
}
}
}
}
/**
* Configures the given class for applicable interceptors.
*
*/
public void configure(AbstractInjectionTargetBean> component, List stack)
{
Class> clazz = ((AbstractOwbBean>)component).getReturnType();
AnnotatedType> annotatedType = component.getAnnotatedType();
Set annotations = null;
if(annotatedType != null)
{
annotations = annotatedType.getAnnotations();
}
Set> componentInterceptors = null;
Set bindingTypeSet = new HashSet();
Annotation[] anns;
Annotation[] typeAnns = null;
if(annotations != null)
{
typeAnns = annotations.toArray(new Annotation[annotations.size()]);
}
else
{
typeAnns = clazz.getDeclaredAnnotations();
}
AnnotationManager annotationManager = component.getWebBeansContext().getAnnotationManager();
if (annotationManager.hasInterceptorBindingMetaAnnotation(typeAnns))
{
anns = annotationManager.getInterceptorBindingMetaAnnotations(typeAnns);
for (Annotation ann : anns)
{
bindingTypeSet.add(ann);
}
}
// check for stereotypes _explicitly_ declared on the bean class (not
// inherited)
Annotation[] stereoTypes =
annotationManager.getStereotypeMetaAnnotations(typeAnns);
for (Annotation stero : stereoTypes)
{
if (annotationManager.hasInterceptorBindingMetaAnnotation(stero.annotationType().getDeclaredAnnotations()))
{
Annotation[] steroInterceptorBindings = annotationManager.getInterceptorBindingMetaAnnotations(
stero.annotationType().getDeclaredAnnotations());
for (Annotation ann : steroInterceptorBindings)
{
bindingTypeSet.add(ann);
}
}
}
// Look for inherited binding types, keeping in mind that
// IBeanInheritedMetaData knows nothing of the transitive
// relationships of Interceptor Bindings or Stereotypes. We must resolve
// these here.
IBeanInheritedMetaData metadata = component.getInheritedMetaData();
if (metadata != null)
{
Set inheritedBindingTypes = metadata.getInheritedInterceptorBindings();
if (!inheritedBindingTypes.isEmpty())
{
Annotation[] inheritedAnns = new Annotation[inheritedBindingTypes.size()];
inheritedAnns = inheritedBindingTypes.toArray(inheritedAnns);
anns = annotationManager.getInterceptorBindingMetaAnnotations(inheritedAnns);
bindingTypeSet.addAll(Arrays.asList(anns));
}
// Retrieve inherited stereotypes, check for meta-annotations, and
// find the ultimate set of bindings
Set inheritedStereotypes = metadata.getInheritedStereoTypes();
if (!inheritedStereotypes.isEmpty())
{
// We need AnnotationUtil to resolve the transitive relationship
// of stereotypes we've found
Annotation[] inherited = new Annotation[inheritedStereotypes.size()];
inherited = inheritedStereotypes.toArray(inherited);
Annotation[] transitiveStereotypes = annotationManager.getStereotypeMetaAnnotations(inherited);
for (Annotation stereo : transitiveStereotypes)
{
if (annotationManager.hasInterceptorBindingMetaAnnotation(stereo.annotationType().getDeclaredAnnotations()))
{
Annotation[] steroInterceptorBindings =
annotationManager.getInterceptorBindingMetaAnnotations(stereo.annotationType().getDeclaredAnnotations());
for (Annotation ann : steroInterceptorBindings)
{
bindingTypeSet.add(ann);
}
}
}
}
}
anns = new Annotation[bindingTypeSet.size()];
anns = bindingTypeSet.toArray(anns);
//Spec Section 9.5.2
List beanAnnots = Arrays.asList(anns);
for(Annotation checkAnn : anns)
{
checkAnns(beanAnnots, checkAnn, component);
}
if (anns.length > 0)
{
componentInterceptors = findDeployedWebBeansInterceptor(anns, component.getWebBeansContext());
// Adding class interceptors
addComponentInterceptors(component, componentInterceptors, stack);
}
// Method level interceptors.
if(annotatedType == null)
{
addMethodInterceptors(component, clazz, stack, componentInterceptors, bindingTypeSet);
}
else
{
addMethodInterceptors(component, annotatedType, stack, componentInterceptors);
}
filterInterceptorsPerBDA(component,stack);
Collections.sort(stack, new InterceptorDataComparator(component.getWebBeansContext()));
}
private void filterInterceptorsPerBDA(AbstractInjectionTargetBean> component, List stack)
{
ScannerService scannerService = component.getWebBeansContext().getScannerService();
if (!scannerService.isBDABeansXmlScanningEnabled())
{
return;
}
BDABeansXmlScanner beansXMLScanner = scannerService.getBDABeansXmlScanner();
String beanBDABeansXML = beansXMLScanner.getBeansXml(component.getBeanClass());
Set> definedInterceptors = beansXMLScanner.getInterceptors(beanBDABeansXML);
InterceptorData interceptorData;
if (stack != null && stack.size() > 0)
{
Iterator it = stack.iterator();
while (it.hasNext())
{
interceptorData = (InterceptorData) it.next();
if (!definedInterceptors.contains(interceptorData.getInterceptorClass()))
{
it.remove();
}
}
}
}
public void addComponentInterceptors(AbstractOwbBean> bean, Set> set, List stack)
{
WebBeansContext webBeansContext = bean.getWebBeansContext();
Iterator> it = set.iterator();
while (it.hasNext())
{
WebBeansInterceptor> interceptor = (WebBeansInterceptor>) it.next();
AnnotatedType> annotatedType = interceptor.getAnnotatedType();
OpenWebBeansEjbLCAPlugin ejbPlugin = webBeansContext.getPluginLoader().getEjbLCAPlugin();
Class extends Annotation> prePassivateClass = null;
Class extends Annotation> postActivateClass = null;
if (null != ejbPlugin)
{
prePassivateClass = ejbPlugin.getPrePassivateClass();
postActivateClass = ejbPlugin.getPostActivateClass();
}
if(annotatedType != null)
{
// interceptor binding
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor, annotatedType,
AroundInvoke.class, true,
false, stack, null);
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor, annotatedType,
PostConstruct.class, true,
false, stack, null);
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor, annotatedType,
PreDestroy.class, true,
false, stack, null);
if (null != ejbPlugin)
{
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
annotatedType,
prePassivateClass,
true, false, stack,
null);
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
annotatedType,
postActivateClass,
true, false, stack,
null);
}
}
else
{
// interceptor binding
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
interceptor.getClazz(),
AroundInvoke.class, true,
false, stack, null, true);
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
interceptor.getClazz(),
PostConstruct.class, true,
false, stack, null, true);
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
interceptor.getClazz(),
PreDestroy.class, true,
false, stack, null, true);
if (null != ejbPlugin)
{
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
interceptor.getClazz(),
prePassivateClass,
true, false, stack,
null, true);
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
interceptor.getClazz(),
postActivateClass,
true, false, stack,
null, true);
}
}
}
}
/**
* Add configured interceptors, combining the bindings at the component-level with annotations on methods
* @param component
* @param clazz the bean class
* @param stack the current interceptor stack for the bean
* @param componentInterceptors the configured interceptors from the component level
* @param resolvedComponentInterceptorBindings complete (including transitive) set of component-level interceptor bindings
*/
private void addMethodInterceptors(AbstractInjectionTargetBean> component, Class> clazz, List stack, Set> componentInterceptors,
Set resolvedComponentInterceptorBindings)
{
WebBeansContext webBeansContext = component.getWebBeansContext();
AnnotationManager annotationManager = webBeansContext.getAnnotationManager();
// All methods, not just those declared
Method[] methods = clazz.getMethods();
Set set = new HashSet();
for(Method m : methods)
{
set.add(m);
}
//GE : I added for private, protected etc. methods.
//Not just for public methods.
methods = webBeansContext.getSecurityService().doPrivilegedGetDeclaredMethods(clazz);
for(Method m : methods)
{
set.add(m);
}
methods = set.toArray(new Method[set.size()]);
for (Method method : methods)
{
Set interceptorAnns = new HashSet();
if (annotationManager.hasInterceptorBindingMetaAnnotation(
method.getDeclaredAnnotations()))
{
Annotation[] anns =
annotationManager.getInterceptorBindingMetaAnnotations(
method.getAnnotations());
for (Annotation ann : anns)
{
interceptorAnns.add(ann);
}
}
// To find the right interceptors, we need to consider method and
// class-level combined
interceptorAnns.addAll(resolvedComponentInterceptorBindings);
if (!interceptorAnns.isEmpty())
{
Annotation[] result = new Annotation[interceptorAnns.size()];
result = interceptorAnns.toArray(result);
Set> setInterceptors = findDeployedWebBeansInterceptor(result, webBeansContext);
if (componentInterceptors != null)
{
setInterceptors.removeAll(componentInterceptors);
}
Iterator> it = setInterceptors.iterator();
while (it.hasNext())
{
WebBeansInterceptor> interceptor = (WebBeansInterceptor>) it.next();
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
interceptor.getClazz(),
AroundInvoke.class,
true, true, stack,
method, true);
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
interceptor.getClazz(),
PostConstruct.class,
true, true, stack,
method, true);
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
interceptor.getClazz(),
PreDestroy.class, true,
true, stack, method,
true);
OpenWebBeansEjbLCAPlugin ejbPlugin = webBeansContext.getPluginLoader().getEjbLCAPlugin();
if (null != ejbPlugin)
{
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
interceptor.getClazz(),
ejbPlugin.getPrePassivateClass(),
true, true, stack,
method, true);
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
interceptor.getClazz(),
ejbPlugin.getPostActivateClass(),
true, true, stack,
method, true);
}
}
}
}
}
@SuppressWarnings("unchecked")
private void addMethodInterceptors(AbstractInjectionTargetBean> component,
AnnotatedType annotatedType,
List stack,
Set> componentInterceptors)
{
WebBeansContext webBeansContext = component.getWebBeansContext();
AnnotationManager annotationManager = webBeansContext.getAnnotationManager();
Set> methods = annotatedType.getMethods();
for(AnnotatedMethod super T> methodA : methods)
{
AnnotatedMethod methodB = (AnnotatedMethod)methodA;
Method method = methodB.getJavaMember();
Set interceptorAnns = new HashSet();
Annotation[] methodAnns = AnnotationUtil.getAnnotationsFromSet(methodB.getAnnotations());
if (annotationManager.hasInterceptorBindingMetaAnnotation(methodAnns))
{
Annotation[] anns =
annotationManager.getInterceptorBindingMetaAnnotations(
methodAnns);
Annotation[] annsClazz =
annotationManager.getInterceptorBindingMetaAnnotations(
AnnotationUtil.getAnnotationsFromSet(annotatedType.getAnnotations()));
for (Annotation ann : anns)
{
interceptorAnns.add(ann);
}
for (Annotation ann : annsClazz)
{
interceptorAnns.add(ann);
}
}
Annotation[] stereoTypes =
annotationManager.getStereotypeMetaAnnotations(
AnnotationUtil.getAnnotationsFromSet(annotatedType.getAnnotations()));
for (Annotation stero : stereoTypes)
{
if (annotationManager.hasInterceptorBindingMetaAnnotation(
stero.annotationType().getDeclaredAnnotations()))
{
Annotation[] steroInterceptorBindings =
annotationManager.getInterceptorBindingMetaAnnotations(
stero.annotationType().getDeclaredAnnotations());
for (Annotation ann : steroInterceptorBindings)
{
interceptorAnns.add(ann);
}
}
}
if (!interceptorAnns.isEmpty())
{
Annotation[] result = new Annotation[interceptorAnns.size()];
result = interceptorAnns.toArray(result);
Set> setInterceptors = findDeployedWebBeansInterceptor(result, webBeansContext);
if(componentInterceptors != null)
{
setInterceptors.removeAll(componentInterceptors);
}
Iterator> it = setInterceptors.iterator();
while (it.hasNext())
{
WebBeansInterceptor> interceptor = (WebBeansInterceptor>) it.next();
AnnotatedType> interAnnoType = interceptor.getAnnotatedType();
if(interAnnoType == null)
{
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
interceptor.getClazz(),
AroundInvoke.class,
true, true, stack,
method, true);
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
interceptor.getClazz(),
PostConstruct.class,
true, true, stack,
method, true);
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
interceptor.getClazz(),
PreDestroy.class,
true, true, stack,
method, true);
}
else
{
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
interAnnoType,
AroundInvoke.class,
true, true, stack,
method);
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
interAnnoType,
PostConstruct.class,
true, true, stack,
method);
webBeansContext.getWebBeansUtil().configureInterceptorMethods(interceptor,
interAnnoType,
PreDestroy.class,
true, true, stack,
method);
}
}
}
}
}
/*
* Find the deployed interceptors with given interceptor binding types.
*/
public Set> findDeployedWebBeansInterceptor(Annotation[] anns, WebBeansContext webBeansContext)
{
Set> set = new HashSet>();
Iterator> it = webBeansContext.getBeanManagerImpl().getInterceptors().iterator();
WebBeansInterceptor> interceptor;
List> bindingTypes = new ArrayList>();
List listAnnot = new ArrayList();
for (Annotation ann : anns)
{
bindingTypes.add(ann.annotationType());
listAnnot.add(ann);
}
while (it.hasNext())
{
interceptor = (WebBeansInterceptor>) it.next();
if (interceptor.hasBinding(bindingTypes, listAnnot))
{
set.add(interceptor);
set.addAll(interceptor.getMetaInceptors());
}
}
return set;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy