package org.postgresql.largeobject; import java.io.InputStream; import java.io.IOException; import java.sql.SQLException; /** * This is an initial implementation of an InputStream from a large object. * For now, the bare minimum is implemented. Later (after 7.1) we will overide * the other read methods to optimise them. */ public class BlobInputStream extends InputStream { /** * The parent LargeObject */ private LargeObject lo; /** * Buffer used to improve performance */ private byte[] buffer; /** * Position within buffer */ private int bpos; /** * The buffer size */ private int bsize; /** * The mark position */ private int mpos=0; /** * @param lo LargeObject to read from */ public BlobInputStream(LargeObject lo) { this(lo,1024); } /** * @param lo LargeObject to read from * @param bsize buffer size */ public BlobInputStream(LargeObject lo,int bsize) { this.lo=lo; buffer=null; bpos=0; this.bsize=bsize; } /** * The minimum required to implement input stream */ public int read() throws java.io.IOException { try { if (buffer == null || bpos >= buffer.length) { buffer=lo.read(bsize); bpos=0; } // Handle EOF if(bpos >= buffer.length) { return -1; } int ret = (buffer[bpos] & 0x7F); if ((buffer[bpos] &0x80) == 0x80) { ret |= 0x80; } bpos++; return ret; } catch(SQLException se) { throw new IOException(se.toString()); } } /** * Closes this input stream and releases any system resources associated * with the stream. * *
The close
method of InputStream
does
* nothing.
*
* @exception IOException if an I/O error occurs.
*/
public void close() throws IOException {
try {
lo.close();
lo=null;
} catch(SQLException se) {
throw new IOException(se.toString());
}
}
/**
* Marks the current position in this input stream. A subsequent call to
* the reset
method repositions this stream at the last marked
* position so that subsequent reads re-read the same bytes.
*
*
The readlimit
arguments tells this input stream to
* allow that many bytes to be read before the mark position gets
* invalidated.
*
*
The general contract of mark
is that, if the method
* markSupported
returns true
, the stream somehow
* remembers all the bytes read after the call to mark
and
* stands ready to supply those same bytes again if and whenever the method
* reset
is called. However, the stream is not required to
* remember any data at all if more than readlimit
bytes are
* read from the stream before reset
is called.
*
*
The mark
method of InputStream
does
* nothing.
*
* @param readlimit the maximum limit of bytes that can be read before
* the mark position becomes invalid.
* @see java.io.InputStream#reset()
*/
public synchronized void mark(int readlimit) {
try {
mpos=lo.tell();
} catch(SQLException se) {
//throw new IOException(se.toString());
}
}
/**
* Repositions this stream to the position at the time the
* mark
method was last called on this input stream.
* NB: If mark is not called we move to the begining.
* @see java.io.InputStream#mark(int)
* @see java.io.IOException
*/
public synchronized void reset() throws IOException {
try {
lo.seek(mpos);
} catch(SQLException se) {
throw new IOException(se.toString());
}
}
/**
* Tests if this input stream supports the mark
and
* reset
methods. The markSupported
method of
* InputStream
returns false
.
*
* @return true
if this true type supports the mark and reset
* method; false
otherwise.
* @see java.io.InputStream#mark(int)
* @see java.io.InputStream#reset()
*/
public boolean markSupported() {
return true;
}
}