42 * <P> |
42 * <P> |
43 * <code>SerialClob</code> methods make it possible to get a substring |
43 * <code>SerialClob</code> methods make it possible to get a substring |
44 * from a <code>SerialClob</code> object or to locate the start of |
44 * from a <code>SerialClob</code> object or to locate the start of |
45 * a pattern of characters. |
45 * a pattern of characters. |
46 * |
46 * |
|
47 * <h4> Thread safety </h4> |
|
48 * |
|
49 * <p> A SerialClob is not safe for use by multiple concurrent threads. If a |
|
50 * SerialClob is to be used by more than one thread then access to the SerialClob |
|
51 * should be controlled by appropriate synchronization. |
47 * @author Jonathan Bruce |
52 * @author Jonathan Bruce |
48 */ |
53 */ |
49 public class SerialClob implements Clob, Serializable, Cloneable { |
54 public class SerialClob implements Clob, Serializable, Cloneable { |
50 |
55 |
51 /** |
56 /** |
178 * Retrieves the number of characters in this <code>SerialClob</code> |
183 * Retrieves the number of characters in this <code>SerialClob</code> |
179 * object's array of characters. |
184 * object's array of characters. |
180 * |
185 * |
181 * @return a <code>long</code> indicating the length in characters of this |
186 * @return a <code>long</code> indicating the length in characters of this |
182 * <code>SerialClob</code> object's array of character |
187 * <code>SerialClob</code> object's array of character |
183 * @throws SerialException if an error occurs |
188 * @throws SerialException if an error occurs; |
|
189 * if {@code free} had previously been called on this object |
184 */ |
190 */ |
185 public long length() throws SerialException { |
191 public long length() throws SerialException { |
|
192 isValid(); |
186 return len; |
193 return len; |
187 } |
194 } |
188 |
195 |
189 /** |
196 /** |
190 * Returns this <code>SerialClob</code> object's data as a stream |
197 * Returns this <code>SerialClob</code> object's data as a stream |
192 * a stream is produced regardless of whether the <code>SerialClob</code> object |
199 * a stream is produced regardless of whether the <code>SerialClob</code> object |
193 * was created with a <code>Clob</code> object or a <code>char</code> array. |
200 * was created with a <code>Clob</code> object or a <code>char</code> array. |
194 * |
201 * |
195 * @return a <code>java.io.Reader</code> object containing this |
202 * @return a <code>java.io.Reader</code> object containing this |
196 * <code>SerialClob</code> object's data |
203 * <code>SerialClob</code> object's data |
197 * @throws SerialException if an error occurs |
204 * @throws SerialException if an error occurs; |
|
205 * if {@code free} had previously been called on this object |
198 */ |
206 */ |
199 public java.io.Reader getCharacterStream() throws SerialException { |
207 public java.io.Reader getCharacterStream() throws SerialException { |
|
208 isValid(); |
200 return (java.io.Reader) new CharArrayReader(buf); |
209 return (java.io.Reader) new CharArrayReader(buf); |
201 } |
210 } |
202 |
211 |
203 /** |
212 /** |
204 * Retrieves the <code>CLOB</code> value designated by this <code>SerialClob</code> |
213 * Retrieves the <code>CLOB</code> value designated by this <code>SerialClob</code> |
208 * object. If this <code>SerialClob</code> object is instantiated with |
217 * object. If this <code>SerialClob</code> object is instantiated with |
209 * a <code>char</code> array, a <code>SerialException</code> object is thrown. |
218 * a <code>char</code> array, a <code>SerialException</code> object is thrown. |
210 * |
219 * |
211 * @return a <code>java.io.InputStream</code> object containing |
220 * @return a <code>java.io.InputStream</code> object containing |
212 * this <code>SerialClob</code> object's data |
221 * this <code>SerialClob</code> object's data |
213 * @throws SerialException if this <code>SerialClob</code> object was not instantiated |
222 * @throws SerialException if this {@code SerialClob} object was not |
214 * with a <code>Clob</code> object |
223 * instantiated with a <code>Clob</code> object; |
|
224 * if {@code free} had previously been called on this object |
215 * @throws SQLException if there is an error accessing the |
225 * @throws SQLException if there is an error accessing the |
216 * <code>CLOB</code> value represented by the <code>Clob</code> object that was |
226 * <code>CLOB</code> value represented by the <code>Clob</code> object |
217 * used to create this <code>SerialClob</code> object |
227 * that was used to create this <code>SerialClob</code> object |
218 */ |
228 */ |
219 public java.io.InputStream getAsciiStream() throws SerialException, SQLException { |
229 public java.io.InputStream getAsciiStream() throws SerialException, SQLException { |
|
230 isValid(); |
220 if (this.clob != null) { |
231 if (this.clob != null) { |
221 return this.clob.getAsciiStream(); |
232 return this.clob.getAsciiStream(); |
222 } else { |
233 } else { |
223 throw new SerialException("Unsupported operation. SerialClob cannot " + |
234 throw new SerialException("Unsupported operation. SerialClob cannot " + |
224 "return a the CLOB value as an ascii stream, unless instantiated " + |
235 "return a the CLOB value as an ascii stream, unless instantiated " + |
246 * <code>SerialClob</code> object |
257 * <code>SerialClob</code> object |
247 * @return a <code>String</code> object containing a substring of |
258 * @return a <code>String</code> object containing a substring of |
248 * this <code>SerialClob</code> object beginning at the |
259 * this <code>SerialClob</code> object beginning at the |
249 * given position and containing the specified number of |
260 * given position and containing the specified number of |
250 * consecutive characters |
261 * consecutive characters |
251 * @throws SerialException if either of the arguments is out of bounds |
262 * @throws SerialException if either of the arguments is out of bounds; |
|
263 * if {@code free} had previously been called on this object |
252 */ |
264 */ |
253 public String getSubString(long pos, int length) throws SerialException { |
265 public String getSubString(long pos, int length) throws SerialException { |
254 |
266 |
|
267 isValid(); |
255 if (pos < 1 || pos > this.length()) { |
268 if (pos < 1 || pos > this.length()) { |
256 throw new SerialException("Invalid position in BLOB object set"); |
269 throw new SerialException("Invalid position in SerialClob object set"); |
257 } |
270 } |
258 |
271 |
259 if ((pos-1) + length > this.length()) { |
272 if ((pos-1) + length > this.length()) { |
260 throw new SerialException("Invalid position and substring length"); |
273 throw new SerialException("Invalid position and substring length"); |
261 } |
274 } |
285 * @return the position at which the given <code>String</code> object |
298 * @return the position at which the given <code>String</code> object |
286 * begins, starting the search at the specified position; |
299 * begins, starting the search at the specified position; |
287 * <code>-1</code> if the given <code>String</code> object is |
300 * <code>-1</code> if the given <code>String</code> object is |
288 * not found or the starting position is out of bounds; position |
301 * not found or the starting position is out of bounds; position |
289 * numbering for the return value starts at <code>1</code> |
302 * numbering for the return value starts at <code>1</code> |
290 * @throws SerialException if an error occurs locating the String signature |
303 * @throws SerialException if the {@code free} method had been |
291 * @throws SQLException if there is an error accessing the Blob value |
304 * previously called on this object |
|
305 * @throws SQLException if there is an error accessing the Clob value |
292 * from the database. |
306 * from the database. |
293 */ |
307 */ |
294 public long position(String searchStr, long start) |
308 public long position(String searchStr, long start) |
295 throws SerialException, SQLException { |
309 throws SerialException, SQLException { |
296 |
310 isValid(); |
297 if (start < 1 || start > len) { |
311 if (start < 1 || start > len) { |
298 return -1; |
312 return -1; |
299 } |
313 } |
300 |
314 |
301 char pattern[] = searchStr.toCharArray(); |
315 char pattern[] = searchStr.toCharArray(); |
330 * <code>1</code>; must not be less than <code>1</code> nor |
344 * <code>1</code>; must not be less than <code>1</code> nor |
331 * greater than the length of this <code>SerialClob</code> object |
345 * greater than the length of this <code>SerialClob</code> object |
332 * @return the position at which the given <code>Clob</code> |
346 * @return the position at which the given <code>Clob</code> |
333 * object begins in this <code>SerialClob</code> object, |
347 * object begins in this <code>SerialClob</code> object, |
334 * at or after the specified starting position |
348 * at or after the specified starting position |
335 * @throws SerialException if an error occurs locating the Clob signature |
349 * @throws SerialException if an error occurs locating the Clob signature; |
336 * @throws SQLException if there is an error accessing the Blob value |
350 * if the {@code free} method had been previously called on this object |
|
351 * @throws SQLException if there is an error accessing the Clob value |
337 * from the database |
352 * from the database |
338 */ |
353 */ |
339 public long position(Clob searchStr, long start) |
354 public long position(Clob searchStr, long start) |
340 throws SerialException, SQLException { |
355 throws SerialException, SQLException { |
341 |
356 isValid(); |
342 return position(searchStr.getSubString(1,(int)searchStr.length()), start); |
357 return position(searchStr.getSubString(1,(int)searchStr.length()), start); |
343 } |
358 } |
344 |
359 |
345 /** |
360 /** |
346 * Writes the given Java <code>String</code> to the <code>CLOB</code> |
361 * Writes the given Java <code>String</code> to the <code>CLOB</code> |
356 * @return the number of characters written |
371 * @return the number of characters written |
357 * @throws SerialException if there is an error accessing the |
372 * @throws SerialException if there is an error accessing the |
358 * <code>CLOB</code> value; if an invalid position is set; if an |
373 * <code>CLOB</code> value; if an invalid position is set; if an |
359 * invalid offset value is set; if number of bytes to be written |
374 * invalid offset value is set; if number of bytes to be written |
360 * is greater than the <code>SerialClob</code> length; or the combined |
375 * is greater than the <code>SerialClob</code> length; or the combined |
361 * values of the length and offset is greater than the Clob buffer |
376 * values of the length and offset is greater than the Clob buffer; |
|
377 * if the {@code free} method had been previously called on this object |
362 */ |
378 */ |
363 public int setString(long pos, String str) throws SerialException { |
379 public int setString(long pos, String str) throws SerialException { |
364 return (setString(pos, str, 0, str.length())); |
380 return (setString(pos, str, 0, str.length())); |
365 } |
381 } |
366 |
382 |
381 * @return the number of characters written |
397 * @return the number of characters written |
382 * @throws SerialException if there is an error accessing the |
398 * @throws SerialException if there is an error accessing the |
383 * <code>CLOB</code> value; if an invalid position is set; if an |
399 * <code>CLOB</code> value; if an invalid position is set; if an |
384 * invalid offset value is set; if number of bytes to be written |
400 * invalid offset value is set; if number of bytes to be written |
385 * is greater than the <code>SerialClob</code> length; or the combined |
401 * is greater than the <code>SerialClob</code> length; or the combined |
386 * values of the length and offset is greater than the Clob buffer |
402 * values of the length and offset is greater than the Clob buffer; |
|
403 * if the {@code free} method had been previously called on this object |
387 */ |
404 */ |
388 public int setString(long pos, String str, int offset, int length) |
405 public int setString(long pos, String str, int offset, int length) |
389 throws SerialException { |
406 throws SerialException { |
|
407 isValid(); |
390 String temp = str.substring(offset); |
408 String temp = str.substring(offset); |
391 char cPattern[] = temp.toCharArray(); |
409 char cPattern[] = temp.toCharArray(); |
392 |
410 |
393 if (offset < 0 || offset > str.length()) { |
411 if (offset < 0 || offset > str.length()) { |
394 throw new SerialException("Invalid offset in byte array set"); |
412 throw new SerialException("Invalid offset in byte array set"); |
395 } |
413 } |
396 |
414 |
397 if (pos < 1 || pos > this.length()) { |
415 if (pos < 1 || pos > this.length()) { |
398 throw new SerialException("Invalid position in BLOB object set"); |
416 throw new SerialException("Invalid position in Clob object set"); |
399 } |
417 } |
400 |
418 |
401 if ((long)(length) > origLen) { |
419 if ((long)(length) > origLen) { |
402 throw new SerialException("Buffer is not sufficient to hold the value"); |
420 throw new SerialException("Buffer is not sufficient to hold the value"); |
403 } |
421 } |
428 * |
446 * |
429 * @param pos the position at which to start writing to the |
447 * @param pos the position at which to start writing to the |
430 * <code>CLOB</code> object |
448 * <code>CLOB</code> object |
431 * @return the stream to which ASCII encoded characters can be written |
449 * @return the stream to which ASCII encoded characters can be written |
432 * @throws SerialException if SerialClob is not instantiated with a |
450 * @throws SerialException if SerialClob is not instantiated with a |
433 * Clob object that supports <code>setAsciiStream</code> |
451 * Clob object; |
|
452 * if the {@code free} method had been previously called on this object |
434 * @throws SQLException if there is an error accessing the |
453 * @throws SQLException if there is an error accessing the |
435 * <code>CLOB</code> value |
454 * <code>CLOB</code> value |
436 * @see #getAsciiStream |
455 * @see #getAsciiStream |
437 */ |
456 */ |
438 public java.io.OutputStream setAsciiStream(long pos) |
457 public java.io.OutputStream setAsciiStream(long pos) |
439 throws SerialException, SQLException { |
458 throws SerialException, SQLException { |
|
459 isValid(); |
440 if (this.clob != null) { |
460 if (this.clob != null) { |
441 return this.clob.setAsciiStream(pos); |
461 return this.clob.setAsciiStream(pos); |
442 } else { |
462 } else { |
443 throw new SerialException("Unsupported operation. SerialClob cannot " + |
463 throw new SerialException("Unsupported operation. SerialClob cannot " + |
444 "return a writable ascii stream\n unless instantiated with a Clob object " + |
464 "return a writable ascii stream\n unless instantiated with a Clob object " + |
458 * @param pos the position at which to start writing to the |
478 * @param pos the position at which to start writing to the |
459 * <code>CLOB</code> value |
479 * <code>CLOB</code> value |
460 * |
480 * |
461 * @return a stream to which Unicode encoded characters can be written |
481 * @return a stream to which Unicode encoded characters can be written |
462 * @throws SerialException if the SerialClob is not instantiated with |
482 * @throws SerialException if the SerialClob is not instantiated with |
463 * a Clob object that supports <code>setCharacterStream</code> |
483 * a Clob object; |
|
484 * if the {@code free} method had been previously called on this object |
464 * @throws SQLException if there is an error accessing the |
485 * @throws SQLException if there is an error accessing the |
465 * <code>CLOB</code> value |
486 * <code>CLOB</code> value |
466 * @see #getCharacterStream |
487 * @see #getCharacterStream |
467 */ |
488 */ |
468 public java.io.Writer setCharacterStream(long pos) |
489 public java.io.Writer setCharacterStream(long pos) |
469 throws SerialException, SQLException { |
490 throws SerialException, SQLException { |
|
491 isValid(); |
470 if (this.clob != null) { |
492 if (this.clob != null) { |
471 return this.clob.setCharacterStream(pos); |
493 return this.clob.setCharacterStream(pos); |
472 } else { |
494 } else { |
473 throw new SerialException("Unsupported operation. SerialClob cannot " + |
495 throw new SerialException("Unsupported operation. SerialClob cannot " + |
474 "return a writable character stream\n unless instantiated with a Clob object " + |
496 "return a writable character stream\n unless instantiated with a Clob object " + |
484 * Truncating a <code>SerialClob</code> object to length 0 has the effect of |
506 * Truncating a <code>SerialClob</code> object to length 0 has the effect of |
485 * clearing its contents. |
507 * clearing its contents. |
486 * |
508 * |
487 * @param length the length, in bytes, to which the <code>CLOB</code> |
509 * @param length the length, in bytes, to which the <code>CLOB</code> |
488 * value should be truncated |
510 * value should be truncated |
489 * @throws SQLException if there is an error accessing the |
511 * @throws SerialLException if there is an error accessing the |
490 * <code>CLOB</code> value |
512 * <code>CLOB</code> value; |
|
513 * if the {@code free} method had been previously called on this object |
491 */ |
514 */ |
492 public void truncate(long length) throws SerialException { |
515 public void truncate(long length) throws SerialException { |
493 if (length > len) { |
516 isValid(); |
494 throw new SerialException |
517 if (length > len) { |
495 ("Length more than what can be truncated"); |
518 throw new SerialException |
496 } else { |
519 ("Length more than what can be truncated"); |
497 len = length; |
520 } else { |
498 // re-size the buffer |
521 len = length; |
499 |
522 // re-size the buffer |
500 if (len == 0) { |
523 |
501 buf = new char[] {}; |
524 if (len == 0) { |
502 } else { |
525 buf = new char[] {}; |
|
526 } else { |
503 buf = (this.getSubString(1, (int)len)).toCharArray(); |
527 buf = (this.getSubString(1, (int)len)).toCharArray(); |
504 } |
528 } |
505 |
529 } |
506 } |
530 } |
507 } |
531 |
508 |
532 |
509 |
533 /** |
|
534 * Returns a {@code Reader} object that contains a partial |
|
535 * {@code SerialClob} value, starting |
|
536 * with the character specified by pos, which is length characters in length. |
|
537 * |
|
538 * @param pos the offset to the first character of the partial value to |
|
539 * be retrieved. The first character in the {@code SerialClob} is at position 1. |
|
540 * @param length the length in characters of the partial value to be retrieved. |
|
541 * @return {@code Reader} through which the partial {@code SerialClob} |
|
542 * value can be read. |
|
543 * @throws SQLException if pos is less than 1 or if pos is greater than the |
|
544 * number of characters in the {@code SerialClob} or if pos + length |
|
545 * is greater than the number of characters in the {@code SerialClob}; |
|
546 * @throws SerialException if the {@code free} method had been previously |
|
547 * called on this object |
|
548 * @since 1.6 |
|
549 */ |
510 public Reader getCharacterStream(long pos, long length) throws SQLException { |
550 public Reader getCharacterStream(long pos, long length) throws SQLException { |
511 throw new java.lang.UnsupportedOperationException("Not supported"); |
551 isValid(); |
512 } |
552 if (pos < 1 || pos > len) { |
513 |
553 throw new SerialException("Invalid position in Clob object set"); |
|
554 } |
|
555 |
|
556 if ((pos-1) + length > len) { |
|
557 throw new SerialException("Invalid position and substring length"); |
|
558 } |
|
559 if (length <= 0) { |
|
560 throw new SerialException("Invalid length specified"); |
|
561 } |
|
562 return new CharArrayReader(buf, (int)pos, (int)length); |
|
563 } |
|
564 |
|
565 /** |
|
566 * This method frees the {@code SeriableClob} object and releases the |
|
567 * resources that it holds. |
|
568 * The object is invalid once the {@code free} method is called. |
|
569 * <p> |
|
570 * If {@code free} is called multiple times, the subsequent |
|
571 * calls to {@code free} are treated as a no-op. |
|
572 * </P> |
|
573 * @throws SQLException if an error occurs releasing |
|
574 * the Clob's resources |
|
575 * @since 1.6 |
|
576 */ |
514 public void free() throws SQLException { |
577 public void free() throws SQLException { |
515 throw new java.lang.UnsupportedOperationException("Not supported"); |
578 if (buf != null) { |
|
579 buf = null; |
|
580 if (clob != null) { |
|
581 clob.free(); |
|
582 } |
|
583 clob = null; |
|
584 } |
516 } |
585 } |
517 |
586 |
518 /** |
587 /** |
519 * Compares this SerialClob to the specified object. The result is {@code |
588 * Compares this SerialClob to the specified object. The result is {@code |
520 * true} if and only if the argument is not {@code null} and is a {@code |
589 * true} if and only if the argument is not {@code null} and is a {@code |
557 * @return a clone of this SerialClob |
626 * @return a clone of this SerialClob |
558 */ |
627 */ |
559 public Object clone() { |
628 public Object clone() { |
560 try { |
629 try { |
561 SerialClob sc = (SerialClob) super.clone(); |
630 SerialClob sc = (SerialClob) super.clone(); |
562 sc.buf = Arrays.copyOf(buf, (int)len); |
631 sc.buf = (buf != null) ? Arrays.copyOf(buf, (int)len) : null; |
563 sc.clob = null; |
632 sc.clob = null; |
564 return sc; |
633 return sc; |
565 } catch (CloneNotSupportedException ex) { |
634 } catch (CloneNotSupportedException ex) { |
566 // this shouldn't happen, since we are Cloneable |
635 // this shouldn't happen, since we are Cloneable |
567 throw new InternalError(); |
636 throw new InternalError(); |