diff options
-rw-r--r-- | org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/Tomcat.java | 160 | ||||
-rw-r--r-- | org.eclipse.gemini.web.tomcat/template.mf | 3 |
2 files changed, 160 insertions, 3 deletions
diff --git a/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/Tomcat.java b/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/Tomcat.java index e1c5b94..db1828c 100644 --- a/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/Tomcat.java +++ b/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/Tomcat.java @@ -17,8 +17,13 @@ package org.eclipse.gemini.web.tomcat.internal; import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; +import java.io.OutputStream; +import java.util.jar.JarFile; +import java.util.zip.ZipEntry; import org.apache.catalina.Container; import org.apache.catalina.Context; @@ -40,6 +45,7 @@ import org.eclipse.gemini.web.core.spi.ServletContainerException; import org.eclipse.gemini.web.tomcat.internal.loading.ChainedClassLoader; import org.eclipse.gemini.web.tomcat.internal.support.BundleFileResolverFactory; import org.eclipse.gemini.web.tomcat.internal.support.PackageAdminBundleDependencyDeterminer; +import org.eclipse.virgo.util.io.IOUtils; import org.osgi.framework.BundleContext; import org.osgi.service.packageadmin.PackageAdmin; import org.slf4j.Logger; @@ -52,6 +58,20 @@ final class Tomcat extends Embedded { private static final String ROOT_CONTEXT_PATH = ""; private static final String ROOT_PATH = "/"; + + private static final String ROOT_CONTEXT_FILE = "ROOT"; + + private static final String CONTEXT_XML = "META-INF/context.xml"; + + private static final String CONTEXT_PROPERTY = "Context"; + + private static final String XML_EXTENSION = ".xml"; + + private static final char SLASH_SEPARATOR = '/'; + + private static final char HASH_SEPARATOR = '#'; + + private static final String DEFAULT_CONFIG_DIRECTORY = "config"; private final static Logger LOGGER = LoggerFactory.getLogger(Tomcat.class); @@ -59,12 +79,19 @@ final class Tomcat extends Embedded { private final JarScanner jarScanner; + private Digester digester; + + private BundleContext bundleContext; + Tomcat(BundleContext context, PackageAdmin packageAdmin) { + this.bundleContext = context; JarScanner bundleDependenciesJarScanner = new BundleDependenciesJarScanner(new PackageAdminBundleDependencyDeterminer(context, packageAdmin), BundleFileResolverFactory.createBundleFileResolver()); JarScanner defaultJarScanner = new DefaultJarScanner(); this.jarScanner = new ChainingJarScanner(bundleDependenciesJarScanner, defaultJarScanner); + + digester = createDigester(); } public void start() throws LifecycleException { @@ -136,9 +163,10 @@ final class Tomcat extends Embedded { if (LOGGER.isDebugEnabled()) { LOGGER.debug("Creating context '" + path + "' with docBase '" + docBase + "'"); } - + StandardContext context = new ExtendedStandardContext(); - + readContextXml(path, docBase, context); + context.setDocBase(docBase); context.setPath(path.equals(ROOT_PATH) ? ROOT_CONTEXT_PATH : path); @@ -211,4 +239,132 @@ final class Tomcat extends Embedded { */ private static class ExtendedContextConfig extends ContextConfig { } + + private Digester createDigester() { + Digester digester = new Digester(); + ClassLoader[] loaders = new ClassLoader[] { Catalina.class.getClassLoader(), Tomcat.class.getClassLoader() }; + digester.setClassLoader(ChainedClassLoader.create(loaders)); + digester.setValidating(false); + digester.addSetProperties(CONTEXT_PROPERTY); + return (digester); + } + + private void readContextXml(String path, String docBase, StandardContext context) { + // Multi-level context paths may be defined using #, e.g. foo#bar.xml + // for a context path of /foo/bar. + if (path.equals(ROOT_PATH)) { + path = ROOT_CONTEXT_FILE; + } else if (SLASH_SEPARATOR == path.charAt(0)) { + path = path.substring(1); + } + path = path.replace(SLASH_SEPARATOR, HASH_SEPARATOR); + + // Initialize config directory location + File configLocation = new File(resolveConfigDir()); + Host host = findHost(); + Container parent = host.getParent(); + if ((parent != null) && (parent instanceof Engine)) { + configLocation = new File(configLocation, parent.getName()); + } + configLocation = new File(configLocation, host.getName()); + + // Try to find the context.xml in the Tomcat's configuration directory + File contextXml = new File(configLocation, path + XML_EXTENSION); + if (contextXml.exists()) { + configureWebContext(contextXml, context); + return; + } + + // Try to find the context.xml in docBase + File docBaseFile = new File(docBase); + if (docBaseFile.isDirectory()) { + contextXml = new File(docBaseFile, CONTEXT_XML); + if (contextXml.exists()) { + File destination = new File(configLocation, path + XML_EXTENSION); + try { + copyFile(new FileInputStream(contextXml), destination); + } catch (IOException e) { + throw new ServletContainerException("Cannot copy " + contextXml.getAbsolutePath() + " to " + + destination.getAbsolutePath(), e); + } + configureWebContext(destination, context); + } + } else { + JarFile jar; + try { + jar = new JarFile(docBaseFile); + } catch (IOException e) { + throw new ServletContainerException("Cannot open for reading " + docBaseFile.getAbsolutePath(), e); + } + ZipEntry contextXmlEntry = jar.getEntry(CONTEXT_XML); + if (contextXmlEntry != null) { + File destination = new File(configLocation, path + XML_EXTENSION); + try { + copyFile(jar.getInputStream(contextXmlEntry), destination); + } catch (IOException e) { + throw new ServletContainerException("Cannot copy " + contextXml.getAbsolutePath() + " to " + + destination.getAbsolutePath(), e); + } + configureWebContext(destination, context); + } + } + } + + private String resolveConfigDir() { + File configFile = null; + + // Search for the property 'org.eclipse.gemini.web.tomcat.config.path' + String path = bundleContext.getProperty(TomcatConfigLocator.CONFIG_PATH_FRAMEWORK_PROPERTY); + if (path != null) { + configFile = new File(path); + if (configFile.exists()) { + return configFile.getParent(); + } + } + + // Search for the 'config' directory + configFile = new File(TomcatConfigLocator.DEFAULT_CONFIG_FILE_PATH); + if (configFile.exists()) { + return configFile.getParent(); + } else { + return DEFAULT_CONFIG_DIRECTORY; + } + } + + private void configureWebContext(File contextXml, StandardContext context) { + synchronized (digester) { + try { + digester.push(context); + try { + digester.parse(contextXml); + context.setConfigFile(contextXml.getAbsolutePath()); + } catch (IOException e) { + throw new ServletContainerException("Cannot read " + contextXml.getAbsolutePath() + + " for web application.", e); + } catch (SAXException e) { + throw new ServletContainerException("Cannot parse " + contextXml.getAbsolutePath() + + " for web application.", e); + } + } finally { + digester.reset(); + } + } + } + + private void copyFile(InputStream source, File destination) throws IOException { + destination.getParentFile().mkdirs(); + + OutputStream outputStream = null; + try { + outputStream = new FileOutputStream(destination); + byte[] buffer = new byte[1024]; + int read; + while ((read = source.read(buffer)) > 0) { + outputStream.write(buffer, 0, read); + } + } finally { + IOUtils.closeQuietly(source); + IOUtils.closeQuietly(outputStream); + } + } } diff --git a/org.eclipse.gemini.web.tomcat/template.mf b/org.eclipse.gemini.web.tomcat/template.mf index 1024713..7a482bb 100644 --- a/org.eclipse.gemini.web.tomcat/template.mf +++ b/org.eclipse.gemini.web.tomcat/template.mf @@ -26,6 +26,7 @@ Import-Template: org.eclipse.gemini.web.*;version="1.0", javax.xml.transform.*;version="0", javax.xml.validation.*;version="0", org.w3c.dom.*;version="0" -Import-Package: org.apache.catalina.deploy;version="6.0.20.S2-r5956" +Import-Package: org.apache.catalina.deploy;version="6.0.20.S2-r5956", + org.apache.catalina.session;version="6.0.20.S2-r5956" Bundle-Activator: org.eclipse.gemini.web.tomcat.internal.Activator Excluded-Exports: *.internal.* |