Introduce toString(Charset) in FastByteArrayOutputStream

This commit introduces a toString() overload in
FastByteArrayOutputStream that accepts a Charset in order to mirror the
method that was introduced in ByteArrayOutputStream in JDK 10,
including a special case for when a single buffer is in use internally
to avoid the need to resize.

This commit also updates getContentAsString() in
ContentCachingRequestWrapper to use this new toString(Charset) method.

Closes gh-31737
This commit is contained in:
Patrick Strawderman
2023-12-01 12:50:19 -08:00
committed by Sam Brannen
parent 0bec8125a4
commit 7cdacf3083
3 changed files with 38 additions and 2 deletions

View File

@@ -19,6 +19,7 @@ package org.springframework.util;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.security.MessageDigest;
import java.util.ArrayDeque;
import java.util.Deque;
@@ -162,9 +163,26 @@ public class FastByteArrayOutputStream extends OutputStream {
*/
@Override
public String toString() {
return new String(toByteArrayUnsafe());
return toString(Charset.defaultCharset());
}
/**
* Converts the buffer's contents into a string by decoding the bytes using
* the specified {@link java.nio.charset.Charset charset}.
*
* @param charset the {@linkplain java.nio.charset.Charset charset}
* to be used to decode the {@code bytes}
* @return a String decoded from the buffer's contents
*/
public String toString(Charset charset) {
if (size() == 0) {
return "";
}
if (buffers.size() == 1) {
return new String(buffers.getFirst(), 0, index, charset);
}
return new String(toByteArrayUnsafe(), charset);
}
// Custom methods

View File

@@ -57,6 +57,24 @@ class FastByteArrayOutputStreamTests {
assertThat(this.os.size()).isEqualTo(sizeBefore);
}
@Test
void stringConversion() throws Exception {
this.os.write(this.helloBytes);
assertThat(this.os.toString()).isEqualTo("Hello World");
assertThat(this.os.toString(StandardCharsets.UTF_8)).isEqualTo("Hello World");
FastByteArrayOutputStream empty = new FastByteArrayOutputStream();
assertThat(empty.toString()).isEqualTo("");
assertThat(empty.toString(StandardCharsets.US_ASCII)).isEqualTo("");
FastByteArrayOutputStream outputStream = new FastByteArrayOutputStream(5);
// Add bytes in multiple writes to ensure we get more than one buffer internally
outputStream.write(this.helloBytes, 0, 5);
outputStream.write(this.helloBytes, 5, 6);
assertThat(outputStream.toString(StandardCharsets.UTF_8)).isEqualTo("Hello World");
assertThat(outputStream.toString()).isEqualTo("Hello World");
}
@Test
void autoGrow() throws IOException {
this.os.resize(1);

View File

@@ -205,7 +205,7 @@ public class ContentCachingRequestWrapper extends HttpServletRequestWrapper {
* @see #getContentAsByteArray()
*/
public String getContentAsString() {
return new String(this.cachedContent.toByteArrayUnsafe(), Charset.forName(getCharacterEncoding()));
return this.cachedContent.toString(Charset.forName(getCharacterEncoding()));
}
/**