From: Mathieu Baudier Date: Tue, 11 Dec 2012 09:50:08 +0000 (+0000) Subject: Move Catalina Start to Commons X-Git-Tag: argeo-commons-2.1.30~708 X-Git-Url: http://git.argeo.org/?a=commitdiff_plain;h=3d0b889489c953358ecaf2d389bbbd8196952bd8;p=lgpl%2Fargeo-commons.git Move Catalina Start to Commons git-svn-id: https://svn.argeo.org/commons/trunk@5945 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc --- diff --git a/server/modules/org.argeo.server.catalina.start/.classpath b/server/modules/org.argeo.server.catalina.start/.classpath new file mode 100644 index 000000000..b56882d64 --- /dev/null +++ b/server/modules/org.argeo.server.catalina.start/.classpath @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/server/modules/org.argeo.server.catalina.start/.project b/server/modules/org.argeo.server.catalina.start/.project new file mode 100644 index 000000000..f35073dde --- /dev/null +++ b/server/modules/org.argeo.server.catalina.start/.project @@ -0,0 +1,27 @@ + + + org.argeo.dep.osgi.catalina.start + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.pde.ManifestBuilder + + + + + org.eclipse.pde.SchemaBuilder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.pde.PluginNature + + + diff --git a/server/modules/org.argeo.server.catalina.start/.settings/org.eclipse.jdt.core.prefs b/server/modules/org.argeo.server.catalina.start/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..6d0bce7d1 --- /dev/null +++ b/server/modules/org.argeo.server.catalina.start/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,12 @@ +#Fri Apr 23 08:40:00 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.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +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/modules/org.argeo.server.catalina.start/META-INF/MANIFEST.MF b/server/modules/org.argeo.server.catalina.start/META-INF/MANIFEST.MF new file mode 100644 index 000000000..2b322c770 --- /dev/null +++ b/server/modules/org.argeo.server.catalina.start/META-INF/MANIFEST.MF @@ -0,0 +1,18 @@ +Bundle-Activator: org.argeo.dep.osgi.catalina.start.CatalinaActivator +Created-By: Argeo +Import-Package: javax.management;resolution:=optional, + org.apache.catalina, + org.apache.catalina.connector, + org.apache.catalina.core, + org.apache.catalina.startup, + org.apache.catalina.util, + org.apache.commons.io, + org.apache.commons.logging;resolution:=optional, + org.apache.naming.resources, + org.osgi.framework;version="1.3", + org.osgi.service.url;version="1.0" +Bundle-Version: 1.0.0.0009 +Bundle-Name: Tomcat Catalina OSGi Activator (Argeo) +Bundle-Description: Tomcat Catalina OSGi Activator with Argeo addons +Bundle-SymbolicName: org.argeo.dep.osgi.catalina.start +Bundle-RequiredExecutionEnvironment: J2SE-1.5 diff --git a/server/modules/org.argeo.server.catalina.start/build.properties b/server/modules/org.argeo.server.catalina.start/build.properties new file mode 100644 index 000000000..2c65f866b --- /dev/null +++ b/server/modules/org.argeo.server.catalina.start/build.properties @@ -0,0 +1,5 @@ +source.. = src/main/java/,\ + src/main/resources/ +output.. = target/classes/ +bin.includes = META-INF/,\ + . diff --git a/server/modules/org.argeo.server.catalina.start/pom.xml b/server/modules/org.argeo.server.catalina.start/pom.xml new file mode 100644 index 000000000..d0455870e --- /dev/null +++ b/server/modules/org.argeo.server.catalina.start/pom.xml @@ -0,0 +1,89 @@ + + 4.0.0 + org.argeo.dep.osgi + org.argeo.dep.osgi.catalina.start + Catalina starter provided by Spring DM + 1.0.0.0009 + jar + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.5 + 1.5 + + + + maven-jar-plugin + + + META-INF/MANIFEST.MF + + + + + + + + org.eclipse.osgi + org.eclipse.osgi + 3.5.1.R35x_v20090827 + + + org.apache.catalina + com.springsource.org.apache.catalina + 6.0.24 + + + org.apache.commons + com.springsource.org.apache.commons.logging + 1.1.1 + + + org.apache.commons + com.springsource.org.apache.commons.io + 1.4.0 + + + + + com.springsource.repository.bundles.external + + SpringSource Enterprise Bundle Repository - External + Bundle + Releases + + + http://repository.springsource.com/maven/bundles/external + + + true + daily + fail + + + false + never + fail + + + + + + false + argeo-restricted + Argeo FOSS Repository + file:///srv/maven/www/argeo + + + true + argeo-snapshots-restricted + Argeo FOSS Snapshots Repository + file:///srv/maven/www/argeo-snapshots + + + diff --git a/server/modules/org.argeo.server.catalina.start/src/main/java/org/argeo/dep/osgi/catalina/start/CatalinaActivator.java b/server/modules/org.argeo.server.catalina.start/src/main/java/org/argeo/dep/osgi/catalina/start/CatalinaActivator.java new file mode 100644 index 000000000..5c1df1acd --- /dev/null +++ b/server/modules/org.argeo.server.catalina.start/src/main/java/org/argeo/dep/osgi/catalina/start/CatalinaActivator.java @@ -0,0 +1,91 @@ +package org.argeo.dep.osgi.catalina.start; + +import java.io.File; +import java.io.InputStream; +import java.net.URL; +import java.util.Properties; + +import org.apache.commons.io.IOUtils; +import org.osgi.framework.BundleContext; +import org.springframework.osgi.web.tomcat.internal.Activator; + +/** Starts Catalina (hacked from Spring OSGi 1.0) */ +public class CatalinaActivator extends Activator { + private final static String ARGEO_OSGI_DATA_DIR = "argeo.osgi.data.dir"; + + public void start(BundleContext context) throws Exception { + if (!System.getProperties().containsKey(ARGEO_OSGI_DATA_DIR)) { + String osgiInstanceArea = System.getProperty("osgi.instance.area"); + String osgiInstanceAreaDefault = System + .getProperty("osgi.instance.area.default"); + String tempDir = System.getProperty("java.io.tmpdir"); + + File dataDir = null; + if (osgiInstanceArea != null) { + // within OSGi with -data specified + osgiInstanceArea = removeFilePrefix(osgiInstanceArea); + dataDir = new File(osgiInstanceArea); + } else if (osgiInstanceAreaDefault != null) { + // within OSGi without -data specified + osgiInstanceAreaDefault = removeFilePrefix(osgiInstanceAreaDefault); + dataDir = new File(osgiInstanceAreaDefault); + } else {// outside OSGi + dataDir = new File(tempDir + File.separator + "osgiData"); + } + + System.setProperty(ARGEO_OSGI_DATA_DIR, dataDir.getAbsolutePath()); + } + + // Load config properties and put them in system properties so that they + // can be used in tomcat conf + Properties confProps = new Properties(); + URL propsUrl = context.getBundle().getResource("tomcat.properties"); + if (propsUrl != null) { + InputStream in = null; + try { + in = propsUrl.openStream(); + confProps.load(in); + } catch (Exception e) { + throw new RuntimeException("Cannot read catalina properties.", + e); + } finally { + IOUtils.closeQuietly(in); + } + + for (Object key : confProps.keySet()) { + // System properties have priority + if (!System.getProperties().containsKey(key)) { + System.setProperty(key.toString(), + confProps.getProperty(key.toString())); + } + } + } + + // calling Catalina.setCatalinaHome(String) or + // Catalina.setCatalinaBase(String) does the same + if (System.getProperty("catalina.home") == null) + System.setProperty("catalina.home", + System.getProperty(ARGEO_OSGI_DATA_DIR) + "/tomcat"); + if (System.getProperty("catalina.base") == null) + System.setProperty("catalina.base", + System.getProperty(ARGEO_OSGI_DATA_DIR) + "/tomcat"); + + // Call Spring starter + super.start(context); + } + + @Override + public void stop(BundleContext context) throws Exception { + super.stop(context); + } + + protected String removeFilePrefix(String url) { + if (url.startsWith("file:")) + return url.substring("file:".length()); + else if (url.startsWith("reference:file:")) + return url.substring("reference:file:".length()); + else + return url; + } + +} diff --git a/server/modules/org.argeo.server.catalina.start/src/main/java/org/springframework/osgi/web/tomcat/internal/Activator.java b/server/modules/org.argeo.server.catalina.start/src/main/java/org/springframework/osgi/web/tomcat/internal/Activator.java new file mode 100644 index 000000000..70284fe18 --- /dev/null +++ b/server/modules/org.argeo.server.catalina.start/src/main/java/org/springframework/osgi/web/tomcat/internal/Activator.java @@ -0,0 +1,257 @@ +/* + * 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.springframework.osgi.web.tomcat.internal; + +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.BundleActivator; +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; + +/** + * Simple activator for starting Apache Tomcat Catalina container inside OSGi + * using Tomcat's XML configuration files. + * + *

This activator looks initially for a conf/server.xml file + * falling back to conf/default-server.xml. This allows the + * default configuration to be tweaked through fragments for example. + * + * @author Costin Leau + */ +public class Activator implements BundleActivator { + + /** logger */ + private static final Log log = LogFactory.getLog(Activator.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; + + private Thread startupThread; + + + public void start(BundleContext context) throws Exception { + this.bundleContext = context; + // do the initialization on a different thread + // so the activator finishes fast + startupThread = new Thread(new Runnable() { + + public void run() { + log.info("Starting " + ServerInfo.getServerInfo() + " ..."); + + // default startup procedure + ClassLoader cl = Activator.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); + } + } + }, "Tomcat Catalina Start Thread"); + + startupThread.start(); + } + + public void stop(BundleContext context) throws Exception { + // unpublish service first + registration.unregister(); + urlRegistration.unregister(); + + log.info("Unpublished " + ServerInfo.getServerInfo() + " OSGi service"); + + // default startup procedure + ClassLoader cl = Activator.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); + } +} \ No newline at end of file diff --git a/server/modules/org.argeo.server.catalina.start/src/main/java/org/springframework/osgi/web/tomcat/internal/OsgiCatalina.java b/server/modules/org.argeo.server.catalina.start/src/main/java/org/springframework/osgi/web/tomcat/internal/OsgiCatalina.java new file mode 100644 index 000000000..f7903ff6a --- /dev/null +++ b/server/modules/org.argeo.server.catalina.start/src/main/java/org/springframework/osgi/web/tomcat/internal/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.springframework.osgi.web.tomcat.internal; + +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; + } +} diff --git a/server/modules/org.argeo.server.catalina.start/src/main/resources/conf/default-server.xml b/server/modules/org.argeo.server.catalina.start/src/main/resources/conf/default-server.xml new file mode 100644 index 000000000..c8cd5bb7b --- /dev/null +++ b/server/modules/org.argeo.server.catalina.start/src/main/resources/conf/default-server.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + +