1bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/*
2bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Licensed to the Apache Software Foundation (ASF) under one or more
3bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * contributor license agreements.  See the NOTICE file distributed with
4bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * this work for additional information regarding copyright ownership.
5bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * The ASF licenses this file to You under the Apache License, Version 2.0
6bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * (the "License"); you may not use this file except in compliance with
7bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * the License.  You may obtain a copy of the License at
8bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
9bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *      http://www.apache.org/licenses/LICENSE-2.0
10bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
11bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * Unless required by applicable law or agreed to in writing, software
12bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * distributed under the License is distributed on an "AS IS" BASIS,
13bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * See the License for the specific language governing permissions and
15bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * limitations under the License.
16bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */
17bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpackage org.apache.commons.io.output;
18bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
19bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.File;
20bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.FileInputStream;
21bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.FileOutputStream;
22bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.IOException;
23bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport java.io.OutputStream;
24bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
25bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookimport org.apache.commons.io.IOUtils;
26bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
27bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
28bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook/**
29bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * An output stream which will retain data in memory until a specified
30bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * threshold is reached, and only then commit it to disk. If the stream is
31bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * closed before the threshold is reached, the data will not be written to
32bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * disk at all.
33bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * <p>
34bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * This class originated in FileUpload processing. In this use case, you do
35bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * not know in advance the size of the file being uploaded. If the file is small
36bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * you want to store it in memory (for speed), but if the file is large you want
37bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * to store it to file (to avoid memory issues).
38bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
39bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @author <a href="mailto:martinc@apache.org">Martin Cooper</a>
40bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @author gaxzerow
41bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook *
42bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook * @version $Id: DeferredFileOutputStream.java 606381 2007-12-22 02:03:16Z ggregory $
43bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook */
44bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrookpublic class DeferredFileOutputStream
45bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    extends ThresholdingOutputStream
46bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook{
47bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
48bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    // ----------------------------------------------------------- Data members
49bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
50bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
51bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
52bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The output stream to which data will be written prior to the theshold
53bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * being reached.
54bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
55bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private ByteArrayOutputStream memoryOutputStream;
56bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
57bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
58bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
59bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The output stream to which data will be written at any given time. This
60bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * will always be one of <code>memoryOutputStream</code> or
61bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <code>diskOutputStream</code>.
62bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
63bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private OutputStream currentOutputStream;
64bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
65bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
66bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
67bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The file to which output will be directed if the threshold is exceeded.
68bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
69bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private File outputFile;
70bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
71bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
72bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The temporary file prefix.
73bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
74bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private String prefix;
75bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
76bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
77bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The temporary file suffix.
78bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
79bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private String suffix;
80bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
81bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
82bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * The directory to use for temporary files.
83bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
84bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private File directory;
85bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
86bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
87bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
88bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * True when close() has been called successfully.
89bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
90bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    private boolean closed = false;
91bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
92bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    // ----------------------------------------------------------- Constructors
93bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
94bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
95bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
96bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Constructs an instance of this class which will trigger an event at the
97bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * specified threshold, and save data to a file beyond that point.
98bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
99bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param threshold  The number of bytes at which to trigger an event.
100bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param outputFile The file to which data is saved beyond the threshold.
101bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
102bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public DeferredFileOutputStream(int threshold, File outputFile)
103bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    {
104bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        super(threshold);
105bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        this.outputFile = outputFile;
106bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
107bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        memoryOutputStream = new ByteArrayOutputStream();
108bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        currentOutputStream = memoryOutputStream;
109bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
110bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
111bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
112bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
113bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Constructs an instance of this class which will trigger an event at the
114bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * specified threshold, and save data to a temporary file beyond that point.
115bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
116bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param threshold  The number of bytes at which to trigger an event.
117bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param prefix Prefix to use for the temporary file.
118bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param suffix Suffix to use for the temporary file.
119bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param directory Temporary file directory.
120bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
121bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @since Commons IO 1.4
122bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
123bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public DeferredFileOutputStream(int threshold, String prefix, String suffix, File directory)
124bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    {
125bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        this(threshold, (File)null);
126bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (prefix == null) {
127bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            throw new IllegalArgumentException("Temporary file prefix is missing");
128bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
129bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        this.prefix = prefix;
130bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        this.suffix = suffix;
131bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        this.directory = directory;
132bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
133bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
134bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
135bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    // --------------------------------------- ThresholdingOutputStream methods
136bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
137bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
138bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
139bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Returns the current output stream. This may be memory based or disk
140bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * based, depending on the current state with respect to the threshold.
141bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
142bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return The underlying output stream.
143bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
144bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @exception IOException if an error occurs.
145bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
146bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected OutputStream getStream() throws IOException
147bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    {
148bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return currentOutputStream;
149bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
150bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
151bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
152bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
153bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Switches the underlying output stream from a memory based stream to one
154bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * that is backed by disk. This is the point at which we realise that too
155bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * much data is being written to keep in memory, so we elect to switch to
156bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * disk-based storage.
157bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
158bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @exception IOException if an error occurs.
159bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
160bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    protected void thresholdReached() throws IOException
161bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    {
162bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (prefix != null) {
163bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            outputFile = File.createTempFile(prefix, suffix, directory);
164bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
165bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        FileOutputStream fos = new FileOutputStream(outputFile);
166bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        memoryOutputStream.writeTo(fos);
167bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        currentOutputStream = fos;
168bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        memoryOutputStream = null;
169bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
170bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
171bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
172bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    // --------------------------------------------------------- Public methods
173bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
174bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
175bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
176bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Determines whether or not the data for this output stream has been
177bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * retained in memory.
178bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
179bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return <code>true</code> if the data is available in memory;
180bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *         <code>false</code> otherwise.
181bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
182bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public boolean isInMemory()
183bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    {
184bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return (!isThresholdExceeded());
185bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
186bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
187bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
188bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
189bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Returns the data for this output stream as an array of bytes, assuming
190bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * that the data has been retained in memory. If the data was written to
191bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * disk, this method returns <code>null</code>.
192bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
193bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return The data for this output stream, or <code>null</code> if no such
194bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *         data is available.
195bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
196bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public byte[] getData()
197bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    {
198bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (memoryOutputStream != null)
199bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        {
200bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            return memoryOutputStream.toByteArray();
201bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
202bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return null;
203bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
204bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
205bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
206bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
207bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Returns either the output file specified in the constructor or
208bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * the temporary file created or null.
209bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <p>
210bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * If the constructor specifying the file is used then it returns that
211bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * same output file, even when threashold has not been reached.
212bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * <p>
213bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * If constructor specifying a temporary file prefix/suffix is used
214bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * then the temporary file created once the threashold is reached is returned
215bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * If the threshold was not reached then <code>null</code> is returned.
216bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
217bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @return The file for this output stream, or <code>null</code> if no such
218bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *         file exists.
219bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
220bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public File getFile()
221bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    {
222bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        return outputFile;
223bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
224bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
225bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
226bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
227bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Closes underlying output stream, and mark this as closed
228bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
229bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @exception IOException if an error occurs.
230bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
231bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void close() throws IOException
232bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    {
233bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        super.close();
234bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        closed = true;
235bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
236bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
237bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
238bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    /**
239bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * Writes the data from this output stream to the specified output stream,
240bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * after it has been closed.
241bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     *
242bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @param out output stream to write to.
243bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     * @exception IOException if this stream is not yet closed or an error occurs.
244bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook     */
245bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    public void writeTo(OutputStream out) throws IOException
246bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    {
247bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // we may only need to check if this is closed if we are working with a file
248bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // but we should force the habit of closing wether we are working with
249bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        // a file or memory.
250bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if (!closed)
251bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        {
252bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            throw new IOException("Stream not closed");
253bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
254bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook
255bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        if(isInMemory())
256bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        {
257bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            memoryOutputStream.writeTo(out);
258bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
259bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        else
260bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        {
261bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            FileInputStream fis = new FileInputStream(outputFile);
262bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            try {
263bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                IOUtils.copy(fis, out);
264bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            } finally {
265bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook                IOUtils.closeQuietly(fis);
266bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook            }
267bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook        }
268bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook    }
269bc47398187c6ffd132435e51d8d61e6ec79a79dbPaul Westbrook}
270