mirror of
https://github.com/spring-projects/spring-boot.git
synced 2026-09-29 21:59:02 +00:00
Merge pull request #51827 from sharanrenukeshbharmshetty
Closes gh-51827 * pr/51827: Polish 'Avoid parsing nested jar URLs for cached resource lookups' Avoid parsing nested jar URLs for cached resource lookups
This commit is contained in:
+8
@@ -44,6 +44,14 @@ final class JarFileUrlKey {
|
||||
this.runtimeRef = "runtime".equals(url.getRef());
|
||||
}
|
||||
|
||||
JarFileUrlKey(String protocol, String host, int port, String file, boolean runtimeRef) {
|
||||
this.protocol = protocol;
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.file = file;
|
||||
this.runtimeRef = runtimeRef;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
|
||||
+6
-8
@@ -45,6 +45,7 @@ import org.springframework.boot.loader.net.util.UrlDecoder;
|
||||
* @author Phillip Webb
|
||||
* @author Andy Wilkinson
|
||||
* @author Rostyslav Dudka
|
||||
* @author Sharan Bharmshetty
|
||||
*/
|
||||
final class JarUrlConnection extends java.net.JarURLConnection {
|
||||
|
||||
@@ -335,15 +336,12 @@ final class JarUrlConnection extends java.net.JarURLConnection {
|
||||
String spec = url.getFile();
|
||||
if (spec.startsWith("nested:")) {
|
||||
int separator = spec.indexOf("!/");
|
||||
boolean specHasEntry = (separator != -1) && (separator + 2 != spec.length());
|
||||
if (specHasEntry) {
|
||||
URL jarFileUrl = new URL(spec.substring(0, separator));
|
||||
if ("runtime".equals(url.getRef())) {
|
||||
jarFileUrl = new URL(jarFileUrl, "#runtime");
|
||||
}
|
||||
boolean specHasJarEntry = (separator != -1) && (separator + 2 != spec.length());
|
||||
if (specHasJarEntry) {
|
||||
String jarFileSpec = spec.substring(0, separator);
|
||||
boolean runtimeRef = "runtime".equals(url.getRef());
|
||||
JarFile jarFile = jarFiles.getOrCreateAndCache(jarFileSpec, runtimeRef);
|
||||
String entryName = UrlDecoder.decode(spec.substring(separator + 2));
|
||||
JarFile jarFile = jarFiles.getOrCreate(true, jarFileUrl);
|
||||
jarFiles.cacheIfAbsent(true, jarFileUrl, jarFile);
|
||||
if (!hasEntry(jarFile, entryName)) {
|
||||
return notFoundConnection(jarFile.getName(), entryName);
|
||||
}
|
||||
|
||||
+40
-5
@@ -31,6 +31,7 @@ import java.util.jar.JarFile;
|
||||
* instances.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Sharan Bharmshetty
|
||||
*/
|
||||
class UrlJarFiles {
|
||||
|
||||
@@ -53,6 +54,20 @@ class UrlJarFiles {
|
||||
this.factory = factory;
|
||||
}
|
||||
|
||||
JarFile getOrCreateAndCache(String jarFileSpec, boolean runtimeRef) throws IOException {
|
||||
JarFileUrlKey jarFileUrlKey = new JarFileUrlKey("jar", "", -1, jarFileSpec, runtimeRef);
|
||||
JarFile jarFile = this.cache.get(jarFileUrlKey);
|
||||
if (jarFile == null) {
|
||||
URL jarFileUrl = new URL(jarFileSpec);
|
||||
if (runtimeRef) {
|
||||
jarFileUrl = new URL(jarFileUrl, "#runtime");
|
||||
}
|
||||
jarFile = this.factory.createJarFile(jarFileUrl, this::onClose);
|
||||
this.cache.putIfAbsent(jarFileUrlKey, jarFile, jarFileUrl);
|
||||
}
|
||||
return jarFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an existing {@link JarFile} instance from the cache, or create a new
|
||||
* {@link JarFile} instance that can be {@link #cacheIfAbsent(boolean, URL, JarFile)
|
||||
@@ -154,9 +169,17 @@ class UrlJarFiles {
|
||||
* @return the cached {@link JarFile} or {@code null}
|
||||
*/
|
||||
JarFile get(URL jarFileUrl) {
|
||||
JarFileUrlKey urlKey = new JarFileUrlKey(jarFileUrl);
|
||||
return get(new JarFileUrlKey(jarFileUrl));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a {@link JarFile} from the cache given a jar file URL key.
|
||||
* @param jarFileUrlKey the jar file URL key
|
||||
* @return the cached {@link JarFile} or {@code null}
|
||||
*/
|
||||
JarFile get(JarFileUrlKey jarFileUrlKey) {
|
||||
synchronized (this) {
|
||||
return this.jarFileUrlToJarFile.get(urlKey);
|
||||
return this.jarFileUrlToJarFile.get(jarFileUrlKey);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -180,11 +203,23 @@ class UrlJarFiles {
|
||||
* they were already there
|
||||
*/
|
||||
boolean putIfAbsent(URL jarFileUrl, JarFile jarFile) {
|
||||
JarFileUrlKey urlKey = new JarFileUrlKey(jarFileUrl);
|
||||
return putIfAbsent(new JarFileUrlKey(jarFileUrl), jarFile, jarFileUrl);
|
||||
}
|
||||
|
||||
/**
|
||||
* Put the given jar file URL and jar file into the cache if they aren't already
|
||||
* there.
|
||||
* @param jarFileUrlKey the jar file URL key
|
||||
* @param jarFileUrl the jar file URL
|
||||
* @param jarFile the jar file
|
||||
* @return {@code true} if the items were added to the cache or {@code false} if
|
||||
* they were already there
|
||||
*/
|
||||
boolean putIfAbsent(JarFileUrlKey jarFileUrlKey, JarFile jarFile, URL jarFileUrl) {
|
||||
synchronized (this) {
|
||||
JarFile cached = this.jarFileUrlToJarFile.get(urlKey);
|
||||
JarFile cached = this.jarFileUrlToJarFile.get(jarFileUrlKey);
|
||||
if (cached == null) {
|
||||
this.jarFileUrlToJarFile.put(urlKey, jarFile);
|
||||
this.jarFileUrlToJarFile.put(jarFileUrlKey, jarFile);
|
||||
this.jarFileToJarFileUrl.put(jarFile, jarFileUrl);
|
||||
return true;
|
||||
}
|
||||
|
||||
+24
@@ -30,6 +30,7 @@ import static org.assertj.core.api.Assertions.assertThat;
|
||||
* Tests for {@link JarFileUrlKey}.
|
||||
*
|
||||
* @author Phillip Webb
|
||||
* @author Sharan Bharmshetty
|
||||
*/
|
||||
class JarFileUrlKeyTests {
|
||||
|
||||
@@ -101,4 +102,27 @@ class JarFileUrlKeyTests {
|
||||
return new JarFileUrlKey(new URL(spec));
|
||||
}
|
||||
|
||||
@Test
|
||||
void directKeyEqualsUrlKey() throws Exception {
|
||||
JarFileUrlKey fromUrl = key("jar:nested:/my.jar/!mynested.jar!/my/path");
|
||||
JarFileUrlKey direct = new JarFileUrlKey("jar", "", -1, "nested:/my.jar/!mynested.jar!/my/path", false);
|
||||
assertThat(direct).isEqualTo(fromUrl);
|
||||
assertThat(direct.hashCode()).isEqualTo(fromUrl.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void directKeyWithRuntimeRefEqualsUrlKey() throws Exception {
|
||||
JarFileUrlKey fromUrl = key("jar:nested:/my.jar/!mynested.jar!/my/path#runtime");
|
||||
JarFileUrlKey direct = new JarFileUrlKey("jar", "", -1, "nested:/my.jar/!mynested.jar!/my/path", true);
|
||||
assertThat(direct).isEqualTo(fromUrl);
|
||||
assertThat(direct.hashCode()).isEqualTo(fromUrl.hashCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
void directKeyWithRuntimeRefNotEqualToKeyWithout() {
|
||||
JarFileUrlKey k1 = new JarFileUrlKey("jar", "", -1, "nested:/my.jar/!mynested.jar!/my/path", true);
|
||||
JarFileUrlKey k2 = new JarFileUrlKey("jar", "", -1, "nested:/my.jar/!mynested.jar!/my/path", false);
|
||||
assertThat(k1).isNotEqualTo(k2);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user