diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java index e79e33e204..12044c4c0f 100644 --- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java +++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java @@ -456,7 +456,7 @@ public class PropertiesLauncher extends Launcher { String root = cleanupPath(stripFileUrlPrefix(path)); List lib = new ArrayList(); File file = new File(root); - if (!root.startsWith("/")) { + if (!isAbsolutePath(root)) { file = new File(this.home, root); } if (file.isDirectory()) { @@ -479,6 +479,11 @@ public class PropertiesLauncher extends Launcher { return lib; } + private boolean isAbsolutePath(String root) { + // Windows contains ":" others start with "/" + return root.contains(":") || root.startsWith("/"); + } + private Archive getArchive(File file) throws IOException { String name = file.getName().toLowerCase(); if (name.endsWith(".jar") || name.endsWith(".zip")) { @@ -534,6 +539,10 @@ public class PropertiesLauncher extends Launcher { private String cleanupPath(String path) { path = path.trim(); + // No need for current dir path + if (path.startsWith("./")) { + path = path.substring(2); + } if (path.toLowerCase().endsWith(".jar") || path.toLowerCase().endsWith(".zip")) { return path; } @@ -542,14 +551,10 @@ public class PropertiesLauncher extends Launcher { } else { // It's a directory - if (!path.endsWith("/")) { + if (!path.endsWith("/") && !path.equals(".")) { path = path + "/"; } } - // No need for current dir path - if (path.startsWith("./")) { - path = path.substring(2); - } return path; } @@ -593,8 +598,7 @@ public class PropertiesLauncher extends Launcher { @Override public boolean matches(Entry entry) { - return entry.isDirectory() || entry.getName().endsWith(DOT_JAR) - || entry.getName().endsWith(DOT_ZIP); + return entry.getName().endsWith(DOT_JAR) || entry.getName().endsWith(DOT_ZIP); } } diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/ExplodedArchive.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/ExplodedArchive.java index cdfdb430a5..66b9eb9afa 100644 --- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/ExplodedArchive.java +++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/archive/ExplodedArchive.java @@ -56,7 +56,7 @@ public class ExplodedArchive extends Archive { private Manifest manifest; - private boolean recursive = true; + private boolean filtered = false; /** * Create a new {@link ExplodedArchive} instance. @@ -78,17 +78,18 @@ public class ExplodedArchive extends Archive { throw new IllegalArgumentException("Invalid source folder " + root); } this.root = root; - this.recursive = recursive; - buildEntries(root); + buildEntries(root, recursive); this.entries = Collections.unmodifiableMap(this.entries); } private ExplodedArchive(File root, Map entries) { this.root = root; + // The entries are pre-filtered + this.filtered = true; this.entries = Collections.unmodifiableMap(entries); } - private void buildEntries(File file) { + private void buildEntries(File file, boolean recursive) { if (!file.equals(this.root)) { String name = file.toURI().getPath() .substring(this.root.toURI().getPath().length()); @@ -102,9 +103,9 @@ public class ExplodedArchive extends Archive { } for (File child : files) { if (!SKIPPED_NAMES.contains(child.getName())) { - if (file.equals(this.root) || this.recursive + if (file.equals(this.root) || recursive || file.getName().equals("META-INF")) { - buildEntries(child); + buildEntries(child, recursive); } } } @@ -113,7 +114,8 @@ public class ExplodedArchive extends Archive { @Override public URL getUrl() throws MalformedURLException { - FilteredURLStreamHandler handler = new FilteredURLStreamHandler(); + FilteredURLStreamHandler handler = this.filtered ? new FilteredURLStreamHandler() + : null; return new URL("file", "", -1, this.root.toURI().getPath(), handler); } diff --git a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java index 3491aa21ce..72b79e24ab 100644 --- a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java +++ b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java @@ -112,6 +112,17 @@ public class PropertiesLauncherTests { waitFor("Hello World"); } + @Test + public void testUserSpecifiedJarPathWithDot() throws Exception { + System.setProperty("loader.path", "./jars/app.jar"); + System.setProperty("loader.main", "demo.Application"); + PropertiesLauncher launcher = new PropertiesLauncher(); + assertEquals("[jars/app.jar]", ReflectionTestUtils.getField(launcher, "paths") + .toString()); + launcher.launch(new String[0]); + waitFor("Hello World"); + } + @Test public void testUserSpecifiedClassLoader() throws Exception { System.setProperty("loader.path", "jars/app.jar"); diff --git a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/archive/ExplodedArchiveTests.java b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/archive/ExplodedArchiveTests.java index d9a2749c02..03c1f21ca5 100644 --- a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/archive/ExplodedArchiveTests.java +++ b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/archive/ExplodedArchiveTests.java @@ -147,6 +147,7 @@ public class ExplodedArchiveTests { new URL[] { filteredArchive.getUrl() }); assertThat(classLoader.getResourceAsStream("1.dat").read(), equalTo(1)); assertThat(classLoader.getResourceAsStream("2.dat"), nullValue()); + classLoader.close(); } @Test @@ -173,6 +174,25 @@ public class ExplodedArchiveTests { assertThat(entries.size(), equalTo(3)); } + @Test + public void getResourceAsStream() throws Exception { + ExplodedArchive archive = new ExplodedArchive(new File("src/test/resources/root")); + assertNotNull(archive.getManifest()); + URLClassLoader loader = new URLClassLoader(new URL[] { archive.getUrl() }); + assertNotNull(loader.getResourceAsStream("META-INF/spring/application.xml")); + loader.close(); + } + + @Test + public void getResourceAsStreamNonRecursive() throws Exception { + ExplodedArchive archive = new ExplodedArchive( + new File("src/test/resources/root"), false); + assertNotNull(archive.getManifest()); + URLClassLoader loader = new URLClassLoader(new URL[] { archive.getUrl() }); + assertNotNull(loader.getResourceAsStream("META-INF/spring/application.xml")); + loader.close(); + } + private Map getEntriesMap(Archive archive) { Map entries = new HashMap(); for (Archive.Entry entry : archive.getEntries()) { 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 2e096462ef..d974c8e246 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 @@ -97,6 +97,7 @@ public class JarFileTests { assertThat(urlClassLoader.getResource("special/\u00EB.dat"), notNullValue()); assertThat(urlClassLoader.getResource("d/9.dat"), notNullValue()); jarFile.close(); + urlClassLoader.close(); } @Test @@ -139,6 +140,7 @@ public class JarFileTests { URLClassLoader urlClassLoader = new URLClassLoader( new URL[] { this.jarFile.getUrl() }); assertThat(urlClassLoader.getResource("special/\u00EB.dat"), notNullValue()); + urlClassLoader.close(); } @Test