001/* A base class for runtime exceptions. 002 003 Copyright (c) 1997-2014 The Regents of the University of California. 004 All rights reserved. 005 Permission is hereby granted, without written agreement and without 006 license or royalty fees, to use, copy, modify, and distribute this 007 software and its documentation for any purpose, provided that the above 008 copyright notice and the following two paragraphs appear in all copies 009 of this software. 010 011 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY 012 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 013 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF 014 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF 015 SUCH DAMAGE. 016 017 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES, 018 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 019 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE 020 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF 021 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, 022 ENHANCEMENTS, OR MODIFICATIONS. 023 024 PT_COPYRIGHT_VERSION_2 025 COPYRIGHTENDKEY 026 027 */ 028package ptolemy.kernel.util; 029 030import java.io.PrintStream; 031import java.io.PrintWriter; 032import java.util.Collection; 033import java.util.LinkedList; 034 035/////////////////////////////////////////////////////////////////// 036//// KernelRuntimeException 037 038/** 039 Base class for runtime exceptions. This class extends the basic 040 Java RuntimeException with a constructor that can take a Nameable as 041 an argument. 042 043 <p>This exception supports all the constructor forms of KernelException, 044 but is implemented as a RuntimeException so that it does not have to 045 be declared. 046 047 <p>The cause argument to the constructor is a Throwable that 048 caused the exception. The cause argument is used when code throws 049 an exception and we want to rethrow the exception but print 050 the stacktrace where the first exception occurred. This is called 051 exception chaining. 052 053 <p>JDK1.4 and later support exception chaining. We are implementing 054 a version of exception chaining here ourselves so that we can use JVMs 055 earlier than JDK1.4. See the {@link KernelException} 056 documentation for differences between our exception chaining 057 implementation and the JDK1.4 implementation. 058 059 @author Edward A. Lee, Christopher Hylands 060 @version $Id$ 061 @since Ptolemy II 1.0 062 @Pt.ProposedRating Green (cxh) 063 @Pt.AcceptedRating Green (cxh) 064 */ 065@SuppressWarnings("serial") 066public class KernelRuntimeException extends RuntimeException { 067 /** Construct an exception with no specific detail message. */ 068 public KernelRuntimeException() { 069 this(null, null, null, null); 070 } 071 072 /** Construct an exception with only a detail message. 073 * @param detail The message. 074 */ 075 public KernelRuntimeException(String detail) { 076 this(null, null, null, detail); 077 } 078 079 /** Construct an exception with a cause and a detail message. 080 * @param cause The cause of this exception. 081 * @param detail The message. 082 */ 083 public KernelRuntimeException(Throwable cause, String detail) { 084 this(null, null, cause, detail); 085 } 086 087 /** Construct an exception with a detail message that includes the 088 * name of the first argument and the value of the second argument 089 * string. 090 * @param object The object. 091 * @param detail The message. 092 */ 093 public KernelRuntimeException(Nameable object, String detail) { 094 this(object, null, null, detail); 095 } 096 097 /** Construct an exception with a detail message that includes the 098 * names of the first two arguments plus the value of the fourth 099 * argument string. If the cause argument is non-null, then the 100 * message of this exception will include the message of the 101 * cause argument. The stack trace of the cause argument is used 102 * when we print the stack trace of this exception. If one or 103 * more of the parameters are null, then the detail message is 104 * adjusted accordingly. 105 * 106 * @param object1 The first object. 107 * @param object2 The second object. 108 * @param cause The cause of this exception. 109 * @param detail The message. 110 */ 111 public KernelRuntimeException(Nameable object1, Nameable object2, 112 Throwable cause, String detail) { 113 _causes = new LinkedList(); 114 _causes.add(object1); 115 _causes.add(object2); 116 _setMessage(KernelException.generateMessage(object1, object2, cause, 117 detail)); 118 _setCause(cause); 119 } 120 121 /** Construct an exception with a detail message that includes the 122 * names of a collection of Nameable objects plus the argument string. 123 * @param objects The Collection of Nameable objects 124 * @param cause The cause of this exception. 125 * @param detail The message. 126 */ 127 public KernelRuntimeException(Collection objects, Throwable cause, 128 String detail) { 129 _causes = objects; 130 _setMessage(KernelException.generateMessage(objects, cause, detail)); 131 _setCause(cause); 132 } 133 134 /////////////////////////////////////////////////////////////////// 135 //// public methods //// 136 137 /** Get the cause of this exception. 138 * @return The cause that was passed in as an argument to the 139 * constructor, or null if no cause was specified. 140 */ 141 @Override 142 public Throwable getCause() { 143 return _cause; 144 } 145 146 /** Get the message of this exception. The message may have been 147 * adjusted if one of the constructor arguments was null, so the 148 * value returned by this method may not necessarily equal the 149 * value of the detail argument of of the constructor. 150 * 151 * @return The error message. 152 */ 153 @Override 154 public String getMessage() { 155 return _message; 156 } 157 158 /** Get the first Nameable, if any, that was passed as an argument. 159 * @return The first Nameable that was passed in. If no Nameable 160 * was passed in, then return null. 161 */ 162 public Collection getNameables() { 163 return _causes; 164 } 165 166 /** Print a stack trace message to stderr including 167 * this exception, its stack trace and if the cause 168 * exception is known, print the cause exception and the 169 * cause stacktrace. 170 */ 171 @Override 172 public void printStackTrace() { 173 // Note that chained exceptions are new JDK1.4. 174 // We are implement them ourselves here so that we can 175 // use JVMs earlier than JDK1.4. The JDK1.4 Throwable.getCause() 176 // documentation states that it is not necessary to overwrite 177 // printStackTrace, but this is only the case when we have a JDK1.4 178 // JVM. 179 // We could try to factor out the printStackTrace() methods 180 // and call package friendly methods in KernelException, 181 // but these methods are so short, so why bother. 182 printStackTrace(new PrintWriter(System.err)); 183 } 184 185 /** Print a stack trace message to printStream including this 186 * exception, its stack trace and if the cause exception is 187 * known, print the cause exception and the cause stacktrace. 188 * 189 * @param printStream The PrintStream to write to. 190 */ 191 @Override 192 public void printStackTrace(PrintStream printStream) { 193 printStackTrace(new PrintWriter(printStream)); 194 } 195 196 /** Print a stack trace message to printWriter including this 197 * exception, its stack trace and if the cause exception is 198 * known, print the cause exception and the cause stacktrace. 199 * 200 * @param printWriter The PrintWriter to write to. 201 */ 202 @Override 203 public void printStackTrace(PrintWriter printWriter) { 204 super.printStackTrace(printWriter); 205 206 if (_cause != null) { 207 printWriter.print("Caused by: "); 208 _cause.printStackTrace(printWriter); 209 } 210 211 printWriter.flush(); 212 } 213 214 /////////////////////////////////////////////////////////////////// 215 //// protected methods //// 216 217 /** Set the cause to the specified throwable. 218 * @param cause The cause of this exception 219 */ 220 protected void _setCause(Throwable cause) { 221 _cause = cause; 222 } 223 224 /** Sets the error message to the specified string. 225 * If the message argument is null, then the error 226 * message is set to the empty string. 227 * @param message The message. 228 */ 229 protected void _setMessage(String message) { 230 // See KernelException._setMessage() for an explanation 231 // about why we need this message instead of calling super(). 232 if (message == null) { 233 _message = ""; 234 } else { 235 _message = message; 236 } 237 } 238 239 /////////////////////////////////////////////////////////////////// 240 //// private variables //// 241 242 // The cause of this exception. 243 private Throwable _cause; 244 245 // The Nameable objects that caused the exception. 246 private Collection _causes; 247 248 // The detail message. 249 private String _message; 250}