001    package railo.commons.io;
002    
003    import java.io.ByteArrayInputStream;
004    import java.io.IOException;
005    import java.io.InputStream;
006    import java.io.OutputStream;
007    
008    import railo.commons.io.res.Resource;
009    
010    public final class TemporaryStream extends OutputStream {
011    
012            private static final int MAX_MEMORY = 1024*1024;
013            private static int index=1;
014            
015            private Resource persis;
016            private long count=0;
017            private OutputStream os;
018            public boolean memoryMode=true;
019            public boolean available=false;
020            
021            /**
022             * Constructor of the class
023             */
024            public TemporaryStream() {
025                    do {
026                    this.persis=SystemUtil.getTempDirectory().getRealResource("temporary-stream-"+(index++));
027                    }
028                    while(persis.exists());
029                    os=new java.io.ByteArrayOutputStream();
030            }
031            
032            /**
033             * @see java.io.OutputStream#write(int)
034             */
035            public void write(int b) throws IOException {
036                    count++;
037                    check();
038                    os.write(b);
039            }
040            
041            /**
042             * @see java.io.OutputStream#write(byte[], int, int)
043             */
044            public void write(byte[] b, int off, int len) throws IOException {
045                    count+=len;
046                    check();
047                    os.write(b, off, len);
048            }
049    
050            /**
051             * @see java.io.OutputStream#write(byte[])
052             */
053            public void write(byte[] b) throws IOException {
054                    count+=b.length;
055                    check();
056                    os.write(b);
057            }
058    
059            private void check() throws IOException {
060                    if(memoryMode && count>=MAX_MEMORY && os instanceof java.io.ByteArrayOutputStream) {
061                            memoryMode=false;
062                            OutputStream nos = persis.getOutputStream();
063                            nos.write(((java.io.ByteArrayOutputStream)os).toByteArray());
064                            os=nos;
065                    }
066            }
067    
068    
069            /**
070             * @see java.io.OutputStream#close()
071             */
072            public void close() throws IOException {
073                    os.close();
074                    available=true;
075            }
076    
077            /**
078             * @see java.io.OutputStream#flush()
079             */
080            public void flush() throws IOException {
081                    os.flush();
082            }
083    
084            public InputStream getInputStream() throws IOException {
085                    return new InpuStreamWrap(this);
086            }
087            
088            class InpuStreamWrap extends InputStream {
089    
090                    private TemporaryStream ts;
091                    private InputStream is;
092    
093                    public InpuStreamWrap(TemporaryStream ts) throws IOException {
094                            this.ts=ts;
095                            if(ts.os instanceof java.io.ByteArrayOutputStream) {
096                                    is=new ByteArrayInputStream(((java.io.ByteArrayOutputStream)ts.os).toByteArray());
097                            }
098                            else if(ts.available) {
099                                    ts.available=false;
100                                    try {
101                                            is=ts.persis.getInputStream();
102                                    } catch (IOException e) {
103                                            ts.persis.delete();
104                                            throw e;
105                                    }
106                            }
107                            else 
108                                    throw new IOException("InputStream no longer available");
109                    }
110                    
111                    /**
112                     * @see java.io.InputStream#read()
113                     */
114                    public int read() throws IOException {
115                            return is.read();
116                    }
117    
118                    /**
119                     * @see java.io.InputStream#available()
120                     */
121                    public int available() throws IOException {
122                            return is.available();
123                    }
124    
125                    /**
126                     * @see java.io.InputStream#close()
127                     */
128                    public void close() throws IOException {
129                            ts.persis.delete();
130                            is.close();
131                    }
132    
133                    /**
134                     *
135                     * @see java.io.InputStream#mark(int)
136                     */
137                    public synchronized void mark(int readlimit) {
138                            is.mark(readlimit);
139                    }
140    
141                    /**
142                     *
143                     * @see java.io.InputStream#markSupported()
144                     */
145                    public boolean markSupported() {
146                            return is.markSupported();
147                    }
148    
149                    /**
150                     *
151                     * @see java.io.InputStream#read(byte[], int, int)
152                     */
153                    public int read(byte[] b, int off, int len) throws IOException {
154                            return is.read(b, off, len);
155                    }
156    
157                    /**
158                     *
159                     * @see java.io.InputStream#read(byte[])
160                     */
161                    public int read(byte[] b) throws IOException {
162                            return is.read(b);
163                    }
164    
165                    /**
166                     *
167                     * @see java.io.InputStream#reset()
168                     */
169                    public synchronized void reset() throws IOException {
170                            is.reset();
171                    }
172    
173                    /**
174                     *
175                     * @see java.io.InputStream#skip(long)
176                     */
177                    public long skip(long n) throws IOException {
178                            return is.skip(n);
179                    }
180            }
181    
182            public long length() {
183                    return count;
184            }
185    }