Inlined AntPathStringMatcher into AntPathMatcher
Also initializing the capacity of the AntPathStringMatcher cache to 256 now.
This commit is contained in:
@@ -18,6 +18,8 @@ package org.springframework.util;
|
|||||||
|
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
@@ -43,6 +45,7 @@ import java.util.regex.Pattern;
|
|||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @author Rob Harrop
|
* @author Rob Harrop
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
* @since 16.07.2003
|
* @since 16.07.2003
|
||||||
*/
|
*/
|
||||||
public class AntPathMatcher implements PathMatcher {
|
public class AntPathMatcher implements PathMatcher {
|
||||||
@@ -55,7 +58,7 @@ public class AntPathMatcher implements PathMatcher {
|
|||||||
private String pathSeparator = DEFAULT_PATH_SEPARATOR;
|
private String pathSeparator = DEFAULT_PATH_SEPARATOR;
|
||||||
|
|
||||||
private final Map<String, AntPathStringMatcher> stringMatcherCache =
|
private final Map<String, AntPathStringMatcher> stringMatcherCache =
|
||||||
new ConcurrentHashMap<String, AntPathStringMatcher>();
|
new ConcurrentHashMap<String, AntPathStringMatcher>(256);
|
||||||
|
|
||||||
|
|
||||||
/** Set the path separator to use for pattern parsing. Default is "/", as in Ant. */
|
/** Set the path separator to use for pattern parsing. Default is "/", as in Ant. */
|
||||||
@@ -213,8 +216,9 @@ public class AntPathMatcher implements PathMatcher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tests whether or not a string matches against a pattern. The pattern may contain two special characters:<br> '*'
|
* Tests whether or not a string matches against a pattern. The pattern may contain two special characters:
|
||||||
* means zero or more characters<br> '?' means one and only one character
|
* <br>'*' means zero or more characters
|
||||||
|
* <br>'?' means one and only one character
|
||||||
* @param pattern pattern to match against. Must not be <code>null</code>.
|
* @param pattern pattern to match against. Must not be <code>null</code>.
|
||||||
* @param str string which must be matched against the pattern. Must not be <code>null</code>.
|
* @param str string which must be matched against the pattern. Must not be <code>null</code>.
|
||||||
* @return <code>true</code> if the string matches against the pattern, or <code>false</code> otherwise.
|
* @return <code>true</code> if the string matches against the pattern, or <code>false</code> otherwise.
|
||||||
@@ -462,4 +466,88 @@ public class AntPathMatcher implements PathMatcher {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests whether or not a string matches against a pattern via a {@link Pattern}.
|
||||||
|
* <p>The pattern may contain special characters: '*' means zero or more characters; '?' means one and
|
||||||
|
* only one character; '{' and '}' indicate a URI template pattern. For example <tt>/users/{user}</tt>.
|
||||||
|
*/
|
||||||
|
private static class AntPathStringMatcher {
|
||||||
|
|
||||||
|
private static final Pattern GLOB_PATTERN = Pattern.compile("\\?|\\*|\\{((?:\\{[^/]+?\\}|[^/{}]|\\\\[{}])+?)\\}");
|
||||||
|
|
||||||
|
private static final String DEFAULT_VARIABLE_PATTERN = "(.*)";
|
||||||
|
|
||||||
|
private final Pattern pattern;
|
||||||
|
|
||||||
|
private final List<String> variableNames = new LinkedList<String>();
|
||||||
|
|
||||||
|
public AntPathStringMatcher(String pattern) {
|
||||||
|
StringBuilder patternBuilder = new StringBuilder();
|
||||||
|
Matcher m = GLOB_PATTERN.matcher(pattern);
|
||||||
|
int end = 0;
|
||||||
|
while (m.find()) {
|
||||||
|
patternBuilder.append(quote(pattern, end, m.start()));
|
||||||
|
String match = m.group();
|
||||||
|
if ("?".equals(match)) {
|
||||||
|
patternBuilder.append('.');
|
||||||
|
}
|
||||||
|
else if ("*".equals(match)) {
|
||||||
|
patternBuilder.append(".*");
|
||||||
|
}
|
||||||
|
else if (match.startsWith("{") && match.endsWith("}")) {
|
||||||
|
int colonIdx = match.indexOf(':');
|
||||||
|
if (colonIdx == -1) {
|
||||||
|
patternBuilder.append(DEFAULT_VARIABLE_PATTERN);
|
||||||
|
this.variableNames.add(m.group(1));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
String variablePattern = match.substring(colonIdx + 1, match.length() - 1);
|
||||||
|
patternBuilder.append('(');
|
||||||
|
patternBuilder.append(variablePattern);
|
||||||
|
patternBuilder.append(')');
|
||||||
|
String variableName = match.substring(1, colonIdx);
|
||||||
|
this.variableNames.add(variableName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
end = m.end();
|
||||||
|
}
|
||||||
|
patternBuilder.append(quote(pattern, end, pattern.length()));
|
||||||
|
this.pattern = Pattern.compile(patternBuilder.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
private String quote(String s, int start, int end) {
|
||||||
|
if (start == end) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return Pattern.quote(s.substring(start, end));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Main entry point.
|
||||||
|
* @return <code>true</code> if the string matches against the pattern, or <code>false</code> otherwise.
|
||||||
|
*/
|
||||||
|
public boolean matchStrings(String str, Map<String, String> uriTemplateVariables) {
|
||||||
|
Matcher matcher = this.pattern.matcher(str);
|
||||||
|
if (matcher.matches()) {
|
||||||
|
if (uriTemplateVariables != null) {
|
||||||
|
// SPR-8455
|
||||||
|
Assert.isTrue(this.variableNames.size() == matcher.groupCount(),
|
||||||
|
"The number of capturing groups in the pattern segment " + this.pattern +
|
||||||
|
" does not match the number of URI template variables it defines, which can occur if " +
|
||||||
|
" capturing groups are used in a URI template regex. Use non-capturing groups instead.");
|
||||||
|
for (int i = 1; i <= matcher.groupCount(); i++) {
|
||||||
|
String name = this.variableNames.get(i - 1);
|
||||||
|
String value = matcher.group(i);
|
||||||
|
uriTemplateVariables.put(name, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,120 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright 2002-2012 the original author or authors.
|
|
||||||
*
|
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
||||||
* you may not use this file except in compliance with the License.
|
|
||||||
* You may obtain a copy of the License at
|
|
||||||
*
|
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
|
||||||
*
|
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
||||||
* See the License for the specific language governing permissions and
|
|
||||||
* limitations under the License.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.springframework.util;
|
|
||||||
|
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Package-protected helper class for {@link AntPathMatcher}. Tests whether or not a string matches against a pattern
|
|
||||||
* via a {@link Pattern}.
|
|
||||||
*
|
|
||||||
* <p>The pattern may contain special characters: '*' means zero or more characters; '?' means one and only one
|
|
||||||
* character; '{' and '}' indicate a URI template pattern. For example <tt>/users/{user}</tt>.
|
|
||||||
*
|
|
||||||
* @author Arjen Poutsma
|
|
||||||
* @author Rossen Stoyanchev
|
|
||||||
* @since 3.0
|
|
||||||
*/
|
|
||||||
class AntPathStringMatcher {
|
|
||||||
|
|
||||||
private static final Pattern GLOB_PATTERN = Pattern.compile("\\?|\\*|\\{((?:\\{[^/]+?\\}|[^/{}]|\\\\[{}])+?)\\}");
|
|
||||||
|
|
||||||
private static final String DEFAULT_VARIABLE_PATTERN = "(.*)";
|
|
||||||
|
|
||||||
private final Pattern pattern;
|
|
||||||
|
|
||||||
private final List<String> variableNames = new LinkedList<String>();
|
|
||||||
|
|
||||||
|
|
||||||
/** Construct a new instance of the <code>AntPatchStringMatcher</code>. */
|
|
||||||
AntPathStringMatcher(String pattern) {
|
|
||||||
this.pattern = createPattern(pattern);
|
|
||||||
}
|
|
||||||
|
|
||||||
private Pattern createPattern(String pattern) {
|
|
||||||
StringBuilder patternBuilder = new StringBuilder();
|
|
||||||
Matcher m = GLOB_PATTERN.matcher(pattern);
|
|
||||||
int end = 0;
|
|
||||||
while (m.find()) {
|
|
||||||
patternBuilder.append(quote(pattern, end, m.start()));
|
|
||||||
String match = m.group();
|
|
||||||
if ("?".equals(match)) {
|
|
||||||
patternBuilder.append('.');
|
|
||||||
}
|
|
||||||
else if ("*".equals(match)) {
|
|
||||||
patternBuilder.append(".*");
|
|
||||||
}
|
|
||||||
else if (match.startsWith("{") && match.endsWith("}")) {
|
|
||||||
int colonIdx = match.indexOf(':');
|
|
||||||
if (colonIdx == -1) {
|
|
||||||
patternBuilder.append(DEFAULT_VARIABLE_PATTERN);
|
|
||||||
variableNames.add(m.group(1));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
String variablePattern = match.substring(colonIdx + 1, match.length() - 1);
|
|
||||||
patternBuilder.append('(');
|
|
||||||
patternBuilder.append(variablePattern);
|
|
||||||
patternBuilder.append(')');
|
|
||||||
String variableName = match.substring(1, colonIdx);
|
|
||||||
variableNames.add(variableName);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
end = m.end();
|
|
||||||
}
|
|
||||||
patternBuilder.append(quote(pattern, end, pattern.length()));
|
|
||||||
return Pattern.compile(patternBuilder.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private String quote(String s, int start, int end) {
|
|
||||||
if (start == end) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return Pattern.quote(s.substring(start, end));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Main entry point.
|
|
||||||
*
|
|
||||||
* @return <code>true</code> if the string matches against the pattern, or <code>false</code> otherwise.
|
|
||||||
*/
|
|
||||||
public boolean matchStrings(String str, Map<String, String> uriTemplateVariables) {
|
|
||||||
Matcher matcher = pattern.matcher(str);
|
|
||||||
if (matcher.matches()) {
|
|
||||||
if (uriTemplateVariables != null) {
|
|
||||||
// SPR-8455
|
|
||||||
Assert.isTrue(variableNames.size() == matcher.groupCount(),
|
|
||||||
"The number of capturing groups in the pattern segment " + pattern +
|
|
||||||
" does not match the number of URI template variables it defines, which can occur if " +
|
|
||||||
" capturing groups are used in a URI template regex. Use non-capturing groups instead.");
|
|
||||||
for (int i = 1; i <= matcher.groupCount(); i++) {
|
|
||||||
String name = this.variableNames.get(i - 1);
|
|
||||||
String value = matcher.group(i);
|
|
||||||
uriTemplateVariables.put(name, value);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user