From ed15345df1f3ec031797cbcd49ba927c8a5dd55f Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Wed, 19 Feb 2014 13:38:53 +0000 Subject: [PATCH] Try to make Jetty scan TLDs in nested JARs Jetty apparently does it differently (different version of Jasper maybe), so you need a unique jarFileURL for each nested JAR (previously they were all set to the parent archive URL). Also added the root of the main archive as a valid document root. For gh-367 --- .../boot/loader/jar/JarURLConnection.java | 31 ++++++++++++++++++- .../boot/loader/jar/JarFileTests.java | 9 ++++-- .../JettyEmbeddedServletContainerFactory.java | 8 ++++- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarURLConnection.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarURLConnection.java index f751c93a8a..f7b29edb3d 100644 --- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarURLConnection.java +++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/jar/JarURLConnection.java @@ -21,6 +21,7 @@ import java.io.IOException; import java.io.InputStream; import java.net.MalformedURLException; import java.net.URL; +import java.util.jar.Manifest; /** * {@link java.net.JarURLConnection} used to support {@link JarFile#getUrl()}. @@ -43,6 +44,8 @@ class JarURLConnection extends java.net.JarURLConnection { private String contentType; + private URL jarFileUrl; + protected JarURLConnection(URL url, JarFile jarFile) throws MalformedURLException { super(new URL(buildRootUrl(jarFile))); this.jarFile = jarFile; @@ -53,9 +56,25 @@ class JarURLConnection extends java.net.JarURLConnection { throw new MalformedURLException("no " + SEPARATOR + " found in url spec:" + spec); } - if (separator + 2 != spec.length()) { + /* + * The superclass constructor creates a jarFileUrl which is equal to the root URL + * of the containing archive (therefore not unique if we are connecting to + * multiple nested jars in the same archive). Therefore we need to make something + * sensible for #getJarFileURL(). + */ + if (separator + SEPARATOR.length() != spec.length()) { + this.jarFileUrl = new URL("jar:" + spec); this.jarEntryName = spec.substring(separator + 2); } + else { + // The root of the archive (!/) + this.jarFileUrl = new URL("jar:" + spec.substring(0, separator)); + } + } + + @Override + public URL getJarFileURL() { + return this.jarFileUrl; } @Override @@ -70,6 +89,16 @@ class JarURLConnection extends java.net.JarURLConnection { this.connected = true; } + @Override + public Manifest getManifest() throws IOException { + try { + return super.getManifest(); + } + finally { + this.connected = false; + } + } + @Override public JarFile getJarFile() throws IOException { connect(); diff --git a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarFileTests.java b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarFileTests.java index 8798611a09..244dcc3004 100644 --- a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarFileTests.java +++ b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/jar/JarFileTests.java @@ -150,6 +150,8 @@ public class JarFileTests { assertThat(jarURLConnection.getContentLength(), greaterThan(1)); assertThat(jarURLConnection.getContent(), sameInstance((Object) this.jarFile)); assertThat(jarURLConnection.getContentType(), equalTo("x-java/jar")); + assertThat(jarURLConnection.getJarFileURL().toString(), equalTo("jar:file:" + + this.rootJarFile)); } @Test @@ -212,8 +214,10 @@ public class JarFileTests { URL url = nestedJarFile.getUrl(); assertThat(url.toString(), equalTo("jar:file:" + this.rootJarFile.getPath() + "!/nested.jar!/")); - assertThat(((JarURLConnection) url.openConnection()).getJarFile(), - sameInstance(nestedJarFile)); + JarURLConnection conn = (JarURLConnection) url.openConnection(); + assertThat(conn.getJarFile(), sameInstance(nestedJarFile)); + assertThat(conn.getJarFileURL().toString(), equalTo("jar:file:" + + this.rootJarFile.getPath() + "!/nested.jar")); } @Test @@ -304,7 +308,6 @@ public class JarFileTests { } @Test - @SuppressWarnings("resource") public void verifySignedJar() throws Exception { String classpath = System.getProperty("java.class.path"); String[] entries = classpath.split(System.getProperty("path.separator")); diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java index 201491ee14..d45982104c 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/jetty/JettyEmbeddedServletContainerFactory.java @@ -137,7 +137,13 @@ public class JettyEmbeddedServletContainerFactory extends File root = getValidDocumentRoot(); if (root != null) { try { - handler.setBaseResource(Resource.newResource(root)); + if (!root.isDirectory()) { + handler.setBaseResource(Resource.newResource("jar:" + root.toURI() + + "!")); + } + else { + handler.setBaseResource(Resource.newResource(root)); + } } catch (Exception ex) { throw new IllegalStateException(ex);