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 }