View Javadoc

    1   /*
    2    * Licensed to the Apache Software Foundation (ASF) under one or more
    3    * contributor license agreements.  See the NOTICE file distributed with
    4    * this work for additional information regarding copyright ownership.
    5    * The ASF licenses this file to You under the Apache License, Version 2.0
    6    * (the "License"); you may not use this file except in compliance with
    7    * the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
    10   *
    11   * Unless required by applicable law or agreed to in writing, software
    12   * distributed under the License is distributed on an "AS IS" BASIS,
    13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    14   * See the License for the specific language governing permissions and
    15   * limitations under the License.
    16   */
    17
    18  /*
    19   * JDOException.java
    20   *
    21   */
    22
    23  package javax.jdo;
    24
    25  import javax.jdo.spi.I18NHelper;
    26
    27  /** This is the root of all JDO Exceptions.  It contains an optional detail
    28   * message, an optional nested <code>Throwable</code> array and an optional failed object.
    29   * @author Craig Russell
    30   * @version 1.0.2
    31   */
    32  public class JDOException extends java.lang.RuntimeException {
    33
    34    /** This exception was generated because of an exception in the runtime library.
    35     * @serial the nested <code>Throwable</code> array
    36     */
    37    Throwable[] nested;
    38
    39    /** This exception may be the result of incorrect parameters supplied
    40     * to an API.  This is the object from which the user can determine
    41     * the cause of the problem.
    42     * @serial the failed <code>Object</code>
    43     */
    44    Object failed;
    45
    46      /** The Internationalization message helper.
    47       */
    48      private static I18NHelper msg = I18NHelper.getInstance ("javax.jdo.Bundle"); //NOI18N
    49
    50      /** Flag indicating whether printStackTrace is being executed.
    51       */
    52      private boolean inPrintStackTrace = false;
    53
    54    /**
    55     * Constructs a new <code>JDOException</code> without a detail message.
    56     */
    57    public JDOException() {
    58    }
    59
    60
    61    /**
    62     * Constructs a new <code>JDOException</code> with the specified detail message.
    63     * @param msg the detail message.
    64     */
    65    public JDOException(String msg) {
    66      super(msg);
    67    }
    68
    69    /** Constructs a new <code>JDOException</code> with the specified detail message
    70     * and nested <code>Throwable</code>s.
    71     * @param msg the detail message.
    72     * @param nested the nested <code>Throwable[]</code>.
    73     */
    74    public JDOException(String msg, Throwable[] nested) {
    75      super(msg);
    76      this.nested = nested;
    77    }
    78
    79    /** Constructs a new <code>JDOException</code> with the specified detail message
    80     * and nested <code>Throwable</code>.
    81     * @param msg the detail message.
    82     * @param nested the nested <code>Throwable</code>.
    83     */
    84    public JDOException(String msg, Throwable nested) {
    85      super(msg);
    86      this.nested = new Throwable[] {nested};
    87    }
    88
    89    /** Constructs a new <code>JDOException</code> with the specified detail message
    90     * and failed object.
    91     * @param msg the detail message.
    92     * @param failed the failed object.
    93     */
    94    public JDOException(String msg, Object failed) {
    95      super(msg);
    96      this.failed = failed;
    97    }
    98
    99    /** Constructs a new <code>JDOException</code> with the specified detail message,
    100    * nested <code>Throwable</code>s, and failed object.
    101    * @param msg the detail message.
    102    * @param nested the nested <code>Throwable[]</code>.
    103    * @param failed the failed object.
    104    */
    105   public JDOException(String msg, Throwable[] nested, Object failed) {
    106     super(msg);
    107     this.nested = nested;
    108     this.failed = failed;
    109   }
    110
    111   /** Constructs a new <code>JDOException</code> with the specified detail message,
    112    * nested <code>Throwable</code>, and failed object.
    113    * @param msg the detail message.
    114    * @param nested the nested <code>Throwable</code>.
    115    * @param failed the failed object.
    116    */
    117   public JDOException(String msg, Throwable nested, Object failed) {
    118     super(msg);
    119     this.nested = new Throwable[] {nested};
    120     this.failed = failed;
    121   }
    122
    123   /** The exception may include a failed object.
    124    * @return the failed object.
    125    */
    126   public Object getFailedObject() {
    127     return failed;
    128   }
    129
    130   /** The exception may have been caused by multiple exceptions in the runtime.
    131    * If multiple objects caused the problem, each failed object will have
    132    * its own <code>Exception</code>.
    133    * @return the nested Throwable array.
    134    */
    135   public Throwable[] getNestedExceptions() {
    136     return nested;
    137   }
    138
    139   /** Often there is only one nested exception, and this method returns it.
    140    * If there are more than one, then this method returns the first nested
    141    * exception. If there is no nested exception, then null is returned.
    142    * @return the first or only nested Throwable.
    143    * @since 1.0.1
    144    */
    145   public synchronized Throwable getCause() {
    146       // super.printStackTrace calls getCause to handle the cause.
    147       // Returning null prevents the superclass from handling the cause;
    148       // instead the local implementation of printStackTrace should
    149       // handle the cause. Otherwise, the cause is printed twice.
    150       if (nested == null || nested.length == 0 || inPrintStackTrace) {
    151           return null;
    152       } else {
    153           return nested[0];
    154       }
    155   }
    156
    157   /** JDK 1.4 includes a new chaining mechanism for Throwable, but since
    158    * JDO has its own "legacy" chaining mechanism, the "standard" mechanism
    159    * cannot be used. This method always throws a JDOFatalInternalException.
    160    * @param cause ignored.
    161    * @return never.
    162    */
    163   public Throwable initCause(Throwable cause) {
    164       throw new JDOFatalInternalException(msg.msg("ERR_CannotInitCause"));
    165   }
    166
    167   /** The <code>String</code> representation includes the name of the class,
    168    * the descriptive comment (if any),
    169    * the <code>String</code> representation of the failed <code>Object</code> (if any),
    170    * and the <code>String</code> representation of the nested <code>Throwable</code>s (if any).
    171    * @return the <code>String</code>.
    172    */
    173   public synchronized String toString() {
    174     int len = nested==null?0:nested.length;
    175     // calculate approximate size of the String to return
    176     StringBuffer sb = new StringBuffer (10 + 100 * len);
    177     sb.append (super.toString());
    178     // include failed object information
    179     if (failed != null) {
    180         sb.append ("\n").append (msg.msg ("MSG_FailedObject"));
    181       String failedToString = null;
    182       try {
    183           failedToString = failed.toString();
    184       } catch (Exception ex) {
    185           // include the information from the exception thrown by failed.toString
    186           Object objectId = JDOHelper.getObjectId(failed);
    187           if (objectId == null) {
    188               failedToString = msg.msg("MSG_ExceptionGettingFailedToString", //NOI18N
    189                                        exceptionToString(ex));
    190           }
    191           else {
    192               // include the ObjectId information
    193               String objectIdToString = null;
    194               try {
    195                   objectIdToString = objectId.toString();
    196               }
    197               catch (Exception ex2) {
    198                   objectIdToString = exceptionToString(ex2);
    199               }
    200               failedToString = msg.msg("MSG_ExceptionGettingFailedToStringObjectId", //NOI18N
    201                                        exceptionToString(ex), objectIdToString);
    202           }
    203       }
    204       sb.append (failedToString);
    205     }
    206     // include nested Throwable information, but only if not called by
    207     // printStackTrace; the stacktrace will include the cause anyway.
    208     if (len > 0 && !inPrintStackTrace) {
    209       sb.append ("\n").append (msg.msg ("MSG_NestedThrowables")).append ("\n");
    210       Throwable exception = nested[0];
    211       sb.append (exception==null?"null":exception.toString()); //NOI18N
    212       for (int i=1; i<len; ++i) {
    213         sb.append ("\n"); //NOI18N
    214         exception = nested[i];
    215       sb.append (exception==null?"null":exception.toString()); //NOI18N
    216       }
    217     }
    218     return sb.toString();
    219   }
    220
    221     /**
    222      * Prints this <code>JDOException</code> and its backtrace to the
    223      * standard error output.
    224      * Print nested Throwables' stack trace as well.
    225      */
    226     public void printStackTrace() {
    227         printStackTrace (System.err);
    228     }
    229
    230     /**
    231      * Prints this <code>JDOException</code> and its backtrace to the
    232      * specified print stream.
    233      * Print nested Throwables' stack trace as well.
    234      * @param s <code>PrintStream</code> to use for output
    235      */
    236     public synchronized void printStackTrace(java.io.PrintStream s) {
    237     int len = nested==null?0:nested.length;
    238         synchronized (s) {
    239             inPrintStackTrace = true;
    240             super.printStackTrace(s);
    241             if (len > 0) {
    242                 s.println (msg.msg ("MSG_NestedThrowablesStackTrace"));
    243                 for (int i=0; i<len; ++i) {
    244                     Throwable exception = nested[i];
    245                     if (exception != null) {
    246                         exception.printStackTrace(s);
    247                     }
    248                 }
    249             }
    250             inPrintStackTrace = false;
    251         }
    252     }
    253
    254     /**
    255      * Prints this <code>JDOException</code> and its backtrace to the specified
    256      * print writer.
    257      * Print nested Throwables' stack trace as well.
    258      * @param s <code>PrintWriter</code> to use for output
    259      */
    260     public synchronized void printStackTrace(java.io.PrintWriter s) {
    261     int len = nested==null?0:nested.length;
    262         synchronized (s) {
    263             inPrintStackTrace = true;
    264             super.printStackTrace(s);
    265             if (len > 0) {
    266                 s.println (msg.msg ("MSG_NestedThrowablesStackTrace"));
    267                 for (int i=0; i<len; ++i) {
    268                     Throwable exception = nested[i];
    269                     if (exception != null) {
    270                         exception.printStackTrace(s);
    271                     }
    272                 }
    273             }
    274             inPrintStackTrace = false;
    275         }
    276     }
    277
    278     /**
    279      * Helper method returning a short description of the exception passed
    280      * as an argument. The returned string has the format defined by
    281      * Throwable.toString. If the exception has a non-null detail message
    282      * string, then it returns the name of exception class concatenated
    283      * with ": " concatenated with the detailed message. Otherwise it
    284      * returns the name of exception class.
    285      * @param ex the exception to be represented.
    286      * @return a string representation of the exception passed as an argument.
    287      */
    288     private static String exceptionToString(Exception ex)
    289     {
    290         if (ex == null) return null;
    291         String s = ex.getClass().getName();
    292         String message = ex.getMessage();
    293         return (message != null) ? (s + ": " + message) : s;
    294     }
    295 }
    296