diff --git a/spring-core/src/main/java/org/springframework/core/io/AbstractFileResolvingResource.java b/spring-core/src/main/java/org/springframework/core/io/AbstractFileResolvingResource.java index 13d4f2cddb..b65ff3faac 100644 --- a/spring-core/src/main/java/org/springframework/core/io/AbstractFileResolvingResource.java +++ b/spring-core/src/main/java/org/springframework/core/io/AbstractFileResolvingResource.java @@ -45,7 +45,6 @@ import org.springframework.util.ResourceUtils; */ public abstract class AbstractFileResolvingResource extends AbstractResource { - @SuppressWarnings("try") @Override public boolean exists() { try { @@ -90,9 +89,15 @@ public abstract class AbstractFileResolvingResource extends AbstractResource { // existence of the entry (or the jar root in case of no entryName). // getJarFile() called for enforced presence check of the jar file, // throwing a NoSuchFileException otherwise (turned to false below). - try (JarFile jarFile = jarCon.getJarFile()) { + JarFile jarFile = jarCon.getJarFile(); + try { return (jarCon.getEntryName() == null || jarCon.getJarEntry() != null); } + finally { + if (!jarCon.getUseCaches()) { + jarFile.close(); + } + } } else if (con.getContentLengthLong() > 0) { return true; diff --git a/spring-core/src/test/java/org/springframework/core/io/support/PathMatchingResourcePatternResolverTests.java b/spring-core/src/test/java/org/springframework/core/io/support/PathMatchingResourcePatternResolverTests.java index 5ce4c7764e..bde76e830c 100644 --- a/spring-core/src/test/java/org/springframework/core/io/support/PathMatchingResourcePatternResolverTests.java +++ b/spring-core/src/test/java/org/springframework/core/io/support/PathMatchingResourcePatternResolverTests.java @@ -44,6 +44,8 @@ import java.util.stream.Collectors; import java.util.zip.ZipEntry; import org.apache.commons.logging.LogFactory; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.Nested; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; @@ -298,8 +300,8 @@ class PathMatchingResourcePatternResolverTests { @Test void rootPatternRetrievalInJarFiles() throws IOException { assertThat(resolver.getResources("classpath*:aspectj*.dtd")).extracting(Resource::getFilename) - .as("Could not find aspectj_1_5_0.dtd in the root of the aspectjweaver jar") - .containsExactly("aspectj_1_5_0.dtd"); + .as("Could not find aspectj_1_5_0.dtd in the root of the aspectjweaver jar") + .containsExactly("aspectj_1_5_0.dtd"); } } @@ -310,6 +312,16 @@ class PathMatchingResourcePatternResolverTests { @TempDir Path temp; + @BeforeAll + static void suppressJarCaches() { + URLConnection.setDefaultUseCaches("jar", false); + } + + @AfterAll + static void restoreJarCaches() { + URLConnection.setDefaultUseCaches("jar", true); + } + @Test void javaDashJarFindsClassPathManifestEntries() throws Exception { Path lib = this.temp.resolve("lib"); @@ -333,6 +345,7 @@ class PathMatchingResourcePatternResolverTests { StreamUtils.copy("test", StandardCharsets.UTF_8, jar); jar.closeEntry(); } + assertThat(new FileSystemResource(path).exists()).isTrue(); assertThat(new UrlResource(ResourceUtils.JAR_URL_PREFIX + ResourceUtils.FILE_URL_PREFIX + path + ResourceUtils.JAR_URL_SEPARATOR).exists()).isTrue(); assertThat(new UrlResource(ResourceUtils.JAR_URL_PREFIX + ResourceUtils.FILE_URL_PREFIX + path + ResourceUtils.JAR_URL_SEPARATOR + "assets/file.txt").exists()).isTrue(); @@ -340,6 +353,14 @@ class PathMatchingResourcePatternResolverTests { assertThat(new UrlResource(ResourceUtils.JAR_URL_PREFIX + ResourceUtils.FILE_URL_PREFIX + "X" + path + ResourceUtils.JAR_URL_SEPARATOR).exists()).isFalse(); assertThat(new UrlResource(ResourceUtils.JAR_URL_PREFIX + ResourceUtils.FILE_URL_PREFIX + "X" + path + ResourceUtils.JAR_URL_SEPARATOR + "assets/file.txt").exists()).isFalse(); assertThat(new UrlResource(ResourceUtils.JAR_URL_PREFIX + ResourceUtils.FILE_URL_PREFIX + "X" + path + ResourceUtils.JAR_URL_SEPARATOR + "assets/none.txt").exists()).isFalse(); + + Resource resource = new UrlResource(ResourceUtils.JAR_URL_PREFIX + ResourceUtils.FILE_URL_PREFIX + path + ResourceUtils.JAR_URL_SEPARATOR + "assets/file.txt"); + try (InputStream is = resource.getInputStream()) { + assertThat(resource.exists()).isTrue(); + assertThat(resource.createRelative("file.txt").exists()).isTrue(); + assertThat(new UrlResource(ResourceUtils.JAR_URL_PREFIX + ResourceUtils.FILE_URL_PREFIX + path + ResourceUtils.JAR_URL_SEPARATOR).exists()).isTrue(); + is.readAllBytes(); + } } private void writeApplicationJar(Path path) throws Exception {