Add CompositeRequestCondition
The new type makes it easier providing multiple custom request mapping conditions via setters on RequestMappingHandlerMapping. Issue: SPR-9350
This commit is contained in:
@@ -0,0 +1,181 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2002-2012 the original author or authors.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.springframework.web.servlet.mvc.condition;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.ObjectUtils;
|
||||||
|
|
||||||
|
import edu.emory.mathcs.backport.java.util.Collections;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implements the {@link RequestCondition} contract by delegating to multiple
|
||||||
|
* {@code RequestCondition} types and using a logical conjunction (' && ') to
|
||||||
|
* ensure all conditions match a given request.
|
||||||
|
*
|
||||||
|
* <p>When {@code CompositeRequestCondition} instances are combined or compared
|
||||||
|
* they are expected to (a) contain the same number of conditions and (b) that
|
||||||
|
* conditions in the respective index are of the same type. It is acceptable to
|
||||||
|
* provide {@code null} conditions or no conditions at all to the constructor.
|
||||||
|
*
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
|
* @since 3.2
|
||||||
|
*/
|
||||||
|
public class CompositeRequestCondition extends AbstractRequestCondition<CompositeRequestCondition> {
|
||||||
|
|
||||||
|
private final RequestConditionHolder[] requestConditions;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create an instance with 0 or more {@code RequestCondition} types. It is
|
||||||
|
* important to create {@code CompositeRequestCondition} instances with the
|
||||||
|
* same number of conditions so they may be compared and combined.
|
||||||
|
* It is acceptable to provide {@code null} conditions.
|
||||||
|
*/
|
||||||
|
public CompositeRequestCondition(RequestCondition<?>... requestConditions) {
|
||||||
|
this.requestConditions = wrap(requestConditions);
|
||||||
|
}
|
||||||
|
|
||||||
|
private RequestConditionHolder[] wrap(RequestCondition<?>... rawConditions) {
|
||||||
|
RequestConditionHolder[] wrappedConditions = new RequestConditionHolder[rawConditions.length];
|
||||||
|
for (int i = 0; i < rawConditions.length; i++) {
|
||||||
|
wrappedConditions[i] = new RequestConditionHolder(rawConditions[i]);
|
||||||
|
}
|
||||||
|
return wrappedConditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
private CompositeRequestCondition(RequestConditionHolder[] requestConditions) {
|
||||||
|
this.requestConditions = requestConditions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether this instance contains 0 conditions or not.
|
||||||
|
*/
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return ObjectUtils.isEmpty(this.requestConditions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the underlying conditions, possibly empty but never {@code null}.
|
||||||
|
*/
|
||||||
|
public List<RequestCondition<?>> getConditions() {
|
||||||
|
return unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
private List<RequestCondition<?>> unwrap() {
|
||||||
|
List<RequestCondition<?>> result = new ArrayList<RequestCondition<?>>();
|
||||||
|
for (RequestConditionHolder holder : this.requestConditions) {
|
||||||
|
result.add(holder.getCondition());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Collection<?> getContent() {
|
||||||
|
return (isEmpty()) ? Collections.emptyList() : getConditions();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getToStringInfix() {
|
||||||
|
return " && ";
|
||||||
|
}
|
||||||
|
|
||||||
|
private int getLength() {
|
||||||
|
return this.requestConditions.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If one instance is empty, return the other.
|
||||||
|
* If both instances have conditions, combine the individual conditions
|
||||||
|
* after ensuring they are of the same type and number.
|
||||||
|
*/
|
||||||
|
public CompositeRequestCondition combine(CompositeRequestCondition other) {
|
||||||
|
if (isEmpty() && other.isEmpty()) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
else if (other.isEmpty()) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
else if (isEmpty()) {
|
||||||
|
return other;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assertNumberOfConditions(other);
|
||||||
|
RequestConditionHolder[] combinedConditions = new RequestConditionHolder[getLength()];
|
||||||
|
for (int i = 0; i < getLength(); i++) {
|
||||||
|
combinedConditions[i] = this.requestConditions[i].combine(other.requestConditions[i]);
|
||||||
|
}
|
||||||
|
return new CompositeRequestCondition(combinedConditions);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertNumberOfConditions(CompositeRequestCondition other) {
|
||||||
|
Assert.isTrue(getLength() == other.getLength(),
|
||||||
|
"Cannot combine CompositeRequestConditions with a different number of conditions. "
|
||||||
|
+ this.requestConditions + " and " + other.requestConditions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Delegate to <em>all</em> contained conditions to match the request and return the
|
||||||
|
* resulting "matching" condition instances.
|
||||||
|
* <p>An empty {@code CompositeRequestCondition} matches to all requests.
|
||||||
|
*/
|
||||||
|
public CompositeRequestCondition getMatchingCondition(HttpServletRequest request) {
|
||||||
|
if (isEmpty()) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
RequestConditionHolder[] matchingConditions = new RequestConditionHolder[getLength()];
|
||||||
|
for (int i = 0; i < getLength(); i++) {
|
||||||
|
matchingConditions[i] = this.requestConditions[i].getMatchingCondition(request);
|
||||||
|
if (matchingConditions[i] == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return new CompositeRequestCondition(matchingConditions);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If one instance is empty, the other "wins". If both instances have
|
||||||
|
* conditions, compare them in the order in which they were provided.
|
||||||
|
*/
|
||||||
|
public int compareTo(CompositeRequestCondition other, HttpServletRequest request) {
|
||||||
|
if (isEmpty() && other.isEmpty()) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else if (isEmpty()) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
else if (other.isEmpty()) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
assertNumberOfConditions(other);
|
||||||
|
for (int i = 0; i < getLength(); i++) {
|
||||||
|
int result = this.requestConditions[i].compareTo(other.requestConditions[i], request);
|
||||||
|
if (result != 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -23,40 +23,42 @@ import javax.servlet.http.HttpServletRequest;
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A holder for a {@link RequestCondition} useful when the type of the held
|
* A holder for a {@link RequestCondition} useful when the type of the request
|
||||||
* request condition is not known ahead of time - e.g. custom condition.
|
* condition is not known ahead of time, e.g. custom condition. Since this
|
||||||
|
* class is also an implementation of {@code RequestCondition}, effectively it
|
||||||
|
* decorates the held request condition and allows it to be combined and compared
|
||||||
|
* with other request conditions in a type and null safe way.
|
||||||
*
|
*
|
||||||
* <p>An implementation of {@code RequestCondition} itself, a
|
* <p>When two {@code RequestConditionHolder} instances are combined or compared
|
||||||
* {@code RequestConditionHolder} decorates the held request condition allowing
|
* with each other, it is expected the conditions they hold are of the same type.
|
||||||
* it to be combined and compared with other custom request conditions while
|
* If they are not, a {@link ClassCastException} is raised.
|
||||||
* ensuring type and null safety.
|
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @since 3.1
|
* @since 3.1
|
||||||
*/
|
*/
|
||||||
public final class RequestConditionHolder extends AbstractRequestCondition<RequestConditionHolder> {
|
public final class RequestConditionHolder extends AbstractRequestCondition<RequestConditionHolder> {
|
||||||
|
|
||||||
@SuppressWarnings("rawtypes")
|
private final RequestCondition<Object> condition;
|
||||||
private final RequestCondition condition;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new holder to wrap the given request condition.
|
* Create a new holder to wrap the given request condition.
|
||||||
* @param requestCondition the condition to hold, may be {@code null}
|
* @param requestCondition the condition to hold, may be {@code null}
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
public RequestConditionHolder(RequestCondition<?> requestCondition) {
|
public RequestConditionHolder(RequestCondition<?> requestCondition) {
|
||||||
this.condition = requestCondition;
|
this.condition = (RequestCondition<Object>) requestCondition;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the held request condition, or {@code null} if not holding one.
|
* Return the held request condition, or {@code null} if not holding one.
|
||||||
*/
|
*/
|
||||||
public RequestCondition<?> getCondition() {
|
public RequestCondition<?> getCondition() {
|
||||||
return condition;
|
return this.condition;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Collection<?> getContent() {
|
protected Collection<?> getContent() {
|
||||||
return condition != null ? Collections.singleton(condition) : Collections.emptyList();
|
return this.condition != null ? Collections.singleton(this.condition) : Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -69,20 +71,19 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
|
|||||||
* instances after making sure the conditions are of the same type.
|
* instances after making sure the conditions are of the same type.
|
||||||
* Or if one holder is empty, the other holder is returned.
|
* Or if one holder is empty, the other holder is returned.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public RequestConditionHolder combine(RequestConditionHolder other) {
|
public RequestConditionHolder combine(RequestConditionHolder other) {
|
||||||
if (condition == null && other.condition == null) {
|
if (this.condition == null && other.condition == null) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
else if (condition == null) {
|
else if (this.condition == null) {
|
||||||
return other;
|
return other;
|
||||||
}
|
}
|
||||||
else if (other.condition == null) {
|
else if (other.condition == null) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertIsCompatible(other);
|
assertEqualConditionTypes(other);
|
||||||
RequestCondition<?> combined = (RequestCondition<?>) condition.combine(other.condition);
|
RequestCondition<?> combined = (RequestCondition<?>) this.condition.combine(other.condition);
|
||||||
return new RequestConditionHolder(combined);
|
return new RequestConditionHolder(combined);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,8 +91,8 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
|
|||||||
/**
|
/**
|
||||||
* Ensure the held request conditions are of the same type.
|
* Ensure the held request conditions are of the same type.
|
||||||
*/
|
*/
|
||||||
private void assertIsCompatible(RequestConditionHolder other) {
|
private void assertEqualConditionTypes(RequestConditionHolder other) {
|
||||||
Class<?> clazz = condition.getClass();
|
Class<?> clazz = this.condition.getClass();
|
||||||
Class<?> otherClazz = other.condition.getClass();
|
Class<?> otherClazz = other.condition.getClass();
|
||||||
if (!clazz.equals(otherClazz)) {
|
if (!clazz.equals(otherClazz)) {
|
||||||
throw new ClassCastException("Incompatible request conditions: " + clazz + " and " + otherClazz);
|
throw new ClassCastException("Incompatible request conditions: " + clazz + " and " + otherClazz);
|
||||||
@@ -104,10 +105,10 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
|
|||||||
* holder, return the same holder instance.
|
* holder, return the same holder instance.
|
||||||
*/
|
*/
|
||||||
public RequestConditionHolder getMatchingCondition(HttpServletRequest request) {
|
public RequestConditionHolder getMatchingCondition(HttpServletRequest request) {
|
||||||
if (condition == null) {
|
if (this.condition == null) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
RequestCondition<?> match = (RequestCondition<?>) condition.getMatchingCondition(request);
|
RequestCondition<?> match = (RequestCondition<?>) this.condition.getMatchingCondition(request);
|
||||||
return (match != null) ? new RequestConditionHolder(match) : null;
|
return (match != null) ? new RequestConditionHolder(match) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -116,20 +117,19 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
|
|||||||
* instances after making sure the conditions are of the same type.
|
* instances after making sure the conditions are of the same type.
|
||||||
* Or if one holder is empty, the other holder is preferred.
|
* Or if one holder is empty, the other holder is preferred.
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public int compareTo(RequestConditionHolder other, HttpServletRequest request) {
|
public int compareTo(RequestConditionHolder other, HttpServletRequest request) {
|
||||||
if (condition == null && other.condition == null) {
|
if (this.condition == null && other.condition == null) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
else if (condition == null) {
|
else if (this.condition == null) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
else if (other.condition == null) {
|
else if (other.condition == null) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assertIsCompatible(other);
|
assertEqualConditionTypes(other);
|
||||||
return condition.compareTo(other.condition, request);
|
return this.condition.compareTo(other.condition, request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,8 @@ import java.lang.reflect.Method;
|
|||||||
import org.springframework.core.annotation.AnnotationUtils;
|
import org.springframework.core.annotation.AnnotationUtils;
|
||||||
import org.springframework.stereotype.Controller;
|
import org.springframework.stereotype.Controller;
|
||||||
import org.springframework.web.bind.annotation.RequestMapping;
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.servlet.mvc.condition.AbstractRequestCondition;
|
||||||
|
import org.springframework.web.servlet.mvc.condition.CompositeRequestCondition;
|
||||||
import org.springframework.web.servlet.mvc.condition.ConsumesRequestCondition;
|
import org.springframework.web.servlet.mvc.condition.ConsumesRequestCondition;
|
||||||
import org.springframework.web.servlet.mvc.condition.HeadersRequestCondition;
|
import org.springframework.web.servlet.mvc.condition.HeadersRequestCondition;
|
||||||
import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition;
|
import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition;
|
||||||
@@ -113,23 +115,16 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
|||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Provide a custom method-level request condition.
|
|
||||||
* The custom {@link RequestCondition} can be of any type so long as the
|
|
||||||
* same condition type is returned from all calls to this method in order
|
|
||||||
* to ensure custom request conditions can be combined and compared.
|
|
||||||
* @param method the handler method for which to create the condition
|
|
||||||
* @return the condition, or {@code null}
|
|
||||||
*/
|
|
||||||
protected RequestCondition<?> getCustomMethodCondition(Method method) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provide a custom type-level request condition.
|
* Provide a custom type-level request condition.
|
||||||
* The custom {@link RequestCondition} can be of any type so long as the
|
* The custom {@link RequestCondition} can be of any type so long as the
|
||||||
* same condition type is returned from all calls to this method in order
|
* same condition type is returned from all calls to this method in order
|
||||||
* to ensure custom request conditions can be combined and compared.
|
* to ensure custom request conditions can be combined and compared.
|
||||||
|
*
|
||||||
|
* <p>Consider extending {@link AbstractRequestCondition} for custom
|
||||||
|
* condition types and using {@link CompositeRequestCondition} to provide
|
||||||
|
* multiple custom conditions.
|
||||||
|
*
|
||||||
* @param handlerType the handler type for which to create the condition
|
* @param handlerType the handler type for which to create the condition
|
||||||
* @return the condition, or {@code null}
|
* @return the condition, or {@code null}
|
||||||
*/
|
*/
|
||||||
@@ -137,6 +132,23 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provide a custom method-level request condition.
|
||||||
|
* The custom {@link RequestCondition} can be of any type so long as the
|
||||||
|
* same condition type is returned from all calls to this method in order
|
||||||
|
* to ensure custom request conditions can be combined and compared.
|
||||||
|
*
|
||||||
|
* <p>Consider extending {@link AbstractRequestCondition} for custom
|
||||||
|
* condition types and using {@link CompositeRequestCondition} to provide
|
||||||
|
* multiple custom conditions.
|
||||||
|
*
|
||||||
|
* @param method the handler method for which to create the condition
|
||||||
|
* @return the condition, or {@code null}
|
||||||
|
*/
|
||||||
|
protected RequestCondition<?> getCustomMethodCondition(Method method) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created a RequestMappingInfo from a RequestMapping annotation.
|
* Created a RequestMappingInfo from a RequestMapping annotation.
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -0,0 +1,141 @@
|
|||||||
|
/*
|
||||||
|
* 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.condition;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertNull;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
|
import org.junit.Before;
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.springframework.mock.web.MockHttpServletRequest;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A test fixture for {@link CompositeRequestCondition} tests.
|
||||||
|
*
|
||||||
|
* @author Rossen Stoyanchev
|
||||||
|
*/
|
||||||
|
public class CompositeRequestConditionTests {
|
||||||
|
|
||||||
|
private ParamsRequestCondition param1;
|
||||||
|
private ParamsRequestCondition param2;
|
||||||
|
private ParamsRequestCondition param3;
|
||||||
|
|
||||||
|
private HeadersRequestCondition header1;
|
||||||
|
private HeadersRequestCondition header2;
|
||||||
|
private HeadersRequestCondition header3;
|
||||||
|
|
||||||
|
@Before
|
||||||
|
public void setup() {
|
||||||
|
this.param1 = new ParamsRequestCondition("param1");
|
||||||
|
this.param2 = new ParamsRequestCondition("param2");
|
||||||
|
this.param3 = this.param1.combine(this.param2);
|
||||||
|
|
||||||
|
this.header1 = new HeadersRequestCondition("header1");
|
||||||
|
this.header2 = new HeadersRequestCondition("header2");
|
||||||
|
this.header3 = this.header1.combine(this.header2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void combine() {
|
||||||
|
CompositeRequestCondition cond1 = new CompositeRequestCondition(this.param1, this.header1);
|
||||||
|
CompositeRequestCondition cond2 = new CompositeRequestCondition(this.param2, this.header2);
|
||||||
|
CompositeRequestCondition cond3 = new CompositeRequestCondition(this.param3, this.header3);
|
||||||
|
|
||||||
|
assertEquals(cond3, cond1.combine(cond2));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void combineEmpty() {
|
||||||
|
CompositeRequestCondition empty = new CompositeRequestCondition();
|
||||||
|
CompositeRequestCondition notEmpty = new CompositeRequestCondition(this.param1);
|
||||||
|
|
||||||
|
assertSame(empty, empty.combine(empty));
|
||||||
|
assertSame(notEmpty, notEmpty.combine(empty));
|
||||||
|
assertSame(notEmpty, empty.combine(notEmpty));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=IllegalArgumentException.class)
|
||||||
|
public void combineDifferentLength() {
|
||||||
|
CompositeRequestCondition cond1 = new CompositeRequestCondition(this.param1);
|
||||||
|
CompositeRequestCondition cond2 = new CompositeRequestCondition(this.param1, this.header1);
|
||||||
|
cond1.combine(cond2);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void match() {
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||||
|
request.setParameter("param1", "paramValue1");
|
||||||
|
request.addHeader("header1", "headerValue1");
|
||||||
|
|
||||||
|
RequestCondition<?> getPostCond = new RequestMethodsRequestCondition(RequestMethod.GET, RequestMethod.POST);
|
||||||
|
RequestCondition<?> getCond = new RequestMethodsRequestCondition(RequestMethod.GET);
|
||||||
|
|
||||||
|
CompositeRequestCondition condition = new CompositeRequestCondition(this.param1, getPostCond);
|
||||||
|
CompositeRequestCondition matchingCondition = new CompositeRequestCondition(this.param1, getCond);
|
||||||
|
|
||||||
|
assertEquals(matchingCondition, condition.getMatchingCondition(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void noMatch() {
|
||||||
|
MockHttpServletRequest request = new MockHttpServletRequest("GET", "/");
|
||||||
|
CompositeRequestCondition cond = new CompositeRequestCondition(this.param1);
|
||||||
|
|
||||||
|
assertNull(cond.getMatchingCondition(request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void matchEmpty() {
|
||||||
|
CompositeRequestCondition empty = new CompositeRequestCondition();
|
||||||
|
assertSame(empty, empty.getMatchingCondition(new MockHttpServletRequest()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void compare() {
|
||||||
|
HttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
|
||||||
|
CompositeRequestCondition cond1 = new CompositeRequestCondition(this.param1);
|
||||||
|
CompositeRequestCondition cond3 = new CompositeRequestCondition(this.param3);
|
||||||
|
|
||||||
|
assertEquals(1, cond1.compareTo(cond3, request));
|
||||||
|
assertEquals(-1, cond3.compareTo(cond1, request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void compareEmpty() {
|
||||||
|
HttpServletRequest request = new MockHttpServletRequest();
|
||||||
|
|
||||||
|
CompositeRequestCondition empty = new CompositeRequestCondition();
|
||||||
|
CompositeRequestCondition notEmpty = new CompositeRequestCondition(this.param1);
|
||||||
|
|
||||||
|
assertEquals(0, empty.compareTo(empty, request));
|
||||||
|
assertEquals(-1, notEmpty.compareTo(empty, request));
|
||||||
|
assertEquals(1, empty.compareTo(notEmpty, request));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected=IllegalArgumentException.class)
|
||||||
|
public void compareDifferentLength() {
|
||||||
|
CompositeRequestCondition cond1 = new CompositeRequestCondition(this.param1);
|
||||||
|
CompositeRequestCondition cond2 = new CompositeRequestCondition(this.param1, this.header1);
|
||||||
|
cond1.compareTo(cond2, new MockHttpServletRequest());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
@@ -27,23 +27,12 @@ import org.springframework.mock.web.MockHttpServletRequest;
|
|||||||
import org.springframework.web.bind.annotation.RequestMethod;
|
import org.springframework.web.bind.annotation.RequestMethod;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A test fixture for
|
* A test fixture for {@link RequestConditionHolder} tests.
|
||||||
* {code org.springframework.web.servlet.mvc.method.RequestConditionHolder} tests.
|
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
*/
|
*/
|
||||||
public class RequestConditionHolderTests {
|
public class RequestConditionHolderTests {
|
||||||
|
|
||||||
@Test
|
|
||||||
public void combineEmpty() {
|
|
||||||
RequestConditionHolder empty = new RequestConditionHolder(null);
|
|
||||||
RequestConditionHolder notEmpty = new RequestConditionHolder(new ParamsRequestCondition("name"));
|
|
||||||
|
|
||||||
assertSame(empty, empty.combine(new RequestConditionHolder(null)));
|
|
||||||
assertSame(notEmpty, notEmpty.combine(empty));
|
|
||||||
assertSame(notEmpty, empty.combine(notEmpty));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void combine() {
|
public void combine() {
|
||||||
RequestConditionHolder params1 = new RequestConditionHolder(new ParamsRequestCondition("name1"));
|
RequestConditionHolder params1 = new RequestConditionHolder(new ParamsRequestCondition("name1"));
|
||||||
@@ -53,6 +42,16 @@ public class RequestConditionHolderTests {
|
|||||||
assertEquals(expected, params1.combine(params2));
|
assertEquals(expected, params1.combine(params2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void combineEmpty() {
|
||||||
|
RequestConditionHolder empty = new RequestConditionHolder(null);
|
||||||
|
RequestConditionHolder notEmpty = new RequestConditionHolder(new ParamsRequestCondition("name"));
|
||||||
|
|
||||||
|
assertSame(empty, empty.combine(empty));
|
||||||
|
assertSame(notEmpty, notEmpty.combine(empty));
|
||||||
|
assertSame(notEmpty, empty.combine(notEmpty));
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected=ClassCastException.class)
|
@Test(expected=ClassCastException.class)
|
||||||
public void combineIncompatible() {
|
public void combineIncompatible() {
|
||||||
RequestConditionHolder params = new RequestConditionHolder(new ParamsRequestCondition("name"));
|
RequestConditionHolder params = new RequestConditionHolder(new ParamsRequestCondition("name"));
|
||||||
|
|||||||
13
src/dist/changelog.txt
vendored
13
src/dist/changelog.txt
vendored
@@ -6,24 +6,25 @@ http://www.springsource.org
|
|||||||
Changes in version 3.2 M1
|
Changes in version 3.2 M1
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|
||||||
|
* add Servlet 3.0 based async support
|
||||||
* upgraded to AspectJ 1.6.12, JUnit 4.10, TestNG 6.5.2
|
* upgraded to AspectJ 1.6.12, JUnit 4.10, TestNG 6.5.2
|
||||||
|
* add HttpMessageConverter and View types compatible with Jackson 2.0
|
||||||
* better handling on failure to parse invalid 'Content-Type' or 'Accept' headers
|
* better handling on failure to parse invalid 'Content-Type' or 'Accept' headers
|
||||||
* handle a controller method's return value based on the actual returned value (vs declared type)
|
* handle a controller method's return value based on the actual returned value (vs declared type)
|
||||||
* fix issue with combining identical controller and method level request mapping paths
|
* fix issue with combining identical controller and method level request mapping paths
|
||||||
* fix concurrency issue in AnnotationMethodHandlerExceptionResolver
|
* fix concurrency issue in AnnotationMethodHandlerExceptionResolver
|
||||||
* fix case-sensitivity issue with some containers on access to 'Content-Disposition' header
|
* fix case-sensitivity issue with some containers on access to 'Content-Disposition' header
|
||||||
* add Servlet 3.0 based async support
|
|
||||||
* fix issue with encoded params in UriComponentsBuilder
|
* fix issue with encoded params in UriComponentsBuilder
|
||||||
* add HttpMessageConverter and View types compatible with Jackson 2.0
|
|
||||||
* add pretty print option to Jackson HttpMessageConverter and View types
|
* add pretty print option to Jackson HttpMessageConverter and View types
|
||||||
* fix issue with resolving Errors controller method argument
|
|
||||||
* detect controller methods via InitializingBean in RequestMappingHandlerMapping
|
|
||||||
* translate IOException from Jackson to HttpMessageNotReadableException
|
* translate IOException from Jackson to HttpMessageNotReadableException
|
||||||
|
* fix issue with resolving Errors controller method argument
|
||||||
|
* implement InitializingBean in RequestMappingHandlerMapping to detect controller methods
|
||||||
* fix content negotiation issue when sorting selected media types by quality value
|
* fix content negotiation issue when sorting selected media types by quality value
|
||||||
* Prevent further writing to the response when @ResponseStatus contains a reason
|
* prevent further writing to the response when @ResponseStatus contains a reason
|
||||||
* Deprecate HttpStatus codes 419, 420, 421
|
* deprecate HttpStatus codes 419, 420, 421
|
||||||
* support access to all URI vars via @PathVariable Map<String, String>
|
* support access to all URI vars via @PathVariable Map<String, String>
|
||||||
* add "excludedExceptions" property to SimpleUrlHandlerMapping
|
* add "excludedExceptions" property to SimpleUrlHandlerMapping
|
||||||
|
* add CompositeRequestCondition for use with multiple custom request mapping conditions
|
||||||
|
|
||||||
Changes in version 3.1.1 (2012-02-16)
|
Changes in version 3.1.1 (2012-02-16)
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
|
|||||||
Reference in New Issue
Block a user