diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java index b96b24b77b..e9d4c215ea 100755 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/PropertiesLauncher.java @@ -20,9 +20,11 @@ import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.InputStream; +import java.io.UnsupportedEncodingException; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; +import java.net.URLDecoder; import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashSet; @@ -203,21 +205,24 @@ public class PropertiesLauncher extends Launcher { if (config.startsWith("classpath:")) { return getClasspathResource(config.substring("classpath:".length())); } - config = stripFileUrlPrefix(config); + config = handleUrl(config); if (isUrl(config)) { return getURLResource(config); } return getFileResource(config); } - private String stripFileUrlPrefix(String config) { - if (config.startsWith("file:")) { - config = config.substring("file:".length()); - if (config.startsWith("//")) { - config = config.substring(2); + private String handleUrl(String path) throws UnsupportedEncodingException { + if (path.startsWith("jar:file:") || path.startsWith("file:")) { + path = URLDecoder.decode(path, "UTF-8"); + if (path.startsWith("file:")) { + path = path.substring("file:".length()); + if (path.startsWith("//")) { + path = path.substring(2); + } } } - return config; + return path; } private boolean isUrl(String config) { @@ -454,8 +459,8 @@ public class PropertiesLauncher extends Launcher { } private List getClassPathArchives(String path) throws Exception { - String root = cleanupPath(stripFileUrlPrefix(path)); - List lib = new ArrayList<>(); + String root = cleanupPath(handleUrl(path)); + List lib = new ArrayList(); File file = new File(root); if (!"/".equals(root)) { if (!isAbsolutePath(root)) { diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java index 0cdfa14540..bdc70e288f 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/PropertiesLauncherTests.java @@ -346,6 +346,17 @@ public class PropertiesLauncherTests { assertThat(launcher.getMainClass()).isEqualTo("demo.FooApplication"); } + @Test + public void encodedFileUrlLoaderPathIsHandledCorrectly() throws Exception { + File loaderPath = this.temporaryFolder.newFolder("loader path"); + System.setProperty("loader.path", loaderPath.toURI().toURL().toString()); + PropertiesLauncher launcher = new PropertiesLauncher(); + List archives = launcher.getClassPathArchives(); + assertThat(archives.size()).isEqualTo(1); + File archiveRoot = (File) ReflectionTestUtils.getField(archives.get(0), "root"); + assertThat(archiveRoot).isEqualTo(loaderPath); + } + private void waitFor(String value) throws Exception { int count = 0; boolean timeout = false;