View Javadoc
1   /*
2    * reserved comment block
3    * DO NOT REMOVE OR ALTER!
4    */
5   /*
6    * Copyright 1999-2004 The Apache Software Foundation.
7    *
8    * Licensed under the Apache License, Version 2.0 (the "License");
9    * you may not use this file except in compliance with the License.
10   * You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing, software
15   * distributed under the License is distributed on an "AS IS" BASIS,
16   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17   * See the License for the specific language governing permissions and
18   * limitations under the License.
19   */
20  /*
21   * $Id: DTMException.java,v 1.3 2005/09/28 13:48:50 pvedula Exp $
22   */
23  package com.sun.org.apache.xml.internal.dtm;
24  
25  
26  import java.lang.reflect.InvocationTargetException;
27  import java.lang.reflect.Method;
28  
29  import javax.xml.transform.SourceLocator;
30  
31  import com.sun.org.apache.xml.internal.res.XMLErrorResources;
32  import com.sun.org.apache.xml.internal.res.XMLMessages;
33  
34  
35  /**
36   * This class specifies an exceptional condition that occured
37   * in the DTM module.
38   */
39  public class DTMException extends RuntimeException {
40      static final long serialVersionUID = -775576419181334734L;
41  
42      /** Field locator specifies where the error occured.
43       *  @serial */
44      SourceLocator locator;
45  
46      /**
47       * Method getLocator retrieves an instance of a SourceLocator
48       * object that specifies where an error occured.
49       *
50       * @return A SourceLocator object, or null if none was specified.
51       */
52      public SourceLocator getLocator() {
53          return locator;
54      }
55  
56      /**
57       * Method setLocator sets an instance of a SourceLocator
58       * object that specifies where an error occured.
59       *
60       * @param location A SourceLocator object, or null to clear the location.
61       */
62      public void setLocator(SourceLocator location) {
63          locator = location;
64      }
65  
66      /** Field containedException specifies a wrapped exception.  May be null.
67       *  @serial */
68      Throwable containedException;
69  
70      /**
71       * This method retrieves an exception that this exception wraps.
72       *
73       * @return An Throwable object, or null.
74       * @see #getCause
75       */
76      public Throwable getException() {
77          return containedException;
78      }
79  
80      /**
81       * Returns the cause of this throwable or <code>null</code> if the
82       * cause is nonexistent or unknown.  (The cause is the throwable that
83       * caused this throwable to get thrown.)
84       */
85      public Throwable getCause() {
86  
87          return ((containedException == this)
88                  ? null
89                  : containedException);
90      }
91  
92      /**
93       * Initializes the <i>cause</i> of this throwable to the specified value.
94       * (The cause is the throwable that caused this throwable to get thrown.)
95       *
96       * <p>This method can be called at most once.  It is generally called from
97       * within the constructor, or immediately after creating the
98       * throwable.  If this throwable was created
99       * with {@link #DTMException(Throwable)} or
100      * {@link #DTMException(String,Throwable)}, this method cannot be called
101      * even once.
102      *
103      * @param  cause the cause (which is saved for later retrieval by the
104      *         {@link #getCause()} method).  (A <tt>null</tt> value is
105      *         permitted, and indicates that the cause is nonexistent or
106      *         unknown.)
107      * @return  a reference to this <code>Throwable</code> instance.
108      * @throws IllegalArgumentException if <code>cause</code> is this
109      *         throwable.  (A throwable cannot
110      *         be its own cause.)
111      * @throws IllegalStateException if this throwable was
112      *         created with {@link #DTMException(Throwable)} or
113      *         {@link #DTMException(String,Throwable)}, or this method has already
114      *         been called on this throwable.
115      */
116     public synchronized Throwable initCause(Throwable cause) {
117 
118         if ((this.containedException == null) && (cause != null)) {
119             throw new IllegalStateException(XMLMessages.createXMLMessage(XMLErrorResources.ER_CANNOT_OVERWRITE_CAUSE, null)); //"Can't overwrite cause");
120         }
121 
122         if (cause == this) {
123             throw new IllegalArgumentException(
124                 XMLMessages.createXMLMessage(XMLErrorResources.ER_SELF_CAUSATION_NOT_PERMITTED, null)); //"Self-causation not permitted");
125         }
126 
127         this.containedException = cause;
128 
129         return this;
130     }
131 
132     /**
133      * Create a new DTMException.
134      *
135      * @param message The error or warning message.
136      */
137     public DTMException(String message) {
138 
139         super(message);
140 
141         this.containedException = null;
142         this.locator            = null;
143     }
144 
145     /**
146      * Create a new DTMException wrapping an existing exception.
147      *
148      * @param e The exception to be wrapped.
149      */
150     public DTMException(Throwable e) {
151 
152         super(e.getMessage());
153 
154         this.containedException = e;
155         this.locator            = null;
156     }
157 
158     /**
159      * Wrap an existing exception in a DTMException.
160      *
161      * <p>This is used for throwing processor exceptions before
162      * the processing has started.</p>
163      *
164      * @param message The error or warning message, or null to
165      *                use the message from the embedded exception.
166      * @param e Any exception
167      */
168     public DTMException(String message, Throwable e) {
169 
170         super(((message == null) || (message.length() == 0))
171               ? e.getMessage()
172               : message);
173 
174         this.containedException = e;
175         this.locator            = null;
176     }
177 
178     /**
179      * Create a new DTMException from a message and a Locator.
180      *
181      * <p>This constructor is especially useful when an application is
182      * creating its own exception from within a DocumentHandler
183      * callback.</p>
184      *
185      * @param message The error or warning message.
186      * @param locator The locator object for the error or warning.
187      */
188     public DTMException(String message, SourceLocator locator) {
189 
190         super(message);
191 
192         this.containedException = null;
193         this.locator            = locator;
194     }
195 
196     /**
197      * Wrap an existing exception in a DTMException.
198      *
199      * @param message The error or warning message, or null to
200      *                use the message from the embedded exception.
201      * @param locator The locator object for the error or warning.
202      * @param e Any exception
203      */
204     public DTMException(String message, SourceLocator locator,
205                                 Throwable e) {
206 
207         super(message);
208 
209         this.containedException = e;
210         this.locator            = locator;
211     }
212 
213     /**
214      * Get the error message with location information
215      * appended.
216      */
217     public String getMessageAndLocation() {
218 
219         StringBuffer sbuffer = new StringBuffer();
220         String       message = super.getMessage();
221 
222         if (null != message) {
223             sbuffer.append(message);
224         }
225 
226         if (null != locator) {
227             String systemID = locator.getSystemId();
228             int    line     = locator.getLineNumber();
229             int    column   = locator.getColumnNumber();
230 
231             if (null != systemID) {
232                 sbuffer.append("; SystemID: ");
233                 sbuffer.append(systemID);
234             }
235 
236             if (0 != line) {
237                 sbuffer.append("; Line#: ");
238                 sbuffer.append(line);
239             }
240 
241             if (0 != column) {
242                 sbuffer.append("; Column#: ");
243                 sbuffer.append(column);
244             }
245         }
246 
247         return sbuffer.toString();
248     }
249 
250     /**
251      * Get the location information as a string.
252      *
253      * @return A string with location info, or null
254      * if there is no location information.
255      */
256     public String getLocationAsString() {
257 
258         if (null != locator) {
259             StringBuffer sbuffer  = new StringBuffer();
260             String       systemID = locator.getSystemId();
261             int          line     = locator.getLineNumber();
262             int          column   = locator.getColumnNumber();
263 
264             if (null != systemID) {
265                 sbuffer.append("; SystemID: ");
266                 sbuffer.append(systemID);
267             }
268 
269             if (0 != line) {
270                 sbuffer.append("; Line#: ");
271                 sbuffer.append(line);
272             }
273 
274             if (0 != column) {
275                 sbuffer.append("; Column#: ");
276                 sbuffer.append(column);
277             }
278 
279             return sbuffer.toString();
280         } else {
281             return null;
282         }
283     }
284 
285     /**
286      * Print the the trace of methods from where the error
287      * originated.  This will trace all nested exception
288      * objects, as well as this object.
289      */
290     public void printStackTrace() {
291         printStackTrace(new java.io.PrintWriter(System.err, true));
292     }
293 
294     /**
295      * Print the the trace of methods from where the error
296      * originated.  This will trace all nested exception
297      * objects, as well as this object.
298      * @param s The stream where the dump will be sent to.
299      */
300     public void printStackTrace(java.io.PrintStream s) {
301         printStackTrace(new java.io.PrintWriter(s));
302     }
303 
304     /**
305      * Print the the trace of methods from where the error
306      * originated.  This will trace all nested exception
307      * objects, as well as this object.
308      * @param s The writer where the dump will be sent to.
309      */
310     public void printStackTrace(java.io.PrintWriter s) {
311 
312         if (s == null) {
313             s = new java.io.PrintWriter(System.err, true);
314         }
315 
316         try {
317             String locInfo = getLocationAsString();
318 
319             if (null != locInfo) {
320                 s.println(locInfo);
321             }
322 
323             super.printStackTrace(s);
324         } catch (Throwable e) {}
325 
326         boolean isJdk14OrHigher = false;
327         try {
328             Throwable.class.getMethod("getCause", (Class[]) null);
329             isJdk14OrHigher = true;
330         } catch (NoSuchMethodException nsme) {
331             // do nothing
332         }
333 
334         // The printStackTrace method of the Throwable class in jdk 1.4
335         // and higher will include the cause when printing the backtrace.
336         // The following code is only required when using jdk 1.3 or lower
337         if (!isJdk14OrHigher) {
338             Throwable exception = getException();
339 
340             for (int i = 0; (i < 10) && (null != exception); i++) {
341                 s.println("---------");
342 
343                 try {
344                     if (exception instanceof DTMException) {
345                         String locInfo =
346                             ((DTMException) exception)
347                                 .getLocationAsString();
348 
349                         if (null != locInfo) {
350                             s.println(locInfo);
351                         }
352                     }
353 
354                     exception.printStackTrace(s);
355                 } catch (Throwable e) {
356                     s.println("Could not print stack trace...");
357                 }
358 
359                 try {
360                     Method meth =
361                         ((Object) exception).getClass().getMethod("getException",
362                             (Class[]) null);
363 
364                     if (null != meth) {
365                         Throwable prev = exception;
366 
367                         exception = (Throwable) meth.invoke(exception, (Object[]) null);
368 
369                         if (prev == exception) {
370                             break;
371                         }
372                     } else {
373                         exception = null;
374                     }
375                 } catch (InvocationTargetException ite) {
376                     exception = null;
377                 } catch (IllegalAccessException iae) {
378                     exception = null;
379                 } catch (NoSuchMethodException nsme) {
380                     exception = null;
381                 }
382             }
383         }
384     }
385 }