src/java.sql/share/classes/java/sql2/SqlBlob.java
branchJDK-8188051-branch
changeset 56380 f06946e00a26
parent 56373 1f76a5f8e999
child 56381 653b066f4a88
equal deleted inserted replaced
56373:1f76a5f8e999 56380:f06946e00a26
     1 /*
       
     2  * Copyright (c)  2017, Oracle and/or its affiliates. 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.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 package java.sql2;
       
    26 
       
    27 import java.nio.channels.AsynchronousByteChannel;
       
    28 import java.util.concurrent.CompletionStage;
       
    29 
       
    30 /**
       
    31  * A reference to a BINARY LARGE OBJECT in the attached database.
       
    32  *
       
    33  */
       
    34 public interface SqlBlob extends AutoCloseable {
       
    35 
       
    36   /**
       
    37    * Return an {@link Operation} that will release the temporary resources
       
    38    * associated with this {@link SqlBlob}.
       
    39    *
       
    40    * @return an {@link Operation} that will release the temporary resources
       
    41    * associated with this {@link SqlBlob}.
       
    42    */
       
    43   public Operation<Void> closeOperation();
       
    44 
       
    45   @Override
       
    46   public default void close() {
       
    47     this.closeOperation().submit();
       
    48   }
       
    49 
       
    50   /**
       
    51    * Return a {@link Operation} that fetches the position of this {@link SqlBlob}.
       
    52    * The position is 1-based. Position 0 is immediately before the first byte in
       
    53    * the {@link SqlBlob}. Position 1 is the first byte in the {@link SqlBlob}, etc.
       
    54    * Position {@link length()} is the last byte in the {@link SqlBlob}.
       
    55    *
       
    56    * Position is between 0 and length + 1.
       
    57    *
       
    58    * @return a {@link Operation} that returns the position of this {@link SqlBlob}
       
    59    * @throws IllegalStateException if the {@link Connection} that created this
       
    60    * {@link SqlBlob} is closed.
       
    61    */
       
    62   public Operation<Long> getPositionOperation();
       
    63 
       
    64   /**
       
    65    * Get the position of this {@link SqlBlob}. The position is 1-based. Position 0
       
    66    * is immediately before the first byte in the {@link SqlBlob}. Position 1 is the
       
    67    * first byte in the {@link SqlBlob}, etc. Position {@link length()} is the last
       
    68    * byte in the {@link SqlBlob}.
       
    69    *
       
    70    * Position is between 0 and length + 1.
       
    71    *
       
    72    * ISSUE: Should position be 1-based as SQL seems to do or 0-based as Java
       
    73    * does?
       
    74    *
       
    75    * @return a future which value is the 1-based position of this {@link SqlBlob}
       
    76    * @throws IllegalStateException if the {@link Connection} that created this
       
    77    * {@link SqlBlob} is closed.
       
    78    */
       
    79   public default CompletionStage<Long> getPosition() {
       
    80     return getPositionOperation().submit().getCompletionStage();
       
    81   }
       
    82 
       
    83   /**
       
    84    * Return a {@link Operation} that fetches the length of this {@link SqlBlob}.
       
    85    *
       
    86    * @return a {@link Operation} that returns the length of this {@link SqlBlob}
       
    87    * @throws IllegalStateException if the {@link Connection} that created this
       
    88    * {@link SqlBlob} is closed.
       
    89    */
       
    90   public Operation<Long> lengthOperation();
       
    91 
       
    92   /**
       
    93    * Get the length of this {@link SqlBlob}.
       
    94    *
       
    95    * @return a future which value is the number of bytes in this {@link SqlBlob}
       
    96    * @throws IllegalStateException if the {@link Connection} that created this
       
    97    * {@link SqlBlob} is closed.
       
    98    */
       
    99   public default CompletionStage<Long> length() {
       
   100     return lengthOperation().submit().getCompletionStage();
       
   101   }
       
   102 
       
   103   /**
       
   104    * Return a {@link Operation} that sets the position of this {@link SqlBlob}. If
       
   105    * offset exceeds the length of this {@link SqlBlob} set position to the length +
       
   106    * 1 of this {@link SqlBlob}, ie one past the last byte.
       
   107    *
       
   108    * @param offset a non-negative number
       
   109    * @return a {@link Operation} that sets the position of this {@link SqlBlob}
       
   110    * @throws IllegalArgumentException if {@code offset} is less than 0
       
   111    * @throws IllegalStateException if the {@link Connection} that created this
       
   112    * {@link SqlBlob} is closed.
       
   113    */
       
   114   public Operation<Long> setPositionOperation(long offset);
       
   115 
       
   116   /**
       
   117    * Set the position of this {@link SqlBlob}. If offset exceeds the length of this
       
   118    * {@link SqlBlob} set position to the length + 1 of this {@link SqlBlob}, ie one
       
   119    * past the last byte.
       
   120    *
       
   121    * @param offset the 1-based position to set
       
   122    * @return this {@link SqlBlob}
       
   123    * @throws IllegalArgumentException if offset is less than 0
       
   124    * @throws IllegalStateException if the {@link Connection} that created this
       
   125    * {@link SqlBlob} is closed.
       
   126    */
       
   127   public default SqlBlob setPosition(long offset) {
       
   128     setPositionOperation(offset).submit();
       
   129     return this;
       
   130   }
       
   131 
       
   132   /**
       
   133    * Return a {@link Operation} to set the position to the beginning of the next
       
   134    * occurrence of the target after the position. If there is no such occurrence
       
   135    * set the position to 0.
       
   136    *
       
   137    * @param target a {@link SqlBlob} created by the same {@link Connection}
       
   138    * containing the byte sequence to search for
       
   139    * @return a {@link Operation} that locates {@code target} in this
       
   140    * {@link SqlBlob}
       
   141    * @throws IllegalArgumentException if {@code target} was created by some
       
   142    * other {@link Connection}
       
   143    * @throws IllegalStateException if the {@link Connection} that created this
       
   144    * {@link SqlBlob} is closed.
       
   145    */
       
   146   public Operation<Long> locateOperation(SqlBlob target);
       
   147 
       
   148   /**
       
   149    * Set the position to the beginning of the next occurrence of the target
       
   150    * after the position. If there is no such occurrence set the position to 0.
       
   151    *
       
   152    * @param target the byte sequence to search for
       
   153    * @return this {@link SqlBlob}
       
   154    * @throws IllegalArgumentException if {@code target} was created by some
       
   155    * other {@link Connection}
       
   156    * @throws IllegalStateException if the {@link Connection} that created this
       
   157    * {@link SqlBlob} is closed
       
   158    */
       
   159   public default SqlBlob locate(SqlBlob target) {
       
   160     locateOperation(target).submit();
       
   161     return this;
       
   162   }
       
   163 
       
   164   /**
       
   165    * Return an {@link Operation} to set the position to the beginning of the
       
   166    * next occurrence of the target after the position. If there is no such
       
   167    * occurrence set the position to 0.
       
   168    *
       
   169    * @param target the byte sequence to search for. Not {@code null}. Captured.
       
   170    * @return a {@link Operation} that locates {@code target} in this
       
   171    * {@link SqlBlob}
       
   172    * @throws IllegalStateException if the {@link Connection} that created this
       
   173    * {@link SqlBlob} is closed.
       
   174    */
       
   175   public Operation<Long> locateOperation(byte[] target);
       
   176 
       
   177   /**
       
   178    * Set the position to the beginning of the next occurrence of the target
       
   179    * after the position. If there is no such occurrence set the position to 0.
       
   180    *
       
   181    * @param target the byte sequence to search for
       
   182    * @return this {@link SqlBlob}
       
   183    * @throws IllegalStateException if the {@link Connection} that created this
       
   184    * {@link SqlBlob} is closed.
       
   185    */
       
   186   public default SqlBlob locate(byte[] target) {
       
   187     locateOperation(target).submit();
       
   188     return this;
       
   189   }
       
   190 
       
   191   /**
       
   192    * Return a {@link Operation} that truncates this {@link SqlBlob} so that the
       
   193    * current position is the end of the {@link SqlBlob}. If the position is N, then
       
   194    * after {@link trim()} the length is N - 1. The position is still N. This
       
   195    * will fail if position is 0.
       
   196    *
       
   197    * @return a {@link Operation} that trims the length of this {@link SqlBlob}
       
   198    * @throws IllegalStateException if the {@link Connection} that created this
       
   199    * {@link SqlBlob} is closed or position is 0.
       
   200    */
       
   201   public Operation<Long> trimOperation();
       
   202 
       
   203   /**
       
   204    * Truncate this {@link SqlBlob} so that the current position is the end of the
       
   205    * {@link SqlBlob}. If the position is N, then after {@link trim()} the length is
       
   206    * N - 1. The position is still N. This will fail if position is 0.
       
   207    *
       
   208    * @return this SqlBlob
       
   209    * @throws IllegalStateException if the {@link Connection} that created this
       
   210    * {@link SqlBlob} is closed or position is 0.
       
   211    */
       
   212   public default SqlBlob trim() {
       
   213     trimOperation().submit();
       
   214     return this;
       
   215   }
       
   216 
       
   217   /**
       
   218    * Return a {@link java.nio.channels.Channel} that can be used to read bytes from the
       
   219    * {@link SqlBlob} beginning at the position. Reading bytes from the returned
       
   220    * {@link java.nio.channels.Channel} advances the position.
       
   221    *
       
   222    * Each call to a read method that fetches bytes from the server creates and
       
   223    * submits a virtual {@link Operation} to fetch those bytes. This virtual
       
   224    * {@link Operation} is executed in sequence with other {@link Operation}s and
       
   225    * may be skipped if an error occurs.
       
   226    *
       
   227    * @return a read-only byte {@link java.nio.channels.Channel} beginning at the position.
       
   228    * @throws IllegalStateException if the {@link Connection} that created this
       
   229  SqlBlob is closed.
       
   230    */
       
   231   public AsynchronousByteChannel getReadChannel();
       
   232 
       
   233   /**
       
   234    * Return a {@link java.nio.channels.Channel} that can be used to write bytes
       
   235    * to this {@link SqlBlob} beginning at the position. Bytes written overwrite
       
   236    * bytes already in the {@link SqlBlob}. Writing bytes to the returned
       
   237    * {@link java.nio.channels.Channel} advances the position.
       
   238    *
       
   239    * Each call to a write method that flushes bytes to the server creates and
       
   240    * submits a virtual {@link Operation} to flush those bytes. This virtual
       
   241    * {@link Operation} is executed in sequence with other {@link Operation}s and
       
   242    * may be skipped if an error occurs.
       
   243    *
       
   244    * ISSUE: Can the app read bytes from a write
       
   245    * {@link java.nio.channels.Channel}? If so then maybe remove
       
   246    * {@link getReadChannel} and add a read-only flag to this method, renamed
       
   247    * {@code getChannel}.
       
   248    *
       
   249    * @return a writable byte {@link java.nio.channels.Channel} beginning at the
       
   250    * position.
       
   251    * @throws IllegalStateException if the {@link Connection} that created this
       
   252    * {@link SqlBlob} is closed.
       
   253    */
       
   254   public AsynchronousByteChannel getWriteChannel();
       
   255 }