Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/jdom/JDOMException.java


1   /*-- 
2   
3    $Id: JDOMException.java,v 1.23 2004/02/27 11:32:57 jhunter Exp $
4   
5    Copyright (C) 2000-2004 Jason Hunter & Brett McLaughlin.
6    All rights reserved.
7    
8    Redistribution and use in source and binary forms, with or without
9    modification, are permitted provided that the following conditions
10   are met:
11   
12   1. Redistributions of source code must retain the above copyright
13      notice, this list of conditions, and the following disclaimer.
14   
15   2. Redistributions in binary form must reproduce the above copyright
16      notice, this list of conditions, and the disclaimer that follows 
17      these conditions in the documentation and/or other materials 
18      provided with the distribution.
19  
20   3. The name "JDOM" must not be used to endorse or promote products
21      derived from this software without prior written permission.  For
22      written permission, please contact <request_AT_jdom_DOT_org>.
23   
24   4. Products derived from this software may not be called "JDOM", nor
25      may "JDOM" appear in their name, without prior written permission
26      from the JDOM Project Management <request_AT_jdom_DOT_org>.
27   
28   In addition, we request (but do not require) that you include in the 
29   end-user documentation provided with the redistribution and/or in the 
30   software itself an acknowledgement equivalent to the following:
31       "This product includes software developed by the
32        JDOM Project (http://www.jdom.org/)."
33   Alternatively, the acknowledgment may be graphical using the logos 
34   available at http://www.jdom.org/images/logos.
35  
36   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
37   WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
38   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39   DISCLAIMED.  IN NO EVENT SHALL THE JDOM AUTHORS OR THE PROJECT
40   CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
41   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
42   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
43   USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
44   ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
45   OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
46   OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
47   SUCH DAMAGE.
48  
49   This software consists of voluntary contributions made by many 
50   individuals on behalf of the JDOM Project and was originally 
51   created by Jason Hunter <jhunter_AT_jdom_DOT_org> and
52   Brett McLaughlin <brett_AT_jdom_DOT_org>.  For more information
53   on the JDOM Project, please see <http://www.jdom.org/>.
54   
55   */
56  
57  package org.jdom;
58  
59  import java.io.*;
60  import java.lang.reflect.*;
61  import java.rmi.*;
62  import java.sql.*;
63  
64  import org.xml.sax.*;
65  
66  /**
67   * The top level exception that JDOM classes can throw. Its subclasses add
68   * specificity to the problems that can occur using JDOM. This single exception
69   * can be caught to handle all JDOM specific problems (some methods may throw
70   * {@link java.io.IOException} and such).
71   *
72   * @version $Revision: 1.23 $, $Date: 2004/02/27 11:32:57 $
73   * @author  Brett McLaughlin
74   * @author  Jason Hunter
75   */
76  public class JDOMException extends Exception {
77  
78      private static final String CVS_ID = 
79        "@(#) $RCSfile: JDOMException.java,v $ $Revision: 1.23 $ $Date: 2004/02/27 11:32:57 $ $Name: jdom_1_0 $";
80  
81      /** A wrapped <code>Throwable</code> */
82      private Throwable cause;
83  
84      /**
85       * This will create an <code>Exception</code>.
86       */
87      public JDOMException() {
88          super("Error occurred in JDOM application.");
89      }
90  
91      /**
92       * This will create an <code>Exception</code> with the given message.
93       *
94       * @param message <code>String</code> message indicating
95       *                the problem that occurred.
96       */    
97      public JDOMException(String message)  {
98          super(message);
99      }
100 
101     /**
102      * This will create an <code>Exception</code> with the given message
103      * and wrap another <code>Exception</code>.  This is useful when
104      * the originating <code>Exception</code> should be held on to.
105      *
106      * @param message <code>String</code> message indicating
107      *                the problem that occurred.
108      * @param cause <code>Throwable</code> that caused this
109      *                  to be thrown.
110      */    
111     public JDOMException(String message, Throwable cause)  {
112         super(message);    
113         this.cause = cause;
114     }    
115 
116     /** 
117      * Intializes the cause of this exception to be the specified value.
118      *
119      * @param cause <code>Throwable</code> that caused this
120      *                  to be thrown.
121      * @return a pointer to this throwable
122      */
123     // Created to match the JDK 1.4 Throwable method.
124     public Throwable initCause(Throwable cause)  {
125         this.cause = cause;
126         return this;
127     }    
128 
129     /**
130      * This returns the message for the <code>Exception</code>. If
131      * there are one or more nested exceptions, their messages
132      * are appended.
133      *
134      * @return <code>String</code> - message for <code>Exception</code>.
135      */
136     public String getMessage() {
137         // Get this exception's message.
138         String msg = super.getMessage();
139 
140         Throwable parent = this;
141         Throwable child;
142         
143         // Look for nested exceptions.
144         while((child = getNestedException(parent)) != null) {
145             // Get the child's message.
146             String msg2 = child.getMessage();
147             
148             // Special case: If a SAXException has no message of its own, but has a 
149             // nested exception, then it returns the nested exception's message as its
150             // message. We don't want to add that message twice.
151             if (child instanceof SAXException) {
152                 Throwable grandchild = ((SAXException)child).getException();
153                 // If the SAXException tells us that it's message is identical to 
154                 // its nested exception's message, then we skip it, so we don't
155                 // add it twice.
156                 if (grandchild != null && msg2 != null && msg2.equals(grandchild.getMessage())) {
157                     msg2 = null;
158                 }
159             }
160 
161             // If we found a message for the child exception, we append it.
162             if (msg2 != null) {
163                 if (msg != null) {
164                     msg += ": " + msg2;
165                 } else {
166                     msg = msg2;
167                 }
168             }
169 
170             // Any nested JDOMException will append its own children,
171             // so we need to break out of here.
172             if (child instanceof JDOMException) {
173                 break;
174             }
175             parent = child;
176         }
177 
178         // Return the completed message.
179         return msg;
180     }
181 
182     /**
183      * This prints the stack trace of the <code>Exception</code>. If
184      * there is a root cause, the stack trace of the root
185      * <code>Exception</code> is printed right after.
186      */
187     public void printStackTrace() {
188         // Print the stack trace for this exception.
189         super.printStackTrace();
190 
191         Throwable parent = this;
192         Throwable child;
193 
194         // Print the stack trace for each nested exception.
195         while((child = getNestedException(parent)) != null) {
196             System.err.print("Caused by: ");
197             child.printStackTrace();
198             // Any nested JDOMException will print its own children,
199             // so we need to break out of here.
200             if (child instanceof JDOMException) {
201                 break;
202             }
203             parent = child;
204         }
205     }
206 
207     /**
208      * Prints the stack trace of the <code>Exception</code> to the given
209      * PrintStream. If there is a root cause, the stack trace of the root
210      * <code>Exception</code> is printed right after.
211      *
212      * @param s PrintStream to print to
213      */
214     public void printStackTrace(PrintStream s) {
215         // Print the stack trace for this exception.
216         super.printStackTrace(s);
217 
218         Throwable parent = this;
219         Throwable child;
220 
221         // Print the stack trace for each nested exception.
222         while((child = getNestedException(parent)) != null) {
223             s.print("Caused by: ");
224             child.printStackTrace(s);
225             // Any nested JDOMException will print its own children,
226             // so we need to break out of here.
227             if (child instanceof JDOMException) {
228                 break;
229             }
230             parent = child;
231         }
232     }
233 
234     /**
235      * Prints the stack trace of the <code>Exception</code> to the given
236      * PrintWriter. If there is a root cause, the stack trace of the root
237      * <code>Exception</code> is printed right after.
238      *
239      * @param w PrintWriter to print to
240      */
241     public void printStackTrace(PrintWriter w) {
242         // Print the stack trace for this exception.
243         super.printStackTrace(w);
244 
245         Throwable parent = this;
246         Throwable child;
247 
248         // Print the stack trace for each nested exception.
249         while((child = getNestedException(parent)) != null) {
250             w.print("Caused by: ");
251             child.printStackTrace(w);
252             // Any nested JDOMException will print its own children,
253             // so we need to break out of here.
254             if (child instanceof JDOMException) {
255                 break;
256             }
257             parent = child;
258         }
259     }
260 
261     /**
262      * This will return the root cause <code>Throwable</code>, or null
263      * if one does not exist.
264      * 
265      * @return <code>Throwable</code> - the wrapped <code>Throwable</code>.
266      */
267     public Throwable getCause()  {
268         return cause;             
269     }
270 
271     // If this Throwable has a nested (child) exception, then we return it.
272     // Otherwise we return null.
273     private static Throwable getNestedException(Throwable parent) {
274         if (parent instanceof JDOMException) {
275             return ((JDOMException)parent).getCause();
276         }
277         
278         if (parent instanceof SAXException) {
279             return ((SAXException)parent).getException();
280         }
281         
282         if (parent instanceof SQLException) {
283             return ((SQLException)parent).getNextException();
284         }
285         
286         if (parent instanceof InvocationTargetException) {
287             return ((InvocationTargetException)parent).getTargetException();
288         }
289         
290         if (parent instanceof ExceptionInInitializerError) {
291             return ((ExceptionInInitializerError)parent).getException();
292         }
293         
294         if (parent instanceof RemoteException) {
295             return ((RemoteException)parent).detail;
296         }
297         
298         // These classes are not part of standard JDK 1.1 or 1.2, so we 
299         // use reflection to access them.
300 
301         Throwable nestedException = getNestedException(parent, "javax.naming.NamingException", "getRootCause");
302         if (nestedException != null) {
303             return nestedException;
304         }
305         
306         nestedException = getNestedException(parent, "javax.servlet.ServletException", "getRootCause");
307         if (nestedException != null) {
308             return nestedException;
309         }
310 
311         return null;
312     }
313 
314     // This method uses reflection to obtain the nest exception of a Throwable. We use reflection
315     // because the desired class may not exist in the currently-running VM.
316     private static Throwable getNestedException(
317                                  Throwable parent, String className, String methodName) {
318         try {
319             // See if this Throwable is of the desired type, by using isAssignableFrom().
320             Class testClass = Class.forName(className);
321             Class objectClass = parent.getClass();
322             if (testClass.isAssignableFrom(objectClass)) {
323                 // Use reflection to call the specified method.
324                 Class[] argClasses = new Class[0];
325                 Method method = testClass.getMethod(methodName, argClasses);
326                 Object[] args = new Object[0];
327                 return (Throwable)method.invoke(parent, args);
328             }
329         }
330         catch(Exception ex) {
331             // Most likely, the desired class is not available in this VM. That's fine.
332             // Even if it's caused by something else, we don't want to display an error
333             // here, since we're already in the process of trying to display the original
334             // error - another error here will just confuse things.
335         }
336 
337         return null;
338     }
339 }