AntPathRequestMatcher implements RequestVariableExtractor

Issue gh-3964
This commit is contained in:
Rob Winch 2016-07-05 08:26:15 -05:00
parent e4c13e3c0e
commit 9d50944cb2
5 changed files with 19 additions and 66 deletions

View File

@ -54,7 +54,6 @@ abstract class AbstractVariableEvaluationContextPostProcessor
if (this.variables == null) { if (this.variables == null) {
this.variables = extractVariables(request); this.variables = extractVariables(request);
} }
name = postProcessVariableName(name);
return this.variables.get(name); return this.variables.get(name);
} }
@ -63,6 +62,4 @@ abstract class AbstractVariableEvaluationContextPostProcessor
abstract Map<String, String> extractVariables(HttpServletRequest request); abstract Map<String, String> extractVariables(HttpServletRequest request);
abstract String postProcessVariableName(String variableName);
} }

View File

@ -93,10 +93,6 @@ public final class ExpressionBasedFilterInvocationSecurityMetadataSource
private static AbstractVariableEvaluationContextPostProcessor createPostProcessor( private static AbstractVariableEvaluationContextPostProcessor createPostProcessor(
Object request) { Object request) {
if (request instanceof AntPathRequestMatcher) {
return new AntPathMatcherEvaluationContextPostProcessor(
(AntPathRequestMatcher) request);
}
if (request instanceof RequestVariablesExtractor) { if (request instanceof RequestVariablesExtractor) {
return new RequestVariablesExtractorEvaluationContextPostProcessor( return new RequestVariablesExtractorEvaluationContextPostProcessor(
(RequestVariablesExtractor) request); (RequestVariablesExtractor) request);
@ -117,11 +113,6 @@ public final class ExpressionBasedFilterInvocationSecurityMetadataSource
Map<String, String> extractVariables(HttpServletRequest request) { Map<String, String> extractVariables(HttpServletRequest request) {
return this.matcher.extractUriTemplateVariables(request); return this.matcher.extractUriTemplateVariables(request);
} }
@Override
String postProcessVariableName(String variableName) {
return this.matcher.postProcessVariableName(variableName);
}
} }
static class RequestVariablesExtractorEvaluationContextPostProcessor static class RequestVariablesExtractorEvaluationContextPostProcessor
@ -137,11 +128,6 @@ public final class ExpressionBasedFilterInvocationSecurityMetadataSource
Map<String, String> extractVariables(HttpServletRequest request) { Map<String, String> extractVariables(HttpServletRequest request) {
return this.matcher.extractUriTemplateVariables(request); return this.matcher.extractUriTemplateVariables(request);
} }
@Override
String postProcessVariableName(String variableName) {
return variableName;
}
} }
} }

View File

@ -52,7 +52,8 @@ import org.springframework.util.StringUtils;
* *
* @see org.springframework.util.AntPathMatcher * @see org.springframework.util.AntPathMatcher
*/ */
public final class AntPathRequestMatcher implements RequestMatcher { public final class AntPathRequestMatcher
implements RequestMatcher, RequestVariablesExtractor {
private static final Log logger = LogFactory.getLog(AntPathRequestMatcher.class); private static final Log logger = LogFactory.getLog(AntPathRequestMatcher.class);
private static final String MATCH_ALL = "/**"; private static final String MATCH_ALL = "/**";
@ -102,10 +103,6 @@ public final class AntPathRequestMatcher implements RequestMatcher {
this.matcher = null; this.matcher = null;
} }
else { else {
if (!caseSensitive) {
pattern = pattern.toLowerCase();
}
// If the pattern ends with {@code /**} and has no other wildcards or path // If the pattern ends with {@code /**} and has no other wildcards or path
// variables, then optimize to a sub-path match // variables, then optimize to a sub-path match
if (pattern.endsWith(MATCH_ALL) if (pattern.endsWith(MATCH_ALL)
@ -113,10 +110,10 @@ public final class AntPathRequestMatcher implements RequestMatcher {
&& pattern.indexOf('}') == -1) && pattern.indexOf('}') == -1)
&& pattern.indexOf("*") == pattern.length() - 2) { && pattern.indexOf("*") == pattern.length() - 2) {
this.matcher = new SubpathMatcher( this.matcher = new SubpathMatcher(
pattern.substring(0, pattern.length() - 3)); pattern.substring(0, pattern.length() - 3), caseSensitive);
} }
else { else {
this.matcher = new SpringAntMatcher(pattern); this.matcher = new SpringAntMatcher(pattern, caseSensitive);
} }
} }
@ -164,6 +161,7 @@ public final class AntPathRequestMatcher implements RequestMatcher {
return this.matcher.matches(url); return this.matcher.matches(url);
} }
@Override
public Map<String, String> extractUriTemplateVariables(HttpServletRequest request) { public Map<String, String> extractUriTemplateVariables(HttpServletRequest request) {
if (this.matcher == null || !matches(request)) { if (this.matcher == null || !matches(request)) {
return Collections.emptyMap(); return Collections.emptyMap();
@ -172,10 +170,6 @@ public final class AntPathRequestMatcher implements RequestMatcher {
return this.matcher.extractUriTemplateVariables(url); return this.matcher.extractUriTemplateVariables(url);
} }
public String postProcessVariableName(String variableName) {
return this.caseSensitive ? variableName : variableName.toLowerCase();
}
private String getRequestPath(HttpServletRequest request) { private String getRequestPath(HttpServletRequest request) {
String url = request.getServletPath(); String url = request.getServletPath();
@ -183,10 +177,6 @@ public final class AntPathRequestMatcher implements RequestMatcher {
url += request.getPathInfo(); url += request.getPathInfo();
} }
if (!this.caseSensitive) {
url = url.toLowerCase();
}
return url; return url;
} }
@ -253,27 +243,29 @@ public final class AntPathRequestMatcher implements RequestMatcher {
} }
private static class SpringAntMatcher implements Matcher { private static class SpringAntMatcher implements Matcher {
private static final AntPathMatcher antMatcher = createMatcher(); private final AntPathMatcher antMatcher;
private final String pattern; private final String pattern;
private SpringAntMatcher(String pattern) { private SpringAntMatcher(String pattern, boolean caseSensitive) {
this.pattern = pattern; this.pattern = pattern;
this.antMatcher = createMatcher(caseSensitive);
} }
@Override @Override
public boolean matches(String path) { public boolean matches(String path) {
return antMatcher.match(this.pattern, path); return this.antMatcher.match(this.pattern, path);
} }
@Override @Override
public Map<String, String> extractUriTemplateVariables(String path) { public Map<String, String> extractUriTemplateVariables(String path) {
return antMatcher.extractUriTemplateVariables(this.pattern, path); return this.antMatcher.extractUriTemplateVariables(this.pattern, path);
} }
private static AntPathMatcher createMatcher() { private static AntPathMatcher createMatcher(boolean caseSensitive) {
AntPathMatcher matcher = new AntPathMatcher(); AntPathMatcher matcher = new AntPathMatcher();
matcher.setTrimTokens(false); matcher.setTrimTokens(false);
matcher.setCaseSensitive(caseSensitive);
return matcher; return matcher;
} }
} }
@ -284,15 +276,20 @@ public final class AntPathRequestMatcher implements RequestMatcher {
private static class SubpathMatcher implements Matcher { private static class SubpathMatcher implements Matcher {
private final String subpath; private final String subpath;
private final int length; private final int length;
private final boolean caseSensitive;
private SubpathMatcher(String subpath) { private SubpathMatcher(String subpath, boolean caseSensitive) {
assert!subpath.contains("*"); assert!subpath.contains("*");
this.subpath = subpath; this.subpath = caseSensitive ? subpath : subpath.toLowerCase();
this.length = subpath.length(); this.length = subpath.length();
this.caseSensitive = caseSensitive;
} }
@Override @Override
public boolean matches(String path) { public boolean matches(String path) {
if (!this.caseSensitive) {
path = path.toLowerCase();
}
return path.startsWith(this.subpath) return path.startsWith(this.subpath)
&& (path.length() == this.length || path.charAt(this.length) == '/'); && (path.length() == this.length || path.charAt(this.length) == '/');
} }

View File

@ -65,13 +65,6 @@ public class AbstractVariableEvaluationContextPostProcessorTests {
assertThat(this.context.lookupVariable(KEY)).isEqualTo(VALUE); assertThat(this.context.lookupVariable(KEY)).isEqualTo(VALUE);
} }
@Test
public void postProcessVariableName() {
this.context = this.processor.postProcess(this.context, this.invocation);
assertThat(this.context.lookupVariable("nothing")).isEqualTo(VALUE);
}
@Test @Test
public void extractVariablesOnlyUsedOnce() { public void extractVariablesOnlyUsedOnce() {
this.context = this.processor.postProcess(this.context, this.invocation); this.context = this.processor.postProcess(this.context, this.invocation);
@ -89,10 +82,5 @@ public class AbstractVariableEvaluationContextPostProcessorTests {
protected Map<String, String> extractVariables(HttpServletRequest request) { protected Map<String, String> extractVariables(HttpServletRequest request) {
return this.results; return this.results;
} }
@Override
String postProcessVariableName(String variableName) {
return KEY;
}
} }
} }

View File

@ -210,21 +210,6 @@ public class AntPathRequestMatcherTests {
assertThat(matcher.matches(request)).isFalse(); assertThat(matcher.matches(request)).isFalse();
} }
@Test
public void postProcessVariableNameCaseInsensitive() {
AntPathRequestMatcher matcher = new AntPathRequestMatcher("/**", null, false);
String variableName = "userName";
assertThat(matcher.postProcessVariableName(variableName))
.isEqualTo(variableName.toLowerCase());
}
@Test
public void postProcessVariableNameCaseSensitive() {
AntPathRequestMatcher matcher = new AntPathRequestMatcher("/**", null, true);
String variableName = "userName";
assertThat(matcher.postProcessVariableName(variableName)).isEqualTo(variableName);
}
private HttpServletRequest createRequestWithNullMethod(String path) { private HttpServletRequest createRequestWithNullMethod(String path) {
when(this.request.getQueryString()).thenReturn("doesntMatter"); when(this.request.getQueryString()).thenReturn("doesntMatter");
when(this.request.getServletPath()).thenReturn(path); when(this.request.getServletPath()).thenReturn(path);