/*
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 {
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, 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, 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 ex) {
145 throw new SerialException("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 {
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 getCharacterStream() throws SerialException {
174 return (java.io.Reader) 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 getAsciiStream() throws SerialException, SQLException {
194 if (this.clob != null) {
195 return this.clob.getAsciiStream();
196 } else {
197 throw new SerialException("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 getSubString(long pos, int length) throws SerialException {
228
229 if (pos < 1 || pos > this.length()) {
230 throw new SerialException("Invalid position in BLOB object set");
231 }
232
233 if ((pos-1) + length > this.length()) {
234 throw new SerialException("Invalid position and substring length");
235 }
236
237 try {
238 return new String(buf, (int)pos - 1, length);
239
240 } catch (StringIndexOutOfBoundsException e) {
241 throw new SerialException("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 searchStr, long start)
269 throws SerialException, 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, SQLException {
315
316 char cPattern[] = null;
317 try {
318 java.io.Reader r = searchStr.getCharacterStream();
319 cPattern = new char[(int)searchStr.length()];
320 r.read(cPattern);
321 } catch (IOException e) {
322 throw new SerialException("Error streaming Clob search data");
323 }
324 return position(new String(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 str) throws SerialException {
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 str, int offset, int length)
371 throws SerialException {
372 String temp = str.substring(offset);
373 char cPattern[] = temp.toCharArray();
374
375 if (offset < 0 || offset > str.length()) {
376 throw new SerialException("Invalid offset in byte array set");
377 }
378
379 if (pos < 1 || pos > this.length()) {
380 throw new SerialException("Invalid position in BLOB object set");
381 }
382
383 if ((long)(length) > origLen) {
384 throw new SerialException("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("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 setAsciiStream(long pos)
421 throws SerialException, SQLException {
422 if (this.clob.setAsciiStream(pos) != null) {
423 return this.clob.setAsciiStream(pos);
424 } else {
425 throw new SerialException("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 setCharacterStream(long pos)
451 throws SerialException, SQLException {
452 if (this.clob.setCharacterStream(pos) != null) {
453 return this.clob.setCharacterStream(pos);
454 } else {
455 throw new SerialException("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 {
475 if (length > len) {
476 throw new SerialException
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 }
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 {
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, 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, 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 ex) {
145 throw new SerialException("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 {
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 getCharacterStream() throws SerialException {
174 return (java.io.Reader) 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 getAsciiStream() throws SerialException, SQLException {
194 if (this.clob != null) {
195 return this.clob.getAsciiStream();
196 } else {
197 throw new SerialException("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 getSubString(long pos, int length) throws SerialException {
228
229 if (pos < 1 || pos > this.length()) {
230 throw new SerialException("Invalid position in BLOB object set");
231 }
232
233 if ((pos-1) + length > this.length()) {
234 throw new SerialException("Invalid position and substring length");
235 }
236
237 try {
238 return new String(buf, (int)pos - 1, length);
239
240 } catch (StringIndexOutOfBoundsException e) {
241 throw new SerialException("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 searchStr, long start)
269 throws SerialException, 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, SQLException {
315
316 char cPattern[] = null;
317 try {
318 java.io.Reader r = searchStr.getCharacterStream();
319 cPattern = new char[(int)searchStr.length()];
320 r.read(cPattern);
321 } catch (IOException e) {
322 throw new SerialException("Error streaming Clob search data");
323 }
324 return position(new String(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 str) throws SerialException {
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 str, int offset, int length)
371 throws SerialException {
372 String temp = str.substring(offset);
373 char cPattern[] = temp.toCharArray();
374
375 if (offset < 0 || offset > str.length()) {
376 throw new SerialException("Invalid offset in byte array set");
377 }
378
379 if (pos < 1 || pos > this.length()) {
380 throw new SerialException("Invalid position in BLOB object set");
381 }
382
383 if ((long)(length) > origLen) {
384 throw new SerialException("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("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 setAsciiStream(long pos)
421 throws SerialException, SQLException {
422 if (this.clob.setAsciiStream(pos) != null) {
423 return this.clob.setAsciiStream(pos);
424 } else {
425 throw new SerialException("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 setCharacterStream(long pos)
451 throws SerialException, SQLException {
452 if (this.clob.setCharacterStream(pos) != null) {
453 return this.clob.setCharacterStream(pos);
454 } else {
455 throw new SerialException("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 {
475 if (length > len) {
476 throw new SerialException
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 }