Extend Spring DM web extender in order to fix issue when undeploying
authorMathieu Baudier <mbaudier@argeo.org>
Fri, 25 Feb 2011 19:26:58 +0000 (19:26 +0000)
committerMathieu Baudier <mbaudier@argeo.org>
Fri, 25 Feb 2011 19:26:58 +0000 (19:26 +0000)
git-svn-id: https://svn.argeo.org/commons/trunk@4210 4cfe0d0a-d680-48aa-b62c-e0a02a3f76cc

18 files changed:
server/runtime/org.argeo.server.catalina/.classpath [deleted file]
server/runtime/org.argeo.server.catalina/.project [deleted file]
server/runtime/org.argeo.server.catalina/.settings/org.eclipse.jdt.core.prefs [deleted file]
server/runtime/org.argeo.server.catalina/.settings/org.eclipse.pde.core.prefs [deleted file]
server/runtime/org.argeo.server.catalina/META-INF/MANIFEST.MF [deleted file]
server/runtime/org.argeo.server.catalina/build.properties [deleted file]
server/runtime/org.argeo.server.catalina/src/main/java/org/argeo/server/catalina/CatalinaServer.java [deleted file]
server/runtime/org.argeo.server.catalina/src/main/java/org/argeo/server/catalina/OsgiCatalina.java [deleted file]
server/runtime/org.argeo.server.catalina/src/main/java/org/argeo/server/catalina/TomcatDeployer.java [deleted file]
server/runtime/org.argeo.server.webextender/.classpath [new file with mode: 0644]
server/runtime/org.argeo.server.webextender/.project [new file with mode: 0644]
server/runtime/org.argeo.server.webextender/.settings/org.eclipse.jdt.core.prefs [new file with mode: 0644]
server/runtime/org.argeo.server.webextender/.settings/org.eclipse.pde.core.prefs [new file with mode: 0644]
server/runtime/org.argeo.server.webextender/build.properties [new file with mode: 0644]
server/runtime/org.argeo.server.webextender/pom.xml [new file with mode: 0644]
server/runtime/org.argeo.server.webextender/src/main/java/org/argeo/server/catalina/CatalinaServer.java [new file with mode: 0644]
server/runtime/org.argeo.server.webextender/src/main/java/org/argeo/server/catalina/OsgiCatalina.java [new file with mode: 0644]
server/runtime/org.argeo.server.webextender/src/main/java/org/argeo/server/catalina/TomcatDeployer.java [new file with mode: 0644]

diff --git a/server/runtime/org.argeo.server.catalina/.classpath b/server/runtime/org.argeo.server.catalina/.classpath
deleted file mode 100644 (file)
index 92f19d2..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<classpath>
-       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
-       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
-       <classpathentry kind="src" path="src/main/java"/>
-       <classpathentry kind="output" path="target/classes"/>
-</classpath>
diff --git a/server/runtime/org.argeo.server.catalina/.project b/server/runtime/org.argeo.server.catalina/.project
deleted file mode 100644 (file)
index 11c4760..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<projectDescription>
-       <name>org.argeo.server.catalina</name>
-       <comment></comment>
-       <projects>
-       </projects>
-       <buildSpec>
-               <buildCommand>
-                       <name>org.eclipse.jdt.core.javabuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-               <buildCommand>
-                       <name>org.eclipse.pde.ManifestBuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-               <buildCommand>
-                       <name>org.eclipse.pde.SchemaBuilder</name>
-                       <arguments>
-                       </arguments>
-               </buildCommand>
-       </buildSpec>
-       <natures>
-               <nature>org.eclipse.pde.PluginNature</nature>
-               <nature>org.eclipse.jdt.core.javanature</nature>
-       </natures>
-</projectDescription>
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
deleted file mode 100644 (file)
index 606000e..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-#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
deleted file mode 100644 (file)
index c0af3ca..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-#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
deleted file mode 100644 (file)
index a76b598..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-Manifest-Version: 1.0
-Bundle-ManifestVersion: 2
-Bundle-Name: Catalina
-Bundle-SymbolicName: org.argeo.server.catalina
-Bundle-Version: 0.2.3.SNAPSHOT
-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.startup;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.aop;version="2.5.6.SEC01",
- org.springframework.beans.factory;version="2.5.6.SEC01",
- org.springframework.osgi.context;version="1.2.1",
- org.springframework.osgi.web.deployer;version="1.2.1",
- org.springframework.osgi.web.deployer.tomcat;version="1.2.1"
-Export-Package: org.argeo.server.catalina
diff --git a/server/runtime/org.argeo.server.catalina/build.properties b/server/runtime/org.argeo.server.catalina/build.properties
deleted file mode 100644 (file)
index 5fc538b..0000000
+++ /dev/null
@@ -1,4 +0,0 @@
-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
deleted file mode 100644 (file)
index 392bbfa..0000000
+++ /dev/null
@@ -1,219 +0,0 @@
-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
deleted file mode 100644 (file)
index f07b9c5..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-/*\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.argeo.server.catalina;\r
-\r
-import org.apache.catalina.Server;\r
-import org.apache.catalina.startup.Catalina;\r
-\r
-/**\r
- * OSGi extension of Catalina class used for easy access to the underlying\r
- * configuration.\r
- * \r
- * @author Costin Leau\r
- * \r
- */\r
-public class OsgiCatalina extends Catalina {\r
-\r
-       public Server getServer() {\r
-               return server;\r
-       }\r
-}\r
diff --git a/server/runtime/org.argeo.server.catalina/src/main/java/org/argeo/server/catalina/TomcatDeployer.java b/server/runtime/org.argeo.server.catalina/src/main/java/org/argeo/server/catalina/TomcatDeployer.java
deleted file mode 100644 (file)
index 3cc16bc..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-package org.argeo.server.catalina;
-
-import org.apache.catalina.Service;
-import org.springframework.osgi.web.deployer.tomcat.TomcatWarDeployer;
-
-/**
- * Wraps the Spring DM Tomcate deployer in order to avoid issue with call to
- * getServerInfo() when undeployed.
- */
-public class TomcatDeployer extends TomcatWarDeployer {
-       private String serverInfo;
-
-       @Override
-       public void setService(Object service) {
-               super.setService(service);
-
-               serverInfo = ((Service) service).getInfo();
-       }
-
-       @Override
-       protected String getServerInfo() {
-               return serverInfo;
-       }
-
-       
-}
diff --git a/server/runtime/org.argeo.server.webextender/.classpath b/server/runtime/org.argeo.server.webextender/.classpath
new file mode 100644 (file)
index 0000000..92f19d2
--- /dev/null
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+       <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+       <classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
+       <classpathentry kind="src" path="src/main/java"/>
+       <classpathentry kind="output" path="target/classes"/>
+</classpath>
diff --git a/server/runtime/org.argeo.server.webextender/.project b/server/runtime/org.argeo.server.webextender/.project
new file mode 100644 (file)
index 0000000..39a8ee8
--- /dev/null
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+       <name>org.argeo.server.webextender</name>
+       <comment></comment>
+       <projects>
+       </projects>
+       <buildSpec>
+               <buildCommand>
+                       <name>org.eclipse.jdt.core.javabuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.ManifestBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+               <buildCommand>
+                       <name>org.eclipse.pde.SchemaBuilder</name>
+                       <arguments>
+                       </arguments>
+               </buildCommand>
+       </buildSpec>
+       <natures>
+               <nature>org.eclipse.pde.PluginNature</nature>
+               <nature>org.eclipse.jdt.core.javanature</nature>
+       </natures>
+</projectDescription>
diff --git a/server/runtime/org.argeo.server.webextender/.settings/org.eclipse.jdt.core.prefs b/server/runtime/org.argeo.server.webextender/.settings/org.eclipse.jdt.core.prefs
new file mode 100644 (file)
index 0000000..606000e
--- /dev/null
@@ -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.webextender/.settings/org.eclipse.pde.core.prefs b/server/runtime/org.argeo.server.webextender/.settings/org.eclipse.pde.core.prefs
new file mode 100644 (file)
index 0000000..c0af3ca
--- /dev/null
@@ -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.webextender/build.properties b/server/runtime/org.argeo.server.webextender/build.properties
new file mode 100644 (file)
index 0000000..5fc538b
--- /dev/null
@@ -0,0 +1,4 @@
+source.. = src/main/java/
+output.. = target/classes/
+bin.includes = META-INF/,\
+               .
diff --git a/server/runtime/org.argeo.server.webextender/pom.xml b/server/runtime/org.argeo.server.webextender/pom.xml
new file mode 100644 (file)
index 0000000..08adbee
--- /dev/null
@@ -0,0 +1,49 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+       <modelVersion>4.0.0</modelVersion>
+       <parent>
+               <groupId>org.argeo.commons.server</groupId>
+               <artifactId>runtime</artifactId>
+               <version>0.2.3-SNAPSHOT</version>
+               <relativePath>..</relativePath>
+       </parent>
+       <artifactId>org.argeo.server.webextender</artifactId>
+       <name>Commons Server Web Extender (Spring DM)</name>
+       <description>Configure / hack Spring DM web extender</description>
+       <build>
+               <plugins>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-compiler-plugin</artifactId>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-source-plugin</artifactId>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.maven.plugins</groupId>
+                               <artifactId>maven-jar-plugin</artifactId>
+                       </plugin>
+                       <plugin>
+                               <groupId>org.apache.felix</groupId>
+                               <artifactId>maven-bundle-plugin</artifactId>
+                               <version>${version.maven-bundle-plugin}</version>
+                               <configuration>
+                                       <instructions>
+
+                                               <Export-Package>
+                                                       org.argeo.server.*
+                                               </Export-Package>
+                                       </instructions>
+                               </configuration>
+                       </plugin>
+               </plugins>
+       </build>
+       <dependencies>
+               <!-- Spring -->
+               <dependency>
+                       <groupId>org.springframework.osgi</groupId>
+                       <artifactId>org.springframework.web.extender</artifactId>
+               </dependency>
+       </dependencies>
+</project>
diff --git a/server/runtime/org.argeo.server.webextender/src/main/java/org/argeo/server/catalina/CatalinaServer.java b/server/runtime/org.argeo.server.webextender/src/main/java/org/argeo/server/catalina/CatalinaServer.java
new file mode 100644 (file)
index 0000000..392bbfa
--- /dev/null
@@ -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.webextender/src/main/java/org/argeo/server/catalina/OsgiCatalina.java b/server/runtime/org.argeo.server.webextender/src/main/java/org/argeo/server/catalina/OsgiCatalina.java
new file mode 100644 (file)
index 0000000..f07b9c5
--- /dev/null
@@ -0,0 +1,34 @@
+/*\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.argeo.server.catalina;\r
+\r
+import org.apache.catalina.Server;\r
+import org.apache.catalina.startup.Catalina;\r
+\r
+/**\r
+ * OSGi extension of Catalina class used for easy access to the underlying\r
+ * configuration.\r
+ * \r
+ * @author Costin Leau\r
+ * \r
+ */\r
+public class OsgiCatalina extends Catalina {\r
+\r
+       public Server getServer() {\r
+               return server;\r
+       }\r
+}\r
diff --git a/server/runtime/org.argeo.server.webextender/src/main/java/org/argeo/server/catalina/TomcatDeployer.java b/server/runtime/org.argeo.server.webextender/src/main/java/org/argeo/server/catalina/TomcatDeployer.java
new file mode 100644 (file)
index 0000000..3cc16bc
--- /dev/null
@@ -0,0 +1,26 @@
+package org.argeo.server.catalina;
+
+import org.apache.catalina.Service;
+import org.springframework.osgi.web.deployer.tomcat.TomcatWarDeployer;
+
+/**
+ * Wraps the Spring DM Tomcate deployer in order to avoid issue with call to
+ * getServerInfo() when undeployed.
+ */
+public class TomcatDeployer extends TomcatWarDeployer {
+       private String serverInfo;
+
+       @Override
+       public void setService(Object service) {
+               super.setService(service);
+
+               serverInfo = ((Service) service).getInfo();
+       }
+
+       @Override
+       protected String getServerInfo() {
+               return serverInfo;
+       }
+
+       
+}