package org.xwt.util;
import java.io.*;
+// FEATURE: don't use a byte[] if we have a diskCache file
/**
* Wraps around an InputStream, caching the stream in a byte[] as it
* is read and permitting multiple simultaneous readers
byte[] cache = new byte[1024 * 128];
int size = 0;
final InputStream is;
+ File diskCache;
- public CachedInputStream(InputStream is) { this.is = is; }
- public InputStream getInputStream() { return new SubStream(); }
+ public CachedInputStream(InputStream is) { this(is, null); }
+ public CachedInputStream(InputStream is, File diskCache) {
+ this.is = is;
+ this.diskCache = diskCache;
+ }
+ public InputStream getInputStream() throws IOException {
+ System.out.println("diskCache == " + diskCache);
+ System.out.println("diskCache.exists() == " + diskCache.exists());
+ if (diskCache != null && diskCache.exists()) return new FileInputStream(diskCache);
+ return new SubStream();
+ }
public void grow(int newLength) {
if (newLength < cache.length) return;
filling = true;
grow(size + howMuch);
int ret = is.read(cache, size, howMuch);
- if (ret == -1) eof = true;
+ if (ret == -1) {
+ eof = true;
+ // FIXME: probably a race here
+ if (diskCache != null && !diskCache.exists())
+ try {
+ File cacheFile = new File(diskCache + ".tmp");
+ FileOutputStream cacheFileStream = new FileOutputStream(cacheFile);
+ cacheFileStream.write(cache, 0, size);
+ cacheFileStream.close();
+ cacheFile.renameTo(diskCache);
+ } catch (IOException e) {
+ Log.log(this, "exception thrown while writing disk cache");
+ Log.log(this, e);
+ }
+ }
else size += ret;
filling = false;
notifyAll();
}
- private class SubStream extends InputStream {
+ private class SubStream extends InputStream implements KnownLength {
int pos = 0;
public int available() { return Math.max(0, size - pos); }
public long skip(long n) throws IOException { pos += (int)n; return n; } // FEATURE: don't skip past EOF
+ public int getLength() { return eof ? size : is instanceof KnownLength ? ((KnownLength)is).getLength() : 0; }
public int read() throws IOException { // FEATURE: be smarter here
byte[] b = new byte[1];
int ret = read(b, 0, 1);
- return ret == -1 ? -1 : b[0];
+ return ret == -1 ? -1 : b[0]&0xff;
}
public int read(byte[] b, int off, int len) throws IOException {
synchronized(CachedInputStream.this) {
if (eof && pos == size) return -1;
int count = Math.min(size - pos, len);
System.arraycopy(cache, pos, b, off, count);
+ pos += count;
return count;
}
}