| /* | |
| * 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 | |
| * | |
| * 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 | |
| * 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 | |
| */ | |
| final 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> | |
| */ | |
| final transient 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 transient boolean inPrintStackTrace = false; | |
| /** Constructs a new <code>JDOException</code> without a detail message. */ | |
| public JDOException() { | |
| this.nested = null; | |
| this.failed = null; | |
| } | |
| /** | |
| * Constructs a new <code>JDOException</code> with the specified detail message. | |
| * | |
| * @param msg the detail message. | |
| */ | |
| public JDOException(String msg) { | |
| super(msg); | |
| this.nested = null; | |
| this.failed = null; | |
| } | |
| /** | |
| * 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; | |
| this.failed = null; | |
| } | |
| /** | |
| * 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}; | |
| this.failed = null; | |
| } | |
| /** | |
| * 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.nested = null; | |
| 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 | |
| */ | |
| @Override | |
| 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. | |
| */ | |
| @Override | |
| public synchronized 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>. | |
| */ | |
| @Override | |
| public synchronized String toString() { | |
| int len = nested == null ? 0 : nested.length; | |
| // calculate approximate size of the String to return | |
| StringBuilder sb = new StringBuilder(10 + 100 * len); | |
| sb.append(super.toString()); | |
| // include failed object information | |
| if (failed != null) { | |
| sb.append("\n").append(MSG.msg("MSG_FailedObject")); | |
| 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 specified print stream. Print | |
| * nested Throwables' stack trace as well. | |
| * | |
| * @param s <code>PrintStream</code> to use for output | |
| */ | |
| @Override | |
| @SuppressWarnings("java:S2445") // Blocks should be synchronized on "private final" fields | |
| public 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 | |
| */ | |
| @Override | |
| @SuppressWarnings("java:S2445") // Blocks should be synchronized on "private final" fields | |
| public 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; | |
| } | |
| private String failedToString() { | |
| 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); | |
| } | |
| } | |
| return failedToString; | |
| } | |
| } |