001: /*
002: * Copyright (c) 2002-2003 by OpenSymphony
003: * All rights reserved.
004: */
005: package com.opensymphony.webwork.util;
006:
007: import java.io.IOException;
008: import java.io.OutputStream;
009: import java.io.RandomAccessFile;
010: import java.io.Writer;
011: import java.util.Iterator;
012: import java.util.LinkedList;
013:
014: /**
015: * A speedy implementation of ByteArrayOutputStream. It's not synchronized, and it
016: * does not copy buffers when it's expanded. There's also no copying of the internal buffer
017: * if it's contents is extracted with the writeTo(stream) method.
018: *
019: * @author Rickard Öberg
020: * @version $Revision: 1282 $
021: */
022: public class FastByteArrayOutputStream extends OutputStream {
023:
024: // Static --------------------------------------------------------
025: private static final int DEFAULT_BLOCK_SIZE = 8192;
026:
027: private LinkedList buffers;
028:
029: // Attributes ----------------------------------------------------
030: // internal buffer
031: private byte[] buffer;
032:
033: // is the stream closed?
034: private boolean closed;
035: private int blockSize;
036: private int index;
037: private int size;
038:
039: // Constructors --------------------------------------------------
040: public FastByteArrayOutputStream() {
041: this (DEFAULT_BLOCK_SIZE);
042: }
043:
044: public FastByteArrayOutputStream(int aSize) {
045: blockSize = aSize;
046: buffer = new byte[blockSize];
047: }
048:
049: public int getSize() {
050: return size + index;
051: }
052:
053: public void close() {
054: closed = true;
055: }
056:
057: public byte[] toByteArray() {
058: byte[] data = new byte[getSize()];
059:
060: // Check if we have a list of buffers
061: int pos = 0;
062:
063: if (buffers != null) {
064: Iterator iter = buffers.iterator();
065:
066: while (iter.hasNext()) {
067: byte[] bytes = (byte[]) iter.next();
068: System.arraycopy(bytes, 0, data, pos, blockSize);
069: pos += blockSize;
070: }
071: }
072:
073: // write the internal buffer directly
074: System.arraycopy(buffer, 0, data, pos, index);
075:
076: return data;
077: }
078:
079: public String toString() {
080: return new String(toByteArray());
081: }
082:
083: // OutputStream overrides ----------------------------------------
084: public void write(int datum) throws IOException {
085: if (closed) {
086: throw new IOException("Stream closed");
087: } else {
088: if (index == blockSize) {
089: addBuffer();
090: }
091:
092: // store the byte
093: buffer[index++] = (byte) datum;
094: }
095: }
096:
097: public void write(byte[] data, int offset, int length)
098: throws IOException {
099: if (data == null) {
100: throw new NullPointerException();
101: } else if ((offset < 0) || ((offset + length) > data.length)
102: || (length < 0)) {
103: throw new IndexOutOfBoundsException();
104: } else if (closed) {
105: throw new IOException("Stream closed");
106: } else {
107: if ((index + length) > blockSize) {
108: int copyLength;
109:
110: do {
111: if (index == blockSize) {
112: addBuffer();
113: }
114:
115: copyLength = blockSize - index;
116:
117: if (length < copyLength) {
118: copyLength = length;
119: }
120:
121: System.arraycopy(data, offset, buffer, index,
122: copyLength);
123: offset += copyLength;
124: index += copyLength;
125: length -= copyLength;
126: } while (length > 0);
127: } else {
128: // Copy in the subarray
129: System.arraycopy(data, offset, buffer, index, length);
130: index += length;
131: }
132: }
133: }
134:
135: // Public
136: public void writeTo(OutputStream out) throws IOException {
137: // Check if we have a list of buffers
138: if (buffers != null) {
139: Iterator iter = buffers.iterator();
140:
141: while (iter.hasNext()) {
142: byte[] bytes = (byte[]) iter.next();
143: out.write(bytes, 0, blockSize);
144: }
145: }
146:
147: // write the internal buffer directly
148: out.write(buffer, 0, index);
149: }
150:
151: public void writeTo(RandomAccessFile out) throws IOException {
152: // Check if we have a list of buffers
153: if (buffers != null) {
154: Iterator iter = buffers.iterator();
155:
156: while (iter.hasNext()) {
157: byte[] bytes = (byte[]) iter.next();
158: out.write(bytes, 0, blockSize);
159: }
160: }
161:
162: // write the internal buffer directly
163: out.write(buffer, 0, index);
164: }
165:
166: public void writeTo(Writer out, String encoding) throws IOException {
167: // Check if we have a list of buffers
168: if (buffers != null) {
169: Iterator iter = buffers.iterator();
170:
171: while (iter.hasNext()) {
172: byte[] bytes = (byte[]) iter.next();
173:
174: if (encoding != null) {
175: out.write(new String(bytes, encoding));
176: } else {
177: out.write(new String(bytes));
178: }
179: }
180: }
181:
182: // write the internal buffer directly
183: if (encoding != null) {
184: out.write(new String(buffer, 0, index, encoding));
185: } else {
186: out.write(new String(buffer, 0, index));
187: }
188: }
189:
190: /**
191: * Create a new buffer and store the
192: * current one in linked list
193: */
194: protected void addBuffer() {
195: if (buffers == null) {
196: buffers = new LinkedList();
197: }
198:
199: buffers.addLast(buffer);
200:
201: buffer = new byte[blockSize];
202: size += index;
203: index = 0;
204: }
205: }
|