From a2f8902b3a8569a1ebb4b4c87fab5a412cf4d389 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 12 Dec 2012 22:24:52 +0100 Subject: [PATCH] Inlined AntPathStringMatcher into AntPathMatcher Also initializing the capacity of the AntPathStringMatcher cache to 256 now. --- .../springframework/util/AntPathMatcher.java | 94 +++++++++++++- .../util/AntPathStringMatcher.java | 120 ------------------ 2 files changed, 91 insertions(+), 123 deletions(-) delete mode 100644 spring-core/src/main/java/org/springframework/util/AntPathStringMatcher.java diff --git a/spring-core/src/main/java/org/springframework/util/AntPathMatcher.java b/spring-core/src/main/java/org/springframework/util/AntPathMatcher.java index dd69dee004..059c9f7a10 100644 --- a/spring-core/src/main/java/org/springframework/util/AntPathMatcher.java +++ b/spring-core/src/main/java/org/springframework/util/AntPathMatcher.java @@ -18,6 +18,8 @@ package org.springframework.util; import java.util.Comparator; import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.regex.Matcher; @@ -43,6 +45,7 @@ import java.util.regex.Pattern; * @author Juergen Hoeller * @author Rob Harrop * @author Arjen Poutsma + * @author Rossen Stoyanchev * @since 16.07.2003 */ public class AntPathMatcher implements PathMatcher { @@ -55,7 +58,7 @@ public class AntPathMatcher implements PathMatcher { private String pathSeparator = DEFAULT_PATH_SEPARATOR; private final Map stringMatcherCache = - new ConcurrentHashMap(); + new ConcurrentHashMap(256); /** 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:
'*' - * means zero or more characters
'?' means one and only one character + * Tests whether or not a string matches against a pattern. The pattern may contain two special characters: + *
'*' means zero or more characters + *
'?' means one and only one character * @param pattern pattern to match against. Must not be null. * @param str string which must be matched against the pattern. Must not be null. * @return true if the string matches against the pattern, or false otherwise. @@ -462,4 +466,88 @@ public class AntPathMatcher implements PathMatcher { } } + + /** + * Tests whether or not a string matches against a pattern via a {@link Pattern}. + *

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 /users/{user}. + */ + 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 variableNames = new LinkedList(); + + 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 true if the string matches against the pattern, or false otherwise. + */ + public boolean matchStrings(String str, Map 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; + } + } + } + } diff --git a/spring-core/src/main/java/org/springframework/util/AntPathStringMatcher.java b/spring-core/src/main/java/org/springframework/util/AntPathStringMatcher.java deleted file mode 100644 index 424b60930e..0000000000 --- a/spring-core/src/main/java/org/springframework/util/AntPathStringMatcher.java +++ /dev/null @@ -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}. - * - *

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 /users/{user}. - * - * @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 variableNames = new LinkedList(); - - - /** Construct a new instance of the AntPatchStringMatcher. */ - 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 true if the string matches against the pattern, or false otherwise. - */ - public boolean matchStrings(String str, Map 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; - } - } - -}