Related polishing

Issue. SPR-11428
This commit is contained in:
Juergen Hoeller 2014-02-14 21:38:44 +01:00
parent f913940402
commit 9c6df766cd
15 changed files with 176 additions and 186 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 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.
@ -37,9 +37,8 @@ import org.springframework.util.ReflectionUtils.MethodFilter;
public abstract class HandlerMethodSelector { public abstract class HandlerMethodSelector {
/** /**
* Selects handler methods for the given handler type. Callers of this method define handler methods * Select handler methods for the given handler type.
* of interest through the {@link MethodFilter} parameter. * <p>Callers define handler methods of interest through the {@link MethodFilter} parameter.
*
* @param handlerType the handler type to search handler methods on * @param handlerType the handler type to search handler methods on
* @param handlerMethodFilter a {@link MethodFilter} to help recognize handler methods of interest * @param handlerMethodFilter a {@link MethodFilter} to help recognize handler methods of interest
* @return the selected methods, or an empty set * @return the selected methods, or an empty set

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 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.
@ -43,14 +43,25 @@ import org.springframework.web.method.HandlerMethodSelector;
*/ */
public class ExceptionHandlerMethodResolver { public class ExceptionHandlerMethodResolver {
/** A filter for selecting annotated exception handling methods. */
public final static MethodFilter EXCEPTION_HANDLER_METHODS = new MethodFilter() {
@Override
public boolean matches(Method method) {
return (AnnotationUtils.findAnnotation(method, ExceptionHandler.class) != null);
}
};
private static final Method NO_METHOD_FOUND = ClassUtils.getMethodIfAvailable(System.class, "currentTimeMillis"); private static final Method NO_METHOD_FOUND = ClassUtils.getMethodIfAvailable(System.class, "currentTimeMillis");
private final Map<Class<? extends Throwable>, Method> mappedMethods = private final Map<Class<? extends Throwable>, Method> mappedMethods =
new ConcurrentHashMap<Class<? extends Throwable>, Method>(16); new ConcurrentHashMap<Class<? extends Throwable>, Method>(16);
private final Map<Class<? extends Throwable>, Method> exceptionLookupCache = private final Map<Class<? extends Throwable>, Method> exceptionLookupCache =
new ConcurrentHashMap<Class<? extends Throwable>, Method>(16); new ConcurrentHashMap<Class<? extends Throwable>, Method>(16);
/** /**
* A constructor that finds {@link ExceptionHandler} methods in the given type. * A constructor that finds {@link ExceptionHandler} methods in the given type.
* @param handlerType the type to introspect * @param handlerType the type to introspect
@ -63,6 +74,7 @@ public class ExceptionHandlerMethodResolver {
} }
} }
/** /**
* Extract exception mappings from the {@code @ExceptionHandler} annotation * Extract exception mappings from the {@code @ExceptionHandler} annotation
* first and as a fall-back from the method signature. * first and as a fall-back from the method signature.
@ -70,9 +82,7 @@ public class ExceptionHandlerMethodResolver {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private List<Class<? extends Throwable>> detectExceptionMappings(Method method) { private List<Class<? extends Throwable>> detectExceptionMappings(Method method) {
List<Class<? extends Throwable>> result = new ArrayList<Class<? extends Throwable>>(); List<Class<? extends Throwable>> result = new ArrayList<Class<? extends Throwable>>();
detectAnnotationExceptionMappings(method, result); detectAnnotationExceptionMappings(method, result);
if (result.isEmpty()) { if (result.isEmpty()) {
for (Class<?> paramType : method.getParameterTypes()) { for (Class<?> paramType : method.getParameterTypes()) {
if (Throwable.class.isAssignableFrom(paramType)) { if (Throwable.class.isAssignableFrom(paramType)) {
@ -80,9 +90,7 @@ public class ExceptionHandlerMethodResolver {
} }
} }
} }
Assert.notEmpty(result, "No exception types mapped to {" + method + "}"); Assert.notEmpty(result, "No exception types mapped to {" + method + "}");
return result; return result;
} }
@ -151,14 +159,4 @@ public class ExceptionHandlerMethodResolver {
} }
} }
/** A filter for selecting annotated exception handling methods. */
public final static MethodFilter EXCEPTION_HANDLER_METHODS = new MethodFilter() {
@Override
public boolean matches(Method method) {
return AnnotationUtils.findAnnotation(method, ExceptionHandler.class) != null;
}
};
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 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.
@ -28,20 +28,13 @@ import java.util.Iterator;
*/ */
public abstract class AbstractRequestCondition<T extends AbstractRequestCondition<T>> implements RequestCondition<T> { public abstract class AbstractRequestCondition<T extends AbstractRequestCondition<T>> implements RequestCondition<T> {
/**
* Return the discrete items a request condition is composed of.
* For example URL patterns, HTTP request methods, param expressions, etc.
* @return a collection of objects, never {@code null}
*/
protected abstract Collection<?> getContent();
@Override @Override
public boolean equals(Object o) { public boolean equals(Object obj) {
if (this == o) { if (this == obj) {
return true; return true;
} }
if (o != null && getClass().equals(o.getClass())) { if (obj != null && getClass().equals(obj.getClass())) {
AbstractRequestCondition<?> other = (AbstractRequestCondition<?>) o; AbstractRequestCondition<?> other = (AbstractRequestCondition<?>) obj;
return getContent().equals(other.getContent()); return getContent().equals(other.getContent());
} }
return false; return false;
@ -66,6 +59,14 @@ public abstract class AbstractRequestCondition<T extends AbstractRequestConditio
return builder.toString(); return builder.toString();
} }
/**
* Return the discrete items a request condition is composed of.
* For example URL patterns, HTTP request methods, param expressions, etc.
* @return a collection of objects, never {@code null}
*/
protected abstract Collection<?> getContent();
/** /**
* The notation to use when printing discrete items of content. * The notation to use when printing discrete items of content.
* For example " || " for URL patterns or " && " for param expressions. * For example " || " for URL patterns or " && " for param expressions.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 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.
@ -20,7 +20,6 @@ import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.springframework.util.Assert; import org.springframework.util.Assert;
@ -43,6 +42,7 @@ public class CompositeRequestCondition extends AbstractRequestCondition<Composit
private final RequestConditionHolder[] requestConditions; private final RequestConditionHolder[] requestConditions;
/** /**
* Create an instance with 0 or more {@code RequestCondition} types. It is * Create an instance with 0 or more {@code RequestCondition} types. It is
* important to create {@code CompositeRequestCondition} instances with the * important to create {@code CompositeRequestCondition} instances with the
@ -53,6 +53,11 @@ public class CompositeRequestCondition extends AbstractRequestCondition<Composit
this.requestConditions = wrap(requestConditions); this.requestConditions = wrap(requestConditions);
} }
private CompositeRequestCondition(RequestConditionHolder[] requestConditions) {
this.requestConditions = requestConditions;
}
private RequestConditionHolder[] wrap(RequestCondition<?>... rawConditions) { private RequestConditionHolder[] wrap(RequestCondition<?>... rawConditions) {
RequestConditionHolder[] wrappedConditions = new RequestConditionHolder[rawConditions.length]; RequestConditionHolder[] wrappedConditions = new RequestConditionHolder[rawConditions.length];
for (int i = 0; i < rawConditions.length; i++) { for (int i = 0; i < rawConditions.length; i++) {
@ -61,10 +66,6 @@ public class CompositeRequestCondition extends AbstractRequestCondition<Composit
return wrappedConditions; return wrappedConditions;
} }
private CompositeRequestCondition(RequestConditionHolder[] requestConditions) {
this.requestConditions = requestConditions;
}
/** /**
* Whether this instance contains 0 conditions or not. * Whether this instance contains 0 conditions or not.
*/ */
@ -129,8 +130,9 @@ public class CompositeRequestCondition extends AbstractRequestCondition<Composit
private void assertNumberOfConditions(CompositeRequestCondition other) { private void assertNumberOfConditions(CompositeRequestCondition other) {
Assert.isTrue(getLength() == other.getLength(), Assert.isTrue(getLength() == other.getLength(),
"Cannot combine CompositeRequestConditions with a different number of conditions. " "Cannot combine CompositeRequestConditions with a different number of conditions. " +
+ this.requestConditions + " and " + other.requestConditions); ObjectUtils.nullSafeToString(this.requestConditions) + " and " +
ObjectUtils.nullSafeToString(other.requestConditions));
} }
/** /**

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 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,7 +23,6 @@ import java.util.Iterator;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.springframework.http.InvalidMediaTypeException; import org.springframework.http.InvalidMediaTypeException;
@ -49,11 +48,12 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
private final List<ConsumeMediaTypeExpression> expressions; private final List<ConsumeMediaTypeExpression> expressions;
/** /**
* Creates a new instance from 0 or more "consumes" expressions. * Creates a new instance from 0 or more "consumes" expressions.
* @param consumes expressions with the syntax described in * @param consumes expressions with the syntax described in
* {@link RequestMapping#consumes()}; if 0 expressions are provided, * {@link RequestMapping#consumes()}; if 0 expressions are provided,
* the condition will match to every request. * the condition will match to every request
*/ */
public ConsumesRequestCondition(String... consumes) { public ConsumesRequestCondition(String... consumes) {
this(consumes, null); this(consumes, null);
@ -79,6 +79,7 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
Collections.sort(this.expressions); Collections.sort(this.expressions);
} }
private static Set<ConsumeMediaTypeExpression> parseExpressions(String[] consumes, String[] headers) { private static Set<ConsumeMediaTypeExpression> parseExpressions(String[] consumes, String[] headers) {
Set<ConsumeMediaTypeExpression> result = new LinkedHashSet<ConsumeMediaTypeExpression>(); Set<ConsumeMediaTypeExpression> result = new LinkedHashSet<ConsumeMediaTypeExpression>();
if (headers != null) { if (headers != null) {
@ -99,6 +100,7 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
return result; return result;
} }
/** /**
* Return the contained MediaType expressions. * Return the contained MediaType expressions.
*/ */
@ -151,9 +153,7 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
* request 'Content-Type' header and returns an instance that is guaranteed * request 'Content-Type' header and returns an instance that is guaranteed
* to contain matching expressions only. The match is performed via * to contain matching expressions only. The match is performed via
* {@link MediaType#includes(MediaType)}. * {@link MediaType#includes(MediaType)}.
*
* @param request the current request * @param request the current request
*
* @return the same instance if the condition contains no expressions; * @return the same instance if the condition contains no expressions;
* or a new condition with matching expressions only; * or a new condition with matching expressions only;
* or {@code null} if no expressions match. * or {@code null} if no expressions match.
@ -180,7 +180,6 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
* <li>Less than 0 if "this" has more or more specific media type expressions * <li>Less than 0 if "this" has more or more specific media type expressions
* <li>Greater than 0 if "other" has more or more specific media type expressions * <li>Greater than 0 if "other" has more or more specific media type expressions
* </ul> * </ul>
*
* <p>It is assumed that both instances have been obtained via * <p>It is assumed that both instances have been obtained via
* {@link #getMatchingCondition(HttpServletRequest)} and each instance contains * {@link #getMatchingCondition(HttpServletRequest)} and each instance contains
* the matching consumable media type expression only or is otherwise empty. * the matching consumable media type expression only or is otherwise empty.
@ -201,6 +200,7 @@ public final class ConsumesRequestCondition extends AbstractRequestCondition<Con
} }
} }
/** /**
* Parses and matches a single media type expression to a request's 'Content-Type' header. * Parses and matches a single media type expression to a request's 'Content-Type' header.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 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.
@ -20,7 +20,6 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -41,12 +40,13 @@ public final class HeadersRequestCondition extends AbstractRequestCondition<Head
private final Set<HeaderExpression> expressions; private final Set<HeaderExpression> expressions;
/** /**
* Create a new instance from the given header expressions. Expressions with * Create a new instance from the given header expressions. Expressions with
* header names 'Accept' or 'Content-Type' are ignored. See {@link ConsumesRequestCondition} * header names 'Accept' or 'Content-Type' are ignored. See {@link ConsumesRequestCondition}
* and {@link ProducesRequestCondition} for those. * and {@link ProducesRequestCondition} for those.
* @param headers media type expressions with syntax defined in {@link RequestMapping#headers()}; * @param headers media type expressions with syntax defined in {@link RequestMapping#headers()};
* if 0, the condition will match to every request. * if 0, the condition will match to every request
*/ */
public HeadersRequestCondition(String... headers) { public HeadersRequestCondition(String... headers) {
this(parseExpressions(headers)); this(parseExpressions(headers));
@ -56,6 +56,7 @@ public final class HeadersRequestCondition extends AbstractRequestCondition<Head
this.expressions = Collections.unmodifiableSet(new LinkedHashSet<HeaderExpression>(conditions)); this.expressions = Collections.unmodifiableSet(new LinkedHashSet<HeaderExpression>(conditions));
} }
private static Collection<HeaderExpression> parseExpressions(String... headers) { private static Collection<HeaderExpression> parseExpressions(String... headers) {
Set<HeaderExpression> expressions = new LinkedHashSet<HeaderExpression>(); Set<HeaderExpression> expressions = new LinkedHashSet<HeaderExpression>();
if (headers != null) { if (headers != null) {
@ -119,7 +120,6 @@ public final class HeadersRequestCondition extends AbstractRequestCondition<Head
* <li>Less than 0 if "this" instance has more header expressions * <li>Less than 0 if "this" instance has more header expressions
* <li>Greater than 0 if the "other" instance has more header expressions * <li>Greater than 0 if the "other" instance has more header expressions
* </ul> * </ul>
*
* <p>It is assumed that both instances have been obtained via * <p>It is assumed that both instances have been obtained via
* {@link #getMatchingCondition(HttpServletRequest)} and each instance * {@link #getMatchingCondition(HttpServletRequest)} and each instance
* contains the matching header expression only or is otherwise empty. * contains the matching header expression only or is otherwise empty.
@ -129,6 +129,7 @@ public final class HeadersRequestCondition extends AbstractRequestCondition<Head
return other.expressions.size() - this.expressions.size(); return other.expressions.size() - this.expressions.size();
} }
/** /**
* Parses and matches a single header expression to a request. * Parses and matches a single header expression to a request.
*/ */
@ -161,4 +162,5 @@ public final class HeadersRequestCondition extends AbstractRequestCondition<Head
return result; return result;
} }
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 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.
@ -20,7 +20,6 @@ import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.Set; import java.util.Set;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
@ -38,6 +37,7 @@ public final class ParamsRequestCondition extends AbstractRequestCondition<Param
private final Set<ParamExpression> expressions; private final Set<ParamExpression> expressions;
/** /**
* Create a new instance from the given param expressions. * Create a new instance from the given param expressions.
* @param params expressions with syntax defined in {@link RequestMapping#params()}; * @param params expressions with syntax defined in {@link RequestMapping#params()};
@ -51,6 +51,7 @@ public final class ParamsRequestCondition extends AbstractRequestCondition<Param
this.expressions = Collections.unmodifiableSet(new LinkedHashSet<ParamExpression>(conditions)); this.expressions = Collections.unmodifiableSet(new LinkedHashSet<ParamExpression>(conditions));
} }
private static Collection<ParamExpression> parseExpressions(String... params) { private static Collection<ParamExpression> parseExpressions(String... params) {
Set<ParamExpression> expressions = new LinkedHashSet<ParamExpression>(); Set<ParamExpression> expressions = new LinkedHashSet<ParamExpression>();
if (params != null) { if (params != null) {
@ -61,6 +62,7 @@ public final class ParamsRequestCondition extends AbstractRequestCondition<Param
return expressions; return expressions;
} }
/** /**
* Return the contained request parameter expressions. * Return the contained request parameter expressions.
*/ */
@ -70,7 +72,7 @@ public final class ParamsRequestCondition extends AbstractRequestCondition<Param
@Override @Override
protected Collection<ParamExpression> getContent() { protected Collection<ParamExpression> getContent() {
return expressions; return this.expressions;
} }
@Override @Override
@ -110,16 +112,16 @@ public final class ParamsRequestCondition extends AbstractRequestCondition<Param
* <li>Less than 0 if "this" instance has more parameter expressions * <li>Less than 0 if "this" instance has more parameter expressions
* <li>Greater than 0 if the "other" instance has more parameter expressions * <li>Greater than 0 if the "other" instance has more parameter expressions
* </ul> * </ul>
*
* <p>It is assumed that both instances have been obtained via * <p>It is assumed that both instances have been obtained via
* {@link #getMatchingCondition(HttpServletRequest)} and each instance * {@link #getMatchingCondition(HttpServletRequest)} and each instance
* contains the matching parameter expressions only or is otherwise empty. * contains the matching parameter expressions only or is otherwise empty.
*/ */
@Override @Override
public int compareTo(ParamsRequestCondition other, HttpServletRequest request) { public int compareTo(ParamsRequestCondition other, HttpServletRequest request) {
return other.expressions.size() - this.expressions.size(); return (other.expressions.size() - this.expressions.size());
} }
/** /**
* Parses and matches a single param expression to a request. * Parses and matches a single param expression to a request.
*/ */

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2014 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.
@ -264,7 +264,6 @@ public final class PatternsRequestCondition extends AbstractRequestCondition<Pat
public int compareTo(PatternsRequestCondition other, HttpServletRequest request) { public int compareTo(PatternsRequestCondition other, HttpServletRequest request) {
String lookupPath = this.pathHelper.getLookupPathForRequest(request); String lookupPath = this.pathHelper.getLookupPathForRequest(request);
Comparator<String> patternComparator = this.pathMatcher.getPatternComparator(lookupPath); Comparator<String> patternComparator = this.pathMatcher.getPatternComparator(lookupPath);
Iterator<String> iterator = this.patterns.iterator(); Iterator<String> iterator = this.patterns.iterator();
Iterator<String> iteratorOther = other.patterns.iterator(); Iterator<String> iteratorOther = other.patterns.iterator();
while (iterator.hasNext() && iteratorOther.hasNext()) { while (iterator.hasNext() && iteratorOther.hasNext()) {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 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,7 +23,6 @@ import java.util.Iterator;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
@ -46,10 +45,14 @@ import org.springframework.web.servlet.mvc.condition.HeadersRequestCondition.Hea
*/ */
public final class ProducesRequestCondition extends AbstractRequestCondition<ProducesRequestCondition> { public final class ProducesRequestCondition extends AbstractRequestCondition<ProducesRequestCondition> {
private final List<ProduceMediaTypeExpression> MEDIA_TYPE_ALL_LIST =
Collections.singletonList(new ProduceMediaTypeExpression("*/*"));
private final List<ProduceMediaTypeExpression> expressions; private final List<ProduceMediaTypeExpression> expressions;
private final ContentNegotiationManager contentNegotiationManager; private final ContentNegotiationManager contentNegotiationManager;
/** /**
* Creates a new instance from "produces" expressions. If 0 expressions * Creates a new instance from "produces" expressions. If 0 expressions
* are provided in total, this condition will match to any request. * are provided in total, this condition will match to any request.
@ -78,14 +81,22 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
* @param headers expressions with syntax defined by {@link RequestMapping#headers()} * @param headers expressions with syntax defined by {@link RequestMapping#headers()}
* @param manager used to determine requested media types * @param manager used to determine requested media types
*/ */
public ProducesRequestCondition(String[] produces, String[] headers, public ProducesRequestCondition(String[] produces, String[] headers, ContentNegotiationManager manager) {
ContentNegotiationManager manager) {
this.expressions = new ArrayList<ProduceMediaTypeExpression>(parseExpressions(produces, headers)); this.expressions = new ArrayList<ProduceMediaTypeExpression>(parseExpressions(produces, headers));
Collections.sort(this.expressions); Collections.sort(this.expressions);
this.contentNegotiationManager = (manager != null) ? manager : new ContentNegotiationManager(); this.contentNegotiationManager = (manager != null ? manager : new ContentNegotiationManager());
} }
/**
* Private constructor with already parsed media type expressions.
*/
private ProducesRequestCondition(Collection<ProduceMediaTypeExpression> expressions, ContentNegotiationManager manager) {
this.expressions = new ArrayList<ProduceMediaTypeExpression>(expressions);
Collections.sort(this.expressions);
this.contentNegotiationManager = (manager != null ? manager : new ContentNegotiationManager());
}
private Set<ProduceMediaTypeExpression> parseExpressions(String[] produces, String[] headers) { private Set<ProduceMediaTypeExpression> parseExpressions(String[] produces, String[] headers) {
Set<ProduceMediaTypeExpression> result = new LinkedHashSet<ProduceMediaTypeExpression>(); Set<ProduceMediaTypeExpression> result = new LinkedHashSet<ProduceMediaTypeExpression>();
if (headers != null) { if (headers != null) {
@ -106,17 +117,6 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
return result; return result;
} }
/**
* Private constructor with already parsed media type expressions.
*/
private ProducesRequestCondition(Collection<ProduceMediaTypeExpression> expressions,
ContentNegotiationManager manager) {
this.expressions = new ArrayList<ProduceMediaTypeExpression>(expressions);
Collections.sort(this.expressions);
this.contentNegotiationManager = (manager != null) ? manager : new ContentNegotiationManager();
}
/** /**
* Return the contained "produces" expressions. * Return the contained "produces" expressions.
*/ */
@ -169,9 +169,7 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
* request 'Content-Type' header and returns an instance that is guaranteed * request 'Content-Type' header and returns an instance that is guaranteed
* to contain matching expressions only. The match is performed via * to contain matching expressions only. The match is performed via
* {@link MediaType#isCompatibleWith(MediaType)}. * {@link MediaType#isCompatibleWith(MediaType)}.
*
* @param request the current request * @param request the current request
*
* @return the same instance if there are no expressions; * @return the same instance if there are no expressions;
* or a new condition with matching expressions; * or a new condition with matching expressions;
* or {@code null} if no expressions match. * or {@code null} if no expressions match.
@ -193,7 +191,6 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
/** /**
* Compares this and another "produces" condition as follows: * Compares this and another "produces" condition as follows:
*
* <ol> * <ol>
* <li>Sort 'Accept' header media types by quality value via * <li>Sort 'Accept' header media types by quality value via
* {@link MediaType#sortByQualityValue(List)} and iterate the list. * {@link MediaType#sortByQualityValue(List)} and iterate the list.
@ -204,7 +201,6 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
* <li>If both indexes are equal, the media types at the index are * <li>If both indexes are equal, the media types at the index are
* compared further with {@link MediaType#SPECIFICITY_COMPARATOR}. * compared further with {@link MediaType#SPECIFICITY_COMPARATOR}.
* </ol> * </ol>
*
* <p>It is assumed that both instances have been obtained via * <p>It is assumed that both instances have been obtained via
* {@link #getMatchingCondition(HttpServletRequest)} and each instance * {@link #getMatchingCondition(HttpServletRequest)} and each instance
* contains the matching producible media type expression only or * contains the matching producible media type expression only or
@ -214,7 +210,6 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
public int compareTo(ProducesRequestCondition other, HttpServletRequest request) { public int compareTo(ProducesRequestCondition other, HttpServletRequest request) {
try { try {
List<MediaType> acceptedMediaTypes = getAcceptedMediaTypes(request); List<MediaType> acceptedMediaTypes = getAcceptedMediaTypes(request);
for (MediaType acceptedMediaType : acceptedMediaTypes) { for (MediaType acceptedMediaType : acceptedMediaTypes) {
int thisIndex = this.indexOfEqualMediaType(acceptedMediaType); int thisIndex = this.indexOfEqualMediaType(acceptedMediaType);
int otherIndex = other.indexOfEqualMediaType(acceptedMediaType); int otherIndex = other.indexOfEqualMediaType(acceptedMediaType);
@ -262,14 +257,14 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
return -1; return -1;
} }
private int compareMatchingMediaTypes(ProducesRequestCondition condition1, private int compareMatchingMediaTypes(ProducesRequestCondition condition1, int index1,
int index1, ProducesRequestCondition condition2, int index2) { ProducesRequestCondition condition2, int index2) {
int result = 0; int result = 0;
if (index1 != index2) { if (index1 != index2) {
result = index2 - index1; result = index2 - index1;
} }
else if (index1 != -1 && index2 != -1) { else if (index1 != -1) {
ProduceMediaTypeExpression expr1 = condition1.getExpressionsToCompare().get(index1); ProduceMediaTypeExpression expr1 = condition1.getExpressionsToCompare().get(index1);
ProduceMediaTypeExpression expr2 = condition2.getExpressionsToCompare().get(index2); ProduceMediaTypeExpression expr2 = condition2.getExpressionsToCompare().get(index2);
result = expr1.compareTo(expr2); result = expr1.compareTo(expr2);
@ -283,12 +278,9 @@ public final class ProducesRequestCondition extends AbstractRequestCondition<Pro
* with a {@code MediaType_ALL} expression. * with a {@code MediaType_ALL} expression.
*/ */
private List<ProduceMediaTypeExpression> getExpressionsToCompare() { private List<ProduceMediaTypeExpression> getExpressionsToCompare() {
return this.expressions.isEmpty() ? MEDIA_TYPE_ALL_LIST : this.expressions; return (this.expressions.isEmpty() ? MEDIA_TYPE_ALL_LIST : this.expressions);
} }
private final List<ProduceMediaTypeExpression> MEDIA_TYPE_ALL_LIST =
Collections.singletonList(new ProduceMediaTypeExpression("*/*"));
/** /**
* Parses and matches a single media type expression to a request's 'Accept' header. * Parses and matches a single media type expression to a request's 'Accept' header.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 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.
@ -21,15 +21,14 @@ import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMapping;
/** /**
* The contract for request conditions. * The contract for request conditions in Spring MVC's mapping infrastructure.
* *
* <p>Request conditions can be combined via {@link #combine(Object)}, matched to * <p>Request conditions can be combined via {@link #combine(Object)}, matched to
* a request via {@link #getMatchingCondition(HttpServletRequest)}, and compared * a request via {@link #getMatchingCondition(HttpServletRequest)}, and compared
* to each other via {@link #compareTo(Object, HttpServletRequest)} to determine * to each other via {@link #compareTo(Object, HttpServletRequest)} to determine
* which matches a request more closely. * which matches a request more closely.
* *
* @param <T> The type of objects that this RequestCondition can be combined * @param <T> the type of objects that this RequestCondition can be combined with and compared to
* with compared to.
* *
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @author Arjen Poutsma * @author Arjen Poutsma
@ -41,7 +40,6 @@ public interface RequestCondition<T> {
* Defines the rules for combining this condition (i.e. the current instance) * Defines the rules for combining this condition (i.e. the current instance)
* with another condition. For example combining type- and method-level * with another condition. For example combining type- and method-level
* {@link RequestMapping} conditions. * {@link RequestMapping} conditions.
*
* @param other the condition to combine with. * @param other the condition to combine with.
* @return a request condition instance that is the result of combining * @return a request condition instance that is the result of combining
* the two condition instances. * the two condition instances.
@ -54,9 +52,8 @@ public interface RequestCondition<T> {
* current request. For example a condition with URL patterns might * current request. For example a condition with URL patterns might
* return a new condition that contains matching patterns sorted * return a new condition that contains matching patterns sorted
* with best matching patterns on top. * with best matching patterns on top.
*
* @return a condition instance in case of a match; * @return a condition instance in case of a match;
* or {@code null} if there is no match. * or {@code null} if there is no match
*/ */
T getMatchingCondition(HttpServletRequest request); T getMatchingCondition(HttpServletRequest request);

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 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.
@ -18,7 +18,6 @@ package org.springframework.web.servlet.mvc.condition;
import java.util.Collection; import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
/** /**
@ -39,6 +38,7 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
private final RequestCondition<Object> condition; private final RequestCondition<Object> 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}
@ -48,6 +48,7 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
this.condition = (RequestCondition<Object>) 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.
*/ */
@ -57,7 +58,7 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
@Override @Override
protected Collection<?> getContent() { protected Collection<?> getContent() {
return this.condition != null ? Collections.singleton(this.condition) : Collections.emptyList(); return (this.condition != null ? Collections.singleton(this.condition) : Collections.emptyList());
} }
@Override @Override
@ -110,7 +111,7 @@ public final class RequestConditionHolder extends AbstractRequestCondition<Reque
return this; return this;
} }
RequestCondition<?> match = (RequestCondition<?>) this.condition.getMatchingCondition(request); RequestCondition<?> match = (RequestCondition<?>) this.condition.getMatchingCondition(request);
return (match != null) ? new RequestConditionHolder(match) : null; return (match != null ? new RequestConditionHolder(match) : null);
} }
/** /**

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2012 the original author or authors. * Copyright 2002-2014 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.
@ -22,7 +22,6 @@ import java.util.Collections;
import java.util.LinkedHashSet; import java.util.LinkedHashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestMethod;
@ -39,36 +38,36 @@ public final class RequestMethodsRequestCondition extends AbstractRequestConditi
private final Set<RequestMethod> methods; private final Set<RequestMethod> methods;
/** /**
* Create a new instance with the given request methods. * Create a new instance with the given request methods.
* @param requestMethods 0 or more HTTP request methods; * @param requestMethods 0 or more HTTP request methods;
* if, 0 the condition will match to every request. * if, 0 the condition will match to every request
*/ */
public RequestMethodsRequestCondition(RequestMethod... requestMethods) { public RequestMethodsRequestCondition(RequestMethod... requestMethods) {
this(asList(requestMethods)); this(asList(requestMethods));
} }
private static List<RequestMethod> asList(RequestMethod... requestMethods) {
return requestMethods != null ? Arrays.asList(requestMethods) : Collections.<RequestMethod>emptyList();
}
/**
* Private constructor.
*/
private RequestMethodsRequestCondition(Collection<RequestMethod> requestMethods) { private RequestMethodsRequestCondition(Collection<RequestMethod> requestMethods) {
this.methods = Collections.unmodifiableSet(new LinkedHashSet<RequestMethod>(requestMethods)); this.methods = Collections.unmodifiableSet(new LinkedHashSet<RequestMethod>(requestMethods));
} }
private static List<RequestMethod> asList(RequestMethod... requestMethods) {
return (requestMethods != null ? Arrays.asList(requestMethods) : Collections.<RequestMethod>emptyList());
}
/** /**
* Returns all {@link RequestMethod}s contained in this condition. * Returns all {@link RequestMethod}s contained in this condition.
*/ */
public Set<RequestMethod> getMethods() { public Set<RequestMethod> getMethods() {
return methods; return this.methods;
} }
@Override @Override
protected Collection<RequestMethod> getContent() { protected Collection<RequestMethod> getContent() {
return methods; return this.methods;
} }
@Override @Override
@ -127,14 +126,13 @@ public final class RequestMethodsRequestCondition extends AbstractRequestConditi
* <li>Less than 0 if "this" instance has an HTTP request method but "other" doesn't * <li>Less than 0 if "this" instance has an HTTP request method but "other" doesn't
* <li>Greater than 0 "other" has an HTTP request method but "this" doesn't * <li>Greater than 0 "other" has an HTTP request method but "this" doesn't
* </ul> * </ul>
*
* <p>It is assumed that both instances have been obtained via * <p>It is assumed that both instances have been obtained via
* {@link #getMatchingCondition(HttpServletRequest)} and therefore each instance * {@link #getMatchingCondition(HttpServletRequest)} and therefore each instance
* contains the matching HTTP request method only or is otherwise empty. * contains the matching HTTP request method only or is otherwise empty.
*/ */
@Override @Override
public int compareTo(RequestMethodsRequestCondition other, HttpServletRequest request) { public int compareTo(RequestMethodsRequestCondition other, HttpServletRequest request) {
return other.methods.size() - this.methods.size(); return (other.methods.size() - this.methods.size());
} }
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2014 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.
@ -16,9 +16,15 @@
package org.springframework.web.servlet.mvc.method; package org.springframework.web.servlet.mvc.method;
import java.util.*; import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set;
import javax.servlet.ServletException; import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
@ -45,7 +51,7 @@ import org.springframework.web.util.WebUtils;
* *
* @author Arjen Poutsma * @author Arjen Poutsma
* @author Rossen Stoyanchev * @author Rossen Stoyanchev
* @since 3.1.0 * @since 3.1
*/ */
public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMethodMapping<RequestMappingInfo> { public abstract class RequestMappingInfoHandlerMapping extends AbstractHandlerMethodMapping<RequestMappingInfo> {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2014 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.
@ -78,7 +78,6 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
/** /**
* Whether to use suffix pattern match for registered file extensions only * Whether to use suffix pattern match for registered file extensions only
* when matching patterns to requests. * when matching patterns to requests.
*
* <p>If enabled, a controller method mapped to "/users" also matches to * <p>If enabled, a controller method mapped to "/users" also matches to
* "/users.json" assuming ".json" is a file extension registered with the * "/users.json" assuming ".json" is a file extension registered with the
* provided {@link #setContentNegotiationManager(ContentNegotiationManager) * provided {@link #setContentNegotiationManager(ContentNegotiationManager)
@ -87,14 +86,13 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
* can lead to ambiguous interpretation of path variable content, (e.g. given * can lead to ambiguous interpretation of path variable content, (e.g. given
* "/users/{user}" and incoming URLs such as "/users/john.j.joe" and * "/users/{user}" and incoming URLs such as "/users/john.j.joe" and
* "/users/john.j.joe.json"). * "/users/john.j.joe.json").
*
* <p>If enabled, this flag also enables * <p>If enabled, this flag also enables
* {@link #setUseSuffixPatternMatch(boolean) useSuffixPatternMatch}. The * {@link #setUseSuffixPatternMatch(boolean) useSuffixPatternMatch}. The
* default value is {@code false}. * default value is {@code false}.
*/ */
public void setUseRegisteredSuffixPatternMatch(boolean useRegisteredSuffixPatternMatch) { public void setUseRegisteredSuffixPatternMatch(boolean useRegisteredSuffixPatternMatch) {
this.useRegisteredSuffixPatternMatch = useRegisteredSuffixPatternMatch; this.useRegisteredSuffixPatternMatch = useRegisteredSuffixPatternMatch;
this.useSuffixPatternMatch = useRegisteredSuffixPatternMatch ? true : this.useSuffixPatternMatch; this.useSuffixPatternMatch = (useRegisteredSuffixPatternMatch || this.useSuffixPatternMatch);
} }
/** /**
@ -106,20 +104,30 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
this.useTrailingSlashMatch = useTrailingSlashMatch; this.useTrailingSlashMatch = useTrailingSlashMatch;
} }
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
this.embeddedValueResolver = resolver;
}
/** /**
* Set the {@link ContentNegotiationManager} to use to determine requested media types. * Set the {@link ContentNegotiationManager} to use to determine requested media types.
* If not set, the default constructor is used. * If not set, the default constructor is used.
*/ */
public void setContentNegotiationManager(ContentNegotiationManager contentNegotiationManager) { public void setContentNegotiationManager(ContentNegotiationManager contentNegotiationManager) {
Assert.notNull(contentNegotiationManager); Assert.notNull(contentNegotiationManager, "ContentNegotiationManager must not be null");
this.contentNegotiationManager = contentNegotiationManager; this.contentNegotiationManager = contentNegotiationManager;
} }
@Override
public void setEmbeddedValueResolver(StringValueResolver resolver) {
this.embeddedValueResolver = resolver;
}
@Override
public void afterPropertiesSet() {
if (this.useRegisteredSuffixPatternMatch) {
this.fileExtensions.addAll(this.contentNegotiationManager.getAllFileExtensions());
}
super.afterPropertiesSet();
}
/** /**
* Whether to use suffix pattern matching. * Whether to use suffix pattern matching.
*/ */
@ -131,7 +139,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
* Whether to use registered suffixes for pattern matching. * Whether to use registered suffixes for pattern matching.
*/ */
public boolean useRegisteredSuffixPatternMatch() { public boolean useRegisteredSuffixPatternMatch() {
return useRegisteredSuffixPatternMatch; return this.useRegisteredSuffixPatternMatch;
} }
/** /**
@ -155,13 +163,6 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
return this.fileExtensions; return this.fileExtensions;
} }
@Override
public void afterPropertiesSet() {
if (this.useRegisteredSuffixPatternMatch) {
this.fileExtensions.addAll(contentNegotiationManager.getAllFileExtensions());
}
super.afterPropertiesSet();
}
/** /**
* {@inheritDoc} * {@inheritDoc}
@ -176,10 +177,8 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
/** /**
* Uses method and type-level @{@link RequestMapping} annotations to create * Uses method and type-level @{@link RequestMapping} annotations to create
* the RequestMappingInfo. * the RequestMappingInfo.
*
* @return the created RequestMappingInfo, or {@code null} if the method * @return the created RequestMappingInfo, or {@code null} if the method
* does not have a {@code @RequestMapping} annotation. * does not have a {@code @RequestMapping} annotation.
*
* @see #getCustomMethodCondition(Method) * @see #getCustomMethodCondition(Method)
* @see #getCustomTypeCondition(Class) * @see #getCustomTypeCondition(Class)
*/ */
@ -204,11 +203,9 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
* 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 * <p>Consider extending {@link AbstractRequestCondition} for custom
* condition types and using {@link CompositeRequestCondition} to provide * condition types and using {@link CompositeRequestCondition} to provide
* multiple custom conditions. * 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}
*/ */
@ -221,11 +218,9 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
* 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 * <p>Consider extending {@link AbstractRequestCondition} for custom
* condition types and using {@link CompositeRequestCondition} to provide * condition types and using {@link CompositeRequestCondition} to provide
* multiple custom conditions. * multiple custom conditions.
*
* @param method the handler method for which to create the condition * @param method the handler method for which to create the condition
* @return the condition, or {@code null} * @return the condition, or {@code null}
*/ */
@ -236,9 +231,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
/** /**
* Created a RequestMappingInfo from a RequestMapping annotation. * Created a RequestMappingInfo from a RequestMapping annotation.
*/ */
protected RequestMappingInfo createRequestMappingInfo(RequestMapping annotation, protected RequestMappingInfo createRequestMappingInfo(RequestMapping annotation, RequestCondition<?> customCondition) {
RequestCondition<?> customCondition) {
String[] patterns = resolveEmbeddedValuesInPatterns(annotation.value()); String[] patterns = resolveEmbeddedValuesInPatterns(annotation.value());
return new RequestMappingInfo( return new RequestMappingInfo(
new PatternsRequestCondition(patterns, getUrlPathHelper(), getPathMatcher(), new PatternsRequestCondition(patterns, getUrlPathHelper(), getPathMatcher(),
@ -247,7 +240,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
new ParamsRequestCondition(annotation.params()), new ParamsRequestCondition(annotation.params()),
new HeadersRequestCondition(annotation.headers()), new HeadersRequestCondition(annotation.headers()),
new ConsumesRequestCondition(annotation.consumes(), annotation.headers()), new ConsumesRequestCondition(annotation.consumes(), annotation.headers()),
new ProducesRequestCondition(annotation.produces(), annotation.headers(), getContentNegotiationManager()), new ProducesRequestCondition(annotation.produces(), annotation.headers(), this.contentNegotiationManager),
customCondition); customCondition);
} }
@ -261,7 +254,7 @@ public class RequestMappingHandlerMapping extends RequestMappingInfoHandlerMappi
} }
else { else {
String[] resolvedPatterns = new String[patterns.length]; String[] resolvedPatterns = new String[patterns.length];
for (int i=0; i < patterns.length; i++) { for (int i = 0; i < patterns.length; i++) {
resolvedPatterns[i] = this.embeddedValueResolver.resolveStringValue(patterns[i]); resolvedPatterns[i] = this.embeddedValueResolver.resolveStringValue(patterns[i]);
} }
return resolvedPatterns; return resolvedPatterns;

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2013 the original author or authors. * Copyright 2002-2014 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.
@ -13,12 +13,8 @@
* See the License for the specific language governing permissions and * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
*/ */
package org.springframework.web.servlet.mvc.method.annotation;
import static org.junit.Assert.assertArrayEquals; package org.springframework.web.servlet.mvc.method.annotation;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays; import java.util.Arrays;
@ -29,6 +25,7 @@ import java.util.Set;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.springframework.http.MediaType; import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller; import org.springframework.stereotype.Controller;
import org.springframework.util.StringValueResolver; import org.springframework.util.StringValueResolver;
@ -38,6 +35,8 @@ import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.context.support.StaticWebApplicationContext; import org.springframework.web.context.support.StaticWebApplicationContext;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import static org.junit.Assert.*;
/** /**
* Tests for {@link RequestMappingHandlerMapping}. * Tests for {@link RequestMappingHandlerMapping}.
* *
@ -47,14 +46,16 @@ public class RequestMappingHandlerMappingTests {
private RequestMappingHandlerMapping handlerMapping; private RequestMappingHandlerMapping handlerMapping;
@Before @Before
public void setup() { public void setup() {
this.handlerMapping = new RequestMappingHandlerMapping(); this.handlerMapping = new RequestMappingHandlerMapping();
this.handlerMapping.setApplicationContext(new StaticWebApplicationContext()); this.handlerMapping.setApplicationContext(new StaticWebApplicationContext());
} }
@Test @Test
public void useRegsiteredSuffixPatternMatch() { public void useRegisteredSuffixPatternMatch() {
assertTrue(this.handlerMapping.useSuffixPatternMatch()); assertTrue(this.handlerMapping.useSuffixPatternMatch());
assertFalse(this.handlerMapping.useRegisteredSuffixPatternMatch()); assertFalse(this.handlerMapping.useRegisteredSuffixPatternMatch());
@ -72,8 +73,7 @@ public class RequestMappingHandlerMappingTests {
} }
@Test @Test
public void useRegsiteredSuffixPatternMatchInitialization() { public void useRegisteredSuffixPatternMatchInitialization() {
Map<String, MediaType> fileExtensions = Collections.singletonMap("json", MediaType.APPLICATION_JSON); Map<String, MediaType> fileExtensions = Collections.singletonMap("json", MediaType.APPLICATION_JSON);
PathExtensionContentNegotiationStrategy strategy = new PathExtensionContentNegotiationStrategy(fileExtensions); PathExtensionContentNegotiationStrategy strategy = new PathExtensionContentNegotiationStrategy(fileExtensions);
ContentNegotiationManager manager = new ContentNegotiationManager(strategy); ContentNegotiationManager manager = new ContentNegotiationManager(strategy);