Skip to content

Commit 081d0b3

Browse files
committedOct 22, 2024
Consistently sort jar entries in doFindPathMatchingJarResources
Includes consistent clearCache() behavior for manifest entries. Closes gh-33771 See gh-33705
1 parent 1c69a3c commit 081d0b3

File tree

1 file changed

+21
-22
lines changed

1 file changed

+21
-22
lines changed
 

Diff for: ‎spring-core/src/main/java/org/springframework/core/io/support/PathMatchingResourcePatternResolver.java

+21-22
Original file line numberDiff line numberDiff line change
@@ -235,9 +235,6 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
235235
private static final Predicate<ResolvedModule> isNotSystemModule =
236236
resolvedModule -> !systemModuleNames.contains(resolvedModule.name());
237237

238-
@Nullable
239-
private static Set<ClassPathManifestEntry> classPathManifestEntriesCache;
240-
241238
@Nullable
242239
private static Method equinoxResolveMethod;
243240

@@ -261,7 +258,10 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol
261258

262259
private final Map<String, Resource[]> rootDirCache = new ConcurrentHashMap<>();
263260

264-
private final Map<String, NavigableSet<String>> jarEntryCache = new ConcurrentHashMap<>();
261+
private final Map<String, NavigableSet<String>> jarEntriesCache = new ConcurrentHashMap<>();
262+
263+
@Nullable
264+
private volatile Set<ClassPathManifestEntry> manifestEntriesCache;
265265

266266

267267
/**
@@ -377,7 +377,8 @@ public Resource[] getResources(String locationPattern) throws IOException {
377377
*/
378378
public void clearCache() {
379379
this.rootDirCache.clear();
380-
this.jarEntryCache.clear();
380+
this.jarEntriesCache.clear();
381+
this.manifestEntriesCache = null;
381382
}
382383

383384

@@ -530,10 +531,10 @@ protected void addAllClassLoaderJarRoots(@Nullable ClassLoader classLoader, Set<
530531
* @since 4.3
531532
*/
532533
protected void addClassPathManifestEntries(Set<Resource> result) {
533-
Set<ClassPathManifestEntry> entries = classPathManifestEntriesCache;
534+
Set<ClassPathManifestEntry> entries = this.manifestEntriesCache;
534535
if (entries == null) {
535536
entries = getClassPathManifestEntries();
536-
classPathManifestEntriesCache = entries;
537+
this.manifestEntriesCache = entries;
537538
}
538539
for (ClassPathManifestEntry entry : entries) {
539540
if (!result.contains(entry.resource()) &&
@@ -544,7 +545,7 @@ protected void addClassPathManifestEntries(Set<Resource> result) {
544545
}
545546

546547
private Set<ClassPathManifestEntry> getClassPathManifestEntries() {
547-
Set<ClassPathManifestEntry> manifestEntries = new HashSet<>();
548+
Set<ClassPathManifestEntry> manifestEntries = new LinkedHashSet<>();
548549
Set<File> seen = new HashSet<>();
549550
try {
550551
String paths = System.getProperty("java.class.path");
@@ -578,9 +579,9 @@ private Set<ClassPathManifestEntry> getClassPathManifestEntriesFromJar(File jar)
578579
File parent = jar.getAbsoluteFile().getParentFile();
579580
try (JarFile jarFile = new JarFile(jar)) {
580581
Manifest manifest = jarFile.getManifest();
581-
Attributes attributes = (manifest != null) ? manifest.getMainAttributes() : null;
582-
String classPath = (attributes != null) ? attributes.getValue(Name.CLASS_PATH) : null;
583-
Set<ClassPathManifestEntry> manifestEntries = new HashSet<>();
582+
Attributes attributes = (manifest != null ? manifest.getMainAttributes() : null);
583+
String classPath = (attributes != null ? attributes.getValue(Name.CLASS_PATH) : null);
584+
Set<ClassPathManifestEntry> manifestEntries = new LinkedHashSet<>();
584585
if (StringUtils.hasLength(classPath)) {
585586
StringTokenizer tokenizer = new StringTokenizer(classPath);
586587
while (tokenizer.hasMoreTokens()) {
@@ -806,11 +807,11 @@ protected Set<Resource> doFindPathMatchingJarResources(Resource rootDirResource,
806807
if (separatorIndex != -1) {
807808
jarFileUrl = urlFile.substring(0, separatorIndex);
808809
rootEntryPath = urlFile.substring(separatorIndex + 2); // both separators are 2 chars
809-
NavigableSet<String> entryCache = this.jarEntryCache.get(jarFileUrl);
810-
if (entryCache != null) {
810+
NavigableSet<String> entriesCache = this.jarEntriesCache.get(jarFileUrl);
811+
if (entriesCache != null) {
811812
Set<Resource> result = new LinkedHashSet<>(64);
812813
// Search sorted entries from first entry with rootEntryPath prefix
813-
for (String entryPath : entryCache.tailSet(rootEntryPath, false)) {
814+
for (String entryPath : entriesCache.tailSet(rootEntryPath, false)) {
814815
if (!entryPath.startsWith(rootEntryPath)) {
815816
// We are beyond the potential matches in the current TreeSet.
816817
break;
@@ -870,11 +871,9 @@ protected Set<Resource> doFindPathMatchingJarResources(Resource rootDirResource,
870871
rootEntryPath = rootEntryPath + "/";
871872
}
872873
Set<Resource> result = new LinkedHashSet<>(64);
873-
NavigableSet<String> entryCache = new TreeSet<>();
874-
for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements(); ) {
875-
JarEntry entry = entries.nextElement();
876-
String entryPath = entry.getName();
877-
entryCache.add(entryPath);
874+
NavigableSet<String> entriesCache = new TreeSet<>();
875+
for (String entryPath : jarFile.stream().map(JarEntry::getName).sorted().toList()) {
876+
entriesCache.add(entryPath);
878877
if (entryPath.startsWith(rootEntryPath)) {
879878
String relativePath = entryPath.substring(rootEntryPath.length());
880879
if (getPathMatcher().match(subPattern, relativePath)) {
@@ -883,7 +882,7 @@ protected Set<Resource> doFindPathMatchingJarResources(Resource rootDirResource,
883882
}
884883
}
885884
// Cache jar entries in TreeSet for efficient searching on re-encounter.
886-
this.jarEntryCache.put(jarFileUrl, entryCache);
885+
this.jarEntriesCache.put(jarFileUrl, entriesCache);
887886
return result;
888887
}
889888
finally {
@@ -1236,9 +1235,9 @@ private static Resource createAlternative(String path) {
12361235
}
12371236
}
12381237

1239-
private static Resource asJarFileResource(String path)
1240-
throws MalformedURLException {
1238+
private static Resource asJarFileResource(String path) throws MalformedURLException {
12411239
return new UrlResource(JARFILE_URL_PREFIX + path + ResourceUtils.JAR_URL_SEPARATOR);
12421240
}
12431241
}
1242+
12441243
}

0 commit comments

Comments
 (0)