1 3 package org.faceless.pdf2; 4 5 import java.io.*; 6 7 15 public class DiskCache implements Cache 16 { 17 private static int next; 20 private final String prefix; private final int threshold; 23 33 public DiskCache(String prefix, int threshold) 34 { 35 this.prefix = prefix; 36 this.threshold = threshold==0 || prefix==null ? Integer.MAX_VALUE : threshold; 37 } 38 39 40 public Cache.Entry newEntry(int size) 41 { 42 return new DiskCacheEntry(size); 43 } 44 45 48 private synchronized File nextFileName() 49 { 50 return prefix==null ? null : new File(prefix+(next++)); 51 } 52 53 54 private class DiskCacheEntry extends OutputStream implements Cache.Entry 55 { 56 private OutputStream out; 57 private File file; private int count; 59 private boolean closed; 60 61 public DiskCacheEntry(int size) 62 { 63 if (prefix!=null && size>threshold) { 64 try { 65 toDisk(); 66 } catch (IOException e) { 67 throw new Error ("Cannot create File \""+file+"\": "+e); 68 } 69 } else { 70 out = new MyByteArrayOutputStream(size); 71 } 72 } 73 74 public OutputStream getOutputStream() 75 { 76 if (closed) throw new IllegalStateException ("Can't write to closed stream \""+file+"\""); 77 return this; 78 } 79 80 public InputStream getInputStream() 81 { 82 if (file!=null) { 83 try { 84 if (!closed) out.flush(); 85 return new BufferedInputStream(new FileInputStream(file)); 86 } catch (IOException e) { 87 throw new Error ("Cannot create FileInputStream for \""+file+"\": "+e); 88 } 89 } else { 90 return new ByteArrayInputStream(((MyByteArrayOutputStream)out).buf, 0, count); 91 } 92 } 93 94 public int size() 95 { 96 return count; 97 } 98 99 public void writeTo(OutputStream stream) 100 throws IOException 101 { 102 if (out instanceof MyByteArrayOutputStream) { 103 stream.write(((MyByteArrayOutputStream)out).buf,0,count); 104 } else { 105 InputStream in = getInputStream(); 106 byte[] b = new byte[8192]; 107 int l; 108 while ((l = in.read(b))>=0) { 109 stream.write(b,0,l); 110 } 111 in.close(); 112 } 113 } 114 115 public Cache.Entry cloneEntry() 116 { 117 if (closed) { 118 return this; 119 } else { 120 DiskCacheEntry copy = new DiskCacheEntry(count); 121 try { 122 writeTo(copy.getOutputStream()); 123 } catch (IOException e) { 124 throw new Error ("Cannot clone stream to \""+copy.file+"\": "+e); 125 } 126 return copy; 127 } 128 } 129 130 public void close() 131 { 132 if (!closed) { 133 try { 134 out.close(); 135 } catch (IOException e) { 136 throw new Error ("Cannot close \""+file+"\": "+e); 137 } 138 closed=true; 139 } 140 } 141 142 public String toString() 143 { 144 return "<filecache size="+size()+" file="+file+">"; 145 } 146 147 public void finalize() 148 { 149 if (file!=null) file.delete(); 150 } 151 152 154 public void write(int b) throws IOException 155 { 156 out.write(b); 157 count++; 158 if (prefix!=null && file==null && count>threshold) toDisk(); 159 } 160 161 public void write(byte[] b, int off, int len) throws IOException 162 { 163 if (prefix!=null && file==null && count+len>threshold) toDisk(); 164 out.write(b,off,len); 165 count+=len; 166 } 167 168 public void write(byte[] b) throws IOException 169 { 170 write(b,0,b.length); 171 } 172 173 private void toDisk() 174 throws IOException 175 { 176 file = nextFileName(); 177 file.deleteOnExit(); 178 byte[] buf = out==null ? null : ((MyByteArrayOutputStream)out).buf; 179 out = new BufferedOutputStream(new FileOutputStream(file)); 180 if (buf!=null) out.write(buf, 0, count); 181 } 182 } 183 184 private final class MyByteArrayOutputStream extends OutputStream 185 { 186 private int count; 187 byte[] buf; 188 189 MyByteArrayOutputStream(int size) 190 { 191 buf = new byte[size==0 ? 16 : size]; 192 } 193 194 public void write(int b) 195 { 196 if (count==buf.length) extend(count+8); 197 buf[count++] = (byte)b; 198 } 199 200 public void write(byte[] b, int off, int len) 201 { 202 if (len==0) { 203 return; 204 } else if (off<0 || len<0 || off+len > b.length) { 205 throw new IndexOutOfBoundsException (off+"+"+len+" outside "+b.length); 206 } 207 if (count+len > buf.length) extend(count+len); 208 System.arraycopy(b, off, buf, count, len); 209 count+=len; 210 } 211 212 public void write(byte[] b) 213 { 214 write(b,0,b.length); 215 } 216 217 220 private final void extend(int newlen) 221 { 222 if (newlen>buf.length) { 223 if (newlen<buf.length+(buf.length>>1)) newlen=buf.length+(buf.length>>1); 224 byte[] newbuf = new byte[newlen]; 225 System.arraycopy(buf, 0, newbuf, 0, count); 226 buf=newbuf; 227 } 228 } 229 } 230 } 231 | Popular Tags |