Merge branch 'master' into bug312752
diff --git a/org.eclipse.gemini.web.core/.classpath b/org.eclipse.gemini.web.core/.classpath index dfeb4f0..3ef650f 100644 --- a/org.eclipse.gemini.web.core/.classpath +++ b/org.eclipse.gemini.web.core/.classpath
@@ -21,10 +21,10 @@ </attributes> </classpathentry> <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/> - <classpathentry kind="var" path="WEB_CONTAINER_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/WEB_CONTAINER_IVY_CACHE/org.junit/com.springsource.org.junit/4.5.0/com.springsource.org.junit-sources-4.5.0.jar"/> + <classpathentry kind="var" path="WEB_CONTAINER_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-4.7.0.jar" sourcepath="/WEB_CONTAINER_IVY_CACHE/org.junit/com.springsource.org.junit/4.7.0/com.springsource.org.junit-sources-4.7.0.jar"/> <classpathentry kind="var" path="WEB_CONTAINER_IVY_CACHE/org.eclipse.osgi/org.eclipse.osgi/3.5.1.R35x_v20091005/org.eclipse.osgi-3.5.1.R35x_v20091005.jar" sourcepath="/WEB_CONTAINER_IVY_CACHE/org.eclipse.osgi/org.eclipse.osgi/3.5.1.R35x_v20091005/org.eclipse.osgi-sources-3.5.1.R35x_v20091005.jar"/> <classpathentry kind="var" path="WEB_CONTAINER_IVY_CACHE/org.eclipse.virgo.util/org.eclipse.virgo.util.osgi/2.1.0.D-20100420091708/org.eclipse.virgo.util.osgi-2.1.0.D-20100420091708.jar" sourcepath="/WEB_CONTAINER_IVY_CACHE/org.eclispe.virgo.util/org.eclipse.virgo.util.osgi/2.0.0.RELEASE/org.eclipse.virgo.util.osgi-sources-2.0.0.RELEASE.jar"/> - <classpathentry kind="var" path="WEB_CONTAINER_IVY_CACHE/org.eclipse.virgo.util/org.eclipse.virgo.util.io/2.1.0.D-20100420091708/org.eclipse.virgo.util.io-2.1.0.D-20100420091708.jar" sourcepath="/WEB_CONTAINER_IVY_CACHE/org.eclispe.virgo.util/org.eclipse.virgo.util.io/2.0.0.RELEASE/org.eclipse.virgo.util.io-sources-2.0.0.RELEASE.jar"/> + <classpathentry kind="var" path="WEB_CONTAINER_IVY_CACHE/org.eclipse.virgo.util/org.eclipse.virgo.util.io/2.1.0.D-20100420091708/org.eclipse.virgo.util.io-2.1.0.D-20100420091708.jar" sourcepath="/WEB_CONTAINER_IVY_CACHE/org.eclipse.virgo.util/org.eclipse.virgo.util.io/2.1.0.D-20100420091708/org.eclipse.virgo.util.io-sources-2.1.0.D-20100420091708.jar"/> <classpathentry kind="var" path="WEB_CONTAINER_IVY_CACHE/org.eclipse.virgo.util/org.eclipse.virgo.util.common/2.1.0.D-20100420091708/org.eclipse.virgo.util.common-2.1.0.D-20100420091708.jar" sourcepath="/WEB_CONTAINER_IVY_CACHE/org.eclispe.virgo.util/org.eclipse.virgo.util.common/2.0.0.RELEASE/org.eclipse.virgo.util.common-sources-2.0.0.RELEASE.jar"/> <classpathentry kind="var" path="WEB_CONTAINER_IVY_CACHE/org.slf4j/com.springsource.slf4j.api/1.5.10/com.springsource.slf4j.api-1.5.10.jar" sourcepath="/WEB_CONTAINER_IVY_CACHE/org.slf4j/com.springsource.slf4j.api/1.5.10/com.springsource.slf4j.api-sources-1.5.10.jar"/> <classpathentry kind="var" path="WEB_CONTAINER_IVY_CACHE/org.apache.catalina.springsource/com.springsource.org.apache.catalina.springsource/6.0.20.S2-r5956/com.springsource.org.apache.catalina.springsource-6.0.20.S2-r5956.jar" sourcepath="/WEB_CONTAINER_IVY_CACHE/org.apache.catalina.springsource/com.springsource.org.apache.catalina.springsource/6.0.20.S2-r5956/com.springsource.org.apache.catalina.springsource-sources-6.0.20.S2-r5956.jar"/>
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..f5ed6c3 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.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; @@ -36,6 +38,7 @@ import javax.servlet.ServletContext; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; import org.junit.runner.RunWith; import org.osgi.framework.Bundle; @@ -47,6 +50,7 @@ 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,9 +79,20 @@ 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; + + @BeforeClass + public static void beforeClass() throws Exception { + System.setProperty("org.eclipse.gemini.web.tomcat.config.path", "target/config/tomcat-server.xml"); + } @Before public void before() throws Exception { @@ -338,4 +353,65 @@ this.container.stopWebApplication(handle); } } + + @Test + public void testWarWithContextXml() throws Exception { + // Copy default context.xml + File defaultContextXml = new File("target/config/context.xml"); + createFileWithContent(defaultContextXml, "<Context crossContext=\"true\"/>"); + + // Copy default context.xml.default + File defaultHostContextXml = new File("target/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("target/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 new file mode 100755 index 0000000..26fecfc --- /dev/null +++ b/org.eclipse.gemini.web.test/src/test/resources/war-with-context-xml-cross-context.war Binary files differ
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 new file mode 100755 index 0000000..102bc64 --- /dev/null +++ b/org.eclipse.gemini.web.test/src/test/resources/war-with-context-xml-resources.war Binary files differ
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..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
@@ -58,8 +58,11 @@ private final ExtendCatalina catalina = new ExtendCatalina(); private final JarScanner jarScanner; + + 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(); @@ -136,16 +139,36 @@ if (LOGGER.isDebugEnabled()) { LOGGER.debug("Creating context '" + path + "' with docBase '" + docBase + "'"); } - + StandardContext context = new ExtendedStandardContext(); + + 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); @@ -210,5 +233,29 @@ * */ private static class ExtendedContextConfig extends ContextConfig { + private File configDir; + + /** + * 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; + } + + if (configDir != null) { + return configDir; + } + + return null; + } + + protected void setConfigBase(File configDir) { + this.configDir = configDir; + } } + }
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..0126e30 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
@@ -48,7 +48,7 @@ private static final Logger LOGGER = LoggerFactory.getLogger(TomcatConfigLocator.class); static final String CONFIG_PATH_FRAMEWORK_PROPERTY = "org.eclipse.gemini.web.tomcat.config.path"; - + static final String DEFAULT_CONFIG_FILE_PATH = "config" + File.separator + "tomcat-server.xml"; static final String CONFIG_PATH = "META-INF/tomcat"; @@ -68,15 +68,63 @@ 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 framework property 'org.eclipse.gemini.web.tomcat.config.path' + * + * Note: this is supposed to search framework and system properties but appears to ignore system properties which + * are set after the framework has initialised. See https://bugs.eclipse.org/bugs/show_bug.cgi?id=319679. + */ + 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 system property 'org.eclipse.gemini.web.tomcat.config.path' + path = System.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; String path = context.getProperty(CONFIG_PATH_FRAMEWORK_PROPERTY); - if(path != null) { + if (path != null) { result = tryGetStreamForFilePath(path); } - - if(result == null) { + + if (result == null) { result = tryGetStreamForFilePath(DEFAULT_CONFIG_FILE_PATH); } return result; @@ -111,7 +159,7 @@ entry = bundle.getEntry(DEFAULT_CONFIG_PATH); if (entry == null) { throw new IllegalStateException("Unable to locate default Tomcat configuration. Is the '" + bundle + "' bundle corrupt?"); - } else if(LOGGER.isInfoEnabled()) { + } else if (LOGGER.isInfoEnabled()) { LOGGER.info("Configuring Tomcat from default config file"); } }
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..6e3da32 --- /dev/null +++ b/org.eclipse.gemini.web.tomcat/src/main/java/org/eclipse/gemini/web/tomcat/internal/WebappConfigLocator.java
@@ -0,0 +1,180 @@ +/******************************************************************************* + * Copyright (c) 2010 SAP AG + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at + * http://www.opensource.org/licenses/apache2.0.php. + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * Violeta Georgieva - initial contribution + *******************************************************************************/ + +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; +import org.eclipse.virgo.util.io.PathReference; + +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 { + PathReference destinationRef = new PathReference(destination); + destinationRef.getParent().createDirectory(); + + 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.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 @@ 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..7243e74 --- /dev/null +++ b/org.eclipse.gemini.web.tomcat/src/test/java/org/eclipse/gemini/web/tomcat/internal/WebappConfigLocatorTest.java
@@ -0,0 +1,209 @@ +/******************************************************************************* + * Copyright (c) 2010 SAP AG + * + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * and Apache License v2.0 which accompanies this distribution. + * The Eclipse Public License is available at + * http://www.eclipse.org/legal/epl-v10.html + * and the Apache License v2.0 is available at + * http://www.opensource.org/licenses/apache2.0.php. + * You may elect to redistribute this code under either of these licenses. + * + * Contributors: + * Violeta Georgieva - initial contribution + *******************************************************************************/ + +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 --- /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 --- /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
diff --git a/org.eclipse.gemini.web.tomcat/template.mf b/org.eclipse.gemini.web.tomcat/template.mf index 6d62570..1abab2a 100644 --- a/org.eclipse.gemini.web.tomcat/template.mf +++ b/org.eclipse.gemini.web.tomcat/template.mf
@@ -26,6 +26,7 @@ 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.*