KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * @(#)SerialClob.java 1.11 04/08/10
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
13 /**
14  * A serialized mapping in the Java programming language of an SQL
15  * <code>CLOB</code> value.
16  * <P>
17  * The <code>SerialClob</code> class provides a constructor for creating
18  * an instance from a <code>Clob</code> object. Note that the <code>Clob</code>
19  * object should have brought the SQL <code>CLOB</code> value's data over
20  * to the client before a <code>SerialClob</code> object
21  * is constructed from it. The data of an SQL <code>CLOB</code> value can
22  * be materialized on the client as a stream of Unicode characters.
23  * <P>
24  * <code>SerialClob</code> methods make it possible to get a substring
25  * from a <code>SerialClob</code> object or to locate the start of
26  * a pattern of characters.
27  *
28  * @author Jonathan Bruce
29  */

30 public class SerialClob implements Clob, Serializable, Cloneable JavaDoc {
31
32     /**
33      * A serialized array of characters containing the data of the SQL
34      * <code>CLOB</code> value that this <code>SerialClob</code> object
35      * represents.
36      *
37      * @serial
38      */

39     private char buf[];
40     
41     /**
42      * Internal Clob representation if SerialClob is intialized with a
43      * Clob
44      */

45     private Clob clob;
46     
47     /**
48      * The length in characters of this <code>SerialClob</code> object's
49      * internal array of characters.
50      *
51      * @serial
52      */

53     private long len;
54     
55     /**
56      * The original length in characters of tgus <code>SerialClob</code>
57      * objects internal array of characters.
58      *
59      * @serial
60      */

61     private long origLen;
62     
63     /**
64      * Constructs a <code>SerialClob</code> object that is a serialized version of
65      * the given <code>char</code> array.
66      * <p>
67      * The new <code>SerialClob</code> object is initialized with the data from the
68      * <code>char</code> array, thus allowing disconnected <code>RowSet</code>
69      * objects to establish a serialized <code>Clob</code> object without touching
70      * the data source.
71      *
72      * @param ch the char array representing the <code>Clob</code> object to be
73      * serialized
74      * @throws SerialException if an error occurs during serialization
75      * @throws SQLException if a SQL error occurs
76      */

77     public SerialClob(char ch[]) throws SerialException JavaDoc, SQLException {
78                         
79         // %%% JMB. Agreed. Add code here to throw a SQLException if no
80
// support is available for locatorsUpdateCopy=false
81
// Serializing locators is not supported.
82

83         len = ch.length;
84         buf = new char[(int)len];
85         for (int i = 0; i < len ; i++){
86            buf[i] = ch[i];
87         }
88         origLen = len;
89     }
90     
91     /**
92      * Constructs a <code>SerialClob</code> object that is a serialized
93      * version of the given <code>Clob</code> object.
94      * <P>
95      * The new <code>SerialClob</code> object is initialized with the
96      * data from the <code>Clob</code> object; therefore, the
97      * <code>Clob</code> object should have previously brought the
98      * SQL <code>CLOB</code> value's data over to the client from
99      * the database. Otherwise, the new <code>SerialClob</code> object
100      * object will contain no data.
101      * <p>
102      * Note: The <code>Clob</code> object supplied to this constructor cannot
103      * return <code>null</code> for the <code>Clob.getCharacterStream()</code>
104      * and <code>Clob.getAsciiStream</code> methods. This <code>SerialClob</code>
105      * constructor cannot serialize a <code>Clob</code> object in this instance
106      * and will throw an <code>SQLException</code> object.
107      *
108      * @param clob the <code>Clob</code> object from which this
109      * <code>SerialClob</code> object is to be constructed; cannot be null
110      * @throws SerialException if an error occurs during serialization
111      * @throws SQLException if a SQL error occurs in capturing the CLOB;
112      * if the <code>Clob</code> object is a null; or if at least one of the
113      * <code>Clob.getCharacterStream()</code> and <code>Clob.getAsciiStream()</code>
114      * methods on the <code>Clob</code> return a null
115      * @see java.sql.Clob
116      */

117     public SerialClob(Clob clob) throws SerialException JavaDoc, SQLException {
118         
119         if (clob == null) {
120             throw new SQLException("Cannot instantiate a SerialClob " +
121                 "object with a null Clob object");
122         }
123         len = clob.length();
124         this.clob = clob;
125         buf = new char[(int)len];
126         int read = 0;
127         int offset = 0;
128         
129         BufferedReader reader;
130         
131         if (clob.getCharacterStream() == null || clob.getAsciiStream() == null) {
132             throw new SQLException("Invalid Clob object. Calls to getCharacterStream " +
133                 "or getAsciiStream return null which cannot be serialized.");
134         }
135         
136         try {
137         reader = new BufferedReader(clob.getCharacterStream());
138             
139             do {
140                 read = reader.read(buf, offset, (int)(len - offset));
141                 offset += read;
142             } while (read > 0);
143             
144         } catch (java.io.IOException JavaDoc ex) {
145             throw new SerialException JavaDoc("SerialClob: " + ex.getMessage());
146         }
147                 
148         origLen = len;
149     }
150
151     /**
152      * Retrieves the number of characters in this <code>SerialClob</code>
153      * object's array of characters.
154      *
155      * @return a <code>long</code> indicating the length in characters of this
156      * <code>SerialClob</code> object's array of character
157      * @throws SerialException if an error occurs
158      */

159     public long length() throws SerialException JavaDoc {
160         return len;
161     }
162
163     /**
164      * Returns this <code>SerialClob</code> object's data as a stream
165      * of Unicode characters. Unlike the related method, <code>getAsciiStream</code>,
166      * a stream is produced regardless of whether the <code>SerialClob</code> object
167      * was created with a <code>Clob</code> object or a <code>char</code> array.
168      *
169      * @return a <code>java.io.Reader</code> object containing this
170      * <code>SerialClob</code> object's data
171      * @throws SerialException if an error occurs
172      */

173     public java.io.Reader JavaDoc getCharacterStream() throws SerialException JavaDoc {
174         return (java.io.Reader JavaDoc) new CharArrayReader(buf);
175     }
176     
177     /**
178      * Retrieves the <code>CLOB</code> value designated by this <code>SerialClob</code>
179      * object as an ascii stream. This method forwards the <code>getAsciiStream</code>
180      * call to the underlying <code>Clob</code> object in the event that this
181      * <code>SerialClob</code> object is instantiated with a <code>Clob</code>
182      * object. If this <code>SerialClob</code> object is instantiated with
183      * a <code>char</code> array, a <code>SerialException</code> object is thrown.
184      *
185      * @return a <code>java.io.InputStream</code> object containing
186      * this <code>SerialClob</code> object's data
187      * @throws SerialException if this <code>SerialClob<code> object was not instantiated
188      * with a <code>Clob</code> object
189      * @throws SQLException if there is an error accessing the
190      * <code>CLOB</code> value represented by the <code>Clob</code> object that was
191      * used to create this <code>SerialClob</code> object
192      */

193     public java.io.InputStream JavaDoc getAsciiStream() throws SerialException JavaDoc, SQLException {
194        if (this.clob != null) {
195              return this.clob.getAsciiStream();
196          } else {
197              throw new SerialException JavaDoc("Unsupported operation. SerialClob cannot " +
198                 "return a the CLOB value as an ascii stream, unless instantiated " +
199                 "with a fully implemented Clob object.");
200          }
201     }
202
203     /**
204      * Returns a copy of the substring contained in this
205      * <code>SerialClob</code> object, starting at the given position
206      * and continuing for the specified number or characters.
207      *
208      * @param pos the position of the first character in the substring
209      * to be copied; the first character of the
210      * <code>SerialClob</code> object is at position
211      * <code>1</code>; must not be less than <code>1</code>,
212      * and the sum of the starting position and the length
213      * of the substring must be less than the length of this
214      * <code>SerialClob</code> object
215      * @param length the number of characters in the substring to be
216      * returned; must not be greater than the length of
217      * this <code>SerialClob</code> object, and the
218      * sum of the starting position and the length
219      * of the substring must be less than the length of this
220      * <code>SerialClob</code> object
221      * @return a <code>String</code> object containing a substring of
222      * this <code>SerialClob</code> object beginning at the
223      * given position and containing the specified number of
224      * consecutive characters
225      * @throws SerialException if either of the arguments is out of bounds
226      */

227     public String JavaDoc getSubString(long pos, int length) throws SerialException JavaDoc {
228        
229         if (pos < 1 || pos > this.length()) {
230             throw new SerialException JavaDoc("Invalid position in BLOB object set");
231         }
232         
233         if ((pos-1) + length > this.length()) {
234             throw new SerialException JavaDoc("Invalid position and substring length");
235         }
236         
237         try {
238             return new String JavaDoc(buf, (int)pos - 1, length);
239             
240         } catch (StringIndexOutOfBoundsException JavaDoc e) {
241             throw new SerialException JavaDoc("StringIndexOutOfBoundsException: " +
242                 e.getMessage());
243         }
244             
245     }
246
247     /**
248      * Returns the position in this <code>SerialClob</code> object
249      * where the given <code>String</code> object begins, starting
250      * the search at the specified position. This method returns
251      * <code>-1</code> if the pattern is not found.
252      *
253      * @param searchStr the <code>String</code> object for which to
254      * search
255      * @param start the position in this <code>SerialClob</code> object
256      * at which to start the search; the first position is
257      * <code>1</code>; must not be less than <code>1</code> nor
258      * greater than the length of this <code>SerialClob</code> object
259      * @return the position at which the given <code>String</code> object
260      * begins, starting the search at the specified position;
261      * <code>-1</code> if the given <code>String</code> object is
262      * not found or the starting position is out of bounds; position
263      * numbering for the return value starts at <code>1</code>
264      * @throws SerialException if an error occurs locating the String signature
265      * @throws SQLException if there is an error accessing the Blob value
266      * from the database.
267      */

268     public long position(String JavaDoc searchStr, long start)
269         throws SerialException JavaDoc, SQLException {
270               
271         if (start < 1 || start > len) {
272             return -1;
273         }
274             
275         char pattern[] = searchStr.toCharArray();
276
277         int pos = (int)start-1;
278         int i = 0;
279         long patlen = pattern.length;
280         
281         while (pos < len) {
282             if (pattern[i] == buf[pos]) {
283                 if (i + 1 == patlen) {
284                     return (pos + 1) - (patlen - 1);
285                 }
286                 i++; pos++; // increment pos, and i
287

288             } else if (pattern[i] != buf[pos]) {
289                 pos++; // increment pos only
290
}
291         }
292         return -1; // not found
293
}
294     
295     /**
296      * Returns the position in this <code>SerialClob</code> object
297      * where the given <code>Clob</code> signature begins, starting
298      * the search at the specified position. This method returns
299      * <code>-1</code> if the pattern is not found.
300      *
301      * @param searchStr the <code>Clob</code> object for which to search
302      * @param start the position in this <code>SerialClob</code> object
303      * at which to begin the search; the first position is
304      * <code>1</code>; must not be less than <code>1</code> nor
305      * greater than the length of this <code>SerialClob</code> object
306      * @return the position at which the given <code>Clob</code>
307      * object begins in this <code>SerialClob</code> object,
308      * at or after the specified starting position
309      * @throws SerialException if an error occurs locating the Clob signature
310      * @throws SQLException if there is an error accessing the Blob value
311      * from the database
312      */

313     public long position(Clob searchStr, long start)
314         throws SerialException JavaDoc, SQLException {
315             
316         char cPattern[] = null;
317         try {
318             java.io.Reader JavaDoc r = searchStr.getCharacterStream();
319             cPattern = new char[(int)searchStr.length()];
320             r.read(cPattern);
321         } catch (IOException e) {
322             throw new SerialException JavaDoc("Error streaming Clob search data");
323         }
324         return position(new String JavaDoc(cPattern), start);
325     }
326     
327     /**
328      * Writes the given Java <code>String</code> to the <code>CLOB</code>
329      * value that this <code>SerialClob</code> object represents, at the position
330      * <code>pos</code>.
331      *
332      * @param pos the position at which to start writing to the <code>CLOB</code>
333      * value that this <code>SerialClob</code> object represents; the first
334      * position is <code>1</code>; must not be less than <code>1</code> nor
335      * greater than the length of this <code>SerialClob</code> object
336      * @param str the string to be written to the <code>CLOB</code>
337      * value that this <code>SerialClob</code> object represents
338      * @return the number of characters written
339      * @throws SerialException if there is an error accessing the
340      * <code>CLOB</code> value; if an invalid position is set; if an
341      * invalid offset value is set; if number of bytes to be written
342      * is greater than the <code>SerialClob</code> length; or the combined
343      * values of the length and offset is greater than the Clob buffer
344      */

345     public int setString(long pos, String JavaDoc str) throws SerialException JavaDoc {
346         return (setString(pos, str, 0, str.length()));
347     }
348     
349     /**
350      * Writes <code>len</code> characters of <code>str</code>, starting
351      * at character <code>offset</code>, to the <code>CLOB</code> value
352      * that this <code>Clob</code> represents.
353      *
354      * @param pos the position at which to start writing to the <code>CLOB</code>
355      * value that this <code>SerialClob</code> object represents; the first
356      * position is <code>1</code>; must not be less than <code>1</code> nor
357      * greater than the length of this <code>SerialClob</code> object
358      * @param str the string to be written to the <code>CLOB</code>
359      * value that this <code>Clob</code> object represents
360      * @param offset the offset into <code>str</code> to start reading
361      * the characters to be written
362      * @param length the number of characters to be written
363      * @return the number of characters written
364      * @throws SerialException if there is an error accessing the
365      * <code>CLOB</code> value; if an invalid position is set; if an
366      * invalid offset value is set; if number of bytes to be written
367      * is greater than the <code>SerialClob</code> length; or the combined
368      * values of the length and offset is greater than the Clob buffer
369      */

370     public int setString(long pos, String JavaDoc str, int offset, int length)
371         throws SerialException JavaDoc {
372         String JavaDoc temp = str.substring(offset);
373         char cPattern[] = temp.toCharArray();
374         
375         if (offset < 0 || offset > str.length()) {
376             throw new SerialException JavaDoc("Invalid offset in byte array set");
377         }
378         
379         if (pos < 1 || pos > this.length()) {
380             throw new SerialException JavaDoc("Invalid position in BLOB object set");
381         }
382                     
383         if ((long)(length) > origLen) {
384         throw new SerialException JavaDoc("Buffer is not sufficient to hold the value");
385     }
386         
387         if ((length + offset) > str.length()) {
388             // need check to ensure length + offset !> bytes.length
389
throw new SerialException JavaDoc("Invalid OffSet. Cannot have combined offset " +
390                 " and length that is greater that the Blob buffer");
391         }
392         
393         int i = 0;
394         pos--; //values in the array are at position one less
395
while ( i < length || (offset + i +1) < (str.length() - offset ) ) {
396             this.buf[(int)pos + i ] = cPattern[offset + i ];
397             i++;
398         }
399         return i;
400     }
401     
402     /**
403      * Retrieves a stream to be used to write Ascii characters to the
404      * <code>CLOB</code> value that this <code>SerialClob</code> object represents,
405      * starting at position <code>pos</code>. This method forwards the
406      * <code>setAsciiStream()</code> call to the underlying <code>Clob</code> object in
407      * the event that this <code>SerialClob</code> object is instantiated with a
408      * <code>Clob</code> object. If this <code>SerialClob</code> object is instantiated
409      * with a <code>char</code> array, a <code>SerialException</code> object is thrown.
410      *
411      * @param pos the position at which to start writing to the
412      * <code>CLOB</code> object
413      * @return the stream to which ASCII encoded characters can be written
414      * @throws SerialException if SerialClob is not instantiated with a
415      * Clob object that supports <code>setAsciiStream</code>
416      * @throws SQLException if there is an error accessing the
417      * <code>CLOB</code> value
418      * @see #getAsciiStream
419      */

420     public java.io.OutputStream JavaDoc setAsciiStream(long pos)
421         throws SerialException JavaDoc, SQLException {
422          if (this.clob.setAsciiStream(pos) != null) {
423              return this.clob.setAsciiStream(pos);
424          } else {
425              throw new SerialException JavaDoc("Unsupported operation. SerialClob cannot " +
426                 "return a writable ascii stream\n unless instantiated with a Clob object " +
427                 "that has a setAsciiStream() implementation");
428          }
429     }
430     
431     /**
432      * Retrieves a stream to be used to write a stream of Unicode characters
433      * to the <code>CLOB</code> value that this <code>SerialClob</code> object
434      * represents, at position <code>pos</code>. This method forwards the
435      * <code>setCharacterStream()</code> call to the underlying <code>Clob</code>
436      * object in the event that this <code>SerialClob</code> object is instantiated with a
437      * <code>Clob</code> object. If this <code>SerialClob</code> object is instantiated with
438      * a <code>char</code> array, a <code>SerialException</code> is thrown.
439      *
440      * @param pos the position at which to start writing to the
441      * <code>CLOB</code> value
442      *
443      * @return a stream to which Unicode encoded characters can be written
444      * @throws SerialException if the SerialClob is not instantiated with
445      * a Clob object that supports <code>setCharacterStream</code>
446      * @throws SQLException if there is an error accessing the
447      * <code>CLOB</code> value
448      * @see #getCharacterStream
449      */

450     public java.io.Writer JavaDoc setCharacterStream(long pos)
451         throws SerialException JavaDoc, SQLException {
452         if (this.clob.setCharacterStream(pos) != null) {
453             return this.clob.setCharacterStream(pos);
454         } else {
455             throw new SerialException JavaDoc("Unsupported operation. SerialClob cannot " +
456                 "return a writable character stream\n unless instantiated with a Clob object " +
457                 "that has a setCharacterStream implementation");
458         }
459     }
460     
461     /**
462      * Truncates the <code>CLOB</code> value that this <code>SerialClob</code>
463      * object represents so that it has a length of <code>len</code>
464      * characters.
465      * <p>
466      * Truncating a <code>SerialClob</code> object to length 0 has the effect of
467      * clearing its contents.
468      *
469      * @param length the length, in bytes, to which the <code>CLOB</code>
470      * value should be truncated
471      * @throws SQLException if there is an error accessing the
472      * <code>CLOB</code> value
473      */

474     public void truncate(long length) throws SerialException JavaDoc {
475          if (length > len) {
476             throw new SerialException JavaDoc
477                ("Length more than what can be truncated");
478          } else {
479               len = length;
480               // re-size the buffer
481

482               if (len == 0) {
483                   buf = new char[] {};
484               } else {
485                 buf = (this.getSubString(1, (int)len)).toCharArray();
486               }
487               
488          }
489     }
490     
491
492
493     /**
494      * The identifier that assists in the serialization of this <code>SerialClob</code>
495      * object.
496      */

497     static final long serialVersionUID = -1662519690087375313L;
498 }
499
Popular Tags