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

org.jboss.weld.bootstrap.BeanDeployer 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 java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map.Entry;
import java.util.Set;

import javax.decorator.Decorator;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.Extension;
import javax.enterprise.inject.spi.ProcessBean;
import javax.enterprise.inject.spi.ProcessBeanAttributes;
import javax.enterprise.inject.spi.ProcessManagedBean;
import javax.interceptor.Interceptor;

import org.jboss.weld.Container;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedType;
import org.jboss.weld.annotated.slim.SlimAnnotatedType;
import org.jboss.weld.annotated.slim.SlimAnnotatedTypeContext;
import org.jboss.weld.annotated.slim.SlimAnnotatedTypeStore;
import org.jboss.weld.bean.AbstractBean;
import org.jboss.weld.bean.AbstractClassBean;
import org.jboss.weld.bean.RIBean;
import org.jboss.weld.bean.attributes.BeanAttributesFactory;
import org.jboss.weld.bean.interceptor.InterceptorBindingsAdapter;
import org.jboss.weld.bootstrap.api.ServiceRegistry;
import org.jboss.weld.bootstrap.enablement.GlobalEnablementBuilder;
import org.jboss.weld.bootstrap.events.ProcessAnnotatedTypeImpl;
import org.jboss.weld.ejb.EjbDescriptors;
import org.jboss.weld.ejb.InternalEjbDescriptor;
import org.jboss.weld.ejb.spi.EjbServices;
import org.jboss.weld.injection.producer.InterceptionModelInitializer;
import org.jboss.weld.interceptor.spi.model.InterceptionModel;
import org.jboss.weld.logging.BootstrapLogger;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.resources.spi.ClassFileServices;
import org.jboss.weld.resources.spi.ResourceLoader;
import org.jboss.weld.util.AnnotatedTypes;
import org.jboss.weld.util.AnnotationApiAbstraction;
import org.jboss.weld.util.Beans;
import org.jboss.weld.util.collections.SetMultimap;
import org.jboss.weld.util.reflection.Reflections;

/**
 * @author Pete Muir
 * @author Jozef Hartinger
 * @author alesj
 * @author Marko Luksa
 */
public class BeanDeployer extends AbstractBeanDeployer {

    private final ResourceLoader resourceLoader;
    private final SlimAnnotatedTypeStore annotatedTypeStore;
    private final GlobalEnablementBuilder globalEnablementBuilder;
    private final AnnotationApiAbstraction annotationApi;
    private final ClassFileServices classFileServices;

    public BeanDeployer(BeanManagerImpl manager, EjbDescriptors ejbDescriptors, ServiceRegistry services) {
        this(manager, ejbDescriptors, services, BeanDeployerEnvironmentFactory.newEnvironment(ejbDescriptors, manager));
    }

    public BeanDeployer(BeanManagerImpl manager, EjbDescriptors ejbDescriptors, ServiceRegistry services, BeanDeployerEnvironment environment) {
        super(manager, services, environment);
        this.resourceLoader = manager.getServices().get(ResourceLoader.class);
        this.annotatedTypeStore = manager.getServices().get(SlimAnnotatedTypeStore.class);
        this.globalEnablementBuilder = manager.getServices().get(GlobalEnablementBuilder.class);
        this.annotationApi = manager.getServices().get(AnnotationApiAbstraction.class);
        this.classFileServices = manager.getServices().get(ClassFileServices.class);
    }

    /**
     * Loads a given class, creates a {@link SlimAnnotatedTypeContext} for it and stores it in {@link BeanDeployerEnvironment}.
     */
    public BeanDeployer addClass(String className, AnnotatedTypeLoader loader) {
        SlimAnnotatedTypeContext ctx = loader.loadAnnotatedType(className, getManager().getId());
        if (ctx != null) {
            getEnvironment().addAnnotatedType(ctx);
        }
        return this;
    }

    private void processPriority(AnnotatedType type) {
        Object priority = type.getAnnotation(annotationApi.PRIORITY_ANNOTATION_CLASS);
        if (priority != null) {
            Integer value = annotationApi.getPriority(priority);
            if (value != null) {
                if (type.isAnnotationPresent(Interceptor.class)) {
                    globalEnablementBuilder.addInterceptor(type.getJavaClass(), value);
                } else if (type.isAnnotationPresent(Decorator.class)) {
                    globalEnablementBuilder.addDecorator(type.getJavaClass(), value);
                } else {
                    /*
                     * An alternative may be given a priority for the application by placing the @Priority annotation on the bean
                     * class that declares the producer method, field or resource.
                     */
                    globalEnablementBuilder.addAlternative(type.getJavaClass(), value);
                }
            }
        }
    }

    public  BeanDeployer addSyntheticClass(AnnotatedType source, Extension extension, String suffix) {
        if (suffix == null) {
            suffix = AnnotatedTypes.createTypeId(source);
        }
        getEnvironment().addSyntheticAnnotatedType(classTransformer.getUnbackedAnnotatedType(source, getManager().getId(), suffix), extension);
        return this;
    }

    public BeanDeployer addClasses(Iterable classes) {
        AnnotatedTypeLoader loader = createAnnotatedTypeLoader();
        for (String className : classes) {
            addClass(className, loader);
        }
        return this;
    }

    protected AnnotatedTypeLoader createAnnotatedTypeLoader() {
        if (classFileServices != null) {
            // Since FastProcessAnnotatedTypeResolver is installed after BeanDeployers are created, we need to query deploymentManager's services instead of the manager of this deployer
            final FastProcessAnnotatedTypeResolver resolver = Container.instance(getManager()).deploymentManager().getServices()
                    .get(FastProcessAnnotatedTypeResolver.class);
            if (resolver != null) {
                return new FastAnnotatedTypeLoader(getManager(), classTransformer, classFileServices, containerLifecycleEvents, resolver);
            }
        }
        // if FastProcessAnnotatedTypeResolver is not available, fall back to AnnotatedTypeLoader
        return new AnnotatedTypeLoader(getManager(), classTransformer, containerLifecycleEvents);
    }

    public void processAnnotatedTypes() {
        Set> classesToBeAdded = new HashSet>();
        Set> classesToBeRemoved = new HashSet>();

        for (SlimAnnotatedTypeContext annotatedTypeContext : getEnvironment().getAnnotatedTypes()) {
            SlimAnnotatedType annotatedType = annotatedTypeContext.getAnnotatedType();
            final ProcessAnnotatedTypeImpl event = containerLifecycleEvents.fireProcessAnnotatedType(getManager(), annotatedTypeContext);

            // process the result
            if (event != null) {
                if (event.isVeto()) {
                    getEnvironment().vetoJavaClass(annotatedType.getJavaClass());
                    classesToBeRemoved.add(annotatedTypeContext);
                } else {
                    boolean dirty = event.isDirty();
                    if (dirty) {
                        classesToBeRemoved.add(annotatedTypeContext); // remove the original class
                        classesToBeAdded.add(SlimAnnotatedTypeContext.of(event.getResultingAnnotatedType(), annotatedTypeContext.getExtension()));
                    }
                    processPriority(event.getResultingAnnotatedType());
                }
            } else {
                processPriority(annotatedType);
            }
        }
        getEnvironment().removeAnnotatedTypes(classesToBeRemoved);
        getEnvironment().addAnnotatedTypes(classesToBeAdded);
    }

    public void registerAnnotatedTypes() {
        for (SlimAnnotatedTypeContext ctx : getEnvironment().getAnnotatedTypes()) {
            annotatedTypeStore.put(ctx.getAnnotatedType());
        }
    }

    public void createClassBeans() {
        SetMultimap, SlimAnnotatedType> otherWeldClasses = SetMultimap.newConcurrentSetMultimap();

        for (SlimAnnotatedTypeContext ctx : getEnvironment().getAnnotatedTypes()) {
            createClassBean(ctx.getAnnotatedType(), otherWeldClasses);
        }
        // create session beans
        for (InternalEjbDescriptor ejbDescriptor : getEnvironment().getEjbDescriptors()) {
            if (getEnvironment().isVetoed(ejbDescriptor.getBeanClass()) || Beans.isVetoed(ejbDescriptor.getBeanClass())) {
                continue;
            }
            if (ejbDescriptor.isSingleton() || ejbDescriptor.isStateful() || ejbDescriptor.isStateless()) {
                if (otherWeldClasses.get(ejbDescriptor.getBeanClass()) != null) {
                    for (SlimAnnotatedType annotatedType : otherWeldClasses.get(ejbDescriptor.getBeanClass())) {
                        EnhancedAnnotatedType weldClass = classTransformer.getEnhancedAnnotatedType(annotatedType);
                        createSessionBean(ejbDescriptor, Reflections. cast(weldClass));
                    }
                } else {
                    createSessionBean(ejbDescriptor);
                }
            }
        }
    }

    protected void createClassBean(SlimAnnotatedType annotatedType,
            SetMultimap, SlimAnnotatedType> otherWeldClasses) {
        boolean managedBeanOrDecorator = !getEnvironment().getEjbDescriptors().contains(annotatedType.getJavaClass()) && Beans.isTypeManagedBeanOrDecoratorOrInterceptor(annotatedType);
        if (managedBeanOrDecorator) {
            containerLifecycleEvents.preloadProcessInjectionTarget(annotatedType.getJavaClass());
            containerLifecycleEvents.preloadProcessBeanAttributes(annotatedType.getJavaClass());
            EnhancedAnnotatedType weldClass = classTransformer.getEnhancedAnnotatedType(annotatedType);
            if (weldClass.isAnnotationPresent(Decorator.class)) {
                containerLifecycleEvents.preloadProcessBean(ProcessBean.class, annotatedType.getJavaClass());
                validateDecorator(weldClass);
                createDecorator(weldClass);
            } else if (weldClass.isAnnotationPresent(Interceptor.class)) {
                containerLifecycleEvents.preloadProcessBean(ProcessBean.class, annotatedType.getJavaClass());
                validateInterceptor(weldClass);
                createInterceptor(weldClass);
            } else if (!weldClass.isAbstract()) {
                containerLifecycleEvents.preloadProcessBean(ProcessManagedBean.class, annotatedType.getJavaClass());
                createManagedBean(weldClass);
            }
        } else {
            if (Beans.isDecoratorDeclaringInAppropriateConstructor(annotatedType)) {
                BootstrapLogger.LOG.decoratorWithNonCdiConstructor(annotatedType.getJavaClass().getName());
            }
            Class scopeClass = Beans.getBeanDefiningAnnotationScope(annotatedType);
            if (scopeClass != null && !Beans.hasSimpleCdiConstructor(annotatedType)) {
                BootstrapLogger.LOG.annotatedTypeNotRegisteredAsBeanDueToMissingAppropriateConstructor(annotatedType.getJavaClass().getName(),
                        scopeClass.getSimpleName());
            }
            otherWeldClasses.put(annotatedType.getJavaClass(), annotatedType);
        }
    }

    /**
     * Fires {@link ProcessBeanAttributes} for each enabled bean and updates the environment based on the events.
     */
    public void processClassBeanAttributes() {
        preInitializeBeans(getEnvironment().getClassBeans());
        preInitializeBeans(getEnvironment().getDecorators());
        preInitializeBeans(getEnvironment().getInterceptors());

        processBeanAttributes(getEnvironment().getClassBeans());
        processBeanAttributes(getEnvironment().getDecorators());
        processBeanAttributes(getEnvironment().getInterceptors());

        // now that we know that the bean won't be vetoed, it's the right time to register @New injection points
        searchForNewBeanDeclarations(getEnvironment().getClassBeans());
        searchForNewBeanDeclarations(getEnvironment().getDecorators());
        searchForNewBeanDeclarations(getEnvironment().getInterceptors());
    }

    private void preInitializeBeans(Iterable> beans) {
        for (AbstractBean bean : beans) {
            bean.preInitialize();
        }
    }

    protected void processBeanAttributes(Iterable> beans) {
        if (!containerLifecycleEvents.isProcessBeanAttributesObserved()) {
            return;
        }
        if (!beans.iterator().hasNext()) {
            return; // exit recursion
        }

        Collection> vetoedBeans = new HashSet>();
        Collection> previouslySpecializedBeans = new HashSet>();
        for (AbstractBean bean : beans) {
            // fire ProcessBeanAttributes for class beans
            boolean vetoed = fireProcessBeanAttributes(bean);
            if (vetoed) {
                vetoedBeans.add(bean);
            }
        }

        // remove vetoed class beans
        for (AbstractBean bean : vetoedBeans) {
            if (bean.isSpecializing()) {
                previouslySpecializedBeans.addAll(specializationAndEnablementRegistry.resolveSpecializedBeans(bean));
                specializationAndEnablementRegistry.vetoSpecializingBean(bean);
            }
            getEnvironment().vetoBean(bean);
        }
        // if a specializing bean was vetoed, let's process the specializing bean now
        processBeanAttributes(previouslySpecializedBeans);
    }

    protected void searchForNewBeanDeclarations(Iterable> beans) {
        for (AbstractBean bean : beans) {
            getEnvironment().addNewBeansFromInjectionPoints(bean);
        }
    }

    public void createProducersAndObservers() {
        for (AbstractClassBean bean : getEnvironment().getClassBeans()) {
            createObserversProducersDisposers(bean);
        }
    }

    public void processProducerAttributes() {
        processBeanAttributes(getEnvironment().getProducerFields());
        searchForNewBeanDeclarations(getEnvironment().getProducerFields());
        // process BeanAttributes for producer methods
        preInitializeBeans(getEnvironment().getProducerMethodBeans());
        processBeanAttributes(getEnvironment().getProducerMethodBeans());
        searchForNewBeanDeclarations(getEnvironment().getProducerMethodBeans());
    }

    public void createNewBeans() {
        for (EnhancedAnnotatedType clazz : getEnvironment().getNewManagedBeanClasses()) {
            createNewManagedBean(clazz);
        }
        for (Entry, EnhancedAnnotatedType> entry : getEnvironment().getNewSessionBeanDescriptorsFromInjectionPoint().entrySet()) {
            InternalEjbDescriptor descriptor = entry.getKey();
            createNewSessionBean(descriptor, BeanAttributesFactory.forSessionBean(entry.getValue(), descriptor, getManager()), entry.getValue());
        }
    }

    public void deploy() {
        initializeBeans();
        fireBeanEvents();
        deployBeans();
        initializeObserverMethods();
        deployObserverMethods();
    }

    protected void validateInterceptor(EnhancedAnnotatedType weldClass) {
        if (weldClass.isAnnotationPresent(Decorator.class)) {
            throw BootstrapLogger.LOG.beanIsBothInterceptorAndDecorator(weldClass.getName());
        }
    }

    protected void validateDecorator(EnhancedAnnotatedType weldClass) {
        if (weldClass.isAnnotationPresent(Interceptor.class)) {
            throw BootstrapLogger.LOG.beanIsBothInterceptorAndDecorator(weldClass.getName());
        }
    }

    public void doAfterBeanDiscovery(List> beanList) {
        for (Bean bean : beanList) {
            if (bean instanceof RIBean) {
                ((RIBean) bean).initializeAfterBeanDiscovery();
            }
        }
    }

    public void registerCdiInterceptorsForMessageDrivenBeans() {
        EjbServices ejbServices = getManager().getServices().get(EjbServices.class);
        for (InternalEjbDescriptor descriptor : getEnvironment().getEjbDescriptors()) {
            if (descriptor.isMessageDriven()) {
                EnhancedAnnotatedType type =  classTransformer.getEnhancedAnnotatedType(descriptor.getBeanClass(), getManager().getId());
                if (!getManager().getInterceptorModelRegistry().containsKey(type.slim())) {
                    InterceptionModelInitializer.of(getManager(), type, null).init();
                }
                InterceptionModel model = getManager().getInterceptorModelRegistry().get(type.slim());
                if (model != null) {
                    ejbServices.registerInterceptors(descriptor.delegate(), new InterceptorBindingsAdapter(model));
                }
            }
        }
    }

    public ResourceLoader getResourceLoader() {
        return resourceLoader;
    }

    public void cleanup() {
        getEnvironment().cleanup();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy