001    /*
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  You may obtain a copy of the License at
008     * 
009     *      http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS,
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014     * See the License for the specific language governing permissions and
015     * limitations under the License.
016     */
017    package org.apache.commons.lang.exception;
018    
019    import java.io.PrintStream;
020    import java.io.PrintWriter;
021    
022    /**
023     * The base class of all exceptions which can contain other exceptions.
024     *
025     * It is intended to ease the debugging by carrying on the information
026     * about the exception which was caught and provoked throwing the
027     * current exception. Catching and rethrowing may occur multiple
028     * times, and provided that all exceptions except the first one
029     * are descendants of <code>NestedException</code>, when the
030     * exception is finally printed out using any of the <code>
031     * printStackTrace()</code> methods, the stack trace will contain
032     * the information about all exceptions thrown and caught on
033     * the way.
034     * <p> Running the following program
035     * <p><blockquote><pre>
036     *  1 import org.apache.commons.lang.exception.NestableException;
037     *  2
038     *  3 public class Test {
039     *  4     public static void main( String[] args ) {
040     *  5         try {
041     *  6             a();
042     *  7         } catch(Exception e) {
043     *  8             e.printStackTrace();
044     *  9         }
045     * 10      }
046     * 11
047     * 12      public static void a() throws Exception {
048     * 13          try {
049     * 14              b();
050     * 15          } catch(Exception e) {
051     * 16              throw new NestableException("foo", e);
052     * 17          }
053     * 18      }
054     * 19
055     * 20      public static void b() throws Exception {
056     * 21          try {
057     * 22              c();
058     * 23          } catch(Exception e) {
059     * 24              throw new NestableException("bar", e);
060     * 25          }
061     * 26      }
062     * 27
063     * 28      public static void c() throws Exception {
064     * 29          throw new Exception("baz");
065     * 30      }
066     * 31 }
067     * </pre></blockquote>
068     * <p>Yields the following stack trace:
069     * <p><blockquote><pre>
070     * org.apache.commons.lang.exception.NestableException: foo
071     *         at Test.a(Test.java:16)
072     *         at Test.main(Test.java:6)
073     * Caused by: org.apache.commons.lang.exception.NestableException: bar
074     *         at Test.b(Test.java:24)
075     *         at Test.a(Test.java:14)
076     *         ... 1 more
077     * Caused by: java.lang.Exception: baz
078     *         at Test.c(Test.java:29)
079     *         at Test.b(Test.java:22)
080     *         ... 2 more
081     * </pre></blockquote><br>
082     *
083     * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
084     * @author Daniel L. Rall
085     * @author <a href="mailto:knielsen@apache.org">Kasper Nielsen</a>
086     * @author <a href="mailto:steven@caswell.name">Steven Caswell</a>
087     * @since 1.0
088     * @version $Id: NestableException.java 512889 2007-02-28 18:18:20Z dlr $
089     */
090    public class NestableException extends Exception implements Nestable {
091        
092        /**
093         * Required for serialization support.
094         * 
095         * @see java.io.Serializable
096         */
097        private static final long serialVersionUID = 1L;
098    
099        /**
100         * The helper instance which contains much of the code which we
101         * delegate to.
102         */
103        protected NestableDelegate delegate = new NestableDelegate(this);
104    
105        /**
106         * Holds the reference to the exception or error that caused
107         * this exception to be thrown.
108         */
109        private Throwable cause = null;
110    
111        /**
112         * Constructs a new <code>NestableException</code> without specified
113         * detail message.
114         */
115        public NestableException() {
116            super();
117        }
118    
119        /**
120         * Constructs a new <code>NestableException</code> with specified
121         * detail message.
122         *
123         * @param msg The error message.
124         */
125        public NestableException(String msg) {
126            super(msg);
127        }
128    
129        /**
130         * Constructs a new <code>NestableException</code> with specified
131         * nested <code>Throwable</code>.
132         *
133         * @param cause the exception or error that caused this exception to be
134         * thrown
135         */
136        public NestableException(Throwable cause) {
137            super();
138            this.cause = cause;
139        }
140    
141        /**
142         * Constructs a new <code>NestableException</code> with specified
143         * detail message and nested <code>Throwable</code>.
144         *
145         * @param msg    the error message
146         * @param cause  the exception or error that caused this exception to be
147         * thrown
148         */
149        public NestableException(String msg, Throwable cause) {
150            super(msg);
151            this.cause = cause;
152        }
153    
154        /**
155         * {@inheritDoc}
156         */
157        public Throwable getCause() {
158            return cause;
159        }
160    
161        /**
162         * Returns the detail message string of this throwable. If it was
163         * created with a null message, returns the following:
164         * (cause==null ? null : cause.toString()).
165         *
166         * @return String message string of the throwable
167         */
168        public String getMessage() {
169            if (super.getMessage() != null) {
170                return super.getMessage();
171            } else if (cause != null) {
172                return cause.toString();
173            } else {
174                return null;
175            }
176        }
177    
178        /**
179         * {@inheritDoc}
180         */
181        public String getMessage(int index) {
182            if (index == 0) {
183                return super.getMessage();
184            }
185            return delegate.getMessage(index);
186        }
187    
188        /**
189         * {@inheritDoc}
190         */
191        public String[] getMessages() {
192            return delegate.getMessages();
193        }
194    
195        /**
196         * {@inheritDoc}
197         */
198        public Throwable getThrowable(int index) {
199            return delegate.getThrowable(index);
200        }
201    
202        /**
203         * {@inheritDoc}
204         */
205        public int getThrowableCount() {
206            return delegate.getThrowableCount();
207        }
208    
209        /**
210         * {@inheritDoc}
211         */
212        public Throwable[] getThrowables() {
213            return delegate.getThrowables();
214        }
215    
216        /**
217         * {@inheritDoc}
218         */
219        public int indexOfThrowable(Class type) {
220            return delegate.indexOfThrowable(type, 0);
221        }
222    
223        /**
224         * {@inheritDoc}
225         */
226        public int indexOfThrowable(Class type, int fromIndex) {
227            return delegate.indexOfThrowable(type, fromIndex);
228        }
229    
230        /**
231         * {@inheritDoc}
232         */
233        public void printStackTrace() {
234            delegate.printStackTrace();
235        }
236    
237        /**
238         * {@inheritDoc}
239         */
240        public void printStackTrace(PrintStream out) {
241            delegate.printStackTrace(out);
242        }
243    
244        /**
245         * {@inheritDoc}
246         */
247        public void printStackTrace(PrintWriter out) {
248            delegate.printStackTrace(out);
249        }
250    
251        /**
252         * {@inheritDoc}
253         */
254        public final void printPartialStackTrace(PrintWriter out) {
255            super.printStackTrace(out);
256        }
257    
258    }