1 package com.atlassian.core.spool;
2
3 import java.io.*;
4
5 /**
6 * This specialisation of DeferredFileOutputStream may be configured with a FileFactory so that files are only created
7 * once the deferred threshold is reached. getInputStream() returns a SpoolFileInputStream to read the result,
8 * which means that the deferred file will be deleted once the input stream is closed.
9 */
10 public class DeferredSpoolFileOutputStream extends DeferredFileOutputStream
11 {
12 private FileFactory fileFactory = DefaultSpoolFileFactory.getInstance();
13 private boolean unspooling = false;
14
15 /**
16 * Create a new DeferredSpoolFileOutputStream with the specified threshold and deferred file
17 * @see #DeferredFileOutputStream(int, File)
18 */
19 public DeferredSpoolFileOutputStream(int threshold, File outputFile)
20 {
21 super(threshold, outputFile);
22 }
23
24 /**
25 * Create a new DeferredSpoolFileOutputStream with the specified threshold and file factory. The file factory
26 * will only be used when the threshold is reached, so you can defer the creation of files until they are necessary
27 * @param threshold
28 * @param fileFactory Factory to use when the deferred file must be created
29 */
30 public DeferredSpoolFileOutputStream(int threshold, FileFactory fileFactory)
31 {
32 super(threshold, null);
33 this.fileFactory = fileFactory;
34 }
35
36 /**
37 * @return True if the stream has been closed
38 */
39 public boolean isClosed()
40 {
41 return closed;
42 }
43
44 /**
45 *
46 * @return True if getInputStream() has been called already
47 */
48 public boolean isUnspooling()
49 {
50 return unspooling;
51 }
52
53 protected void thresholdReached() throws IOException
54 {
55 if (outputFile == null)
56 outputFile = fileFactory.createNewFile();
57 super.thresholdReached();
58 }
59
60 /**
61 * Return an input stream of the written data. This method may only be called once and only once the output stream
62 * has been closed.
63 *
64 * @return A InputStream - If the deferred stream has been written to disk, a SpoolFileInputStream will be returned
65 * and the deferred file will be deleted when this stream is closed.
66 * @throws IOException If the output stream is not closed or an input stream has already been returned
67 */
68 public InputStream getInputStream() throws IOException
69 {
70 if (!isClosed())
71 throw new IOException("Output stream not closed");
72
73 if (isUnspooling())
74 throw new IOException("Stream is already being unspooled");
75
76 InputStream spoolStream;
77
78 if (isInMemory())
79 spoolStream = new ByteArrayInputStream(getData());
80 else
81 try
82 {
83 spoolStream = new SpoolFileInputStream(getFile());
84 }
85 catch (FileNotFoundException ex)
86 {
87 throw new IOException("Deferred file does not exist");
88 }
89
90 unspooling = true;
91 return spoolStream;
92 }
93 }