KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > quadcap > sql > types > ValueBlob


1 package com.quadcap.sql.types;
2
3 /* Copyright 1999 - 2003 Quadcap Software. All rights reserved.
4  *
5  * This software is distributed under the Quadcap Free Software License.
6  * This software may be used or modified for any purpose, personal or
7  * commercial. Open Source redistributions are permitted. Commercial
8  * redistribution of larger works derived from, or works which bundle
9  * this software requires a "Commercial Redistribution License"; see
10  * http://www.quadcap.com/purchase.
11  *
12  * Redistributions qualify as "Open Source" under one of the following terms:
13  *
14  * Redistributions are made at no charge beyond the reasonable cost of
15  * materials and delivery.
16  *
17  * Redistributions are accompanied by a copy of the Source Code or by an
18  * irrevocable offer to provide a copy of the Source Code for up to three
19  * years at the cost of materials and delivery. Such redistributions
20  * must allow further use, modification, and redistribution of the Source
21  * Code under substantially the same terms as this license.
22  *
23  * Redistributions of source code must retain the copyright notices as they
24  * appear in each source code file, these license terms, and the
25  * disclaimer/limitation of liability set forth as paragraph 6 below.
26  *
27  * Redistributions in binary form must reproduce this Copyright Notice,
28  * these license terms, and the disclaimer/limitation of liability set
29  * forth as paragraph 6 below, in the documentation and/or other materials
30  * provided with the distribution.
31  *
32  * The Software is provided on an "AS IS" basis. No warranty is
33  * provided that the Software is free of defects, or fit for a
34  * particular purpose.
35  *
36  * Limitation of Liability. Quadcap Software shall not be liable
37  * for any damages suffered by the Licensee or any third party resulting
38  * from use of the Software.
39  */

40
41 import java.io.BufferedInputStream JavaDoc;
42 import java.io.BufferedOutputStream JavaDoc;
43 import java.io.ByteArrayInputStream JavaDoc;
44 import java.io.Externalizable JavaDoc;
45 import java.io.InputStream JavaDoc;
46 import java.io.IOException JavaDoc;
47 import java.io.ObjectInput JavaDoc;
48 import java.io.ObjectOutput JavaDoc;
49 import java.io.OutputStream JavaDoc;
50
51 //#ifndef JDK11
52
import java.sql.Blob JavaDoc;
53 //#endif
54
import java.sql.SQLException JavaDoc;
55
56 import com.quadcap.sql.DbException;
57
58 import com.quadcap.sql.file.BlockFile;
59 import com.quadcap.sql.file.Datafile;
60 import com.quadcap.sql.file.RandomAccess;
61 import com.quadcap.sql.file.RandomAccessInputStream;
62 import com.quadcap.sql.file.RandomAccessOutputStream;
63
64 import com.quadcap.util.text.TextMatch;
65
66 import com.quadcap.util.Debug;
67 import com.quadcap.util.Util;
68
69 /**
70  * A <b>BLOB</b> value.
71  *
72  * @author Stan Bailes
73  */

74 public class ValueBlob extends Value
75     //#ifdef JDK11
76
//- implements Externalizable
77
//#else
78
implements Blob JavaDoc, Externalizable JavaDoc
79     //#endif
80
{
81     //#ifdef DEBUG
82
static final boolean trace = false;
83     static int serial = 0;
84     int mySerial = serial++;
85     public String JavaDoc show() {
86         return "ValueBlob[" + mySerial + "] @ " + Util.stackTrace();
87     }
88     //#endif
89

90     Datafile file;
91     long permBlock = -1;
92     long tempBlock = -1;
93
94     RandomAccess ra;
95
96     byte[] bytes;
97
98     public ValueBlob() {
99         //#ifdef DEBUG
100
if (trace) {
101             Debug.println(show() + "()");
102         }
103         //#endif
104
}
105
106     public ValueBlob(byte[] bytes) {
107         //#ifdef DEBUG
108
if (trace) {
109             Debug.println(show() + "(" + Util.hexBytes(bytes) + ")");
110         }
111         //#endif
112
this.bytes = bytes;
113     }
114
115     public ValueBlob(Datafile file, long transId,
116              InputStream JavaDoc is, int length)
117     throws IOException JavaDoc
118     {
119     init(file, transId, is, length);
120     }
121
122     public void init(Datafile file, long transId,
123              InputStream JavaDoc is, int length)
124     throws IOException JavaDoc
125     {
126         synchronized (file.getFileLock()) {
127             this.file = file;
128             BlockFile perm = file.getFile();
129             this.permBlock = perm.newPage();
130
131             //#ifdef DEBUG
132
if (trace) {
133                 Debug.println(show() + ".init(" + file + ", " + transId +
134                               " [" + length + " bytes]) -> " + permBlock);
135             }
136             //#endif
137

138             BlockFile temp = file.getTempFile();
139             this.tempBlock = temp.newPage();
140             
141             RandomAccessOutputStream ps = perm.getOutputStream(permBlock);
142             RandomAccessOutputStream ts = temp.getOutputStream(tempBlock);
143             ps.resize(length);
144             ts.resize(length);
145             byte[] buf = new byte[4096];
146             int cnt;
147             int toread = Math.min(4096, length);
148             if (length < 0) toread = 4096;
149             while ((cnt = is.read(buf, 0, toread)) > 0) {
150                 ps.write(buf, 0, cnt);
151                 ts.write(buf, 0, cnt);
152                 if (length > 0) {
153                     length -= cnt;
154                     toread = Math.min(4096, length);
155                 }
156             }
157             ps.close();
158             ts.close();
159         }
160     }
161
162
163     public byte[] getBytesVal() {
164     return bytes;
165     }
166
167     public void passivate(Datafile file, long transId)
168         throws IOException JavaDoc
169     {
170         synchronized (file.getFileLock()) {
171             this.file = file;
172             BlockFile perm = file.getFile();
173             this.permBlock = perm.newPage();
174
175             //#ifdef DEBUG
176
if (trace) {
177                 Debug.println(show() + ".passivate(" + file + ", " +
178                               transId + ")");
179             }
180             //#endif
181

182             BlockFile temp = file.getTempFile();
183             this.tempBlock = temp.newPage();
184     
185             RandomAccessOutputStream ps = perm.getOutputStream(permBlock);
186             ps.resize(0);
187             ps.write(bytes);
188             ps.close();
189
190             RandomAccessOutputStream ts = temp.getOutputStream(tempBlock);
191             ts.resize(0);
192             ts.write(bytes);
193             ts.close();
194
195             this.bytes = null;
196         }
197
198     }
199
200     public void close() {
201         file = null;
202     }
203
204     public void setDatafile(Datafile file) {
205     this.file = file;
206     }
207
208     public long getPermBlock() { return permBlock; }
209     public long getTempBlock() { return tempBlock; }
210
211     public void setPermBlock(long block) {
212         permBlock = block;
213     }
214
215     public Value unop(int op) throws ValueException {
216     switch (op) {
217     case Op.NULL: // isnull(BLOB) -> FALSE
218
return ValueBoolean.falseBoolean;
219     default:
220         throw new ValueException("Unary op: " + Op.toString(op) +
221                      " not implemented for this type");
222     }
223     }
224     
225     public Value binop(int op, Value v) throws ValueException {
226     throw badBinop(op, this, v);
227     }
228
229     public Object JavaDoc asJavaObject() {
230         return this;
231     }
232
233     public void fromJavaObject(Object JavaDoc obj) throws ValueException {
234     throw new ValueException("bad type: " + obj);
235     }
236
237     public Type getType() throws SQLException JavaDoc {
238     return new TypeBlob((int)(length() * 8));
239     }
240
241     public InputStream JavaDoc getBinaryStream() throws SQLException JavaDoc {
242         if (bytes == null) {
243             RandomAccessInputStream is =
244                 new RandomAccessInputStream(getRandomAccess());
245             BufferedInputStream JavaDoc bis = new BufferedInputStream JavaDoc(is);
246             return bis;
247         } else {
248             return new ByteArrayInputStream JavaDoc(bytes);
249         }
250     }
251
252     RandomAccess getRandomAccess() throws SQLException JavaDoc {
253     try {
254         if (ra == null) {
255                 if (file != null) {
256                     ra = file.getFile().getStream(permBlock);
257                 }
258         }
259         return ra;
260         } catch (Exception JavaDoc e2) {
261             throw DbException.wrapThrowable(e2);
262         }
263     }
264
265   /**
266    * Retrieves all or part of the <code>BLOB</code>
267    * value that this <code>Blob</code> object represents, as an array of
268    * bytes. This <code>byte</code> array contains up to <code>length</code>
269    * consecutive bytes starting at position <code>pos</code>.
270    *
271    * @param pos the ordinal position of the first byte in the
272    * <code>BLOB</code> value to be extracted; the first byte is at
273    * position 1
274    * @param length the number of consecutive bytes to be copied
275    * @return a byte array containing up to <code>length</code>
276    * consecutive bytes from the <code>BLOB</code> value designated
277    * by this <code>Blob</code> object, starting with the
278    * byte at position <code>pos</code>
279    * @exception SQLException if there is an error accessing the
280    * <code>BLOB</code> value
281    * @see #setBytes
282    * @since 1.2
283    */

284     public byte[] getBytes(long lpos, int length) throws SQLException JavaDoc {
285         int pos = (int)(lpos - 1);
286     try {
287         byte[] buf = new byte[length];
288             if (bytes == null) {
289                 getRandomAccess().read(pos, buf, 0, length);
290             } else {
291                 System.arraycopy(bytes, pos, buf, 0, length);
292             }
293         return buf;
294     } catch (IOException JavaDoc e) {
295         throw new SQLException JavaDoc(e.toString(), "Q001G");
296     }
297     }
298     
299   /**
300    * Returns the number of bytes in the <code>BLOB</code> value
301    * designated by this <code>Blob</code> object.
302    * @return length of the <code>BLOB</code> in bytes
303    * @exception SQLException if there is an error accessing the
304    * length of the <code>BLOB</code>
305    * @since 1.2
306    */

307     public long length() throws SQLException JavaDoc {
308         if (bytes == null) {
309             return getRandomAccess().size();
310         } else {
311             return bytes.length;
312         }
313     }
314
315     //#ifndef JDK11
316
public long position(Blob JavaDoc blob, long start) throws SQLException JavaDoc {
317     byte[] pattern = blob.getBytes(1, (int)blob.length());
318     return position(pattern, start);
319     }
320     //#endif
321

322     /**
323      * Zero based!
324      */

325     final InputStream JavaDoc getPositionedStream(int pos) throws SQLException JavaDoc {
326         InputStream JavaDoc is;
327         if (bytes == null) {
328         RandomAccessInputStream ris =
329         new RandomAccessInputStream(getRandomAccess());
330         ris.setPosition(pos);
331         is = new BufferedInputStream JavaDoc(ris);
332         } else {
333             is = new ByteArrayInputStream JavaDoc(bytes, pos, bytes.length - pos);
334         }
335         return is;
336     }
337     
338     public long position(byte[] pattern, long start) throws SQLException JavaDoc {
339     try {
340             int pos = (int)(start - 1);
341             InputStream JavaDoc is = getPositionedStream(pos);
342         long ret = TextMatch.match(is, pattern);
343         if (ret < 0) return -1;
344         return ret + start;
345     } catch (IOException JavaDoc e) {
346         throw new SQLException JavaDoc(e.toString(), "Q001E");
347     }
348     }
349
350     public void readExternal(ObjectInput JavaDoc in)
351     throws IOException JavaDoc, ClassNotFoundException JavaDoc
352     {
353     permBlock = in.readLong();
354     }
355     
356     public void writeExternal(ObjectOutput JavaDoc out) throws IOException JavaDoc {
357     out.writeLong(permBlock);
358     }
359
360     public Value convert(TypeBlob type) throws ValueException {
361     return this;
362     }
363
364     public Value convert(TypeVarBinary type) throws ValueException {
365     try {
366         byte[] b = getBytes(1L, (int)length());
367         return new ValueOctets(b, (int)(length() * 8));
368     } catch (SQLException JavaDoc e) {
369         throw new ValueException(e.toString());
370     }
371     }
372
373     public void serializeKey(KeyStream out) throws IOException JavaDoc {
374     throw new IOException JavaDoc("Can't use BLOB as key");
375     }
376
377     public String JavaDoc toString() {
378     try {
379             if (length() < 4 * 1024L) {
380                 byte[] b = getBytes(1L, (int)length());
381                 return Util.hexBytes(b);
382             } else {
383                 return "Too long (" + length() + ") bytes";
384             }
385     } catch (SQLException JavaDoc e) {
386         return "ValueBlob.toString() error: " + e.toString();
387     }
388     }
389
390
391     // -------------------------- JDBC 3.0 -----------------------------------
392

393     /**
394      * Writes the given array of bytes to the <code>BLOB</code> value that
395      * this <code>Blob</code> object represents, starting at position
396      * <code>pos</code>, and returns the number of bytes written.
397      *
398      * @param pos the position in the <code>BLOB</code> object at which
399      * to start writing
400      * @param bytes the array of bytes to be written to the <code>BLOB</code>
401      * value that this <code>Blob</code> object represents
402      * @return the number of bytes written
403      * @exception SQLException if there is an error accessing the
404      * <code>BLOB</code> value
405      * @see #getBytes
406      * @since 1.4
407      */

408     public int setBytes(long lpos, byte[] bytes)
409         throws SQLException JavaDoc
410     {
411         int pos = (int)(lpos - 1);
412     try {
413             getRandomAccess().write(pos, bytes, 0, bytes.length);
414             return bytes.length;
415     } catch (IOException JavaDoc e) {
416         throw new SQLException JavaDoc(e.toString(), "Q001G");
417     }
418     }
419
420     /**
421      * Writes all or part of the given <code>byte</code> array to the
422      * <code>BLOB</code> value that this <code>Blob</code> object represents
423      * and returns the number of bytes written.
424      * Writing starts at position <code>pos</code> in the <code>BLOB</code>
425      * value; <code>len</code> bytes from the given byte array are written.
426      *
427      * @param pos the position in the <code>BLOB</code> object at which
428      * to start writing
429      * @param bytes the array of bytes to be written to this <code>BLOB</code>
430      * object
431      * @param offset the offset into the array <code>bytes</code> at which
432      * to start reading the bytes to be set
433      * @param len the number of bytes to be written to the <code>BLOB</code>
434      * value from the array of bytes <code>bytes</code>
435      * @return the number of bytes written
436      * @exception SQLException if there is an error accessing the
437      * <code>BLOB</code> value
438      * @see #getBytes
439      * @since 1.4
440      */

441     public int setBytes(long lpos, byte[] bytes, int offset, int len)
442         throws SQLException JavaDoc
443     {
444         int pos = (int)(lpos - 1);
445     try {
446             getRandomAccess().write(pos, bytes, offset, len);
447             return len;
448     } catch (IOException JavaDoc e) {
449         throw new SQLException JavaDoc(e.toString(), "Q001G");
450     }
451     }
452
453     /**
454      * Retrieves a stream that can be used to write to the <code>BLOB</code>
455      * value that this <code>Blob</code> object represents. The stream begins
456      * at position <code>pos</code>.
457      *
458      * @param pos the position in the <code>BLOB</code> value at which
459      * to start writing
460      * @return a <code>java.io.OutputStream</code> object to which data can
461      * be written
462      * @exception SQLException if there is an error accessing the
463      * <code>BLOB</code> value
464      * @see #getBinaryStream
465      * @since 1.4
466      */

467     public java.io.OutputStream JavaDoc setBinaryStream(long lpos)
468         throws SQLException JavaDoc
469     {
470         int pos = (int)(lpos - 1);
471         RandomAccessOutputStream rao =
472             new RandomAccessOutputStream(getRandomAccess());
473         rao.setPosition(pos);
474         return rao;
475     }
476
477     /**
478      * Truncates the <code>BLOB</code> value that this <code>Blob</code>
479      * object represents to be <code>len</code> bytes in length.
480      *
481      * @param len the length, in bytes, to which the <code>BLOB</code> value
482      * that this <code>Blob</code> object represents should be truncated
483      * @exception SQLException if there is an error accessing the
484      * <code>BLOB</code> value.
485      * @since 1.4
486      */

487     public void truncate(long len)
488         throws SQLException JavaDoc
489     {
490     try {
491             getRandomAccess().resize(len);
492     } catch (IOException JavaDoc e) {
493         throw new SQLException JavaDoc(e.toString(), "Q001G");
494     }
495     }
496 }
497
Popular Tags