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

org.jboss.weld.bootstrap.BeanDeployerEnvironment Maven / Gradle / Ivy

There is a newer version: 3.0.0.Alpha1
Show newest version
/*
 * 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.bootstrap;

import static org.jboss.weld.util.cache.LoadingCacheUtils.getCacheValue;
import static org.jboss.weld.util.reflection.Reflections.cast;

import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import javax.enterprise.event.Event;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.New;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.InjectionPoint;

import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedType;
import org.jboss.weld.annotated.enhanced.MethodSignature;
import org.jboss.weld.annotated.slim.SlimAnnotatedType;
import org.jboss.weld.annotated.slim.SlimAnnotatedTypeContext;
import org.jboss.weld.bean.AbstractBean;
import org.jboss.weld.bean.AbstractClassBean;
import org.jboss.weld.bean.DecoratorImpl;
import org.jboss.weld.bean.DisposalMethod;
import org.jboss.weld.bean.InterceptorImpl;
import org.jboss.weld.bean.ManagedBean;
import org.jboss.weld.bean.NewBean;
import org.jboss.weld.bean.NewManagedBean;
import org.jboss.weld.bean.NewSessionBean;
import org.jboss.weld.bean.ProducerField;
import org.jboss.weld.bean.ProducerMethod;
import org.jboss.weld.bean.RIBean;
import org.jboss.weld.bean.SessionBean;
import org.jboss.weld.bean.builtin.AbstractBuiltInBean;
import org.jboss.weld.bean.builtin.ExtensionBean;
import org.jboss.weld.ejb.EjbDescriptors;
import org.jboss.weld.ejb.InternalEjbDescriptor;
import org.jboss.weld.injection.attributes.WeldInjectionPointAttributes;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.resolution.ResolvableBuilder;
import org.jboss.weld.resolution.TypeSafeDisposerResolver;
import org.jboss.weld.resources.ClassTransformer;
import org.jboss.weld.util.InjectionPoints;
import org.jboss.weld.util.collections.Multimaps;
import org.jboss.weld.util.reflection.Reflections;

import com.google.common.cache.LoadingCache;
import com.google.common.collect.Iterables;

public class BeanDeployerEnvironment {

    private final Set> annotatedTypes;
    private final Set> vetoedClasses;
    private final LoadingCache, Set>> classBeanMap;
    private final LoadingCache>> producerMethodBeanMap;
    private final Set> producerFields;
    private final Set> beans;
    private final Set> observers;
    private final Set> allDisposalBeans;
    private final Set> resolvedDisposalBeans;
    private final Set> decorators;
    private final Set> interceptors;
    private final EjbDescriptors ejbDescriptors;
    private final TypeSafeDisposerResolver disposalMethodResolver;
    private final ClassTransformer classTransformer;
    private final Set> newManagedBeanClasses;
    private final Map, EnhancedAnnotatedType> newSessionBeanDescriptorsFromInjectionPoint;
    private final BeanManagerImpl manager;

    protected BeanDeployerEnvironment(EjbDescriptors ejbDescriptors, BeanManagerImpl manager) {
        this(
                new HashSet>(),
                new HashSet>(),
                Multimaps., AbstractClassBean>newConcurrentSetMultimap(),
                new HashSet>(),
                Multimaps.>newConcurrentSetMultimap(),
                new HashSet>(),
                new HashSet>(),
                new HashSet>(),
                new HashSet>(),
                new HashSet>(),
                new HashSet>(),
                ejbDescriptors,
                new HashSet>(),
                new HashMap, EnhancedAnnotatedType>(),
                manager);
    }

    protected BeanDeployerEnvironment(
            Set> annotatedTypes,
            Set> vetoedClasses,
            LoadingCache, Set>> classBeanMap,
            Set> producerFields,
            LoadingCache>> producerMethodBeanMap,
            Set> beans,
            Set> observers,
            Set> allDisposalBeans,
            Set> resolvedDisposalBeans,
            Set> decorators,
            Set> interceptors,
            EjbDescriptors ejbDescriptors,
            Set> newManagedBeanClasses,
            Map, EnhancedAnnotatedType> newSessionBeanDescriptorsFromInjectionPoint,
            BeanManagerImpl manager) {
        this.annotatedTypes = annotatedTypes;
        this.vetoedClasses = vetoedClasses;
        this.classBeanMap = classBeanMap;
        this.producerFields = producerFields;
        this.producerMethodBeanMap = producerMethodBeanMap;
        this.beans = beans;
        this.observers = observers;
        this.allDisposalBeans = allDisposalBeans;
        this.resolvedDisposalBeans = resolvedDisposalBeans;
        this.decorators = decorators;
        this.interceptors = interceptors;
        this.ejbDescriptors = ejbDescriptors;
        this.disposalMethodResolver = new TypeSafeDisposerResolver(allDisposalBeans);
        this.classTransformer = manager.getServices().get(ClassTransformer.class);
        this.newManagedBeanClasses = newManagedBeanClasses;
        this.newSessionBeanDescriptorsFromInjectionPoint = newSessionBeanDescriptorsFromInjectionPoint;
        this.manager = manager;
    }

    public void addAnnotatedType(SlimAnnotatedTypeContext annotatedType) {
        this.annotatedTypes.add(annotatedType);
    }

    public void addAnnotatedTypes(Collection> annotatedTypes) {
        this.annotatedTypes.addAll(annotatedTypes);
    }

    public void addSyntheticAnnotatedType(SlimAnnotatedType annotatedType, Extension extension) {
        addAnnotatedType(SlimAnnotatedTypeContext.of(annotatedType, classTransformer, extension));
    }

    public Set> getAnnotatedTypes() {
        return Collections.unmodifiableSet(annotatedTypes);
    }

    public void removeAnnotatedType(SlimAnnotatedTypeContext annotatedType) {
        annotatedTypes.remove(annotatedType);
    }

    public void removeAnnotatedTypes(Collection> annotatedTypes) {
        this.annotatedTypes.removeAll(annotatedTypes);
    }

    public void vetoJavaClass(Class javaClass) {
        vetoedClasses.add(javaClass);
    }

    public boolean isVetoed(Class clazz) {
        return vetoedClasses.contains(clazz);
    }

    public Set> getNewManagedBeanClasses() {
        return newManagedBeanClasses;
    }

    public Map, EnhancedAnnotatedType> getNewSessionBeanDescriptorsFromInjectionPoint() {
        return newSessionBeanDescriptorsFromInjectionPoint;
    }

    public Set> getProducerMethod(Class declaringClass, MethodSignature signature) {
        WeldMethodKey key = new WeldMethodKey(declaringClass, signature);
        Set> beans = getCacheValue(producerMethodBeanMap, key);
        for (ProducerMethod producerMethod : beans) {
            producerMethod.initialize(this);
        }
        return beans;
    }

    public Set> getClassBeans(Class clazz) {
        Set> beans = getCacheValue(classBeanMap, clazz);
        for (AbstractClassBean bean : beans) {
            bean.preInitialize();
        }
        return beans;
    }

    public void addProducerMethod(ProducerMethod bean) {
        getCacheValue(producerMethodBeanMap, WeldMethodKey.of(bean)).add(bean);
        addAbstractBean(bean);
    }

    public void addProducerField(ProducerField bean) {
        producerFields.add(bean);
        addAbstractBean(bean);
    }

    public void addExtension(ExtensionBean bean) {
        beans.add(bean);
    }

    public void addBuiltInBean(AbstractBuiltInBean bean) {
        beans.add(bean);
    }

    protected void addAbstractClassBean(AbstractClassBean bean) {
        if (!(bean instanceof NewBean)) {
            getCacheValue(classBeanMap, bean.getBeanClass()).add(bean);
        }
        addAbstractBean(bean);
    }

    public void addManagedBean(ManagedBean bean) {
        addAbstractClassBean(bean);
    }

    public void addSessionBean(SessionBean bean) {
        addAbstractClassBean(bean);
    }

    public void addNewManagedBean(NewManagedBean bean) {
        beans.add(bean);
    }

    public void addNewSessionBean(NewSessionBean bean) {
        beans.add(bean);
    }

    protected void addAbstractBean(AbstractBean bean) {
        beans.add(bean);
    }

    public void addDecorator(DecoratorImpl bean) {
        decorators.add(bean);
    }

    public void addInterceptor(InterceptorImpl bean) {
        interceptors.add(bean);
    }

    public void addDisposesMethod(DisposalMethod bean) {
        allDisposalBeans.add(bean);
        addNewBeansFromInjectionPoints(bean.getInjectionPoints());
    }

    public void addObserverMethod(ObserverInitializationContext observerInitializer) {
        this.observers.add(observerInitializer);
        addNewBeansFromInjectionPoints(observerInitializer.getObserver().getInjectionPoints());
    }

    public void addNewBeansFromInjectionPoints(AbstractBean bean) {
        addNewBeansFromInjectionPoints(bean.getInjectionPoints());
    }

    public void addNewBeansFromInjectionPoints(Set injectionPoints) {
        for (InjectionPoint injectionPoint : injectionPoints) {
            WeldInjectionPointAttributes weldInjectionPoint = InjectionPoints.getWeldInjectionPoint(injectionPoint);
            if (weldInjectionPoint.getQualifier(New.class) != null) {

                Class rawType = Reflections.getRawType(weldInjectionPoint.getType());
                if (Event.class.equals(rawType)) {
                    continue;
                }
                New _new = weldInjectionPoint.getQualifier(New.class);
                if (_new.value().equals(New.class)) {
                    if (rawType.equals(Instance.class)) {
                        // e.g. @Inject @New(ChequePaymentProcessor.class) Instance chequePaymentProcessor;
                        // see WELD-975
                        Type typeParameter = Reflections.getActualTypeArguments(weldInjectionPoint.getType())[0];
                        addNewBeanFromInjectionPoint(Reflections.getRawType(typeParameter), typeParameter);
                    } else {
                        addNewBeanFromInjectionPoint(rawType, weldInjectionPoint.getType());
                    }
                } else {
                    addNewBeanFromInjectionPoint(_new.value(), _new.value());
                }
            }
        }
    }

    private void addNewBeanFromInjectionPoint(Class rawType, Type baseType) {
        if (getEjbDescriptors().contains(rawType)) {
            InternalEjbDescriptor descriptor = getEjbDescriptors().getUnique(rawType);
            newSessionBeanDescriptorsFromInjectionPoint.put(descriptor, classTransformer.getEnhancedAnnotatedType(rawType, baseType, manager.getId()));
        } else {
            newManagedBeanClasses.add(classTransformer.getEnhancedAnnotatedType(rawType, baseType, manager.getId()));
        }
    }

    public Set> getBeans() {
        return Collections.unmodifiableSet(beans);
    }

    public Set> getDecorators() {
        return Collections.unmodifiableSet(decorators);
    }

    public Set> getInterceptors() {
        return Collections.unmodifiableSet(interceptors);
    }

    public Set> getObservers() {
        return Collections.unmodifiableSet(observers);
    }

    public Set> getUnresolvedDisposalBeans() {
        Set> beans = new HashSet>(allDisposalBeans);
        beans.removeAll(resolvedDisposalBeans);
        return Collections.unmodifiableSet(beans);
    }

    public EjbDescriptors getEjbDescriptors() {
        return ejbDescriptors;
    }

    /**
     * Resolve the disposal method for the given producer method. Any resolved
     * beans will be marked as such for the purpose of validating that all
     * disposal methods are used. For internal use.
     *
     * @param types the types
     * @param qualifiers The binding types to match
     * @param declaringBean declaring bean
     * @return The set of matching disposal methods
     */
    public  Set> resolveDisposalBeans(Set types, Set qualifiers, AbstractClassBean declaringBean) {
        // We can always cache as this is only ever called by Weld where we avoid non-static inner classes for annotation literals
        Set> beans = cast(disposalMethodResolver.resolve(new ResolvableBuilder(manager).addTypes(types).addQualifiers(qualifiers).setDeclaringBean(declaringBean).create(), true));
        resolvedDisposalBeans.addAll(beans);
        return Collections.unmodifiableSet(beans);
    }

    protected static class WeldMethodKey {

        static WeldMethodKey of(ProducerMethod producerMethod) {
            return new WeldMethodKey(producerMethod.getBeanClass(), producerMethod.getEnhancedAnnotated().getSignature());
        }

        private final Class declaringClass;
        private final MethodSignature signature;

        WeldMethodKey(Class clazz, MethodSignature signature) {
            this.declaringClass = clazz;
            this.signature = signature;
        }

        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((declaringClass == null) ? 0 : declaringClass.hashCode());
            result = prime * result + ((signature == null) ? 0 : signature.hashCode());
            return result;
        }

        @Override
        public boolean equals(Object obj) {
            if (this == obj) {
                return true;
            }
            if (obj == null) {
                return false;
            }
            if (getClass() != obj.getClass()) {
                return false;
            }
            WeldMethodKey other = (WeldMethodKey) obj;
            if (declaringClass == null) {
                if (other.declaringClass != null) {
                    return false;
                }
            } else if (!declaringClass.equals(other.declaringClass)) {
                return false;
            }
            if (signature == null) {
                if (other.signature != null) {
                    return false;
                }
            } else if (!signature.equals(other.signature)) {
                return false;
            }
            return true;
        }
    }

    public void vetoBean(AbstractBean bean) {
        beans.remove(bean);
        if (bean instanceof AbstractClassBean) {
            getCacheValue(classBeanMap, bean.getBeanClass()).remove(bean);
            if (bean instanceof InterceptorImpl) {
                interceptors.remove(bean);
            }
            if (bean instanceof DecoratorImpl) {
                decorators.remove(bean);
            }
        }
        if (bean instanceof ProducerMethod) {
            ProducerMethod producerMethod = cast(bean);
            getCacheValue(producerMethodBeanMap, WeldMethodKey.of(producerMethod)).remove(producerMethod);
        }
        if (bean instanceof ProducerField) {
            producerFields.remove(bean);
        }
    }

    public Iterable> getClassBeans() {
        return Iterables.concat(classBeanMap.asMap().values());
    }

    public Iterable> getProducerMethodBeans() {
        return Iterables.concat(producerMethodBeanMap.asMap().values());
    }

    public Set> getProducerFields() {
        return Collections.unmodifiableSet(producerFields);
    }

    public void cleanup() {
        this.annotatedTypes.clear();
        this.vetoedClasses.clear();
        this.classBeanMap.invalidateAll();
        this.producerMethodBeanMap.invalidateAll();
        this.producerFields.clear();
        this.allDisposalBeans.clear();
        this.resolvedDisposalBeans.clear();
        this.beans.clear();
        this.decorators.clear();
        this.interceptors.clear();
        this.observers.clear();
        this.disposalMethodResolver.clear();
        this.newManagedBeanClasses.clear();
        this.newSessionBeanDescriptorsFromInjectionPoint.clear();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy