mirror of
https://github.com/spring-projects/spring-framework.git
synced 2024-10-23 07:05:25 +08:00
Consistently sort jar entries in doFindPathMatchingJarResources
Includes consistent clearCache() behavior for manifest entries. Closes gh-33771 See gh-33705
This commit is contained in:
parent
1c69a3c521
commit
081d0b33d4
@ -235,9 +235,6 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
private static final Predicate<ResolvedModule> isNotSystemModule =
|
||||
resolvedModule -> !systemModuleNames.contains(resolvedModule.name());
|
||||
|
||||
@Nullable
|
||||
private static Set<ClassPathManifestEntry> classPathManifestEntriesCache;
|
||||
|
||||
@Nullable
|
||||
private static Method equinoxResolveMethod;
|
||||
|
||||
@ -261,7 +258,10 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
|
||||
private final Map<String, Resource[]> rootDirCache = new ConcurrentHashMap<>();
|
||||
|
||||
private final Map<String, NavigableSet<String>> jarEntryCache = new ConcurrentHashMap<>();
|
||||
private final Map<String, NavigableSet<String>> jarEntriesCache = new ConcurrentHashMap<>();
|
||||
|
||||
@Nullable
|
||||
private volatile Set<ClassPathManifestEntry> manifestEntriesCache;
|
||||
|
||||
|
||||
/**
|
||||
@ -377,7 +377,8 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
*/
|
||||
public void clearCache() {
|
||||
this.rootDirCache.clear();
|
||||
this.jarEntryCache.clear();
|
||||
this.jarEntriesCache.clear();
|
||||
this.manifestEntriesCache = null;
|
||||
}
|
||||
|
||||
|
||||
@ -530,10 +531,10 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
* @since 4.3
|
||||
*/
|
||||
protected void addClassPathManifestEntries(Set<Resource> result) {
|
||||
Set<ClassPathManifestEntry> entries = classPathManifestEntriesCache;
|
||||
Set<ClassPathManifestEntry> entries = this.manifestEntriesCache;
|
||||
if (entries == null) {
|
||||
entries = getClassPathManifestEntries();
|
||||
classPathManifestEntriesCache = entries;
|
||||
this.manifestEntriesCache = entries;
|
||||
}
|
||||
for (ClassPathManifestEntry entry : entries) {
|
||||
if (!result.contains(entry.resource()) &&
|
||||
@ -544,7 +545,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
}
|
||||
|
||||
private Set<ClassPathManifestEntry> getClassPathManifestEntries() {
|
||||
Set<ClassPathManifestEntry> manifestEntries = new HashSet<>();
|
||||
Set<ClassPathManifestEntry> manifestEntries = new LinkedHashSet<>();
|
||||
Set<File> seen = new HashSet<>();
|
||||
try {
|
||||
String paths = System.getProperty("java.class.path");
|
||||
@ -578,9 +579,9 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
File parent = jar.getAbsoluteFile().getParentFile();
|
||||
try (JarFile jarFile = new JarFile(jar)) {
|
||||
Manifest manifest = jarFile.getManifest();
|
||||
Attributes attributes = (manifest != null) ? manifest.getMainAttributes() : null;
|
||||
String classPath = (attributes != null) ? attributes.getValue(Name.CLASS_PATH) : null;
|
||||
Set<ClassPathManifestEntry> manifestEntries = new HashSet<>();
|
||||
Attributes attributes = (manifest != null ? manifest.getMainAttributes() : null);
|
||||
String classPath = (attributes != null ? attributes.getValue(Name.CLASS_PATH) : null);
|
||||
Set<ClassPathManifestEntry> manifestEntries = new LinkedHashSet<>();
|
||||
if (StringUtils.hasLength(classPath)) {
|
||||
StringTokenizer tokenizer = new StringTokenizer(classPath);
|
||||
while (tokenizer.hasMoreTokens()) {
|
||||
@ -806,11 +807,11 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
if (separatorIndex != -1) {
|
||||
jarFileUrl = urlFile.substring(0, separatorIndex);
|
||||
rootEntryPath = urlFile.substring(separatorIndex + 2); // both separators are 2 chars
|
||||
NavigableSet<String> entryCache = this.jarEntryCache.get(jarFileUrl);
|
||||
if (entryCache != null) {
|
||||
NavigableSet<String> entriesCache = this.jarEntriesCache.get(jarFileUrl);
|
||||
if (entriesCache != null) {
|
||||
Set<Resource> result = new LinkedHashSet<>(64);
|
||||
// Search sorted entries from first entry with rootEntryPath prefix
|
||||
for (String entryPath : entryCache.tailSet(rootEntryPath, false)) {
|
||||
for (String entryPath : entriesCache.tailSet(rootEntryPath, false)) {
|
||||
if (!entryPath.startsWith(rootEntryPath)) {
|
||||
// We are beyond the potential matches in the current TreeSet.
|
||||
break;
|
||||
@ -870,11 +871,9 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
rootEntryPath = rootEntryPath + "/";
|
||||
}
|
||||
Set<Resource> result = new LinkedHashSet<>(64);
|
||||
NavigableSet<String> entryCache = new TreeSet<>();
|
||||
for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements(); ) {
|
||||
JarEntry entry = entries.nextElement();
|
||||
String entryPath = entry.getName();
|
||||
entryCache.add(entryPath);
|
||||
NavigableSet<String> entriesCache = new TreeSet<>();
|
||||
for (String entryPath : jarFile.stream().map(JarEntry::getName).sorted().toList()) {
|
||||
entriesCache.add(entryPath);
|
||||
if (entryPath.startsWith(rootEntryPath)) {
|
||||
String relativePath = entryPath.substring(rootEntryPath.length());
|
||||
if (getPathMatcher().match(subPattern, relativePath)) {
|
||||
@ -883,7 +882,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
}
|
||||
}
|
||||
// Cache jar entries in TreeSet for efficient searching on re-encounter.
|
||||
this.jarEntryCache.put(jarFileUrl, entryCache);
|
||||
this.jarEntriesCache.put(jarFileUrl, entriesCache);
|
||||
return result;
|
||||
}
|
||||
finally {
|
||||
@ -1236,9 +1235,9 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
|
||||
}
|
||||
}
|
||||
|
||||
private static Resource asJarFileResource(String path)
|
||||
throws MalformedURLException {
|
||||
private static Resource asJarFileResource(String path) throws MalformedURLException {
|
||||
return new UrlResource(JARFILE_URL_PREFIX + path + ResourceUtils.JAR_URL_SEPARATOR);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user