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.*