/*
* Copyright (c) 1998-2011 Caucho Technology -- all rights reserved
*
* This file is part of Resin(R) Open Source
*
* Each copy or derived work must preserve the copyright notice and this
* notice unmodified.
*
* Resin Open Source is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* Resin Open Source is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
* of NON-INFRINGEMENT. See the GNU General Public License for more
* details.
*
* You should have received a copy of the GNU General Public License
* along with Resin Open Source; if not, write to the
*
* Free Software Foundation, Inc.
* 59 Temple Place, Suite 330
* Boston, MA 02111-1307 USA
*
* @author Scott Ferguson
*/
package com.caucho.config.inject;
import java.io.IOException;
import java.io.InputStream;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Type;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicLong;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.annotation.sql.DataSourceDefinition;
import javax.annotation.sql.DataSourceDefinitions;
import javax.ejb.EJB;
import javax.ejb.EJBs;
import javax.ejb.Stateful;
import javax.el.ELResolver;
import javax.el.ExpressionFactory;
import javax.enterprise.context.ContextNotActiveException;
import javax.enterprise.context.Conversation;
import javax.enterprise.context.ConversationScoped;
import javax.enterprise.context.Dependent;
import javax.enterprise.context.NormalScope;
import javax.enterprise.context.spi.Context;
import javax.enterprise.context.spi.Contextual;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.event.Event;
import javax.enterprise.inject.Alternative;
import javax.enterprise.inject.AmbiguousResolutionException;
import javax.enterprise.inject.IllegalProductException;
import javax.enterprise.inject.InjectionException;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.New;
import javax.enterprise.inject.Specializes;
import javax.enterprise.inject.Stereotype;
import javax.enterprise.inject.UnsatisfiedResolutionException;
import javax.enterprise.inject.spi.Annotated;
import javax.enterprise.inject.spi.AnnotatedField;
import javax.enterprise.inject.spi.AnnotatedMethod;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.Decorator;
import javax.enterprise.inject.spi.Extension;
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 javax.enterprise.inject.spi.PassivationCapable;
import javax.enterprise.inject.spi.ProcessBean;
import javax.enterprise.inject.spi.Producer;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Qualifier;
import javax.inject.Scope;
import javax.interceptor.InterceptorBinding;
import javax.naming.InitialContext;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceUnit;
import com.caucho.config.CauchoDeployment;
import com.caucho.config.ConfigException;
import com.caucho.config.Configured;
import com.caucho.config.ContextDependent;
import com.caucho.config.LineConfigException;
import com.caucho.config.ModulePrivate;
import com.caucho.config.ModulePrivateLiteral;
import com.caucho.config.bytecode.ScopeAdapter;
import com.caucho.config.el.CandiElResolver;
import com.caucho.config.el.CandiExpressionFactory;
import com.caucho.config.event.EventBeanImpl;
import com.caucho.config.event.EventManager;
import com.caucho.config.extension.ExtensionManager;
import com.caucho.config.j2ee.DataSourceDefinitionHandler;
import com.caucho.config.j2ee.EjbHandler;
import com.caucho.config.j2ee.PersistenceContextHandler;
import com.caucho.config.j2ee.PersistenceUnitHandler;
import com.caucho.config.j2ee.ResourceHandler;
import com.caucho.config.program.ConfigProgram;
import com.caucho.config.program.ResourceProgramManager;
import com.caucho.config.reflect.AnnotatedTypeUtil;
import com.caucho.config.reflect.BaseType;
import com.caucho.config.reflect.BaseTypeFactory;
import com.caucho.config.reflect.ReflectionAnnotatedFactory;
import com.caucho.config.scope.ApplicationContext;
import com.caucho.config.scope.DependentContext;
import com.caucho.config.scope.ErrorContext;
import com.caucho.config.scope.SingletonScope;
import com.caucho.config.xml.XmlCookie;
import com.caucho.config.xml.XmlCookieLiteral;
import com.caucho.config.xml.XmlStandardPlugin;
import com.caucho.inject.Module;
import com.caucho.inject.RequestContext;
import com.caucho.loader.DynamicClassLoader;
import com.caucho.loader.Environment;
import com.caucho.loader.EnvironmentApply;
import com.caucho.loader.EnvironmentClassLoader;
import com.caucho.loader.EnvironmentListener;
import com.caucho.loader.EnvironmentLocal;
import com.caucho.util.Alarm;
import com.caucho.util.IoUtil;
import com.caucho.util.L10N;
import com.caucho.vfs.Path;
import com.caucho.vfs.ReadStream;
import com.caucho.vfs.Vfs;
/**
* The CDI container for a given environment.
*/
@ModulePrivate
@SuppressWarnings("serial")
public final class InjectManager
implements BeanManager, EnvironmentListener,
Serializable, HandleAware
{
private static final L10N L = new L10N(InjectManager.class);
private static final Logger log
= Logger.getLogger(InjectManager.class.getName());
private static final EnvironmentLocal<InjectManager> _localContainer
= new EnvironmentLocal<InjectManager>();
private static final int DEFAULT_PRIORITY = 1;
private static final Annotation []DEFAULT_ANN
= DefaultLiteral.DEFAULT_ANN_LIST;
private static final String []FORBIDDEN_ANNOTATIONS = {
"javax.persistence.Entity",
/*
"javax.ejb.Stateful",
"javax.ejb.Stateless",
"javax.ejb.Singleton",
"javax.ejb.MessageDriven"
*/
};
private static final String []FORBIDDEN_CLASSES = {
"javax.servlet.Servlet",
"javax.servlet.Filter",
"javax.servlet.ServletContextListener",
"javax.servlet.http.HttpSessionListener",
"javax.servlet.ServletRequestListener",
"javax.ejb.EnterpriseBean",
"javax.faces.component.UIComponent",
"javax.enterprise.inject.spi.Extension",
};
private static final Class<? extends Annotation> []_forbiddenAnnotations;
private static final Class<?> []_forbiddenClasses;
private static final ClassLoader _systemClassLoader;
private String _id;
private InjectManager _parent;
private EnvironmentClassLoader _classLoader;
private ClassLoader _jndiClassLoader;
private boolean _isChildManager;
private final InjectScanManager _scanManager;
private final ExtensionManager _extensionManager;
private EventManager _eventManager = new EventManager(this);
private AtomicLong _version = new AtomicLong();
private HashMap<Class<?>,Class<?>> _specializedMap
= new HashMap<Class<?>,Class<?>>();
private HashMap<Class<?>,Integer> _deploymentMap
= new HashMap<Class<?>,Integer>();
private BaseTypeFactory _baseTypeFactory = new BaseTypeFactory();
private HashMap<Class<?>,InjectionPointHandler> _injectionMap
= new HashMap<Class<?>,InjectionPointHandler>();
private ResourceProgramManager _resourceManager
= new ResourceProgramManager();
//
// self configuration
//
private ConcurrentHashMap<Class<?>,ArrayList<TypedBean>> _selfBeanMap
= new ConcurrentHashMap<Class<?>,ArrayList<TypedBean>>();
private ConcurrentHashMap<String,ArrayList<Bean<?>>> _selfNamedBeanMap
= new ConcurrentHashMap<String,ArrayList<Bean<?>>>();
private HashMap<String,Bean<?>> _selfPassivationBeanMap
= new HashMap<String,Bean<?>>();
//
// combined visibility configuration
//
private HashMap<Class<?>,WebComponent> _beanMap
= new HashMap<Class<?>,WebComponent>();
private ConcurrentHashMap<String,ArrayList<Bean<?>>> _namedBeanMap
= new ConcurrentHashMap<String,ArrayList<Bean<?>>>();
private HashMap<Type,Bean<?>> _newBeanMap
= new HashMap<Type,Bean<?>>();
private HashSet<Class<? extends Annotation>> _qualifierSet
= new HashSet<Class<? extends Annotation>>();
private HashSet<Class<? extends Annotation>> _scopeTypeSet
= new HashSet<Class<? extends Annotation>>();
private HashSet<Class<? extends Annotation>> _normalScopeSet
= new HashSet<Class<? extends Annotation>>();
private HashSet<Class<? extends Annotation>> _passivatingScopeSet
= new HashSet<Class<? extends Annotation>>();
private HashMap<Class<? extends Annotation>, Set<Annotation>> _stereotypeMap
= new HashMap<Class<? extends Annotation>, Set<Annotation>>();
private HashMap<Class<?>,Context> _contextMap
= new HashMap<Class<?>,Context>();
private ArrayList<Class<?>> _interceptorClassList
= new ArrayList<Class<?>>();
private ArrayList<InterceptorEntry<?>> _interceptorList
= new ArrayList<InterceptorEntry<?>>();
private ArrayList<Class<?>> _decoratorClassList
= new ArrayList<Class<?>>();
private ArrayList<DecoratorEntry<?>> _decoratorList
= new ArrayList<DecoratorEntry<?>>();
private HashSet<Bean<?>> _beanSet = new HashSet<Bean<?>>();
private boolean _isEnableAutoUpdate = true;
private boolean _isUpdateNeeded = true;
private boolean _isAfterValidationNeeded = true;
private ConcurrentHashMap<Path, List<Path>> _beansXMLOverrides
= new ConcurrentHashMap<Path, List<Path>>();
private ArrayList<AnnotatedType<?>> _pendingAnnotatedTypes
= new ArrayList<AnnotatedType<?>>();
private ArrayList<AbstractBean<?>> _pendingBindList
= new ArrayList<AbstractBean<?>>();
private ArrayList<Bean<?>> _pendingValidationBeans
= new ArrayList<Bean<?>>();
private ArrayList<Bean<?>> _pendingServiceList
= new ArrayList<Bean<?>>();
private ArrayList<ConfigProgram> _globalProgram
= new ArrayList<ConfigProgram>();
private ConcurrentHashMap<Bean<?>,ReferenceFactory<?>> _refFactoryMap
= new ConcurrentHashMap<Bean<?>,ReferenceFactory<?>>();
private ConcurrentHashMap<String,ReferenceFactory<?>> _namedRefFactoryMap
= new ConcurrentHashMap<String,ReferenceFactory<?>>();
private ConcurrentHashMap<Member,AtomicBoolean> _staticMemberMap
= new ConcurrentHashMap<Member,AtomicBoolean>();
private ThreadLocal<CreationalContextImpl<?>> _proxyThreadLocal
= new ThreadLocal<CreationalContextImpl<?>>();
private ConcurrentHashMap<Class<?>,ManagedBeanImpl<?>> _transientMap
= new ConcurrentHashMap<Class<?>,ManagedBeanImpl<?>>();
private ConcurrentHashMap<Long,InjectionTarget<?>> _xmlTargetMap
= new ConcurrentHashMap<Long,InjectionTarget<?>>();
private boolean _isBeforeBeanDiscoveryComplete;
private boolean _isAfterBeanDiscoveryComplete;
private final AtomicLong _xmlCookieSequence
= new AtomicLong(Alarm.getCurrentTime());
// XXX: needs to be a local resolver
private ELResolver _elResolver = new CandiElResolver(this);
private DependentContext _dependentContext = new DependentContext();
private SingletonScope _singletonScope;
private ApplicationContext _applicationScope;
private XmlStandardPlugin _xmlExtension;
private RuntimeException _configException;
private Object _serializationHandle;
private InjectManager(String id,
InjectManager parent,
EnvironmentClassLoader loader,
boolean isSetLocal)
{
_id = id;
_classLoader = loader;
_parent = parent;
_extensionManager = new ExtensionManager(this);
_scanManager = new InjectScanManager(this);
Thread thread = Thread.currentThread();
ClassLoader oldLoader = thread.getContextClassLoader();
try {
thread.setContextClassLoader(_classLoader);
if (isSetLocal) {
_localContainer.set(this, _classLoader);
if (_parent == null) {
_localContainer.setGlobal(this);
}
}
if (_classLoader != null)
_classLoader.getNewTempClassLoader();
else
new DynamicClassLoader(null);
} finally {
thread.setContextClassLoader(oldLoader);
}
}
private void init(boolean isSetLocal)
{
Thread thread = Thread.currentThread();
ClassLoader oldLoader = thread.getContextClassLoader();
try {
thread.setContextClassLoader(_classLoader);
try {
InitialContext ic = new InitialContext();
ic.rebind("java:comp/BeanManager", new WebBeansJndiProxy());
} catch (Throwable e) {
log.log(Level.FINEST, e.toString(), e);
}
_singletonScope = new SingletonScope();
_applicationScope = new ApplicationContext();
addContext(new RequestContext());
addContext("com.caucho.server.webbeans.SessionScope");
addContext("com.caucho.server.webbeans.ConversationContext");
addContext("com.caucho.server.webbeans.TransactionScope");
addContext(_applicationScope);
addContext(_singletonScope);
addContext(_dependentContext);
_injectionMap.put(PersistenceContext.class,
new PersistenceContextHandler(this));
_injectionMap.put(PersistenceUnit.class,
new PersistenceUnitHandler(this));
_injectionMap.put(Resource.class,
new ResourceHandler(this));
_injectionMap.put(EJB.class,
new EjbHandler(this));
_injectionMap.put(EJBs.class,
new EjbHandler(this));
_injectionMap.put(DataSourceDefinition.class,
new DataSourceDefinitionHandler(this));
_injectionMap.put(DataSourceDefinitions.class,
new DataSourceDefinitionHandler(this));
_deploymentMap.put(CauchoDeployment.class, 0);
// DEFAULT_PRIORITY
_deploymentMap.put(Configured.class, 2);
BeanBuilder<InjectManager> factory = createBeanFactory(InjectManager.class);
// factory.deployment(Standard.class);
factory.type(InjectManager.class);
factory.type(BeanManager.class);
factory.annotation(ModulePrivateLiteral.create());
addBean(factory.singleton(this));
// ioc/0162
addBean(new InjectionPointStandardBean());
_xmlExtension = new XmlStandardPlugin(this);
addExtension(_xmlExtension);
_extensionManager.createExtension("com.caucho.server.webbeans.ResinStandardPlugin");
if (_classLoader != null && isSetLocal) {
// _classLoader.addScanListener(this);
_classLoader.addScanListener(_scanManager);
}
Environment.addEnvironmentListener(this, _classLoader);
} finally {
thread.setContextClassLoader(oldLoader);
}
}
/**
* Returns the modification version.
*/
public long getVersion()
{
return _version.get();
}
public InjectScanManager getScanManager()
{
return _scanManager;
}
public void setIsCustomExtension(boolean isCustom)
{
getScanManager().setIsCustomExtension(isCustom);
}
@Module
public EventManager getEventManager()
{
return _eventManager;
}
@Module
public ExtensionManager getExtensionManager()
{
return _extensionManager;
}
private void addContext(String contextClassName)
{
try {
Class<?> cl = Class.forName(contextClassName);
Context context = (Context) cl.newInstance();
addContext(context);
} catch (ClassNotFoundException e) {
log.log(Level.FINER, e.toString(), e);
} catch (Exception e) {
throw ConfigException.create(e);
}
}
/**
* Returns the local container.
*/
public static InjectManager getCurrent()
{
return getCurrent(Thread.currentThread().getContextClassLoader());
}
/**
* Returns the current environment container.
*/
public static InjectManager getCurrent(ClassLoader loader)
{
return _localContainer.get(loader);
}
/**
* Returns the current active container.
*/
public static InjectManager create()
{
return create(Thread.currentThread().getContextClassLoader());
}
/**
* Returns the current active container.
*/
public static InjectManager create(ClassLoader loader)
{
if (loader == null)
loader = _systemClassLoader;
InjectManager manager = null;
manager = _localContainer.getLevel(loader);
if (manager != null)
return manager;
EnvironmentClassLoader envLoader
= Environment.getEnvironmentClassLoader(loader);
// ejb doesn't create a new InjectManager even though it's a new
// environment
// XXX: yes it does, because of the SessionContext
// ejb/2016 vs ejb/12h0
/*
if (envLoader != null
&& Boolean.FALSE.equals(envLoader.getAttribute("caucho.inject"))) {
manager = create(envLoader.getParent());
if (manager != null)
return manager;
}
*/
String id;
if (envLoader != null)
id = envLoader.getId();
else
id = "";
InjectManager parent = null;
if (envLoader != null && envLoader != _systemClassLoader)
parent = create(envLoader.getParent());
synchronized (_localContainer) {
manager = _localContainer.getLevel(envLoader);
if (manager != null)
return manager;
manager = new InjectManager(id, parent, envLoader, true);
}
manager.init(true);
return manager;
}
/**
* Returns the current active container.
*/
public InjectManager createParent(String prefix)
{
_parent = new InjectManager(prefix + _id,
_parent,
_classLoader,
false);
_parent.init(false);
return _parent;
}
public ClassLoader getClassLoader()
{
return _classLoader;
}
public ClassLoader getJndiClassLoader()
{
return _jndiClassLoader;
}
public boolean isChildManager()
{
return _isChildManager;
}
public void setJndiClassLoader(ClassLoader loader)
{
if (_parent == null)
throw new IllegalStateException();
_isChildManager = true;
_jndiClassLoader = loader;
}
public InjectManager getParent()
{
return _parent;
}
public ApplicationContext getApplicationScope()
{
return _applicationScope;
}
public void setParent(InjectManager parent)
{
_parent = parent;
}
public void addXmlPath(Path path)
{
_isUpdateNeeded = true;
_xmlExtension.addXmlPath(path);
}
public void addBeansXmlOverride(Path path, Path beansXmlPath)
{
if (path == null)
throw new NullPointerException();
List<Path> beansXmlPaths = _beansXMLOverrides.get(path);
if (beansXmlPaths == null) {
beansXmlPaths = new ArrayList<Path>();
}
beansXmlPaths.add(beansXmlPath);
_beansXMLOverrides.put(path, beansXmlPaths);
}
public List<Path> getBeansXmlOverride(Path path)
{
return _beansXMLOverrides.get(path);
}
public void setEnableAutoUpdate(boolean isEnable)
{
_isEnableAutoUpdate = isEnable;
}
public void setDeploymentTypes(ArrayList<Class<?>> deploymentList)
{
_deploymentMap.clear();
_deploymentMap.put(CauchoDeployment.class, 0);
// DEFAULT_PRIORITY
int priority = DEFAULT_PRIORITY + 1;
if (! deploymentList.contains(Configured.class)) {
_deploymentMap.put(Configured.class, priority);
}
for (int i = deploymentList.size() - 1; i >= 0; i--) {
_deploymentMap.put(deploymentList.get(i), priority);
}
}
/**
* Adds the bean to the named bean map.
*/
private void addBeanByName(String name, Bean<?> bean)
{
ArrayList<Bean<?>> beanList = _selfNamedBeanMap.get(name);
if (beanList == null) {
beanList = new ArrayList<Bean<?>>();
_selfNamedBeanMap.put(name, beanList);
}
else if (bean.isAlternative()) {
}
else if (_specializedMap.get(bean.getBeanClass()) != null) {
}
else {
// ioc/0n18 vs ioc/0g30
for (Bean<?> testBean : beanList) {
if (testBean.isAlternative()) {
}
else if (bean.isAlternative()) {
}
else if (bean.getBeanClass().isAnnotationPresent(Specializes.class)
&& testBean.getBeanClass().isAssignableFrom(bean.getBeanClass())) {
}
else if (testBean.getBeanClass().isAnnotationPresent(Specializes.class)
&& bean.getBeanClass().isAssignableFrom(testBean.getBeanClass())) {
}
else if ((bean instanceof AbstractIntrospectedBean<?>)
&& ((AbstractIntrospectedBean<?>) bean).getAnnotated().isAnnotationPresent(Specializes.class)) {
// ioc/07a2
}
else if ((testBean instanceof AbstractIntrospectedBean<?>)
&& ((AbstractIntrospectedBean<?>) testBean).getAnnotated().isAnnotationPresent(Specializes.class)) {
}
else {
throw new ConfigException(L.l("@Named('{0}') is a duplicate name for\n {1}\n {2}",
name, bean, testBean));
}
}
}
beanList.add(bean);
_namedBeanMap.remove(name);
// ioc/0g31
int p = name.indexOf('.');
if (p > 0) {
addBeanByName(name.substring(0, p), bean);
}
}
/**
* Adds a bean by the interface type
*
* @param type the interface type to expose the component
* @param bean the component to register
*/
private void addBeanByType(Type type,
Annotated annotated,
Bean<?> bean)
{
if (type == null)
return;
BaseType baseType = createSourceBaseType(type);
addBeanByType(baseType, annotated, bean);
}
private void addBeanByType(BaseType type,
Annotated annotated,
Bean<?> bean)
{
if (type == null)
return;
if (isSpecialized(bean.getBeanClass())) {
return;
}
if (log.isLoggable(Level.FINEST))
log.finest(bean + "(" + type + ") added to " + this);
Class<?> rawType = type.getRawClass();
ArrayList<TypedBean> beanSet = _selfBeanMap.get(rawType);
if (beanSet == null) {
beanSet = new ArrayList<TypedBean>();
_selfBeanMap.put(rawType, beanSet);
}
_beanMap.remove(rawType);
TypedBean typedBean = new TypedBean(type, annotated, bean);
if (! beanSet.contains(typedBean)) {
beanSet.add(typedBean);
}
}
/**
* Finds a component by its component name.
*/
protected ArrayList<Bean<?>> findByName(String name)
{
// #3334 - shutdown timing issues
ConcurrentHashMap<String,ArrayList<Bean<?>>> namedBeanMap = _namedBeanMap;
if (namedBeanMap == null)
return null;
ArrayList<Bean<?>> beanList = _namedBeanMap.get(name);
if (beanList == null) {
beanList = new ArrayList<Bean<?>>();
if (_classLoader != null)
_classLoader.applyVisibleModules(new FillByName(name, beanList));
// ioc/0680
/*
for (int i = beanList.size() - 1; i >= 0; i--) {
if (getDeploymentPriority(beanList.get(i)) < 0) {
beanList.remove(i);
}
}
*/
_namedBeanMap.put(name, beanList);
}
return beanList;
}
private void fillByName(String name, ArrayList<Bean<?>> beanList)
{
ArrayList<Bean<?>> localBeans = _selfNamedBeanMap.get(name);
if (localBeans != null) {
for (Bean<?> bean : localBeans) {
/*
if (getDeploymentPriority(bean) < 0)
continue;
*/
// ioc/0g20
if (bean.isAlternative() && ! isEnabled(bean))
continue;
if (_specializedMap.containsKey(bean.getBeanClass()))
continue;
if (! beanList.contains(bean))
beanList.add(bean);
}
}
}
//
// javax.enterprise.context.Conversation
//
public Conversation createConversation()
{
return (Conversation) _contextMap.get(ConversationScoped.class);
}
/**
* Creates an object, but does not register the
* component with webbeans.
*/
public <T> T createTransientObject(Class<T> type)
{
ManagedBeanImpl<T> bean = createCachedManagedBean(type);
validate(bean);
// server/10gn
//return factory.create(new ConfigContext());
InjectionTarget<T> injectionTarget = bean.getInjectionTarget();
CreationalContext<T> env = new OwnerCreationalContext<T>(bean);
T instance = injectionTarget.produce(env);
injectionTarget.inject(instance, env);
// jsp/1o60
injectionTarget.postConstruct(instance);
return instance;
}
/**
* Creates an object, but does not register the
* component with webbeans.
*/
private <T> ManagedBeanImpl<T> createCachedManagedBean(Class<T> type)
{
ManagedBeanImpl<T> bean = (ManagedBeanImpl<T>) _transientMap.get(type);
if (bean == null) {
bean = createManagedBean(type);
validate(bean);
_transientMap.putIfAbsent(type, bean);
bean = (ManagedBeanImpl<T>) _transientMap.get(type);
}
return bean;
}
/**
* Returns a new instance for a class, but does not register the
* component with webbeans.
*/
public <T> BeanBuilder<T> createBeanFactory(ManagedBeanImpl<T> managedBean)
{
return new BeanBuilder<T>(managedBean);
}
/**
* Returns a new instance for a class, but does not register the
* component with webbeans.
*/
public <T> BeanBuilder<T> createBeanFactory(Class<T> type)
{
ManagedBeanImpl<T> managedBean = createManagedBean(type);
if (managedBean != null)
return createBeanFactory(managedBean);
else
return null;
}
/**
* Returns a new instance for a class, but does not register the
* component with CDI.
*/
public <T> BeanBuilder<T> createBeanFactory(AnnotatedType<T> type)
{
return createBeanFactory(createManagedBean(type));
}
public <T> Bean<T> addSingleton(T obj)
{
BeanBuilder<T> builder = createBeanFactory((Class<T>) obj.getClass());
Bean<T> bean = builder.singleton(obj);
addBean(bean);
return bean;
}
//
// enabled deployment types, scopes, and qualifiers
//
@Module
public void addScope(Class<? extends Annotation> scopeType,
boolean isNormal,
boolean isPassivating)
{
if (isPassivating && ! isNormal)
throw new ConfigException(L.l("@{0} must be 'normal' because it's using 'passivating'",
scopeType.getName()));
_scopeTypeSet.add(scopeType);
if (isNormal)
_normalScopeSet.add(scopeType);
if (isPassivating)
_passivatingScopeSet.add(scopeType);
if (isNormal) {
// TCK - force validation of all methods
_scanManager.setIsCustomExtension(true);
}
}
/**
* Tests if an annotation is an enabled scope type
*/
@Override
public boolean isScope(Class<? extends Annotation> annotationType)
{
return (annotationType.isAnnotationPresent(Scope.class)
|| annotationType.isAnnotationPresent(NormalScope.class)
|| _scopeTypeSet.contains(annotationType));
}
/**
* Tests if an annotation is an enabled scope type
*/
@Override
public boolean isNormalScope(Class<? extends Annotation> annotationType)
{
return (annotationType.isAnnotationPresent(NormalScope.class)
|| _normalScopeSet.contains(annotationType));
}
/**
* Tests if an annotation is an enabled scope type
*/
@Override
public boolean isPassivatingScope(Class<? extends Annotation> annotationType)
{
NormalScope scope = annotationType.getAnnotation(NormalScope.class);
if (scope != null)
return scope.passivating();
return _passivatingScopeSet.contains(annotationType);
}
@Module
public void addQualifier(Class<? extends Annotation> qualifier)
{
_qualifierSet.add(qualifier);
}
/**
* Tests if an annotation is an enabled binding type
*/
@Override
public boolean isQualifier(Class<? extends Annotation> annotationType)
{
return (annotationType.isAnnotationPresent(Qualifier.class)
|| _qualifierSet.contains(annotationType));
}
/**
* Tests if an annotation is an enabled interceptor binding type
*/
@Override
public boolean isInterceptorBinding(Class<? extends Annotation> annotationType)
{
return annotationType.isAnnotationPresent(InterceptorBinding.class);
}
/**
* Returns the bindings for an interceptor binding type
*/
@Override
public Set<Annotation> getInterceptorBindingDefinition(Class<? extends Annotation> bindingType)
{
LinkedHashSet<Annotation> annSet = new LinkedHashSet<Annotation>();
for (Annotation ann : bindingType.getAnnotations()) {
annSet.add(ann);
}
return annSet;
}
@Module
public void addStereotype(Class<? extends Annotation> annotationType,
Annotation []annotations)
{
LinkedHashSet<Annotation> annSet = new LinkedHashSet<Annotation>();
for (Annotation ann : annotations)
annSet.add(ann);
_stereotypeMap.put(annotationType, annSet);
}
/**
* Tests if an annotation is an enabled stereotype.
*/
@Override
public boolean isStereotype(Class<? extends Annotation> annotationType)
{
return (annotationType.isAnnotationPresent(Stereotype.class)
|| _stereotypeMap.get(annotationType) != null);
}
/**
* Returns the annotations associated with a stereotype
*/
@Override
public Set<Annotation> getStereotypeDefinition(Class<? extends Annotation> stereotype)
{
Set<Annotation> mapAnnSet = _stereotypeMap.get(stereotype);
if (mapAnnSet != null)
return mapAnnSet;
if (! stereotype.isAnnotationPresent(Stereotype.class))
return null;
LinkedHashMap<Class<?>, Annotation> annMap
= new LinkedHashMap<Class<?>, Annotation>();
addStereotypeDefinitions(annMap, stereotype);
mapAnnSet = new LinkedHashSet<Annotation>(annMap.values());
_stereotypeMap.put(stereotype, mapAnnSet);
return mapAnnSet;
}
private void addStereotypeDefinitions(Map<Class<?>,Annotation> annMap,
Class<? extends Annotation> stereotype)
{
for (Annotation ann : stereotype.getAnnotations()) {
if (annMap.get(ann.annotationType()) == null)
annMap.put(ann.annotationType(), ann);
}
for (Annotation ann : stereotype.getAnnotations()) {
Class<? extends Annotation> annType = ann.annotationType();
if (annType.isAnnotationPresent(Stereotype.class)) {
addStereotypeDefinitions(annMap, annType);
}
}
}
//
// bean resolution and instantiation
//
/**
* Creates a BaseType from a Type used as a target, for example
* an injection point.
*/
public BaseType createTargetBaseType(Type type)
{
return _baseTypeFactory.createForTarget(type);
}
/**
* Creates a BaseType from a Type used as a source, for example a Bean.
*/
public BaseType createSourceBaseType(Type type)
{
return _baseTypeFactory.createForSource(type);
}
/**
* Creates an annotated type.
*/
@Override
public <T> AnnotatedType<T> createAnnotatedType(Class<T> cl)
{
if (cl == null)
throw new NullPointerException();
AnnotatedType<T> annType = ReflectionAnnotatedFactory.introspectType(cl);
// TCK:
// return getExtensionManager().processAnnotatedType(annType);
return annType;
}
/**
* Creates an injection target
*/
@Override
public <T> InjectionTarget<T> createInjectionTarget(AnnotatedType<T> type)
{
InjectionTarget<T> target = new InjectionTargetBuilder<T>(this, type);
return getExtensionManager().processInjectionTarget(target, type);
}
/**
* Creates a managed bean.
*/
public <T> InjectionTarget<T> createInjectionTarget(Class<T> type)
{
try {
AnnotatedType<T> annType = ReflectionAnnotatedFactory.introspectType(type);
AnnotatedType<T> enhAnnType
= getExtensionManager().processAnnotatedType(annType);
if (enhAnnType != null)
return createInjectionTarget(enhAnnType);
else {
// special call from servlet, etc.
return createInjectionTarget(annType);
}
} catch (Exception e) {
throw ConfigException.createConfig(e);
}
}
public <T,X> void addObserver(ObserverMethod<T> observer,
AnnotatedMethod<X> method)
{
_extensionManager.processObserver(observer, method);
getEventManager().addObserver(observer);
}
/**
* Creates a managed bean.
*/
public <T> ManagedBeanImpl<T> createManagedBean(AnnotatedType<T> type)
{
if (type == null)
throw new NullPointerException();
ManagedBeanImpl<T> bean
= new ManagedBeanImpl<T>(this, type, false);
bean.introspect();
return bean;
}
/**
* Creates a managed bean.
*/
public <T> ManagedBeanImpl<T> createManagedBean(Class<T> cl)
{
if (cl == null)
throw new NullPointerException();
AnnotatedType<T> type = createAnnotatedType(cl);
AnnotatedType<T> extType = getExtensionManager().processAnnotatedType(type);
if (extType != null)
return createManagedBean(extType);
else
return createManagedBean(type);
}
/**
* Processes the discovered bean
*/
public <T> void addBean(Bean<T> bean)
{
if (bean == null)
throw new NullPointerException(L.l("null bean passed to addBean"));
addBean(bean, (Annotated) null);
}
/**
* Processes the discovered bean
*/
@Module
public <T> void addBean(Bean<T> bean, Annotated ann)
{
if (ann == null && bean instanceof AbstractBean<?>)
ann = ((AbstractBean<T>) bean).getAnnotatedType();
if (bean instanceof ManagedBeanImpl<?>) {
ManagedBeanImpl<T> managedBean = (ManagedBeanImpl<T>) bean;
bean = getExtensionManager().processManagedBean(managedBean, ann);
}
else if (bean instanceof ProducesMethodBean<?,?>) {
ProducesMethodBean<?,T> methodBean = (ProducesMethodBean<?,T>) bean;
bean = getExtensionManager().processProducerMethod(methodBean);
}
else if (bean instanceof ProducesFieldBean<?,?>) {
ProducesFieldBean<?,T> fieldBean = (ProducesFieldBean<?,T>) bean;
bean = getExtensionManager().processProducerField(fieldBean);
}
else
bean = getExtensionManager().processBean(bean, ann);
addBeanImpl(bean, ann);
}
/**
* Adds a new bean definition to the manager
*/
public <T> void addBean(Bean<T> bean, ProcessBean<T> process)
{
bean = getExtensionManager().processBean(bean, process);
if (bean != null)
addBeanImpl(bean, process.getAnnotated());
}
/**
* Adds a new bean definition to the manager
*/
public <T> void addBeanImpl(Bean<T> bean, Annotated ann)
{
if (bean == null)
return;
if (log.isLoggable(Level.FINER))
log.finer(this + " add bean " + bean);
_isAfterValidationNeeded = true;
_version.incrementAndGet();
if (bean instanceof Interceptor<?>) {
addInterceptor((Interceptor<?>) bean);
return;
}
else if (bean instanceof Decorator<?>) {
addDecorator((Decorator<?>) bean);
return;
}
// bean = new InjectBean<T>(bean, this);
_beanSet.add(bean);
for (Type type : bean.getTypes()) {
addBeanByType(type, ann, bean);
}
if (bean.getName() != null) {
addBeanByName(bean.getName(), bean);
}
// XXX: required for TCK, although we use lazily
boolean isNullable = bean.isNullable();
if (bean instanceof PassivationCapable) {
PassivationCapable pass = (PassivationCapable) bean;
if (pass.getId() != null)
_selfPassivationBeanMap.put(pass.getId(), bean);
}
registerJmx(bean);
}
public ResourceProgramManager getResourceManager()
{
return _resourceManager;
}
private void registerJmx(Bean<?> bean)
{
Thread thread = Thread.currentThread();
ClassLoader oldLoader = thread.getContextClassLoader();
try {
thread.setContextClassLoader(_classLoader);
/*
WebBeanAdmin admin = new WebBeanAdmin(bean, _beanId);
admin.register();
*/
} finally {
thread.setContextClassLoader(oldLoader);
}
}
public void addGlobalProgram(ConfigProgram program)
{
if (program != null) {
if (_isChildManager)
_parent.addGlobalProgram(program);
else {
_globalProgram.add(program);
}
}
}
/**
* Returns the bean definitions matching a given name
*
* @param name the name of the bean to match
*/
@Override
public Set<Bean<?>> getBeans(String name)
{
ArrayList<Bean<?>> beanList = findByName(name);
if (beanList != null)
return new LinkedHashSet<Bean<?>>(beanList);
else
return new LinkedHashSet<Bean<?>>();
}
@Module
public AtomicBoolean getStaticMemberBoolean(Member member)
{
AtomicBoolean flag = _staticMemberMap.get(member);
if (flag == null) {
flag = new AtomicBoolean();
_staticMemberMap.putIfAbsent(member, flag);
flag = _staticMemberMap.get(member);
}
return flag;
}
@Module
public ReferenceFactory<?> getReferenceFactory(String name)
{
// ioc/23n3
update();
ReferenceFactory<?> refFactory = _namedRefFactoryMap.get(name);
if (refFactory == null) {
Set<Bean<?>> beanSet = getBeans(name);
if (beanSet != null && beanSet.size() > 0) {
Bean<?> bean = resolve(beanSet);
// server/10sx
if (name.equals(bean.getName())) {
refFactory = getReferenceFactory(bean);
// ioc/0301
if (refFactory instanceof DependentReferenceFactoryImpl<?>)
refFactory = new DependentElReferenceFactoryImpl((ManagedBeanImpl<?>) bean);
}
}
if (refFactory == null) {
refFactory = new UnresolvedReferenceFactory();
}
_namedRefFactoryMap.put(name, refFactory);
}
return refFactory;
}
/**
* Returns the beans matching a class and annotation set
*
* @param type the bean's class
* @param qualifiers required @Qualifier annotations
*/
@Override
public Set<Bean<?>> getBeans(Type type,
Annotation... qualifiers)
{
if (qualifiers != null) {
for (int i = 0; i < qualifiers.length; i++) {
for (int j = i + 1; j < qualifiers.length; j++) {
if (qualifiers[i].annotationType() == qualifiers[j].annotationType())
throw new IllegalArgumentException(L.l("getBeans may not have a duplicate qualifier '{0}'",
qualifiers[i]));
}
}
}
Set<Bean<?>> set = resolve(type, qualifiers, null);
if (set != null)
return (Set<Bean<?>>) set;
else
return new HashSet<Bean<?>>();
}
/**
* Returns the beans matching a class and annotation set
*
* @param type the bean's class
* @param qualifiers required @Qualifier annotations
*/
private Set<Bean<?>> getBeans(Type type,
Set<Annotation> qualifierSet)
{
Annotation []qualifiers = new Annotation[qualifierSet.size()];
qualifierSet.toArray(qualifiers);
return getBeans(type, qualifiers);
}
/**
* Returns the web beans component with a given binding list.
*/
private Set<Bean<?>> resolve(Type type,
Annotation []bindings,
InjectionPoint ip)
{
if (type == null)
throw new NullPointerException();
if (bindings == null || bindings.length == 0) {
if (Object.class.equals(type))
return resolveAllBeans();
bindings = DEFAULT_ANN;
}
BaseType baseType = createTargetBaseType(type);
// ioc/024n
/*
if (baseType.isGeneric())
throw new IllegalArgumentException(L.l("'{0}' is an invalid getBeans type because it's generic.",
baseType));
*/
// ioc/02b1
if (baseType.isVariable())
throw new IllegalArgumentException(L.l("'{0}' is an invalid getBeans type because it's a type variable.",
baseType));
return resolveRec(baseType, bindings, ip);
}
/**
* Returns the web beans component with a given binding list.
*/
private Set<Bean<?>> resolveRec(BaseType baseType,
Annotation []qualifiers,
InjectionPoint ip)
{
WebComponent component = getWebComponent(baseType);
if (component != null) {
Set<Bean<?>> beans = component.resolve(baseType, qualifiers);
if (beans != null && beans.size() > 0) {
if (log.isLoggable(Level.FINEST))
log.finest(this + " bind(" + baseType.getSimpleName()
+ "," + toList(qualifiers) + ") -> " + beans);
return beans;
}
}
if (New.class.equals(qualifiers[0].annotationType())) {
// ioc/0721
New newQualifier = (New) qualifiers[0];
HashSet<Bean<?>> set = new HashSet<Bean<?>>();
Class<?> newClass = newQualifier.value();
if (newClass == null || newClass.equals(void.class))
newClass = baseType.getRawClass();
AnnotatedType<?> ann = ReflectionAnnotatedFactory.introspectType(newClass);
NewBean<?> newBean = new NewBean(this, baseType.getRawClass(), ann);
newBean.introspect();
if (component != null) {
component.addComponent(baseType, null, newBean);
}
set.add(newBean);
return set;
}
Class<?> rawType = baseType.getRawClass();
if (Instance.class.equals(rawType)
|| Provider.class.equals(rawType)) {
BaseType []param = baseType.getParameters();
Type beanType;
if (param.length > 0)
beanType = param[0].getRawClass();
else
beanType = Object.class;
HashSet<Bean<?>> set = new HashSet<Bean<?>>();
set.add(new InstanceBeanImpl(this, beanType, qualifiers, ip));
return set;
}
else if (Event.class.equals(rawType)) {
if (baseType.isGenericRaw())
throw new InjectionException(L.l("Event must have parameters because a non-parameterized Event would observe no events."));
BaseType []param = baseType.getParameters();
Type beanType;
if (param.length > 0)
beanType = param[0].getRawClass();
else
beanType = Object.class;
HashSet<Annotation> qualifierSet = new LinkedHashSet<Annotation>();
for (Annotation ann : qualifiers) {
qualifierSet.add(ann);
}
qualifierSet.add(AnyLiteral.ANY);
HashSet<Bean<?>> set = new HashSet<Bean<?>>();
set.add(new EventBeanImpl(this, beanType, qualifierSet));
return set;
}
if (_parent != null) {
return _parent.resolveRec(baseType, qualifiers, ip);
}
for (Annotation ann : qualifiers) {
if (! ann.annotationType().isAnnotationPresent(Qualifier.class)) {
throw new IllegalArgumentException(L.l("'{0}' is an invalid binding annotation because it does not have a @Qualifier meta-annotation",
ann));
}
}
if (log.isLoggable(Level.FINEST)) {
log.finest(this + " bind(" + baseType.getSimpleName()
+ "," + toList(qualifiers) + ") -> none");
}
return null;
}
/**
* Returns the web beans component with a given binding list.
*/
public Set<Bean<?>> resolveAllByType(Class<?> type)
{
Annotation []bindings = new Annotation[0];
WebComponent component = getWebComponent(createTargetBaseType(type));
if (component != null) {
Set<Bean<?>> beans = component.resolve(type, bindings);
if (log.isLoggable(Level.FINEST))
log.finest(this + " bind(" + getSimpleName(type)
+ "," + toList(bindings) + ") -> " + beans);
if (beans != null && beans.size() > 0)
return beans;
}
if (_parent != null) {
return _parent.resolveAllByType(type);
}
return null;
}
private WebComponent getWebComponent(BaseType baseType)
{
if (_beanMap == null)
return null;
WebComponent beanSet = _beanMap.get(baseType.getRawClass());
if (beanSet == null) {
HashSet<TypedBean> typedBeans = new HashSet<TypedBean>();
if (_classLoader != null) {
FillByType fillByType = new FillByType(baseType, typedBeans, this);
_classLoader.applyVisibleModules(fillByType);
}
Class<?> rawClass = baseType.getRawClass();
beanSet = new WebComponent(this, rawClass);
_beanMap.put(rawClass, beanSet);
for (TypedBean typedBean : typedBeans) {
if (getDeploymentPriority(typedBean.getBean()) < 0) {
continue;
}
_pendingValidationBeans.add(typedBean.getBean());
beanSet.addComponent(typedBean.getType(),
typedBean.getAnnotated(),
typedBean.getBean());
}
}
return beanSet;
}
private void fillByType(BaseType baseType,
HashSet<TypedBean> beanSet,
InjectManager beanManager)
{
Class<?> rawClass = baseType.getRawClass();
InjectScanClass scanClass
= _scanManager.getScanClass(rawClass.getName());
if (scanClass != null && ! scanClass.isRegistered()) {
discoverScanClass(scanClass);
processPendingAnnotatedTypes();
}
ArrayList<TypedBean> localBeans = _selfBeanMap.get(rawClass);
if (localBeans != null) {
// ioc/0k00, ioc/0400 - XXX: not exactly right. want local beans to have
// priority if type and binding match
/*
if (this == beanManager)
beanSet.clear();
else if (beanSet.size() > 0) {
return;
}
*/
for (TypedBean bean : localBeans) {
if (getDeploymentPriority(bean.getBean()) < 0)
continue;
if (bean.isModulePrivate() && this != beanManager)
continue;
beanSet.add(bean);
}
}
}
//@Override
public <X> Bean<X> getMostSpecializedBean(Bean<X> bean)
{
throw new UnsupportedOperationException();
/*
Bean<?> special = _specializedMap.get(bean.getBeanClass());
if (special != null)
return (Bean<X>) special;
else
return bean;
*/
}
@Module
public boolean isSpecialized(Class<?> beanClass)
{
return _specializedMap.get(beanClass) != null;
}
@Override
public <X> Bean<? extends X> resolve(Set<Bean<? extends X>> beans)
{
Bean<? extends X> bestBean = null;
Bean<? extends X> secondBean = null;
int bestPriority = -1;
boolean isSpecializes = false;
for (Bean<? extends X> bean : beans) {
if (_specializedMap.get(bean.getBeanClass()) != null)
continue;
if ((bean instanceof AbstractIntrospectedBean<?>)
&& ((AbstractIntrospectedBean<?>) bean).getAnnotated().isAnnotationPresent(Specializes.class)) {
if (! isSpecializes) {
// ioc/07a3
bestPriority = -1;
bestBean = null;
secondBean = null;
isSpecializes = true;
}
}
else if (isSpecializes) {
continue;
}
int priority = getDeploymentPriority(bean);
if (priority < 0) {
// alternatives
}
else if (bestPriority < priority) {
bestBean = bean;
secondBean = null;
bestPriority = priority;
}
else if (bestPriority == priority) {
secondBean = bean;
// TCK: ProducerFieldDefinitionTest
boolean isFirstProduces = (bestBean instanceof ProducesMethodBean<?,?>
|| bestBean instanceof ProducesFieldBean<?,?>);
boolean isSecondProduces = (secondBean instanceof ProducesMethodBean<?,?>
|| secondBean instanceof ProducesFieldBean<?,?>);
// ioc/02b0
if (isFirstProduces && ! isSecondProduces) {
secondBean = null;
}
else if (isSecondProduces && ! isFirstProduces) {
bestBean = bean;
secondBean = null;
}
}
}
if (secondBean == null)
return bestBean;
else {
throw ambiguousException(beans, bestPriority);
}
}
private void validate(Type type)
{
BaseType baseType = createTargetBaseType(type);
WebComponent comp = getWebComponent(baseType);
}
private void validate(Bean<?> bean)
{
if (bean.isAlternative() && ! isEnabled(bean))
return;
boolean isPassivating = isPassivatingScope(bean.getScope());
if (bean instanceof InjectEnvironmentBean) {
InjectEnvironmentBean envBean = (InjectEnvironmentBean) bean;
if (envBean.getCdiManager() != this) {
envBean.getCdiManager().validate(bean);
return;
}
}
if (bean instanceof CdiStatefulBean)
isPassivating = true;
if (bean instanceof ManagedBeanImpl
&& ((ManagedBeanImpl) bean).validate()) {
}
for (InjectionPoint ip : bean.getInjectionPoints()) {
ReferenceFactory<?> factory = validateInjectionPoint(ip);
if (ip.isDelegate() && ! (bean instanceof Decorator))
throw new ConfigException(L.l("'{0}' is an invalid delegate because {1} is not a Decorator.",
ip.getMember().getName(),
bean));
RuntimeException exn = validatePassivation(ip);
if (exn != null && ! factory.isProducer())
throw exn;
}
if (isNormalScope(bean.getScope())) {
validateNormal(bean);
}
}
private RuntimeException validatePassivation(InjectionPoint ip)
{
Bean<?> bean = ip.getBean();
if (bean == null)
return null;
boolean isPassivating = isPassivatingScope(bean.getScope());
if (bean instanceof CdiStatefulBean
|| bean.getBeanClass().isAnnotationPresent(Stateful.class)) {
isPassivating = true;
}
if (isPassivating && ! ip.isTransient()) {
Class<?> cl = getRawClass(ip.getType());
Bean<?> prodBean = resolve(getBeans(ip.getType(), ip.getQualifiers()));
// TCK conflict
if (! cl.isInterface()
&& ! cl.isPrimitive()
&& ! Serializable.class.isAssignableFrom(cl)
&& ! isPassivationCapable(prodBean)) {
RuntimeException exn;
if (isProduct(prodBean))
exn = new IllegalProductException(L.l("'{0}' is an invalid injection point of type {1} because it's not serializable for {2}",
ip.getMember().getName(),
ip.getType(),
bean));
else
exn = new ConfigException(L.l("'{0}.{1}' is an invalid injection point of type {2} ({3}) because it's not serializable for {4}",
bean.getBeanClass().getName(),
ip.getMember().getName(),
ip.getType(),
prodBean,
bean));
return exn;
}
}
return null;
}
private boolean isPassivationCapable(Bean<?> bean)
{
if (isNormalScope(bean.getScope()))
return true;
// ioc/05e2
if (bean instanceof PassivationCapable
&& ((PassivationCapable) bean).getId() != null) {
return true;
}
return false;
}
private boolean isProduct(Bean<?> bean)
{
return ((bean instanceof ProducesFieldBean<?,?>)
|| (bean instanceof ProducesMethodBean<?,?>));
}
private Class<?> getRawClass(Type type)
{
if (type instanceof Class<?>)
return (Class<?>) type;
BaseType baseType = createSourceBaseType(type);
return baseType.getRawClass();
}
private void validateNormal(Bean<?> bean)
{
Annotated ann = null;
if (bean instanceof AbstractBean) {
AbstractBean absBean = (AbstractBean) bean;
ann = absBean.getAnnotated();
}
if (ann == null)
return;
Type baseType = ann.getBaseType();
Class<?> cl = createTargetBaseType(baseType).getRawClass();
if (cl.isInterface())
return;
int modifiers = cl.getModifiers();
if (Modifier.isFinal(modifiers)) {
throw new ConfigException(L.l("'{0}' is an invalid @{1} bean because it's a final class, for {2}.",
cl.getSimpleName(), bean.getScope().getSimpleName(),
bean));
}
Constructor<?> ctor = null;
for (Constructor<?> ctorPtr : cl.getDeclaredConstructors()) {
if (ctorPtr.getParameterTypes().length > 0
&& ! ctorPtr.isAnnotationPresent(Inject.class)) {
// ioc/05am
continue;
}
if (Modifier.isPrivate(ctorPtr.getModifiers())) {
throw new ConfigException(L.l("'{0}' is an invalid @{1} bean because its constructor is private for {2}.",
cl.getSimpleName(), bean.getScope().getSimpleName(),
bean));
}
ctor = ctorPtr;
}
if (ctor == null) {
throw new ConfigException(L.l("'{0}' is an invalid @{1} bean because it doesn't have a zero-arg constructor for {2}.",
cl.getName(), bean.getScope().getSimpleName(),
bean));
}
for (Method method : cl.getMethods()) {
if (method.getDeclaringClass() == Object.class)
continue;
if (Modifier.isFinal(method.getModifiers())) {
throw new ConfigException(L.l("'{0}' is an invalid @{1} bean because {2} is a final method for {3}.",
cl.getSimpleName(), bean.getScope().getSimpleName(),
method.getName(),
bean));
}
}
for (Field field : cl.getFields()) {
if (Modifier.isStatic(field.getModifiers()))
continue;
if (Modifier.isPublic(field.getModifiers())) {
throw new ConfigException(L.l("'{0}' is an invalid @{1} bean because {2} is a public field for {3}.",
cl.getSimpleName(), bean.getScope().getSimpleName(),
field.getName(),
bean));
}
}
for (InjectionPoint ip : bean.getInjectionPoints()) {
if (ip.getType().equals(InjectionPoint.class))
throw new ConfigException(L.l("'{0}' is an invalid @{1} bean because '{2}' injects an InjectionPoint for {3}.",
cl.getSimpleName(), bean.getScope().getSimpleName(),
ip.getMember().getName(),
bean));
}
}
@Override
public void validate(InjectionPoint ij)
{
validateInjectionPoint(ij);
}
public ReferenceFactory<?> validateInjectionPoint(InjectionPoint ij)
{
try {
if (ij.isDelegate()) {
if (! (ij.getBean() instanceof Decorator<?>))
throw new ConfigException(L.l("'{0}' is an invalid @Delegate because {1} is not a decorator",
ij.getMember().getName(), ij.getBean()));
}
else {
return getReferenceFactory(ij);
}
} catch (AmbiguousResolutionException e) {
throw new AmbiguousResolutionException(L.l("{0}.{1}: {2}",
ij.getMember().getDeclaringClass().getName(),
ij.getMember().getName(),
e.getMessage()),
e);
} catch (UnsatisfiedResolutionException e) {
throw new UnsatisfiedResolutionException(L.l("{0}.{1}: {2}",
ij.getMember().getDeclaringClass().getName(),
ij.getMember().getName(),
e.getMessage()),
e);
} catch (IllegalProductException e) {
throw new IllegalProductException(L.l("{0}.{1}: {2}",
ij.getMember().getDeclaringClass().getName(),
ij.getMember().getName(),
e.getMessage()),
e);
} catch (Exception e) {
throw new InjectionException(L.l("{0}.{1}: {2}",
ij.getMember().getDeclaringClass().getName(),
ij.getMember().getName(),
e.getMessage()),
e);
}
return null;
}
public int getDeploymentPriority(Bean<?> bean)
{
int priority = DEFAULT_PRIORITY;
if (bean.isAlternative()) {
priority = -1;
Integer value = getPriority(bean.getBeanClass());
if (value != null)
priority = value;
}
Set<Class<? extends Annotation>> stereotypes = bean.getStereotypes();
if (stereotypes != null) {
for (Class<? extends Annotation> annType : stereotypes) {
Integer value = _deploymentMap.get(annType);
if (value != null) {
if (priority < value)
priority = value;
}
else if (annType.isAnnotationPresent(Alternative.class)
&& priority == DEFAULT_PRIORITY)
priority = -1;
}
}
if (priority < 0)
return priority;
else if (bean instanceof AbstractBean<?>) {
// ioc/0213
AbstractBean<?> absBean = (AbstractBean<?>) bean;
if (absBean.getBeanManager() == this)
priority += 1000000;
}
else
priority += 1000000;
return priority;
}
private Integer getPriority(Class<?> cl)
{
Integer value = _deploymentMap.get(cl);
if (value != null)
return value;
else if (_parent != null)
return _parent.getPriority(cl);
else
return null;
}
private Set<Bean<?>> resolveAllBeans()
{
LinkedHashSet<Bean<?>> beans = new LinkedHashSet<Bean<?>>();
for (ArrayList<TypedBean> comp : _selfBeanMap.values()) {
for (TypedBean typedBean : comp) {
beans.add(typedBean.getBean());
}
}
return beans;
}
@Override
public <T> CreationalContext<T> createCreationalContext(Contextual<T> bean)
{
return new OwnerCreationalContext<T>(bean);
}
/**
* Convenience-class for Resin.
*/
public <T> T getReference(Class<T> type, Annotation... qualifiers)
{
Set<Bean<?>> beans = getBeans(type, qualifiers);
Bean<T> bean = (Bean<T>) resolve(beans);
if (bean == null)
return null;
return getReference(bean);
}
/**
* Convenience for Resin.
*/
public <T> T getReference(Bean<T> bean)
{
ReferenceFactory<T> factory = getReferenceFactory(bean);
if (factory != null)
return factory.create(null, null, null);
else
return null;
}
/**
* Convenience for Resin.
*/
public <T> T findReference(Bean<T> bean)
{
Context context = getContext(bean.getScope());
if (context != null)
return context.get(bean);
else
return null;
}
/**
* Convenience for Resin.
*/
public <T> T getReference(Bean<T> bean, CreationalContextImpl<?> parentEnv)
{
ReferenceFactory<T> factory = getReferenceFactory(bean);
return factory.create(null, parentEnv, null);
}
/**
* Convenience-class for Resin.
*/
public <T> T getReference(String name)
{
Set<Bean<?>> beans = getBeans(name);
Bean<T> bean = (Bean<T>) resolve(beans);
if (bean == null)
return null;
ReferenceFactory<T> factory = getReferenceFactory(bean);
return factory.create(null, null, null);
}
/**
* Convenience-class for Resin.
*/
public <T> T getReference(String name, CreationalContextImpl parentEnv)
{
Set<Bean<?>> beans = getBeans(name);
Bean<T> bean = (Bean<T>) resolve(beans);
if (bean == null)
return null;
ReferenceFactory<T> factory = getReferenceFactory(bean);
return factory.create(null, parentEnv, null);
}
/**
* Returns an instance for the given bean. This method will obey
* the scope of the bean, so a singleton will return the single bean.
*
* @param bean the metadata for the bean
*
* @return an instance of the bean obeying scope
*/
@Override
public Object getReference(Bean<?> bean,
Type type,
CreationalContext<?> createContext)
{
Thread thread = Thread.currentThread();
ClassLoader oldLoader = thread.getContextClassLoader();
try {
thread.setContextClassLoader(getClassLoader());
ReferenceFactory factory = getReferenceFactory(bean);
if (createContext instanceof CreationalContextImpl<?>)
return factory.create((CreationalContextImpl) createContext, null, null);
else
return factory.create(null, null, null);
} finally {
thread.setContextClassLoader(oldLoader);
}
}
/**
* Used by ScopeProxy
*/
private <T> T getInstanceForProxy(Bean<T> bean)
{
CreationalContextImpl<?> oldEnv = _proxyThreadLocal.get();
T value;
if (oldEnv != null) {
value = oldEnv.get(bean);
if (value != null)
return value;
}
try {
CreationalContextImpl<T> env = new OwnerCreationalContext(bean, oldEnv);
_proxyThreadLocal.set(env);
value = bean.create(env);
return value;
} finally {
_proxyThreadLocal.set(oldEnv);
}
}
public <T> ReferenceFactory<T> getReferenceFactory(Bean<T> bean)
{
if (bean == null)
return null;
ReferenceFactory<T> factory = (ReferenceFactory<T>) _refFactoryMap.get(bean);
if (factory == null) {
factory = createReferenceFactory(bean);
_refFactoryMap.put(bean, factory);
factory.validate();
}
return factory;
}
private <T> ReferenceFactory<T> createReferenceFactory(Bean<T> bean)
{
Class<? extends Annotation> scopeType = bean.getScope();
if (InjectionPoint.class.equals(bean.getBeanClass()))
return (ReferenceFactory) new InjectionPointReferenceFactory();
if (Dependent.class == scopeType) {
if (bean instanceof ManagedBeanImpl<?>)
return new DependentReferenceFactoryImpl<T>((ManagedBeanImpl<T>) bean);
else
return new DependentReferenceFactory<T>(bean);
}
if (scopeType == null) {
throw new IllegalStateException("Unknown scope for " + bean);
}
InjectManager ownerManager;
if (bean instanceof AbstractBean<?>)
ownerManager = ((AbstractBean<?>) bean).getBeanManager();
else
ownerManager = this;
Context context = ownerManager.getContextImpl(scopeType);
/*
if (context == null)
return null;
*/
if (context == null)
throw new InjectionException(L.l("Bean has an unknown scope '{0}' for bean {1}",
scopeType, bean));
if (isNormalScope(scopeType) && bean instanceof ScopeAdapterBean<?>) {
ScopeAdapterBean<T> scopeAdapterBean = (ScopeAdapterBean<T>) bean;
return new NormalContextReferenceFactory<T>(bean, scopeAdapterBean, context);
}
else
return new ContextReferenceFactory<T>(bean, context);
}
public <T> ReferenceFactory<T> createNormalInstanceFactory(Bean<T> bean)
{
Class<? extends Annotation> scopeType = bean.getScope();
if (! isNormalScope(scopeType)) {
throw new IllegalStateException(L.l("{0} is an invalid normal scope for {1}",
scopeType, bean));
}
InjectManager ownerManager;
if (bean instanceof AbstractBean<?>)
ownerManager = ((AbstractBean<?>) bean).getBeanManager();
else
ownerManager = this;
Context context = ownerManager.getContextImpl(scopeType);
if (context == null)
throw new InjectionException(L.l("Bean has an unknown scope '{0}' for bean {1}",
scopeType, bean));
return new NormalInstanceReferenceFactory<T>(bean, context);
}
public RuntimeException unsatisfiedException(Type type,
Annotation []qualifiers)
{
WebComponent component = getWebComponent(createTargetBaseType(type));
if (component == null) {
throw new UnsatisfiedResolutionException(L.l("Can't find a bean for '{0}' because no beans implementing that class have been registered with the injection manager {1}.",
type, this));
}
else {
ArrayList<Bean<?>> enabledList = component.getEnabledBeanList();
if (enabledList.size() == 0) {
throw new UnsatisfiedResolutionException(L.l("Can't find a bean for '{0}' because no beans implementing that class have been registered with the injection manager {1}.",
type, this));
}
else {
return new UnsatisfiedResolutionException(L.l("Can't find a bean for '{0}' because no beans match the type and qualifiers {1}.\nBeans:{2}",
type,
toList(qualifiers),
listToLines(enabledList)));
}
}
}
private String listToLines(List<?> list)
{
StringBuilder sb = new StringBuilder();
ArrayList<String> lines = new ArrayList<String>();
for (int i = 0; i < list.size(); i++) {
lines.add(list.get(i).toString());
}
Collections.sort(lines);
for (String line : lines) {
sb.append("\n ").append(line);
}
return sb.toString();
}
/**
* Convert an annotation array to a list for debugging purposes
*/
private ArrayList<Annotation> toList(Annotation []annList)
{
ArrayList<Annotation> list = new ArrayList<Annotation>();
if (annList != null) {
for (Annotation ann : annList) {
list.add(ann);
}
}
return list;
}
InjectionPointHandler getInjectionPointHandler(AnnotatedField<?> field)
{
// InjectIntrospector.introspect(_injectProgramList, field);
for (Annotation ann : field.getAnnotations()) {
Class<? extends Annotation> annType = ann.annotationType();
InjectionPointHandler handler = _injectionMap.get(annType);
if (handler != null) {
return handler;
}
}
return null;
}
InjectionPointHandler getInjectionPointHandler(AnnotatedMethod<?> method)
{
// InjectIntrospector.introspect(_injectProgramList, field);
for (Annotation ann : method.getAnnotations()) {
Class<? extends Annotation> annType = ann.annotationType();
InjectionPointHandler handler = _injectionMap.get(annType);
if (handler != null) {
return handler;
}
}
return null;
}
public InjectionPointHandler
getInjectionPointHandler(Class<? extends Annotation> annType)
{
return _injectionMap.get(annType);
}
/**
* Internal callback during creation to get a new injection instance.
*/
@Override
public Object getInjectableReference(InjectionPoint ij,
CreationalContext<?> parentCxt)
{
CreationalContextImpl<?> parentEnv = null;
if (parentCxt instanceof CreationalContextImpl<?>)
parentEnv = (CreationalContextImpl<?>) parentCxt;
if (InjectionPoint.class.equals(ij.getType())) {
if (parentEnv != null) {
return parentEnv.findInjectionPoint();
}
}
ReferenceFactory<?> factory = getReferenceFactory(ij);
return factory.create(null, parentEnv, ij);
}
public ReferenceFactory<?> getReferenceFactory(InjectionPoint ij)
{
if (ij.isDelegate())
return new DelegateReferenceFactory();
else if (ij.getType().equals(InjectionPoint.class))
return new InjectionPointReferenceFactory();
Type type = ij.getType();
Set<Annotation> qualifiers = ij.getQualifiers();
ReferenceFactory factory = getReferenceFactory(type, qualifiers, ij);
RuntimeException exn = validatePassivation(ij);
if (exn != null) {
if (factory.isProducer())
return new ErrorReferenceFactory(exn);
else
throw exn;
}
return factory;
}
public ReferenceFactory<?> getReferenceFactory(Type type,
Set<Annotation> qualifiers,
InjectionPoint ij)
{
if (ij != null && ij.isDelegate())
return new DelegateReferenceFactory();
Bean<?> bean = resolveByInjectionPoint(type, qualifiers, ij);
return getReferenceFactory(bean);
}
private Bean<?> resolveByInjectionPoint(Type type,
Set<Annotation> qualifierSet,
InjectionPoint ij)
{
Annotation []qualifiers;
if (qualifierSet != null && qualifierSet.size() > 0) {
qualifiers = new Annotation[qualifierSet.size()];
qualifierSet.toArray(qualifiers);
if (qualifiers.length == 1
&& qualifiers[0].annotationType().equals(New.class)) {
New newQualifier = (New) qualifiers[0];
return createNewBean(type, newQualifier);
}
}
else
qualifiers = new Annotation[] { DefaultLiteral.DEFAULT };
BaseType baseType = createTargetBaseType(type);
/*
if (baseType.isGeneric())
throw new InjectionException(L.l("'{0}' is an invalid type for injection because it's generic. {1}",
baseType, ij));
*/
if (baseType.isGenericVariable())
throw new InjectionException(L.l("'{0}' is an invalid type for injection because it's a variable generic type.\n {1}",
baseType, ij));
Set<Bean<?>> set = resolveRec(baseType, qualifiers, ij);
if (set == null || set.size() == 0) {
if (InjectionPoint.class.equals(type))
return new InjectionPointBean(this, ij);
throw unsatisfiedException(type, qualifiers);
}
Bean<?> bean = resolve(set);
if (bean != null
&& type instanceof Class<?>
&& ((Class<?>) type).isPrimitive()
&& bean.isNullable()) {
throw new InjectionException(L.l("'{0}' cannot be injected because it's a primitive with {1}",
type, bean));
}
return bean;
/*
else if (set.size() == 1) {
Iterator iter = set.iterator();
if (iter.hasNext()) {
Bean bean = (Bean) iter.next();
return bean;
}
}
else {
throw new AmbiguousResolutionException(L.l("'{0}' with binding {1} matches too many configured beans{2}",
BaseType.create(type, null),
bindingSet,
toLineList(set)));
}
return null;
*/
}
private <T> Bean<?> createNewBean(Type type, New newQualifier)
{
Class<?> newClass = newQualifier.value();
if (newClass == null
|| void.class.equals(newClass)
|| New.class.equals(newClass)) {
BaseType baseType = createTargetBaseType(type);
newClass = (Class<T>) baseType.getRawClass();
}
Bean<?> bean = _newBeanMap.get(newClass);
if (bean == null) {
AnnotatedType<T> annType = (AnnotatedType<T>) ReflectionAnnotatedFactory.introspectType(newClass);
BaseType newType = createSourceBaseType(type);
NewBean<T> newBean = new NewBean<T>(this, newType.getRawClass(), annType);
newBean.introspect();
_newBeanMap.put(type, bean);
bean = newBean;
}
return bean;
}
private <X> AmbiguousResolutionException
ambiguousException(Set<Bean<? extends X>> beanSet, int bestPriority)
{
ArrayList<Bean<?>> matchBeans = new ArrayList<Bean<?>>();
for (Bean<?> bean : beanSet) {
int priority = getDeploymentPriority(bean);
if (priority == bestPriority)
matchBeans.add(bean);
}
return new AmbiguousResolutionException(L.l("Too many beans match, because they all have equal precedence. See the @Alternative and <alternatives> tags to choose a precedence. Beans:{0}\nfor {1}",
listToLines(matchBeans), this));
}
@Override
public ELResolver getELResolver()
{
return _elResolver;
}
@Override
public ExpressionFactory
wrapExpressionFactory(ExpressionFactory expressionFactory)
{
return new CandiExpressionFactory(expressionFactory);
}
//
// scopes
//
/**
* Adds a new scope context
*/
public void addContext(Context context)
{
Class<? extends Annotation> scopeType = context.getScope();
Context oldContext = _contextMap.get(scopeType);
if (oldContext == null) {
_contextMap.put(context.getScope(), context);
}
else {
// ioc/0p41 - CDI TCK
RuntimeException exn
= new IllegalStateException(L.l("{0} is an invalid new context because @{1} is already registered as a scope",
context, scopeType.getName()));
_contextMap.put(context.getScope(), new ErrorContext(exn, context));
}
}
public void replaceContext(Context context)
{
_contextMap.put(context.getScope(), context);
}
/**
* Returns the scope context for the given type
*/
@Override
public Context getContext(Class<? extends Annotation> scopeType)
{
Context context = _contextMap.get(scopeType);
if (context != null && context.isActive()) {
return context;
}
if (context instanceof ErrorContext) {
ErrorContext cxt = (ErrorContext) context;
throw cxt.getException();
}
/*
if (! isScope(scopeType)) {
throw new IllegalStateException(L.l("'@{0}' is not a valid scope because it does not have a @Scope annotation",
scopeType));
}
*/
throw new ContextNotActiveException(L.l("'@{0}' is not an active Java Injection context.",
scopeType.getName()));
}
/**
* Required for TCK. Returns the scope context for the given type.
*/
public Context getContextImpl(Class<? extends Annotation> scopeType)
{
return _contextMap.get(scopeType);
}
/**
* Returns the bean for the given passivation id.
*/
public Bean<?> getPassivationCapableBean(String id)
{
return _selfPassivationBeanMap.get(id);
}
public Annotation []getQualifiers(Set<Annotation> annotations)
{
ArrayList<Annotation> bindingList = new ArrayList<Annotation>();
for (Annotation ann : annotations) {
if (ann.annotationType().isAnnotationPresent(Qualifier.class))
bindingList.add(ann);
}
Annotation []bindings = new Annotation[bindingList.size()];
bindingList.toArray(bindings);
return bindings;
}
public Annotation []getQualifiers(Annotation []annotations)
{
ArrayList<Annotation> bindingList = new ArrayList<Annotation>();
for (Annotation ann : annotations) {
if (ann.annotationType().isAnnotationPresent(Qualifier.class))
bindingList.add(ann);
}
Annotation []bindings = new Annotation[bindingList.size()];
bindingList.toArray(bindings);
return bindings;
}
/**
* Sends the specified event to any observer instances in the scope
*/
@Override
public void fireEvent(Object event, Annotation... qualifiers)
{
if (log.isLoggable(Level.FINEST))
log.finest(this + " fireEvent " + event);
getEventManager().fireEvent(event, qualifiers);
}
/**
* Returns the observers listening for an event
*
* @param eventType event to resolve
* @param bindings the binding set for the event
*/
@Override
public <T> Set<ObserverMethod<? super T>>
resolveObserverMethods(T event, Annotation... qualifiers)
{
return getEventManager().resolveObserverMethods(event, qualifiers);
}
//
// interceptor support
//
/**
* Adds a new decorator class
*/
public <X> BeanManager addInterceptorClass(Class<?> interceptorClass)
{
_interceptorClassList.add(interceptorClass);
return this;
}
/**
* Adds a new interceptor to the manager
*/
private <X> InterceptorEntry<X> addInterceptor(Interceptor<X> interceptor)
{
InterceptorEntry<X> entry = new InterceptorEntry<X>(interceptor);
_interceptorList.add(entry);
return entry;
}
/**
* Resolves the interceptors for a given interceptor type
*
* @param type the main interception type
* @param qualifiers qualifying bindings
*
* @return the matching interceptors
*/
@Override
public List<Interceptor<?>> resolveInterceptors(InterceptionType type,
Annotation... qualifiers)
{
if (qualifiers == null || qualifiers.length == 0)
throw new IllegalArgumentException(L.l("resolveInterceptors requires at least one @InterceptorBinding"));
for (int i = 0; i < qualifiers.length; i++) {
Class<? extends Annotation> annType = qualifiers[i].annotationType();
if (! annType.isAnnotationPresent(InterceptorBinding.class))
throw new IllegalArgumentException(L.l("Annotation must be an @InterceptorBinding at '{0}' in resolveInterceptors",
qualifiers[i]));
for (int j = i + 1; j < qualifiers.length; j++) {
if (annType.equals(qualifiers[j].annotationType()))
throw new IllegalArgumentException(L.l("Duplicate binding '{0}' is not allowed in resolveInterceptors",
qualifiers[i]));
}
}
ArrayList<Interceptor<?>> interceptorList
= new ArrayList<Interceptor<?>>();
for (InterceptorEntry<?> entry : _interceptorList) {
Interceptor<?> interceptor = entry.getInterceptor();
if (! interceptor.intercepts(type)) {
continue;
}
if (entry.isMatch(qualifiers)) {
interceptorList.add(interceptor);
}
}
return interceptorList;
}
//
// decorator
//
/**
* Adds a new decorator
*/
private <X> DecoratorEntry<X> addDecorator(Decorator<X> decorator)
{
BaseType baseType = createTargetBaseType(decorator.getDelegateType());
DecoratorEntry<X> entry = new DecoratorEntry<X>(this, decorator, baseType);
_decoratorList.add(entry);
for (Type type : decorator.getDecoratedTypes()) {
if (type instanceof Class<?>) {
Class<?> cl = (Class<?>) type;
if (Object.class.equals(cl)
|| Serializable.class.equals(cl)) {
continue;
}
String javaClassName = cl.getName();
InjectScanClass scanClass = getScanManager().getScanClass(javaClassName);
if (scanClass != null && ! scanClass.isRegistered()) {
discoverScanClass(scanClass);
}
}
}
processPendingAnnotatedTypes();
return entry;
}
/**
* Adds a new decorator class
*/
public <X> BeanManager addDecoratorClass(Class<?> decoratorClass)
{
_decoratorClassList.add(decoratorClass);
return this;
}
/**
* Called by the generated code.
*/
public List<Decorator<?>> resolveDecorators(Class<?> type)
{
HashSet<Type> types = new HashSet<Type>();
types.add(type);
ArrayList<Annotation> bindingList = new ArrayList<Annotation>();
boolean isQualifier = false;
for (Annotation ann : type.getAnnotations()) {
if (isQualifier(ann.annotationType())) {
bindingList.add(ann);
if (! Named.class.equals(ann.annotationType())) {
isQualifier = true;
}
}
}
if (! isQualifier)
bindingList.add(DefaultLiteral.DEFAULT);
bindingList.add(AnyLiteral.ANY);
Annotation []bindings = new Annotation[bindingList.size()];
bindingList.toArray(bindings);
List<Decorator<?>> decorators = resolveDecorators(types, bindings);
// XXX: 4.0.7
// log.info("DECORATORS: " + decorators + " " + types + " " + this);
return decorators;
}
/**
* Resolves the decorators for a given set of types
*
* @param types the types to match for the decorator
* @param qualifiers qualifying bindings
*
* @return the matching interceptors
*/
@Override
public List<Decorator<?>> resolveDecorators(Set<Type> types,
Annotation... qualifiers)
{
if (types.size() == 0)
throw new IllegalArgumentException(L.l("type set must contain at least one type"));
if (qualifiers != null) {
for (int i = 0; i < qualifiers.length; i++) {
for (int j = i + 1; j < qualifiers.length; j++) {
if (qualifiers[i].annotationType() == qualifiers[j].annotationType())
throw new IllegalArgumentException(L.l("resolveDecorators may not have a duplicate qualifier '{0}'",
qualifiers[i]));
}
}
}
ArrayList<Decorator<?>> decorators = new ArrayList<Decorator<?>>();
if (qualifiers == null || qualifiers.length == 0)
qualifiers = DEFAULT_ANN;
if (_decoratorList == null)
return decorators;
for (Annotation ann : qualifiers) {
if (! isQualifier(ann.annotationType()))
throw new IllegalArgumentException(L.l("@{0} must be a qualifier", ann.annotationType()));
}
ArrayList<BaseType> targetTypes = new ArrayList<BaseType>();
for (Type type : types) {
targetTypes.add(createSourceBaseType(type));
}
for (DecoratorEntry<?> entry : _decoratorList) {
Decorator<?> decorator = entry.getDecorator();
// XXX: delegateTypes
if (isDelegateAssignableFrom(entry.getDelegateType(), targetTypes)
&& entry.isMatch(qualifiers)) {
decorators.add(decorator);
}
}
return decorators;
}
private boolean isDelegateAssignableFrom(BaseType delegateType,
ArrayList<BaseType> sourceTypes)
{
for (BaseType sourceType : sourceTypes) {
if (delegateType.isAssignableFrom(sourceType)) {
return true;
}
}
return false;
}
public void addConfiguredClass(String className)
{
_xmlExtension.addConfiguredBean(className);
// _configuredClasses.add(className);
}
public XmlCookie generateXmlCookie()
{
return new XmlCookieLiteral(_xmlCookieSequence.incrementAndGet());
}
public void addLoader()
{
_isUpdateNeeded = true;
}
public void update()
{
// ioc/0044
if (! _isEnableAutoUpdate)
return;
if (! _isUpdateNeeded
&& ! _scanManager.isPending()
&& _pendingAnnotatedTypes.size() == 0) {
return;
}
_isUpdateNeeded = false;
Thread thread = Thread.currentThread();
ClassLoader oldLoader = thread.getContextClassLoader();
try {
thread.setContextClassLoader(_classLoader);
_extensionManager.updateExtensions();
ArrayList<ScanRootContext> rootContextList
= _scanManager.getPendingScanRootList();
for (ScanRootContext context : rootContextList) {
_xmlExtension.addRoot(context.getRoot());
}
_isBeforeBeanDiscoveryComplete = true;
getExtensionManager().fireBeforeBeanDiscovery();
/*
// ioc/0061
if (rootContextList.size() == 0)
return;
for (ScanRootContext context : rootContextList) {
for (String className : context.getClassNameList()) {
if (! _configuredClasses.contains(className)) {
discoverBean(className);
}
}
}
*/
processPendingAnnotatedTypes();
} catch (ConfigException e) {
if (_configException == null)
_configException = e;
throw e;
} finally {
thread.setContextClassLoader(oldLoader);
}
}
public void processPendingAnnotatedTypes()
{
_scanManager.discover();
ArrayList<AnnotatedType<?>> types = new ArrayList<AnnotatedType<?>>(_pendingAnnotatedTypes);
_pendingAnnotatedTypes.clear();
for (AnnotatedType<?> type : types) {
discoverBeanImpl(type);
}
_extensionManager.processPendingEvents();
}
void discoverScanClass(InjectScanClass scanClass)
{
scanClass.register();
// processPendingAnnotatedTypes();
}
void discoverBean(InjectScanClass scanClass)
{
AnnotatedType<?> type = createDiscoveredType(scanClass.getClassName());
if (type != null)
discoverBean(type);
}
void discoverBean(String className)
{
AnnotatedType<?> type = createDiscoveredType(className);
if (type != null)
discoverBean(type);
}
private AnnotatedType<?> createDiscoveredType(String className)
{
try {
Class<?> cl;
cl = Class.forName(className, false, _classLoader);
/*
if (! isValidSimpleBean(cl))
return;
*/
if (cl.getDeclaringClass() != null
&& ! Modifier.isStatic(cl.getModifiers()))
return null;
for (Class<? extends Annotation> forbiddenAnnotation : _forbiddenAnnotations) {
if (cl.isAnnotationPresent(forbiddenAnnotation))
return null;
}
for (Class<?> forbiddenClass : _forbiddenClasses) {
if (forbiddenClass.isAssignableFrom(cl))
return null;
}
// ioc/0619
/*
if (isDisabled(cl))
return;
*/
if (cl.isInterface()) {
if (Annotation.class.isAssignableFrom(cl)
&& cl.isAnnotationPresent(Qualifier.class)) {
// validateQualifier(cl);
QualifierBinding.validateQualifier(cl, null);
}
}
return createAnnotatedType(cl);
} catch (ClassNotFoundException e) {
log.log(Level.FINER, e.toString(), e);
}
return null;
}
public <X> void discoverBean(AnnotatedType<X> beanType)
{
Class<X> cl;
// ioc/07fb
cl = beanType.getJavaClass();
if (cl.isAnnotationPresent(Specializes.class)) {
Class<?> parent = cl.getSuperclass();
if (parent != null) {
addSpecialize(cl, parent);
}
}
AnnotatedType<X> type = getExtensionManager().processAnnotatedType(beanType);
if (type == null)
return;
_pendingAnnotatedTypes.add(type);
}
private void addSpecialize(Class<?> specializedType, Class<?> parentType)
{
Class<?> oldSpecialized = _specializedMap.get(parentType);
if (oldSpecialized != null)
throw new ConfigException(L.l("@Specialized on '{0}' is invalid because it conflicts with an older specialized '{1}'",
specializedType.getName(),
oldSpecialized.getName()));
if (! isValidSimpleBean(parentType))
throw new ConfigException(L.l("@Specialized on '{0}' is invalid because its parent '{1}' is not a managed bean.",
specializedType.getName(),
parentType.getName()));
_specializedMap.put(parentType, specializedType);
}
boolean isEnabled(Bean<?> bean)
{
if (! bean.isAlternative())
return true;
if (_deploymentMap.containsKey(bean.getBeanClass()))
return true;
for (Class<?> stereotype : bean.getStereotypes()) {
if (_deploymentMap.containsKey(stereotype))
return true;
}
return false;
}
boolean isIntrospectObservers(AnnotatedType<?> type)
{
if (type.isAnnotationPresent(Specializes.class))
return true;
String javaClassName = type.getJavaClass().getName();
InjectScanClass scanClass = getScanManager().getScanClass(javaClassName);
if (scanClass == null)
return true;
return scanClass.isObserves();
}
private boolean isValidSimpleBean(Class<?> type)
{
if (type.isInterface())
return false;
else if (type.isAnonymousClass())
return false;
/*
else if (type.isMemberClass())
return false;
*/
if (Modifier.isAbstract(type.getModifiers()))
return false;
/* XXX: ioc/024d */
// ioc/070c, ioc/0j0g
/*
if (type.getTypeParameters() != null
&& type.getTypeParameters().length > 0) {
return false;
}
*/
if (! isValidConstructor(type))
return false;
return true;
}
private boolean isValidSimpleBean(AnnotatedType<?> type)
{
if (type.isAnnotationPresent(XmlCookie.class)) {
// ioc/04d0
return true;
}
return isValidSimpleBean(type.getJavaClass());
}
private boolean isValidConstructor(Class<?> type)
{
for (Constructor<?> ctor : type.getDeclaredConstructors()) {
if (ctor.getParameterTypes().length == 0)
return true;
if (ctor.isAnnotationPresent(Inject.class))
return true;
}
return false;
}
private <T> void discoverBeanImpl(AnnotatedType<T> type)
{
// ioc/0n18
/*
if (_specializedMap.get(type.getJavaClass()) != null)
return;
*/
// XXX: not sure this is correct.
if (Throwable.class.isAssignableFrom(type.getJavaClass()))
return;
if (! isValidSimpleBean(type)) {
return;
}
ManagedBeanImpl<T> bean = new ManagedBeanImpl<T>(this, type, false);
InjectionTarget<T> target = bean.getInjectionTarget(); //createInjectionTarget(type);
if (target instanceof InjectionTargetBuilder<?>) {
InjectionTargetBuilder<?> targetImpl = (InjectionTargetBuilder<?>) target;
targetImpl.setGenerateInterception(true);
}
target = processInjectionTarget(target, type);
if (target == null)
return;
if (target instanceof InjectionTargetBuilder<?>) {
InjectionTargetBuilder<T> targetImpl = (InjectionTargetBuilder<T>) target;
targetImpl.setBean(bean);
}
bean.setInjectionTarget(target);
bean.introspect();
AnnotatedType<T> annType = bean.getAnnotatedType();
// ioc/0i04
if (annType.isAnnotationPresent(javax.decorator.Decorator.class)) {
if (annType.isAnnotationPresent(javax.interceptor.Interceptor.class))
throw new ConfigException(L.l("'{0}' bean may not have both a @Decorator and @Interceptor annotation.",
annType.getJavaClass()));
// ioc/0c92
DecoratorBean decoratorBean = new DecoratorBean(this, annType.getJavaClass());
// addBean(decoratorBean);
return;
}
// ioc/0c1a
if (annType.isAnnotationPresent(javax.interceptor.Interceptor.class)) {
InterceptorBean interceptorBean = new InterceptorBean(this, annType.getJavaClass());
addBean(interceptorBean);
return;
}
addDiscoveredBean(bean);
fillProducerBeans(bean);
// beans.addScannedClass(cl);
}
public <T> InjectionTarget<T> processInjectionTarget(InjectionTarget<T> target,
AnnotatedType<T> ann)
{
return getExtensionManager().processInjectionTarget(target, ann);
}
private void fillProducerBeans(ManagedBeanImpl<?> bean)
{
}
private <X> void addDiscoveredBean(ManagedBeanImpl<X> managedBean)
{
/*
// ioc/04d0
if (! isValidSimpleBean(managedBean.getBeanClass()))
return;
*/
// ioc/0680
if (! managedBean.isAlternative() || isEnabled(managedBean)) {
// ioc/0680
addBean(managedBean);
// ioc/0b0f
if (! _specializedMap.containsKey(managedBean.getBeanClass()))
managedBean.introspectObservers();
/*
for (ObserverMethodImpl<X,?> observer : managedBean.getObserverMethods()) {
// observer = processObserver(observer);
if (observer != null) {
Set<Annotation> annSet = observer.getObservedQualifiers();
Annotation []bindings = new Annotation[annSet.size()];
annSet.toArray(bindings);
BaseType baseType = createSourceBaseType(observer.getObservedType());
_eventManager.addObserver(observer, baseType, bindings);
}
}
*/
}
// ioc/07d2
if (! _specializedMap.containsKey(managedBean.getBeanClass())
&& isEnabled(managedBean)) {
managedBean.introspectProduces();
}
}
public <X> void addProduces(Bean<X> bean, AnnotatedType<X> beanType)
{
ProducesBuilder builder = new ProducesBuilder(this);
builder.introspectProduces(bean, beanType);
}
public <X> void addManagedProduces(Bean<X> bean, AnnotatedType<X> beanType)
{
ProducesBuilder builder = new ManagedProducesBuilder(this);
builder.introspectProduces(bean, beanType);
}
public <X,T> void addProducesBean(ProducesMethodBean<X,T> bean)
{
AnnotatedMethod<X> producesMethod
= (AnnotatedMethod<X>) bean.getProducesMethod();
Producer<T> producer = bean.getProducer();
producer = getExtensionManager().processProducer(producesMethod, producer);
bean.setProducer(producer);
addBean(bean, producesMethod);
}
public <X,T> void addProducesFieldBean(ProducesFieldBean<X,T> bean)
{
AnnotatedField<X> producesField
= (AnnotatedField<X>) bean.getField();
Producer<T> producer = bean.getProducer();
producer = getExtensionManager().processProducer(producesField, producer);
bean.setProducer(producer);
addBean(bean, producesField);
}
public <X> void addManagedBean(ManagedBeanImpl<X> managedBean)
{
addBean(managedBean);
managedBean.introspectProduces();
}
public <T> ArrayList<T> loadServices(Class<T> serviceClass)
{
return loadServices(serviceClass, new HashSet<URL>(), false);
}
public <T> ArrayList<T> loadLocalServices(Class<T> serviceClass)
{
return loadServices(serviceClass, new HashSet<URL>(), true);
}
private <T> ArrayList<T> loadServices(Class<T> serviceApiClass,
HashSet<URL> serviceSet,
boolean isLocal)
{
ArrayList<T> services = new ArrayList<T>();
try {
DynamicClassLoader loader = _classLoader;
if (loader == null)
return services;
String serviceName = "META-INF/services/" + serviceApiClass.getName();
Enumeration<URL> e;
if (isLocal)
e = loader.findResources(serviceName);
else
e = loader.getResources(serviceName);
while (e.hasMoreElements()) {
URL url = e.nextElement();
if (serviceSet.contains(url))
continue;
serviceSet.add(url);
InputStream is = null;
try {
is = url.openStream();
ReadStream in = Vfs.openRead(is);
String line;
while ((line = in.readLine()) != null) {
int p = line.indexOf('#');
if (p >= 0)
line = line.substring(0, p);
line = line.trim();
if (line.length() > 0) {
Class<T> cl = loadServiceClass(serviceApiClass, line);
if (cl != null)
services.add(createTransientObject(cl));
}
}
in.close();
} catch (IOException e1) {
log.log(Level.WARNING, e1.toString(), e1);
} finally {
IoUtil.close(is);
}
}
} catch (Exception e) {
log.log(Level.WARNING, e.toString(), e);
}
return services;
}
private <T> Class<T> loadServiceClass(Class<T> serviceApi,
String className)
{
try {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
Class<?> serviceClass = Class.forName(className, false, loader);
if (! serviceApi.isAssignableFrom(serviceClass))
throw new InjectionException(L.l("'{0}' is not a valid servicebecause it does not implement {1}",
serviceClass, serviceApi.getName()));
return (Class<T>) serviceClass;
} catch (Exception e) {
log.log(Level.WARNING, e.toString(), e);
return null;
}
}
public void addExtension(Extension extension)
{
_extensionManager.addExtension(extension);
}
/**
* Starts the bind phase
*/
public void bind()
{
Thread thread = Thread.currentThread();
ClassLoader oldLoader = thread.getContextClassLoader();
boolean isBind = false;
try {
thread.setContextClassLoader(_classLoader);
processPendingAnnotatedTypes();
if (_pendingBindList != null) {
ArrayList<AbstractBean<?>> bindList
= new ArrayList<AbstractBean<?>>(_pendingBindList);
_pendingBindList.clear();
if (bindList.size() > 0)
isBind = true;
}
if (! _isAfterBeanDiscoveryComplete)
isBind = true;
if (isBind) {
_isAfterBeanDiscoveryComplete = true;
getExtensionManager().fireAfterBeanDiscovery();
}
if (_configException != null)
throw _configException;
/*
for (AbstractBean comp : bindList) {
if (_deploymentMap.get(comp.getDeploymentType()) != null)
comp.bind();
}
*/
addDecorators();
addInterceptors();
bindGlobals();
validate();
/*
if (isBind) {
getExtensionManager().fireAfterDeploymentValidation();
}
*/
} catch (RuntimeException e) {
if (_configException == null)
_configException = e;
else {
log.log(Level.WARNING, e.toString(), e);
}
throw e;
} finally {
thread.setContextClassLoader(oldLoader);
}
}
public void bindGlobals()
{
if (_globalProgram.size() > 0) {
ArrayList<ConfigProgram> programList
= new ArrayList<ConfigProgram>(_globalProgram);
_globalProgram.clear();
for (ConfigProgram program : programList) {
program.inject(this, null);
}
}
}
private void addInterceptors()
{
if (_interceptorClassList.size() == 0)
return;
ArrayList<Class<?>> interceptorClassList
= new ArrayList<Class<?>>(_interceptorClassList);
_interceptorClassList.clear();
for (Class<?> interceptorClass : interceptorClassList) {
for (InterceptorEntry<?> entry : _interceptorList) {
if (entry.getInterceptor().getBeanClass().equals(interceptorClass)) {
entry.setEnabled(true);
return;
}
}
if (! interceptorClass.isAnnotationPresent(javax.interceptor.Interceptor.class))
throw new ConfigException(L.l("'{0}' is an invalid interceptor because it does not have an @Interceptor.",
interceptorClass.getName()));
InterceptorBean<?> bean = new InterceptorBean(this, interceptorClass);
InterceptorEntry<?> entry = addInterceptor(bean);
entry.setEnabled(true);
}
}
private void addDecorators()
{
if (_decoratorClassList.size() == 0)
return;
ArrayList<Class<?>> decoratorClassList
= new ArrayList<Class<?>>(_decoratorClassList);
_decoratorClassList.clear();
for (Class<?> decoratorClass : decoratorClassList) {
for (DecoratorEntry<?> entry : _decoratorList) {
if (entry.getDecorator().getBeanClass().equals(decoratorClass)) {
entry.setEnabled(true);
return;
}
}
DecoratorBean<?> bean = new DecoratorBean(this, decoratorClass);
DecoratorEntry<?> entry = addDecorator(bean);
entry.setEnabled(true);
}
// ioc/0i57 - validation must be early
for (DecoratorEntry<?> entry : _decoratorList) {
if (entry.isEnabled()) {
for (Type type : entry.getDelegateType().getTypeClosure(this)) {
validate(type);
}
}
}
}
private void validate()
{
ArrayList<ArrayList<TypedBean>> typeValues
= new ArrayList<ArrayList<TypedBean>>(_selfBeanMap.values());
for (int i = typeValues.size() - 1; i >= 0; i--) {
ArrayList<TypedBean> beans = typeValues.get(i);
validateSpecializes(beans);
}
for (int i = typeValues.size() - 1; i >= 0; i--) {
ArrayList<TypedBean> beans = typeValues.get(i);
if (beans == null)
continue;
for (int j = beans.size() - 1; j >= 0; j--) {
TypedBean typedBean = beans.get(j);
typedBean.validate();
}
}
}
private void validateSpecializes(ArrayList<TypedBean> beans)
{
if (beans == null)
return;
for (int i = beans.size() - 1; i >= 0; i--) {
TypedBean bean = beans.get(i);
Annotated ann = bean.getAnnotated();
if (ann == null || ! ann.isAnnotationPresent(Specializes.class))
continue;
for (int j = beans.size() - 1; j >= 0; j--) {
if (i == j)
continue;
TypedBean bean2 = beans.get(j);
// XXX:
Annotated ann2 = bean.getAnnotated();
if (ann2 == null)
continue;
if (isSpecializes(ann, ann2) && isMatchInject(bean, bean2)) {
beans.remove(j);
i = 0;
}
}
}
}
private boolean isMatchInject(TypedBean typedBeanA, TypedBean typedBeanB)
{
Bean<?> beanA = typedBeanA.getBean();
Bean<?> beanB = typedBeanB.getBean();
return (beanA.getTypes().equals(beanB.getTypes())
&& beanA.getQualifiers().equals(beanB.getQualifiers()));
}
private boolean isSpecializes(Annotated childAnn, Annotated parentAnn)
{
if (childAnn instanceof AnnotatedMethod<?>
&& parentAnn instanceof AnnotatedMethod<?>) {
Method childMethod = ((AnnotatedMethod<?>) childAnn).getJavaMember();
Method parentMethod = ((AnnotatedMethod<?>) parentAnn).getJavaMember();
if (! AnnotatedTypeUtil.isMatch(childMethod, parentMethod)) {
return false;
}
Class<?> childClass = childMethod.getDeclaringClass();
Class<?> parentClass = parentMethod.getDeclaringClass();
if (parentClass.isAssignableFrom(childClass))
return true;
}
return false;
}
/**
* Handles the case the environment config phase
*/
public void environmentConfigure(EnvironmentClassLoader loader)
{
initialize();
}
/**
* Handles the case the environment config phase
*/
@Override
public void environmentBind(EnvironmentClassLoader loader)
{
initialize();
bind();
}
/**
* Handles the case where the environment is starting (after init).
*/
@Override
public void environmentStart(EnvironmentClassLoader loader)
{
start();
}
public void initialize()
{
update();
/*
if (_lifecycle.toInit()) {
fireEvent(this, new AnnotationLiteral<Initialized>() {});
}
*/
}
public void start()
{
initialize();
bind();
startServices();
if (_configException != null) {
// ioc/0p91
throw _configException;
}
notifyStart();
}
public void notifyStart()
{
Thread thread = Thread.currentThread();
ClassLoader oldLoader = thread.getContextClassLoader();
try {
thread.setContextClassLoader(_classLoader);
update();
// cloud/0300
if (_isAfterValidationNeeded) {
_isAfterValidationNeeded = false;
getExtensionManager().fireAfterDeploymentValidation();
}
} catch (ConfigException e) {
if (_configException == null)
_configException = e;
throw e;
} finally {
thread.setContextClassLoader(oldLoader);
}
// ioc/0p30
if (_configException != null)
throw _configException;
}
public void addDefinitionError(Throwable t)
{
if (_configException != null) {
log.log(Level.WARNING, t.toString(), t);
}
else if (t instanceof RuntimeException) {
_configException = (RuntimeException) t;
}
else {
_configException = ConfigException.create(t);
}
}
public RuntimeException getConfigException()
{
return _configException;
}
public void addConfiguredBean(String className)
{
_xmlExtension.addConfiguredBean(className);
}
public void addXmlInjectionTarget(long cookie, InjectionTarget<?> target)
{
_xmlTargetMap.put(cookie, target);
}
public InjectionTarget<?> getXmlInjectionTarget(long cookie)
{
return _xmlTargetMap.get(cookie);
}
void addService(Bean<?> bean)
{
_pendingServiceList.add(bean);
}
/**
* Initialize all the services
*/
private void startServices()
{
ArrayList<Bean<?>> services;
// ArrayList<ManagedBean> registerServices;
synchronized (_pendingServiceList) {
services = new ArrayList<Bean<?>>(_pendingServiceList);
_pendingServiceList.clear();
}
for (Bean<?> bean : services) {
CreationalContext<?> env = createCreationalContext(bean);
getReference(bean, bean.getBeanClass(), env);
}
/*
for (ManagedBean bean : registerServices) {
startRegistration(bean);
}
*/
}
/**
* Handles the case where the environment is stopping
*/
@Override
public void environmentStop(EnvironmentClassLoader loader)
{
destroy();
}
public void destroy()
{
_singletonScope.closeContext();
_parent = null;
_classLoader = null;
_deploymentMap = null;
_selfBeanMap = null;
_selfNamedBeanMap = null;
_beanMap = null;
_namedBeanMap = null;
_contextMap = null;
_interceptorList = null;
_decoratorList = null;
_pendingBindList = null;
_pendingServiceList = null;
_eventManager = null;
}
public static ConfigException injectError(AccessibleObject prop, String msg)
{
String location = "";
if (prop instanceof Field) {
Field field = (Field) prop;
String className = field.getDeclaringClass().getName();
location = className + "." + field.getName() + ": ";
}
else if (prop instanceof Method) {
Method method = (Method) prop;
String className = method.getDeclaringClass().getName();
location = className + "." + method.getName() + ": ";
}
return new ConfigException(location + msg);
}
public static String location(Field field)
{
return field.getDeclaringClass().getName() + "." + field.getName() + ": ";
}
public static String location(Method method)
{
return LineConfigException.loc(method);
}
public static ConfigException error(Method method, String msg)
{
return new ConfigException(location(method) + msg);
}
public void setSerializationHandle(Object handle)
{
_serializationHandle = handle;
}
/**
* Serialization rewriting
*/
public Object writeReplace()
{
return _serializationHandle;
}
public void checkActive()
{
}
public String toString()
{
if (_classLoader != null)
return getClass().getSimpleName() + "[" + _classLoader.getId() + "]";
else
return getClass().getSimpleName() + "[" + _id + "]";
}
static String getSimpleName(Type type)
{
if (type instanceof Class<?>)
return ((Class<?>) type).getSimpleName();
else
return String.valueOf(type);
}
class TypedBean {
private final BaseType _type;
private final Annotated _annotated;
private final Bean<?> _bean;
private final boolean _isModulePrivate;
private boolean _isValidated;
TypedBean(BaseType type, Annotated annotated, Bean<?> bean)
{
_type = type;
_annotated = annotated;
_bean = bean;
_isModulePrivate = isModulePrivate(bean) || bean.isAlternative();
}
public Annotated getAnnotated()
{
return _annotated;
}
/**
*
*/
public void validate()
{
if (! _isValidated) {
_isValidated = true;
InjectManager.this.validate(_bean);
/*
for (InjectionPoint ip : _bean.getInjectionPoints()) {
InjectManager.this.validate(ip);
}
*/
}
}
boolean isModulePrivate()
{
return _isModulePrivate;
}
BaseType getType()
{
return _type;
}
Bean<?> getBean()
{
return _bean;
}
boolean isModulePrivate(Bean<?> bean)
{
if (! (bean instanceof AnnotatedBean))
return false;
Annotated annotated = ((AnnotatedBean) bean).getAnnotated();
if (annotated == null)
return false;
for (Annotation ann : annotated.getAnnotations()) {
Class<?> annType = ann.annotationType();
if (annType.equals(ModulePrivate.class)
|| annType.isAnnotationPresent(ModulePrivate.class)
|| annType.equals(Module.class)
|| annType.isAnnotationPresent(Module.class)) {
return true;
}
}
return false;
}
@Override
public int hashCode()
{
return 65521 * _type.hashCode() + _bean.hashCode();
}
@Override
public boolean equals(Object o)
{
if (! (o instanceof TypedBean))
return false;
TypedBean bean = (TypedBean) o;
return _type.equals(bean._type) && _bean.equals(bean._bean);
}
public String toString()
{
return getClass().getSimpleName() + "[" + _type + "," + _bean + "]";
}
}
static class FillByName implements EnvironmentApply
{
private String _name;
private ArrayList<Bean<?>> _beanList;
FillByName(String name, ArrayList<Bean<?>> beanList)
{
_name = name;
_beanList = beanList;
}
public void apply(EnvironmentClassLoader loader)
{
InjectManager beanManager = InjectManager.getCurrent(loader);
beanManager.fillByName(_name, _beanList);
}
}
static class FillByType implements EnvironmentApply
{
private BaseType _baseType;
private HashSet<TypedBean> _beanSet;
private InjectManager _manager;
FillByType(BaseType baseType,
HashSet<TypedBean> beanSet,
InjectManager manager)
{
_baseType = baseType;
_beanSet = beanSet;
_manager = manager;
}
@Override
public void apply(EnvironmentClassLoader loader)
{
InjectManager beanManager = InjectManager.getCurrent(loader);
beanManager.fillByType(_baseType, _beanSet, _manager);
}
}
static class FactoryBinding {
private static final Annotation []NULL = new Annotation[0];
private final Type _type;
private final Annotation []_ann;
FactoryBinding(Type type, Annotation []ann)
{
_type = type;
if (ann != null)
_ann = ann;
else
_ann = NULL;
}
@Override
public int hashCode()
{
int hash = _type.hashCode();
for (Annotation ann : _ann)
hash = 65521 * hash + ann.hashCode();
return hash;
}
@Override
public boolean equals(Object obj)
{
if (! (obj instanceof FactoryBinding))
return false;
FactoryBinding binding = (FactoryBinding) obj;
if (_type != binding._type)
return false;
if (_ann.length != binding._ann.length)
return false;
for (int i = 0; i < _ann.length; i++) {
if (! _ann[i].equals(binding._ann[i]))
return false;
}
return true;
}
}
static class InjectBean<X> extends BeanWrapper<X>
implements PassivationCapable, ScopeAdapterBean<X>
{
private ClassLoader _loader;
InjectBean(Bean<X> bean, InjectManager beanManager)
{
super(beanManager, bean);
_loader = Thread.currentThread().getContextClassLoader();
if (bean instanceof AbstractBean) {
AbstractBean<X> absBean = (AbstractBean<X>) bean;
Annotated annotated = absBean.getAnnotated();
if (annotated != null
&& annotated.isAnnotationPresent(ContextDependent.class)) {
// ioc/0e17
_loader = null;
}
}
}
public String getId()
{
Bean<?> bean = getBean();
if (bean instanceof PassivationCapable)
return ((PassivationCapable) bean).getId();
else
return null;
}
public X getScopeAdapter(Bean<?> topBean, CreationalContextImpl<X> cxt)
{
Bean<?> bean = getBean();
if (bean instanceof ScopeAdapterBean<?>)
return (X) ((ScopeAdapterBean) bean).getScopeAdapter(topBean, cxt);
else
return null;
}
@Override
public X create(CreationalContext<X> env)
{
Thread thread = Thread.currentThread();
ClassLoader oldLoader = thread.getContextClassLoader();
try {
if (_loader != null) {
// ioc/0e17
thread.setContextClassLoader(_loader);
}
X value = getBean().create(env);
return value;
} finally {
thread.setContextClassLoader(oldLoader);
}
}
@Override
public int hashCode()
{
return getBean().hashCode();
}
public boolean equals(Object o)
{
if (! (o instanceof InjectBean<?>))
return false;
InjectBean<?> bean = (InjectBean<?>) o;
return getBean().equals(bean.getBean());
}
public String toString()
{
return getClass().getSimpleName() + "[" + getBean() + "]";
}
}
abstract public class ReferenceFactory<T> {
public Bean<T> getBean()
{
return null;
}
protected void validate()
{
}
public final T create()
{
return create(null, null, null);
}
public boolean isResolved()
{
return true;
}
public boolean isProducer()
{
Bean<T> bean = getBean();
return ((bean instanceof ProducesMethodBean<?,?>)
|| (bean instanceof ProducesFieldBean<?,?>));
}
abstract public T create(CreationalContextImpl<T> env,
CreationalContextImpl<?> parentEnv,
InjectionPoint ip);
}
public class DependentReferenceFactory<T> extends ReferenceFactory<T> {
private Bean<T> _bean;
DependentReferenceFactory(Bean<T> bean)
{
_bean = bean;
}
@Override
public Bean<T> getBean()
{
return _bean;
}
@Override
public T create(CreationalContextImpl<T> env,
CreationalContextImpl<?> parentEnv,
InjectionPoint ip)
{
Bean<T> bean = _bean;
T instance = CreationalContextImpl.find(parentEnv, bean);
if (instance != null)
return instance;
if (env == null) {
if (parentEnv != null)
env = new DependentCreationalContext<T>(bean, parentEnv, ip);
else {
env = new OwnerCreationalContext<T>(bean);
if (ip != null)
env = new DependentCreationalContext<T>(bean, env, ip);
}
}
instance = bean.create(env);
env.push(instance);
/*
if (env.isTop() && ! (bean instanceof CdiStatefulBean)) {
bean.destroy(instance, env);
}
*/
return instance;
}
@Override
public String toString()
{
return getClass().getSimpleName() + "[" + _bean + "]";
}
}
public class DependentReferenceFactoryImpl<T> extends ReferenceFactory<T> {
private ManagedBeanImpl<T> _bean;
DependentReferenceFactoryImpl(ManagedBeanImpl<T> bean)
{
_bean = bean;
}
@Override
public Bean<T> getBean()
{
return _bean;
}
@Override
public T create(CreationalContextImpl<T> env,
CreationalContextImpl<?> parentEnv,
InjectionPoint ip)
{
ManagedBeanImpl<T> bean = _bean;
T instance = CreationalContextImpl.find(parentEnv, bean);
if (instance != null)
return instance;
if (env == null) {
if (parentEnv != null)
env = new DependentCreationalContext<T>(bean, parentEnv, ip);
else
env = new OwnerCreationalContext<T>(bean);
}
instance = bean.createDependent(env);
// ioc/0k13
/*
if (env.isTop() && ! (bean instanceof CdiStatefulBean)) {
bean.destroy(instance, env);
}
*/
return instance;
}
}
public class DependentElReferenceFactoryImpl<T> extends ReferenceFactory<T> {
private ManagedBeanImpl<T> _bean;
DependentElReferenceFactoryImpl(ManagedBeanImpl<T> bean)
{
_bean = bean;
}
@Override
public Bean<T> getBean()
{
return _bean;
}
@Override
public T create(CreationalContextImpl<T> env,
CreationalContextImpl<?> parentEnv,
InjectionPoint ip)
{
ManagedBeanImpl<T> bean = _bean;
T instance = CreationalContextImpl.findAny(parentEnv, bean);
if (instance != null)
return instance;
if (env == null) {
if (parentEnv != null)
env = new DependentCreationalContext<T>(bean, parentEnv, ip);
else
env = new OwnerCreationalContext<T>(bean);
}
instance = bean.createDependent(env);
if (env.isTop() && ! (bean instanceof CdiStatefulBean)) {
bean.destroy(instance, env);
}
return instance;
}
}
public class ContextReferenceFactory<T> extends ReferenceFactory<T> {
private Bean<T> _bean;
private Context _context;
ContextReferenceFactory(Bean<T> bean,
Context context)
{
_bean = bean;
_context = context;
}
@Override
public Bean<T> getBean()
{
return _bean;
}
@Override
public T create(CreationalContextImpl<T> env,
CreationalContextImpl<?> parentEnv,
InjectionPoint ip)
{
Bean<T> bean = _bean;
T instance = CreationalContextImpl.find(parentEnv, bean);
if (instance != null)
return instance;
if (env == null)
env = new OwnerCreationalContext<T>(bean, parentEnv);
instance = _context.get(bean, env);
if (instance == null)
throw new NullPointerException(L.l("null instance returned by '{0}' for bean '{1}'",
_context, bean));
return instance;
}
}
public class NormalInstanceReferenceFactory<T> extends ReferenceFactory<T> {
private ThreadLocal<CreationalContextImpl<T>> _threadLocal
= new ThreadLocal<CreationalContextImpl<T>>();
private Bean<T> _bean;
private Context _context;
NormalInstanceReferenceFactory(Bean<T> bean,
Context context)
{
_bean = bean;
_context = context;
}
@Override
public Bean<T> getBean()
{
return _bean;
}
@Override
public T create(CreationalContextImpl<T> env,
CreationalContextImpl<?> parentEnv,
InjectionPoint ip)
{
Bean<T> bean = _bean;
// ioc/0155
// XXX: possibly restrict to NormalScope adapter
CreationalContextImpl<T> oldEnv = _threadLocal.get();
try {
T instance = CreationalContextImpl.find(oldEnv, bean);
if (instance != null) {
return instance;
}
env = new OwnerCreationalContext<T>(bean, oldEnv);
_threadLocal.set(env);
instance = _context.get(bean, env);
if (instance == null)
throw new NullPointerException(L.l("null instance returned by '{0}' for bean '{1}'",
_context, bean));
return instance;
} finally {
_threadLocal.set(oldEnv);
}
}
}
public class NormalContextReferenceFactory<T> extends ReferenceFactory<T> {
private Bean<T> _bean;
private ScopeAdapterBean<T> _scopeAdapterBean;
private Context _context;
private T _scopeAdapter;
NormalContextReferenceFactory(Bean<T> bean,
ScopeAdapterBean<T> scopeAdapterBean,
Context context)
{
_bean = bean;
_scopeAdapterBean = scopeAdapterBean;
_context = context;
ScopeAdapter scopeAdapter = ScopeAdapter.create(bean);
_scopeAdapter = scopeAdapter.wrap(createNormalInstanceFactory(bean));
}
protected void validate()
{
validateNormal(_bean);
}
@Override
public Bean<T> getBean()
{
return _bean;
}
@Override
public T create(CreationalContextImpl<T> env,
CreationalContextImpl<?> parentEnv,
InjectionPoint ip)
{
return _scopeAdapter;
}
}
public class DelegateReferenceFactory<T> extends ReferenceFactory<T> {
DelegateReferenceFactory()
{
}
@Override
public T create(CreationalContextImpl<T> env,
CreationalContextImpl<?> parentEnv,
InjectionPoint ip)
{
return (T) parentEnv.getDelegate();
}
}
public class ErrorReferenceFactory<T> extends ReferenceFactory<T> {
private RuntimeException _exn;
ErrorReferenceFactory(RuntimeException e)
{
_exn = e;
}
@Override
public boolean isProducer()
{
return true;
}
@Override
public T create(CreationalContextImpl<T> env,
CreationalContextImpl<?> parentEnv,
InjectionPoint ip)
{
throw _exn;
}
}
public class InjectionPointReferenceFactory
extends ReferenceFactory<InjectionPoint> {
InjectionPointReferenceFactory()
{
}
@Override
public InjectionPoint create(CreationalContextImpl<InjectionPoint> env,
CreationalContextImpl<?> parentEnv,
InjectionPoint ip)
{
InjectionPoint ip2 = parentEnv.findInjectionPoint();
if (ip2 != null)
return ip2;
throw new InjectionException(L.l("no injection point available in this context {0}",
ip));
}
}
public class UnresolvedReferenceFactory extends ReferenceFactory<Object> {
private InjectionException _exn;
UnresolvedReferenceFactory()
{
_exn = new InjectionException("unresolved injection");
}
@Override
public boolean isResolved()
{
return false;
}
@Override
public Object create(CreationalContextImpl<Object> env,
CreationalContextImpl<?> parentEnv,
InjectionPoint ip)
{
throw _exn;
}
}
static {
ArrayList<Class<?>> forbiddenAnnotations = new ArrayList<Class<?>>();
ArrayList<Class<?>> forbiddenClasses = new ArrayList<Class<?>>();
for (String className : FORBIDDEN_ANNOTATIONS) {
try {
Class<?> cl = Class.forName(className);
if (cl != null)
forbiddenAnnotations.add(cl);
} catch (Throwable e) {
log.log(Level.FINEST, e.toString(), e);
}
}
for (String className : FORBIDDEN_CLASSES) {
try {
Class<?> cl = Class.forName(className);
if (cl != null)
forbiddenClasses.add(cl);
} catch (Throwable e) {
log.log(Level.FINEST, e.toString(), e);
}
}
_forbiddenAnnotations = new Class[forbiddenAnnotations.size()];
forbiddenAnnotations.toArray(_forbiddenAnnotations);
_forbiddenClasses = new Class[forbiddenClasses.size()];
forbiddenClasses.toArray(_forbiddenClasses);
ClassLoader systemClassLoader = null;
try {
systemClassLoader = ClassLoader.getSystemClassLoader();
} catch (Throwable e) {
// a security manager may not allow this call
log.log(Level.FINEST, e.toString(), e);
}
_systemClassLoader = systemClassLoader;
}
}