From 4432ffb9f9b4e4d23b2515bde9872910ff8e4e36 Mon Sep 17 00:00:00 2001 From: Mathieu Baudier Date: Fri, 9 Jul 2010 14:46:51 +0000 Subject: [PATCH] Introduce Argeo Server Catalina git-svn-id: https://svn.argeo.org/commons/trunk@3658 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- .../org.argeo.server.catalina/.classpath | 7 + .../org.argeo.server.catalina/.project | 28 +++ .../.settings/org.eclipse.jdt.core.prefs | 8 + .../.settings/org.eclipse.pde.core.prefs | 4 + .../META-INF/MANIFEST.MF | 15 ++ .../build.properties | 4 + .../argeo/server/catalina/CatalinaServer.java | 219 ++++++++++++++++++ .../argeo/server/catalina/OsgiCatalina.java | 34 +++ 8 files changed, 319 insertions(+) create mode 100644 server/runtime/org.argeo.server.catalina/.classpath create mode 100644 server/runtime/org.argeo.server.catalina/.project create mode 100644 server/runtime/org.argeo.server.catalina/.settings/org.eclipse.jdt.core.prefs create mode 100644 server/runtime/org.argeo.server.catalina/.settings/org.eclipse.pde.core.prefs create mode 100644 server/runtime/org.argeo.server.catalina/META-INF/MANIFEST.MF create mode 100644 server/runtime/org.argeo.server.catalina/build.properties create mode 100644 server/runtime/org.argeo.server.catalina/src/main/java/org/argeo/server/catalina/CatalinaServer.java create mode 100644 server/runtime/org.argeo.server.catalina/src/main/java/org/argeo/server/catalina/OsgiCatalina.java diff --git a/server/runtime/org.argeo.server.catalina/.classpath b/server/runtime/org.argeo.server.catalina/.classpath new file mode 100644 index 000000000..92f19d2ff --- /dev/null +++ b/server/runtime/org.argeo.server.catalina/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/server/runtime/org.argeo.server.catalina/.project b/server/runtime/org.argeo.server.catalina/.project new file mode 100644 index 000000000..11c4760fb --- /dev/null +++ b/server/runtime/org.argeo.server.catalina/.project @@ -0,0 +1,28 @@ + + + org.argeo.server.catalina + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.pde.PluginNature + org.eclipse.jdt.core.javanature + + diff --git a/server/runtime/org.argeo.server.catalina/.settings/org.eclipse.jdt.core.prefs b/server/runtime/org.argeo.server.catalina/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..606000e33 --- /dev/null +++ b/server/runtime/org.argeo.server.catalina/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,8 @@ +#Fri Jul 09 14:46:32 CEST 2010 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.source=1.5 diff --git a/server/runtime/org.argeo.server.catalina/.settings/org.eclipse.pde.core.prefs b/server/runtime/org.argeo.server.catalina/.settings/org.eclipse.pde.core.prefs new file mode 100644 index 000000000..c0af3cae0 --- /dev/null +++ b/server/runtime/org.argeo.server.catalina/.settings/org.eclipse.pde.core.prefs @@ -0,0 +1,4 @@ +#Fri Jul 09 14:46:32 CEST 2010 +eclipse.preferences.version=1 +pluginProject.extensions=false +resolve.requirebundle=false diff --git a/server/runtime/org.argeo.server.catalina/META-INF/MANIFEST.MF b/server/runtime/org.argeo.server.catalina/META-INF/MANIFEST.MF new file mode 100644 index 000000000..f296913d8 --- /dev/null +++ b/server/runtime/org.argeo.server.catalina/META-INF/MANIFEST.MF @@ -0,0 +1,15 @@ +Manifest-Version: 1.0 +Bundle-ManifestVersion: 2 +Bundle-Name: Catalina +Bundle-SymbolicName: org.argeo.server.catalina +Bundle-Version: 1.0.0.qualifier +Bundle-RequiredExecutionEnvironment: J2SE-1.5 +Import-Package: org.apache.catalina;version="6.0.24", + org.apache.catalina.connector;version="6.0.24", + org.apache.catalina.core;version="6.0.24", + org.apache.catalina.util;version="6.0.24", + org.apache.commons.logging;version="1.1.1", + org.apache.naming.resources;version="6.0.24", + org.osgi.framework;version="1.5.0", + org.osgi.service.url;version="1.0.0", + org.springframework.beans.factory;version="2.5.6.SEC01" diff --git a/server/runtime/org.argeo.server.catalina/build.properties b/server/runtime/org.argeo.server.catalina/build.properties new file mode 100644 index 000000000..5fc538bc8 --- /dev/null +++ b/server/runtime/org.argeo.server.catalina/build.properties @@ -0,0 +1,4 @@ +source.. = src/main/java/ +output.. = target/classes/ +bin.includes = META-INF/,\ + . diff --git a/server/runtime/org.argeo.server.catalina/src/main/java/org/argeo/server/catalina/CatalinaServer.java b/server/runtime/org.argeo.server.catalina/src/main/java/org/argeo/server/catalina/CatalinaServer.java new file mode 100644 index 000000000..392bbfa30 --- /dev/null +++ b/server/runtime/org.argeo.server.catalina/src/main/java/org/argeo/server/catalina/CatalinaServer.java @@ -0,0 +1,219 @@ +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); + } + +} diff --git a/server/runtime/org.argeo.server.catalina/src/main/java/org/argeo/server/catalina/OsgiCatalina.java b/server/runtime/org.argeo.server.catalina/src/main/java/org/argeo/server/catalina/OsgiCatalina.java new file mode 100644 index 000000000..f07b9c5d1 --- /dev/null +++ b/server/runtime/org.argeo.server.catalina/src/main/java/org/argeo/server/catalina/OsgiCatalina.java @@ -0,0 +1,34 @@ +/* + * Copyright 2006-2008 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.argeo.server.catalina; + +import org.apache.catalina.Server; +import org.apache.catalina.startup.Catalina; + +/** + * OSGi extension of Catalina class used for easy access to the underlying + * configuration. + * + * @author Costin Leau + * + */ +public class OsgiCatalina extends Catalina { + + public Server getServer() { + return server; + } +} -- 2.30.2