You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by ma...@apache.org on 2017/02/17 14:24:34 UTC

svn commit: r1783408 - in /tomcat/trunk: java/org/apache/catalina/webresources/ java/org/apache/tomcat/util/buf/ java/org/apache/tomcat/util/scan/ test/org/apache/tomcat/util/buf/ webapps/docs/ webapps/docs/config/

Author: markt
Date: Fri Feb 17 14:24:33 2017
New Revision: 1783408

URL: http://svn.apache.org/viewvc?rev=1783408&view=rev
Log:
Fix https://issues.apache.org/bugzilla/show_bug.cgi?id=60728
Make the separator Tomcat uses in the Tomcat specific war:file:... URL protocol customizable via a system property. The separator is equivalent to the use of the '!' character in jar:file:... URLs. The default separator of '*' remains unchanged.

Added:
    tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil24.java
    tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil26.java
    tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil2A.java
    tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil40.java
    tomcat/trunk/test/org/apache/tomcat/util/buf/TesterUriUtilBase.java
      - copied, changed from r1783407, tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil.java
Removed:
    tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil.java
Modified:
    tomcat/trunk/java/org/apache/catalina/webresources/JarWarResource.java
    tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java
    tomcat/trunk/java/org/apache/catalina/webresources/WarResource.java
    tomcat/trunk/java/org/apache/tomcat/util/buf/UriUtil.java
    tomcat/trunk/java/org/apache/tomcat/util/scan/JarFactory.java
    tomcat/trunk/webapps/docs/changelog.xml
    tomcat/trunk/webapps/docs/config/systemprops.xml

Modified: tomcat/trunk/java/org/apache/catalina/webresources/JarWarResource.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/JarWarResource.java?rev=1783408&r1=1783407&r2=1783408&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/JarWarResource.java (original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/JarWarResource.java Fri Feb 17 14:24:33 2017
@@ -24,6 +24,7 @@ import java.util.jar.JarInputStream;
 
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.buf.UriUtil;
 
 /**
  * Represents a single resource (file or directory) that is located within a
@@ -38,8 +39,9 @@ public class JarWarResource extends Abst
     public JarWarResource(AbstractArchiveResourceSet archiveResourceSet, String webAppPath,
             String baseUrl, JarEntry jarEntry, String archivePath) {
 
-        super(archiveResourceSet, webAppPath, "jar:war:" + baseUrl + "*/" + archivePath + "!/",
-                jarEntry, "war:" + baseUrl + "*/" + archivePath);
+        super(archiveResourceSet, webAppPath,
+                "jar:war:" + baseUrl + UriUtil.getWarSeparator() + archivePath + "!/",
+                jarEntry, "war:" + baseUrl + UriUtil.getWarSeparator() + archivePath);
         this.archivePath = archivePath;
     }
 

Modified: tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java?rev=1783408&r1=1783407&r2=1783408&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java (original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/StandardRoot.java Fri Feb 17 14:24:33 2017
@@ -44,6 +44,7 @@ import org.apache.catalina.WebResourceSe
 import org.apache.catalina.util.LifecycleMBeanBase;
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.buf.UriUtil;
 import org.apache.tomcat.util.http.RequestUtil;
 import org.apache.tomcat.util.res.StringManager;
 
@@ -806,7 +807,7 @@ public class StandardRoot extends Lifecy
                 if ("jar".equals(url.getProtocol())) {
                     endOfFileUrl = jarUrl.indexOf("!/");
                 } else {
-                    endOfFileUrl = jarUrl.indexOf("*/");
+                    endOfFileUrl = jarUrl.indexOf(UriUtil.getWarSeparator());
                 }
                 String fileUrl = jarUrl.substring(4, endOfFileUrl);
                 try {

Modified: tomcat/trunk/java/org/apache/catalina/webresources/WarResource.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/catalina/webresources/WarResource.java?rev=1783408&r1=1783407&r2=1783408&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/catalina/webresources/WarResource.java (original)
+++ tomcat/trunk/java/org/apache/catalina/webresources/WarResource.java Fri Feb 17 14:24:33 2017
@@ -20,6 +20,7 @@ import java.util.jar.JarEntry;
 
 import org.apache.juli.logging.Log;
 import org.apache.juli.logging.LogFactory;
+import org.apache.tomcat.util.buf.UriUtil;
 
 /**
  * Represents a single resource (file or directory) that is located within a
@@ -32,7 +33,8 @@ public class WarResource extends Abstrac
 
     public WarResource(AbstractArchiveResourceSet archiveResourceSet, String webAppPath,
             String baseUrl, JarEntry jarEntry) {
-        super(archiveResourceSet, webAppPath, "war:" + baseUrl + "*/", jarEntry, baseUrl);
+        super(archiveResourceSet, webAppPath, "war:" + baseUrl + UriUtil.getWarSeparator(),
+                jarEntry, baseUrl);
     }
 
 

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=1783408&r1=1783407&r2=1783408&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/buf/UriUtil.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/buf/UriUtil.java Fri Feb 17 14:24:33 2017
@@ -26,9 +26,42 @@ import java.util.regex.Pattern;
  */
 public final class UriUtil {
 
-    private static Pattern PATTERN_EXCLAMATION_MARK = Pattern.compile("!/");
-    private static Pattern PATTERN_CARET = Pattern.compile("\\^/");
-    private static Pattern PATTERN_ASTERISK = Pattern.compile("\\*/");
+    private static final char[] HEX =
+        {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
+
+    private static final Pattern PATTERN_EXCLAMATION_MARK = Pattern.compile("!/");
+    private static final Pattern PATTERN_CARET = Pattern.compile("\\^/");
+    private static final Pattern PATTERN_ASTERISK = Pattern.compile("\\*/");
+    private static final Pattern PATTERN_CUSTOM;
+    private static final String REPLACE_CUSTOM;
+
+    private static final String WAR_SEPARATOR;
+
+    static {
+        String custom = System.getProperty("org.apache.tomcat.util.buf.UriUtil.WAR_SEPARATOR");
+        if (custom == null) {
+            WAR_SEPARATOR = "*/";
+            PATTERN_CUSTOM = null;
+            REPLACE_CUSTOM = null;
+        } else {
+            WAR_SEPARATOR = custom + "/";
+            PATTERN_CUSTOM = Pattern.compile(Pattern.quote(WAR_SEPARATOR));
+            StringBuffer sb = new StringBuffer(custom.length() * 3);
+            // Deliberately use the platform's default encoding
+            byte[] ba = custom.getBytes();
+            for (int j = 0; j < ba.length; j++) {
+                // Converting each byte in the buffer
+                byte toEncode = ba[j];
+                sb.append('%');
+                int low = toEncode & 0x0f;
+                int high = (toEncode & 0xf0) >> 4;
+                sb.append(HEX[high]);
+                sb.append(HEX[low]);
+            }
+            REPLACE_CUSTOM = sb.toString();
+        }
+    }
+
 
     private UriUtil() {
         // Utility class. Hide default constructor
@@ -126,7 +159,11 @@ public final class UriUtil {
         String tmp = PATTERN_EXCLAMATION_MARK.matcher(input).replaceAll("%21/");
         // Tomcat's custom jar:war: URL handling treats */ and ^/ as special
         tmp = PATTERN_CARET.matcher(tmp).replaceAll("%5e/");
-        return PATTERN_ASTERISK.matcher(tmp).replaceAll("%2a/");
+        tmp = PATTERN_ASTERISK.matcher(tmp).replaceAll("%2a/");
+        if (PATTERN_CUSTOM != null) {
+            tmp = PATTERN_CUSTOM.matcher(tmp).replaceAll(REPLACE_CUSTOM);
+        }
+        return tmp;
     }
 
 
@@ -145,10 +182,17 @@ public final class UriUtil {
         String file = warUrl.getFile();
         if (file.contains("*/")) {
             file = file.replaceFirst("\\*/", "!/");
-        } else {
+        } else if (file.contains("^/")) {
             file = file.replaceFirst("\\^/", "!/");
+        } else if (PATTERN_CUSTOM != null) {
+            file = file.replaceFirst(PATTERN_CUSTOM.pattern(), "!/");
         }
 
         return new URL("jar", warUrl.getHost(), warUrl.getPort(), file);
     }
+
+
+    public static String getWarSeparator() {
+        return WAR_SEPARATOR;
+    }
 }

Modified: tomcat/trunk/java/org/apache/tomcat/util/scan/JarFactory.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/scan/JarFactory.java?rev=1783408&r1=1783407&r2=1783408&view=diff
==============================================================================
--- tomcat/trunk/java/org/apache/tomcat/util/scan/JarFactory.java (original)
+++ tomcat/trunk/java/org/apache/tomcat/util/scan/JarFactory.java Fri Feb 17 14:24:33 2017
@@ -19,6 +19,7 @@ package org.apache.tomcat.util.scan;
 import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URL;
+import java.util.regex.Matcher;
 
 import org.apache.tomcat.Jar;
 import org.apache.tomcat.util.buf.UriUtil;
@@ -61,7 +62,8 @@ public class JarFactory {
             // Assume this is pointing to a JAR file within a WAR. Java doesn't
             // support jar:jar:file:... so switch to Tomcat's war:file:...
             baseExternal = baseExternal.replaceFirst("^jar:", "war:");
-            baseExternal = baseExternal.replaceFirst("!/", "*/");
+            baseExternal = baseExternal.replaceFirst("!/",
+                    Matcher.quoteReplacement(UriUtil.getWarSeparator()));
         }
 
         return new URL("jar:" + baseExternal + "!/" + entryName);

Added: tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil24.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil24.java?rev=1783408&view=auto
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil24.java (added)
+++ tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil24.java Fri Feb 17 14:24:33 2017
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.buf;
+
+public class TestUriUtil24 extends TesterUriUtilBase {
+
+    public TestUriUtil24() {
+        super("$");
+    }
+}

Added: tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil26.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil26.java?rev=1783408&view=auto
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil26.java (added)
+++ tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil26.java Fri Feb 17 14:24:33 2017
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.buf;
+
+public class TestUriUtil26 extends TesterUriUtilBase {
+
+    public TestUriUtil26() {
+        super("&");
+    }
+}

Added: tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil2A.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil2A.java?rev=1783408&view=auto
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil2A.java (added)
+++ tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil2A.java Fri Feb 17 14:24:33 2017
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.buf;
+
+public class TestUriUtil2A extends TesterUriUtilBase {
+
+    public TestUriUtil2A() {
+        super("*");
+    }
+}

Added: tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil40.java
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil40.java?rev=1783408&view=auto
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil40.java (added)
+++ tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil40.java Fri Feb 17 14:24:33 2017
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.tomcat.util.buf;
+
+public class TestUriUtil40 extends TesterUriUtilBase {
+
+    public TestUriUtil40() {
+        super("@");
+    }
+}

Copied: tomcat/trunk/test/org/apache/tomcat/util/buf/TesterUriUtilBase.java (from r1783407, tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil.java)
URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/tomcat/util/buf/TesterUriUtilBase.java?p2=tomcat/trunk/test/org/apache/tomcat/util/buf/TesterUriUtilBase.java&p1=tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil.java&r1=1783407&r2=1783408&rev=1783408&view=diff
==============================================================================
--- tomcat/trunk/test/org/apache/tomcat/util/buf/TestUriUtil.java (original)
+++ tomcat/trunk/test/org/apache/tomcat/util/buf/TesterUriUtilBase.java Fri Feb 17 14:24:33 2017
@@ -23,7 +23,18 @@ import java.net.URL;
 import org.junit.Assert;
 import org.junit.Test;
 
-public class TestUriUtil {
+import org.apache.catalina.webresources.TomcatURLStreamHandlerFactory;
+
+public abstract class TesterUriUtilBase {
+
+    private final String separator;
+
+    protected TesterUriUtilBase(String separator) {
+        this.separator = separator;
+        TomcatURLStreamHandlerFactory.register();
+        System.setProperty("org.apache.tomcat.util.buf.UriUtil.WAR_SEPARATOR", separator);
+    }
+
 
     @Test
     public void testBuildJarUrl01() throws MalformedURLException {
@@ -61,6 +72,44 @@ public class TestUriUtil {
     }
 
 
+    @Test
+    public void testBuildJarUrl04() throws MalformedURLException {
+        File jarFile = new File("/patha/pathb" + separator + "/pathc");
+        String result = UriUtil.buildJarUrl(jarFile).toString();
+
+        int index = result.indexOf("!/");
+        Assert.assertEquals(result, result.length() - 2, index);
+
+        index = result.indexOf(separator + "/");
+        Assert.assertEquals(result, -1, index);
+    }
+
+
+    @Test
+    public void testWarToJar01() throws MalformedURLException {
+        doTestWarToJar("^");
+    }
+
+
+    @Test
+    public void testWarToJar02() throws MalformedURLException {
+        doTestWarToJar("*");
+    }
+
+
+    @Test
+    public void testWarToJar03() throws MalformedURLException {
+        doTestWarToJar(separator);
+    }
+
+
+    private void doTestWarToJar(String separator) throws MalformedURLException {
+        URL warUrl = new URL("war:file:/external/path" + separator + "/internal/path");
+        URL jarUrl = UriUtil.warToJar(warUrl);
+        Assert.assertEquals("jar:file:/external/path!/internal/path", jarUrl.toString());
+    }
+
+
     // @Test /* Uncomment to test performance for different implementations. */
     public void performanceTestBuildJarUrl() throws MalformedURLException {
         File jarFile = new File("/patha/pathb^/pathc");

Modified: tomcat/trunk/webapps/docs/changelog.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/changelog.xml?rev=1783408&r1=1783407&r2=1783408&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/changelog.xml (original)
+++ tomcat/trunk/webapps/docs/changelog.xml Fri Feb 17 14:24:33 2017
@@ -119,6 +119,13 @@
         <strong>Context</strong> when generating paths for dispatches triggered
         by <code>AsyncContext.dispatch()</code>. (markt)
       </fix>
+      <fix>
+        <bug>60728</bug>: Make the separator Tomcat uses in the Tomcat specific
+        <code>war:file:...</code> URL protocol customizable via a system
+        property. The separator is equivalent to the use of the <code>!</code>
+        character in <code>jar:file:...</code> URLs. The default separator of
+        <code>*</code> remains unchanged. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">

Modified: tomcat/trunk/webapps/docs/config/systemprops.xml
URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/systemprops.xml?rev=1783408&r1=1783407&r2=1783408&view=diff
==============================================================================
--- tomcat/trunk/webapps/docs/config/systemprops.xml (original)
+++ tomcat/trunk/webapps/docs/config/systemprops.xml Fri Feb 17 14:24:33 2017
@@ -606,6 +606,13 @@
       <p>If not specified, the default value of <code>200</code> will be used.</p>
     </property>
 
+    <property name="org.apache.tomcat.util.buf.UriUtil.WAR_SEPARATOR">
+      <p>The character to use to separate the WAR file and WAR content parts of
+      a WAR URL using the custom WAR scheme provided by Tomcat. This is
+      equivalent to how <code>!</code> is used in JAR URLs.</p>
+      <p>If not specified, the default value of <code>*</code> will be used.</p>
+    </property>
+
     <property name="tomcat.util.buf.StringCache.maxStringSize">
       <p>The maximum length of String that will be cached.</p>
       <p>If not specified, the default value of <code>128</code> will be used.</p>



---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org