/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
<<<<<<< Updated upstream
 *
 *     https://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
=======
 * 
 *     https://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
>>>>>>> Stashed changes
 * limitations under the License.
 */

/*
 * JDOException.java
 *
 */

package javax.jdo;

import javax.jdo.spi.I18NHelper;

/**
 * This is the root of all JDO Exceptions. It contains an optional detail message, an optional
 * nested <code>Throwable</code> array and an optional failed object.
 *
 * @author Craig Russell
 * @version 1.0.2
 */
public class JDOException extends java.lang.RuntimeException {

  private static final long serialVersionUID = 1950979275859696534L;

  /**
   * This exception was generated because of an exception in the runtime library.
   *
   * @serial the nested <code>Throwable</code> array
   */
  Throwable[] nested;

  /**
   * This exception may be the result of incorrect parameters supplied to an API. This is the object
   * from which the user can determine the cause of the problem.
   *
   * @serial the failed <code>Object</code>
   */
  Object failed;

  /** The Internationalization message helper. */
  private static final I18NHelper MSG = I18NHelper.getInstance("javax.jdo.Bundle"); // NOI18N

  /** Flag indicating whether printStackTrace is being executed. */
  private boolean inPrintStackTrace = false;

  /** Constructs a new <code>JDOException</code> without a detail message. */
  public JDOException() {}

  /**
   * Constructs a new <code>JDOException</code> with the specified detail message.
   *
   * @param msg the detail message.
   */
  public JDOException(String msg) {
    super(msg);
  }

  /**
   * Constructs a new <code>JDOException</code> with the specified detail message and nested <code>
   * Throwable</code>s.
   *
   * @param msg the detail message.
   * @param nested the nested <code>Throwable[]</code>.
   */
  public JDOException(String msg, Throwable[] nested) {
    super(msg);
    this.nested = nested;
  }

  /**
   * Constructs a new <code>JDOException</code> with the specified detail message and nested <code>
   * Throwable</code>.
   *
   * @param msg the detail message.
   * @param nested the nested <code>Throwable</code>.
   */
  public JDOException(String msg, Throwable nested) {
    super(msg);
    this.nested = new Throwable[] {nested};
  }

  /**
   * Constructs a new <code>JDOException</code> with the specified detail message and failed object.
   *
   * @param msg the detail message.
   * @param failed the failed object.
   */
  public JDOException(String msg, Object failed) {
    super(msg);
    this.failed = failed;
  }

  /**
   * Constructs a new <code>JDOException</code> with the specified detail message, nested <code>
   * Throwable</code>s, and failed object.
   *
   * @param msg the detail message.
   * @param nested the nested <code>Throwable[]</code>.
   * @param failed the failed object.
   */
  public JDOException(String msg, Throwable[] nested, Object failed) {
    super(msg);
    this.nested = nested;
    this.failed = failed;
  }

  /**
   * Constructs a new <code>JDOException</code> with the specified detail message, nested <code>
   * Throwable</code>, and failed object.
   *
   * @param msg the detail message.
   * @param nested the nested <code>Throwable</code>.
   * @param failed the failed object.
   */
  public JDOException(String msg, Throwable nested, Object failed) {
    super(msg);
    this.nested = new Throwable[] {nested};
    this.failed = failed;
  }

  /**
   * The exception may include a failed object.
   *
   * @return the failed object.
   */
  public Object getFailedObject() {
    return failed;
  }

  /**
   * The exception may have been caused by multiple exceptions in the runtime. If multiple objects
   * caused the problem, each failed object will have its own <code>Exception</code>.
   *
   * @return the nested Throwable array.
   */
  public Throwable[] getNestedExceptions() {
    return nested;
  }

  /**
   * Often there is only one nested exception, and this method returns it. If there are more than
   * one, then this method returns the first nested exception. If there is no nested exception, then
   * null is returned.
   *
   * @return the first or only nested Throwable.
   * @since 1.0.1
   */
  public synchronized Throwable getCause() {
    // super.printStackTrace calls getCause to handle the cause.
    // Returning null prevents the superclass from handling the cause;
    // instead the local implementation of printStackTrace should
    // handle the cause. Otherwise, the cause is printed twice.
    if (nested == null || nested.length == 0 || inPrintStackTrace) {
      return null;
    } else {
      return nested[0];
    }
  }

  /**
   * JDK 1.4 includes a new chaining mechanism for Throwable, but since JDO has its own "legacy"
   * chaining mechanism, the "standard" mechanism cannot be used. This method always throws a
   * JDOFatalInternalException.
   *
   * @param cause ignored.
   * @return never.
   */
  public Throwable initCause(Throwable cause) {
    throw new JDOFatalInternalException(MSG.msg("ERR_CannotInitCause"));
  }

  /**
   * The <code>String</code> representation includes the name of the class, the descriptive comment
   * (if any), the <code>String</code> representation of the failed <code>Object</code> (if any),
   * and the <code>String</code> representation of the nested <code>Throwable</code>s (if any).
   *
   * @return the <code>String</code>.
   */
  public synchronized String toString() {
    int len = nested == null ? 0 : nested.length;
    // calculate approximate size of the String to return
    StringBuffer sb = new StringBuffer(10 + 100 * len);
    sb.append(super.toString());
    // include failed object information
    if (failed != null) {
      sb.append("\n").append(MSG.msg("MSG_FailedObject"));
      String failedToString = null;
      try {
        failedToString = failed.toString();
      } catch (Exception ex) {
        // include the information from the exception thrown by failed.toString
        Object objectId = JDOHelper.getObjectId(failed);
        if (objectId == null) {
          failedToString =
              MSG.msg(
                  "MSG_ExceptionGettingFailedToString", // NOI18N
                  exceptionToString(ex));
        } else {
          // include the ObjectId information
          String objectIdToString = null;
          try {
            objectIdToString = objectId.toString();
          } catch (Exception ex2) {
            objectIdToString = exceptionToString(ex2);
          }
          failedToString =
              MSG.msg(
                  "MSG_ExceptionGettingFailedToStringObjectId", // NOI18N
                  exceptionToString(ex),
                  objectIdToString);
        }
      }
      sb.append(failedToString);
    }
    // include nested Throwable information, but only if not called by
    // printStackTrace; the stacktrace will include the cause anyway.
    if (len > 0 && !inPrintStackTrace) {
      sb.append("\n").append(MSG.msg("MSG_NestedThrowables")).append("\n");
      Throwable exception = nested[0];
      sb.append(exception == null ? "null" : exception.toString()); // NOI18N
      for (int i = 1; i < len; ++i) {
        sb.append("\n"); // NOI18N
        exception = nested[i];
        sb.append(exception == null ? "null" : exception.toString()); // NOI18N
      }
    }
    return sb.toString();
  }

  /**
   * Prints this <code>JDOException</code> and its backtrace to the standard error output. Print
   * nested Throwables' stack trace as well.
   */
  public void printStackTrace() {
    printStackTrace(System.err);
  }

  /**
   * Prints this <code>JDOException</code> and its backtrace to the specified print stream. Print
   * nested Throwables' stack trace as well.
   *
   * @param s <code>PrintStream</code> to use for output
   */
  public synchronized void printStackTrace(java.io.PrintStream s) {
    int len = nested == null ? 0 : nested.length;
    synchronized (s) {
      inPrintStackTrace = true;
      super.printStackTrace(s);
      if (len > 0) {
        s.println(MSG.msg("MSG_NestedThrowablesStackTrace"));
        for (int i = 0; i < len; ++i) {
          Throwable exception = nested[i];
          if (exception != null) {
            exception.printStackTrace(s);
          }
        }
      }
      inPrintStackTrace = false;
    }
  }

  /**
   * Prints this <code>JDOException</code> and its backtrace to the specified print writer. Print
   * nested Throwables' stack trace as well.
   *
   * @param s <code>PrintWriter</code> to use for output
   */
  public synchronized void printStackTrace(java.io.PrintWriter s) {
    int len = nested == null ? 0 : nested.length;
    synchronized (s) {
      inPrintStackTrace = true;
      super.printStackTrace(s);
      if (len > 0) {
        s.println(MSG.msg("MSG_NestedThrowablesStackTrace"));
        for (int i = 0; i < len; ++i) {
          Throwable exception = nested[i];
          if (exception != null) {
            exception.printStackTrace(s);
          }
        }
      }
      inPrintStackTrace = false;
    }
  }

  /**
   * Helper method returning a short description of the exception passed as an argument. The
   * returned string has the format defined by Throwable.toString. If the exception has a non-null
   * detail message string, then it returns the name of exception class concatenated with ": "
   * concatenated with the detailed message. Otherwise it returns the name of exception class.
   *
   * @param ex the exception to be represented.
   * @return a string representation of the exception passed as an argument.
   */
  private static String exceptionToString(Exception ex) {
    if (ex == null) return null;
    String s = ex.getClass().getName();
    String message = ex.getMessage();
    return (message != null) ? (s + ": " + message) : s;
  }
}
