|
|
|
@ -235,9 +235,6 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol |
|
|
|
private static final Predicate<ResolvedModule> isNotSystemModule = |
|
|
|
private static final Predicate<ResolvedModule> isNotSystemModule = |
|
|
|
resolvedModule -> !systemModuleNames.contains(resolvedModule.name()); |
|
|
|
resolvedModule -> !systemModuleNames.contains(resolvedModule.name()); |
|
|
|
|
|
|
|
|
|
|
|
@Nullable |
|
|
|
|
|
|
|
private static Set<ClassPathManifestEntry> classPathManifestEntriesCache; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@Nullable |
|
|
|
@Nullable |
|
|
|
private static Method equinoxResolveMethod; |
|
|
|
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, 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() { |
|
|
|
public void clearCache() { |
|
|
|
this.rootDirCache.clear(); |
|
|
|
this.rootDirCache.clear(); |
|
|
|
this.jarEntryCache.clear(); |
|
|
|
this.jarEntriesCache.clear(); |
|
|
|
|
|
|
|
this.manifestEntriesCache = null; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
@ -530,10 +531,10 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol |
|
|
|
* @since 4.3 |
|
|
|
* @since 4.3 |
|
|
|
*/ |
|
|
|
*/ |
|
|
|
protected void addClassPathManifestEntries(Set<Resource> result) { |
|
|
|
protected void addClassPathManifestEntries(Set<Resource> result) { |
|
|
|
Set<ClassPathManifestEntry> entries = classPathManifestEntriesCache; |
|
|
|
Set<ClassPathManifestEntry> entries = this.manifestEntriesCache; |
|
|
|
if (entries == null) { |
|
|
|
if (entries == null) { |
|
|
|
entries = getClassPathManifestEntries(); |
|
|
|
entries = getClassPathManifestEntries(); |
|
|
|
classPathManifestEntriesCache = entries; |
|
|
|
this.manifestEntriesCache = entries; |
|
|
|
} |
|
|
|
} |
|
|
|
for (ClassPathManifestEntry entry : entries) { |
|
|
|
for (ClassPathManifestEntry entry : entries) { |
|
|
|
if (!result.contains(entry.resource()) && |
|
|
|
if (!result.contains(entry.resource()) && |
|
|
|
@ -544,7 +545,7 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private Set<ClassPathManifestEntry> getClassPathManifestEntries() { |
|
|
|
private Set<ClassPathManifestEntry> getClassPathManifestEntries() { |
|
|
|
Set<ClassPathManifestEntry> manifestEntries = new HashSet<>(); |
|
|
|
Set<ClassPathManifestEntry> manifestEntries = new LinkedHashSet<>(); |
|
|
|
Set<File> seen = new HashSet<>(); |
|
|
|
Set<File> seen = new HashSet<>(); |
|
|
|
try { |
|
|
|
try { |
|
|
|
String paths = System.getProperty("java.class.path"); |
|
|
|
String paths = System.getProperty("java.class.path"); |
|
|
|
@ -578,9 +579,9 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol |
|
|
|
File parent = jar.getAbsoluteFile().getParentFile(); |
|
|
|
File parent = jar.getAbsoluteFile().getParentFile(); |
|
|
|
try (JarFile jarFile = new JarFile(jar)) { |
|
|
|
try (JarFile jarFile = new JarFile(jar)) { |
|
|
|
Manifest manifest = jarFile.getManifest(); |
|
|
|
Manifest manifest = jarFile.getManifest(); |
|
|
|
Attributes attributes = (manifest != null) ? manifest.getMainAttributes() : null; |
|
|
|
Attributes attributes = (manifest != null ? manifest.getMainAttributes() : null); |
|
|
|
String classPath = (attributes != null) ? attributes.getValue(Name.CLASS_PATH) : null; |
|
|
|
String classPath = (attributes != null ? attributes.getValue(Name.CLASS_PATH) : null); |
|
|
|
Set<ClassPathManifestEntry> manifestEntries = new HashSet<>(); |
|
|
|
Set<ClassPathManifestEntry> manifestEntries = new LinkedHashSet<>(); |
|
|
|
if (StringUtils.hasLength(classPath)) { |
|
|
|
if (StringUtils.hasLength(classPath)) { |
|
|
|
StringTokenizer tokenizer = new StringTokenizer(classPath); |
|
|
|
StringTokenizer tokenizer = new StringTokenizer(classPath); |
|
|
|
while (tokenizer.hasMoreTokens()) { |
|
|
|
while (tokenizer.hasMoreTokens()) { |
|
|
|
@ -806,11 +807,11 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol |
|
|
|
if (separatorIndex != -1) { |
|
|
|
if (separatorIndex != -1) { |
|
|
|
jarFileUrl = urlFile.substring(0, separatorIndex); |
|
|
|
jarFileUrl = urlFile.substring(0, separatorIndex); |
|
|
|
rootEntryPath = urlFile.substring(separatorIndex + 2); // both separators are 2 chars
|
|
|
|
rootEntryPath = urlFile.substring(separatorIndex + 2); // both separators are 2 chars
|
|
|
|
NavigableSet<String> entryCache = this.jarEntryCache.get(jarFileUrl); |
|
|
|
NavigableSet<String> entriesCache = this.jarEntriesCache.get(jarFileUrl); |
|
|
|
if (entryCache != null) { |
|
|
|
if (entriesCache != null) { |
|
|
|
Set<Resource> result = new LinkedHashSet<>(64); |
|
|
|
Set<Resource> result = new LinkedHashSet<>(64); |
|
|
|
// Search sorted entries from first entry with rootEntryPath prefix
|
|
|
|
// 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)) { |
|
|
|
if (!entryPath.startsWith(rootEntryPath)) { |
|
|
|
// We are beyond the potential matches in the current TreeSet.
|
|
|
|
// We are beyond the potential matches in the current TreeSet.
|
|
|
|
break; |
|
|
|
break; |
|
|
|
@ -870,11 +871,9 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol |
|
|
|
rootEntryPath = rootEntryPath + "/"; |
|
|
|
rootEntryPath = rootEntryPath + "/"; |
|
|
|
} |
|
|
|
} |
|
|
|
Set<Resource> result = new LinkedHashSet<>(64); |
|
|
|
Set<Resource> result = new LinkedHashSet<>(64); |
|
|
|
NavigableSet<String> entryCache = new TreeSet<>(); |
|
|
|
NavigableSet<String> entriesCache = new TreeSet<>(); |
|
|
|
for (Enumeration<JarEntry> entries = jarFile.entries(); entries.hasMoreElements(); ) { |
|
|
|
for (String entryPath : jarFile.stream().map(JarEntry::getName).sorted().toList()) { |
|
|
|
JarEntry entry = entries.nextElement(); |
|
|
|
entriesCache.add(entryPath); |
|
|
|
String entryPath = entry.getName(); |
|
|
|
|
|
|
|
entryCache.add(entryPath); |
|
|
|
|
|
|
|
if (entryPath.startsWith(rootEntryPath)) { |
|
|
|
if (entryPath.startsWith(rootEntryPath)) { |
|
|
|
String relativePath = entryPath.substring(rootEntryPath.length()); |
|
|
|
String relativePath = entryPath.substring(rootEntryPath.length()); |
|
|
|
if (getPathMatcher().match(subPattern, relativePath)) { |
|
|
|
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.
|
|
|
|
// Cache jar entries in TreeSet for efficient searching on re-encounter.
|
|
|
|
this.jarEntryCache.put(jarFileUrl, entryCache); |
|
|
|
this.jarEntriesCache.put(jarFileUrl, entriesCache); |
|
|
|
return result; |
|
|
|
return result; |
|
|
|
} |
|
|
|
} |
|
|
|
finally { |
|
|
|
finally { |
|
|
|
@ -1236,9 +1235,9 @@ public class PathMatchingResourcePatternResolver implements ResourcePatternResol |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private static Resource asJarFileResource(String path) |
|
|
|
private static Resource asJarFileResource(String path) throws MalformedURLException { |
|
|
|
throws MalformedURLException { |
|
|
|
|
|
|
|
return new UrlResource(JARFILE_URL_PREFIX + path + ResourceUtils.JAR_URL_SEPARATOR); |
|
|
|
return new UrlResource(JARFILE_URL_PREFIX + path + ResourceUtils.JAR_URL_SEPARATOR); |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
} |
|
|
|
|