Author: markt
Date: Tue Mar 1 14:20:56 2016
New Revision: 1733077
URL: http://svn.apache.org/viewvc?rev=1733077&view=rev
Log:
Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=59001
Correctly handle the case when Tomcat is installed on a path where one of the
segments ends in an exclamation mark.
Modified:
tomcat/trunk/java/org/apache/catalina/startup/ClassLoaderFactory.java
tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java
tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java
tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java
tomcat/trunk/java/org/apache/catalina/webresources/JarResourceSet.java
tomcat/trunk/java/org/apache/catalina/webresources/JarWarResourceSet.java
tomcat/trunk/java/org/apache/tomcat/util/buf/UriUtil.java
tomcat/trunk/java/org/apache/tomcat/util/scan/StandardJarScanner.java
tomcat/trunk/webapps/docs/changelog.xml
Modified: tomcat/trunk/java/org/apache/catalina/startup/ClassLoaderFactory.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/ClassLoaderFactory.java?rev=1733077&r1=1733076&r2=1733077&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/ClassLoaderFactory.java
(original)
+++ tomcat/trunk/java/org/apache/catalina/startup/ClassLoaderFactory.java Tue
Mar 1 14:20:56 2016
@@ -18,6 +18,7 @@ package org.apache.catalina.startup;
import java.io.File;
import java.io.IOException;
+import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.security.AccessController;
@@ -160,7 +161,7 @@ public final class ClassLoaderFactory {
if (repositories != null) {
for (Repository repository : repositories) {
if (repository.getType() == RepositoryType.URL) {
- URL url = new URL(repository.getLocation());
+ URL url = buildClassLoaderUrl(repository.getLocation());
if (log.isDebugEnabled())
log.debug(" Including URL " + url);
set.add(url);
@@ -170,7 +171,7 @@ public final class ClassLoaderFactory {
if (!validateFile(directory, RepositoryType.DIR)) {
continue;
}
- URL url = directory.toURI().toURL();
+ URL url = buildClassLoaderUrl(directory);
if (log.isDebugEnabled())
log.debug(" Including directory " + url);
set.add(url);
@@ -180,7 +181,7 @@ public final class ClassLoaderFactory {
if (!validateFile(file, RepositoryType.JAR)) {
continue;
}
- URL url = file.toURI().toURL();
+ URL url = buildClassLoaderUrl(file);
if (log.isDebugEnabled())
log.debug(" Including jar file " + url);
set.add(url);
@@ -209,7 +210,7 @@ public final class ClassLoaderFactory {
if (log.isDebugEnabled())
log.debug(" Including glob jar file "
+ file.getAbsolutePath());
- URL url = file.toURI().toURL();
+ URL url = buildClassLoaderUrl(file);
set.add(url);
}
}
@@ -273,6 +274,30 @@ public final class ClassLoaderFactory {
return true;
}
+
+ /*
+ * These two methods would ideally be in the utility class
+ * org.apache.tomcat.util.buf.UriUtil but that class is not visible until
+ * after the class loaders have been constructed.
+ */
+ public static URL buildClassLoaderUrl(String urlString) throws
MalformedURLException {
+ // URLs passed to class loaders may point to directories that contain
+ // JARs. If these URLs are used to construct URLs for resources in a
JAR
+ // the URL will be used as is. It is therefore necessary to ensure that
+ // the sequence "!/" is not present in a class loader URL.
+ String result = urlString.replaceAll("!/", "%21/");
+ return new URL(result);
+ }
+
+
+ public static URL buildClassLoaderUrl(File file) throws
MalformedURLException {
+ // Could be a directory or a file
+ String fileUrlString = file.toURI().toURL().toString();
+ fileUrlString = fileUrlString.replaceAll("!/", "%21/");
+ return new URL(fileUrlString);
+ }
+
+
public static enum RepositoryType {
DIR,
GLOB,
Modified: tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java?rev=1733077&r1=1733076&r2=1733077&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/ContextConfig.java Tue Mar 1
14:20:56 2016
@@ -78,6 +78,7 @@ import org.apache.tomcat.util.bcel.class
import org.apache.tomcat.util.bcel.classfile.ElementValue;
import org.apache.tomcat.util.bcel.classfile.ElementValuePair;
import org.apache.tomcat.util.bcel.classfile.JavaClass;
+import org.apache.tomcat.util.buf.UriUtil;
import org.apache.tomcat.util.descriptor.XmlErrorHandler;
import org.apache.tomcat.util.descriptor.web.ContextEjb;
import org.apache.tomcat.util.descriptor.web.ContextEnvironment;
@@ -608,7 +609,7 @@ public class ContextConfig implements Li
boolean docBaseInAppBase = docBase.startsWith(appBase.getPath() +
File.separatorChar);
if (docBase.toLowerCase(Locale.ENGLISH).endsWith(".war") &&
!file.isDirectory()) {
- URL war = new URL("jar:" + (new File(docBase)).toURI().toURL() +
"!/");
+ URL war = UriUtil.buildJarUrl(new File(docBase));
if (unpackWARs) {
docBase = ExpandWar.expand(host, war, pathName);
file = new File(docBase);
@@ -624,7 +625,7 @@ public class ContextConfig implements Li
File warFile = new File(docBase + ".war");
URL war = null;
if (warFile.exists() && docBaseInAppBase) {
- war = new URL("jar:" + warFile.toURI().toURL() + "!/");
+ war = UriUtil.buildJarUrl(warFile);
}
if (docDir.exists()) {
if (war != null && unpackWARs) {
Modified: tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java?rev=1733077&r1=1733076&r2=1733077&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/HostConfig.java Tue Mar 1
14:20:56 2016
@@ -22,7 +22,6 @@ import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.net.URL;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.HashMap;
@@ -59,6 +58,7 @@ import org.apache.catalina.util.ContextN
import org.apache.juli.logging.Log;
import org.apache.juli.logging.LogFactory;
import org.apache.tomcat.util.ExceptionUtils;
+import org.apache.tomcat.util.buf.UriUtil;
import org.apache.tomcat.util.digester.Digester;
import org.apache.tomcat.util.modeler.Registry;
import org.apache.tomcat.util.res.StringManager;
@@ -852,9 +852,8 @@ public class HostConfig implements Lifec
if (context == null) {
context = new FailedContext();
}
- context.setConfigFile(new URL("jar:" +
- war.toURI().toString() + "!/" +
- Constants.ApplicationContextXml));
+ context.setConfigFile(
+ UriUtil.buildJarUrl(war,
Constants.ApplicationContextXml));
}
}
} else if (!deployXML && xmlInWar) {
Modified: tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java?rev=1733077&r1=1733076&r2=1733077&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java (original)
+++ tomcat/trunk/java/org/apache/catalina/startup/Tomcat.java Tue Mar 1
14:20:56 2016
@@ -61,6 +61,7 @@ import org.apache.catalina.core.Standard
import org.apache.catalina.core.StandardWrapper;
import org.apache.catalina.realm.GenericPrincipal;
import org.apache.catalina.realm.RealmBase;
+import org.apache.tomcat.util.buf.UriUtil;
import org.apache.tomcat.util.descriptor.web.LoginConfig;
// TODO: lazy init for the temp dir - only when a JSP is compiled or
@@ -1203,8 +1204,7 @@ public class Tomcat {
try (JarFile jar = new JarFile(docBase)) {
JarEntry entry = jar.getJarEntry(Constants.ApplicationContextXml);
if (entry != null) {
- result = new URL("jar:" + docBase.toURI().toString() + "!/"
- + Constants.ApplicationContextXml);
+ result = UriUtil.buildJarUrl(docBase,
Constants.ApplicationContextXml);
}
} catch (IOException e) {
Logger.getLogger(getLoggerName(getHost(),
contextName)).log(Level.WARNING,
Modified: tomcat/trunk/java/org/apache/catalina/webresources/JarResourceSet.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/JarResourceSet.java?rev=1733077&r1=1733076&r2=1733077&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/JarResourceSet.java
(original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/JarResourceSet.java Tue
Mar 1 14:20:56 2016
@@ -28,6 +28,7 @@ import java.util.jar.Manifest;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.WebResource;
import org.apache.catalina.WebResourceRoot;
+import org.apache.tomcat.util.buf.UriUtil;
/**
* Represents a {@link org.apache.catalina.WebResourceSet} based on a JAR file.
@@ -139,7 +140,7 @@ public class JarResourceSet extends Abst
}
try {
- setBaseUrl((new File(getBase())).toURI().toURL());
+ setBaseUrl(UriUtil.buildJarSafeUrl(new File(getBase())));
} catch (MalformedURLException e) {
throw new IllegalArgumentException(e);
}
Modified:
tomcat/trunk/java/org/apache/catalina/webresources/JarWarResourceSet.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/JarWarResourceSet.java?rev=1733077&r1=1733076&r2=1733077&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/JarWarResourceSet.java
(original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/JarWarResourceSet.java
Tue Mar 1 14:20:56 2016
@@ -29,6 +29,7 @@ import java.util.jar.Manifest;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.WebResource;
import org.apache.catalina.WebResourceRoot;
+import org.apache.tomcat.util.buf.UriUtil;
/**
* Represents a {@link org.apache.catalina.WebResourceSet} based on a JAR file
@@ -162,7 +163,7 @@ public class JarWarResourceSet extends A
}
try {
- setBaseUrl((new File(getBase())).toURI().toURL());
+ setBaseUrl(UriUtil.buildJarSafeUrl(new File(getBase())));
} catch (MalformedURLException e) {
throw new IllegalArgumentException(e);
}
Modified: tomcat/trunk/java/org/apache/tomcat/util/buf/UriUtil.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/buf/UriUtil.java?rev=1733077&r1=1733076&r2=1733077&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/buf/UriUtil.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/buf/UriUtil.java Tue Mar 1
14:20:56 2016
@@ -16,6 +16,10 @@
*/
package org.apache.tomcat.util.buf;
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+
/**
* Utility class for working with URIs and URLs.
*/
@@ -59,4 +63,49 @@ public final class UriUtil {
}
return false;
}
+
+
+ public static URL buildJarUrl(File jarFile) throws MalformedURLException {
+ return buildJarUrl(jarFile, null);
+ }
+
+
+ public static URL buildJarUrl(File jarFile, String entryPath) throws
MalformedURLException {
+ return buildJarUrl(jarFile.toURI().toURL().toString(), entryPath);
+ }
+
+
+ public static URL buildJarUrl(String fileUrlString) throws
MalformedURLException {
+ return buildJarUrl(fileUrlString, null);
+ }
+
+
+ public static URL buildJarUrl(String fileUrlString, String entryPath)
throws MalformedURLException {
+ String safeString = makeSafeForJarUrl(fileUrlString);
+ StringBuilder sb = new StringBuilder();
+ sb.append("jar:");
+ sb.append(safeString);
+ sb.append("!/");
+ if (entryPath != null) {
+ sb.append(makeSafeForJarUrl(entryPath));
+ }
+ return new URL(sb.toString());
+ }
+
+
+ public static URL buildJarSafeUrl(File file) throws MalformedURLException {
+ String safe = makeSafeForJarUrl(file.toURI().toURL().toString());
+ return new URL(safe);
+ }
+
+
+ /*
+ * Pulled out into a separate method in case we need to handle other
unusual
+ * sequences in the future.
+ */
+ private static String makeSafeForJarUrl(String input) {
+ // Since "!/" has a special meaning in a JAR URL, make sure that the
+ // sequence is properly escaped if present.
+ return input.replaceAll("!/", "%21/");
+ }
}
Modified: tomcat/trunk/java/org/apache/tomcat/util/scan/StandardJarScanner.java
URL:
http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/scan/StandardJarScanner.java?rev=1733077&r1=1733076&r2=1733077&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/scan/StandardJarScanner.java
(original)
+++ tomcat/trunk/java/org/apache/tomcat/util/scan/StandardJarScanner.java Tue
Mar 1 14:20:56 2016
@@ -36,6 +36,7 @@ import org.apache.tomcat.JarScanType;
import org.apache.tomcat.JarScanner;
import org.apache.tomcat.JarScannerCallback;
import org.apache.tomcat.util.ExceptionUtils;
+import org.apache.tomcat.util.buf.UriUtil;
import org.apache.tomcat.util.res.StringManager;
/**
@@ -317,7 +318,7 @@ public class StandardJarScanner implemen
String urlStr = url.toString();
if (urlStr.startsWith("file:") || urlStr.startsWith("http:") ||
urlStr.startsWith("https:")) {
if (urlStr.endsWith(Constants.JAR_EXT)) {
- URL jarURL = new URL("jar:" + urlStr + "!/");
+ URL jarURL = UriUtil.buildJarUrl(urlStr);
callback.scan((JarURLConnection) jarURL.openConnection(),
webappPath, isWebapp);
} else {
@@ -326,7 +327,7 @@ public class StandardJarScanner implemen
f = new File(url.toURI());
if (f.isFile() && isScanAllFiles()) {
// Treat this file as a JAR
- URL jarURL = new URL("jar:" + urlStr + "!/");
+ URL jarURL = UriUtil.buildJarUrl(f);
callback.scan(
(JarURLConnection) jarURL.openConnection(),
webappPath, isWebapp);
Modified: tomcat/trunk/webapps/docs/changelog.xml
URL:
http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1733077&r1=1733076&r2=1733077&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Tue Mar 1 14:20:56 2016
@@ -103,6 +103,10 @@
modified Context configuration parameters and reduces (slightly) the
memory footprint of a running Tomcat instance. (markt)
</fix>
+ <fix>
+ <bug>59001</bug>: Correctly handle the case when Tomcat is installed on
+ a path where one of the segments ends in an exclamation mark. (markt)
+ </fix>
<update>
Switch to the web application class loader to the
<code>ParallelWebappClassLoader</code> by default. (markt)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]