Cache AntPathStringMatcher instances

AntPathMatcher now caches AntPathStringMatcher instances by pattern
thus avoiding java.util.regex.Pattern recompilation.

Issue: SPR-9749
This commit is contained in:
Rossen Stoyanchev 2012-09-10 16:57:10 -04:00
parent 0a877afa06
commit 34c3e821dd
2 changed files with 17 additions and 14 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2010 the original author or authors. * Copyright 2002-2012 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -19,6 +19,7 @@ package org.springframework.util;
import java.util.Comparator; import java.util.Comparator;
import java.util.LinkedHashMap; import java.util.LinkedHashMap;
import java.util.Map; import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher; import java.util.regex.Matcher;
import java.util.regex.Pattern; import java.util.regex.Pattern;
@ -53,6 +54,9 @@ public class AntPathMatcher implements PathMatcher {
private String pathSeparator = DEFAULT_PATH_SEPARATOR; private String pathSeparator = DEFAULT_PATH_SEPARATOR;
private final Map<String, AntPathStringMatcher> stringMatcherCache =
new ConcurrentHashMap<String, AntPathStringMatcher>();
/** 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. */
public void setPathSeparator(String pathSeparator) { public void setPathSeparator(String pathSeparator) {
@ -216,8 +220,12 @@ public class AntPathMatcher implements PathMatcher {
* @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.
*/ */
private boolean matchStrings(String pattern, String str, Map<String, String> uriTemplateVariables) { private boolean matchStrings(String pattern, String str, Map<String, String> uriTemplateVariables) {
AntPathStringMatcher matcher = new AntPathStringMatcher(pattern, str, uriTemplateVariables); AntPathStringMatcher matcher = this.stringMatcherCache.get(pattern);
return matcher.matchStrings(); if (matcher == null) {
matcher = new AntPathStringMatcher(pattern);
this.stringMatcherCache.put(pattern, matcher);
}
return matcher.matchStrings(str, uriTemplateVariables);
} }
/** /**

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2009 the original author or authors. * Copyright 2002-2012 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -41,16 +41,11 @@ class AntPathStringMatcher {
private final Pattern pattern; private final Pattern pattern;
private String str;
private final List<String> variableNames = new LinkedList<String>(); private final List<String> variableNames = new LinkedList<String>();
private final Map<String, String> uriTemplateVariables;
/** Construct a new instance of the <code>AntPatchStringMatcher</code>. */ /** Construct a new instance of the <code>AntPatchStringMatcher</code>. */
AntPathStringMatcher(String pattern, String str, Map<String, String> uriTemplateVariables) { AntPathStringMatcher(String pattern) {
this.str = str;
this.uriTemplateVariables = uriTemplateVariables;
this.pattern = createPattern(pattern); this.pattern = createPattern(pattern);
} }
@ -100,14 +95,14 @@ class AntPathStringMatcher {
* *
* @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.
*/ */
public boolean matchStrings() { public boolean matchStrings(String str, Map<String, String> uriTemplateVariables) {
Matcher matcher = pattern.matcher(str); Matcher matcher = pattern.matcher(str);
if (matcher.matches()) { if (matcher.matches()) {
if (uriTemplateVariables != null) { if (uriTemplateVariables != null) {
// SPR-8455 // SPR-8455
Assert.isTrue(variableNames.size() == matcher.groupCount(), Assert.isTrue(variableNames.size() == matcher.groupCount(),
"The number of capturing groups in the pattern segment " + pattern + "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 " + " 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."); " capturing groups are used in a URI template regex. Use non-capturing groups instead.");
for (int i = 1; i <= matcher.groupCount(); i++) { for (int i = 1; i <= matcher.groupCount(); i++) {
String name = this.variableNames.get(i - 1); String name = this.variableNames.get(i - 1);