/*
 * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package java.sql;

import java.io.IOException;
import java.io.InvalidObjectException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.Arrays;

/**
 * The subclass of {@link SQLException} thrown when an error
 * occurs during a batch update operation.  In addition to the
 * information provided by {@link SQLException}, a
 * <code>BatchUpdateException</code> provides the update
 * counts for all commands that were executed successfully during the
 * batch update, that is, all commands that were executed before the error
 * occurred.  The order of elements in an array of update counts
 * corresponds to the order in which commands were added to the batch.
 * <P>
 * After a command in a batch update fails to execute properly
 * and a <code>BatchUpdateException</code> is thrown, the driver
 * may or may not continue to process the remaining commands in
 * the batch.  If the driver continues processing after a failure,
 * the array returned by the method
 * <code>BatchUpdateException.getUpdateCounts</code> will have
 * an element for every command in the batch rather than only
 * elements for the commands that executed successfully before
 * the error.  In the case where the driver continues processing
 * commands, the array element for any command
 * that failed is <code>Statement.EXECUTE_FAILED</code>.
 * <P>
 * A JDBC driver implementation should use
 * the constructor {@code BatchUpdateException(String reason, String SQLState,
 * int vendorCode, long []updateCounts,Throwable cause) } instead of
 * constructors that take {@code int[]} for the update counts to avoid the
 * possibility of overflow.
 * <p>
 * If {@code Statement.executeLargeBatch} method is invoked it is recommended that
 * {@code getLargeUpdateCounts} be called instead of {@code getUpdateCounts}
 * in order to avoid a possible overflow of the integer update count.
 * @since 1.2
 */

public class BatchUpdateException extends SQLException {

  /**
   * Constructs a <code>BatchUpdateException</code> object initialized with a given
   * <code>reason</code>, <code>SQLState</code>, <code>vendorCode</code> and
   * <code>updateCounts</code>.
   * The <code>cause</code> is not initialized, and may subsequently be
   * initialized by a call to the
   * {@link Throwable#initCause(java.lang.Throwable)} method.
   * <p>
   * <strong>Note:</strong> There is no validation of {@code updateCounts} for
   * overflow and because of this it is recommended that you use the constructor
   * {@code BatchUpdateException(String reason, String SQLState,
   * int vendorCode, long []updateCounts,Throwable cause) }.
   * </p>
   * @param reason a description of the error
   * @param SQLState an XOPEN or SQL:2003 code identifying the exception
   * @param vendorCode an exception code used by a particular
   * database vendor
   * @param updateCounts an array of <code>int</code>, with each element
   * indicating the update count, <code>Statement.SUCCESS_NO_INFO</code> or
   * <code>Statement.EXECUTE_FAILED</code> for each SQL command in
   * the batch for JDBC drivers that continue processing
   * after a command failure; an update count or
   * <code>Statement.SUCCESS_NO_INFO</code> for each SQL command in the batch
   * prior to the failure for JDBC drivers that stop processing after a command
   * failure
   * @since 1.2
   * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],
   * java.lang.Throwable)
   */
  public BatchUpdateException( String reason, String SQLState, int vendorCode,
                               int[] updateCounts ) {
      super(reason, SQLState, vendorCode);
      this.updateCounts  = (updateCounts == null) ? null : Arrays.copyOf(updateCounts, updateCounts.length);
      this.longUpdateCounts = (updateCounts == null) ? null : copyUpdateCount(updateCounts);
  }

  /**
   * Constructs a <code>BatchUpdateException</code> object initialized with a given
   * <code>reason</code>, <code>SQLState</code> and
   * <code>updateCounts</code>.
   * The <code>cause</code> is not initialized, and may subsequently be
   * initialized by a call to the
   * {@link Throwable#initCause(java.lang.Throwable)} method. The vendor code
   * is initialized to 0.
   * <p>
   * <strong>Note:</strong> There is no validation of {@code updateCounts} for
   * overflow and because of this it is recommended that you use the constructor
   * {@code BatchUpdateException(String reason, String SQLState,
   * int vendorCode, long []updateCounts,Throwable cause) }.
   * </p>
   * @param reason a description of the exception
   * @param SQLState an XOPEN or SQL:2003 code identifying the exception
   * @param updateCounts an array of <code>int</code>, with each element
   * indicating the update count, <code>Statement.SUCCESS_NO_INFO</code> or
   * <code>Statement.EXECUTE_FAILED</code> for each SQL command in
   * the batch for JDBC drivers that continue processing
   * after a command failure; an update count or
   * <code>Statement.SUCCESS_NO_INFO</code> for each SQL command in the batch
   * prior to the failure for JDBC drivers that stop processing after a command
   * failure
   * @since 1.2
   * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],
   * java.lang.Throwable)
   */
  public BatchUpdateException(String reason, String SQLState,
                              int[] updateCounts) {
      this(reason, SQLState, 0, updateCounts);
  }

  /**
   * Constructs a <code>BatchUpdateException</code> object initialized with a given
   * <code>reason</code> and <code>updateCounts</code>.
   * The <code>cause</code> is not initialized, and may subsequently be
   * initialized by a call to the
   * {@link Throwable#initCause(java.lang.Throwable)} method.  The
   * <code>SQLState</code> is initialized to <code>null</code>
   * and the vendor code is initialized to 0.
   * <p>
   * <strong>Note:</strong> There is no validation of {@code updateCounts} for
   * overflow and because of this it is recommended that you use the constructor
   * {@code BatchUpdateException(String reason, String SQLState,
   * int vendorCode, long []updateCounts,Throwable cause) }.
   * </p>
   * @param reason a description of the exception
   * @param updateCounts an array of <code>int</code>, with each element
   * indicating the update count, <code>Statement.SUCCESS_NO_INFO</code> or
   * <code>Statement.EXECUTE_FAILED</code> for each SQL command in
   * the batch for JDBC drivers that continue processing
   * after a command failure; an update count or
   * <code>Statement.SUCCESS_NO_INFO</code> for each SQL command in the batch
   * prior to the failure for JDBC drivers that stop processing after a command
   * failure
   * @since 1.2
   * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],
   * java.lang.Throwable)
   */
  public  BatchUpdateException(String reason, int[] updateCounts) {
      this(reason, null, 0, updateCounts);
  }

  /**
   * Constructs a <code>BatchUpdateException</code> object initialized with a given
   * <code>updateCounts</code>.
   * initialized by a call to the
   * {@link Throwable#initCause(java.lang.Throwable)} method. The  <code>reason</code>
   * and <code>SQLState</code> are initialized to null and the vendor code
   * is initialized to 0.
   * <p>
   * <strong>Note:</strong> There is no validation of {@code updateCounts} for
   * overflow and because of this it is recommended that you use the constructor
   * {@code BatchUpdateException(String reason, String SQLState,
   * int vendorCode, long []updateCounts,Throwable cause) }.
   * </p>
   * @param updateCounts an array of <code>int</code>, with each element
   * indicating the update count, <code>Statement.SUCCESS_NO_INFO</code> or
   * <code>Statement.EXECUTE_FAILED</code> for each SQL command in
   * the batch for JDBC drivers that continue processing
   * after a command failure; an update count or
   * <code>Statement.SUCCESS_NO_INFO</code> for each SQL command in the batch
   * prior to the failure for JDBC drivers that stop processing after a command
   * failure
   * @since 1.2
   * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],
   * java.lang.Throwable)
   */
  public BatchUpdateException(int[] updateCounts) {
      this(null, null, 0, updateCounts);
  }

  /**
   * Constructs a <code>BatchUpdateException</code> object.
   * The <code>reason</code>, <code>SQLState</code> and <code>updateCounts</code>
   *  are initialized to <code>null</code> and the vendor code is initialized to 0.
   * The <code>cause</code> is not initialized, and may subsequently be
   * initialized by a call to the
   * {@link Throwable#initCause(java.lang.Throwable)} method.
   * <p>
   *
   * @since 1.2
   * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],
   * java.lang.Throwable)
   */
  public BatchUpdateException() {
        this(null, null, 0, null);
  }

  /**
   * Constructs a <code>BatchUpdateException</code> object initialized with
   *  a given <code>cause</code>.
   * The <code>SQLState</code> and <code>updateCounts</code>
   * are initialized
   * to <code>null</code> and the vendor code is initialized to 0.
   * The <code>reason</code>  is initialized to <code>null</code> if
   * <code>cause==null</code> or to <code>cause.toString()</code> if
   *  <code>cause!=null</code>.
   * @param cause the underlying reason for this <code>SQLException</code>
   * (which is saved for later retrieval by the <code>getCause()</code> method);
   * may be null indicating the cause is non-existent or unknown.
   * @since 1.6
   * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],
   * java.lang.Throwable)
   */
  public BatchUpdateException(Throwable cause) {
      this((cause == null ? null : cause.toString()), null, 0, (int[])null, cause);
  }

  /**
   * Constructs a <code>BatchUpdateException</code> object initialized with a
   * given <code>cause</code> and <code>updateCounts</code>.
   * The <code>SQLState</code> is initialized
   * to <code>null</code> and the vendor code is initialized to 0.
   * The <code>reason</code>  is initialized to <code>null</code> if
   * <code>cause==null</code> or to <code>cause.toString()</code> if
   * <code>cause!=null</code>.
   * <p>
   * <strong>Note:</strong> There is no validation of {@code updateCounts} for
   * overflow and because of this it is recommended that you use the constructor
   * {@code BatchUpdateException(String reason, String SQLState,
   * int vendorCode, long []updateCounts,Throwable cause) }.
   * </p>
   * @param updateCounts an array of <code>int</code>, with each element
   * indicating the update count, <code>Statement.SUCCESS_NO_INFO</code> or
   * <code>Statement.EXECUTE_FAILED</code> for each SQL command in
   * the batch for JDBC drivers that continue processing
   * after a command failure; an update count or
   * <code>Statement.SUCCESS_NO_INFO</code> for each SQL command in the batch
   * prior to the failure for JDBC drivers that stop processing after a command
   * failure
   * @param cause the underlying reason for this <code>SQLException</code>
   * (which is saved for later retrieval by the <code>getCause()</code> method); may be null indicating
   * the cause is non-existent or unknown.
   * @since 1.6
   * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],
   * java.lang.Throwable)
   */
  public BatchUpdateException(int []updateCounts , Throwable cause) {
      this((cause == null ? null : cause.toString()), null, 0, updateCounts, cause);
  }

  /**
   * Constructs a <code>BatchUpdateException</code> object initialized with
   * a given <code>reason</code>, <code>cause</code>
   * and <code>updateCounts</code>. The <code>SQLState</code> is initialized
   * to <code>null</code> and the vendor code is initialized to 0.
   * <p>
   * <strong>Note:</strong> There is no validation of {@code updateCounts} for
   * overflow and because of this it is recommended that you use the constructor
   * {@code BatchUpdateException(String reason, String SQLState,
   * int vendorCode, long []updateCounts,Throwable cause) }.
   * </p>
   * @param reason a description of the exception
   * @param updateCounts an array of <code>int</code>, with each element
   *indicating the update count, <code>Statement.SUCCESS_NO_INFO</code> or
   * <code>Statement.EXECUTE_FAILED</code> for each SQL command in
   * the batch for JDBC drivers that continue processing
   * after a command failure; an update count or
   * <code>Statement.SUCCESS_NO_INFO</code> for each SQL command in the batch
   * prior to the failure for JDBC drivers that stop processing after a command
   * failure
   * @param cause the underlying reason for this <code>SQLException</code> (which is saved for later retrieval by the <code>getCause()</code> method);
   * may be null indicating
   * the cause is non-existent or unknown.
   * @since 1.6
   * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],
   * java.lang.Throwable)
   */
  public BatchUpdateException(String reason, int []updateCounts, Throwable cause) {
      this(reason, null, 0, updateCounts, cause);
  }

  /**
   * Constructs a <code>BatchUpdateException</code> object initialized with
   * a given <code>reason</code>, <code>SQLState</code>,<code>cause</code>, and
   * <code>updateCounts</code>. The vendor code is initialized to 0.
   *
   * @param reason a description of the exception
   * @param SQLState an XOPEN or SQL:2003 code identifying the exception
   * @param updateCounts an array of <code>int</code>, with each element
   * indicating the update count, <code>Statement.SUCCESS_NO_INFO</code> or
   * <code>Statement.EXECUTE_FAILED</code> for each SQL command in
   * the batch for JDBC drivers that continue processing
   * after a command failure; an update count or
   * <code>Statement.SUCCESS_NO_INFO</code> for each SQL command in the batch
   * prior to the failure for JDBC drivers that stop processing after a command
   * failure
   * <p>
   * <strong>Note:</strong> There is no validation of {@code updateCounts} for
   * overflow and because of this it is recommended that you use the constructor
   * {@code BatchUpdateException(String reason, String SQLState,
   * int vendorCode, long []updateCounts,Throwable cause) }.
   * </p>
   * @param cause the underlying reason for this <code>SQLException</code>
   * (which is saved for later retrieval by the <code>getCause()</code> method);
   * may be null indicating
   * the cause is non-existent or unknown.
   * @since 1.6
   * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],
   * java.lang.Throwable)
   */
  public BatchUpdateException(String reason, String SQLState,
          int []updateCounts, Throwable cause) {
      this(reason, SQLState, 0, updateCounts, cause);
  }

  /**
   * Constructs a <code>BatchUpdateException</code> object initialized with
   * a given <code>reason</code>, <code>SQLState</code>, <code>vendorCode</code>
   * <code>cause</code> and <code>updateCounts</code>.
   *
   * @param reason a description of the error
   * @param SQLState an XOPEN or SQL:2003 code identifying the exception
   * @param vendorCode an exception code used by a particular
   * database vendor
   * @param updateCounts an array of <code>int</code>, with each element
   *indicating the update count, <code>Statement.SUCCESS_NO_INFO</code> or
   * <code>Statement.EXECUTE_FAILED</code> for each SQL command in
   * the batch for JDBC drivers that continue processing
   * after a command failure; an update count or
   * <code>Statement.SUCCESS_NO_INFO</code> for each SQL command in the batch
   * prior to the failure for JDBC drivers that stop processing after a command
   * failure
   * <p>
   * <strong>Note:</strong> There is no validation of {@code updateCounts} for
   * overflow and because of this it is recommended that you use the constructor
   * {@code BatchUpdateException(String reason, String SQLState,
   * int vendorCode, long []updateCounts,Throwable cause) }.
   * </p>
   * @param cause the underlying reason for this <code>SQLException</code> (which is saved for later retrieval by the <code>getCause()</code> method);
   * may be null indicating
   * the cause is non-existent or unknown.
   * @since 1.6
   * @see #BatchUpdateException(java.lang.String, java.lang.String, int, long[],
   * java.lang.Throwable)
   */
  public BatchUpdateException(String reason, String SQLState, int vendorCode,
                                int []updateCounts,Throwable cause) {
        super(reason, SQLState, vendorCode, cause);
        this.updateCounts  = (updateCounts == null) ? null : Arrays.copyOf(updateCounts, updateCounts.length);
        this.longUpdateCounts = (updateCounts == null) ? null : copyUpdateCount(updateCounts);
  }

  /**
   * Retrieves the update count for each update statement in the batch
   * update that executed successfully before this exception occurred.
   * A driver that implements batch updates may or may not continue to
   * process the remaining commands in a batch when one of the commands
   * fails to execute properly. If the driver continues processing commands,
   * the array returned by this method will have as many elements as
   * there are commands in the batch; otherwise, it will contain an
   * update count for each command that executed successfully before
   * the <code>BatchUpdateException</code> was thrown.
   *<P>
   * The possible return values for this method were modified for
   * the Java 2 SDK, Standard Edition, version 1.3.  This was done to
   * accommodate the new option of continuing to process commands
   * in a batch update after a <code>BatchUpdateException</code> object
   * has been thrown.
   *
   * @return an array of <code>int</code> containing the update counts
   * for the updates that were executed successfully before this error
   * occurred.  Or, if the driver continues to process commands after an
   * error, one of the following for every command in the batch:
   * <OL>
   * <LI>an update count
   *  <LI><code>Statement.SUCCESS_NO_INFO</code> to indicate that the command
   *     executed successfully but the number of rows affected is unknown
   *  <LI><code>Statement.EXECUTE_FAILED</code> to indicate that the command
   *     failed to execute successfully
   * </OL>
   * @since 1.3
   * @see #getLargeUpdateCounts()
   */
  public int[] getUpdateCounts() {
      return (updateCounts == null) ? null : Arrays.copyOf(updateCounts, updateCounts.length);
  }

  /**
   * Constructs a <code>BatchUpdateException</code> object initialized with
   * a given <code>reason</code>, <code>SQLState</code>, <code>vendorCode</code>
   * <code>cause</code> and <code>updateCounts</code>.
   * <p>
   * This constructor should be used when the returned update count may exceed
   * {@link Integer#MAX_VALUE}.
   * <p>
   * @param reason a description of the error
   * @param SQLState an XOPEN or SQL:2003 code identifying the exception
   * @param vendorCode an exception code used by a particular
   * database vendor
   * @param updateCounts an array of <code>long</code>, with each element
   *indicating the update count, <code>Statement.SUCCESS_NO_INFO</code> or
   * <code>Statement.EXECUTE_FAILED</code> for each SQL command in
   * the batch for JDBC drivers that continue processing
   * after a command failure; an update count or
   * <code>Statement.SUCCESS_NO_INFO</code> for each SQL command in the batch
   * prior to the failure for JDBC drivers that stop processing after a command
   * failure
   * @param cause the underlying reason for this <code>SQLException</code>
   * (which is saved for later retrieval by the <code>getCause()</code> method);
   * may be null indicating the cause is non-existent or unknown.
   * @since 1.8
   */
  public BatchUpdateException(String reason, String SQLState, int vendorCode,
          long []updateCounts,Throwable cause) {
      super(reason, SQLState, vendorCode, cause);
      this.longUpdateCounts  = (updateCounts == null) ? null : Arrays.copyOf(updateCounts, updateCounts.length);
      this.updateCounts = (longUpdateCounts == null) ? null : copyUpdateCount(longUpdateCounts);
  }

  /**
   * Retrieves the update count for each update statement in the batch
   * update that executed successfully before this exception occurred.
   * A driver that implements batch updates may or may not continue to
   * process the remaining commands in a batch when one of the commands
   * fails to execute properly. If the driver continues processing commands,
   * the array returned by this method will have as many elements as
   * there are commands in the batch; otherwise, it will contain an
   * update count for each command that executed successfully before
   * the <code>BatchUpdateException</code> was thrown.
   * <p>
   * This method should be used when {@code Statement.executeLargeBatch} is
   * invoked and the returned update count may exceed {@link Integer#MAX_VALUE}.
   * <p>
   * @return an array of <code>long</code> containing the update counts
   * for the updates that were executed successfully before this error
   * occurred.  Or, if the driver continues to process commands after an
   * error, one of the following for every command in the batch:
   * <OL>
   * <LI>an update count
   *  <LI><code>Statement.SUCCESS_NO_INFO</code> to indicate that the command
   *     executed successfully but the number of rows affected is unknown
   *  <LI><code>Statement.EXECUTE_FAILED</code> to indicate that the command
   *     failed to execute successfully
   * </OL>
   * @since 1.8
   */
  public long[] getLargeUpdateCounts() {
      return (longUpdateCounts == null) ? null :
              Arrays.copyOf(longUpdateCounts, longUpdateCounts.length);
  }

  /**
   * The array that describes the outcome of a batch execution.
   * @serial
   * @since 1.2
   */
  private  int[] updateCounts;

  /*
   * Starting with Java SE 8, JDBC has added support for returning an update
   * count > Integer.MAX_VALUE.  Because of this the following changes were made
   * to BatchUpdateException:
   * <ul>
   * <li>Add field longUpdateCounts</li>
   * <li>Add Constructorr which takes long[] for update counts</li>
   * <li>Add getLargeUpdateCounts method</li>
   * </ul>
   * When any of the constructors are called, the int[] and long[] updateCount
   * fields are populated by copying the one array to each other.
   *
   * As the JDBC driver passes in the updateCounts, there has always been the
   * possiblity for overflow and BatchUpdateException does not need to account
   * for that, it simply copies the arrays.
   *
   * JDBC drivers should always use the constructor that specifies long[] and
   * JDBC application developers should call getLargeUpdateCounts.
   */

  /**
   * The array that describes the outcome of a batch execution.
   * @serial
   * @since 1.8
   */
  private  long[] longUpdateCounts;

  private static final long serialVersionUID = 5977529877145521757L;

  /*
   * Utility method to copy int[] updateCount to long[] updateCount
   */
  private static long[] copyUpdateCount(int[] uc) {
      long[] copy = new long[uc.length];
      for(int i= 0; i< uc.length; i++) {
          copy[i] = uc[i];
      }
      return copy;
  }

  /*
   * Utility method to copy long[] updateCount to int[] updateCount.
   * No checks for overflow will be done as it is expected a  user will call
   * getLargeUpdateCounts.
   */
  private static int[] copyUpdateCount(long[] uc) {
      int[] copy = new int[uc.length];
      for(int i= 0; i< uc.length; i++) {
          copy[i] = (int) uc[i];
      }
      return copy;
  }
    /**
     * readObject is called to restore the state of the
     * {@code BatchUpdateException} from a stream.
     */
    private void readObject(ObjectInputStream s)
            throws IOException, ClassNotFoundException {

       ObjectInputStream.GetField fields = s.readFields();
       int[] tmp = (int[])fields.get("updateCounts", null);
       long[] tmp2 = (long[])fields.get("longUpdateCounts", null);
       if(tmp != null && tmp2 != null && tmp.length != tmp2.length)
           throw new InvalidObjectException("update counts are not the expected size");
       if (tmp != null)
           updateCounts = tmp.clone();
       if (tmp2 != null)
           longUpdateCounts = tmp2.clone();
       if(updateCounts == null && longUpdateCounts != null)
           updateCounts = copyUpdateCount(longUpdateCounts);
       if(longUpdateCounts == null && updateCounts != null)
           longUpdateCounts = copyUpdateCount(updateCounts);

    }

    /**
     * writeObject is called to save the state of the {@code BatchUpdateException}
     * to a stream.
     */
    private void writeObject(ObjectOutputStream s)
            throws IOException, ClassNotFoundException {

        ObjectOutputStream.PutField fields = s.putFields();
        fields.put("updateCounts", updateCounts);
        fields.put("longUpdateCounts", longUpdateCounts);
        s.writeFields();
    }
}
