001: //The contents of this file are subject to the Mozilla Public License Version 1.1
002: //(the "License"); you may not use this file except in compliance with the
003: //License. You may obtain a copy of the License at http://www.mozilla.org/MPL/
004: //
005: //Software distributed under the License is distributed on an "AS IS" basis,
006: //WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
007: //for the specific language governing rights and
008: //limitations under the License.
009: //
010: //The Original Code is "The Columba Project"
011: //
012: //The Initial Developers of the Original Code are Frederik Dietz and Timo Stich.
013: //Portions created by Frederik Dietz and Timo Stich are Copyright (C) 2003.
014: //
015: //All Rights Reserved.
016: package org.columba.core.io;
017:
018: import java.io.ByteArrayInputStream;
019: import java.io.ByteArrayOutputStream;
020: import java.io.File;
021: import java.io.FileInputStream;
022: import java.io.FileNotFoundException;
023: import java.io.FileOutputStream;
024: import java.io.IOException;
025: import java.io.InputStream;
026: import java.util.ArrayList;
027: import java.util.List;
028:
029: /**
030: * The model that needs to be instanciated if you want to create
031: * CloneInputStreams from a master.
032: *
033: * @author Timo Stich <tstich@users.sourceforge.net>
034: */
035: public class CloneStreamMaster {
036: private static int uid = 0;
037:
038: private InputStream master;
039:
040: private int nextId;
041:
042: private List<InputStream> streamList;
043:
044: private File tempFile;
045:
046: private byte[] buffer;
047:
048: private int openClones;
049:
050: private boolean usesFile;
051:
052: private int size;
053:
054: /**
055: * Constructs a CloneStreamMaster. Note that the master must NOT be read
056: * from after the construction!
057: *
058: * @param master
059: */
060: public CloneStreamMaster(InputStream master) throws IOException {
061: super ();
062: this .master = master;
063:
064: streamList = new ArrayList<InputStream>(2);
065:
066: if (this .master.available() > 51200) {
067: tempFile = File.createTempFile("columba-stream-clone"
068: + (uid++), ".tmp");
069:
070: // make sure file is deleted automatically when closing VM
071: tempFile.deleteOnExit();
072:
073: FileOutputStream tempOut = new FileOutputStream(tempFile);
074:
075: size = (int) StreamUtils.streamCopy(master, tempOut);
076:
077: tempOut.close();
078:
079: usesFile = true;
080: } else {
081: ByteArrayOutputStream tempOut = new ByteArrayOutputStream();
082:
083: size = (int) StreamUtils.streamCopy(master, tempOut);
084: tempOut.close();
085:
086: buffer = tempOut.toByteArray();
087: usesFile = false;
088: }
089:
090: this .master.close();
091: }
092:
093: /**
094: * Gets a new clone of the master.
095: *
096: * @return Clone of the master
097: */
098: public CloneInputStream getClone() {
099: if (usesFile) {
100: try {
101: // add a new inputstream to read from
102: streamList.add(new FileInputStream(tempFile));
103: } catch (FileNotFoundException e) {
104: e.printStackTrace();
105:
106: // only if tempfile was corrupted
107: }
108: } else {
109: streamList.add(new ByteArrayInputStream(buffer));
110: }
111:
112: openClones++;
113:
114: return new CloneInputStream(this , nextId++);
115: }
116:
117: public int read(int id) throws IOException {
118: return streamList.get(id).read();
119: }
120:
121: public int read(int id, byte[] out, int offset, int length)
122: throws IOException {
123: return streamList.get(id).read(out, offset, length);
124: }
125:
126: /**
127: * @return
128: */
129: public int available() throws IOException {
130: return size;
131: }
132:
133: /**
134: * {@inheritDoc}
135: */
136: @Override
137: protected void finalize() throws Throwable {
138: super .finalize();
139:
140: if (usesFile) {
141: // Delete the tempfile immedietly
142: tempFile.delete();
143: }
144: }
145:
146: /**
147: * @param id
148: */
149: public void close(int id) throws IOException {
150: streamList.get(id).close();
151: }
152: }
|