Browse Source

Fix error when writing empty String to DataBuffer

Prior to this commit, `DataBuffer.write` would throw an
`IllegalStateException` when called with an empty `String`, since the
`CharsetEncoder` would be flushed on an incorrent state.

This commit skips entirely the encoding phase for empty `String`.

Fixes #22262
pull/22392/head
Brian Clozel 7 years ago
parent
commit
2b65d0e51f
  1. 46
      spring-core/src/main/java/org/springframework/core/io/buffer/DataBuffer.java
  2. 12
      spring-core/src/test/java/org/springframework/core/io/buffer/DataBufferTests.java

46
spring-core/src/main/java/org/springframework/core/io/buffer/DataBuffer.java

@ -246,30 +246,32 @@ public interface DataBuffer { @@ -246,30 +246,32 @@ public interface DataBuffer {
default DataBuffer write(CharSequence charSequence, Charset charset) {
Assert.notNull(charSequence, "CharSequence must not be null");
Assert.notNull(charset, "Charset must not be null");
CharsetEncoder charsetEncoder = charset.newEncoder()
.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE);
CharBuffer inBuffer = CharBuffer.wrap(charSequence);
int estimatedSize = (int) (inBuffer.remaining() * charsetEncoder.averageBytesPerChar());
ByteBuffer outBuffer = ensureCapacity(estimatedSize)
.asByteBuffer(writePosition(), writableByteCount());
while (true) {
CoderResult cr = (inBuffer.hasRemaining() ?
charsetEncoder.encode(inBuffer, outBuffer, true) : CoderResult.UNDERFLOW);
if (cr.isUnderflow()) {
cr = charsetEncoder.flush(outBuffer);
}
if (cr.isUnderflow()) {
break;
}
if (cr.isOverflow()) {
writePosition(outBuffer.position());
int maximumSize = (int) (inBuffer.remaining() * charsetEncoder.maxBytesPerChar());
ensureCapacity(maximumSize);
outBuffer = asByteBuffer(writePosition(), writableByteCount());
if (charSequence.length() != 0) {
CharsetEncoder charsetEncoder = charset.newEncoder()
.onMalformedInput(CodingErrorAction.REPLACE)
.onUnmappableCharacter(CodingErrorAction.REPLACE);
CharBuffer inBuffer = CharBuffer.wrap(charSequence);
int estimatedSize = (int) (inBuffer.remaining() * charsetEncoder.averageBytesPerChar());
ByteBuffer outBuffer = ensureCapacity(estimatedSize)
.asByteBuffer(writePosition(), writableByteCount());
while (true) {
CoderResult cr = (inBuffer.hasRemaining() ?
charsetEncoder.encode(inBuffer, outBuffer, true) : CoderResult.UNDERFLOW);
if (cr.isUnderflow()) {
cr = charsetEncoder.flush(outBuffer);
}
if (cr.isUnderflow()) {
break;
}
if (cr.isOverflow()) {
writePosition(outBuffer.position());
int maximumSize = (int) (inBuffer.remaining() * charsetEncoder.maxBytesPerChar());
ensureCapacity(maximumSize);
outBuffer = asByteBuffer(writePosition(), writableByteCount());
}
}
writePosition(outBuffer.position());
}
writePosition(outBuffer.position());
return this;
}

12
spring-core/src/test/java/org/springframework/core/io/buffer/DataBufferTests.java

@ -1,5 +1,5 @@ @@ -1,5 +1,5 @@
/*
* Copyright 2002-2018 the original author or authors.
* Copyright 2002-2019 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.
@ -179,6 +179,16 @@ public class DataBufferTests extends AbstractDataBufferAllocatingTestCase { @@ -179,6 +179,16 @@ public class DataBufferTests extends AbstractDataBufferAllocatingTestCase {
}
}
@Test
public void writeEmptyString() {
DataBuffer buffer = createDataBuffer(1);
buffer.write("", StandardCharsets.UTF_8);
assertEquals(0, buffer.readableByteCount());
release(buffer);
}
@Test
public void writeUtf8String() {
DataBuffer buffer = createDataBuffer(6);

Loading…
Cancel
Save