webwork/src/main/webwork/util FastByteArrayOutputStream.java, 1.4, 1.5
[email protected] Wed, 16 Jan 2008 02:54:07 -0800
| Newsgroups | gmane.comp.java.open-symphony.cvs |
|---|---|
| Message-ID | <[email protected]> |
--===============0742283853==
Update of /cvsroot/opensymphony/webwork/src/main/webwork/util
In directory sc8-pr-cvs3.sourceforge.net:/tmp/cvs-serv9103/main/webwork/util
Modified Files:
FastByteArrayOutputStream.java
Log Message:
Fix encoding so that multi-byte characters don't mess up webwork's tags.
This fixes WW-1495 for the 1.4 webwork branch.
Patch courtesy of Brad Baker from Atlassian.
Index: FastByteArrayOutputStream.java
===================================================================
RCS file: /cvsroot/opensymphony/webwork/src/main/webwork/util/FastByteArrayOutputStream.java,v
retrieving revision 1.4
retrieving revision 1.5
diff -u -d -r1.4 -r1.5
--- FastByteArrayOutputStream.java 16 Feb 2004 17:31:29 -0000 1.4
+++ FastByteArrayOutputStream.java 16 Jan 2008 10:54:04 -0000 1.5
@@ -6,10 +6,12 @@
*/
package webwork.util;
-import javax.servlet.jsp.JspWriter;
-import java.io.*;
-import java.util.LinkedList;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.RandomAccessFile;
import java.util.Iterator;
+import java.util.LinkedList;
+import javax.servlet.jsp.JspWriter;
/**
* A speedy implementation of ByteArrayOutputStream. It's not synchronized, and it
@@ -19,200 +21,253 @@
* @author Rickard �berg
* @version $Revision$
*/
-public class FastByteArrayOutputStream
- extends OutputStream
+public class FastByteArrayOutputStream extends OutputStream
{
- // Static --------------------------------------------------------
- private static final int DEFAULT_BLOCK_SIZE = 8192;
+ // Static --------------------------------------------------------
+ private static final int DEFAULT_BLOCK_SIZE = 8192;
- // Attributes ----------------------------------------------------
- // internal buffer
- private byte[] buffer;
- private LinkedList buffers;
- private int index;
- private int size;
- private int blockSize;
- // is the stream closed?
- private boolean closed;
+ // Attributes ----------------------------------------------------
+ // internal buffer
+ byte[] buffer;
+ LinkedList buffers;
+ int index;
+ int size;
+ int blockSize;
+ // is the stream closed?
+ boolean closed;
- // Constructors --------------------------------------------------
- public FastByteArrayOutputStream()
- {
- this(DEFAULT_BLOCK_SIZE);
- }
+ // Constructors --------------------------------------------------
+ public FastByteArrayOutputStream()
+ {
+ this(DEFAULT_BLOCK_SIZE);
+ }
- public FastByteArrayOutputStream(int aSize)
- {
- blockSize = aSize;
- buffer = new byte[blockSize];
- }
+ public FastByteArrayOutputStream(int aSize)
+ {
+ blockSize = aSize;
+ buffer = new byte[blockSize];
+ }
- // Public
- public void writeTo(OutputStream out) throws IOException
- {
- // Check if we have a list of buffers
- if (buffers != null)
- {
- Iterator iterator = buffers.iterator();
- while (iterator.hasNext())
- {
- byte[] bytes = (byte[]) iterator.next();
- out.write(bytes, 0, blockSize);
- }
- }
+ // Public
+ public void writeTo(OutputStream out) throws IOException
+ {
+ // Check if we have a list of buffers
+ if (buffers != null)
+ {
+ Iterator iterator = buffers.iterator();
+ while (iterator.hasNext())
+ {
+ byte[] bytes = (byte[]) iterator.next();
+ out.write(bytes, 0, blockSize);
+ }
+ }
- // write the internal buffer directly
- out.write(buffer, 0, index);
- }
+ // write the internal buffer directly
+ out.write(buffer, 0, index);
+ }
- public void writeTo(RandomAccessFile out) throws IOException
- {
- // Check if we have a list of buffers
- if (buffers != null)
- {
- Iterator iterator = buffers.iterator();
- while (iterator.hasNext())
- {
- byte[] bytes = (byte[]) iterator.next();
- out.write(bytes, 0, blockSize);
- }
- }
+ public void writeTo(RandomAccessFile out) throws IOException
+ {
+ // Check if we have a list of buffers
+ if (buffers != null)
+ {
+ Iterator iterator = buffers.iterator();
+ while (iterator.hasNext())
+ {
+ byte[] bytes = (byte[]) iterator.next();
+ out.write(bytes, 0, blockSize);
+ }
+ }
- // write the internal buffer directly
- out.write(buffer, 0, index);
- }
+ // write the internal buffer directly
+ out.write(buffer, 0, index);
+ }
- public void writeTo(JspWriter out, String encoding) throws IOException
- {
- // Check if we have a list of buffers
- if (buffers != null)
- {
- Iterator iterator = buffers.iterator();
- while (iterator.hasNext())
- {
- byte[] bytes = (byte[]) iterator.next();
+ public void writeTo(final JspWriter out, String encoding) throws IOException
+ {
+ /*
+ There is design tradeoff between being fast, correct and using too much memory when decoding bytes to strings.
- if (encoding != null)
- out.write(new String(bytes, encoding));
- else
- out.write(new String(bytes));
- }
- }
+ The rules are thus :
- // write the internal buffer directly
- if (encoding != null)
- out.write(new String(buffer, 0, index, encoding));
- else
- out.write(new String(buffer, 0, index));
- }
+ 1. if there is only one buffer then its a simple String conversion
- public int getSize()
- {
- return size+index;
- }
+ REASON : Fast!!!
- public byte[] toByteArray()
- {
- byte[] data = new byte[getSize()];
+ 2. uses full buffer allocation annd System.arrayCopy() to smooosh together the bytes
+ and then use String conversion
- // Check if we have a list of buffers
- int pos = 0;
- if (buffers != null)
- {
- Iterator iterator = buffers.iterator();
- while (iterator.hasNext())
- {
- byte[] bytes = (byte[]) iterator.next();
- System.arraycopy(bytes,0,data,pos,blockSize);
- pos+=blockSize;
- }
- }
+ REASON : Fast at the expense of a known amount of memory (eg the used memory * 2)
+ */
+ if (buffers != null)
+ {
+ // RULE 2 : a balance between using some memory and speed
+ writeToViaSmoosh(out, encoding);
+ }
+ else
+ {
+ // RULE 1 : fastest!
+ writeToViaString(out, encoding);
+ }
+ }
- // write the internal buffer directly
- System.arraycopy(buffer, 0, data, pos, index);
+ /**
+ * This can ONLY be called if there is only a single buffer to write.
+ *
+ * @param out the JspWriter
+ * @param encoding the encoding
+ * @throws IOException
+ */
+ void writeToViaString(JspWriter out, String encoding) throws IOException
+ {
+ byte[] bufferToWrite = buffer; // this is always the last buffer to write
+ int bufferToWriteLen = index; // index points to our place in the last buffer
+ writeToImpl(out, encoding, bufferToWrite, bufferToWriteLen);
+ }
- return data;
- }
+ void writeToViaSmoosh(JspWriter out, String encoding) throws IOException
+ {
+ byte[] bufferToWrite = toByteArray();
+ int bufferToWriteLen = bufferToWrite.length;
+ writeToImpl(out, encoding, bufferToWrite, bufferToWriteLen);
+ }
- public String toString()
- {
- return new String(toByteArray());
- }
+ private void writeToImpl(JspWriter out, String encoding, byte[] bufferToWrite, int bufferToWriteLen)
+ throws IOException
+ {
+ String writeStr;
+ if (encoding != null)
+ {
+ writeStr = new String(bufferToWrite, 0, bufferToWriteLen, encoding);
+ }
+ else
+ {
+ writeStr = new String(bufferToWrite, 0, bufferToWriteLen);
+ }
+ out.write(writeStr);
+ }
- /**
- * Create a new buffer and store the
- * current one in linked list
- */
- protected void addBuffer()
- {
- if (buffers == null)
- buffers = new LinkedList();
+ public int getSize()
+ {
+ return size + index;
+ }
- buffers.addLast(buffer);
+ public byte[] toByteArray()
+ {
+ byte[] data = new byte[getSize()];
- buffer = new byte[blockSize];
- size += index;
- index = 0;
- }
+ // Check if we have a list of buffers
+ int pos = 0;
+ if (buffers != null)
+ {
+ Iterator iterator = buffers.iterator();
+ while (iterator.hasNext())
+ {
+ byte[] bytes = (byte[]) iterator.next();
+ System.arraycopy(bytes, 0, data, pos, blockSize);
+ pos += blockSize;
+ }
+ }
- // OutputStream overrides ----------------------------------------
- public void write(int datum) throws IOException
- {
- if (closed)
- {
- throw new IOException("Stream closed");
- } else
- {
- if (index == blockSize)
- addBuffer();
+ // write the internal buffer directly
+ System.arraycopy(buffer, 0, data, pos, index);
- // store the byte
- buffer[index++] = (byte) datum;
- }
- }
+ return data;
+ }
- public void write(byte[] data, int offset, int length)
- throws IOException
- {
- if (data == null)
- {
- throw new NullPointerException();
- } else if ((offset < 0) || (offset + length > data.length)
- || (length < 0))
- {
- throw new IndexOutOfBoundsException();
- } else if (closed)
- {
- throw new IOException("Stream closed");
- } else
- {
- if (index + length > blockSize)
- {
- int copyLength;
- do
+ public String toString()
+ {
+ return new String(toByteArray());
+ }
+
+ /**
+ * Create a new buffer and store the
+ * current one in linked list
+ */
+ protected void addBuffer()
+ {
+ if (buffers == null)
+ {
+ buffers = new LinkedList();
+ }
+
+ buffers.addLast(buffer);
+
+ buffer = new byte[blockSize];
+ size += index;
+ index = 0;
+ }
+
+ // OutputStream overrides ----------------------------------------
+ public void write(int datum) throws IOException
+ {
+ if (closed)
+ {
+ throw new IOException("Stream closed");
+ }
+ else
+ {
+ if (index == blockSize)
{
- if (index==blockSize)
- addBuffer();
+ addBuffer();
+ }
- copyLength = blockSize-index;
- if (length < copyLength)
- copyLength = length;
- System.arraycopy(data, offset, buffer, index, copyLength);
- offset += copyLength;
- index += copyLength;
- length -= copyLength;
- } while (length > 0);
- } else
- {
- // Copy in the subarray
- System.arraycopy(data, offset, buffer, index, length);
- index += length;
- }
- }
- }
+ // store the byte
+ buffer[index++] = (byte) datum;
+ }
+ }
- public void close()
- {
- closed = true;
- }
+ public void write(byte[] data, int offset, int length)
+ throws IOException
+ {
+ if (data == null)
+ {
+ throw new NullPointerException();
+ }
+ else if ((offset < 0) || (offset + length > data.length)
+ || (length < 0))
+ {
+ throw new IndexOutOfBoundsException();
+ }
+ else if (closed)
+ {
+ throw new IOException("Stream closed");
+ }
+ else
+ {
+ if (index + length > blockSize)
+ {
+ int copyLength;
+ do
+ {
+ if (index == blockSize)
+ {
+ addBuffer();
+ }
+
+ copyLength = blockSize - index;
+ if (length < copyLength)
+ {
+ copyLength = length;
+ }
+ System.arraycopy(data, offset, buffer, index, copyLength);
+ offset += copyLength;
+ index += copyLength;
+ length -= copyLength;
+ }
+ while (length > 0);
+ }
+ else
+ {
+ // Copy in the subarray
+ System.arraycopy(data, offset, buffer, index, length);
+ index += length;
+ }
+ }
+ }
+
+ public void close()
+ {
+ closed = true;
+ }
}
--===============0742283853==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
--===============0742283853==
Content-Type: text/plain; charset="us-ascii"
MIME-Version: 1.0
Content-Transfer-Encoding: 7bit
Content-Disposition: inline
_______________________________________________
Opensymphony-cvsmail mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/opensymphony-cvsmail
--===============0742283853==--