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

org.jboss.weld.module.ejb.SessionBeanInjectionTarget Maven / Gradle / Ivy

The newest version!
/*
 * JBoss, Home of Professional Open Source
 * Copyright 2012, 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.module.ejb;

import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.List;
import java.util.Set;

import jakarta.enterprise.context.spi.CreationalContext;
import jakarta.enterprise.inject.spi.Bean;
import jakarta.enterprise.inject.spi.Decorator;
import jakarta.enterprise.inject.spi.InjectionPoint;

import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedConstructor;
import org.jboss.weld.annotated.enhanced.EnhancedAnnotatedType;
import org.jboss.weld.bean.SessionBean;
import org.jboss.weld.bean.proxy.CombinedInterceptorAndDecoratorStackMethodHandler;
import org.jboss.weld.bean.proxy.MethodHandler;
import org.jboss.weld.bean.proxy.ProxyObject;
import org.jboss.weld.injection.producer.AbstractInstantiator;
import org.jboss.weld.injection.producer.BeanInjectionTarget;
import org.jboss.weld.injection.producer.DefaultInjector;
import org.jboss.weld.injection.producer.DefaultInstantiator;
import org.jboss.weld.injection.producer.DefaultLifecycleCallbackInvoker;
import org.jboss.weld.injection.producer.Injector;
import org.jboss.weld.injection.producer.Instantiator;
import org.jboss.weld.injection.producer.InterceptionModelInitializer;
import org.jboss.weld.injection.producer.LifecycleCallbackInvoker;
import org.jboss.weld.injection.producer.SubclassDecoratorApplyingInstantiator;
import org.jboss.weld.injection.producer.SubclassedComponentInstantiator;
import org.jboss.weld.manager.BeanManagerImpl;
import org.jboss.weld.util.Types;

class SessionBeanInjectionTarget extends BeanInjectionTarget {

    public static  SessionBeanInjectionTarget of(EnhancedAnnotatedType type, SessionBean bean,
            BeanManagerImpl beanManager) {
        LifecycleCallbackInvoker invoker = DefaultLifecycleCallbackInvoker.of(type);
        Injector injector;
        if (bean.getEjbDescriptor().isStateless() || bean.getEjbDescriptor().isSingleton()) {
            injector = new DynamicInjectionPointInjector(type, bean, beanManager);
        } else {
            injector = new DefaultInjector(type, bean, beanManager);
        }
        return new SessionBeanInjectionTarget(type, bean, beanManager, injector, invoker);
    }

    private final SessionBean bean;

    private SessionBeanInjectionTarget(EnhancedAnnotatedType type, SessionBean bean, BeanManagerImpl beanManager,
            Injector injector, LifecycleCallbackInvoker invoker) {
        super(type, bean, beanManager, injector, invoker);
        this.bean = bean;
    }

    @Override
    public SessionBean getBean() {
        return bean;
    }

    @Override
    protected Instantiator initInstantiator(EnhancedAnnotatedType type, Bean bean, BeanManagerImpl beanManager,
            Set injectionPoints) {
        if (bean instanceof SessionBean) {
            EnhancedAnnotatedType implementationClass = SessionBeans.getEjbImplementationClass((SessionBean) bean);

            AbstractInstantiator instantiator = null;
            if (type.equals(implementationClass)) {
                instantiator = new DefaultInstantiator(type, bean, beanManager);
            } else {
                // Session bean subclassed by the EJB container
                instantiator = SubclassedComponentInstantiator.forSubclassedEjb(type, implementationClass, bean, beanManager);
            }
            injectionPoints.addAll(instantiator.getConstructorInjectionPoint().getParameterInjectionPoints());
            return instantiator;
        } else {
            throw new IllegalArgumentException("Cannot create SessionBeanInjectionTarget for " + bean);
        }
    }

    @Override
    public void initializeAfterBeanDiscovery(EnhancedAnnotatedType annotatedType) {
        initializeInterceptionModel(annotatedType);

        List> decorators = beanManager.resolveDecorators(getBean().getTypes(), getBean().getQualifiers());
        if (!decorators.isEmpty()) {
            Instantiator instantiator = getInstantiator();
            EnhancedAnnotatedType implementationClass = SessionBeans.getEjbImplementationClass(getBean());
            instantiator = SubclassedComponentInstantiator.forInterceptedDecoratedBean(implementationClass, getBean(),
                    (AbstractInstantiator) instantiator, beanManager);
            instantiator = new SubclassDecoratorApplyingInstantiator(getBeanManager().getContextId(), instantiator,
                    getBean(), decorators, implementationClass.getJavaClass());
            setInstantiator(instantiator);
        }

        /*
         * We only take care of @AroundConstructor interception. The EJB container deals with the other types of interception.
         */
        setupConstructorInterceptionInstantiator(beanManager.getInterceptorModelRegistry().get(getType()));
    }

    @Override
    protected void buildInterceptionModel(EnhancedAnnotatedType annotatedType, AbstractInstantiator instantiator) {
        /*
         * instantiator.getConstructorInjectionPoint() may represent the constructor of the SessionBean subclass which may not
         * have annotations applied
         * Therefore, use the component class constructor instead of the one from subclass.
         */
        EnhancedAnnotatedConstructor constructor = annotatedType
                .getDeclaredEnhancedConstructor(instantiator.getConstructorInjectionPoint().getSignature());
        new InterceptionModelInitializer(beanManager, annotatedType, constructor, getBean()).init();
    }

    @Override
    public T produce(CreationalContext ctx) {
        T result = super.produce(ctx);

        if (result instanceof ProxyObject) {
            // if decorators are applied, use SessionBeanViewMethodHandler
            ProxyObject proxy = (ProxyObject) result;
            proxy.weld_setHandler(new SessionBeanViewMethodHandler(bean.getTypes(),
                    (CombinedInterceptorAndDecoratorStackMethodHandler) proxy.weld_getHandler()));
        }
        return result;
    }

    @Override
    public void inject(T instance, CreationalContext ctx) {
        // explicitly use bean's AnnotatedType, not InjectionPoint's as this.getAnnotated()
        // may represent the annotated type for the EJB-container subclass (see SubclassedComponentDescriptor)
        getInjector().inject(instance, ctx, beanManager, bean.getAnnotated(), this);
    }

    /**
     * This {@link MethodHandler} assures that any method invoked on a decorated {@link SessionBean} is a method that belongs to
     * a bean type of the bean. If the methods belongs to the bean implementation and the bean implementation is not a bean type
     * the handler tries to replace the method with the equivalent method defined on a bean type.
     *
     * @author Jozef Hartinger
     *
     */
    private static class SessionBeanViewMethodHandler extends CombinedInterceptorAndDecoratorStackMethodHandler {

        private static final long serialVersionUID = -8038819529432133787L;

        private final Set> beanTypes;

        public SessionBeanViewMethodHandler(Set types, CombinedInterceptorAndDecoratorStackMethodHandler delegate) {
            this.beanTypes = Types.getRawTypes(types);
            setOuterDecorator(delegate.getOuterDecorator());
            setInterceptorMethodHandler(delegate.getInterceptorMethodHandler());
        }

        @Override
        public Object invoke(Object self, Method thisMethod, Method proceed, Object[] args) throws Throwable {
            if (beanTypes.contains(thisMethod.getDeclaringClass())) {
                return super.invoke(self, thisMethod, proceed, args);
            } else {
                Method decoratedTypeMethod = getBeanTypeMethod(thisMethod);
                return super.invoke(self, decoratedTypeMethod, proceed, args);
            }
        }

        private Method getBeanTypeMethod(Method method) {
            for (Class c : beanTypes) {
                try {
                    return c.getMethod(method.getName(), method.getParameterTypes());
                } catch (NoSuchMethodException e) {
                    continue;
                }
            }
            return method;
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy