Skip to content

Commit 7f6039c

Browse files
committed
Add ThresholdingOutputStream and DeferredFileOutputStream, along with tests
for the latter. (There are no tests for the former, since it is an abstract class.) These classes originated in Commons FileUpload (and will continue to exist there as well, until IO gets to an official release). git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/io/trunk@140496 13f79535-47bb-0310-9956-ffa450edef68
1 parent aa4317c commit 7f6039c

4 files changed

Lines changed: 770 additions & 0 deletions

File tree

project.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@
104104
</roles>
105105
</developer>
106106

107+
<developer>
108+
<name>Martin Cooper</name>
109+
<id>martinc</id>
110+
<email>martinc@apache.org</email>
111+
<organization/>
112+
<roles>
113+
<role>Java Developer</role>
114+
</roles>
115+
</developer>
116+
107117
</developers>
108118

109119
<contributors>
Lines changed: 218 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,218 @@
1+
/*
2+
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//io/src/java/org/apache/commons/io/output/DeferredFileOutputStream.java,v 1.1 2004/02/01 07:37:36 martinc Exp $
3+
* $Revision: 1.1 $
4+
* $Date: 2004/02/01 07:37:36 $
5+
*
6+
* ====================================================================
7+
*
8+
* The Apache Software License, Version 1.1
9+
*
10+
* Copyright (c) 2001-2003 The Apache Software Foundation. All rights
11+
* reserved.
12+
*
13+
* Redistribution and use in source and binary forms, with or without
14+
* modification, are permitted provided that the following conditions
15+
* are met:
16+
*
17+
* 1. Redistributions of source code must retain the above copyright
18+
* notice, this list of conditions and the following disclaimer.
19+
*
20+
* 2. Redistributions in binary form must reproduce the above copyright
21+
* notice, this list of conditions and the following disclaimer in
22+
* the documentation and/or other materials provided with the
23+
* distribution.
24+
*
25+
* 3. The end-user documentation included with the redistribution, if
26+
* any, must include the following acknowledgement:
27+
* "This product includes software developed by the
28+
* Apache Software Foundation (http://www.apache.org/)."
29+
* Alternately, this acknowledgement may appear in the software itself,
30+
* if and wherever such third-party acknowledgements normally appear.
31+
*
32+
* 4. The names "The Jakarta Project", "Commons", and "Apache Software
33+
* Foundation" must not be used to endorse or promote products derived
34+
* from this software without prior written permission. For written
35+
* permission, please contact apache@apache.org.
36+
*
37+
* 5. Products derived from this software may not be called "Apache"
38+
* nor may "Apache" appear in their names without prior written
39+
* permission of the Apache Software Foundation.
40+
*
41+
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42+
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43+
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44+
* DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45+
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46+
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47+
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48+
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49+
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50+
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51+
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52+
* SUCH DAMAGE.
53+
* ====================================================================
54+
*
55+
* This software consists of voluntary contributions made by many
56+
* individuals on behalf of the Apache Software Foundation. For more
57+
* information on the Apache Software Foundation, please see
58+
* <http://www.apache.org/>.
59+
*
60+
*/
61+
62+
63+
package org.apache.commons.io.output;
64+
65+
import java.io.ByteArrayOutputStream;
66+
import java.io.File;
67+
import java.io.FileOutputStream;
68+
import java.io.IOException;
69+
import java.io.OutputStream;
70+
71+
/**
72+
* <p>An output stream which will retain data in memory until a specified
73+
* threshold is reached, and only then commit it to disk. If the stream is
74+
* closed before the threshold is reached, the data will not be written to
75+
* disk at all.</p>
76+
*
77+
* @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
78+
*
79+
* @version $Id: DeferredFileOutputStream.java,v 1.1 2004/02/01 07:37:36 martinc Exp $
80+
*/
81+
public class DeferredFileOutputStream
82+
extends ThresholdingOutputStream
83+
{
84+
85+
// ----------------------------------------------------------- Data members
86+
87+
88+
/**
89+
* The output stream to which data will be written prior to the theshold
90+
* being reached.
91+
*/
92+
private ByteArrayOutputStream memoryOutputStream;
93+
94+
95+
/**
96+
* The output stream to which data will be written after the theshold is
97+
* reached.
98+
*/
99+
private FileOutputStream diskOutputStream;
100+
101+
102+
/**
103+
* The output stream to which data will be written at any given time. This
104+
* will always be one of <code>memoryOutputStream</code> or
105+
* <code>diskOutputStream</code>.
106+
*/
107+
private OutputStream currentOutputStream;
108+
109+
110+
/**
111+
* The file to which output will be directed if the threshold is exceeded.
112+
*/
113+
private File outputFile;
114+
115+
116+
// ----------------------------------------------------------- Constructors
117+
118+
119+
/**
120+
* Constructs an instance of this class which will trigger an event at the
121+
* specified threshold, and save data to a file beyond that point.
122+
*
123+
* @param threshold The number of bytes at which to trigger an event.
124+
* @param outputFile The file to which data is saved beyond the threshold.
125+
*/
126+
public DeferredFileOutputStream(int threshold, File outputFile)
127+
{
128+
super(threshold);
129+
this.outputFile = outputFile;
130+
131+
memoryOutputStream = new ByteArrayOutputStream(threshold);
132+
currentOutputStream = memoryOutputStream;
133+
}
134+
135+
136+
// --------------------------------------- ThresholdingOutputStream methods
137+
138+
139+
/**
140+
* Returns the current output stream. This may be memory based or disk
141+
* based, depending on the current state with respect to the threshold.
142+
*
143+
* @return The underlying output stream.
144+
*
145+
* @exception IOException if an error occurs.
146+
*/
147+
protected OutputStream getStream() throws IOException
148+
{
149+
return currentOutputStream;
150+
}
151+
152+
153+
/**
154+
* Switches the underlying output stream from a memory based stream to one
155+
* that is backed by disk. This is the point at which we realise that too
156+
* much data is being written to keep in memory, so we elect to switch to
157+
* disk-based storage.
158+
*
159+
* @exception IOException if an error occurs.
160+
*/
161+
protected void thresholdReached() throws IOException
162+
{
163+
byte[] data = memoryOutputStream.toByteArray();
164+
FileOutputStream fos = new FileOutputStream(outputFile);
165+
fos.write(data);
166+
diskOutputStream = fos;
167+
currentOutputStream = fos;
168+
memoryOutputStream = null;
169+
}
170+
171+
172+
// --------------------------------------------------------- Public methods
173+
174+
175+
/**
176+
* Determines whether or not the data for this output stream has been
177+
* retained in memory.
178+
*
179+
* @return <code>true</code> if the data is available in memory;
180+
* <code>false</code> otherwise.
181+
*/
182+
public boolean isInMemory()
183+
{
184+
return (!isThresholdExceeded());
185+
}
186+
187+
188+
/**
189+
* Returns the data for this output stream as an array of bytes, assuming
190+
* that the data has been retained in memory. If the data was written to
191+
* disk, this method returns <code>null</code>.
192+
*
193+
* @return The data for this output stream, or <code>null</code> if no such
194+
* data is available.
195+
*/
196+
public byte[] getData()
197+
{
198+
if (memoryOutputStream != null)
199+
{
200+
return memoryOutputStream.toByteArray();
201+
}
202+
return null;
203+
}
204+
205+
206+
/**
207+
* Returns the data for this output stream as a <code>File</code>, assuming
208+
* that the data was written to disk. If the data was retained in memory,
209+
* this method returns <code>null</code>.
210+
*
211+
* @return The file for this output stream, or <code>null</code> if no such
212+
* file exists.
213+
*/
214+
public File getFile()
215+
{
216+
return outputFile;
217+
}
218+
}

0 commit comments

Comments
 (0)