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