/*
* 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 CDIServletStateListener extends ForwardingServletListener {
private static final Logger log = LoggerFactory.getLogger(CDIServletStateListener.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 CDIServletStateListener() {
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 AbstractInjector 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);
bootstrap.deployBeans().endInitialization();
super.contextInitialized(sce);
}
@Override
protected ServletListener delegate() {
return weldListener;
}
private void attachErraiBus() {
}
}