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}