/* Base class for exceptions that report the names of Nameable objects.
Copyright (c) 1997-2014 The Regents of the University of California.
All rights reserved.
Permission is hereby granted, without written agreement and without
license or royalty fees, to use, copy, modify, and distribute this
software and its documentation for any purpose, provided that the above
copyright notice and the following two paragraphs appear in all copies
of this software.
IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
ENHANCEMENTS, OR MODIFICATIONS.
PT_COPYRIGHT_VERSION_2
COPYRIGHTENDKEY
*/
package ptolemy.kernel.util;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.util.Collection;
import java.util.Iterator;
///////////////////////////////////////////////////////////////////
//// KernelException
/**
Base class for Ptolemy exceptions. This class extends the basic
JavaException with a constructor that can take a Nameable as
an argument.
(Note however, that it is better to use a class derived from
KernelException than it is to throw a KernelException directly.)
JDK1.4 and later support exception chaining. We are implementing a
version of exception chaining here ourselves so that we can use JVMs
earlier than JDK1.4.
In this implementation, we have the following differences from
the JDK1.4 exception chaining implementation:
@see KernelRuntimeException
@author John S. Davis, II, Edward A. Lee, Christopher Hylands
@version $Id: KernelException.java 70402 2014-10-23 00:52:20Z cxh $
@since Ptolemy II 0.2
@Pt.ProposedRating Green (cxh)
@Pt.AcceptedRating Green (cxh)
*/
@SuppressWarnings("serial")
public class KernelException extends Exception {
/** Construct an exception with a no specific detail message. */
public KernelException() {
this(null, null, null, null);
}
/** Construct an exception with a detail message that includes the
* names of the first two arguments plus the third argument
* string. If one or more of the parameters are null, then the
* message of the exception is adjusted accordingly.
*
* @param object1 The first object.
* @param object2 The second object.
* @param detail The message.
*/
public KernelException(Nameable object1, Nameable object2, String detail) {
this(object1, object2, null, detail);
}
/** Construct an exception with a detail message that includes the
* names of the first two arguments plus the third argument
* string. If the cause argument is non-null, then the message
* of this exception will include the message of the cause
* argument. The stack trace of the cause argument is used when
* we print the stack trace of this exception. If one or more of
* the parameters are null, then the message of the exception is
* adjusted accordingly.
*
* @param object1 The first object.
* @param object2 The second object.
* @param cause The cause of this exception.
* @param detail The message.
*/
public KernelException(Nameable object1, Nameable object2, Throwable cause,
String detail) {
_object1 = object1;
_object2 = object2;
_setMessage(generateMessage(object1, object2, cause, detail));
_setCause(cause);
}
///////////////////////////////////////////////////////////////////
//// public methods ////
/** Generate a properly formatted exception message.
* If one or more of the parameters are null, then the message
* of the exception is adjusted accordingly. In particular, if
* the first two arguments are non-null, then the exception
* message may include the full names of the first two arguments.
*
*
This method is public static so that both
* KernelException and KernelRuntimeException and any classes
* derived from those classes can use it.
* KernelRuntimeException must extend RuntimeException so that
* the java compiler will allow methods that throw
* KernelRuntimeException to not declare that they throw it, and
* KernelException cannot extend RuntimeException for the same
* reason.
*
* @param object1 The first object.
* @param object2 The second object.
* @param cause The cause of this exception.
* @param detail The detail message.
* @return A properly formatted message
*/
public static String generateMessage(Nameable object1, Nameable object2,
Throwable cause, String detail) {
String object1String = getFullName(object1);
String object2String = getFullName(object2);
String whereString = null;
// KernelException.getFullName() returns the empty string if
// argument was null, and it returns "" if the
// argument was the empty string, so if the return value of
// getFullName() is the empty string, then the argument was
// null, so we adjust accordingly.
if (!object1String.equals("")) {
if (!object2String.equals("")) {
whereString = " in " + object1String + " and " + object2String;
} else {
whereString = " in " + object1String;
}
} else {
if (!object2String.equals("")) {
whereString = " in " + object2String;
}
}
return generateMessage(whereString, cause, detail);
}
/** Generate a properly formatted exception message where the
* origin of the error is a collection.
*
This method is public static so that both
* KernelException and KernelRuntimeException and any classes
* derived from those classes can use it.
* KernelRuntimeException must extend RuntimeException so that
* the java compiler will allow methods that throw
* KernelRuntimeException to not declare that they throw it, and
* KernelException cannot extend RuntimeException for the same
* reason.
* @param objects The where objects.
* @param cause The cause of this exception.
* @param detail The detail message.
* @return A properly formatted message
*/
public static String generateMessage(Collection objects, Throwable cause,
String detail) {
StringBuffer prefixBuffer = new StringBuffer(" in ");
Iterator objectIterator = objects.iterator();
while (objectIterator.hasNext()) {
Object object = objectIterator.next();
if (object instanceof Nameable) {
prefixBuffer.append(KernelException
.getFullName((Nameable) object));
} else {
prefixBuffer.append("