1 /* Copyright 2002-2004 Elliotte Rusty Harold
2 
3    This library is free software; you can redistribute it and/or modify
4    it under the terms of version 2.1 of the GNU Lesser General Public
5    License as published by the Free Software Foundation.
6 
7    This library is distributed in the hope that it will be useful,
8    but WITHOUT ANY WARRANTY; without even the implied warranty of
9    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10    GNU Lesser General Public License for more details.
11 
12    You should have received a copy of the GNU Lesser General Public
13    License along with this library; if not, write to the
14    Free Software Foundation, Inc., 59 Temple Place, Suite 330,
15    Boston, MA 02111-1307  USA
16 
17    You can contact Elliotte Rusty Harold by sending e-mail to
18    elharo@ibiblio.org. Please include the word "XOM" in the
19    subject line. The XOM home page is located at http://www.xom.nu/
20 */
21 
22 package nu.xom;
23 
24 /**
25  * <p>
26  *  The generic superclass for all the
27  *  checked exceptions thrown in XOM. The general
28  *  principle followed is that anything that could
29  *  plausibly be detected by testing such as
30  *  using spaces in an element name is a runtime exception.
31  *  Exceptions that depend on environmental conditions,
32  *  such as might occur when parsing an external file,
33  *  are checked exceptions, because these depend on variable input,
34  *  and thus problems may not all be detected during testing.
35  * </p>
36  *
37  * @author Elliotte Rusty Harold
38  * @version 1.1b3
39  *
40  */
41 public class ParsingException extends Exception {
42 
43 
44     private static final long serialVersionUID = -5185450480590174490L;
45 
46     private Throwable cause;
47     private int lineNumber = -1;
48     private int columnNumber = -1;
49     private String uri;
50 
51 
52     /**
53      * <p>
54      * Creates a new <code>ParsingException</code> with a detail message
55      * and an underlying root cause.
56      * </p>
57      *
58      * @param message a string indicating the specific problem
59      * @param cause the original cause of this exception
60      */
ParsingException(String message, Throwable cause)61     public ParsingException(String message, Throwable cause) {
62         super(message);
63         this.initCause(cause);
64     }
65 
66 
67     /**
68      * <p>
69      * Creates a new <code>ParsingException</code> with a detail message
70      * and an underlying root cause.
71      * </p>
72      *
73      * @param message a string indicating the specific problem
74      * @param uri the URI of the document that caused this exception
75      * @param cause the original cause of this exception
76      */
ParsingException(String message, String uri, Throwable cause)77     public ParsingException(String message, String uri, Throwable cause) {
78         super(message);
79         this.uri = uri;
80         this.initCause(cause);
81     }
82 
83 
84     /**
85      * <p>
86      * Creates a new <code>ParsingException</code> with a detail message
87      * and line and column numbers.
88      * </p>
89      *
90      * @param message a string indicating the specific problem
91      * @param lineNumber the approximate line number
92      *     where the problem occurs
93      * @param columnNumber the approximate column number
94      *     where the problem occurs
95      */
ParsingException(String message, int lineNumber, int columnNumber)96     public ParsingException(String message,
97       int lineNumber, int columnNumber) {
98         this(message, null, lineNumber, columnNumber, null);
99     }
100 
101 
102     /**
103      * <p>
104      * Creates a new <code>ParsingException</code> with a detail message
105      * and line and column numbers.
106      * </p>
107      *
108      * @param message a string indicating the specific problem
109      * @param uri the URI of the document that caused this exception
110      * @param lineNumber the approximate line number
111      *     where the problem occurs
112      * @param columnNumber the approximate column number
113      *     where the problem occurs
114      */
ParsingException(String message, String uri, int lineNumber, int columnNumber)115     public ParsingException(String message, String uri,
116       int lineNumber, int columnNumber) {
117         this(message, uri, lineNumber, columnNumber, null);
118     }
119 
120 
121     /**
122      * <p>
123      * Creates a new <code>ParsingException</code> with a detail
124      * message, line and column numbers, and an underlying exception.
125      * </p>
126      *
127      * @param message a string indicating the specific problem
128      * @param uri the URI of the document that caused this exception
129      * @param lineNumber the approximate line number
130      *     where the problem occurs
131      * @param columnNumber the approximate column number
132      *     where the problem occurs
133      * @param cause the original cause of this exception
134      */
ParsingException(String message, String uri, int lineNumber, int columnNumber, Throwable cause)135     public ParsingException(String message, String uri, int lineNumber,
136       int columnNumber, Throwable cause) {
137         super(message);
138         this.lineNumber = lineNumber;
139         this.columnNumber = columnNumber;
140         this.uri = uri;
141         this.initCause(cause);
142     }
143 
144 
145     /**
146      * <p>
147      * Creates a new <code>ParsingException</code> with a detail
148      * message, line and column numbers, and an underlying exception.
149      * </p>
150      *
151      * @param message a string indicating the specific problem
152      * @param lineNumber the approximate line number
153      *     where the problem occurs
154      * @param columnNumber the approximate column number
155      *     where the problem occurs
156      * @param cause the original cause of this exception
157      */
ParsingException(String message, int lineNumber, int columnNumber, Throwable cause)158     public ParsingException(String message, int lineNumber,
159       int columnNumber, Throwable cause) {
160         super(message);
161         this.lineNumber = lineNumber;
162         this.columnNumber = columnNumber;
163         this.initCause(cause);
164     }
165 
166 
167     /**
168      * <p>
169      * Creates a new <code>ParsingException</code> with a detail message.
170      * </p>
171      *
172      * @param message a string indicating the specific problem
173      */
ParsingException(String message)174     public ParsingException(String message) {
175         super(message);
176     }
177 
178 
179     /**
180      * <p>
181      * Returns the approximate row number of the construct that
182      * caused this exception. If the row number is not known,
183      * -1 is returned.
184      * </p>
185      *
186      * @return row number where the exception occurred
187      */
getLineNumber()188     public int getLineNumber() {
189         return this.lineNumber;
190     }
191 
192     /**
193      * <p>
194      * Returns the approximate column number of the construct that
195      * caused this exception. If the column number is not known,
196      * -1 is returned.
197      * </p>
198      *
199      * @return column number where the exception occurred
200      */
getColumnNumber()201     public int getColumnNumber() {
202         return this.columnNumber;
203     }
204 
205 
206     /**
207      * <p>
208      * Returns the system ID (generally a URL) of the document that
209      * caused this exception. If this is not known, for instance
210      * because the document was parsed from a raw input stream or from
211      * a string, it returns null.
212      * </p>
213      *
214      * @return the URI of the document that caused this exception
215      */
getURI()216     public String getURI() {
217         return this.uri;
218     }
219 
220 
221     // null is insufficient for determining unset cause.
222     // The cause may be set to null which may not then be reset.
223     private boolean causeSet = false;
224 
225     /**
226      * <p>
227      * Sets the root cause of this exception. This may
228      * only be called once. Subsequent calls throw an
229      * <code>IllegalStateException</code>.
230      * </p>
231      *
232      * <p>
233      * This method is unnecessary in Java 1.4 where it could easily be
234      * inherited from the superclass. However, including it here
235      * allows this  method to be used in Java 1.3 and earlier.
236      * </p>
237      *
238      * @param cause the root cause of this exception
239      *
240      * @return this <code>XMLException</code>
241      *
242      * @throws IllegalArgumentException if the cause is this exception
243      *   (An exception cannot be its own cause.)
244      * @throws IllegalStateException if this method is called twice
245      */
initCause(Throwable cause)246     public final Throwable initCause(Throwable cause) {
247 
248         if (causeSet) {
249             throw new IllegalStateException("Can't overwrite cause");
250         }
251         else if (cause == this) {
252             throw new IllegalArgumentException("Self-causation not permitted");
253         }
254         else this.cause = cause;
255         causeSet = true;
256         return this;
257 
258     }
259 
260 
261     /**
262      * <p>
263      * Returns the underlying exception that caused this exception.
264      * </p>
265      *
266      * @return the root exception that caused this exception
267      *     to be thrown
268      */
getCause()269     public Throwable getCause() {
270         return this.cause;
271     }
272 
273 
274     /**
275      * <p>
276      * Returns a string suitable for display to the developer
277      * summarizing what went wrong where.
278      * </p>
279      *
280      * @return an exception message suitable for display to a developer
281      */
toString()282     public String toString() {
283         StringBuffer result = new StringBuffer(super.toString());
284         if (lineNumber >= 0) {
285             result.append(" at line ");
286             result.append(lineNumber);
287             result.append(", column ");
288             result.append(columnNumber);
289         }
290 
291         if (this.uri != null) {
292             result.append(" in ");
293             result.append(uri);
294         }
295         return result.toString();
296     }
297 
298 
299 }