src/share/classes/javax/sql/rowset/serial/SerialBlob.java

Print this page

        

@@ -79,10 +79,12 @@
      * array of bytes when it was first established.
      * @serial
      */
     private long origLen;
 
+    private boolean isFree = false;
+
     /**
      * Constructs a <code>SerialBlob</code> object that is a serialized version of
      * the given <code>byte</code> array.
      * <p>
      * The new <code>SerialBlob</code> object is initialized with the data from the

@@ -158,12 +160,15 @@
      * @param length the number of bytes to be copied
      * @return an array of bytes that is a copy of a region of this
      *         <code>SerialBlob</code> object, starting at the given
      *         position and containing the given number of consecutive bytes
      * @throws SerialException if the given starting position is out of bounds
+     *         or called after free() has been called.
      */
     public byte[] getBytes(long pos, int length) throws SerialException {
+        isFreed();
+
         if (length > len) {
             length = (int)len;
         }
 
         if (pos < 1 || len - pos < 0 ) {

@@ -186,13 +191,14 @@
      * Retrieves the number of bytes in this <code>SerialBlob</code>
      * object's array of bytes.
      *
      * @return a <code>long</code> indicating the length in bytes of this
      *         <code>SerialBlob</code> object's array of bytes
-     * @throws SerialException if an error occurs
+     * @throws SerialException if an error occurs or called after free() has been called.
      */
     public long length() throws SerialException {
+        isFreed();
         return len;
     }
 
     /**
      * Returns this <code>SerialBlob</code> object as an input stream.

@@ -200,14 +206,17 @@
      * a stream is produced regardless of whether the <code>SerialBlob</code>
      * was created with a <code>Blob</code> object or a <code>byte</code> array.
      *
      * @return a <code>java.io.InputStream</code> object that contains
      *         this <code>SerialBlob</code> object's array of bytes
-     * @throws SerialException if an error occurs
+     * @throws SerialException if an error occurs or called after free() has
+     *         been called.
      * @see #setBinaryStream
      */
     public java.io.InputStream getBinaryStream() throws SerialException {
+        isFreed();
+
          InputStream stream = new ByteArrayInputStream(buf);
          return stream;
     }
 
     /**

@@ -224,16 +233,19 @@
      * @return the position in this <code>SerialBlob</code> object
      *         where the given pattern begins, starting at the specified
      *         position; <code>-1</code> if the pattern is not found
      *         or the given starting position is out of bounds; position
      *         numbering for the return value starts at <code>1</code>
-     * @throws SerialException if an error occurs when serializing the blob
+     * @throws SerialException if an error occurs when serializing the blob or
+     *         called after free() has been called.
      * @throws SQLException if there is an error accessing the <code>BLOB</code>
      *         value from the database
      */
     public long position(byte[] pattern, long start)
                 throws SerialException, SQLException {
+        isFreed();
+
         if (start < 1 || start > len) {
             return -1;
         }
 
         int pos = (int)start-1; // internally Blobs are stored as arrays.

@@ -267,16 +279,18 @@
      * @return the position in this <code>SerialBlob</code> object
      *         where the given <code>Blob</code> object begins, starting
      *         at the specified position; <code>-1</code> if the pattern is
      *         not found or the given starting position is out of bounds;
      *         position numbering for the return value starts at <code>1</code>
-     * @throws SerialException if an error occurs when serializing the blob
+     * @throws SerialException if an error occurs when serializing the blob or
+     *         called after free() has been called.
      * @throws SQLException if there is an error accessing the <code>BLOB</code>
      *         value from the database
      */
     public long position(Blob pattern, long start)
        throws SerialException, SQLException {
+        isFreed();
         return position(pattern.getBytes(1, (int)(pattern.length())), start);
     }
 
     /**
      * Writes the given array of bytes to the <code>BLOB</code> value that

@@ -290,17 +304,18 @@
      * @param bytes the array of bytes to be written to the <code>BLOB</code>
      *        value that this <code>Blob</code> object represents
      * @return the number of bytes written
      * @throws SerialException if there is an error accessing the
      *     <code>BLOB</code> value; or if an invalid position is set; if an
-     *     invalid offset value is set
+     *     invalid offset value is set or called after free() has been called.
      * @throws SQLException if there is an error accessing the <code>BLOB</code>
      *         value from the database
      * @see #getBytes
      */
     public int setBytes(long pos, byte[] bytes)
         throws SerialException, SQLException {
+        isFreed();
         return (setBytes(pos, bytes, 0, bytes.length));
     }
 
     /**
      * Writes all or part of the given <code>byte</code> array to the

@@ -325,17 +340,19 @@
      * @return the number of bytes written
      * @throws SerialException if there is an error accessing the
      *     <code>BLOB</code> value; if an invalid position is set; if an
      *     invalid offset value is set; if number of bytes to be written
      *     is greater than the <code>SerialBlob</code> length; or the combined
-     *     values of the length and offset is greater than the Blob buffer
+     *     values of the length and offset is greater than the Blob buffer or
+     *     called after free() has been called.
      * @throws SQLException if there is an error accessing the <code>BLOB</code>
      *         value from the database.
      * @see #getBytes
      */
     public int setBytes(long pos, byte[] bytes, int offset, int length)
         throws SerialException, SQLException {
+        isFreed();
 
         if (offset < 0 || offset > bytes.length) {
             throw new SerialException("Invalid offset in byte array set");
         }
 

@@ -376,14 +393,17 @@
      *         be written
      * @throws SQLException if there is an error accessing the
      *            <code>BLOB</code> value
      * @throws SerialException if the SerialBlob in not instantiated with a
      *     <code>Blob</code> object that supports <code>setBinaryStream()</code>
+     *     or called after free() has been called.
      * @see #getBinaryStream
      */
     public java.io.OutputStream setBinaryStream(long pos)
         throws SerialException, SQLException {
+        isFreed();
+
         if (this.blob != null) {
             return this.blob.setBinaryStream(pos);
         } else {
             throw new SerialException("Unsupported operation. SerialBlob cannot " +
                 "return a writable binary stream, unless instantiated with a Blob object " +

@@ -397,13 +417,15 @@
      *
      * @param length the length, in bytes, to which the <code>BLOB</code>
      *        value that this <code>Blob</code> object represents should be
      *        truncated
      * @throws SerialException if there is an error accessing the Blob value;
-     *     or the length to truncate is greater that the SerialBlob length
+     *     or the length to truncate is greater that the SerialBlob length or
+     *     called after free() has been called.
      */
     public void truncate(long length) throws SerialException {
+        isFreed();
 
          if (length > len) {
             throw new SerialException
                ("Length more than what can be truncated");
          } else if((int)length == 0) {

@@ -422,34 +444,68 @@
      *
      * @param pos the offset to the first byte of the partial value to be retrieved.
      *  The first byte in the <code>Blob</code> is at position 1
      * @param length the length in bytes of the partial value to be retrieved
      * @return <code>InputStream</code> through which the partial <code>Blob</code> value can be read.
+     * @throws SerialException if called after free() has been called.
      * @throws SQLException if pos is less than 1 or if pos is greater than the number of bytes
      * in the <code>Blob</code> or if pos + length is greater than the number of bytes
      * in the <code>Blob</code>
      *
      * @since 1.6
      */
-    public InputStream getBinaryStream(long pos,long length) throws SQLException {
-        throw new java.lang.UnsupportedOperationException("Not supported");
+    public InputStream getBinaryStream(long pos,long length) throws SerialException, SQLException {
+        isFreed();
+
+        if (pos < 1 || pos > len) {
+            throw new SerialException("Invalid pos in getBinaryStream");
+        }
+        if ((pos - 1) + length > len) {
+            throw new SerialException(
+                    "pos + length greater than total number of bytes");
+        }
+        return new ByteArrayInputStream(buf, (int) pos - 1, (int) length);
     }
 
 
     /**
-     * This method frees the <code>Blob</code> object and releases the resources that it holds.
-     * <code>Blob</code> object. The object is invalid once the <code>free</code>
-     * method is called. If <code>free</code> is called multiple times, the subsequent
-     * calls to <code>free</code> are treated as a no-op.
+     * This method frees the <code>Blob</code> object and releases the
+     * resources that it holds. <code>Blob</code> object. The object is
+     * invalid once the <code>free</code> method is called. After
+     * <code>free</code> has been called, any attempt to invoke a method
+     * other than <code>free</code> will result in a
+     * <code>SerialException</code> being thrown. If <code>free</code> is
+     * called multiple times, the subsequent calls to <code>free</code>
+     * are treated as a no-op.
      *
-     * @throws SQLException if an error occurs releasing
-     * the Blob's resources
+     * @throws SQLException if an error occurs releasing the Blob's resources
      * @since 1.6
      */
     public void free() throws SQLException {
-        throw new java.lang.UnsupportedOperationException("Not supported");
+        if (isFree == false) {
+            len = -1;
+            origLen = -1;
+            buf = null;
+
+            if (blob != null) {
+                blob.free();
+                blob = null;
+            }
+
+            isFree = true;
+        }
     }
+
+    private void isFreed() throws SerialException {
+        if (isFree == true) {
+            throw new SerialException(
+                    "Unsupported operation. SerialBlob cannot "
+                            + "execute this operation when it"
+                            + "has already been freed by free()");
+        }
+    }
+
     /**
          * The identifier that assists in the serialization of this <code>SerialBlob</code>
      * object.
      */