blob: 017946842910f2c08c818c9377062297412f65cf [file]
/*
* 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.container;
import java.lang.annotation.Annotation;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.lang.reflect.WildcardType;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import jakarta.annotation.PostConstruct;
import jakarta.annotation.PreDestroy;
import jakarta.el.ELResolver;
import jakarta.el.ExpressionFactory;
import jakarta.enterprise.context.ContextNotActiveException;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.context.NormalScope;
import jakarta.enterprise.context.spi.AlterableContext;
import jakarta.enterprise.context.spi.Context;
import jakarta.enterprise.context.spi.Contextual;
import jakarta.enterprise.context.spi.CreationalContext;
import jakarta.enterprise.event.Event;
import jakarta.enterprise.inject.Any;
import jakarta.enterprise.inject.Default;
import jakarta.enterprise.inject.InjectionException;
import jakarta.enterprise.inject.Instance;
import jakarta.enterprise.inject.Stereotype;
import jakarta.enterprise.inject.Vetoed;
import jakarta.enterprise.inject.spi.*;
import jakarta.inject.Named;
import jakarta.inject.Scope;
import jakarta.interceptor.InterceptorBinding;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.Referenceable;
import javax.naming.StringRefAddr;
import org.apache.webbeans.annotation.AnyLiteral;
import org.apache.webbeans.annotation.DefaultLiteral;
import org.apache.webbeans.component.AbstractOwbBean;
import org.apache.webbeans.component.AbstractProducerBean;
import org.apache.webbeans.component.CdiInterceptorBean;
import org.apache.webbeans.component.DecoratorBean;
import org.apache.webbeans.component.EnterpriseBeanMarker;
import org.apache.webbeans.component.InjectionTargetBean;
import org.apache.webbeans.component.JmsBeanMarker;
import org.apache.webbeans.component.ManagedBean;
import org.apache.webbeans.component.OwbBean;
import org.apache.webbeans.component.ProducerAwareInjectionTargetBean;
import org.apache.webbeans.component.WebBeansType;
import org.apache.webbeans.component.creation.BeanAttributesBuilder;
import org.apache.webbeans.component.creation.CdiInterceptorBeanBuilder;
import org.apache.webbeans.component.creation.DecoratorBeanBuilder;
import org.apache.webbeans.component.creation.FieldProducerFactory;
import org.apache.webbeans.component.creation.MethodProducerFactory;
import org.apache.webbeans.component.third.PassivationCapableThirdpartyBeanImpl;
import org.apache.webbeans.component.third.ThirdpartyBeanImpl;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.context.CustomAlterablePassivatingContextImpl;
import org.apache.webbeans.context.CustomPassivatingContextImpl;
import org.apache.webbeans.context.creational.CreationalContextImpl;
import org.apache.webbeans.decorator.DecoratorComparator;
import org.apache.webbeans.event.EventImpl;
import org.apache.webbeans.event.EventMetadataImpl;
import org.apache.webbeans.exception.WebBeansConfigurationException;
import org.apache.webbeans.exception.DuplicateDefinitionException;
import org.apache.webbeans.intercept.InterceptorUtil;
import org.apache.webbeans.plugins.OpenWebBeansJmsPlugin;
import org.apache.webbeans.portable.AnnotatedElementFactory;
import org.apache.webbeans.portable.InjectionTargetImpl;
import org.apache.webbeans.portable.LazyInterceptorDefinedInjectionTarget;
import org.apache.webbeans.portable.events.discovery.ErrorStack;
import org.apache.webbeans.portable.events.generics.GProcessInjectionPoint;
import org.apache.webbeans.portable.events.generics.GProcessInjectionTarget;
import org.apache.webbeans.spi.adaptor.ELAdaptor;
import org.apache.webbeans.spi.plugins.OpenWebBeansEjbPlugin;
import org.apache.webbeans.util.AnnotationUtil;
import org.apache.webbeans.util.Asserts;
import org.apache.webbeans.util.ClassUtil;
import org.apache.webbeans.util.GenericsUtil;
import org.apache.webbeans.util.WebBeansUtil;
/**
* Implementation of the {@link BeanManager} contract of the web beans
* container.
*
* <p>
* It is written as thread-safe.
* </p>
*
* @version $Rev$ $Date$
* @see BeanManager
*/
@SuppressWarnings("unchecked")
public class BeanManagerImpl implements BeanManager, Referenceable
{
private static final long serialVersionUID = 2L;
/**
* Holds the non-standard contexts with key = scope type
* This will get used if more than 1 scope exists.
* Since the contexts will only get added through the
* {@link org.apache.webbeans.portable.events.discovery.AfterBeanDiscoveryImpl}
* we don't even need a ConcurrentHashMap.
* @see #singleContextMap
*/
private Map<Class<? extends Annotation>, List<Context>> contextMap = new HashMap<>();
/**
* This will hold non-standard contexts where only one Context implementation got registered
* for the given key = scope type
* Since the contexts will only get added through the
* {@link org.apache.webbeans.portable.events.discovery.AfterBeanDiscoveryImpl}
* we don't even need a ConcurrentHashMap.
* @see #contextMap
*/
private Map<Class<? extends Annotation>, Context> singleContextMap = new HashMap<>();
/**Deployment archive beans*/
private Set<Bean<?>> deploymentBeans = new HashSet<>();
/**Normal scoped cache proxies*/
private Map<Contextual<?>, Object> cacheProxies = new ConcurrentHashMap<>();
/**Injection resolver instance*/
private InjectionResolver injectionResolver;
/**
* This list contains additional qualifiers which got set via the
* {@link jakarta.enterprise.inject.spi.BeforeBeanDiscovery#addQualifier(Class)}
* event function.
*/
private List<Class<? extends Annotation>> additionalQualifiers = new ArrayList<>();
private Map<Class<?>, AnnotatedType<? extends Annotation>> additionalAnnotatedTypeQualifiers = new HashMap<>();
/**
* This list contains additional scopes which got set via the
* {@link jakarta.enterprise.inject.spi.BeforeBeanDiscovery#addScope(Class, boolean, boolean)} event function.
*/
private List<ExternalScope> additionalScopes = new ArrayList<>();
/** quick detection if an annotation is a scope-annotation */
private Set<Class<? extends Annotation>> scopeAnnotations = new HashSet<>();
/** quick detection if an annotation is NOT a scope-annotation */
private Set<Class<? extends Annotation>> nonscopeAnnotations = new HashSet<>();
private ConcurrentMap<Class<?>, ConcurrentMap<String, AnnotatedType<?>>> additionalAnnotatedTypes = new ConcurrentHashMap<>();
private ErrorStack errorStack = new ErrorStack();
/**
* This map stores all beans along with their unique {@link jakarta.enterprise.inject.spi.PassivationCapable} id.
* This is used as a reference for serialization.
*/
private ConcurrentMap<String, Bean<?>> passivationBeans = new ConcurrentHashMap<>();
/**InjectionTargets for Java EE component instances that supports injections*/
private Map<Class<?>, Producer<?>> producersForJavaEeComponents =
new ConcurrentHashMap<>();
private AnnotatedElementFactory annotatedElementFactory;
/**
* A cache for bean classes which get created 'on the fly' by manually calling createInjectionTarget without a bean.
*/
private ConcurrentMap<Class<?>, Bean> unmanagedClassBeans = new ConcurrentHashMap<>();
private final WebBeansContext webBeansContext;
/**
* This flag will get set to <code>true</code> if a custom bean
* (all non-internal beans like {@link org.apache.webbeans.component.BeanManagerBean;} etc)
* gets set.
*/
private boolean inUse;
/**
* This flag will get set to handle lifecyle around
* {@link jakarta.enterprise.inject.spi.AfterBeanDiscovery}
*/
private LifecycleState beanDiscoveryState = LifecycleState.BEFORE_DISCOVERY;
/**
* This flag will get set to {@code true} after the
* {@link jakarta.enterprise.inject.spi.AfterDeploymentValidation} gets fired
*/
private boolean afterDeploymentValidationFired;
/**
* we cache results of calls to {@link #isNormalScope(Class)} because
* this doesn't change at runtime.
* We don't need to take special care about classloader
* hierarchies, because each cl has other classes.
*/
private Map<Class<? extends Annotation>, Boolean> isScopeTypeNormalCache =
new ConcurrentHashMap<>();
/**
* Map to be able to lookup always 3rd party beans when user does lookups with custom beans.
*/
private Map<Bean<?>, Bean<?>> thirdPartyMapping = new HashMap<>();
/**
* Creates a new {@link BeanManager} instance.
* Called by the system. Do not use outside of the
* system.
*/
public BeanManagerImpl(WebBeansContext webBeansContext)
{
this.webBeansContext = webBeansContext;
injectionResolver = new InjectionResolver(webBeansContext);
annotatedElementFactory = webBeansContext.getAnnotatedElementFactory();
}
public WebBeansContext getWebBeansContext()
{
return webBeansContext;
}
public <T> void putProducerForJavaEeComponent(Class<T> javaEeComponentClass, Producer<T> wrapper)
{
Asserts.assertNotNull(javaEeComponentClass);
Asserts.assertNotNull(wrapper);
producersForJavaEeComponents.put(javaEeComponentClass, wrapper);
}
public <T> Producer<T> getProducerForJavaEeComponent(Class<T> javaEeComponentClass)
{
Asserts.assertNotNull(javaEeComponentClass);
return (Producer<T>) producersForJavaEeComponents.get(javaEeComponentClass);
}
public ErrorStack getErrorStack()
{
return errorStack;
}
public ConcurrentMap<Class<?>, Bean> getUnmanagedClassBeans()
{
return unmanagedClassBeans;
}
/**
* Gets injection resolver.
*
* @return injection resolver
*/
public InjectionResolver getInjectionResolver()
{
return injectionResolver;
}
/**
* Gets the active context for the given scope type.
*
* @param scopeType scope type of the context
* @throws ContextNotActiveException if no active context
* @throws IllegalStateException if more than one active context
*/
@Override
public Context getContext(Class<? extends Annotation> scopeType)
{
Asserts.assertNotNull(scopeType, "scopeType");
Context standardContext = webBeansContext.getContextsService().getCurrentContext(scopeType);
if(standardContext != null && standardContext.isActive())
{
return standardContext;
}
// this is by far the most case
Context singleContext = singleContextMap.get(scopeType);
if (singleContext != null)
{
if (!singleContext.isActive())
{
throw new ContextNotActiveException("WebBeans context with scope type annotation @"
+ scopeType.getSimpleName()
+ " does not exist within current thread");
}
return singleContext;
}
// the spec also allows for multiple contexts existing for the same scope type
// but in this case only one must be active at a time (for the current thread)
List<Context> others = contextMap.get(scopeType);
Context found = null;
if(others != null)
{
for(Context otherContext : others)
{
if(otherContext.isActive())
{
if (found != null)
{
throw new IllegalStateException("More than one active context exists with scope type annotation @"
+ scopeType.getSimpleName());
}
found = otherContext;
}
}
}
if (found == null)
{
throw new ContextNotActiveException("WebBeans context with scope type annotation @"
+ scopeType.getSimpleName() + " does not exist within current thread");
}
return found;
}
@Override
public Instance<Object> createInstance()
{
return OwbCDI.current().select(DefaultLiteral.INSTANCE);
}
/**
* Add new bean to the BeanManager.
* This will also set OWBs {@link #inUse} status.
*
* @param newBean new bean instance
* @return the this manager
*/
public BeanManager addBean(Bean<?> newBean)
{
inUse = true;
return addInternalBean(newBean);
}
/**
* This method is reserved for adding 'internal beans'
* like e.g. a BeanManagerBean,
* @param newBean
* @return
*/
public <T> BeanManager addInternalBean(Bean<T> newBean)
{
if(newBean instanceof AbstractOwbBean)
{
addPassivationInfo(newBean);
deploymentBeans.add(newBean);
}
else
{
ThirdpartyBeanImpl<?> bean;
if (!PassivationCapable.class.isInstance(newBean))
{
bean = new ThirdpartyBeanImpl<>(webBeansContext, newBean);
}
else
{
bean = new PassivationCapableThirdpartyBeanImpl<>(webBeansContext, newBean);
}
addPassivationInfo(bean);
deploymentBeans.add(bean);
thirdPartyMapping.put(newBean, bean);
}
return this;
}
/**
* Check if the bean is has a passivation id and add it to the id store.
*
* @param bean
* @throws DefinitionException if the id is not unique.
*/
public void addPassivationInfo(Bean<?> bean) throws DefinitionException
{
String id = null;
if (bean instanceof OwbBean<?>)
{
id = ((OwbBean) bean).getId();
}
if (id == null && bean instanceof PassivationCapable)
{
id = ((PassivationCapable) bean).getId();
}
if(id != null)
{
Bean<?> oldBean = passivationBeans.putIfAbsent(id, bean);
if (oldBean != null)
{
throw new DuplicateDefinitionException("PassivationCapable bean id is not unique: " +
id + " bean:" + bean + ", existing: " + oldBean);
}
}
}
public BeanManager addContext(Context context)
{
addContext(context.getScope(), wrapCustomContext(context));
return this;
}
/**
* If the context is passivating then we need to wrap it into a version which
* uses the {@link SerializableBeanVault }
*/
public Context wrapCustomContext(Context context)
{
if (isPassivatingScope(context.getScope()))
{
if (context instanceof AlterableContext)
{
return new CustomAlterablePassivatingContextImpl(webBeansContext.getSerializableBeanVault(), (AlterableContext) context);
}
else
{
return new CustomPassivatingContextImpl(webBeansContext.getSerializableBeanVault(), context);
}
}
return context;
}
/**
* @deprecated This method got deprecated in CDI-2.0.
* Users should use {@link #getEvent()} instead.
*/
public void fireEvent(Object event, Annotation... bindings)
{
fireEvent(event, false, bindings);
}
@Override
public Event<Object> getEvent()
{
return new EventImpl<>(new EventMetadataImpl(null, Object.class, null, new Annotation[]{AnyLiteral.INSTANCE}, webBeansContext), webBeansContext);
}
public void fireEvent(Object event, boolean containerEvent, Annotation... bindings)
{
Type type = event.getClass();
if (GenericsUtil.hasTypeParameters(type))
{
type = GenericsUtil.getParameterizedType(type);
}
fireEvent(event, new EventMetadataImpl(null, type, null, bindings, webBeansContext), containerEvent);
}
/**
* Fire &#064;Initialized and &#064Destroyed events, but only IF any observers do exist.
*/
public void fireContextLifecyleEvent(Object payload, Annotation lifecycleQualifier)
{
if (webBeansContext.getNotificationManager().hasContextLifecycleObserver(lifecycleQualifier))
{
fireEvent(payload, lifecycleQualifier);
}
}
/**
* Like {@link #fireEvent(Object, java.lang.annotation.Annotation...)} but intended for
* internal CDI Container lifecycle events. The difference is that those
* events must only be delivered to CDI Extensions and not to normal beans.
*/
public void fireLifecycleEvent(Object event, Annotation... bindings)
{
fireEvent(event, new EventMetadataImpl(null, event.getClass(), null, bindings, webBeansContext), true);
}
public void fireEvent(Object event, EventMetadataImpl metadata, boolean isLifecycleEvent)
{
webBeansContext.getNotificationManager().fireEvent(event, metadata, isLifecycleEvent, null);
}
public Set<Bean<?>> getComponents()
{
return deploymentBeans;
}
/**
* {@inheritDoc}
*/
@Override
public List<Decorator<?>> resolveDecorators(Set<Type> types, Annotation... bindingTypes)
{
webBeansContext.getAnnotationManager().checkDecoratorResolverParams(types, bindingTypes);
return unsafeResolveDecorators(types, bindingTypes);
}
public List<Decorator<?>> unsafeResolveDecorators(Set<Type> types, Annotation[] bindingTypes)
{
webBeansContext.getAnnotationManager().checkQualifiersParams(types, bindingTypes); // checkDecoratorResolverParams is too restrictive for repeatable bindings
Set<Decorator<?>> intsSet = webBeansContext.getDecoratorsManager().findDeployedWebBeansDecorator(types, bindingTypes);
List<Decorator<?>> decoratorList = new ArrayList<>(intsSet);
decoratorList.sort(new DecoratorComparator(webBeansContext));
return decoratorList;
}
/**
* {@inheritDoc}
*/
@Override
public List<Interceptor<?>> resolveInterceptors(InterceptionType type, Annotation... interceptorBindings)
{
webBeansContext.getAnnotationManager().checkInterceptorResolverParams(interceptorBindings);
return webBeansContext.getInterceptorsManager().resolveInterceptors(type, interceptorBindings);
}
public Set<Bean<?>> getBeans()
{
return deploymentBeans;
}
private void addContext(Class<? extends Annotation> scopeType, jakarta.enterprise.context.spi.Context context)
{
Asserts.assertNotNull(scopeType, "scopeType");
Asserts.assertNotNull(context, "context");
List<Context> contextList = contextMap.get(scopeType);
if(contextList == null)
{
Context singleContext = singleContextMap.get(scopeType);
if (singleContext == null)
{
// first put them into the singleContextMap
singleContextMap.put(scopeType, context);
}
else
{
// from the 2nd Context for this scopetype on, we need to maintain a List for them
contextList = new ArrayList<>();
contextList.add(singleContext);
contextList.add(context);
contextMap.put(scopeType, contextList);
singleContextMap.remove(scopeType);
}
}
else
{
contextList.add(context);
}
}
@Override
public Reference getReference() throws NamingException
{
return new Reference(BeanManagerImpl.class.getName(), new StringRefAddr("ManagerImpl", "ManagerImpl"), ManagerObjectFactory.class.getName(), null);
}
/**
* {@inheritDoc}
*/
@Override
public <T> AnnotatedType<T> createAnnotatedType(Class<T> type)
{
return annotatedElementFactory.newAnnotatedType(type);
}
/**
* {@inheritDoc}
*/
@Override
public <T> CreationalContextImpl<T> createCreationalContext(Contextual<T> contextual)
{
if (contextual instanceof SerializableBean)
{
contextual = ((SerializableBean)contextual).getBean();
}
return webBeansContext.getCreationalContextFactory().getCreationalContext(contextual);
}
/**
* {@inheritDoc}
*/
@Override
public Set<Bean<?>> getBeans(Type beanType, Annotation... bindings)
{
if(ClassUtil.isTypeVariable(beanType))
{
throw new IllegalArgumentException("Exception in getBeans method. Bean type can not be TypeVariable for bean type : " + beanType);
}
webBeansContext.getAnnotationManager().checkQualifierConditions(bindings);
return injectionResolver.implResolveByType(false, beanType, bindings);
}
@Override
public Set<Bean<?>> getBeans(String name)
{
Asserts.assertNotNull(name, "name");
return injectionResolver.implResolveByName(name);
}
@Override
public ELResolver getELResolver()
{
ELAdaptor elAdaptor = webBeansContext.getService(ELAdaptor.class);
return elAdaptor.getOwbELResolver();
}
/**
* {@inheritDoc}
*/
@Override
public Object getInjectableReference(InjectionPoint injectionPoint, CreationalContext<?> ownerCreationalContext)
{
//Injection point is null
if(injectionPoint == null)
{
return null;
}
//Injected instance
Object instance;
//Find the injection point Bean
Bean<Object> injectedBean = (Bean<Object>)injectionResolver.getInjectionPointBean(injectionPoint);
if(WebBeansUtil.isDependent(injectedBean))
{
if (!(ownerCreationalContext instanceof CreationalContextImpl))
{
ownerCreationalContext = webBeansContext.getCreationalContextFactory().wrappedCreationalContext(ownerCreationalContext, injectionPoint.getBean());
}
if (injectionPoint.isDelegate() && ((CreationalContextImpl<?>)ownerCreationalContext).getDelegate() != null)
{
// this is a dirty hack for Custom Decorators which inject into @Delegate InjectionPoints
// by using getInjectableReference. Done in the TCK. Never seen this for real though...
return ((CreationalContextImpl<?>)ownerCreationalContext).getDelegate();
}
((CreationalContextImpl<?>)ownerCreationalContext).putInjectionPoint(injectionPoint);
//Using owner creational context
//Dependents use parent creational context
try
{
instance = getReference(injectedBean, injectionPoint.getType(), ownerCreationalContext);
}
finally
{
((CreationalContextImpl<?>)ownerCreationalContext).removeInjectionPoint();
}
}
else
{
//New creational context for normal scoped beans
CreationalContextImpl<Object> injectedCreational = (CreationalContextImpl<Object>)createCreationalContext(injectedBean);
injectedCreational.putInjectionPoint(injectionPoint);
try
{
instance = getReference(injectedBean, injectionPoint.getType(), injectedCreational);
}
finally
{
injectedCreational.removeInjectionPoint();
}
}
return instance;
}
/**
* {@inheritDoc}
*/
@Override
public Set<Annotation> getInterceptorBindingDefinition(Class<? extends Annotation> binding)
{
Annotation[] annotations = binding.getDeclaredAnnotations();
Set<Annotation> set = new HashSet<>();
if(binding.isAnnotationPresent(InterceptorBinding.class))
{
Collections.addAll(set, annotations);
}
return set;
}
@Override
public Bean<?> getPassivationCapableBean(String id)
{
return passivationBeans.get(id);
}
/**
* {@inheritDoc}
*/
@Override
public Object getReference(Bean<?> providedBean, Type beanType, CreationalContext<?> creationalContext)
{
Asserts.assertNotNull(providedBean, "bean parameter");
Context context;
Object instance;
Bean<?> bean = !OwbBean.class.isInstance(providedBean) ? thirdPartyMapping.get(providedBean) : providedBean;
if (bean == null) // more than unlikely but still possible and not invalid (user could create new instance of bean each time, not forbidden)
{
bean = providedBean;
}
if (bean instanceof SerializableBean)
{
bean = ((SerializableBean)bean).getBean();
}
if(!(creationalContext instanceof CreationalContextImpl))
{
creationalContext = webBeansContext.getCreationalContextFactory().wrappedCreationalContext(creationalContext, bean);
}
if (ManagedBean.class.isInstance(bean))
{
ManagedBean.class.cast(bean).valid();
}
//Check type if bean type is given
if(beanType != null && beanType != Object.class)
{
boolean isProducer = bean instanceof AbstractProducerBean;
if(!isProducer && // we have different rules for producers
!isBeanTypeAssignableToGivenType(bean.getTypes(), beanType, false) &&
!GenericsUtil.satisfiesDependency(false, false, beanType, bean.getBeanClass(), new HashMap<>()) &&
!GenericsUtil.satisfiesDependencyRaw(false, false, beanType, bean.getBeanClass(), new HashMap<>()))
{
throw new IllegalArgumentException("Given bean type : " + beanType + " is not applicable for the bean instance : " + bean);
}
}
else if (bean instanceof OwbBean)
{
// we cannot always use getBeanClass() as this will
// return the containing class for producer methods and fields
beanType = ((OwbBean) bean).getReturnType();
}
else
{
beanType = bean.getBeanClass();
}
//Scope is normal
if (isNormalScope(bean.getScope()))
{
instance = getEjbOrJmsProxyReference(bean, beanType,creationalContext);
if(instance != null)
{
return instance;
}
instance = cacheProxies.get(bean);
if (instance == null)
{
//Create Managed Bean Proxy
instance = webBeansContext.getNormalScopeProxyFactory().createNormalScopeProxy(bean);
//Cached instance
cacheProxies.put(bean, instance);
}
}
//Create Pseudo-Scope Bean Instance
else
{
//Get bean context
context = getContext(bean.getScope());
//Get instance for ejb or jms
instance = getEjbOrJmsProxyReference(bean, beanType, creationalContext);
if(instance != null)
{
return instance;
}
//Get dependent from DependentContex that create contextual instance
instance = context.get((Bean<Object>)bean, (CreationalContext<Object>)creationalContext);
}
return instance;
}
/**
* {@inheritDoc}
*/
@Override
public BeanAttributes<?> createBeanAttributes(AnnotatedMember<?> member)
{
if (member instanceof AnnotatedField)
{
return BeanAttributesBuilder.forContext(webBeansContext).newBeanAttibutes((AnnotatedField<?>)member).build();
}
else if (member instanceof AnnotatedMethod)
{
return BeanAttributesBuilder.forContext(webBeansContext).newBeanAttibutes((AnnotatedMethod<?>)member).build();
}
else
{
throw new IllegalArgumentException("Unsupported member type " + member.getClass().getName());
}
}
@Override
public InjectionPoint createInjectionPoint(AnnotatedField<?> field)
{
return webBeansContext.getInjectionPointFactory().buildInjectionPoint(null, field, false);
}
@Override
public InjectionPoint createInjectionPoint(AnnotatedParameter<?> parameter)
{
InjectionPoint injectionPoint = webBeansContext.getInjectionPointFactory().buildInjectionPoint(null, parameter, false);
if (AnnotatedMethod.class.isInstance(parameter.getDeclaringCallable()))
{
try
{
validate(injectionPoint);
}
catch (Exception e)
{
throw new IllegalArgumentException(e);
}
} // TODO else constructor rules are a bit different
GProcessInjectionPoint event = webBeansContext.getWebBeansUtil().fireProcessInjectionPointEvent(injectionPoint);
injectionPoint = event.getInjectionPoint();
event.setStarted();
return injectionPoint;
}
@Override
public <X> ProducerFactory<X> getProducerFactory(AnnotatedField<? super X> field, Bean<X> bean)
{
return new FieldProducerFactory<>(field, bean, webBeansContext);
}
@Override
public <X> ProducerFactory<X> getProducerFactory(AnnotatedMethod<? super X> method, Bean<X> bean)
{
return new MethodProducerFactory<>(method, bean, webBeansContext);
}
@Override
public <X> InjectionTargetFactory<X> getInjectionTargetFactory(AnnotatedType<X> type)
{
return new ValidatingInjectionTargetFactory<>(type, webBeansContext);
}
@Override
public <T> Bean<T> createBean(BeanAttributes<T> attributes, Class<T> type, InjectionTargetFactory<T> factory)
{
AnnotatedType annotatedType = InjectionTargetFactoryImpl.class.isInstance(factory) ?
InjectionTargetFactoryImpl.class.cast(factory).getAnnotatedType() : getOrCreateAnnotatedType(type);
if (WebBeansUtil.isDecorator(annotatedType))
{
DecoratorBeanBuilder<T> dbb = new DecoratorBeanBuilder<T>(webBeansContext, annotatedType, attributes);
DecoratorBean<T> decorator = null;
if (dbb.isDecoratorEnabled())
{
dbb.defineDecoratorRules();
decorator = dbb.getBean();
webBeansContext.getDecoratorsManager().addDecorator(decorator);
}
return decorator;
}
else if(WebBeansUtil.isCdiInterceptor(annotatedType))
{
CdiInterceptorBeanBuilder<T> ibb = new CdiInterceptorBeanBuilder<T>(webBeansContext, annotatedType, attributes);
CdiInterceptorBean<T> interceptor = null;
if (ibb.isInterceptorEnabled())
{
ibb.defineCdiInterceptorRules();
interceptor = ibb.getBean();
webBeansContext.getInterceptorsManager().addCdiInterceptor(interceptor);
}
return interceptor;
}
InjectionTargetBean<T> bean = new InjectionTargetBean<T>(
webBeansContext,
WebBeansType.THIRDPARTY,
annotatedType,
attributes, type, factory);
if (webBeansContext.getOpenWebBeansConfiguration().supportsInterceptionOnProducers())
{
bean.defineInterceptorsIfNeeded();
}
return bean;
}
private <T> AnnotatedType<T> getOrCreateAnnotatedType(Class<T> type)
{
AnnotatedType<T> annotatedType = webBeansContext.getAnnotatedElementFactory().getAnnotatedType(type);
if (annotatedType == null)
{
annotatedType = webBeansContext.getAnnotatedElementFactory().newAnnotatedType(type);
}
return annotatedType;
}
private boolean isBeanTypeAssignableToGivenType(Set<Type> beanTypes, Type givenType, boolean producer)
{
for (Type beanApiType : beanTypes)
{
if (GenericsUtil.satisfiesDependency(false, producer, givenType, beanApiType, new HashMap<>()))
{
return true;
}
}
return false;
}
private Object getEjbOrJmsProxyReference(Bean<?> bean,Type beanType, CreationalContext<?> creationalContext)
{
//Create session bean proxy
if(bean instanceof EnterpriseBeanMarker)
{
if(isNormalScope(bean.getScope()))
{
//Maybe it is cached
if(cacheProxies.containsKey(bean))
{
return cacheProxies.get(bean);
}
}
OpenWebBeansEjbPlugin ejbPlugin = webBeansContext.getPluginLoader().getEjbPlugin();
if(ejbPlugin == null)
{
throw new IllegalStateException("There is no EJB plugin provider. Injection is failed for bean : " + bean);
}
return ejbPlugin.getSessionBeanProxy(bean,ClassUtil.getClazz(beanType), creationalContext);
}
//Create JMS Proxy
else if(bean instanceof JmsBeanMarker)
{
OpenWebBeansJmsPlugin jmsPlugin = webBeansContext.getPluginLoader().getJmsPlugin();
if(jmsPlugin == null)
{
throw new IllegalStateException("There is no JMS plugin provider. Injection is failed for bean : " + bean);
}
return jmsPlugin.getJmsBeanProxy(bean, ClassUtil.getClass(beanType));
}
return null;
}
@Override
public Set<Annotation> getStereotypeDefinition(Class<? extends Annotation> stereotype)
{
Annotation[] annotations = stereotype.getDeclaredAnnotations();
Set<Annotation> set = new HashSet<>();
if(stereotype.isAnnotationPresent(Stereotype.class))
{
Collections.addAll(set, annotations);
}
return set;
}
@Override
public boolean isQualifier(Class<? extends Annotation> annotationType)
{
return webBeansContext.getAnnotationManager().isQualifierAnnotation(annotationType);
}
@Override
public boolean isInterceptorBinding(Class<? extends Annotation> annotationType)
{
return webBeansContext.getAnnotationManager().isInterceptorBindingAnnotation(annotationType);
}
@Override
public boolean isScope(Class<? extends Annotation> annotationType)
{
if (nonscopeAnnotations.contains(annotationType))
{
return false;
}
if (scopeAnnotations.contains(annotationType))
{
return true;
}
boolean isScopeAnnotation = annotationType.getAnnotation(Scope.class) != null ||
annotationType.getAnnotation(NormalScope.class) != null;
if (!isScopeAnnotation)
{
// also check external scopes
for (ExternalScope es : getAdditionalScopes())
{
if (es.getScope().equals(annotationType))
{
isScopeAnnotation = true;
break;
}
}
}
if (isScopeAnnotation)
{
scopeAnnotations.add(annotationType);
}
else
{
nonscopeAnnotations.add(annotationType);
}
return isScopeAnnotation;
}
@Override
public boolean isNormalScope(Class<? extends Annotation> scopeType)
{
Boolean isNormal = isScopeTypeNormalCache.get(scopeType);
if (isNormal != null)
{
return isNormal;
}
for(ExternalScope extScope : additionalScopes)
{
if (extScope.getScope().equals(scopeType))
{
isScopeTypeNormalCache.put(scopeType, extScope.isNormal());
return extScope.isNormal();
}
}
isNormal = scopeType.getAnnotation(NormalScope.class) != null;
isScopeTypeNormalCache.put(scopeType, isNormal);
return isNormal;
}
@Override
public boolean isPassivatingScope(Class<? extends Annotation> annotationType)
{
for(ExternalScope extScope : additionalScopes)
{
if (extScope.getScope().equals(annotationType))
{
return extScope.isPassivating();
}
}
NormalScope scope = annotationType.getAnnotation(NormalScope.class);
if(scope != null)
{
return scope.passivating();
}
return false;
}
@Override
public boolean isStereotype(Class<? extends Annotation> annotationType)
{
return AnnotationUtil.hasAnnotation(annotationType.getDeclaredAnnotations(), Stereotype.class);
}
@Override
public boolean areInterceptorBindingsEquivalent(Annotation annotation1, Annotation annotation2)
{
return AnnotationUtil.isCdiAnnotationEqual(annotation1, annotation2);
}
@Override
public boolean areQualifiersEquivalent(Annotation annotation1, Annotation annotation2)
{
return AnnotationUtil.isCdiAnnotationEqual(annotation1, annotation2);
}
@Override
public int getInterceptorBindingHashCode(Annotation annotation)
{
return AnnotationUtil.getCdiAnnotationHashCode(annotation);
}
@Override
public int getQualifierHashCode(Annotation annotation)
{
return AnnotationUtil.getCdiAnnotationHashCode(annotation);
}
/**
* {@inheritDoc}
*/
public <T> BeanAttributes<T> createBeanAttributes(AnnotatedType<T> type)
{
OpenWebBeansEjbPlugin ejbPlugin = webBeansContext.getPluginLoader().getEjbPlugin();
if (ejbPlugin != null && ejbPlugin.isSessionBean(type.getJavaClass()))
{
return ejbPlugin.createBeanAttributes(type);
}
return BeanAttributesBuilder.forContext(webBeansContext).newBeanAttibutes(type).build();
}
@Override
public <T, X> Bean<T> createBean(BeanAttributes<T> attributes, Class<X> type, ProducerFactory<X> factory)
{
return new ProducerAwareInjectionTargetBean<>(
webBeansContext,
WebBeansType.THIRDPARTY,
attributes,
findClass(factory, type),
factory);
}
private Class<?> findClass(ProducerFactory<?> factory, Class<?> type)
{
if (MethodProducerFactory.class.isInstance(factory))
{
return MethodProducerFactory.class.cast(factory).getReturnType();
}
if (FieldProducerFactory.class.isInstance(factory))
{
return FieldProducerFactory.class.cast(factory).getReturnType();
}
return type;
}
public <T extends Extension> T getExtension(Class<T> type)
{
T extension = webBeansContext.getExtensionLoader().getExtension(type);
if (extension == null)
{
throw new IllegalArgumentException("extension " + type + " not registered");
}
return extension;
}
@Override
public <X> Bean<? extends X> resolve(Set<Bean<? extends X>> beans)
{
return injectionResolver.resolve(beans, null);
}
@Override
public <T> InterceptionFactory<T> createInterceptionFactory(CreationalContext<T> creationalContext, Class<T> clazz)
{
return new InterceptionFactoryImpl(
webBeansContext, createAnnotatedType(clazz), AnnotationUtil.DEFAULT_AND_ANY_ANNOTATION_SET,
// ok, we can need to not cast that brutally
CreationalContextImpl.class.cast(creationalContext));
}
/**
* {@inheritDoc}
*/
@Override
public void validate(InjectionPoint injectionPoint)
{
if (injectionPoint == null)
{
throw new IllegalArgumentException("InjectionPoint parameter must not be nul");
}
Bean<?> bean = injectionPoint.getBean();
//Check for correct injection type
injectionResolver.checkInjectionPointType(injectionPoint);
Class<?> rawType = ClassUtil.getRawTypeForInjectionPoint(injectionPoint);
// check for InjectionPoint injection
if (rawType.equals(InjectionPoint.class))
{
if (AnnotationUtil.hasAnnotation(AnnotationUtil.asArray(injectionPoint.getQualifiers()), Default.class))
{
if (!bean.getScope().equals(Dependent.class))
{
throw new WebBeansConfigurationException("Bean " + bean.getBeanClass() + " scope can not define other scope except @Dependent to inject InjectionPoint");
}
}
}
else
{
injectionResolver.checkInjectionPoint(injectionPoint);
}
}
/**
* @deprecated This method got deprecated in CDI-1.1 and removed in CDI-4.0.
* Use {@link #getInjectionTargetFactory(AnnotatedType)} instead.
*/
@Deprecated
public <T> InjectionTarget<T> createInjectionTarget(AnnotatedType<T> type)
{
InjectionTargetFactoryImpl<T> factory = new InjectionTargetFactoryImpl<>(type, webBeansContext);
InterceptorUtil interceptorUtil = webBeansContext.getInterceptorUtil();
InjectionTargetImpl<T> injectionTarget = new LazyInterceptorDefinedInjectionTarget<>(
type,
factory.createInjectionPoints(null),
webBeansContext,
interceptorUtil.getLifecycleMethods(type, PostConstruct.class),
interceptorUtil.getLifecycleMethods(type, PreDestroy.class));
if (isAfterBeanDiscoveryDone())
{
try
{
webBeansContext.getWebBeansUtil().validate(injectionTarget.getInjectionPoints(), null);
}
catch (InjectionException | DeploymentException | WebBeansConfigurationException ie)
{
throw new IllegalArgumentException(ie);
}
}
GProcessInjectionTarget event = webBeansContext.getWebBeansUtil().fireProcessInjectionTargetEvent(injectionTarget, type);
InjectionTarget it = event.getInjectionTarget();
event.setStarted();
return it;
}
@Override
public <T> Set<ObserverMethod<? super T>> resolveObserverMethods(T event, Annotation... qualifiers)
{
return resolveObserverMethods(event, new EventMetadataImpl(null, event.getClass(), null, qualifiers, webBeansContext));
}
public <T> Set<ObserverMethod<? super T>> resolveObserverMethods(T event, EventMetadataImpl metadata)
{
LinkedList<ObserverMethod<? super Object>> observerMethods
= new LinkedList<>(webBeansContext.getNotificationManager().resolveObservers(event, metadata, false));
// new in CDI-2.0: sort observers
observerMethods.sort(Comparator.comparingInt(ObserverMethod::getPriority));
return new LinkedHashSet<>(observerMethods);
}
@Override
public ExpressionFactory wrapExpressionFactory(ExpressionFactory expressionFactory)
{
ELAdaptor elAdaptor = webBeansContext.getService(ELAdaptor.class);
return elAdaptor.getOwbWrappedExpressionFactory(expressionFactory);
}
@Override
public Collection<Context> getContexts(Class<? extends Annotation> scopeType)
{
Asserts.assertNotNull(scopeType, "scopeType");
List<Context> result = new ArrayList<>();
Context standardContext = webBeansContext.getContextsService().getCurrentContext(scopeType, false);
if (standardContext != null)
{
result.add(standardContext);
}
List<Context> registered = contextMap.get(scopeType);
if (registered != null && !registered.isEmpty())
{
result.addAll(registered);
}
else
{
Context singleRegistered = singleContextMap.get(scopeType);
if (singleRegistered != null)
{
result.add(singleRegistered);
}
}
return List.copyOf(result);
}
@Override
public boolean isMatchingBean(Set<Type> beanTypes, Set<Annotation> beanQualifiers, Type requiredType, Set<Annotation> requiredQualifiers)
{
if (beanTypes == null)
{
throw new IllegalArgumentException("Null bean types");
}
if (beanQualifiers == null)
{
throw new IllegalArgumentException("Null bean qualifiers");
}
if (requiredType == null)
{
throw new IllegalArgumentException("Null bean type");
}
if (requiredQualifiers == null)
{
throw new IllegalArgumentException("Null required qualifiers");
}
validateAssignabilityQualifiers(beanQualifiers, "beanQualifiers annotation not a qualifier");
validateAssignabilityQualifiers(requiredQualifiers, "requiredQualifiers annotation not a qualifier");
Set<Type> legalBeanTypes = new HashSet<>();
legalBeanTypes.add(Object.class);
for (Type beanType : beanTypes)
{
if (!isIllegalBeanTypeForAssignability(beanType))
{
legalBeanTypes.add(beanType);
}
}
if (!matchesRequiredBeanType(requiredType, legalBeanTypes))
{
return false;
}
Set<Annotation> normalizedBeanQualifiers = normalizeBeanQualifiersForAssignability(beanQualifiers);
Set<Annotation> normalizedRequired = requiredQualifiers.isEmpty()
? Collections.singleton(DefaultLiteral.INSTANCE)
: new HashSet<>(requiredQualifiers);
return hasAllQualifiers(normalizedBeanQualifiers, normalizedRequired);
}
@Override
public boolean isMatchingEvent(Type specifiedType, Set<Annotation> specifiedQualifiers, Type observedEventType, Set<Annotation> observedEventQualifiers)
{
if (specifiedType == null)
{
throw new IllegalArgumentException("Null event type");
}
if (specifiedQualifiers == null)
{
throw new IllegalArgumentException("Null specified qualifiers");
}
if (observedEventType == null)
{
throw new IllegalArgumentException("Null observed event type");
}
if (observedEventQualifiers == null)
{
throw new IllegalArgumentException("Null observed event qualifiers");
}
if (containsUnboundTypeVariable(specifiedType))
{
throw new IllegalArgumentException("Type variable in event type");
}
validateAssignabilityQualifiers(specifiedQualifiers, "A specifiedQualifiers annotation not a qualifier");
validateAssignabilityQualifiers(observedEventQualifiers, "An observedEventQualifiers annotation not a qualifier");
Class<?> eventClass = ClassUtil.getClazz(specifiedType);
Set<Type> eventTypeClosure = GenericsUtil.getTypeClosure(specifiedType, eventClass);
if (GenericsUtil.containTypeVariable(eventTypeClosure))
{
throw new IllegalArgumentException("Type variable in event type");
}
if (!matchesObservedEventType(observedEventType, eventTypeClosure))
{
return false;
}
Set<Annotation> normalizedEventQualifiers = new HashSet<>(specifiedQualifiers);
if (normalizedEventQualifiers.isEmpty())
{
normalizedEventQualifiers.add(DefaultLiteral.INSTANCE);
}
normalizedEventQualifiers.add(AnyLiteral.INSTANCE);
return hasAllQualifiers(normalizedEventQualifiers, observedEventQualifiers);
}
public void addAdditionalQualifier(Class<? extends Annotation> qualifier)
{
if (!additionalQualifiers.contains(qualifier))
{
additionalQualifiers.add(qualifier);
}
}
public void addAdditionalQualifier(AnnotatedType<? extends Annotation> qualifier)
{
if (qualifier != null && !additionalQualifiers.contains(qualifier.getJavaClass()))
{
additionalAnnotatedTypeQualifiers.put(qualifier.getJavaClass(), qualifier);
additionalQualifiers.add(qualifier.getJavaClass());
}
}
public void addAdditionalAnnotatedType(Object extension, AnnotatedType<?> annotatedType)
{
addAdditionalAnnotatedType(
extension, annotatedType,
// ensure this string is stable accross a cluster for web scopes
extension.getClass().getName() + annotatedType + AnnotatedElementFactory.OWB_DEFAULT_KEY);
}
public <T> void addAdditionalAnnotatedType(Object extension, AnnotatedType<T> inAnnotatedType, String id)
{
if (id == null)
{
id = AnnotatedElementFactory.OWB_DEFAULT_KEY;
}
AnnotatedType<T> annotatedType = new AnnotatedTypeWrapper<>(Extension.class.cast(extension), inAnnotatedType, id);
if (annotatedType.getAnnotation(Vetoed.class) != null)
{
// we could check package here too but would be a lost of time 99.99% of the time
return;
}
webBeansContext.getAnnotatedElementFactory().setAnnotatedType(annotatedType, id);
ConcurrentMap<String, AnnotatedType<?>> annotatedTypes = additionalAnnotatedTypes.get(annotatedType.getJavaClass());
if (annotatedTypes == null)
{
annotatedTypes = new ConcurrentHashMap<>();
ConcurrentMap<String, AnnotatedType<?>> oldAnnotatedTypes = additionalAnnotatedTypes.putIfAbsent(annotatedType.getJavaClass(), annotatedTypes);
if (oldAnnotatedTypes != null)
{
annotatedTypes = oldAnnotatedTypes;
}
}
annotatedTypes.put(id, annotatedType);
}
public void removeAdditionalAnnotatedType(AnnotatedType<?> annotatedType)
{
removeAdditionalAnnotatedType(annotatedType, AnnotatedElementFactory.OWB_DEFAULT_KEY);
}
public void removeAdditionalAnnotatedType(AnnotatedType<?> annotatedType, String id)
{
ConcurrentMap<String, AnnotatedType<?>> annotatedTypes = additionalAnnotatedTypes.get(annotatedType.getJavaClass());
if (annotatedTypes == null)
{
return;
}
if (annotatedType.equals(annotatedTypes.get(id)))
{
annotatedTypes.remove(id);
}
}
public List<Class<? extends Annotation>> getAdditionalQualifiers()
{
return additionalQualifiers;
}
public Map<Class<?>, AnnotatedType<? extends Annotation>> getAdditionalAnnotatedTypeQualifiers()
{
return additionalAnnotatedTypeQualifiers;
}
public void addAdditionalScope(ExternalScope additionalScope)
{
if (!additionalScopes.contains(additionalScope))
{
additionalScopes.add(additionalScope);
}
}
public List<ExternalScope> getAdditionalScopes()
{
return additionalScopes;
}
public Collection<AnnotatedType<?>> getAdditionalAnnotatedTypes()
{
Collection<AnnotatedType<?>> annotatedTypes = new ArrayList<>();
for (ConcurrentMap<String,AnnotatedType<?>> types: additionalAnnotatedTypes.values())
{
annotatedTypes.addAll(types.values());
}
return annotatedTypes;
}
public <T> AnnotatedType<T> getAdditionalAnnotatedType(Class<T> type, String id)
{
if (id == null)
{
return annotatedElementFactory.getAnnotatedType(type);
}
ConcurrentMap<String, AnnotatedType<?>> annotatedTypes = additionalAnnotatedTypes.get(type);
if (annotatedTypes == null)
{
return null;
}
return (AnnotatedType<T>)annotatedTypes.get(id);
}
public <T> String getId(Class<T> type, AnnotatedType<T> at)
{
ConcurrentMap<String, AnnotatedType<?>> additionals = additionalAnnotatedTypes.get(type);
if (additionals != null)
{
for (Map.Entry<String, AnnotatedType<?>> entry : additionals.entrySet())
{
if (entry.getValue() == at)
{
return entry.getKey();
}
}
}
return null;
}
public <T> Collection<AnnotatedType<T>> getUserAnnotatedTypes(Class<T> type)
{
final ConcurrentMap<String, AnnotatedType<?>> aTypes = additionalAnnotatedTypes.get(type);
if (aTypes != null)
{
Collection<AnnotatedType<T>> types = new ArrayList<>(2);
for (AnnotatedType at : aTypes.values())
{
types.add(at);
}
return types;
}
return null;
}
public boolean hasAdditionalDefaultAnnotatedType(AnnotatedType<?> annotatedType)
{
final ConcurrentMap<String, AnnotatedType<?>> annotatedTypes = additionalAnnotatedTypes.get(annotatedType.getJavaClass());
if (annotatedTypes == null)
{
return false;
}
for (AnnotatedType<?> candidate : annotatedTypes.values())
{
if (candidate == annotatedType || !(candidate instanceof AnnotatedTypeWrapper))
{
continue;
}
AnnotatedTypeWrapper<?> wrapper = (AnnotatedTypeWrapper<?>) candidate;
if (wrapper.getId().endsWith(AnnotatedElementFactory.OWB_DEFAULT_KEY) &&
candidate.getAnnotations().equals(annotatedType.getAnnotations())) // strictly it is qualifiers only but faster
{
return true;
}
}
return false;
}
public <T> Iterable<AnnotatedType<T>> getAnnotatedTypes(Class<T> type)
{
final Collection<AnnotatedType<T>> types = new ArrayList<>(2);
AnnotatedType<T> annotatedType = annotatedElementFactory.getAnnotatedType(type);
if (annotatedType != null)
{
types.add(annotatedType);
}
final Collection<AnnotatedType<T>> userAnnotatedTypes = getUserAnnotatedTypes(type);
if (userAnnotatedTypes != null)
{
types.addAll(userAnnotatedTypes);
}
return types;
}
public void clear()
{
additionalAnnotatedTypes.clear();
additionalQualifiers.clear();
additionalScopes.clear();
scopeAnnotations.clear();
nonscopeAnnotations.clear();
clearCacheProxies();
singleContextMap.clear();
contextMap.clear();
deploymentBeans.clear();
errorStack.clear();
producersForJavaEeComponents.clear();
passivationBeans.clear();
webBeansContext.getInterceptorsManager().clear();
webBeansContext.getDecoratorsManager().clear();
webBeansContext.getAnnotatedElementFactory().clear();
injectionResolver.clearCaches();
webBeansContext.getAnnotationManager().clearCaches();
// finally destroy all SPI services
webBeansContext.clear();
}
public void clearCacheProxies()
{
cacheProxies.clear();
}
public boolean isInUse()
{
return inUse;
}
public boolean isAfterDeploymentValidationFired()
{
return afterDeploymentValidationFired;
}
public void setAfterDeploymentValidationFired(boolean afterDeploymentValidationFired)
{
this.afterDeploymentValidationFired = afterDeploymentValidationFired;
}
public void setAfterBeanDiscoveryStart()
{
this.beanDiscoveryState = LifecycleState.DISCOVERY;
}
public void setAfterBeanDiscoveryDone()
{
this.beanDiscoveryState = LifecycleState.AFTER_DISCOVERY;
}
public boolean isAfterBeanDiscoveryDone()
{
return beanDiscoveryState == LifecycleState.AFTER_DISCOVERY;
}
public boolean isAfterBeanDiscovery()
{
return beanDiscoveryState == LifecycleState.DISCOVERY;
}
private void validateAssignabilityQualifiers(Set<Annotation> qualifiers, String failureMessage)
{
for (Annotation qualifier : qualifiers)
{
if (!isQualifier(qualifier.annotationType()))
{
throw new IllegalArgumentException(failureMessage);
}
}
}
private static boolean isIllegalBeanTypeForAssignability(Type beanType)
{
if (beanType instanceof Class<?>)
{
Class<?> c = (Class<?>) beanType;
if (c.isPrimitive())
{
return true;
}
if (c.isArray())
{
Class<?> ct = c.getComponentType();
while (ct.isArray())
{
ct = ct.getComponentType();
}
return ct.isPrimitive();
}
return false;
}
if (beanType instanceof TypeVariable<?>)
{
return true;
}
if (beanType instanceof ParameterizedType)
{
ParameterizedType parameterizedType = (ParameterizedType) beanType;
for (Type typeArgument : parameterizedType.getActualTypeArguments())
{
if (typeArgument instanceof TypeVariable<?>)
{
continue;
}
if (typeArgument instanceof WildcardType || isIllegalBeanTypeForAssignability(typeArgument))
{
return true;
}
}
return false;
}
if (beanType instanceof GenericArrayType)
{
return isIllegalBeanTypeForAssignability(((GenericArrayType) beanType).getGenericComponentType());
}
return false;
}
private boolean matchesRequiredBeanType(Type requiredType, Set<Type> legalBeanTypes)
{
for (Type beanType : legalBeanTypes)
{
if (GenericsUtil.satisfiesDependency(false, false, requiredType, beanType, new HashMap<>())
|| GenericsUtil.satisfiesDependency(false, true, requiredType, beanType, new HashMap<>()))
{
return true;
}
}
return false;
}
private Set<Annotation> normalizeBeanQualifiersForAssignability(Set<Annotation> beanQualifiers)
{
Set<Annotation> normalized = new HashSet<>(beanQualifiers);
normalized.add(AnyLiteral.INSTANCE);
boolean onlyAnyOrNamed = true;
for (Annotation a : normalized)
{
Class<? extends Annotation> t = a.annotationType();
if (!Any.class.equals(t) && !Named.class.equals(t))
{
onlyAnyOrNamed = false;
break;
}
}
if (onlyAnyOrNamed)
{
normalized.add(DefaultLiteral.INSTANCE);
}
return normalized;
}
private boolean hasAllQualifiers(Set<Annotation> beanQualifiers, Set<Annotation> requiredQualifiers)
{
for (Annotation required : requiredQualifiers)
{
if (!containsEquivalentQualifier(beanQualifiers, required))
{
return false;
}
}
return true;
}
private boolean containsEquivalentQualifier(Set<Annotation> beanQualifiers, Annotation required)
{
for (Annotation beanQ : beanQualifiers)
{
if (!required.annotationType().equals(beanQ.annotationType()))
{
continue;
}
AnnotatedType<? extends Annotation> at = additionalAnnotatedTypeQualifiers.get(beanQ.annotationType());
if (at == null)
{
if (AnnotationUtil.isCdiAnnotationEqual(beanQ, required))
{
return true;
}
}
else if (AnnotationUtil.isCdiAnnotationEqual(at, beanQ, required))
{
return true;
}
}
return false;
}
private static boolean containsUnboundTypeVariable(Type type)
{
if (type instanceof TypeVariable<?>)
{
return true;
}
if (type instanceof ParameterizedType)
{
for (Type arg : ((ParameterizedType) type).getActualTypeArguments())
{
if (containsUnboundTypeVariable(arg))
{
return true;
}
}
}
else if (type instanceof GenericArrayType)
{
return containsUnboundTypeVariable(((GenericArrayType) type).getGenericComponentType());
}
else if (type instanceof WildcardType)
{
WildcardType w = (WildcardType) type;
for (Type b : w.getUpperBounds())
{
if (containsUnboundTypeVariable(b))
{
return true;
}
}
for (Type b : w.getLowerBounds())
{
if (containsUnboundTypeVariable(b))
{
return true;
}
}
}
return false;
}
private static boolean matchesObservedEventType(Type observedEventType, Set<Type> eventTypeClosure)
{
for (Type eventType : eventTypeClosure)
{
if (eventType instanceof ParameterizedType && observedEventType instanceof Class<?>)
{
if (GenericsUtil.isAssignableFrom(true, false, observedEventType,
((ParameterizedType) eventType).getRawType(), new HashMap<>()))
{
return true;
}
}
if (GenericsUtil.isAssignableFrom(true, false, observedEventType, eventType, new HashMap<>()))
{
return true;
}
}
return false;
}
private enum LifecycleState
{
BEFORE_DISCOVERY, DISCOVERY, AFTER_DISCOVERY
}
}