All Downloads are FREE. Search and download functionalities are using the official Maven repository.
Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.fabric3.container.web.jetty.JettyWebApplicationActivator Maven / Gradle / Ivy
/*
* Fabric3
* Copyright (c) 2009-2015 Metaform Systems
*
* 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.
* Portions originally based on Apache Tuscany 2007
* licensed under the Apache 2.0 license.
*/
package org.fabric3.container.web.jetty;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.net.URI;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.jetty.annotations.AnnotationConfiguration;
import org.eclipse.jetty.servlet.ServletHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.eclipse.jetty.util.resource.ResourceCollection;
import org.eclipse.jetty.webapp.Configuration;
import org.eclipse.jetty.webapp.FragmentConfiguration;
import org.eclipse.jetty.webapp.JettyWebXmlConfiguration;
import org.eclipse.jetty.webapp.MetaInfConfiguration;
import org.eclipse.jetty.webapp.WebAppClassLoader;
import org.eclipse.jetty.webapp.WebAppContext;
import org.eclipse.jetty.webapp.WebInfConfiguration;
import org.eclipse.jetty.webapp.WebXmlConfiguration;
import org.fabric3.api.annotation.monitor.Monitor;
import org.fabric3.container.web.spi.InjectingSessionListener;
import org.fabric3.container.web.spi.WebApplicationActivationException;
import org.fabric3.container.web.spi.WebApplicationActivator;
import org.fabric3.spi.classloader.ClassLoaderRegistry;
import org.fabric3.spi.classloader.MultiParentClassLoader;
import org.fabric3.spi.container.objectfactory.Injector;
import org.fabric3.spi.container.objectfactory.ObjectCreationException;
import org.fabric3.spi.contribution.ContributionResolver;
import org.fabric3.spi.management.ManagementException;
import org.fabric3.spi.management.ManagementService;
import org.fabric3.transport.jetty.JettyService;
import org.oasisopen.sca.ComponentContext;
import org.oasisopen.sca.annotation.Destroy;
import org.oasisopen.sca.annotation.Reference;
/**
* Activates a web application in an embedded Jetty instance.
*/
public class JettyWebApplicationActivator implements WebApplicationActivator {
private JettyService jettyService;
private ClassLoaderRegistry classLoaderRegistry;
private ContributionResolver resolver;
private ManagementService managementService;
private WebApplicationActivatorMonitor monitor;
private Map mappings;
public JettyWebApplicationActivator(@Reference JettyService jettyService,
@Reference ClassLoaderRegistry classLoaderRegistry,
@Reference ContributionResolver resolver,
@Reference ManagementService managementService,
@Monitor WebApplicationActivatorMonitor monitor) {
this.jettyService = jettyService;
this.classLoaderRegistry = classLoaderRegistry;
this.resolver = resolver;
this.managementService = managementService;
this.monitor = monitor;
mappings = new ConcurrentHashMap<>();
}
@Destroy
public void destroy() {
for (Holder holder : mappings.values()) {
try {
remove(holder.getContext());
} catch (ManagementException e) {
monitor.error("Error removing managed bean for context: " + holder.getContext().getDisplayName(), e);
}
}
}
public ClassLoader getWebComponentClassLoader(URI componentId) {
return classLoaderRegistry.getClassLoader(componentId);
}
@SuppressWarnings({"unchecked"})
public ServletContext activate(String contextPath,
final URI uri,
URI parentClassLoaderId,
final Map>> injectors,
ComponentContext componentContext) throws WebApplicationActivationException {
if (mappings.containsKey(uri)) {
throw new WebApplicationActivationException("Mapping already exists: " + uri.toString());
}
try {
// resolve the url to a local artifact
List locations = resolver.resolveAllLocations(uri);
ClassLoader parentClassLoader = createParentClassLoader(parentClassLoaderId, uri);
final WebAppContext context = createWebAppContext("/" + contextPath, injectors, locations, parentClassLoader);
// Use a ServletContextListener to setup session injectors and perform context injection.
// Note context injection must be done here since servlet filters may rely on SCA reference proxies, c.f. FABRICTHREE-570
context.addEventListener(new ServletContextListener() {
public void contextInitialized(ServletContextEvent sce) {
// Setup the session listener to inject reference proxies in newly created sessions
// Note the listener must be added after the context is started as Jetty web xml configurer clears event listeners
List> sessionInjectors = List.class.cast(injectors.get(SESSION_CONTEXT_SITE));
InjectingSessionListener listener = new InjectingSessionListener(sessionInjectors);
context.getSessionHandler().addEventListener(listener);
ServletContext servletContext = context.getServletContext();
try {
injectServletContext(servletContext, injectors);
} catch (ObjectCreationException e) {
monitor.error("Error initializing web component: " + uri, e);
}
}
// remove all the registered Listeners
// Note the listeners must also be unregistered , c.f. FABRICTHREE-630
public void contextDestroyed(ServletContextEvent sce) {
context.getSessionHandler().clearEventListeners();
}
});
jettyService.registerHandler(context); // the context needs to be registered before it is started
context.start();
ServletContext servletContext = context.getServletContext();
Holder holder = new Holder(contextPath, context);
mappings.put(uri, holder);
export(context);
monitor.activated(holder.getContextPath());
return servletContext;
} catch (Exception e) {
throw new WebApplicationActivationException(e);
}
}
public void deactivate(URI uri) throws WebApplicationActivationException {
Holder holder = mappings.remove(uri);
if (holder == null) {
throw new WebApplicationActivationException("Mapping does not exist: " + uri.toString());
}
WebAppContext context = holder.getContext();
jettyService.getServer().removeBean(context);
try {
remove(context);
// Stop must called be after remove() as it releases servlets which are accessed by the latter to
// unregister them from the MBean server
context.stop();
} catch (Exception e) {
throw new WebApplicationActivationException(e);
}
context.setClassLoader(null);
jettyService.removeHandler(context);
monitor.deactivated(holder.getContextPath());
}
private ClassLoader createParentClassLoader(URI parentClassLoaderId, URI id) {
ClassLoader cl = classLoaderRegistry.getClassLoader(parentClassLoaderId);
MultiParentClassLoader parentClassLoader = new MultiParentClassLoader(id, cl);
// we need to make user and web container extensions available for JSP compilation
parentClassLoader.addParent(getClass().getClassLoader());
return parentClassLoader;
}
private WebAppContext createWebAppContext(String contextPath, Map>> injectors, List locations, ClassLoader parentClassLoader)
throws IOException {
WebAppContext context;
if (locations.size() == 1) {
context = new ManagedWebAppContext(locations.get(0).toExternalForm(), contextPath);
} else {
context = new ManagedWebAppContext(null, contextPath);
// add the resource paths
String[] paths = new String[locations.size()];
for (int i = 0; i < locations.size(); i++) {
URL location = locations.get(i);
paths[i] = (location.toExternalForm());
}
ResourceCollection resources = new ResourceCollection(paths);
context.setBaseResource(resources);
}
context.setParentLoaderPriority(true);
InjectingDecorator decorator = new InjectingDecorator(injectors);
context.addDecorator(decorator);
WebAppClassLoader webAppClassLoader = new WebAppClassLoader(parentClassLoader, context);
context.setClassLoader(webAppClassLoader);
// don't extract the war since this has already been done by the WAR classpath processor
context.setExtractWAR(false);
Configuration[] configurations = createConfigurations();
context.setConfigurations(configurations);
return context;
}
@SuppressWarnings({"unchecked"})
private void injectServletContext(ServletContext servletContext, Map>> injectors) throws ObjectCreationException {
List> list = injectors.get(SERVLET_CONTEXT_SITE);
if (list == null) {
// nothing to inject
return;
}
for (Injector injector : list) {
injector.inject(servletContext);
}
}
private void export(WebAppContext context) throws ManagementException {
String displayName = context.getDisplayName();
if (displayName == null) {
displayName = UUID.randomUUID().toString();
}
String webAppName = encodeName(displayName);
managementService.export(webAppName, "webapps/" + webAppName, "web application", context);
ServletHandler handler = context.getServletHandler();
for (ServletHolder servletHolder : handler.getServlets()) {
final String group = "webapps/" + webAppName + "/servlets";
managementService.export(webAppName + "/" + servletHolder.getName(), group, "web application", servletHolder);
}
}
private void remove(WebAppContext context) throws ManagementException {
String displayName = context.getDisplayName();
if (displayName == null) {
displayName = context.toString();
}
String webAppName = encodeName(displayName);
managementService.remove(webAppName, "webapps/" + webAppName);
ServletHandler handler = context.getServletHandler();
for (ServletHolder servletHolder : handler.getServlets()) {
final String group = "webapps/" + webAppName + "/servlets";
managementService.remove(webAppName + "/" + servletHolder.getName(), group);
}
}
private String encodeName(String name) {
return name.toLowerCase().replace('\n', ' ');
}
/**
* Creates Jetty configurations, overriding the default WebInfConfiguration to not scan library resources and create duplicates (the resources are already
* on the classpath).
*
* @return the configuration
*/
private Configuration[] createConfigurations() {
WebInfConfiguration webInfConfig = new NonScanningWebInfConfiguration();
WebXmlConfiguration webXmlConfig = new WebXmlConfiguration();
MetaInfConfiguration metaInfConfig = new MetaInfConfiguration();
FragmentConfiguration fragmentConfig = new FragmentConfiguration();
JettyWebXmlConfiguration jettyXmlConfig = new JettyWebXmlConfiguration();
AnnotationConfiguration annotationConfig = new AnnotationConfiguration();
return new Configuration[]{webInfConfig, webXmlConfig, metaInfConfig, fragmentConfig, jettyXmlConfig, annotationConfig};
}
private static class Holder {
private String contextPath;
private WebAppContext context;
private Holder(String contextPath, WebAppContext context) {
this.contextPath = contextPath;
this.context = context;
}
public String getContextPath() {
return contextPath;
}
public WebAppContext getContext() {
return context;
}
}
}