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

org.ops4j.pax.cdi.openwebbeans.impl.OpenWebBeansCdiContainer Maven / Gradle / Ivy

There is a newer version: 1.1.4
Show newest version
/*
 * Copyright 2012 Harald Wellmann.
 *
 * 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.ops4j.pax.cdi.openwebbeans.impl;

import static org.ops4j.pax.swissbox.core.ContextClassLoaderUtils.doWithClassLoader;

import java.lang.annotation.Annotation;
import java.util.Collection;
import java.util.Collections;
import java.util.concurrent.Callable;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.context.ConversationScoped;
import javax.enterprise.context.RequestScoped;
import javax.enterprise.context.SessionScoped;
import javax.enterprise.context.spi.CreationalContext;
import javax.enterprise.event.Event;
import javax.enterprise.inject.Instance;
import javax.enterprise.inject.spi.AnnotatedType;
import javax.enterprise.inject.spi.Bean;
import javax.enterprise.inject.spi.BeanManager;
import javax.enterprise.inject.spi.InjectionTarget;
import javax.inject.Singleton;

import org.apache.webbeans.config.WebBeansContext;
import org.apache.webbeans.spi.ContainerLifecycle;
import org.apache.webbeans.spi.ContextsService;
import org.ops4j.lang.Ops4jException;
import org.ops4j.pax.cdi.spi.AbstractCdiContainer;
import org.ops4j.pax.cdi.spi.CdiContainer;
import org.ops4j.pax.cdi.spi.CdiContainerType;
import org.osgi.framework.Bundle;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * {@link CdiContainer} implementation wrapping an Apache OpenWebBeans container, represented by a
 * {@link WebBeansContext}.
 * 
 * @author Harald Wellmann
 * 
 */
public class OpenWebBeansCdiContainer extends AbstractCdiContainer {

    private static Logger log = LoggerFactory.getLogger(OpenWebBeansCdiContainer.class);

    /**
     * OpenWebBeans container lifecycle.
     */
    private ContainerLifecycle lifecycle;

    /**
     * Helper for accessing Instance and Event of CDI container.
     */
    private InstanceManager instanceManager;

    private WebBeansContext context;

    /**
     * Construct a CDI container for the given extended bundle.
     * 
     * @param ownBundle
     *            bundle containing this class
     * @param extendedBundle
     *            bundle to be extended with CDI container
     * @param extensionBundles
     *            CDI extension bundles to be loaded by OpenWebBeans
     */
    public OpenWebBeansCdiContainer(CdiContainerType containerType, Bundle ownBundle,
        Bundle extendedBundle, Collection extensionBundles) {
        super(containerType, extendedBundle, extensionBundles, Collections.singletonList(ownBundle));
        log.debug("creating OpenWebBeans CDI container for bundle {}", extendedBundle);
    }

    /**
     * Creates and starts a WebBeansContext for the given bundle using an appropriate class loader
     * as TCCL.
     * 
     * @param bundle
     * @return
     */
    private WebBeansContext createWebBeansContext(Bundle bundle, final Object environment) {
        buildContextClassLoader();
        try {
            return doWithClassLoader(getContextClassLoader(), new Callable() {

                @Override
                public WebBeansContext call() throws Exception {
                    WebBeansContext webBeansContext = WebBeansContext.currentInstance();
                    lifecycle = webBeansContext.getService(ContainerLifecycle.class);
                    lifecycle.startApplication(environment);
                    startContexts(webBeansContext);
                    return webBeansContext;
                }
            });
        }
        // CHECKSTYLE:SKIP
        catch (Exception exc) {
            throw new Ops4jException(exc);
        }
    }

    /**
     * Starts all CDI contexts.
     * 
     * @param webBeansContext
     */
    private void startContexts(WebBeansContext webBeansContext) {
        ContextsService contextService = lifecycle.getContextService();
        contextService.startContext(RequestScoped.class, null);
        contextService.startContext(ConversationScoped.class, null);
        contextService.startContext(SessionScoped.class, null);
        contextService.startContext(ApplicationScoped.class, null);
        contextService.startContext(Singleton.class, null);
    }

    /**
     * Stops all CDI contexts.
     */
    private void stopContexts() {
        ContextsService contextService = lifecycle.getContextService();
        contextService.endContext(RequestScoped.class, null);
        contextService.endContext(ConversationScoped.class, null);
        contextService.endContext(SessionScoped.class, null);
        contextService.endContext(ApplicationScoped.class, null);
        contextService.endContext(Singleton.class, null);
    }

    @Override
    protected void doStart(Object environment) {
        context = createWebBeansContext(getBundle(), environment);
        if (log.isDebugEnabled()) {
            for (Bean bean : context.getBeanManagerImpl().getBeans()) {
                log.debug("  {}", bean);
            }
        }
    }

    @Override
    protected void doStop() {
        try {
            doWithClassLoader(getContextClassLoader(), new Callable() {
                @Override
                public Void call() throws Exception {
                    if (lifecycle != null) {
                        stopContexts();
                        lifecycle.stopApplication(getContextClassLoader());
                    }
                    return null;
                }
            });
        }
        // CHECKSTYLE:SKIP
        catch (Exception exc) {
            throw new Ops4jException(exc);
        }
    }

    @Override
    public Event getEvent() {
        return getInstanceManager().getEvent();
    }

    @Override
    public BeanManager getBeanManager() {
        return lifecycle.getBeanManager();
    }

    @Override
    public Instance getInstance() {
        return getInstanceManager().getInstance();
    }

    private InstanceManager getInstanceManager() {
        if (instanceManager == null) {
            BeanManager beanManager = getBeanManager();
            instanceManager = new InstanceManager();
            AnnotatedType annotatedType = beanManager
                .createAnnotatedType(InstanceManager.class);
            InjectionTarget target = beanManager
                .createInjectionTarget(annotatedType);
            CreationalContext cc = beanManager.createCreationalContext(null);
            target.inject(instanceManager, cc);
        }
        return instanceManager;
    }

    @Override
    public  T unwrap(Class wrappedClass) {
        if (wrappedClass.isAssignableFrom(WebBeansContext.class)) {
            return wrappedClass.cast(context);
        }
        if (wrappedClass.isAssignableFrom(ContainerLifecycle.class)) {
            return wrappedClass.cast(lifecycle);
        }
        return null;
    }

    @Override
    public void startContext(Class scope) {
        ContextsService contextsService = context.getService(ContextsService.class);
        contextsService.startContext(scope, null);

    }

    @Override
    public void stopContext(Class scope) {
        ContextsService contextsService = context.getService(ContextsService.class);
        contextsService.endContext(scope, null);
    }
}