All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.jboss.weld.BeanManagerImpl Maven / Gradle / Ivy

There is a newer version: 3.0.0.Alpha6
Show newest version
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2008, Red Hat Middleware LLC, 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;

import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.Stack;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CopyOnWriteArraySet;
import java.util.concurrent.atomic.AtomicInteger;

import javax.el.ELResolver;
import javax.el.ExpressionFactory;
import javax.enterprise.context.ContextNotActiveException;
import javax.enterprise.context.spi.Context;
import javax.enterprise.context.spi.Contextual;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.AmbiguousResolutionException;
import javax.enterprise.inject.InjectionException;
import javax.enterprise.inject.UnproxyableResolutionException;
import javax.enterprise.inject.UnsatisfiedResolutionException;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.Decorator;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.enterprise.inject.spi.InterceptionType;
import javax.enterprise.inject.spi.Interceptor;
import javax.enterprise.inject.spi.ObserverMethod;
import javax.enterprise.inject.spi.PassivationCapable;
import javax.inject.Qualifier;

import org.jboss.interceptor.registry.InterceptorRegistry;
import org.jboss.weld.bean.DecoratorImpl;
import org.jboss.weld.bean.InterceptorImpl;
import org.jboss.weld.bean.SessionBean;
import org.jboss.weld.bean.proxy.ClientProxyProvider;
import org.jboss.weld.bootstrap.api.ServiceRegistry;
import org.jboss.weld.context.CreationalContextImpl;
import org.jboss.weld.context.WeldCreationalContext;
import org.jboss.weld.context.SerializableContextual;
import org.jboss.weld.ejb.EjbDescriptors;
import org.jboss.weld.ejb.spi.EjbDescriptor;
import org.jboss.weld.el.Namespace;
import org.jboss.weld.el.WeldELResolver;
import org.jboss.weld.el.WeldExpressionFactory;
import org.jboss.weld.introspector.WeldAnnotated;
import org.jboss.weld.literal.AnyLiteral;
import org.jboss.weld.literal.DefaultLiteral;
import org.jboss.weld.log.Log;
import org.jboss.weld.log.Logging;
import org.jboss.weld.manager.api.WeldManager;
import org.jboss.weld.metadata.cache.MetaAnnotationStore;
import org.jboss.weld.metadata.cache.ScopeModel;
import org.jboss.weld.resolution.NameBasedResolver;
import org.jboss.weld.resolution.Resolvable;
import org.jboss.weld.resolution.ResolvableFactory;
import org.jboss.weld.resolution.ResolvableWeldClass;
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.resolution.TypeSafeResolver;
import org.jboss.weld.resources.ClassTransformer;
import org.jboss.weld.util.Beans;
import org.jboss.weld.util.Observers;
import org.jboss.weld.util.Proxies;
import org.jboss.weld.util.Reflections;

import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Multimaps;

/**
 * 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
 */
public class BeanManagerImpl implements WeldManager, Serializable
{


   private static class CurrentActivity
   {
	
      private final Context context;
      private final BeanManagerImpl manager;
		
      public CurrentActivity(Context context, BeanManagerImpl manager)
      {
         this.context = context;
         this.manager = manager;
      }

      public Context getContext()
      {
         return context;
      }
      
      public BeanManagerImpl getManager()
      {
         return manager;
      }
      
      @Override
      public boolean equals(Object obj)
      {
         if (obj instanceof CurrentActivity)
         {
            return this.getContext().equals(((CurrentActivity) obj).getContext());
         }
         else
         {
            return false;
         }
      }
      
      @Override
      public int hashCode()
      {
         return getContext().hashCode();
      }
      
      @Override
      public String toString()
      {
         return getContext() + " -> " + getManager();
      }
   }
   
   private static final Log log = Logging.getLog(BeanManagerImpl.class);

   private static final long serialVersionUID = 3021562879133838561L;

   // The JNDI key to place the manager under
   public static final String JNDI_KEY = "java:app/Manager";
   
   /*
    * Application scoped services 
    * ***************************
    */
   private transient final ServiceRegistry services;

   /*
    * Application scoped data structures 
    * ***********************************
    */
   
   // Contexts are shared across the application
   private transient final ListMultimap, Context> contexts;
   
   // Client proxies can be used application wide
   private transient final ClientProxyProvider clientProxyProvider;
   
   // TODO review this structure
   private transient final Map, SessionBean> enterpriseBeans;
   
   // TODO This isn't right, specialization should follow accessibility rules, but I think we can enforce these in resolve()
   private transient final Map, Contextual> specializedBeans;
   
   /*
    * 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 Collection> enabledPolicyClasses;
   private transient Collection> enabledPolicyStereotypes;
   private transient List> enabledDecoratorClasses;
   private transient List> enabledInterceptorClasses;
   private transient final Set currentActivities;   

   /*
    * Activity scoped services 
    * *************************
    */ 
   
   /* These services are scoped to this activity only, but use data 
    * structures that are transitive accessible from other bean deployment 
    * archives
    */
   private transient final TypeSafeBeanResolver> beanResolver;
   private transient final TypeSafeResolver> decoratorResolver;
   private transient final TypeSafeResolver> interceptorResolver;
   private transient final TypeSafeResolver> observerResolver;
   private transient final NameBasedResolver nameBasedResolver;
   private transient final ELResolver weldELResolver;
   private transient Namespace rootNamespace;

   /*
    * Activity scoped data structures 
    * ********************************
    */
    
   /* These data structures are scoped to this bean deployment archive activity
    * only and represent the beans, decorators, interceptors, namespaces and 
    * observers deployed in this bean deployment archive activity
    */
   private transient final List> beans;
   private transient final List> decorators;
   private transient final List> interceptors;
   private transient final List namespaces;
   private transient final List> observers;
   
   /*
    * These data structures represent the managers *accessible* from this bean 
    * deployment archive activity
    */
   private transient final HashSet accessibleManagers;
   
   /*
    * This data structures represents child activities for this activity, it is
    * not transitively accessible
    */
   private transient final Set childActivities;
   
   private final AtomicInteger childIds;
   private final String id;
   
   /*
    * Runtime data transfer
    * *********************
    */
   private transient final ThreadLocal> currentInjectionPoint;

   /**
    * Interception model
    */
   private transient final InterceptorRegistry, SerializableContextual, ?>> boundInterceptorsRegistry = new InterceptorRegistry, SerializableContextual,?>>();
   private transient final InterceptorRegistry, Class> declaredInterceptorsRegistry = new InterceptorRegistry, Class>();

   /**
    * Create a new, root, manager
    * 
    * @param serviceRegistry
    * @return
    */
   public static BeanManagerImpl newRootManager(String id, ServiceRegistry serviceRegistry)
   {  
      ListMultimap, Context> contexts = Multimaps.newListMultimap(new ConcurrentHashMap, Collection>(), new Supplier>() 
      {
         
         public List get()
         {
            return new CopyOnWriteArrayList();
         }
         
      });

      return new BeanManagerImpl(
            serviceRegistry, 
            new CopyOnWriteArrayList>(),
            new CopyOnWriteArrayList>(),
            new CopyOnWriteArrayList>(),
            new CopyOnWriteArrayList>(),
            new CopyOnWriteArrayList(),
            new ConcurrentHashMap, SessionBean>(),
            new ClientProxyProvider(),
            contexts, 
            new CopyOnWriteArraySet(), 
            new HashMap, Contextual>(), 
            new ArrayList>(),
            new ArrayList>(),
            new ArrayList>(),
            new ArrayList>(), 
            id,
            new AtomicInteger());
   }
   
   /**
    * Create a new, root, manager
    * 
    * @param serviceRegistry
    * @return
    */
   public static BeanManagerImpl newManager(BeanManagerImpl rootManager, String id, ServiceRegistry services)
   {  
      return new BeanManagerImpl(
            services, 
            new CopyOnWriteArrayList>(),
            new CopyOnWriteArrayList>(),
            new CopyOnWriteArrayList>(),
            new CopyOnWriteArrayList>(),
            new CopyOnWriteArrayList(),
            rootManager.getEnterpriseBeans(),
            rootManager.getClientProxyProvider(),
            rootManager.getContexts(), 
            new CopyOnWriteArraySet(), 
            new HashMap, Contextual>(), 
            new ArrayList>(),
            new ArrayList>(),
            new ArrayList>(),
            new ArrayList>(),
            id,
            new AtomicInteger());
   }

   /**
    * Create a new child manager
    * 
    * @param parentManager
    * @return
    */
   public static BeanManagerImpl newChildActivityManager(BeanManagerImpl parentManager)
   {
      List> beans = new CopyOnWriteArrayList>();
      beans.addAll(parentManager.getBeans());
      
      List> registeredObservers = new CopyOnWriteArrayList>();
      registeredObservers.addAll(parentManager.getObservers());
      List namespaces = new CopyOnWriteArrayList();
      namespaces.addAll(parentManager.getNamespaces());

      return new BeanManagerImpl(
            parentManager.getServices(), 
            beans, 
            parentManager.getDecorators(),
            parentManager.getInterceptors(),
            registeredObservers, 
            namespaces, 
            parentManager.getEnterpriseBeans(),  
            parentManager.getClientProxyProvider(), 
            parentManager.getContexts(), 
            parentManager.getCurrentActivities(), 
            parentManager.getSpecializedBeans(),
            parentManager.getEnabledPolicyClasses(),
            parentManager.getEnabledPolicyStereotypes(),
            parentManager.getEnabledDecoratorClasses(),
            parentManager.getEnabledInterceptorClasses(),
            new StringBuilder().append(parentManager.getChildIds().incrementAndGet()).toString(),
            parentManager.getChildIds());
   }

   /**
    * Create a new manager
    * @param enabledDecoratorClasses 
    * 
    * @param ejbServices the ejbResolver to use
    */
   private BeanManagerImpl(
         ServiceRegistry serviceRegistry, 
         List> beans, 
         List> decorators,
         List> interceptors,
         List> observers, 
         List namespaces,
         Map, SessionBean> enterpriseBeans, 
         ClientProxyProvider clientProxyProvider, 
         ListMultimap, Context> contexts, 
         Set currentActivities, 
         Map, Contextual> specializedBeans, 
         Collection> enabledPolicyClasses,
         Collection> enabledPolicyStereotypes,
         List> enabledDecoratorClasses,
         List> enabledInterceptorClasses,
         String id,
         AtomicInteger childIds)
   {
      this.services = serviceRegistry;
      this.beans = beans;
      this.decorators = decorators;
      this.interceptors = interceptors;
      this.enterpriseBeans = enterpriseBeans;
      this.clientProxyProvider = clientProxyProvider;
      this.contexts = contexts;
      this.currentActivities = currentActivities;
      this.specializedBeans = specializedBeans;
      this.observers = observers;
      this.enabledPolicyClasses = enabledPolicyClasses;
      this.enabledPolicyStereotypes = enabledPolicyStereotypes;
      setEnabledDecoratorClasses(enabledDecoratorClasses);
      setEnabledInterceptorClasses(enabledInterceptorClasses);
      this.namespaces = namespaces;
      this.id = id;
      this.childIds = new AtomicInteger();
      
      // Set up the structure to store accessible managers in
      this.accessibleManagers = new HashSet();
      
      

      // TODO Currently we build the accessible bean list on the fly, we need to set it in stone once bootstrap is finished...
      this.beanResolver = new TypeSafeBeanResolver>(this, createDynamicAccessibleIterable(Transform.BEAN));
      this.decoratorResolver = new TypeSafeDecoratorResolver(this, createDynamicAccessibleIterable(Transform.DECORATOR_BEAN));
      this.interceptorResolver = new TypeSafeInterceptorResolver(this, createDynamicAccessibleIterable(Transform.INTERCEPTOR_BEAN));
      this.observerResolver = new TypeSafeObserverResolver(this, createDynamicAccessibleIterable(Transform.EVENT_OBSERVER));
      this.nameBasedResolver = new NameBasedResolver(this, createDynamicAccessibleIterable(Transform.BEAN));
      this.weldELResolver = new WeldELResolver(this);
      this.childActivities = new CopyOnWriteArraySet();
      
      this.currentInjectionPoint = new ThreadLocal>()
      {
         @Override
         protected Stack initialValue()
         {
            return new Stack();
         }
      };
   }
   
   private  Set> buildAccessibleClosure(Collection hierarchy, Transform transform)
   {
      Set> result = new HashSet>();
      hierarchy.add(this);
      result.add(transform.transform(this));
      for (BeanManagerImpl beanManager : accessibleManagers)
      {
         // Only add if we aren't already in the tree (remove cycles)
         if (!hierarchy.contains(beanManager))
         {
            result.addAll(beanManager.buildAccessibleClosure(new ArrayList(hierarchy), transform));
         }
      }
      return result;
   }
   
   private  Iterable createDynamicAccessibleIterable(final Transform transform)
   {
      return new Iterable()
      {
         
         private Function, Iterator> function = new Function, Iterator>()
         {

            public Iterator apply(Iterable iterable)
            {
               return iterable.iterator();
            }
            
         };

         public Iterator iterator()
         {
            Set> iterable = buildAccessibleClosure(new ArrayList(), transform);
            return Iterators.concat(Iterators.transform(iterable.iterator(), function));
         }
         
      };
   }
   
   private  Iterable createStaticAccessibleIterable(final Transform transform)
   {
      Set> iterable = buildAccessibleClosure(new ArrayList(), transform);
      return Iterables.concat(iterable); 
   }
   
   private static interface Transform
   {
      
      public static Transform> BEAN = new Transform>()
      {

         public Iterable> transform(BeanManagerImpl beanManager)
         {
            return beanManager.getBeans();
         }
         
      };
      
      public static Transform> DECORATOR_BEAN = new Transform>()
      {

         public Iterable> transform(BeanManagerImpl beanManager)
         {
            return beanManager.getDecorators();
         }
         
      };

      public static Transform> INTERCEPTOR_BEAN = new Transform>()
      {

         public Iterable> transform(BeanManagerImpl beanManager)
         {
            return beanManager.getInterceptors();
         }

      };
      
      public static Transform> EVENT_OBSERVER = new Transform>()
      {

         public Iterable> transform(BeanManagerImpl beanManager)
         {
            return beanManager.getObservers();
         }
         
      };
      
      public static Transform NAMESPACE = new Transform()
      {

         public Iterable transform(BeanManagerImpl beanManager)
         {
            return beanManager.getNamespaces();
         }
         
      };
      
      public Iterable transform(BeanManagerImpl beanManager);
      
   }
   
   public void addAccessibleBeanManager(BeanManagerImpl accessibleBeanManager)
   {
      accessibleManagers.add(accessibleBeanManager);
      beanResolver.clear();
   }
   
   protected Set getAccessibleManagers()
   {

      return accessibleManagers;
   }

   public void addBean(Bean bean)
   {
      if (beans.contains(bean))
      {
         return;
      }
      if (bean.getClass().equals(SessionBean.class))
      {
         SessionBean enterpriseBean = (SessionBean) bean;
         enterpriseBeans.put(enterpriseBean.getEjbDescriptor(), enterpriseBean);
      }
      if (bean instanceof PassivationCapable)
      {
         Container.instance().deploymentServices().get(ContextualStore.class).putIfAbsent(bean);
      }
      registerBeanNamespace(bean);
      for (BeanManagerImpl childActivity : childActivities)
      {
         childActivity.addBean(bean);
      }
      this.beans.add(bean);
      beanResolver.clear();
   }
   
   public void addDecorator(DecoratorImpl bean)
   {
      decorators.add(bean);
      getServices().get(ContextualStore.class).putIfAbsent(bean);
      decoratorResolver.clear();
   }
   
   public  Set> resolveObserverMethods(T event, Annotation... bindings)
   {
      Observers.checkEventObjectType(event);
      return resolveObserverMethods(event.getClass(), bindings);
   }

   public void addInterceptor(InterceptorImpl bean)
   {
      interceptors.add(bean);
      //TODO decide if interceptor is passivationCapable
      interceptorResolver.clear();
   }


   @SuppressWarnings("unchecked")
   private  Set> resolveObserverMethods(Type eventType, Annotation... bindings)
   {
      checkBindingTypes(Arrays.asList(bindings));
      
      // Manually hack in the default annotations here. We need to redo all the annotation defaulting throughout. PLM
      HashSet bindingAnnotations = new HashSet(Arrays.asList(bindings));
      if (bindingAnnotations.size() == 0)
      {
         bindingAnnotations.add(new DefaultLiteral());
      }
      bindingAnnotations.add(new AnyLiteral());
      Set> observers = new HashSet>();
      Set> eventObservers = observerResolver.resolve(ResolvableFactory.of(new Reflections.HierarchyDiscovery(eventType).getFlattenedTypes(),  bindingAnnotations, null));
      for (ObserverMethod observer : eventObservers)
      {
         observers.add((ObserverMethod) observer);
      }
      return observers;
   }
   
   private void checkBindingTypes(Collection bindings)
   {
      HashSet bindingAnnotations = new HashSet(bindings);
      for (Annotation annotation : bindings)
      {
         if (!getServices().get(MetaAnnotationStore.class).getBindingTypeModel(annotation.annotationType()).isValid())
         {
            throw new IllegalArgumentException("Not a binding type " + annotation);
         }
      }
      if (bindingAnnotations.size() < bindings.size())
      {
         throw new IllegalArgumentException("Duplicate binding types: " + bindings);
      }

   }

   /**
    * A collection of enabled policy classes
    * 
    */
   public Collection> getEnabledPolicyClasses()
   {
      return Collections.unmodifiableCollection(enabledPolicyClasses);
   }
   
   /**
    * @return the enabledPolicySterotypes
    */
   public Collection> getEnabledPolicyStereotypes()
   {
      return Collections.unmodifiableCollection(enabledPolicyStereotypes);
   }
   
   public boolean isBeanEnabled(Bean bean)
   {
      return Beans.isBeanEnabled(bean, getEnabledPolicyClasses(), getEnabledPolicyStereotypes());   
   }

   /**
    * @return the enabledDecoratorClasses
    */
   public List> getEnabledDecoratorClasses()
   {
      return Collections.unmodifiableList(enabledDecoratorClasses);
   }
   
   /**
    * @return the enabledInterceptorClasses
    */
   public List> getEnabledInterceptorClasses()
   {
      return Collections.unmodifiableList(enabledInterceptorClasses);
   }

   public void setEnabledPolicyClasses(Collection> enabledPolicyClasses)
   {
      this.enabledPolicyClasses = enabledPolicyClasses;
   }
   
   public void setEnabledPolicyStereotypes(Collection> enabledPolicySterotypes)
   {
      this.enabledPolicyStereotypes = enabledPolicySterotypes;
   }
   
   public void setEnabledDecoratorClasses(List> enabledDecoratorClasses)
   {
      this.enabledDecoratorClasses = enabledDecoratorClasses;
   }
   
   public void setEnabledInterceptorClasses(List> enabledInterceptorClasses)
   {
      this.enabledInterceptorClasses = enabledInterceptorClasses;
   }
   
   public Set> getBeans(Type beanType, Annotation... bindings)
   {
      return getBeans(ResolvableWeldClass.of(beanType, bindings, this), bindings);
   }
   
   public Set> getBeans(WeldAnnotated element, Annotation... bindings)
   {
      for (Annotation annotation : element.getAnnotations())
      {
         if (!getServices().get(MetaAnnotationStore.class).getBindingTypeModel(annotation.annotationType()).isValid())
         {
            throw new IllegalArgumentException("Not a binding type " + annotation);
         }
      }
//      for (Type type : element.getActualTypeArguments())
//      {
//         if (type instanceof WildcardType)
//         {
//            throw new IllegalArgumentException("Cannot resolve a type parameterized with a wildcard " + element);
//         }
//         if (type instanceof TypeVariable)
//         {
//            throw new IllegalArgumentException("Cannot resolve a type parameterized with a type parameter " + element);
//         }
//      }
      if (bindings != null && bindings.length > element.getMetaAnnotations(Qualifier.class).size())
      {
         throw new IllegalArgumentException("Duplicate bindings (" + Arrays.asList(bindings) + ") type passed " + element.toString());
      }
      return beanResolver.resolve(ResolvableFactory.of(element));
   }

   public Set> getInjectableBeans(InjectionPoint injectionPoint)
   {
      boolean registerInjectionPoint = !injectionPoint.getType().equals(InjectionPoint.class);
      try
      {
         if (registerInjectionPoint)
         {
            currentInjectionPoint.get().push(injectionPoint);
         }
         // TODO Do this properly
         Set> beans = getBeans(ResolvableWeldClass.of(injectionPoint.getType(), injectionPoint.getQualifiers().toArray(new Annotation[0]), this));
         Set> injectableBeans = new HashSet>();
         for (Bean bean : beans)
         {
            if (!(bean instanceof Decorator || bean instanceof Interceptor))
            {
               injectableBeans.add(bean);
            }
         }
         return injectableBeans;
      }
      finally
      {
         if (registerInjectionPoint)
         {
            currentInjectionPoint.get().pop();
         }
      }
   }
   
   protected void registerBeanNamespace(Bean bean)
   {
      if (bean.getName() != null && bean.getName().indexOf('.') > 0)
      {
         namespaces.add(bean.getName().substring(0, bean.getName().lastIndexOf('.')));
      }
   }

   /**
    * 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 Collections.unmodifiableList(beans);
   }
   
   public List> getDecorators()
   {
      return Collections.unmodifiableList(decorators);
   }

    public List> getInterceptors()
   {
      return Collections.unmodifiableList(interceptors);
   }
   
   public Iterable> getAccessibleBeans()
   {
      return createDynamicAccessibleIterable(Transform.BEAN);
   }

   public void addContext(Context context)
   {
      contexts.put(context.getScope(), context);
   }

   /**
    * Does the actual observer registration
    * 
    * @param observer
=    */
   public void addObserver(ObserverMethod observer)
   {
      //checkEventType(observer.getObservedType());
      observers.add(observer);
      log.trace("Added observer " + observer);
      for (BeanManagerImpl childActivity : childActivities)
      {
         childActivity.addObserver(observer);
      }
   }
   
   /**
    * Fires an event object with given event object for given bindings
    * 
    * @param event The event object to pass along
    * @param bindings The binding types to match
    * 
    * @see javax.enterprise.inject.spi.BeanManager#fireEvent(java.lang.Object,
    *      java.lang.annotation.Annotation[])
    */
   public void fireEvent(Object event, Annotation... qualifiers)
   {
      fireEvent(event.getClass(), event, qualifiers);
   }
   
   public void fireEvent(Type eventType, Object event, Annotation... qualifiers)
   {
      Observers.checkEventObjectType(event);
      notifyObservers(event, resolveObserverMethods(eventType, qualifiers));
   }

   private  void notifyObservers(final T event, final Set> observers)
   {
      for (ObserverMethod observer : observers)
      {
         observer.notify(event);
      }     
   }

   /**
    * 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
    * 
    * @param scopeType The scope to match
    * @return A single active context of the given scope
    * 
    * @see javax.enterprise.inject.spi.BeanManager#getContext(java.lang.Class)
    */
   public Context getContext(Class scopeType)
   {
      List activeContexts = new ArrayList();
      for (Context context : contexts.get(scopeType))
      {
         if (context.isActive())
         {
            activeContexts.add(context);
         }
      }
      if (activeContexts.isEmpty())
      {
         throw new ContextNotActiveException("No active contexts for scope type " + scopeType.getName());
      }
      if (activeContexts.size() > 1)
      {
         throw new IllegalStateException("More than one context active for scope type " + scopeType.getName());
      }
      return activeContexts.iterator().next();

   }
   
   public Object getReference(Bean bean, CreationalContext creationalContext)
   {
      bean = getMostSpecializedBean(bean);
      if (creationalContext instanceof WeldCreationalContext)
      {
         creationalContext = ((WeldCreationalContext) creationalContext).getCreationalContext(bean);
      }
      if (getServices().get(MetaAnnotationStore.class).getScopeModel(bean.getScope()).isNormal())
      {
         if (creationalContext != null || getContext(bean.getScope()).get(bean) != null)
         {
            return clientProxyProvider.getClientProxy(this, bean);
         }
         else
         {
            return null;
         }
      }
      else
      {
         return getContext(bean.getScope()).get((Contextual) bean, creationalContext);
      }
   }

   public Object getReference(Bean bean, Type beanType, CreationalContext creationalContext)
   {
      
      if (!Reflections.isAssignableFrom(bean.getTypes(), beanType))
      {
         throw new IllegalArgumentException("The given beanType is not a type " + beanType +" of the bean " + bean );
      }
      return getReference(bean, creationalContext);
   }

   
   /**
    * 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
    */
   public Object getReference(InjectionPoint injectionPoint, Bean resolvedBean, CreationalContext creationalContext)
   {
      boolean registerInjectionPoint = (injectionPoint != null && !injectionPoint.getType().equals(InjectionPoint.class));
      try
      {
         if (registerInjectionPoint)
         {
            currentInjectionPoint.get().push(injectionPoint);
         }
         if (getServices().get(MetaAnnotationStore.class).getScopeModel(resolvedBean.getScope()).isNormal() && !Proxies.isTypeProxyable(injectionPoint.getType()))
         {
            throw new UnproxyableResolutionException("Attempting to inject an unproxyable normal scoped bean " + resolvedBean + " into " + injectionPoint);
         }
         // TODO Can we move this logic to getReference?
         if (creationalContext instanceof WeldCreationalContext)
         {
            WeldCreationalContext wbCreationalContext = (WeldCreationalContext) creationalContext;
            if (wbCreationalContext.containsIncompleteInstance(resolvedBean))
            {
               return wbCreationalContext.getIncompleteInstance(resolvedBean);
            }
            else
            {
               return getReference(resolvedBean, wbCreationalContext);
            }
         }
         else
         {
            return getReference(resolvedBean, creationalContext);
         }
      }
      finally
      {
         if (registerInjectionPoint)
         {
            currentInjectionPoint.get().pop();
         }
      }
   }
  
   
   public Object getInjectableReference(InjectionPoint injectionPoint, CreationalContext creationalContext)
   {
      WeldAnnotated element = ResolvableWeldClass.of(injectionPoint.getType(), injectionPoint.getQualifiers().toArray(new Annotation[0]), this);
      Bean resolvedBean = getBean(element, element.getBindingsAsArray());
      return getReference(injectionPoint, resolvedBean, creationalContext);
   }

   /**
    * Returns an instance by API type and binding types
    * 
    * @param beanType The API type to match
    * @param bindings The binding types to match
    * @return An instance of the bean
    * 
    */
   @Deprecated
   public  T getInstanceByType(Class beanType, Annotation... bindings)
   {
      Set> beans = getBeans(beanType, bindings);
      Bean bean = resolve(beans);
      Object reference = getReference(bean, beanType, createCreationalContext(bean));
      
      @SuppressWarnings("unchecked")
      T instance = (T) reference;
      
      return instance;
   }

   public  Bean getBean(WeldAnnotated element, Annotation... bindings)
   {
      Bean bean = (Bean) resolve(getBeans(element, bindings));
      if (bean == null)
      {
         throw new UnsatisfiedResolutionException(element + "Unable to resolve any Managed Beans");
      }
      
      boolean normalScoped = getServices().get(MetaAnnotationStore.class).getScopeModel(bean.getScope()).isNormal();
      if (normalScoped && !Beans.isBeanProxyable(bean))
      {
         throw new UnproxyableResolutionException("Normal scoped bean " + bean + " is not proxyable");
      }
      return bean;
   }

   public Set> getBeans(String name)
   {
      return nameBasedResolver.resolve(name);
   }

   /**
    * Resolves a list of decorators based on API types and binding types
    * 
    * @param types The set of API types to match
    * @param bindings The binding types to match
    * @return A list of matching decorators
    * 
    * @see javax.enterprise.inject.spi.BeanManager#resolveDecorators(java.util.Set,
    *      java.lang.annotation.Annotation[])
    */
   public List> resolveDecorators(Set types, Annotation... bindings)
   {
      checkResolveDecoratorsArguments(types, Arrays.asList(bindings));
      // TODO Fix this cast and make the resolver return a list
      return new ArrayList>(decoratorResolver.resolve(ResolvableFactory.of(types, null, bindings)));
   }
   
   public List> resolveDecorators(Set types, Set bindings)
   {
      checkResolveDecoratorsArguments(types, bindings);
      // TODO Fix this cast and make the resolver return a list
      return new ArrayList>(decoratorResolver.resolve(ResolvableFactory.of(types, bindings, null)));
   }

   private void checkResolveDecoratorsArguments(Set types, Collection bindings)
   {
      if (types.isEmpty())
      {
         throw new IllegalArgumentException("No decorator types were specified in the set");
      }
      checkBindingTypes(bindings);
   }

   /**
    * Resolves a list of interceptors based on interception type and interceptor
    * bindings
    * 
    * @param type The interception type to resolve
    * @param interceptorBindings The binding types to match
    * @return A list of matching interceptors
    * 
    * @see javax.enterprise.inject.spi.BeanManager#resolveInterceptors(javax.enterprise.inject.spi.InterceptionType,
    *      java.lang.annotation.Annotation[])
    */
   public List> resolveInterceptors(InterceptionType type, Annotation... interceptorBindings)
   {
      return new ArrayList>(interceptorResolver.resolve(ResolvableFactory.of(type,interceptorBindings)));
   }

   /**
    * Get the web bean resolver. For internal use
    * 
    * @return The resolver
    */
   public TypeSafeBeanResolver> getBeanResolver()
   {
      return beanResolver;
   }

   /**
    * Gets a string representation
    * 
    * @return A string representation
    */
   @Override
   public String toString()
   {
      StringBuilder buffer = new StringBuilder();
      buffer.append("Manager\n");
      buffer.append("Enabled policies: " + getEnabledPolicyClasses() + " " + getEnabledPolicyStereotypes() + "\n");
      buffer.append("Registered contexts: " + contexts.keySet() + "\n");
      buffer.append("Registered beans: " + getBeans().size() + "\n");
      buffer.append("Specialized beans: " + specializedBeans.size() + "\n");
      return buffer.toString();
   }

   public BeanManagerImpl createActivity()
   {
      BeanManagerImpl childActivity = newChildActivityManager(this);
      childActivities.add(childActivity);
      Container.instance().addActivity(childActivity);
      return childActivity;
   }

   public BeanManagerImpl setCurrent(Class scopeType)
   {
      if (!getServices().get(MetaAnnotationStore.class).getScopeModel(scopeType).isNormal())
      {
         throw new IllegalArgumentException("Scope must be a normal scope type " + scopeType);
      }
      currentActivities.add(new CurrentActivity(getContext(scopeType), this));
      return this;
   }
   
   public BeanManagerImpl getCurrent()
   {
      List activeCurrentActivities = new ArrayList();
      for (CurrentActivity currentActivity : currentActivities)
      {
         if (currentActivity.getContext().isActive())
         {
            activeCurrentActivities.add(currentActivity);
         }
      }
      if (activeCurrentActivities.size() == 0)
      {
         return this;
      }
      else if (activeCurrentActivities.size() == 1)
      {
         return activeCurrentActivities.get(0).getManager();
      }
      throw new IllegalStateException("More than one current activity for an active context " + currentActivities);
   }

   public ServiceRegistry getServices()
   {
      return services;
   }

   /**
    * The injection point being operated on for this thread
    * 
    * @return the current injection point
    */
   public InjectionPoint getCurrentInjectionPoint()
   {
      if (!currentInjectionPoint.get().empty())
      {
         return currentInjectionPoint.get().peek();
      }
      else
      {
         return null;
      }
   }
   
   /**
    * Replaces (or adds) the current injection point. If a current injection 
    * point exists, it will be replaced. If no current injection point exists, 
    * one will be added.
    * 
    * @param injectionPoint the injection point to use
    * @return the injection point added, or null if non previous existed
    */
   public InjectionPoint replaceOrPushCurrentInjectionPoint(InjectionPoint injectionPoint)
   {
      InjectionPoint originalInjectionPoint = null;
      if (!currentInjectionPoint.get().empty())
      {
         originalInjectionPoint = currentInjectionPoint.get().pop();
      }
      else
      {
         log.trace("No current injection point to replace #0", injectionPoint);
      }
      currentInjectionPoint.get().push(injectionPoint);
      return originalInjectionPoint;
   }

   /**
    * 
    * @return
    */
   public Map, Contextual> getSpecializedBeans()
   {
      // TODO make this unmodifiable after deploy!
      return specializedBeans;
   }

   // Serialization

   protected Object readResolve()
   {
      return Container.instance().activityManager(id);
   }
   
   protected ClientProxyProvider getClientProxyProvider()
   {
      return clientProxyProvider;
   }
   
   protected ListMultimap, Context> getContexts()
   {
      return contexts;
   }
   
   /**
    * @return the namespaces
    */
   protected List getNamespaces()
   {
      return namespaces;
   }
   
   public Iterable getAccessibleNamespaces()
   {
      // TODO Cache this
      return createDynamicAccessibleIterable(Transform.NAMESPACE);
   }
   
   private Set getCurrentActivities()
   {
      return currentActivities;
   }
   
   public String getId()
   {
      return id;
   }
   
   public AtomicInteger getChildIds()
   {
      return childIds;
   }
   
   public List> getObservers()
   {
      return observers;
   }
   
   public Namespace getRootNamespace()
   {
      // TODO I don't like this lazy init
      if (rootNamespace == null)
      {
         rootNamespace = new Namespace(createDynamicAccessibleIterable(Transform.NAMESPACE));
      }
      return rootNamespace;
   }

   public  InjectionTarget createInjectionTarget(AnnotatedType type)
   {
      return new SimpleInjectionTarget(getServices().get(ClassTransformer.class).loadClass(type), this);
   }
   
   public  InjectionTarget createInjectionTarget(EjbDescriptor descriptor)
   {
      return getBean(descriptor).getInjectionTarget();
   }

   public  Bean getMostSpecializedBean(Bean bean)
   {
      Contextual key = bean;
      while (specializedBeans.containsKey(key))
      {
         if (key == null)
         {
            System.out.println("null key " + bean);
         }
         key = specializedBeans.get(key);
      }
      return (Bean) key;
   }

   public void validate(InjectionPoint ij)
   {
      try
      {
         getServices().get(Validator.class).validateInjectionPoint(ij, this);
      }
      catch (DeploymentException e) 
      {
         throw new InjectionException(e.getMessage(), e.getCause());
      }
   }

   public Set getInterceptorBindingTypeDefinition(Class bindingType)
   {
      if (getServices().get(MetaAnnotationStore.class).getInterceptorBindingModel(bindingType).isValid())
      {
         return getServices().get(MetaAnnotationStore.class).getInterceptorBindingModel(bindingType).getInheritedInterceptionBindingTypes();
      }
      else
      {
         throw new IllegalArgumentException("Not a interception binding :" + bindingType);
      }
   }

   public Bean getPassivationCapableBean(String id)
   {
      return getServices().get(ContextualStore.class)., Object>getContextual(id);
   }

   public Set getStereotypeDefinition(Class stereotype)
   {
      if (getServices().get(MetaAnnotationStore.class).getStereotype(stereotype).isValid())
      {
         return getServices().get(MetaAnnotationStore.class).getStereotype(stereotype).getMetaAnnotations();
      }
      else
      {
         throw new IllegalArgumentException("Not a stereotype " + stereotype);
      }
   }

   public boolean isQualifier(Class annotationType)
   {
      return getServices().get(MetaAnnotationStore.class).getBindingTypeModel(annotationType).isValid();
   }

   public boolean isInterceptorBindingType(Class annotationType)
   {
      return getServices().get(MetaAnnotationStore.class).getInterceptorBindingModel(annotationType).isValid();
   }

   public boolean isNormalScope(Class annotationType)
   {
      ScopeModel scope = getServices().get(MetaAnnotationStore.class).getScopeModel(annotationType);
      return scope.isValid() && scope.isNormal(); 
   }
   
   public boolean isPassivatingScope(Class annotationType)
   {
      ScopeModel scope = getServices().get(MetaAnnotationStore.class).getScopeModel(annotationType);
      return scope.isValid() && scope.isPassivating();
   }
   
   public boolean isScope(Class annotationType)
   {
      return getServices().get(MetaAnnotationStore.class).getScopeModel(annotationType).isValid();
   }

   public boolean isStereotype(Class annotationType)
   {
      return getServices().get(MetaAnnotationStore.class).getStereotype(annotationType).isValid();
   }

   public ELResolver getELResolver()
   {
      return weldELResolver;
   }
   
   public ExpressionFactory wrapExpressionFactory(ExpressionFactory expressionFactory)
   {
      return new WeldExpressionFactory(expressionFactory);
   }
   
   public  WeldCreationalContext createCreationalContext(Contextual contextual)
   {
      return new CreationalContextImpl(contextual);
   }

   public  AnnotatedType createAnnotatedType(Class type)
   {
      return getServices().get(ClassTransformer.class).loadClass(type);
   }

   public  Bean resolve(Set> beans)
   {
      Set> resolvedBeans = beanResolver.resolve(beans);
      if (resolvedBeans.size() == 0)
      {
         return null;
      }
      if (resolvedBeans.size() == 1)
      {
         return resolvedBeans.iterator().next();
      }
      else
      {
         throw new AmbiguousResolutionException("Cannot resolve an ambiguous dependency between " + beans);
      }
   }

   public  EjbDescriptor getEjbDescriptor(String beanName)
   {
      return getServices().get(EjbDescriptors.class).get(beanName);
   }
   
   public  SessionBean getBean(EjbDescriptor descriptor)
   {
      return (SessionBean) getEnterpriseBeans().get(descriptor);
   }
   
   public void cleanup()
   {
      services.cleanup();
      this.currentInjectionPoint.remove();
   }

   public InterceptorRegistry, SerializableContextual, ?>> getBoundInterceptorsRegistry()
   {
      return boundInterceptorsRegistry;
   }

   public InterceptorRegistry, Class> getDeclaredInterceptorsRegistry()
   {
      return declaredInterceptorsRegistry;
   }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy