Change `NestedLocation` to hold a `Path` rather than a `File`

Refactor `NestedLocation` so that it holds a `Path` rather than a
`File`.

See gh-37668
This commit is contained in:
Phillip Webb 2023-10-18 15:00:50 -07:00
parent ec6415f04b
commit 4b495ca2a9
5 changed files with 28 additions and 18 deletions

View File

@ -82,7 +82,7 @@ class UrlJarFileFactory {
private JarFile createJarFileForNested(URL url, Runtime.Version version, Consumer<JarFile> closeAction) private JarFile createJarFileForNested(URL url, Runtime.Version version, Consumer<JarFile> closeAction)
throws IOException { throws IOException {
NestedLocation location = NestedLocation.fromUrl(url); NestedLocation location = NestedLocation.fromUrl(url);
return new UrlNestedJarFile(location.file(), location.nestedEntryName(), version, closeAction); return new UrlNestedJarFile(location.path().toFile(), location.nestedEntryName(), version, closeAction);
} }
private JarFile createJarFileForStream(URL url, Version version, Consumer<JarFile> closeAction) throws IOException { private JarFile createJarFileForStream(URL url, Version version, Consumer<JarFile> closeAction) throws IOException {

View File

@ -16,8 +16,9 @@
package org.springframework.boot.loader.net.protocol.nested; package org.springframework.boot.loader.net.protocol.nested;
import java.io.File; import java.net.URI;
import java.net.URL; import java.net.URL;
import java.nio.file.Path;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -43,18 +44,18 @@ import org.springframework.boot.loader.net.util.UrlDecoder;
* uncompressed entry that contains the nested jar, or a directory entry. The entry must * uncompressed entry that contains the nested jar, or a directory entry. The entry must
* not start with a {@code '/'}. * not start with a {@code '/'}.
* *
* @param file the zip file that contains the nested entry * @param path the path to the zip that contains the nested entry
* @param nestedEntryName the nested entry name * @param nestedEntryName the nested entry name
* @author Phillip Webb * @author Phillip Webb
* @since 3.2.0 * @since 3.2.0
*/ */
public record NestedLocation(File file, String nestedEntryName) { public record NestedLocation(Path path, String nestedEntryName) {
private static final Map<String, NestedLocation> cache = new ConcurrentHashMap<>(); private static final Map<String, NestedLocation> cache = new ConcurrentHashMap<>();
public NestedLocation { public NestedLocation {
if (file == null) { if (path == null) {
throw new IllegalArgumentException("'file' must not be null"); throw new IllegalArgumentException("'path' must not be null");
} }
if (nestedEntryName == null || nestedEntryName.trim().isEmpty()) { if (nestedEntryName == null || nestedEntryName.trim().isEmpty()) {
throw new IllegalArgumentException("'nestedEntryName' must not be empty"); throw new IllegalArgumentException("'nestedEntryName' must not be empty");
@ -86,9 +87,9 @@ public record NestedLocation(File file, String nestedEntryName) {
} }
private static NestedLocation create(int index, String location) { private static NestedLocation create(int index, String location) {
String file = location.substring(0, index); String path = location.substring(0, index);
String nestedEntryName = location.substring(index + 2); String nestedEntryName = location.substring(index + 2);
return new NestedLocation((!file.isEmpty()) ? new File(file) : null, nestedEntryName); return new NestedLocation((!path.isEmpty()) ? Path.of(path) : null, nestedEntryName);
} }
static void clearCache() { static void clearCache() {

View File

@ -16,6 +16,7 @@
package org.springframework.boot.loader.net.protocol.nested; package org.springframework.boot.loader.net.protocol.nested;
import java.io.File;
import java.io.FilePermission; import java.io.FilePermission;
import java.io.FilterInputStream; import java.io.FilterInputStream;
import java.io.IOException; import java.io.IOException;
@ -25,6 +26,7 @@ import java.lang.ref.Cleaner.Cleanable;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.net.URLConnection; import java.net.URLConnection;
import java.nio.file.Files;
import java.security.Permission; import java.security.Permission;
import org.springframework.boot.loader.ref.Cleaner; import org.springframework.boot.loader.ref.Cleaner;
@ -43,7 +45,7 @@ class NestedUrlConnection extends URLConnection {
private final Cleanable cleanup; private final Cleanable cleanup;
private long lastModified; private long lastModified = -1;
private FilePermission permission; private FilePermission permission;
@ -91,8 +93,13 @@ class NestedUrlConnection extends URLConnection {
@Override @Override
public long getLastModified() { public long getLastModified() {
if (this.lastModified == 0) { if (this.lastModified == -1) {
this.lastModified = this.resources.getLocation().file().lastModified(); try {
this.lastModified = Files.getLastModifiedTime(this.resources.getLocation().path()).toMillis();
}
catch (IOException ex) {
this.lastModified = 0;
}
} }
return this.lastModified; return this.lastModified;
} }
@ -100,7 +107,8 @@ class NestedUrlConnection extends URLConnection {
@Override @Override
public Permission getPermission() throws IOException { public Permission getPermission() throws IOException {
if (this.permission == null) { if (this.permission == null) {
this.permission = new FilePermission(this.resources.getLocation().file().getCanonicalPath(), "read"); File file = this.resources.getLocation().path().toFile();
this.permission = new FilePermission(file.getCanonicalPath(), "read");
} }
return this.permission; return this.permission;
} }

View File

@ -51,7 +51,7 @@ class NestedUrlConnectionResources implements Runnable {
void connect() throws IOException { void connect() throws IOException {
synchronized (this) { synchronized (this) {
if (this.zipContent == null) { if (this.zipContent == null) {
this.zipContent = ZipContent.open(this.location.file().toPath(), this.location.nestedEntryName()); this.zipContent = ZipContent.open(this.location.path(), this.location.nestedEntryName());
try { try {
connectData(); connectData();
} }

View File

@ -18,6 +18,7 @@ package org.springframework.boot.loader.net.protocol.nested;
import java.io.File; import java.io.File;
import java.net.URL; import java.net.URL;
import java.nio.file.Path;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -44,20 +45,20 @@ class NestedLocationTests {
} }
@Test @Test
void createWhenFileIsNullThrowsException() { void createWhenPathIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> new NestedLocation(null, "nested.jar")) assertThatIllegalArgumentException().isThrownBy(() -> new NestedLocation(null, "nested.jar"))
.withMessageContaining("'file' must not be null"); .withMessageContaining("'path' must not be null");
} }
@Test @Test
void createWhenNestedEntryNameIsNullThrowsException() { void createWhenNestedEntryNameIsNullThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> new NestedLocation(new File("test.jar"), null)) assertThatIllegalArgumentException().isThrownBy(() -> new NestedLocation(Path.of("test.jar"), null))
.withMessageContaining("'nestedEntryName' must not be empty"); .withMessageContaining("'nestedEntryName' must not be empty");
} }
@Test @Test
void createWhenNestedEntryNameIsEmptyThrowsException() { void createWhenNestedEntryNameIsEmptyThrowsException() {
assertThatIllegalArgumentException().isThrownBy(() -> new NestedLocation(new File("test.jar"), null)) assertThatIllegalArgumentException().isThrownBy(() -> new NestedLocation(Path.of("test.jar"), null))
.withMessageContaining("'nestedEntryName' must not be empty"); .withMessageContaining("'nestedEntryName' must not be empty");
} }
@ -91,7 +92,7 @@ class NestedLocationTests {
File file = new File(this.temp, "test.jar"); File file = new File(this.temp, "test.jar");
NestedLocation location = NestedLocation NestedLocation location = NestedLocation
.fromUrl(new URL("nested:" + file.getAbsolutePath() + "/!lib/nested.jar")); .fromUrl(new URL("nested:" + file.getAbsolutePath() + "/!lib/nested.jar"));
assertThat(location.file()).isEqualTo(file); assertThat(location.path()).isEqualTo(file.toPath());
assertThat(location.nestedEntryName()).isEqualTo("lib/nested.jar"); assertThat(location.nestedEntryName()).isEqualTo("lib/nested.jar");
} }