1/*
2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements.  See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License.  You may obtain a copy of the License at
8 *
9 *     http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17
18// $Id: TransformerException.java 569994 2007-08-27 04:28:57Z mrglavas $
19
20package javax.xml.transform;
21
22/**
23 * This class specifies an exceptional condition that occurred
24 * during the transformation process.
25 */
26public class TransformerException extends Exception {
27
28    // Added serialVersionUID to preserve binary compatibility
29    private static final long serialVersionUID = 975798773772956428L;
30
31    /** Field locator specifies where the error occurred */
32    SourceLocator locator;
33
34    /**
35     * Method getLocator retrieves an instance of a SourceLocator
36     * object that specifies where an error occurred.
37     *
38     * @return A SourceLocator object, or null if none was specified.
39     */
40    public SourceLocator getLocator() {
41        return locator;
42    }
43
44    /**
45     * Method setLocator sets an instance of a SourceLocator
46     * object that specifies where an error occurred.
47     *
48     * @param location A SourceLocator object, or null to clear the location.
49     */
50    public void setLocator(SourceLocator location) {
51        locator = location;
52    }
53
54    /** Field containedException specifies a wrapped exception.  May be null. */
55    Throwable containedException;
56
57    /**
58     * This method retrieves an exception that this exception wraps.
59     *
60     * @return An Throwable object, or null.
61     * @see #getCause
62     */
63    public Throwable getException() {
64        return containedException;
65    }
66
67    /**
68     * Returns the cause of this throwable or <code>null</code> if the
69     * cause is nonexistent or unknown.  (The cause is the throwable that
70     * caused this throwable to get thrown.)
71     */
72    public Throwable getCause() {
73
74        return ((containedException == this)
75                ? null
76                : containedException);
77    }
78
79    /**
80     * Initializes the <i>cause</i> of this throwable to the specified value.
81     * (The cause is the throwable that caused this throwable to get thrown.)
82     *
83     * <p>This method can be called at most once.  It is generally called from
84     * within the constructor, or immediately after creating the
85     * throwable.  If this throwable was created
86     * with {@link #TransformerException(Throwable)} or
87     * {@link #TransformerException(String,Throwable)}, this method cannot be called
88     * even once.
89     *
90     * @param  cause the cause (which is saved for later retrieval by the
91     *         {@link #getCause()} method).  (A <tt>null</tt> value is
92     *         permitted, and indicates that the cause is nonexistent or
93     *         unknown.)
94     * @return  a reference to this <code>Throwable</code> instance.
95     * @throws IllegalArgumentException if <code>cause</code> is this
96     *         throwable.  (A throwable cannot
97     *         be its own cause.)
98     * @throws IllegalStateException if this throwable was
99     *         created with {@link #TransformerException(Throwable)} or
100     *         {@link #TransformerException(String,Throwable)}, or this method has already
101     *         been called on this throwable.
102     */
103    public synchronized Throwable initCause(Throwable cause) {
104
105        if (this.containedException != null) {
106            throw new IllegalStateException("Can't overwrite cause");
107        }
108
109        if (cause == this) {
110            throw new IllegalArgumentException(
111                "Self-causation not permitted");
112        }
113
114        this.containedException = cause;
115
116        return this;
117    }
118
119    /**
120     * Create a new TransformerException.
121     *
122     * @param message The error or warning message.
123     */
124    public TransformerException(String message) {
125
126        super(message);
127
128        this.containedException = null;
129        this.locator            = null;
130    }
131
132    /**
133     * Create a new TransformerException wrapping an existing exception.
134     *
135     * @param e The exception to be wrapped.
136     */
137    public TransformerException(Throwable e) {
138
139        super(e.toString());
140
141        this.containedException = e;
142        this.locator            = null;
143    }
144
145    /**
146     * Wrap an existing exception in a TransformerException.
147     *
148     * <p>This is used for throwing processor exceptions before
149     * the processing has started.</p>
150     *
151     * @param message The error or warning message, or null to
152     *                use the message from the embedded exception.
153     * @param e Any exception
154     */
155    public TransformerException(String message, Throwable e) {
156
157        super(((message == null) || (message.length() == 0))
158              ? e.toString()
159              : message);
160
161        this.containedException = e;
162        this.locator            = null;
163    }
164
165    /**
166     * Create a new TransformerException from a message and a Locator.
167     *
168     * <p>This constructor is especially useful when an application is
169     * creating its own exception from within a DocumentHandler
170     * callback.</p>
171     *
172     * @param message The error or warning message.
173     * @param locator The locator object for the error or warning.
174     */
175    public TransformerException(String message, SourceLocator locator) {
176
177        super(message);
178
179        this.containedException = null;
180        this.locator            = locator;
181    }
182
183    /**
184     * Wrap an existing exception in a TransformerException.
185     *
186     * @param message The error or warning message, or null to
187     *                use the message from the embedded exception.
188     * @param locator The locator object for the error or warning.
189     * @param e Any exception
190     */
191    public TransformerException(String message, SourceLocator locator,
192                                Throwable e) {
193
194        super(message);
195
196        this.containedException = e;
197        this.locator            = locator;
198    }
199
200    /**
201     * Get the error message with location information
202     * appended.
203     *
204     * @return A <code>String</code> representing the error message with
205     *         location information appended.
206     */
207    public String getMessageAndLocation() {
208
209        StringBuilder sbuffer = new StringBuilder();
210        String       message = super.getMessage();
211
212        if (null != message) {
213            sbuffer.append(message);
214        }
215
216        if (null != locator) {
217            String systemID = locator.getSystemId();
218            int    line     = locator.getLineNumber();
219            int    column   = locator.getColumnNumber();
220
221            if (null != systemID) {
222                sbuffer.append("; SystemID: ");
223                sbuffer.append(systemID);
224            }
225
226            if (0 != line) {
227                sbuffer.append("; Line#: ");
228                sbuffer.append(line);
229            }
230
231            if (0 != column) {
232                sbuffer.append("; Column#: ");
233                sbuffer.append(column);
234            }
235        }
236
237        return sbuffer.toString();
238    }
239
240    /**
241     * Get the location information as a string.
242     *
243     * @return A string with location info, or null
244     * if there is no location information.
245     */
246    public String getLocationAsString() {
247
248        if (null != locator) {
249            StringBuilder sbuffer  = new StringBuilder();
250            String       systemID = locator.getSystemId();
251            int          line     = locator.getLineNumber();
252            int          column   = locator.getColumnNumber();
253
254            if (null != systemID) {
255                sbuffer.append("; SystemID: ");
256                sbuffer.append(systemID);
257            }
258
259            if (0 != line) {
260                sbuffer.append("; Line#: ");
261                sbuffer.append(line);
262            }
263
264            if (0 != column) {
265                sbuffer.append("; Column#: ");
266                sbuffer.append(column);
267            }
268
269            return sbuffer.toString();
270        } else {
271            return null;
272        }
273    }
274
275    /**
276     * Print the the trace of methods from where the error
277     * originated.  This will trace all nested exception
278     * objects, as well as this object.
279     */
280    public void printStackTrace() {
281        printStackTrace(new java.io.PrintWriter(System.err, true));
282    }
283
284    /**
285     * Print the the trace of methods from where the error
286     * originated.  This will trace all nested exception
287     * objects, as well as this object.
288     * @param s The stream where the dump will be sent to.
289     */
290    public void printStackTrace(java.io.PrintStream s) {
291        printStackTrace(new java.io.PrintWriter(s));
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 writer where the dump will be sent to.
299     */
300    public void printStackTrace(java.io.PrintWriter s) {
301
302        if (s == null) {
303            s = new java.io.PrintWriter(System.err, true);
304        }
305
306        try {
307            String locInfo = getLocationAsString();
308
309            if (null != locInfo) {
310                s.println(locInfo);
311            }
312
313            super.printStackTrace(s);
314        } catch (Throwable e) {}
315    }
316}
317