/* * 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 java.lang.annotation.Annotation; import java.util.Collection; import java.util.Collections; import java.util.concurrent.Callable; 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 org.apache.webbeans.config.WebBeansContext; import org.apache.webbeans.spi.ContainerLifecycle; import org.apache.webbeans.spi.ContextsService; import org.ops4j.pax.cdi.spi.AbstractCdiContainer; import org.ops4j.pax.cdi.spi.util.Exceptions; import org.osgi.framework.Bundle; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * {@code 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(Bundle ownBundle, Bundle extendedBundle, Collection<Bundle> extensionBundles) { super(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(final Object environment) { try { return doWithClassLoader(new Callable<WebBeansContext>() { @Override public WebBeansContext call() throws Exception { WebBeansContext webBeansContext = WebBeansContext.currentInstance(); lifecycle = webBeansContext.getService(ContainerLifecycle.class); lifecycle.startApplication(environment); return webBeansContext; } }); } // CHECKSTYLE:SKIP catch (Exception exc) { throw Exceptions.unchecked(exc); } } @Override protected void doStart(Object environment) { context = createWebBeansContext(environment); if (log.isDebugEnabled()) { for (Bean<?> bean : context.getBeanManagerImpl().getBeans()) { log.debug(" {}", bean); } } } @Override protected void doStop() { try { doWithClassLoader(new Callable<Void>() { @Override public Void call() throws Exception { if (lifecycle != null) { lifecycle.stopApplication(getContextClassLoader()); } return null; } }); } // CHECKSTYLE:SKIP catch (Exception exc) { throw Exceptions.unchecked(exc); } } @Override public Event<Object> getEvent() { return getInstanceManager().getEvent(); } @Override public BeanManager getBeanManager() { return lifecycle.getBeanManager(); } @Override public Instance<Object> getInstance() { return getInstanceManager().getInstance(); } private InstanceManager getInstanceManager() { if (instanceManager == null) { BeanManager beanManager = getBeanManager(); instanceManager = new InstanceManager(); AnnotatedType<InstanceManager> annotatedType = beanManager .createAnnotatedType(InstanceManager.class); InjectionTarget<InstanceManager> target = beanManager .createInjectionTarget(annotatedType); CreationalContext<InstanceManager> cc = beanManager.createCreationalContext(null); target.inject(instanceManager, cc); } return instanceManager; } @Override public <T> T unwrap(Class<T> 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<? extends Annotation> scope) { ContextsService contextsService = context.getService(ContextsService.class); contextsService.startContext(scope, null); } @Override public void stopContext(Class<? extends Annotation> scope) { ContextsService contextsService = context.getService(ContextsService.class); contextsService.endContext(scope, null); } }