
org.jboss.weld.manager.BeanManagerImpl Maven / Gradle / Ivy
/*
* JBoss, Home of Professional Open Source
* Copyright 2008, Red Hat, Inc., and individual contributors
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
* http://www.apache.org/licenses/LICENSE-2.0
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jboss.weld.manager;
import static org.jboss.weld.annotated.AnnotatedTypeValidator.validateAnnotatedType;
import static org.jboss.weld.util.collections.Iterables.concat;
import static org.jboss.weld.util.collections.Iterables.flatMap;
import static org.jboss.weld.util.reflection.Reflections.cast;
import static org.jboss.weld.util.reflection.Reflections.isCacheable;
import java.io.ObjectStreamException;
import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Member;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.regex.Pattern;
import jakarta.el.ELResolver;
import jakarta.el.ExpressionFactory;
import jakarta.enterprise.context.BeforeDestroyed;
import jakarta.enterprise.context.Dependent;
import jakarta.enterprise.context.Destroyed;
import jakarta.enterprise.context.Initialized;
import jakarta.enterprise.context.spi.Context;
import jakarta.enterprise.context.spi.Contextual;
import jakarta.enterprise.context.spi.CreationalContext;
import jakarta.enterprise.event.Event;
import jakarta.enterprise.inject.Any;
import jakarta.enterprise.inject.Default;
import jakarta.enterprise.inject.Instance;
import jakarta.enterprise.inject.spi.Annotated;
import jakarta.enterprise.inject.spi.AnnotatedField;
import jakarta.enterprise.inject.spi.AnnotatedMember;
import jakarta.enterprise.inject.spi.AnnotatedMethod;
import jakarta.enterprise.inject.spi.AnnotatedParameter;
import jakarta.enterprise.inject.spi.AnnotatedType;
import jakarta.enterprise.inject.spi.Bean;
import jakarta.enterprise.inject.spi.BeanAttributes;
import jakarta.enterprise.inject.spi.BeanManager;
import jakarta.enterprise.inject.spi.BeforeShutdown;
import jakarta.enterprise.inject.spi.Decorator;
import jakarta.enterprise.inject.spi.Extension;
import jakarta.enterprise.inject.spi.InjectionPoint;
import jakarta.enterprise.inject.spi.InjectionTarget;
import jakarta.enterprise.inject.spi.InjectionTargetFactory;
import jakarta.enterprise.inject.spi.InterceptionFactory;
import jakarta.enterprise.inject.spi.InterceptionType;
import jakarta.enterprise.inject.spi.Interceptor;
import jakarta.enterprise.inject.spi.ObserverMethod;
import jakarta.enterprise.inject.spi.PassivationCapable;
import jakarta.enterprise.inject.spi.Prioritized;
import jakarta.enterprise.inject.spi.ProcessInjectionPoint;
import jakarta.enterprise.inject.spi.ProcessInjectionTarget;
import jakarta.enterprise.inject.spi.ProducerFactory;
import jakarta.enterprise.util.TypeLiteral;
import org.jboss.weld.Container;
import org.jboss.weld.annotated.AnnotatedTypeValidator;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedField;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedMember;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedParameter;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedType;
import org.jboss.weld.annotated.slim.SlimAnnotatedType;
import org.jboss.weld.bean.AbstractClassBean;
import org.jboss.weld.bean.AbstractProducerBean;
import org.jboss.weld.bean.ContextualInstance;
import org.jboss.weld.bean.RIBean;
import org.jboss.weld.bean.SessionBean;
import org.jboss.weld.bean.SyntheticBeanFactory;
import org.jboss.weld.bean.WeldBean;
import org.jboss.weld.bean.attributes.BeanAttributesFactory;
import org.jboss.weld.bean.builtin.AbstractBuiltInBean;
import org.jboss.weld.bean.builtin.ExtensionBean;
import org.jboss.weld.bean.builtin.InstanceImpl;
import org.jboss.weld.bean.proxy.ClientProxyProvider;
import org.jboss.weld.bean.proxy.DecorationHelper;
import org.jboss.weld.bootstrap.SpecializationAndEnablementRegistry;
import org.jboss.weld.bootstrap.Validator;
import org.jboss.weld.bootstrap.WeldUnusedMetadataExtension;
import org.jboss.weld.bootstrap.api.Bootstrap;
import org.jboss.weld.bootstrap.api.Environment;
import org.jboss.weld.bootstrap.api.ServiceRegistry;
import org.jboss.weld.bootstrap.enablement.ModuleEnablement;
import org.jboss.weld.bootstrap.events.ContainerLifecycleEvents;
import org.jboss.weld.bootstrap.spi.CDI11Deployment;
import org.jboss.weld.config.ConfigurationKey;
import org.jboss.weld.config.ConfigurationKey.UnusedBeans;
import org.jboss.weld.config.WeldConfiguration;
import org.jboss.weld.contexts.CreationalContextImpl;
import org.jboss.weld.contexts.PassivatingContextWrapper;
import org.jboss.weld.contexts.WeldCreationalContext;
import org.jboss.weld.ejb.spi.EjbDescriptor;
import org.jboss.weld.event.ContainerLifecycleEventObserverMethod;
import org.jboss.weld.event.EventImpl;
import org.jboss.weld.event.FastEvent;
import org.jboss.weld.event.GlobalObserverNotifierService;
import org.jboss.weld.event.ObserverMethodImpl;
import org.jboss.weld.event.ObserverNotifier;
import org.jboss.weld.events.WeldEvent;
import org.jboss.weld.exceptions.DefinitionException;
import org.jboss.weld.exceptions.DeploymentException;
import org.jboss.weld.exceptions.IllegalArgumentException;
import org.jboss.weld.exceptions.IllegalStateException;
import org.jboss.weld.exceptions.InjectionException;
import org.jboss.weld.inject.WeldInstance;
import org.jboss.weld.injection.CurrentInjectionPoint;
import org.jboss.weld.injection.EmptyInjectionPoint;
import org.jboss.weld.injection.InterceptionFactoryImpl;
import org.jboss.weld.injection.ThreadLocalStack.ThreadLocalStackReference;
import org.jboss.weld.injection.attributes.FieldInjectionPointAttributes;
import org.jboss.weld.injection.attributes.InferringFieldInjectionPointAttributes;
import org.jboss.weld.injection.attributes.InferringParameterInjectionPointAttributes;
import org.jboss.weld.injection.attributes.ParameterInjectionPointAttributes;
import org.jboss.weld.injection.producer.WeldInjectionTargetBuilderImpl;
import org.jboss.weld.interceptor.reader.InterceptorMetadataReader;
import org.jboss.weld.interceptor.spi.model.InterceptionModel;
import org.jboss.weld.invokable.AbstractInvokerBuilder;
import org.jboss.weld.logging.BeanManagerLogger;
import org.jboss.weld.logging.BootstrapLogger;
import org.jboss.weld.manager.api.WeldInjectionTargetBuilder;
import org.jboss.weld.manager.api.WeldInjectionTargetFactory;
import org.jboss.weld.manager.api.WeldManager;
import org.jboss.weld.metadata.cache.InterceptorBindingModel;
import org.jboss.weld.metadata.cache.MetaAnnotationStore;
import org.jboss.weld.metadata.cache.ScopeModel;
import org.jboss.weld.metadata.cache.StereotypeModel;
import org.jboss.weld.module.EjbSupport;
import org.jboss.weld.module.ExpressionLanguageSupport;
import org.jboss.weld.module.ObserverNotifierFactory;
import org.jboss.weld.resolution.BeanTypeAssignabilityRules;
import org.jboss.weld.resolution.DecoratorResolvableBuilder;
import org.jboss.weld.resolution.EventTypeAssignabilityRules;
import org.jboss.weld.resolution.InterceptorResolvable;
import org.jboss.weld.resolution.InterceptorResolvableBuilder;
import org.jboss.weld.resolution.NameBasedResolver;
import org.jboss.weld.resolution.QualifierInstance;
import org.jboss.weld.resolution.Resolvable;
import org.jboss.weld.resolution.ResolvableBuilder;
import org.jboss.weld.resolution.TypeSafeBeanResolver;
import org.jboss.weld.resolution.TypeSafeDecoratorResolver;
import org.jboss.weld.resolution.TypeSafeInterceptorResolver;
import org.jboss.weld.resolution.TypeSafeObserverResolver;
import org.jboss.weld.resources.ClassTransformer;
import org.jboss.weld.resources.MemberTransformer;
import org.jboss.weld.serialization.ContextualStoreImpl;
import org.jboss.weld.serialization.spi.BeanIdentifier;
import org.jboss.weld.serialization.spi.ContextualStore;
import org.jboss.weld.util.Beans;
import org.jboss.weld.util.Bindings;
import org.jboss.weld.util.ForwardingBeanManager;
import org.jboss.weld.util.InjectionPoints;
import org.jboss.weld.util.Interceptors;
import org.jboss.weld.util.LazyValueHolder;
import org.jboss.weld.util.Observers;
import org.jboss.weld.util.Preconditions;
import org.jboss.weld.util.Types;
import org.jboss.weld.util.collections.ImmutableSet;
import org.jboss.weld.util.collections.SetMultimap;
import org.jboss.weld.util.collections.WeldCollections;
import org.jboss.weld.util.reflection.HierarchyDiscovery;
import org.jboss.weld.util.reflection.Reflections;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
/**
* Implementation of the Bean Manager.
*
* Essentially a singleton for registering Beans, Contexts, Observers, Interceptors etc. as well as providing resolution
*
* @author Pete Muir
* @author Marius Bogoevici
* @author Ales Justin
* @author Jozef Hartinger
*/
public class BeanManagerImpl implements WeldManager, Serializable {
private static final long serialVersionUID = 3021562879133838561L;
private static final String CREATIONAL_CONTEXT = "creationalContext";
/*
* Application scoped services ***************************
*/
private final transient ServiceRegistry services;
/*
* Application scoped data structures ***********************************
*/
// Contexts are shared across the application
private final transient Map, List> contexts;
// Client proxies can be used application wide
private final transient ClientProxyProvider clientProxyProvider;
private final transient Map, SessionBean>> enterpriseBeans;
/*
* Archive scoped data structures ******************************
*/
/*
* These data structures are all non-transitive in terms of bean deployment archive accessibility, and the configuration for
* this bean deployment archive
*/
private transient volatile ModuleEnablement enabled;
/*
* Bean Archive scoped services *************************
*/
/*
* These services are scoped to this bean archive only, but use data structures that are transitive accessible from other
* bean deployment archives
*/
private final transient TypeSafeBeanResolver beanResolver;
private final transient TypeSafeDecoratorResolver decoratorResolver;
private final transient TypeSafeInterceptorResolver interceptorResolver;
private final transient NameBasedResolver nameBasedResolver;
private final transient ELResolver weldELResolver;
/*
* Lenient instances do not perform event type checking - this is required for firing container lifecycle events. Strict
* instances do perform event type
* checking and are used for firing application an extension events.
*/
private final transient ObserverNotifier accessibleLenientObserverNotifier;
private final transient ObserverNotifier globalLenientObserverNotifier;
private final transient ObserverNotifier globalStrictObserverNotifier;
/*
* Bean archive scoped data structures ********************************
*/
/*
* These data structures are scoped to this bean deployment archive only and represent the beans, decorators, interceptors,
* namespaces, observers and invokers
* deployed in this bean deployment archive
*/
private final transient List> enabledBeans;
// shared beans are accessible from other bean archives (generally all beans except for built-in beans and @New beans)
private final transient List> sharedBeans;
private final transient List> specializedBeans;
private final transient List> decorators;
private final transient List> interceptors;
private final transient List namespaces;
private final transient List> observers;
private final transient List> invokers; // only for validation, cleaned up afterward
/*
* set that is only used to make sure that no duplicate beans are added
*/
private transient Set> beanSet = Collections.synchronizedSet(new HashSet>());
/*
* Data structure representing all managers from this deployment
*/
private final transient Set managers;
/*
* These data structures represent the managers *accessible* from this bean deployment archive
*/
private final transient HashSet accessibleManagers;
private final String id;
private final String contextId;
/**
* Interception model
*/
private final transient ConcurrentMap, InterceptionModel> interceptorModelRegistry = new ConcurrentHashMap, InterceptionModel>();
private final transient InterceptorMetadataReader interceptorMetadataReader = new InterceptorMetadataReader(this);
private final transient ContainerLifecycleEvents containerLifecycleEvents;
private final transient SpecializationAndEnablementRegistry registry;
/*
* Stuff that is used often thus we cache it here to reduce service lookups
*/
private final transient CurrentInjectionPoint currentInjectionPoint;
private final transient boolean clientProxyOptimization;
private final transient List> validationFailureCallbacks;
/**
* Request context lifecycle events
*/
private final transient LazyValueHolder> requestInitializedEvent;
private final transient LazyValueHolder> requestBeforeDestroyedEvent;
private final transient LazyValueHolder> requestDestroyedEvent;
/**
* Create a new, root, manager
*
* @param serviceRegistry
* @return
*/
public static BeanManagerImpl newRootManager(String contextId, String id, ServiceRegistry serviceRegistry) {
Map, List> contexts = new ConcurrentHashMap, List>();
return new BeanManagerImpl(serviceRegistry, new CopyOnWriteArrayList>(), new CopyOnWriteArrayList>(),
new CopyOnWriteArrayList>(), new CopyOnWriteArrayList>(),
new CopyOnWriteArrayList>(),
new CopyOnWriteArrayList(), new CopyOnWriteArrayList>(),
new ConcurrentHashMap, SessionBean>>(),
new ClientProxyProvider(contextId), contexts,
ModuleEnablement.EMPTY_ENABLEMENT, id, new AtomicInteger(), new HashSet(), contextId);
}
public static BeanManagerImpl newManager(BeanManagerImpl rootManager, String id, ServiceRegistry services) {
return new BeanManagerImpl(services, new CopyOnWriteArrayList>(), new CopyOnWriteArrayList>(),
new CopyOnWriteArrayList>(),
new CopyOnWriteArrayList>(), new CopyOnWriteArrayList>(),
new CopyOnWriteArrayList(), new CopyOnWriteArrayList>(),
rootManager.getEnterpriseBeans(), rootManager.getClientProxyProvider(), rootManager.getContexts(),
ModuleEnablement.EMPTY_ENABLEMENT, id,
new AtomicInteger(), rootManager.managers, rootManager.contextId);
}
private BeanManagerImpl(ServiceRegistry serviceRegistry, List> beans, List> transitiveBeans,
List> decorators, List> interceptors, List> observers,
List namespaces, List> invokers,
Map, SessionBean>> enterpriseBeans, ClientProxyProvider clientProxyProvider,
Map, List> contexts, ModuleEnablement enabled, String id,
AtomicInteger childIds,
Set managers, String contextId) {
this.services = serviceRegistry;
this.enabledBeans = beans;
this.sharedBeans = transitiveBeans;
this.decorators = decorators;
this.interceptors = interceptors;
this.enterpriseBeans = enterpriseBeans;
this.clientProxyProvider = clientProxyProvider;
this.contexts = contexts;
this.observers = observers;
this.enabled = enabled;
this.namespaces = namespaces;
this.invokers = invokers;
this.id = id;
this.managers = managers;
this.contextId = contextId;
managers.add(this);
// Set up the structure to store accessible managers in
this.accessibleManagers = new HashSet();
BeanTransform beanTransform = new BeanTransform(this);
this.beanResolver = new TypeSafeBeanResolver(this, createDynamicAccessibleIterable(beanTransform));
this.decoratorResolver = new TypeSafeDecoratorResolver(this,
createDynamicGlobalIterable(BeanManagerImpl::getDecorators));
this.interceptorResolver = new TypeSafeInterceptorResolver(this,
createDynamicGlobalIterable(BeanManagerImpl::getInterceptors));
this.nameBasedResolver = new NameBasedResolver(this, createDynamicAccessibleIterable(beanTransform));
this.weldELResolver = services.getOptional(ExpressionLanguageSupport.class).map(el -> el.createElResolver(this))
.orElse(null);
TypeSafeObserverResolver accessibleObserverResolver = new TypeSafeObserverResolver(
getServices().get(MetaAnnotationStore.class),
createDynamicAccessibleIterable(BeanManagerImpl::getObservers), getServices().get(WeldConfiguration.class));
this.accessibleLenientObserverNotifier = getServices().get(ObserverNotifierFactory.class).create(contextId,
accessibleObserverResolver, getServices(),
false);
GlobalObserverNotifierService globalObserverNotifierService = services.get(GlobalObserverNotifierService.class);
this.globalLenientObserverNotifier = globalObserverNotifierService.getGlobalLenientObserverNotifier();
this.globalStrictObserverNotifier = globalObserverNotifierService.getGlobalStrictObserverNotifier();
globalObserverNotifierService.registerBeanManager(this);
this.containerLifecycleEvents = serviceRegistry.get(ContainerLifecycleEvents.class);
this.registry = getServices().get(SpecializationAndEnablementRegistry.class);
this.currentInjectionPoint = getServices().get(CurrentInjectionPoint.class);
this.clientProxyOptimization = getServices().get(WeldConfiguration.class)
.getBooleanProperty(ConfigurationKey.INJECTABLE_REFERENCE_OPTIMIZATION);
this.requestInitializedEvent = LazyValueHolder
.forSupplier(() -> FastEvent.of(Object.class, this, Initialized.Literal.REQUEST));
this.requestBeforeDestroyedEvent = LazyValueHolder
.forSupplier(() -> FastEvent.of(Object.class, this, BeforeDestroyed.Literal.REQUEST));
this.requestDestroyedEvent = LazyValueHolder
.forSupplier(() -> FastEvent.of(Object.class, this, Destroyed.Literal.REQUEST));
this.validationFailureCallbacks = new CopyOnWriteArrayList<>();
this.specializedBeans = new CopyOnWriteArrayList<>();
}
private Iterable createDynamicGlobalIterable(final Function> transform) {
return flatMap(managers, transform);
}
public String getContextId() {
return contextId;
}
private Iterable createDynamicAccessibleIterable(final Function> transform) {
return concat(flatMap(getAccessibleManagers(), transform), transform.apply(this));
}
public void addAccessibleBeanManager(BeanManagerImpl accessibleBeanManager) {
accessibleManagers.add(accessibleBeanManager);
beanResolver.clear();
interceptorResolver.clear();
decoratorResolver.clear();
accessibleLenientObserverNotifier.clear();
}
public HashSet getAccessibleManagers() {
return accessibleManagers;
}
public void addBean(Bean> bean) {
addBean(bean, enabledBeans, sharedBeans);
}
/**
* Optimization which modifies CopyOnWrite structures only once instead of once for every bean.
*
* @param beans
*/
public void addBeans(Collection extends Bean>> beans) {
List> beanList = new ArrayList>(beans.size());
List> transitiveBeans = new ArrayList>(beans.size());
for (Bean> bean : beans) {
addBean(bean, beanList, transitiveBeans);
}
// optimize so that we do not modify CopyOnWriteLists for each Bean
this.enabledBeans.addAll(beanList);
this.sharedBeans.addAll(transitiveBeans);
}
/**
* Helper method which allows to recognize if bean was created by BeanConfigurator and has any priority set. Note that such
* bean will not implement
* Prioritized interface.
*/
private boolean isConfiguratorBeanWithPriority(Bean> bean) {
return bean instanceof WeldBean && ((WeldBean>) bean).getPriority() != null;
}
private void addBean(Bean> bean, List> beanList, List> transitiveBeans) {
if (beanSet.add(bean)) {
if (bean.isAlternative() && (!registry.isEnabledInAnyBeanDeployment(bean) && !(bean instanceof Prioritized))
&& !isConfiguratorBeanWithPriority(bean)) {
BootstrapLogger.LOG.foundDisabledAlternative(bean);
} else if (registry.isSpecializedInAnyBeanDeployment(bean)) {
BootstrapLogger.LOG.foundSpecializedBean(bean);
} else if (bean instanceof AbstractProducerBean, ?, ?>
&& registry.isSpecializedInAnyBeanDeployment(((AbstractProducerBean, ?, ?>) bean).getDeclaringBean())) {
BootstrapLogger.LOG.foundProducerOfSpecializedBean(bean);
specializedBeans.add(bean);
} else {
BootstrapLogger.LOG.foundBean(bean);
beanList.add(bean);
if (bean instanceof SessionBean) {
SessionBean> enterpriseBean = (SessionBean>) bean;
enterpriseBeans.put(enterpriseBean.getEjbDescriptor(), enterpriseBean);
}
if (bean instanceof PassivationCapable) {
getServices().get(ContextualStore.class).putIfAbsent(bean);
}
registerBeanNamespace(bean);
// SessionBeans and most built in beans aren't resolvable transitively
if (bean instanceof ExtensionBean || bean instanceof SessionBean
|| (!(bean instanceof AbstractBuiltInBean>))) {
transitiveBeans.add(bean);
}
}
}
}
public void addDecorator(Decorator> bean) {
decorators.add(bean);
getServices().get(ContextualStore.class).putIfAbsent(bean);
decoratorResolver.clear();
}
@Override
public Set> resolveObserverMethods(T event, Annotation... bindings) {
return ImmutableSet
.copyOf(globalStrictObserverNotifier.resolveObserverMethods(event.getClass(), bindings).getAllObservers());
}
public void addInterceptor(Interceptor> bean) {
interceptors.add(bean);
getServices().get(ContextualStore.class).putIfAbsent(bean);
interceptorResolver.clear();
}
/**
* Enabled Alternatives, Interceptors and Decorators
*
* @return
*/
public ModuleEnablement getEnabled() {
return enabled;
}
public void setEnabled(ModuleEnablement enabled) {
this.enabled = enabled;
}
public boolean isBeanEnabled(Bean> bean) {
return Beans.isBeanEnabled(bean, getEnabled());
}
@Override
public Set> getBeans(Type beanType, Annotation... qualifiers) {
Resolvable resolvable = new ResolvableBuilder(beanType, this).addQualifiers(qualifiers).create();
return beanResolver.resolve(resolvable, isCacheable(qualifiers));
}
public Set> getBeans(Type beanType, Set qualifiers) {
return beanResolver.resolve(new ResolvableBuilder(beanType, this).addQualifiers(qualifiers).create(),
isCacheable(qualifiers));
}
public Set> getBeans(InjectionPoint injectionPoint) {
boolean registerInjectionPoint = isRegisterableInjectionPoint(injectionPoint);
final ThreadLocalStackReference stack = currentInjectionPoint.pushConditionally(injectionPoint,
registerInjectionPoint);
try {
// We always cache, we assume that people don't use inline annotation literal declarations, a little risky but FAQd
return beanResolver.resolve(new ResolvableBuilder(injectionPoint, this).create(), true);
} finally {
stack.pop();
}
}
protected void registerBeanNamespace(Bean> bean) {
if (bean.getName() != null) {
String[] parts = bean.getName().split("\\.");
if (parts.length > 1) {
for (int i = 0; i < parts.length - 1; i++) {
StringBuilder builder = new StringBuilder();
for (int j = 0; j <= i; j++) {
if (j > 0) {
builder.append('.');
}
builder.append(parts[j]);
}
namespaces.add(builder.toString());
}
}
}
}
/**
* Gets the class-mapped beans. For internal use.
*
* @return The bean map
*/
public Map, SessionBean>> getEnterpriseBeans() {
return enterpriseBeans;
}
/**
* The beans registered with the Web Bean manager which are resolvable. Does not include interceptor and decorator beans
*
* @return The list of known beans
*/
public List> getBeans() {
return WeldCollections.immutableListView(enabledBeans);
}
List> getSharedBeans() {
return WeldCollections.immutableListView(sharedBeans);
}
public List> getDecorators() {
return WeldCollections.immutableListView(decorators);
}
public List> getInterceptors() {
return WeldCollections.immutableListView(interceptors);
}
public Iterable> getDynamicAccessibleBeans() {
return createDynamicAccessibleIterable(new BeanTransform(this));
}
/**
* Unlike {@link #getDynamicAccessibleBeans()} this method returns a mutable set which is not updated automatically.
*
* @return all accessible beans
*/
public Set> getAccessibleBeans() {
Set> beans = new HashSet<>();
beans.addAll(getBeans());
for (BeanManagerImpl beanManager : getAccessibleManagers()) {
beans.addAll(beanManager.getSharedBeans());
}
return beans;
}
public Iterable> getDynamicAccessibleInterceptors() {
return createDynamicAccessibleIterable(BeanManagerImpl::getInterceptors);
}
public Iterable> getDynamicAccessibleDecorators() {
return createDynamicAccessibleIterable(BeanManagerImpl::getDecorators);
}
public void addContext(Context context) {
Class extends Annotation> scope = context.getScope();
if (isPassivatingScope(scope)) {
context = PassivatingContextWrapper.wrap(context, services.get(ContextualStore.class));
}
List contextList = contexts.get(scope);
if (contextList == null) {
contextList = new CopyOnWriteArrayList();
contexts.put(scope, contextList);
}
contextList.add(context);
}
/**
* Does the actual observer registration
*
* @param observer =
*/
public void addObserver(ObserverMethod> observer) {
// checkEventType(observer.getObservedType());
observers.add(observer);
}
public void addInvoker(AbstractInvokerBuilder, ?> invoker) {
invokers.add(invoker);
}
public void forgetInvokersAfterValidation() {
invokers.clear();
}
/**
* Gets an active context of the given scope. Throws an exception if there are no active contexts found or if there are too
* many matches
*
* @throws IllegalStateException if there are multiple active scopes for a given context
* @param scopeType The scope to match
* @return A single active context of the given scope
* @seejakarta.enterprise.inject.spi.BeanManager#getContext(java.lang.Class)
*/
@Override
public Context getContext(Class extends Annotation> scopeType) {
Context activeContext = internalGetContext(scopeType);
if (activeContext == null) {
throw BeanManagerLogger.LOG.contextNotActive(scopeType.getName());
}
return activeContext;
}
@Override
public Collection getContexts(Class extends Annotation> scopeType) {
List found = this.contexts.get(scopeType);
return found != null ? Collections.unmodifiableList(found) : Collections.EMPTY_LIST;
}
public Context getUnwrappedContext(Class extends Annotation> scopeType) {
return PassivatingContextWrapper.unwrap(getContext(scopeType));
}
@Override
public boolean isContextActive(Class extends Annotation> scopeType) {
return internalGetContext(scopeType) != null;
}
private Context internalGetContext(Class extends Annotation> scopeType) {
Context activeContext = null;
final List ctx = contexts.get(scopeType);
if (ctx == null) {
return null;
}
for (Context context : ctx) {
if (context.isActive()) {
if (activeContext == null) {
activeContext = context;
} else {
throw BeanManagerLogger.LOG.duplicateActiveContexts(scopeType.getName());
}
}
}
return activeContext;
}
public Object getReference(Bean> bean, Type requestedType, CreationalContext> creationalContext, boolean noProxy) {
if (creationalContext == null) {
// null CC indicates we need to create a new one that has no parent linked to it
creationalContext = createCreationalContext(null);
} else if (creationalContext instanceof CreationalContextImpl>) {
creationalContext = ((CreationalContextImpl>) creationalContext).getCreationalContext(bean);
}
if (!noProxy && isProxyRequired(bean)) {
if (requestedType == null) {
return clientProxyProvider.getClientProxy(bean);
} else {
return clientProxyProvider.getClientProxy(bean, requestedType);
}
} else {
return ContextualInstance.get(bean, this, creationalContext);
}
}
private boolean isProxyRequired(Bean> bean) {
if (bean instanceof RIBean>) {
return ((RIBean>) bean).isProxyRequired();
} else {
return isNormalScope(bean.getScope());
}
}
@Override
public Object getReference(Bean> bean, Type requestedType, CreationalContext> creationalContext) {
Preconditions.checkArgumentNotNull(bean, "bean");
Preconditions.checkArgumentNotNull(requestedType, "requestedType");
Preconditions.checkArgumentNotNull(creationalContext, CREATIONAL_CONTEXT);
if (!BeanTypeAssignabilityRules.instance().matches(requestedType, bean.getTypes())) {
throw BeanManagerLogger.LOG.specifiedTypeNotBeanType(requestedType, bean);
}
// Ensure that there is no injection point associated
final ThreadLocalStackReference stack = currentInjectionPoint.push(EmptyInjectionPoint.INSTANCE);
try {
return getReference(bean, requestedType, creationalContext, false);
} finally {
stack.pop();
}
}
/**
* Get a reference, registering the injection point used.
*
* @param injectionPoint the injection point to register
* @param resolvedBean the bean to get a reference to
* @param creationalContext the creationalContext
* @return the injectable reference
*/
public Object getInjectableReference(InjectionPoint injectionPoint, Bean> resolvedBean,
CreationalContext> creationalContext) {
Preconditions.checkArgumentNotNull(resolvedBean, "resolvedBean");
Preconditions.checkArgumentNotNull(creationalContext, CREATIONAL_CONTEXT);
boolean registerInjectionPoint = isRegisterableInjectionPoint(injectionPoint);
boolean delegateInjectionPoint = injectionPoint != null && injectionPoint.isDelegate();
final ThreadLocalStackReference stack = currentInjectionPoint.pushConditionally(injectionPoint,
registerInjectionPoint);
try {
Type requestedType = null;
if (injectionPoint != null) {
requestedType = injectionPoint.getType();
}
if (clientProxyOptimization && injectionPoint != null && injectionPoint.getBean() != null) {
// For certain combinations of scopes, the container is permitted to optimize an injectable reference lookup
// This should also partially solve circular @PostConstruct invocation
CreationalContextImpl> weldCreationalContext = null;
Bean> bean = injectionPoint.getBean();
// Do not optimize for self injection
if (!bean.equals(resolvedBean)) {
if (creationalContext instanceof CreationalContextImpl) {
weldCreationalContext = (CreationalContextImpl>) creationalContext;
}
if (weldCreationalContext != null && Dependent.class.equals(bean.getScope())
&& isNormalScope(resolvedBean.getScope())) {
bean = findNormalScopedDependant(weldCreationalContext);
}
if (InjectionPoints.isInjectableReferenceLookupOptimizationAllowed(bean, resolvedBean)) {
if (weldCreationalContext != null) {
final Object incompleteInstance = weldCreationalContext.getIncompleteInstance(resolvedBean);
if (incompleteInstance != null) {
return incompleteInstance;
}
}
Context context = internalGetContext(resolvedBean.getScope());
if (context != null) {
@SuppressWarnings({ "unchecked", "rawtypes" })
final Object existinInstance = context.get(Reflections. cast(resolvedBean));
if (existinInstance != null) {
return existinInstance;
}
}
}
}
}
// #getReference always creates a child CC and links it to the CC we pass an argument
// This is exactly what we want for dependent beans but all other beans shouldn't have that
if (Dependent.class.equals(resolvedBean.getScope())) {
return getReference(resolvedBean, requestedType, creationalContext, delegateInjectionPoint);
} else {
return getReference(resolvedBean, requestedType, null, delegateInjectionPoint);
}
} finally {
stack.pop();
}
}
@Override
public Object getInjectableReference(InjectionPoint injectionPoint, CreationalContext> creationalContext) {
if (injectionPoint.isDelegate()) {
return DecorationHelper.peek().getNextDelegate(injectionPoint, creationalContext);
} else {
Bean> resolvedBean = getBean(new ResolvableBuilder(injectionPoint, this).create());
return getInjectableReference(injectionPoint, resolvedBean, creationalContext);
}
}
public Bean getBean(Resolvable resolvable) {
// We can always cache as this is only ever called by Weld where we avoid non-static inner classes for annotation literals
Bean bean = cast(resolve(beanResolver.resolve(resolvable, true)));
if (bean == null) {
throw BeanManagerLogger.LOG.unresolvableElement(resolvable);
}
return bean;
}
@Override
public Set> getBeans(String name) {
return nameBasedResolver.resolve(name);
}
@Override
public List> resolveDecorators(Set types, Annotation... qualifiers) {
checkResolveDecoratorsArguments(types);
return decoratorResolver.resolve(
new DecoratorResolvableBuilder(this).addTypes(types).addQualifiers(qualifiers).create(),
isCacheable(qualifiers));
}
public List> resolveDecorators(Set types, Set qualifiers) {
checkResolveDecoratorsArguments(types);
return decoratorResolver
.resolve(new DecoratorResolvableBuilder(this).addTypes(types).addQualifiers(qualifiers).create(), true);
}
private void checkResolveDecoratorsArguments(Set types) {
if (types.isEmpty()) {
throw BeanManagerLogger.LOG.noDecoratorTypes();
}
}
/**
* Resolves a list of interceptors based on interception type and interceptor bindings. Transitive interceptor bindings of
* the interceptor bindings passed
* as a parameter are considered in the resolution process.
*
* @param type The interception type to resolve
* @param interceptorBindings The binding types to match
* @return A list of matching interceptors
* @seejakarta.enterprise.inject.spi.BeanManager#resolveInterceptors(jakarta.enterprise.inject.spi.InterceptionType, java.lang.annotation.Annotation[])
*/
@Override
public List> resolveInterceptors(InterceptionType type, Annotation... interceptorBindings) {
if (interceptorBindings.length == 0) {
throw BeanManagerLogger.LOG.interceptorBindingsEmpty();
}
for (Annotation annotation : interceptorBindings) {
if (!isInterceptorBinding(annotation.annotationType())) {
throw BeanManagerLogger.LOG.notInterceptorBindingType(annotation);
}
}
Set flattenedInterceptorBindings = Interceptors.flattenInterceptorBindings(null, this,
Arrays.asList(interceptorBindings), true, true);
return resolveInterceptors(type, flattenedInterceptorBindings);
}
/**
* Resolves a list of interceptors based on interception type and interceptor bindings. Transitive interceptor bindings of
* the interceptor bindings passed
* as a parameter are NOT considered in the resolution process. Therefore, the caller is responsible for filtering of
* transitive interceptor bindings in
* order to comply with interceptor binding inheritance and overriding (See JSR-346 9.5.2). This is a Weld-specific method.
*
* @param type The interception type to resolve
* @param interceptorBindings The binding types to match
* @return A list of matching interceptors
*/
public List> resolveInterceptors(InterceptionType type, Collection interceptorBindings) {
// We can always cache as this is only ever called by Weld where we avoid non-static inner classes for annotation literals
InterceptorResolvable interceptorResolvable = new InterceptorResolvableBuilder(Object.class, this)
.setInterceptionType(type)
.addQualifiers(interceptorBindings).create();
return interceptorResolver.resolve(interceptorResolvable, isCacheable(interceptorBindings));
}
/**
* Get the web bean resolver. For internal use
*
* @return The resolver
*/
public TypeSafeBeanResolver getBeanResolver() {
return beanResolver;
}
/**
* Get the decorator resolver. For internal use
*
* @return The resolver
*/
public TypeSafeDecoratorResolver getDecoratorResolver() {
return decoratorResolver;
}
public TypeSafeInterceptorResolver getInterceptorResolver() {
return interceptorResolver;
}
public NameBasedResolver getNameBasedResolver() {
return nameBasedResolver;
}
/**
* Get the lenient observer notifier for accessible observer methods. Should never be exposed to an application.
*
* @return The {@link ObserverNotifier}
*/
public ObserverNotifier getAccessibleLenientObserverNotifier() {
return accessibleLenientObserverNotifier;
}
/**
* Get the lenient global observer notifier. Should never be exposed to an application.
*
* @return The {@link ObserverNotifier}
*/
public ObserverNotifier getGlobalLenientObserverNotifier() {
return globalLenientObserverNotifier;
}
/**
* Get the Strict global observer notifier. This one should be used for firing application / extension events.
*
* @return The {@link ObserverNotifier}
*/
public ObserverNotifier getGlobalStrictObserverNotifier() {
return globalStrictObserverNotifier;
}
/**
* Gets a string representation
*
* @return A string representation
*/
@Override
public String toString() {
return "Weld BeanManager for " + getId() + " [bean count=" + getBeans().size() + "]";
}
@Override
@SuppressFBWarnings("EQ_CHECK_FOR_OPERAND_NOT_COMPATIBLE_WITH_THIS")
public boolean equals(Object obj) {
if (obj instanceof ForwardingBeanManager) {
ForwardingBeanManager proxy = (ForwardingBeanManager) obj;
obj = proxy.delegate();
}
if (obj instanceof BeanManagerImpl) {
BeanManagerImpl that = (BeanManagerImpl) obj;
return this.getId().equals(that.getId());
} else {
return false;
}
}
@Override
public int hashCode() {
return getId().hashCode();
}
@Override
public ServiceRegistry getServices() {
return services;
}
// Serialization
protected Object readResolve() throws ObjectStreamException {
return Container.instance(contextId).getBeanManager(id);
}
public ClientProxyProvider getClientProxyProvider() {
return clientProxyProvider;
}
protected Map, List> getContexts() {
return contexts;
}
/**
* @return the namespaces
*/
protected List getNamespaces() {
return namespaces;
}
public Iterable getDynamicAccessibleNamespaces() {
return createDynamicAccessibleIterable(BeanManagerImpl::getNamespaces);
}
/**
* Unlike {@link #getDynamicAccessibleNamespaces()} this method returns a mutable set which is not updated automatically.
*
* @return the accessible namespaces
*/
public List getAccessibleNamespaces() {
List namespaces = new ArrayList<>();
namespaces.addAll(getNamespaces());
for (BeanManagerImpl beanManagerImpl : getAccessibleManagers()) {
namespaces.addAll(beanManagerImpl.getNamespaces());
}
return namespaces;
}
@Override
public String getId() {
return id;
}
public List> getObservers() {
return observers;
}
public List> getInvokers() {
return invokers;
}
@Override
public InjectionTarget createInjectionTarget(EjbDescriptor descriptor) {
if (descriptor.isMessageDriven()) {
AnnotatedType type = Reflections.cast(createAnnotatedType(descriptor.getBeanClass()));
return getLocalInjectionTargetFactory(type).createMessageDrivenInjectionTarget(descriptor);
} else {
InjectionTarget injectionTarget = getBean(descriptor).getProducer();
return injectionTarget;
}
}
@Override
public void validate(InjectionPoint ij) {
try {
getServices().get(Validator.class).validateInjectionPoint(ij, this);
} catch (DeploymentException e) {
throw new InjectionException(e.getLocalizedMessage(), e.getCause());
}
}
@Override
public Set getInterceptorBindingDefinition(Class extends Annotation> bindingType) {
InterceptorBindingModel extends Annotation> model = getServices().get(MetaAnnotationStore.class)
.getInterceptorBindingModel(bindingType);
if (model.isValid()) {
return model.getMetaAnnotations();
} else {
throw BeanManagerLogger.LOG.notInterceptorBindingType(bindingType);
}
}
@Override
public Bean> getPassivationCapableBean(String id) {
return getServices().get(ContextualStore.class)., Object> getContextual(id);
}
@Override
public Bean> getPassivationCapableBean(BeanIdentifier identifier) {
return getServices().get(ContextualStore.class)., Object> getContextual(identifier);
}
@Override
public Set getStereotypeDefinition(Class extends Annotation> stereotype) {
final StereotypeModel extends Annotation> model = getServices().get(MetaAnnotationStore.class)
.getStereotype(stereotype);
if (model.isValid()) {
return model.getMetaAnnotations();
} else {
throw BeanManagerLogger.LOG.notStereotype(stereotype);
}
}
@Override
public boolean isQualifier(Class extends Annotation> annotationType) {
return getServices().get(MetaAnnotationStore.class).getBindingTypeModel(annotationType).isValid();
}
@Override
public boolean isInterceptorBinding(Class extends Annotation> annotationType) {
return getServices().get(MetaAnnotationStore.class).getInterceptorBindingModel(annotationType).isValid();
}
@Override
public boolean isNormalScope(Class extends Annotation> annotationType) {
ScopeModel> scope = getServices().get(MetaAnnotationStore.class).getScopeModel(annotationType);
return scope.isValid() && scope.isNormal();
}
@Override
public boolean isPassivatingScope(Class extends Annotation> annotationType) {
ScopeModel> scope = getServices().get(MetaAnnotationStore.class).getScopeModel(annotationType);
return scope.isValid() && scope.isPassivating();
}
@Override
public boolean isScope(Class extends Annotation> annotationType) {
return getServices().get(MetaAnnotationStore.class).getScopeModel(annotationType).isValid();
}
@Override
public boolean isStereotype(Class extends Annotation> annotationType) {
return getServices().get(MetaAnnotationStore.class).getStereotype(annotationType).isValid();
}
@Override
public ELResolver getELResolver() {
if (weldELResolver == null) {
throw BootstrapLogger.LOG.unspecifiedRequiredService(ExpressionLanguageSupport.class, id);
}
return weldELResolver;
}
@Override
public ExpressionFactory wrapExpressionFactory(ExpressionFactory expressionFactory) {
return services.getOptional(ExpressionLanguageSupport.class)
.orElseThrow(() -> BootstrapLogger.LOG.unspecifiedRequiredService(ExpressionLanguageSupport.class, id))
.wrapExpressionFactory(expressionFactory);
}
@Override
public WeldCreationalContext createCreationalContext(Contextual contextual) {
return new CreationalContextImpl(contextual);
}
@Override
public AnnotatedType createAnnotatedType(Class type) {
// first, make sure to use the right BDA ID for this class
String bdaId = BeanManagerLookupService.lookupBeanManager(type, this).getId();
return getServices().get(ClassTransformer.class).getBackedAnnotatedType(type, bdaId);
}
public EnhancedAnnotatedType createEnhancedAnnotatedType(Class type) {
// first, make sure to use the right BDA ID for this class
String bdaId = BeanManagerLookupService.lookupBeanManager(type, this).getId();
return getServices().get(ClassTransformer.class).getEnhancedAnnotatedType(type, bdaId);
}
@Override
public AnnotatedType createAnnotatedType(Class type, String id) {
return getServices().get(ClassTransformer.class).getBackedAnnotatedType(type,
BeanManagerLookupService.lookupBeanManager(type, this).getId(), id);
}
@Override
public void disposeAnnotatedType(Class type, String id) {
getServices().get(ClassTransformer.class).disposeBackedAnnotatedType(type,
BeanManagerLookupService.lookupBeanManager(type, this).getId(), id);
}
@Override
public Bean extends X> resolve(Set> beans) {
if (beans == null || beans.isEmpty()) {
return null;
}
Set> resolvedBeans = beanResolver.resolve(beans);
if (resolvedBeans.size() == 1) {
return resolvedBeans.iterator().next();
} else if (resolvedBeans.size() == 0) {
return null;
} else {
throw BeanManagerLogger.LOG.ambiguousBeansForDependency(WeldCollections.toMultiRowString(beans));
}
}
@Override
public EjbDescriptor getEjbDescriptor(String beanName) {
return getServices().get(EjbSupport.class).getEjbDescriptor(beanName);
}
@Override
public SessionBean getBean(EjbDescriptor descriptor) {
return cast(getEnterpriseBeans().get(descriptor));
}
public void cleanup() {
services.cleanup();
this.accessibleManagers.clear();
this.managers.clear();
this.beanResolver.clear();
this.enabledBeans.clear();
this.clientProxyProvider.clear();
this.contexts.clear();
this.decoratorResolver.clear();
this.decorators.clear();
this.enterpriseBeans.clear();
this.interceptorResolver.clear();
this.interceptors.clear();
this.nameBasedResolver.clear();
this.namespaces.clear();
this.accessibleLenientObserverNotifier.clear();
this.observers.clear();
}
/**
* For internal use only. This happens after bootstrap services cleanup but before {@link RIBean#cleanupAfterBoot()}.
*
* @see Bootstrap#endInitialization()
*/
public void cleanupAfterBoot() {
// Clear the bean set that is only used to make sure that no duplicate beans are added
if (beanSet != null) {
beanSet.clear();
beanSet = null;
}
this.validationFailureCallbacks.clear();
boolean isOptimizedCleanupAllowed = getServices().get(WeldConfiguration.class)
.getBooleanProperty(ConfigurationKey.ALLOW_OPTIMIZED_CLEANUP);
// Drop removable container lifecycle event observers
if (!observers.isEmpty()) {
observers.removeIf((o) -> {
return o instanceof ContainerLifecycleEventObserverMethod
// Do not use Observers.isContainerLifecycleObserverMethod() - e.g. @Observes Object must be retained
&& Observers.CONTAINER_LIFECYCLE_EVENT_TYPES.contains(Reflections.getRawType(o.getObservedType()))
// Do not drop BeforeShutdown
&& !BeforeShutdown.class.equals(Reflections.getRawType(o.getObservedType()))
// Note that some integrators may call Bootstrap.endInitialization() before all EE components are installed
&& (isOptimizedCleanupAllowed
|| (!ProcessInjectionPoint.class.equals(Reflections.getRawType(o.getObservedType()))
&& !ProcessInjectionTarget.class.equals(Reflections.getRawType(o.getObservedType()))));
});
}
if (isOptimizedCleanupAllowed) {
removeUnusedBeans();
// Make sure specialized beans and corresponding resources are released
if (!specializedBeans.isEmpty()) {
((ContextualStoreImpl) getServices().get(ContextualStore.class)).removeAll(specializedBeans);
cleanupBeansAfterBoot(specializedBeans);
specializedBeans.clear();
}
}
}
public ConcurrentMap, InterceptionModel> getInterceptorModelRegistry() {
return interceptorModelRegistry;
}
public InterceptorMetadataReader getInterceptorMetadataReader() {
return interceptorMetadataReader;
}
@Override
public InjectionTarget fireProcessInjectionTarget(AnnotatedType annotatedType) {
return fireProcessInjectionTarget(annotatedType, getInjectionTargetFactory(annotatedType).createInjectionTarget(null));
}
@Override
public InjectionTarget fireProcessInjectionTarget(AnnotatedType annotatedType,
InjectionTarget injectionTarget) {
return services.get(ContainerLifecycleEvents.class).fireProcessInjectionTarget(this, annotatedType, injectionTarget);
}
public Set extractInterceptorBindingsForQualifierInstance(Iterable annotations) {
Set foundInterceptionBindingTypes = new HashSet();
for (QualifierInstance annotation : annotations) {
if (isInterceptorBinding(annotation.getAnnotationClass())) {
foundInterceptionBindingTypes.add(annotation);
}
}
return foundInterceptionBindingTypes;
}
private static class InstanceInjectionPoint implements InjectionPoint, Serializable {
private static final long serialVersionUID = -2952474261839554286L;
private static final InjectionPoint INSTANCE = new InstanceInjectionPoint();
private transient Type type;
@SuppressWarnings("serial")
@Override
public Type getType() {
if (type == null) {
this.type = new TypeLiteral>() {
}.getType();
}
return type;
}
// there are no qualifiers by default
// ResolvableBuilder.create() takes care of adding @Default if there is no qualifier selected
@Override
public Set getQualifiers() {
return Collections.emptySet();
}
@Override
public Bean> getBean() {
return null;
}
@Override
public Member getMember() {
return null;
}
@Override
public Annotated getAnnotated() {
return null;
}
@Override
public boolean isDelegate() {
return false;
}
@Override
public boolean isTransient() {
return false;
}
}
@Override
public Instance
© 2015 - 2025 Weber Informatics LLC | Privacy Policy