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:
parent
05213c684c
commit
dd7f54c3c0
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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
|
@Override
|
||||||
public String convert(Properties source) {
|
public String convert(Properties source) {
|
||||||
try {
|
try {
|
||||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
ByteArrayOutputStream os = new ByteArrayOutputStream(256);
|
||||||
source.store(os, null);
|
source.store(os, null);
|
||||||
return os.toString("ISO-8859-1");
|
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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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
|
@Override
|
||||||
public byte[] convert(Object source) {
|
public byte[] convert(Object source) {
|
||||||
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(128);
|
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(256);
|
||||||
try {
|
try {
|
||||||
this.serializer.serialize(source, byteStream);
|
this.serializer.serialize(source, byteStream);
|
||||||
return byteStream.toByteArray();
|
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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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);
|
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;
|
private boolean styledFirstField;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,143 +13,79 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.util;
|
package org.springframework.util;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.OutputStream;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A variation of {@link java.io.ByteArrayOutputStream} that:
|
* An extension of {@link java.io.ByteArrayOutputStream} that:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>has public {@link org.springframework.util.ResizableByteArrayOutputStream#grow(int)} and
|
* <li>has public {@link org.springframework.util.ResizableByteArrayOutputStream#grow(int)}
|
||||||
* {@link org.springframework.util.ResizableByteArrayOutputStream#resize(int)} methods to get more control
|
* and {@link org.springframework.util.ResizableByteArrayOutputStream#resize(int)} methods
|
||||||
* over the the size of the internal buffer</li>
|
* 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
|
* <li>has a higher initial capacity (256) by default</li>
|
||||||
* to the buffer is expected</li>
|
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
|
* @author Juergen Hoeller
|
||||||
* @since 4.0
|
* @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() {
|
public ResizableByteArrayOutputStream() {
|
||||||
this(INITIAL_BUFFER_SIZE);
|
super(DEFAULT_INITIAL_CAPACITY);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new <code>ByteArrayOutputStream</code> with a specified initial buffer size.
|
* Create a new <code>ResizableByteArrayOutputStream</code>
|
||||||
*
|
* with the specified initial capacity.
|
||||||
* @param size The initial buffer size in bytes
|
* @param initialCapacity the initial buffer size in bytes
|
||||||
*/
|
*/
|
||||||
public ResizableByteArrayOutputStream(int size) {
|
public ResizableByteArrayOutputStream(int initialCapacity) {
|
||||||
buffer = new byte[size];
|
super(initialCapacity);
|
||||||
count = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
* Resize the internal buffer size to a specified capacity.
|
||||||
*/
|
* @param targetCapacity the desired size of the buffer
|
||||||
public int count() {
|
* @throws IllegalArgumentException if the given capacity is smaller than
|
||||||
return count;
|
* the actual size of the content stored in the buffer already
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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
|
|
||||||
* @see ResizableByteArrayOutputStream#size()
|
* @see ResizableByteArrayOutputStream#size()
|
||||||
*/
|
*/
|
||||||
public void grow(int add) {
|
public synchronized void resize(int targetCapacity) {
|
||||||
if (count + add > buffer.length) {
|
Assert.isTrue(targetCapacity >= this.count, "New capacity must not be smaller than current size");
|
||||||
int newlen = Math.max(buffer.length * 2, count + add);
|
byte[] resizedBuffer = new byte[targetCapacity];
|
||||||
resize(newlen);
|
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
|
* Return the current size of this stream's internal buffer.
|
||||||
* @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()
|
|
||||||
*/
|
*/
|
||||||
public void resize(int size) {
|
public synchronized int capacity() {
|
||||||
Assert.isTrue(size >= count);
|
return this.buf.length;
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with 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) {
|
if (object == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);
|
||||||
try {
|
try {
|
||||||
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
ObjectOutputStream oos = new ObjectOutputStream(baos);
|
||||||
oos.writeObject(object);
|
oos.writeObject(object);
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.util;
|
package org.springframework.util;
|
||||||
|
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
|
|
@ -22,56 +23,56 @@ import static org.junit.Assert.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Brian Clozel
|
* @author Brian Clozel
|
||||||
|
* @author Juergen Hoeller
|
||||||
*/
|
*/
|
||||||
public class ResizableByteArrayOutputStreamTests {
|
public class ResizableByteArrayOutputStreamTests {
|
||||||
|
|
||||||
private ResizableByteArrayOutputStream baos;
|
private static final int INITIAL_CAPACITY = 256;
|
||||||
|
|
||||||
private String helloString;
|
private ResizableByteArrayOutputStream baos;
|
||||||
|
|
||||||
private byte[] helloBytes;
|
private byte[] helloBytes;
|
||||||
|
|
||||||
private static final int INITIAL_SIZE = 32;
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
this.baos = new ResizableByteArrayOutputStream(INITIAL_SIZE);
|
this.baos = new ResizableByteArrayOutputStream(INITIAL_CAPACITY);
|
||||||
this.helloString = "Hello World";
|
this.helloBytes = "Hello World".getBytes("UTF-8");
|
||||||
this.helloBytes = helloString.getBytes("UTF-8");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void resize() throws Exception {
|
public void resize() throws Exception {
|
||||||
assertEquals(INITIAL_SIZE, this.baos.buffer.length);
|
assertEquals(INITIAL_CAPACITY, this.baos.capacity());
|
||||||
this.baos.write(helloBytes);
|
this.baos.write(helloBytes);
|
||||||
int size = 64;
|
int size = 64;
|
||||||
this.baos.resize(size);
|
this.baos.resize(size);
|
||||||
assertEquals(size, this.baos.buffer.length);
|
assertEquals(size, this.baos.capacity());
|
||||||
assertByteArrayEqualsString(helloString, this.baos);
|
assertByteArrayEqualsString(this.baos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void autoGrow() {
|
public void autoGrow() {
|
||||||
assertEquals(INITIAL_SIZE, this.baos.buffer.length);
|
assertEquals(INITIAL_CAPACITY, this.baos.capacity());
|
||||||
for(int i= 0; i < 33; i++) {
|
for(int i = 0; i < 129; i++) {
|
||||||
this.baos.write(0);
|
this.baos.write(0);
|
||||||
}
|
}
|
||||||
assertEquals(64, this.baos.buffer.length);
|
assertEquals(256, this.baos.capacity());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void grow() throws Exception {
|
public void grow() throws Exception {
|
||||||
assertEquals(INITIAL_SIZE, this.baos.buffer.length);
|
assertEquals(INITIAL_CAPACITY, this.baos.capacity());
|
||||||
this.baos.write(helloBytes);
|
this.baos.write(helloBytes);
|
||||||
this.baos.grow(100);
|
this.baos.grow(1000);
|
||||||
assertEquals(this.helloString.length() + 100, this.baos.buffer.length);
|
assertEquals(this.helloBytes.length + 1000, this.baos.capacity());
|
||||||
assertByteArrayEqualsString(helloString, this.baos);
|
assertByteArrayEqualsString(this.baos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void write() throws Exception{
|
public void write() throws Exception{
|
||||||
this.baos.write(helloBytes);
|
this.baos.write(helloBytes);
|
||||||
assertByteArrayEqualsString(helloString, this.baos);
|
assertByteArrayEqualsString(this.baos);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expected = IllegalArgumentException.class)
|
@Test(expected = IllegalArgumentException.class)
|
||||||
|
|
@ -80,9 +81,9 @@ public class ResizableByteArrayOutputStreamTests {
|
||||||
this.baos.resize(5);
|
this.baos.resize(5);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertByteArrayEqualsString(String expected, ResizableByteArrayOutputStream actual) {
|
|
||||||
String actualString = new String(actual.buffer, 0, actual.count());
|
private void assertByteArrayEqualsString(ResizableByteArrayOutputStream actual) {
|
||||||
assertEquals(expected, actualString);
|
assertArrayEquals(helloBytes, actual.toByteArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -218,7 +218,7 @@ public class MappingJackson2MessageConverter implements MessageConverter, BeanCl
|
||||||
protected BytesMessage mapToBytesMessage(Object object, Session session, ObjectMapper objectMapper)
|
protected BytesMessage mapToBytesMessage(Object object, Session session, ObjectMapper objectMapper)
|
||||||
throws JMSException, IOException {
|
throws JMSException, IOException {
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
|
||||||
OutputStreamWriter writer = new OutputStreamWriter(bos, this.encoding);
|
OutputStreamWriter writer = new OutputStreamWriter(bos, this.encoding);
|
||||||
objectMapper.writeValue(writer, object);
|
objectMapper.writeValue(writer, object);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -221,7 +221,7 @@ public class MappingJacksonMessageConverter implements MessageConverter, BeanCla
|
||||||
protected BytesMessage mapToBytesMessage(Object object, Session session, ObjectMapper objectMapper)
|
protected BytesMessage mapToBytesMessage(Object object, Session session, ObjectMapper objectMapper)
|
||||||
throws JMSException, IOException {
|
throws JMSException, IOException {
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
|
||||||
OutputStreamWriter writer = new OutputStreamWriter(bos, this.encoding);
|
OutputStreamWriter writer = new OutputStreamWriter(bos, this.encoding);
|
||||||
objectMapper.writeValue(writer, object);
|
objectMapper.writeValue(writer, object);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -231,7 +231,7 @@ public class MarshallingMessageConverter implements MessageConverter, Initializi
|
||||||
protected BytesMessage marshalToBytesMessage(Object object, Session session, Marshaller marshaller)
|
protected BytesMessage marshalToBytesMessage(Object object, Session session, Marshaller marshaller)
|
||||||
throws JMSException, IOException, XmlMappingException {
|
throws JMSException, IOException, XmlMappingException {
|
||||||
|
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
|
||||||
StreamResult streamResult = new StreamResult(bos);
|
StreamResult streamResult = new StreamResult(bos);
|
||||||
marshaller.marshal(object, streamResult);
|
marshaller.marshal(object, streamResult);
|
||||||
BytesMessage message = session.createBytesMessage();
|
BytesMessage message = session.createBytesMessage();
|
||||||
|
|
|
||||||
|
|
@ -181,7 +181,7 @@ public class MappingJackson2MessageConverter extends AbstractMessageConverter {
|
||||||
public Object convertToInternal(Object payload, MessageHeaders headers) {
|
public Object convertToInternal(Object payload, MessageHeaders headers) {
|
||||||
try {
|
try {
|
||||||
if (byte[].class.equals(getSerializedPayloadClass())) {
|
if (byte[].class.equals(getSerializedPayloadClass())) {
|
||||||
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
ByteArrayOutputStream out = new ByteArrayOutputStream(1024);
|
||||||
JsonEncoding encoding = getJsonEncoding(getMimeType(headers));
|
JsonEncoding encoding = getJsonEncoding(getMimeType(headers));
|
||||||
|
|
||||||
// The following has been deprecated as late as Jackson 2.2 (April 2013);
|
// The following has been deprecated as late as Jackson 2.2 (April 2013);
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,6 @@ import org.springframework.messaging.simp.SimpMessageType;
|
||||||
import org.springframework.messaging.support.MessageBuilder;
|
import org.springframework.messaging.support.MessageBuilder;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
import org.springframework.util.LinkedMultiValueMap;
|
||||||
import org.springframework.util.MultiValueMap;
|
import org.springframework.util.MultiValueMap;
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Decodes STOMP frames from a {@link ByteBuffer}. If the buffer does not contain
|
* Decodes STOMP frames from a {@link ByteBuffer}. If the buffer does not contain
|
||||||
|
|
@ -52,20 +51,15 @@ public class StompDecoder {
|
||||||
* Decodes a STOMP frame in the given {@code buffer} into a {@link Message}.
|
* Decodes a STOMP frame in the given {@code buffer} into a {@link Message}.
|
||||||
* If the given ByteBuffer contains partial STOMP frame content, the method
|
* If the given ByteBuffer contains partial STOMP frame content, the method
|
||||||
* resets the buffer and returns {@code null}.
|
* resets the buffer and returns {@code null}.
|
||||||
*
|
* @param buffer the buffer to decode the frame from
|
||||||
* @param buffer The buffer to decode the frame from
|
* @return the decoded message or {@code null}
|
||||||
*
|
|
||||||
* @return The decoded message or {@code null}
|
|
||||||
*/
|
*/
|
||||||
public Message<byte[]> decode(ByteBuffer buffer) {
|
public Message<byte[]> decode(ByteBuffer buffer) {
|
||||||
|
|
||||||
Message<byte[]> decodedMessage = null;
|
Message<byte[]> decodedMessage = null;
|
||||||
|
|
||||||
skipLeadingEol(buffer);
|
skipLeadingEol(buffer);
|
||||||
buffer.mark();
|
buffer.mark();
|
||||||
|
|
||||||
String command = readCommand(buffer);
|
String command = readCommand(buffer);
|
||||||
|
|
||||||
if (command.length() > 0) {
|
if (command.length() > 0) {
|
||||||
MultiValueMap<String, String> headers = readHeaders(buffer);
|
MultiValueMap<String, String> headers = readHeaders(buffer);
|
||||||
byte[] payload = readPayload(buffer, headers);
|
byte[] payload = readPayload(buffer, headers);
|
||||||
|
|
@ -108,7 +102,7 @@ public class StompDecoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String readCommand(ByteBuffer buffer) {
|
private String readCommand(ByteBuffer buffer) {
|
||||||
ByteArrayOutputStream command = new ByteArrayOutputStream();
|
ByteArrayOutputStream command = new ByteArrayOutputStream(256);
|
||||||
while (buffer.remaining() > 0 && !isEol(buffer)) {
|
while (buffer.remaining() > 0 && !isEol(buffer)) {
|
||||||
command.write(buffer.get());
|
command.write(buffer.get());
|
||||||
}
|
}
|
||||||
|
|
@ -118,7 +112,7 @@ public class StompDecoder {
|
||||||
private MultiValueMap<String, String> readHeaders(ByteBuffer buffer) {
|
private MultiValueMap<String, String> readHeaders(ByteBuffer buffer) {
|
||||||
MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
|
MultiValueMap<String, String> headers = new LinkedMultiValueMap<String, String>();
|
||||||
while (true) {
|
while (true) {
|
||||||
ByteArrayOutputStream headerStream = new ByteArrayOutputStream();
|
ByteArrayOutputStream headerStream = new ByteArrayOutputStream(256);
|
||||||
while (buffer.remaining() > 0 && !isEol(buffer)) {
|
while (buffer.remaining() > 0 && !isEol(buffer)) {
|
||||||
headerStream.write(buffer.get());
|
headerStream.write(buffer.get());
|
||||||
}
|
}
|
||||||
|
|
@ -176,7 +170,7 @@ public class StompDecoder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ByteArrayOutputStream payload = new ByteArrayOutputStream();
|
ByteArrayOutputStream payload = new ByteArrayOutputStream(256);
|
||||||
while (buffer.remaining() > 0) {
|
while (buffer.remaining() > 0) {
|
||||||
byte b = buffer.get();
|
byte b = buffer.get();
|
||||||
if (b == 0) {
|
if (b == 0) {
|
||||||
|
|
@ -208,4 +202,5 @@ public class StompDecoder {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -26,6 +26,7 @@ import java.util.Map.Entry;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
import org.springframework.messaging.Message;
|
import org.springframework.messaging.Message;
|
||||||
import org.springframework.messaging.simp.SimpMessageType;
|
import org.springframework.messaging.simp.SimpMessageType;
|
||||||
|
|
||||||
|
|
@ -45,23 +46,22 @@ public final class StompEncoder {
|
||||||
|
|
||||||
private final Log logger = LogFactory.getLog(StompEncoder.class);
|
private final Log logger = LogFactory.getLog(StompEncoder.class);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encodes the given STOMP {@code message} into a {@code byte[]}
|
* Encodes the given STOMP {@code message} into a {@code byte[]}
|
||||||
*
|
* @param message the message to encode
|
||||||
* @param message The message to encode
|
* @return the encoded message
|
||||||
*
|
|
||||||
* @return The encoded message
|
|
||||||
*/
|
*/
|
||||||
public byte[] encode(Message<byte[]> message) {
|
public byte[] encode(Message<byte[]> message) {
|
||||||
try {
|
try {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(256);
|
||||||
DataOutputStream output = new DataOutputStream(baos);
|
DataOutputStream output = new DataOutputStream(baos);
|
||||||
|
|
||||||
StompHeaderAccessor headers = StompHeaderAccessor.wrap(message);
|
StompHeaderAccessor headers = StompHeaderAccessor.wrap(message);
|
||||||
|
|
||||||
if (isHeartbeat(headers)) {
|
if (isHeartbeat(headers)) {
|
||||||
output.write(message.getPayload());
|
output.write(message.getPayload());
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
writeCommand(headers, output);
|
writeCommand(headers, output);
|
||||||
writeHeaders(headers, message, output);
|
writeHeaders(headers, message, output);
|
||||||
output.write(LF);
|
output.write(LF);
|
||||||
|
|
@ -77,7 +77,7 @@ public final class StompEncoder {
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isHeartbeat(StompHeaderAccessor headers) {
|
private boolean isHeartbeat(StompHeaderAccessor headers) {
|
||||||
return headers.getMessageType() == SimpMessageType.HEARTBEAT;
|
return (headers.getMessageType() == SimpMessageType.HEARTBEAT);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void writeCommand(StompHeaderAccessor headers, DataOutputStream output) throws IOException {
|
private void writeCommand(StompHeaderAccessor headers, DataOutputStream output) throws IOException {
|
||||||
|
|
@ -132,4 +132,5 @@ public final class StompEncoder {
|
||||||
.replaceAll("\n", "\\\\n")
|
.replaceAll("\n", "\\\\n")
|
||||||
.replaceAll("\r", "\\\\r");
|
.replaceAll("\r", "\\\\r");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -336,7 +336,7 @@ public class JibxMarshaller extends AbstractMarshaller implements InitializingBe
|
||||||
|
|
||||||
private void transformAndMarshal(Object graph, Result result) throws IOException {
|
private void transformAndMarshal(Object graph, Result result) throws IOException {
|
||||||
try {
|
try {
|
||||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
|
||||||
marshalOutputStream(graph, os);
|
marshalOutputStream(graph, os);
|
||||||
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
|
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
|
||||||
Transformer transformer = this.transformerFactory.newTransformer();
|
Transformer transformer = this.transformerFactory.newTransformer();
|
||||||
|
|
@ -424,7 +424,7 @@ public class JibxMarshaller extends AbstractMarshaller implements InitializingBe
|
||||||
if (encoding != null) {
|
if (encoding != null) {
|
||||||
transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
|
transformer.setOutputProperty(OutputKeys.ENCODING, encoding);
|
||||||
}
|
}
|
||||||
ByteArrayOutputStream os = new ByteArrayOutputStream();
|
ByteArrayOutputStream os = new ByteArrayOutputStream(1024);
|
||||||
transformer.transform(source, new StreamResult(os));
|
transformer.transform(source, new StreamResult(os));
|
||||||
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
|
ByteArrayInputStream is = new ByteArrayInputStream(os.toByteArray());
|
||||||
return unmarshalInputStream(is);
|
return unmarshalInputStream(is);
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -13,6 +13,7 @@
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.springframework.mock.http;
|
package org.springframework.mock.http;
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
|
|
@ -36,7 +37,7 @@ public class MockHttpOutputMessage implements HttpOutputMessage {
|
||||||
|
|
||||||
private final HttpHeaders headers = new HttpHeaders();
|
private final HttpHeaders headers = new HttpHeaders();
|
||||||
|
|
||||||
private final ByteArrayOutputStream body = new ByteArrayOutputStream();
|
private final ByteArrayOutputStream body = new ByteArrayOutputStream(1024);
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -76,7 +77,6 @@ public class MockHttpOutputMessage implements HttpOutputMessage {
|
||||||
public String getBodyAsString(Charset charset) {
|
public String getBodyAsString(Charset charset) {
|
||||||
byte[] bytes = getBodyAsBytes();
|
byte[] bytes = getBodyAsBytes();
|
||||||
try {
|
try {
|
||||||
// Use
|
|
||||||
return new String(bytes, charset.name());
|
return new String(bytes, charset.name());
|
||||||
}
|
}
|
||||||
catch (UnsupportedEncodingException ex) {
|
catch (UnsupportedEncodingException ex) {
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -71,7 +71,7 @@ public class MockHttpServletResponse implements HttpServletResponse {
|
||||||
|
|
||||||
private boolean charset = false;
|
private boolean charset = false;
|
||||||
|
|
||||||
private final ByteArrayOutputStream content = new ByteArrayOutputStream();
|
private final ByteArrayOutputStream content = new ByteArrayOutputStream(1024);
|
||||||
|
|
||||||
private final ServletOutputStream outputStream = new ResponseServletOutputStream(this.content);
|
private final ServletOutputStream outputStream = new ResponseServletOutputStream(this.content);
|
||||||
|
|
||||||
|
|
@ -189,8 +189,8 @@ public class MockHttpServletResponse implements HttpServletResponse {
|
||||||
|
|
||||||
public String getContentAsString() throws UnsupportedEncodingException {
|
public String getContentAsString() throws UnsupportedEncodingException {
|
||||||
flushBuffer();
|
flushBuffer();
|
||||||
return (this.characterEncoding != null) ?
|
return (this.characterEncoding != null ?
|
||||||
this.content.toString(this.characterEncoding) : this.content.toString();
|
this.content.toString(this.characterEncoding) : this.content.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -218,8 +218,7 @@ public class MockHttpServletResponse implements HttpServletResponse {
|
||||||
if (contentType != null) {
|
if (contentType != null) {
|
||||||
int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
|
int charsetIndex = contentType.toLowerCase().indexOf(CHARSET_PREFIX);
|
||||||
if (charsetIndex != -1) {
|
if (charsetIndex != -1) {
|
||||||
String encoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length());
|
this.characterEncoding = contentType.substring(charsetIndex + CHARSET_PREFIX.length());
|
||||||
this.characterEncoding = encoding;
|
|
||||||
this.charset = true;
|
this.charset = true;
|
||||||
}
|
}
|
||||||
updateContentTypeHeader();
|
updateContentTypeHeader();
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -56,7 +56,7 @@ public class MockMimeResponse extends MockPortletResponse implements MimeRespons
|
||||||
|
|
||||||
private int bufferSize = 4096;
|
private int bufferSize = 4096;
|
||||||
|
|
||||||
private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
|
private final ByteArrayOutputStream outputStream = new ByteArrayOutputStream(1024);
|
||||||
|
|
||||||
private final CacheControl cacheControl = new MockCacheControl();
|
private final CacheControl cacheControl = new MockCacheControl();
|
||||||
|
|
||||||
|
|
@ -130,9 +130,9 @@ public class MockMimeResponse extends MockPortletResponse implements MimeRespons
|
||||||
@Override
|
@Override
|
||||||
public PrintWriter getWriter() throws UnsupportedEncodingException {
|
public PrintWriter getWriter() throws UnsupportedEncodingException {
|
||||||
if (this.writer == null) {
|
if (this.writer == null) {
|
||||||
Writer targetWriter = (this.characterEncoding != null
|
Writer targetWriter = (this.characterEncoding != null ?
|
||||||
? new OutputStreamWriter(this.outputStream, this.characterEncoding)
|
new OutputStreamWriter(this.outputStream, this.characterEncoding) :
|
||||||
: new OutputStreamWriter(this.outputStream));
|
new OutputStreamWriter(this.outputStream));
|
||||||
this.writer = new PrintWriter(targetWriter);
|
this.writer = new PrintWriter(targetWriter);
|
||||||
}
|
}
|
||||||
return this.writer;
|
return this.writer;
|
||||||
|
|
@ -145,9 +145,8 @@ public class MockMimeResponse extends MockPortletResponse implements MimeRespons
|
||||||
|
|
||||||
public String getContentAsString() throws UnsupportedEncodingException {
|
public String getContentAsString() throws UnsupportedEncodingException {
|
||||||
flushBuffer();
|
flushBuffer();
|
||||||
return (this.characterEncoding != null)
|
return (this.characterEncoding != null ?
|
||||||
? this.outputStream.toString(this.characterEncoding)
|
this.outputStream.toString(this.characterEncoding) : this.outputStream.toString());
|
||||||
: this.outputStream.toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setLocale(Locale locale) {
|
public void setLocale(Locale locale) {
|
||||||
|
|
@ -174,13 +173,11 @@ public class MockMimeResponse extends MockPortletResponse implements MimeRespons
|
||||||
if (this.writer != null) {
|
if (this.writer != null) {
|
||||||
this.writer.flush();
|
this.writer.flush();
|
||||||
}
|
}
|
||||||
if (this.outputStream != null) {
|
try {
|
||||||
try {
|
this.outputStream.flush();
|
||||||
this.outputStream.flush();
|
}
|
||||||
}
|
catch (IOException ex) {
|
||||||
catch (IOException ex) {
|
throw new IllegalStateException("Could not flush OutputStream: " + ex.getMessage());
|
||||||
throw new IllegalStateException("Could not flush OutputStream: " + ex.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
this.committed = true;
|
this.committed = true;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -32,7 +32,7 @@ import org.springframework.util.concurrent.ListenableFuture;
|
||||||
*/
|
*/
|
||||||
abstract class AbstractBufferingAsyncClientHttpRequest extends AbstractAsyncClientHttpRequest {
|
abstract class AbstractBufferingAsyncClientHttpRequest extends AbstractAsyncClientHttpRequest {
|
||||||
|
|
||||||
private ByteArrayOutputStream bufferedOutput = new ByteArrayOutputStream();
|
private ByteArrayOutputStream bufferedOutput = new ByteArrayOutputStream(1024);
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -31,7 +31,7 @@ import org.springframework.http.HttpHeaders;
|
||||||
*/
|
*/
|
||||||
abstract class AbstractBufferingClientHttpRequest extends AbstractClientHttpRequest {
|
abstract class AbstractBufferingClientHttpRequest extends AbstractClientHttpRequest {
|
||||||
|
|
||||||
private ByteArrayOutputStream bufferedOutput = new ByteArrayOutputStream();
|
private ByteArrayOutputStream bufferedOutput = new ByteArrayOutputStream(1024);
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2002-2013 the original author or authors.
|
* Copyright 2002-2014 the original author or authors.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -27,9 +27,9 @@ import org.springframework.util.StreamUtils;
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link HttpMessageConverter} that can read and write byte arrays.
|
* Implementation of {@link HttpMessageConverter} that can read and write byte arrays.
|
||||||
*
|
*
|
||||||
* <p>By default, this converter supports all media types ({@code */*}), and writes with a {@code
|
* <p>By default, this converter supports all media types ({@code */*}), and
|
||||||
* Content-Type} of {@code application/octet-stream}. This can be overridden by setting the {@link
|
* writes with a {@code Content-Type} of {@code application/octet-stream}. This can be
|
||||||
* #setSupportedMediaTypes(java.util.List) supportedMediaTypes} property.
|
* overridden by setting the {@link #setSupportedMediaTypes supportedMediaTypes} property.
|
||||||
*
|
*
|
||||||
* @author Arjen Poutsma
|
* @author Arjen Poutsma
|
||||||
* @since 3.0
|
* @since 3.0
|
||||||
|
|
@ -49,7 +49,8 @@ public class ByteArrayHttpMessageConverter extends AbstractHttpMessageConverter<
|
||||||
@Override
|
@Override
|
||||||
public byte[] readInternal(Class<? extends byte[]> clazz, HttpInputMessage inputMessage) throws IOException {
|
public byte[] readInternal(Class<? extends byte[]> clazz, HttpInputMessage inputMessage) throws IOException {
|
||||||
long contentLength = inputMessage.getHeaders().getContentLength();
|
long contentLength = inputMessage.getHeaders().getContentLength();
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream(contentLength >= 0 ? (int) contentLength : StreamUtils.BUFFER_SIZE);
|
ByteArrayOutputStream bos =
|
||||||
|
new ByteArrayOutputStream(contentLength >= 0 ? (int) contentLength : StreamUtils.BUFFER_SIZE);
|
||||||
StreamUtils.copy(inputMessage.getBody(), bos);
|
StreamUtils.copy(inputMessage.getBody(), bos);
|
||||||
return bos.toByteArray();
|
return bos.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -34,7 +34,6 @@ import java.util.HashMap;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.servlet.http.HttpServletRequest;
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
|
||||||
import org.springframework.http.HttpHeaders;
|
import org.springframework.http.HttpHeaders;
|
||||||
|
|
@ -56,6 +55,7 @@ public class ServletServerHttpRequest implements ServerHttpRequest {
|
||||||
|
|
||||||
private static final String METHOD_POST = "POST";
|
private static final String METHOD_POST = "POST";
|
||||||
|
|
||||||
|
|
||||||
private final HttpServletRequest servletRequest;
|
private final HttpServletRequest servletRequest;
|
||||||
|
|
||||||
private HttpHeaders headers;
|
private HttpHeaders headers;
|
||||||
|
|
@ -167,7 +167,7 @@ public class ServletServerHttpRequest implements ServerHttpRequest {
|
||||||
* to access a parameter thus causing the input stream to be "consumed".
|
* to access a parameter thus causing the input stream to be "consumed".
|
||||||
*/
|
*/
|
||||||
private InputStream getBodyFromServletRequestParameters(HttpServletRequest request) throws IOException {
|
private InputStream getBodyFromServletRequestParameters(HttpServletRequest request) throws IOException {
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
|
||||||
Writer writer = new OutputStreamWriter(bos, FORM_CHARSET);
|
Writer writer = new OutputStreamWriter(bos, FORM_CHARSET);
|
||||||
|
|
||||||
Map<String, String[]> form = request.getParameterMap();
|
Map<String, String[]> form = request.getParameterMap();
|
||||||
|
|
|
||||||
|
|
@ -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");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
|
|
@ -21,7 +21,6 @@ import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
|
|
||||||
import javax.servlet.FilterChain;
|
import javax.servlet.FilterChain;
|
||||||
import javax.servlet.ServletException;
|
import javax.servlet.ServletException;
|
||||||
import javax.servlet.ServletInputStream;
|
import javax.servlet.ServletInputStream;
|
||||||
|
|
@ -53,9 +52,9 @@ import org.springframework.web.util.WebUtils;
|
||||||
* @author Rob Harrop
|
* @author Rob Harrop
|
||||||
* @author Juergen Hoeller
|
* @author Juergen Hoeller
|
||||||
* @author Rossen Stoyanchev
|
* @author Rossen Stoyanchev
|
||||||
|
* @since 1.2.5
|
||||||
* @see #beforeRequest
|
* @see #beforeRequest
|
||||||
* @see #afterRequest
|
* @see #afterRequest
|
||||||
* @since 1.2.5
|
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter {
|
public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
|
@ -69,6 +68,7 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter
|
||||||
|
|
||||||
private static final int DEFAULT_MAX_PAYLOAD_LENGTH = 50;
|
private static final int DEFAULT_MAX_PAYLOAD_LENGTH = 50;
|
||||||
|
|
||||||
|
|
||||||
private boolean includeQueryString = false;
|
private boolean includeQueryString = false;
|
||||||
|
|
||||||
private boolean includeClientInfo = false;
|
private boolean includeClientInfo = false;
|
||||||
|
|
@ -85,6 +85,7 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter
|
||||||
|
|
||||||
private String afterMessageSuffix = DEFAULT_AFTER_MESSAGE_SUFFIX;
|
private String afterMessageSuffix = DEFAULT_AFTER_MESSAGE_SUFFIX;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set whether or not the query string should be included in the log message. <p>Should be configured using an
|
* Set whether or not the query string should be included in the log message. <p>Should be configured using an
|
||||||
* {@code <init-param>} for parameter name "includeQueryString" in the filter definition in
|
* {@code <init-param>} for parameter name "includeQueryString" in the filter definition in
|
||||||
|
|
@ -177,6 +178,7 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter
|
||||||
this.afterMessageSuffix = afterMessageSuffix;
|
this.afterMessageSuffix = afterMessageSuffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The default value is "false" so that the filter may log a "before" message
|
* The default value is "false" so that the filter may log a "before" message
|
||||||
* at the start of request processing and an "after" message at the end from
|
* at the start of request processing and an "after" message at the end from
|
||||||
|
|
@ -188,9 +190,8 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Forwards the request to the next filter in the chain and delegates down to the subclasses to perform the actual
|
* Forwards the request to the next filter in the chain and delegates down to the subclasses
|
||||||
* request logging both before and after the request is processed.
|
* to perform the actual request logging both before and after the request is processed.
|
||||||
*
|
|
||||||
* @see #beforeRequest
|
* @see #beforeRequest
|
||||||
* @see #afterRequest
|
* @see #afterRequest
|
||||||
*/
|
*/
|
||||||
|
|
@ -221,7 +222,6 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the message to write to the log before the request.
|
* Get the message to write to the log before the request.
|
||||||
*
|
|
||||||
* @see #createMessage
|
* @see #createMessage
|
||||||
*/
|
*/
|
||||||
private String getBeforeMessage(HttpServletRequest request) {
|
private String getBeforeMessage(HttpServletRequest request) {
|
||||||
|
|
@ -230,7 +230,6 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the message to write to the log after the request.
|
* Get the message to write to the log after the request.
|
||||||
*
|
|
||||||
* @see #createMessage
|
* @see #createMessage
|
||||||
*/
|
*/
|
||||||
private String getAfterMessage(HttpServletRequest request) {
|
private String getAfterMessage(HttpServletRequest request) {
|
||||||
|
|
@ -238,10 +237,12 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a log message for the given request, prefix and suffix. <p>If {@code includeQueryString} is
|
* Create a log message for the given request, prefix and suffix.
|
||||||
* {@code true} then the inner part of the log message will take the form {@code request_uri?query_string}
|
* <p>If {@code includeQueryString} is {@code true}, then the inner part
|
||||||
* otherwise the message will simply be of the form {@code request_uri}. <p>The final message is composed of the
|
* of the log message will take the form {@code request_uri?query_string};
|
||||||
* inner part as described and the supplied prefix and suffix.
|
* otherwise the message will simply be of the form {@code request_uri}.
|
||||||
|
* <p>The final message is composed of the inner part as described and
|
||||||
|
* the supplied prefix and suffix.
|
||||||
*/
|
*/
|
||||||
protected String createMessage(HttpServletRequest request, String prefix, String suffix) {
|
protected String createMessage(HttpServletRequest request, String prefix, String suffix) {
|
||||||
StringBuilder msg = new StringBuilder();
|
StringBuilder msg = new StringBuilder();
|
||||||
|
|
@ -285,16 +286,16 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete subclasses should implement this method to write a log message <i>before</i> the request is processed.
|
* Concrete subclasses should implement this method to write a log message
|
||||||
*
|
* <i>before</i> the request is processed.
|
||||||
* @param request current HTTP request
|
* @param request current HTTP request
|
||||||
* @param message the message to log
|
* @param message the message to log
|
||||||
*/
|
*/
|
||||||
protected abstract void beforeRequest(HttpServletRequest request, String message);
|
protected abstract void beforeRequest(HttpServletRequest request, String message);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concrete subclasses should implement this method to write a log message <i>after</i> the request is processed.
|
* Concrete subclasses should implement this method to write a log message
|
||||||
*
|
* <i>after</i> the request is processed.
|
||||||
* @param request current HTTP request
|
* @param request current HTTP request
|
||||||
* @param message the message to log
|
* @param message the message to log
|
||||||
*/
|
*/
|
||||||
|
|
@ -303,7 +304,7 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter
|
||||||
|
|
||||||
private static class RequestCachingRequestWrapper extends HttpServletRequestWrapper {
|
private static class RequestCachingRequestWrapper extends HttpServletRequestWrapper {
|
||||||
|
|
||||||
private final ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
private final ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
|
||||||
|
|
||||||
private final ServletInputStream inputStream;
|
private final ServletInputStream inputStream;
|
||||||
|
|
||||||
|
|
@ -316,19 +317,19 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServletInputStream getInputStream() throws IOException {
|
public ServletInputStream getInputStream() throws IOException {
|
||||||
return inputStream;
|
return this.inputStream;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getCharacterEncoding() {
|
public String getCharacterEncoding() {
|
||||||
return super.getCharacterEncoding() != null ? super.getCharacterEncoding() :
|
String enc = super.getCharacterEncoding();
|
||||||
WebUtils.DEFAULT_CHARACTER_ENCODING;
|
return (enc != null ? enc : WebUtils.DEFAULT_CHARACTER_ENCODING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BufferedReader getReader() throws IOException {
|
public BufferedReader getReader() throws IOException {
|
||||||
if (this.reader == null) {
|
if (this.reader == null) {
|
||||||
this.reader = new BufferedReader(new InputStreamReader(inputStream, getCharacterEncoding()));
|
this.reader = new BufferedReader(new InputStreamReader(this.inputStream, getCharacterEncoding()));
|
||||||
}
|
}
|
||||||
return this.reader;
|
return this.reader;
|
||||||
}
|
}
|
||||||
|
|
@ -337,17 +338,18 @@ public abstract class AbstractRequestLoggingFilter extends OncePerRequestFilter
|
||||||
return this.bos.toByteArray();
|
return this.bos.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class RequestCachingInputStream extends ServletInputStream {
|
private class RequestCachingInputStream extends ServletInputStream {
|
||||||
|
|
||||||
private final ServletInputStream is;
|
private final ServletInputStream is;
|
||||||
|
|
||||||
private RequestCachingInputStream(ServletInputStream is) {
|
public RequestCachingInputStream(ServletInputStream is) {
|
||||||
this.is = is;
|
this.is = is;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int read() throws IOException {
|
public int read() throws IOException {
|
||||||
int ch = is.read();
|
int ch = this.is.read();
|
||||||
if (ch != -1) {
|
if (ch != -1) {
|
||||||
bos.write(ch);
|
bos.write(ch);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,8 +29,8 @@ import javax.servlet.http.HttpServletResponseWrapper;
|
||||||
|
|
||||||
import org.springframework.http.HttpMethod;
|
import org.springframework.http.HttpMethod;
|
||||||
import org.springframework.util.Assert;
|
import org.springframework.util.Assert;
|
||||||
import org.springframework.util.ResizableByteArrayOutputStream;
|
|
||||||
import org.springframework.util.DigestUtils;
|
import org.springframework.util.DigestUtils;
|
||||||
|
import org.springframework.util.ResizableByteArrayOutputStream;
|
||||||
import org.springframework.util.StreamUtils;
|
import org.springframework.util.StreamUtils;
|
||||||
import org.springframework.web.util.WebUtils;
|
import org.springframework.web.util.WebUtils;
|
||||||
|
|
||||||
|
|
@ -175,7 +175,7 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter {
|
||||||
*/
|
*/
|
||||||
private static class ShallowEtagResponseWrapper extends HttpServletResponseWrapper {
|
private static class ShallowEtagResponseWrapper extends HttpServletResponseWrapper {
|
||||||
|
|
||||||
private final ResizableByteArrayOutputStream content = new ResizableByteArrayOutputStream();
|
private final ResizableByteArrayOutputStream content = new ResizableByteArrayOutputStream(1024);
|
||||||
|
|
||||||
private final ServletOutputStream outputStream = new ResponseServletOutputStream();
|
private final ServletOutputStream outputStream = new ResponseServletOutputStream();
|
||||||
|
|
||||||
|
|
@ -232,22 +232,22 @@ public class ShallowEtagHeaderFilter extends OncePerRequestFilter {
|
||||||
return this.writer;
|
return this.writer;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void resetBuffer() {
|
|
||||||
this.content.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reset() {
|
public void reset() {
|
||||||
super.reset();
|
super.reset();
|
||||||
resetBuffer();
|
resetBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
private int getStatusCode() {
|
@Override
|
||||||
|
public void resetBuffer() {
|
||||||
|
this.content.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getStatusCode() {
|
||||||
return this.statusCode;
|
return this.statusCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
private byte[] toByteArray() {
|
public byte[] toByteArray() {
|
||||||
return this.content.toByteArray();
|
return this.content.toByteArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -104,7 +104,7 @@ public class MarshallingView extends AbstractView {
|
||||||
if (toBeMarshalled == null) {
|
if (toBeMarshalled == null) {
|
||||||
throw new IllegalStateException("Unable to locate object to be marshalled in model: " + model);
|
throw new IllegalStateException("Unable to locate object to be marshalled in model: " + model);
|
||||||
}
|
}
|
||||||
ByteArrayOutputStream bos = new ByteArrayOutputStream(2048);
|
ByteArrayOutputStream bos = new ByteArrayOutputStream(1024);
|
||||||
this.marshaller.marshal(toBeMarshalled, new StreamResult(bos));
|
this.marshaller.marshal(toBeMarshalled, new StreamResult(bos));
|
||||||
|
|
||||||
setResponseContentType(request, response);
|
setResponseContentType(request, response);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue