001: package com.quadcap.io;
002:
003: /* Copyright 1997 - 2003 Quadcap Software. All rights reserved.
004: *
005: * This software is distributed under the Quadcap Free Software License.
006: * This software may be used or modified for any purpose, personal or
007: * commercial. Open Source redistributions are permitted. Commercial
008: * redistribution of larger works derived from, or works which bundle
009: * this software requires a "Commercial Redistribution License"; see
010: * http://www.quadcap.com/purchase.
011: *
012: * Redistributions qualify as "Open Source" under one of the following terms:
013: *
014: * Redistributions are made at no charge beyond the reasonable cost of
015: * materials and delivery.
016: *
017: * Redistributions are accompanied by a copy of the Source Code or by an
018: * irrevocable offer to provide a copy of the Source Code for up to three
019: * years at the cost of materials and delivery. Such redistributions
020: * must allow further use, modification, and redistribution of the Source
021: * Code under substantially the same terms as this license.
022: *
023: * Redistributions of source code must retain the copyright notices as they
024: * appear in each source code file, these license terms, and the
025: * disclaimer/limitation of liability set forth as paragraph 6 below.
026: *
027: * Redistributions in binary form must reproduce this Copyright Notice,
028: * these license terms, and the disclaimer/limitation of liability set
029: * forth as paragraph 6 below, in the documentation and/or other materials
030: * provided with the distribution.
031: *
032: * The Software is provided on an "AS IS" basis. No warranty is
033: * provided that the Software is free of defects, or fit for a
034: * particular purpose.
035: *
036: * Limitation of Liability. Quadcap Software shall not be liable
037: * for any damages suffered by the Licensee or any third party resulting
038: * from use of the Software.
039: */
040:
041: import java.io.ByteArrayInputStream;
042: import java.io.ByteArrayOutputStream;
043: import java.io.File;
044: import java.io.FileInputStream;
045: import java.io.FileNotFoundException;
046: import java.io.FileOutputStream;
047: import java.io.InputStream;
048: import java.io.IOException;
049: import java.io.OutputStream;
050:
051: /**
052: * This class implements a simple persistent object which can be written
053: * as an OutputStream and read as an InputStream. Small objects can be
054: * stored in memory, larger objects can be stored in temp files on disk.
055: *
056: * @author Stan Bailes
057: */
058: public class SaveRestoreStream {
059: ByteArrayOutputStream bos = null;
060: FileOutputStream fos = null;
061: File file = null;
062: int len = 0;
063: int max = 4096;
064:
065: /**
066: * Construct a new SaveRestoreStream with the default max buffered
067: */
068: public SaveRestoreStream() {
069: }
070:
071: /**
072: * Construct a new SaveRestoreStream with the specified max buffered
073: * size.
074: *
075: * @param max the maximum amount of data to be buffered in memory.
076: */
077: public SaveRestoreStream(int max) {
078: this .max = max;
079: }
080:
081: /**
082: * Construct a new SaveRestoreStream using the data in the specified
083: * InputStream.
084: *
085: * @param in the InputStream supplying the data for this stream
086: */
087: public SaveRestoreStream(InputStream in) throws IOException {
088: OutputStream out = getOutputStream();
089: try {
090: IO.copyStream(in, out);
091: } finally {
092: out.close();
093: }
094: }
095:
096: /**
097: * Return an output stream that the caller can use to save his object
098: *
099: * @return the output stream
100: */
101: public OutputStream getOutputStream() throws IOException {
102: if (file == null) {
103: bos = new ByteArrayOutputStream();
104: if (fos != null)
105: fos.close();
106: fos = null;
107: } else {
108: bos = null;
109: fos = new FileOutputStream(file);
110: }
111:
112: return new OutputStream() {
113: public void write(int c) throws IOException {
114: doWrite(c);
115: }
116:
117: public void flush() throws IOException {
118: if (bos != null)
119: bos.flush();
120: else
121: fos.flush();
122: }
123:
124: public void close() throws IOException {
125: if (bos != null) {
126: len = bos.size();
127: } else if (fos != null) {
128: fos.close();
129: fos = null;
130: len = (int) file.length();
131: }
132: }
133: };
134: }
135:
136: public int length() {
137: return len;
138: }
139:
140: static int tmpFileCount = 0;
141:
142: static synchronized File tmpFile() throws IOException {
143: return File.createTempFile("" + System.currentTimeMillis()
144: + "." + (tmpFileCount++), ".tmp");
145: }
146:
147: /**
148: * Write a byte to the stream.
149: *
150: * @param c the byte
151: * @exception IOException may be thrown
152: */
153: public void doWrite(int c) throws IOException {
154: if (bos != null) {
155: if (bos.size() < max) {
156: bos.write(c);
157: } else {
158: file = tmpFile();
159: fos = new FileOutputStream(file);
160: bos.writeTo(fos);
161: fos.write(c);
162: bos.close();
163: bos = null;
164: }
165: } else {
166: fos.write(c);
167: }
168: }
169:
170: /**
171: * Return an input stream that the user can use to get his data back
172: *
173: * @return the input stream
174: */
175: public InputStream getInputStream() throws IOException {
176: return getInputStream(true);
177: }
178:
179: public InputStream getInputStream(final boolean del)
180: throws IOException {
181: if (bos != null)
182: return new ByteArrayInputStream(bos.toByteArray());
183: if (fos != null) {
184: fos.close();
185: fos = null;
186: }
187: if (file != null) {
188: final FileInputStream fis = new FileInputStream(file);
189: final File f = file;
190: if (del)
191: file = null;
192: return new InputStream() {
193: public int read() throws IOException {
194: return fis.read();
195: }
196:
197: public int read(byte[] buf) throws IOException {
198: return fis.read(buf);
199: }
200:
201: public int read(byte[] buf, int off, int cnt)
202: throws IOException {
203: return fis.read(buf, off, cnt);
204: }
205:
206: public void close() throws IOException {
207: fis.close();
208: if (del)
209: f.delete();
210: }
211:
212: public void finalize() {
213: try {
214: close();
215: } catch (Throwable t) {
216: }
217: }
218: };
219: }
220: throw new IOException("no data");
221: }
222:
223: /**
224: * Return the data as a string
225: */
226: public String toString() {
227: if (bos != null)
228: return bos.toString();
229: if (fos != null) {
230: throw new RuntimeException("too large");
231: }
232: return null;
233: }
234:
235: public void close() {
236: bos = null;
237: if (fos != null) {
238: try {
239: fos.close();
240: } catch (Exception e) {
241: }
242: }
243: fos = null;
244: if (file != null) {
245: try {
246: file.delete();
247: } catch (Exception e) {
248: }
249: }
250: file = null;
251: len = 0;
252: }
253:
254: public void reset() {
255: close();
256: }
257:
258: public void finalize() {
259: close();
260: }
261: }
|