375096 If starting a server instance fails in osgi it is cleaned up.

This commit is contained in:
Jan Bartel 2012-03-26 22:48:50 +11:00
parent 241997b449
commit 72951403d3
4 changed files with 336 additions and 340 deletions

View File

@ -88,7 +88,7 @@ public class DefaultJettyAtJettyHomeHelper {
* that might use them as part of their properties.
* </p>
*/
public static void startJettyAtJettyHome(BundleContext bundleContext)
public static void startJettyAtJettyHome(BundleContext bundleContext) throws Exception
{
String jettyHomeSysProp = System.getProperty(SYS_PROP_JETTY_HOME);
String jettyHomeBundleSysProp = System.getProperty(SYS_PROP_JETTY_HOME_BUNDLE);
@ -137,8 +137,7 @@ public class DefaultJettyAtJettyHomeHelper {
LOG.warn("No default jetty started.");
return;
}
try
{
Server server = new Server();
Dictionary properties = new Hashtable();
properties.put(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME, OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME);
@ -156,11 +155,7 @@ public class DefaultJettyAtJettyHomeHelper {
bundleContext.registerService(Server.class.getName(), server, properties);
// hookNestedConnectorToBridgeServlet(server);
}
catch (Throwable t)
{
t.printStackTrace();
}
}
/**

View File

@ -18,25 +18,30 @@ import java.util.Properties;
import org.eclipse.jetty.osgi.boot.OSGiServerConstants;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.util.log.Log;
import org.eclipse.jetty.util.log.Logger;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
/**
* Deploy the jetty server instances when they are registered as an OSGi service.
* Deploy the jetty server instances when they are registered as an OSGi
* service.
*/
public class JettyServerServiceTracker implements ServiceListener, IManagedJettyServerRegistry
{
private static Logger LOG = Log.getLogger(JettyServerServiceTracker.class.getName());
/**
* Servers indexed by PIDs. PIDs are generated by the ConfigurationAdmin service.
* Servers indexed by PIDs. PIDs are generated by the ConfigurationAdmin
* service.
*/
private Map<String, ServerInstanceWrapper> _serversIndexedByName = new HashMap<String, ServerInstanceWrapper>();
/** The context-handler to deactivate indexed by ServerInstanceWrapper */
private Map<ServiceReference, ServerInstanceWrapper> _indexByServiceReference = new HashMap<ServiceReference, ServerInstanceWrapper>();
/**
* Stops each one of the registered servers.
*/
@ -51,17 +56,15 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
}
catch (Throwable t)
{
LOG.warn(t);
}
}
}
/**
* Receives notification that a service has had a lifecycle change.
*
* @param ev
* The <code>ServiceEvent</code> object.
* @param ev The <code>ServiceEvent</code> object.
*/
public void serviceChanged(ServiceEvent ev)
{
@ -80,8 +83,7 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
LOG.warn(e);
}
}
}
@ -95,6 +97,8 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
// we can register it.
}
case ServiceEvent.REGISTERED:
{
try
{
Bundle contributor = sr.getBundle();
Server server = (Server) contributor.getBundleContext().getService(sr);
@ -106,6 +110,11 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
props.put(key, value);
}
wrapper.start(server, props);
}
catch (Exception e)
{
LOG.warn(e);
}
break;
}
}
@ -114,11 +123,7 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
private ServerInstanceWrapper registerInIndex(Server server, ServiceReference sr)
{
String name = (String) sr.getProperty(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
if (name == null)
{
throw new IllegalArgumentException("The property " +
OSGiServerConstants.MANAGED_JETTY_SERVER_NAME + " is mandatory");
}
if (name == null) { throw new IllegalArgumentException("The property " + OSGiServerConstants.MANAGED_JETTY_SERVER_NAME + " is mandatory"); }
ServerInstanceWrapper wrapper = new ServerInstanceWrapper(name);
_indexByServiceReference.put(sr, wrapper);
_serversIndexedByName.put(name, wrapper);
@ -149,13 +154,12 @@ public class JettyServerServiceTracker implements ServiceListener, IManagedJetty
/**
* @param managedServerName The server name
* @return the corresponding jetty server wrapped with its deployment properties.
* @return the corresponding jetty server wrapped with its deployment
* properties.
*/
public ServerInstanceWrapper getServerInstanceWrapper(String managedServerName)
{
return _serversIndexedByName.get(managedServerName == null
? OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME : managedServerName);
return _serversIndexedByName.get(managedServerName == null ? OSGiServerConstants.MANAGED_JETTY_SERVER_DEFAULT_NAME : managedServerName);
}
}

View File

@ -106,8 +106,15 @@ public class JettyServersManagedFactory implements ManagedServiceFactory, IManag
_serversIndexedByPID.put(pid, serverInstanceWrapper);
_serversNameIndexedByPID.put(pid, name);
_serversPIDIndexedByName.put(name, pid);
try
{
serverInstanceWrapper.start(new Server(), properties);
}
catch (Exception e)
{
throw new ConfigurationException(null, "Error starting jetty server instance", e);
}
}
public synchronized void deleted(String pid)
{

View File

@ -44,21 +44,21 @@ import org.eclipse.jetty.util.resource.Resource;
import org.eclipse.jetty.xml.XmlConfiguration;
import org.xml.sax.SAXParseException;
/**
* Exposes a Jetty Server to be managed by an OSGi ManagedServiceFactory
* Configure and start it.
* Can also be used from the ManagedServiceFactory
* Configure and start it. Can also be used from the ManagedServiceFactory
*/
public class ServerInstanceWrapper {
public class ServerInstanceWrapper
{
/** The value of this property points to the parent director of
* the jetty.xml configuration file currently executed.
* Everything is passed as a URL to support the
* case where the bundle is zipped. */
/**
* The value of this property points to the parent director of the jetty.xml
* configuration file currently executed. Everything is passed as a URL to
* support the case where the bundle is zipped.
*/
public static final String PROPERTY_THIS_JETTY_XML_FOLDER_URL = "this.jetty.xml.parent.folder.url";
private static Logger __logger = Log.getLogger(ServerInstanceWrapper.class.getName());
private static Logger LOG = Log.getLogger(ServerInstanceWrapper.class.getName());
private final String _managedServerName;
@ -66,6 +66,7 @@ public class ServerInstanceWrapper {
* The managed jetty server
*/
private Server _server;
private ContextHandlerCollection _ctxtHandler;
/**
@ -74,12 +75,13 @@ public class ServerInstanceWrapper {
* let the TldScanner find the jars where the tld files are.
*/
private ClassLoader _commonParentClassLoaderForWebapps;
private DeploymentManager _deploymentManager;
private OSGiAppProvider _provider;
private WebBundleDeployerHelper _webBundleDeployerHelper;
public ServerInstanceWrapper(String managedServerName)
{
_managedServerName = managedServerName;
@ -91,8 +93,9 @@ public class ServerInstanceWrapper {
}
/**
* The classloader that should be the parent classloader for
* each webapp deployed on this server.
* The classloader that should be the parent classloader for each webapp
* deployed on this server.
*
* @return
*/
public ClassLoader getParentClassLoaderForWebapps()
@ -116,13 +119,11 @@ public class ServerInstanceWrapper {
return _provider;
}
public Server getServer()
{
return _server;
}
public WebBundleDeployerHelper getWebBundleDeployerHelp()
{
return _webBundleDeployerHelper;
@ -136,8 +137,7 @@ public class ServerInstanceWrapper {
return _ctxtHandler;
}
public void start(Server server, Dictionary props)
public void start(Server server, Dictionary props) throws Exception
{
_server = server;
ClassLoader contextCl = Thread.currentThread().getContextClassLoader();
@ -147,16 +147,9 @@ public class ServerInstanceWrapper {
// makes sure there is access to all the jetty's bundles
ClassLoader libExtClassLoader = null;
String sharedURLs = (String) props.get(OSGiServerConstants.MANAGED_JETTY_SHARED_LIB_FOLDER_URLS);
try
{
List<File> shared = sharedURLs != null ? extractFiles(sharedURLs) : null;
libExtClassLoader = LibExtClassLoaderHelper.createLibExtClassLoader(
shared, null, server, JettyBootstrapActivator.class.getClassLoader());
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
libExtClassLoader = LibExtClassLoaderHelper.createLibExtClassLoader(shared, null, server, JettyBootstrapActivator.class.getClassLoader());
Thread.currentThread().setContextClassLoader(libExtClassLoader);
@ -164,44 +157,50 @@ public class ServerInstanceWrapper {
init();
//now that we have an app provider we can call the registration customizer.
try
{
URL[] jarsWithTlds = getJarsWithTlds();
_commonParentClassLoaderForWebapps = jarsWithTlds == null
? libExtClassLoader
:new TldLocatableURLClassloader(libExtClassLoader,jarsWithTlds);
}
catch (MalformedURLException e)
{
e.printStackTrace();
}
// now that we have an app provider we can call the registration
// customizer.
URL[] jarsWithTlds = getJarsWithTlds();
_commonParentClassLoaderForWebapps = jarsWithTlds == null ? libExtClassLoader : new TldLocatableURLClassloader(libExtClassLoader, jarsWithTlds);
server.start();
_webBundleDeployerHelper = new WebBundleDeployerHelper(this);
}
catch (Throwable t)
catch (Exception e)
{
t.printStackTrace();
if (server != null)
{
try
{
server.stop();
}
catch (Exception x)
{
LOG.ignore(x);
}
}
throw e;
}
finally
{
Thread.currentThread().setContextClassLoader(contextCl);
}
_webBundleDeployerHelper = new WebBundleDeployerHelper(this);
}
}
public void stop()
{
try {
try
{
if (_server.isRunning())
{
_server.stop();
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
catch (Exception e)
{
LOG.warn(e);
}
}
@ -235,8 +234,7 @@ public class ServerInstanceWrapper {
URL[] urls = regCustomizer.getJarsWithTlds(_provider, WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER);
for (URL url : urls)
{
if (!res.contains(url))
res.add(url);
if (!res.contains(url)) res.add(url);
}
}
if (!res.isEmpty())
@ -248,12 +246,8 @@ public class ServerInstanceWrapper {
private void configure(Server server, Dictionary props) throws Exception
{
String jettyConfigurationUrls = (String) props.get(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS);
List<URL> jettyConfigurations = jettyConfigurationUrls != null
? extractResources(jettyConfigurationUrls) : null;
if (jettyConfigurations == null || jettyConfigurations.isEmpty())
{
return;
}
List<URL> jettyConfigurations = jettyConfigurationUrls != null ? extractResources(jettyConfigurationUrls) : null;
if (jettyConfigurations == null || jettyConfigurations.isEmpty()) { return; }
Map<String, Object> id_map = new HashMap<String, Object>();
id_map.put("Server", server);
Map<String, String> properties = new HashMap<String, String>();
@ -276,8 +270,10 @@ public class ServerInstanceWrapper {
XmlConfiguration config = new XmlConfiguration(is);
config.getIdMap().putAll(id_map);
//#334062 compute the URL of the folder that contains the jetty.xml conf file
//and set it as a property so we can compute relative paths from it.
// #334062 compute the URL of the folder that contains the
// jetty.xml conf file
// and set it as a property so we can compute relative paths
// from it.
String urlPath = jettyConfiguration.toString();
int lastSlash = urlPath.lastIndexOf('/');
if (lastSlash > 4)
@ -296,7 +292,7 @@ public class ServerInstanceWrapper {
}
catch (SAXParseException saxparse)
{
__logger.warn("Unable to configure the jetty/etc file " + jettyConfiguration,saxparse);
LOG.warn("Unable to configure the jetty/etc file " + jettyConfiguration, saxparse);
throw saxparse;
}
finally
@ -307,7 +303,6 @@ public class ServerInstanceWrapper {
}
/**
* Must be called after the server is configured.
*
@ -341,28 +336,26 @@ public class ServerInstanceWrapper {
try
{
_provider = new OSGiAppProvider();
_provider.setMonitoredDirResource(
Resource.newResource(getDefaultOSGiContextsHome(
new File(System.getProperty("jetty.home"))).toURI()));
} catch (IOException e) {
e.printStackTrace();
_provider.setMonitoredDirResource(Resource.newResource(getDefaultOSGiContextsHome(new File(System.getProperty("jetty.home"))).toURI()));
}
catch (IOException e)
{
LOG.warn(e);
}
_deploymentManager.addAppProvider(_provider);
}
}
if (_ctxtHandler == null || _provider==null)
throw new IllegalStateException("ERROR: No ContextHandlerCollection or OSGiAppProvider configured");
if (_ctxtHandler == null || _provider == null) throw new IllegalStateException("ERROR: No ContextHandlerCollection or OSGiAppProvider configured");
}
/**
* @return The default folder in which the context files of the osgi bundles
* are located and watched. Or null when the system property
* "jetty.osgi.contexts.home" is not defined.
* If the configuration file defines the OSGiAppProvider's context.
* This will not be taken into account.
* "jetty.osgi.contexts.home" is not defined. If the configuration
* file defines the OSGiAppProvider's context. This will not be
* taken into account.
*/
File getDefaultOSGiContextsHome(File jettyHome)
{
@ -370,10 +363,9 @@ public class ServerInstanceWrapper {
if (jettyContextsHome != null)
{
File contextsHome = new File(jettyContextsHome);
if (!contextsHome.exists() || !contextsHome.isDirectory())
{
throw new IllegalArgumentException("the ${jetty.osgi.contexts.home} '" + jettyContextsHome + " must exist and be a folder");
}
if (!contextsHome.exists() || !contextsHome.isDirectory()) { throw new IllegalArgumentException(
"the ${jetty.osgi.contexts.home} '" + jettyContextsHome
+ " must exist and be a folder"); }
return contextsHome;
}
return new File(jettyHome, "/contexts");
@ -396,19 +388,19 @@ public class ServerInstanceWrapper {
String tok = tokenizer.nextToken();
try
{
urls.add(((DefaultFileLocatorHelper) WebBundleDeployerHelper
.BUNDLE_FILE_LOCATOR_HELPER).getLocalURL(new URL(tok)));
urls.add(((DefaultFileLocatorHelper) WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER).getLocalURL(new URL(tok)));
}
catch (Throwable mfe)
{
LOG.warn(mfe);
}
}
return urls;
}
/**
* Get the folders that might contain jars for the legacy J2EE shared libraries
* Get the folders that might contain jars for the legacy J2EE shared
* libraries
*/
private List<File> extractFiles(String propertyValue)
{
@ -420,8 +412,7 @@ public class ServerInstanceWrapper {
try
{
URL url = new URL(tok);
url = ((DefaultFileLocatorHelper) WebBundleDeployerHelper
.BUNDLE_FILE_LOCATOR_HELPER).getFileURL(url);
url = ((DefaultFileLocatorHelper) WebBundleDeployerHelper.BUNDLE_FILE_LOCATOR_HELPER).getFileURL(url);
if (url.getProtocol().equals("file"))
{
Resource res = Resource.newResource(url);
@ -434,11 +425,10 @@ public class ServerInstanceWrapper {
}
catch (Throwable mfe)
{
LOG.warn(mfe);
}
}
return files;
}
}