This is an automated email from the ASF dual-hosted git repository. markt pushed a commit to branch 8.5.x in repository https://gitbox.apache.org/repos/asf/tomcat.git
The following commit(s) were added to refs/heads/8.5.x by this push: new c7e660d Fix https://bz.apache.org/bugzilla/show_bug.cgi?id=63970 cast JAR conns c7e660d is described below commit c7e660d7b43c190847b7c3c19255876ac0f09de5 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 483f98d..e738239 100644 --- a/webapps/docs/changelog.xml +++ b/webapps/docs/changelog.xml @@ -62,6 +62,11 @@ <code>Expires</code> filter which was a regression in the fix for <bug>63909</bug>. (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-unsubscr...@tomcat.apache.org For additional commands, e-mail: dev-h...@tomcat.apache.org