/*
* @(#)MemoryCacheImageInputStream.java 1.23 03/12/19
*
* Copyright 2004 Sun Microsystems, Inc. All rights reserved.
* SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
*/
package javax.imageio.stream;
import java.io.InputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;
/**
* An implementation of ImageInputStream
that gets its
* input from a regular InputStream
. A memory buffer is
* used to cache at least the data between the discard position and
* the current read position.
*
*
In general, it is preferable to use a
* FileCacheImageInputStream
when reading from a regular
* InputStream
. This class is provided for cases where
* it is not possible to create a writable temporary file.
*
* @version 0.5
*/
public class MemoryCacheImageInputStream extends ImageInputStreamImpl {
private InputStream stream;
private MemoryCache cache = new MemoryCache();
/**
* Constructs a MemoryCacheImageInputStream
that will read
* from a given InputStream
.
*
* @param stream an InputStream
to read from.
*
* @exception IllegalArgumentException if stream
is
* null
.
*/
public MemoryCacheImageInputStream(InputStream stream) {
if (stream == null) {
throw new IllegalArgumentException("stream == null!");
}
this.stream = stream;
}
public int read() throws IOException {
checkClosed();
bitOffset = 0;
long thisByte = streamPos;
long pos = cache.loadFromStream(stream, streamPos+1);
if (pos >= streamPos+1) {
return cache.read(streamPos++);
} else {
return -1;
}
}
public int read(byte[] b, int off, int len) throws IOException {
checkClosed();
// Will throw NullPointerException
if (off < 0 || len < 0 || off + len > b.length || off + len < 0) {
throw new IndexOutOfBoundsException
("off < 0 || len < 0 || off + len > b.length!");
}
bitOffset = 0;
if (len == 0) {
return 0;
}
long pos = cache.loadFromStream(stream, streamPos+len);
len = (int)(pos - streamPos); // In case stream ended early
if (len > 0) {
cache.read(b, off, len, streamPos);
streamPos += len;
return len;
} else {
return -1;
}
}
public void flushBefore(long pos) throws IOException {
super.flushBefore(pos);
cache.disposeBefore(pos);
}
/**
* Returns true
since this
* ImageInputStream
caches data in order to allow
* seeking backwards.
*
* @return true
.
*
* @see #isCachedMemory
* @see #isCachedFile
*/
public boolean isCached() {
return true;
}
/**
* Returns false
since this
* ImageInputStream
does not maintain a file cache.
*
* @return false
.
*
* @see #isCached
* @see #isCachedMemory
*/
public boolean isCachedFile() {
return false;
}
/**
* Returns true
since this
* ImageInputStream
maintains a main memory cache.
*
* @return true
.
*
* @see #isCached
* @see #isCachedFile
*/
public boolean isCachedMemory() {
return true;
}
/**
* Closes this MemoryCacheImageInputStream
, freeing
* the cache. The source InputStream
is not closed.
*/
public void close() throws IOException {
super.close();
cache.reset();
stream = null;
}
}