From d879bad2481c2207f13defc9fc6fdd87bcd682b8 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Fri, 6 Mar 2015 23:47:54 +0100 Subject: [PATCH] Polishing (cherry picked from commit 7ed7f98) --- .../config/PropertyPlaceholderConfigurer.java | 5 +- .../context/annotation/Role.java | 18 +-- .../annotation/ProxyAsyncConfiguration.java | 2 +- .../springframework/util/CollectionUtils.java | 42 +++--- .../org/springframework/tests/TestGroup.java | 5 +- .../oxm/castor/CastorMarshallerTests.java | 66 +++++----- .../oxm/castor/CastorUnmarshallerTests.java | 121 +++++++++--------- .../web/bind/annotation/RequestBody.java | 5 +- .../RequestResponseBodyMethodProcessor.java | 8 +- ...questResponseBodyMethodProcessorTests.java | 38 +++--- 10 files changed, 154 insertions(+), 156 deletions(-) diff --git a/spring-beans/src/main/java/org/springframework/beans/factory/config/PropertyPlaceholderConfigurer.java b/spring-beans/src/main/java/org/springframework/beans/factory/config/PropertyPlaceholderConfigurer.java index 57e6800ac7..b51694ffa5 100644 --- a/spring-beans/src/main/java/org/springframework/beans/factory/config/PropertyPlaceholderConfigurer.java +++ b/spring-beans/src/main/java/org/springframework/beans/factory/config/PropertyPlaceholderConfigurer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2015 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. @@ -219,8 +219,7 @@ public class PropertyPlaceholderConfigurer extends PlaceholderConfigurerSupport throws BeansException { StringValueResolver valueResolver = new PlaceholderResolvingStringValueResolver(props); - - this.doProcessProperties(beanFactoryToProcess, valueResolver); + doProcessProperties(beanFactoryToProcess, valueResolver); } /** diff --git a/spring-context/src/main/java/org/springframework/context/annotation/Role.java b/spring-context/src/main/java/org/springframework/context/annotation/Role.java index 3abdca32b1..f8dc81ca6d 100644 --- a/spring-context/src/main/java/org/springframework/context/annotation/Role.java +++ b/spring-context/src/main/java/org/springframework/context/annotation/Role.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2015 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. @@ -28,16 +28,16 @@ import org.springframework.beans.factory.config.BeanDefinition; * Indicates the 'role' hint for a given bean. * *

May be used on any class directly or indirectly annotated with - * {@link org.springframework.stereotype.Component} or on methods annotated with - * {@link Bean}. + * {@link org.springframework.stereotype.Component} or on methods + * annotated with {@link Bean}. * - *

If this annotation is not present on a Component or Bean definition, the - * default value of {@link BeanDefinition#ROLE_APPLICATION} will apply. + *

If this annotation is not present on a Component or Bean definition, + * the default value of {@link BeanDefinition#ROLE_APPLICATION} will apply. * - *

If Role is present on a {@link Configuration @Configuration} class, this - * indicates the role of the configuration class bean definition and does not - * cascade to all @{@code Bean} methods defined within. This behavior is - * different than that of the @{@link Lazy} annotation, for example. + *

If Role is present on a {@link Configuration @Configuration} class, + * this indicates the role of the configuration class bean definition and + * does not cascade to all @{@code Bean} methods defined within. This behavior + * is different than that of the @{@link Lazy} annotation, for example. * * @author Chris Beams * @since 3.1 diff --git a/spring-context/src/main/java/org/springframework/scheduling/annotation/ProxyAsyncConfiguration.java b/spring-context/src/main/java/org/springframework/scheduling/annotation/ProxyAsyncConfiguration.java index 2ca230a1d5..ce8b2c9c85 100644 --- a/spring-context/src/main/java/org/springframework/scheduling/annotation/ProxyAsyncConfiguration.java +++ b/spring-context/src/main/java/org/springframework/scheduling/annotation/ProxyAsyncConfiguration.java @@ -43,7 +43,7 @@ public class ProxyAsyncConfiguration extends AbstractAsyncConfiguration { public AsyncAnnotationBeanPostProcessor asyncAdvisor() { Assert.notNull(this.enableAsync, "@EnableAsync annotation metadata was not injected"); AsyncAnnotationBeanPostProcessor bpp = new AsyncAnnotationBeanPostProcessor(); - Class customAsyncAnnotation = enableAsync.getClass("annotation"); + Class customAsyncAnnotation = this.enableAsync.getClass("annotation"); if (customAsyncAnnotation != AnnotationUtils.getDefaultValue(EnableAsync.class, "annotation")) { bpp.setAsyncAnnotationType(customAsyncAnnotation); } diff --git a/spring-core/src/main/java/org/springframework/util/CollectionUtils.java b/spring-core/src/main/java/org/springframework/util/CollectionUtils.java index 5e74473fa9..dcc3a4858e 100644 --- a/spring-core/src/main/java/org/springframework/util/CollectionUtils.java +++ b/spring-core/src/main/java/org/springframework/util/CollectionUtils.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,8 +42,8 @@ import java.util.Set; public abstract class CollectionUtils { /** - * Return {@code true} if the supplied Collection is {@code null} - * or empty. Otherwise, return {@code false}. + * Return {@code true} if the supplied Collection is {@code null} or empty. + * Otherwise, return {@code false}. * @param collection the Collection to check * @return whether the given Collection is empty */ @@ -52,8 +52,8 @@ public abstract class CollectionUtils { } /** - * Return {@code true} if the supplied Map is {@code null} - * or empty. Otherwise, return {@code false}. + * Return {@code true} if the supplied Map is {@code null} or empty. + * Otherwise, return {@code false}. * @param map the Map to check * @return whether the given Map is empty */ @@ -62,13 +62,16 @@ public abstract class CollectionUtils { } /** - * Convert the supplied array into a List. A primitive array gets - * converted into a List of the appropriate wrapper type. - *

A {@code null} source value will be converted to an - * empty List. + * Convert the supplied array into a List. A primitive array gets converted + * into a List of the appropriate wrapper type. + *

NOTE: Generally prefer the standard {@link Arrays#asList} method. + * This {@code arrayToList} method is just meant to deal with an incoming Object + * value that might be an {@code Object[]} or a primitive array at runtime. + *

A {@code null} source value will be converted to an empty List. * @param source the (potentially primitive) array * @return the converted List result * @see ObjectUtils#toObjectArray(Object) + * @see Arrays#asList(Object[]) */ public static List arrayToList(Object source) { return Arrays.asList(ObjectUtils.toObjectArray(source)); @@ -312,7 +315,7 @@ public abstract class CollectionUtils { * Enumeration elements must be assignable to the type of the given array. The array * returned will be a different instance than the array given. */ - public static A[] toArray(Enumeration enumeration, A[] array) { + public static A[] toArray(Enumeration enumeration, A[] array) { ArrayList elements = new ArrayList(); while (enumeration.hasMoreElements()) { elements.add(enumeration.nextElement()); @@ -330,10 +333,10 @@ public abstract class CollectionUtils { } /** - * Adapts a {@code Map>} to an {@code MultiValueMap}. - * - * @param map the map + * Adapt a {@code Map>} to an {@code MultiValueMap}. + * @param map the original map * @return the multi-value map + * @since 3.1 */ public static MultiValueMap toMultiValueMap(Map> map) { return new MultiValueMapAdapter(map); @@ -341,12 +344,12 @@ public abstract class CollectionUtils { } /** - * Returns an unmodifiable view of the specified multi-value map. - * + * Return an unmodifiable view of the specified multi-value map. * @param map the map for which an unmodifiable view is to be returned. * @return an unmodifiable view of the specified multi-value map. + * @since 3.1 */ - public static MultiValueMap unmodifiableMultiValueMap(MultiValueMap map) { + public static MultiValueMap unmodifiableMultiValueMap(MultiValueMap map) { Assert.notNull(map, "'map' must not be null"); Map> result = new LinkedHashMap>(map.size()); for (Map.Entry> entry : map.entrySet()) { @@ -358,13 +361,12 @@ public abstract class CollectionUtils { } - /** * Iterator wrapping an Enumeration. */ private static class EnumerationIterator implements Iterator { - private Enumeration enumeration; + private final Enumeration enumeration; public EnumerationIterator(Enumeration enumeration) { this.enumeration = enumeration; @@ -458,8 +460,8 @@ public abstract class CollectionUtils { return this.map.remove(key); } - public void putAll(Map> m) { - this.map.putAll(m); + public void putAll(Map> map) { + this.map.putAll(map); } public void clear() { diff --git a/spring-core/src/test/java/org/springframework/tests/TestGroup.java b/spring-core/src/test/java/org/springframework/tests/TestGroup.java index c135e8e68a..285341ef96 100644 --- a/spring-core/src/test/java/org/springframework/tests/TestGroup.java +++ b/spring-core/src/test/java/org/springframework/tests/TestGroup.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2015 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,7 +34,6 @@ import static java.lang.String.*; */ public enum TestGroup { - /** * Tests that take a considerable amount of time to run. Any test lasting longer than * 500ms should be considered a candidate in order to avoid making the overall test @@ -68,6 +67,7 @@ public enum TestGroup { */ CUSTOM_COMPILATION; + /** * Parse the specified comma separates string of groups. * @param value the comma separated string of groups @@ -93,4 +93,5 @@ public enum TestGroup { } return groups; } + } diff --git a/spring-oxm/src/test/java/org/springframework/oxm/castor/CastorMarshallerTests.java b/spring-oxm/src/test/java/org/springframework/oxm/castor/CastorMarshallerTests.java index 8178d70452..61ade3e367 100644 --- a/spring-oxm/src/test/java/org/springframework/oxm/castor/CastorMarshallerTests.java +++ b/spring-oxm/src/test/java/org/springframework/oxm/castor/CastorMarshallerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2013 the original author or authors. + * Copyright 2002-2015 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. @@ -20,7 +20,6 @@ import java.io.StringWriter; import java.util.Arrays; import java.util.HashMap; import java.util.Map; - import javax.xml.transform.sax.SAXResult; import javax.xml.transform.stream.StreamResult; @@ -28,21 +27,24 @@ import org.custommonkey.xmlunit.NamespaceContext; import org.custommonkey.xmlunit.SimpleNamespaceContext; import org.custommonkey.xmlunit.XMLUnit; import org.custommonkey.xmlunit.XpathEngine; -import org.junit.Assert; import org.junit.Test; import org.mockito.InOrder; -import org.springframework.core.io.ClassPathResource; -import org.springframework.oxm.AbstractMarshallerTests; -import org.springframework.oxm.Marshaller; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.Attributes; import org.xml.sax.ContentHandler; -import static org.custommonkey.xmlunit.XMLAssert.assertXMLEqual; -import static org.junit.Assert.*; -import static org.mockito.Matchers.*; +import org.springframework.core.io.ClassPathResource; +import org.springframework.oxm.AbstractMarshallerTests; +import org.springframework.oxm.Marshaller; + +import static org.custommonkey.xmlunit.XMLAssert.*; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertTrue; import static org.mockito.BDDMockito.*; +import static org.mockito.Matchers.eq; +import static org.mockito.Matchers.isA; /** * Tests the {@link CastorMarshaller} class. @@ -77,6 +79,7 @@ public class CastorMarshallerTests extends AbstractMarshallerTests { */ private static final String XSI_EXPECTED_STRING = "" + "" + "test8"; @@ -91,6 +94,7 @@ public class CastorMarshallerTests extends AbstractMarshallerTests { */ private static final String ROOT_WITH_XSI_EXPECTED_STRING = "" + "" + "" + "test8"; @@ -100,9 +104,11 @@ public class CastorMarshallerTests extends AbstractMarshallerTests { */ private static final String ROOT_WITHOUT_XSI_EXPECTED_STRING = "" + "" + "test8"; + @Override protected Marshaller createMarshaller() throws Exception { CastorMarshaller marshaller = new CastorMarshaller(); @@ -121,6 +127,7 @@ public class CastorMarshallerTests extends AbstractMarshallerTests { return flights; } + @Test public void marshalSaxResult() throws Exception { ContentHandler contentHandler = mock(ContentHandler.class); @@ -129,9 +136,12 @@ public class CastorMarshallerTests extends AbstractMarshallerTests { InOrder ordered = inOrder(contentHandler); ordered.verify(contentHandler).startDocument(); ordered.verify(contentHandler).startPrefixMapping("tns", "http://samples.springframework.org/flight"); - ordered.verify(contentHandler).startElement(eq("http://samples.springframework.org/flight"), eq("flights"), eq("tns:flights"), isA(Attributes.class)); - ordered.verify(contentHandler).startElement(eq("http://samples.springframework.org/flight"), eq("flight"), eq("tns:flight"), isA(Attributes.class)); - ordered.verify(contentHandler).startElement(eq("http://samples.springframework.org/flight"), eq("number"), eq("tns:number"), isA(Attributes.class)); + ordered.verify(contentHandler).startElement(eq("http://samples.springframework.org/flight"), + eq("flights"), eq("tns:flights"), isA(Attributes.class)); + ordered.verify(contentHandler).startElement(eq("http://samples.springframework.org/flight"), + eq("flight"), eq("tns:flight"), isA(Attributes.class)); + ordered.verify(contentHandler).startElement(eq("http://samples.springframework.org/flight"), + eq("number"), eq("tns:number"), isA(Attributes.class)); ordered.verify(contentHandler).characters(eq(new char[]{'4', '2'}), eq(0), eq(2)); ordered.verify(contentHandler).endElement("http://samples.springframework.org/flight", "number", "tns:number"); ordered.verify(contentHandler).endElement("http://samples.springframework.org/flight", "flight", "tns:flight"); @@ -142,8 +152,8 @@ public class CastorMarshallerTests extends AbstractMarshallerTests { @Test public void supports() throws Exception { - Assert.assertTrue("CastorMarshaller does not support Flights", marshaller.supports(Flights.class)); - Assert.assertTrue("CastorMarshaller does not support Flight", marshaller.supports(Flight.class)); + assertTrue("CastorMarshaller does not support Flights", marshaller.supports(Flights.class)); + assertTrue("CastorMarshaller does not support Flight", marshaller.supports(Flight.class)); } @Test @@ -163,7 +173,6 @@ public class CastorMarshallerTests extends AbstractMarshallerTests { @Test public void testSuppressXsiTypeTrue() throws Exception { CastorObject castorObject = createCastorObject(); - getCastorMarshaller().setSuppressXsiType(true); getCastorMarshaller().setRootElement("objects"); String result = marshal(Arrays.asList(castorObject)); @@ -173,7 +182,6 @@ public class CastorMarshallerTests extends AbstractMarshallerTests { @Test public void testSuppressXsiTypeFalse() throws Exception { CastorObject castorObject = createCastorObject(); - getCastorMarshaller().setSuppressXsiType(false); getCastorMarshaller().setRootElement("objects"); String result = marshal(Arrays.asList(castorObject)); @@ -182,26 +190,23 @@ public class CastorMarshallerTests extends AbstractMarshallerTests { @Test public void testMarshalAsDocumentTrue() throws Exception { - getCastorMarshaller().setMarshalAsDocument(true); String result = marshalFlights(); assertXMLEqual("Marshaller wrote invalid result", DOCUMENT_EXPECTED_STRING, result); - Assert.assertTrue("Result doesn't contain xml declaration.", + assertTrue("Result doesn't contain xml declaration.", result.contains("")); } @Test public void testMarshalAsDocumentFalse() throws Exception { - getCastorMarshaller().setMarshalAsDocument(true); String result = marshalFlights(); assertXMLEqual("Marshaller wrote invalid result", EXPECTED_STRING, result); - Assert.assertFalse("Result contains xml declaration.", result.matches("<\\?\\s*xml")); + assertFalse("Result contains xml declaration.", result.matches("<\\?\\s*xml")); } @Test public void testRootElement() throws Exception { - getCastorMarshaller().setRootElement("canceledFlights"); String result = marshalFlights(); assertXMLEqual("Marshaller wrote invalid result", ROOT_ELEMENT_EXPECTED_STRING, result); @@ -210,10 +215,8 @@ public class CastorMarshallerTests extends AbstractMarshallerTests { @Test public void testNoNamespaceSchemaLocation() throws Exception { String noNamespaceSchemaLocation = "flights.xsd"; - getCastorMarshaller().setNoNamespaceSchemaLocation(noNamespaceSchemaLocation); String result = marshalFlights(); - assertXpathEvaluatesTo("The xsi:noNamespaceSchemaLocation hasn't been written or has invalid value.", noNamespaceSchemaLocation, "/tns:flights/@xsi:noNamespaceSchemaLocation", result); assertXMLEqual("Marshaller wrote invalid result", EXPECTED_STRING, result); @@ -222,10 +225,8 @@ public class CastorMarshallerTests extends AbstractMarshallerTests { @Test public void testSchemaLocation() throws Exception { String schemaLocation = "flights.xsd"; - getCastorMarshaller().setSchemaLocation(schemaLocation); String result = marshalFlights(); - assertXpathEvaluatesTo("The xsi:noNamespaceSchemaLocation hasn't been written or has invalid value.", schemaLocation, "/tns:flights/@xsi:schemaLocation", result); assertXMLEqual("Marshaller wrote invalid result", EXPECTED_STRING, result); @@ -234,7 +235,6 @@ public class CastorMarshallerTests extends AbstractMarshallerTests { @Test public void testUseXsiTypeAsRootTrue() throws Exception { CastorObject castorObject = createCastorObject(); - getCastorMarshaller().setSuppressXsiType(false); getCastorMarshaller().setUseXSITypeAtRoot(true); getCastorMarshaller().setRootElement("objects"); @@ -245,7 +245,6 @@ public class CastorMarshallerTests extends AbstractMarshallerTests { @Test public void testUseXsiTypeAsRootFalse() throws Exception { CastorObject castorObject = createCastorObject(); - getCastorMarshaller().setSuppressXsiType(false); getCastorMarshaller().setUseXSITypeAtRoot(false); getCastorMarshaller().setRootElement("objects"); @@ -259,11 +258,9 @@ public class CastorMarshallerTests extends AbstractMarshallerTests { } private String marshal(Object object) throws Exception { - StringWriter writer = new StringWriter(); StreamResult result = new StreamResult(writer); getCastorMarshaller().marshal(object, result); - return writer.toString(); } @@ -272,9 +269,9 @@ public class CastorMarshallerTests extends AbstractMarshallerTests { } /** - * Asserts the values of xpath expression evaluation is exactly the same as expected value.

The xpath may contain - * the xml namespace prefixes, since namespaces from flight example are being registered. - * + * Assert the values of xpath expression evaluation is exactly the same as expected value. + *

The xpath may contain the xml namespace prefixes, since namespaces from flight example + * are being registered. * @param msg the error message that will be used in case of test failure * @param expected the expected value * @param xpath the xpath to evaluate @@ -296,9 +293,7 @@ public class CastorMarshallerTests extends AbstractMarshallerTests { } /** - * Creates a instance of {@link CastorObject} for testing. - * - * @return a instance of {@link CastorObject} + * Create an instance of {@link CastorObject} for testing. */ private CastorObject createCastorObject() { CastorObject castorObject = new CastorObject(); @@ -306,4 +301,5 @@ public class CastorMarshallerTests extends AbstractMarshallerTests { castorObject.setValue(8); return castorObject; } + } diff --git a/spring-oxm/src/test/java/org/springframework/oxm/castor/CastorUnmarshallerTests.java b/spring-oxm/src/test/java/org/springframework/oxm/castor/CastorUnmarshallerTests.java index 8d32deb901..374df68faa 100644 --- a/spring-oxm/src/test/java/org/springframework/oxm/castor/CastorUnmarshallerTests.java +++ b/spring-oxm/src/test/java/org/springframework/oxm/castor/CastorUnmarshallerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -25,13 +25,13 @@ import javax.xml.transform.stream.StreamSource; import org.junit.Ignore; import org.junit.Test; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; import org.springframework.core.io.ClassPathResource; import org.springframework.oxm.AbstractUnmarshallerTests; import org.springframework.oxm.MarshallingException; import org.springframework.oxm.Unmarshaller; -import org.xml.sax.InputSource; -import org.xml.sax.XMLReader; import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; @@ -47,15 +47,16 @@ public class CastorUnmarshallerTests extends AbstractUnmarshallerTests { */ protected static final String EXTRA_ATTRIBUTES_STRING = "" + - "42"; + "42"; /** * Represents the xml with additional element that is not mapped in Castor config. */ protected static final String EXTRA_ELEMENTS_STRING = "" + - "422011-06-14" + - ""; + "422011-06-14" + + ""; + @Override protected void testFlights(Object o) { @@ -81,6 +82,7 @@ public class CastorUnmarshallerTests extends AbstractUnmarshallerTests { return marshaller; } + @Test public void unmarshalTargetClass() throws Exception { CastorMarshaller unmarshaller = new CastorMarshaller(); @@ -136,7 +138,6 @@ public class CastorUnmarshallerTests extends AbstractUnmarshallerTests { @Test(expected = MarshallingException.class) public void testIgnoreExtraAttributesFalse() throws Exception { - getCastorUnmarshaller().setIgnoreExtraAttributes(false); unmarshal(EXTRA_ATTRIBUTES_STRING); } @@ -152,7 +153,6 @@ public class CastorUnmarshallerTests extends AbstractUnmarshallerTests { @Test(expected = MarshallingException.class) public void testIgnoreExtraElementsFalse() throws Exception { - getCastorUnmarshaller().setIgnoreExtraElements(false); unmarshal(EXTRA_ELEMENTS_STRING); } @@ -180,7 +180,7 @@ public class CastorUnmarshallerTests extends AbstractUnmarshallerTests { } @Test - @Ignore("Fails on the builder server for some reason") + @Ignore("Fails on the build server for some reason") public void testClearCollectionsFalse() throws Exception { Flights flights = new Flights(); flights.setFlight(new Flight[]{new Flight(), null}); @@ -195,6 +195,55 @@ public class CastorUnmarshallerTests extends AbstractUnmarshallerTests { testFlight(flights.getFlight()[2]); } + @Test + public void unmarshalStreamSourceExternalEntities() throws Exception { + final AtomicReference result = new AtomicReference(); + CastorMarshaller marshaller = new CastorMarshaller() { + @Override + protected Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource) { + result.set(xmlReader); + return null; + } + }; + + // 1. external-general-entities disabled (default) + marshaller.unmarshal(new StreamSource("1")); + assertNotNull(result.get()); + assertEquals(false, result.get().getFeature("http://xml.org/sax/features/external-general-entities")); + + // 2. external-general-entities disabled (default) + result.set(null); + marshaller.setProcessExternalEntities(true); + marshaller.unmarshal(new StreamSource("1")); + assertNotNull(result.get()); + assertEquals(true, result.get().getFeature("http://xml.org/sax/features/external-general-entities")); + } + + @Test + public void unmarshalSaxSourceExternalEntities() throws Exception { + final AtomicReference result = new AtomicReference(); + CastorMarshaller marshaller = new CastorMarshaller() { + @Override + protected Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource) { + result.set(xmlReader); + return null; + } + }; + + // 1. external-general-entities disabled (default) + marshaller.unmarshal(new SAXSource(new InputSource("1"))); + assertNotNull(result.get()); + assertEquals(false, result.get().getFeature("http://xml.org/sax/features/external-general-entities")); + + // 2. external-general-entities disabled (default) + result.set(null); + marshaller.setProcessExternalEntities(true); + marshaller.unmarshal(new SAXSource(new InputSource("1"))); + assertNotNull(result.get()); + assertEquals(true, result.get().getFeature("http://xml.org/sax/features/external-general-entities")); + } + + private CastorMarshaller getCastorUnmarshaller() { return (CastorMarshaller) unmarshaller; } @@ -208,58 +257,4 @@ public class CastorUnmarshallerTests extends AbstractUnmarshallerTests { return unmarshaller.unmarshal(source); } - @Test - public void unmarshalStreamSourceExternalEntities() throws Exception { - - final AtomicReference result = new AtomicReference(); - CastorMarshaller marshaller = new CastorMarshaller() { - @Override - protected Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource) { - result.set(xmlReader); - return null; - } - }; - - // 1. external-general-entities disabled (default) - - marshaller.unmarshal(new StreamSource("1")); - assertNotNull(result.get()); - assertEquals(false, result.get().getFeature("http://xml.org/sax/features/external-general-entities")); - - // 2. external-general-entities disabled (default) - - result.set(null); - marshaller.setProcessExternalEntities(true); - marshaller.unmarshal(new StreamSource("1")); - assertNotNull(result.get()); - assertEquals(true, result.get().getFeature("http://xml.org/sax/features/external-general-entities")); - } - - @Test - public void unmarshalSaxSourceExternalEntities() throws Exception { - - final AtomicReference result = new AtomicReference(); - CastorMarshaller marshaller = new CastorMarshaller() { - @Override - protected Object unmarshalSaxReader(XMLReader xmlReader, InputSource inputSource) { - result.set(xmlReader); - return null; - } - }; - - // 1. external-general-entities disabled (default) - - marshaller.unmarshal(new SAXSource(new InputSource("1"))); - assertNotNull(result.get()); - assertEquals(false, result.get().getFeature("http://xml.org/sax/features/external-general-entities")); - - // 2. external-general-entities disabled (default) - - result.set(null); - marshaller.setProcessExternalEntities(true); - marshaller.unmarshal(new SAXSource(new InputSource("1"))); - assertNotNull(result.get()); - assertEquals(true, result.get().getFeature("http://xml.org/sax/features/external-general-entities")); - } - } diff --git a/spring-web/src/main/java/org/springframework/web/bind/annotation/RequestBody.java b/spring-web/src/main/java/org/springframework/web/bind/annotation/RequestBody.java index b04bb01567..9a51146c48 100644 --- a/spring-web/src/main/java/org/springframework/web/bind/annotation/RequestBody.java +++ b/spring-web/src/main/java/org/springframework/web/bind/annotation/RequestBody.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,11 +33,11 @@ import org.springframework.http.converter.HttpMessageConverter; *

Supported for annotated handler methods in Servlet environments. * * @author Arjen Poutsma + * @since 3.0 * @see RequestHeader * @see ResponseBody * @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter * @see org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter - * @since 3.0 */ @Target(ElementType.PARAMETER) @Retention(RetentionPolicy.RUNTIME) @@ -49,6 +49,7 @@ public @interface RequestBody { *

Default is {@code true}, leading to an exception thrown in case * there is no body content. Switch this to {@code false} if you prefer * {@code null} to be passed when the body content is {@code null}. + * @since 3.2 */ boolean required() default true; diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessor.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessor.java index b56bd79492..a3d786ee33 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessor.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessor.java @@ -52,8 +52,8 @@ import org.springframework.web.servlet.mvc.support.DefaultHandlerExceptionResolv * *

An {@code @RequestBody} method argument is also validated if it is annotated * with {@code @javax.validation.Valid}. In case of validation failure, - * {@link MethodArgumentNotValidException} is raised and results in a 400 response - * status code if {@link DefaultHandlerExceptionResolver} is configured. + * {@link MethodArgumentNotValidException} is raised and results in an HTTP 400 + * response status code if {@link DefaultHandlerExceptionResolver} is configured. * * @author Arjen Poutsma * @author Rossen Stoyanchev @@ -141,7 +141,7 @@ public class RequestResponseBodyMethodProcessor extends AbstractMessageConverter protected Object readWithMessageConverters(NativeWebRequest webRequest, MethodParameter methodParam, Type paramType) throws IOException, HttpMediaTypeNotSupportedException { - final HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class); + HttpServletRequest servletRequest = webRequest.getNativeRequest(HttpServletRequest.class); HttpInputMessage inputMessage = new ServletServerHttpRequest(servletRequest); RequestBody ann = methodParam.getParameterAnnotation(RequestBody.class); @@ -168,7 +168,7 @@ public class RequestResponseBodyMethodProcessor extends AbstractMessageConverter } inputMessage = new ServletServerHttpRequest(servletRequest) { @Override - public InputStream getBody() throws IOException { + public InputStream getBody() { // Form POST should not get here return pushbackInputStream; } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessorTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessorTests.java index 5c69b6f424..1e287af60e 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessorTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/mvc/method/annotation/RequestResponseBodyMethodProcessorTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2012 the original author or authors. + * Copyright 2002-2015 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,9 +16,6 @@ package org.springframework.web.servlet.mvc.method.annotation; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - import java.io.Serializable; import java.lang.reflect.Method; import java.util.ArrayList; @@ -26,6 +23,7 @@ import java.util.List; import org.junit.Before; import org.junit.Test; + import org.springframework.core.MethodParameter; import org.springframework.http.MediaType; import org.springframework.http.converter.ByteArrayHttpMessageConverter; @@ -45,9 +43,11 @@ import org.springframework.web.context.request.ServletWebRequest; import org.springframework.web.method.HandlerMethod; import org.springframework.web.method.support.ModelAndViewContainer; +import static org.junit.Assert.*; + /** - * Test fixture for a {@link RequestResponseBodyMethodProcessor} with actual delegation - * to HttpMessageConverter instances. + * Test fixture for a {@link RequestResponseBodyMethodProcessor} with + * actual delegation to {@link HttpMessageConverter} instances. * *

Also see {@link RequestResponseBodyMethodProcessorMockTests}. * @@ -74,9 +74,7 @@ public class RequestResponseBodyMethodProcessorTests { @Before public void setUp() throws Exception { - - Method method = getClass().getMethod("handle", - List.class, SimpleBean.class, MultiValueMap.class, String.class); + Method method = getClass().getMethod("handle", List.class, SimpleBean.class, MultiValueMap.class, String.class); paramGenericList = new MethodParameter(method, 0); paramSimpleBean = new MethodParameter(method, 1); @@ -165,11 +163,8 @@ public class RequestResponseBodyMethodProcessorTests { assertEquals("foobarbaz", result); } - // SPR-9964 - - @Test + @Test // SPR-9964 public void resolveArgumentTypeVariable() throws Exception { - Method method = MySimpleParameterizedController.class.getMethod("handleDto", Identifiable.class); HandlerMethod handlerMethod = new HandlerMethod(new MySimpleParameterizedController(), method); MethodParameter methodParam = handlerMethod.getMethodParameters()[0]; @@ -188,9 +183,7 @@ public class RequestResponseBodyMethodProcessorTests { assertEquals("Jad", result.getName()); } - // SPR-9160 - - @Test + @Test // SPR-9160 public void handleReturnValueSortByQuality() throws Exception { this.servletRequest.addHeader("Accept", "text/plain; q=0.5, application/json"); @@ -241,22 +234,31 @@ public class RequestResponseBodyMethodProcessorTests { return null; } + private static abstract class MyParameterizedController { + @SuppressWarnings("unused") public void handleDto(@RequestBody DTO dto) {} } - private static class MySimpleParameterizedController extends MyParameterizedController { } + + private static class MySimpleParameterizedController extends MyParameterizedController { + } + private interface Identifiable extends Serializable { + public Long getId(); + public void setId(Long id); } + @SuppressWarnings({ "serial" }) private static class SimpleBean implements Identifiable { private Long id; + private String name; @Override @@ -278,7 +280,9 @@ public class RequestResponseBodyMethodProcessorTests { } } + private final class ValidatingBinderFactory implements WebDataBinderFactory { + @Override public WebDataBinder createBinder(NativeWebRequest webRequest, Object target, String objectName) throws Exception { LocalValidatorFactoryBean validator = new LocalValidatorFactoryBean();