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