This project has retired. For details please refer to its
Attic page.
ThresholdOutputStream xref
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.apache.chemistry.opencmis.server.shared;
20
21 import java.io.BufferedInputStream;
22 import java.io.BufferedOutputStream;
23 import java.io.File;
24 import java.io.FileInputStream;
25 import java.io.FileNotFoundException;
26 import java.io.FileOutputStream;
27 import java.io.FilterInputStream;
28 import java.io.IOException;
29 import java.io.InputStream;
30 import java.io.OutputStream;
31
32
33
34
35
36
37
38
39
40
41 public class ThresholdOutputStream extends OutputStream {
42 private static final int MAX_GROW = 10 * 1024 * 1024;
43 private static final int DEFAULT_THRESHOLD = 4 * 1024 * 1024;
44
45 private File tempDir;
46 private int memoryThreshold;
47
48 private byte[] buf = null;
49 private int bufSize = 0;
50 private long size;
51 private File tempFile;
52 private OutputStream tmpStream;
53
54 public ThresholdOutputStream(File tempDir, int memoryThreshold) {
55 this(64 * 1024, tempDir, memoryThreshold);
56 }
57
58 public ThresholdOutputStream(int initSize, File tempDir, int memoryThreshold) {
59 if (initSize < 0) {
60 throw new IllegalArgumentException("Negative initial size: " + initSize);
61 }
62
63 this.tempDir = tempDir;
64 this.memoryThreshold = (memoryThreshold < 0 ? DEFAULT_THRESHOLD : memoryThreshold);
65
66 buf = new byte[initSize];
67 }
68
69 private void expand(int nextBufferSize) throws IOException {
70 if (bufSize + nextBufferSize <= buf.length) {
71 return;
72 }
73
74 if (bufSize + nextBufferSize > memoryThreshold) {
75 if (tmpStream == null) {
76 tempFile = File.createTempFile("opencmis", null, tempDir);
77 tmpStream = new BufferedOutputStream(new FileOutputStream(tempFile));
78 }
79 tmpStream.write(buf, 0, bufSize);
80
81 if (buf.length != memoryThreshold) {
82 buf = new byte[memoryThreshold];
83 }
84 bufSize = 0;
85
86 return;
87 }
88
89 int newSize = ((bufSize + nextBufferSize) * 2 < MAX_GROW ? (bufSize + nextBufferSize) * 2 : buf.length
90 + nextBufferSize + MAX_GROW);
91 byte[] newbuf = new byte[newSize];
92 System.arraycopy(buf, 0, newbuf, 0, bufSize);
93 buf = newbuf;
94 }
95
96 public long getSize() {
97 return size;
98 }
99
100 @Override
101 public void write(byte[] buffer) throws IOException {
102 write(buffer, 0, buffer.length);
103 }
104
105 @Override
106 public void write(byte[] buffer, int offset, int len) throws IOException {
107 if (len == 0) {
108 return;
109 }
110
111 expand(len);
112 System.arraycopy(buffer, offset, buf, bufSize, len);
113 bufSize += len;
114 size += len;
115 }
116
117 @Override
118 public void write(int oneByte) throws IOException {
119 if (bufSize == buf.length) {
120 expand(1);
121 }
122
123 buf[bufSize++] = (byte) oneByte;
124 size++;
125 }
126
127 @Override
128 public void flush() throws IOException {
129 if (tmpStream != null) {
130 if (bufSize > 0) {
131 tmpStream.write(buf, 0, bufSize);
132 bufSize = 0;
133 }
134 tmpStream.flush();
135 }
136 }
137
138 @Override
139 public void close() throws IOException {
140 flush();
141
142 if (tmpStream != null) {
143 tmpStream.close();
144 }
145 }
146
147
148
149
150 public void destroy() {
151 try {
152 close();
153 } catch (Exception e) {
154
155 }
156
157 if (tempFile != null) {
158 tempFile.delete();
159 }
160
161 buf = null;
162 }
163
164
165
166
167 public InputStream getInputStream() throws Exception {
168 if (tmpStream != null) {
169 close();
170 buf = null;
171
172 return new InternalTempFileInputStream();
173 } else {
174 return new InternalBufferInputStream();
175 }
176 }
177
178
179
180
181 public interface ThresholdInputStream {
182
183
184
185
186
187 boolean isInMemory();
188
189
190
191
192
193 File getTemporaryFile();
194 }
195
196
197
198
199 private class InternalBufferInputStream extends InputStream implements ThresholdInputStream {
200
201 private int pos = 0;
202
203 public boolean isInMemory() {
204 return true;
205 }
206
207 public File getTemporaryFile() {
208 return null;
209 }
210
211 @Override
212 public boolean markSupported() {
213 return false;
214 }
215
216 @Override
217 public int available() {
218 return bufSize - pos;
219 }
220
221 @Override
222 public int read() {
223 return (pos < bufSize) && (buf != null) ? (buf[pos++] & 0xff) : -1;
224 }
225
226 @Override
227 public int read(byte[] b) throws IOException {
228 return read(b, 0, b.length);
229 }
230
231 @Override
232 public int read(byte[] b, int off, int len) {
233 if ((pos >= bufSize) || (buf == null)) {
234 return -1;
235 }
236
237 if ((pos + len) > bufSize) {
238 len = (bufSize - pos);
239 }
240
241 System.arraycopy(buf, pos, b, off, len);
242 pos += len;
243
244 return len;
245 }
246
247 @Override
248 public long skip(long n) {
249 if ((pos + n) > bufSize) {
250 n = bufSize - pos;
251 }
252
253 if (n < 0) {
254 return 0;
255 }
256
257 pos += n;
258
259 return n;
260 }
261
262 @Override
263 public void close() throws IOException {
264 buf = null;
265 }
266 }
267
268
269
270
271 private class InternalTempFileInputStream extends FilterInputStream implements ThresholdInputStream {
272
273 private boolean isDeleted = false;
274
275 public InternalTempFileInputStream() throws FileNotFoundException {
276 super(new BufferedInputStream(new FileInputStream(tempFile), memoryThreshold));
277 }
278
279 public boolean isInMemory() {
280 return false;
281 }
282
283 public File getTemporaryFile() {
284 return tempFile;
285 }
286
287 @Override
288 public boolean markSupported() {
289 return false;
290 }
291
292 @Override
293 public int read() throws IOException {
294 int b = super.read();
295
296 if (b == -1 && !isDeleted) {
297 super.close();
298 isDeleted = tempFile.delete();
299 }
300
301 return b;
302 }
303
304 @Override
305 public int read(byte[] b) throws IOException {
306 return read(b, 0, b.length);
307 }
308
309 @Override
310 public int read(byte[] b, int off, int len) throws IOException {
311 int n = super.read(b, off, len);
312
313 if (n == -1 && !isDeleted) {
314 super.close();
315 isDeleted = tempFile.delete();
316 }
317
318 return n;
319 }
320
321 @Override
322 public void close() throws IOException {
323 if (!isDeleted) {
324 super.close();
325 isDeleted = tempFile.delete();
326 }
327 }
328 }
329 }