more code in progress to support multiple instances of jetty

git-svn-id: svn+ssh://dev.eclipse.org/svnroot/rt/org.eclipse.jetty/jetty/trunk@2030 7e9141cc-0065-0410-87d8-b60c137991c4
This commit is contained in:
Hugues Malphettes 2010-06-20 02:45:41 +00:00
parent 5e2110d894
commit dacfcc8903
5 changed files with 231 additions and 96 deletions

View File

@ -14,13 +14,10 @@
// ========================================================================
package org.eclipse.jetty.osgi.boot;
import java.net.URL;
import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Properties;
import java.util.StringTokenizer;
import org.eclipse.jetty.osgi.boot.internal.serverfactory.JettyServersManagedFactory;
import org.eclipse.jetty.osgi.boot.internal.webapp.JettyContextHandlerServiceTracker;
import org.eclipse.jetty.osgi.boot.internal.webapp.WebBundleTrackerCustomizer;
import org.eclipse.jetty.osgi.boot.utils.internal.PackageAdminServiceTracker;
@ -30,11 +27,7 @@ import org.eclipse.jetty.webapp.WebAppContext;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ManagedServiceFactory;
import org.osgi.util.tracker.BundleTracker;
/**
@ -74,7 +67,7 @@ public class JettyBootstrapActivator implements BundleActivator
private PackageAdminServiceTracker _packageAdminServiceTracker;
private BundleTracker _webBundleTracker;
private ServiceRegistration _jettyServerFactoryService;
// private ServiceRegistration _jettyServerFactoryService;
/**
@ -94,11 +87,11 @@ public class JettyBootstrapActivator implements BundleActivator
_packageAdminServiceTracker = new PackageAdminServiceTracker(context);
//Register the Jetty Server Factory as a ManagedServiceFactory:
Properties jettyServerMgdFactoryServiceProps = new Properties();
jettyServerMgdFactoryServiceProps.put("pid", OSGiWebappConstants.MANAGED_JETTY_SERVER_FACTORY_PID);
_jettyServerFactoryService = context.registerService(
ManagedServiceFactory.class.getName(), new JettyServersManagedFactory(),
jettyServerMgdFactoryServiceProps);
// Properties jettyServerMgdFactoryServiceProps = new Properties();
// jettyServerMgdFactoryServiceProps.put("pid", OSGiWebappConstants.MANAGED_JETTY_SERVER_FACTORY_PID);
// _jettyServerFactoryService = context.registerService(
// ManagedServiceFactory.class.getName(), new JettyServersManagedFactory(),
// jettyServerMgdFactoryServiceProps);
// todo: replace all this by the ManagedFactory so that we can start
@ -277,53 +270,5 @@ public class JettyBootstrapActivator implements BundleActivator
// todo
}
public static void createNewServer(Bundle contributor, String serverName, String urlsToJettyXml) throws Exception
{
ServiceReference configurationAdminReference =
contributor.getBundleContext().getServiceReference( ConfigurationAdmin.class.getName() );
ConfigurationAdmin confAdmin = (ConfigurationAdmin) contributor.getBundleContext()
.getService( configurationAdminReference );
Configuration configuration = confAdmin.createFactoryConfiguration(
OSGiWebappConstants.MANAGED_JETTY_SERVER_FACTORY_PID, contributor.getLocation() );
Dictionary properties = new Hashtable();
properties.put(OSGiWebappConstants.MANAGED_JETTY_SERVER_NAME, serverName);
StringBuilder actualBundleUrls = new StringBuilder();
StringTokenizer tokenizer = new StringTokenizer(urlsToJettyXml, ",", false);
while (tokenizer.hasMoreTokens())
{
if (actualBundleUrls.length() != 0)
{
actualBundleUrls.append(",");
}
String token = tokenizer.nextToken();
if (token.indexOf(':') != -1)
{
//a complete url. no change needed:
actualBundleUrls.append(token);
}
else if (token.startsWith("/"))
{
//url relative to the contributor bundle:
URL url = contributor.getEntry(token);
if (url == null)
{
actualBundleUrls.append(token);
}
else
{
actualBundleUrls.append(url.toString());
}
}
}
properties.put(OSGiWebappConstants.MANAGED_JETTY_XML_CONFIG_URLS, actualBundleUrls.toString());
configuration.update(properties);
}
}

View File

@ -0,0 +1,129 @@
// ========================================================================
// Copyright (c) 2009-2010 Intalio, Inc.
// ------------------------------------------------------------------------
// All rights reserved. This program and the accompanying materials
// are made available under the terms of the Eclipse Public License v1.0
// and Apache License v2.0 which accompanies this distribution.
// The Eclipse Public License is available at
// http://www.eclipse.org/legal/epl-v10.html
// The Apache License v2.0 is available at
// http://www.opensource.org/licenses/apache2.0.php
// You may elect to redistribute this code under either of these licenses.
// ========================================================================
package org.eclipse.jetty.osgi.boot.internal.serverfactory;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
import org.eclipse.jetty.server.Server;
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.
*/
public class JettyServerServiceTracker implements ServiceListener
{
/**
* 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>();
/**
* Receives notification that a service has had a lifecycle change.
*
* @param ev
* The <code>ServiceEvent</code> object.
*/
public void serviceChanged(ServiceEvent ev)
{
ServiceReference sr = ev.getServiceReference();
switch (ev.getType())
{
case ServiceEvent.MODIFIED:
case ServiceEvent.UNREGISTERING:
{
ServerInstanceWrapper instance = unregisterInIndex(ev.getServiceReference());
if (instance != null)
{
try
{
instance.stop();
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
if (ev.getType() == ServiceEvent.UNREGISTERING)
{
break;
}
else
{
// modified, meaning: we reload it. now that we stopped it;
// we can register it.
}
case ServiceEvent.REGISTERED:
{
Bundle contributor = sr.getBundle();
Server server = (Server)contributor.getBundleContext().getService(sr);
ServerInstanceWrapper wrapper = registerInIndex(server, sr);
Properties props = new Properties();
for (String key : sr.getPropertyKeys())
{
Object value = sr.getProperty(key);
props.put(key, value);
}
wrapper.start(server, props);
break;
}
}
}
private ServerInstanceWrapper registerInIndex(Server server, ServiceReference sr)
{
String name = (String)sr.getProperty(OSGiWebappConstants.MANAGED_JETTY_SERVER_NAME);
if (name == null)
{
throw new IllegalArgumentException("The property " +
OSGiWebappConstants.MANAGED_JETTY_SERVER_NAME + " is mandatory");
}
ServerInstanceWrapper wrapper = new ServerInstanceWrapper(name);
_indexByServiceReference.put(sr,wrapper);
_serversIndexedByName.put(name,wrapper);
return wrapper;
}
/**
* Returns the ContextHandler to stop.
*
* @param reg
* @return the ContextHandler to stop.
*/
private ServerInstanceWrapper unregisterInIndex(ServiceReference sr)
{
ServerInstanceWrapper handler = _indexByServiceReference.remove(sr);
if (handler == null)
{
// a warning?
return null;
}
String name = handler.getManagedServerName();
if (name != null)
{
_serversIndexedByName.remove(name);
}
return handler;
}
}

View File

@ -14,42 +14,25 @@
// ========================================================================
package org.eclipse.jetty.osgi.boot.internal.serverfactory;
import java.net.URL;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.StringTokenizer;
import org.eclipse.jetty.osgi.boot.OSGiWebappConstants;
import org.eclipse.jetty.server.Server;
import org.osgi.framework.Bundle;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.Configuration;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationException;
import org.osgi.service.cm.ManagedServiceFactory;
/**
* This is a work in progress. <br/>
* In particular there is a lot of work required during the update of the
* configuration of a server. It might not be practical to in fact support that
* and re-deploy the webapps in the same state than before the server was
* stopped.
* <p>
* jetty servers are managed as OSGi services registered here. try to find out
* if a configuration will fail (ports already opened etc).
* </p>
* <p>
* Try to enable the creation and configuration of jetty servers in all the
* usual standard ways. The configuration of the server is defined by the
* properties passed to the service:
* <ol>
* <li>First look for jettyfactory. If the value is a jetty server, use that
* server</li>
* <li>Then look for jettyhome key. The value should be a java.io.File or a
* String that is a path to the folder It is required that a etc/jetty.xml file
* will be loated from that folder.</li>
* <li>Then look for a jettyxml key. The value should be a java.io.File or an
* InputStream that contains a jetty configuration file.</li>
* <li>TODO: More ways to configure a jetty server? (other IOCs like spring,
* equinox properties...)</li>
* <li>Throw an exception if none of the relevant parameters are found</li>
* </ol>
* </p>
* Manages the deployment of jetty server instances.
* Not sure this is bringing much compared to the JettyServerServiceTracker.
*
* @author hmalphettes
*/
@ -161,4 +144,59 @@ public class JettyServersManagedFactory implements ManagedServiceFactory
return pid != null ? _serversIndexedByPID.get(pid) : null;
}
/**
* Helper method to create and configure a new Jetty Server via the ManagedServiceFactory
* @param contributor
* @param serverName
* @param urlsToJettyXml
* @throws Exception
*/
public static void createNewServer(Bundle contributor, String serverName, String urlsToJettyXml) throws Exception
{
ServiceReference configurationAdminReference =
contributor.getBundleContext().getServiceReference( ConfigurationAdmin.class.getName() );
ConfigurationAdmin confAdmin = (ConfigurationAdmin) contributor.getBundleContext()
.getService( configurationAdminReference );
Configuration configuration = confAdmin.createFactoryConfiguration(
OSGiWebappConstants.MANAGED_JETTY_SERVER_FACTORY_PID, contributor.getLocation() );
Dictionary properties = new Hashtable();
properties.put(OSGiWebappConstants.MANAGED_JETTY_SERVER_NAME, serverName);
StringBuilder actualBundleUrls = new StringBuilder();
StringTokenizer tokenizer = new StringTokenizer(urlsToJettyXml, ",", false);
while (tokenizer.hasMoreTokens())
{
if (actualBundleUrls.length() != 0)
{
actualBundleUrls.append(",");
}
String token = tokenizer.nextToken();
if (token.indexOf(':') != -1)
{
//a complete url. no change needed:
actualBundleUrls.append(token);
}
else if (token.startsWith("/"))
{
//url relative to the contributor bundle:
URL url = contributor.getEntry(token);
if (url == null)
{
actualBundleUrls.append(token);
}
else
{
actualBundleUrls.append(url.toString());
}
}
}
properties.put(OSGiWebappConstants.MANAGED_JETTY_XML_CONFIG_URLS, actualBundleUrls.toString());
configuration.update(properties);
}
}

View File

@ -84,6 +84,29 @@ public class ServerInstanceWrapper {
{
_managedServerName = managedServerName;
}
public String getManagedServerName()
{
return _managedServerName;
}
/**
* The classloader that should be the parent classloader for
* each webapp deployed on this server.
* @return
*/
public ClassLoader getParentClassLoaderForWebapps()
{
return _commonParentClassLoaderForWebapps;
}
/**
* @return The deployment manager registered on this server.
*/
public DeploymentManager getDeploymentManager()
{
return _deploymentManager;
}
public void start(Server server, Dictionary props)

View File

@ -146,15 +146,15 @@ public class JettyContextHandlerServiceTracker implements ServiceListener
}
}
}
if (ev.getType() == ServiceEvent.UNREGISTERING)
{
break;
}
else
{
// modified, meaning: we reload it. now that we stopped it;
// we can register it.
}
if (ev.getType() == ServiceEvent.UNREGISTERING)
{
break;
}
else
{
// modified, meaning: we reload it. now that we stopped it;
// we can register it.
}
case ServiceEvent.REGISTERED:
{
Bundle contributor = sr.getBundle();