KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > sql > rowset > serial > SerialBlob


1 /*
2  * @(#)SerialBlob.java 1.8 04/05/29
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.sql.rowset.serial;
9
10 import java.sql.*;
11 import java.io.*;
12 import java.lang.reflect.*;
13
14
15 /**
16  * A serialized mapping in the Java programming language of an SQL
17  * <code>BLOB</code> value.
18  * <P>
19  * The <code>SerialBlob</code> class provides a constructor for creating
20  * an instance from a <code>Blob</code> object. Note that the
21  * <code>Blob</code>
22  * object should have brought the SQL <code>BLOB</code> value's data over
23  * to the client before a <code>SerialBlob</code> object
24  * is constructed from it. The data of an SQL <code>BLOB</code> value can
25  * be materialized on the client as an array of bytes (using the method
26  * <code>Blob.getBytes</code>) or as a stream of uninterpreted bytes
27  * (using the method <code>Blob.getBinaryStream</code>).
28  * <P>
29  * <code>SerialBlob</code> methods make it possible to make a copy of a
30  * <code>SerialBlob</code> object as an array of bytes or as a stream.
31  * They also make it possible to locate a given pattern of bytes or a
32  * <code>Blob</code> object within a <code>SerialBlob</code> object
33  * and to update or truncate a <code>Blob</code> object.
34  *
35  * @author Jonathan Bruce
36  */

37 public class SerialBlob implements Blob, Serializable, Cloneable JavaDoc {
38        
39     /**
40      * A serialized array of uninterpreted bytes representing the
41      * value of this <code>SerialBlob</code> object.
42      * @serial
43      */

44     private byte buf[];
45     
46     /**
47      * The internal representation of the <code>Blob</code> object on which this
48      * <code>SerialBlob</code> object is based.
49      */

50     private Blob blob;
51
52     /**
53      * The number of bytes in this <code>SerialBlob</code> object's
54      * array of bytes.
55      * @serial
56      */

57     private long len;
58     
59     /**
60      * The orginal number of bytes in this <code>SerialBlob</code> object's
61      * array of bytes when it was first established.
62      * @serial
63      */

64     private long origLen;
65         
66     /**
67      * Constructs a <code>SerialBlob</code> object that is a serialized version of
68      * the given <code>byte</code> array.
69      * <p>
70      * The new <code>SerialBlob</code> object is initialized with the data from the
71      * <code>byte</code> array, thus allowing disconnected <code>RowSet</code>
72      * objects to establish serialized <code>Blob</code> objects without
73      * touching the data source.
74      *
75      * @param b the <code>byte</code> array containing the data for the
76      * <code>Blob</code> object to be serialized
77      * @throws SerialException if an error occurs during serialization
78      * @throws SQLException if a SQL errors occurs
79      */

80     public SerialBlob(byte[] b) throws SerialException JavaDoc, SQLException {
81         
82         len = b.length;
83         buf = new byte[(int)len];
84         for(int i = 0; i < len; i++) {
85            buf[i] = b[i];
86         }
87         origLen = len;
88     }
89     
90        
91     /**
92      * Constructs a <code>SerialBlob</code> object that is a serialized
93      * version of the given <code>Blob</code> object.
94      * <P>
95      * The new <code>SerialBlob</code> object is initialized with the
96      * data from the <code>Blob</code> object; therefore, the
97      * <code>Blob</code> object should have previously brought the
98      * SQL <code>BLOB</code> value's data over to the client from
99      * the database. Otherwise, the new <code>SerialBlob</code> object
100      * will contain no data.
101      *
102      * @param blob the <code>Blob</code> object from which this
103      * <code>SerialBlob</code> object is to be constructed;
104      * cannot be null.
105      * @throws SerialException if an error occurs during serialization
106      * @throws SQLException if the <code>Blob</code> passed to this
107      * to this constructor is a <code>null</code>.
108      * @see java.sql.Blob
109      */

110     public SerialBlob (Blob blob) throws SerialException JavaDoc, SQLException {
111     
112         if (blob == null) {
113             throw new SQLException("Cannot instantiate a SerialBlob " +
114                  "object with a null Blob object");
115         }
116         
117         len = blob.length();
118         buf = blob.getBytes(1, (int)len );
119         this.blob = blob;
120         
121          //if ( len < 10240000)
122
// len = 10240000;
123
origLen = len;
124     }
125     
126     /**
127      * Copies the specified number of bytes, starting at the given
128      * position, from this <code>SerialBlob</code> object to
129      * another array of bytes.
130      * <P>
131      * Note that if the given number of bytes to be copied is larger than
132      * the length of this <code>SerialBlob</code> object's array of
133      * bytes, the given number will be shortened to the array's length.
134      *
135      * @param pos the ordinal position of the first byte in this
136      * <code>SerialBlob</code> object to be copied;
137      * numbering starts at <code>1</code>; must not be less
138      * than <code>1</code> and must be less than or equal
139      * to the length of this <code>SerialBlob</code> object
140      * @param length the number of bytes to be copied
141      * @return an array of bytes that is a copy of a region of this
142      * <code>SerialBlob</code> object, starting at the given
143      * position and containing the given number of consecutive bytes
144      * @throws SerialException if the given starting position is out of bounds
145      */

146     public byte[] getBytes(long pos, int length) throws SerialException JavaDoc {
147         if (length > len) {
148             length = (int)len;
149         }
150
151         if (pos < 1 || length - pos < 0 ) {
152             throw new SerialException JavaDoc("Invalid arguments: position cannot be less that 1");
153         }
154         
155         pos--; // correct pos to array index
156

157         byte[] b = new byte[length];
158         
159         for (int i = 0; i < length; i++) {
160             b[i] = this.buf[(int)pos];
161             pos++;
162         }
163         return b;
164     }
165     
166     /**
167      * Retrieves the number of bytes in this <code>SerialBlob</code>
168      * object's array of bytes.
169      *
170      * @return a <code>long</code> indicating the length in bytes of this
171      * <code>SerialBlob</code> object's array of bytes
172      * @throws SerialException if an error occurs
173      */

174     public long length() throws SerialException JavaDoc {
175         return len;
176     }
177
178     /**
179      * Returns this <code>SerialBlob</code> object as an input stream.
180      * Unlike the related method, <code>setBinaryStream</code>,
181      * a stream is produced regardless of whether the <code>SerialBlob</code>
182      * was created with a <code>Blob</code> object or a <code>byte</code> array.
183      *
184      * @return a <code>java.io.InputStream</code> object that contains
185      * this <code>SerialBlob</code> object's array of bytes
186      * @throws SerialException if an error occurs
187      * @see #setBinaryStream
188      */

189     public java.io.InputStream JavaDoc getBinaryStream() throws SerialException JavaDoc {
190          InputStream stream = new ByteArrayInputStream(buf);
191          return (java.io.InputStream JavaDoc)stream;
192     }
193     
194     /**
195      * Returns the position in this <code>SerialBlob</code> object where
196      * the given pattern of bytes begins, starting the search at the
197      * specified position.
198      *
199      * @param pattern the pattern of bytes for which to search
200      * @param start the position of the byte in this
201      * <code>SerialBlob</code> object from which to begin
202      * the search; the first position is <code>1</code>;
203      * must not be less than <code>1</code> nor greater than
204      * the length of this <code>SerialBlob</code> object
205      * @return the position in this <code>SerialBlob</code> object
206      * where the given pattern begins, starting at the specified
207      * position; <code>-1</code> if the pattern is not found
208      * or the given starting position is out of bounds; position
209      * numbering for the return value starts at <code>1</code>
210      * @throws SerialException if an error occurs when serializing the blob
211      * @throws SQLException if there is an error accessing the <code>BLOB</code>
212      * value from the database
213      */

214     public long position(byte[] pattern, long start)
215                 throws SerialException JavaDoc, SQLException {
216         if (start < 1 || start > len) {
217             return -1;
218         }
219
220         int pos = (int)start-1; // internally Blobs are stored as arrays.
221
int i = 0;
222         long patlen = pattern.length;
223         
224         while (pos < len) {
225             if (pattern[i] == buf[pos]) {
226                 if (i + 1 == patlen) {
227                     return (pos + 1) - (patlen - 1);
228                 }
229                 i++; pos++; // increment pos, and i
230
} else if (pattern[i] != buf[pos]) {
231                 pos++; // increment pos only
232
}
233         }
234         return -1; // not found
235
}
236         
237     /**
238      * Returns the position in this <code>SerialBlob</code> object where
239      * the given <code>Blob</code> object begins, starting the search at the
240      * specified position.
241      *
242      * @param pattern the <code>Blob</code> object for which to search;
243      * @param start the position of the byte in this
244      * <code>SerialBlob</code> object from which to begin
245      * the search; the first position is <code>1</code>;
246      * must not be less than <code>1</code> nor greater than
247      * the length of this <code>SerialBlob</code> object
248      * @return the position in this <code>SerialBlob</code> object
249      * where the given <code>Blob</code> object begins, starting
250      * at the specified position; <code>-1</code> if the pattern is
251      * not found or the given starting position is out of bounds;
252      * position numbering for the return value starts at <code>1</code>
253      * @throws SerialException if an error occurs when serializing the blob
254      * @throws SQLException if there is an error accessing the <code>BLOB</code>
255      * value from the database
256      */

257     public long position(Blob pattern, long start)
258        throws SerialException JavaDoc, SQLException {
259         return position(pattern.getBytes(1, (int)(pattern.length())), start);
260     }
261     
262     /**
263      * Writes the given array of bytes to the <code>BLOB</code> value that
264      * this <code>Blob</code> object represents, starting at position
265      * <code>pos</code>, and returns the number of bytes written.
266      *
267      * @param pos the position in the SQL <code>BLOB</code> value at which
268      * to start writing. The first position is <code>1</code>;
269      * must not be less than <code>1</code> nor greater than
270      * the length of this <code>SerialBlob</code> object.
271      * @param bytes the array of bytes to be written to the <code>BLOB</code>
272      * value that this <code>Blob</code> object represents
273      * @return the number of bytes written
274      * @throws SerialException if there is an error accessing the
275      * <code>BLOB</code> value; or if an invalid position is set; if an
276      * invalid offset value is set
277      * @throws SQLException if there is an error accessing the <code>BLOB</code>
278      * value from the database
279      * @see #getBytes
280      */

281     public int setBytes(long pos, byte[] bytes)
282         throws SerialException JavaDoc, SQLException {
283         return (setBytes(pos, bytes, 0, bytes.length));
284     }
285     
286     /**
287      * Writes all or part of the given <code>byte</code> array to the
288      * <code>BLOB</code> value that this <code>Blob</code> object represents
289      * and returns the number of bytes written.
290      * Writing starts at position <code>pos</code> in the <code>BLOB</code>
291      * value; <i>len</i> bytes from the given byte array are written.
292      *
293      * @param pos the position in the <code>BLOB</code> object at which
294      * to start writing. The first position is <code>1</code>;
295      * must not be less than <code>1</code> nor greater than
296      * the length of this <code>SerialBlob</code> object.
297      * @param bytes the array of bytes to be written to the <code>BLOB</code>
298      * value
299      * @param offset the offset in the <code>byte</code> array at which
300      * to start reading the bytes. The first offset position is
301      * <code>0</code>; must not be less than <code>0</code> nor greater
302      * than the length of the <code>byte</code> array
303      * @param length the number of bytes to be written to the
304      * <code>BLOB</code> value from the array of bytes <i>bytes</i>.
305      *
306      * @return the number of bytes written
307      * @throws SerialException if there is an error accessing the
308      * <code>BLOB</code> value; if an invalid position is set; if an
309      * invalid offset value is set; if number of bytes to be written
310      * is greater than the <code>SerialBlob</code> length; or the combined
311      * values of the length and offset is greater than the Blob buffer
312      * @throws SQLException if there is an error accessing the <code>BLOB</code>
313      * value from the database.
314      * @see #getBytes
315      */

316     public int setBytes(long pos, byte[] bytes, int offset, int length)
317         throws SerialException JavaDoc, SQLException {
318         
319         if (offset < 0 || offset > bytes.length) {
320             throw new SerialException JavaDoc("Invalid offset in byte array set");
321         }
322         
323         if (pos < 1 || pos > this.length()) {
324             throw new SerialException JavaDoc("Invalid position in BLOB object set");
325         }
326                     
327         if ((long)(length) > origLen) {
328         throw new SerialException JavaDoc("Buffer is not sufficient to hold the value");
329     }
330         
331         if ((length + offset) > bytes.length) {
332             throw new SerialException JavaDoc("Invalid OffSet. Cannot have combined offset " +
333                 "and length that is greater that the Blob buffer");
334         }
335         
336         int i = 0;
337         pos--; // correct to array indexing
338
while ( i < length || (offset + i +1) < (bytes.length-offset) ) {
339             this.buf[(int)pos + i] = bytes[offset + i ];
340             i++;
341         }
342         return i;
343     }
344     
345     /**
346      * Retrieves a stream that can be used to write to the <code>BLOB</code>
347      * value that this <code>Blob</code> object represents. The stream begins
348      * at position <code>pos</code>. This method forwards the
349      * <code>setBinaryStream()</code> call to the underlying <code>Blob</code> in
350      * the event that this <code>SerialBlob</code> object is instantiated with a
351      * <code>Blob</code>. If this <code>SerialBlob</code> is instantiated with
352      * a <code>byte</code> array, a <code>SerialException</code> is thrown.
353      *
354      * @param pos the position in the <code>BLOB</code> value at which
355      * to start writing
356      * @return a <code>java.io.OutputStream</code> object to which data can
357      * be written
358      * @throws SQLException if there is an error accessing the
359      * <code>BLOB</code> value
360      * @throws SerialException if the SerialBlob in not instantiated with a
361      * <code>Blob</code> object that supports <code>setBinaryStream()</code>
362      * @see #getBinaryStream
363      */

364     public java.io.OutputStream JavaDoc setBinaryStream(long pos)
365         throws SerialException JavaDoc, SQLException {
366         if (this.blob.setBinaryStream(pos) != null) {
367             return this.blob.setBinaryStream(pos);
368         } else {
369             throw new SerialException JavaDoc("Unsupported operation. SerialBlob cannot " +
370                 "return a writable binary stream, unless instantiated with a Blob object " +
371                 "that provides a setBinaryStream() implementation");
372         }
373     }
374     
375     /**
376      * Truncates the <code>BLOB</code> value that this <code>Blob</code>
377      * object represents to be <code>len</code> bytes in length.
378      *
379      * @param length the length, in bytes, to which the <code>BLOB</code>
380      * value that this <code>Blob</code> object represents should be
381      * truncated
382      * @throws SerialException if there is an error accessing the Blob value;
383      * or the length to truncate is greater that the SerialBlob length
384      */

385     public void truncate(long length) throws SerialException JavaDoc {
386          
387          if (length > len) {
388             throw new SerialException JavaDoc
389                ("Length more than what can be truncated");
390          } else if((int)length == 0) {
391               buf = new byte[0];
392               len = length;
393          } else {
394               len = length;
395               buf = this.getBytes(1, (int)len);
396          }
397     }
398
399     
400     /**
401      * The identifier that assists in the serialization of this <code>SerialBlob</code>
402      * object.
403      */

404
405     static final long serialVersionUID = -8144641928112860441L;
406 }
407
Popular Tags