diff --git a/org.springframework.web/src/main/java/org/springframework/http/converter/AbstractHttpMessageConverter.java b/org.springframework.web/src/main/java/org/springframework/http/converter/AbstractHttpMessageConverter.java index 75782d74484..5b303a2a516 100644 --- a/org.springframework.web/src/main/java/org/springframework/http/converter/AbstractHttpMessageConverter.java +++ b/org.springframework.web/src/main/java/org/springframework/http/converter/AbstractHttpMessageConverter.java @@ -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"); * 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. * - *

This base class adds support for setting supported {@code MediaTypes}, through the {@link - * #setSupportedMediaTypes(List) supportedMediaTypes} bean property. It also adds support for {@code Content-Type} and - * {@code Content-Length} when writing to output messages. + *

This base class adds support for setting supported {@code MediaTypes}, through the + * {@link #setSupportedMediaTypes(List) supportedMediaTypes} bean property. It also adds + * support for {@code Content-Type} and {@code Content-Length} when writing to output messages. * * @author Arjen Poutsma + * @author Juergen Hoeller * @since 3.0 */ public abstract class AbstractHttpMessageConverter implements HttpMessageConverter { @@ -48,9 +49,9 @@ public abstract class AbstractHttpMessageConverter implements HttpMessageConv private List supportedMediaTypes = Collections.emptyList(); + /** * Construct an {@code AbstractHttpMessageConverter} with no supported media types. - * * @see #setSupportedMediaTypes */ protected AbstractHttpMessageConverter() { @@ -58,7 +59,6 @@ public abstract class AbstractHttpMessageConverter implements HttpMessageConv /** * Construct an {@code AbstractHttpMessageConverter} with one supported media type. - * * @param supportedMediaType the supported media type */ protected AbstractHttpMessageConverter(MediaType supportedMediaType) { @@ -67,14 +67,16 @@ public abstract class AbstractHttpMessageConverter implements HttpMessageConv /** * Construct an {@code AbstractHttpMessageConverter} with multiple supported media type. - * * @param supportedMediaTypes the supported media types */ protected AbstractHttpMessageConverter(MediaType... 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 supportedMediaTypes) { Assert.notEmpty(supportedMediaTypes, "'supportedMediaTypes' must not be empty"); this.supportedMediaTypes = new ArrayList(supportedMediaTypes); @@ -84,21 +86,20 @@ public abstract class AbstractHttpMessageConverter implements HttpMessageConv return Collections.unmodifiableList(this.supportedMediaTypes); } + /** * {@inheritDoc} - * - *

This implementation checks if the given class is {@linkplain #supports(Class) supported}, and if the {@linkplain - * #getSupportedMediaTypes() supported media types} {@linkplain MediaType#includes(MediaType) include} the given media - * type. + *

This implementation checks if the given class is {@linkplain #supports(Class) supported}, + * and if the {@linkplain #getSupportedMediaTypes() supported media types} + * {@linkplain MediaType#includes(MediaType) include} the given media type. */ public boolean canRead(Class clazz, MediaType mediaType) { return supports(clazz) && canRead(mediaType); } /** - * Returns true if any of the {@linkplain #setSupportedMediaTypes(List) supported media types} include the given media - * type. - * + * Returns true if any of the {@linkplain #setSupportedMediaTypes(List) supported media types} + * include the given 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} */ @@ -116,10 +117,9 @@ public abstract class AbstractHttpMessageConverter implements HttpMessageConv /** * {@inheritDoc} - * - *

This implementation checks if the given class is {@linkplain #supports(Class) supported}, and if the {@linkplain - * #getSupportedMediaTypes() supported media types} {@linkplain MediaType#includes(MediaType) include} the given media - * type. + *

This implementation checks if the given class is {@linkplain #supports(Class) supported}, + * and if the {@linkplain #getSupportedMediaTypes() supported media types} + * {@linkplain MediaType#includes(MediaType) include} the given media type. */ public boolean canWrite(Class clazz, MediaType mediaType) { return supports(clazz) && canWrite(mediaType); @@ -128,7 +128,6 @@ public abstract class AbstractHttpMessageConverter implements HttpMessageConv /** * Returns true if the given media type includes any of the * {@linkplain #setSupportedMediaTypes(List) supported media types}. - * * @param mediaType the media type * @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 implements HttpMessageConv return false; } - /** - * Indicates whether the given class is supported by this converter. - * - * @param clazz the class to test for support - * @return true if supported; false otherwise - */ - protected abstract boolean supports(Class clazz); - /** * {@inheritDoc} - * - *

This implementation simple delegates to {@link #readInternal(Class, HttpInputMessage)}. Future implementations - * might add some default behavior, however. + *

This implementation simple delegates to {@link #readInternal(Class, HttpInputMessage)}. + * Future implementations might add some default behavior, however. */ - public final T read(Class clazz, HttpInputMessage inputMessage) throws IOException { + public final T read(Class clazz, HttpInputMessage inputMessage) throws IOException { 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 clazz, HttpInputMessage inputMessage) - throws IOException, HttpMessageNotReadableException; - /** * {@inheritDoc} - * - *

This implementation delegates to {@link #getDefaultContentType(Object)} if a content type was not provided, calls - * {@link #getContentLength}, and sets the corresponding headers on the output message. It then calls {@link - * #writeInternal}. + *

This implementation delegates to {@link #getDefaultContentType(Object)} if a content + * type was not provided, calls {@link #getContentLength}, and sets the corresponding headers + * on the output message. It then calls {@link #writeInternal}. */ public final void write(T t, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { + HttpHeaders headers = outputMessage.getHeaders(); if (contentType == null || contentType.isWildcardType() || contentType.isWildcardSubtype()) { contentType = getDefaultContentType(t); @@ -199,12 +177,11 @@ public abstract class AbstractHttpMessageConverter implements HttpMessageConv } /** - * Returns the default content type for the given type. Called when {@link #write} is invoked without a specified - * content type parameter. - * - *

By default, this returns the first element of the {@link #setSupportedMediaTypes(List) supportedMediaTypes} - * property, if any. Can be overriden in subclasses. - * + * Returns the default content type for the given type. Called when {@link #write} + * is invoked without a specified content type parameter. + *

By default, this returns the first element of the + * {@link #setSupportedMediaTypes(List) supportedMediaTypes} property, if any. + * Can be overridden in subclasses. * @param t the type to return the content type for * @return the content type, or null if not known */ @@ -215,10 +192,8 @@ public abstract class AbstractHttpMessageConverter implements HttpMessageConv /** * Returns the content length for the given type. - * - *

By default, this returns {@code null}, meaning that the content length is unknown. Can be overriden in - * subclasses. - * + *

By default, this returns {@code null}, meaning that the content length is unknown. + * Can be overridden in subclasses. * @param t the type to return the content length for * @return the content length, or {@code null} if not known */ @@ -226,9 +201,27 @@ public abstract class AbstractHttpMessageConverter implements HttpMessageConv return null; } + + /** + * Indicates whether the given class is supported by this converter. + * @param clazz the class to test for support + * @return true if supported; false 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 clazz, HttpInputMessage inputMessage) + throws IOException, HttpMessageNotReadableException; + /** * Abstract template method that writes the actual body. Invoked from {@link #write}. - * * @param t the object to write to the output message * @param outputMessage the message to write to * @throws IOException in case of I/O errors diff --git a/org.springframework.web/src/main/java/org/springframework/http/converter/BufferedImageHttpMessageConverter.java b/org.springframework.web/src/main/java/org/springframework/http/converter/BufferedImageHttpMessageConverter.java index 838a7c6f80b..b9392d0d95d 100644 --- a/org.springframework.web/src/main/java/org/springframework/http/converter/BufferedImageHttpMessageConverter.java +++ b/org.springframework.web/src/main/java/org/springframework/http/converter/BufferedImageHttpMessageConverter.java @@ -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"); * 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 { - private List readableMediaTypes = new ArrayList(); + private final List readableMediaTypes = new ArrayList(); private MediaType defaultContentType; private File cacheDir; + public BufferedImageHttpMessageConverter() { String[] readerMediaTypes = ImageIO.getReaderMIMETypes(); for (String mediaType : readerMediaTypes) { - readableMediaTypes.add(MediaType.parseMediaType(mediaType)); + this.readableMediaTypes.add(MediaType.parseMediaType(mediaType)); } String[] writerMediaTypes = ImageIO.getWriterMIMETypes(); 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. - * * @throws IllegalArgumentException if the given content type is not supported by the Java Image I/O API */ public void setDefaultContentType(MediaType defaultContentType) { @@ -106,20 +96,27 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter clazz, MediaType mediaType) { - if (BufferedImage.class.equals(clazz)) { - return isReadable(mediaType); - } - else { - return false; - } + return (BufferedImage.class.equals(clazz) && isReadable(mediaType)); } private boolean isReadable(MediaType mediaType) { @@ -131,12 +128,7 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter clazz, MediaType mediaType) { - if (BufferedImage.class.equals(clazz)) { - return isWritable(mediaType); - } - else { - return false; - } + return (BufferedImage.class.equals(clazz) && isWritable(mediaType)); } private boolean isWritable(MediaType mediaType) { @@ -148,11 +140,12 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter getSupportedMediaTypes() { - return Collections.unmodifiableList(readableMediaTypes); + return Collections.unmodifiableList(this.readableMediaTypes); } - public BufferedImage read(Class clazz, HttpInputMessage inputMessage) + public BufferedImage read(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { + ImageInputStream imageInputStream = null; ImageReader imageReader = null; try { @@ -187,7 +180,7 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverterDefault implementation is empty. */ protected void process(ImageReadParam irp) { @@ -254,9 +248,9 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverterDefault implementation is empty. */ protected void process(ImageWriteParam iwp) { } + } diff --git a/org.springframework.web/src/main/java/org/springframework/http/converter/ByteArrayHttpMessageConverter.java b/org.springframework.web/src/main/java/org/springframework/http/converter/ByteArrayHttpMessageConverter.java index d113e07f042..93517ea81e1 100644 --- a/org.springframework.web/src/main/java/org/springframework/http/converter/ByteArrayHttpMessageConverter.java +++ b/org.springframework.web/src/main/java/org/springframework/http/converter/ByteArrayHttpMessageConverter.java @@ -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"); * you may not use this file except in compliance with the License. @@ -47,7 +47,7 @@ public class ByteArrayHttpMessageConverter extends AbstractHttpMessageConverter< } @Override - public byte[] readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException { + public byte[] readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException { long contentLength = inputMessage.getHeaders().getContentLength(); if (contentLength >= 0) { ByteArrayOutputStream bos = new ByteArrayOutputStream((int) contentLength); diff --git a/org.springframework.web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java b/org.springframework.web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java index c9b17a7ab5e..f042d82d512 100644 --- a/org.springframework.web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java +++ b/org.springframework.web/src/main/java/org/springframework/http/converter/FormHttpMessageConverter.java @@ -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"); * you may not use this file except in compliance with the License. @@ -50,19 +50,20 @@ public class FormHttpMessageConverter extends AbstractHttpMessageConverter clazz) { return MultiValueMap.class.isAssignableFrom(clazz); } @Override - public MultiValueMap readInternal(Class> clazz, - HttpInputMessage inputMessage) throws IOException { + public MultiValueMap readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException { MediaType contentType = inputMessage.getHeaders().getContentType(); Charset charset = contentType.getCharSet() != null ? contentType.getCharSet() : DEFAULT_CHARSET; String body = FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset)); @@ -112,4 +113,5 @@ public class FormHttpMessageConverter extends AbstractHttpMessageConverter { @@ -55,23 +56,24 @@ public interface HttpMessageConverter { /** * 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 - * canRead} method of this interface, which must have returned {@code true}. + * @param clazz the type of object to return. This type must have previously been passed to the + * {@link #canRead canRead} method of this interface, which must have returned {@code true}. * @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 */ - T read(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException; + T read(Class clazz, HttpInputMessage inputMessage) + throws IOException, HttpMessageNotReadableException; /** * 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 passed to the - * {@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 the default - * content type of the converter must be used. If not {@code null}, this media type must have previously been passed to - * the {@link #canWrite canWrite} method of this interface, which must have returned {@code true}. + * @param t the object to write to the output message. The type of this object must have previously been + * passed to the {@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 + * default content type of the converter must be used. If not {@code null}, this media type must have + * previously been passed to the {@link #canWrite canWrite} method of this interface, which must have + * returned {@code true}. * @param outputMessage the message to write to * @throws IOException in case of I/O errors * @throws HttpMessageNotWritableException in case of conversion errors diff --git a/org.springframework.web/src/main/java/org/springframework/http/converter/StringHttpMessageConverter.java b/org.springframework.web/src/main/java/org/springframework/http/converter/StringHttpMessageConverter.java index 842479a3479..a71c88ce3e4 100644 --- a/org.springframework.web/src/main/java/org/springframework/http/converter/StringHttpMessageConverter.java +++ b/org.springframework.web/src/main/java/org/springframework/http/converter/StringHttpMessageConverter.java @@ -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"); * you may not use this file except in compliance with the License. @@ -56,7 +56,7 @@ public class StringHttpMessageConverter extends AbstractHttpMessageConverter clazz, HttpInputMessage inputMessage) throws IOException { + protected String readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException { MediaType contentType = inputMessage.getHeaders().getContentType(); Charset charset = contentType.getCharSet() != null ? contentType.getCharSet() : DEFAULT_CHARSET; return FileCopyUtils.copyToString(new InputStreamReader(inputMessage.getBody(), charset)); diff --git a/org.springframework.web/src/main/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverter.java b/org.springframework.web/src/main/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverter.java index c8ce393d905..00635716e07 100644 --- a/org.springframework.web/src/main/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverter.java +++ b/org.springframework.web/src/main/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverter.java @@ -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"); * 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; /** - * Implementation of {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverter} that can read - * and write JSON using Jackson's {@link ObjectMapper}. + * Implementation of {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverter} + * that can read and write JSON using Jackson's {@link ObjectMapper}. * *

This converter can be used to bind to typed beans, or untyped {@link java.util.HashMap HashMap} instances. * - *

By default, this converter supports {@code application/json}. This can be overridden by setting the {@link - * #setSupportedMediaTypes(List) supportedMediaTypes} property. - * method. + *

By default, this converter supports {@code application/json}. This can be overridden by setting the + * {@link #setSupportedMediaTypes(List) supportedMediaTypes} property. * * @author Arjen Poutsma - * @see org.springframework.web.servlet.view.json.BindingJacksonJsonView * @since 3.0 + * @see org.springframework.web.servlet.view.json.BindingJacksonJsonView */ public class MappingJacksonHttpMessageConverter extends AbstractHttpMessageConverter { @@ -56,15 +55,17 @@ public class MappingJacksonHttpMessageConverter extends AbstractHttpMessageConve private boolean prefixJson = false; - /** Construct a new {@code BindingJacksonHttpMessageConverter}, */ + + /** + * Construct a new {@code BindingJacksonHttpMessageConverter}. + */ public MappingJacksonHttpMessageConverter() { super(new MediaType("application", "json", DEFAULT_CHARSET)); } /** - * Sets the {@code ObjectMapper} for this view. If not set, a default {@link ObjectMapper#ObjectMapper() ObjectMapper} - * is used. - * + * Sets the {@code ObjectMapper} for this view. If not set, a default + * {@link ObjectMapper#ObjectMapper() ObjectMapper} is used. *

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 * 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. - * *

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, * 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; } + @Override public boolean canRead(Class clazz, MediaType mediaType) { JavaType javaType = TypeFactory.fromClass(clazz); - return objectMapper.canDeserialize(javaType) && canRead(mediaType); + return this.objectMapper.canDeserialize(javaType) && canRead(mediaType); } @Override public boolean canWrite(Class clazz, MediaType mediaType) { - return objectMapper.canSerialize(clazz) && canWrite(mediaType); + return this.objectMapper.canSerialize(clazz) && canWrite(mediaType); } @Override 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(); } @Override - protected Object readInternal(Class clazz, HttpInputMessage inputMessage) + protected Object readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { - return objectMapper.readValue(inputMessage.getBody(), clazz); + + return this.objectMapper.readValue(inputMessage.getBody(), clazz); } @Override protected void writeInternal(Object o, HttpOutputMessage outputMessage) throws IOException, HttpMessageNotWritableException { + JsonEncoding encoding = getEncoding(outputMessage.getHeaders().getContentType()); JsonGenerator jsonGenerator = - objectMapper.getJsonFactory().createJsonGenerator(outputMessage.getBody(), encoding); - if (prefixJson) { + this.objectMapper.getJsonFactory().createJsonGenerator(outputMessage.getBody(), encoding); + if (this.prefixJson) { jsonGenerator.writeRaw("{} && "); } - objectMapper.writeValue(jsonGenerator, o); + this.objectMapper.writeValue(jsonGenerator, o); } private JsonEncoding getEncoding(MediaType contentType) { diff --git a/org.springframework.web/src/main/java/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java b/org.springframework.web/src/main/java/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java index fea5c9650a9..bdb3c351d9d 100644 --- a/org.springframework.web/src/main/java/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java +++ b/org.springframework.web/src/main/java/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java @@ -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"); * 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 javax.xml.transform.Result; import javax.xml.transform.Source; -import javax.xml.transform.Transformer; import javax.xml.transform.TransformerException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.stream.StreamResult; @@ -33,8 +32,8 @@ import org.springframework.http.converter.AbstractHttpMessageConverter; import org.springframework.http.converter.HttpMessageConversionException; /** - * Abstract base class for {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverters} that - * convert from/to XML. + * Abstract base class for {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverters} + * that convert from/to XML. * *

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) @@ -47,58 +46,58 @@ public abstract class AbstractXmlHttpMessageConverter extends AbstractHttpMes private final TransformerFactory transformerFactory = TransformerFactory.newInstance(); + /** - * Protected constructor that sets the {@link #setSupportedMediaTypes(java.util.List) supportedMediaTypes} to {@code - * text/xml} and {@code application/xml}, and {@code application/*-xml}. + * Protected constructor that sets the {@link #setSupportedMediaTypes(java.util.List) supportedMediaTypes} + * to {@code text/xml} and {@code application/xml}, and {@code application/*-xml}. */ protected AbstractXmlHttpMessageConverter() { super(new MediaType("application", "xml"), new MediaType("text", "xml"), new MediaType("application", "*+xml")); } - /** Invokes {@link #readFromSource(Class, HttpHeaders, Source)}. */ + @Override - public final T readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException { + public final T readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException { 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 clazz, HttpHeaders headers, Source source) throws IOException; - @Override protected final void writeInternal(T t, HttpOutputMessage outputMessage) throws IOException { 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 clazz, HttpHeaders headers, Source source) + throws IOException; + /** * Abstract template method called from {@link #writeInternal(Object, HttpOutputMessage)}. - * * @param t the object to write to the output message * @param headers the HTTP output headers * @param result the HTTP output body * @throws IOException in case of I/O errors * @throws HttpMessageConversionException in case of conversion errors */ - 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); - } + protected abstract void writeToResult(T t, HttpHeaders headers, Result result) + throws IOException; } diff --git a/org.springframework.web/src/main/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverter.java b/org.springframework.web/src/main/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverter.java index 8eb0fbfb4c2..89d5bd0bd2f 100644 --- a/org.springframework.web/src/main/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverter.java +++ b/org.springframework.web/src/main/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverter.java @@ -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"); * you may not use this file except in compliance with the License. @@ -67,14 +67,14 @@ public class Jaxb2RootElementHttpMessageConverter extends AbstractJaxb2HttpMessa } @Override - protected Object readFromSource(Class clazz, HttpHeaders headers, Source source) throws IOException { + protected Object readFromSource(Class clazz, HttpHeaders headers, Source source) throws IOException { try { Unmarshaller unmarshaller = createUnmarshaller(clazz); if (clazz.isAnnotationPresent(XmlRootElement.class)) { return unmarshaller.unmarshal(source); } else { - JAXBElement jaxbElement = unmarshaller.unmarshal(source, clazz); + JAXBElement jaxbElement = unmarshaller.unmarshal(source, clazz); return jaxbElement.getValue(); } } diff --git a/org.springframework.web/src/main/java/org/springframework/http/converter/xml/MarshallingHttpMessageConverter.java b/org.springframework.web/src/main/java/org/springframework/http/converter/xml/MarshallingHttpMessageConverter.java index ff319965ae9..97770b6e68e 100644 --- a/org.springframework.web/src/main/java/org/springframework/http/converter/xml/MarshallingHttpMessageConverter.java +++ b/org.springframework.web/src/main/java/org/springframework/http/converter/xml/MarshallingHttpMessageConverter.java @@ -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"); * you may not use this file except in compliance with the License. @@ -49,6 +49,7 @@ public class MarshallingHttpMessageConverter extends AbstractXmlHttpMessageConve private Unmarshaller unmarshaller; + /** * 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 @@ -62,7 +63,6 @@ public class MarshallingHttpMessageConverter extends AbstractXmlHttpMessageConve * Marshaller} also implements the {@link Unmarshaller} interface, it is used for both marshalling and unmarshalling. * Otherwise, an exception is thrown.

Note that all {@code Marshaller} implementations in Spring also implement the * {@code Unmarshaller} interface, so that you can safely use this constructor. - * * @param marshaller object used as marshaller and unmarshaller */ public MarshallingHttpMessageConverter(Marshaller marshaller) { @@ -76,7 +76,6 @@ public class MarshallingHttpMessageConverter extends AbstractXmlHttpMessageConve /** * Construct a new MarshallingMessageConverter with the given {@code Marshaller} and {@code * Unmarshaller}. - * * @param marshaller the Marshaller to use * @param unmarshaller the Unmarshaller to use */ @@ -87,26 +86,31 @@ public class MarshallingHttpMessageConverter extends AbstractXmlHttpMessageConve 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) { 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) { this.unmarshaller = unmarshaller; } + @Override public boolean supports(Class clazz) { - return unmarshaller.supports(clazz); + return this.unmarshaller.supports(clazz); } @Override - protected Object readFromSource(Class 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"); try { - return unmarshaller.unmarshal(source); + return this.unmarshaller.unmarshal(source); } catch (UnmarshallingFailureException 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 { Assert.notNull(this.marshaller, "Property 'marshaller' is required"); try { - marshaller.marshal(o, result); + this.marshaller.marshal(o, result); } catch (MarshallingFailureException ex) { throw new HttpMessageNotWritableException("Could not write [" + o + "]", ex); } } + } diff --git a/org.springframework.web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java b/org.springframework.web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java index 7d25f34c92b..4ba1aacfee8 100644 --- a/org.springframework.web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java +++ b/org.springframework.web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java @@ -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"); * 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; /** - * Implementation of {@link org.springframework.http.converter.HttpMessageConverter} that can read and write {@link - * Source} objects. + * Implementation of {@link org.springframework.http.converter.HttpMessageConverter} + * that can read and write {@link Source} objects. * * @author Arjen Poutsma * @since 3.0 @@ -52,7 +52,7 @@ public class SourceHttpMessageConverter extends AbstractXmlHtt @Override @SuppressWarnings("unchecked") - protected T readFromSource(Class clazz, HttpHeaders headers, Source source) throws IOException { + protected T readFromSource(Class clazz, HttpHeaders headers, Source source) throws IOException { try { if (DOMSource.class.equals(clazz)) { DOMResult domResult = new DOMResult(); @@ -93,4 +93,5 @@ public class SourceHttpMessageConverter extends AbstractXmlHtt throw new HttpMessageNotWritableException("Could not transform [" + t + "] to [" + result + "]", ex); } } + } diff --git a/org.springframework.web/src/test/java/org/springframework/http/converter/HttpMessageConverterTests.java b/org.springframework.web/src/test/java/org/springframework/http/converter/HttpMessageConverterTests.java index 1332c9ae486..0de4c197367 100644 --- a/org.springframework.web/src/test/java/org/springframework/http/converter/HttpMessageConverterTests.java +++ b/org.springframework.web/src/test/java/org/springframework/http/converter/HttpMessageConverterTests.java @@ -17,10 +17,17 @@ package org.springframework.http.converter; 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 org.junit.Test; import org.springframework.http.HttpInputMessage; import org.springframework.http.HttpOutputMessage; @@ -79,7 +86,7 @@ public class HttpMessageConverterTests { } @Override - protected T readInternal(Class clazz, HttpInputMessage inputMessage) + protected T readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { fail("Not expected"); return null; @@ -95,4 +102,5 @@ public class HttpMessageConverterTests { private static class MyType { } + } diff --git a/org.springframework.web/src/test/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverterTests.java b/org.springframework.web/src/test/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverterTests.java index 1fd36ee12ec..32fb7fd3b16 100644 --- a/org.springframework.web/src/test/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverterTests.java +++ b/org.springframework.web/src/test/java/org/springframework/http/converter/json/MappingJacksonHttpMessageConverterTests.java @@ -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"); * 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.MockHttpOutputMessage; -/** @author Arjen Poutsma */ +/** + * @author Arjen Poutsma + */ public class MappingJacksonHttpMessageConverterTests { private MappingJacksonHttpMessageConverter converter; @@ -60,7 +62,7 @@ public class MappingJacksonHttpMessageConverterTests { "{\"bytes\":\"AQI=\",\"array\":[\"Foo\",\"Bar\"],\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}"; MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8")); 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(42, result.getNumber()); 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}"; MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8")); inputMessage.getHeaders().setContentType(new MediaType("application", "json")); - HashMap result = (HashMap) converter.read((Class)HashMap.class, inputMessage); + HashMap result = (HashMap) converter.read(HashMap.class, inputMessage); assertEquals("Foo", result.get("string")); assertEquals(42, result.get("number")); assertEquals(42D, (Double) result.get("fraction"), 0D);