From 2f973ebc331ac551e767b185bbe9349a39476ce9 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Fri, 5 Jun 2020 19:32:06 -0700 Subject: [PATCH] Fix default Launcher.isExploded() result Fix the default implementation of `Launcher.isExploded` which should have returned `true`. Fixes gh-21575 --- .../springframework/boot/loader/Launcher.java | 2 +- .../boot/loader/PropertiesLauncherTests.java | 41 +++++++++++++++++-- .../boot/loader/TestJarCreator.java | 2 - 3 files changed, 39 insertions(+), 6 deletions(-) diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/Launcher.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/Launcher.java index 7be83a3153e..d33121ba91f 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/Launcher.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/Launcher.java @@ -172,7 +172,7 @@ public abstract class Launcher { * @since 2.3.0 */ protected boolean isExploded() { - return true; + return false; } /** 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 304ed794fde..aa0b9497798 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 @@ -19,12 +19,14 @@ package org.springframework.boot.loader; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; +import java.lang.ref.SoftReference; import java.net.URL; import java.net.URLClassLoader; import java.time.Duration; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Map; import java.util.jar.Attributes; import java.util.jar.Manifest; @@ -39,10 +41,13 @@ import org.junit.jupiter.api.io.TempDir; import org.springframework.boot.loader.archive.Archive; import org.springframework.boot.loader.archive.ExplodedArchive; import org.springframework.boot.loader.archive.JarFileArchive; +import org.springframework.boot.loader.jar.Handler; +import org.springframework.boot.loader.jar.JarFile; import org.springframework.boot.testsupport.system.CapturedOutput; import org.springframework.boot.testsupport.system.OutputCaptureExtension; import org.springframework.core.io.FileSystemResource; import org.springframework.test.util.ReflectionTestUtils; +import org.springframework.util.FileCopyUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; @@ -65,14 +70,15 @@ class PropertiesLauncherTests { private CapturedOutput output; @BeforeEach - void setup(CapturedOutput capturedOutput) { + void setup(CapturedOutput capturedOutput) throws Exception { this.contextClassLoader = Thread.currentThread().getContextClassLoader(); + clearHandlerCache(); System.setProperty("loader.home", new File("src/test/resources").getAbsolutePath()); this.output = capturedOutput; } @AfterEach - void close() { + void close() throws Exception { Thread.currentThread().setContextClassLoader(this.contextClassLoader); System.clearProperty("loader.home"); System.clearProperty("loader.path"); @@ -81,6 +87,19 @@ class PropertiesLauncherTests { System.clearProperty("loader.config.location"); System.clearProperty("loader.system"); System.clearProperty("loader.classLoader"); + clearHandlerCache(); + } + + @SuppressWarnings("unchecked") + private void clearHandlerCache() throws Exception { + Map rootFileCache = ((SoftReference>) ReflectionTestUtils + .getField(Handler.class, "rootFileCache")).get(); + if (rootFileCache != null) { + for (JarFile rootJarFile : rootFileCache.values()) { + rootJarFile.close(); + } + rootFileCache.clear(); + } } @Test @@ -290,7 +309,6 @@ class PropertiesLauncherTests { @Test void testUserSpecifiedConfigPathWins() throws Exception { - System.setProperty("loader.config.name", "foo"); System.setProperty("loader.config.location", "classpath:bar.properties"); PropertiesLauncher launcher = new PropertiesLauncher(); @@ -354,6 +372,23 @@ class PropertiesLauncherTests { assertThat(archiveRoot).isEqualTo(loaderPath); } + @Test // gh-21575 + void loadResourceFromJarFile() throws Exception { + File jarFile = new File(this.tempDir, "app.jar"); + TestJarCreator.createTestJar(jarFile); + System.setProperty("loader.home", this.tempDir.getAbsolutePath()); + System.setProperty("loader.path", "app.jar"); + PropertiesLauncher launcher = new PropertiesLauncher(); + try { + launcher.launch(new String[0]); + } + catch (Exception ex) { + } + URL resource = new URL("jar:" + jarFile.toURI() + "!/nested.jar!/3.dat"); + byte[] bytes = FileCopyUtils.copyToByteArray(resource.openStream()); + assertThat(bytes).isNotEmpty(); + } + private void waitFor(String value) throws Exception { Awaitility.waitAtMost(Duration.ofSeconds(5)).until(this.output::toString, containsString(value)); } diff --git a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/TestJarCreator.java b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/TestJarCreator.java index 6844282800f..7fde7c5bf1c 100644 --- a/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/TestJarCreator.java +++ b/spring-boot-project/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/TestJarCreator.java @@ -49,7 +49,6 @@ public abstract class TestJarCreator { writeEntry(jarOutputStream, "d/9.dat", 9); writeDirEntry(jarOutputStream, "special/"); writeEntry(jarOutputStream, "special/\u00EB.dat", '\u00EB'); - writeNestedEntry("nested.jar", unpackNested, jarOutputStream); writeNestedEntry("another-nested.jar", unpackNested, jarOutputStream); writeNestedEntry("space nested.jar", unpackNested, jarOutputStream); @@ -79,7 +78,6 @@ public abstract class TestJarCreator { CRC32 crc32 = new CRC32(); crc32.update(nestedJarData); nestedEntry.setCrc(crc32.getValue()); - nestedEntry.setMethod(ZipEntry.STORED); jarOutputStream.putNextEntry(nestedEntry); jarOutputStream.write(nestedJarData);