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