Package org.springframework.core.io.support

# Class PathMatchingResourcePatternResolver

java.lang.Object
org.springframework.core.io.support.PathMatchingResourcePatternResolver

All Implemented Interfaces:
  `ResourceLoader`, `ResourcePatternResolver`

public class PathMatchingResourcePatternResolver extends Object implements ResourcePatternResolver
A `ResourcePatternResolver` implementation that is able to resolve a specified resource location path into one or more matching Resources.

The source path may be a simple path which has a one-to-one mapping to a target `Resource`, or alternatively may contain the special "`classpath*:`" prefix and/or internal Ant-style path patterns (matched using Spring's `AntPathMatcher` utility). Both of the latter are effectively wildcards.

### No Wildcards

In the simple case, if the specified location path does not start with the `"classpath*:`" prefix and does not contain a `PathMatcher` pattern, this resolver will simply return a single resource via a `getResource()` call on the underlying `ResourceLoader`. Examples are real URLs such as "`file:C:/context.xml`", pseudo-URLs such as "`classpath:/context.xml`", and simple unprefixed paths such as "`/WEB-INF/context.xml`". The latter will resolve in a fashion specific to the underlying `ResourceLoader` (for example, `ServletContextResource` for a `WebApplicationContext`).

### Ant-style Patterns

When the path location contains an Ant-style pattern, for example:

     /WEB-INF/*-context.xml
     com/example/**/applicationContext.xml
     file:C:/some/path/*-context.xml
     classpath:com/example/**/applicationContext.xml

the resolver follows a more complex but defined procedure to try to resolve the wildcard. It produces a `Resource` for the path up to the last non-wildcard segment and obtains a `URL` from it. If this URL is not a "`jar:`" URL or container-specific variant (for example, "`zip:`" in WebLogic, "`wsjar`" in WebSphere", etc.), then the root directory of the filesystem associated with the URL is obtained and used to resolve the wildcards by walking the filesystem. In the case of a jar URL, the resolver either gets a `java.net.JarURLConnection` from it, or manually parses the jar URL, and then traverses the contents of the jar file, to resolve the wildcards.

### Implications on Portability

If the specified path is already a file URL (either explicitly, or implicitly because the base `ResourceLoader` is a filesystem one), then wildcarding is guaranteed to work in a completely portable fashion.

If the specified path is a class path location, then the resolver must obtain the last non-wildcard path segment URL via a `Classloader.getResource()` call. Since this is just a node of the path (not the file at the end) it is actually undefined (in the ClassLoader Javadocs) exactly what sort of URL is returned in this case. In practice, it is usually a `java.io.File` representing the directory, where the class path resource resolves to a filesystem location, or a jar URL of some sort, where the class path resource resolves to a jar location. Still, there is a portability concern on this operation.

If a jar URL is obtained for the last non-wildcard segment, the resolver must be able to get a `java.net.JarURLConnection` from it, or manually parse the jar URL, to be able to walk the contents of the jar and resolve the wildcard. This will work in most environments but will fail in others, and it is strongly recommended that the wildcard resolution of resources coming from jars be thoroughly tested in your specific environment before you rely on it.

### `classpath*:` Prefix

There is special support for retrieving multiple class path resources with the same name, via the "`classpath*:`" prefix. For example, "`classpath*:META-INF/beans.xml`" will find all "META-INF/beans.xml" files in the class path, be it in "classes" directories or in JAR files. This is particularly useful for autodetecting config files of the same name at the same location within each jar file. Internally, this happens via a `ClassLoader.getResources()` call, and is completely portable.

The "`classpath*:`" prefix can also be combined with a `PathMatcher` pattern in the rest of the location path — for example, "`classpath*:META-INF/*-beans.xml"`. In this case, the resolution strategy is fairly simple: a `ClassLoader.getResources()` call is used on the last non-wildcard path segment to get all the matching resources in the class loader hierarchy, and then off each resource the same `PathMatcher` resolution strategy described above is used for the wildcard sub pattern.

### Other Notes

As of Spring Framework 6.0, if `getResources(String)` is invoked with a location pattern using the "`classpath*:`" prefix it will first search all modules in the boot layer, excluding system modules. It will then search the class path using `ClassLoader` APIs as described previously and return the combined results. Consequently, some of the limitations of class path searches may not apply when applications are deployed as modules.

WARNING: Note that "`classpath*:`" when combined with Ant-style patterns will only work reliably with at least one root directory before the pattern starts, unless the actual target files reside in the file system. This means that a pattern like "`classpath*:*.xml`" will not retrieve files from the root of jar files but rather only from the root of expanded directories. This originates from a limitation in the JDK's `ClassLoader.getResources()` method which only returns file system locations for a passed-in empty String (indicating potential roots to search). This `ResourcePatternResolver` implementation tries to mitigate the jar root lookup limitation through `URLClassLoader` introspection and "`java.class.path`" manifest evaluation; however, without portability guarantees.

WARNING: Ant-style patterns with "`classpath:`" resources are not guaranteed to find matching resources if the base package to search is available in multiple class path locations. This is because a resource such as

       com/example/package1/service-context.xml

may exist in only one class path location, but when a location pattern such as

       classpath:com/example/**/service-context.xml

is used to try to resolve it, the resolver will work off the (first) URL returned by `getResource("com/example")`. If the `com/example` base package node exists in multiple class path locations, the actual desired resource may not be present under the `com/example` base package in the first URL. Therefore, preferably, use "`classpath*:`" with the same Ant-style pattern in such a case, which will search all class path locations that contain the base package.

Since:
  1.0.2
Author:
  Juergen Hoeller, Colin Sampaleanu, Marius Bogoevici, Costin Leau, Phillip Webb, Sam Brannen, Sebastien Deleuze, Dave Syer
See Also:
  - `ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX`
  - `AntPathMatcher`
  - `ResourceLoader.getResource(String)`
  - `ClassLoader.getResources(String)`

## Field Summary

### Fields inherited from interface org.springframework.core.io.ResourceLoader

`CLASSPATH_URL_PREFIX`

### Fields inherited from interface org.springframework.core.io.support.ResourcePatternResolver

`CLASSPATH_ALL_URL_PREFIX`

## Constructor Summary

Constructors
Constructor
Description
`PathMatchingResourcePatternResolver()`
Create a `PathMatchingResourcePatternResolver` with a `DefaultResourceLoader`.
`PathMatchingResourcePatternResolver(ClassLoader classLoader)`
Create a `PathMatchingResourcePatternResolver` with a `DefaultResourceLoader` and the supplied `ClassLoader`.
`PathMatchingResourcePatternResolver(ResourceLoader resourceLoader)`
Create a `PathMatchingResourcePatternResolver` with the supplied `ResourceLoader`.

## Method Summary

Modifier and Type
Method
Description
`protected void`
`addAllClassLoaderJarRoots(ClassLoader classLoader, Set<Resource> result)`
Search all `URLClassLoader` URLs for jar file references and add each to the given set of resources in the form of a pointer to the root of the jar file content.
`protected void`
`addClassPathManifestEntries(Set<Resource> result)`
Determine jar file references from `Class-Path` manifest entries (which are added to the `java.class.path` JVM system property by the system class loader) and add each to the given set of resources in the form of a pointer to the root of the jar file content.
`void`
`clearCache()`
Clear the local resource cache, removing all cached classpath/jar structures.
`protected Resource`
`convertClassLoaderURL(URL url)`
Convert the given URL as returned from the configured `ClassLoader` into a `Resource`, applying to path lookups without a pattern (see `findAllClassPathResources(java.lang.String)`).
`protected String`
`determineRootDir(String location)`
Determine the root directory for the given location.
`protected Set<Resource>`
`doFindAllClassPathResources(String path)`
Find all class path resources with the given path via the configured `ClassLoader`.
`protected Set<Resource>`
`doFindPathMatchingFileResources(Resource rootDirResource, String subPattern)`
Find all resources in the file system of the supplied root directory that match the given location sub pattern via the Ant-style `PathMatcher`.
`protected Set<Resource>`
`doFindPathMatchingJarResources(Resource rootDirResource, URL rootDirUrl, String subPattern)`
Find all resources in jar files that match the given location pattern via the Ant-style `PathMatcher`.
`protected Resource[]`
`findAllClassPathResources(String location)`
Find all class location resources with the given location via the ClassLoader.
`protected Set<Resource>`
`findAllModulePathResources(String locationPattern)`
Resolve the given location pattern into `Resource` objects for all matching resources found in the module path.
`protected Resource[]`
`findPathMatchingResources(String locationPattern)`
Find all resources that match the given location pattern via the Ant-style `PathMatcher`.
`ClassLoader`
`getClassLoader()`
Expose the `ClassLoader` used by this `ResourceLoader`.
`protected JarFile`
`getJarFile(String jarFileUrl)`
Resolve the given jar file URL into a JarFile object.
`PathMatcher`
`getPathMatcher()`
Return the `PathMatcher` that this resource pattern resolver uses.
`Resource`
`getResource(String location)`
Return a `Resource` handle for the specified resource location.
`ResourceLoader`
`getResourceLoader()`
Return the `ResourceLoader` that this pattern resolver works with.
`Resource[]`
`getResources(String locationPattern)`
Resolve the given location pattern into `Resource` objects.
`protected boolean`
`isJarResource(Resource resource)`
Determine if the given resource handle indicates a jar resource that the `doFindPathMatchingJarResources(org.springframework.core.io.Resource, java.net.URL, java.lang.String)` method can handle.
`protected Resource`
`resolveRootDirResource(Resource original)`
Resolve the supplied root directory resource for path matching.
`void`
`setPathMatcher(PathMatcher pathMatcher)`
Set the `PathMatcher` implementation to use for this resource pattern resolver.
`void`
`setUseCaches(boolean useCaches)`
Specify whether this resolver should use jar caches.

### Methods inherited from class java.lang.Object

`clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait`

## Constructor Details

### PathMatchingResourcePatternResolver

public PathMatchingResourcePatternResolver()
Create a `PathMatchingResourcePatternResolver` with a `DefaultResourceLoader`.

ClassLoader access will happen via the thread context class loader.

See Also:
  - `DefaultResourceLoader`

### PathMatchingResourcePatternResolver

public PathMatchingResourcePatternResolver(ResourceLoader resourceLoader)
Create a `PathMatchingResourcePatternResolver` with the supplied `ResourceLoader`.

ClassLoader access will happen via the thread context class loader.

Parameters:
  `resourceLoader` - the `ResourceLoader` to load root directories and actual resources with

### PathMatchingResourcePatternResolver

public PathMatchingResourcePatternResolver(@Nullable ClassLoader classLoader)
Create a `PathMatchingResourcePatternResolver` with a `DefaultResourceLoader` and the supplied `ClassLoader`.

Parameters:
  `classLoader` - the ClassLoader to load class path resources with, or `null` for using the thread context class loader at the time of actual resource access
See Also:
  - `DefaultResourceLoader`

## Method Details

### getResourceLoader

public ResourceLoader getResourceLoader()
Return the `ResourceLoader` that this pattern resolver works with.

### getClassLoader

@Nullable public ClassLoader getClassLoader()
Description copied from interface: `ResourceLoader`
Expose the `ClassLoader` used by this `ResourceLoader`.

Clients which need to access the `ClassLoader` directly can do so in a uniform manner with the `ResourceLoader`, rather than relying on the thread context `ClassLoader`.

Specified by:
  `getClassLoader` in interface `ResourceLoader`
Returns:
  the `ClassLoader` (only `null` if even the system `ClassLoader` isn't accessible)
See Also:
  - `ClassUtils.getDefaultClassLoader()`
  - `ClassUtils.forName(String, ClassLoader)`

### setPathMatcher

public void setPathMatcher(PathMatcher pathMatcher)
Set the `PathMatcher` implementation to use for this resource pattern resolver.

Default is `AntPathMatcher`.

See Also:
  - `AntPathMatcher`

### getPathMatcher

public PathMatcher getPathMatcher()
Return the `PathMatcher` that this resource pattern resolver uses.

### setUseCaches

public void setUseCaches(boolean useCaches)
Specify whether this resolver should use jar caches. Default is `true`.

Switch this flag to `false` in order to avoid any jar caching, at the `JarURLConnection` level as well as within this resolver instance.

Note that `URLConnection.setDefaultUseCaches(boolean)` can be turned off independently. This resolver-level setting is designed to only enforce `JarURLConnection#setUseCaches(false)` if necessary but otherwise leaves the JVM-level default in place.

Since:
  6.1.19
See Also:
  - `URLConnection.setUseCaches(boolean)`
  - `clearCache()`

### getResource

public Resource getResource(String location)
Description copied from interface: `ResourceLoader`
Return a `Resource` handle for the specified resource location.

The handle should always be a reusable resource descriptor, allowing for multiple `InputStreamSource.getInputStream()` calls.

- Must support fully qualified URLs, for example, "file:C:/test.dat".
- Must support classpath pseudo-URLs, for example, "classpath:test.dat".
- Should support relative file paths, for example, "WEB-INF/test.dat". (This will be implementation-specific, typically provided by an ApplicationContext implementation.)

Note that a `Resource` handle does not imply an existing resource; you need to invoke `Resource.exists()` to check for existence.

Specified by:
  `getResource` in interface `ResourceLoader`
Parameters:
  `location` - the resource location
Returns:
  a corresponding `Resource` handle (never `null`)
See Also:
  - `ResourceLoader.CLASSPATH_URL_PREFIX`
  - `Resource.exists()`
  - `InputStreamSource.getInputStream()`

### getResources

public Resource[] getResources(String locationPattern) throws IOException
Description copied from interface: `ResourcePatternResolver`
Resolve the given location pattern into `Resource` objects.

Overlapping resource entries that point to the same physical resource should be avoided, as far as possible. The result should have set semantics.

Specified by:
  `getResources` in interface `ResourcePatternResolver`
Parameters:
  `locationPattern` - the location pattern to resolve
Returns:
  the corresponding `Resource` objects
Throws:
  `IOException` - in case of I/O errors

### clearCache

public void clearCache()
Clear the local resource cache, removing all cached classpath/jar structures.

Since:
  6.2

### findAllClassPathResources

protected Resource[] findAllClassPathResources(String location) throws IOException
Find all class location resources with the given location via the ClassLoader.

Delegates to `doFindAllClassPathResources(String)`.

Parameters:
  `location` - the absolute path within the class path
Returns:
  the result as Resource array
Throws:
  `IOException` - in case of I/O errors
See Also:
  - `ClassLoader.getResources(java.lang.String)`
  - `convertClassLoaderURL(java.net.URL)`

### doFindAllClassPathResources

protected Set<Resource> doFindAllClassPathResources(String path) throws IOException
Find all class path resources with the given path via the configured `ClassLoader`.

Called by `findAllClassPathResources(String)`.

Parameters:
  `path` - the absolute path within the class path (never a leading slash)
Returns:
  a mutable Set of matching Resource instances
Throws:
  `IOException`
Since:
  4.1.1

### convertClassLoaderURL

protected Resource convertClassLoaderURL(URL url)
Convert the given URL as returned from the configured `ClassLoader` into a `Resource`, applying to path lookups without a pattern (see `findAllClassPathResources(java.lang.String)`).

As of 6.0.5, the default implementation creates a `FileSystemResource` in case of the "file" protocol or a `UrlResource` otherwise, matching the outcome of pattern-based class path traversal in the same resource layout, as well as matching the outcome of module path searches.

Parameters:
  `url` - a URL as returned from the configured ClassLoader
Returns:
  the corresponding Resource object
See Also:
  - `ClassLoader.getResources(java.lang.String)`
  - `doFindAllClassPathResources(java.lang.String)`
  - `doFindPathMatchingFileResources(org.springframework.core.io.Resource, java.lang.String)`

### addAllClassLoaderJarRoots

protected void addAllClassLoaderJarRoots(@Nullable ClassLoader classLoader, Set<Resource> result)
Search all `URLClassLoader` URLs for jar file references and add each to the given set of resources in the form of a pointer to the root of the jar file content.

Parameters:
  `classLoader` - the ClassLoader to search (including its ancestors)
  `result` - the set of resources to add jar roots to
Since:
  4.1.1

### addClassPathManifestEntries

protected void addClassPathManifestEntries(Set<Resource> result)
Determine jar file references from `Class-Path` manifest entries (which are added to the `java.class.path` JVM system property by the system class loader) and add each to the given set of resources in the form of a pointer to the root of the jar file content.

Parameters:
  `result` - the set of resources to add jar roots to
Since:
  4.3

### findPathMatchingResources

protected Resource[] findPathMatchingResources(String locationPattern) throws IOException
Find all resources that match the given location pattern via the Ant-style `PathMatcher`.

Supports resources in OSGi bundles, JBoss VFS, jar files, zip files, and file systems.

Parameters:
  `locationPattern` - the location pattern to match
Returns:
  the result as Resource array
Throws:
  `IOException` - in case of I/O errors
See Also:
  - `determineRootDir(String)`
  - `resolveRootDirResource(Resource)`
  - `isJarResource(Resource)`
  - `doFindPathMatchingJarResources(Resource, URL, String)`
  - `doFindPathMatchingFileResources(Resource, String)`
  - `PathMatcher`

### determineRootDir

protected String determineRootDir(String location)
Determine the root directory for the given location.

Used for determining the starting point for file matching, resolving the root directory location to be passed into `getResources(String)`, with the remainder of the location to be used as the sub pattern.

Will return "/WEB-INF/" for the location "/WEB-INF/*.xml", for example.

Parameters:
  `location` - the location to check
Returns:
  the part of the location that denotes the root directory
See Also:
  - `findPathMatchingResources(String)`

### resolveRootDirResource

protected Resource resolveRootDirResource(Resource original) throws IOException
Resolve the supplied root directory resource for path matching.

By default, `findPathMatchingResources(String)` resolves Equinox OSGi "bundleresource:" and "bundleentry:" URLs into standard jar file URLs that will be traversed using Spring's standard jar file traversal algorithm.

For any custom resolution, override this template method and replace the supplied resource handle accordingly.

The default implementation of this method returns the supplied resource unmodified.

Parameters:
  `original` - the resource to resolve
Returns:
  the resolved resource (may be identical to the supplied resource)
Throws:
  `IOException` - in case of resolution failure
See Also:
  - `findPathMatchingResources(String)`

### isJarResource

protected boolean isJarResource(Resource resource) throws IOException
Determine if the given resource handle indicates a jar resource that the `doFindPathMatchingJarResources(org.springframework.core.io.Resource, java.net.URL, java.lang.String)` method can handle.

`findPathMatchingResources(String)` delegates to `ResourceUtils.isJarURL(URL)` to determine whether the given URL points to a resource in a jar file, and only invokes this method as a fallback.

This template method therefore allows for detecting further kinds of jar-like resources — for example, via `instanceof` checks on the resource handle type.

The default implementation of this method returns `false`.

Parameters:
  `resource` - the resource handle to check (usually the root directory to start path matching from)
Returns:
  `true` if the given resource handle indicates a jar resource
Throws:
  `IOException` - in case of I/O errors
See Also:
  - `findPathMatchingResources(String)`
  - `doFindPathMatchingJarResources(Resource, URL, String)`
  - `ResourceUtils.isJarURL(java.net.URL)`

### doFindPathMatchingJarResources

protected Set<Resource> doFindPathMatchingJarResources(Resource rootDirResource, URL rootDirUrl, String subPattern) throws IOException
Find all resources in jar files that match the given location pattern via the Ant-style `PathMatcher`.

Parameters:
  `rootDirResource` - the root directory as Resource
  `rootDirUrl` - the pre-resolved root directory URL
  `subPattern` - the sub pattern to match (below the root directory)
Returns:
  a mutable Set of matching Resource instances
Throws:
  `IOException` - in case of I/O errors
Since:
  4.3
See Also:
  - `JarURLConnection`
  - `PathMatcher`

### getJarFile

protected JarFile getJarFile(String jarFileUrl) throws IOException
Resolve the given jar file URL into a JarFile object.

Throws:
  `IOException`

### doFindPathMatchingFileResources

protected Set<Resource> doFindPathMatchingFileResources(Resource rootDirResource, String subPattern) throws IOException
Find all resources in the file system of the supplied root directory that match the given location sub pattern via the Ant-style `PathMatcher`.

Parameters:
  `rootDirResource` - the root directory as a Resource
  `subPattern` - the sub pattern to match (below the root directory)
Returns:
  a mutable Set of matching Resource instances
Throws:
  `IOException` - in case of I/O errors
See Also:
  - `PathMatcher`

### findAllModulePathResources

protected Set<Resource> findAllModulePathResources(String locationPattern) throws IOException
Resolve the given location pattern into `Resource` objects for all matching resources found in the module path.

The location pattern may be an explicit resource path such as `"com/example/config.xml"` or a pattern such as `"com/example/**/config-*.xml"` to be matched using the configured `PathMatcher`.

The default implementation scans all modules in the boot layer, excluding system modules.

Parameters:
  `locationPattern` - the location pattern to resolve
Returns:
  a modifiable `Set` containing the corresponding `Resource` objects
Throws:
  `IOException` - in case of I/O errors
Since:
  6.0
See Also:
  - `ModuleLayer.boot()`
  - `ModuleFinder.ofSystem()`
  - `ModuleReader`
  - `PathMatcher.match(String, String)`