Added cache for path pattern tokenization
Issue: SPR-11258
This commit is contained in:
parent
240819f955
commit
ff26dfdd28
|
|
@ -50,13 +50,13 @@ import java.util.regex.Pattern;
|
||||||
*/
|
*/
|
||||||
public class AntPathMatcher implements PathMatcher {
|
public class AntPathMatcher implements PathMatcher {
|
||||||
|
|
||||||
|
/** Default path separator: "/" */
|
||||||
|
public static final String DEFAULT_PATH_SEPARATOR = "/";
|
||||||
|
|
||||||
private static final int CACHE_TURNOFF_THRESHOLD = 65536;
|
private static final int CACHE_TURNOFF_THRESHOLD = 65536;
|
||||||
|
|
||||||
private static final Pattern VARIABLE_PATTERN = Pattern.compile("\\{[^/]+?\\}");
|
private static final Pattern VARIABLE_PATTERN = Pattern.compile("\\{[^/]+?\\}");
|
||||||
|
|
||||||
/** Default path separator: "/" */
|
|
||||||
public static final String DEFAULT_PATH_SEPARATOR = "/";
|
|
||||||
|
|
||||||
|
|
||||||
private String pathSeparator = DEFAULT_PATH_SEPARATOR;
|
private String pathSeparator = DEFAULT_PATH_SEPARATOR;
|
||||||
|
|
||||||
|
|
@ -64,8 +64,9 @@ public class AntPathMatcher implements PathMatcher {
|
||||||
|
|
||||||
private volatile Boolean cachePatterns;
|
private volatile Boolean cachePatterns;
|
||||||
|
|
||||||
final Map<String, AntPathStringMatcher> stringMatcherCache =
|
private final Map<String, String[]> tokenizedPatternCache = new ConcurrentHashMap<String, String[]>(256);
|
||||||
new ConcurrentHashMap<String, AntPathStringMatcher>(256);
|
|
||||||
|
final Map<String, AntPathStringMatcher> stringMatcherCache = new ConcurrentHashMap<String, AntPathStringMatcher>(256);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -99,6 +100,12 @@ public class AntPathMatcher implements PathMatcher {
|
||||||
this.cachePatterns = cachePatterns;
|
this.cachePatterns = cachePatterns;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void deactivatePatternCache() {
|
||||||
|
this.cachePatterns = false;
|
||||||
|
this.tokenizedPatternCache.clear();
|
||||||
|
this.stringMatcherCache.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isPattern(String path) {
|
public boolean isPattern(String path) {
|
||||||
|
|
@ -128,8 +135,8 @@ public class AntPathMatcher implements PathMatcher {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] pattDirs = StringUtils.tokenizeToStringArray(pattern, this.pathSeparator, this.trimTokens, true);
|
String[] pattDirs = tokenizePattern(pattern);
|
||||||
String[] pathDirs = StringUtils.tokenizeToStringArray(path, this.pathSeparator, this.trimTokens, true);
|
String[] pathDirs = tokenizePath(path);
|
||||||
|
|
||||||
int pattIdxStart = 0;
|
int pattIdxStart = 0;
|
||||||
int pattIdxEnd = pattDirs.length - 1;
|
int pattIdxEnd = pattDirs.length - 1;
|
||||||
|
|
@ -248,6 +255,44 @@ public class AntPathMatcher implements PathMatcher {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tokenize the given path pattern into parts, based on this matcher's settings.
|
||||||
|
* <p>Performs caching based on {@link #setCachePatterns}, delegating to
|
||||||
|
* {@link #tokenizePath(String)} for the actual tokenization algorithm.
|
||||||
|
* @param pattern the pattern to tokenize
|
||||||
|
* @return the tokenized pattern parts
|
||||||
|
*/
|
||||||
|
protected String[] tokenizePattern(String pattern) {
|
||||||
|
String[] tokenized = null;
|
||||||
|
Boolean cachePatterns = this.cachePatterns;
|
||||||
|
if (cachePatterns == null || cachePatterns.booleanValue()) {
|
||||||
|
tokenized = this.tokenizedPatternCache.get(pattern);
|
||||||
|
}
|
||||||
|
if (tokenized == null) {
|
||||||
|
tokenized = tokenizePath(pattern);
|
||||||
|
if (cachePatterns == null && this.tokenizedPatternCache.size() >= CACHE_TURNOFF_THRESHOLD) {
|
||||||
|
// Try to adapt to the runtime situation that we're encountering:
|
||||||
|
// There are obviously too many different patterns coming in here...
|
||||||
|
// So let's turn off the cache since the patterns are unlikely to be reoccurring.
|
||||||
|
deactivatePatternCache();
|
||||||
|
return tokenized;
|
||||||
|
}
|
||||||
|
if (cachePatterns == null || cachePatterns.booleanValue()) {
|
||||||
|
this.tokenizedPatternCache.put(pattern, tokenized);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return tokenized;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tokenize the given path String into parts, based on this matcher's settings.
|
||||||
|
* @param path the path to tokenize
|
||||||
|
* @return the tokenized path parts
|
||||||
|
*/
|
||||||
|
protected String[] tokenizePath(String path) {
|
||||||
|
return StringUtils.tokenizeToStringArray(path, this.pathSeparator, this.trimTokens, true);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests whether or not a string matches against a pattern.
|
* Tests whether or not a string matches against a pattern.
|
||||||
* @param pattern the pattern to match against (never {@code null})
|
* @param pattern the pattern to match against (never {@code null})
|
||||||
|
|
@ -281,10 +326,9 @@ public class AntPathMatcher implements PathMatcher {
|
||||||
matcher = new AntPathStringMatcher(pattern);
|
matcher = new AntPathStringMatcher(pattern);
|
||||||
if (cachePatterns == null && this.stringMatcherCache.size() >= CACHE_TURNOFF_THRESHOLD) {
|
if (cachePatterns == null && this.stringMatcherCache.size() >= CACHE_TURNOFF_THRESHOLD) {
|
||||||
// Try to adapt to the runtime situation that we're encountering:
|
// Try to adapt to the runtime situation that we're encountering:
|
||||||
// There are obviously too many different paths coming in here...
|
// There are obviously too many different patterns coming in here...
|
||||||
// So let's turn off the cache since the patterns are unlikely to be reoccurring.
|
// So let's turn off the cache since the patterns are unlikely to be reoccurring.
|
||||||
this.cachePatterns = false;
|
deactivatePatternCache();
|
||||||
this.stringMatcherCache.clear();
|
|
||||||
return matcher;
|
return matcher;
|
||||||
}
|
}
|
||||||
if (cachePatterns == null || cachePatterns.booleanValue()) {
|
if (cachePatterns == null || cachePatterns.booleanValue()) {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue