PathMatchingResourcePatternResolver reuses resolved root dir URL

Issue: SPR-14202
This commit is contained in:
Juergen Hoeller 2016-04-26 17:05:39 +02:00
parent f73df2e138
commit 65a8f5ed64
1 changed files with 53 additions and 23 deletions

View File

@ -462,11 +462,18 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
Set<Resource> result = new LinkedHashSet<Resource>(16); Set<Resource> result = new LinkedHashSet<Resource>(16);
for (Resource rootDirResource : rootDirResources) { for (Resource rootDirResource : rootDirResources) {
rootDirResource = resolveRootDirResource(rootDirResource); rootDirResource = resolveRootDirResource(rootDirResource);
if (rootDirResource.getURL().getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) { URL rootDirURL = rootDirResource.getURL();
result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirResource, subPattern, getPathMatcher())); if (equinoxResolveMethod != null) {
if (rootDirURL.getProtocol().startsWith("bundle")) {
rootDirURL = (URL) ReflectionUtils.invokeMethod(equinoxResolveMethod, null, rootDirURL);
rootDirResource = new UrlResource(rootDirURL);
}
} }
else if (isJarResource(rootDirResource)) { if (rootDirURL.getProtocol().startsWith(ResourceUtils.URL_PROTOCOL_VFS)) {
result.addAll(doFindPathMatchingJarResources(rootDirResource, subPattern)); result.addAll(VfsResourceMatchingDelegate.findMatchingResources(rootDirURL, subPattern, getPathMatcher()));
}
else if (ResourceUtils.isJarURL(rootDirURL) || isJarResource(rootDirResource)) {
result.addAll(doFindPathMatchingJarResources(rootDirResource, rootDirURL, subPattern));
} }
else { else {
result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern)); result.addAll(doFindPathMatchingFileResources(rootDirResource, subPattern));
@ -504,52 +511,57 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
/** /**
* Resolve the specified resource for path matching. * Resolve the specified resource for path matching.
* <p>The default implementation detects an Equinox OSGi "bundleresource:" * <p>By default, Equinox OSGi "bundleresource:" / "bundleentry:" URL will be
* / "bundleentry:" URL and resolves it into a standard jar file URL that * resolved into a standard jar file URL that be traversed using Spring's
* can be traversed using Spring's standard jar file traversal algorithm. * standard jar file traversal algorithm. For any preceding custom resolution,
* override this method and replace the resource handle accordingly.
* @param original the resource to resolve * @param original the resource to resolve
* @return the resolved resource (may be identical to the passed-in resource) * @return the resolved resource (may be identical to the passed-in resource)
* @throws IOException in case of resolution failure * @throws IOException in case of resolution failure
*/ */
protected Resource resolveRootDirResource(Resource original) throws IOException { protected Resource resolveRootDirResource(Resource original) throws IOException {
if (equinoxResolveMethod != null) {
URL url = original.getURL();
if (url.getProtocol().startsWith("bundle")) {
return new UrlResource((URL) ReflectionUtils.invokeMethod(equinoxResolveMethod, null, url));
}
}
return original; return original;
} }
/** /**
* Return whether the given resource handle indicates a jar resource * Return whether the given resource handle indicates a jar resource
* that the {@code doFindPathMatchingJarResources} method can handle. * that the {@code doFindPathMatchingJarResources} method can handle.
* <p>The default implementation checks against the URL protocols * <p>By default, the URL protocols "jar", "zip", "vfszip and "wsjar"
* "jar", "zip" and "wsjar" (the latter are used by BEA WebLogic Server * will be treated as jar resources. This template method allows for
* and IBM WebSphere, respectively, but can be treated like jar files). * detecting further kinds of jar-like resources, e.g. through
* {@code instanceof} checks on the resource handle type.
* @param resource the resource handle to check * @param resource the resource handle to check
* (usually the root directory to start path matching from) * (usually the root directory to start path matching from)
* @see #doFindPathMatchingJarResources * @see #doFindPathMatchingJarResources
* @see org.springframework.util.ResourceUtils#isJarURL * @see org.springframework.util.ResourceUtils#isJarURL
*/ */
protected boolean isJarResource(Resource resource) throws IOException { protected boolean isJarResource(Resource resource) throws IOException {
return ResourceUtils.isJarURL(resource.getURL()); return false;
} }
/** /**
* Find all resources in jar files that match the given location pattern * Find all resources in jar files that match the given location pattern
* via the Ant-style PathMatcher. * via the Ant-style PathMatcher.
* @param rootDirResource the root directory as Resource * @param rootDirResource the root directory as Resource
* @param rootDirURL the pre-resolved root directory URL
* @param subPattern the sub pattern to match (below the root directory) * @param subPattern the sub pattern to match (below the root directory)
* @return a mutable Set of matching Resource instances * @return a mutable Set of matching Resource instances
* @throws IOException in case of I/O errors * @throws IOException in case of I/O errors
* @since 4.3
* @see java.net.JarURLConnection * @see java.net.JarURLConnection
* @see org.springframework.util.PathMatcher * @see org.springframework.util.PathMatcher
*/ */
protected Set<Resource> doFindPathMatchingJarResources(Resource rootDirResource, String subPattern) @SuppressWarnings("deprecation")
protected Set<Resource> doFindPathMatchingJarResources(Resource rootDirResource, URL rootDirURL, String subPattern)
throws IOException { throws IOException {
URLConnection con = rootDirResource.getURL().openConnection(); // Check deprecated variant for potential overriding first...
Set<Resource> result = doFindPathMatchingJarResources(rootDirResource, subPattern);
if (result != null) {
return result;
}
URLConnection con = rootDirURL.openConnection();
JarFile jarFile; JarFile jarFile;
String jarFileUrl; String jarFileUrl;
String rootEntryPath; String rootEntryPath;
@ -570,7 +582,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
// We'll assume URLs of the format "jar:path!/entry", with the protocol // We'll assume URLs of the format "jar:path!/entry", with the protocol
// being arbitrary as long as following the entry format. // being arbitrary as long as following the entry format.
// We'll also handle paths with and without leading "file:" prefix. // We'll also handle paths with and without leading "file:" prefix.
String urlFile = rootDirResource.getURL().getFile(); String urlFile = rootDirURL.getFile();
try { try {
int separatorIndex = urlFile.indexOf(ResourceUtils.JAR_URL_SEPARATOR); int separatorIndex = urlFile.indexOf(ResourceUtils.JAR_URL_SEPARATOR);
if (separatorIndex != -1) { if (separatorIndex != -1) {
@ -602,7 +614,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
// The Sun JRE does not return a slash here, but BEA JRockit does. // The Sun JRE does not return a slash here, but BEA JRockit does.
rootEntryPath = rootEntryPath + "/"; rootEntryPath = rootEntryPath + "/";
} }
Set<Resource> result = new LinkedHashSet<Resource>(8); result = new LinkedHashSet<Resource>(8);
for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements();) { for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements();) {
JarEntry entry = entries.nextElement(); JarEntry entry = entries.nextElement();
String entryPath = entry.getName(); String entryPath = entry.getName();
@ -622,6 +634,23 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
} }
} }
/**
* Find all resources in jar files that match the given location pattern
* via the Ant-style PathMatcher.
* @param rootDirResource the root directory as Resource
* @param subPattern the sub pattern to match (below the root directory)
* @return a mutable Set of matching Resource instances
* @throws IOException in case of I/O errors
* @deprecated as of Spring 4.3, in favor of
* {@link #doFindPathMatchingJarResources(Resource, URL, String)}
*/
@Deprecated
protected Set<Resource> doFindPathMatchingJarResources(Resource rootDirResource, String subPattern)
throws IOException {
return null;
}
/** /**
* Resolve the given jar file URL into a JarFile object. * Resolve the given jar file URL into a JarFile object.
*/ */
@ -778,8 +807,9 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
private static class VfsResourceMatchingDelegate { private static class VfsResourceMatchingDelegate {
public static Set<Resource> findMatchingResources( public static Set<Resource> findMatchingResources(
Resource rootResource, String locationPattern, PathMatcher pathMatcher) throws IOException { URL rootDirURL, String locationPattern, PathMatcher pathMatcher) throws IOException {
Object root = VfsPatternUtils.findRoot(rootResource.getURL());
Object root = VfsPatternUtils.findRoot(rootDirURL);
PatternVirtualFileVisitor visitor = PatternVirtualFileVisitor visitor =
new PatternVirtualFileVisitor(VfsPatternUtils.getPath(root), locationPattern, pathMatcher); new PatternVirtualFileVisitor(VfsPatternUtils.getPath(root), locationPattern, pathMatcher);
VfsPatternUtils.visit(root, visitor); VfsPatternUtils.visit(root, visitor);