| /* |
| * 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.myfaces.extension.scripting.weld.startup; |
| |
| import javassist.util.proxy.ProxyFactory; |
| import javassist.util.proxy.ProxyFactory.ClassLoaderProvider; |
| import org.jboss.weld.bootstrap.api.Bootstrap; |
| import org.jboss.weld.bootstrap.api.Environments; |
| import org.jboss.weld.environment.Container; |
| import org.jboss.weld.environment.ContainerContext; |
| import org.jboss.weld.environment.gwtdev.GwtDevHostedModeContainer; |
| import org.jboss.weld.environment.jetty.Jetty6Container; |
| import org.jboss.weld.environment.jetty.Jetty7Container; |
| import org.jboss.weld.environment.jetty.JettyPost72Container; |
| import org.jboss.weld.environment.servlet.deployment.ServletDeployment; |
| import org.jboss.weld.environment.servlet.deployment.URLScanner; |
| import org.jboss.weld.environment.servlet.deployment.VFSURLScanner; |
| import org.jboss.weld.environment.servlet.services.ServletResourceInjectionServices; |
| import org.jboss.weld.environment.servlet.util.Reflections; |
| import org.jboss.weld.environment.servlet.util.ServiceLoader; |
| import org.jboss.weld.environment.tomcat.Tomcat6Container; |
| import org.jboss.weld.environment.tomcat7.Tomcat7Container; |
| 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; |
| |
| import javax.el.ELContextListener; |
| import javax.enterprise.inject.spi.BeanManager; |
| import javax.servlet.ServletContext; |
| import javax.servlet.ServletContextEvent; |
| import javax.servlet.jsp.JspApplicationContext; |
| import javax.servlet.jsp.JspFactory; |
| import java.util.Arrays; |
| |
| /** |
| * @author Pete Muir |
| * @author Ales Justin |
| */ |
| public class Listener extends ForwardingServletListener { |
| private static final Logger log = LoggerFactory.getLogger(Listener.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"; |
| 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 Container container; |
| |
| public Listener() { |
| 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(); |
| |
| if (container != null) |
| container.destroy(new ContainerContext(sce, null)); |
| |
| super.contextDestroyed(sce); |
| } |
| |
| /** |
| * Create server deployment. |
| * <p> </p> |
| * Can be overridden with custom servlet deployment. |
| * e.g. exact resources listing in ristricted wnv like GAE |
| * |
| * @param context the servlet context |
| * @param bootstrap the bootstrap |
| * @return new servlet deployment |
| */ |
| protected ServletDeployment createServletDeployment(ServletContext context, Bootstrap bootstrap) { |
| return new ServletDeployment(context, bootstrap); |
| } |
| |
| /** |
| * Get appropriate scanner. |
| * Return null to leave it to defaults. |
| * |
| * @param classLoader the classloader |
| * @param context the servlet context |
| * @return custom url scanner or null if we should use default |
| */ |
| protected URLScanner createUrlScanner(ClassLoader classLoader, ServletContext context) { |
| try { |
| classLoader.loadClass("org.jboss.virtual.VFS"); // check if we can use JBoss VFS |
| return new VFSURLScanner(classLoader); |
| } catch (Throwable t) { |
| return null; |
| } |
| } |
| |
| @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(); |
| } |
| |
| }; |
| |
| ClassLoader classLoader = Reflections.getClassLoader(); |
| ServletContext context = sce.getServletContext(); |
| |
| URLScanner scanner = createUrlScanner(classLoader, context); |
| if (scanner != null) { |
| context.setAttribute(URLScanner.class.getName(), scanner); |
| } |
| |
| ServletDeployment deployment = createServletDeployment(context, 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(); |
| WeldManager manager = bootstrap.getManager(deployment.getWebAppBeanDeploymentArchive()); |
| |
| ContainerContext cc = new ContainerContext(sce, manager); |
| StringBuilder dump = new StringBuilder(); |
| Container container = findContainer(cc, dump); |
| if (container == null) { |
| log.info("No supported servlet container detected, CDI injection will NOT be available" + |
| " in Servlets, Filters or Listeners"); |
| if (log.isDebugEnabled()) |
| log.debug("Exception dump from Container lookup: " + dump); |
| } else { |
| container.initialize(cc); |
| this.container = container; |
| } |
| |
| // Push the manager into the servlet context so we can access in JSF |
| context.setAttribute(BEAN_MANAGER_ATTRIBUTE_NAME, manager); |
| |
| if (JspFactory.getDefaultFactory() != null) { |
| JspApplicationContext jspApplicationContext = JspFactory.getDefaultFactory(). |
| getJspApplicationContext(context); |
| |
| // 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 |
| context.setAttribute(EXPRESSION_FACTORY_NAME, manager.wrapExpressionFactory( |
| jspApplicationContext.getExpressionFactory())); |
| } |
| |
| bootstrap.deployBeans().validateBeans().endInitialization(); |
| super.contextInitialized(sce); |
| } |
| |
| @Override |
| protected ServletListener delegate() { |
| return weldListener; |
| } |
| |
| /** |
| * Find container env. |
| * |
| * @param cc the container context |
| * @param dump the exception dump |
| * @return valid container or null |
| */ |
| protected Container findContainer(ContainerContext cc, StringBuilder dump) { |
| Iterable<Container> extContainers = ServiceLoader.load(Container.class, getClass().getClassLoader()); |
| Container container = checkContainers(cc, dump, extContainers); |
| if (container == null) |
| container = checkContainers(cc, dump, Arrays.asList( |
| // Needs to be first: gwt-dev jar has tomcat classes but uses jetty |
| GwtDevHostedModeContainer.INSTANCE, |
| Tomcat7Container.INSTANCE, |
| Tomcat6Container.INSTANCE, |
| Jetty6Container.INSTANCE, |
| JettyPost72Container.INSTANCE, |
| Jetty7Container.INSTANCE) |
| ); |
| return container; |
| } |
| |
| protected Container checkContainers(ContainerContext cc, StringBuilder dump, Iterable<Container> containers) { |
| for (Container c : containers) { |
| try { |
| if (c.touch(cc)) |
| return c; |
| } catch (Throwable t) { |
| dump.append(c).append("->").append(t.getMessage()).append("\n"); |
| } |
| } |
| return null; |
| } |
| } |