001: /*
002: * $Id: FastByteArrayOutputStream.java 471756 2006-11-06 15:01:43Z husted $
003: *
004: * Licensed to the Apache Software Foundation (ASF) under one
005: * or more contributor license agreements. See the NOTICE file
006: * distributed with this work for additional information
007: * regarding copyright ownership. The ASF licenses this file
008: * to you under the Apache License, Version 2.0 (the
009: * "License"); you may not use this file except in compliance
010: * with the License. You may obtain a copy of the License at
011: *
012: * http://www.apache.org/licenses/LICENSE-2.0
013: *
014: * Unless required by applicable law or agreed to in writing,
015: * software distributed under the License is distributed on an
016: * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
017: * KIND, either express or implied. See the License for the
018: * specific language governing permissions and limitations
019: * under the License.
020: */
021: package org.apache.struts2.util;
022:
023: import java.io.IOException;
024: import java.io.OutputStream;
025: import java.io.RandomAccessFile;
026: import java.io.Writer;
027: import java.util.Iterator;
028: import java.util.LinkedList;
029:
030: /**
031: * A speedy implementation of ByteArrayOutputStream. It's not synchronized, and it
032: * does not copy buffers when it's expanded. There's also no copying of the internal buffer
033: * if it's contents is extracted with the writeTo(stream) method.
034: *
035: */
036: public class FastByteArrayOutputStream extends OutputStream {
037:
038: // Static --------------------------------------------------------
039: private static final int DEFAULT_BLOCK_SIZE = 8192;
040:
041: private LinkedList buffers;
042:
043: // Attributes ----------------------------------------------------
044: // internal buffer
045: private byte[] buffer;
046:
047: // is the stream closed?
048: private boolean closed;
049: private int blockSize;
050: private int index;
051: private int size;
052:
053: // Constructors --------------------------------------------------
054: public FastByteArrayOutputStream() {
055: this (DEFAULT_BLOCK_SIZE);
056: }
057:
058: public FastByteArrayOutputStream(int aSize) {
059: blockSize = aSize;
060: buffer = new byte[blockSize];
061: }
062:
063: public int getSize() {
064: return size + index;
065: }
066:
067: public void close() {
068: closed = true;
069: }
070:
071: public byte[] toByteArray() {
072: byte[] data = new byte[getSize()];
073:
074: // Check if we have a list of buffers
075: int pos = 0;
076:
077: if (buffers != null) {
078: Iterator iter = buffers.iterator();
079:
080: while (iter.hasNext()) {
081: byte[] bytes = (byte[]) iter.next();
082: System.arraycopy(bytes, 0, data, pos, blockSize);
083: pos += blockSize;
084: }
085: }
086:
087: // write the internal buffer directly
088: System.arraycopy(buffer, 0, data, pos, index);
089:
090: return data;
091: }
092:
093: public String toString() {
094: return new String(toByteArray());
095: }
096:
097: // OutputStream overrides ----------------------------------------
098: public void write(int datum) throws IOException {
099: if (closed) {
100: throw new IOException("Stream closed");
101: } else {
102: if (index == blockSize) {
103: addBuffer();
104: }
105:
106: // store the byte
107: buffer[index++] = (byte) datum;
108: }
109: }
110:
111: public void write(byte[] data, int offset, int length)
112: throws IOException {
113: if (data == null) {
114: throw new NullPointerException();
115: } else if ((offset < 0) || ((offset + length) > data.length)
116: || (length < 0)) {
117: throw new IndexOutOfBoundsException();
118: } else if (closed) {
119: throw new IOException("Stream closed");
120: } else {
121: if ((index + length) > blockSize) {
122: int copyLength;
123:
124: do {
125: if (index == blockSize) {
126: addBuffer();
127: }
128:
129: copyLength = blockSize - index;
130:
131: if (length < copyLength) {
132: copyLength = length;
133: }
134:
135: System.arraycopy(data, offset, buffer, index,
136: copyLength);
137: offset += copyLength;
138: index += copyLength;
139: length -= copyLength;
140: } while (length > 0);
141: } else {
142: // Copy in the subarray
143: System.arraycopy(data, offset, buffer, index, length);
144: index += length;
145: }
146: }
147: }
148:
149: // Public
150: public void writeTo(OutputStream out) throws IOException {
151: // Check if we have a list of buffers
152: if (buffers != null) {
153: Iterator iter = buffers.iterator();
154:
155: while (iter.hasNext()) {
156: byte[] bytes = (byte[]) iter.next();
157: out.write(bytes, 0, blockSize);
158: }
159: }
160:
161: // write the internal buffer directly
162: out.write(buffer, 0, index);
163: }
164:
165: public void writeTo(RandomAccessFile out) throws IOException {
166: // Check if we have a list of buffers
167: if (buffers != null) {
168: Iterator iter = buffers.iterator();
169:
170: while (iter.hasNext()) {
171: byte[] bytes = (byte[]) iter.next();
172: out.write(bytes, 0, blockSize);
173: }
174: }
175:
176: // write the internal buffer directly
177: out.write(buffer, 0, index);
178: }
179:
180: public void writeTo(Writer out, String encoding) throws IOException {
181: // Check if we have a list of buffers
182: if (buffers != null) {
183: Iterator iter = buffers.iterator();
184:
185: while (iter.hasNext()) {
186: byte[] bytes = (byte[]) iter.next();
187:
188: if (encoding != null) {
189: out.write(new String(bytes, encoding));
190: } else {
191: out.write(new String(bytes));
192: }
193: }
194: }
195:
196: // write the internal buffer directly
197: if (encoding != null) {
198: out.write(new String(buffer, 0, index, encoding));
199: } else {
200: out.write(new String(buffer, 0, index));
201: }
202: }
203:
204: /**
205: * Create a new buffer and store the
206: * current one in linked list
207: */
208: protected void addBuffer() {
209: if (buffers == null) {
210: buffers = new LinkedList();
211: }
212:
213: buffers.addLast(buffer);
214:
215: buffer = new byte[blockSize];
216: size += index;
217: index = 0;
218: }
219: }
|