Revised ResizableByteArrayOutputStream as an actual subclass of ByteArrayOutputStream, and consistently applied appropriate ByteArrayOutputStream initial capacities across the codebase
Issue: SPR-11594
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2014 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,7 @@ final class PropertiesToStringConverter implements Converter<Properties, String>
|
||||
@Override
|
||||
public String convert(Properties source) {
|
||||
try {
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
||||
ByteArrayOutputStream os = new ByteArrayOutputStream(256);
|
||||
source.store(os, null);
|
||||
return os.toString("ISO-8859-1");
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -57,7 +57,7 @@ public class SerializingConverter implements Converter<Object, byte[]> {
|
||||
*/
|
||||
@Override
|
||||
public byte[] convert(Object source) {
|
||||
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(128);
|
||||
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(256);
|
||||
try {
|
||||
this.serializer.serialize(source, byteStream);
|
||||
return byteStream.toByteArray();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2012 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -36,11 +36,11 @@ public class ToStringCreator {
|
||||
new DefaultToStringStyler(StylerUtils.DEFAULT_VALUE_STYLER);
|
||||
|
||||
|
||||
private StringBuilder buffer = new StringBuilder(512);
|
||||
private final StringBuilder buffer = new StringBuilder(256);
|
||||
|
||||
private ToStringStyler styler;
|
||||
private final ToStringStyler styler;
|
||||
|
||||
private Object object;
|
||||
private final Object object;
|
||||
|
||||
private boolean styledFirstField;
|
||||
|
||||
|
||||
@@ -13,143 +13,79 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
||||
/**
|
||||
* A variation of {@link java.io.ByteArrayOutputStream} that:
|
||||
* An extension of {@link java.io.ByteArrayOutputStream} that:
|
||||
* <ul>
|
||||
* <li>has public {@link org.springframework.util.ResizableByteArrayOutputStream#grow(int)} and
|
||||
* {@link org.springframework.util.ResizableByteArrayOutputStream#resize(int)} methods to get more control
|
||||
* over the the size of the internal buffer</li>
|
||||
* <li>does not synchronize on buffer access - so this class should not be used if concurrent access
|
||||
* to the buffer is expected</li>
|
||||
* <li>has public {@link org.springframework.util.ResizableByteArrayOutputStream#grow(int)}
|
||||
* and {@link org.springframework.util.ResizableByteArrayOutputStream#resize(int)} methods
|
||||
* to get more control over the the size of the internal buffer</li>
|
||||
* <li>has a higher initial capacity (256) by default</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author Brian Clozel
|
||||
* @author Juergen Hoeller
|
||||
* @since 4.0
|
||||
*/
|
||||
public class ResizableByteArrayOutputStream extends OutputStream {
|
||||
public class ResizableByteArrayOutputStream extends ByteArrayOutputStream {
|
||||
|
||||
private static final int INITIAL_BUFFER_SIZE = 32;
|
||||
private static final int DEFAULT_INITIAL_CAPACITY = 256;
|
||||
|
||||
protected byte[] buffer;
|
||||
|
||||
protected int count;
|
||||
|
||||
/**
|
||||
* Create a new <code>ByteArrayOutputStream</code> with the default buffer size of 32 bytes.
|
||||
* Create a new <code>ResizableByteArrayOutputStream</code>
|
||||
* with the default initial capacity of 128 bytes.
|
||||
*/
|
||||
public ResizableByteArrayOutputStream() {
|
||||
this(INITIAL_BUFFER_SIZE);
|
||||
super(DEFAULT_INITIAL_CAPACITY);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new <code>ByteArrayOutputStream</code> with a specified initial buffer size.
|
||||
*
|
||||
* @param size The initial buffer size in bytes
|
||||
* Create a new <code>ResizableByteArrayOutputStream</code>
|
||||
* with the specified initial capacity.
|
||||
* @param initialCapacity the initial buffer size in bytes
|
||||
*/
|
||||
public ResizableByteArrayOutputStream(int size) {
|
||||
buffer = new byte[size];
|
||||
count = 0;
|
||||
public ResizableByteArrayOutputStream(int initialCapacity) {
|
||||
super(initialCapacity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the size of the internal buffer.
|
||||
*/
|
||||
public int size() {
|
||||
return buffer.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the number of bytes that have been written to the buffer so far.
|
||||
*/
|
||||
public int count() {
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discard all bytes written to the internal buffer by setting the <code>count</code> variable to 0.
|
||||
*/
|
||||
public void reset() {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow the internal buffer size
|
||||
* @param add number of bytes to add to the current buffer size
|
||||
* Resize the internal buffer size to a specified capacity.
|
||||
* @param targetCapacity the desired size of the buffer
|
||||
* @throws IllegalArgumentException if the given capacity is smaller than
|
||||
* the actual size of the content stored in the buffer already
|
||||
* @see ResizableByteArrayOutputStream#size()
|
||||
*/
|
||||
public void grow(int add) {
|
||||
if (count + add > buffer.length) {
|
||||
int newlen = Math.max(buffer.length * 2, count + add);
|
||||
resize(newlen);
|
||||
public synchronized void resize(int targetCapacity) {
|
||||
Assert.isTrue(targetCapacity >= this.count, "New capacity must not be smaller than current size");
|
||||
byte[] resizedBuffer = new byte[targetCapacity];
|
||||
System.arraycopy(this.buf, 0, resizedBuffer, 0, this.count);
|
||||
this.buf = resizedBuffer;
|
||||
}
|
||||
|
||||
/**
|
||||
* Grow the internal buffer size.
|
||||
* @param additionalCapacity the number of bytes to add to the current buffer size
|
||||
* @see ResizableByteArrayOutputStream#size()
|
||||
*/
|
||||
public synchronized void grow(int additionalCapacity) {
|
||||
Assert.isTrue(additionalCapacity >= 0, "Additional capacity must be 0 or higher");
|
||||
if (this.count + additionalCapacity > this.buf.length) {
|
||||
int newCapacity = Math.max(this.buf.length * 2, this.count + additionalCapacity);
|
||||
resize(newCapacity);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resize the internal buffer size to a specified value
|
||||
* @param size the size of the buffer
|
||||
* @throws java.lang.IllegalArgumentException if the given size is
|
||||
* smaller than the actual size of the content stored in the buffer
|
||||
* @see ResizableByteArrayOutputStream#size()
|
||||
* Return the current size of this stream's internal buffer.
|
||||
*/
|
||||
public void resize(int size) {
|
||||
Assert.isTrue(size >= count);
|
||||
|
||||
byte[] newbuf = new byte[size];
|
||||
System.arraycopy(buffer, 0, newbuf, 0, count);
|
||||
buffer = newbuf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the specified byte into the internal buffer, thus incrementing the
|
||||
* {{@link org.springframework.util.ResizableByteArrayOutputStream#count()}}
|
||||
* @param oneByte the byte to be written in the buffer
|
||||
* @see ResizableByteArrayOutputStream#count()
|
||||
*/
|
||||
public void write(int oneByte) {
|
||||
grow(1);
|
||||
buffer[count++] = (byte) oneByte;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write <code>add</code> bytes from the passed in array
|
||||
* <code>inBuffer</code> starting at index <code>offset</code> into the
|
||||
* internal buffer.
|
||||
*
|
||||
* @param inBuffer The byte array to write data from
|
||||
* @param offset The index into the buffer to start writing data from
|
||||
* @param add The number of bytes to write
|
||||
* @see ResizableByteArrayOutputStream#count()
|
||||
*/
|
||||
public void write(byte[] inBuffer, int offset, int add) {
|
||||
if (add >= 0) {
|
||||
grow(add);
|
||||
}
|
||||
System.arraycopy(inBuffer, offset, buffer, count, add);
|
||||
count += add;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write all bytes that have been written to the specified <code>OutputStream</code>.
|
||||
*
|
||||
* @param out The <code>OutputStream</code> to write to
|
||||
* @exception IOException If an error occurs
|
||||
*/
|
||||
public void writeTo(OutputStream out) throws IOException {
|
||||
out.write(buffer, 0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a byte array containing the bytes that have been written to this stream so far.
|
||||
*/
|
||||
public byte[] toByteArray() {
|
||||
byte[] ret = new byte[count];
|
||||
System.arraycopy(buffer, 0, ret, 0, count);
|
||||
return ret;
|
||||
public synchronized int capacity() {
|
||||
return this.buf.length;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2010 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -39,7 +39,7 @@ public abstract class SerializationUtils {
|
||||
if (object == null) {
|
||||
return null;
|
||||
}
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
|
||||
try {
|
||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||
oos.writeObject(object);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.util;
|
||||
|
||||
import org.junit.Before;
|
||||
@@ -22,56 +23,56 @@ import static org.junit.Assert.*;
|
||||
|
||||
/**
|
||||
* @author Brian Clozel
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class ResizableByteArrayOutputStreamTests {
|
||||
|
||||
private ResizableByteArrayOutputStream baos;
|
||||
private static final int INITIAL_CAPACITY = 256;
|
||||
|
||||
private String helloString;
|
||||
private ResizableByteArrayOutputStream baos;
|
||||
|
||||
private byte[] helloBytes;
|
||||
|
||||
private static final int INITIAL_SIZE = 32;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.baos = new ResizableByteArrayOutputStream(INITIAL_SIZE);
|
||||
this.helloString = "Hello World";
|
||||
this.helloBytes = helloString.getBytes("UTF-8");
|
||||
this.baos = new ResizableByteArrayOutputStream(INITIAL_CAPACITY);
|
||||
this.helloBytes = "Hello World".getBytes("UTF-8");
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void resize() throws Exception {
|
||||
assertEquals(INITIAL_SIZE, this.baos.buffer.length);
|
||||
assertEquals(INITIAL_CAPACITY, this.baos.capacity());
|
||||
this.baos.write(helloBytes);
|
||||
int size = 64;
|
||||
this.baos.resize(size);
|
||||
assertEquals(size, this.baos.buffer.length);
|
||||
assertByteArrayEqualsString(helloString, this.baos);
|
||||
assertEquals(size, this.baos.capacity());
|
||||
assertByteArrayEqualsString(this.baos);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void autoGrow() {
|
||||
assertEquals(INITIAL_SIZE, this.baos.buffer.length);
|
||||
for(int i= 0; i < 33; i++) {
|
||||
assertEquals(INITIAL_CAPACITY, this.baos.capacity());
|
||||
for(int i = 0; i < 129; i++) {
|
||||
this.baos.write(0);
|
||||
}
|
||||
assertEquals(64, this.baos.buffer.length);
|
||||
assertEquals(256, this.baos.capacity());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void grow() throws Exception {
|
||||
assertEquals(INITIAL_SIZE, this.baos.buffer.length);
|
||||
assertEquals(INITIAL_CAPACITY, this.baos.capacity());
|
||||
this.baos.write(helloBytes);
|
||||
this.baos.grow(100);
|
||||
assertEquals(this.helloString.length() + 100, this.baos.buffer.length);
|
||||
assertByteArrayEqualsString(helloString, this.baos);
|
||||
this.baos.grow(1000);
|
||||
assertEquals(this.helloBytes.length + 1000, this.baos.capacity());
|
||||
assertByteArrayEqualsString(this.baos);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void write() throws Exception{
|
||||
this.baos.write(helloBytes);
|
||||
assertByteArrayEqualsString(helloString, this.baos);
|
||||
assertByteArrayEqualsString(this.baos);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
@@ -80,9 +81,9 @@ public class ResizableByteArrayOutputStreamTests {
|
||||
this.baos.resize(5);
|
||||
}
|
||||
|
||||
private void assertByteArrayEqualsString(String expected, ResizableByteArrayOutputStream actual) {
|
||||
String actualString = new String(actual.buffer, 0, actual.count());
|
||||
assertEquals(expected, actualString);
|
||||
|
||||
private void assertByteArrayEqualsString(ResizableByteArrayOutputStream actual) {
|
||||
assertArrayEquals(helloBytes, actual.toByteArray());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user