commit
ac9d2e7c11
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright 2012-2023 the original author or authors.
|
||||
* Copyright 2012-2024 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
|
|
@ -20,6 +20,7 @@ import java.io.File;
|
|||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Path;
|
||||
import java.security.CodeSource;
|
||||
import java.security.ProtectionDomain;
|
||||
import java.util.Set;
|
||||
|
|
@ -107,11 +108,10 @@ public interface Archive extends AutoCloseable {
|
|||
static Archive create(ProtectionDomain protectionDomain) throws Exception {
|
||||
CodeSource codeSource = protectionDomain.getCodeSource();
|
||||
URI location = (codeSource != null) ? codeSource.getLocation().toURI() : null;
|
||||
String path = (location != null) ? location.getSchemeSpecificPart() : null;
|
||||
if (path == null) {
|
||||
if (location == null) {
|
||||
throw new IllegalStateException("Unable to determine code source archive");
|
||||
}
|
||||
return create(new File(path));
|
||||
return create(Path.of(location).toFile());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -53,7 +53,9 @@ import org.springframework.boot.loader.net.util.UrlDecoder;
|
|||
*/
|
||||
public record NestedLocation(Path path, String nestedEntryName) {
|
||||
|
||||
private static final Map<String, NestedLocation> cache = new ConcurrentHashMap<>();
|
||||
private static final Map<String, NestedLocation> locationCache = new ConcurrentHashMap<>();
|
||||
|
||||
private static final Map<String, Path> pathCache = new ConcurrentHashMap<>();
|
||||
|
||||
public NestedLocation(Path path, String nestedEntryName) {
|
||||
if (path == null) {
|
||||
|
|
@ -89,35 +91,37 @@ public record NestedLocation(Path path, String nestedEntryName) {
|
|||
return parse(uri.getSchemeSpecificPart());
|
||||
}
|
||||
|
||||
static NestedLocation parse(String path) {
|
||||
if (path == null || path.isEmpty()) {
|
||||
throw new IllegalArgumentException("'path' must not be empty");
|
||||
static NestedLocation parse(String location) {
|
||||
if (location == null || location.isEmpty()) {
|
||||
throw new IllegalArgumentException("'location' must not be empty");
|
||||
}
|
||||
int index = path.lastIndexOf("/!");
|
||||
return cache.computeIfAbsent(path, (l) -> create(index, l));
|
||||
return locationCache.computeIfAbsent(location, (key) -> create(location));
|
||||
}
|
||||
|
||||
private static NestedLocation create(int index, String location) {
|
||||
private static NestedLocation create(String location) {
|
||||
int index = location.lastIndexOf("/!");
|
||||
String locationPath = (index != -1) ? location.substring(0, index) : location;
|
||||
if (isWindows() && !isUncPath(location)) {
|
||||
while (locationPath.startsWith("/")) {
|
||||
locationPath = locationPath.substring(1, locationPath.length());
|
||||
}
|
||||
}
|
||||
String nestedEntryName = (index != -1) ? location.substring(index + 2) : null;
|
||||
return new NestedLocation((!locationPath.isEmpty()) ? Path.of(locationPath) : null, nestedEntryName);
|
||||
return new NestedLocation((!locationPath.isEmpty()) ? asPath(locationPath) : null, nestedEntryName);
|
||||
}
|
||||
|
||||
private static Path asPath(String locationPath) {
|
||||
return pathCache.computeIfAbsent(locationPath, (key) -> {
|
||||
if (isWindows() && locationPath.length() > 2 && locationPath.charAt(2) == ':') {
|
||||
// Use the same logic as Java's internal WindowsUriSupport class
|
||||
return Path.of(locationPath.substring(1));
|
||||
}
|
||||
return Path.of(locationPath);
|
||||
});
|
||||
}
|
||||
|
||||
private static boolean isWindows() {
|
||||
return File.separatorChar == '\\';
|
||||
}
|
||||
|
||||
private static boolean isUncPath(String input) {
|
||||
return !input.contains(":");
|
||||
}
|
||||
|
||||
static void clearCache() {
|
||||
cache.clear();
|
||||
locationCache.clear();
|
||||
pathCache.clear();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.springframework.boot.loader.net.util.UrlDecoder;
|
||||
import org.springframework.boot.loader.ref.Cleaner;
|
||||
|
||||
/**
|
||||
|
|
@ -77,7 +76,7 @@ class NestedUrlConnection extends URLConnection {
|
|||
|
||||
private NestedLocation parseNestedLocation(URL url) throws MalformedURLException {
|
||||
try {
|
||||
return NestedLocation.parse(UrlDecoder.decode(url.getPath()));
|
||||
return NestedLocation.fromUrl(url);
|
||||
}
|
||||
catch (IllegalArgumentException ex) {
|
||||
throw new MalformedURLException(ex.getMessage());
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ class NestedLocationTests {
|
|||
@Test
|
||||
void fromUrlWhenNoPathThrowsException() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> NestedLocation.fromUrl(new URL("nested:")))
|
||||
.withMessageContaining("'path' must not be empty");
|
||||
.withMessageContaining("'location' must not be empty");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
|||
Loading…
Reference in New Issue