+++ /dev/null
-/*\r
- * Copyright 2006-2008 the original author or authors.\r
- * \r
- * Licensed under the Apache License, Version 2.0 (the "License");\r
- * you may not use this file except in compliance with the License.\r
- * You may obtain a copy of the License at\r
- * \r
- * http://www.apache.org/licenses/LICENSE-2.0\r
- * \r
- * Unless required by applicable law or agreed to in writing, software\r
- * distributed under the License is distributed on an "AS IS" BASIS,\r
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
- * See the License for the specific language governing permissions and\r
- * limitations under the License.\r
- */\r
-\r
-package org.springframework.osgi.web.tomcat.internal;\r
-\r
-import java.io.File;\r
-import java.io.FileOutputStream;\r
-import java.io.IOException;\r
-import java.io.InputStream;\r
-import java.net.MalformedURLException;\r
-import java.net.URL;\r
-import java.net.URLConnection;\r
-import java.net.URLStreamHandler;\r
-import java.util.Properties;\r
-\r
-import javax.management.MBeanRegistration;\r
-\r
-import org.apache.catalina.Lifecycle;\r
-import org.apache.catalina.Server;\r
-import org.apache.catalina.Service;\r
-import org.apache.catalina.connector.Connector;\r
-import org.apache.catalina.core.StandardService;\r
-import org.apache.catalina.util.ServerInfo;\r
-import org.apache.commons.logging.Log;\r
-import org.apache.commons.logging.LogFactory;\r
-import org.apache.naming.resources.DirContextURLStreamHandler;\r
-import org.argeo.catalina.start.CatalinaActivator;\r
-import org.osgi.framework.Bundle;\r
-import org.osgi.framework.BundleActivator;\r
-import org.osgi.framework.BundleContext;\r
-import org.osgi.framework.Constants;\r
-import org.osgi.framework.ServiceRegistration;\r
-import org.osgi.service.url.AbstractURLStreamHandlerService;\r
-import org.osgi.service.url.URLConstants;\r
-import org.osgi.service.url.URLStreamHandlerService;\r
-\r
-/**\r
- * Simple activator for starting Apache Tomcat Catalina container inside OSGi\r
- * using Tomcat's XML configuration files.\r
- * \r
- * <p/>\r
- * This activator looks initially for a <code>conf/server.xml</code> file\r
- * falling back to <code>conf/default-server.xml</code>. This allows the default\r
- * configuration to be tweaked through fragments for example.\r
- * \r
- * @author Costin Leau\r
- */\r
-public class Activator implements BundleActivator {\r
-\r
- /** logger */\r
- private static final Log log = LogFactory.getLog(Activator.class);\r
-\r
- /** default XML configuration */\r
- private static final String DEFAULT_XML_CONF_LOCATION = "conf/default-server.xml";\r
-\r
- /** user-configurable XML configuration */\r
- private static final String XML_CONF_LOCATION = "conf/server.xml";\r
-\r
- private BundleContext bundleContext;\r
-\r
- private StandardService server;\r
-\r
- private ServiceRegistration registration, urlRegistration;\r
-\r
- private Thread startupThread;\r
-\r
- public void start(BundleContext context) throws Exception {\r
- this.bundleContext = context;\r
- // do the initialization on a different thread\r
- // so the activator finishes fast\r
- startupThread = new Thread(new Runnable() {\r
-\r
- public void run() {\r
- log.info("Starting " + ServerInfo.getServerInfo() + " ...");\r
-\r
- // default startup procedure\r
- ClassLoader cl = Activator.class.getClassLoader();\r
- Thread current = Thread.currentThread();\r
- ClassLoader old = current.getContextClassLoader();\r
-\r
- try {\r
- current.setContextClassLoader(cl);\r
-\r
- server = createCatalinaServer(bundleContext.getBundle());\r
-\r
- server.start();\r
-\r
- Connector[] connectors = server.findConnectors();\r
- for (int i = 0; i < connectors.length; i++) {\r
- Connector conn = connectors[i];\r
- log.info("Succesfully started "\r
- + ServerInfo.getServerInfo() + " @ "\r
- + conn.getDomain() + ":" + conn.getPort());\r
- }\r
-\r
- // register URL service\r
- urlRegistration = registerTomcatJNDIUrlService();\r
- // publish server as an OSGi service\r
- registration = publishServerAsAService(server);\r
- log.info("Published " + ServerInfo.getServerInfo()\r
- + " as an OSGi service");\r
- } catch (Exception ex) {\r
- String msg = "Cannot start " + ServerInfo.getServerInfo();\r
- log.error(msg, ex);\r
- throw new RuntimeException(msg, ex);\r
- } finally {\r
- current.setContextClassLoader(old);\r
- }\r
- }\r
- }, "Tomcat Catalina Start Thread");\r
-\r
- startupThread.start();\r
- }\r
-\r
- public void stop(BundleContext context) throws Exception {\r
- // unpublish service first\r
- registration.unregister();\r
- urlRegistration.unregister();\r
-\r
- log.info("Unpublished " + ServerInfo.getServerInfo() + " OSGi service");\r
-\r
- // default startup procedure\r
- ClassLoader cl = Activator.class.getClassLoader();\r
- Thread current = Thread.currentThread();\r
- ClassLoader old = current.getContextClassLoader();\r
-\r
- try {\r
- current.setContextClassLoader(cl);\r
- // reset CCL\r
- // current.setContextClassLoader(null);\r
- log.info("Stopping " + ServerInfo.getServerInfo() + " ...");\r
- server.stop();\r
- log.info("Succesfully stopped " + ServerInfo.getServerInfo());\r
- } catch (Exception ex) {\r
- log.error("Cannot stop " + ServerInfo.getServerInfo(), ex);\r
- throw ex;\r
- } finally {\r
- current.setContextClassLoader(old);\r
- }\r
- }\r
-\r
- private StandardService createCatalinaServer(Bundle bundle)\r
- throws Exception {\r
- URL xmlConfiguration = null;\r
-\r
- if (System.getProperty(CatalinaActivator.ARGEO_SERVER_TOMCAT_CONFIG) != null) {\r
- String customConfig = System\r
- .getProperty(CatalinaActivator.ARGEO_SERVER_TOMCAT_CONFIG);\r
- try {\r
- xmlConfiguration = new URL(customConfig);\r
- } catch (MalformedURLException e) {\r
- // within this bundle\r
- // typically 'default-server-ssl.xml'\r
- xmlConfiguration = bundle.getResource(customConfig);\r
- }\r
- } else {\r
- // fragment\r
- xmlConfiguration = bundle.getResource(XML_CONF_LOCATION);\r
- }\r
-\r
- if (xmlConfiguration != null) {\r
- log.info("Using custom XML configuration " + xmlConfiguration);\r
- } else {\r
- xmlConfiguration = bundle.getResource(DEFAULT_XML_CONF_LOCATION);\r
- if (xmlConfiguration == null)\r
- log.error("No XML configuration found; bailing out...");\r
- else\r
- log.info("Using default XML configuration " + xmlConfiguration);\r
- }\r
-\r
- return createServerFromXML(xmlConfiguration);\r
- }\r
-\r
- private StandardService createServerFromXML(URL xmlConfiguration)\r
- throws IOException {\r
- OsgiCatalina catalina = new OsgiCatalina();\r
- catalina.setAwait(false);\r
- catalina.setUseShutdownHook(false);\r
- catalina.setName("Catalina");\r
- catalina.setParentClassLoader(Thread.currentThread()\r
- .getContextClassLoader());\r
-\r
- // copy the URL file to a local temporary file (since Catalina doesn't\r
- // use URL unfortunately)\r
- File configTempFile = File.createTempFile("dm.catalina", ".cfg.xml");\r
- configTempFile.deleteOnExit();\r
-\r
- // copy URL to temporary file\r
- copyURLToFile(xmlConfiguration.openStream(), new FileOutputStream(\r
- configTempFile));\r
- log.debug("Copied configuration " + xmlConfiguration\r
- + " to temporary file " + configTempFile);\r
-\r
- catalina.setConfigFile(configTempFile.getAbsolutePath());\r
-\r
- catalina.load();\r
-\r
- Server server = catalina.getServer();\r
-\r
- return (StandardService) server.findServices()[0];\r
- }\r
-\r
- private void copyURLToFile(InputStream inStream, FileOutputStream outStream) {\r
-\r
- int bytesRead;\r
- byte[] buf = new byte[4096];\r
- try {\r
- while ((bytesRead = inStream.read(buf)) >= 0) {\r
- outStream.write(buf, 0, bytesRead);\r
- }\r
- } catch (IOException ex) {\r
- throw (RuntimeException) new IllegalStateException(\r
- "Cannot copy URL to file").initCause(ex);\r
- } finally {\r
- try {\r
- inStream.close();\r
- } catch (IOException ignore) {\r
- }\r
- try {\r
- outStream.close();\r
- } catch (IOException ignore) {\r
- }\r
- }\r
- }\r
-\r
- private ServiceRegistration publishServerAsAService(StandardService server) {\r
- Properties props = new Properties();\r
- // put some extra properties to easily identify the service\r
- props.put(Constants.SERVICE_VENDOR, "Spring Dynamic Modules");\r
- props.put(Constants.SERVICE_DESCRIPTION, ServerInfo.getServerInfo());\r
- props.put(Constants.BUNDLE_VERSION, ServerInfo.getServerNumber());\r
- props.put(Constants.BUNDLE_NAME, bundleContext.getBundle()\r
- .getSymbolicName());\r
-\r
- // spring-dm specific property\r
- props.put("org.springframework.osgi.bean.name", "tomcat-server");\r
-\r
- // publish just the interfaces and the major classes\r
- // (server/handlerWrapper)\r
- String[] classes = new String[] { StandardService.class.getName(),\r
- Service.class.getName(), MBeanRegistration.class.getName(),\r
- Lifecycle.class.getName() };\r
-\r
- return bundleContext.registerService(classes, server, props);\r
- }\r
-\r
- private ServiceRegistration registerTomcatJNDIUrlService() {\r
- Properties properties = new Properties();\r
- properties.put(URLConstants.URL_HANDLER_PROTOCOL, "jndi");\r
- final URLStreamHandler handler = new DirContextURLStreamHandler();\r
-\r
- return bundleContext.registerService(\r
- URLStreamHandlerService.class.getName(),\r
- new AbstractURLStreamHandlerService() {\r
-\r
- private final static String EMPTY_STRING = "";\r
-\r
- public URLConnection openConnection(URL u)\r
- throws IOException {\r
- return new URL(u, EMPTY_STRING, handler)\r
- .openConnection();\r
- }\r
- }, properties);\r
- }\r
-}
\ No newline at end of file