| author | Violeta Georgieva | 2010-07-08 11:21:08 (EDT) |
|---|---|---|
| committer | Glyn Normington | 2010-07-08 11:22:58 (EDT) |
| commit | e9142ece90ac9c8c43ead7d0c32127ea42148302 (patch) (side-by-side diff) | |
| tree | 22ad0fb6a120e6fd09b1b40049bc5743ecce8d74 | |
| parent | 4feac292ffbb339d33f585f7b86a49e1997e0d8b (diff) | |
| download | org.eclipse.gemini.web.gemini-web-container-e9142ece90ac9c8c43ead7d0c32127ea42148302.zip org.eclipse.gemini.web.gemini-web-container-e9142ece90ac9c8c43ead7d0c32127ea42148302.tar.gz org.eclipse.gemini.web.gemini-web-container-e9142ece90ac9c8c43ead7d0c32127ea42148302.tar.bz2 | |
bug 312752: support for configuring Context elements for all web apps
Author: Violeta Georgieva <milesg78@gmail.com>
10 files changed, 545 insertions, 147 deletions
diff --git a/org.eclipse.gemini.web.test/src/test/java/org/eclipse/gemini/web/test/tomcat/TomcatServletContainerTests.java b/org.eclipse.gemini.web.test/src/test/java/org/eclipse/gemini/web/test/tomcat/TomcatServletContainerTests.java index e5d0c6e..2acfffd 100644 --- a/org.eclipse.gemini.web.test/src/test/java/org/eclipse/gemini/web/test/tomcat/TomcatServletContainerTests.java +++ b/org.eclipse.gemini.web.test/src/test/java/org/eclipse/gemini/web/test/tomcat/TomcatServletContainerTests.java @@ -23,6 +23,8 @@ import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.BufferedReader; +import java.io.File; +import java.io.FileWriter; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; @@ -47,6 +49,7 @@ import org.eclipse.gemini.web.core.spi.ServletContainer; import org.eclipse.gemini.web.core.spi.WebApplicationHandle; import org.eclipse.virgo.test.framework.OsgiTestRunner; import org.eclipse.virgo.test.framework.TestFrameworkUtils; +import org.eclipse.virgo.util.io.IOUtils; import org.eclipse.virgo.util.io.PathReference; import org.eclipse.virgo.util.io.ZipUtils; @@ -75,6 +78,12 @@ public class TomcatServletContainerTests { private static final String LOCATION_WAR_WITH_TLD_IMPORT_SYSTEM_PACKAGES = LOCATION_PREFIX + "../org.eclipse.gemini.web.test/src/test/resources/war-with-tld-import-system-packages.war?Web-ContextPath=/war-with-tld-import-system-packages"; + private static final String LOCATION_WAR_WITH_CONTEXT_XML_RESOURCES = LOCATION_PREFIX + + "../org.eclipse.gemini.web.test/src/test/resources/war-with-context-xml-resources.war?Web-ContextPath=/war-with-context-xml-resources"; + + private static final String LOCATION_WAR_WITH_CONTEXT_XML_CROSS_CONTEXT = LOCATION_PREFIX + + "../org.eclipse.gemini.web.test/src/test/resources/war-with-context-xml-cross-context.war?Web-ContextPath=/war-with-context-xml-cross-context"; + private BundleContext bundleContext; private ServletContainer container; @@ -338,4 +347,65 @@ public class TomcatServletContainerTests { this.container.stopWebApplication(handle); } } + + @Test + public void testWarWithContextXml() throws Exception { + // Copy default context.xml + File defaultContextXml = new File("config/context.xml"); + createFileWithContent(defaultContextXml, "<Context crossContext=\"true\"/>"); + + // Copy default context.xml.default + File defaultHostContextXml = new File("config/Catalina/localhost/context.xml.default"); + String content = "<Context>" + + "<Resource name=\"mail/Session1\" auth=\"Container\" type=\"javax.mail.Session\" mail.smtp.host=\"localhost\"/>" + + "</Context>"; + createFileWithContent(defaultHostContextXml, content); + + File tomcatServerXml = new File("config/tomcat-server.xml"); + createFileWithContent(tomcatServerXml, ""); + + String location1 = LOCATION_WAR_WITH_CONTEXT_XML_RESOURCES; + Bundle bundle1 = this.bundleContext.installBundle(location1); + bundle1.start(); + + String location2 = LOCATION_WAR_WITH_CONTEXT_XML_CROSS_CONTEXT; + Bundle bundle2 = this.bundleContext.installBundle(location2); + bundle2.start(); + + WebApplicationHandle handle1 = this.container.createWebApplication("/war-with-context-xml-resources", bundle1); + this.container.startWebApplication(handle1); + + WebApplicationHandle handle2 = this.container.createWebApplication("/war-with-context-xml-cross-context", + bundle2); + this.container.startWebApplication(handle2); + try { + // tests JNDI resources + validateURL("http://localhost:8080/war-with-context-xml-resources/index.jsp"); + + // tests cross context functionality + validateURL("http://localhost:8080/war-with-context-xml-cross-context/index.jsp"); + } finally { + this.container.stopWebApplication(handle1); + bundle1.uninstall(); + + this.container.stopWebApplication(handle2); + bundle2.uninstall(); + + defaultContextXml.delete(); + defaultHostContextXml.delete(); + tomcatServerXml.delete(); + } + } + + private void createFileWithContent(File file, String content) throws Exception { + file.getParentFile().mkdirs(); + FileWriter fWriter = null; + try { + fWriter = new FileWriter(file); + fWriter.write(content); + fWriter.flush(); + } finally { + IOUtils.closeQuietly(fWriter); + } + } } diff --git a/org.eclipse.gemini.web.test/src/test/resources/war-with-context-xml-cross-context.war b/org.eclipse.gemini.web.test/src/test/resources/war-with-context-xml-cross-context.war Binary files differnew file mode 100755 index 0000000..26fecfc --- a/dev/null +++ b/org.eclipse.gemini.web.test/src/test/resources/war-with-context-xml-cross-context.war diff --git a/org.eclipse.gemini.web.test/src/test/resources/war-with-context-xml-resources.war b/org.eclipse.gemini.web.test/src/test/resources/war-with-context-xml-resources.war Binary files differnew file mode 100755 index 0000000..102bc64 --- a/dev/null +++ b/org.eclipse.gemini.web.test/src/test/resources/war-with-context-xml-resources.war 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 db1828c..78709de 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,13 +17,8 @@ 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; @@ -45,7 +40,6 @@ 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; @@ -58,40 +52,22 @@ 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); private final ExtendCatalina catalina = new ExtendCatalina(); private final JarScanner jarScanner; - - private Digester digester; private BundleContext bundleContext; Tomcat(BundleContext context, PackageAdmin packageAdmin) { - this.bundleContext = context; + 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 { @@ -165,15 +141,34 @@ final class Tomcat extends Embedded { } StandardContext context = new ExtendedStandardContext(); - readContextXml(path, docBase, context); + + ExtendedContextConfig config = new ExtendedContextConfig(); + + // Allocate the tomcat's configuration directory + File configDir = TomcatConfigLocator.resolveConfigDir(bundleContext); + config.setConfigBase(configDir); + + // If default context.xml is existing, set it to the ContextConfig + String defaultContextXml = WebappConfigLocator.resolveDefaultContextXml(configDir); + if (defaultContextXml != null) { + config.setDefaultContextXml(defaultContextXml); + } + + // Allocate the web application's configuration directory + File configLocation = WebappConfigLocator.resolveWebappConfigDir(configDir, findHost()); + + // If web application's context.xml is existing, set it to the + // StandardContext + File contextXml = WebappConfigLocator.resolveWebappContextXml(path, docBase, configLocation); + if (contextXml != null) { + context.setConfigFile(contextXml.getAbsolutePath()); + } context.setDocBase(docBase); context.setPath(path.equals(ROOT_PATH) ? ROOT_CONTEXT_PATH : path); context.setJarScanner(this.jarScanner); - ContextConfig config = new ExtendedContextConfig(); - config.setCustomAuthenticators(this.authenticators); ((Lifecycle) context).addLifecycleListener(config); @@ -238,133 +233,29 @@ 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 File configDir; - 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); + /** + * If there is not configuration directory, return custom configuration + * directory. It is used to resolve the context.xml.default + */ + @Override + protected File getConfigBase() { + File configBase = super.getConfigBase(); + if (configBase != null) { + return configBase; } - } - } - - 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(); + if (configDir != null) { + return configDir; } - } - // Search for the 'config' directory - configFile = new File(TomcatConfigLocator.DEFAULT_CONFIG_FILE_PATH); - if (configFile.exists()) { - return configFile.getParent(); - } else { - return DEFAULT_CONFIG_DIRECTORY; + return null; } - } - 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(); - } + protected void setConfigBase(File configDir) { + this.configDir = configDir; } } - 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/src/main/java/org/eclipse/gemini/web/tomcat/internal/TomcatConfigLocator.java b/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/TomcatConfigLocator.java index 837a099..160a2a3 100644 --- a/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/TomcatConfigLocator.java +++ b/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/TomcatConfigLocator.java @@ -68,6 +68,44 @@ final class TomcatConfigLocator { return is; } + /** + * Returns the directory where the Tomcat configuration files resides. + * + * The location algorithm is as follows: + * <ol> + * <li>Check for <code>org.eclipse.gemini.web.tomcat.config.path</code> + * framework property, use if found</li> + * <li>Check for <code>config/tomcat-server.xml</code> in the current + * working directory, use if found</li> + * <li>If the previous checks do not return a result, return + * <code>null</code></li> + * </ol> + * + * @param context + * the bundle context + * @return the directory where the Tomcat configuration files resides. + */ + public static File resolveConfigDir(BundleContext context) { + File configFile = null; + + // Search for the property 'org.eclipse.gemini.web.tomcat.config.path' + String path = context.getProperty(TomcatConfigLocator.CONFIG_PATH_FRAMEWORK_PROPERTY); + if (path != null) { + configFile = new File(path); + if (configFile.exists()) { + return configFile.getParentFile(); + } + } + + // Search for the 'config' directory + configFile = new File(TomcatConfigLocator.DEFAULT_CONFIG_FILE_PATH); + if (configFile.exists()) { + return configFile.getParentFile(); + } + + return null; + } + private static InputStream lookupConfigInFileSystem(BundleContext context) { InputStream result = null; diff --git a/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/WebappConfigLocator.java b/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/WebappConfigLocator.java new file mode 100755 index 0000000..79cf128 --- a/dev/null +++ b/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/WebappConfigLocator.java @@ -0,0 +1,177 @@ +package org.eclipse.gemini.web.tomcat.internal; + +import java.io.File; +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.Engine; +import org.apache.catalina.Host; +import org.eclipse.gemini.web.core.spi.ServletContainerException; +import org.eclipse.virgo.util.io.IOUtils; + +public class WebappConfigLocator { + + static final String DEFAULT_CONFIG_DIRECTORY = "config"; + + private static final String DEFAULT_CONTEXT_XML = "context.xml"; + + private static final String CONTEXT_XML = "META-INF/context.xml"; + + private static final String XML_EXTENSION = ".xml"; + + private static final String ROOT_PATH = "/"; + + private static final String ROOT_CONTEXT_FILE = "ROOT"; + + private static final char SLASH_SEPARATOR = '/'; + + private static final char HASH_SEPARATOR = '#'; + + /** + * Resolves the default context.xml and returns a relative path to it, if it + * exists in the main Tomcat's configuration directory, otherwise returns + * <code>null</code>. The method returns <code>null</code> also in case main + * Tomcat's configuration directory does not exists. + * + * @param configLocation + * the main Tomcat's configuration directory + * @return a relative path to default context.xml file, if it exists in the + * main Tomcat's configuration directory, otherwise returns + * <code>null</code>. + */ + public static String resolveDefaultContextXml(File configLocation) { + if (configLocation == null) { + return null; + } + + File defaultContextXml = new File(configLocation, DEFAULT_CONTEXT_XML); + if (defaultContextXml.exists()) { + return getRelativePath(defaultContextXml); + } else { + return null; + } + } + + /** + * Resolves the web application's specific context.xml The algorithm is the + * following: + * <ol> + * <li>The composite context path i.e. /foo/bar are formated. The "/" are + * replaced with "#" i.e. foo#bar</li> + * <li>Check for <code><formated-web-app-context-path>.xml</code> file in + * the main Tomcat Host's configuration directory, use if found</li> + * <li>If <code>docBase</code> is directory check for + * <code>META-INF/context.xml</code> file, use if found</li> + * <li>If <code>docBase</code> is an archive check for + * <code>META-INF/context.xml</code> entry. If it exists, copy it to the + * main Tomcat Host's configuration directory and use it. The next time this + * copy will be used instead of the one in the archive.</li> + * <li>Return <code>null</code> in other cases.</li> + * </ol> + * + * @param path + * the context path + * @param docBase + * the root directory/file for the web application + * @param configLocation + * Host's configuration directory + * @return the context.xml if it is found following the algorithm above, + * otherwise <code>null</code> + */ + public static File resolveWebappContextXml(String path, String docBase, File configLocation) { + path = formatContextPath(path); + + // Try to find the context.xml in the Tomcat's configuration directory + File contextXml = new File(configLocation, path + XML_EXTENSION); + if (contextXml.exists()) { + return contextXml; + } + + // 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()) { + return contextXml; + } + } 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); + } + return destination; + } + } + return null; + } + + /** + * Resolves the directory where the web application' context.xml files are + * placed. Typically this is the Host's configuration directory. + * + * @param mainConfigDir + * the main Tomcat's configuration directory + * @return the directory where the web applications' context.xml files are + * placed. + */ + public static File resolveWebappConfigDir(File mainConfigDir, Host host) { + mainConfigDir = mainConfigDir != null ? mainConfigDir : new File(DEFAULT_CONFIG_DIRECTORY); + + File configLocation = mainConfigDir; + + Container parent = host.getParent(); + if ((parent != null) && (parent instanceof Engine)) { + configLocation = new File(configLocation, parent.getName()); + } + + return new File(configLocation, host.getName()); + } + + private static String formatContextPath(String contextPath) { + // Multi-level context paths may be defined using #, e.g. foo#bar.xml + // for a context path of /foo/bar. + if (contextPath.equals(ROOT_PATH)) { + contextPath = ROOT_CONTEXT_FILE; + } else if (SLASH_SEPARATOR == contextPath.charAt(0)) { + contextPath = contextPath.substring(1); + } + return contextPath.replace(SLASH_SEPARATOR, HASH_SEPARATOR); + } + + private static 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); + } + } + + private static String getRelativePath(File file) { + return new File(".").toURI().relativize(file.toURI()).toString(); + } +} diff --git a/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/TomcatConfigLocatorTests.java b/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/TomcatConfigLocatorTests.java index eba96a5..004129a 100644 --- a/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/TomcatConfigLocatorTests.java +++ b/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/TomcatConfigLocatorTests.java @@ -21,7 +21,10 @@ import static org.easymock.EasyMock.createNiceMock; import static org.easymock.EasyMock.expect; import static org.easymock.EasyMock.replay; import static org.easymock.EasyMock.verify; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; +import java.io.File; import java.net.URL; import java.util.Vector; @@ -78,6 +81,27 @@ public class TomcatConfigLocatorTests { TomcatConfigLocator.resolveConfigFile(mockContext); } + + @Test + public void testResolveConfigDir() throws Exception { + URL existingUrl = new URL("file:src/test/resources/server.xml"); + URL nonexistingUrl = new URL("file:src/test/resources/server1.xml"); + + BundleContext mockContext = createMock(BundleContext.class); + expect(mockContext.getProperty(TomcatConfigLocator.CONFIG_PATH_FRAMEWORK_PROPERTY)).andReturn( + (new File(existingUrl.getPath())).getAbsolutePath()).andReturn( + (new File(nonexistingUrl.getPath())).getAbsolutePath()).andReturn(null); + + replay(mockContext); + + String result = "src" + File.separator + "test" + File.separator + "resources"; + + assertTrue(TomcatConfigLocator.resolveConfigDir(mockContext).getAbsolutePath().endsWith(result)); + assertEquals(null, TomcatConfigLocator.resolveConfigDir(mockContext)); + assertEquals(null, TomcatConfigLocator.resolveConfigDir(mockContext)); + + verify(mockContext); + } private BundleContext createMockBundleContext(Bundle mockBundle) { BundleContext mockContext = createNiceMock(BundleContext.class); diff --git a/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/WebappConfigLocatorTest.java b/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/WebappConfigLocatorTest.java new file mode 100755 index 0000000..1dd19c9 --- a/dev/null +++ b/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/WebappConfigLocatorTest.java @@ -0,0 +1,193 @@ +package org.eclipse.gemini.web.tomcat.internal; + +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.assertEquals; +import static org.easymock.EasyMock.createMock; +import static org.easymock.EasyMock.expect; +import static org.easymock.EasyMock.replay; +import static org.easymock.EasyMock.verify; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.URL; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.jar.Manifest; + +import org.apache.catalina.Container; +import org.apache.catalina.Engine; +import org.apache.catalina.Host; +import org.eclipse.gemini.web.core.spi.ServletContainerException; +import org.eclipse.virgo.util.io.IOUtils; +import org.junit.Before; +import org.junit.Test; + +public class WebappConfigLocatorTest { + private static final String CONTEXT_PATH_1 = "test"; + private static final String CONTEXT_PATH_2 = "test1"; + private static final String CONTEXT_PATH_3 = "/"; + private static final String CONTEXT_PATH_4 = "/test/test"; + private static final String CONTEXT_PATH_5 = "test/test"; + + private static final String CONFIG_FILE_LOCATION_1 = "file:src/test/resources/test.xml"; + private static final String CONFIG_FILE_LOCATION_2 = "file:src/test/resources/META-INF/context.xml"; + private static final String CONFIG_FILE_LOCATION_3 = "file:target/test-classes/test1.xml"; + private static final String CONFIG_FILE_LOCATION_4 = "file:target/test-classes/ROOT.xml"; + private static final String CONFIG_FILE_LOCATION_5 = "file:target/test-classes/test%23test.xml"; + + private static final String CONFIG_DIR_LOCATION_1 = "file:src/test/resources"; + private static final String CONFIG_DIR_LOCATION_2 = "file:src/test"; + private static final String CONFIG_DIR_LOCATION_3 = "file:target/test-classes"; + + private static final String CORRUPTED_JAR_NAME = "file:target/test-classes/corrupted.jar"; + private static final String JAR_NAME_1 = "file:target/test-classes/test1.jar"; + private static final String JAR_NAME_2 = "file:target/test-classes/test2.jar"; + private static final String JAR_ENTRY_NAME = "META-INF/context.xml"; + + private static final String HOST_NAME = "localhost"; + private static final String ENGINE_NAME = "Catalina"; + + @Before + public void setUp() throws Exception { + URL urlFile2 = new URL(CONFIG_FILE_LOCATION_2); + URL jarFile1 = new URL(JAR_NAME_1); + URL jarFile2 = new URL(JAR_NAME_2); + URL corruptedJarFile = new URL(CORRUPTED_JAR_NAME); + new File(corruptedJarFile.getPath()).createNewFile(); + + byte[] buffer = new byte[1024]; + int bytesRead; + + FileOutputStream stream = null; + JarOutputStream out = null; + FileInputStream file = null; + try { + stream = new FileOutputStream(jarFile1.getPath()); + out = new JarOutputStream(stream, new Manifest()); + file = new FileInputStream(new File(urlFile2.getPath())); + JarEntry jarAdd = new JarEntry(JAR_ENTRY_NAME); + out.putNextEntry(jarAdd); + while ((bytesRead = file.read(buffer)) != -1) { + out.write(buffer, 0, bytesRead); + } + out.closeEntry(); + } finally { + IOUtils.closeQuietly(file); + IOUtils.closeQuietly(out); + IOUtils.closeQuietly(stream); + } + + try { + stream = new FileOutputStream(jarFile2.getPath()); + out = new JarOutputStream(stream, new Manifest()); + } finally { + IOUtils.closeQuietly(out); + IOUtils.closeQuietly(stream); + } + } + + @Test + public void testResolveWebappContextXml() throws Exception { + URL urlFile1 = new URL(CONFIG_FILE_LOCATION_1); + URL urlDir1 = new URL(CONFIG_DIR_LOCATION_1); + // context.xml exists in the configuration directory + assertEquals(new File(urlFile1.getPath()), WebappConfigLocator.resolveWebappContextXml(CONTEXT_PATH_1, null, + new File(urlDir1.getPath()))); + + URL urlFile2 = new URL(CONFIG_FILE_LOCATION_2); + URL urlDir2 = new URL(CONFIG_DIR_LOCATION_2); + // context.xml does not exist in the configuration directory, but exists + // in doc base + // doc base is directory + assertEquals(new File(urlFile2.getPath()), WebappConfigLocator.resolveWebappContextXml(CONTEXT_PATH_2, urlDir1 + .getPath(), new File(urlDir1.getPath()))); + // context.xml does not exist in the configuration directory and in doc + // base + // doc base is directory + assertEquals(null, WebappConfigLocator.resolveWebappContextXml(CONTEXT_PATH_2, urlDir2.getPath(), new File( + urlDir1.getPath()))); + + try { + // context.xml does not exist in the configuration directory, doc + // base is jar and does not exist + URL corruptedJarFile = new URL(CORRUPTED_JAR_NAME); + WebappConfigLocator.resolveWebappContextXml(CONTEXT_PATH_2, corruptedJarFile.getPath(), new File(urlDir1 + .getPath())); + } catch (ServletContainerException e) { + assertTrue(e.getCause() instanceof IOException); + } + + URL jarFile1 = new URL(JAR_NAME_1); + URL jarFile2 = new URL(JAR_NAME_2); + URL urlDir3 = new URL(CONFIG_DIR_LOCATION_3); + URL urlFile3 = new URL(CONFIG_FILE_LOCATION_3); + // context.xml does not exist in the configuration directory, but exists + // in doc base + // doc base is jar + // copy will be performed + assertEquals(new File(urlFile3.getPath()), WebappConfigLocator.resolveWebappContextXml(CONTEXT_PATH_2, jarFile1 + .getPath(), new File(urlDir3.getPath()))); + // context.xml does not exist in the configuration directory and in doc + // base + // doc base is jar + assertEquals(null, WebappConfigLocator.resolveWebappContextXml(CONTEXT_PATH_2, jarFile2.getPath(), new File( + urlDir1.getPath()))); + + URL urlFile4 = new URL(CONFIG_FILE_LOCATION_4); + URL urlFile5 = new URL(CONFIG_FILE_LOCATION_5); + // different types of context path + assertEquals(new File(urlFile4.getPath()), WebappConfigLocator.resolveWebappContextXml(CONTEXT_PATH_3, jarFile1 + .getPath(), new File(urlDir3.getPath()))); + assertEquals(new File(urlFile5.toURI().getSchemeSpecificPart()), WebappConfigLocator.resolveWebappContextXml( + CONTEXT_PATH_4, jarFile1.getPath(), new File(urlDir3.getPath()))); + assertEquals(new File(urlFile5.toURI().getSchemeSpecificPart()), WebappConfigLocator.resolveWebappContextXml( + CONTEXT_PATH_5, jarFile1.getPath(), new File(urlDir3.getPath()))); + } + + @Test + public void testResolveWebappConfigDir() { + Host mockHost = createMock(Host.class); + Engine mockEngine = createMock(Engine.class); + Container mockContainer = createMock(Container.class); + expect(mockHost.getParent()).andReturn(mockEngine).andReturn(mockContainer).andReturn(null).andReturn( + mockEngine).andReturn(mockContainer).andReturn(null); + expect(mockHost.getName()).andReturn(HOST_NAME).times(6); + expect(mockEngine.getName()).andReturn(ENGINE_NAME).times(2); + + replay(mockHost, mockEngine); + + File configDir = new File(""); + File expected = new File(configDir, ENGINE_NAME); + expected = new File(expected, HOST_NAME); + assertEquals(expected, WebappConfigLocator.resolveWebappConfigDir(configDir, mockHost)); + + expected = new File(configDir, HOST_NAME); + assertEquals(expected, WebappConfigLocator.resolveWebappConfigDir(configDir, mockHost)); + assertEquals(expected, WebappConfigLocator.resolveWebappConfigDir(configDir, mockHost)); + + configDir = new File(WebappConfigLocator.DEFAULT_CONFIG_DIRECTORY); + expected = new File(configDir, ENGINE_NAME); + expected = new File(expected, HOST_NAME); + assertEquals(expected, WebappConfigLocator.resolveWebappConfigDir(null, mockHost)); + + expected = new File(configDir, HOST_NAME); + assertEquals(expected, WebappConfigLocator.resolveWebappConfigDir(null, mockHost)); + assertEquals(expected, WebappConfigLocator.resolveWebappConfigDir(null, mockHost)); + + verify(mockHost, mockEngine); + } + + @Test + public void testResolveDefaultContextXml() throws Exception { + assertEquals(null, WebappConfigLocator.resolveDefaultContextXml(null)); + + URL urlFile = new URL(CONFIG_FILE_LOCATION_2); + assertEquals(urlFile.getPath(), WebappConfigLocator.resolveDefaultContextXml(new File(urlFile.getPath()) + .getParentFile())); + + assertEquals(null, WebappConfigLocator.resolveDefaultContextXml(new File(urlFile.getPath()).getParentFile() + .getParentFile())); + } +} diff --git a/org.eclipse.gemini.web.tomcat/src/test/resources/META-INF/context.xml b/org.eclipse.gemini.web.tomcat/src/test/resources/META-INF/context.xml new file mode 100755 index 0000000..e69de29 --- a/dev/null +++ b/org.eclipse.gemini.web.tomcat/src/test/resources/META-INF/context.xml diff --git a/org.eclipse.gemini.web.tomcat/src/test/resources/test.xml b/org.eclipse.gemini.web.tomcat/src/test/resources/test.xml new file mode 100755 index 0000000..e3e359d --- a/dev/null +++ b/org.eclipse.gemini.web.tomcat/src/test/resources/test.xml @@ -0,0 +1,5 @@ +<Context crossContext="true" + privileged="true" + reloadable="true" + useHTTPOnly="true" +/>
\ No newline at end of file |

