PathMatchingResourcePatternResolver evaluates classpath manifest entries as well
Issue: SPR-13685
This commit is contained in:
parent
2cfe00ce32
commit
08748ecaa4
|
@ -144,6 +144,9 @@ import org.springframework.util.StringUtils;
|
|||
* root of expanded directories. This originates from a limitation in the JDK's
|
||||
* {@code ClassLoader.getResources()} method which only returns file system
|
||||
* locations for a passed-in empty String (indicating potential roots to search).
|
||||
* This {@code ResourcePatternResolver} implementation is trying to mitigate the
|
||||
* jar root lookup limitation through {@link URLClassLoader} introspection and
|
||||
* "java.class.path" manifest evaluation; however, without portability guarantees.
|
||||
*
|
||||
* <p><b>WARNING:</b> Ant-style patterns with "classpath:" resources are not
|
||||
* guaranteed to find matching resources if the root package to search is available
|
||||
|
@ -156,9 +159,9 @@ import org.springframework.util.StringUtils;
|
|||
* classpath:com/mycompany/**/service-context.xml
|
||||
* </pre>
|
||||
* is used to try to resolve it, the resolver will work off the (first) URL
|
||||
* returned by {@code getResource("com/mycompany");}. If this base package
|
||||
* node exists in multiple classloader locations, the actual end resource may
|
||||
* not be underneath. Therefore, preferably, use "{@code classpath*:}" with the same
|
||||
* returned by {@code getResource("com/mycompany");}. If this base package node
|
||||
* exists in multiple classloader locations, the actual end resource may not be
|
||||
* underneath. Therefore, preferably, use "{@code classpath*:}" with the same
|
||||
* Ant-style pattern in such a case, which will search <i>all</i> class path
|
||||
* locations that contain the root package.
|
||||
*
|
||||
|
@ -166,6 +169,7 @@ import org.springframework.util.StringUtils;
|
|||
* @author Colin Sampaleanu
|
||||
* @author Marius Bogoevici
|
||||
* @author Costin Leau
|
||||
* @author Phil Webb
|
||||
* @since 1.0.2
|
||||
* @see #CLASSPATH_ALL_URL_PREFIX
|
||||
* @see org.springframework.util.AntPathMatcher
|
||||
|
@ -316,6 +320,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
|||
* Called by {@link #findAllClassPathResources(String)}.
|
||||
* @param path the absolute path within the classpath (never a leading slash)
|
||||
* @return a mutable Set of matching Resource instances
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected Set<Resource> doFindAllClassPathResources(String path) throws IOException {
|
||||
Set<Resource> result = new LinkedHashSet<Resource>(16);
|
||||
|
@ -350,6 +355,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
|||
* given set of resources in the form of pointers to the root of the jar file content.
|
||||
* @param classLoader the ClassLoader to search (including its ancestors)
|
||||
* @param result the set of resources to add jar roots to
|
||||
* @since 4.1.1
|
||||
*/
|
||||
protected void addAllClassLoaderJarRoots(ClassLoader classLoader, Set<Resource> result) {
|
||||
if (classLoader instanceof URLClassLoader) {
|
||||
|
@ -379,8 +385,15 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (classLoader == ClassLoader.getSystemClassLoader()) {
|
||||
// "java.class.path" manifest evaluation...
|
||||
addClassPathManifestEntries(result);
|
||||
}
|
||||
|
||||
if (classLoader != null) {
|
||||
try {
|
||||
// Hierarchy traversal...
|
||||
addAllClassLoaderJarRoots(classLoader.getParent(), result);
|
||||
}
|
||||
catch (Exception ex) {
|
||||
|
@ -392,6 +405,41 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine jar file references from the "java.class.path." manifest property and add them
|
||||
* to the given set of resources in the form of pointers to the root of the jar file content.
|
||||
* @param result the set of resources to add jar roots to
|
||||
* @since 4.3
|
||||
*/
|
||||
protected void addClassPathManifestEntries(Set<Resource> result) {
|
||||
try {
|
||||
String javaClassPathProperty = System.getProperty("java.class.path");
|
||||
for (String url : StringUtils.delimitedListToStringArray(
|
||||
javaClassPathProperty, System.getProperty("path.separator"))) {
|
||||
try {
|
||||
if (url.endsWith(ResourceUtils.JAR_FILE_EXTENSION)) {
|
||||
UrlResource jarResource = new UrlResource(ResourceUtils.JAR_URL_PREFIX +
|
||||
ResourceUtils.FILE_URL_PREFIX + url + ResourceUtils.JAR_URL_SEPARATOR);
|
||||
if (jarResource.exists()) {
|
||||
result.add(jarResource);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (MalformedURLException ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Cannot search for matching files underneath [" + url +
|
||||
"] because it cannot be converted to a valid 'jar:' URL: " + ex.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Failed to evaluate 'java.class.path' manifest entries: " + ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find all resources that match the given location pattern via the
|
||||
* Ant-style PathMatcher. Supports resources in jar files and zip files
|
||||
|
|
Loading…
Reference in New Issue