Skip to content

Commit a2f8902

Browse files
jhoellerunknown
authored and
unknown
committed
Inlined AntPathStringMatcher into AntPathMatcher
Also initializing the capacity of the AntPathStringMatcher cache to 256 now.
1 parent 710fe93 commit a2f8902

File tree

2 files changed

+91
-123
lines changed

2 files changed

+91
-123
lines changed

spring-core/src/main/java/org/springframework/util/AntPathMatcher.java

Lines changed: 91 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818

1919
import java.util.Comparator;
2020
import java.util.LinkedHashMap;
21+
import java.util.LinkedList;
22+
import java.util.List;
2123
import java.util.Map;
2224
import java.util.concurrent.ConcurrentHashMap;
2325
import java.util.regex.Matcher;
@@ -43,6 +45,7 @@
4345
* @author Juergen Hoeller
4446
* @author Rob Harrop
4547
* @author Arjen Poutsma
48+
* @author Rossen Stoyanchev
4649
* @since 16.07.2003
4750
*/
4851
public class AntPathMatcher implements PathMatcher {
@@ -55,7 +58,7 @@ public class AntPathMatcher implements PathMatcher {
5558
private String pathSeparator = DEFAULT_PATH_SEPARATOR;
5659

5760
private final Map<String, AntPathStringMatcher> stringMatcherCache =
58-
new ConcurrentHashMap<String, AntPathStringMatcher>();
61+
new ConcurrentHashMap<String, AntPathStringMatcher>(256);
5962

6063

6164
/** Set the path separator to use for pattern parsing. Default is "/", as in Ant. */
@@ -213,8 +216,9 @@ else if (!fullMatch && "**".equals(pattDirs[pattIdxStart])) {
213216
}
214217

215218
/**
216-
* Tests whether or not a string matches against a pattern. The pattern may contain two special characters:<br> '*'
217-
* means zero or more characters<br> '?' means one and only one character
219+
* Tests whether or not a string matches against a pattern. The pattern may contain two special characters:
220+
* <br>'*' means zero or more characters
221+
* <br>'?' means one and only one character
218222
* @param pattern pattern to match against. Must not be <code>null</code>.
219223
* @param str string which must be matched against the pattern. Must not be <code>null</code>.
220224
* @return <code>true</code> if the string matches against the pattern, or <code>false</code> otherwise.
@@ -462,4 +466,88 @@ private int getPatternLength(String pattern) {
462466
}
463467
}
464468

469+
470+
/**
471+
* Tests whether or not a string matches against a pattern via a {@link Pattern}.
472+
* <p>The pattern may contain special characters: '*' means zero or more characters; '?' means one and
473+
* only one character; '{' and '}' indicate a URI template pattern. For example <tt>/users/{user}</tt>.
474+
*/
475+
private static class AntPathStringMatcher {
476+
477+
private static final Pattern GLOB_PATTERN = Pattern.compile("\\?|\\*|\\{((?:\\{[^/]+?\\}|[^/{}]|\\\\[{}])+?)\\}");
478+
479+
private static final String DEFAULT_VARIABLE_PATTERN = "(.*)";
480+
481+
private final Pattern pattern;
482+
483+
private final List<String> variableNames = new LinkedList<String>();
484+
485+
public AntPathStringMatcher(String pattern) {
486+
StringBuilder patternBuilder = new StringBuilder();
487+
Matcher m = GLOB_PATTERN.matcher(pattern);
488+
int end = 0;
489+
while (m.find()) {
490+
patternBuilder.append(quote(pattern, end, m.start()));
491+
String match = m.group();
492+
if ("?".equals(match)) {
493+
patternBuilder.append('.');
494+
}
495+
else if ("*".equals(match)) {
496+
patternBuilder.append(".*");
497+
}
498+
else if (match.startsWith("{") && match.endsWith("}")) {
499+
int colonIdx = match.indexOf(':');
500+
if (colonIdx == -1) {
501+
patternBuilder.append(DEFAULT_VARIABLE_PATTERN);
502+
this.variableNames.add(m.group(1));
503+
}
504+
else {
505+
String variablePattern = match.substring(colonIdx + 1, match.length() - 1);
506+
patternBuilder.append('(');
507+
patternBuilder.append(variablePattern);
508+
patternBuilder.append(')');
509+
String variableName = match.substring(1, colonIdx);
510+
this.variableNames.add(variableName);
511+
}
512+
}
513+
end = m.end();
514+
}
515+
patternBuilder.append(quote(pattern, end, pattern.length()));
516+
this.pattern = Pattern.compile(patternBuilder.toString());
517+
}
518+
519+
private String quote(String s, int start, int end) {
520+
if (start == end) {
521+
return "";
522+
}
523+
return Pattern.quote(s.substring(start, end));
524+
}
525+
526+
/**
527+
* Main entry point.
528+
* @return <code>true</code> if the string matches against the pattern, or <code>false</code> otherwise.
529+
*/
530+
public boolean matchStrings(String str, Map<String, String> uriTemplateVariables) {
531+
Matcher matcher = this.pattern.matcher(str);
532+
if (matcher.matches()) {
533+
if (uriTemplateVariables != null) {
534+
// SPR-8455
535+
Assert.isTrue(this.variableNames.size() == matcher.groupCount(),
536+
"The number of capturing groups in the pattern segment " + this.pattern +
537+
" does not match the number of URI template variables it defines, which can occur if " +
538+
" capturing groups are used in a URI template regex. Use non-capturing groups instead.");
539+
for (int i = 1; i <= matcher.groupCount(); i++) {
540+
String name = this.variableNames.get(i - 1);
541+
String value = matcher.group(i);
542+
uriTemplateVariables.put(name, value);
543+
}
544+
}
545+
return true;
546+
}
547+
else {
548+
return false;
549+
}
550+
}
551+
}
552+
465553
}

spring-core/src/main/java/org/springframework/util/AntPathStringMatcher.java

Lines changed: 0 additions & 120 deletions
This file was deleted.

0 commit comments

Comments
 (0)