1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.struts2.util;
19
20 import java.io.IOException;
21 import java.io.OutputStream;
22 import java.io.RandomAccessFile;
23 import java.io.Writer;
24 import java.util.Iterator;
25 import java.util.LinkedList;
26
27
28 /***
29 * A speedy implementation of ByteArrayOutputStream. It's not synchronized, and it
30 * does not copy buffers when it's expanded. There's also no copying of the internal buffer
31 * if it's contents is extracted with the writeTo(stream) method.
32 *
33 */
34 public class FastByteArrayOutputStream extends OutputStream {
35
36
37 private static final int DEFAULT_BLOCK_SIZE = 8192;
38
39
40 private LinkedList buffers;
41
42
43
44 private byte[] buffer;
45
46
47 private boolean closed;
48 private int blockSize;
49 private int index;
50 private int size;
51
52
53
54 public FastByteArrayOutputStream() {
55 this(DEFAULT_BLOCK_SIZE);
56 }
57
58 public FastByteArrayOutputStream(int aSize) {
59 blockSize = aSize;
60 buffer = new byte[blockSize];
61 }
62
63
64 public int getSize() {
65 return size + index;
66 }
67
68 public void close() {
69 closed = true;
70 }
71
72 public byte[] toByteArray() {
73 byte[] data = new byte[getSize()];
74
75
76 int pos = 0;
77
78 if (buffers != null) {
79 Iterator iter = buffers.iterator();
80
81 while (iter.hasNext()) {
82 byte[] bytes = (byte[]) iter.next();
83 System.arraycopy(bytes, 0, data, pos, blockSize);
84 pos += blockSize;
85 }
86 }
87
88
89 System.arraycopy(buffer, 0, data, pos, index);
90
91 return data;
92 }
93
94 public String toString() {
95 return new String(toByteArray());
96 }
97
98
99 public void write(int datum) throws IOException {
100 if (closed) {
101 throw new IOException("Stream closed");
102 } else {
103 if (index == blockSize) {
104 addBuffer();
105 }
106
107
108 buffer[index++] = (byte) datum;
109 }
110 }
111
112 public void write(byte[] data, int offset, int length) throws IOException {
113 if (data == null) {
114 throw new NullPointerException();
115 } else if ((offset < 0) || ((offset + length) > data.length) || (length < 0)) {
116 throw new IndexOutOfBoundsException();
117 } else if (closed) {
118 throw new IOException("Stream closed");
119 } else {
120 if ((index + length) > blockSize) {
121 int copyLength;
122
123 do {
124 if (index == blockSize) {
125 addBuffer();
126 }
127
128 copyLength = blockSize - index;
129
130 if (length < copyLength) {
131 copyLength = length;
132 }
133
134 System.arraycopy(data, offset, buffer, index, copyLength);
135 offset += copyLength;
136 index += copyLength;
137 length -= copyLength;
138 } while (length > 0);
139 } else {
140
141 System.arraycopy(data, offset, buffer, index, length);
142 index += length;
143 }
144 }
145 }
146
147
148 public void writeTo(OutputStream out) throws IOException {
149
150 if (buffers != null) {
151 Iterator iter = buffers.iterator();
152
153 while (iter.hasNext()) {
154 byte[] bytes = (byte[]) iter.next();
155 out.write(bytes, 0, blockSize);
156 }
157 }
158
159
160 out.write(buffer, 0, index);
161 }
162
163 public void writeTo(RandomAccessFile out) throws IOException {
164
165 if (buffers != null) {
166 Iterator iter = buffers.iterator();
167
168 while (iter.hasNext()) {
169 byte[] bytes = (byte[]) iter.next();
170 out.write(bytes, 0, blockSize);
171 }
172 }
173
174
175 out.write(buffer, 0, index);
176 }
177
178 public void writeTo(Writer out, String encoding) throws IOException {
179
180 if (buffers != null) {
181 Iterator iter = buffers.iterator();
182
183 while (iter.hasNext()) {
184 byte[] bytes = (byte[]) iter.next();
185
186 if (encoding != null) {
187 out.write(new String(bytes, encoding));
188 } else {
189 out.write(new String(bytes));
190 }
191 }
192 }
193
194
195 if (encoding != null) {
196 out.write(new String(buffer, 0, index, encoding));
197 } else {
198 out.write(new String(buffer, 0, index));
199 }
200 }
201
202 /***
203 * Create a new buffer and store the
204 * current one in linked list
205 */
206 protected void addBuffer() {
207 if (buffers == null) {
208 buffers = new LinkedList();
209 }
210
211 buffers.addLast(buffer);
212
213 buffer = new byte[blockSize];
214 size += index;
215 index = 0;
216 }
217 }