Polishing
This commit is contained in:
parent
23fa37b08b
commit
8dbe753963
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2014 the original author or authors.
|
* Copyright 2002-2015 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.
|
||||||
|
|
@ -309,6 +309,7 @@ public class MethodParameter {
|
||||||
/**
|
/**
|
||||||
* Return the generic type of the method/constructor parameter.
|
* Return the generic type of the method/constructor parameter.
|
||||||
* @return the parameter type (never {@code null})
|
* @return the parameter type (never {@code null})
|
||||||
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public Type getGenericParameterType() {
|
public Type getGenericParameterType() {
|
||||||
if (this.genericParameterType == null) {
|
if (this.genericParameterType == null) {
|
||||||
|
|
@ -324,6 +325,12 @@ public class MethodParameter {
|
||||||
return this.genericParameterType;
|
return this.genericParameterType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the nested type of the method/constructor parameter.
|
||||||
|
* @return the parameter type (never {@code null})
|
||||||
|
* @see #getNestingLevel()
|
||||||
|
* @since 3.1
|
||||||
|
*/
|
||||||
public Class<?> getNestedParameterType() {
|
public Class<?> getNestedParameterType() {
|
||||||
if (this.nestingLevel > 1) {
|
if (this.nestingLevel > 1) {
|
||||||
Type type = getGenericParameterType();
|
Type type = getGenericParameterType();
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2014 the original author or authors.
|
* Copyright 2002-2015 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.
|
||||||
|
|
@ -1092,9 +1092,8 @@ public final class ResolvableType implements Serializable {
|
||||||
public static ResolvableType forMethodParameter(MethodParameter methodParameter, Type targetType) {
|
public static ResolvableType forMethodParameter(MethodParameter methodParameter, Type targetType) {
|
||||||
Assert.notNull(methodParameter, "MethodParameter must not be null");
|
Assert.notNull(methodParameter, "MethodParameter must not be null");
|
||||||
ResolvableType owner = forType(methodParameter.getContainingClass()).as(methodParameter.getDeclaringClass());
|
ResolvableType owner = forType(methodParameter.getContainingClass()).as(methodParameter.getDeclaringClass());
|
||||||
return forType(targetType, new MethodParameterTypeProvider(methodParameter),
|
return forType(targetType, new MethodParameterTypeProvider(methodParameter), owner.asVariableResolver()).
|
||||||
owner.asVariableResolver()).getNested(methodParameter.getNestingLevel(),
|
getNested(methodParameter.getNestingLevel(), methodParameter.typeIndexesPerLevel);
|
||||||
methodParameter.typeIndexesPerLevel);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2014 the original author or authors.
|
* Copyright 2002-2015 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.
|
||||||
|
|
@ -32,10 +32,10 @@ import org.springframework.util.Assert;
|
||||||
import org.springframework.util.MimeType;
|
import org.springframework.util.MimeType;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for {@link MessageConverter} implementations including support for
|
* Abstract base class for {@link MessageConverter} implementations including support
|
||||||
* common properties and a partial implementation of the conversion methods mainly to
|
* for common properties and a partial implementation of the conversion methods,
|
||||||
* check if the converter supports the conversion based on the payload class and MIME
|
* mainly to check if the converter supports the conversion based on the payload class
|
||||||
* type.
|
* and MIME type.
|
||||||
*
|
*
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @since 4.0
|
* @since 4.0
|
||||||
|
|
@ -68,7 +68,7 @@ public abstract class AbstractMessageConverter implements MessageConverter {
|
||||||
* @param supportedMimeTypes the supported MIME types
|
* @param supportedMimeTypes the supported MIME types
|
||||||
*/
|
*/
|
||||||
protected AbstractMessageConverter(Collection<MimeType> supportedMimeTypes) {
|
protected AbstractMessageConverter(Collection<MimeType> supportedMimeTypes) {
|
||||||
Assert.notNull(supportedMimeTypes, "SupportedMimeTypes must not be null");
|
Assert.notNull(supportedMimeTypes, "supportedMimeTypes must not be null");
|
||||||
this.supportedMimeTypes = new ArrayList<MimeType>(supportedMimeTypes);
|
this.supportedMimeTypes = new ArrayList<MimeType>(supportedMimeTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -83,13 +83,11 @@ public abstract class AbstractMessageConverter implements MessageConverter {
|
||||||
/**
|
/**
|
||||||
* Configure the {@link ContentTypeResolver} to use to resolve the content
|
* Configure the {@link ContentTypeResolver} to use to resolve the content
|
||||||
* type of an input message.
|
* type of an input message.
|
||||||
* <p>
|
* <p>Note that if no resolver is configured, then
|
||||||
* Note that if no resolver is configured, then
|
|
||||||
* {@link #setStrictContentTypeMatch(boolean) strictContentTypeMatch} should
|
* {@link #setStrictContentTypeMatch(boolean) strictContentTypeMatch} should
|
||||||
* be left as {@code false} (the default) or otherwise this converter will
|
* be left as {@code false} (the default) or otherwise this converter will
|
||||||
* ignore all messages.
|
* ignore all messages.
|
||||||
* <p>
|
* <p>By default, a {@code DefaultContentTypeResolver} instance is used.
|
||||||
* By default, a {@code DefaultContentTypeResolver} instance is used.
|
|
||||||
*/
|
*/
|
||||||
public void setContentTypeResolver(ContentTypeResolver resolver) {
|
public void setContentTypeResolver(ContentTypeResolver resolver) {
|
||||||
this.contentTypeResolver = resolver;
|
this.contentTypeResolver = resolver;
|
||||||
|
|
@ -106,20 +104,17 @@ public abstract class AbstractMessageConverter implements MessageConverter {
|
||||||
* Whether this converter should convert messages for which no content type
|
* Whether this converter should convert messages for which no content type
|
||||||
* could be resolved through the configured
|
* could be resolved through the configured
|
||||||
* {@link org.springframework.messaging.converter.ContentTypeResolver}.
|
* {@link org.springframework.messaging.converter.ContentTypeResolver}.
|
||||||
* A converter can configured to be strict only when a
|
* <p>A converter can configured to be strict only when a
|
||||||
* {@link #setContentTypeResolver(ContentTypeResolver) contentTypeResolver}
|
* {@link #setContentTypeResolver contentTypeResolver} is configured and the
|
||||||
* is configured and the list of {@link #getSupportedMimeTypes() supportedMimeTypes}
|
* list of {@link #getSupportedMimeTypes() supportedMimeTypes} is not be empty.
|
||||||
* is not be empty.
|
* <p>When this flag is set to {@code true}, {@link #supportsMimeType(MessageHeaders)}
|
||||||
*
|
* will return {@code false} if the {@link #setContentTypeResolver contentTypeResolver}
|
||||||
* then requires the content type of a message to be resolved
|
* is not defined or if no content-type header is present.
|
||||||
*
|
|
||||||
* When set to true, #supportsMimeType(MessageHeaders) will return false if the
|
|
||||||
* contentTypeResolver is not defined or if no content-type header is present.
|
|
||||||
*/
|
*/
|
||||||
public void setStrictContentTypeMatch(boolean strictContentTypeMatch) {
|
public void setStrictContentTypeMatch(boolean strictContentTypeMatch) {
|
||||||
if (strictContentTypeMatch) {
|
if (strictContentTypeMatch) {
|
||||||
Assert.notEmpty(getSupportedMimeTypes(), "Strict match requires non-empty list of supported mime types.");
|
Assert.notEmpty(getSupportedMimeTypes(), "Strict match requires non-empty list of supported mime types");
|
||||||
Assert.notNull(getContentTypeResolver(), "Strict match requires ContentTypeResolver.");
|
Assert.notNull(getContentTypeResolver(), "Strict match requires ContentTypeResolver");
|
||||||
}
|
}
|
||||||
this.strictContentTypeMatch = strictContentTypeMatch;
|
this.strictContentTypeMatch = strictContentTypeMatch;
|
||||||
}
|
}
|
||||||
|
|
@ -166,14 +161,6 @@ public abstract class AbstractMessageConverter implements MessageConverter {
|
||||||
return (!mimeTypes.isEmpty() ? mimeTypes.get(0) : null);
|
return (!mimeTypes.isEmpty() ? mimeTypes.get(0) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Whether the given class is supported by this converter.
|
|
||||||
* @param clazz the class to test for support
|
|
||||||
* @return {@code true} if supported; {@code false} otherwise
|
|
||||||
*/
|
|
||||||
protected abstract boolean supports(Class<?> clazz);
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Object fromMessage(Message<?> message, Class<?> targetClass) {
|
public final Object fromMessage(Message<?> message, Class<?> targetClass) {
|
||||||
if (!canConvertFrom(message, targetClass)) {
|
if (!canConvertFrom(message, targetClass)) {
|
||||||
|
|
@ -186,14 +173,8 @@ public abstract class AbstractMessageConverter implements MessageConverter {
|
||||||
return (supports(targetClass) && supportsMimeType(message.getHeaders()));
|
return (supports(targetClass) && supportsMimeType(message.getHeaders()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert the message payload from serialized form to an Object.
|
|
||||||
*/
|
|
||||||
public abstract Object convertFromInternal(Message<?> message, Class<?> targetClass);
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final Message<?> toMessage(Object payload, MessageHeaders headers) {
|
public final Message<?> toMessage(Object payload, MessageHeaders headers) {
|
||||||
|
|
||||||
if (!canConvertTo(payload, headers)) {
|
if (!canConvertTo(payload, headers)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
@ -218,15 +199,10 @@ public abstract class AbstractMessageConverter implements MessageConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected boolean canConvertTo(Object payload, MessageHeaders headers) {
|
protected boolean canConvertTo(Object payload, MessageHeaders headers) {
|
||||||
Class<?> clazz = (payload != null) ? payload.getClass() : null;
|
Class<?> clazz = (payload != null ? payload.getClass() : null);
|
||||||
return (supports(clazz) && supportsMimeType(headers));
|
return (supports(clazz) && supportsMimeType(headers));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Convert the payload object to serialized form.
|
|
||||||
*/
|
|
||||||
public abstract Object convertToInternal(Object payload, MessageHeaders headers);
|
|
||||||
|
|
||||||
protected boolean supportsMimeType(MessageHeaders headers) {
|
protected boolean supportsMimeType(MessageHeaders headers) {
|
||||||
if (getSupportedMimeTypes().isEmpty()) {
|
if (getSupportedMimeTypes().isEmpty()) {
|
||||||
return true;
|
return true;
|
||||||
|
|
@ -249,7 +225,26 @@ public abstract class AbstractMessageConverter implements MessageConverter {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MimeType getMimeType(MessageHeaders headers) {
|
protected MimeType getMimeType(MessageHeaders headers) {
|
||||||
return (this.contentTypeResolver != null) ? this.contentTypeResolver.resolve(headers) : null;
|
return (this.contentTypeResolver != null ? this.contentTypeResolver.resolve(headers) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Whether the given class is supported by this converter.
|
||||||
|
* @param clazz the class to test for support
|
||||||
|
* @return {@code true} if supported; {@code false} otherwise
|
||||||
|
*/
|
||||||
|
protected abstract boolean supports(Class<?> clazz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the message payload from serialized form to an Object.
|
||||||
|
*/
|
||||||
|
public abstract Object convertFromInternal(Message<?> message, Class<?> targetClass);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert the payload object to serialized form.
|
||||||
|
*/
|
||||||
|
public abstract Object convertToInternal(Object payload, MessageHeaders headers);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2012 the original author or authors.
|
* Copyright 2002-2015 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.
|
||||||
|
|
@ -29,7 +29,6 @@ import org.springframework.http.MediaType;
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
* @since 3.2
|
* @since 3.2
|
||||||
*
|
|
||||||
* @see org.springframework.core.ParameterizedTypeReference
|
* @see org.springframework.core.ParameterizedTypeReference
|
||||||
*/
|
*/
|
||||||
public interface GenericHttpMessageConverter<T> extends HttpMessageConverter<T> {
|
public interface GenericHttpMessageConverter<T> extends HttpMessageConverter<T> {
|
||||||
|
|
@ -38,7 +37,7 @@ public interface GenericHttpMessageConverter<T> extends HttpMessageConverter<T>
|
||||||
* Indicates whether the given type can be read by this converter.
|
* Indicates whether the given type can be read by this converter.
|
||||||
* @param type the type to test for readability
|
* @param type the type to test for readability
|
||||||
* @param contextClass a context class for the target type, for example a class
|
* @param contextClass a context class for the target type, for example a class
|
||||||
* in which the target type appears in a method signature, can be {@code null}
|
* in which the target type appears in a method signature (can be {@code null})
|
||||||
* @param mediaType the media type to read, can be {@code null} if not specified.
|
* @param mediaType the media type to read, can be {@code null} if not specified.
|
||||||
* Typically the value of a {@code Content-Type} header.
|
* Typically the value of a {@code Content-Type} header.
|
||||||
* @return {@code true} if readable; {@code false} otherwise
|
* @return {@code true} if readable; {@code false} otherwise
|
||||||
|
|
@ -51,7 +50,7 @@ public interface GenericHttpMessageConverter<T> extends HttpMessageConverter<T>
|
||||||
* been passed to the {@link #canRead canRead} method of this interface,
|
* been passed to the {@link #canRead canRead} method of this interface,
|
||||||
* which must have returned {@code true}.
|
* which must have returned {@code true}.
|
||||||
* @param contextClass a context class for the target type, for example a class
|
* @param contextClass a context class for the target type, for example a class
|
||||||
* in which the target type appears in a method signature, can be {@code null}
|
* in which the target type appears in a method signature (can be {@code null})
|
||||||
* @param inputMessage the HTTP input message to read from
|
* @param inputMessage the HTTP input message to read from
|
||||||
* @return the converted object
|
* @return the converted object
|
||||||
* @throws IOException in case of I/O errors
|
* @throws IOException in case of I/O errors
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2014 the original author or authors.
|
* Copyright 2002-2015 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.
|
||||||
|
|
@ -596,7 +596,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||||
logger.debug(method.name() + " request for \"" + url + "\" resulted in " +
|
logger.debug(method.name() + " request for \"" + url + "\" resulted in " +
|
||||||
response.getRawStatusCode() + " (" + response.getStatusText() + ")");
|
response.getRawStatusCode() + " (" + response.getStatusText() + ")");
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException ex) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -608,7 +608,7 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||||
logger.warn(method.name() + " request for \"" + url + "\" resulted in " +
|
logger.warn(method.name() + " request for \"" + url + "\" resulted in " +
|
||||||
response.getRawStatusCode() + " (" + response.getStatusText() + "); invoking error handler");
|
response.getRawStatusCode() + " (" + response.getStatusText() + "); invoking error handler");
|
||||||
}
|
}
|
||||||
catch (IOException e) {
|
catch (IOException ex) {
|
||||||
// ignore
|
// ignore
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -668,12 +668,11 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void doWithRequest(ClientHttpRequest request) throws IOException {
|
public void doWithRequest(ClientHttpRequest request) throws IOException {
|
||||||
if (responseType != null) {
|
if (this.responseType != null) {
|
||||||
Class<?> responseClass = null;
|
Class<?> responseClass = null;
|
||||||
if (responseType instanceof Class) {
|
if (this.responseType instanceof Class) {
|
||||||
responseClass = (Class<?>) responseType;
|
responseClass = (Class<?>) this.responseType;
|
||||||
}
|
}
|
||||||
|
|
||||||
List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();
|
List<MediaType> allSupportedMediaTypes = new ArrayList<MediaType>();
|
||||||
for (HttpMessageConverter<?> converter : getMessageConverters()) {
|
for (HttpMessageConverter<?> converter : getMessageConverters()) {
|
||||||
if (responseClass != null) {
|
if (responseClass != null) {
|
||||||
|
|
@ -682,13 +681,11 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (converter instanceof GenericHttpMessageConverter) {
|
else if (converter instanceof GenericHttpMessageConverter) {
|
||||||
|
|
||||||
GenericHttpMessageConverter<?> genericConverter = (GenericHttpMessageConverter<?>) converter;
|
GenericHttpMessageConverter<?> genericConverter = (GenericHttpMessageConverter<?>) converter;
|
||||||
if (genericConverter.canRead(responseType, null, null)) {
|
if (genericConverter.canRead(this.responseType, null, null)) {
|
||||||
allSupportedMediaTypes.addAll(getSupportedMediaTypes(converter));
|
allSupportedMediaTypes.addAll(getSupportedMediaTypes(converter));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
if (!allSupportedMediaTypes.isEmpty()) {
|
if (!allSupportedMediaTypes.isEmpty()) {
|
||||||
MediaType.sortBySpecificity(allSupportedMediaTypes);
|
MediaType.sortBySpecificity(allSupportedMediaTypes);
|
||||||
|
|
@ -744,9 +741,9 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public void doWithRequest(ClientHttpRequest httpRequest) throws IOException {
|
public void doWithRequest(ClientHttpRequest httpRequest) throws IOException {
|
||||||
super.doWithRequest(httpRequest);
|
super.doWithRequest(httpRequest);
|
||||||
if (!requestEntity.hasBody()) {
|
if (!this.requestEntity.hasBody()) {
|
||||||
HttpHeaders httpHeaders = httpRequest.getHeaders();
|
HttpHeaders httpHeaders = httpRequest.getHeaders();
|
||||||
HttpHeaders requestHeaders = requestEntity.getHeaders();
|
HttpHeaders requestHeaders = this.requestEntity.getHeaders();
|
||||||
if (!requestHeaders.isEmpty()) {
|
if (!requestHeaders.isEmpty()) {
|
||||||
httpHeaders.putAll(requestHeaders);
|
httpHeaders.putAll(requestHeaders);
|
||||||
}
|
}
|
||||||
|
|
@ -755,9 +752,9 @@ public class RestTemplate extends InterceptingHttpAccessor implements RestOperat
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Object requestBody = requestEntity.getBody();
|
Object requestBody = this.requestEntity.getBody();
|
||||||
Class<?> requestType = requestBody.getClass();
|
Class<?> requestType = requestBody.getClass();
|
||||||
HttpHeaders requestHeaders = requestEntity.getHeaders();
|
HttpHeaders requestHeaders = this.requestEntity.getHeaders();
|
||||||
MediaType requestContentType = requestHeaders.getContentType();
|
MediaType requestContentType = requestHeaders.getContentType();
|
||||||
for (HttpMessageConverter<?> messageConverter : getMessageConverters()) {
|
for (HttpMessageConverter<?> messageConverter : getMessageConverters()) {
|
||||||
if (messageConverter.canWrite(requestType, requestContentType)) {
|
if (messageConverter.canWrite(requestType, requestContentType)) {
|
||||||
|
|
|
||||||
|
|
@ -268,9 +268,9 @@ public class UriComponentsBuilder implements Cloneable {
|
||||||
* Create a new {@code UriComponents} object from the URI associated with
|
* Create a new {@code UriComponents} object from the URI associated with
|
||||||
* the given HttpRequest while also overlaying with values from the headers
|
* the given HttpRequest while also overlaying with values from the headers
|
||||||
* "X-Forwarded-Host", "X-Forwarded-Port", and "X-Forwarded-Proto" if present.
|
* "X-Forwarded-Host", "X-Forwarded-Port", and "X-Forwarded-Proto" if present.
|
||||||
*
|
|
||||||
* @param request the source request
|
* @param request the source request
|
||||||
* @return the URI components of the UR
|
* @return the URI components of the URI
|
||||||
|
* @since 4.1.5
|
||||||
*/
|
*/
|
||||||
public static UriComponentsBuilder fromHttpRequest(HttpRequest request) {
|
public static UriComponentsBuilder fromHttpRequest(HttpRequest request) {
|
||||||
URI uri = request.getURI();
|
URI uri = request.getURI();
|
||||||
|
|
|
||||||
|
|
@ -18,8 +18,8 @@ package org.springframework.web.util;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
|
@ -33,7 +33,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||||
import javax.servlet.http.HttpServletResponse;
|
import javax.servlet.http.HttpServletResponse;
|
||||||
import javax.servlet.http.HttpSession;
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
import org.springframework.http.server.ServerHttpRequest;
|
import org.springframework.http.HttpRequest;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
|
|
@ -742,9 +742,9 @@ public abstract class WebUtils {
|
||||||
* like this {@code "q1=a;q1=b;q2=a,b,c"}. The resulting map would contain
|
* like this {@code "q1=a;q1=b;q2=a,b,c"}. The resulting map would contain
|
||||||
* keys {@code "q1"} and {@code "q2"} with values {@code ["a","b"]} and
|
* keys {@code "q1"} and {@code "q2"} with values {@code ["a","b"]} and
|
||||||
* {@code ["a","b","c"]} respectively.
|
* {@code ["a","b","c"]} respectively.
|
||||||
*
|
|
||||||
* @param matrixVariables the unparsed matrix variables string
|
* @param matrixVariables the unparsed matrix variables string
|
||||||
* @return a map with matrix variable names and values, never {@code null}
|
* @return a map with matrix variable names and values, never {@code null}
|
||||||
|
* @since 3.2
|
||||||
*/
|
*/
|
||||||
public static MultiValueMap<String, String> parseMatrixVariables(String matrixVariables) {
|
public static MultiValueMap<String, String> parseMatrixVariables(String matrixVariables) {
|
||||||
MultiValueMap<String, String> result = new LinkedMultiValueMap<String, String>();
|
MultiValueMap<String, String> result = new LinkedMultiValueMap<String, String>();
|
||||||
|
|
@ -773,12 +773,11 @@ public abstract class WebUtils {
|
||||||
* Check the given request origin against a list of allowed origins.
|
* Check the given request origin against a list of allowed origins.
|
||||||
* A list containing "*" means that all origins are allowed.
|
* A list containing "*" means that all origins are allowed.
|
||||||
* An empty list means only same origin is allowed.
|
* An empty list means only same origin is allowed.
|
||||||
*
|
|
||||||
* @return true if the request origin is valid, false otherwise
|
* @return true if the request origin is valid, false otherwise
|
||||||
* @since 4.1.5
|
* @since 4.1.5
|
||||||
* @see <a href="https://tools.ietf.org/html/rfc6454">RFC 6454: The Web Origin Concept</a>
|
* @see <a href="https://tools.ietf.org/html/rfc6454">RFC 6454: The Web Origin Concept</a>
|
||||||
*/
|
*/
|
||||||
public static boolean isValidOrigin(ServerHttpRequest request, List<String> allowedOrigins) {
|
public static boolean isValidOrigin(HttpRequest request, Collection<String> allowedOrigins) {
|
||||||
Assert.notNull(request, "Request must not be null");
|
Assert.notNull(request, "Request must not be null");
|
||||||
Assert.notNull(allowedOrigins, "Allowed origins must not be null");
|
Assert.notNull(allowedOrigins, "Allowed origins must not be null");
|
||||||
|
|
||||||
|
|
@ -791,7 +790,7 @@ public abstract class WebUtils {
|
||||||
UriComponents requestComponents = UriComponentsBuilder.fromHttpRequest(request).build();
|
UriComponents requestComponents = UriComponentsBuilder.fromHttpRequest(request).build();
|
||||||
int originPort = getPort(originComponents);
|
int originPort = getPort(originComponents);
|
||||||
int requestPort = getPort(requestComponents);
|
int requestPort = getPort(requestComponents);
|
||||||
return originComponents.getHost().equals(requestComponents.getHost()) && (originPort == requestPort);
|
return (originComponents.getHost().equals(requestComponents.getHost()) && originPort == requestPort);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return allowedOrigins.contains(origin);
|
return allowedOrigins.contains(origin);
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ public abstract class AbstractMessageConverterMethodArgumentResolver implements
|
||||||
* from the given HttpInputMessage.
|
* from the given HttpInputMessage.
|
||||||
* @param <T> the expected type of the argument value to be created
|
* @param <T> the expected type of the argument value to be created
|
||||||
* @param inputMessage the HTTP input message representing the current request
|
* @param inputMessage the HTTP input message representing the current request
|
||||||
* @param methodParam the method argument
|
* @param methodParam the method parameter descriptor
|
||||||
* @param targetType the type of object to create, not necessarily the same as
|
* @param targetType the type of object to create, not necessarily the same as
|
||||||
* the method parameter type (e.g. for {@code HttpEntity<String>} method
|
* the method parameter type (e.g. for {@code HttpEntity<String>} method
|
||||||
* parameter the target type is String)
|
* parameter the target type is String)
|
||||||
|
|
@ -113,8 +113,8 @@ public abstract class AbstractMessageConverterMethodArgumentResolver implements
|
||||||
* @throws HttpMediaTypeNotSupportedException if no suitable message converter is found
|
* @throws HttpMediaTypeNotSupportedException if no suitable message converter is found
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage,
|
protected <T> Object readWithMessageConverters(HttpInputMessage inputMessage, MethodParameter methodParam,
|
||||||
MethodParameter methodParam, Type targetType) throws IOException, HttpMediaTypeNotSupportedException {
|
Type targetType) throws IOException, HttpMediaTypeNotSupportedException {
|
||||||
|
|
||||||
MediaType contentType;
|
MediaType contentType;
|
||||||
try {
|
try {
|
||||||
|
|
@ -128,6 +128,8 @@ public abstract class AbstractMessageConverterMethodArgumentResolver implements
|
||||||
}
|
}
|
||||||
|
|
||||||
Class<?> contextClass = methodParam.getContainingClass();
|
Class<?> contextClass = methodParam.getContainingClass();
|
||||||
|
Class<T> targetClass = (Class<T>)
|
||||||
|
ResolvableType.forMethodParameter(methodParam, targetType).resolve(Object.class);
|
||||||
|
|
||||||
for (HttpMessageConverter<?> converter : this.messageConverters) {
|
for (HttpMessageConverter<?> converter : this.messageConverters) {
|
||||||
if (converter instanceof GenericHttpMessageConverter) {
|
if (converter instanceof GenericHttpMessageConverter) {
|
||||||
|
|
@ -140,8 +142,6 @@ public abstract class AbstractMessageConverterMethodArgumentResolver implements
|
||||||
return genericConverter.read(targetType, contextClass, inputMessage);
|
return genericConverter.read(targetType, contextClass, inputMessage);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Class<T> targetClass = (Class<T>)
|
|
||||||
ResolvableType.forMethodParameter(methodParam, targetType).resolve(Object.class);
|
|
||||||
if (converter.canRead(targetClass, contentType)) {
|
if (converter.canRead(targetClass, contentType)) {
|
||||||
if (logger.isDebugEnabled()) {
|
if (logger.isDebugEnabled()) {
|
||||||
logger.debug("Reading [" + targetClass.getName() + "] as \"" +
|
logger.debug("Reading [" + targetClass.getName() + "] as \"" +
|
||||||
|
|
|
||||||
|
|
@ -80,12 +80,13 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM
|
||||||
super(messageConverters);
|
super(messageConverters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Supports the following:
|
* Supports the following:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>Annotated with {@code @RequestPart}
|
* <li>Annotated with {@code @RequestPart}
|
||||||
* <li>Of type {@link MultipartFile} unless annotated with {@code @RequestParam}.
|
* <li>Of type {@link MultipartFile} unless annotated with {@code @RequestParam}.
|
||||||
* <li>Of type {@code javax.servlet.http.Part} unless annotated with {@code @RequestParam}.
|
* <li>Of type {@code javax.servlet.http.Part} unless annotated with {@code @RequestParam}.
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -117,7 +118,7 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM
|
||||||
assertIsMultipartRequest(servletRequest);
|
assertIsMultipartRequest(servletRequest);
|
||||||
|
|
||||||
MultipartHttpServletRequest multipartRequest =
|
MultipartHttpServletRequest multipartRequest =
|
||||||
WebUtils.getNativeRequest(servletRequest, MultipartHttpServletRequest.class);
|
WebUtils.getNativeRequest(servletRequest, MultipartHttpServletRequest.class);
|
||||||
|
|
||||||
String partName = getPartName(parameter);
|
String partName = getPartName(parameter);
|
||||||
Object arg;
|
Object arg;
|
||||||
|
|
@ -180,41 +181,44 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getPartName(MethodParameter parameter) {
|
private String getPartName(MethodParameter param) {
|
||||||
RequestPart annot = parameter.getParameterAnnotation(RequestPart.class);
|
RequestPart annot = param.getParameterAnnotation(RequestPart.class);
|
||||||
String partName = (annot != null ? annot.value() : "");
|
String partName = (annot != null ? annot.value() : "");
|
||||||
if (partName.length() == 0) {
|
if (partName.length() == 0) {
|
||||||
partName = parameter.getParameterName();
|
partName = param.getParameterName();
|
||||||
Assert.notNull(partName, "Request part name for argument type [" + parameter.getParameterType().getName() +
|
if (partName == null) {
|
||||||
"] not specified, and parameter name information not found in class file either.");
|
throw new IllegalArgumentException("Request part name for argument type [" +
|
||||||
|
param.getNestedParameterType().getName() +
|
||||||
|
"] not specified, and parameter name information not found in class file either.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return partName;
|
return partName;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isMultipartFileCollection(MethodParameter parameter) {
|
private boolean isMultipartFileCollection(MethodParameter param) {
|
||||||
Class<?> collectionType = getCollectionParameterType(parameter);
|
Class<?> collectionType = getCollectionParameterType(param);
|
||||||
return (collectionType != null && collectionType.equals(MultipartFile.class));
|
return (collectionType != null && collectionType.equals(MultipartFile.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isMultipartFileArray(MethodParameter parameter) {
|
private boolean isMultipartFileArray(MethodParameter param) {
|
||||||
Class<?> paramType = parameter.getParameterType().getComponentType();
|
Class<?> paramType = param.getNestedParameterType().getComponentType();
|
||||||
return (paramType != null && MultipartFile.class.equals(paramType));
|
return (paramType != null && MultipartFile.class.equals(paramType));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPartCollection(MethodParameter parameter) {
|
private boolean isPartCollection(MethodParameter param) {
|
||||||
Class<?> collectionType = getCollectionParameterType(parameter);
|
Class<?> collectionType = getCollectionParameterType(param);
|
||||||
return (collectionType != null && "javax.servlet.http.Part".equals(collectionType.getName()));
|
return (collectionType != null && "javax.servlet.http.Part".equals(collectionType.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isPartArray(MethodParameter parameter) {
|
private boolean isPartArray(MethodParameter param) {
|
||||||
Class<?> paramType = parameter.getParameterType().getComponentType();
|
Class<?> paramType = param.getNestedParameterType().getComponentType();
|
||||||
return (paramType != null && "javax.servlet.http.Part".equals(paramType.getName()));
|
return (paramType != null && "javax.servlet.http.Part".equals(paramType.getName()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private Class<?> getCollectionParameterType(MethodParameter parameter) {
|
private Class<?> getCollectionParameterType(MethodParameter param) {
|
||||||
Class<?> paramType = parameter.getParameterType();
|
Class<?> paramType = param.getNestedParameterType();
|
||||||
if (Collection.class.equals(paramType) || List.class.isAssignableFrom(paramType)){
|
if (Collection.class.equals(paramType) || List.class.isAssignableFrom(paramType)){
|
||||||
Class<?> valueType = GenericCollectionTypeResolver.getCollectionParameterType(parameter);
|
Class<?> valueType = GenericCollectionTypeResolver.getCollectionParameterType(param);
|
||||||
if (valueType != null) {
|
if (valueType != null) {
|
||||||
return valueType;
|
return valueType;
|
||||||
}
|
}
|
||||||
|
|
@ -228,13 +232,13 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM
|
||||||
* Spring's {@link org.springframework.validation.annotation.Validated},
|
* Spring's {@link org.springframework.validation.annotation.Validated},
|
||||||
* and custom annotations whose name starts with "Valid".
|
* and custom annotations whose name starts with "Valid".
|
||||||
* @param binder the DataBinder to be used
|
* @param binder the DataBinder to be used
|
||||||
* @param parameter the method parameter
|
* @param param the method parameter
|
||||||
* @throws MethodArgumentNotValidException in case of a binding error which
|
* @throws MethodArgumentNotValidException in case of a binding error which
|
||||||
* is meant to be fatal (i.e. without a declared {@link Errors} parameter)
|
* is meant to be fatal (i.e. without a declared {@link Errors} parameter)
|
||||||
* @see #isBindingErrorFatal
|
* @see #isBindingErrorFatal
|
||||||
*/
|
*/
|
||||||
protected void validate(WebDataBinder binder, MethodParameter parameter) throws MethodArgumentNotValidException {
|
protected void validate(WebDataBinder binder, MethodParameter param) throws MethodArgumentNotValidException {
|
||||||
Annotation[] annotations = parameter.getParameterAnnotations();
|
Annotation[] annotations = param.getParameterAnnotations();
|
||||||
for (Annotation ann : annotations) {
|
for (Annotation ann : annotations) {
|
||||||
Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class);
|
Validated validatedAnn = AnnotationUtils.getAnnotation(ann, Validated.class);
|
||||||
if (validatedAnn != null || ann.annotationType().getSimpleName().startsWith("Valid")) {
|
if (validatedAnn != null || ann.annotationType().getSimpleName().startsWith("Valid")) {
|
||||||
|
|
@ -243,8 +247,8 @@ public class RequestPartMethodArgumentResolver extends AbstractMessageConverterM
|
||||||
binder.validate(validationHints);
|
binder.validate(validationHints);
|
||||||
BindingResult bindingResult = binder.getBindingResult();
|
BindingResult bindingResult = binder.getBindingResult();
|
||||||
if (bindingResult.hasErrors()) {
|
if (bindingResult.hasErrors()) {
|
||||||
if (isBindingErrorFatal(parameter)) {
|
if (isBindingErrorFatal(param)) {
|
||||||
throw new MethodArgumentNotValidException(parameter, bindingResult);
|
throw new MethodArgumentNotValidException(param, bindingResult);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2014 the original author or authors.
|
* Copyright 2002-2015 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.
|
||||||
|
|
@ -93,7 +93,7 @@ public class RequestResponseBodyMethodProcessor extends AbstractMessageConverter
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @throws MethodArgumentNotValidException if validation fails
|
* Throws MethodArgumentNotValidException if validation fails.
|
||||||
* @throws HttpMessageNotReadableException if {@link RequestBody#required()}
|
* @throws HttpMessageNotReadableException if {@link RequestBody#required()}
|
||||||
* is {@code true} and there is no body content or if there is no suitable
|
* is {@code true} and there is no body content or if there is no suitable
|
||||||
* converter to read the content with.
|
* converter to read the content with.
|
||||||
|
|
@ -143,8 +143,8 @@ public class RequestResponseBodyMethodProcessor extends AbstractMessageConverter
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected <T> Object readWithMessageConverters(NativeWebRequest webRequest,
|
protected <T> Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter methodParam,
|
||||||
MethodParameter methodParam, Type paramType) throws IOException, HttpMediaTypeNotSupportedException {
|
Type paramType) throws IOException, HttpMediaTypeNotSupportedException {
|
||||||
|
|
||||||
final HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
|
final HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class);
|
||||||
HttpInputMessage inputMessage = new ServletServerHttpRequest(servletRequest);
|
HttpInputMessage inputMessage = new ServletServerHttpRequest(servletRequest);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue