1*fd76c71bSTreehugger Robot package SQLite; 2*fd76c71bSTreehugger Robot 3*fd76c71bSTreehugger Robot import java.io.*; 4*fd76c71bSTreehugger Robot 5*fd76c71bSTreehugger Robot /** 6*fd76c71bSTreehugger Robot * Internal class implementing java.io.InputStream on 7*fd76c71bSTreehugger Robot * SQLite 3.4.0 incremental blob I/O interface. 8*fd76c71bSTreehugger Robot */ 9*fd76c71bSTreehugger Robot 10*fd76c71bSTreehugger Robot class BlobR extends InputStream { 11*fd76c71bSTreehugger Robot 12*fd76c71bSTreehugger Robot /** 13*fd76c71bSTreehugger Robot * Blob instance 14*fd76c71bSTreehugger Robot */ 15*fd76c71bSTreehugger Robot 16*fd76c71bSTreehugger Robot private Blob blob; 17*fd76c71bSTreehugger Robot 18*fd76c71bSTreehugger Robot /** 19*fd76c71bSTreehugger Robot * Read position, file pointer. 20*fd76c71bSTreehugger Robot */ 21*fd76c71bSTreehugger Robot 22*fd76c71bSTreehugger Robot private int pos; 23*fd76c71bSTreehugger Robot 24*fd76c71bSTreehugger Robot /** 25*fd76c71bSTreehugger Robot * Contruct InputStream from blob instance. 26*fd76c71bSTreehugger Robot */ 27*fd76c71bSTreehugger Robot BlobR(Blob blob)28*fd76c71bSTreehugger Robot BlobR(Blob blob) { 29*fd76c71bSTreehugger Robot this.blob = blob; 30*fd76c71bSTreehugger Robot this.pos = 0; 31*fd76c71bSTreehugger Robot } 32*fd76c71bSTreehugger Robot 33*fd76c71bSTreehugger Robot /** 34*fd76c71bSTreehugger Robot * Return number of available bytes for reading. 35*fd76c71bSTreehugger Robot * @return available input bytes 36*fd76c71bSTreehugger Robot */ 37*fd76c71bSTreehugger Robot available()38*fd76c71bSTreehugger Robot public int available() throws IOException { 39*fd76c71bSTreehugger Robot int ret = blob.size - pos; 40*fd76c71bSTreehugger Robot return (ret < 0) ? 0 : ret; 41*fd76c71bSTreehugger Robot } 42*fd76c71bSTreehugger Robot 43*fd76c71bSTreehugger Robot /** 44*fd76c71bSTreehugger Robot * Mark method; dummy to satisfy InputStream class. 45*fd76c71bSTreehugger Robot */ 46*fd76c71bSTreehugger Robot mark(int limit)47*fd76c71bSTreehugger Robot public void mark(int limit) { 48*fd76c71bSTreehugger Robot } 49*fd76c71bSTreehugger Robot 50*fd76c71bSTreehugger Robot /** 51*fd76c71bSTreehugger Robot * Reset method; dummy to satisfy InputStream class. 52*fd76c71bSTreehugger Robot */ 53*fd76c71bSTreehugger Robot reset()54*fd76c71bSTreehugger Robot public void reset() throws IOException { 55*fd76c71bSTreehugger Robot } 56*fd76c71bSTreehugger Robot 57*fd76c71bSTreehugger Robot /** 58*fd76c71bSTreehugger Robot * Mark support; not for this class. 59*fd76c71bSTreehugger Robot * @return always false 60*fd76c71bSTreehugger Robot */ 61*fd76c71bSTreehugger Robot markSupported()62*fd76c71bSTreehugger Robot public boolean markSupported() { 63*fd76c71bSTreehugger Robot return false; 64*fd76c71bSTreehugger Robot } 65*fd76c71bSTreehugger Robot 66*fd76c71bSTreehugger Robot /** 67*fd76c71bSTreehugger Robot * Close this blob InputStream. 68*fd76c71bSTreehugger Robot */ 69*fd76c71bSTreehugger Robot close()70*fd76c71bSTreehugger Robot public void close() throws IOException { 71*fd76c71bSTreehugger Robot blob.close(); 72*fd76c71bSTreehugger Robot blob = null; 73*fd76c71bSTreehugger Robot pos = 0; 74*fd76c71bSTreehugger Robot } 75*fd76c71bSTreehugger Robot 76*fd76c71bSTreehugger Robot /** 77*fd76c71bSTreehugger Robot * Skip over blob data. 78*fd76c71bSTreehugger Robot */ 79*fd76c71bSTreehugger Robot skip(long n)80*fd76c71bSTreehugger Robot public long skip(long n) throws IOException { 81*fd76c71bSTreehugger Robot long ret = pos + n; 82*fd76c71bSTreehugger Robot if (ret < 0) { 83*fd76c71bSTreehugger Robot ret = 0; 84*fd76c71bSTreehugger Robot pos = 0; 85*fd76c71bSTreehugger Robot } else if (ret > blob.size) { 86*fd76c71bSTreehugger Robot ret = blob.size; 87*fd76c71bSTreehugger Robot pos = blob.size; 88*fd76c71bSTreehugger Robot } else { 89*fd76c71bSTreehugger Robot pos = (int) ret; 90*fd76c71bSTreehugger Robot } 91*fd76c71bSTreehugger Robot return ret; 92*fd76c71bSTreehugger Robot } 93*fd76c71bSTreehugger Robot 94*fd76c71bSTreehugger Robot /** 95*fd76c71bSTreehugger Robot * Read single byte from blob. 96*fd76c71bSTreehugger Robot * @return byte read 97*fd76c71bSTreehugger Robot */ 98*fd76c71bSTreehugger Robot read()99*fd76c71bSTreehugger Robot public int read() throws IOException { 100*fd76c71bSTreehugger Robot byte b[] = new byte[1]; 101*fd76c71bSTreehugger Robot int n = blob.read(b, 0, pos, b.length); 102*fd76c71bSTreehugger Robot if (n > 0) { 103*fd76c71bSTreehugger Robot pos += n; 104*fd76c71bSTreehugger Robot return b[0]; 105*fd76c71bSTreehugger Robot } 106*fd76c71bSTreehugger Robot return -1; 107*fd76c71bSTreehugger Robot } 108*fd76c71bSTreehugger Robot 109*fd76c71bSTreehugger Robot /** 110*fd76c71bSTreehugger Robot * Read byte array from blob. 111*fd76c71bSTreehugger Robot * @param b byte array to be filled 112*fd76c71bSTreehugger Robot * @return number of bytes read 113*fd76c71bSTreehugger Robot */ 114*fd76c71bSTreehugger Robot read(byte b[])115*fd76c71bSTreehugger Robot public int read(byte b[]) throws IOException { 116*fd76c71bSTreehugger Robot int n = blob.read(b, 0, pos, b.length); 117*fd76c71bSTreehugger Robot if (n > 0) { 118*fd76c71bSTreehugger Robot pos += n; 119*fd76c71bSTreehugger Robot return n; 120*fd76c71bSTreehugger Robot } 121*fd76c71bSTreehugger Robot return -1; 122*fd76c71bSTreehugger Robot } 123*fd76c71bSTreehugger Robot 124*fd76c71bSTreehugger Robot /** 125*fd76c71bSTreehugger Robot * Read slice of byte array from blob. 126*fd76c71bSTreehugger Robot * @param b byte array to be filled 127*fd76c71bSTreehugger Robot * @param off offset into byte array 128*fd76c71bSTreehugger Robot * @param len length to be read 129*fd76c71bSTreehugger Robot * @return number of bytes read 130*fd76c71bSTreehugger Robot */ 131*fd76c71bSTreehugger Robot read(byte b[], int off, int len)132*fd76c71bSTreehugger Robot public int read(byte b[], int off, int len) throws IOException { 133*fd76c71bSTreehugger Robot if (off + len > b.length) { 134*fd76c71bSTreehugger Robot len = b.length - off; 135*fd76c71bSTreehugger Robot } 136*fd76c71bSTreehugger Robot if (len < 0) { 137*fd76c71bSTreehugger Robot return -1; 138*fd76c71bSTreehugger Robot } 139*fd76c71bSTreehugger Robot if (len == 0) { 140*fd76c71bSTreehugger Robot return 0; 141*fd76c71bSTreehugger Robot } 142*fd76c71bSTreehugger Robot int n = blob.read(b, off, pos, len); 143*fd76c71bSTreehugger Robot if (n > 0) { 144*fd76c71bSTreehugger Robot pos += n; 145*fd76c71bSTreehugger Robot return n; 146*fd76c71bSTreehugger Robot } 147*fd76c71bSTreehugger Robot return -1; 148*fd76c71bSTreehugger Robot } 149*fd76c71bSTreehugger Robot } 150*fd76c71bSTreehugger Robot 151*fd76c71bSTreehugger Robot /** 152*fd76c71bSTreehugger Robot * Internal class implementing java.io.OutputStream on 153*fd76c71bSTreehugger Robot * SQLite 3.4.0 incremental blob I/O interface. 154*fd76c71bSTreehugger Robot */ 155*fd76c71bSTreehugger Robot 156*fd76c71bSTreehugger Robot class BlobW extends OutputStream { 157*fd76c71bSTreehugger Robot 158*fd76c71bSTreehugger Robot /** 159*fd76c71bSTreehugger Robot * Blob instance 160*fd76c71bSTreehugger Robot */ 161*fd76c71bSTreehugger Robot 162*fd76c71bSTreehugger Robot private Blob blob; 163*fd76c71bSTreehugger Robot 164*fd76c71bSTreehugger Robot /** 165*fd76c71bSTreehugger Robot * Read position, file pointer. 166*fd76c71bSTreehugger Robot */ 167*fd76c71bSTreehugger Robot 168*fd76c71bSTreehugger Robot private int pos; 169*fd76c71bSTreehugger Robot 170*fd76c71bSTreehugger Robot /** 171*fd76c71bSTreehugger Robot * Contruct OutputStream from blob instance. 172*fd76c71bSTreehugger Robot */ 173*fd76c71bSTreehugger Robot BlobW(Blob blob)174*fd76c71bSTreehugger Robot BlobW(Blob blob) { 175*fd76c71bSTreehugger Robot this.blob = blob; 176*fd76c71bSTreehugger Robot this.pos = 0; 177*fd76c71bSTreehugger Robot } 178*fd76c71bSTreehugger Robot 179*fd76c71bSTreehugger Robot /** 180*fd76c71bSTreehugger Robot * Flush blob; dummy to satisfy OutputStream class. 181*fd76c71bSTreehugger Robot */ 182*fd76c71bSTreehugger Robot flush()183*fd76c71bSTreehugger Robot public void flush() throws IOException { 184*fd76c71bSTreehugger Robot } 185*fd76c71bSTreehugger Robot 186*fd76c71bSTreehugger Robot /** 187*fd76c71bSTreehugger Robot * Close this blob OutputStream. 188*fd76c71bSTreehugger Robot */ 189*fd76c71bSTreehugger Robot close()190*fd76c71bSTreehugger Robot public void close() throws IOException { 191*fd76c71bSTreehugger Robot blob.close(); 192*fd76c71bSTreehugger Robot blob = null; 193*fd76c71bSTreehugger Robot pos = 0; 194*fd76c71bSTreehugger Robot } 195*fd76c71bSTreehugger Robot 196*fd76c71bSTreehugger Robot /** 197*fd76c71bSTreehugger Robot * Write blob data. 198*fd76c71bSTreehugger Robot * @param v byte to be written at current position. 199*fd76c71bSTreehugger Robot */ 200*fd76c71bSTreehugger Robot write(int v)201*fd76c71bSTreehugger Robot public void write(int v) throws IOException { 202*fd76c71bSTreehugger Robot byte b[] = new byte[1]; 203*fd76c71bSTreehugger Robot b[0] = (byte) v; 204*fd76c71bSTreehugger Robot pos += blob.write(b, 0, pos, 1); 205*fd76c71bSTreehugger Robot } 206*fd76c71bSTreehugger Robot 207*fd76c71bSTreehugger Robot /** 208*fd76c71bSTreehugger Robot * Write blob data. 209*fd76c71bSTreehugger Robot * @param b byte array to be written at current position. 210*fd76c71bSTreehugger Robot */ 211*fd76c71bSTreehugger Robot write(byte[] b)212*fd76c71bSTreehugger Robot public void write(byte[] b) throws IOException { 213*fd76c71bSTreehugger Robot if (b != null && b.length > 0) { 214*fd76c71bSTreehugger Robot pos += blob.write(b, 0, pos, b.length); 215*fd76c71bSTreehugger Robot } 216*fd76c71bSTreehugger Robot } 217*fd76c71bSTreehugger Robot 218*fd76c71bSTreehugger Robot /** 219*fd76c71bSTreehugger Robot * Write blob data. 220*fd76c71bSTreehugger Robot * @param b byte array to be written. 221*fd76c71bSTreehugger Robot * @param off offset within byte array 222*fd76c71bSTreehugger Robot * @param len length of data to be written 223*fd76c71bSTreehugger Robot */ 224*fd76c71bSTreehugger Robot write(byte[] b, int off, int len)225*fd76c71bSTreehugger Robot public void write(byte[] b, int off, int len) throws IOException { 226*fd76c71bSTreehugger Robot if (b != null) { 227*fd76c71bSTreehugger Robot if (off + len > b.length) { 228*fd76c71bSTreehugger Robot len = b.length - off; 229*fd76c71bSTreehugger Robot } 230*fd76c71bSTreehugger Robot if (len <= 0) { 231*fd76c71bSTreehugger Robot return; 232*fd76c71bSTreehugger Robot } 233*fd76c71bSTreehugger Robot pos += blob.write(b, off, pos, len); 234*fd76c71bSTreehugger Robot } 235*fd76c71bSTreehugger Robot } 236*fd76c71bSTreehugger Robot } 237*fd76c71bSTreehugger Robot 238*fd76c71bSTreehugger Robot /** 239*fd76c71bSTreehugger Robot * Class to represent SQLite3 3.4.0 incremental blob I/O interface. 240*fd76c71bSTreehugger Robot * 241*fd76c71bSTreehugger Robot * Note, that all native methods of this class are 242*fd76c71bSTreehugger Robot * not synchronized, i.e. it is up to the caller 243*fd76c71bSTreehugger Robot * to ensure that only one thread is in these 244*fd76c71bSTreehugger Robot * methods at any one time. 245*fd76c71bSTreehugger Robot */ 246*fd76c71bSTreehugger Robot 247*fd76c71bSTreehugger Robot public class Blob { 248*fd76c71bSTreehugger Robot 249*fd76c71bSTreehugger Robot /** 250*fd76c71bSTreehugger Robot * Internal handle for the SQLite3 blob. 251*fd76c71bSTreehugger Robot */ 252*fd76c71bSTreehugger Robot 253*fd76c71bSTreehugger Robot private long handle = 0; 254*fd76c71bSTreehugger Robot 255*fd76c71bSTreehugger Robot /** 256*fd76c71bSTreehugger Robot * Cached size of blob, setup right after blob 257*fd76c71bSTreehugger Robot * has been opened. 258*fd76c71bSTreehugger Robot */ 259*fd76c71bSTreehugger Robot 260*fd76c71bSTreehugger Robot protected int size = 0; 261*fd76c71bSTreehugger Robot 262*fd76c71bSTreehugger Robot /** 263*fd76c71bSTreehugger Robot * Return InputStream for this blob 264*fd76c71bSTreehugger Robot * @return InputStream 265*fd76c71bSTreehugger Robot */ 266*fd76c71bSTreehugger Robot getInputStream()267*fd76c71bSTreehugger Robot public InputStream getInputStream() { 268*fd76c71bSTreehugger Robot return (InputStream) new BlobR(this); 269*fd76c71bSTreehugger Robot } 270*fd76c71bSTreehugger Robot 271*fd76c71bSTreehugger Robot /** 272*fd76c71bSTreehugger Robot * Return OutputStream for this blob 273*fd76c71bSTreehugger Robot * @return OutputStream 274*fd76c71bSTreehugger Robot */ 275*fd76c71bSTreehugger Robot getOutputStream()276*fd76c71bSTreehugger Robot public OutputStream getOutputStream() { 277*fd76c71bSTreehugger Robot return (OutputStream) new BlobW(this); 278*fd76c71bSTreehugger Robot } 279*fd76c71bSTreehugger Robot 280*fd76c71bSTreehugger Robot /** 281*fd76c71bSTreehugger Robot * Close blob. 282*fd76c71bSTreehugger Robot */ 283*fd76c71bSTreehugger Robot close()284*fd76c71bSTreehugger Robot public native void close(); 285*fd76c71bSTreehugger Robot 286*fd76c71bSTreehugger Robot /** 287*fd76c71bSTreehugger Robot * Internal blob write method. 288*fd76c71bSTreehugger Robot * @param b byte array to be written 289*fd76c71bSTreehugger Robot * @param off offset into byte array 290*fd76c71bSTreehugger Robot * @param pos offset into blob 291*fd76c71bSTreehugger Robot * @param len length to be written 292*fd76c71bSTreehugger Robot * @return number of bytes written to blob 293*fd76c71bSTreehugger Robot */ 294*fd76c71bSTreehugger Robot write(byte[] b, int off, int pos, int len)295*fd76c71bSTreehugger Robot native int write(byte[] b, int off, int pos, int len) throws IOException; 296*fd76c71bSTreehugger Robot 297*fd76c71bSTreehugger Robot /** 298*fd76c71bSTreehugger Robot * Internal blob read method. 299*fd76c71bSTreehugger Robot * @param b byte array to be written 300*fd76c71bSTreehugger Robot * @param off offset into byte array 301*fd76c71bSTreehugger Robot * @param pos offset into blob 302*fd76c71bSTreehugger Robot * @param len length to be written 303*fd76c71bSTreehugger Robot * @return number of bytes written to blob 304*fd76c71bSTreehugger Robot */ 305*fd76c71bSTreehugger Robot read(byte[] b, int off, int pos, int len)306*fd76c71bSTreehugger Robot native int read(byte[] b, int off, int pos, int len) throws IOException; 307*fd76c71bSTreehugger Robot 308*fd76c71bSTreehugger Robot /** 309*fd76c71bSTreehugger Robot * Destructor for object. 310*fd76c71bSTreehugger Robot */ 311*fd76c71bSTreehugger Robot finalize()312*fd76c71bSTreehugger Robot protected native void finalize(); 313*fd76c71bSTreehugger Robot 314*fd76c71bSTreehugger Robot /** 315*fd76c71bSTreehugger Robot * Internal native initializer. 316*fd76c71bSTreehugger Robot */ 317*fd76c71bSTreehugger Robot internal_init()318*fd76c71bSTreehugger Robot private static native void internal_init(); 319*fd76c71bSTreehugger Robot 320*fd76c71bSTreehugger Robot static { internal_init()321*fd76c71bSTreehugger Robot internal_init(); 322*fd76c71bSTreehugger Robot } 323*fd76c71bSTreehugger Robot } 324