blob: f1a497ce0530f3dba63f83fc7b501bdc9712d002 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2008, 2010 VMware Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware Inc. - initial contribution
*******************************************************************************/
package org.eclipse.virgo.web.core.internal;
import java.io.IOException;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import org.eclipse.virgo.kernel.deployer.core.DeploymentException;
import org.eclipse.virgo.kernel.install.artifact.BundleInstallArtifact;
import org.eclipse.virgo.kernel.install.artifact.InstallArtifact;
import org.eclipse.virgo.kernel.install.artifact.InstallArtifactLifecycleListenerSupport;
import org.eclipse.virgo.osgi.extensions.equinox.hooks.PluggableDelegatingClassLoaderDelegateHook;
import org.eclipse.gemini.web.core.WebApplication;
import org.eclipse.gemini.web.core.WebApplicationStartFailedException;
import org.eclipse.gemini.web.core.WebContainer;
import org.eclipse.virgo.util.osgi.manifest.BundleManifest;
import org.eclipse.virgo.web.core.WebApplicationRegistry;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.event.Event;
import org.osgi.service.event.EventConstants;
import org.osgi.service.event.EventHandler;
/**
* <strong>Concurrent Semantics</strong><br />
*
* Thread-safe.
*
*/
final class WebBundleLifecycleListener extends InstallArtifactLifecycleListenerSupport {
private static final String EMPTY_CONTEXT_PATH = "";
private static final String ROOT_CONTEXT_PATH = "/";
private final Map<InstallArtifact, WebApplication> webApplications = new ConcurrentHashMap<InstallArtifact, WebApplication>();
private final Map<Bundle, BundleInstallArtifact> webBundleInstallArtifacts = new ConcurrentHashMap<Bundle, BundleInstallArtifact>();
private final WebAppClassLoaderDelegateHook classLoaderDelegateHook = new WebAppClassLoaderDelegateHook();
private final EventHandler webBundleDeployedEventHandler = new WebBundleDeployedEventHandler();
private final WebDeploymentEnvironment environment;
private final BundleContext bundleContext;
private volatile ServiceRegistration<EventHandler> eventHandlerRegistration;
WebBundleLifecycleListener(WebDeploymentEnvironment environment, BundleContext bundleContext) {
this.environment = environment;
this.bundleContext = bundleContext;
}
public void init() {
PluggableDelegatingClassLoaderDelegateHook.getInstance().addDelegate(this.classLoaderDelegateHook);
registerEventHandler();
}
private void registerEventHandler() {
Dictionary<String, String> properties = new Hashtable<String, String>();
properties.put(EventConstants.EVENT_TOPIC, WebContainer.EVENT_DEPLOYED);
this.eventHandlerRegistration = this.bundleContext.registerService(EventHandler.class, this.webBundleDeployedEventHandler, properties);
}
public void destroy() {
PluggableDelegatingClassLoaderDelegateHook.getInstance().removeDelegate(this.classLoaderDelegateHook);
unregisterEventHandler();
}
private void unregisterEventHandler() {
ServiceRegistration<EventHandler> localRegistration = this.eventHandlerRegistration;
if (localRegistration != null) {
this.eventHandlerRegistration = null;
localRegistration.unregister();
}
}
/**
* {@inheritDoc}
*/
@Override
public void onStarting(InstallArtifact installArtifact) throws DeploymentException {
if (isWebBundle(installArtifact)) {
try {
this.webApplications.put(installArtifact, getWebContainer().createWebApplication(((BundleInstallArtifact)installArtifact).getBundle()));
} catch (BundleException be) {
throw new DeploymentException("Failed to create new web application for web bundle '" + installArtifact + "'.", be);
}
}
}
/**
* {@inheritDoc}
*/
@Override
public void onStarted(InstallArtifact installArtifact) throws DeploymentException {
WebApplication webApplication = this.webApplications.get(installArtifact);
if (webApplication != null) {
BundleInstallArtifact bundleInstallArtifact = (BundleInstallArtifact)installArtifact;
Bundle bundle = bundleInstallArtifact.getBundle();
this.webBundleInstallArtifacts.put(bundle, bundleInstallArtifact);
try {
//webApplication.start();
this.classLoaderDelegateHook.addWebApplication(bundle, the classloader of the web application from tomcat. Should be a BundleWebappClassLoader instance);
String contextPath = getContextPath(webApplication);
getApplicationRegistry().registerWebApplication(contextPath, getApplicationName(installArtifact));
installArtifact.setProperty("org.eclipse.virgo.web.contextPath", contextPath);
installArtifact.setProperty("artifact-type", "Web Bundle");
} catch (WebApplicationStartFailedException wasfe) {
throw new DeploymentException("Web application failed to start", wasfe);
}
}
}
public boolean isDeployed(Bundle webBundle){
return this.webBundleInstallArtifacts.containsKey(webBundle);
}
protected void webBundleDeployed(Bundle webBundle) {
BundleInstallArtifact installArtifact = this.webBundleInstallArtifacts.get(webBundle);
if (installArtifact != null) {
WebApplication webApplication = this.webApplications.get(installArtifact);
if (webApplication != null) {
}
}
}
/**
* {@inheritDoc}
*/
@Override
public void onStopping(InstallArtifact installArtifact) {
WebApplication webApplication = this.webApplications.remove(installArtifact);
if (webApplication != null) {
webApplication.stop();
getApplicationRegistry().unregisterWebApplication(getContextPath(webApplication));
this.webBundleInstallArtifacts.remove(((BundleInstallArtifact)installArtifact).getBundle());
}
}
private static boolean isWebBundle(InstallArtifact installArtifact) throws DeploymentException {
if (installArtifact instanceof BundleInstallArtifact) {
try {
BundleManifest bundleManifest = ((BundleInstallArtifact)installArtifact).getBundleManifest();
return (WebBundleTransformer.WEB_BUNDLE_MODULE_TYPE.equals(bundleManifest.getModuleType()));
} catch (IOException ioe) {
throw new DeploymentException("Failed to get bundle manifest from '" + installArtifact + "'", ioe);
}
}
return false;
}
private String getContextPath(WebApplication webApplication) {
String contextPath = webApplication.getServletContext().getContextPath();
if(EMPTY_CONTEXT_PATH.equals(contextPath)) {
return ROOT_CONTEXT_PATH;
}
return contextPath;
}
private WebContainer getWebContainer() {
return this.environment.getWebContainer();
}
private WebApplicationRegistry getApplicationRegistry() {
return this.environment.getApplicationRegistry();
}
private String getApplicationName(InstallArtifact installArtifact) {
return installArtifact.getName() + "-" + installArtifact.getVersion();
}
private final class WebBundleDeployedEventHandler implements EventHandler {
public void handleEvent(Event event) {
if (WebContainer.EVENT_DEPLOYED.equals(event.getTopic())) {
webBundleDeployed((Bundle)event.getProperty(EventConstants.BUNDLE));
}
}
}
}