SPR-7354 - Added equivalent of JAX-RS @Consumes to Spring MVC
This commit is contained in:
parent
7f247a6b27
commit
71aae405d5
|
|
@ -24,7 +24,6 @@ import java.util.Iterator;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
|
|
@ -128,7 +127,7 @@ public class RequestMappingHandlerMapping extends AbstractHandlerMethodMapping<R
|
|||
return new RequestMappingInfo(Arrays.asList(annotation.value()), Arrays.asList(annotation.method()),
|
||||
RequestConditionFactory.parseParams(annotation.params()),
|
||||
RequestConditionFactory.parseHeaders(annotation.headers()),
|
||||
RequestConditionFactory.parseConsumes());
|
||||
RequestConditionFactory.parseConsumes(annotation.consumes(), annotation.headers()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -240,6 +239,10 @@ public class RequestMappingHandlerMapping extends AbstractHandlerMethodMapping<R
|
|||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
result = mapping.getConsumes().compareTo(otherMapping.getConsumes());
|
||||
if (result != 0) {
|
||||
return result;
|
||||
}
|
||||
/*
|
||||
TODO: fix
|
||||
result = compareAcceptHeaders(mapping.getAcceptHeaderMediaTypes(), otherMapping.getAcceptHeaderMediaTypes());
|
||||
|
|
|
|||
|
|
@ -22,14 +22,14 @@ import java.util.Collections;
|
|||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.util.PathMatcher;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.bind.annotation.RequestMethod;
|
||||
import org.springframework.web.servlet.mvc.method.condition.RequestCondition;
|
||||
import org.springframework.web.servlet.mvc.method.condition.RequestConditionFactory;
|
||||
import org.springframework.web.servlet.mvc.method.condition.ConsumesRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.method.condition.HeadersRequestCondition;
|
||||
import org.springframework.web.servlet.mvc.method.condition.ParamsRequestCondition;
|
||||
|
||||
/**
|
||||
* Contains a set of conditions to match to a given request such as URL patterns, HTTP methods, request parameters
|
||||
|
|
@ -49,16 +49,16 @@ public final class RequestMappingInfo {
|
|||
|
||||
private final Set<RequestMethod> methods;
|
||||
|
||||
private final RequestCondition paramsCondition;
|
||||
private final ParamsRequestCondition paramsCondition;
|
||||
|
||||
private final RequestCondition headersCondition;
|
||||
private final HeadersRequestCondition headersCondition;
|
||||
|
||||
private final RequestCondition consumesCondition;
|
||||
private final ConsumesRequestCondition consumesCondition;
|
||||
|
||||
private int hash;
|
||||
|
||||
/**
|
||||
* Creates a new {@code RequestKey} instance with the given URL patterns and HTTP methods.
|
||||
* Creates a new {@code RequestMappingInfo} instance with the given URL patterns and HTTP methods.
|
||||
*
|
||||
* <p>Package protected for testing purposes.
|
||||
*/
|
||||
|
|
@ -67,18 +67,18 @@ public final class RequestMappingInfo {
|
|||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code RequestKey} instance with a full set of conditions.
|
||||
* Creates a new {@code RequestMappingInfo} instance with a full set of conditions.
|
||||
*/
|
||||
public RequestMappingInfo(Collection<String> patterns,
|
||||
Collection<RequestMethod> methods,
|
||||
RequestCondition paramsCondition,
|
||||
RequestCondition headersCondition,
|
||||
RequestCondition consumesCondition) {
|
||||
ParamsRequestCondition paramsCondition,
|
||||
HeadersRequestCondition headersCondition,
|
||||
ConsumesRequestCondition consumesCondition) {
|
||||
this.patterns = asUnmodifiableSet(prependLeadingSlash(patterns));
|
||||
this.methods = asUnmodifiableSet(methods);
|
||||
this.paramsCondition = paramsCondition != null ? paramsCondition : RequestConditionFactory.trueCondition();
|
||||
this.headersCondition = headersCondition != null ? headersCondition : RequestConditionFactory.trueCondition();
|
||||
this.consumesCondition = consumesCondition != null ? consumesCondition : RequestConditionFactory.trueCondition();
|
||||
this.paramsCondition = paramsCondition != null ? paramsCondition : new ParamsRequestCondition();
|
||||
this.headersCondition = headersCondition != null ? headersCondition : new HeadersRequestCondition();
|
||||
this.consumesCondition = consumesCondition != null ? consumesCondition : new ConsumesRequestCondition();
|
||||
}
|
||||
|
||||
private static Set<String> prependLeadingSlash(Collection<String> patterns) {
|
||||
|
|
@ -118,21 +118,28 @@ public final class RequestMappingInfo {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns the request parameters of this request key.
|
||||
* Returns the request parameters conditions of this request key.
|
||||
*/
|
||||
public RequestCondition getParams() {
|
||||
public ParamsRequestCondition getParams() {
|
||||
return paramsCondition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the request headers of this request key.
|
||||
* Returns the request headers conditions of this request key.
|
||||
*/
|
||||
public RequestCondition getHeaders() {
|
||||
public HeadersRequestCondition getHeaders() {
|
||||
return headersCondition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines this {@code RequestKey} with another as follows:
|
||||
* Returns the request consumes conditions of this request key.
|
||||
*/
|
||||
public ConsumesRequestCondition getConsumes() {
|
||||
return consumesCondition;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines this {@code RequestMappingInfo} with another as follows:
|
||||
* <ul>
|
||||
* <li>URL patterns:
|
||||
* <ul>
|
||||
|
|
@ -141,9 +148,9 @@ public final class RequestMappingInfo {
|
|||
* <li>If neither contains patterns use ""
|
||||
* </ul>
|
||||
* <li>HTTP methods are combined as union of all HTTP methods listed in both keys.
|
||||
* <li>Request parameter are combined into a logical AND.
|
||||
* <li>Request header are combined into a logical AND.
|
||||
* <li>Consumes .. TODO
|
||||
* <li>Request parameters are combined as per {@link ParamsRequestCondition#combine(ParamsRequestCondition)}.
|
||||
* <li>Request headers are combined as per {@link HeadersRequestCondition#combine(HeadersRequestCondition)}.
|
||||
* <li>Consumes are combined as per {@link ConsumesRequestCondition#combine(ConsumesRequestCondition)}.
|
||||
* </ul>
|
||||
* @param methodKey the key to combine with
|
||||
* @param pathMatcher to {@linkplain PathMatcher#combine(String, String) combine} the patterns
|
||||
|
|
@ -152,9 +159,9 @@ public final class RequestMappingInfo {
|
|||
public RequestMappingInfo combine(RequestMappingInfo methodKey, PathMatcher pathMatcher) {
|
||||
Set<String> patterns = combinePatterns(this.patterns, methodKey.patterns, pathMatcher);
|
||||
Set<RequestMethod> methods = union(this.methods, methodKey.methods);
|
||||
RequestCondition params = RequestConditionFactory.and(this.paramsCondition, methodKey.paramsCondition);
|
||||
RequestCondition headers = RequestConditionFactory.and(this.headersCondition, methodKey.headersCondition);
|
||||
RequestCondition consumes = RequestConditionFactory.mostSpecific(methodKey.consumesCondition, this.consumesCondition);
|
||||
ParamsRequestCondition params = this.paramsCondition.combine(methodKey.paramsCondition);
|
||||
HeadersRequestCondition headers = this.headersCondition.combine(methodKey.headersCondition);
|
||||
ConsumesRequestCondition consumes = this.consumesCondition.combine(methodKey.consumesCondition);
|
||||
|
||||
return new RequestMappingInfo(patterns, methods, params, headers, consumes);
|
||||
}
|
||||
|
|
@ -189,7 +196,7 @@ public final class RequestMappingInfo {
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@code RequestKey} that contains all conditions of this key that are relevant to the request.
|
||||
* Returns a new {@code RequestMappingInfo} that contains all conditions of this key that are relevant to the request.
|
||||
* <ul>
|
||||
* <li>The list of URL path patterns is trimmed to contain the patterns that match the URL with matching patterns
|
||||
* sorted via {@link PathMatcher#getPatternComparator(String)}.
|
||||
|
|
@ -203,16 +210,20 @@ public final class RequestMappingInfo {
|
|||
* @return a new request key that contains all matching attributes, or {@code null} if not all conditions match
|
||||
*/
|
||||
public RequestMappingInfo getMatchingRequestMapping(String lookupPath, HttpServletRequest request, PathMatcher pathMatcher) {
|
||||
if (!checkMethod(request) || !paramsCondition.match(request) || !headersCondition.match(request) ||
|
||||
!consumesCondition.match(request)) {
|
||||
ParamsRequestCondition matchingParamsCondition = paramsCondition.getMatchingCondition(request);
|
||||
HeadersRequestCondition matchingHeadersCondition = headersCondition.getMatchingCondition(request);
|
||||
ConsumesRequestCondition matchingConsumesCondition = consumesCondition.getMatchingCondition(request);
|
||||
|
||||
if (!checkMethod(request) || matchingParamsCondition == null || matchingHeadersCondition == null ||
|
||||
matchingConsumesCondition == null) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
List<String> matchingPatterns = getMatchingPatterns(lookupPath, request, pathMatcher);
|
||||
if (!matchingPatterns.isEmpty()) {
|
||||
Set<RequestMethod> matchingMethods = getMatchingMethod(request);
|
||||
return new RequestMappingInfo(matchingPatterns, matchingMethods, this.paramsCondition, this.headersCondition,
|
||||
this.consumesCondition);
|
||||
return new RequestMappingInfo(matchingPatterns, matchingMethods, matchingParamsCondition,
|
||||
matchingHeadersCondition, matchingConsumesCondition);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
|
|
@ -277,7 +288,8 @@ public final class RequestMappingInfo {
|
|||
RequestMappingInfo other = (RequestMappingInfo) obj;
|
||||
return (this.patterns.equals(other.patterns) && this.methods.equals(other.methods) &&
|
||||
this.paramsCondition.equals(other.paramsCondition) &&
|
||||
this.headersCondition.equals(other.headersCondition));
|
||||
this.headersCondition.equals(other.headersCondition) &&
|
||||
this.consumesCondition.equals(other.consumesCondition));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -290,6 +302,7 @@ public final class RequestMappingInfo {
|
|||
result = 31 * result + methods.hashCode();
|
||||
result = 31 * result + paramsCondition.hashCode();
|
||||
result = 31 * result + headersCondition.hashCode();
|
||||
result = 31 * result + consumesCondition.hashCode();
|
||||
hash = result;
|
||||
}
|
||||
return result;
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||
* @author Arjen Poutsma
|
||||
* @since 3.1
|
||||
*/
|
||||
abstract class AbstractNameValueCondition<T> extends AbstractRequestCondition {
|
||||
abstract class AbstractNameValueCondition<T> implements RequestCondition {
|
||||
|
||||
protected final String name;
|
||||
|
||||
|
|
@ -65,11 +65,6 @@ abstract class AbstractNameValueCondition<T> extends AbstractRequestCondition {
|
|||
|
||||
protected abstract boolean matchValue(HttpServletRequest request);
|
||||
|
||||
@Override
|
||||
public int getSpecificity() {
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = name.hashCode();
|
||||
|
|
|
|||
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2011 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.web.servlet.mvc.method.condition;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link RequestCondition} that provides a standard {@link Comparable} implementation based on
|
||||
* the conditions {@linkplain #getSpecificity() specificity}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.1
|
||||
*/
|
||||
public abstract class AbstractRequestCondition implements RequestCondition {
|
||||
|
||||
/**
|
||||
* Returns the conditions specificity. More specific conditions should return a higher value than ones which are less
|
||||
* so.
|
||||
*
|
||||
* @return the conditions specificity
|
||||
*/
|
||||
protected abstract int getSpecificity();
|
||||
|
||||
public int compareTo(RequestCondition o) {
|
||||
AbstractRequestCondition other = (AbstractRequestCondition) o;
|
||||
return other.getSpecificity() - this.getSpecificity();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -16,57 +16,186 @@
|
|||
|
||||
package org.springframework.web.servlet.mvc.method.condition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* Represents a collection of consumes conditions, typically obtained from {@link
|
||||
* org.springframework.web.bind.annotation.RequestMapping#consumes() @RequestMapping.consumes()}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see RequestConditionFactory#parseHeaders(String...)
|
||||
* @since 3.1
|
||||
*/
|
||||
class ConsumesRequestCondition extends AbstractRequestCondition {
|
||||
public class ConsumesRequestCondition
|
||||
extends LogicalDisjunctionRequestCondition<ConsumesRequestCondition.ConsumeRequestCondition>
|
||||
implements Comparable<ConsumesRequestCondition> {
|
||||
|
||||
private final MediaType mediaType;
|
||||
private final ConsumeRequestCondition mostSpecificCondition;
|
||||
|
||||
ConsumesRequestCondition(String mediaType) {
|
||||
this.mediaType = MediaType.parseMediaType(mediaType);
|
||||
ConsumesRequestCondition(Collection<ConsumeRequestCondition> conditions) {
|
||||
super(conditions);
|
||||
Assert.notEmpty(conditions, "'conditions' must not be empty");
|
||||
mostSpecificCondition = getMostSpecificCondition();
|
||||
}
|
||||
|
||||
public boolean match(HttpServletRequest request) {
|
||||
MediaType contentType;
|
||||
if (StringUtils.hasLength(request.getContentType())) {
|
||||
contentType = MediaType.parseMediaType(request.getContentType());
|
||||
private ConsumeRequestCondition getMostSpecificCondition() {
|
||||
List<ConsumeRequestCondition> conditions = new ArrayList<ConsumeRequestCondition>(getConditions());
|
||||
Collections.sort(conditions);
|
||||
return conditions.get(0);
|
||||
}
|
||||
|
||||
ConsumesRequestCondition(String... consumes) {
|
||||
this(parseConditions(Arrays.asList(consumes)));
|
||||
}
|
||||
|
||||
private static Set<ConsumeRequestCondition> parseConditions(List<String> consumes) {
|
||||
if (consumes.isEmpty()) {
|
||||
consumes = Collections.singletonList("*/*");
|
||||
}
|
||||
Set<ConsumeRequestCondition> conditions = new LinkedHashSet<ConsumeRequestCondition>(consumes.size());
|
||||
for (String consume : consumes) {
|
||||
conditions.add(new ConsumeRequestCondition(consume));
|
||||
}
|
||||
return conditions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an default set of consumes request conditions.
|
||||
*/
|
||||
public ConsumesRequestCondition() {
|
||||
this(Collections.singleton(new ConsumeRequestCondition(MediaType.ALL, false)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@code RequestCondition} that contains all conditions of this key that match the request.
|
||||
*
|
||||
* @param request the request
|
||||
* @return a new request condition that contains all matching attributes, or {@code null} if not all conditions match
|
||||
*/
|
||||
public ConsumesRequestCondition getMatchingCondition(HttpServletRequest request) {
|
||||
Set<ConsumeRequestCondition> matchingConditions = new LinkedHashSet<ConsumeRequestCondition>(getConditions());
|
||||
for (Iterator<ConsumeRequestCondition> iterator = matchingConditions.iterator(); iterator.hasNext();) {
|
||||
ConsumeRequestCondition condition = iterator.next();
|
||||
if (!condition.match(request)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
if (matchingConditions.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
contentType = MediaType.APPLICATION_OCTET_STREAM;
|
||||
return new ConsumesRequestCondition(matchingConditions);
|
||||
}
|
||||
return this.mediaType.includes(contentType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSpecificity() {
|
||||
return 1;
|
||||
/**
|
||||
* Combines this collection of request condition with another. Returns {@code other}, unless it has the default
|
||||
* value (i.e. <code>*/*</code>).
|
||||
*
|
||||
* @param other the condition to combine with
|
||||
*/
|
||||
public ConsumesRequestCondition combine(ConsumesRequestCondition other) {
|
||||
return !other.hasDefaultValue() ? other : this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
private boolean hasDefaultValue() {
|
||||
Set<ConsumeRequestCondition> conditions = getConditions();
|
||||
if (conditions.size() == 1) {
|
||||
ConsumeRequestCondition condition = conditions.iterator().next();
|
||||
return condition.getMediaType().equals(MediaType.ALL);
|
||||
}
|
||||
if (obj != null && obj instanceof ConsumesRequestCondition) {
|
||||
ConsumesRequestCondition other = (ConsumesRequestCondition) obj;
|
||||
return this.mediaType.equals(other.mediaType);
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (mediaType != null) {
|
||||
public int compareTo(ConsumesRequestCondition other) {
|
||||
return this.mostSpecificCondition.compareTo(other.mostSpecificCondition);
|
||||
}
|
||||
|
||||
private static MediaType getContentType(HttpServletRequest request) {
|
||||
if (StringUtils.hasLength(request.getContentType())) {
|
||||
return MediaType.parseMediaType(request.getContentType());
|
||||
}
|
||||
else {
|
||||
return MediaType.APPLICATION_OCTET_STREAM;
|
||||
}
|
||||
}
|
||||
|
||||
static class ConsumeRequestCondition implements RequestCondition, Comparable<ConsumeRequestCondition> {
|
||||
|
||||
private final MediaType mediaType;
|
||||
|
||||
private final boolean isNegated;
|
||||
|
||||
ConsumeRequestCondition(String expression) {
|
||||
if (expression.startsWith("!")) {
|
||||
isNegated = true;
|
||||
expression = expression.substring(1);
|
||||
}
|
||||
else {
|
||||
isNegated = false;
|
||||
}
|
||||
this.mediaType = MediaType.parseMediaType(expression);
|
||||
}
|
||||
|
||||
ConsumeRequestCondition(MediaType mediaType, boolean isNegated) {
|
||||
this.mediaType = mediaType;
|
||||
this.isNegated = isNegated;
|
||||
}
|
||||
|
||||
public boolean match(HttpServletRequest request) {
|
||||
MediaType contentType = getContentType(request);
|
||||
boolean match = this.mediaType.includes(contentType);
|
||||
return !isNegated ? match : !match;
|
||||
}
|
||||
|
||||
public int compareTo(ConsumeRequestCondition other) {
|
||||
return MediaType.SPECIFICITY_COMPARATOR.compare(this.mediaType, other.mediaType);
|
||||
}
|
||||
|
||||
MediaType getMediaType() {
|
||||
return mediaType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj != null && obj instanceof ConsumeRequestCondition) {
|
||||
ConsumeRequestCondition other = (ConsumeRequestCondition) obj;
|
||||
return (this.mediaType.equals(other.mediaType)) && (this.isNegated == other.isNegated);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return mediaType.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
if (isNegated) {
|
||||
builder.append('!');
|
||||
}
|
||||
builder.append(mediaType.toString());
|
||||
return builder.toString();
|
||||
}
|
||||
return builder.toString();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,64 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2011 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.web.servlet.mvc.method.condition;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Request header name-value condition.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Arjen Poutsma
|
||||
* @see org.springframework.web.bind.annotation.RequestMapping#headers()
|
||||
* @since 3.1
|
||||
*/
|
||||
class HeaderRequestCondition extends AbstractNameValueCondition<String> {
|
||||
|
||||
public HeaderRequestCondition(String expression) {
|
||||
super(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String parseValue(String valueExpression) {
|
||||
return valueExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchName(HttpServletRequest request) {
|
||||
return request.getHeader(name) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchValue(HttpServletRequest request) {
|
||||
return value.equals(request.getHeader(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj != null && obj instanceof HeaderRequestCondition) {
|
||||
HeaderRequestCondition other = (HeaderRequestCondition) obj;
|
||||
return ((this.name.equalsIgnoreCase(other.name)) &&
|
||||
(this.value != null ? this.value.equals(other.value) : other.value == null) &&
|
||||
this.isNegated == other.isNegated);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright 2002-2011 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.web.servlet.mvc.method.condition;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
* Represents a collection of header request conditions, typically obtained from {@link
|
||||
* org.springframework.web.bind.annotation.RequestMapping#headers() @RequestMapping.headers()}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see RequestConditionFactory#parseHeaders(String...)
|
||||
* @since 3.1
|
||||
*/
|
||||
public class HeadersRequestCondition
|
||||
extends LogicalConjunctionRequestCondition<HeadersRequestCondition.HeaderRequestCondition>
|
||||
implements Comparable<HeadersRequestCondition> {
|
||||
|
||||
HeadersRequestCondition(Collection<HeaderRequestCondition> conditions) {
|
||||
super(conditions);
|
||||
}
|
||||
|
||||
HeadersRequestCondition(String... headers) {
|
||||
this(parseConditions(Arrays.asList(headers)));
|
||||
}
|
||||
|
||||
private static Set<HeaderRequestCondition> parseConditions(Collection<String> params) {
|
||||
Set<HeaderRequestCondition> conditions = new LinkedHashSet<HeaderRequestCondition>(params.size());
|
||||
for (String param : params) {
|
||||
conditions.add(new HeaderRequestCondition(param));
|
||||
}
|
||||
return conditions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty set of header request conditions.
|
||||
*/
|
||||
public HeadersRequestCondition() {
|
||||
this(Collections.<HeaderRequestCondition>emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@code RequestCondition} that contains all conditions of this key that match the request.
|
||||
*
|
||||
* @param request the request
|
||||
* @return a new request condition that contains all matching attributes, or {@code null} if not all conditions match
|
||||
*/
|
||||
public HeadersRequestCondition getMatchingCondition(HttpServletRequest request) {
|
||||
return match(request) ? this : null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Combines this collection of request condition with another by combining all header request conditions into a
|
||||
* logical AND.
|
||||
*
|
||||
* @param other the condition to combine with
|
||||
*/
|
||||
public HeadersRequestCondition combine(HeadersRequestCondition other) {
|
||||
Set<HeaderRequestCondition> conditions = new LinkedHashSet<HeaderRequestCondition>(getConditions());
|
||||
conditions.addAll(other.getConditions());
|
||||
return new HeadersRequestCondition(conditions);
|
||||
}
|
||||
|
||||
|
||||
public int compareTo(HeadersRequestCondition other) {
|
||||
return other.getConditions().size() - this.getConditions().size();
|
||||
}
|
||||
|
||||
static class HeaderRequestCondition extends AbstractNameValueCondition<String> {
|
||||
|
||||
public HeaderRequestCondition(String expression) {
|
||||
super(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String parseValue(String valueExpression) {
|
||||
return valueExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchName(HttpServletRequest request) {
|
||||
return request.getHeader(name) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchValue(HttpServletRequest request) {
|
||||
return value.equals(request.getHeader(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj != null && obj instanceof HeaderRequestCondition) {
|
||||
HeaderRequestCondition other = (HeaderRequestCondition) obj;
|
||||
return ((this.name.equalsIgnoreCase(other.name)) &&
|
||||
(this.value != null ? this.value.equals(other.value) : other.value == null) &&
|
||||
this.isNegated == other.isNegated);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = name.toLowerCase().hashCode();
|
||||
result = 31 * result + (value != null ? value.hashCode() : 0);
|
||||
result = 31 * result + (isNegated ? 1 : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -16,7 +16,8 @@
|
|||
|
||||
package org.springframework.web.servlet.mvc.method.condition;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import java.util.Set;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
|
|
@ -25,14 +26,18 @@ import javax.servlet.http.HttpServletRequest;
|
|||
* @author Arjen Poutsma
|
||||
* @since 3.1
|
||||
*/
|
||||
class LogicalConjunctionRequestCondition extends RequestConditionComposite {
|
||||
class LogicalConjunctionRequestCondition<T extends RequestCondition> extends RequestConditionComposite<T> {
|
||||
|
||||
LogicalConjunctionRequestCondition(List<RequestCondition> conditions) {
|
||||
LogicalConjunctionRequestCondition(Collection<T> conditions) {
|
||||
super(conditions);
|
||||
}
|
||||
|
||||
public boolean match(HttpServletRequest request) {
|
||||
for (RequestCondition condition : conditions) {
|
||||
Set<T> conditions = getConditions();
|
||||
if (conditions.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
for (T condition : conditions) {
|
||||
if (!condition.match(request)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -40,6 +45,7 @@ class LogicalConjunctionRequestCondition extends RequestConditionComposite {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected String getToStringInfix() {
|
||||
return " && ";
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
package org.springframework.web.servlet.mvc.method.condition;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Collection;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
/**
|
||||
|
|
@ -25,14 +25,14 @@ import javax.servlet.http.HttpServletRequest;
|
|||
* @author Arjen Poutsma
|
||||
* @since 3.1
|
||||
*/
|
||||
class LogicalDisjunctionRequestCondition extends RequestConditionComposite {
|
||||
class LogicalDisjunctionRequestCondition<T extends RequestCondition> extends RequestConditionComposite<T> {
|
||||
|
||||
LogicalDisjunctionRequestCondition(List<RequestCondition> conditions) {
|
||||
LogicalDisjunctionRequestCondition(Collection<T> conditions) {
|
||||
super(conditions);
|
||||
}
|
||||
|
||||
public boolean match(HttpServletRequest request) {
|
||||
for (RequestCondition condition : conditions) {
|
||||
for (RequestCondition condition : getConditions()) {
|
||||
if (condition.match(request)) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2011 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.web.servlet.mvc.method.condition;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link RequestCondition} implementation that represents a logical NOT (i.e. !).
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @since 3.1
|
||||
*/
|
||||
class LogicalNegationRequestCondition extends AbstractRequestCondition {
|
||||
|
||||
private final RequestCondition requestCondition;
|
||||
|
||||
LogicalNegationRequestCondition(RequestCondition requestCondition) {
|
||||
Assert.notNull(requestCondition, "'requestCondition' must not be null");
|
||||
this.requestCondition = requestCondition;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSpecificity() {
|
||||
if (requestCondition instanceof AbstractRequestCondition) {
|
||||
return ((AbstractRequestCondition) requestCondition).getSpecificity();
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean match(HttpServletRequest request) {
|
||||
return !requestCondition.match(request);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o != null && o instanceof LogicalNegationRequestCondition) {
|
||||
LogicalNegationRequestCondition other = (LogicalNegationRequestCondition) o;
|
||||
return this.requestCondition.equals(other.requestCondition);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return requestCondition.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "!(" + requestCondition.toString() + ")";
|
||||
}
|
||||
}
|
||||
|
|
@ -1,73 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2011 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.web.servlet.mvc.method.condition;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
/**
|
||||
* A RequestCondition that for headers that contain {@link org.springframework.http.MediaType MediaTypes}.
|
||||
*/
|
||||
class MediaTypeHeaderRequestCondition extends AbstractNameValueCondition<List<MediaType>> {
|
||||
|
||||
public MediaTypeHeaderRequestCondition(String expression) {
|
||||
super(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<MediaType> parseValue(String valueExpression) {
|
||||
return Collections.unmodifiableList(MediaType.parseMediaTypes(valueExpression));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchName(HttpServletRequest request) {
|
||||
return request.getHeader(name) != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchValue(HttpServletRequest request) {
|
||||
List<MediaType> requestMediaTypes = MediaType.parseMediaTypes(request.getHeader(name));
|
||||
|
||||
for (MediaType mediaType : this.value) {
|
||||
for (MediaType requestMediaType : requestMediaTypes) {
|
||||
if (mediaType.includes(requestMediaType)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj != null && obj instanceof MediaTypeHeaderRequestCondition) {
|
||||
MediaTypeHeaderRequestCondition other = (MediaTypeHeaderRequestCondition) obj;
|
||||
return ((this.name.equalsIgnoreCase(other.name)) &&
|
||||
(this.value != null ? this.value.equals(other.value) : other.value == null) &&
|
||||
this.isNegated == other.isNegated);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -1,66 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2011 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.web.servlet.mvc.method.condition;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
* Request parameter name-value condition.
|
||||
*
|
||||
* @author Rossen Stoyanchev
|
||||
* @author Arjen Poutsma
|
||||
* @see org.springframework.web.bind.annotation.RequestMapping#params()
|
||||
* @since 3.1
|
||||
*/
|
||||
class ParamRequestCondition extends AbstractNameValueCondition<String> {
|
||||
|
||||
ParamRequestCondition(String expression) {
|
||||
super(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String parseValue(String valueExpression) {
|
||||
return valueExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchName(HttpServletRequest request) {
|
||||
return WebUtils.hasSubmitParameter(request, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchValue(HttpServletRequest request) {
|
||||
return value.equals(request.getParameter(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj != null && obj instanceof ParamRequestCondition) {
|
||||
ParamRequestCondition other = (ParamRequestCondition) obj;
|
||||
return ((this.name.equals(other.name)) &&
|
||||
(this.value != null ? this.value.equals(other.value) : other.value == null) &&
|
||||
this.isNegated == other.isNegated);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,126 @@
|
|||
/*
|
||||
* Copyright 2002-2011 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.web.servlet.mvc.method.condition;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.springframework.web.util.WebUtils;
|
||||
|
||||
/**
|
||||
* Represents a collection of parameter request conditions, typically obtained from {@link
|
||||
* org.springframework.web.bind.annotation.RequestMapping#params() @RequestMapping.params()}.
|
||||
*
|
||||
* @author Arjen Poutsma
|
||||
* @see RequestConditionFactory#parseParams(String...)
|
||||
* @since 3.1
|
||||
*/
|
||||
public class ParamsRequestCondition
|
||||
extends LogicalConjunctionRequestCondition<ParamsRequestCondition.ParamRequestCondition>
|
||||
implements Comparable<ParamsRequestCondition> {
|
||||
|
||||
private ParamsRequestCondition(Collection<ParamRequestCondition> conditions) {
|
||||
super(conditions);
|
||||
}
|
||||
|
||||
ParamsRequestCondition(String... params) {
|
||||
this(parseConditions(Arrays.asList(params)));
|
||||
}
|
||||
|
||||
private static Set<ParamRequestCondition> parseConditions(List<String> params) {
|
||||
Set<ParamRequestCondition> conditions = new LinkedHashSet<ParamRequestCondition>(params.size());
|
||||
for (String param : params) {
|
||||
conditions.add(new ParamRequestCondition(param));
|
||||
}
|
||||
return conditions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an empty set of parameter request conditions.
|
||||
*/
|
||||
public ParamsRequestCondition() {
|
||||
this(Collections.<ParamRequestCondition>emptySet());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@code RequestCondition} that contains all conditions of this key that match the request.
|
||||
*
|
||||
* @param request the request
|
||||
* @return a new request condition that contains all matching attributes, or {@code null} if not all conditions match
|
||||
*/
|
||||
public ParamsRequestCondition getMatchingCondition(HttpServletRequest request) {
|
||||
return match(request) ? this : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines this collection of request condition with another by combining all parameter request conditions into a
|
||||
* logical AND.
|
||||
*
|
||||
* @param other the condition to combine with
|
||||
*/
|
||||
public ParamsRequestCondition combine(ParamsRequestCondition other) {
|
||||
Set<ParamRequestCondition> conditions = new LinkedHashSet<ParamRequestCondition>(getConditions());
|
||||
conditions.addAll(other.getConditions());
|
||||
return new ParamsRequestCondition(conditions);
|
||||
}
|
||||
|
||||
public int compareTo(ParamsRequestCondition other) {
|
||||
return other.getConditions().size() - this.getConditions().size();
|
||||
}
|
||||
|
||||
static class ParamRequestCondition extends AbstractNameValueCondition<String> {
|
||||
|
||||
ParamRequestCondition(String expression) {
|
||||
super(expression);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String parseValue(String valueExpression) {
|
||||
return valueExpression;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchName(HttpServletRequest request) {
|
||||
return WebUtils.hasSubmitParameter(request, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchValue(HttpServletRequest request) {
|
||||
return value.equals(request.getParameter(name));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (obj != null && obj instanceof ParamRequestCondition) {
|
||||
ParamRequestCondition other = (ParamRequestCondition) obj;
|
||||
return ((this.name.equals(other.name)) &&
|
||||
(this.value != null ? this.value.equals(other.value) : other.value == null) &&
|
||||
this.isNegated == other.isNegated);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -29,7 +29,7 @@ import javax.servlet.http.HttpServletRequest;
|
|||
* @see RequestConditionFactory
|
||||
* @since 3.1
|
||||
*/
|
||||
public interface RequestCondition extends Comparable<RequestCondition> {
|
||||
public interface RequestCondition {
|
||||
|
||||
/**
|
||||
* Indicates whether this condition matches against the given servlet request.
|
||||
|
|
|
|||
|
|
@ -16,11 +16,11 @@
|
|||
|
||||
package org.springframework.web.servlet.mvc.method.condition;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Abstract base class for {@link RequestCondition} implementations that wrap other request conditions.
|
||||
|
|
@ -28,25 +28,16 @@ import org.springframework.util.Assert;
|
|||
* @author Arjen Poutsma
|
||||
* @since 3.1
|
||||
*/
|
||||
abstract class RequestConditionComposite extends AbstractRequestCondition {
|
||||
abstract class RequestConditionComposite<T extends RequestCondition> implements RequestCondition {
|
||||
|
||||
protected final List<RequestCondition> conditions;
|
||||
private final Set<T> conditions;
|
||||
|
||||
protected RequestConditionComposite(List<RequestCondition> conditions) {
|
||||
Assert.notEmpty(conditions, "'conditions' must not be empty");
|
||||
this.conditions = Collections.unmodifiableList(conditions);
|
||||
protected RequestConditionComposite(Collection<T> conditions) {
|
||||
this.conditions = Collections.unmodifiableSet(new LinkedHashSet<T>(conditions));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSpecificity() {
|
||||
int weight = 0;
|
||||
for (RequestCondition condition : conditions) {
|
||||
if (condition instanceof AbstractRequestCondition) {
|
||||
AbstractRequestCondition abstractRequestCondition = (AbstractRequestCondition) condition;
|
||||
weight += abstractRequestCondition.getSpecificity();
|
||||
}
|
||||
}
|
||||
return weight;
|
||||
protected Set<T> getConditions() {
|
||||
return conditions;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -70,7 +61,7 @@ abstract class RequestConditionComposite extends AbstractRequestCondition {
|
|||
public String toString() {
|
||||
StringBuilder builder = new StringBuilder("[");
|
||||
String infix = getToStringInfix();
|
||||
for (Iterator<RequestCondition> iterator = conditions.iterator(); iterator.hasNext();) {
|
||||
for (Iterator<T> iterator = conditions.iterator(); iterator.hasNext();) {
|
||||
RequestCondition condition = iterator.next();
|
||||
builder.append(condition.toString());
|
||||
if (iterator.hasNext()) {
|
||||
|
|
|
|||
|
|
@ -17,13 +17,12 @@
|
|||
package org.springframework.web.servlet.mvc.method.condition;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.http.MediaType;
|
||||
|
||||
/**
|
||||
* Factory for {@link RequestCondition} objects.
|
||||
|
|
@ -34,132 +33,9 @@ import org.springframework.util.StringUtils;
|
|||
*/
|
||||
public abstract class RequestConditionFactory {
|
||||
|
||||
private static final RequestCondition TRUE_CONDITION = new AbstractRequestCondition() {
|
||||
public boolean match(HttpServletRequest request) {
|
||||
return true;
|
||||
}
|
||||
private static final String CONTENT_TYPE_HEADER = "Content-Type";
|
||||
|
||||
@Override
|
||||
public int getSpecificity() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "TRUE";
|
||||
}
|
||||
};
|
||||
|
||||
private static final RequestCondition FALSE_CONDITION = new AbstractRequestCondition() {
|
||||
public boolean match(HttpServletRequest request) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getSpecificity() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FALSE";
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Returns a condition that always returns {@code true} for {@link RequestCondition#match(HttpServletRequest)}.
|
||||
*
|
||||
* @return a condition that returns {@code true}
|
||||
*/
|
||||
public static RequestCondition trueCondition() {
|
||||
return TRUE_CONDITION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a condition that always returns {@code false} for {@link RequestCondition#match(HttpServletRequest)}.
|
||||
*
|
||||
* @return a condition that returns {@code false}
|
||||
*/
|
||||
public static RequestCondition falseCondition() {
|
||||
return FALSE_CONDITION;
|
||||
}
|
||||
|
||||
public static RequestCondition mostSpecific(RequestCondition... conditions) {
|
||||
if (ObjectUtils.isEmpty(conditions)) {
|
||||
return trueCondition();
|
||||
}
|
||||
RequestCondition[] copy = new RequestCondition[conditions.length];
|
||||
System.arraycopy(conditions, 0, copy, 0, conditions.length);
|
||||
Arrays.sort(copy);
|
||||
return copy[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the given condition in a logical NOT, i.e. the returned condition will return {@code true} for {@link
|
||||
* RequestCondition#match(HttpServletRequest)} if the given condition return {@code false}, and vice-versa.
|
||||
*
|
||||
* @return a condition that represents a logical NOT
|
||||
*/
|
||||
public static RequestCondition not(RequestCondition condition) {
|
||||
if (condition == TRUE_CONDITION) {
|
||||
return falseCondition();
|
||||
}
|
||||
else if (condition == FALSE_CONDITION) {
|
||||
return trueCondition();
|
||||
}
|
||||
else {
|
||||
return new LogicalNegationRequestCondition(condition);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines the given conditions into a logical AND, i.e. the returned condition will return {@code true} for {@link
|
||||
* RequestCondition#match(HttpServletRequest)} if all of the given conditions do so.
|
||||
*
|
||||
* @param conditions the conditions
|
||||
* @return a condition that represents a logical AND
|
||||
*/
|
||||
public static RequestCondition and(RequestCondition... conditions) {
|
||||
List<RequestCondition> filteredConditions = new ArrayList<RequestCondition>(Arrays.asList(conditions));
|
||||
for (Iterator<RequestCondition> iterator = filteredConditions.iterator(); iterator.hasNext();) {
|
||||
RequestCondition condition = iterator.next();
|
||||
if (condition == TRUE_CONDITION) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
if (filteredConditions.isEmpty()) {
|
||||
return trueCondition();
|
||||
}
|
||||
else {
|
||||
return new LogicalConjunctionRequestCondition(filteredConditions);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Combines the given conditions into a logical OR, i.e. the returned condition will return {@code true} for {@link
|
||||
* RequestCondition#match(HttpServletRequest)} if any of the given conditions do so.
|
||||
*
|
||||
* @param conditions the conditions
|
||||
* @return a condition that represents a logical OR
|
||||
*/
|
||||
public static RequestCondition or(RequestCondition... conditions) {
|
||||
List<RequestCondition> filteredConditions = new ArrayList<RequestCondition>(Arrays.asList(conditions));
|
||||
for (Iterator<RequestCondition> iterator = filteredConditions.iterator(); iterator.hasNext();) {
|
||||
RequestCondition condition = iterator.next();
|
||||
if (condition == TRUE_CONDITION) {
|
||||
return trueCondition();
|
||||
}
|
||||
else if (condition == FALSE_CONDITION) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
if (filteredConditions.isEmpty()) {
|
||||
return trueCondition();
|
||||
}
|
||||
else {
|
||||
return new LogicalDisjunctionRequestCondition(filteredConditions);
|
||||
}
|
||||
}
|
||||
private static final String ACCEPT_HEADER = "Accept";
|
||||
|
||||
/**
|
||||
* Parses the given parameters, and returns them as a single request conditions.
|
||||
|
|
@ -168,15 +44,8 @@ public abstract class RequestConditionFactory {
|
|||
* @return the request condition
|
||||
* @see org.springframework.web.bind.annotation.RequestMapping#params()
|
||||
*/
|
||||
public static RequestCondition parseParams(String... params) {
|
||||
if (ObjectUtils.isEmpty(params)) {
|
||||
return trueCondition();
|
||||
}
|
||||
RequestCondition[] result = new RequestCondition[params.length];
|
||||
for (int i = 0; i < params.length; i++) {
|
||||
result[i] = new ParamRequestCondition(params[i]);
|
||||
}
|
||||
return and(result);
|
||||
public static ParamsRequestCondition parseParams(String... params) {
|
||||
return new ParamsRequestCondition(params);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -186,29 +55,22 @@ public abstract class RequestConditionFactory {
|
|||
* @return the request condition
|
||||
* @see org.springframework.web.bind.annotation.RequestMapping#headers()
|
||||
*/
|
||||
public static RequestCondition parseHeaders(String... headers) {
|
||||
if (ObjectUtils.isEmpty(headers)) {
|
||||
return trueCondition();
|
||||
}
|
||||
RequestCondition[] result = new RequestCondition[headers.length];
|
||||
for (int i = 0; i < headers.length; i++) {
|
||||
HeaderRequestCondition header = new HeaderRequestCondition(headers[i]);
|
||||
if ("Content-Type".equalsIgnoreCase(header.name) && StringUtils.hasLength(header.value)) {
|
||||
RequestCondition consumesCondition = new ConsumesRequestCondition(header.value);
|
||||
result[i] = header.isNegated ? not(consumesCondition) : consumesCondition;
|
||||
}
|
||||
else if (isMediaTypeHeader(header.name)) {
|
||||
result[i] = new MediaTypeHeaderRequestCondition(headers[i]);
|
||||
}
|
||||
else {
|
||||
result[i] = header;
|
||||
}
|
||||
}
|
||||
return and(result);
|
||||
}
|
||||
public static HeadersRequestCondition parseHeaders(String... headers) {
|
||||
HeadersRequestCondition headersCondition = new HeadersRequestCondition(headers);
|
||||
|
||||
private static boolean isMediaTypeHeader(String name) {
|
||||
return "Accept".equalsIgnoreCase(name) || "Content-Type".equalsIgnoreCase(name);
|
||||
// filter out Accept and Content-Type headers, they are dealt with by produces and consumes respectively
|
||||
Set<HeadersRequestCondition.HeaderRequestCondition> filteredConditions =
|
||||
new LinkedHashSet<HeadersRequestCondition.HeaderRequestCondition>(headersCondition.getConditions());
|
||||
|
||||
for (Iterator<HeadersRequestCondition.HeaderRequestCondition> iterator = filteredConditions.iterator();
|
||||
iterator.hasNext();) {
|
||||
HeadersRequestCondition.HeaderRequestCondition headerCondition = iterator.next();
|
||||
if (ACCEPT_HEADER.equalsIgnoreCase(headerCondition.name) ||
|
||||
CONTENT_TYPE_HEADER.equalsIgnoreCase(headerCondition.name)) {
|
||||
iterator.remove();
|
||||
}
|
||||
}
|
||||
return new HeadersRequestCondition(filteredConditions);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -218,15 +80,39 @@ public abstract class RequestConditionFactory {
|
|||
* @return the request condition
|
||||
* @see org.springframework.web.bind.annotation.RequestMapping#consumes()
|
||||
*/
|
||||
public static RequestCondition parseConsumes(String... consumes) {
|
||||
if (ObjectUtils.isEmpty(consumes)) {
|
||||
return trueCondition();
|
||||
public static ConsumesRequestCondition parseConsumes(String... consumes) {
|
||||
return new ConsumesRequestCondition(consumes);
|
||||
}
|
||||
|
||||
public static ConsumesRequestCondition parseConsumes(String[] consumes, String[] headers) {
|
||||
|
||||
List<ConsumesRequestCondition.ConsumeRequestCondition> allConditions = parseContentTypeHeaders(headers);
|
||||
|
||||
// ignore the default consumes() value if any content-type headers have been set
|
||||
boolean headersHasContentType = !allConditions.isEmpty();
|
||||
boolean consumesHasDefaultValue = consumes.length == 1 && consumes[0].equals("*/*");
|
||||
if (!headersHasContentType || !consumesHasDefaultValue) {
|
||||
for (String consume : consumes) {
|
||||
allConditions.add(new ConsumesRequestCondition.ConsumeRequestCondition(consume));
|
||||
}
|
||||
}
|
||||
RequestCondition[] result = new RequestCondition[consumes.length];
|
||||
for (int i = 0; i < consumes.length; i++) {
|
||||
result[i] = new ConsumesRequestCondition(consumes[i]);
|
||||
return new ConsumesRequestCondition(allConditions);
|
||||
}
|
||||
|
||||
private static List<ConsumesRequestCondition.ConsumeRequestCondition> parseContentTypeHeaders(String[] headers) {
|
||||
List<ConsumesRequestCondition.ConsumeRequestCondition> allConditions =
|
||||
new ArrayList<ConsumesRequestCondition.ConsumeRequestCondition>();
|
||||
HeadersRequestCondition headersCondition = new HeadersRequestCondition(headers);
|
||||
for (HeadersRequestCondition.HeaderRequestCondition headerCondition : headersCondition.getConditions()) {
|
||||
if (CONTENT_TYPE_HEADER.equalsIgnoreCase(headerCondition.name)) {
|
||||
List<MediaType> mediaTypes = MediaType.parseMediaTypes(headerCondition.value);
|
||||
for (MediaType mediaType : mediaTypes) {
|
||||
allConditions.add(
|
||||
new ConsumesRequestCondition.ConsumeRequestCondition(mediaType, headerCondition.isNegated));
|
||||
}
|
||||
}
|
||||
}
|
||||
return or(result);
|
||||
return allConditions;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,192 @@
|
|||
/*
|
||||
* Copyright 2002-2011 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.web.servlet.mvc.method.condition;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class ConsumesRequestConditionTests {
|
||||
|
||||
@Test
|
||||
public void consumesMatch() {
|
||||
RequestCondition condition = new ConsumesRequestCondition("text/plain");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContentType("text/plain");
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void negatedConsumesMatch() {
|
||||
RequestCondition condition = new ConsumesRequestCondition("!text/plain");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContentType("text/plain");
|
||||
|
||||
assertFalse(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void consumesWildcardMatch() {
|
||||
RequestCondition condition = new ConsumesRequestCondition("text/*");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContentType("text/plain");
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void consumesMultipleMatch() {
|
||||
RequestCondition condition = new ConsumesRequestCondition("text/plain", "application/xml");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContentType("text/plain");
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void consumesSingleNoMatch() {
|
||||
RequestCondition condition = new ConsumesRequestCondition("text/plain");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContentType("application/xml");
|
||||
|
||||
assertFalse(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareToSingle() {
|
||||
ConsumesRequestCondition condition1 = new ConsumesRequestCondition("text/plain");
|
||||
ConsumesRequestCondition condition2 = new ConsumesRequestCondition("text/*");
|
||||
|
||||
int result = condition1.compareTo(condition2);
|
||||
assertTrue("Invalid comparison result: " + result, result < 0);
|
||||
|
||||
result = condition2.compareTo(condition1);
|
||||
assertTrue("Invalid comparison result: " + result, result > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareToMultiple() {
|
||||
ConsumesRequestCondition condition1 = new ConsumesRequestCondition("*/*", "text/plain");
|
||||
ConsumesRequestCondition condition2 = new ConsumesRequestCondition("text/*", "text/plain;q=0.7");
|
||||
|
||||
int result = condition1.compareTo(condition2);
|
||||
assertTrue("Invalid comparison result: " + result, result < 0);
|
||||
|
||||
result = condition2.compareTo(condition1);
|
||||
assertTrue("Invalid comparison result: " + result, result > 0);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void combine() {
|
||||
ConsumesRequestCondition condition1 = new ConsumesRequestCondition("text/plain");
|
||||
ConsumesRequestCondition condition2 = new ConsumesRequestCondition("application/xml");
|
||||
|
||||
ConsumesRequestCondition result = condition1.combine(condition2);
|
||||
assertEquals(condition2, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void combineWithDefault() {
|
||||
ConsumesRequestCondition condition1 = new ConsumesRequestCondition("text/plain");
|
||||
ConsumesRequestCondition condition2 = new ConsumesRequestCondition("*/*");
|
||||
|
||||
ConsumesRequestCondition result = condition1.combine(condition2);
|
||||
assertEquals(condition1, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseConsumesAndHeaders() {
|
||||
String[] consumes = new String[] {"text/plain"};
|
||||
String[] headers = new String[]{"foo=bar", "content-type=application/xml,application/pdf"};
|
||||
ConsumesRequestCondition condition = RequestConditionFactory.parseConsumes(consumes, headers);
|
||||
|
||||
assertConditions(condition, "text/plain", "application/xml", "application/pdf");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void parseConsumesDefault() {
|
||||
String[] consumes = new String[] {"*/*"};
|
||||
String[] headers = new String[0];
|
||||
ConsumesRequestCondition condition = RequestConditionFactory.parseConsumes(consumes, headers);
|
||||
|
||||
assertConditions(condition, "*/*");
|
||||
}
|
||||
@Test
|
||||
public void parseConsumesDefaultAndHeaders() {
|
||||
String[] consumes = new String[] {"*/*"};
|
||||
String[] headers = new String[]{"foo=bar", "content-type=text/plain"};
|
||||
ConsumesRequestCondition condition = RequestConditionFactory.parseConsumes(consumes, headers);
|
||||
|
||||
assertConditions(condition, "text/plain");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMatchingCondition() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContentType("text/plain");
|
||||
|
||||
ConsumesRequestCondition condition = new ConsumesRequestCondition("text/plain", "application/xml");
|
||||
|
||||
ConsumesRequestCondition result = condition.getMatchingCondition(request);
|
||||
assertConditions(result, "text/plain");
|
||||
|
||||
condition = new ConsumesRequestCondition("application/xml");
|
||||
|
||||
result = condition.getMatchingCondition(request);
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
private void assertConditions(ConsumesRequestCondition condition, String... expected) {
|
||||
Set<ConsumesRequestCondition.ConsumeRequestCondition> conditions = condition.getConditions();
|
||||
assertEquals("Invalid amount of conditions", conditions.size(), expected.length);
|
||||
for (String s : expected) {
|
||||
boolean found = false;
|
||||
for (ConsumesRequestCondition.ConsumeRequestCondition requestCondition : conditions) {
|
||||
String conditionMediaType = requestCondition.getMediaType().toString();
|
||||
if (conditionMediaType.equals(s)) {
|
||||
found = true;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
if (!found) {
|
||||
fail("Condition [" + s + "] not found");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Copyright 2002-2011 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.web.servlet.mvc.method.condition;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class HeadersRequestConditionTests {
|
||||
|
||||
@Test
|
||||
public void headerEquals() {
|
||||
assertEquals(new HeadersRequestCondition("foo"), new HeadersRequestCondition("foo"));
|
||||
assertEquals(new HeadersRequestCondition("foo"), new HeadersRequestCondition("FOO"));
|
||||
assertFalse(new HeadersRequestCondition("foo").equals(new HeadersRequestCondition("bar")));
|
||||
assertEquals(new HeadersRequestCondition("foo=bar"), new HeadersRequestCondition("foo=bar"));
|
||||
assertEquals(new HeadersRequestCondition("foo=bar"), new HeadersRequestCondition("FOO=bar"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerPresent() {
|
||||
RequestCondition condition = new HeadersRequestCondition("accept");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Accept", "");
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerPresentNoMatch() {
|
||||
RequestCondition condition = new HeadersRequestCondition("foo");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("bar", "");
|
||||
|
||||
assertFalse(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerNotPresent() {
|
||||
RequestCondition condition = new HeadersRequestCondition("!accept");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerValueMatch() {
|
||||
RequestCondition condition = new HeadersRequestCondition("foo=bar");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("foo", "bar");
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerValueNoMatch() {
|
||||
RequestCondition condition = new HeadersRequestCondition("foo=bar");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("foo", "bazz");
|
||||
|
||||
assertFalse(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerCaseSensitiveValueMatch() {
|
||||
RequestCondition condition = new HeadersRequestCondition("foo=Bar");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("foo", "bar");
|
||||
|
||||
assertFalse(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerValueMatchNegated() {
|
||||
RequestCondition condition = new HeadersRequestCondition("foo!=bar");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("foo", "baz");
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareTo() {
|
||||
HeadersRequestCondition condition1 = new HeadersRequestCondition("foo", "bar", "baz");
|
||||
HeadersRequestCondition condition2 = new HeadersRequestCondition("foo", "bar");
|
||||
|
||||
int result = condition1.compareTo(condition2);
|
||||
assertTrue("Invalid comparison result: " + result, result < 0);
|
||||
|
||||
result = condition2.compareTo(condition1);
|
||||
assertTrue("Invalid comparison result: " + result, result > 0);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void combine() {
|
||||
HeadersRequestCondition condition1 = new HeadersRequestCondition("foo=bar");
|
||||
HeadersRequestCondition condition2 = new HeadersRequestCondition("foo=baz");
|
||||
|
||||
HeadersRequestCondition result = condition1.combine(condition2);
|
||||
Set<HeadersRequestCondition.HeaderRequestCondition> conditions = result.getConditions();
|
||||
assertEquals(2, conditions.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMatchingCondition() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("foo", "bar");
|
||||
|
||||
HeadersRequestCondition condition = new HeadersRequestCondition("foo");
|
||||
|
||||
HeadersRequestCondition result = condition.getMatchingCondition(request);
|
||||
assertEquals(condition, result);
|
||||
|
||||
condition = new HeadersRequestCondition("bar");
|
||||
|
||||
result = condition.getMatchingCondition(request);
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,129 @@
|
|||
/*
|
||||
* Copyright 2002-2011 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.web.servlet.mvc.method.condition;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class ParamsRequestConditionTests {
|
||||
|
||||
@Test
|
||||
public void paramEquals() {
|
||||
assertEquals(new ParamsRequestCondition("foo"), new ParamsRequestCondition("foo"));
|
||||
assertFalse(new ParamsRequestCondition("foo").equals(new ParamsRequestCondition("bar")));
|
||||
assertFalse(new ParamsRequestCondition("foo").equals(new ParamsRequestCondition("FOO")));
|
||||
assertEquals(new ParamsRequestCondition("foo=bar"), new ParamsRequestCondition("foo=bar"));
|
||||
assertFalse(
|
||||
new ParamsRequestCondition("foo=bar").equals(new ParamsRequestCondition("FOO=bar")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramPresent() {
|
||||
RequestCondition condition = new ParamsRequestCondition("foo");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter("foo", "");
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramPresentNoMatch() {
|
||||
RequestCondition condition = new ParamsRequestCondition("foo");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("bar", "");
|
||||
|
||||
assertFalse(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramNotPresent() {
|
||||
RequestCondition condition = new ParamsRequestCondition("!foo");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramValueMatch() {
|
||||
RequestCondition condition = new ParamsRequestCondition("foo=bar");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter("foo", "bar");
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramValueNoMatch() {
|
||||
RequestCondition condition = new ParamsRequestCondition("foo=bar");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter("foo", "bazz");
|
||||
|
||||
assertFalse(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void compareTo() {
|
||||
ParamsRequestCondition condition1 = new ParamsRequestCondition("foo", "bar", "baz");
|
||||
ParamsRequestCondition condition2 = new ParamsRequestCondition("foo", "bar");
|
||||
|
||||
int result = condition1.compareTo(condition2);
|
||||
assertTrue("Invalid comparison result: " + result, result < 0);
|
||||
|
||||
result = condition2.compareTo(condition1);
|
||||
assertTrue("Invalid comparison result: " + result, result > 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void combine() {
|
||||
ParamsRequestCondition condition1 = new ParamsRequestCondition("foo=bar");
|
||||
ParamsRequestCondition condition2 = new ParamsRequestCondition("foo=baz");
|
||||
|
||||
ParamsRequestCondition result = condition1.combine(condition2);
|
||||
Set<ParamsRequestCondition.ParamRequestCondition> conditions = result.getConditions();
|
||||
assertEquals(2, conditions.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getMatchingCondition() {
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addParameter("foo", "bar");
|
||||
|
||||
ParamsRequestCondition condition = new ParamsRequestCondition("foo");
|
||||
|
||||
ParamsRequestCondition result = condition.getMatchingCondition(request);
|
||||
assertEquals(condition, result);
|
||||
|
||||
condition = new ParamsRequestCondition("bar");
|
||||
|
||||
result = condition.getMatchingCondition(request);
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -1,212 +0,0 @@
|
|||
/*
|
||||
* Copyright 2002-2011 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.web.servlet.mvc.method.condition;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.mock.web.MockHttpServletRequest;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Arjen Poutsma
|
||||
*/
|
||||
public class RequestConditionFactoryTests {
|
||||
|
||||
|
||||
@Test
|
||||
public void andMatch() {
|
||||
RequestCondition condition1 = RequestConditionFactory.trueCondition();
|
||||
RequestCondition condition2 = RequestConditionFactory.trueCondition();
|
||||
RequestCondition and = RequestConditionFactory.and(condition1, condition2);
|
||||
assertTrue(and.match(new MockHttpServletRequest()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void andNoMatch() {
|
||||
RequestCondition condition1 = RequestConditionFactory.trueCondition();
|
||||
RequestCondition condition2 = RequestConditionFactory.falseCondition();
|
||||
RequestCondition and = RequestConditionFactory.and(condition1, condition2);
|
||||
assertFalse(and.match(new MockHttpServletRequest()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void orMatch() {
|
||||
RequestCondition condition1 = RequestConditionFactory.trueCondition();
|
||||
RequestCondition condition2 = RequestConditionFactory.falseCondition();
|
||||
RequestCondition and = RequestConditionFactory.or(condition1, condition2);
|
||||
assertTrue(and.match(new MockHttpServletRequest()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void orNoMatch() {
|
||||
RequestCondition condition1 = RequestConditionFactory.falseCondition();
|
||||
RequestCondition condition2 = RequestConditionFactory.falseCondition();
|
||||
RequestCondition and = RequestConditionFactory.and(condition1, condition2);
|
||||
assertFalse(and.match(new MockHttpServletRequest()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void paramEquals() {
|
||||
assertEquals(RequestConditionFactory.parseParams("foo"), RequestConditionFactory.parseParams("foo"));
|
||||
assertFalse(RequestConditionFactory.parseParams("foo").equals(RequestConditionFactory.parseParams("bar")));
|
||||
assertFalse(RequestConditionFactory.parseParams("foo").equals(RequestConditionFactory.parseParams("FOO")));
|
||||
assertEquals(RequestConditionFactory.parseParams("foo=bar"), RequestConditionFactory.parseParams("foo=bar"));
|
||||
assertFalse(
|
||||
RequestConditionFactory.parseParams("foo=bar").equals(RequestConditionFactory.parseParams("FOO=bar")));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerEquals() {
|
||||
assertEquals(RequestConditionFactory.parseHeaders("foo"), RequestConditionFactory.parseHeaders("foo"));
|
||||
assertEquals(RequestConditionFactory.parseHeaders("foo"), RequestConditionFactory.parseHeaders("FOO"));
|
||||
assertFalse(RequestConditionFactory.parseHeaders("foo").equals(RequestConditionFactory.parseHeaders("bar")));
|
||||
assertEquals(RequestConditionFactory.parseHeaders("foo=bar"), RequestConditionFactory.parseHeaders("foo=bar"));
|
||||
assertEquals(RequestConditionFactory.parseHeaders("foo=bar"), RequestConditionFactory.parseHeaders("FOO=bar"));
|
||||
assertEquals(RequestConditionFactory.parseHeaders("content-type=text/xml"),
|
||||
RequestConditionFactory.parseHeaders("Content-Type=TEXT/XML"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerPresent() {
|
||||
RequestCondition condition = RequestConditionFactory.parseHeaders("accept");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Accept", "");
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerPresentNoMatch() {
|
||||
RequestCondition condition = RequestConditionFactory.parseHeaders("foo");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("bar", "");
|
||||
|
||||
assertFalse(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerNotPresent() {
|
||||
RequestCondition condition = RequestConditionFactory.parseHeaders("!accept");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerValueMatch() {
|
||||
RequestCondition condition = RequestConditionFactory.parseHeaders("foo=bar");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("foo", "bar");
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerValueNoMatch() {
|
||||
RequestCondition condition = RequestConditionFactory.parseHeaders("foo=bar");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("foo", "bazz");
|
||||
|
||||
assertFalse(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerCaseSensitiveValueMatch() {
|
||||
RequestCondition condition = RequestConditionFactory.parseHeaders("foo=Bar");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("foo", "bar");
|
||||
|
||||
assertFalse(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void headerValueMatchNegated() {
|
||||
RequestCondition condition = RequestConditionFactory.parseHeaders("foo!=bar");
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("foo", "baz");
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mediaTypeHeaderValueMatch() {
|
||||
RequestCondition condition = RequestConditionFactory.parseHeaders("accept=text/html");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Accept", "text/html");
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mediaTypeHeaderValueMatchNegated() {
|
||||
RequestCondition condition = RequestConditionFactory.parseHeaders("accept!=text/html");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.addHeader("Accept", "application/html");
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void consumesMatch() {
|
||||
RequestCondition condition = RequestConditionFactory.parseConsumes("text/plain");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContentType("text/plain");
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void consumesWildcardMatch() {
|
||||
RequestCondition condition = RequestConditionFactory.parseConsumes("text/*");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContentType("text/plain");
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void consumesMultipleMatch() {
|
||||
RequestCondition condition = RequestConditionFactory.parseConsumes("text/plain", "application/xml");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContentType("text/plain");
|
||||
|
||||
assertTrue(condition.match(request));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void consumesSingleNoMatch() {
|
||||
RequestCondition condition = RequestConditionFactory.parseConsumes("text/plain");
|
||||
|
||||
MockHttpServletRequest request = new MockHttpServletRequest();
|
||||
request.setContentType("application/xml");
|
||||
|
||||
assertFalse(condition.match(request));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -153,7 +153,7 @@ import java.lang.annotation.Target;
|
|||
* converters}.
|
||||
* <li>A {@link org.springframework.http.HttpEntity HttpEntity<?>} or
|
||||
* {@link org.springframework.http.ResponseEntity ResponseEntity<?>} object
|
||||
* to access to the Servlet reponse HTTP headers and contents. The entity body will
|
||||
* to access to the Servlet response HTTP headers and contents. The entity body will
|
||||
* be converted to the response stream using
|
||||
* {@linkplain org.springframework.http.converter.HttpMessageConverter message
|
||||
* converters}.
|
||||
|
|
@ -297,4 +297,18 @@ public @interface RequestMapping {
|
|||
*/
|
||||
String[] headers() default {};
|
||||
|
||||
/**
|
||||
* The consumable media types of the mapped request, narrowing the primary mapping.
|
||||
* <p>The format is a sequence of media types ("text/plain", "application/*),
|
||||
* with a request only mapped if the {@code Content-Type} matches one of these media types.
|
||||
* Expressions can be negated by using the "!" operator, as in "!text/plain", which matches
|
||||
* all requests with a {@code Content-Type} other than "text/plain".
|
||||
* <p><b>Supported at the type level as well as at the method level!</b>
|
||||
* When used at the type level, all method-level mappings override
|
||||
* this consumes restriction.
|
||||
* @see org.springframework.http.MediaType
|
||||
* @see javax.servlet.http.HttpServletRequest#getContentType()
|
||||
*/
|
||||
String[] consumes() default "*/*";
|
||||
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue