blob: 34d2d2a3bd44e1d7c6fd2541d87b407b7392e926 [file] [log] [blame]
/**
* 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.openejb.cdi;
import org.apache.webbeans.component.BeanManagerBean;
import org.apache.webbeans.component.BuildInOwbBean;
import org.apache.webbeans.component.ConversationBean;
import org.apache.webbeans.component.InjectionPointBean;
import org.apache.webbeans.container.BeanManagerImpl;
import org.apache.webbeans.portable.events.generics.GenericBeanEvent;
import org.apache.webbeans.util.WebBeansUtil;
import javax.el.ELResolver;
import javax.el.ExpressionFactory;
import javax.enterprise.context.spi.Context;
import javax.enterprise.context.spi.Contextual;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.UnsatisfiedResolutionException;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.Decorator;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.enterprise.inject.spi.InterceptionType;
import javax.enterprise.inject.spi.Interceptor;
import javax.enterprise.inject.spi.ObserverMethod;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
public class WebappBeanManager extends BeanManagerImpl {
private final WebappWebBeansContext webappCtx;
private final ThreadLocal<Boolean> internalUse = new ThreadLocal<Boolean>() {
@Override
public Boolean initialValue() {
return false;
}
};
private Set<Bean<?>> deploymentBeans;
public WebappBeanManager(WebappWebBeansContext ctx) {
super(ctx);
webappCtx = ctx;
deploymentBeans = super.getBeans(); // use the parent one while starting
}
@Override
public Object getReference(Bean<?> bean, Type beanType, CreationalContext<?> ctx) {
Object ref;
try {
ref = getParentBm().getReference(bean, beanType, ctx);
if (ref == null) {
ref = super.getReference(bean, beanType, ctx);
}
} catch (RuntimeException e) {
ref = super.getReference(bean, beanType, ctx);
}
return ref;
}
@Override
public Object getInjectableReference(InjectionPoint injectionPoint, CreationalContext<?> ctx) {
try {
return super.getInjectableReference(injectionPoint, ctx);
} catch (RuntimeException e) {
return getParentBm().getInjectableReference(injectionPoint, ctx);
}
}
@Override
public <T> CreationalContext<T> createCreationalContext(Contextual<T> contextual) {
try {
return super.createCreationalContext(contextual);
} catch (RuntimeException e) { // can happen?
try {
return getParentBm().createCreationalContext(contextual);
} catch (RuntimeException ignored) {
throw e;
}
}
}
@Override
public Set<Bean<?>> getBeans(Type beanType, Annotation... qualifiers) {
final Set<Bean<?>> beans = new HashSet<Bean<?>>();
internalUse.set(true);
try {
beans.addAll(super.getBeans(beanType, qualifiers));
} finally {
internalUse.set(false);
}
if (!internalUse.get()) {
beans.addAll(getParentBm().getBeans(beanType, qualifiers));
}
internalUse.remove();
return beans;
}
@Override
public Set<Bean<?>> getBeans(String name) {
final Set<Bean<?>> beans = new HashSet<Bean<?>>();
internalUse.set(true);
try {
beans.addAll(super.getBeans(name));
} finally {
internalUse.set(false);
}
if (!internalUse.get()) {
beans.addAll(getParentBm().getBeans(name));
}
internalUse.remove();
return beans;
}
@Override
public Bean<?> getPassivationCapableBean(String id) {
try {
return getParentBm().getPassivationCapableBean(id);
} catch (RuntimeException e) {
return super.getPassivationCapableBean(id);
}
}
@Override
public <X> Bean<? extends X> resolve(Set<Bean<? extends X>> beans) {
try {
return super.resolve(beans);
} catch (RuntimeException e) {
try {
return getParentBm().resolve(beans);
} catch (RuntimeException ignored) {
throw e;
}
}
}
@Override
public void fireEvent(Object event, Annotation... qualifiers) {
super.fireEvent(event, qualifiers);
// don't propagate to parent extension events since extensions are already here (loaded from spi)
if (!isExtensionEvent(event.getClass())) {
getParentBm().fireEvent(event, qualifiers);
}
}
private static boolean isExtensionEvent(final Type type) {
if (!(type instanceof Class<?>)) {
return false;
}
final Class<?> aClass = (Class<?>) type;
if (WebBeansUtil.isExtensionEventType(aClass)
|| WebBeansUtil.isExtensionProducerOrObserverEventType(aClass)) {
return true;
}
final Class<?>[] itfs = aClass.getInterfaces();
if (itfs != null) {
for (Class<?> i : itfs) {
if (GenericBeanEvent.class.equals(i)
|| WebBeansUtil.isExtensionEventType(i)
|| WebBeansUtil.isDefaultExtensionBeanEventType(i)
|| WebBeansUtil.isDefaultExtensionProducerOrObserverEventType(i)) {
return true;
}
}
}
return false;
}
@Override
public <T> Set<ObserverMethod<? super T>> resolveObserverMethods(T event, Annotation... qualifiers) {
final Set<ObserverMethod<? super T>> mtds = new HashSet<ObserverMethod<? super T>>();
internalUse.set(true);
try {
mtds.addAll(super.resolveObserverMethods(event, qualifiers));
} finally {
internalUse.set(false);
}
if (!internalUse.get()) {
Set<ObserverMethod<? super T>> c = getParentBm().resolveObserverMethods(event, qualifiers);
for (ObserverMethod<? super T> o : c) {
if (!isExtensionEvent(o.getObservedType())) {
mtds.add(o);
}
}
}
internalUse.remove();
return mtds;
}
@Override
public List<Decorator<?>> resolveDecorators(Set<Type> types, Annotation... qualifiers) {
final List<Decorator<?>> decorators = new ArrayList<Decorator<?>>();
internalUse.set(true);
try {
decorators.addAll(super.resolveDecorators(types, qualifiers));
} finally {
internalUse.set(false);
}
if (!internalUse.get()) {
decorators.addAll(getParentBm().resolveDecorators(types, qualifiers));
}
return decorators;
}
@Override
public List<Interceptor<?>> resolveInterceptors(InterceptionType type, Annotation... qualifiers) {
final List<Interceptor<?>> interceptors = new ArrayList<Interceptor<?>>();
internalUse.set(true);
try {
interceptors.addAll(super.resolveInterceptors(type, qualifiers));
} finally {
internalUse.set(false);
}
if (!internalUse.get()) {
interceptors.addAll(getParentBm().resolveInterceptors(type, qualifiers));
}
internalUse.remove();
return interceptors;
}
@Override
public void validate(InjectionPoint injectionPoint) {
try {
super.validate(injectionPoint);
} catch (UnsatisfiedResolutionException ure) {
try {
getParentBm().validate(injectionPoint); // prevent injections from webapp only if called directly
} catch (UnsatisfiedResolutionException ure2) {
throw ure;
}
}
}
@Override
public boolean isScope(Class<? extends Annotation> annotationType) {
try {
return super.isScope(annotationType);
} catch (RuntimeException e) {
try {
return getParentBm().isScope(annotationType);
} catch (RuntimeException ignored) {
throw e;
}
}
}
@Override
public boolean isNormalScope(Class<? extends Annotation> annotationType) {
try {
return super.isNormalScope(annotationType);
} catch (RuntimeException e) {
try {
return getParentBm().isNormalScope(annotationType);
} catch (RuntimeException ignored) {
throw e;
}
}
}
@Override
public boolean isPassivatingScope(Class<? extends Annotation> annotationType) {
try {
return super.isPassivatingScope(annotationType);
} catch (RuntimeException e) {
try {
return getParentBm().isPassivatingScope(annotationType);
} catch (RuntimeException ignored) {
throw e;
}
}
}
@Override
public boolean isQualifier(Class<? extends Annotation> annotationType) {
try {
return super.isQualifier(annotationType);
} catch (RuntimeException e) {
try {
return getParentBm().isQualifier(annotationType);
} catch (RuntimeException ignored) {
throw e;
}
}
}
@Override
public boolean isInterceptorBinding(Class<? extends Annotation> annotationType) {
try {
return super.isInterceptorBinding(annotationType);
} catch (RuntimeException e) {
try {
return getParentBm().isInterceptorBinding(annotationType);
} catch (RuntimeException ignored) {
throw e;
}
}
}
@Override
public boolean isStereotype(Class<? extends Annotation> annotationType) {
try {
return super.isStereotype(annotationType);
} catch (RuntimeException e) {
try {
return getParentBm().isStereotype(annotationType);
} catch (RuntimeException ignored) {
throw e;
}
}
}
@Override
public Set<Annotation> getInterceptorBindingDefinition(Class<? extends Annotation> qualifier) {
try {
return super.getInterceptorBindingDefinition(qualifier);
} catch (RuntimeException e) {
try {
return getParentBm().getInterceptorBindingDefinition(qualifier);
} catch (RuntimeException ignored) {
throw e;
}
}
}
@Override
public Set<Annotation> getStereotypeDefinition(Class<? extends Annotation> stereotype) {
final Set<Annotation> mtds = new HashSet<Annotation>();
internalUse.set(true);
try {
mtds.addAll(super.getStereotypeDefinition(stereotype));
} finally {
internalUse.set(false);
}
if (!internalUse.get()) {
mtds.addAll(getParentBm().getStereotypeDefinition(stereotype));
}
internalUse.remove();
return mtds;
}
@Override
public Context getContext(Class<? extends Annotation> scope) {
try {
return super.getContext(scope);
} catch (RuntimeException e) {
try {
return getParentBm().getContext(scope);
} catch (RuntimeException ignored) {
throw e;
}
}
}
@Override
public ELResolver getELResolver() {
return new WebAppElResolver(super.getELResolver(), getParentBm().getELResolver());
}
@Override
public <T> AnnotatedType<T> createAnnotatedType(Class<T> type) {
try {
return super.createAnnotatedType(type);
} catch (RuntimeException e) {
try {
return getParentBm().createAnnotatedType(type);
} catch (RuntimeException ignored) {
throw e;
}
}
}
@Override
public <T> InjectionTarget<T> createInjectionTarget(AnnotatedType<T> type) {
try {
return super.createInjectionTarget(type);
} catch (RuntimeException e) {
try {
return getParentBm().createInjectionTarget(type);
} catch (RuntimeException ignored) {
throw e;
}
}
}
@Override
public ExpressionFactory wrapExpressionFactory(javax.el.ExpressionFactory expressionFactory) {
return super.wrapExpressionFactory(expressionFactory);
}
public BeanManagerImpl getParentBm() {
return webappCtx.getParent().getBeanManagerImpl();
}
@Override
public boolean isInUse() {
return super.isInUse() || getParentBm().isInUse();
}
@Override
public Set<Bean<?>> getComponents() {
if (deploymentBeans.isEmpty()) {
// probably not yet merged (afterStart())
// so reuse parent beans
// this can happen for validations
return super.getBeans();
}
return deploymentBeans;
}
@Override
public Set<Bean<?>> getBeans() {
return deploymentBeans;
}
public void afterStart() {
deploymentBeans = new CopyOnWriteArraySet<Bean<?>>(); // override parent one with a "webapp" bean list
for (Bean<?> bean : getParentBm().getBeans()) {
if (bean instanceof BeanManagerBean || bean instanceof BuildInOwbBean
|| bean instanceof ConversationBean || bean instanceof InjectionPointBean) {
continue;
}
deploymentBeans.add(bean);
}
deploymentBeans.addAll(super.getBeans());
}
}