diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java index 1fec5d58f11217732f04f53bc39a24627e848494..fc1efccc49a99ddc0ccf387881427b1acd2662b1 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/handler/AbstractHandlerMethodMapping.java @@ -204,16 +204,18 @@ public abstract class AbstractHandlerMethodMapping extends AbstractHandlerMap logger.info("Mapped \"" + mapping + "\" onto " + handlerMethod); } - Set paths = getMappingPaths(mapping); - for (String path : paths) { - urlMap.add(path, mapping); + Set patterns = getMappingPathPatterns(mapping); + for (String pattern : patterns) { + if (!getPathMatcher().isPattern(pattern)) { + urlMap.add(pattern, mapping); + } } } /** * Get the URL paths associated with the given mapping. */ - protected abstract Set getMappingPaths(T mapping); + protected abstract Set getMappingPathPatterns(T mapping); @Override protected HandlerMethod getHandlerInternal(HttpServletRequest request) throws Exception { diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/condition/AbstractRequestCondition.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/condition/AbstractRequestCondition.java index ed8e153b52f703f4e0f4c578f9193a8a2e82efaf..72c3dae280bc6ad4ed5b9feb8c6f4d0c338003b1 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/condition/AbstractRequestCondition.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/condition/AbstractRequestCondition.java @@ -25,10 +25,10 @@ import java.util.Iterator; * @author Rossen Stoyanchev * @since 3.1 */ -abstract class AbstractRequestCondition> implements RequestCondition { +public abstract class AbstractRequestCondition> implements RequestCondition { /** - * Returns the discrete expressions a request condition is composed of such as URL patterns, + * Returns the discrete items a request condition is composed of such as URL patterns, * HTTP request methods, parameter expressions, etc. */ protected abstract Collection getContent(); @@ -65,8 +65,8 @@ abstract class AbstractRequestCondition> i } /** - * Returns {@code true} if the individual expressions of the condition are combined via logical - * conjunction (" && "); or {@code false} otherwise. + * The notation to use when printing discrete items of content in the toString() method. + * For example URL patterns use " || " while parameter expressions use " && ". */ protected abstract String getToStringInfix(); diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/condition/CustomRequestCondition.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/CustomRequestCondition.java similarity index 79% rename from org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/condition/CustomRequestCondition.java rename to org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/CustomRequestCondition.java index b548f813f8d29a2ef3df31c543007c148969859b..62e05e3fd3128c46f94ba81d3249dcd0ce39796b 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/condition/CustomRequestCondition.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/CustomRequestCondition.java @@ -14,42 +14,44 @@ * limitations under the License. */ -package org.springframework.web.servlet.mvc.condition; +package org.springframework.web.servlet.mvc.method; import java.util.Collection; import java.util.Collections; import javax.servlet.http.HttpServletRequest; +import org.springframework.web.servlet.mvc.condition.AbstractRequestCondition; +import org.springframework.web.servlet.mvc.condition.RequestCondition; + /** - * Wraps and delegates operations to a custom {@link RequestCondition} whose type is not known and even its - * presence is not guaranteed ahead of time. The main purpose of this class is to ensure a type-safe and - * null-safe way of combining and comparing custom request conditions. + * Wraps and delegates operations to a {@link RequestCondition} whose type is not known ahead of time. The main goal + * is to provide type-safe and null-safe way of comparing and combining optional custom {@link RequestCondition}s. * * @author Rossen Stoyanchev * @since 3.1 */ -public final class CustomRequestCondition extends AbstractRequestCondition { +final class CustomRequestCondition extends AbstractRequestCondition { @SuppressWarnings("rawtypes") private final RequestCondition customCondition; /** - * Creates a {@link CustomRequestCondition} that wraps the given {@link RequestCondition} instance. - * @param requestCondition the custom request condition to wrap + * Creates an instance that wraps the given custom request condition. + * @param requestCondition the custom request condition */ - public CustomRequestCondition(RequestCondition requestCondition) { + CustomRequestCondition(RequestCondition requestCondition) { this.customCondition = requestCondition; } /** - * Creates an empty {@link CustomRequestCondition}. + * Creates an instance that does not wrap any custom request condition. */ - public CustomRequestCondition() { + CustomRequestCondition() { this(null); } - public RequestCondition getRequestCondition() { + public RequestCondition getCondition() { return customCondition; } @@ -60,7 +62,7 @@ public final class CustomRequestCondition extends AbstractRequestCondition{@link ProducesRequestCondition} * * - * Optionally a custom request condition may also be provided by wrapping it in an instance - * of {@link CustomRequestCondition}. + * Optionally a custom request condition may also be provided. * * @author Arjen Poutsma * @author Rossen Stoyanchev @@ -60,95 +57,82 @@ public final class RequestMappingInfo { private final ProducesRequestCondition producesCondition; - private CustomRequestCondition customCondition = new CustomRequestCondition(); + private final CustomRequestCondition customCondition; private int hash; /** * Creates a new {@code RequestMappingInfo} instance. */ - public RequestMappingInfo(PatternsRequestCondition patterns, - RequestMethodsRequestCondition methods, - ParamsRequestCondition params, - HeadersRequestCondition headers, - ConsumesRequestCondition consumes, - ProducesRequestCondition produces) { - this(patterns, methods, params, headers, consumes, produces, null); - } - - /** - * Creates a new {@code RequestMappingInfo} instance also providing a custom {@link RequestCondition}. - */ public RequestMappingInfo(PatternsRequestCondition patterns, RequestMethodsRequestCondition methods, ParamsRequestCondition params, HeadersRequestCondition headers, ConsumesRequestCondition consumes, ProducesRequestCondition produces, - CustomRequestCondition custom) { + RequestCondition custom) { this.patternsCondition = patterns != null ? patterns : new PatternsRequestCondition(); this.methodsCondition = methods != null ? methods : new RequestMethodsRequestCondition(); this.paramsCondition = params != null ? params : new ParamsRequestCondition(); this.headersCondition = headers != null ? headers : new HeadersRequestCondition(); this.consumesCondition = consumes != null ? consumes : new ConsumesRequestCondition(); this.producesCondition = produces != null ? produces : new ProducesRequestCondition(); - this.customCondition = custom != null ? custom : new CustomRequestCondition(); - } - - /** - * Package protected constructor for tests. - */ - RequestMappingInfo(String[] patterns, RequestMethod... methods) { - this(new PatternsRequestCondition(patterns), new RequestMethodsRequestCondition(methods), null, null, null, null); + this.customCondition = custom != null ? new CustomRequestCondition(custom) : new CustomRequestCondition(); } /** - * Returns the URL patterns of this request mapping info. + * Returns the URL patterns of this {@link RequestMappingInfo}; + * or instance with 0 patterns, never {@code null} */ public PatternsRequestCondition getPatternsCondition() { return patternsCondition; } /** - * Returns the HTTP request methods of this {@link RequestMappingInfo}. + * Returns the HTTP request methods of this {@link RequestMappingInfo}; + * or instance with 0 request methods, never {@code null} */ public RequestMethodsRequestCondition getMethodsCondition() { return methodsCondition; } /** - * Returns the "parameters" condition of this {@link RequestMappingInfo}. + * Returns the "parameters" condition of this {@link RequestMappingInfo}; + * or instance with 0 parameter expressions, never {@code null} */ public ParamsRequestCondition getParamsCondition() { return paramsCondition; } /** - * Returns the "headers" condition of this {@link RequestMappingInfo}. + * Returns the "headers" condition of this {@link RequestMappingInfo}; + * or instance with 0 header expressions, never {@code null} */ public HeadersRequestCondition getHeadersCondition() { return headersCondition; } /** - * Returns the "consumes" condition of this {@link RequestMappingInfo}. + * Returns the "consumes" condition of this {@link RequestMappingInfo}; + * or instance with 0 consumes expressions, never {@code null} */ public ConsumesRequestCondition getConsumesCondition() { return consumesCondition; } /** - * Returns the "produces" condition of this {@link RequestMappingInfo}. + * Returns the "produces" condition of this {@link RequestMappingInfo}; + * or instance with 0 produces expressions, never {@code null} */ public ProducesRequestCondition getProducesCondition() { return producesCondition; } /** - * Sets a custom request condition. + * Returns the "custom" condition of this {@link RequestMappingInfo}; or {@code null} */ - public void setCustomCondition(CustomRequestCondition customCondition) { - this.customCondition = customCondition; + public RequestCondition getCustomCondition() { + return customCondition.getCondition(); } /** @@ -165,7 +149,7 @@ public final class RequestMappingInfo { ProducesRequestCondition produces = this.producesCondition.combine(other.producesCondition); CustomRequestCondition custom = this.customCondition.combine(other.customCondition); - return new RequestMappingInfo(patterns, methods, params, headers, consumes, produces, custom); + return new RequestMappingInfo(patterns, methods, params, headers, consumes, produces, custom.getCondition()); } /** @@ -175,7 +159,7 @@ public final class RequestMappingInfo { * the current request, sorted with best matching patterns on top. * @return a new instance in case all conditions match; or {@code null} otherwise */ - public RequestMappingInfo getMatchingRequestMappingInfo(HttpServletRequest request) { + public RequestMappingInfo getMatchingInfo(HttpServletRequest request) { RequestMethodsRequestCondition methods = methodsCondition.getMatchingCondition(request); ParamsRequestCondition params = paramsCondition.getMatchingCondition(request); HeadersRequestCondition headers = headersCondition.getMatchingCondition(request); @@ -196,13 +180,13 @@ public final class RequestMappingInfo { return null; } - return new RequestMappingInfo(patterns, methods, params, headers, consumes, produces, custom); + return new RequestMappingInfo(patterns, methods, params, headers, consumes, produces, custom.getCondition()); } /** * Compares "this" info (i.e. the current instance) with another info in the context of a request. *

Note: it is assumed both instances have been obtained via - * {@link #getMatchingRequestMappingInfo(HttpServletRequest)} to ensure they have conditions with + * {@link #getMatchingInfo(HttpServletRequest)} to ensure they have conditions with * content relevant to current request. */ public int compareTo(RequestMappingInfo other, HttpServletRequest request) { diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping.java index bbf1acea62e529e777a9dbd181a8fcd145103077..6b277f7677de6527b33c4f1b5d38ce4955cb5e6c 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMapping.java @@ -48,27 +48,21 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe @Override protected void handlerMethodsInitialized(Map handlerMethods) { - List mappings = new ArrayList(handlerMethods.keySet()); - while (mappings.size() > 1) { - RequestMappingInfo mapping = mappings.remove(0); - for (RequestMappingInfo otherMapping : mappings) { - // TODO: further validate mapping conditions + List infos = new ArrayList(handlerMethods.keySet()); + while (infos.size() > 1) { + RequestMappingInfo info1 = infos.remove(0); + for (RequestMappingInfo info2 : infos) { + // TODO: validate duplicate consumable and producible media types } } } /** - * Get the URL paths associated with this {@link RequestMappingInfo}. + * Get the URL path patterns associated with this {@link RequestMappingInfo}. */ @Override - protected Set getMappingPaths(RequestMappingInfo mapping) { - Set paths = new HashSet(); - for (String pattern : mapping.getPatternsCondition().getPatterns()) { - if (!getPathMatcher().isPattern(pattern)) { - paths.add(pattern); - } - } - return paths; + protected Set getMappingPathPatterns(RequestMappingInfo info) { + return info.getPatternsCondition().getPatterns(); } /** @@ -79,8 +73,8 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe * @returns a RequestMappingInfo instance in case of a match; or {@code null} in case of no match. */ @Override - protected RequestMappingInfo getMatchingMapping(RequestMappingInfo mapping, HttpServletRequest request) { - return mapping.getMatchingRequestMappingInfo(request); + protected RequestMappingInfo getMatchingMapping(RequestMappingInfo info, HttpServletRequest request) { + return info.getMatchingInfo(request); } /** @@ -89,8 +83,8 @@ public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMe @Override protected Comparator getMappingComparator(final HttpServletRequest request) { return new Comparator() { - public int compare(RequestMappingInfo info, RequestMappingInfo otherInfo) { - return info.compareTo(otherInfo, request); + public int compare(RequestMappingInfo info1, RequestMappingInfo info2) { + return info1.compareTo(info2, request); } }; } diff --git a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java index dd94724ef3c5a8183173c47725359aeafa562abb..858b3222ccaabe5faf431d80684680ea2aa5f83a 100644 --- a/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java +++ b/org.springframework.web.servlet/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestMappingHandlerMapping.java @@ -84,7 +84,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi new ParamsRequestCondition(annotation.params()), new HeadersRequestCondition(annotation.headers()), new ConsumesRequestCondition(annotation.consumes(), annotation.headers()), - new ProducesRequestCondition(annotation.produces(), annotation.headers())); + new ProducesRequestCondition(annotation.produces(), annotation.headers()), null); } } diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/handler/HandlerMethodMappingTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/handler/HandlerMethodMappingTests.java index 8f5e31d7543411e5cca7885c7d5de943f760877a..10bdb33ab10a1ecbcc4e7ce9ee659e8b3b1472fb 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/handler/HandlerMethodMappingTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/handler/HandlerMethodMappingTests.java @@ -118,7 +118,7 @@ public class HandlerMethodMappingTests { } @Override - protected Set getMappingPaths(String key) { + protected Set getMappingPathPatterns(String key) { return new HashSet(); } } diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/condition/PatternsRequestConditionTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/condition/PatternsRequestConditionTests.java new file mode 100644 index 0000000000000000000000000000000000000000..a0f4e29cf4307b43d3f514b5fbf5e06beddd05d5 --- /dev/null +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/condition/PatternsRequestConditionTests.java @@ -0,0 +1,154 @@ +/* + * 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.assertNotNull; +import static org.junit.Assert.assertNull; + +import javax.servlet.http.HttpServletRequest; + +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; + +/** + * @author Rossen Stoyanchev + */ +public class PatternsRequestConditionTests { + + @Test + public void prependSlash() { + PatternsRequestCondition c = new PatternsRequestCondition("foo"); + assertEquals("/foo", c.getPatterns().iterator().next()); + } + + @Test + public void prependNonEmptyPatternsOnly() { + PatternsRequestCondition c = new PatternsRequestCondition(""); + assertEquals("Do not prepend empty patterns (SPR-8255)", "", c.getPatterns().iterator().next()); + } + + @Test + public void combineEmptySets() { + PatternsRequestCondition c1 = new PatternsRequestCondition(); + PatternsRequestCondition c2 = new PatternsRequestCondition(); + + assertEquals(new PatternsRequestCondition(""), c1.combine(c2)); + } + + @Test + public void combineOnePatternWithEmptySet() { + PatternsRequestCondition c1 = new PatternsRequestCondition("/type1", "/type2"); + PatternsRequestCondition c2 = new PatternsRequestCondition(); + + assertEquals(new PatternsRequestCondition("/type1", "/type2"), c1.combine(c2)); + + c1 = new PatternsRequestCondition(); + c2 = new PatternsRequestCondition("/method1", "/method2"); + + assertEquals(new PatternsRequestCondition("/method1", "/method2"), c1.combine(c2)); + } + + @Test + public void combineMultiplePatterns() { + PatternsRequestCondition c1 = new PatternsRequestCondition("/t1", "/t2"); + PatternsRequestCondition c2 = new PatternsRequestCondition("/m1", "/m2"); + + assertEquals(new PatternsRequestCondition("/t1/m1", "/t1/m2", "/t2/m1", "/t2/m2"), c1.combine(c2)); + } + + @Test + public void matchDirectPath() { + PatternsRequestCondition condition = new PatternsRequestCondition("/foo"); + PatternsRequestCondition match = condition.getMatchingCondition(new MockHttpServletRequest("GET", "/foo")); + + assertNotNull(match); + } + + @Test + public void matchPattern() { + PatternsRequestCondition condition = new PatternsRequestCondition("/foo/*"); + PatternsRequestCondition match = condition.getMatchingCondition(new MockHttpServletRequest("GET", "/foo/bar")); + + assertNotNull(match); + } + + @Test + public void matchSortPatterns() { + PatternsRequestCondition condition = new PatternsRequestCondition("/**", "/foo/bar", "/foo/*"); + PatternsRequestCondition match = condition.getMatchingCondition(new MockHttpServletRequest("GET", "/foo/bar")); + PatternsRequestCondition expected = new PatternsRequestCondition("/foo/bar", "/foo/*", "/**"); + + assertEquals(expected, match); + } + + @Test + public void matchImplicitByExtension() { + PatternsRequestCondition condition = new PatternsRequestCondition("/foo"); + PatternsRequestCondition match = condition.getMatchingCondition(new MockHttpServletRequest("GET", "/foo.html")); + + assertNotNull(match); + assertEquals("/foo.*", match.getPatterns().iterator().next()); + } + + @Test + public void matchImplicitTrailingSlash() { + PatternsRequestCondition condition = new PatternsRequestCondition("/foo"); + PatternsRequestCondition match = condition.getMatchingCondition(new MockHttpServletRequest("GET", "/foo/")); + + assertNotNull(match); + assertEquals("/foo/", match.getPatterns().iterator().next()); + } + + @Test + public void matchPatternContainsExtension() { + PatternsRequestCondition condition = new PatternsRequestCondition("/foo.jpg"); + PatternsRequestCondition match = condition.getMatchingCondition(new MockHttpServletRequest("GET", "/foo.html")); + + assertNull(match); + } + + @Test + public void compareEqualPatterns() { + PatternsRequestCondition c1 = new PatternsRequestCondition("/foo*"); + PatternsRequestCondition c2 = new PatternsRequestCondition("/foo*"); + + assertEquals(0, c1.compareTo(c2, new MockHttpServletRequest("GET", "/foo"))); + } + + @Test + public void comparePatternSpecificity() { + PatternsRequestCondition c1 = new PatternsRequestCondition("/fo*"); + PatternsRequestCondition c2 = new PatternsRequestCondition("/foo"); + + assertEquals(1, c1.compareTo(c2, new MockHttpServletRequest("GET", "/foo"))); + } + + @Test + public void compareNumberOfMatchingPatterns() throws Exception { + HttpServletRequest request = new MockHttpServletRequest("GET", "/foo.html"); + + PatternsRequestCondition c1 = new PatternsRequestCondition("/foo", "*.jpeg"); + PatternsRequestCondition c2 = new PatternsRequestCondition("/foo", "*.html"); + + PatternsRequestCondition match1 = c1.getMatchingCondition(request); + PatternsRequestCondition match2 = c2.getMatchingCondition(request); + + assertEquals(1, match1.compareTo(match2, request)); + } + +} diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/condition/ProducesRequestConditionTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/condition/ProducesRequestConditionTests.java index b11467fb2f3f62a9d2d29790477bff5c811a17cd..4e57104a4c9925b4564f24bd2502d4131f9704e4 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/condition/ProducesRequestConditionTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/condition/ProducesRequestConditionTests.java @@ -26,7 +26,6 @@ import java.util.Collection; import org.junit.Test; import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition; import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition.ProduceMediaTypeExpression; /** @@ -84,6 +83,42 @@ public class ProducesRequestConditionTests { assertNull(condition.getMatchingCondition(request)); } + @Test + public void compareTo() { + ProducesRequestCondition html = new ProducesRequestCondition("text/html"); + ProducesRequestCondition xml = new ProducesRequestCondition("application/xml"); + ProducesRequestCondition none = new ProducesRequestCondition(); + + MockHttpServletRequest request = new MockHttpServletRequest(); + request.addHeader("Accept", "application/xml, text/html"); + + assertTrue(html.compareTo(xml, request) > 0); + assertTrue(xml.compareTo(html, request) < 0); + assertTrue(xml.compareTo(none, request) < 0); + assertTrue(none.compareTo(xml, request) > 0); + assertTrue(html.compareTo(none, request) < 0); + assertTrue(none.compareTo(html, request) > 0); + + request = new MockHttpServletRequest(); + request.addHeader("Accept", "application/xml, text/*"); + + assertTrue(html.compareTo(xml, request) > 0); + assertTrue(xml.compareTo(html, request) < 0); + + request = new MockHttpServletRequest(); + request.addHeader("Accept", "application/pdf"); + + assertTrue(html.compareTo(xml, request) == 0); + assertTrue(xml.compareTo(html, request) == 0); + + // See SPR-7000 + request = new MockHttpServletRequest(); + request.addHeader("Accept", "text/html;q=0.9,application/xml"); + + assertTrue(html.compareTo(xml, request) > 0); + assertTrue(xml.compareTo(html, request) < 0); + } + @Test public void compareToSingle() { MockHttpServletRequest request = new MockHttpServletRequest(); @@ -151,7 +186,7 @@ public class ProducesRequestConditionTests { result = condition2.compareTo(condition1, request); assertTrue("Invalid comparison result: " + result, result < 0); } - + @Test public void combine() { ProducesRequestCondition condition1 = new ProducesRequestCondition("text/plain"); @@ -212,12 +247,6 @@ public class ProducesRequestConditionTests { fail("Condition [" + s + "] not found"); } } - - - } - - - } diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/condition/RequestMethodsRequestConditionTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/condition/RequestMethodsRequestConditionTests.java index 718823e1b5f8fab8cbe72e90dc75f4b3954e4a6f..b8aa875359d47b57e227e8423972d98b67d3e573 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/condition/RequestMethodsRequestConditionTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/condition/RequestMethodsRequestConditionTests.java @@ -16,13 +16,14 @@ package org.springframework.web.servlet.mvc.condition; -import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; +import org.junit.Test; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition; - -import static org.junit.Assert.*; /** * @author Arjen Poutsma @@ -56,6 +57,14 @@ public class RequestMethodsRequestConditionTests { assertNotNull(condition.getMatchingCondition(request)); } + @Test + public void noMethodsMatchAll() { + RequestMethodsRequestCondition condition = new RequestMethodsRequestCondition(); + + assertNotNull(condition.getMatchingCondition(new MockHttpServletRequest("GET", ""))); + assertNotNull(condition.getMatchingCondition(new MockHttpServletRequest("POST", ""))); + assertNotNull(condition.getMatchingCondition(new MockHttpServletRequest("HEAD", ""))); + } @Test public void compareTo() { diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/CustomRequestConditionTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/CustomRequestConditionTests.java new file mode 100644 index 0000000000000000000000000000000000000000..39cfb4dd145d659dfb817d6a6ee057ccdac624a1 --- /dev/null +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/CustomRequestConditionTests.java @@ -0,0 +1,111 @@ +/* + * 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; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertSame; + +import javax.servlet.http.HttpServletRequest; + +import org.junit.Test; +import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.web.bind.annotation.RequestMethod; +import org.springframework.web.servlet.mvc.condition.HeadersRequestCondition; +import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition; +import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition; + +/** + * @author Rossen Stoyanchev + */ +public class CustomRequestConditionTests { + + @Test + public void combineEmpty() { + CustomRequestCondition empty = new CustomRequestCondition(); + CustomRequestCondition custom = new CustomRequestCondition(new ParamsRequestCondition("name")); + + assertSame(empty, empty.combine(new CustomRequestCondition())); + assertSame(custom, custom.combine(empty)); + assertSame(custom, empty.combine(custom)); + } + + @Test + public void combine() { + CustomRequestCondition params1 = new CustomRequestCondition(new ParamsRequestCondition("name1")); + CustomRequestCondition params2 = new CustomRequestCondition(new ParamsRequestCondition("name2")); + CustomRequestCondition expected = new CustomRequestCondition(new ParamsRequestCondition("name1", "name2")); + + assertEquals(expected, params1.combine(params2)); + } + + @Test(expected=ClassCastException.class) + public void combineIncompatible() { + CustomRequestCondition params = new CustomRequestCondition(new ParamsRequestCondition("name")); + CustomRequestCondition headers = new CustomRequestCondition(new HeadersRequestCondition("name")); + params.combine(headers); + } + + @Test + public void match() { + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/"); + request.setParameter("name1", "value1"); + + RequestMethodsRequestCondition rm = new RequestMethodsRequestCondition(RequestMethod.GET, RequestMethod.POST); + CustomRequestCondition custom = new CustomRequestCondition(rm); + RequestMethodsRequestCondition expected = new RequestMethodsRequestCondition(RequestMethod.GET); + + assertEquals(expected, custom.getMatchingCondition(request).getCondition()); + } + + @Test + public void matchEmpty() { + CustomRequestCondition empty = new CustomRequestCondition(); + assertSame(empty, empty.getMatchingCondition(new MockHttpServletRequest())); + } + + @Test + public void compare() { + HttpServletRequest request = new MockHttpServletRequest(); + + CustomRequestCondition params11 = new CustomRequestCondition(new ParamsRequestCondition("1")); + CustomRequestCondition params12 = new CustomRequestCondition(new ParamsRequestCondition("1", "2")); + + assertEquals(1, params11.compareTo(params12, request)); + assertEquals(-1, params12.compareTo(params11, request)); + } + + @Test + public void compareEmpty() { + HttpServletRequest request = new MockHttpServletRequest(); + + CustomRequestCondition empty = new CustomRequestCondition(); + CustomRequestCondition empty2 = new CustomRequestCondition(); + CustomRequestCondition custom = new CustomRequestCondition(new ParamsRequestCondition("name")); + + assertEquals(0, empty.compareTo(empty2, request)); + assertEquals(-1, custom.compareTo(empty, request)); + assertEquals(1, empty.compareTo(custom, request)); + } + + @Test(expected=ClassCastException.class) + public void compareIncompatible() { + CustomRequestCondition params = new CustomRequestCondition(new ParamsRequestCondition("name")); + CustomRequestCondition headers = new CustomRequestCondition(new HeadersRequestCondition("name")); + params.compareTo(headers, new MockHttpServletRequest()); + } + +} diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoComparatorTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoComparatorTests.java deleted file mode 100644 index 334a01ebca9f479ef6d037f7e4b0f9bf56aba5ef..0000000000000000000000000000000000000000 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoComparatorTests.java +++ /dev/null @@ -1,167 +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; - -import static java.util.Arrays.asList; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertSame; -import static org.junit.Assert.assertTrue; - -import java.lang.reflect.Method; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import org.junit.Before; -import org.junit.Test; -import org.springframework.mock.web.MockHttpServletRequest; -import org.springframework.web.bind.annotation.RequestMethod; -import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition; -import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition; -import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition; -import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; - -/** - * Test fixture with {@link RequestMappingHandlerMapping} testing its {@link RequestMappingInfo} comparator. - * - * @author Arjen Poutsma - * @author Rossen Stoyanchev - */ -public class RequestMappingInfoComparatorTests { - - private TestRequestMappingInfoHandlerMapping handlerMapping; - - private MockHttpServletRequest request; - - @Before - public void setup() { - this.handlerMapping = new TestRequestMappingInfoHandlerMapping(); - this.request = new MockHttpServletRequest(); - } - - @Test - public void moreSpecificPatternWins() { - request.setRequestURI("/foo"); - Comparator comparator = handlerMapping.getMappingComparator(request); - RequestMappingInfo key1 = new RequestMappingInfo(new String[]{"/fo*"}); - RequestMappingInfo key2 = new RequestMappingInfo(new String[]{"/foo"}); - - assertEquals(1, comparator.compare(key1, key2)); - } - - @Test - public void equalPatterns() { - request.setRequestURI("/foo"); - Comparator comparator = handlerMapping.getMappingComparator(request); - RequestMappingInfo key1 = new RequestMappingInfo(new String[]{"/foo*"}); - RequestMappingInfo key2 = new RequestMappingInfo(new String[]{"/foo*"}); - - assertEquals(0, comparator.compare(key1, key2)); - } - - @Test - public void greaterNumberOfMatchingPatternsWins() throws Exception { - request.setRequestURI("/foo.html"); - RequestMappingInfo key1 = new RequestMappingInfo(new String[]{"/foo", "*.jpeg"}); - RequestMappingInfo key2 = new RequestMappingInfo(new String[]{"/foo", "*.html"}); - RequestMappingInfo match1 = handlerMapping.getMatchingMapping(key1, request); - RequestMappingInfo match2 = handlerMapping.getMatchingMapping(key2, request); - List matches = asList(match1, match2); - Collections.sort(matches, handlerMapping.getMappingComparator(request)); - - assertSame(match2.getPatternsCondition(), matches.get(0).getPatternsCondition()); - } - - @Test - public void oneMethodWinsOverNone() { - Comparator comparator = handlerMapping.getMappingComparator(request); - RequestMappingInfo key1 = new RequestMappingInfo(null); - RequestMappingInfo key2 = new RequestMappingInfo(null, new RequestMethod[] {RequestMethod.GET}); - - assertEquals(1, comparator.compare(key1, key2)); - } - - @Test - public void methodsAndParams() { - RequestMappingInfo empty = new RequestMappingInfo(null); - RequestMappingInfo oneMethod = new RequestMappingInfo(null, new RequestMethod[] {RequestMethod.GET}); - RequestMappingInfo oneMethodOneParam = - new RequestMappingInfo(null, new RequestMethodsRequestCondition(RequestMethod.GET), - new ParamsRequestCondition("foo"), null, null, null); - List list = asList(empty, oneMethod, oneMethodOneParam); - Collections.shuffle(list); - Collections.sort(list, handlerMapping.getMappingComparator(request)); - - assertEquals(oneMethodOneParam, list.get(0)); - assertEquals(oneMethod, list.get(1)); - assertEquals(empty, list.get(2)); - } - - @Test - public void produces() { - RequestMappingInfo html = new RequestMappingInfo(null, null, null, null, null, new ProducesRequestCondition("text/html")); - RequestMappingInfo xml = new RequestMappingInfo(null, null, null, null, null, new ProducesRequestCondition("application/xml")); - RequestMappingInfo none = new RequestMappingInfo(null); - - request.addHeader("Accept", "application/xml, text/html"); - Comparator comparator = handlerMapping.getMappingComparator(request); - - int result = comparator.compare(html, xml); - assertTrue("Invalid comparison result: " + result, result > 0); - assertTrue(comparator.compare(xml, html) < 0); - assertTrue(comparator.compare(xml, none) < 0); - assertTrue(comparator.compare(none, xml) > 0); - assertTrue(comparator.compare(html, none) < 0); - assertTrue(comparator.compare(none, html) > 0); - - request = new MockHttpServletRequest(); - request.addHeader("Accept", "application/xml, text/*"); - comparator = handlerMapping.getMappingComparator(request); - - assertTrue(comparator.compare(html, xml) > 0); - assertTrue(comparator.compare(xml, html) < 0); - - request = new MockHttpServletRequest(); - request.addHeader("Accept", "application/pdf"); - comparator = handlerMapping.getMappingComparator(request); - - assertTrue(comparator.compare(html, xml) == 0); - assertTrue(comparator.compare(xml, html) == 0); - - // See SPR-7000 - request = new MockHttpServletRequest(); - request.addHeader("Accept", "text/html;q=0.9,application/xml"); - comparator = handlerMapping.getMappingComparator(request); - - assertTrue(comparator.compare(html, xml) > 0); - assertTrue(comparator.compare(xml, html) < 0); - } - - private static class TestRequestMappingInfoHandlerMapping extends RequestMappingInfoHandlerMapping { - - @Override - protected boolean isHandler(Class beanType) { - return false; - } - - @Override - protected RequestMappingInfo getMappingForMethod(Method method, Class handlerType) { - return null; - } - } - -} \ No newline at end of file diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMappingTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMappingTests.java index 673ece77fe978a5eb6a282b1c0a47e98c91ccf71..20a4b1c8f88cd6a1cf0ba9a5774a2d20d42d3602 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMappingTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoHandlerMappingTests.java @@ -24,7 +24,10 @@ import static org.junit.Assert.assertSame; import static org.junit.Assert.fail; import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.HashSet; import java.util.Map; +import java.util.Set; import org.junit.Before; import org.junit.Test; @@ -85,6 +88,16 @@ public class RequestMappingInfoHandlerMappingTests { mapping.setApplicationContext(context); } + @Test + public void getMappingPathPatterns() throws Exception { + RequestMappingInfo info = new RequestMappingInfo( + new PatternsRequestCondition("/foo/*", "/foo", "/bar/*", "/bar"), null, null, null, null, null, null); + Set paths = mapping.getMappingPathPatterns(info); + HashSet expected = new HashSet(Arrays.asList("/foo/*", "/foo", "/bar/*", "/bar")); + + assertEquals(expected, paths); + } + @Test public void directMatch() throws Exception { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); @@ -132,7 +145,8 @@ public class RequestMappingInfoHandlerMappingTests { @Test public void uriTemplateVariables() { - RequestMappingInfo key = new RequestMappingInfo(new String[] {"/{path1}/{path2}"}); + PatternsRequestCondition patterns = new PatternsRequestCondition("/{path1}/{path2}"); + RequestMappingInfo key = new RequestMappingInfo(patterns, null, null, null, null, null, null); MockHttpServletRequest request = new MockHttpServletRequest("GET", "/1/2"); String lookupPath = new UrlPathHelper().getLookupPathForRequest(request); @@ -206,7 +220,7 @@ public class RequestMappingInfoHandlerMappingTests { new ParamsRequestCondition(annotation.params()), new HeadersRequestCondition(annotation.headers()), new ConsumesRequestCondition(annotation.consumes(), annotation.headers()), - new ProducesRequestCondition(annotation.produces(), annotation.headers())); + new ProducesRequestCondition(annotation.produces(), annotation.headers()), null); } } diff --git a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoTests.java b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoTests.java index 0cd9e11d8764acf1779167ca935fe38c60327aa8..9fad86f395c064115bcff6d2ea96b2b702eecb52 100644 --- a/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoTests.java +++ b/org.springframework.web.servlet/src/test/java/org/springframework/web/servlet/mvc/method/RequestMappingInfoTests.java @@ -16,19 +16,26 @@ package org.springframework.web.servlet.mvc.method; +import static java.util.Arrays.asList; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; -import static org.springframework.web.bind.annotation.RequestMethod.GET; -import static org.springframework.web.bind.annotation.RequestMethod.POST; +import static org.junit.Assert.assertTrue; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; import org.junit.Test; import org.springframework.mock.web.MockHttpServletRequest; +import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.servlet.mvc.condition.ConsumesRequestCondition; import org.springframework.web.servlet.mvc.condition.HeadersRequestCondition; import org.springframework.web.servlet.mvc.condition.ParamsRequestCondition; import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition; import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition; +import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition; /** * Test fixture for {@link RequestMappingInfo} tests. @@ -39,209 +46,276 @@ import org.springframework.web.servlet.mvc.condition.ProducesRequestCondition; public class RequestMappingInfoTests { @Test - public void equals() { - RequestMappingInfo key1 = new RequestMappingInfo(new String[] {"/foo"}, GET); - RequestMappingInfo key2 = new RequestMappingInfo(new String[] {"/foo"}, GET); - - assertEquals(key1, key2); - assertEquals(key1.hashCode(), key2.hashCode()); - } - - @Test - public void equalsPrependSlash() { - RequestMappingInfo key1 = new RequestMappingInfo(new String[] {"/foo"}, GET); - RequestMappingInfo key2 = new RequestMappingInfo(new String[] {"foo"}, GET); - - assertEquals(key1, key2); - assertEquals(key1.hashCode(), key2.hashCode()); - } - - @Test - public void combinePatterns() { - RequestMappingInfo key1 = createFromPatterns("/t1", "/t2"); - RequestMappingInfo key2 = createFromPatterns("/m1", "/m2"); - RequestMappingInfo key3 = createFromPatterns("/t1/m1", "/t1/m2", "/t2/m1", "/t2/m2"); - assertEquals(key3.getPatternsCondition(), key1.combine(key2).getPatternsCondition()); - - key1 = createFromPatterns("/t1"); - key2 = createFromPatterns(); - key3 = createFromPatterns("/t1"); - assertEquals(key3.getPatternsCondition(), key1.combine(key2).getPatternsCondition()); - - key1 = createFromPatterns(); - key2 = createFromPatterns("/m1"); - key3 = createFromPatterns("/m1"); - assertEquals(key3.getPatternsCondition(), key1.combine(key2).getPatternsCondition()); - - key1 = createFromPatterns(); - key2 = createFromPatterns(); - key3 = createFromPatterns(""); - assertEquals(key3.getPatternsCondition(), key1.combine(key2).getPatternsCondition()); - - key1 = createFromPatterns("/t1"); - key2 = createFromPatterns(""); - key3 = createFromPatterns("/t1"); - assertEquals(key3.getPatternsCondition(), key1.combine(key2).getPatternsCondition()); - } - - @Test - public void matchPatternsToRequest() { - MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); - RequestMappingInfo match = createFromPatterns("/foo").getMatchingRequestMappingInfo(request); - - assertNotNull(match); - - request = new MockHttpServletRequest("GET", "/foo/bar"); - match = createFromPatterns("/foo/*").getMatchingRequestMappingInfo(request); - - assertNotNull("Pattern match", match); - - request = new MockHttpServletRequest("GET", "/foo.html"); - match = createFromPatterns("/foo").getMatchingRequestMappingInfo(request); - - assertNotNull("Implicit match by extension", match); - assertEquals("Contains matched pattern", "/foo.*", match.getPatternsCondition().getPatterns().iterator().next()); - - request = new MockHttpServletRequest("GET", "/foo/"); - match = createFromPatterns("/foo").getMatchingRequestMappingInfo(request); - - assertNotNull("Implicit match by trailing slash", match); - assertEquals("Contains matched pattern", "/foo/", match.getPatternsCondition().getPatterns().iterator().next()); - - request = new MockHttpServletRequest("GET", "/foo.html"); - match = createFromPatterns("/foo.jpg").getMatchingRequestMappingInfo(request); - - assertNull("Implicit match ignored if pattern has extension", match); - - request = new MockHttpServletRequest("GET", "/foo.html"); - match = createFromPatterns("/foo.jpg").getMatchingRequestMappingInfo(request); - - assertNull("Implicit match ignored on pattern with trailing slash", match); - } - - @Test - public void matchRequestMethods() { - MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); - - RequestMappingInfo key = createFromPatterns("/foo"); - RequestMappingInfo match = createFromPatterns("/foo").getMatchingRequestMappingInfo(request); - - assertNotNull("No method matches any method", match); - - key = new RequestMappingInfo(new String[]{"/foo"}, GET); - match = key.getMatchingRequestMappingInfo(request); - - assertNotNull("Exact match", match); - - key = new RequestMappingInfo(new String[]{"/foo"}, POST); - match = key.getMatchingRequestMappingInfo(request); - - assertNull("No match", match); + public void createEmpty() { + RequestMappingInfo info = new RequestMappingInfo(null, null, null, null, null, null, null); + + assertEquals(0, info.getPatternsCondition().getPatterns().size()); + assertEquals(0, info.getMethodsCondition().getMethods().size()); + assertEquals(0, info.getConsumesCondition().getMediaTypes().size()); + assertEquals(0, info.getProducesCondition().getMediaTypes().size()); + assertNotNull(info.getParamsCondition()); + assertNotNull(info.getHeadersCondition()); + assertNull(info.getCustomCondition()); } - + @Test - public void matchingKeyContent() { + public void matchPatternsCondition() { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); - RequestMappingInfo key = new RequestMappingInfo(new String[] {"/foo*", "/bar"}, GET, POST); - RequestMappingInfo match = key.getMatchingRequestMappingInfo(request); - RequestMappingInfo expected = new RequestMappingInfo(new String[] {"/foo*"}, GET); - - assertEquals("Matching RequestKey contains matched patterns and methods only", expected, match); - - key = createFromPatterns("/**", "/foo*", "/foo"); - match = key.getMatchingRequestMappingInfo(request); - expected = createFromPatterns("/foo", "/foo*", "/**"); - - assertEquals("Matched patterns are sorted with best match at the top", expected, match); + RequestMappingInfo info = new RequestMappingInfo( + new PatternsRequestCondition("/foo*", "/bar"), null, null, null, null, null, null); + RequestMappingInfo expected = new RequestMappingInfo( + new PatternsRequestCondition("/foo*"), null, null, null, null, null, null); + + assertEquals(expected, info.getMatchingInfo(request)); + + info = new RequestMappingInfo( + new PatternsRequestCondition("/**", "/foo*", "/foo"), null, null, null, null, null, null); + expected = new RequestMappingInfo( + new PatternsRequestCondition("/foo", "/foo*", "/**"), null, null, null, null, null, null); + + assertEquals(expected, info.getMatchingInfo(request)); } @Test - public void paramsCondition() { + public void matchParamsCondition() { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); request.setParameter("foo", "bar"); - RequestMappingInfo key = + RequestMappingInfo info = new RequestMappingInfo( new PatternsRequestCondition("/foo"), null, - new ParamsRequestCondition("foo=bar"), null, null, null); - RequestMappingInfo match = key.getMatchingRequestMappingInfo(request); + new ParamsRequestCondition("foo=bar"), null, null, null, null); + RequestMappingInfo match = info.getMatchingInfo(request); assertNotNull(match); - key = new RequestMappingInfo( + info = new RequestMappingInfo( new PatternsRequestCondition("/foo"), null, - new ParamsRequestCondition("foo!=bar"), null, null, null); - match = key.getMatchingRequestMappingInfo(request); + new ParamsRequestCondition("foo!=bar"), null, null, null, null); + match = info.getMatchingInfo(request); assertNull(match); } @Test - public void headersCondition() { + public void matchHeadersCondition() { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); request.addHeader("foo", "bar"); - RequestMappingInfo key = + RequestMappingInfo info = new RequestMappingInfo( new PatternsRequestCondition("/foo"), null, null, - new HeadersRequestCondition("foo=bar"), null, null); - RequestMappingInfo match = key.getMatchingRequestMappingInfo(request); + new HeadersRequestCondition("foo=bar"), null, null, null); + RequestMappingInfo match = info.getMatchingInfo(request); assertNotNull(match); - key = new RequestMappingInfo( + info = new RequestMappingInfo( new PatternsRequestCondition("/foo"), null, null, - new HeadersRequestCondition("foo!=bar"), null, null); - match = key.getMatchingRequestMappingInfo(request); + new HeadersRequestCondition("foo!=bar"), null, null, null); + match = info.getMatchingInfo(request); assertNull(match); } @Test - public void consumesCondition() { + public void matchConsumesCondition() { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); request.setContentType("text/plain"); - RequestMappingInfo key = + RequestMappingInfo info = new RequestMappingInfo( new PatternsRequestCondition("/foo"), null, null, null, - new ConsumesRequestCondition("text/plain"), null); - RequestMappingInfo match = key.getMatchingRequestMappingInfo(request); + new ConsumesRequestCondition("text/plain"), null, null); + RequestMappingInfo match = info.getMatchingInfo(request); assertNotNull(match); - key = new RequestMappingInfo( + info = new RequestMappingInfo( new PatternsRequestCondition("/foo"), null, null, null, - new ConsumesRequestCondition("application/xml"), null); - match = key.getMatchingRequestMappingInfo(request); + new ConsumesRequestCondition("application/xml"), null, null); + match = info.getMatchingInfo(request); assertNull(match); } @Test - public void producesCondition() { + public void matchProducesCondition() { MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); request.addHeader("Accept", "text/plain"); - RequestMappingInfo key = + RequestMappingInfo info = new RequestMappingInfo( new PatternsRequestCondition("/foo"), null, null, null, null, - new ProducesRequestCondition("text/plain")); - RequestMappingInfo match = key.getMatchingRequestMappingInfo(request); + new ProducesRequestCondition("text/plain"), null); + RequestMappingInfo match = info.getMatchingInfo(request); assertNotNull(match); - key = new RequestMappingInfo( + info = new RequestMappingInfo( new PatternsRequestCondition("/foo"), null, null, null, null, - new ProducesRequestCondition("application/xml")); - match = key.getMatchingRequestMappingInfo(request); + new ProducesRequestCondition("application/xml"), null); + match = info.getMatchingInfo(request); + + assertNull(match); + } + + @Test + public void matchCustomCondition() { + MockHttpServletRequest request = new MockHttpServletRequest("GET", "/foo"); + request.setParameter("foo", "bar"); + + RequestMappingInfo info = + new RequestMappingInfo( + new PatternsRequestCondition("/foo"), null, null, null, null, null, + new ParamsRequestCondition("foo=bar")); + RequestMappingInfo match = info.getMatchingInfo(request); + + assertNotNull(match); + + info = new RequestMappingInfo( + new PatternsRequestCondition("/foo"), null, + new ParamsRequestCondition("foo!=bar"), null, null, null, + new ParamsRequestCondition("foo!=bar")); + match = info.getMatchingInfo(request); assertNull(match); + } + + @Test + public void compareTwoHttpMethodsOneParam() { + RequestMappingInfo none = new RequestMappingInfo(null, null, null, null, null, null, null); + RequestMappingInfo oneMethod = + new RequestMappingInfo(null, + new RequestMethodsRequestCondition(RequestMethod.GET), null, null, null, null, null); + RequestMappingInfo oneMethodOneParam = + new RequestMappingInfo(null, + new RequestMethodsRequestCondition(RequestMethod.GET), + new ParamsRequestCondition("foo"), null, null, null, null); + + Comparator comparator = new Comparator() { + public int compare(RequestMappingInfo info, RequestMappingInfo otherInfo) { + return info.compareTo(otherInfo, new MockHttpServletRequest()); + } + }; + + List list = asList(none, oneMethod, oneMethodOneParam); + Collections.shuffle(list); + Collections.sort(list, comparator); + + assertEquals(oneMethodOneParam, list.get(0)); + assertEquals(oneMethod, list.get(1)); + assertEquals(none, list.get(2)); } - private RequestMappingInfo createFromPatterns(String... patterns) { - return new RequestMappingInfo(patterns); + @Test + public void equals() { + + RequestMappingInfo info1 = new RequestMappingInfo( + new PatternsRequestCondition("/foo"), + new RequestMethodsRequestCondition(RequestMethod.GET), + new ParamsRequestCondition("foo=bar"), + new HeadersRequestCondition("foo=bar"), + new ConsumesRequestCondition("text/plain"), + new ProducesRequestCondition("text/plain"), + new ParamsRequestCondition("customFoo=customBar")); + + RequestMappingInfo info2 = new RequestMappingInfo( + new PatternsRequestCondition("/foo"), + new RequestMethodsRequestCondition(RequestMethod.GET), + new ParamsRequestCondition("foo=bar"), + new HeadersRequestCondition("foo=bar"), + new ConsumesRequestCondition("text/plain"), + new ProducesRequestCondition("text/plain"), + new ParamsRequestCondition("customFoo=customBar")); + + assertEquals(info1, info2); + assertEquals(info1.hashCode(), info2.hashCode()); + + info2 = new RequestMappingInfo( + new PatternsRequestCondition("/foo", "/NOOOOOO"), + new RequestMethodsRequestCondition(RequestMethod.GET), + new ParamsRequestCondition("foo=bar"), + new HeadersRequestCondition("foo=bar"), + new ConsumesRequestCondition("text/plain"), + new ProducesRequestCondition("text/plain"), + new ParamsRequestCondition("customFoo=customBar")); + + assertFalse(info1.equals(info2)); + assertTrue(info1.hashCode() != info2.hashCode()); + + info2 = new RequestMappingInfo( + new PatternsRequestCondition("/foo"), + new RequestMethodsRequestCondition(RequestMethod.GET, RequestMethod.POST), + new ParamsRequestCondition("foo=bar"), + new HeadersRequestCondition("foo=bar"), + new ConsumesRequestCondition("text/plain"), + new ProducesRequestCondition("text/plain"), + new ParamsRequestCondition("customFoo=customBar")); + + assertFalse(info1.equals(info2)); + assertTrue(info1.hashCode() != info2.hashCode()); + + info2 = new RequestMappingInfo( + new PatternsRequestCondition("/foo"), + new RequestMethodsRequestCondition(RequestMethod.GET), + new ParamsRequestCondition("/NOOOOOO"), + new HeadersRequestCondition("foo=bar"), + new ConsumesRequestCondition("text/plain"), + new ProducesRequestCondition("text/plain"), + new ParamsRequestCondition("customFoo=customBar")); + + assertFalse(info1.equals(info2)); + assertTrue(info1.hashCode() != info2.hashCode()); + + info2 = new RequestMappingInfo( + new PatternsRequestCondition("/foo"), + new RequestMethodsRequestCondition(RequestMethod.GET), + new ParamsRequestCondition("foo=bar"), + new HeadersRequestCondition("/NOOOOOO"), + new ConsumesRequestCondition("text/plain"), + new ProducesRequestCondition("text/plain"), + new ParamsRequestCondition("customFoo=customBar")); + + assertFalse(info1.equals(info2)); + assertTrue(info1.hashCode() != info2.hashCode()); + + info2 = new RequestMappingInfo( + new PatternsRequestCondition("/foo"), + new RequestMethodsRequestCondition(RequestMethod.GET), + new ParamsRequestCondition("foo=bar"), + new HeadersRequestCondition("foo=bar"), + new ConsumesRequestCondition("text/NOOOOOO"), + new ProducesRequestCondition("text/plain"), + new ParamsRequestCondition("customFoo=customBar")); + + assertFalse(info1.equals(info2)); + assertTrue(info1.hashCode() != info2.hashCode()); + + info2 = new RequestMappingInfo( + new PatternsRequestCondition("/foo"), + new RequestMethodsRequestCondition(RequestMethod.GET), + new ParamsRequestCondition("foo=bar"), + new HeadersRequestCondition("foo=bar"), + new ConsumesRequestCondition("text/plain"), + new ProducesRequestCondition("text/NOOOOOO"), + new ParamsRequestCondition("customFoo=customBar")); + + assertFalse(info1.equals(info2)); + assertTrue(info1.hashCode() != info2.hashCode()); + + info2 = new RequestMappingInfo( + new PatternsRequestCondition("/foo"), + new RequestMethodsRequestCondition(RequestMethod.GET), + new ParamsRequestCondition("foo=bar"), + new HeadersRequestCondition("foo=bar"), + new ConsumesRequestCondition("text/plain"), + new ProducesRequestCondition("text/plain"), + new ParamsRequestCondition("customFoo=NOOOOOO")); + + assertFalse(info1.equals(info2)); + assertTrue(info1.hashCode() != info2.hashCode()); } } \ No newline at end of file