Save This Page
Home » openjdk-7 » javax » sql » rowset » serial » [javadoc | source]
    1   /*
    2    * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package javax.sql.rowset.serial;
   27   
   28   import java.sql;
   29   import java.io;
   30   import java.lang.reflect;
   31   
   32   
   33   /**
   34    * A serialized mapping in the Java programming language of an SQL
   35    * <code>BLOB</code> value.
   36    * <P>
   37    * The <code>SerialBlob</code> class provides a constructor for creating
   38    * an instance from a <code>Blob</code> object.  Note that the
   39    * <code>Blob</code>
   40    * object should have brought the SQL <code>BLOB</code> value's data over
   41    * to the client before a <code>SerialBlob</code> object
   42    * is constructed from it.  The data of an SQL <code>BLOB</code> value can
   43    * be materialized on the client as an array of bytes (using the method
   44    * <code>Blob.getBytes</code>) or as a stream of uninterpreted bytes
   45    * (using the method <code>Blob.getBinaryStream</code>).
   46    * <P>
   47    * <code>SerialBlob</code> methods make it possible to make a copy of a
   48    * <code>SerialBlob</code> object as an array of bytes or as a stream.
   49    * They also make it possible to locate a given pattern of bytes or a
   50    * <code>Blob</code> object within a <code>SerialBlob</code> object
   51    * and to update or truncate a <code>Blob</code> object.
   52    *
   53    * @author Jonathan Bruce
   54    */
   55   public class SerialBlob implements Blob, Serializable, Cloneable {
   56   
   57       /**
   58        * A serialized array of uninterpreted bytes representing the
   59        * value of this <code>SerialBlob</code> object.
   60        * @serial
   61        */
   62       private byte buf[];
   63   
   64       /**
   65        * The internal representation of the <code>Blob</code> object on which this
   66        * <code>SerialBlob</code> object is based.
   67        */
   68       private Blob blob;
   69   
   70       /**
   71        * The number of bytes in this <code>SerialBlob</code> object's
   72        * array of bytes.
   73        * @serial
   74        */
   75       private long len;
   76   
   77       /**
   78        * The orginal number of bytes in this <code>SerialBlob</code> object's
   79        * array of bytes when it was first established.
   80        * @serial
   81        */
   82       private long origLen;
   83   
   84       /**
   85        * Constructs a <code>SerialBlob</code> object that is a serialized version of
   86        * the given <code>byte</code> array.
   87        * <p>
   88        * The new <code>SerialBlob</code> object is initialized with the data from the
   89        * <code>byte</code> array, thus allowing disconnected <code>RowSet</code>
   90        * objects to establish serialized <code>Blob</code> objects without
   91        * touching the data source.
   92        *
   93        * @param b the <code>byte</code> array containing the data for the
   94        *        <code>Blob</code> object to be serialized
   95        * @throws SerialException if an error occurs during serialization
   96        * @throws SQLException if a SQL errors occurs
   97        */
   98       public SerialBlob(byte[] b) throws SerialException, SQLException {
   99   
  100           len = b.length;
  101           buf = new byte[(int)len];
  102           for(int i = 0; i < len; i++) {
  103              buf[i] = b[i];
  104           }
  105           origLen = len;
  106       }
  107   
  108   
  109       /**
  110        * Constructs a <code>SerialBlob</code> object that is a serialized
  111        * version of the given <code>Blob</code> object.
  112        * <P>
  113        * The new <code>SerialBlob</code> object is initialized with the
  114        * data from the <code>Blob</code> object; therefore, the
  115        * <code>Blob</code> object should have previously brought the
  116        * SQL <code>BLOB</code> value's data over to the client from
  117        * the database. Otherwise, the new <code>SerialBlob</code> object
  118        * will contain no data.
  119        *
  120        * @param blob the <code>Blob</code> object from which this
  121        *     <code>SerialBlob</code> object is to be constructed;
  122        *     cannot be null.
  123        * @throws SerialException if an error occurs during serialization
  124        * @throws SQLException if the <code>Blob</code> passed to this
  125        *     to this constructor is a <code>null</code>.
  126        * @see java.sql.Blob
  127        */
  128       public SerialBlob (Blob blob) throws SerialException, SQLException {
  129   
  130           if (blob == null) {
  131               throw new SQLException("Cannot instantiate a SerialBlob " +
  132                    "object with a null Blob object");
  133           }
  134   
  135           len = blob.length();
  136           buf = blob.getBytes(1, (int)len );
  137           this.blob = blob;
  138   
  139            //if ( len < 10240000)
  140            // len = 10240000;
  141           origLen = len;
  142       }
  143   
  144       /**
  145        * Copies the specified number of bytes, starting at the given
  146        * position, from this <code>SerialBlob</code> object to
  147        * another array of bytes.
  148        * <P>
  149        * Note that if the given number of bytes to be copied is larger than
  150        * the length of this <code>SerialBlob</code> object's array of
  151        * bytes, the given number will be shortened to the array's length.
  152        *
  153        * @param pos the ordinal position of the first byte in this
  154        *            <code>SerialBlob</code> object to be copied;
  155        *            numbering starts at <code>1</code>; must not be less
  156        *            than <code>1</code> and must be less than or equal
  157        *            to the length of this <code>SerialBlob</code> object
  158        * @param length the number of bytes to be copied
  159        * @return an array of bytes that is a copy of a region of this
  160        *         <code>SerialBlob</code> object, starting at the given
  161        *         position and containing the given number of consecutive bytes
  162        * @throws SerialException if the given starting position is out of bounds
  163        */
  164       public byte[] getBytes(long pos, int length) throws SerialException {
  165           if (length > len) {
  166               length = (int)len;
  167           }
  168   
  169           if (pos < 1 || length - pos < 0 ) {
  170               throw new SerialException("Invalid arguments: position cannot be less that 1");
  171           }
  172   
  173           pos--; // correct pos to array index
  174   
  175           byte[] b = new byte[length];
  176   
  177           for (int i = 0; i < length; i++) {
  178               b[i] = this.buf[(int)pos];
  179               pos++;
  180           }
  181           return b;
  182       }
  183   
  184       /**
  185        * Retrieves the number of bytes in this <code>SerialBlob</code>
  186        * object's array of bytes.
  187        *
  188        * @return a <code>long</code> indicating the length in bytes of this
  189        *         <code>SerialBlob</code> object's array of bytes
  190        * @throws SerialException if an error occurs
  191        */
  192       public long length() throws SerialException {
  193           return len;
  194       }
  195   
  196       /**
  197        * Returns this <code>SerialBlob</code> object as an input stream.
  198        * Unlike the related method, <code>setBinaryStream</code>,
  199        * a stream is produced regardless of whether the <code>SerialBlob</code>
  200        * was created with a <code>Blob</code> object or a <code>byte</code> array.
  201        *
  202        * @return a <code>java.io.InputStream</code> object that contains
  203        *         this <code>SerialBlob</code> object's array of bytes
  204        * @throws SerialException if an error occurs
  205        * @see #setBinaryStream
  206        */
  207       public java.io.InputStream getBinaryStream() throws SerialException {
  208            InputStream stream = new ByteArrayInputStream(buf);
  209            return (java.io.InputStream)stream;
  210       }
  211   
  212       /**
  213        * Returns the position in this <code>SerialBlob</code> object where
  214        * the given pattern of bytes begins, starting the search at the
  215        * specified position.
  216        *
  217        * @param pattern the pattern of bytes for which to search
  218        * @param start the position of the byte in this
  219        *              <code>SerialBlob</code> object from which to begin
  220        *              the search; the first position is <code>1</code>;
  221        *              must not be less than <code>1</code> nor greater than
  222        *              the length of this <code>SerialBlob</code> object
  223        * @return the position in this <code>SerialBlob</code> object
  224        *         where the given pattern begins, starting at the specified
  225        *         position; <code>-1</code> if the pattern is not found
  226        *         or the given starting position is out of bounds; position
  227        *         numbering for the return value starts at <code>1</code>
  228        * @throws SerialException if an error occurs when serializing the blob
  229        * @throws SQLException if there is an error accessing the <code>BLOB</code>
  230        *         value from the database
  231        */
  232       public long position(byte[] pattern, long start)
  233                   throws SerialException, SQLException {
  234           if (start < 1 || start > len) {
  235               return -1;
  236           }
  237   
  238           int pos = (int)start-1; // internally Blobs are stored as arrays.
  239           int i = 0;
  240           long patlen = pattern.length;
  241   
  242           while (pos < len) {
  243               if (pattern[i] == buf[pos]) {
  244                   if (i + 1 == patlen) {
  245                       return (pos + 1) - (patlen - 1);
  246                   }
  247                   i++; pos++; // increment pos, and i
  248               } else if (pattern[i] != buf[pos]) {
  249                   pos++; // increment pos only
  250               }
  251           }
  252           return -1; // not found
  253       }
  254   
  255       /**
  256        * Returns the position in this <code>SerialBlob</code> object where
  257        * the given <code>Blob</code> object begins, starting the search at the
  258        * specified position.
  259        *
  260        * @param pattern the <code>Blob</code> object for which to search;
  261        * @param start the position of the byte in this
  262        *              <code>SerialBlob</code> object from which to begin
  263        *              the search; the first position is <code>1</code>;
  264        *              must not be less than <code>1</code> nor greater than
  265        *              the length of this <code>SerialBlob</code> object
  266        * @return the position in this <code>SerialBlob</code> object
  267        *         where the given <code>Blob</code> object begins, starting
  268        *         at the specified position; <code>-1</code> if the pattern is
  269        *         not found or the given starting position is out of bounds;
  270        *         position numbering for the return value starts at <code>1</code>
  271        * @throws SerialException if an error occurs when serializing the blob
  272        * @throws SQLException if there is an error accessing the <code>BLOB</code>
  273        *         value from the database
  274        */
  275       public long position(Blob pattern, long start)
  276          throws SerialException, SQLException {
  277           return position(pattern.getBytes(1, (int)(pattern.length())), start);
  278       }
  279   
  280       /**
  281        * Writes the given array of bytes to the <code>BLOB</code> value that
  282        * this <code>Blob</code> object represents, starting at position
  283        * <code>pos</code>, and returns the number of bytes written.
  284        *
  285        * @param pos the position in the SQL <code>BLOB</code> value at which
  286        *     to start writing. The first position is <code>1</code>;
  287        *     must not be less than <code>1</code> nor greater than
  288        *     the length of this <code>SerialBlob</code> object.
  289        * @param bytes the array of bytes to be written to the <code>BLOB</code>
  290        *        value that this <code>Blob</code> object represents
  291        * @return the number of bytes written
  292        * @throws SerialException if there is an error accessing the
  293        *     <code>BLOB</code> value; or if an invalid position is set; if an
  294        *     invalid offset value is set
  295        * @throws SQLException if there is an error accessing the <code>BLOB</code>
  296        *         value from the database
  297        * @see #getBytes
  298        */
  299       public int setBytes(long pos, byte[] bytes)
  300           throws SerialException, SQLException {
  301           return (setBytes(pos, bytes, 0, bytes.length));
  302       }
  303   
  304       /**
  305        * Writes all or part of the given <code>byte</code> array to the
  306        * <code>BLOB</code> value that this <code>Blob</code> object represents
  307        * and returns the number of bytes written.
  308        * Writing starts at position <code>pos</code> in the <code>BLOB</code>
  309        * value; <i>len</i> bytes from the given byte array are written.
  310        *
  311        * @param pos the position in the <code>BLOB</code> object at which
  312        *     to start writing. The first position is <code>1</code>;
  313        *     must not be less than <code>1</code> nor greater than
  314        *     the length of this <code>SerialBlob</code> object.
  315        * @param bytes the array of bytes to be written to the <code>BLOB</code>
  316        *     value
  317        * @param offset the offset in the <code>byte</code> array at which
  318        *     to start reading the bytes. The first offset position is
  319        *     <code>0</code>; must not be less than <code>0</code> nor greater
  320        *     than the length of the <code>byte</code> array
  321        * @param length the number of bytes to be written to the
  322        *     <code>BLOB</code> value from the array of bytes <i>bytes</i>.
  323        *
  324        * @return the number of bytes written
  325        * @throws SerialException if there is an error accessing the
  326        *     <code>BLOB</code> value; if an invalid position is set; if an
  327        *     invalid offset value is set; if number of bytes to be written
  328        *     is greater than the <code>SerialBlob</code> length; or the combined
  329        *     values of the length and offset is greater than the Blob buffer
  330        * @throws SQLException if there is an error accessing the <code>BLOB</code>
  331        *         value from the database.
  332        * @see #getBytes
  333        */
  334       public int setBytes(long pos, byte[] bytes, int offset, int length)
  335           throws SerialException, SQLException {
  336   
  337           if (offset < 0 || offset > bytes.length) {
  338               throw new SerialException("Invalid offset in byte array set");
  339           }
  340   
  341           if (pos < 1 || pos > this.length()) {
  342               throw new SerialException("Invalid position in BLOB object set");
  343           }
  344   
  345           if ((long)(length) > origLen) {
  346               throw new SerialException("Buffer is not sufficient to hold the value");
  347           }
  348   
  349           if ((length + offset) > bytes.length) {
  350               throw new SerialException("Invalid OffSet. Cannot have combined offset " +
  351                   "and length that is greater that the Blob buffer");
  352           }
  353   
  354           int i = 0;
  355           pos--; // correct to array indexing
  356           while ( i < length || (offset + i +1) < (bytes.length-offset) ) {
  357               this.buf[(int)pos + i] = bytes[offset + i ];
  358               i++;
  359           }
  360           return i;
  361       }
  362   
  363       /**
  364        * Retrieves a stream that can be used to write to the <code>BLOB</code>
  365        * value that this <code>Blob</code> object represents.  The stream begins
  366        * at position <code>pos</code>. This method forwards the
  367        * <code>setBinaryStream()</code> call to the underlying <code>Blob</code> in
  368        * the event that this <code>SerialBlob</code> object is instantiated with a
  369        * <code>Blob</code>. If this <code>SerialBlob</code> is instantiated with
  370        * a <code>byte</code> array, a <code>SerialException</code> is thrown.
  371        *
  372        * @param pos the position in the <code>BLOB</code> value at which
  373        *        to start writing
  374        * @return a <code>java.io.OutputStream</code> object to which data can
  375        *         be written
  376        * @throws SQLException if there is an error accessing the
  377        *            <code>BLOB</code> value
  378        * @throws SerialException if the SerialBlob in not instantiated with a
  379        *     <code>Blob</code> object that supports <code>setBinaryStream()</code>
  380        * @see #getBinaryStream
  381        */
  382       public java.io.OutputStream setBinaryStream(long pos)
  383           throws SerialException, SQLException {
  384           if (this.blob.setBinaryStream(pos) != null) {
  385               return this.blob.setBinaryStream(pos);
  386           } else {
  387               throw new SerialException("Unsupported operation. SerialBlob cannot " +
  388                   "return a writable binary stream, unless instantiated with a Blob object " +
  389                   "that provides a setBinaryStream() implementation");
  390           }
  391       }
  392   
  393       /**
  394        * Truncates the <code>BLOB</code> value that this <code>Blob</code>
  395        * object represents to be <code>len</code> bytes in length.
  396        *
  397        * @param length the length, in bytes, to which the <code>BLOB</code>
  398        *        value that this <code>Blob</code> object represents should be
  399        *        truncated
  400        * @throws SerialException if there is an error accessing the Blob value;
  401        *     or the length to truncate is greater that the SerialBlob length
  402        */
  403       public void truncate(long length) throws SerialException {
  404   
  405            if (length > len) {
  406               throw new SerialException
  407                  ("Length more than what can be truncated");
  408            } else if((int)length == 0) {
  409                 buf = new byte[0];
  410                 len = length;
  411            } else {
  412                 len = length;
  413                 buf = this.getBytes(1, (int)len);
  414            }
  415       }
  416   
  417   
  418       /**
  419        * Returns an <code>InputStream</code> object that contains a partial <code>Blob</code> value,
  420        * starting  with the byte specified by pos, which is length bytes in length.
  421        *
  422        * @param pos the offset to the first byte of the partial value to be retrieved.
  423        *  The first byte in the <code>Blob</code> is at position 1
  424        * @param length the length in bytes of the partial value to be retrieved
  425        * @return <code>InputStream</code> through which the partial <code>Blob</code> value can be read.
  426        * @throws SQLException if pos is less than 1 or if pos is greater than the number of bytes
  427        * in the <code>Blob</code> or if pos + length is greater than the number of bytes
  428        * in the <code>Blob</code>
  429        *
  430        * @since 1.6
  431        */
  432       public InputStream getBinaryStream(long pos,long length) throws SQLException {
  433           throw new java.lang.UnsupportedOperationException("Not supported");
  434       }
  435   
  436   
  437       /**
  438        * This method frees the <code>Blob</code> object and releases the resources that it holds.
  439        * <code>Blob</code> object. The object is invalid once the <code>free</code>
  440        * method is called. If <code>free</code> is called multiple times, the subsequent
  441        * calls to <code>free</code> are treated as a no-op.
  442        *
  443        * @throws SQLException if an error occurs releasing
  444        * the Blob's resources
  445        * @since 1.6
  446        */
  447       public void free() throws SQLException {
  448           throw new java.lang.UnsupportedOperationException("Not supported");
  449       }
  450       /**
  451            * The identifier that assists in the serialization of this <code>SerialBlob</code>
  452        * object.
  453        */
  454   
  455       static final long serialVersionUID = -8144641928112860441L;
  456   }

Save This Page
Home » openjdk-7 » javax » sql » rowset » serial » [javadoc | source]