001    package railo.commons.io;
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            @Override
037            public void write(int b) throws IOException {
038                    count++;
039                    check();
040                    os.write(b);
041            }
042            
043            @Override
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            @Override
051            public void write(byte[] b) throws IOException {
052                    count+=b.length;
053                    check();
054                    os.write(b);
055            }
056    
057            private void check() throws IOException {
058                    if(memoryMode && count>=MAX_MEMORY && os instanceof java.io.ByteArrayOutputStream) {
059                            memoryMode=false;
060                            OutputStream nos = persis.getOutputStream();
061                            nos.write(((java.io.ByteArrayOutputStream)os).toByteArray());
062                            os=nos;
063                    }
064            }
065    
066    
067            @Override
068            public void close() throws IOException {
069                    os.close();
070                    available=true;
071            }
072    
073            @Override
074            public void flush() throws IOException {
075                    os.flush();
076            }
077    
078            public InputStream getInputStream() throws IOException {
079                    return new InpuStreamWrap(this);
080            }
081            
082            class InpuStreamWrap extends InputStream {
083    
084                    private TemporaryStream ts;
085                    private InputStream is;
086    
087                    public InpuStreamWrap(TemporaryStream ts) throws IOException {
088                            this.ts=ts;
089                            if(ts.os instanceof java.io.ByteArrayOutputStream) {
090                                    is=new ByteArrayInputStream(((java.io.ByteArrayOutputStream)ts.os).toByteArray());
091                            }
092                            else if(ts.available) {
093                                    ts.available=false;
094                                    try {
095                                            is=ts.persis.getInputStream();
096                                    } catch (IOException e) {
097                                            ts.persis.delete();
098                                            throw e;
099                                    }
100                            }
101                            else 
102                                    throw new IOException("InputStream no longer available");
103                    }
104                    
105                    @Override
106                    public int read() throws IOException {
107                            return is.read();
108                    }
109    
110                    @Override
111                    public int available() throws IOException {
112                            return is.available();
113                    }
114    
115                    @Override
116                    public void close() throws IOException {
117                            ts.persis.delete();
118                            is.close();
119                    }
120    
121                    @Override
122                    public synchronized void mark(int readlimit) {
123                            is.mark(readlimit);
124                    }
125    
126                    @Override
127                    public boolean markSupported() {
128                            return is.markSupported();
129                    }
130    
131                    @Override
132                    public int read(byte[] b, int off, int len) throws IOException {
133                            return is.read(b, off, len);
134                    }
135    
136                    @Override
137                    public int read(byte[] b) throws IOException {
138                            return is.read(b);
139                    }
140    
141                    @Override
142                    public synchronized void reset() throws IOException {
143                            is.reset();
144                    }
145    
146                    @Override
147                    public long skip(long n) throws IOException {
148                            return is.skip(n);
149                    }
150            }
151    
152            public long length() {
153                    return count;
154            }
155            
156            public static Resource getTempDirectory() {
157            if(tempFile!=null) return tempFile;
158            String tmpStr = System.getProperty("java.io.tmpdir");
159            if(tmpStr!=null) {
160                    
161                    tempFile=ResourceUtil.toResourceNotExisting(ThreadLocalPageContext.get(), tmpStr);
162                    //tempFile=CFMLEngineFactory.getInstance().getCastUtil().toResource(tmpStr,null);
163                
164                if(tempFile!=null && tempFile.exists()) {
165                    tempFile=getCanonicalResourceEL(tempFile);
166                    return tempFile;
167                }
168            }
169            File tmp =null;
170            try {
171                    tmp = File.createTempFile("a","a");
172                    tempFile=ResourceUtil.toResourceNotExisting(ThreadLocalPageContext.get(), tmp.getParent());
173                    //tempFile=CFMLEngineFactory.getInstance().getCastUtil().toResource(tmp.getParent(),null);
174                tempFile=getCanonicalResourceEL(tempFile);   
175            }
176            catch(IOException ioe) {}
177            finally {
178                    if(tmp!=null)tmp.delete();
179            }
180            return tempFile;
181        }
182            
183            private static Resource getCanonicalResourceEL(Resource res) {
184                    try {
185                            return res.getCanonicalResource();
186                    } catch (IOException e) {
187                            return res.getAbsoluteResource();
188                    }
189            }
190    }