Skip to content

Commit

Permalink
Add exclude patterns for mapped interceptors
Browse files Browse the repository at this point in the history
Add the ability provide exclude patterns for mapped interceptors in the
MVC namespace and in the MVC Java config.

Issue: SPR-6570
  • Loading branch information
rstoyanchev committed Jul 20, 2012
1 parent 5a36507 commit 92759ed
Show file tree
Hide file tree
Showing 10 changed files with 236 additions and 84 deletions.
Original file line number Diff line number Diff line change
@@ -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");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -31,7 +31,7 @@
/**
* {@link org.springframework.beans.factory.xml.BeanDefinitionParser} that parses a {@code interceptors} element to register
* a set of {@link MappedInterceptor} definitions.
*
*
* @author Keith Donald
* @since 3.0
*/
Expand All @@ -40,37 +40,44 @@ class InterceptorsBeanDefinitionParser implements BeanDefinitionParser {
public BeanDefinition parse(Element element, ParserContext parserContext) {
CompositeComponentDefinition compDefinition = new CompositeComponentDefinition(element.getTagName(), parserContext.extractSource(element));
parserContext.pushContainingComponent(compDefinition);

List<Element> interceptors = DomUtils.getChildElementsByTagName(element, new String[] { "bean", "ref", "interceptor" });
for (Element interceptor : interceptors) {
RootBeanDefinition mappedInterceptorDef = new RootBeanDefinition(MappedInterceptor.class);
mappedInterceptorDef.setSource(parserContext.extractSource(interceptor));
mappedInterceptorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

String[] pathPatterns;

String[] includePatterns = null;
String[] excludePatterns = null;
Object interceptorBean;
if ("interceptor".equals(interceptor.getLocalName())) {
List<Element> paths = DomUtils.getChildElementsByTagName(interceptor, "mapping");
pathPatterns = new String[paths.size()];
for (int i = 0; i < paths.size(); i++) {
pathPatterns[i] = paths.get(i).getAttribute("path");
}
includePatterns = getIncludePatterns(interceptor, "mapping");
excludePatterns = getIncludePatterns(interceptor, "exclude-mapping");
Element beanElem = DomUtils.getChildElementsByTagName(interceptor, new String[] { "bean", "ref"}).get(0);
interceptorBean = parserContext.getDelegate().parsePropertySubElement(beanElem, null);
}
else {
pathPatterns = null;
interceptorBean = parserContext.getDelegate().parsePropertySubElement(interceptor, null);
}
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, pathPatterns);
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, interceptorBean);
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(0, includePatterns);
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(1, excludePatterns);
mappedInterceptorDef.getConstructorArgumentValues().addIndexedArgumentValue(2, interceptorBean);

String beanName = parserContext.getReaderContext().registerWithGeneratedName(mappedInterceptorDef);
parserContext.registerComponent(new BeanComponentDefinition(mappedInterceptorDef, beanName));
}

parserContext.popAndRegisterContainingComponent();
return null;
}

private String[] getIncludePatterns(Element interceptor, String elementName) {
List<Element> paths = DomUtils.getChildElementsByTagName(interceptor, elementName);
String[] patterns = new String[paths.size()];
for (int i = 0; i < paths.size(); i++) {
patterns[i] = paths.get(i).getAttribute("path");
}
return patterns;
}

}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* 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.
Expand All @@ -21,22 +21,24 @@
import java.util.List;

import org.springframework.util.Assert;
import org.springframework.util.CollectionUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.handler.MappedInterceptor;

/**
* Encapsulates a {@link HandlerInterceptor} and an optional list of URL patterns.
* Results in the creation of a {@link MappedInterceptor} if URL patterns are provided.
*
* Assists with the creation of a {@link MappedInterceptor}.
*
* @author Rossen Stoyanchev
* @author Keith Donald
* @since 3.1
*/
public class InterceptorRegistration {

private final HandlerInterceptor interceptor;

private final List<String> pathPatterns = new ArrayList<String>();

private final List<String> includePatterns = new ArrayList<String>();

private final List<String> excludePatterns = new ArrayList<String>();

/**
* Creates an {@link InterceptorRegistration} instance.
Expand All @@ -47,22 +49,39 @@ public InterceptorRegistration(HandlerInterceptor interceptor) {
}

/**
* Adds one or more URL patterns to which the registered interceptor should apply to.
* If no URL patterns are provided, the interceptor applies to all paths.
* Add URL patterns to which the registered interceptor should apply to.
*/
public void addPathPatterns(String... pathPatterns) {
this.pathPatterns.addAll(Arrays.asList(pathPatterns));
public InterceptorRegistration addPathPatterns(String... patterns) {
this.includePatterns.addAll(Arrays.asList(patterns));
return this;
}

/**
* Returns the underlying interceptor. If URL patterns are provided the returned type is
* Add URL patterns to which the registered interceptor should not apply to.
*/
public InterceptorRegistration excludePathPatterns(String... patterns) {
this.excludePatterns.addAll(Arrays.asList(patterns));
return this;
}

/**
* Returns the underlying interceptor. If URL patterns are provided the returned type is
* {@link MappedInterceptor}; otherwise {@link HandlerInterceptor}.
*/
protected Object getInterceptor() {
if (pathPatterns.isEmpty()) {
return interceptor;
if (this.includePatterns.isEmpty()) {
return this.interceptor;
}
return new MappedInterceptor(toArray(this.includePatterns), toArray(this.excludePatterns), interceptor);
}

private static String[] toArray(List<String> list) {
if (CollectionUtils.isEmpty(list)) {
return null;
}
else {
return list.toArray(new String[list.size()]);
}
return new MappedInterceptor(pathPatterns.toArray(new String[pathPatterns.size()]), interceptor);
}

}
Original file line number Diff line number Diff line change
@@ -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");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -29,38 +29,58 @@
* @since 3.0
*/
public final class MappedInterceptor {

private final String[] pathPatterns;


private final String[] includePatterns;

private final String[] excludePatterns;

private final HandlerInterceptor interceptor;


/**
* Create a new MappedInterceptor instance.
* @param includePatterns the path patterns to map with a {@code null} value matching to all paths
* @param interceptor the HandlerInterceptor instance to map to the given patterns
*/
public MappedInterceptor(String[] includePatterns, HandlerInterceptor interceptor) {
this(includePatterns, null, interceptor);
}

/**
* Create a new MappedInterceptor instance.
* @param pathPatterns the path patterns to map with a {@code null} value matching to all paths
* @param interceptor the HandlerInterceptor instance to map to the given patterns
*/
public MappedInterceptor(String[] pathPatterns, HandlerInterceptor interceptor) {
this.pathPatterns = pathPatterns;
public MappedInterceptor(String[] includePatterns, String[] excludePatterns, HandlerInterceptor interceptor) {
this.includePatterns = includePatterns;
this.excludePatterns = excludePatterns;
this.interceptor = interceptor;
}

/**
* Create a new MappedInterceptor instance.
* @param pathPatterns the path patterns to map with a {@code null} value matching to all paths
* @param includePatterns the path patterns to map with a {@code null} value matching to all paths
* @param interceptor the WebRequestInterceptor instance to map to the given patterns
*/
public MappedInterceptor(String[] pathPatterns, WebRequestInterceptor interceptor) {
this.pathPatterns = pathPatterns;
this.interceptor = new WebRequestHandlerInterceptorAdapter(interceptor);
public MappedInterceptor(String[] includePatterns, WebRequestInterceptor interceptor) {
this(includePatterns, null, interceptor);
}

/**
* Create a new MappedInterceptor instance.
* @param includePatterns the path patterns to map with a {@code null} value matching to all paths
* @param interceptor the WebRequestInterceptor instance to map to the given patterns
*/
public MappedInterceptor(String[] includePatterns, String[] excludePatterns, WebRequestInterceptor interceptor) {
this(includePatterns, excludePatterns, new WebRequestHandlerInterceptorAdapter(interceptor));
}


/**
* The path into the application the interceptor is mapped to.
*/
public String[] getPathPatterns() {
return this.pathPatterns;
return this.includePatterns;
}

/**
Expand All @@ -69,19 +89,26 @@ public String[] getPathPatterns() {
public HandlerInterceptor getInterceptor() {
return this.interceptor;
}

/**
* Returns {@code true} if the interceptor applies to the given request path.
* Returns {@code true} if the interceptor applies to the given request path.
* @param lookupPath the current request path
* @param pathMatcher a path matcher for path pattern matching
*/
public boolean matches(String lookupPath, PathMatcher pathMatcher) {
if (pathPatterns == null) {
if (this.excludePatterns != null) {
for (String pattern : this.excludePatterns) {
if (pathMatcher.match(pattern, lookupPath)) {
return false;
}
}
}
if (this.includePatterns == null) {
return true;
}
else {
for (String pathPattern : pathPatterns) {
if (pathMatcher.match(pathPattern, lookupPath)) {
for (String pattern : this.includePatterns) {
if (pathMatcher.match(pattern, lookupPath)) {
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,18 @@
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:element name="exclude-mapping" minOccurs="0" maxOccurs="unbounded">
<xsd:complexType>
<xsd:attribute name="path" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
A path into the application that should not be intercepted by this interceptor.
Exact path mapping URIs (such as "/admin") are supported as well as Ant-stype path patterns (such as /admin/**).
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
</xsd:element>
<xsd:choice>
<xsd:element ref="beans:bean">
<xsd:annotation>
Expand Down
Loading

0 comments on commit 92759ed

Please sign in to comment.