/* * Copyright 2013 eXo Platform SAS * * 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 juzu.impl.inject.spi.cdi; import juzu.Scope; import juzu.impl.plugin.application.Application; import juzu.impl.common.JSON; import juzu.impl.inject.spi.InjectionContext; import juzu.impl.common.Tools; import juzu.impl.inject.spi.cdi.provided.ProvidedCDIInjector; import juzu.impl.plugin.application.descriptor.ApplicationDescriptor; import juzu.impl.resource.ResourceResolver; import javax.enterprise.context.spi.CreationalContext; import javax.enterprise.event.Observes; import javax.enterprise.inject.spi.AfterBeanDiscovery; import javax.enterprise.inject.spi.AnnotatedType; import javax.enterprise.inject.spi.Bean; import javax.enterprise.inject.spi.BeanManager; import javax.enterprise.inject.spi.BeforeBeanDiscovery; import javax.enterprise.inject.spi.BeforeShutdown; import javax.enterprise.inject.spi.Extension; import javax.enterprise.inject.spi.ProcessAnnotatedType; import javax.enterprise.inject.spi.ProcessBean; import javax.inject.Singleton; import java.io.InputStream; import java.net.URL; import java.util.ArrayList; import java.util.List; /** * Juzu CDI extension. * * @author <a href="mailto:julien.viet@exoplatform.com">Julien Viet</a> */ public class ExtensionImpl implements Extension { /** . */ private CDIContext context; /** The singletons to shut down. */ private final List<Bean<?>> singletons; /** . */ private boolean configured; public ExtensionImpl() { this.context = CDIContext.boot.get(); this.singletons = new ArrayList<Bean<?>>(); this.configured = false; } void beforeBeanDiscovery(@Observes BeforeBeanDiscovery event, final BeanManager beanManager) { // We are in provided mode if (this.context == null) { // This is not really clean : it couples the inject to the application notion // but avoiding that would mean to introduce more complex stuff and so // it's fine for the moment try { final ClassLoader cl = Thread.currentThread().getContextClassLoader(); InputStream in = cl.getResourceAsStream("juzu/config.json"); //JUZU-42 check if this webapp is juzu or not if (in != null) { String serializedConfig = Tools.read(in); JSON config = (JSON)JSON.parse(serializedConfig); JSON applications = config.getJSON("application"); if (applications.names().size() != 1) { throw new RuntimeException("Was expecting application size to be 1 instead of " + applications); } String packageFQN = applications.names().iterator().next(); ApplicationDescriptor descriptor = ApplicationDescriptor.create(cl, packageFQN); // For now we don't resolve anything... ResourceResolver resourceResolver = new ResourceResolver() { public URL resolve(String uri) { return null; } }; // ProvidedCDIInjector injector = new ProvidedCDIInjector(cl, beanManager, descriptor, resourceResolver); // We start the application // it should: // - instantiate the plugins // - bind the beans from the plugins in the container // we rely on the lazy nature of the beans for not really starting... Application application = injector.getApplication(); application.start(); // At this point the application is not really started // we must go through the other CDI phases for effectively registering // the beans in the container this.context = (CDIContext)application.getInjectionContext(); } } catch (Exception e) { throw new UnsupportedOperationException(e); } } } <T> void processAnnotatedType(@Observes ProcessAnnotatedType<T> pat) { if (context != null) { AnnotatedType<T> annotatedType = pat.getAnnotatedType(); Class<T> type = annotatedType.getJavaClass(); // Determine if bean should be processed boolean veto = !context.filter.handle(type); if (!veto) { for (AbstractBean boundBean : context.injector.boundBeans) { Class<?> beanType = boundBean.getBeanClass(); if (beanType.isAssignableFrom(type)) { veto = true; break; } } } // if (veto) { pat.veto(); } } } void afterBeanDiscovery(@Observes AfterBeanDiscovery event, BeanManager beanManager) { if (context != null) { for (Scope scope : context.injector.scopes) { if (!scope.isBuiltIn()) { event.addContext(new ContextImpl(context.injector.scopeController, scope, scope.getAnnotationType())); } } // Add the manager event.addBean(new SingletonBean(InjectionContext.class, Tools.set(AbstractBean.DEFAULT_QUALIFIER, AbstractBean.ANY_QUALIFIER), context)); // Add bound beans for (AbstractBean bean : context.injector.boundBeans) { bean.register(beanManager); event.addBean(bean); } } } void processBean(@Observes ProcessBean event, BeanManager beanManager) { if (context != null) { Bean bean = event.getBean(); context.beans.add(bean); // if (bean.getScope() == Singleton.class) { singletons.add(bean); } } } public void beforeShutdown(@Observes BeforeShutdown event, BeanManager beanManager) { // Take care of destroying singletons for (Bean singleton : singletons) { CreationalContext cc = beanManager.createCreationalContext(singleton); Object o = beanManager.getReference(singleton, singleton.getBeanClass(), cc); singleton.destroy(o, cc); } } }