relaxed generic Class declaration in HttpMessageConverter's canRead/canWrite/read signatures (SPR-6848)
This commit is contained in:
parent
19cdd558d3
commit
4ae1709313
|
|
@ -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.
|
||||||
|
|
@ -34,11 +34,12 @@ import org.springframework.util.Assert;
|
||||||
/**
|
/**
|
||||||
* Abstract base class for most {@link HttpMessageConverter} implementations.
|
* Abstract base class for most {@link HttpMessageConverter} implementations.
|
||||||
*
|
*
|
||||||
* <p>This base class adds support for setting supported {@code MediaTypes}, through the {@link
|
* <p>This base class adds support for setting supported {@code MediaTypes}, through the
|
||||||
* #setSupportedMediaTypes(List) supportedMediaTypes} bean property. It also adds support for {@code Content-Type} and
|
* {@link #setSupportedMediaTypes(List) supportedMediaTypes} bean property. It also adds
|
||||||
* {@code Content-Length} when writing to output messages.
|
* support for {@code Content-Type} and {@code Content-Length} when writing to output messages.
|
||||||
*
|
*
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConverter<T> {
|
public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConverter<T> {
|
||||||
|
|
@ -48,9 +49,9 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
|
||||||
|
|
||||||
private List<MediaType> supportedMediaTypes = Collections.emptyList();
|
private List<MediaType> supportedMediaTypes = Collections.emptyList();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an {@code AbstractHttpMessageConverter} with no supported media types.
|
* Construct an {@code AbstractHttpMessageConverter} with no supported media types.
|
||||||
*
|
|
||||||
* @see #setSupportedMediaTypes
|
* @see #setSupportedMediaTypes
|
||||||
*/
|
*/
|
||||||
protected AbstractHttpMessageConverter() {
|
protected AbstractHttpMessageConverter() {
|
||||||
|
|
@ -58,7 +59,6 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an {@code AbstractHttpMessageConverter} with one supported media type.
|
* Construct an {@code AbstractHttpMessageConverter} with one supported media type.
|
||||||
*
|
|
||||||
* @param supportedMediaType the supported media type
|
* @param supportedMediaType the supported media type
|
||||||
*/
|
*/
|
||||||
protected AbstractHttpMessageConverter(MediaType supportedMediaType) {
|
protected AbstractHttpMessageConverter(MediaType supportedMediaType) {
|
||||||
|
|
@ -67,14 +67,16 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an {@code AbstractHttpMessageConverter} with multiple supported media type.
|
* Construct an {@code AbstractHttpMessageConverter} with multiple supported media type.
|
||||||
*
|
|
||||||
* @param supportedMediaTypes the supported media types
|
* @param supportedMediaTypes the supported media types
|
||||||
*/
|
*/
|
||||||
protected AbstractHttpMessageConverter(MediaType... supportedMediaTypes) {
|
protected AbstractHttpMessageConverter(MediaType... supportedMediaTypes) {
|
||||||
setSupportedMediaTypes(Arrays.asList(supportedMediaTypes));
|
setSupportedMediaTypes(Arrays.asList(supportedMediaTypes));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the list of {@link MediaType} objects supported by this converter. */
|
|
||||||
|
/**
|
||||||
|
* Set the list of {@link MediaType} objects supported by this converter.
|
||||||
|
*/
|
||||||
public void setSupportedMediaTypes(List<MediaType> supportedMediaTypes) {
|
public void setSupportedMediaTypes(List<MediaType> supportedMediaTypes) {
|
||||||
Assert.notEmpty(supportedMediaTypes, "'supportedMediaTypes' must not be empty");
|
Assert.notEmpty(supportedMediaTypes, "'supportedMediaTypes' must not be empty");
|
||||||
this.supportedMediaTypes = new ArrayList<MediaType>(supportedMediaTypes);
|
this.supportedMediaTypes = new ArrayList<MediaType>(supportedMediaTypes);
|
||||||
|
|
@ -84,21 +86,20 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
|
||||||
return Collections.unmodifiableList(this.supportedMediaTypes);
|
return Collections.unmodifiableList(this.supportedMediaTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
* <p>This implementation checks if the given class is {@linkplain #supports(Class) supported},
|
||||||
* <p>This implementation checks if the given class is {@linkplain #supports(Class) supported}, and if the {@linkplain
|
* and if the {@linkplain #getSupportedMediaTypes() supported media types}
|
||||||
* #getSupportedMediaTypes() supported media types} {@linkplain MediaType#includes(MediaType) include} the given media
|
* {@linkplain MediaType#includes(MediaType) include} the given media type.
|
||||||
* type.
|
|
||||||
*/
|
*/
|
||||||
public boolean canRead(Class<?> clazz, MediaType mediaType) {
|
public boolean canRead(Class<?> clazz, MediaType mediaType) {
|
||||||
return supports(clazz) && canRead(mediaType);
|
return supports(clazz) && canRead(mediaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns true if any of the {@linkplain #setSupportedMediaTypes(List) supported media types} include the given media
|
* Returns true if any of the {@linkplain #setSupportedMediaTypes(List) supported media types}
|
||||||
* type.
|
* include the given media type.
|
||||||
*
|
|
||||||
* @param mediaType the media type
|
* @param mediaType the media type
|
||||||
* @return true if the supported media types include the media type, or if the media type is {@code null}
|
* @return true if the supported media types include the media type, or if the media type is {@code null}
|
||||||
*/
|
*/
|
||||||
|
|
@ -116,10 +117,9 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
* <p>This implementation checks if the given class is {@linkplain #supports(Class) supported},
|
||||||
* <p>This implementation checks if the given class is {@linkplain #supports(Class) supported}, and if the {@linkplain
|
* and if the {@linkplain #getSupportedMediaTypes() supported media types}
|
||||||
* #getSupportedMediaTypes() supported media types} {@linkplain MediaType#includes(MediaType) include} the given media
|
* {@linkplain MediaType#includes(MediaType) include} the given media type.
|
||||||
* type.
|
|
||||||
*/
|
*/
|
||||||
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
|
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
|
||||||
return supports(clazz) && canWrite(mediaType);
|
return supports(clazz) && canWrite(mediaType);
|
||||||
|
|
@ -128,7 +128,6 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
|
||||||
/**
|
/**
|
||||||
* Returns true if the given media type includes any of the
|
* Returns true if the given media type includes any of the
|
||||||
* {@linkplain #setSupportedMediaTypes(List) supported media types}.
|
* {@linkplain #setSupportedMediaTypes(List) supported media types}.
|
||||||
*
|
|
||||||
* @param mediaType the media type
|
* @param mediaType the media type
|
||||||
* @return true if the supported media types include the media type, or if the media type is {@code null}
|
* @return true if the supported media types include the media type, or if the media type is {@code null}
|
||||||
*/
|
*/
|
||||||
|
|
@ -144,45 +143,24 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Indicates whether the given class is supported by this converter.
|
|
||||||
*
|
|
||||||
* @param clazz the class to test for support
|
|
||||||
* @return <code>true</code> if supported; <code>false</code> otherwise
|
|
||||||
*/
|
|
||||||
protected abstract boolean supports(Class<?> clazz);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
* <p>This implementation simple delegates to {@link #readInternal(Class, HttpInputMessage)}.
|
||||||
* <p>This implementation simple delegates to {@link #readInternal(Class, HttpInputMessage)}. Future implementations
|
* Future implementations might add some default behavior, however.
|
||||||
* might add some default behavior, however.
|
|
||||||
*/
|
*/
|
||||||
public final T read(Class<T> clazz, HttpInputMessage inputMessage) throws IOException {
|
public final T read(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException {
|
||||||
return readInternal(clazz, inputMessage);
|
return readInternal(clazz, inputMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract template method that reads the actualy object. Invoked from {@link #read(Class, HttpInputMessage)}.
|
|
||||||
*
|
|
||||||
* @param clazz the type of object to return
|
|
||||||
* @param inputMessage the HTTP input message to read from
|
|
||||||
* @return the converted object
|
|
||||||
* @throws IOException in case of I/O errors
|
|
||||||
* @throws HttpMessageNotReadableException in case of conversion errors
|
|
||||||
*/
|
|
||||||
protected abstract T readInternal(Class<T> clazz, HttpInputMessage inputMessage)
|
|
||||||
throws IOException, HttpMessageNotReadableException;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*
|
* <p>This implementation delegates to {@link #getDefaultContentType(Object)} if a content
|
||||||
* <p>This implementation delegates to {@link #getDefaultContentType(Object)} if a content type was not provided, calls
|
* type was not provided, calls {@link #getContentLength}, and sets the corresponding headers
|
||||||
* {@link #getContentLength}, and sets the corresponding headers on the output message. It then calls {@link
|
* on the output message. It then calls {@link #writeInternal}.
|
||||||
* #writeInternal}.
|
|
||||||
*/
|
*/
|
||||||
public final void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
|
public final void write(T t, MediaType contentType, HttpOutputMessage outputMessage)
|
||||||
throws IOException, HttpMessageNotWritableException {
|
throws IOException, HttpMessageNotWritableException {
|
||||||
|
|
||||||
HttpHeaders headers = outputMessage.getHeaders();
|
HttpHeaders headers = outputMessage.getHeaders();
|
||||||
if (contentType == null || contentType.isWildcardType() || contentType.isWildcardSubtype()) {
|
if (contentType == null || contentType.isWildcardType() || contentType.isWildcardSubtype()) {
|
||||||
contentType = getDefaultContentType(t);
|
contentType = getDefaultContentType(t);
|
||||||
|
|
@ -199,12 +177,11 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the default content type for the given type. Called when {@link #write} is invoked without a specified
|
* Returns the default content type for the given type. Called when {@link #write}
|
||||||
* content type parameter.
|
* is invoked without a specified content type parameter.
|
||||||
*
|
* <p>By default, this returns the first element of the
|
||||||
* <p>By default, this returns the first element of the {@link #setSupportedMediaTypes(List) supportedMediaTypes}
|
* {@link #setSupportedMediaTypes(List) supportedMediaTypes} property, if any.
|
||||||
* property, if any. Can be overriden in subclasses.
|
* Can be overridden in subclasses.
|
||||||
*
|
|
||||||
* @param t the type to return the content type for
|
* @param t the type to return the content type for
|
||||||
* @return the content type, or <code>null</code> if not known
|
* @return the content type, or <code>null</code> if not known
|
||||||
*/
|
*/
|
||||||
|
|
@ -215,10 +192,8 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the content length for the given type.
|
* Returns the content length for the given type.
|
||||||
*
|
* <p>By default, this returns {@code null}, meaning that the content length is unknown.
|
||||||
* <p>By default, this returns {@code null}, meaning that the content length is unknown. Can be overriden in
|
* Can be overridden in subclasses.
|
||||||
* subclasses.
|
|
||||||
*
|
|
||||||
* @param t the type to return the content length for
|
* @param t the type to return the content length for
|
||||||
* @return the content length, or {@code null} if not known
|
* @return the content length, or {@code null} if not known
|
||||||
*/
|
*/
|
||||||
|
|
@ -226,9 +201,27 @@ public abstract class AbstractHttpMessageConverter<T> implements HttpMessageConv
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Indicates whether the given class is supported by this converter.
|
||||||
|
* @param clazz the class to test for support
|
||||||
|
* @return <code>true</code> if supported; <code>false</code> otherwise
|
||||||
|
*/
|
||||||
|
protected abstract boolean supports(Class<?> clazz);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract template method that reads the actualy object. Invoked from {@link #read}.
|
||||||
|
* @param clazz the type of object to return
|
||||||
|
* @param inputMessage the HTTP input message to read from
|
||||||
|
* @return the converted object
|
||||||
|
* @throws IOException in case of I/O errors
|
||||||
|
* @throws HttpMessageNotReadableException in case of conversion errors
|
||||||
|
*/
|
||||||
|
protected abstract T readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage)
|
||||||
|
throws IOException, HttpMessageNotReadableException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract template method that writes the actual body. Invoked from {@link #write}.
|
* Abstract template method that writes the actual body. Invoked from {@link #write}.
|
||||||
*
|
|
||||||
* @param t the object to write to the output message
|
* @param t the object to write to the output message
|
||||||
* @param outputMessage the message to write to
|
* @param outputMessage the message to write to
|
||||||
* @throws IOException in case of I/O errors
|
* @throws IOException in case of I/O errors
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -62,37 +62,27 @@ import org.springframework.util.Assert;
|
||||||
*/
|
*/
|
||||||
public class BufferedImageHttpMessageConverter implements HttpMessageConverter<BufferedImage> {
|
public class BufferedImageHttpMessageConverter implements HttpMessageConverter<BufferedImage> {
|
||||||
|
|
||||||
private List<MediaType> readableMediaTypes = new ArrayList<MediaType>();
|
private final List<MediaType> readableMediaTypes = new ArrayList<MediaType>();
|
||||||
|
|
||||||
private MediaType defaultContentType;
|
private MediaType defaultContentType;
|
||||||
|
|
||||||
private File cacheDir;
|
private File cacheDir;
|
||||||
|
|
||||||
|
|
||||||
public BufferedImageHttpMessageConverter() {
|
public BufferedImageHttpMessageConverter() {
|
||||||
String[] readerMediaTypes = ImageIO.getReaderMIMETypes();
|
String[] readerMediaTypes = ImageIO.getReaderMIMETypes();
|
||||||
for (String mediaType : readerMediaTypes) {
|
for (String mediaType : readerMediaTypes) {
|
||||||
readableMediaTypes.add(MediaType.parseMediaType(mediaType));
|
this.readableMediaTypes.add(MediaType.parseMediaType(mediaType));
|
||||||
}
|
}
|
||||||
|
|
||||||
String[] writerMediaTypes = ImageIO.getWriterMIMETypes();
|
String[] writerMediaTypes = ImageIO.getWriterMIMETypes();
|
||||||
if (writerMediaTypes.length > 0) {
|
if (writerMediaTypes.length > 0) {
|
||||||
defaultContentType = MediaType.parseMediaType(writerMediaTypes[0]);
|
this.defaultContentType = MediaType.parseMediaType(writerMediaTypes[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the default {@code Content-Type} to be used for writing. Called when {@link #write} is invoked without a
|
|
||||||
* specified content type parameter.
|
|
||||||
*
|
|
||||||
* @return the default content type
|
|
||||||
*/
|
|
||||||
public MediaType getDefaultContentType() {
|
|
||||||
return defaultContentType;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the default {@code Content-Type} to be used for writing.
|
* Sets the default {@code Content-Type} to be used for writing.
|
||||||
*
|
|
||||||
* @throws IllegalArgumentException if the given content type is not supported by the Java Image I/O API
|
* @throws IllegalArgumentException if the given content type is not supported by the Java Image I/O API
|
||||||
*/
|
*/
|
||||||
public void setDefaultContentType(MediaType defaultContentType) {
|
public void setDefaultContentType(MediaType defaultContentType) {
|
||||||
|
|
@ -106,20 +96,27 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
|
||||||
this.defaultContentType = defaultContentType;
|
this.defaultContentType = defaultContentType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Sets the cache directory. If this property is set to an existing directory, this converter will cache image data. */
|
/**
|
||||||
|
* Returns the default {@code Content-Type} to be used for writing.
|
||||||
|
* Called when {@link #write} is invoked without a specified content type parameter.
|
||||||
|
*/
|
||||||
|
public MediaType getDefaultContentType() {
|
||||||
|
return this.defaultContentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the cache directory. If this property is set to an existing directory,
|
||||||
|
* this converter will cache image data.
|
||||||
|
*/
|
||||||
public void setCacheDir(File cacheDir) {
|
public void setCacheDir(File cacheDir) {
|
||||||
Assert.notNull(cacheDir, "'cacheDir' must not be null");
|
Assert.notNull(cacheDir, "'cacheDir' must not be null");
|
||||||
Assert.isTrue(cacheDir.isDirectory(), "'cacheDir' is not a directory");
|
Assert.isTrue(cacheDir.isDirectory(), "'cacheDir' is not a directory");
|
||||||
this.cacheDir = cacheDir;
|
this.cacheDir = cacheDir;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public boolean canRead(Class<?> clazz, MediaType mediaType) {
|
public boolean canRead(Class<?> clazz, MediaType mediaType) {
|
||||||
if (BufferedImage.class.equals(clazz)) {
|
return (BufferedImage.class.equals(clazz) && isReadable(mediaType));
|
||||||
return isReadable(mediaType);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isReadable(MediaType mediaType) {
|
private boolean isReadable(MediaType mediaType) {
|
||||||
|
|
@ -131,12 +128,7 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
|
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
|
||||||
if (BufferedImage.class.equals(clazz)) {
|
return (BufferedImage.class.equals(clazz) && isWritable(mediaType));
|
||||||
return isWritable(mediaType);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isWritable(MediaType mediaType) {
|
private boolean isWritable(MediaType mediaType) {
|
||||||
|
|
@ -148,11 +140,12 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
|
||||||
}
|
}
|
||||||
|
|
||||||
public List<MediaType> getSupportedMediaTypes() {
|
public List<MediaType> getSupportedMediaTypes() {
|
||||||
return Collections.unmodifiableList(readableMediaTypes);
|
return Collections.unmodifiableList(this.readableMediaTypes);
|
||||||
}
|
}
|
||||||
|
|
||||||
public BufferedImage read(Class<BufferedImage> clazz, HttpInputMessage inputMessage)
|
public BufferedImage read(Class<? extends BufferedImage> clazz, HttpInputMessage inputMessage)
|
||||||
throws IOException, HttpMessageNotReadableException {
|
throws IOException, HttpMessageNotReadableException {
|
||||||
|
|
||||||
ImageInputStream imageInputStream = null;
|
ImageInputStream imageInputStream = null;
|
||||||
ImageReader imageReader = null;
|
ImageReader imageReader = null;
|
||||||
try {
|
try {
|
||||||
|
|
@ -187,7 +180,7 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImageInputStream createImageInputStream(InputStream is) throws IOException {
|
private ImageInputStream createImageInputStream(InputStream is) throws IOException {
|
||||||
if (cacheDir != null) {
|
if (this.cacheDir != null) {
|
||||||
return new FileCacheImageInputStream(is, cacheDir);
|
return new FileCacheImageInputStream(is, cacheDir);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
@ -197,6 +190,7 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
|
||||||
|
|
||||||
public void write(BufferedImage image, MediaType contentType, HttpOutputMessage outputMessage)
|
public void write(BufferedImage image, MediaType contentType, HttpOutputMessage outputMessage)
|
||||||
throws IOException, HttpMessageNotWritableException {
|
throws IOException, HttpMessageNotWritableException {
|
||||||
|
|
||||||
if (contentType == null) {
|
if (contentType == null) {
|
||||||
contentType = getDefaultContentType();
|
contentType = getDefaultContentType();
|
||||||
}
|
}
|
||||||
|
|
@ -236,17 +230,17 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
|
||||||
}
|
}
|
||||||
|
|
||||||
private ImageOutputStream createImageOutputStream(OutputStream os) throws IOException {
|
private ImageOutputStream createImageOutputStream(OutputStream os) throws IOException {
|
||||||
if (cacheDir != null) {
|
if (this.cacheDir != null) {
|
||||||
return new FileCacheImageOutputStream(os, cacheDir);
|
return new FileCacheImageOutputStream(os, this.cacheDir);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return new MemoryCacheImageOutputStream(os);
|
return new MemoryCacheImageOutputStream(os);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Template method that allows for manipulating the {@link ImageReadParam} before it is used to read an image.
|
* Template method that allows for manipulating the {@link ImageReadParam} before it is used to read an image.
|
||||||
*
|
|
||||||
* <p>Default implementation is empty.
|
* <p>Default implementation is empty.
|
||||||
*/
|
*/
|
||||||
protected void process(ImageReadParam irp) {
|
protected void process(ImageReadParam irp) {
|
||||||
|
|
@ -254,9 +248,9 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter<B
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Template method that allows for manipulating the {@link ImageWriteParam} before it is used to write an image.
|
* Template method that allows for manipulating the {@link ImageWriteParam} before it is used to write an image.
|
||||||
*
|
|
||||||
* <p>Default implementation is empty.
|
* <p>Default implementation is empty.
|
||||||
*/
|
*/
|
||||||
protected void process(ImageWriteParam iwp) {
|
protected void process(ImageWriteParam iwp) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -47,7 +47,7 @@ public class ByteArrayHttpMessageConverter extends AbstractHttpMessageConverter<
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public byte[] readInternal(Class<byte[]> clazz, HttpInputMessage inputMessage) throws IOException {
|
public byte[] readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException {
|
||||||
long contentLength = inputMessage.getHeaders().getContentLength();
|
long contentLength = inputMessage.getHeaders().getContentLength();
|
||||||
if (contentLength >= 0) {
|
if (contentLength >= 0) {
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream((int) contentLength);
|
ByteArrayOutputStream bos = new ByteArrayOutputStream((int) contentLength);
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -50,19 +50,20 @@ public class FormHttpMessageConverter extends AbstractHttpMessageConverter<Multi
|
||||||
|
|
||||||
public static final Charset DEFAULT_CHARSET = Charset.forName(WebUtils.DEFAULT_CHARACTER_ENCODING);
|
public static final Charset DEFAULT_CHARSET = Charset.forName(WebUtils.DEFAULT_CHARACTER_ENCODING);
|
||||||
|
|
||||||
|
|
||||||
/** Creates a new instance of the {@code FormHttpMessageConverter}. */
|
/** Creates a new instance of the {@code FormHttpMessageConverter}. */
|
||||||
public FormHttpMessageConverter() {
|
public FormHttpMessageConverter() {
|
||||||
super(new MediaType("application", "x-www-form-urlencoded"));
|
super(new MediaType("application", "x-www-form-urlencoded"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(Class<?> clazz) {
|
public boolean supports(Class<?> clazz) {
|
||||||
return MultiValueMap.class.isAssignableFrom(clazz);
|
return MultiValueMap.class.isAssignableFrom(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public MultiValueMap<String, String> readInternal(Class<MultiValueMap<String, String>> clazz,
|
public MultiValueMap<String, String> readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException {
|
||||||
HttpInputMessage inputMessage) throws IOException {
|
|
||||||
MediaType contentType = inputMessage.getHeaders().getContentType();
|
MediaType contentType = inputMessage.getHeaders().getContentType();
|
||||||
Charset charset = contentType.getCharSet() != null ? contentType.getCharSet() : DEFAULT_CHARSET;
|
Charset charset = contentType.getCharSet() != null ? contentType.getCharSet() : DEFAULT_CHARSET;
|
||||||
String body = FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset));
|
String body = FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset));
|
||||||
|
|
@ -112,4 +113,5 @@ public class FormHttpMessageConverter extends AbstractHttpMessageConverter<Multi
|
||||||
}
|
}
|
||||||
FileCopyUtils.copy(builder.toString(), new OutputStreamWriter(outputMessage.getBody(), charset));
|
FileCopyUtils.copy(builder.toString(), new OutputStreamWriter(outputMessage.getBody(), charset));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -27,6 +27,7 @@ import org.springframework.http.MediaType;
|
||||||
* Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.
|
* Strategy interface that specifies a converter that can convert from and to HTTP requests and responses.
|
||||||
*
|
*
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
*/
|
*/
|
||||||
public interface HttpMessageConverter<T> {
|
public interface HttpMessageConverter<T> {
|
||||||
|
|
@ -55,23 +56,24 @@ public interface HttpMessageConverter<T> {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read an object of the given type form the given input message, and returns it.
|
* Read an object of the given type form the given input message, and returns it.
|
||||||
* @param clazz the type of object to return. This type must have previously been passed to the {@link #canRead
|
* @param clazz the type of object to return. This type must have previously been passed to the
|
||||||
* canRead} method of this interface, which must have returned {@code true}.
|
* {@link #canRead canRead} method of this interface, which must have returned {@code true}.
|
||||||
* @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
|
||||||
* @throws HttpMessageNotReadableException in case of conversion errors
|
* @throws HttpMessageNotReadableException in case of conversion errors
|
||||||
*/
|
*/
|
||||||
T read(Class<T> clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException;
|
T read(Class<? extends T> clazz, HttpInputMessage inputMessage)
|
||||||
|
throws IOException, HttpMessageNotReadableException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Write an given object to the given output message.
|
* Write an given object to the given output message.
|
||||||
*
|
* @param t the object to write to the output message. The type of this object must have previously been
|
||||||
* @param t the object to write to the output message. The type of this object must have previously been passed to the
|
* passed to the {@link #canWrite canWrite} method of this interface, which must have returned {@code true}.
|
||||||
* {@link #canWrite canWrite} method of this interface, which must have returned {@code true}.
|
* @param contentType the content type to use when writing. May be {@code null} to indicate that the
|
||||||
* @param contentType the content type to use when writing. May be {@code null} to indicate that the the default
|
* default content type of the converter must be used. If not {@code null}, this media type must have
|
||||||
* content type of the converter must be used. If not {@code null}, this media type must have previously been passed to
|
* previously been passed to the {@link #canWrite canWrite} method of this interface, which must have
|
||||||
* the {@link #canWrite canWrite} method of this interface, which must have returned {@code true}.
|
* returned {@code true}.
|
||||||
* @param outputMessage the message to write to
|
* @param outputMessage the message to write to
|
||||||
* @throws IOException in case of I/O errors
|
* @throws IOException in case of I/O errors
|
||||||
* @throws HttpMessageNotWritableException in case of conversion errors
|
* @throws HttpMessageNotWritableException in case of conversion errors
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -56,7 +56,7 @@ public class StringHttpMessageConverter extends AbstractHttpMessageConverter<Str
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String readInternal(Class<String> clazz, HttpInputMessage inputMessage) throws IOException {
|
protected String readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException {
|
||||||
MediaType contentType = inputMessage.getHeaders().getContentType();
|
MediaType contentType = inputMessage.getHeaders().getContentType();
|
||||||
Charset charset = contentType.getCharSet() != null ? contentType.getCharSet() : DEFAULT_CHARSET;
|
Charset charset = contentType.getCharSet() != null ? contentType.getCharSet() : DEFAULT_CHARSET;
|
||||||
return FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset));
|
return FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset));
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -35,18 +35,17 @@ import org.springframework.http.converter.HttpMessageNotWritableException;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverter} that can read
|
* Implementation of {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverter}
|
||||||
* and write JSON using <a href="http://jackson.codehaus.org/">Jackson's</a> {@link ObjectMapper}.
|
* that can read and write JSON using <a href="http://jackson.codehaus.org/">Jackson's</a> {@link ObjectMapper}.
|
||||||
*
|
*
|
||||||
* <p>This converter can be used to bind to typed beans, or untyped {@link java.util.HashMap HashMap} instances.
|
* <p>This converter can be used to bind to typed beans, or untyped {@link java.util.HashMap HashMap} instances.
|
||||||
*
|
*
|
||||||
* <p>By default, this converter supports {@code application/json}. This can be overridden by setting the {@link
|
* <p>By default, this converter supports {@code application/json}. This can be overridden by setting the
|
||||||
* #setSupportedMediaTypes(List) supportedMediaTypes} property.
|
* {@link #setSupportedMediaTypes(List) supportedMediaTypes} property.
|
||||||
* method.
|
|
||||||
*
|
*
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
* @see org.springframework.web.servlet.view.json.BindingJacksonJsonView
|
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
|
* @see org.springframework.web.servlet.view.json.BindingJacksonJsonView
|
||||||
*/
|
*/
|
||||||
public class MappingJacksonHttpMessageConverter extends AbstractHttpMessageConverter<Object> {
|
public class MappingJacksonHttpMessageConverter extends AbstractHttpMessageConverter<Object> {
|
||||||
|
|
||||||
|
|
@ -56,15 +55,17 @@ public class MappingJacksonHttpMessageConverter extends AbstractHttpMessageConve
|
||||||
|
|
||||||
private boolean prefixJson = false;
|
private boolean prefixJson = false;
|
||||||
|
|
||||||
/** Construct a new {@code BindingJacksonHttpMessageConverter}, */
|
|
||||||
|
/**
|
||||||
|
* Construct a new {@code BindingJacksonHttpMessageConverter}.
|
||||||
|
*/
|
||||||
public MappingJacksonHttpMessageConverter() {
|
public MappingJacksonHttpMessageConverter() {
|
||||||
super(new MediaType("application", "json", DEFAULT_CHARSET));
|
super(new MediaType("application", "json", DEFAULT_CHARSET));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the {@code ObjectMapper} for this view. If not set, a default {@link ObjectMapper#ObjectMapper() ObjectMapper}
|
* Sets the {@code ObjectMapper} for this view. If not set, a default
|
||||||
* is used.
|
* {@link ObjectMapper#ObjectMapper() ObjectMapper} is used.
|
||||||
*
|
|
||||||
* <p>Setting a custom-configured {@code ObjectMapper} is one way to take further control of the JSON serialization
|
* <p>Setting a custom-configured {@code ObjectMapper} is one way to take further control of the JSON serialization
|
||||||
* process. For example, an extended {@link org.codehaus.jackson.map.SerializerFactory} can be configured that provides
|
* process. For example, an extended {@link org.codehaus.jackson.map.SerializerFactory} can be configured that provides
|
||||||
* custom serializers for specific types. The other option for refining the serialization process is to use Jackson's
|
* custom serializers for specific types. The other option for refining the serialization process is to use Jackson's
|
||||||
|
|
@ -77,7 +78,6 @@ public class MappingJacksonHttpMessageConverter extends AbstractHttpMessageConve
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Indicates whether the JSON output by this view should be prefixed with "{} &&". Default is false.
|
* Indicates whether the JSON output by this view should be prefixed with "{} &&". Default is false.
|
||||||
*
|
|
||||||
* <p> Prefixing the JSON string in this manner is used to help prevent JSON Hijacking. The prefix renders the string
|
* <p> Prefixing the JSON string in this manner is used to help prevent JSON Hijacking. The prefix renders the string
|
||||||
* syntactically invalid as a script so that it cannot be hijacked. This prefix does not affect the evaluation of JSON,
|
* syntactically invalid as a script so that it cannot be hijacked. This prefix does not affect the evaluation of JSON,
|
||||||
* but if JSON validation is performed on the string, the prefix would need to be ignored.
|
* but if JSON validation is performed on the string, the prefix would need to be ignored.
|
||||||
|
|
@ -86,39 +86,42 @@ public class MappingJacksonHttpMessageConverter extends AbstractHttpMessageConve
|
||||||
this.prefixJson = prefixJson;
|
this.prefixJson = prefixJson;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canRead(Class<?> clazz, MediaType mediaType) {
|
public boolean canRead(Class<?> clazz, MediaType mediaType) {
|
||||||
JavaType javaType = TypeFactory.fromClass(clazz);
|
JavaType javaType = TypeFactory.fromClass(clazz);
|
||||||
return objectMapper.canDeserialize(javaType) && canRead(mediaType);
|
return this.objectMapper.canDeserialize(javaType) && canRead(mediaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
|
public boolean canWrite(Class<?> clazz, MediaType mediaType) {
|
||||||
return objectMapper.canSerialize(clazz) && canWrite(mediaType);
|
return this.objectMapper.canSerialize(clazz) && canWrite(mediaType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected boolean supports(Class<?> clazz) {
|
protected boolean supports(Class<?> clazz) {
|
||||||
// should not be called, since we override canRead/Write
|
// should not be called, since we override canRead/Write instead
|
||||||
throw new UnsupportedOperationException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object readInternal(Class<Object> clazz, HttpInputMessage inputMessage)
|
protected Object readInternal(Class<?> clazz, HttpInputMessage inputMessage)
|
||||||
throws IOException, HttpMessageNotReadableException {
|
throws IOException, HttpMessageNotReadableException {
|
||||||
return objectMapper.readValue(inputMessage.getBody(), clazz);
|
|
||||||
|
return this.objectMapper.readValue(inputMessage.getBody(), clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void writeInternal(Object o, HttpOutputMessage outputMessage)
|
protected void writeInternal(Object o, HttpOutputMessage outputMessage)
|
||||||
throws IOException, HttpMessageNotWritableException {
|
throws IOException, HttpMessageNotWritableException {
|
||||||
|
|
||||||
JsonEncoding encoding = getEncoding(outputMessage.getHeaders().getContentType());
|
JsonEncoding encoding = getEncoding(outputMessage.getHeaders().getContentType());
|
||||||
JsonGenerator jsonGenerator =
|
JsonGenerator jsonGenerator =
|
||||||
objectMapper.getJsonFactory().createJsonGenerator(outputMessage.getBody(), encoding);
|
this.objectMapper.getJsonFactory().createJsonGenerator(outputMessage.getBody(), encoding);
|
||||||
if (prefixJson) {
|
if (this.prefixJson) {
|
||||||
jsonGenerator.writeRaw("{} && ");
|
jsonGenerator.writeRaw("{} && ");
|
||||||
}
|
}
|
||||||
objectMapper.writeValue(jsonGenerator, o);
|
this.objectMapper.writeValue(jsonGenerator, o);
|
||||||
}
|
}
|
||||||
|
|
||||||
private JsonEncoding getEncoding(MediaType contentType) {
|
private JsonEncoding getEncoding(MediaType contentType) {
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -19,7 +19,6 @@ package org.springframework.http.converter.xml;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import javax.xml.transform.Result;
|
import javax.xml.transform.Result;
|
||||||
import javax.xml.transform.Source;
|
import javax.xml.transform.Source;
|
||||||
import javax.xml.transform.Transformer;
|
|
||||||
import javax.xml.transform.TransformerException;
|
import javax.xml.transform.TransformerException;
|
||||||
import javax.xml.transform.TransformerFactory;
|
import javax.xml.transform.TransformerFactory;
|
||||||
import javax.xml.transform.stream.StreamResult;
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
|
@ -33,8 +32,8 @@ import org.springframework.http.converter.AbstractHttpMessageConverter;
|
||||||
import org.springframework.http.converter.HttpMessageConversionException;
|
import org.springframework.http.converter.HttpMessageConversionException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract base class for {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverters} that
|
* Abstract base class for {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverters}
|
||||||
* convert from/to XML.
|
* that convert from/to XML.
|
||||||
*
|
*
|
||||||
* <p>By default, subclasses of this converter support {@code text/xml}, {@code application/xml}, and {@code
|
* <p>By default, subclasses of this converter support {@code text/xml}, {@code application/xml}, and {@code
|
||||||
* application/*-xml}. This can be overridden by setting the {@link #setSupportedMediaTypes(java.util.List)
|
* application/*-xml}. This can be overridden by setting the {@link #setSupportedMediaTypes(java.util.List)
|
||||||
|
|
@ -47,58 +46,58 @@ public abstract class AbstractXmlHttpMessageConverter<T> extends AbstractHttpMes
|
||||||
|
|
||||||
private final TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
private final TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Protected constructor that sets the {@link #setSupportedMediaTypes(java.util.List) supportedMediaTypes} to {@code
|
* Protected constructor that sets the {@link #setSupportedMediaTypes(java.util.List) supportedMediaTypes}
|
||||||
* text/xml} and {@code application/xml}, and {@code application/*-xml}.
|
* to {@code text/xml} and {@code application/xml}, and {@code application/*-xml}.
|
||||||
*/
|
*/
|
||||||
protected AbstractXmlHttpMessageConverter() {
|
protected AbstractXmlHttpMessageConverter() {
|
||||||
super(new MediaType("application", "xml"), new MediaType("text", "xml"), new MediaType("application", "*+xml"));
|
super(new MediaType("application", "xml"), new MediaType("text", "xml"), new MediaType("application", "*+xml"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Invokes {@link #readFromSource(Class, HttpHeaders, Source)}. */
|
|
||||||
@Override
|
@Override
|
||||||
public final T readInternal(Class<T> clazz, HttpInputMessage inputMessage) throws IOException {
|
public final T readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage) throws IOException {
|
||||||
return readFromSource(clazz, inputMessage.getHeaders(), new StreamSource(inputMessage.getBody()));
|
return readFromSource(clazz, inputMessage.getHeaders(), new StreamSource(inputMessage.getBody()));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstract template method called from {@link #read(Class, HttpInputMessage)}.
|
|
||||||
*
|
|
||||||
* @param clazz the type of object to return
|
|
||||||
* @param headers the HTTP input headers
|
|
||||||
* @param source the HTTP input body
|
|
||||||
* @return the converted object
|
|
||||||
* @throws IOException in case of I/O errors
|
|
||||||
* @throws org.springframework.http.converter.HttpMessageConversionException in case of conversion errors
|
|
||||||
*/
|
|
||||||
protected abstract T readFromSource(Class<T> clazz, HttpHeaders headers, Source source) throws IOException;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected final void writeInternal(T t, HttpOutputMessage outputMessage) throws IOException {
|
protected final void writeInternal(T t, HttpOutputMessage outputMessage) throws IOException {
|
||||||
writeToResult(t, outputMessage.getHeaders(), new StreamResult(outputMessage.getBody()));
|
writeToResult(t, outputMessage.getHeaders(), new StreamResult(outputMessage.getBody()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transforms the given {@code Source} to the {@code Result}.
|
||||||
|
* @param source the source to transform from
|
||||||
|
* @param result the result to transform to
|
||||||
|
* @throws HttpMessageConversionException in case of transformation errors
|
||||||
|
*/
|
||||||
|
protected void transform(Source source, Result result) throws TransformerException {
|
||||||
|
this.transformerFactory.newTransformer().transform(source, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Abstract template method called from {@link #read(Class, HttpInputMessage)}.
|
||||||
|
* @param clazz the type of object to return
|
||||||
|
* @param headers the HTTP input headers
|
||||||
|
* @param source the HTTP input body
|
||||||
|
* @return the converted object
|
||||||
|
* @throws IOException in case of I/O errors
|
||||||
|
* @throws org.springframework.http.converter.HttpMessageConversionException in case of conversion errors
|
||||||
|
*/
|
||||||
|
protected abstract T readFromSource(Class<? extends T> clazz, HttpHeaders headers, Source source)
|
||||||
|
throws IOException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Abstract template method called from {@link #writeInternal(Object, HttpOutputMessage)}.
|
* Abstract template method called from {@link #writeInternal(Object, HttpOutputMessage)}.
|
||||||
*
|
|
||||||
* @param t the object to write to the output message
|
* @param t the object to write to the output message
|
||||||
* @param headers the HTTP output headers
|
* @param headers the HTTP output headers
|
||||||
* @param result the HTTP output body
|
* @param result the HTTP output body
|
||||||
* @throws IOException in case of I/O errors
|
* @throws IOException in case of I/O errors
|
||||||
* @throws HttpMessageConversionException in case of conversion errors
|
* @throws HttpMessageConversionException in case of conversion errors
|
||||||
*/
|
*/
|
||||||
protected abstract void writeToResult(T t, HttpHeaders headers, Result result) throws IOException;
|
protected abstract void writeToResult(T t, HttpHeaders headers, Result result)
|
||||||
|
throws IOException;
|
||||||
/**
|
|
||||||
* Transforms the given {@code Source} to the {@code Result}.
|
|
||||||
*
|
|
||||||
* @param source the source to transform from
|
|
||||||
* @param result the result to transform to
|
|
||||||
* @throws HttpMessageConversionException in case of transformation errors
|
|
||||||
*/
|
|
||||||
protected void transform(Source source, Result result) throws TransformerException {
|
|
||||||
Transformer transformer = transformerFactory.newTransformer();
|
|
||||||
transformer.transform(source, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -67,14 +67,14 @@ public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessa
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object readFromSource(Class<Object> clazz, HttpHeaders headers, Source source) throws IOException {
|
protected Object readFromSource(Class<?> clazz, HttpHeaders headers, Source source) throws IOException {
|
||||||
try {
|
try {
|
||||||
Unmarshaller unmarshaller = createUnmarshaller(clazz);
|
Unmarshaller unmarshaller = createUnmarshaller(clazz);
|
||||||
if (clazz.isAnnotationPresent(XmlRootElement.class)) {
|
if (clazz.isAnnotationPresent(XmlRootElement.class)) {
|
||||||
return unmarshaller.unmarshal(source);
|
return unmarshaller.unmarshal(source);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
JAXBElement<Object> jaxbElement = unmarshaller.unmarshal(source, clazz);
|
JAXBElement jaxbElement = unmarshaller.unmarshal(source, clazz);
|
||||||
return jaxbElement.getValue();
|
return jaxbElement.getValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -49,6 +49,7 @@ public class MarshallingHttpMessageConverter extends AbstractXmlHttpMessageConve
|
||||||
|
|
||||||
private Unmarshaller unmarshaller;
|
private Unmarshaller unmarshaller;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new {@code MarshallingHttpMessageConverter} with no {@link Marshaller} or {@link Unmarshaller} set. The
|
* Construct a new {@code MarshallingHttpMessageConverter} with no {@link Marshaller} or {@link Unmarshaller} set. The
|
||||||
* marshaller and unmarshaller must be set after construction by invoking {@link #setMarshaller(Marshaller)} and {@link
|
* marshaller and unmarshaller must be set after construction by invoking {@link #setMarshaller(Marshaller)} and {@link
|
||||||
|
|
@ -62,7 +63,6 @@ public class MarshallingHttpMessageConverter extends AbstractXmlHttpMessageConve
|
||||||
* Marshaller} also implements the {@link Unmarshaller} interface, it is used for both marshalling and unmarshalling.
|
* Marshaller} also implements the {@link Unmarshaller} interface, it is used for both marshalling and unmarshalling.
|
||||||
* Otherwise, an exception is thrown. <p>Note that all {@code Marshaller} implementations in Spring also implement the
|
* Otherwise, an exception is thrown. <p>Note that all {@code Marshaller} implementations in Spring also implement the
|
||||||
* {@code Unmarshaller} interface, so that you can safely use this constructor.
|
* {@code Unmarshaller} interface, so that you can safely use this constructor.
|
||||||
*
|
|
||||||
* @param marshaller object used as marshaller and unmarshaller
|
* @param marshaller object used as marshaller and unmarshaller
|
||||||
*/
|
*/
|
||||||
public MarshallingHttpMessageConverter(Marshaller marshaller) {
|
public MarshallingHttpMessageConverter(Marshaller marshaller) {
|
||||||
|
|
@ -76,7 +76,6 @@ public class MarshallingHttpMessageConverter extends AbstractXmlHttpMessageConve
|
||||||
/**
|
/**
|
||||||
* Construct a new <code>MarshallingMessageConverter</code> with the given {@code Marshaller} and {@code
|
* Construct a new <code>MarshallingMessageConverter</code> with the given {@code Marshaller} and {@code
|
||||||
* Unmarshaller}.
|
* Unmarshaller}.
|
||||||
*
|
|
||||||
* @param marshaller the Marshaller to use
|
* @param marshaller the Marshaller to use
|
||||||
* @param unmarshaller the Unmarshaller to use
|
* @param unmarshaller the Unmarshaller to use
|
||||||
*/
|
*/
|
||||||
|
|
@ -87,26 +86,31 @@ public class MarshallingHttpMessageConverter extends AbstractXmlHttpMessageConve
|
||||||
this.unmarshaller = unmarshaller;
|
this.unmarshaller = unmarshaller;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the {@link Marshaller} to be used by this message converter. */
|
/**
|
||||||
|
* Set the {@link Marshaller} to be used by this message converter.
|
||||||
|
*/
|
||||||
public void setMarshaller(Marshaller marshaller) {
|
public void setMarshaller(Marshaller marshaller) {
|
||||||
this.marshaller = marshaller;
|
this.marshaller = marshaller;
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Set the {@link Unmarshaller} to be used by this message converter. */
|
/**
|
||||||
|
* Set the {@link Unmarshaller} to be used by this message converter.
|
||||||
|
*/
|
||||||
public void setUnmarshaller(Unmarshaller unmarshaller) {
|
public void setUnmarshaller(Unmarshaller unmarshaller) {
|
||||||
this.unmarshaller = unmarshaller;
|
this.unmarshaller = unmarshaller;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean supports(Class<?> clazz) {
|
public boolean supports(Class<?> clazz) {
|
||||||
return unmarshaller.supports(clazz);
|
return this.unmarshaller.supports(clazz);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Object readFromSource(Class<Object> clazz, HttpHeaders headers, Source source) throws IOException {
|
protected Object readFromSource(Class<?> clazz, HttpHeaders headers, Source source) throws IOException {
|
||||||
Assert.notNull(this.unmarshaller, "Property 'unmarshaller' is required");
|
Assert.notNull(this.unmarshaller, "Property 'unmarshaller' is required");
|
||||||
try {
|
try {
|
||||||
return unmarshaller.unmarshal(source);
|
return this.unmarshaller.unmarshal(source);
|
||||||
}
|
}
|
||||||
catch (UnmarshallingFailureException ex) {
|
catch (UnmarshallingFailureException ex) {
|
||||||
throw new HttpMessageNotReadableException("Could not read [" + clazz + "]", ex);
|
throw new HttpMessageNotReadableException("Could not read [" + clazz + "]", ex);
|
||||||
|
|
@ -117,10 +121,11 @@ public class MarshallingHttpMessageConverter extends AbstractXmlHttpMessageConve
|
||||||
protected void writeToResult(Object o, HttpHeaders headers, Result result) throws IOException {
|
protected void writeToResult(Object o, HttpHeaders headers, Result result) throws IOException {
|
||||||
Assert.notNull(this.marshaller, "Property 'marshaller' is required");
|
Assert.notNull(this.marshaller, "Property 'marshaller' is required");
|
||||||
try {
|
try {
|
||||||
marshaller.marshal(o, result);
|
this.marshaller.marshal(o, result);
|
||||||
}
|
}
|
||||||
catch (MarshallingFailureException ex) {
|
catch (MarshallingFailureException ex) {
|
||||||
throw new HttpMessageNotWritableException("Could not write [" + o + "]", ex);
|
throw new HttpMessageNotWritableException("Could not write [" + o + "]", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -36,8 +36,8 @@ import org.springframework.http.converter.HttpMessageNotReadableException;
|
||||||
import org.springframework.http.converter.HttpMessageNotWritableException;
|
import org.springframework.http.converter.HttpMessageNotWritableException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link org.springframework.http.converter.HttpMessageConverter} that can read and write {@link
|
* Implementation of {@link org.springframework.http.converter.HttpMessageConverter}
|
||||||
* Source} objects.
|
* that can read and write {@link Source} objects.
|
||||||
*
|
*
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
|
|
@ -52,7 +52,7 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractXmlHtt
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
protected T readFromSource(Class<T> clazz, HttpHeaders headers, Source source) throws IOException {
|
protected T readFromSource(Class clazz, HttpHeaders headers, Source source) throws IOException {
|
||||||
try {
|
try {
|
||||||
if (DOMSource.class.equals(clazz)) {
|
if (DOMSource.class.equals(clazz)) {
|
||||||
DOMResult domResult = new DOMResult();
|
DOMResult domResult = new DOMResult();
|
||||||
|
|
@ -93,4 +93,5 @@ public class SourceHttpMessageConverter<T extends Source> extends AbstractXmlHtt
|
||||||
throw new HttpMessageNotWritableException("Could not transform [" + t + "] to [" + result + "]", ex);
|
throw new HttpMessageNotWritableException("Could not transform [" + t + "] to [" + result + "]", ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -17,10 +17,17 @@
|
||||||
package org.springframework.http.converter;
|
package org.springframework.http.converter;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.StringReader;
|
||||||
|
import java.io.StringWriter;
|
||||||
|
|
||||||
|
import javax.xml.bind.JAXBContext;
|
||||||
|
import javax.xml.bind.JAXBElement;
|
||||||
|
import javax.xml.transform.Source;
|
||||||
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
import javax.xml.namespace.QName;
|
||||||
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.springframework.http.HttpInputMessage;
|
import org.springframework.http.HttpInputMessage;
|
||||||
import org.springframework.http.HttpOutputMessage;
|
import org.springframework.http.HttpOutputMessage;
|
||||||
|
|
@ -79,7 +86,7 @@ public class HttpMessageConverterTests {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected T readInternal(Class<T> clazz, HttpInputMessage inputMessage)
|
protected T readInternal(Class clazz, HttpInputMessage inputMessage)
|
||||||
throws IOException, HttpMessageNotReadableException {
|
throws IOException, HttpMessageNotReadableException {
|
||||||
fail("Not expected");
|
fail("Not expected");
|
||||||
return null;
|
return null;
|
||||||
|
|
@ -95,4 +102,5 @@ public class HttpMessageConverterTests {
|
||||||
private static class MyType {
|
private static class MyType {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
@ -31,7 +31,9 @@ import org.springframework.http.MediaType;
|
||||||
import org.springframework.http.MockHttpInputMessage;
|
import org.springframework.http.MockHttpInputMessage;
|
||||||
import org.springframework.http.MockHttpOutputMessage;
|
import org.springframework.http.MockHttpOutputMessage;
|
||||||
|
|
||||||
/** @author Arjen Poutsma */
|
/**
|
||||||
|
* @author Arjen Poutsma
|
||||||
|
*/
|
||||||
public class MappingJacksonHttpMessageConverterTests {
|
public class MappingJacksonHttpMessageConverterTests {
|
||||||
|
|
||||||
private MappingJacksonHttpMessageConverter converter;
|
private MappingJacksonHttpMessageConverter converter;
|
||||||
|
|
@ -60,7 +62,7 @@ public class MappingJacksonHttpMessageConverterTests {
|
||||||
"{\"bytes\":\"AQI=\",\"array\":[\"Foo\",\"Bar\"],\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}";
|
"{\"bytes\":\"AQI=\",\"array\":[\"Foo\",\"Bar\"],\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}";
|
||||||
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
|
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
|
||||||
inputMessage.getHeaders().setContentType(new MediaType("application", "json"));
|
inputMessage.getHeaders().setContentType(new MediaType("application", "json"));
|
||||||
MyBean result = (MyBean) converter.read((Class) MyBean.class, inputMessage);
|
MyBean result = (MyBean) converter.read(MyBean.class, inputMessage);
|
||||||
assertEquals("Foo", result.getString());
|
assertEquals("Foo", result.getString());
|
||||||
assertEquals(42, result.getNumber());
|
assertEquals(42, result.getNumber());
|
||||||
assertEquals(42F, result.getFraction(), 0F);
|
assertEquals(42F, result.getFraction(), 0F);
|
||||||
|
|
@ -76,7 +78,7 @@ public class MappingJacksonHttpMessageConverterTests {
|
||||||
"{\"bytes\":\"AQI=\",\"array\":[\"Foo\",\"Bar\"],\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}";
|
"{\"bytes\":\"AQI=\",\"array\":[\"Foo\",\"Bar\"],\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}";
|
||||||
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
|
MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8"));
|
||||||
inputMessage.getHeaders().setContentType(new MediaType("application", "json"));
|
inputMessage.getHeaders().setContentType(new MediaType("application", "json"));
|
||||||
HashMap<String, Object> result = (HashMap<String, Object>) converter.read((Class)HashMap.class, inputMessage);
|
HashMap<String, Object> result = (HashMap<String, Object>) converter.read(HashMap.class, inputMessage);
|
||||||
assertEquals("Foo", result.get("string"));
|
assertEquals("Foo", result.get("string"));
|
||||||
assertEquals(42, result.get("number"));
|
assertEquals(42, result.get("number"));
|
||||||
assertEquals(42D, (Double) result.get("fraction"), 0D);
|
assertEquals(42D, (Double) result.get("fraction"), 0D);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue