@@ -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