Update StreamUtils drain and emptyInput to use JDK builtins

Update StreamUtils.drain to use InputStream.transferTo with a null
OutputStream. This avoids allocating buffers for cases where the
supplied InputStream has an optimized transferTo method (e.g.,
ByteArrayInputStream and FileInputStream).

Additionally, update StreamUtils.emptyInput to simply call
InputStream.nullInputStream.

Closes gh-28961
This commit is contained in:
Patrick Strawderman
2022-08-13 14:32:55 -07:00
committed by Brian Clozel
parent 7642ac82f6
commit d4a74c8f9d
2 changed files with 9 additions and 13 deletions

View File

@@ -16,7 +16,6 @@
package org.springframework.util;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FilterInputStream;
import java.io.FilterOutputStream;
@@ -62,7 +61,7 @@ public abstract class StreamUtils {
*/
public static byte[] copyToByteArray(@Nullable InputStream in) throws IOException {
if (in == null) {
return new byte[0];
return EMPTY_CONTENT;
}
ByteArrayOutputStream out = new ByteArrayOutputStream(BUFFER_SIZE);
@@ -215,22 +214,15 @@ public abstract class StreamUtils {
*/
public static int drain(InputStream in) throws IOException {
Assert.notNull(in, "No InputStream specified");
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = -1;
int byteCount = 0;
while ((bytesRead = in.read(buffer)) != -1) {
byteCount += bytesRead;
}
return byteCount;
return (int) in.transferTo(OutputStream.nullOutputStream());
}
/**
* Return an efficient empty {@link InputStream}.
* @return a {@link ByteArrayInputStream} based on an empty byte array
* @return an InputStream which contains no bytes
* @since 4.2.2
*/
public static InputStream emptyInput() {
return new ByteArrayInputStream(EMPTY_CONTENT);
return InputStream.nullInputStream();
}
/**

View File

@@ -28,6 +28,7 @@ import org.springframework.util.StreamUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.BDDMockito.given;
import static org.mockito.BDDMockito.willDoNothing;
import static org.mockito.Mockito.mock;
@@ -99,7 +100,10 @@ public class SimpleClientHttpResponseTests {
InputStream is = mock(InputStream.class);
given(this.connection.getErrorStream()).willReturn(is);
willDoNothing().given(is).close();
given(is.read(any())).willThrow(new NullPointerException("from HttpURLConnection#ErrorStream"));
given(is.transferTo(any())).willCallRealMethod();
given(is.read(any(), anyInt(), anyInt())).willThrow(new NullPointerException("from HttpURLConnection#ErrorStream"));
is.readAllBytes();
InputStream responseStream = this.response.getBody();
responseStream.close();