1
2
3
4
5
6
7
8 package org.xwt.util;
9 import java.io.*;
10
11
12
16 public class CachedInputStream {
17
18 boolean filling = false;
19 boolean eof = false;
20 byte[] cache = new byte[1024 * 128];
21 int size = 0;
22 final InputStream is;
23 File diskCache;
24
25 public CachedInputStream(InputStream is) { this(is, null); }
26 public CachedInputStream(InputStream is, File diskCache) {
27 this.is = is;
28 this.diskCache = diskCache;
29 }
30 public InputStream getInputStream() throws IOException {
31 if (diskCache != null && diskCache.exists()) return new FileInputStream(diskCache);
32 return new SubStream();
33 }
34
35 public void grow(int newLength) {
36 if (newLength < cache.length) return;
37 byte[] newCache = new byte[cache.length + 2 * (newLength - cache.length)];
38 System.arraycopy(cache, 0, newCache, 0, size);
39 cache = newCache;
40 }
41
42 synchronized void fillCache(int howMuch) throws IOException {
43 if (filling) { try { wait(); } catch (InterruptedException e) { }; return; }
44 filling = true;
45 grow(size + howMuch);
46 int ret = is.read(cache, size, howMuch);
47 if (ret == -1) {
48 eof = true;
49
50 if (diskCache != null && !diskCache.exists())
51 try {
52 File cacheFile = new File(diskCache + ".incomplete");
53 FileOutputStream cacheFileStream = new FileOutputStream(cacheFile);
54 cacheFileStream.write(cache, 0, size);
55 cacheFileStream.close();
56 cacheFile.renameTo(diskCache);
57 } catch (IOException e) {
58 Log.info(this, "exception thrown while writing disk cache");
59 Log.info(this, e);
60 }
61 }
62 else size += ret;
63 filling = false;
64 notifyAll();
65 }
66
67 private class SubStream extends InputStream implements KnownLength {
68 int pos = 0;
69 public int available() { return Math.max(0, size - pos); }
70 public long skip(long n) throws IOException { pos += (int)n; return n; }
71 public int getLength() { return eof ? size : is instanceof KnownLength ? ((KnownLength)is).getLength() : 0; }
72 public int read() throws IOException {
73 byte[] b = new byte[1];
74 int ret = read(b, 0, 1);
75 return ret == -1 ? -1 : b[0]&0xff;
76 }
77 public int read(byte[] b, int off, int len) throws IOException {
78 synchronized(CachedInputStream.this) {
79 while (pos >= size && !eof) fillCache(pos + len - size);
80 if (eof && pos == size) return -1;
81 int count = Math.min(size - pos, len);
82 System.arraycopy(cache, pos, b, off, count);
83 pos += count;
84 return count;
85 }
86 }
87 }
88 }
89