mirror of
https://github.com/spring-projects/spring-framework.git
synced 2026-09-26 08:59:09 +00:00
Introduce useCaches flag on UrlResource (for URLConnection access)
Propagated from PathMatchingResourcePatternResolver's setUseCaches. Closes gh-35218
This commit is contained in:
+11
-1
@@ -361,12 +361,22 @@ public abstract class AbstractFileResolvingResource extends AbstractResource {
|
||||
* @throws IOException if thrown from URLConnection methods
|
||||
*/
|
||||
protected void customizeConnection(URLConnection con) throws IOException {
|
||||
ResourceUtils.useCachesIfNecessary(con);
|
||||
useCachesIfNecessary(con);
|
||||
if (con instanceof HttpURLConnection httpCon) {
|
||||
customizeConnection(httpCon);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply {@link URLConnection#setUseCaches useCaches} if necessary.
|
||||
* @param con the URLConnection to customize
|
||||
* @since 6.2.10
|
||||
* @see ResourceUtils#useCachesIfNecessary(URLConnection)
|
||||
*/
|
||||
void useCachesIfNecessary(URLConnection con) {
|
||||
ResourceUtils.useCachesIfNecessary(con);
|
||||
}
|
||||
|
||||
/**
|
||||
* Customize the given {@link HttpURLConnection} before fetching the resource.
|
||||
* <p>Can be overridden in subclasses for configuring request headers and timeouts.
|
||||
|
||||
@@ -109,7 +109,9 @@ public class FileUrlResource extends UrlResource implements WritableResource {
|
||||
|
||||
@Override
|
||||
public Resource createRelative(String relativePath) throws MalformedURLException {
|
||||
return new FileUrlResource(createRelativeURL(relativePath));
|
||||
FileUrlResource resource = new FileUrlResource(createRelativeURL(relativePath));
|
||||
resource.useCaches = this.useCaches;
|
||||
return resource;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -67,6 +67,12 @@ public class UrlResource extends AbstractFileResolvingResource {
|
||||
@Nullable
|
||||
private volatile String cleanedUrl;
|
||||
|
||||
/**
|
||||
* Whether to use URLConnection caches ({@code null} means default).
|
||||
*/
|
||||
@Nullable
|
||||
volatile Boolean useCaches;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new {@code UrlResource} based on the given URL object.
|
||||
@@ -216,11 +222,22 @@ public class UrlResource extends AbstractFileResolvingResource {
|
||||
return cleanedUrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set an explicit flag for {@link URLConnection#setUseCaches},
|
||||
* to be applied for any {@link URLConnection} operation in this resource.
|
||||
* <p>By default, caching will be applied only to jar resources.
|
||||
* An explicit {@code true} flag applies caching to all resources, whereas an
|
||||
* explicit {@code false} flag turns off caching for jar resources as well.
|
||||
* @since 6.2.10
|
||||
* @see ResourceUtils#useCachesIfNecessary
|
||||
*/
|
||||
public void setUseCaches(boolean useCaches) {
|
||||
this.useCaches = useCaches;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This implementation opens an InputStream for the given URL.
|
||||
* <p>It sets the {@code useCaches} flag to {@code false},
|
||||
* mainly to avoid jar file locking on Windows.
|
||||
* @see java.net.URL#openConnection()
|
||||
* @see java.net.URLConnection#setUseCaches(boolean)
|
||||
* @see java.net.URLConnection#getInputStream()
|
||||
@@ -251,6 +268,17 @@ public class UrlResource extends AbstractFileResolvingResource {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
void useCachesIfNecessary(URLConnection con) {
|
||||
Boolean useCaches = this.useCaches;
|
||||
if (useCaches != null) {
|
||||
con.setUseCaches(useCaches);
|
||||
}
|
||||
else {
|
||||
super.useCachesIfNecessary(con);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation returns the underlying URL reference.
|
||||
*/
|
||||
@@ -305,7 +333,9 @@ public class UrlResource extends AbstractFileResolvingResource {
|
||||
*/
|
||||
@Override
|
||||
public Resource createRelative(String relativePath) throws MalformedURLException {
|
||||
return new UrlResource(createRelativeURL(relativePath));
|
||||
UrlResource resource = new UrlResource(createRelativeURL(relativePath));
|
||||
resource.useCaches = this.useCaches;
|
||||
return resource;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+46
-21
@@ -260,7 +260,8 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
|
||||
private PathMatcher pathMatcher = new AntPathMatcher();
|
||||
|
||||
private boolean useCaches = true;
|
||||
@Nullable
|
||||
private Boolean useCaches;
|
||||
|
||||
private final Map<String, Resource[]> rootDirCache = new ConcurrentHashMap<>();
|
||||
|
||||
@@ -342,10 +343,12 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
* the {@link JarURLConnection} level as well as within this resolver instance.
|
||||
* <p>Note that {@link JarURLConnection#setDefaultUseCaches} can be turned off
|
||||
* independently. This resolver-level setting is designed to only enforce
|
||||
* {@code JarURLConnection#setUseCaches(false)} if necessary but otherwise
|
||||
* leaves the JVM-level default in place.
|
||||
* {@code JarURLConnection#setUseCaches(true/false)} if necessary but otherwise
|
||||
* leaves the JVM-level default in place (if this setter has not been called).
|
||||
* <p>As of 6.2.10, this setting propagates to {@link UrlResource#setUseCaches}.
|
||||
* @since 6.1.19
|
||||
* @see JarURLConnection#setUseCaches
|
||||
* @see UrlResource#setUseCaches
|
||||
* @see #clearCache()
|
||||
*/
|
||||
public void setUseCaches(boolean useCaches) {
|
||||
@@ -355,7 +358,11 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
|
||||
@Override
|
||||
public Resource getResource(String location) {
|
||||
return getResourceLoader().getResource(location);
|
||||
Resource resource = getResourceLoader().getResource(location);
|
||||
if (this.useCaches != null && resource instanceof UrlResource urlResource) {
|
||||
urlResource.setUseCaches(this.useCaches);
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -473,20 +480,27 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
}
|
||||
}
|
||||
else {
|
||||
UrlResource resource = null;
|
||||
String urlString = url.toString();
|
||||
String cleanedPath = StringUtils.cleanPath(urlString);
|
||||
if (!cleanedPath.equals(urlString)) {
|
||||
// Prefer cleaned URL, aligned with UrlResource#createRelative(String)
|
||||
try {
|
||||
// Retain original URL instance, potentially including custom URLStreamHandler.
|
||||
return new UrlResource(new URL(url, cleanedPath));
|
||||
resource = new UrlResource(new URL(url, cleanedPath));
|
||||
}
|
||||
catch (MalformedURLException ex) {
|
||||
// Fallback to regular URL construction below...
|
||||
}
|
||||
}
|
||||
// Retain original URL instance, potentially including custom URLStreamHandler.
|
||||
return new UrlResource(url);
|
||||
if (resource == null) {
|
||||
resource = new UrlResource(url);
|
||||
}
|
||||
if (this.useCaches != null) {
|
||||
resource.setUseCaches(this.useCaches);
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -505,6 +519,9 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
UrlResource jarResource = (ResourceUtils.URL_PROTOCOL_JAR.equals(url.getProtocol()) ?
|
||||
new UrlResource(url) :
|
||||
new UrlResource(ResourceUtils.JAR_URL_PREFIX + url + ResourceUtils.JAR_URL_SEPARATOR));
|
||||
if (this.useCaches != null) {
|
||||
jarResource.setUseCaches(this.useCaches);
|
||||
}
|
||||
if (jarResource.exists()) {
|
||||
result.add(jarResource);
|
||||
}
|
||||
@@ -556,7 +573,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
Set<ClassPathManifestEntry> entries = this.manifestEntriesCache;
|
||||
if (entries == null) {
|
||||
entries = getClassPathManifestEntries();
|
||||
if (this.useCaches) {
|
||||
if (this.useCaches == null || this.useCaches) {
|
||||
this.manifestEntriesCache = entries;
|
||||
}
|
||||
}
|
||||
@@ -577,7 +594,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
try {
|
||||
File jar = new File(path).getAbsoluteFile();
|
||||
if (jar.isFile() && seen.add(jar)) {
|
||||
manifestEntries.add(ClassPathManifestEntry.of(jar));
|
||||
manifestEntries.add(ClassPathManifestEntry.of(jar, this.useCaches));
|
||||
manifestEntries.addAll(getClassPathManifestEntriesFromJar(jar));
|
||||
}
|
||||
}
|
||||
@@ -616,7 +633,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
}
|
||||
File candidate = new File(parent, path);
|
||||
if (candidate.isFile() && candidate.getCanonicalPath().contains(parent.getCanonicalPath())) {
|
||||
manifestEntries.add(ClassPathManifestEntry.of(candidate));
|
||||
manifestEntries.add(ClassPathManifestEntry.of(candidate, this.useCaches));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -710,7 +727,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
if (rootDirResources == null) {
|
||||
// Lookup for specific directory, creating a cache entry for it.
|
||||
rootDirResources = getResources(rootDirPath);
|
||||
if (this.useCaches) {
|
||||
if (this.useCaches == null || this.useCaches) {
|
||||
this.rootDirCache.put(rootDirPath, rootDirResources);
|
||||
}
|
||||
}
|
||||
@@ -729,7 +746,11 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
if (resolvedUrl != null) {
|
||||
rootDirUrl = resolvedUrl;
|
||||
}
|
||||
rootDirResource = new UrlResource(rootDirUrl);
|
||||
UrlResource urlResource = new UrlResource(rootDirUrl);
|
||||
if (this.useCaches != null) {
|
||||
urlResource.setUseCaches(this.useCaches);
|
||||
}
|
||||
rootDirResource = urlResource;
|
||||
}
|
||||
if (rootDirUrl.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
|
||||
result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirUrl, subPattern, getPathMatcher()));
|
||||
@@ -865,8 +886,8 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
|
||||
if (con instanceof JarURLConnection jarCon) {
|
||||
// Should usually be the case for traditional JAR files.
|
||||
if (!this.useCaches) {
|
||||
jarCon.setUseCaches(false);
|
||||
if (this.useCaches != null) {
|
||||
jarCon.setUseCaches(this.useCaches);
|
||||
}
|
||||
try {
|
||||
jarFile = jarCon.getJarFile();
|
||||
@@ -931,7 +952,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.useCaches) {
|
||||
if (this.useCaches == null || this.useCaches) {
|
||||
// Cache jar entries in TreeSet for efficient searching on re-encounter.
|
||||
this.jarEntriesCache.put(jarFileUrl, entriesCache);
|
||||
}
|
||||
@@ -1257,10 +1278,10 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
|
||||
private static final String JARFILE_URL_PREFIX = ResourceUtils.JAR_URL_PREFIX + ResourceUtils.FILE_URL_PREFIX;
|
||||
|
||||
static ClassPathManifestEntry of(File file) throws MalformedURLException {
|
||||
static ClassPathManifestEntry of(File file, @Nullable Boolean useCaches) throws MalformedURLException {
|
||||
String path = fixPath(file.getAbsolutePath());
|
||||
Resource resource = asJarFileResource(path);
|
||||
Resource alternative = createAlternative(path);
|
||||
Resource resource = asJarFileResource(path, useCaches);
|
||||
Resource alternative = createAlternative(path, useCaches);
|
||||
return new ClassPathManifestEntry(resource, alternative);
|
||||
}
|
||||
|
||||
@@ -1281,18 +1302,22 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
* @return the alternative form or {@code null}
|
||||
*/
|
||||
@Nullable
|
||||
private static Resource createAlternative(String path) {
|
||||
private static Resource createAlternative(String path, @Nullable Boolean useCaches) {
|
||||
try {
|
||||
String alternativePath = path.startsWith("/") ? path.substring(1) : "/" + path;
|
||||
return asJarFileResource(alternativePath);
|
||||
return asJarFileResource(alternativePath, useCaches);
|
||||
}
|
||||
catch (MalformedURLException ex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private static Resource asJarFileResource(String path) throws MalformedURLException {
|
||||
return new UrlResource(JARFILE_URL_PREFIX + path + ResourceUtils.JAR_URL_SEPARATOR);
|
||||
private static Resource asJarFileResource(String path, @Nullable Boolean useCaches) throws MalformedURLException {
|
||||
UrlResource resource = new UrlResource(JARFILE_URL_PREFIX + path + ResourceUtils.JAR_URL_SEPARATOR);
|
||||
if (useCaches != null) {
|
||||
resource.setUseCaches(useCaches);
|
||||
}
|
||||
return resource;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user