+++ /dev/null
-package org.argeo.server.catalina;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.net.URLConnection;
-import java.net.URLStreamHandler;
-import java.util.Properties;
-
-import javax.management.MBeanRegistration;
-
-import org.apache.catalina.Lifecycle;
-import org.apache.catalina.Server;
-import org.apache.catalina.Service;
-import org.apache.catalina.connector.Connector;
-import org.apache.catalina.core.StandardService;
-import org.apache.catalina.util.ServerInfo;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.naming.resources.DirContextURLStreamHandler;
-import org.osgi.framework.Bundle;
-import org.osgi.framework.BundleContext;
-import org.osgi.framework.Constants;
-import org.osgi.framework.ServiceRegistration;
-import org.osgi.service.url.AbstractURLStreamHandlerService;
-import org.osgi.service.url.URLConstants;
-import org.osgi.service.url.URLStreamHandlerService;
-import org.springframework.beans.factory.DisposableBean;
-import org.springframework.beans.factory.InitializingBean;
-
-public class CatalinaServer implements DisposableBean,InitializingBean{
- /** logger */
- private static final Log log = LogFactory.getLog(CatalinaServer.class);
-
- /** default XML configuration */
- private static final String DEFAULT_XML_CONF_LOCATION = "conf/default-server.xml";
-
- /** user-configurable XML configuration */
- private static final String XML_CONF_LOCATION = "conf/server.xml";
-
- private BundleContext bundleContext;
-
- private StandardService server;
-
- private ServiceRegistration registration, urlRegistration;
-
- public void afterPropertiesSet() throws Exception {
- log.info("Starting " + ServerInfo.getServerInfo() + " ...");
-
- // default startup procedure
- ClassLoader cl = CatalinaServer.class.getClassLoader();
- Thread current = Thread.currentThread();
- ClassLoader old = current.getContextClassLoader();
-
- try {
- current.setContextClassLoader(cl);
-
- server = createCatalinaServer(bundleContext.getBundle());
-
- server.start();
-
- Connector[] connectors = server.findConnectors();
- for (int i = 0; i < connectors.length; i++) {
- Connector conn = connectors[i];
- log.info("Succesfully started " + ServerInfo.getServerInfo() + " @ " + conn.getDomain() + ":"
- + conn.getPort());
- }
-
- // register URL service
- urlRegistration = registerTomcatJNDIUrlService();
- // publish server as an OSGi service
- registration = publishServerAsAService(server);
- log.info("Published " + ServerInfo.getServerInfo() + " as an OSGi service");
- }
- catch (Exception ex) {
- String msg = "Cannot start " + ServerInfo.getServerInfo();
- log.error(msg, ex);
- throw new RuntimeException(msg, ex);
- }
- finally {
- current.setContextClassLoader(old);
- }
- }
-
- public void destroy() throws Exception {
- // unpublish service first
- registration.unregister();
- urlRegistration.unregister();
-
- log.info("Unpublished " + ServerInfo.getServerInfo() + " OSGi service");
-
- // default startup procedure
- ClassLoader cl = CatalinaServer.class.getClassLoader();
- Thread current = Thread.currentThread();
- ClassLoader old = current.getContextClassLoader();
-
- try {
- current.setContextClassLoader(cl);
- //reset CCL
- // current.setContextClassLoader(null);
- log.info("Stopping " + ServerInfo.getServerInfo() + " ...");
- server.stop();
- log.info("Succesfully stopped " + ServerInfo.getServerInfo());
- }
- catch (Exception ex) {
- log.error("Cannot stop " + ServerInfo.getServerInfo(), ex);
- throw ex;
- }
- finally {
- current.setContextClassLoader(old);
- }
- }
-
- private StandardService createCatalinaServer(Bundle bundle) throws Exception {
- // first try to use the XML file
- URL xmlConfiguration = bundle.getResource(XML_CONF_LOCATION);
-
- if (xmlConfiguration != null) {
- log.info("Using custom XML configuration " + xmlConfiguration);
- }
- else {
- xmlConfiguration = bundle.getResource(DEFAULT_XML_CONF_LOCATION);
- if (xmlConfiguration == null)
- log.error("No XML configuration found; bailing out...");
- else
- log.info("Using default XML configuration " + xmlConfiguration);
- }
-
- return createServerFromXML(xmlConfiguration);
- }
-
- private StandardService createServerFromXML(URL xmlConfiguration) throws IOException {
- OsgiCatalina catalina = new OsgiCatalina();
- catalina.setAwait(false);
- catalina.setUseShutdownHook(false);
- catalina.setName("Catalina");
- catalina.setParentClassLoader(Thread.currentThread().getContextClassLoader());
-
- // copy the URL file to a local temporary file (since Catalina doesn't use URL unfortunately)
- File configTempFile = File.createTempFile("dm.catalina", ".cfg.xml");
- configTempFile.deleteOnExit();
-
- // copy URL to temporary file
- copyURLToFile(xmlConfiguration.openStream(), new FileOutputStream(configTempFile));
- log.debug("Copied configuration " + xmlConfiguration + " to temporary file " + configTempFile);
-
- catalina.setConfigFile(configTempFile.getAbsolutePath());
-
- catalina.load();
-
- Server server = catalina.getServer();
-
- return (StandardService) server.findServices()[0];
- }
-
- private void copyURLToFile(InputStream inStream, FileOutputStream outStream) {
-
- int bytesRead;
- byte[] buf = new byte[4096];
- try {
- while ((bytesRead = inStream.read(buf)) >= 0) {
- outStream.write(buf, 0, bytesRead);
- }
- }
- catch (IOException ex) {
- throw (RuntimeException) new IllegalStateException("Cannot copy URL to file").initCause(ex);
- }
- finally {
- try {
- inStream.close();
- }
- catch (IOException ignore) {
- }
- try {
- outStream.close();
- }
- catch (IOException ignore) {
- }
- }
- }
-
- private ServiceRegistration publishServerAsAService(StandardService server) {
- Properties props = new Properties();
- // put some extra properties to easily identify the service
- props.put(Constants.SERVICE_VENDOR, "Spring Dynamic Modules");
- props.put(Constants.SERVICE_DESCRIPTION, ServerInfo.getServerInfo());
- props.put(Constants.BUNDLE_VERSION, ServerInfo.getServerNumber());
- props.put(Constants.BUNDLE_NAME, bundleContext.getBundle().getSymbolicName());
-
- // spring-dm specific property
- props.put("org.springframework.osgi.bean.name", "tomcat-server");
-
- // publish just the interfaces and the major classes (server/handlerWrapper)
- String[] classes = new String[] { StandardService.class.getName(), Service.class.getName(),
- MBeanRegistration.class.getName(), Lifecycle.class.getName() };
-
- return bundleContext.registerService(classes, server, props);
- }
-
- private ServiceRegistration registerTomcatJNDIUrlService() {
- Properties properties = new Properties();
- properties.put(URLConstants.URL_HANDLER_PROTOCOL, "jndi");
- final URLStreamHandler handler = new DirContextURLStreamHandler();
-
- return bundleContext.registerService(URLStreamHandlerService.class.getName(),
- new AbstractURLStreamHandlerService() {
-
- private final static String EMPTY_STRING = "";
-
-
- public URLConnection openConnection(URL u) throws IOException {
- return new URL(u, EMPTY_STRING, handler).openConnection();
- }
- }, properties);
- }
-
-}