Package org.apache.openejb.cdi

Source Code of org.apache.openejb.cdi.CdiEjbBean

/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements.  See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You 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.apache.openejb.cdi;

import org.apache.openejb.BeanContext;
import org.apache.openejb.BeanType;
import org.apache.openejb.OpenEJBRuntimeException;
import org.apache.openejb.assembler.classic.ProxyInterfaceResolver;
import org.apache.webbeans.config.OWBLogConst;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.decorator.WebBeansDecorator;
import org.apache.webbeans.ejb.common.component.BaseEjbBean;
import org.apache.webbeans.exception.WebBeansConfigurationException;
import org.apache.webbeans.intercept.InterceptorData;
import org.apache.webbeans.intercept.webbeans.WebBeansInterceptor;
import org.apache.webbeans.logger.WebBeansLoggerFacade;

import javax.ejb.NoSuchEJBException;
import javax.ejb.Remove;
import javax.enterprise.context.Dependent;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.Disposes;
import javax.enterprise.inject.Typed;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.Decorator;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.SessionBeanType;
import javax.persistence.EntityManager;
import java.io.Serializable;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.UndeclaredThrowableException;
import java.rmi.NoSuchObjectException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;

public class CdiEjbBean<T> extends BaseEjbBean<T> {
    private final Map<Integer, Object> dependentSFSBToBeRemoved = new ConcurrentHashMap<Integer, Object>();

    private final BeanContext beanContext;

    public CdiEjbBean(BeanContext beanContext, WebBeansContext webBeansContext) {
        this(beanContext, webBeansContext, beanContext.getManagedClass());
    }

    public CdiEjbBean(BeanContext beanContext, WebBeansContext webBeansContext, Class beanClass) {
        super(beanClass, toSessionType(beanContext.getComponentType()), webBeansContext);
        this.beanContext = beanContext;
        beanContext.set(Bean.class, this);
    }

    @Override // copied to be able to produce EM (should be fixed in OWB for next CDI spec)
    public void validatePassivationDependencies() {
        if(isPassivationCapable()) {
            final Set<InjectionPoint> beanInjectionPoints = getInjectionPoints();
            for(InjectionPoint injectionPoint : beanInjectionPoints) {
                if(!injectionPoint.isTransient()) {
                    if(!getWebBeansContext().getWebBeansUtil().isPassivationCapableDependency(injectionPoint)) {
                        if(injectionPoint.getAnnotated().isAnnotationPresent(Disposes.class)
                                // here is the hack, this is temporary until OWB manages correctly serializable instances
                                || EntityManager.class.equals(injectionPoint.getAnnotated().getBaseType())) {
                            continue;
                        }
                        throw new WebBeansConfigurationException(
                                "Passivation capable beans must satisfy passivation capable dependencies. " +
                                        "Bean : " + toString() + " does not satisfy. Details about the Injection-point: " +
                                        injectionPoint.toString());
                    }
                }
            }
        }

        //Check for interceptors and decorators, copied from parent(s)
        for (Decorator<?> dec : decorators) {
            WebBeansDecorator<?> decorator = (WebBeansDecorator<?>) dec;
            if (!decorator.isPassivationCapable()) {
                throw new WebBeansConfigurationException(MessageFormat.format(
                        WebBeansLoggerFacade.getTokenString(OWBLogConst.EXCEPT_0015), toString()));
            } else {
                decorator.validatePassivationDependencies();
            }
        }

        for (InterceptorData interceptorData : interceptorStack) {
            if (interceptorData.isDefinedWithWebBeansInterceptor()) {
                WebBeansInterceptor<?> interceptor = (WebBeansInterceptor<?>) interceptorData.getWebBeansInterceptor();
                if (!interceptor.isPassivationCapable()) {
                    throw new WebBeansConfigurationException(MessageFormat.format(
                            WebBeansLoggerFacade.getTokenString(OWBLogConst.EXCEPT_0016), toString()));
                } else {
                    interceptor.validatePassivationDependencies();
                }
            } else {
                if (interceptorData.isDefinedInInterceptorClass()) {
                    Class<?> interceptorClass = interceptorData.getInterceptorClass();
                    if (!Serializable.class.isAssignableFrom(interceptorClass)) {
                        throw new WebBeansConfigurationException(MessageFormat.format(
                                WebBeansLoggerFacade.getTokenString(OWBLogConst.EXCEPT_0016), toString()));
                    } else {
                        if (!getWebBeansContext().getAnnotationManager().checkInjectionPointForInterceptorPassivation(interceptorClass)) {
                            throw new WebBeansConfigurationException(MessageFormat.format(
                                    WebBeansLoggerFacade.getTokenString(OWBLogConst.EXCEPT_0017), toString(), interceptorClass));
                        }
                    }
                }
            }
        }
    }

    @Override
    public void addApiType(final Class<?> apiType) {
        if (apiType == null) return;

        super.addApiType(apiType);
    }

    public BeanContext getBeanContext() {
        return this.beanContext;
    }

    private static SessionBeanType toSessionType(BeanType beanType) {
        switch (beanType) {
        case SINGLETON:
            return SessionBeanType.SINGLETON;
        case MESSAGE_DRIVEN: // OWB implementation test stateful or not so do we really care?
        case STATELESS:
            return SessionBeanType.STATELESS;
        case STATEFUL:
        case MANAGED:
            return SessionBeanType.STATEFUL;
        default:
            throw new IllegalStateException("Unknown Session BeanType " + beanType);
        }
    }

    @Override
    public String getId() {
        return beanContext.getDeploymentID() + getReturnType().getName();
    }

    @Override
    protected void afterConstructor(T instance, CreationalContext<T> tCreationalContext) {
        // no-op
    }

//    @Override
//    public void postConstruct(T instance, CreationalContext<T> cretionalContext) {
//    }

    public String getEjbName() {
        return this.beanContext.getEjbName();
    }

    public boolean needsBeanLocalViewAddedToTypes() {
        return beanContext.isLocalbean() && beanContext.getBeanClass().getAnnotation(Typed.class) == null;
    }

    @Override
    @SuppressWarnings("unchecked")
    public List<Class<?>> getBusinessLocalInterfaces() {
        final List<Class<?>> clazzes = new ArrayList<Class<?>>();

        if (beanContext.isLocalbean()) {
            addApiTypes(clazzes, beanContext.getBeanClass());
        }

        if (beanContext.getProxyClass() != null) {
            addApiTypes(clazzes, beanContext.getProxyClass());
        }

        final List<Class> cl = beanContext.getBusinessLocalInterfaces();
        if (cl != null && !cl.isEmpty()) {
            for (Class<?> c : cl) {
                clazzes.add(c);
            }
        }

        if (!clazzes.contains(Serializable.class)) {
            clazzes.add(Serializable.class);
        }

        return clazzes;
    }

    private static void addApiTypes(final List<Class<?>> clazzes, final Class<?> beanClass) {
        final Typed typed = beanClass.getAnnotation(Typed.class);
        if (typed == null || typed.value().length == 0) {
            clazzes.add(beanClass);
        } else {
            for (Class<?> clazz : typed.value()) {
                clazzes.add(clazz);
            }
        }
    }

    @Override
    @SuppressWarnings("unchecked")
    protected T getInstance(final CreationalContext<T> creationalContext) {
        return createEjb(creationalContext);

        /*
        final T instance;
        if (scopeClass == null || Dependent.class == scopeClass) { // no need to add any layer, null = @New
            instance = createEjb(creationalContext);
        } else { // only stateful normally
            final InstanceBean<T> bean = new InstanceBean<T>(this);
            if (webBeansContext.getBeanManagerImpl().isScopeTypeNormal(scopeClass)) {
                instance = (T) webBeansContext.getProxyFactory().createNormalScopedBeanProxy(bean, creationalContext);
            } else {
                final Context context = webBeansContext.getBeanManagerImpl().getContext(scopeClass);
                instance = context.get(bean, creationalContext);
            }
            bean.setOWBProxy(instance);
        }
        return instance;
        */
    }

    @Override
    protected void destroyComponentInstance(final T instance, final CreationalContext<T> creational) {
        if (scopeClass == null || Dependent.class == scopeClass) {
            destroyStatefulSessionBeanInstance(instance, creational);
        } else {
            destroyScopedStateful(instance, creational);
        }
    }

    @Override
    protected void destroyStatefulSessionBeanInstance(final T proxyInstance, final Object ejbInstance) {
        if (proxyInstance instanceof BeanContext.Removable) {
            try {
                ((BeanContext.Removable) proxyInstance).$$remove();
            } catch (NoSuchEJBException nsee) {
                // no-op
            } catch (UndeclaredThrowableException nsoe) {
                if (!(nsoe.getCause() instanceof NoSuchObjectException)) {
                    throw nsoe;
                }
            } catch (Exception e) {
                if (!(e instanceof NoSuchObjectException)) {
                    if (e instanceof RuntimeException) {
                        throw (RuntimeException) e;
                    }
                    throw new OpenEJBRuntimeException(e);
                }
            }
        }
    }

    @Override
    public List<Method> getRemoveMethods() {
        // Should we delegate to super and merge both?
        if (beanContext.isLocalbean()) {
            return findRemove(beanContext.getBeanClass(), beanContext.getBeanClass());
        }
        return findRemove(beanContext.getBeanClass(), beanContext.getBusinessLocalInterface());
    }

    public List<InjectionPoint> getInjectionPoint(Member member)
    {
        if (member instanceof Method) {
            Method method = (Method) member;
            member = beanContext.getMatchingBeanMethod(method);
        }

        List<InjectionPoint> points = new ArrayList<InjectionPoint>();

        for(InjectionPoint ip : injectionPoints)
        {
            if(ip.getMember().equals(member))
            {
                points.add(ip);
            }
        }

        return points;
    }

    protected void specialize(CdiEjbBean<?> superBean) {
        final CdiEjbBean<T> bean = this;
        bean.setName(superBean.getName());
        bean.setSerializable(superBean.isSerializable());

        this.scopeClass = superBean.scopeClass;
        this.implQualifiers.addAll(superBean.getQualifiers());
        this.stereoTypeClasses.addAll(superBean.stereoTypeClasses);
        this.stereoTypes.addAll(superBean.stereoTypes);
    }

    /* (non-Javadoc)
     * @see org.apache.webbeans.component.AbstractBean#isPassivationCapable()
     */
    @Override
    public boolean isPassivationCapable() {
        return getWebBeansContext().getBeanManagerImpl().isPassivatingScope(getScope());
    }

    @SuppressWarnings("unchecked")
    private List<Method> findRemove(Class beanClass, Class beanInterface) {
        List<Method> toReturn = new ArrayList<Method>();

        // Get all the public methods of the bean class and super class
        Method[] methods = beanClass.getMethods();

        // Search for methods annotated with @Remove
        for (Method method : methods) {
            Remove annotation = method.getAnnotation(Remove.class);
            if (annotation != null) {
                // Get the corresponding method into the bean interface
                Method interfaceMethod;
                try {
                    interfaceMethod = beanInterface.getMethod(method.getName(), method
                            .getParameterTypes());

                    toReturn.add(interfaceMethod);
                } catch (SecurityException e) {
                    e.printStackTrace();
                } catch (NoSuchMethodException e) {
                    // The method can not be into the interface in which case we
                    // don't wonder of
                }
            }
        }

        return toReturn;
    }

    protected T createEjb(final CreationalContext<T> creationalContext) {
        final List<Class> classes = beanContext.getBusinessLocalInterfaces();
        final CurrentCreationalContext currentCreationalContext = beanContext.get(CurrentCreationalContext.class);
        final CreationalContext existing = currentCreationalContext.get();
        currentCreationalContext.set(creationalContext);
        try {
            if (classes.size() == 0 && beanContext.isLocalbean()) {
                final BeanContext.BusinessLocalBeanHome home = beanContext.getBusinessLocalBeanHome();
                return (T) home.create();
            } else {
                final Class<?> mainInterface = classes.get(0);
                final List<Class> interfaces = ProxyInterfaceResolver.getInterfaces(beanContext.getBeanClass(), mainInterface, classes);
                final BeanContext.BusinessLocalHome home = beanContext.getBusinessLocalHome(interfaces, mainInterface);
                return (T) home.create();
            }
        } finally {
            currentCreationalContext.set(existing);
        }
    }

    private void destroyScopedStateful(final T instance, final CreationalContext<T> cc) {
        try {
            instance.hashCode(); // force the instance to be created - otherwise we'll miss @PreDestroy for instance
        } catch (NoSuchEJBException e) {
            logger.log(Level.FINE, "The stateful instance " + instance + " can't be removed since it was invalidated", e);
            return;
        }

        Object ejbInstance = dependentSFSBToBeRemoved.remove(System.identityHashCode(instance));
        if (ejbInstance != null) {
            destroyStatefulSessionBeanInstance((T) ejbInstance, cc);
        } else {
            destroyStatefulSessionBeanInstance(instance, cc);
        }
    }

    public void storeStatefulInstance(final Object proxy, final T instance) {
        dependentSFSBToBeRemoved.put(System.identityHashCode(proxy), instance);
    }
}
TOP

Related Classes of org.apache.openejb.cdi.CdiEjbBean

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.