// ========================================================================
// Copyright (c) 2009 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.
// Contributors:
// Hugues Malphettes - initial API and implementation
// ========================================================================
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.OSGiServerConstants;
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;
/**
* Manages the deployment of jetty server instances.
* Not sure this is bringing much compared to the JettyServerServiceTracker.
*
* @author hmalphettes
*/
public class JettyServersManagedFactory implements ManagedServiceFactory, IManagedJettyServerRegistry
{
/**
* key to configure the server according to a jetty home folder. the value
* is the corresponding java.io.File
*/
public static final String JETTY_HOME = "jettyhome";
/** key to configure the server according to a jetty.xml file */
public static final String JETTY_CONFIG_XML = "jettyxml";
/**
* invoke jetty-factory class. the value of this property is the instance of
* that class to call back.
*/
public static final String JETTY_FACTORY = "jettyfactory";
/**
* default property in jetty.xml that is used as the value of the http port.
*/
public static final String JETTY_HTTP_PORT = "jetty.http.port";
/**
* default property in jetty.xml that is used as the value of the https
* port.
*/
public static final String JETTY_HTTPS_PORT = "jetty.http.port";
/**
* Servers indexed by PIDs. PIDs are generated by the ConfigurationAdmin service.
*/
private Map<String, ServerInstanceWrapper> _serversIndexedByPID = new HashMap<String, ServerInstanceWrapper>();
/**
* PID -> {@link OSGiWebappConstants#MANAGED_JETTY_SERVER_NAME}
*/
private Map<String, String> _serversNameIndexedByPID = new HashMap<String, String>();
/**
* {@link OSGiWebappConstants#MANAGED_JETTY_SERVER_NAME} -> PID
*/
private Map<String, String> _serversPIDIndexedByName = new HashMap<String, String>();
/**
* Return a descriptive name of this factory.
*
* @return the name for the factory, which might be localized
*/
public String getName()
{
return getClass().getName();
}
public void updated(String pid, Dictionary properties) throws ConfigurationException
{
ServerInstanceWrapper serverInstanceWrapper = getServerByPID(pid);
deleted(pid);
// do we need to collect the currently deployed http services and
// webapps
// to be able to re-deploy them later?
// probably not. simply restart and see the various service trackers
// do everything that is needed.
String name = (String)properties.get(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME);
if (name == null)
{
throw new ConfigurationException(OSGiServerConstants.MANAGED_JETTY_SERVER_NAME,
"The name of the server is mandatory");
}
serverInstanceWrapper = new ServerInstanceWrapper(name);
_serversIndexedByPID.put(pid, serverInstanceWrapper);
_serversNameIndexedByPID.put(pid, name);
_serversPIDIndexedByName.put(name, pid);
serverInstanceWrapper.start(new Server(), properties);
}
public synchronized void deleted(String pid)
{
ServerInstanceWrapper server = (ServerInstanceWrapper)_serversIndexedByPID.remove(pid);
String name = _serversNameIndexedByPID.remove(pid);
if (name != null)
{
_serversPIDIndexedByName.remove(name);
}
else
{
//something incorrect going on.
}
if (server != null)
{
try
{
server.stop();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
public synchronized ServerInstanceWrapper getServerByPID(String pid)
{
return _serversIndexedByPID.get(pid);
}
/**
* @param managedServerName The server name
* @return the corresponding jetty server wrapped with its deployment properties.
*/
public ServerInstanceWrapper getServerInstanceWrapper(String managedServerName)
{
String pid = _serversPIDIndexedByName.get(managedServerName);
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(
OSGiServerConstants.MANAGED_JETTY_SERVER_FACTORY_PID, contributor.getLocation() );
Dictionary properties = new Hashtable();
properties.put(OSGiServerConstants.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(OSGiServerConstants.MANAGED_JETTY_XML_CONFIG_URLS, actualBundleUrls.toString());
configuration.update(properties);
}
}