Skip to content

Commit 1c3a668

Browse files
committed
AbstractFileResolvingResource uses extractArchiveURL for last-modified check
Issue: SPR-13393 (cherry picked from commit 302a069)
1 parent 8fbba84 commit 1c3a668

File tree

3 files changed

+67
-17
lines changed

3 files changed

+67
-17
lines changed

spring-core/src/main/java/org/springframework/core/io/AbstractFileResolvingResource.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2013 the original author or authors.
2+
* Copyright 2002-2015 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -60,7 +60,7 @@ public File getFile() throws IOException {
6060
protected File getFileForLastModifiedCheck() throws IOException {
6161
URL url = getURL();
6262
if (ResourceUtils.isJarURL(url)) {
63-
URL actualUrl = ResourceUtils.extractJarFileURL(url);
63+
URL actualUrl = ResourceUtils.extractArchiveURL(url);
6464
if (actualUrl.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
6565
return VfsResourceDelegate.getResource(actualUrl).getFile();
6666
}

spring-core/src/main/java/org/springframework/util/ResourceUtils.java

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -57,9 +57,12 @@ public abstract class ResourceUtils {
5757
/** URL prefix for loading from the file system: "file:" */
5858
public static final String FILE_URL_PREFIX = "file:";
5959

60-
/** URL prefix for loading from the file system: "jar:" */
60+
/** URL prefix for loading from a jar file: "jar:" */
6161
public static final String JAR_URL_PREFIX = "jar:";
6262

63+
/** URL prefix for loading from a war file on Tomcat: "war:" */
64+
public static final String WAR_URL_PREFIX = "war:";
65+
6366
/** URL protocol for a file in the file system: "file" */
6467
public static final String URL_PROTOCOL_FILE = "file";
6568

@@ -69,9 +72,6 @@ public abstract class ResourceUtils {
6972
/** URL protocol for an entry from a zip file: "zip" */
7073
public static final String URL_PROTOCOL_ZIP = "zip";
7174

72-
/** URL protocol for an entry from a Tomcat war file: "war" */
73-
public static final String URL_PROTOCOL_WAR = "war";
74-
7575
/** URL protocol for an entry from a WebSphere jar file: "wsjar" */
7676
public static final String URL_PROTOCOL_WSJAR = "wsjar";
7777

@@ -90,6 +90,9 @@ public abstract class ResourceUtils {
9090
/** Separator between JAR URL and file path within the JAR: "!/" */
9191
public static final String JAR_URL_SEPARATOR = "!/";
9292

93+
/** Special separator between WAR URL and jar part on Tomcat */
94+
public static final String WAR_URL_SEPARATOR = "*/";
95+
9396

9497
/**
9598
* Return whether the given resource location is a URL:
@@ -278,8 +281,7 @@ public static boolean isFileURL(URL url) {
278281
public static boolean isJarURL(URL url) {
279282
String protocol = url.getProtocol();
280283
return (URL_PROTOCOL_JAR.equals(protocol) || URL_PROTOCOL_ZIP.equals(protocol) ||
281-
URL_PROTOCOL_WAR.equals(protocol) || URL_PROTOCOL_WSJAR.equals(protocol) ||
282-
URL_PROTOCOL_VFSZIP.equals(protocol));
284+
URL_PROTOCOL_VFSZIP.equals(protocol) || URL_PROTOCOL_WSJAR.equals(protocol));
283285
}
284286

285287
/**
@@ -303,10 +305,9 @@ public static boolean isJarFileURL(URL url) {
303305
*/
304306
public static URL extractJarFileURL(URL jarUrl) throws MalformedURLException {
305307
String urlFile = jarUrl.getFile();
306-
int startIndex = (urlFile.startsWith(JAR_URL_PREFIX) ? JAR_URL_PREFIX.length() : 0);
307-
int endIndex = urlFile.indexOf(JAR_URL_SEPARATOR);
308-
if (endIndex != -1) {
309-
String jarFile = urlFile.substring(startIndex, endIndex);
308+
int separatorIndex = urlFile.indexOf(JAR_URL_SEPARATOR);
309+
if (separatorIndex != -1) {
310+
String jarFile = urlFile.substring(0, separatorIndex);
310311
try {
311312
return new URL(jarFile);
312313
}
@@ -324,6 +325,34 @@ public static URL extractJarFileURL(URL jarUrl) throws MalformedURLException {
324325
}
325326
}
326327

328+
/**
329+
* Extract the URL for the outermost archive from the given jar/war URL
330+
* (which may point to a resource in a jar file or to a jar file itself).
331+
* <p>In the case of a jar file nested within a war file, this will return
332+
* a URL to the war file since that is the one resolvable in the file system.
333+
* @param jarUrl the original URL
334+
* @return the URL for the actual jar file
335+
* @throws MalformedURLException if no valid jar file URL could be extracted
336+
* @since 4.1.8
337+
* @see #extractJarFileURL(URL)
338+
*/
339+
public static URL extractArchiveURL(URL jarUrl) throws MalformedURLException {
340+
String urlFile = jarUrl.getFile();
341+
342+
int endIndex = urlFile.indexOf(WAR_URL_SEPARATOR);
343+
if (endIndex != -1) {
344+
// Tomcat's "jar:war:file:...mywar.war*/WEB-INF/lib/myjar.jar!/myentry.txt"
345+
String warFile = urlFile.substring(0, endIndex);
346+
int startIndex = warFile.indexOf(WAR_URL_PREFIX);
347+
if (startIndex != -1) {
348+
return new URL(warFile.substring(startIndex + WAR_URL_PREFIX.length()));
349+
}
350+
}
351+
352+
// Regular "jar:file:...myjar.jar!/myentry.txt"
353+
return extractJarFileURL(jarUrl);
354+
}
355+
327356
/**
328357
* Create a URI instance for the given URL,
329358
* replacing spaces with "%20" URI encoding first.

spring-core/src/test/java/org/springframework/util/ResourceUtilsTests.java

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ public void isJarURL() throws Exception {
3535
assertTrue(ResourceUtils.isJarURL(new URL("jar:file:myjar.jar!/mypath")));
3636
assertTrue(ResourceUtils.isJarURL(new URL(null, "zip:file:myjar.jar!/mypath", new DummyURLStreamHandler())));
3737
assertTrue(ResourceUtils.isJarURL(new URL(null, "wsjar:file:myjar.jar!/mypath", new DummyURLStreamHandler())));
38-
assertTrue(ResourceUtils.isJarURL(new URL(null, "war:jar:file:myjar.jar!/mypath", new DummyURLStreamHandler())));
38+
assertTrue(ResourceUtils.isJarURL(new URL(null, "jar:war:file:mywar.war*/myjar.jar!/mypath", new DummyURLStreamHandler())));
3939
assertFalse(ResourceUtils.isJarURL(new URL("file:myjar.jar")));
4040
assertFalse(ResourceUtils.isJarURL(new URL("http:myserver/myjar.jar")));
4141
}
@@ -50,19 +50,40 @@ public void extractJarFileURL() throws Exception {
5050
ResourceUtils.extractJarFileURL(new URL(null, "zip:file:myjar.jar!/mypath", new DummyURLStreamHandler())));
5151
assertEquals(new URL("file:myjar.jar"),
5252
ResourceUtils.extractJarFileURL(new URL(null, "wsjar:file:myjar.jar!/mypath", new DummyURLStreamHandler())));
53-
assertEquals(new URL("file:myjar.jar"),
54-
ResourceUtils.extractJarFileURL(new URL(null, "war:jar:file:myjar.jar!/mypath", new DummyURLStreamHandler())));
5553

54+
assertEquals(new URL("file:myjar.jar"),
55+
ResourceUtils.extractJarFileURL(new URL("file:myjar.jar")));
5656
assertEquals(new URL("file:myjar.jar"),
5757
ResourceUtils.extractJarFileURL(new URL("jar:file:myjar.jar!/")));
5858
assertEquals(new URL("file:myjar.jar"),
5959
ResourceUtils.extractJarFileURL(new URL(null, "zip:file:myjar.jar!/", new DummyURLStreamHandler())));
6060
assertEquals(new URL("file:myjar.jar"),
6161
ResourceUtils.extractJarFileURL(new URL(null, "wsjar:file:myjar.jar!/", new DummyURLStreamHandler())));
62+
}
63+
64+
@Test
65+
public void extractArchiveURL() throws Exception {
66+
assertEquals(new URL("file:myjar.jar"),
67+
ResourceUtils.extractArchiveURL(new URL("jar:file:myjar.jar!/mypath")));
68+
assertEquals(new URL("file:/myjar.jar"),
69+
ResourceUtils.extractArchiveURL(new URL(null, "jar:myjar.jar!/mypath", new DummyURLStreamHandler())));
6270
assertEquals(new URL("file:myjar.jar"),
63-
ResourceUtils.extractJarFileURL(new URL(null, "war:jar:file:myjar.jar!/", new DummyURLStreamHandler())));
71+
ResourceUtils.extractArchiveURL(new URL(null, "zip:file:myjar.jar!/mypath", new DummyURLStreamHandler())));
6472
assertEquals(new URL("file:myjar.jar"),
65-
ResourceUtils.extractJarFileURL(new URL("file:myjar.jar")));
73+
ResourceUtils.extractArchiveURL(new URL(null, "wsjar:file:myjar.jar!/mypath", new DummyURLStreamHandler())));
74+
assertEquals(new URL("file:mywar.war"),
75+
ResourceUtils.extractArchiveURL(new URL(null, "jar:war:file:mywar.war*/myjar.jar!/mypath", new DummyURLStreamHandler())));
76+
77+
assertEquals(new URL("file:myjar.jar"),
78+
ResourceUtils.extractArchiveURL(new URL("file:myjar.jar")));
79+
assertEquals(new URL("file:myjar.jar"),
80+
ResourceUtils.extractArchiveURL(new URL("jar:file:myjar.jar!/")));
81+
assertEquals(new URL("file:myjar.jar"),
82+
ResourceUtils.extractArchiveURL(new URL(null, "zip:file:myjar.jar!/", new DummyURLStreamHandler())));
83+
assertEquals(new URL("file:myjar.jar"),
84+
ResourceUtils.extractArchiveURL(new URL(null, "wsjar:file:myjar.jar!/", new DummyURLStreamHandler())));
85+
assertEquals(new URL("file:mywar.war"),
86+
ResourceUtils.extractArchiveURL(new URL(null, "jar:war:file:mywar.war*/myjar.jar!/", new DummyURLStreamHandler())));
6687
}
6788

6889

0 commit comments

Comments
 (0)