package com.waldura.util; import java.io.PrintWriter; import java.io.StringWriter; /** * This exception allows for error chaining. It embeds ("nests") another * exception, assigned at construction time. The nested exception is used * for the {@link #getMessage() error message} generated by this class, * as well as its {@link #getChainedStackTrace() stack trace}. *

* Use this class to promote encapsulation and loose coupling between * sub-systems. * IMO, every logical subsystem should have very few "exit points" for propagating * errors, and these points should re-type errors to their own type * before propagating them. * Doing so by creating a new exception and throwing it results in lost * information; the ChainingException class lets you propagate * the error as a new type without losing the original error. *

* This class is declared abstract; while it doesn't actually * have any abstract methods, * it is meant to be extended and used as base for a custom exception. * For example, a database management subsystem could * throw its own DatabaseException and chain to the actual * SQLException that generated the error. * The DatabaseException class could be written like so: *

 *	class DatabaseException extends ChainingException
 *  {
 *		public DatabaseException() {}
 *		public DatabaseException(String mesg) { super(mesg); }
 *		public DatabaseException(SQLException chainedError) { super(chainedError); }
 *		public DatabaseException(String mesg, SQLException chainedError) { super(mesg, chainedError); }
 *	}
 * 
*

* Note 1 *

* This class, contrarily to the basic {@link java.lang.Exception Exception} * class, is fully serializable. The nested exception's stack trace is * saved and can be retrieved by remote users of this class. *

* Note 2 *

* This class has been integrated in JDK 1.4. * * @author Renaud Waldura 7/11/00 * @author Quenio dos Santos 10/01/01 */ public abstract class ChainingException extends Exception { /** * The error that originally caused this Exception object to be thrown. */ private Throwable chainedException; /** * Instantiates this exception with no message and no chained exception. */ public ChainingException() { this(null, null); } /** * Instantiates this exception with a message, but no chained exception. * * @param message The message that explains what is this exception. */ public ChainingException(String message) { this(message, null); } /** * Instantiates this exception with a chained exception, but no message. * * @param nestedException the error that originally caused * this Exception object to be thrown. */ public ChainingException(Throwable chainedException) { this(null, chainedException); } /** * Instantiates this exception with a message and a chained exception. * * @param message The message that explains what is this exception. * @param nestedException The error that originally caused * this Exception object to be thrown. */ public ChainingException(String message, Throwable chainedException) { super(message); this.chainedException = chainedException; } /** * @return the Exception object that originally caused this * Exception object to be thrown. */ public Throwable getChainedException() { return chainedException; } /** * Returns the stack trace of all chained exceptions, showing the stack * trace of this exception (which is the outermost exception) first and * the innermost stack trace last. */ public String getChainedStackTrace() { StringWriter stringWriter = new StringWriter(); PrintWriter printWriter = new PrintWriter(stringWriter); super.printStackTrace(printWriter); if (chainedException != null) { printWriter.println("<><><><><>< chained to ><><><><><>"); chainedException.printStackTrace(printWriter); } return stringWriter.toString(); } /** * Print this Throwable and its stack trace to the standard * error stream. */ public void printStackTrace() { printStackTrace(System.err); } /** * Prints this exception and its backtrace to the specified * print stream. */ public void printStackTrace(java.io.PrintStream s) { s.println(getChainedStackTrace()); } /** * Prints this exception and its backtrace to the specified * print writer. */ public void printStackTrace(java.io.PrintWriter s) { s.println(getChainedStackTrace()); } /** * Overrides {@link Exception#getMessage() Exception.getMessage} to * return a concatenation of all of the chained exceptions' messages. */ public String getMessage() { String superMesg = super.getMessage(); // default if (chainedException == null) return superMesg; StringBuffer mesg = new StringBuffer(); // get the chained exception's message String chainedMesg = chainedException.getMessage(); if (superMesg != null) mesg.append(superMesg).append(": ").append(chainedMesg); else mesg.append(chainedMesg); return mesg.toString(); } }