Package org.apache.openejb.cdi

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

/*
* 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.OpenEJBException;
import org.apache.webbeans.component.OwbBean;
import org.apache.webbeans.component.WebBeansType;
import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.config.WebBeansFinder;
import org.apache.webbeans.portable.events.discovery.BeforeShutdownImpl;
import org.apache.webbeans.spi.ResourceInjectionService;
import org.apache.webbeans.spi.SecurityService;
import org.apache.webbeans.spi.TransactionService;
import org.apache.webbeans.spi.plugins.AbstractOwbPlugin;
import org.apache.webbeans.spi.plugins.OpenWebBeansEjbPlugin;
import org.apache.webbeans.spi.plugins.OpenWebBeansJavaEEPlugin;
import org.apache.webbeans.util.WebBeansUtil;

import javax.ejb.Stateful;
import javax.enterprise.context.Dependent;
import javax.enterprise.context.spi.Context;
import javax.enterprise.context.spi.Contextual;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.InjectionPoint;
import javax.enterprise.inject.spi.PassivationCapable;
import javax.enterprise.inject.spi.ProcessAnnotatedType;
import javax.enterprise.inject.spi.SessionBeanType;
import java.lang.annotation.Annotation;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.WeakHashMap;
import java.util.concurrent.ConcurrentHashMap;


public class CdiPlugin extends AbstractOwbPlugin implements OpenWebBeansJavaEEPlugin, OpenWebBeansEjbPlugin {

    private Set<Class<?>> beans;

    private WebBeansContext webBeansContext;
    private CdiAppContextsService contexsServices;
    private ClassLoader classLoader;

    private final Map<Contextual<?>, Object> cacheProxies = new ConcurrentHashMap<Contextual<?>, Object>();

    public void setWebBeansContext(WebBeansContext webBeansContext) {
        this.webBeansContext = webBeansContext;
    }

    public void setClassLoader(ClassLoader classLoader) {
        this.classLoader = classLoader;
    }

    @Override
    public void shutDown() {
        super.shutDown();
        // this plugin may have been installed in a non-ejb lifecycle???
        if (beans != null) {
            this.beans.clear();
        }
    }

    public void configureDeployments(List<BeanContext> ejbDeployments) {
        WeakHashMap<Class<?>, Object> beans = new WeakHashMap<Class<?>, Object>();
        for (BeanContext deployment : ejbDeployments) {
            if (deployment.getComponentType().isSession()) {
                beans.put(deployment.getBeanClass(), null);
            }
        }
        this.beans = beans.keySet();
    }

    public CdiAppContextsService getContexsServices() {
        return contexsServices;
    }

    public void startup() {
        this.contexsServices = (CdiAppContextsService) webBeansContext.getContextsService();
        this.contexsServices.init(null);
    }

    public void stop() throws OpenEJBException {
        ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
        try {
            // Setting context class loader for cleaning
            Thread.currentThread().setContextClassLoader(classLoader);

            // Fire shut down
            webBeansContext.getBeanManagerImpl().fireEvent(new BeforeShutdownImpl());

            // Destroys context
            this.contexsServices.destroy(null);

            // Free all plugin resources
            webBeansContext.getPluginLoader().shutDown();

            // Clear extensions
            webBeansContext.getExtensionLoader().clear();

            // Delete Resolutions Cache
            webBeansContext.getBeanManagerImpl().getInjectionResolver().clearCaches();

            // Delte proxies
            webBeansContext.getProxyFactory().clear();

            // Delete AnnotateTypeCache
            webBeansContext.getAnnotatedElementFactory().clear();

            // Clear the resource injection service
            CdiResourceInjectionService injectionServices = (CdiResourceInjectionService) webBeansContext.getService(ResourceInjectionService.class);
            injectionServices.clear();

            // Clear singleton list
            WebBeansFinder.clearInstances(WebBeansUtil.getCurrentClassLoader());

        } catch (Exception e) {
            throw new OpenEJBException(e);
        } finally {
            Thread.currentThread().setContextClassLoader(oldCl);
        }
    }

    @Override
    public <T> T getSupportedService(Class<T> serviceClass) {
        return supportService(serviceClass) ? serviceClass.cast(this) : null;
    }

    @Override
    public void isManagedBean(Class<?> clazz) {
    }

    @Override
    public boolean supportService(Class<?> serviceClass) {
        return serviceClass == TransactionService.class || serviceClass == SecurityService.class;
    }

    @Override
    public Object getSessionBeanProxy(Bean<?> inBean, Class<?> interfce, CreationalContext<?> creationalContext) {
        Object instance = cacheProxies.get(inBean);
        if (instance != null) {
            return instance;
        }

        final Class<? extends Annotation> scopeClass = inBean.getScope();
        final CdiEjbBean<Object> cdiEjbBean = (CdiEjbBean<Object>) inBean;
        final CreationalContext<Object> cc = (CreationalContext<Object>) creationalContext;

        if (scopeClass == null || Dependent.class == scopeClass) { // no need to add any layer, null = @New
            return cdiEjbBean.createEjb(cc);
        }

        // only stateful normally
        final InstanceBean<Object> bean = new InstanceBean<Object>(cdiEjbBean);
        if (webBeansContext.getBeanManagerImpl().isScopeTypeNormal(scopeClass)) {
            instance = webBeansContext.getProxyFactory().createNormalScopedBeanProxy(bean, creationalContext);
            cacheProxies.put(inBean, instance);
        } else {
            final Context context = webBeansContext.getBeanManagerImpl().getContext(scopeClass);
            instance = context.get(bean, cc);
        }
        bean.setOWBProxy(instance);
        return instance;
    }

    @Override
    public boolean isSessionBean(Class<?> clazz) {
        // this may be called from a web app without ejbs in which case beans will not have been initialized by openejb.
        return beans != null && beans.contains(clazz);
    }

    @Override
    public <T> Bean<T> defineSessionBean(Class<T> clazz, ProcessAnnotatedType<T> processAnnotateTypeEvent) {
        throw new IllegalStateException("Statement should never be reached");
    }

    @Override
    public boolean isSingletonBean(Class<?> clazz) {
        throw new IllegalStateException("Statement should never be reached");
    }

    @Override
    public boolean isStatefulBean(Class<?> clazz) {
        // TODO Make the EjbPlugin pass in the Bean<T> instance
        return clazz.isAnnotationPresent(Stateful.class);
    }

    @Override
    public boolean isStatelessBean(Class<?> clazz) {
        throw new IllegalStateException("Statement should never be reached");
    }

    @Override
    public Method resolveViewMethod(Bean<?> component, Method declaredMethod) {
        if (!(component instanceof CdiEjbBean)) return declaredMethod;

        CdiEjbBean cdiEjbBean = (CdiEjbBean) component;

        final BeanContext beanContext = cdiEjbBean.getBeanContext();

        for (Class intface : beanContext.getBusinessLocalInterfaces()) {
            try {
                return intface.getMethod(declaredMethod.getName(), declaredMethod.getParameterTypes());
            } catch (NoSuchMethodException ignore) {
            }
        }
        return declaredMethod;
    }

    //TODO Delete if we end up not needing this
    public Method resolveBeanMethod(Bean<?> component, Method declaredMethod) {
        if (!(component instanceof CdiEjbBean)) return declaredMethod;

        CdiEjbBean cdiEjbBean = (CdiEjbBean) component;

        final BeanContext beanContext = cdiEjbBean.getBeanContext();

        try {
            return beanContext.getBeanClass().getMethod(declaredMethod.getName(), declaredMethod.getParameterTypes());
        } catch (NoSuchMethodException e) {
            return declaredMethod;
        }
    }

    public void clearProxies() {
        cacheProxies.clear();
    }

    // does pretty much nothing
    // used only to get a layer between our EJB proxies and OWB proxies to let them manage the scope
    private static class InstanceBean<T> implements OwbBean<T>, PassivationCapable {
        private final CdiEjbBean<T> bean;
        private T OWBProxy;

        public InstanceBean(final CdiEjbBean<T> tCdiEjbBean) {
            bean = tCdiEjbBean;
        }

        @Override
        public T createNewInstance(final CreationalContext<T> creationalContext) {
            return create(creationalContext);
        }

        @Override
        public void destroyCreatedInstance(final T instance, final CreationalContext<T> creationalContext) {
            bean.destroyComponentInstance(instance, creationalContext);
        }

        @Override
        public Set<Type> getTypes() {
            return bean.getTypes();
        }

        @Override
        public Set<Annotation> getQualifiers() {
            return bean.getQualifiers();
        }

        @Override
        public Class<? extends Annotation> getScope() {
            return bean.getScope();
        }

        @Override
        public String getName() {
            return bean.getName();
        }

        @Override
        public boolean isNullable() {
            return bean.isNullable();
        }

        @Override
        public Set<InjectionPoint> getInjectionPoints() {
            return Collections.emptySet();
        }

        @Override
        public Class<?> getBeanClass() {
            return bean.getBeanClass();
        }

        @Override
        public Set<Class<? extends Annotation>> getStereotypes() {
            return bean.getStereotypes();
        }

        @Override
        public boolean isAlternative() {
            return bean.isAlternative();
        }

        @Override
        public T create(final CreationalContext<T> creationalContext) {
            final T instance = bean.createEjb(creationalContext);
            if (OWBProxy != null && SessionBeanType.STATEFUL.equals(bean.getEjbType())) { // we need to be able to remove OWB proxy to remove (statefuls for instance)
                bean.storeStatefulInstance(OWBProxy, instance);
            }
            return instance;
        }

        @Override
        public void destroy(final T instance, final CreationalContext<T> cc) {
            if (!SessionBeanType.STATEFUL.equals(bean.getEjbType())) {
                return;
            }

            bean.destroy(instance, cc);
        }

        @Override
        public void setImplScopeType(final Annotation scopeType) {
            // no-op
        }

        @Override
        public WebBeansType getWebBeansType() {
            return bean.getWebBeansType();
        }

        @Override
        public void addQualifier(final Annotation qualifier) {
            // no-op
        }

        @Override
        public boolean isSerializable() {
            return bean.isSerializable();
        }

        @Override
        public void addStereoType(final Annotation stereoType) {
            // no-op
        }

        @Override
        public void addApiType(final Class<?> apiType) {
            // no-op
        }

        @Override
        public void addInjectionPoint(final InjectionPoint injectionPoint) {
            // no-op
        }

        @Override
        public Set<Annotation> getOwbStereotypes() {
            return bean.getOwbStereotypes();
        }

        @Override
        public void setName(final String name) {
            // no-op
        }

        @Override
        public List<InjectionPoint> getInjectionPoint(final Member member) {
            return Collections.emptyList();
        }

        @Override
        public Class<T> getReturnType() {
            return bean.getReturnType();
        }

        @Override
        public void setSerializable(final boolean serializable) {
            // no-op
        }

        @Override
        public void setNullable(final boolean nullable) {
            // no-op
        }

        @Override
        public void setSpecializedBean(boolean specialized) {
            // no-op
        }

        @Override
        public boolean isSpecializedBean() {
            return bean.isSpecializedBean();
        }

        @Override
        public void setEnabled(boolean enabled) {
            // no-op
        }

        @Override
        public boolean isEnabled() {
            return bean.isEnabled();
        }

        @Override
        public String getId() {
            return bean.getId();
        }

        @Override
        public boolean isPassivationCapable() {
            return bean.isPassivationCapable();
        }

        @Override
        public boolean isDependent() {
            return bean.isDependent();
        }

        @Override
        public void validatePassivationDependencies() {
            bean.validatePassivationDependencies();
        }

        @Override
        public WebBeansContext getWebBeansContext() {
            return bean.getWebBeansContext();
        }

        public void setOWBProxy(final T OWBProxy) {
            this.OWBProxy = OWBProxy;
        }

        @Override
        public boolean equals(final Object o) {
            return this == o || bean == o;
        }

        @Override
        public int hashCode() {
            return bean.hashCode();
        }
    }
}
TOP

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

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.