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 }