From 8d5a6520ce033c38c57a9ec026102e17bd598acc Mon Sep 17 00:00:00 2001 From: rstoyanchev Date: Wed, 2 Feb 2022 15:32:21 +0000 Subject: [PATCH] Ensure all converters don't close InputStream Closes gh-27969 --- .../BufferedImageHttpMessageConverter.java | 2 ++ .../feed/AbstractWireFeedHttpMessageConverter.java | 7 +++++-- .../json/AbstractJackson2HttpMessageConverter.java | 12 +++++++----- .../xml/AbstractXmlHttpMessageConverter.java | 7 +++++-- .../converter/xml/SourceHttpMessageConverter.java | 4 ++-- .../BufferedImageHttpMessageConverterTests.java | 11 +++++++++-- .../feed/AtomFeedHttpMessageConverterTests.java | 11 ++++++++--- .../feed/RssChannelHttpMessageConverterTests.java | 11 ++++++++--- .../json/GsonHttpMessageConverterTests.java | 12 ++++++++++-- .../json/JsonbHttpMessageConverterTests.java | 12 ++++++++++-- .../MappingJackson2HttpMessageConverterTests.java | 9 +++++++-- .../ProtobufHttpMessageConverterTests.java | 9 ++++++++- ...rotobufJsonFormatHttpMessageConverterTests.java | 9 ++++++++- ...pingJackson2SmileHttpMessageConverterTests.java | 12 ++++++++++-- .../Jaxb2CollectionHttpMessageConverterTests.java | 12 ++++++++++-- .../Jaxb2RootElementHttpMessageConverterTests.java | 12 ++++++++++-- ...appingJackson2XmlHttpMessageConverterTests.java | 12 ++++++++++-- .../xml/MarshallingHttpMessageConverterTests.java | 14 ++++++++++++-- .../xml/SourceHttpMessageConverterTests.java | 12 ++++++++++-- 19 files changed, 151 insertions(+), 39 deletions(-) diff --git a/spring-web/src/main/java/org/springframework/http/converter/BufferedImageHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/BufferedImageHttpMessageConverter.java index 0dbfc02f09..62a899f9b3 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/BufferedImageHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/BufferedImageHttpMessageConverter.java @@ -45,6 +45,7 @@ import org.springframework.http.MediaType; import org.springframework.http.StreamingHttpOutputMessage; import org.springframework.lang.Nullable; import org.springframework.util.Assert; +import org.springframework.util.StreamUtils; import org.springframework.util.StringUtils; /** @@ -207,6 +208,7 @@ public class BufferedImageHttpMessageConverter implements HttpMessageConverter Charset charset = (contentType != null && contentType.getCharset() != null ? contentType.getCharset() : DEFAULT_CHARSET); try { - Reader reader = new InputStreamReader(inputMessage.getBody(), charset); + InputStream inputStream = StreamUtils.nonClosing(inputMessage.getBody()); + Reader reader = new InputStreamReader(inputStream, charset); return (T) feedInput.build(reader); } catch (FeedException ex) { diff --git a/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java index 19b22fef2c..b5273919e4 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/json/AbstractJackson2HttpMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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. @@ -17,6 +17,7 @@ package org.springframework.http.converter.json; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.io.OutputStream; import java.io.Reader; @@ -361,24 +362,25 @@ public abstract class AbstractJackson2HttpMessageConverter extends AbstractGener "UTF-16".equals(charset.name()) || "UTF-32".equals(charset.name()); try { + InputStream inputStream = StreamUtils.nonClosing(inputMessage.getBody()); if (inputMessage instanceof MappingJacksonInputMessage) { Class deserializationView = ((MappingJacksonInputMessage) inputMessage).getDeserializationView(); if (deserializationView != null) { ObjectReader objectReader = objectMapper.readerWithView(deserializationView).forType(javaType); if (isUnicode) { - return objectReader.readValue(inputMessage.getBody()); + return objectReader.readValue(inputStream); } else { - Reader reader = new InputStreamReader(inputMessage.getBody(), charset); + Reader reader = new InputStreamReader(inputStream, charset); return objectReader.readValue(reader); } } } if (isUnicode) { - return objectMapper.readValue(inputMessage.getBody(), javaType); + return objectMapper.readValue(inputStream, javaType); } else { - Reader reader = new InputStreamReader(inputMessage.getBody(), charset); + Reader reader = new InputStreamReader(inputStream, charset); return objectMapper.readValue(reader, javaType); } } diff --git a/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java index 9da6bcb42c..19d95e4bef 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/xml/AbstractXmlHttpMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2018 the original author or authors. + * Copyright 2002-2022 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. @@ -17,6 +17,7 @@ package org.springframework.http.converter.xml; import java.io.IOException; +import java.io.InputStream; import javax.xml.transform.Result; import javax.xml.transform.Source; @@ -33,6 +34,7 @@ import org.springframework.http.converter.AbstractHttpMessageConverter; import org.springframework.http.converter.HttpMessageConversionException; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.converter.HttpMessageNotWritableException; +import org.springframework.util.StreamUtils; /** * Abstract base class for {@link org.springframework.http.converter.HttpMessageConverter HttpMessageConverters} @@ -66,7 +68,8 @@ public abstract class AbstractXmlHttpMessageConverter extends AbstractHttpMes throws IOException, HttpMessageNotReadableException { try { - return readFromSource(clazz, inputMessage.getHeaders(), new StreamSource(inputMessage.getBody())); + InputStream inputStream = StreamUtils.nonClosing(inputMessage.getBody()); + return readFromSource(clazz, inputMessage.getHeaders(), new StreamSource(inputStream)); } catch (IOException | HttpMessageConversionException ex) { throw ex; diff --git a/spring-web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java b/spring-web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java index 63c70e30c6..468152e2ce 100644 --- a/spring-web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java +++ b/spring-web/src/main/java/org/springframework/http/converter/xml/SourceHttpMessageConverter.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -146,7 +146,7 @@ public class SourceHttpMessageConverter extends AbstractHttpMe protected T readInternal(Class clazz, HttpInputMessage inputMessage) throws IOException, HttpMessageNotReadableException { - InputStream body = inputMessage.getBody(); + InputStream body = StreamUtils.nonClosing(inputMessage.getBody()); if (DOMSource.class == clazz) { return (T) readDOMSource(body, inputMessage); } diff --git a/spring-web/src/test/java/org/springframework/http/converter/BufferedImageHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/BufferedImageHttpMessageConverterTests.java index b91f6b429e..477cd7138c 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/BufferedImageHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/BufferedImageHttpMessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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,6 +19,7 @@ package org.springframework.http.converter; import java.awt.image.BufferedImage; import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import javax.imageio.ImageIO; @@ -33,6 +34,9 @@ import org.springframework.http.MockHttpOutputMessage; import org.springframework.util.FileCopyUtils; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; /** * Unit tests for BufferedImageHttpMessageConverter. @@ -65,11 +69,13 @@ public class BufferedImageHttpMessageConverterTests { public void read() throws IOException { Resource logo = new ClassPathResource("logo.jpg", BufferedImageHttpMessageConverterTests.class); byte[] body = FileCopyUtils.copyToByteArray(logo.getInputStream()); - MockHttpInputMessage inputMessage = new MockHttpInputMessage(body); + InputStream inputStream = spy(new ByteArrayInputStream(body)); + MockHttpInputMessage inputMessage = new MockHttpInputMessage(inputStream); inputMessage.getHeaders().setContentType(new MediaType("image", "jpeg")); BufferedImage result = converter.read(BufferedImage.class, inputMessage); assertThat(result.getHeight()).as("Invalid height").isEqualTo(500); assertThat(result.getWidth()).as("Invalid width").isEqualTo(750); + verify(inputStream, never()).close(); } @Test @@ -84,6 +90,7 @@ public class BufferedImageHttpMessageConverterTests { BufferedImage result = ImageIO.read(new ByteArrayInputStream(outputMessage.getBodyAsBytes())); assertThat(result.getHeight()).as("Invalid height").isEqualTo(500); assertThat(result.getWidth()).as("Invalid width").isEqualTo(750); + verify(outputMessage.getBody(), never()).close(); } @Test diff --git a/spring-web/src/test/java/org/springframework/http/converter/feed/AtomFeedHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/feed/AtomFeedHttpMessageConverterTests.java index 856dcd7870..cd71fa9f39 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/feed/AtomFeedHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/feed/AtomFeedHttpMessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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. @@ -38,6 +38,9 @@ import org.springframework.http.MockHttpOutputMessage; import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; /** * @author Arjen Poutsma @@ -71,8 +74,8 @@ public class AtomFeedHttpMessageConverterTests { @Test public void read() throws IOException { - InputStream is = getClass().getResourceAsStream("atom.xml"); - MockHttpInputMessage inputMessage = new MockHttpInputMessage(is); + InputStream inputStream = spy(getClass().getResourceAsStream("atom.xml")); + MockHttpInputMessage inputMessage = new MockHttpInputMessage(inputStream); inputMessage.getHeaders().setContentType(ATOM_XML_UTF8); Feed result = converter.read(Feed.class, inputMessage); assertThat(result.getTitle()).isEqualTo("title"); @@ -87,6 +90,7 @@ public class AtomFeedHttpMessageConverterTests { Entry entry2 = (Entry) entries.get(1); assertThat(entry2.getId()).isEqualTo("id2"); assertThat(entry2.getTitle()).isEqualTo("title2"); + verify(inputStream, never()).close(); } @Test @@ -119,6 +123,7 @@ public class AtomFeedHttpMessageConverterTests { NodeMatcher nm = new DefaultNodeMatcher(ElementSelectors.byName); assertThat(XmlContent.of(outputMessage.getBodyAsString(StandardCharsets.UTF_8))) .isSimilarToIgnoringWhitespace(expected, nm); + verify(outputMessage.getBody(), never()).close(); } @Test diff --git a/spring-web/src/test/java/org/springframework/http/converter/feed/RssChannelHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/feed/RssChannelHttpMessageConverterTests.java index 5d1e01f328..b537604ad3 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/feed/RssChannelHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/feed/RssChannelHttpMessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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,6 +34,9 @@ import org.springframework.http.MockHttpOutputMessage; import static java.util.Collections.singletonMap; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; /** * @author Arjen Poutsma @@ -56,8 +59,8 @@ public class RssChannelHttpMessageConverterTests { @Test public void read() throws IOException { - InputStream is = getClass().getResourceAsStream("rss.xml"); - MockHttpInputMessage inputMessage = new MockHttpInputMessage(is); + InputStream inputStream = spy(getClass().getResourceAsStream("rss.xml")); + MockHttpInputMessage inputMessage = new MockHttpInputMessage(inputStream); inputMessage.getHeaders().setContentType(RSS_XML_UTF8); Channel result = converter.read(Channel.class, inputMessage); assertThat(result.getTitle()).isEqualTo("title"); @@ -72,6 +75,7 @@ public class RssChannelHttpMessageConverterTests { Item item2 = (Item) items.get(1); assertThat(item2.getTitle()).isEqualTo("title2"); + verify(inputStream, never()).close(); } @Test @@ -105,6 +109,7 @@ public class RssChannelHttpMessageConverterTests { ""; assertThat(XmlContent.of(outputMessage.getBodyAsString(StandardCharsets.UTF_8))) .isSimilarToIgnoringWhitespace(expected); + verify(outputMessage.getBody(), never()).close(); } @Test diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/GsonHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/GsonHttpMessageConverterTests.java index aa2c777ae4..60d7306c47 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/json/GsonHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/json/GsonHttpMessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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,7 +16,9 @@ package org.springframework.http.converter.json; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Type; import java.nio.charset.Charset; @@ -38,6 +40,9 @@ import org.springframework.http.converter.HttpMessageNotReadableException; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.within; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; /** * Gson 2.x converter tests. @@ -72,7 +77,8 @@ public class GsonHttpMessageConverterTests { public void readTyped() throws IOException { String body = "{\"bytes\":[1,2],\"array\":[\"Foo\",\"Bar\"]," + "\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}"; - MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8")); + InputStream inputStream = spy(new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8))); + MockHttpInputMessage inputMessage = new MockHttpInputMessage(inputStream); inputMessage.getHeaders().setContentType(new MediaType("application", "json")); MyBean result = (MyBean) this.converter.read(MyBean.class, inputMessage); @@ -83,6 +89,7 @@ public class GsonHttpMessageConverterTests { assertThat(result.getArray()).isEqualTo(new String[] {"Foo", "Bar"}); assertThat(result.isBool()).isTrue(); assertThat(result.getBytes()).isEqualTo(new byte[] {0x1, 0x2}); + verify(inputStream, never()).close(); } @Test @@ -132,6 +139,7 @@ public class GsonHttpMessageConverterTests { assertThat(result.contains("\"bool\":true")).isTrue(); assertThat(result.contains("\"bytes\":[1,2]")).isTrue(); assertThat(outputMessage.getHeaders().getContentType()).as("Invalid content-type").isEqualTo(new MediaType("application", "json", utf8)); + verify(outputMessage.getBody(), never()).close(); } @Test diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/JsonbHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/JsonbHttpMessageConverterTests.java index 44e14ac576..d2aad2f424 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/json/JsonbHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/json/JsonbHttpMessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2021 the original author or authors. + * Copyright 2002-2022 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,7 +16,9 @@ package org.springframework.http.converter.json; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.lang.reflect.Field; import java.lang.reflect.Type; import java.nio.charset.Charset; @@ -38,6 +40,9 @@ import org.springframework.http.converter.HttpMessageNotReadableException; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.within; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; /** * Integration tests for the JSON Binding API, running against Apache Johnzon. @@ -72,7 +77,8 @@ public class JsonbHttpMessageConverterTests { public void readTyped() throws IOException { String body = "{\"bytes\":[1,2],\"array\":[\"Foo\",\"Bar\"]," + "\"number\":42,\"string\":\"Foo\",\"bool\":true,\"fraction\":42.0}"; - MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes(StandardCharsets.UTF_8)); + InputStream inputStream = spy(new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8))); + MockHttpInputMessage inputMessage = new MockHttpInputMessage(inputStream); inputMessage.getHeaders().setContentType(new MediaType("application", "json")); MyBean result = (MyBean) this.converter.read(MyBean.class, inputMessage); @@ -83,6 +89,7 @@ public class JsonbHttpMessageConverterTests { assertThat(result.getArray()).isEqualTo(new String[] {"Foo", "Bar"}); assertThat(result.isBool()).isTrue(); assertThat(result.getBytes()).isEqualTo(new byte[] {0x1, 0x2}); + verify(inputStream, never()).close(); } @Test @@ -132,6 +139,7 @@ public class JsonbHttpMessageConverterTests { assertThat(result.contains("\"bool\":true")).isTrue(); assertThat(result.contains("\"bytes\":[1,2]")).isTrue(); assertThat(outputMessage.getHeaders().getContentType()).as("Invalid content-type").isEqualTo(new MediaType("application", "json", utf8)); + verify(outputMessage.getBody(), never()).close(); } @Test diff --git a/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java index cea6e8c7cf..f67a56433e 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/json/MappingJackson2HttpMessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2020 the original author or authors. + * Copyright 2002-2022 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,7 +16,9 @@ package org.springframework.http.converter.json; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.lang.reflect.Type; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -48,6 +50,7 @@ import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.entry; import static org.assertj.core.api.Assertions.within; import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.verify; /** @@ -134,7 +137,8 @@ public class MappingJackson2HttpMessageConverterTests { "\"string\":\"Foo\"," + "\"bool\":true," + "\"fraction\":42.0}"; - MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8")); + InputStream inputStream = spy(new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8))); + MockHttpInputMessage inputMessage = new MockHttpInputMessage(inputStream); inputMessage.getHeaders().setContentType(new MediaType("application", "json")); MyBean result = (MyBean) converter.read(MyBean.class, inputMessage); assertThat(result.getString()).isEqualTo("Foo"); @@ -143,6 +147,7 @@ public class MappingJackson2HttpMessageConverterTests { assertThat(result.getArray()).isEqualTo(new String[] {"Foo", "Bar"}); assertThat(result.isBool()).isTrue(); assertThat(result.getBytes()).isEqualTo(new byte[] {0x1, 0x2}); + verify(inputStream, never()).close(); } @Test diff --git a/spring-web/src/test/java/org/springframework/http/converter/protobuf/ProtobufHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/protobuf/ProtobufHttpMessageConverterTests.java index 26106e13d3..f0b83166da 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/protobuf/ProtobufHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/protobuf/ProtobufHttpMessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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,7 +16,9 @@ package org.springframework.http.converter.protobuf; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.nio.charset.Charset; import com.google.protobuf.ExtensionRegistry; @@ -34,6 +36,8 @@ import org.springframework.protobuf.SecondMsg; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -108,10 +112,12 @@ public class ProtobufHttpMessageConverterTests { @Test public void read() throws IOException { byte[] body = this.testMsg.toByteArray(); + InputStream inputStream = spy(new ByteArrayInputStream(body)); MockHttpInputMessage inputMessage = new MockHttpInputMessage(body); inputMessage.getHeaders().setContentType(ProtobufHttpMessageConverter.PROTOBUF); Message result = this.converter.read(Msg.class, inputMessage); assertThat(result).isEqualTo(this.testMsg); + verify(inputStream, never()).close(); } @Test @@ -138,6 +144,7 @@ public class ProtobufHttpMessageConverterTests { String schemaHeader = outputMessage.getHeaders().getFirst(ProtobufHttpMessageConverter.X_PROTOBUF_SCHEMA_HEADER); assertThat(schemaHeader).isEqualTo("sample.proto"); + verify(outputMessage.getBody(), never()).close(); } @Test diff --git a/spring-web/src/test/java/org/springframework/http/converter/protobuf/ProtobufJsonFormatHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/protobuf/ProtobufJsonFormatHttpMessageConverterTests.java index 296efbd8b3..c933c42622 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/protobuf/ProtobufJsonFormatHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/protobuf/ProtobufJsonFormatHttpMessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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,7 +16,9 @@ package org.springframework.http.converter.protobuf; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import com.google.protobuf.ExtensionRegistry; import com.google.protobuf.Message; @@ -32,6 +34,8 @@ import org.springframework.protobuf.SecondMsg; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; @@ -88,10 +92,12 @@ public class ProtobufJsonFormatHttpMessageConverterTests { @Test public void read() throws IOException { byte[] body = this.testMsg.toByteArray(); + InputStream inputStream = spy(new ByteArrayInputStream(body)); MockHttpInputMessage inputMessage = new MockHttpInputMessage(body); inputMessage.getHeaders().setContentType(ProtobufHttpMessageConverter.PROTOBUF); Message result = this.converter.read(Msg.class, inputMessage); assertThat(result).isEqualTo(this.testMsg); + verify(inputStream, never()).close(); } @Test @@ -118,6 +124,7 @@ public class ProtobufJsonFormatHttpMessageConverterTests { String schemaHeader = outputMessage.getHeaders().getFirst(ProtobufHttpMessageConverter.X_PROTOBUF_SCHEMA_HEADER); assertThat(schemaHeader).isEqualTo("sample.proto"); + verify(outputMessage.getBody(), never()).close(); } @Test diff --git a/spring-web/src/test/java/org/springframework/http/converter/smile/MappingJackson2SmileHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/smile/MappingJackson2SmileHttpMessageConverterTests.java index 2cbb22bdef..9d3e8470a7 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/smile/MappingJackson2SmileHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/smile/MappingJackson2SmileHttpMessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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,7 +16,9 @@ package org.springframework.http.converter.smile; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.dataformat.smile.SmileFactory; @@ -28,6 +30,9 @@ import org.springframework.http.MockHttpOutputMessage; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.within; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; /** * Jackson 2.x Smile converter tests. @@ -63,7 +68,8 @@ public class MappingJackson2SmileHttpMessageConverterTests { body.setArray(new String[]{"Foo", "Bar"}); body.setBool(true); body.setBytes(new byte[]{0x1, 0x2}); - MockHttpInputMessage inputMessage = new MockHttpInputMessage(mapper.writeValueAsBytes(body)); + InputStream inputStream = spy(new ByteArrayInputStream(mapper.writeValueAsBytes(body))); + MockHttpInputMessage inputMessage = new MockHttpInputMessage(inputStream); inputMessage.getHeaders().setContentType(new MediaType("application", "x-jackson-smile")); MyBean result = (MyBean) converter.read(MyBean.class, inputMessage); assertThat(result.getString()).isEqualTo("Foo"); @@ -73,6 +79,7 @@ public class MappingJackson2SmileHttpMessageConverterTests { assertThat(result.getArray()).isEqualTo(new String[]{"Foo", "Bar"}); assertThat(result.isBool()).isTrue(); assertThat(result.getBytes()).isEqualTo(new byte[]{0x1, 0x2}); + verify(inputStream, never()).close(); } @Test @@ -88,6 +95,7 @@ public class MappingJackson2SmileHttpMessageConverterTests { converter.write(body, null, outputMessage); assertThat(outputMessage.getBodyAsBytes()).isEqualTo(mapper.writeValueAsBytes(body)); assertThat(outputMessage.getHeaders().getContentType()).as("Invalid content-type").isEqualTo(new MediaType("application", "x-jackson-smile")); + verify(outputMessage.getBody(), never()).close(); } diff --git a/spring-web/src/test/java/org/springframework/http/converter/xml/Jaxb2CollectionHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/xml/Jaxb2CollectionHttpMessageConverterTests.java index 0b02ce6ae1..9c0c08646f 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/xml/Jaxb2CollectionHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/xml/Jaxb2CollectionHttpMessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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,7 +16,10 @@ package org.springframework.http.converter.xml; +import java.io.ByteArrayInputStream; +import java.io.InputStream; import java.lang.reflect.Type; +import java.nio.charset.StandardCharsets; import java.util.Collection; import java.util.List; import java.util.Set; @@ -38,6 +41,9 @@ import org.springframework.http.converter.HttpMessageNotReadableException; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; /** * Test fixture for {@link Jaxb2CollectionHttpMessageConverter}. @@ -79,12 +85,14 @@ public class Jaxb2CollectionHttpMessageConverterTests { @SuppressWarnings("unchecked") public void readXmlRootElementList() throws Exception { String content = ""; - MockHttpInputMessage inputMessage = new MockHttpInputMessage(content.getBytes("UTF-8")); + InputStream inputStream = spy(new ByteArrayInputStream(content.getBytes(StandardCharsets.UTF_8))); + MockHttpInputMessage inputMessage = new MockHttpInputMessage(inputStream); List result = (List) converter.read(rootElementListType, null, inputMessage); assertThat(result.size()).as("Invalid result").isEqualTo(2); assertThat(result.get(0).type.s).as("Invalid result").isEqualTo("1"); assertThat(result.get(1).type.s).as("Invalid result").isEqualTo("2"); + verify(inputStream, never()).close(); } @Test diff --git a/spring-web/src/test/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverterTests.java index cf5fa05d46..202776f685 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/xml/Jaxb2RootElementHttpMessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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,6 +16,8 @@ package org.springframework.http.converter.xml; +import java.io.ByteArrayInputStream; +import java.io.InputStream; import java.nio.charset.StandardCharsets; import javax.xml.bind.Marshaller; @@ -44,6 +46,9 @@ import org.springframework.http.converter.HttpMessageNotReadableException; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; import static org.xmlunit.diff.ComparisonType.XML_STANDALONE; import static org.xmlunit.diff.DifferenceEvaluators.Default; import static org.xmlunit.diff.DifferenceEvaluators.chain; @@ -95,9 +100,11 @@ public class Jaxb2RootElementHttpMessageConverterTests { @Test public void readXmlRootElement() throws Exception { byte[] body = "".getBytes("UTF-8"); - MockHttpInputMessage inputMessage = new MockHttpInputMessage(body); + InputStream inputStream = spy(new ByteArrayInputStream(body)); + MockHttpInputMessage inputMessage = new MockHttpInputMessage(inputStream); RootElement result = (RootElement) converter.read(RootElement.class, inputMessage); assertThat(result.type.s).as("Invalid result").isEqualTo("Hello World"); + verify(inputStream, never()).close(); } @Test @@ -177,6 +184,7 @@ public class Jaxb2RootElementHttpMessageConverterTests { DifferenceEvaluator ev = chain(Default, downgradeDifferencesToEqual(XML_STANDALONE)); assertThat(XmlContent.of(outputMessage.getBodyAsString(StandardCharsets.UTF_8))) .isSimilarTo("", ev); + verify(outputMessage.getBody(), never()).close(); } @Test diff --git a/spring-web/src/test/java/org/springframework/http/converter/xml/MappingJackson2XmlHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/xml/MappingJackson2XmlHttpMessageConverterTests.java index ab8c617b6f..631ff4848e 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/xml/MappingJackson2XmlHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/xml/MappingJackson2XmlHttpMessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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,7 +16,9 @@ package org.springframework.http.converter.xml; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; @@ -34,6 +36,9 @@ import org.springframework.http.converter.json.MappingJacksonValue; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.within; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; /** * Jackson 2.x XML converter tests. @@ -74,7 +79,8 @@ public class MappingJackson2XmlHttpMessageConverterTests { "Bar" + "true" + "AQI="; - MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8")); + InputStream inputStream = spy(new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8))); + MockHttpInputMessage inputMessage = new MockHttpInputMessage(inputStream); inputMessage.getHeaders().setContentType(new MediaType("application", "xml")); MyBean result = (MyBean) converter.read(MyBean.class, inputMessage); assertThat(result.getString()).isEqualTo("Foo"); @@ -83,6 +89,7 @@ public class MappingJackson2XmlHttpMessageConverterTests { assertThat(result.getArray()).isEqualTo(new String[]{"Foo", "Bar"}); assertThat(result.isBool()).isTrue(); assertThat(result.getBytes()).isEqualTo(new byte[]{0x1, 0x2}); + verify(inputStream, never()).close(); } @Test @@ -104,6 +111,7 @@ public class MappingJackson2XmlHttpMessageConverterTests { assertThat(result.contains("true")).isTrue(); assertThat(result.contains("AQI=")).isTrue(); assertThat(outputMessage.getHeaders().getContentType()).as("Invalid content-type").isEqualTo(new MediaType("application", "xml", StandardCharsets.UTF_8)); + verify(outputMessage.getBody(), never()).close(); } @Test diff --git a/spring-web/src/test/java/org/springframework/http/converter/xml/MarshallingHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/xml/MarshallingHttpMessageConverterTests.java index b3f95c9c81..d79f9dc5ac 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/xml/MarshallingHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/xml/MarshallingHttpMessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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,6 +16,10 @@ package org.springframework.http.converter.xml; +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; + import javax.xml.transform.Result; import javax.xml.transform.stream.StreamSource; @@ -40,6 +44,9 @@ import static org.mockito.BDDMockito.given; import static org.mockito.BDDMockito.willDoNothing; import static org.mockito.BDDMockito.willThrow; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; /** * Tests for {@link MarshallingHttpMessageConverter}. @@ -81,7 +88,8 @@ public class MarshallingHttpMessageConverterTests { @Test public void read() throws Exception { String body = "Hello World"; - MockHttpInputMessage inputMessage = new MockHttpInputMessage(body.getBytes("UTF-8")); + InputStream inputStream = spy(new ByteArrayInputStream(body.getBytes(StandardCharsets.UTF_8))); + MockHttpInputMessage inputMessage = new MockHttpInputMessage(inputStream); Unmarshaller unmarshaller = mock(Unmarshaller.class); given(unmarshaller.unmarshal(isA(StreamSource.class))).willReturn(body); @@ -91,6 +99,7 @@ public class MarshallingHttpMessageConverterTests { String result = (String) converter.read(Object.class, inputMessage); assertThat(result).as("Invalid result").isEqualTo(body); + verify(inputStream, never()).close(); } @Test @@ -135,6 +144,7 @@ public class MarshallingHttpMessageConverterTests { converter.write(body, null, outputMessage); assertThat(outputMessage.getHeaders().getContentType()).as("Invalid content-type").isEqualTo(new MediaType("application", "xml")); + verify(outputMessage.getBody(), never()).close(); } @Test diff --git a/spring-web/src/test/java/org/springframework/http/converter/xml/SourceHttpMessageConverterTests.java b/spring-web/src/test/java/org/springframework/http/converter/xml/SourceHttpMessageConverterTests.java index a54e6895ef..c2341a9bed 100644 --- a/spring-web/src/test/java/org/springframework/http/converter/xml/SourceHttpMessageConverterTests.java +++ b/spring-web/src/test/java/org/springframework/http/converter/xml/SourceHttpMessageConverterTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2019 the original author or authors. + * Copyright 2002-2022 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,7 +16,9 @@ package org.springframework.http.converter.xml; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.io.StringReader; import java.nio.charset.StandardCharsets; @@ -50,6 +52,9 @@ import org.springframework.util.FileCopyUtils; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatExceptionOfType; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.verify; /** * @author Arjen Poutsma @@ -90,11 +95,13 @@ public class SourceHttpMessageConverterTests { @Test public void readDOMSource() throws Exception { - MockHttpInputMessage inputMessage = new MockHttpInputMessage(BODY.getBytes("UTF-8")); + InputStream inputStream = spy(new ByteArrayInputStream(BODY.getBytes("UTF-8"))); + MockHttpInputMessage inputMessage = new MockHttpInputMessage(inputStream); inputMessage.getHeaders().setContentType(new MediaType("application", "xml")); DOMSource result = (DOMSource) converter.read(DOMSource.class, inputMessage); Document document = (Document) result.getNode(); assertThat(document.getDocumentElement().getLocalName()).as("Invalid result").isEqualTo("root"); + verify(inputStream, never()).close(); } @Test @@ -294,6 +301,7 @@ public class SourceHttpMessageConverterTests { .isSimilarTo("Hello World"); assertThat(outputMessage.getHeaders().getContentType()).as("Invalid content-type").isEqualTo(new MediaType("application", "xml")); assertThat(outputMessage.getHeaders().getContentLength()).as("Invalid content-length").isEqualTo(outputMessage.getBodyAsBytes().length); + verify(outputMessage.getBody(), never()).close(); } @Test