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 2019/11/27 19:38:29 UTC

[tomcat] branch master updated: Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63970 cast JAR conns

This is an automated email from the ASF dual-hosted git repository.

markt pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/tomcat.git


The following commit(s) were added to refs/heads/master by this push:
     new 709b629  Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63970 cast JAR conns
709b629 is described below

commit 709b6295087a0bfb5576ffb2acb7fcb5896a6f1c
Author: Mark Thomas <ma...@apache.org>
AuthorDate: Wed Nov 27 19:37:47 2019 +0000

    Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63970 cast JAR conns
    
    Correct a regression in the static resource caching changes introduced
    in 9.0.28. Connections to URLs obtained for JAR resources could not be
    cast to JarURLConnection.
---
 .../catalina/webresources/CachedResource.java      | 87 +++++++++++++++++++++-
 .../catalina/webresources/TestCachedResource.java  | 27 +++++++
 webapps/docs/changelog.xml                         |  5 ++
 3 files changed, 115 insertions(+), 4 deletions(-)

diff --git a/java/org/apache/catalina/webresources/CachedResource.java b/java/org/apache/catalina/webresources/CachedResource.java
index 6b3e615..ec21f40 100644
--- a/java/org/apache/catalina/webresources/CachedResource.java
+++ b/java/org/apache/catalina/webresources/CachedResource.java
@@ -19,12 +19,14 @@ package org.apache.catalina.webresources;
 import java.io.ByteArrayInputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.net.JarURLConnection;
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.net.URLConnection;
 import java.net.URLStreamHandler;
 import java.security.Permission;
 import java.security.cert.Certificate;
+import java.util.jar.JarFile;
 import java.util.jar.Manifest;
 
 import org.apache.catalina.WebResource;
@@ -358,8 +360,11 @@ public class CachedResource implements WebResource {
             return null;
         }
         try {
-            return new URL(null, resourceURL.toExternalForm(),
-                    new CachedResourceURLStreamHandler(resourceURL, root, webAppPath, usesClassLoaderResources));
+            CachedResourceURLStreamHandler handler =
+                    new CachedResourceURLStreamHandler(resourceURL, root, webAppPath, usesClassLoaderResources);
+            URL result = new URL(null, resourceURL.toExternalForm(), handler);
+            handler.setAssociatedURL(result);
+            return result;
         } catch (MalformedURLException e) {
             log.error(sm.getString("cachedResource.invalidURL", resourceURL.toExternalForm()), e);
             return null;
@@ -413,6 +418,8 @@ public class CachedResource implements WebResource {
         private final String webAppPath;
         private final boolean usesClassLoaderResources;
 
+        private URL associatedURL = null;
+
         public CachedResourceURLStreamHandler(URL resourceURL, StandardRoot root, String webAppPath,
                 boolean usesClassLoaderResources) {
             this.resourceURL = resourceURL;
@@ -421,13 +428,21 @@ public class CachedResource implements WebResource {
             this.usesClassLoaderResources = usesClassLoaderResources;
         }
 
+        protected void setAssociatedURL(URL associatedURL) {
+            this.associatedURL = associatedURL;
+        }
+
         @Override
         protected URLConnection openConnection(URL u) throws IOException {
             // This deliberately uses ==. If u isn't the URL object this
             // URLStreamHandler was constructed for we do not want to use this
             // URLStreamHandler to create a connection.
-            if (u == resourceURL) {
-                return new CachedResourceURLConnection(resourceURL, root, webAppPath, usesClassLoaderResources);
+            if (associatedURL != null && u == associatedURL) {
+                if ("jar".equals(associatedURL.getProtocol())) {
+                    return new CachedResourceJarURLConnection(resourceURL, root, webAppPath, usesClassLoaderResources);
+                } else {
+                    return new CachedResourceURLConnection(resourceURL, root, webAppPath, usesClassLoaderResources);
+                }
             } else {
                 // The stream handler has been inherited by a URL that was
                 // constructed from a cache URL. We need to break that link.
@@ -438,6 +453,9 @@ public class CachedResource implements WebResource {
     }
 
 
+    /*
+     * Keep this in sync with CachedResourceJarURLConnection.
+     */
     private static class CachedResourceURLConnection extends URLConnection {
 
         private final StandardRoot root;
@@ -489,4 +507,65 @@ public class CachedResource implements WebResource {
             return root.getResource(webAppPath, false, usesClassLoaderResources);
         }
     }
+
+
+    /*
+     * Keep this in sync with CachedResourceURLConnection.
+     */
+    private static class CachedResourceJarURLConnection extends JarURLConnection {
+
+        private final StandardRoot root;
+        private final String webAppPath;
+        private final boolean usesClassLoaderResources;
+        private final JarURLConnection resourceURLConnection;
+        private boolean connected;
+
+        protected CachedResourceJarURLConnection(URL resourceURL, StandardRoot root, String webAppPath,
+                boolean usesClassLoaderResources) throws IOException {
+            super(resourceURL);
+            this.root = root;
+            this.webAppPath = webAppPath;
+            this.usesClassLoaderResources = usesClassLoaderResources;
+            this.resourceURLConnection = (JarURLConnection) url.openConnection();
+        }
+
+        @Override
+        public void connect() throws IOException {
+            if (!connected) {
+                resourceURLConnection.connect();
+                connected = true;
+            }
+        }
+
+        @Override
+        public InputStream getInputStream() throws IOException {
+            connect();
+            InputStream is = getResource().getInputStream();
+            return is;
+        }
+
+        @Override
+        public Permission getPermission() throws IOException {
+            return resourceURLConnection.getPermission();
+        }
+
+        @Override
+        public long getLastModified() {
+            return getResource().getLastModified();
+        }
+
+        @Override
+        public long getContentLengthLong() {
+            return getResource().getContentLength();
+        }
+
+        private WebResource getResource() {
+            return root.getResource(webAppPath, false, usesClassLoaderResources);
+        }
+
+        @Override
+        public JarFile getJarFile() throws IOException {
+            return resourceURLConnection.getJarFile();
+        }
+    }
 }
diff --git a/test/org/apache/catalina/webresources/TestCachedResource.java b/test/org/apache/catalina/webresources/TestCachedResource.java
index e75819b..0215349 100644
--- a/test/org/apache/catalina/webresources/TestCachedResource.java
+++ b/test/org/apache/catalina/webresources/TestCachedResource.java
@@ -18,6 +18,7 @@ package org.apache.catalina.webresources;
 
 import java.io.File;
 import java.io.InputStream;
+import java.net.JarURLConnection;
 import java.net.URL;
 
 import org.junit.Assert;
@@ -49,4 +50,30 @@ public class TestCachedResource extends TomcatBaseTest {
             Assert.assertNotNull(is);
         }
     }
+
+
+    // https://bz.apache.org/bugzilla/show_bug.cgi?id=63970
+    @Test
+    public void testCachedJarUrlConnection() throws Exception {
+
+        Tomcat tomcat = getTomcatInstance();
+        File docBase = new File("test/webresources/war-url-connection.war");
+        Context ctx = tomcat.addWebapp("/test", docBase.getAbsolutePath());
+        tomcat.start();
+
+        WebResourceRoot root = ctx.getResources();
+
+        // WAR contains a resoucres JAR so this should return a JAR URL
+        URL webinf = root.getResource("/index.html").getURL();
+
+        Assert.assertEquals("jar", webinf.getProtocol());
+        JarURLConnection jarConn = null;
+        try {
+            jarConn = (JarURLConnection) webinf.openConnection();
+        } catch (ClassCastException e) {
+            // Ignore
+        }
+        Assert.assertNotNull(jarConn);
+    }
+
 }
diff --git a/webapps/docs/changelog.xml b/webapps/docs/changelog.xml
index 2375a3a..8d9724e 100644
--- a/webapps/docs/changelog.xml
+++ b/webapps/docs/changelog.xml
@@ -52,6 +52,11 @@
         changes introduced in 9.0.28. URLs constructed from URLs obtained from
         the cache could not be used to access resources. (markt)
       </fix>
+      <fix>
+        <bug>63970</bug>: Correct a regression in the static resource caching
+        changes introduced in 9.0.28. Connections to URLs obtained for JAR
+        resources could not be cast to <code>JarURLConnection</code>. (markt)
+      </fix>
     </changelog>
   </subsection>
   <subsection name="Coyote">


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