polishing
git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@3392 50f2f4bb-b051-0410-bef5-90022cba6387
This commit is contained in:
parent
5e35ea0a5a
commit
92a49cba89
|
|
@ -65,6 +65,7 @@ public class TypeDescriptor {
|
||||||
typeDescriptorCache.put(String.class, new TypeDescriptor(String.class));
|
typeDescriptorCache.put(String.class, new TypeDescriptor(String.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private Class<?> type;
|
private Class<?> type;
|
||||||
|
|
||||||
private MethodParameter methodParameter;
|
private MethodParameter methodParameter;
|
||||||
|
|
@ -81,6 +82,7 @@ public class TypeDescriptor {
|
||||||
|
|
||||||
private Annotation[] annotations;
|
private Annotation[] annotations;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new type descriptor from a method or constructor parameter.
|
* Create a new type descriptor from a method or constructor parameter.
|
||||||
* <p>Use this constructor when a target conversion point originates from a method parameter,
|
* <p>Use this constructor when a target conversion point originates from a method parameter,
|
||||||
|
|
@ -127,38 +129,36 @@ public class TypeDescriptor {
|
||||||
this.type = type;
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
// static factory methods
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new type descriptor for the class of the given object.
|
* Internal constructor for a NULL descriptor.
|
||||||
* @param object the object
|
|
||||||
* @return the type descriptor
|
|
||||||
*/
|
*/
|
||||||
public static TypeDescriptor forObject(Object object) {
|
private TypeDescriptor() {
|
||||||
if (object == null) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
else if (object instanceof Collection<?> || object instanceof Map<?, ?>) {
|
|
||||||
return new TypeDescriptor(object);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return valueOf(object.getClass());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new type descriptor for the given class.
|
* Create a new descriptor for the type of the given value.
|
||||||
* @param type the class
|
* <p>Use this constructor when a conversion point comes from a source such as a Map or
|
||||||
* @return the type descriptor
|
* Collection, where no additional context is available but elements can be introspected.
|
||||||
|
* @param type the actual type to wrap
|
||||||
*/
|
*/
|
||||||
public static TypeDescriptor valueOf(Class<?> type) {
|
private TypeDescriptor(Object value) {
|
||||||
if (type == null) {
|
Assert.notNull(value, "Value must not be null");
|
||||||
return TypeDescriptor.NULL;
|
this.value = value;
|
||||||
|
this.type = value.getClass();
|
||||||
}
|
}
|
||||||
TypeDescriptor desc = typeDescriptorCache.get(type);
|
|
||||||
return (desc != null ? desc : new TypeDescriptor(type));
|
/**
|
||||||
|
* Create a new descriptor for the given type.
|
||||||
|
* <p>Use this constructor when a conversion point comes from a plain source type,
|
||||||
|
* where no additional context is available.
|
||||||
|
* @param type the actual type to wrap
|
||||||
|
*/
|
||||||
|
private TypeDescriptor(Class<?> type) {
|
||||||
|
Assert.notNull(type, "Type must not be null");
|
||||||
|
this.type = type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the wrapped MethodParameter, if any.
|
* Return the wrapped MethodParameter, if any.
|
||||||
* <p>Note: Either MethodParameter or Field is available.
|
* <p>Note: Either MethodParameter or Field is available.
|
||||||
|
|
@ -255,13 +255,14 @@ public class TypeDescriptor {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the element type as a type descriptor; if the element type is null (cannot be determined), the type descriptor is derived from the element argument.
|
* Return the element type as a type descriptor; if the element type is null (cannot be determined),
|
||||||
|
* the type descriptor is derived from the element argument.
|
||||||
* @param element the element
|
* @param element the element
|
||||||
* @return the element type descriptor
|
* @return the element type descriptor
|
||||||
*/
|
*/
|
||||||
public TypeDescriptor getElementTypeDescriptor(Object element) {
|
public TypeDescriptor getElementTypeDescriptor(Object element) {
|
||||||
TypeDescriptor elementType = getElementTypeDescriptor();
|
TypeDescriptor elementType = getElementTypeDescriptor();
|
||||||
return elementType != TypeDescriptor.NULL ? elementType : TypeDescriptor.forObject(element);
|
return (elementType != TypeDescriptor.NULL ? elementType : forObject(element));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -318,20 +319,21 @@ public class TypeDescriptor {
|
||||||
* Returns map value type as a type descriptor.
|
* Returns map value type as a type descriptor.
|
||||||
*/
|
*/
|
||||||
public synchronized TypeDescriptor getMapValueTypeDescriptor() {
|
public synchronized TypeDescriptor getMapValueTypeDescriptor() {
|
||||||
if (mapValueType == null) {
|
if (this.mapValueType == null) {
|
||||||
mapValueType = forElementType(resolveMapValueType());
|
mapValueType = forElementType(resolveMapValueType());
|
||||||
}
|
}
|
||||||
return mapValueType;
|
return this.mapValueType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the map value type as a type descriptor; if the value type is null (cannot be determined), the type descriptor is derived from the value argument.
|
* Return the map value type as a type descriptor; if the value type is null
|
||||||
|
* (cannot be determined), the type descriptor is derived from the value argument.
|
||||||
* @param value the value
|
* @param value the value
|
||||||
* @return the map value type descriptor
|
* @return the map value type descriptor
|
||||||
*/
|
*/
|
||||||
public TypeDescriptor getMapValueTypeDescriptor(Object value) {
|
public TypeDescriptor getMapValueTypeDescriptor(Object value) {
|
||||||
TypeDescriptor valueType = getMapValueTypeDescriptor();
|
TypeDescriptor valueType = getMapValueTypeDescriptor();
|
||||||
return valueType != TypeDescriptor.NULL ? valueType : TypeDescriptor.forObject(value);
|
return (valueType != TypeDescriptor.NULL ? valueType : TypeDescriptor.forObject(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -366,10 +368,15 @@ public class TypeDescriptor {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
if (isCollection() && targetType.isCollection() || isArray() && targetType.isArray()) {
|
if (isCollection() && targetType.isCollection() || isArray() && targetType.isArray()) {
|
||||||
return targetType.getType().isAssignableFrom(getType()) && getElementTypeDescriptor().isAssignableTo(targetType.getElementTypeDescriptor());
|
return targetType.getType().isAssignableFrom(getType()) &&
|
||||||
} else if (isMap() && targetType.isMap()) {
|
getElementTypeDescriptor().isAssignableTo(targetType.getElementTypeDescriptor());
|
||||||
return targetType.getType().isAssignableFrom(getType()) && getMapKeyTypeDescriptor().isAssignableTo(targetType.getMapKeyTypeDescriptor()) && getMapValueTypeDescriptor().isAssignableTo(targetType.getMapValueTypeDescriptor());
|
}
|
||||||
} else {
|
else if (isMap() && targetType.isMap()) {
|
||||||
|
return targetType.getType().isAssignableFrom(getType()) &&
|
||||||
|
getMapKeyTypeDescriptor().isAssignableTo(targetType.getMapKeyTypeDescriptor()) &&
|
||||||
|
getMapValueTypeDescriptor().isAssignableTo(targetType.getMapValueTypeDescriptor());
|
||||||
|
}
|
||||||
|
else {
|
||||||
return targetType.getObjectType().isAssignableFrom(getObjectType());
|
return targetType.getObjectType().isAssignableFrom(getObjectType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -383,14 +390,17 @@ public class TypeDescriptor {
|
||||||
public TypeDescriptor forElementType(Class<?> elementType) {
|
public TypeDescriptor forElementType(Class<?> elementType) {
|
||||||
if (getType().equals(elementType)) {
|
if (getType().equals(elementType)) {
|
||||||
return this;
|
return this;
|
||||||
} else if (elementType == null) {
|
}
|
||||||
|
else if (elementType == null) {
|
||||||
return TypeDescriptor.NULL;
|
return TypeDescriptor.NULL;
|
||||||
} else if (this.methodParameter != null) {
|
}
|
||||||
|
else if (this.methodParameter != null) {
|
||||||
return new TypeDescriptor(this.methodParameter, elementType);
|
return new TypeDescriptor(this.methodParameter, elementType);
|
||||||
}
|
}
|
||||||
else if (this.field != null) {
|
else if (this.field != null) {
|
||||||
return new TypeDescriptor(this.field, elementType);
|
return new TypeDescriptor(this.field, elementType);
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
return TypeDescriptor.valueOf(elementType);
|
return TypeDescriptor.valueOf(elementType);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -403,12 +413,16 @@ public class TypeDescriptor {
|
||||||
if (this == td) {
|
if (this == td) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
boolean annotatedTypeEquals = getType().equals(td.getType()) && ObjectUtils.nullSafeEquals(getAnnotations(), td.getAnnotations());
|
boolean annotatedTypeEquals =
|
||||||
|
getType().equals(td.getType()) && ObjectUtils.nullSafeEquals(getAnnotations(), td.getAnnotations());
|
||||||
if (isCollection()) {
|
if (isCollection()) {
|
||||||
return annotatedTypeEquals && ObjectUtils.nullSafeEquals(getElementType(), td.getElementType());
|
return annotatedTypeEquals && ObjectUtils.nullSafeEquals(getElementType(), td.getElementType());
|
||||||
} else if (isMap()) {
|
}
|
||||||
return annotatedTypeEquals && ObjectUtils.nullSafeEquals(getMapKeyType(), td.getMapKeyType()) && ObjectUtils.nullSafeEquals(getMapValueType(), td.getMapValueType());
|
else if (isMap()) {
|
||||||
} else {
|
return annotatedTypeEquals && ObjectUtils.nullSafeEquals(getMapKeyType(), td.getMapKeyType()) &&
|
||||||
|
ObjectUtils.nullSafeEquals(getMapValueType(), td.getMapValueType());
|
||||||
|
}
|
||||||
|
else {
|
||||||
return annotatedTypeEquals;
|
return annotatedTypeEquals;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -439,8 +453,11 @@ public class TypeDescriptor {
|
||||||
if (isMap()) {
|
if (isMap()) {
|
||||||
Class<?> mapKeyType = getMapKeyType();
|
Class<?> mapKeyType = getMapKeyType();
|
||||||
Class<?> valueKeyType = getMapValueType();
|
Class<?> valueKeyType = getMapValueType();
|
||||||
builder.append("<").append(mapKeyType != null ? ClassUtils.getQualifiedName(mapKeyType) : "?").append(", ").append(valueKeyType != null ? ClassUtils.getQualifiedName(valueKeyType) : "?").append(">");
|
builder.append("<").append(mapKeyType != null ? ClassUtils.getQualifiedName(mapKeyType) : "?");
|
||||||
} else if (isCollection()) {
|
builder.append(", ").append(valueKeyType != null ? ClassUtils.getQualifiedName(valueKeyType) : "?");
|
||||||
|
builder.append(">");
|
||||||
|
}
|
||||||
|
else if (isCollection()) {
|
||||||
Class<?> elementType = getElementType();
|
Class<?> elementType = getElementType();
|
||||||
builder.append("<").append(elementType != null ? ClassUtils.getQualifiedName(elementType) : "?").append(">");
|
builder.append("<").append(elementType != null ? ClassUtils.getQualifiedName(elementType) : "?").append(">");
|
||||||
}
|
}
|
||||||
|
|
@ -481,7 +498,7 @@ public class TypeDescriptor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return type != null ? GenericCollectionTypeResolver.getCollectionType((Class<? extends Collection>) this.type) : null;
|
return (this.type != null ? GenericCollectionTypeResolver.getCollectionType((Class<? extends Collection>) this.type) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
|
@ -501,7 +518,7 @@ public class TypeDescriptor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return type != null && isMap() ? GenericCollectionTypeResolver.getMapKeyType((Class<? extends Map>) this.type) : null;
|
return (this.type != null && isMap() ? GenericCollectionTypeResolver.getMapKeyType((Class<? extends Map>) this.type) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
|
@ -521,7 +538,7 @@ public class TypeDescriptor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return isMap() && type != null ? GenericCollectionTypeResolver.getMapValueType((Class<? extends Map>) this.type) : null;
|
return (isMap() && this.type != null ? GenericCollectionTypeResolver.getMapValueType((Class<? extends Map>) this.type) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Annotation[] resolveAnnotations() {
|
private Annotation[] resolveAnnotations() {
|
||||||
|
|
@ -541,33 +558,37 @@ public class TypeDescriptor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// static factory methods
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Internal constructor for a NULL descriptor.
|
* Create a new type descriptor for the class of the given object.
|
||||||
|
* @param object the object
|
||||||
|
* @return the type descriptor
|
||||||
*/
|
*/
|
||||||
private TypeDescriptor() {
|
public static TypeDescriptor forObject(Object object) {
|
||||||
|
if (object == null) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
else if (object instanceof Collection<?> || object instanceof Map<?, ?>) {
|
||||||
|
return new TypeDescriptor(object);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return valueOf(object.getClass());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new descriptor for the type of the given value.
|
* Create a new type descriptor for the given class.
|
||||||
* <p>Use this constructor when a conversion point comes from a source such as a Map or
|
* @param type the class
|
||||||
* Collection, where no additional context is available but elements can be introspected.
|
* @return the type descriptor
|
||||||
* @param type the actual type to wrap
|
|
||||||
*/
|
*/
|
||||||
private TypeDescriptor(Object value) {
|
public static TypeDescriptor valueOf(Class<?> type) {
|
||||||
Assert.notNull(value, "Value must not be null");
|
if (type == null) {
|
||||||
this.value = value;
|
return TypeDescriptor.NULL;
|
||||||
this.type = value.getClass();
|
|
||||||
}
|
}
|
||||||
|
TypeDescriptor desc = typeDescriptorCache.get(type);
|
||||||
/**
|
return (desc != null ? desc : new TypeDescriptor(type));
|
||||||
* Create a new descriptor for the given type.
|
|
||||||
* <p>Use this constructor when a conversion point comes from a plain source type,
|
|
||||||
* where no additional context is available.
|
|
||||||
* @param type the actual type to wrap
|
|
||||||
*/
|
|
||||||
private TypeDescriptor(Class<?> type) {
|
|
||||||
Assert.notNull(type, "Type must not be null");
|
|
||||||
this.type = type;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -71,8 +71,10 @@ public class PropertyPlaceholderHelper {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new <code>PropertyPlaceholderHelper</code> that uses the supplied prefix and suffix.
|
* Creates a new <code>PropertyPlaceholderHelper</code> that uses the supplied prefix and suffix.
|
||||||
* @param placeholderPrefix the prefix that denotes the start of a placeholder.
|
* @param placeholderPrefix the prefix that denotes the start of a placeholder
|
||||||
* @param placeholderSuffix the suffix that denotes the end of a placeholder.
|
* @param placeholderSuffix the suffix that denotes the end of a placeholder
|
||||||
|
* @param valueSeparator the separating character between the placeholder variable
|
||||||
|
* and the associated default value, if any
|
||||||
* @param ignoreUnresolvablePlaceholders indicates whether unresolvable placeholders should be ignored
|
* @param ignoreUnresolvablePlaceholders indicates whether unresolvable placeholders should be ignored
|
||||||
* (<code>true</code>) or cause an exception (<code>false</code>).
|
* (<code>true</code>) or cause an exception (<code>false</code>).
|
||||||
*/
|
*/
|
||||||
|
|
@ -158,11 +160,9 @@ public class PropertyPlaceholderHelper {
|
||||||
// previously resolved placeholder value.
|
// previously resolved placeholder value.
|
||||||
propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
|
propVal = parseStringValue(propVal, placeholderResolver, visitedPlaceholders);
|
||||||
buf.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
|
buf.replace(startIndex, endIndex + this.placeholderSuffix.length(), propVal);
|
||||||
|
|
||||||
if (logger.isTraceEnabled()) {
|
if (logger.isTraceEnabled()) {
|
||||||
logger.trace("Resolved placeholder '" + placeholder + "'");
|
logger.trace("Resolved placeholder '" + placeholder + "'");
|
||||||
}
|
}
|
||||||
|
|
||||||
startIndex = buf.indexOf(this.placeholderPrefix, startIndex + propVal.length());
|
startIndex = buf.indexOf(this.placeholderPrefix, startIndex + propVal.length());
|
||||||
}
|
}
|
||||||
else if (this.ignoreUnresolvablePlaceholders) {
|
else if (this.ignoreUnresolvablePlaceholders) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2009 the original author or authors.
|
* Copyright 2002-2010 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.
|
||||||
|
|
@ -550,7 +550,7 @@ public abstract class StringUtils {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Apply the given relative path to the given path,
|
* Apply the given relative path to the given path,
|
||||||
* assuming standard Java folder separation (i.e. "/" separators);
|
* assuming standard Java folder separation (i.e. "/" separators).
|
||||||
* @param path the path to start from (usually a full file path)
|
* @param path the path to start from (usually a full file path)
|
||||||
* @param relativePath the relative path to apply
|
* @param relativePath the relative path to apply
|
||||||
* (relative to the full file path above)
|
* (relative to the full file path above)
|
||||||
|
|
|
||||||
|
|
@ -53,13 +53,14 @@ final class CommonsClientHttpRequest extends AbstractClientHttpRequest {
|
||||||
this.httpMethod = httpMethod;
|
this.httpMethod = httpMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public HttpMethod getMethod() {
|
public HttpMethod getMethod() {
|
||||||
return HttpMethod.valueOf(httpMethod.getName());
|
return HttpMethod.valueOf(this.httpMethod.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
public URI getURI() {
|
public URI getURI() {
|
||||||
try {
|
try {
|
||||||
return URI.create(httpMethod.getURI().getEscapedURI());
|
return URI.create(this.httpMethod.getURI().getEscapedURI());
|
||||||
}
|
}
|
||||||
catch (URIException ex) {
|
catch (URIException ex) {
|
||||||
throw new IllegalStateException("Could not get HttpMethod URI: " + ex.getMessage(), ex);
|
throw new IllegalStateException("Could not get HttpMethod URI: " + ex.getMessage(), ex);
|
||||||
|
|
@ -74,13 +75,13 @@ final class CommonsClientHttpRequest extends AbstractClientHttpRequest {
|
||||||
httpMethod.addRequestHeader(headerName, headerValue);
|
httpMethod.addRequestHeader(headerName, headerValue);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (httpMethod instanceof EntityEnclosingMethod) {
|
if (this.httpMethod instanceof EntityEnclosingMethod) {
|
||||||
EntityEnclosingMethod entityEnclosingMethod = (EntityEnclosingMethod) httpMethod;
|
EntityEnclosingMethod entityEnclosingMethod = (EntityEnclosingMethod) this.httpMethod;
|
||||||
RequestEntity requestEntity = new ByteArrayRequestEntity(output);
|
RequestEntity requestEntity = new ByteArrayRequestEntity(output);
|
||||||
entityEnclosingMethod.setRequestEntity(requestEntity);
|
entityEnclosingMethod.setRequestEntity(requestEntity);
|
||||||
}
|
}
|
||||||
httpClient.executeMethod(httpMethod);
|
this.httpClient.executeMethod(this.httpMethod);
|
||||||
return new CommonsClientHttpResponse(httpMethod);
|
return new CommonsClientHttpResponse(this.httpMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2009 the original author or authors.
|
* Copyright 2002-2010 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.
|
||||||
|
|
@ -24,7 +24,6 @@ import org.apache.commons.httpclient.HttpMethod;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
import org.springframework.http.HttpStatus;
|
import org.springframework.http.HttpStatus;
|
||||||
import org.springframework.http.client.ClientHttpResponse;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@link org.springframework.http.client.ClientHttpResponse} implementation that uses
|
* {@link org.springframework.http.client.ClientHttpResponse} implementation that uses
|
||||||
|
|
@ -42,34 +41,36 @@ final class CommonsClientHttpResponse implements ClientHttpResponse {
|
||||||
|
|
||||||
private HttpHeaders headers;
|
private HttpHeaders headers;
|
||||||
|
|
||||||
|
|
||||||
CommonsClientHttpResponse(HttpMethod httpMethod) {
|
CommonsClientHttpResponse(HttpMethod httpMethod) {
|
||||||
this.httpMethod = httpMethod;
|
this.httpMethod = httpMethod;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public HttpStatus getStatusCode() {
|
public HttpStatus getStatusCode() {
|
||||||
return HttpStatus.valueOf(httpMethod.getStatusCode());
|
return HttpStatus.valueOf(this.httpMethod.getStatusCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
public String getStatusText() {
|
public String getStatusText() {
|
||||||
return httpMethod.getStatusText();
|
return this.httpMethod.getStatusText();
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpHeaders getHeaders() {
|
public HttpHeaders getHeaders() {
|
||||||
if (headers == null) {
|
if (this.headers == null) {
|
||||||
headers = new HttpHeaders();
|
this.headers = new HttpHeaders();
|
||||||
for (Header header : httpMethod.getResponseHeaders()) {
|
for (Header header : this.httpMethod.getResponseHeaders()) {
|
||||||
headers.add(header.getName(), header.getValue());
|
this.headers.add(header.getName(), header.getValue());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return headers;
|
return this.headers;
|
||||||
}
|
}
|
||||||
|
|
||||||
public InputStream getBody() throws IOException {
|
public InputStream getBody() throws IOException {
|
||||||
return httpMethod.getResponseBodyAsStream();
|
return this.httpMethod.getResponseBodyAsStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void close() {
|
public void close() {
|
||||||
httpMethod.releaseConnection();
|
this.httpMethod.releaseConnection();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -97,6 +97,7 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
|
||||||
|
|
||||||
private List<HttpMessageConverter<?>> partConverters = new ArrayList<HttpMessageConverter<?>>();
|
private List<HttpMessageConverter<?>> partConverters = new ArrayList<HttpMessageConverter<?>>();
|
||||||
|
|
||||||
|
|
||||||
public FormHttpMessageConverter() {
|
public FormHttpMessageConverter() {
|
||||||
this.partConverters.add(new ByteArrayHttpMessageConverter());
|
this.partConverters.add(new ByteArrayHttpMessageConverter());
|
||||||
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
|
StringHttpMessageConverter stringHttpMessageConverter = new StringHttpMessageConverter();
|
||||||
|
|
@ -106,6 +107,7 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
|
||||||
this.partConverters.add(new SourceHttpMessageConverter());
|
this.partConverters.add(new SourceHttpMessageConverter());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the message body converters to use. These converters are used to convert objects to MIME parts.
|
* Set the message body converters to use. These converters are used to convert objects to MIME parts.
|
||||||
*/
|
*/
|
||||||
|
|
@ -121,6 +123,7 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
|
||||||
this.charset = charset;
|
this.charset = charset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean canRead(Class<?> clazz, MediaType mediaType) {
|
public boolean canRead(Class<?> clazz, MediaType mediaType) {
|
||||||
if (!MultiValueMap.class.isAssignableFrom(clazz)) {
|
if (!MultiValueMap.class.isAssignableFrom(clazz)) {
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -151,8 +154,8 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
|
||||||
}
|
}
|
||||||
|
|
||||||
public MultiValueMap<String, String> read(Class<? extends MultiValueMap<String, ?>> clazz,
|
public MultiValueMap<String, String> read(Class<? extends MultiValueMap<String, ?>> clazz,
|
||||||
HttpInputMessage inputMessage)
|
HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException {
|
||||||
throws IOException, HttpMessageNotReadableException {
|
|
||||||
MediaType contentType = inputMessage.getHeaders().getContentType();
|
MediaType contentType = inputMessage.getHeaders().getContentType();
|
||||||
Charset charset = contentType.getCharSet() != null ? contentType.getCharSet() : this.charset;
|
Charset charset = contentType.getCharSet() != null ? contentType.getCharSet() : this.charset;
|
||||||
String body = FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset));
|
String body = FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset));
|
||||||
|
|
@ -201,9 +204,7 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeForm(MultiValueMap<String, String> form, HttpOutputMessage outputMessage) throws IOException {
|
private void writeForm(MultiValueMap<String, String> form, HttpOutputMessage outputMessage) throws IOException {
|
||||||
|
|
||||||
outputMessage.getHeaders().setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
outputMessage.getHeaders().setContentType(MediaType.APPLICATION_FORM_URLENCODED);
|
||||||
|
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
for (Iterator<String> nameIterator = form.keySet().iterator(); nameIterator.hasNext();) {
|
for (Iterator<String> nameIterator = form.keySet().iterator(); nameIterator.hasNext();) {
|
||||||
String name = nameIterator.next();
|
String name = nameIterator.next();
|
||||||
|
|
@ -225,8 +226,7 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
|
||||||
FileCopyUtils.copy(builder.toString(), new OutputStreamWriter(outputMessage.getBody(), charset));
|
FileCopyUtils.copy(builder.toString(), new OutputStreamWriter(outputMessage.getBody(), charset));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeMultipart(MultiValueMap<String, Object> parts, HttpOutputMessage outputMessage)
|
private void writeMultipart(MultiValueMap<String, Object> parts, HttpOutputMessage outputMessage) throws IOException {
|
||||||
throws IOException {
|
|
||||||
byte[] boundary = generateMultipartBoundary();
|
byte[] boundary = generateMultipartBoundary();
|
||||||
|
|
||||||
Map<String, String> parameters = Collections.singletonMap("boundary", new String(boundary, "US-ASCII"));
|
Map<String, String> parameters = Collections.singletonMap("boundary", new String(boundary, "US-ASCII"));
|
||||||
|
|
@ -304,7 +304,6 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generate a multipart boundary.
|
* Generate a multipart boundary.
|
||||||
*
|
|
||||||
* <p>Default implementation returns a random boundary. Can be overridden in subclasses.
|
* <p>Default implementation returns a random boundary. Can be overridden in subclasses.
|
||||||
*/
|
*/
|
||||||
protected byte[] generateMultipartBoundary() {
|
protected byte[] generateMultipartBoundary() {
|
||||||
|
|
@ -316,11 +315,9 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the filename of the given multipart part. This value will be used for the {@code Content-Disposition} header.
|
* Return the filename of the given multipart part. This value will be used for the {@code Content-Disposition} header.
|
||||||
*
|
|
||||||
* <p>Default implementation returns {@link Resource#getFilename()} if the part is a {@code Resource}, and
|
* <p>Default implementation returns {@link Resource#getFilename()} if the part is a {@code Resource}, and
|
||||||
* {@code null} in other cases. Can be overridden in subclasses.
|
* {@code null} in other cases. Can be overridden in subclasses.
|
||||||
*
|
|
||||||
* @param part the part to determine the file name for
|
* @param part the part to determine the file name for
|
||||||
* @return the filename, or {@code null} if not known
|
* @return the filename, or {@code null} if not known
|
||||||
*/
|
*/
|
||||||
|
|
@ -334,10 +331,10 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link org.springframework.http.HttpOutputMessage} used for writing multipart data.
|
* Implementation of {@link org.springframework.http.HttpOutputMessage} used for writing multipart data.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
private class MultipartHttpOutputMessage implements HttpOutputMessage {
|
private class MultipartHttpOutputMessage implements HttpOutputMessage {
|
||||||
|
|
||||||
private final HttpHeaders headers = new HttpHeaders();
|
private final HttpHeaders headers = new HttpHeaders();
|
||||||
|
|
@ -386,7 +383,6 @@ public class FormHttpMessageConverter implements HttpMessageConverter<MultiValue
|
||||||
throw new IllegalStateException(ex);
|
throw new IllegalStateException(ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,11 +32,11 @@ import org.springframework.util.StringUtils;
|
||||||
* retrievable via {@link HttpServletRequest#getMethod()}. Since browsers currently only
|
* retrievable via {@link HttpServletRequest#getMethod()}. Since browsers currently only
|
||||||
* support GET and POST, a common technique - used by the Prototype library, for instance -
|
* support GET and POST, a common technique - used by the Prototype library, for instance -
|
||||||
* is to use a normal POST with an additional hidden form field (<code>_method</code>)
|
* is to use a normal POST with an additional hidden form field (<code>_method</code>)
|
||||||
* to pass the "real" HTTP method. This filter reads that parameter, and changes of
|
* to pass the "real" HTTP method along. This filter reads that parameter and changes
|
||||||
* {@link HttpServletRequestWrapper#getMethod()} accordingly.
|
* the {@link HttpServletRequestWrapper#getMethod()} return value accordingly.
|
||||||
*
|
*
|
||||||
* <p>The name of the request parameter defaults to <code>_method</code>, but can be
|
* <p>The name of the request parameter defaults to <code>_method</code>, but can be
|
||||||
* changed via the {@link #setMethodParam(String) methodParam} property.
|
* adapted via the {@link #setMethodParam(String) methodParam} property.
|
||||||
*
|
*
|
||||||
* <p><b>NOTE: This filter needs to run after multipart processing in case of a multipart
|
* <p><b>NOTE: This filter needs to run after multipart processing in case of a multipart
|
||||||
* POST request, due to its inherent need for checking a POST body parameter.</b>
|
* POST request, due to its inherent need for checking a POST body parameter.</b>
|
||||||
|
|
@ -70,7 +70,7 @@ public class HiddenHttpMethodFilter extends OncePerRequestFilter {
|
||||||
String paramValue = request.getParameter(this.methodParam);
|
String paramValue = request.getParameter(this.methodParam);
|
||||||
if ("POST".equals(request.getMethod()) && StringUtils.hasLength(paramValue)) {
|
if ("POST".equals(request.getMethod()) && StringUtils.hasLength(paramValue)) {
|
||||||
String method = paramValue.toUpperCase(Locale.ENGLISH);
|
String method = paramValue.toUpperCase(Locale.ENGLISH);
|
||||||
HttpServletRequest wrapper = new HttpMethodRequestWrapper(method, request);
|
HttpServletRequest wrapper = new HttpMethodRequestWrapper(request, method);
|
||||||
filterChain.doFilter(wrapper, response);
|
filterChain.doFilter(wrapper, response);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -87,7 +87,7 @@ public class HiddenHttpMethodFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
private final String method;
|
private final String method;
|
||||||
|
|
||||||
public HttpMethodRequestWrapper(String method, HttpServletRequest request) {
|
public HttpMethodRequestWrapper(HttpServletRequest request, String method) {
|
||||||
super(request);
|
super(request);
|
||||||
this.method = method;
|
this.method = method;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue