jdk/src/share/classes/javax/sql/rowset/serial/SerialClob.java
changeset 14781 701d0765f75f
parent 14337 a003c6a54cb6
child 16732 c96397eeca72
equal deleted inserted replaced
14780:a65826af2aa4 14781:701d0765f75f
    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();
   603         fields.put("clob", clob instanceof Serializable ? clob : null);
   672         fields.put("clob", clob instanceof Serializable ? clob : null);
   604         s.writeFields();
   673         s.writeFields();
   605     }
   674     }
   606 
   675 
   607     /**
   676     /**
   608          * The identifier that assists in the serialization of this <code>SerialClob</code>
   677      * Check to see if this object had previously had its {@code free} method
       
   678      * called
       
   679      *
       
   680      * @throws SerialException
       
   681      */
       
   682     private void isValid() throws SerialException {
       
   683         if (buf == null) {
       
   684             throw new SerialException("Error: You cannot call a method on a "
       
   685                     + "SerialClob instance once free() has been called.");
       
   686         }
       
   687     }
       
   688 
       
   689     /**
       
   690      * The identifier that assists in the serialization of this {@code SerialClob}
   609      * object.
   691      * object.
   610      */
   692      */
   611     static final long serialVersionUID = -1662519690087375313L;
   693     static final long serialVersionUID = -1662519690087375313L;
   612 }
   694 }