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