001: /*
002: * This software is released under a licence similar to the Apache Software Licence.
003: * See org.logicalcobwebs.proxool.package.html for details.
004: * The latest version is available at http://proxool.sourceforge.net
005: */
006: package org.logicalcobwebs.proxool;
007:
008: import java.io.PrintStream;
009: import java.io.PrintWriter;
010:
011: /**
012: * Proxool exception class that emulates the behaviour of the new cause
013: * facility in jdk 1.4. It is also known as the <i>chained
014: * exception</i> facility, as the cause can, itself, have a cause, and so on,
015: * leading to a "chain" of exceptions, each caused by another.
016: *
017: * <p>A cause can be associated with a throwable in two ways: via a
018: * constructor that takes the cause as an argument, or via the
019: * {@link #initCause(Throwable)} method. New throwable classes that
020: * wish to allow causes to be associated with them should provide constructors
021: * that take a cause and delegate (perhaps indirectly) to one of the
022: * <tt>Throwable</tt> constructors that takes a cause.
023: *
024: * @version $Revision: 1.2 $, $Date: 2003/03/03 11:11:58 $
025: * @author Christian Nedregaard (christian_nedregaard@email.com)
026: * @author $Author: billhorsman $ (current maintainer)
027: * @since Proxool 0.6
028: */
029: public class ProxoolException extends Exception {
030: /**
031: * The throwable that caused this ProxoolException to get thrown, or null if this
032: * ProxoolException was not caused by another throwable, or if the causative
033: * throwable is unknown.
034: */
035: private Throwable cause = this ;
036:
037: /**
038: * Constructs a new instance with <code>null</code> as its detail message.
039: * The cause is not initialized, and may subsequently be initialized by a
040: * call to {@link #initCause}.
041: */
042: public ProxoolException() {
043: super ();
044: }
045:
046: /**
047: * Constructs a new instance with the specified detail message. The
048: * cause is not initialized, and may subsequently be initialized by
049: * a call to {@link #initCause}.
050: *
051: * @param message the detail message. The detail message is saved for
052: * later retrieval by the {@link #getMessage()} method.
053: */
054: public ProxoolException(String message) {
055: super (message);
056: }
057:
058: /**
059: * Constructs a new instance with the specified detail message and cause.
060: *
061: * <p>Note that the detail message associated with
062: * <code>cause</code> is <i>not</i> automatically incorporated in
063: * this throwable's detail message.
064: *
065: * @param message the detail message (which is saved for later retrieval
066: * by the {@link #getMessage()} method).
067: * @param cause the cause (which is saved for later retrieval by the
068: * {@link #getCause()} method). (A <tt>null</tt> value is
069: * permitted, and indicates that the cause is nonexistent or
070: * unknown.)
071: */
072: public ProxoolException(String message, Throwable cause) {
073: this (message);
074: this .cause = cause;
075: }
076:
077: /**
078: * Constructs a new throwable with the specified cause and a detail
079: * message of <tt>(cause==null ? null : cause.toString())</tt> (which
080: * typically contains the class and detail message of <tt>cause</tt>).
081: * This constructor is useful for throwables that are little more than
082: * wrappers for other throwables.
083: *
084: * @param cause the cause (which is saved for later retrieval by the
085: * {@link #getCause()} method). (A <tt>null</tt> value is
086: * permitted, and indicates that the cause is nonexistent or
087: * unknown.)
088: */
089: public ProxoolException(Throwable cause) {
090: this (cause == null ? null : cause.toString());
091: this .cause = cause;
092: }
093:
094: /**
095: * Returns the cause of this exception or <code>null</code> if the
096: * cause is nonexistent or unknown. (The cause is the throwable that
097: * caused this exception to get thrown.)
098: *
099: * <p>This implementation returns the cause that was supplied via one of
100: * the constructors requiring a <tt>Throwable</tt>, or that was set after
101: * creation with the {@link #initCause(Throwable)} method.
102: *
103: * @return the cause of this throwable or <code>null</code> if the
104: * cause is nonexistent or unknown.
105: */
106: public Throwable getCause() {
107: return (cause == this ? null : cause);
108: }
109:
110: /**
111: * Initializes the <i>cause</i> of this exception to the specified value.
112: * (The cause is the throwable that caused this exception to get thrown.)
113: *
114: * <p>This method can be called at most once. It is generally called from
115: * within the constructor, or immediately after creating the
116: * throwable. If this throwable was created
117: * with {@link #ProxoolException(Throwable)} or
118: * {@link #ProxoolException(String,Throwable)}, this method cannot be called
119: * even once.
120: *
121: * @param cause the cause (which is saved for later retrieval by the
122: * {@link #getCause()} method). (A <tt>null</tt> value is
123: * permitted, and indicates that the cause is nonexistent or
124: * unknown.)
125: * @return a reference to this <code>ProxoolException</code> instance.
126: */
127: public synchronized Throwable initCause(Throwable cause) {
128: if (this .cause != this ) {
129: throw new IllegalStateException("Can't overwrite cause");
130: }
131: if (cause == this ) {
132: throw new IllegalArgumentException(
133: "Self-causation not permitted");
134: }
135: this .cause = cause;
136: return this ;
137: }
138:
139: /**
140: * Prints this ProxoolException and its backtrace to the
141: * standard error stream.
142: *
143: * The backtrace for a ProxoolException with an initialized, non-null cause
144: * should generally include the backtrace for the cause.
145: */
146: public void printStackTrace() {
147: printStackTrace(System.err);
148: }
149:
150: /**
151: * Prints this ProxoolException and its backtrace to the specified print stream.
152: *
153: * @param stream <code>PrintStream</code> to use for output
154: */
155: public void printStackTrace(PrintStream stream) {
156: synchronized (stream) {
157: super .printStackTrace(stream);
158: Throwable ourCause = getCause();
159: if (ourCause != null) {
160: stream.println();
161: stream.println("Caused by:");
162: ourCause.printStackTrace(stream);
163: }
164: }
165: }
166:
167: /**
168: * Prints this ProxoolException and its backtrace to the specified
169: * print writer.
170: *
171: * @param writer <code>PrintWriter</code> to use for output
172: */
173: public void printStackTrace(PrintWriter writer) {
174: synchronized (writer) {
175: super .printStackTrace(writer);
176: Throwable ourCause = getCause();
177: if (ourCause != null) {
178: writer.println();
179: writer.println("Caused by:");
180: ourCause.printStackTrace(writer);
181: }
182: }
183: }
184:
185: }
|