/* * Copyright 2009 JBoss, a divison Red Hat, Inc * * 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.jboss.errai.container; import javassist.util.proxy.ProxyFactory; import javassist.util.proxy.ProxyFactory.ClassLoaderProvider; import javax.enterprise.inject.spi.BeanManager; import javax.servlet.ServletContextEvent; import org.jboss.weld.bootstrap.api.Bootstrap; import org.jboss.weld.bootstrap.api.Environments; import org.jboss.weld.environment.jetty.JettyWeldInjector; import org.jboss.weld.environment.servlet.Listener; import org.jboss.weld.environment.servlet.deployment.ServletDeployment; import org.jboss.weld.environment.servlet.services.ServletResourceInjectionServices; import org.jboss.weld.environment.servlet.util.Reflections; import org.jboss.weld.environment.tomcat.WeldForwardingAnnotationProcessor; import org.jboss.weld.environment.tomcat7.WeldForwardingInstanceManager; import org.jboss.weld.injection.spi.ResourceInjectionServices; import org.jboss.weld.manager.api.WeldManager; import org.jboss.weld.servlet.api.ServletListener; import org.jboss.weld.servlet.api.helpers.ForwardingServletListener; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author Pete Muir */ public class DevModeCDIBootstrap extends ForwardingServletListener { private static final Logger log = LoggerFactory.getLogger(DevModeCDIBootstrap.class); private static final String BOOTSTRAP_IMPL_CLASS_NAME = "org.jboss.weld.bootstrap.WeldBootstrap"; private static final String WELD_LISTENER_CLASS_NAME = "org.jboss.weld.servlet.WeldListener"; private static final String EXPRESSION_FACTORY_NAME = "org.jboss.weld.el.ExpressionFactory"; private static final String JETTY_REQUIRED_CLASS_NAME = "org.mortbay.jetty.servlet.ServletHandler"; public static final String INJECTOR_ATTRIBUTE_NAME = "org.jboss.weld.environment.jetty.JettyWeldInjector"; public static final String BEAN_MANAGER_ATTRIBUTE_NAME = Listener.class.getPackage().getName() + "." + BeanManager.class.getName(); private final transient Bootstrap bootstrap; private final transient ServletListener weldListener; private WeldManager manager; public DevModeCDIBootstrap() { try { bootstrap = Reflections.newInstance(BOOTSTRAP_IMPL_CLASS_NAME); } catch (IllegalArgumentException e) { throw new IllegalStateException("Error loading Weld bootstrap, check that Weld is on the classpath", e); } try { weldListener = Reflections.newInstance(WELD_LISTENER_CLASS_NAME); } catch (IllegalArgumentException e) { throw new IllegalStateException("Error loading Weld listener, check that Weld is on the classpath", e); } } @Override public void contextDestroyed(ServletContextEvent sce) { bootstrap.shutdown(); try { Reflections.classForName("org.apache.AnnotationProcessor"); WeldForwardingAnnotationProcessor.restoreAnnotationProcessor(sce); } catch (IllegalArgumentException ignore) {} try { Reflections.classForName(JETTY_REQUIRED_CLASS_NAME); sce.getServletContext().removeAttribute(INJECTOR_ATTRIBUTE_NAME); } catch (IllegalArgumentException ignore) {} super.contextDestroyed(sce); } @Override public void contextInitialized(ServletContextEvent sce) { // Make Javassist always use the TCCL to load classes ProxyFactory.classLoaderProvider = new ClassLoaderProvider() { public ClassLoader get(ProxyFactory pf) { return Thread.currentThread().getContextClassLoader(); } }; ServletDeployment deployment = new ServletDeployment(sce.getServletContext(), bootstrap); try { deployment.getWebAppBeanDeploymentArchive().getServices().add( ResourceInjectionServices.class, new ServletResourceInjectionServices() {}); } catch (NoClassDefFoundError e) { // Support GAE log.warn("@Resource injection not available in simple beans"); } bootstrap.startContainer(Environments.SERVLET, deployment).startInitialization(); manager = bootstrap.getManager(deployment.getWebAppBeanDeploymentArchive()); boolean tomcat = true; boolean tomcat7 = false; try { Reflections.classForName("org.apache.AnnotationProcessor"); } catch (IllegalArgumentException e) { tomcat = false; } if (tomcat) { try { WeldForwardingAnnotationProcessor.replaceAnnotationProcessor(sce, manager); log.info("Tomcat 6 detected, CDI injection will be available in Servlets and Filters. Injection into Listeners is not supported"); } catch (Exception e) { log.error("Unable to replace Tomcat AnnotationProcessor. CDI injection will not be available in Servlets, Filters, or Listeners", e); } } try { Reflections.classForName("org.apache.tomcat.InstanceManager"); tomcat7 = true; } catch (IllegalArgumentException e) { tomcat7 = false; } boolean jetty = true; try { Reflections.classForName(JETTY_REQUIRED_CLASS_NAME); } catch (IllegalArgumentException e) { jetty = false; } if (jetty) { // Try pushing a Jetty Injector into the servlet context try { Class<?> clazz = Reflections.classForName(JettyWeldInjector.class.getName()); Object injector = clazz.getConstructor(WeldManager.class).newInstance(manager); sce.getServletContext().setAttribute(INJECTOR_ATTRIBUTE_NAME, injector); log.info("Jetty detected, JSR-299 injection will be available in Servlets and Filters. Injection into Listeners is not supported."); } catch (Exception e) { log.error("Unable to create JettyWeldInjector. CDI injection will not be available in Servlets, Filters or Listeners", e); } } if (tomcat7) { try { WeldForwardingInstanceManager.replacInstanceManager(sce, manager); log.info("Tomcat 7 detected, CDI injection will be available in Servlets and Filters. Injection into Listeners is not supported"); } catch (Exception e) { log.error("Unable to replace Tomcat 7 AnnotationProcessor. CDI injection will not be available in Servlets, Filters, or Listeners", e); } } if (!tomcat && !jetty&&!tomcat7) { log.info("No supported servlet container detected, CDI injection will NOT be available in Servlets, Filtersor or Listeners"); } // Push the manager into the servlet context so we can access in JSF sce.getServletContext().setAttribute(BEAN_MANAGER_ATTRIBUTE_NAME, manager); /*if (JspFactory.getDefaultFactory() != null) { JspApplicationContext jspApplicationContext = JspFactory.getDefaultFactory().getJspApplicationContext(sce.getServletContext()); // Register the ELResolver with JSP jspApplicationContext.addELResolver(manager.getELResolver()); // Register ELContextListener with JSP jspApplicationContext.addELContextListener(Reflections.<ELContextListener> newInstance("org.jboss.weld.el.WeldELContextListener")); // Push the wrapped expression factory into the servlet context so that Tomcat or Jetty can hook it in using a container code sce.getServletContext().setAttribute(EXPRESSION_FACTORY_NAME, manager.wrapExpressionFactory(jspApplicationContext.getExpressionFactory())); } */ bootstrap.deployBeans().endInitialization(); super.contextInitialized(sce); } @Override protected ServletListener delegate() { return weldListener; } }