001// XmlException.java: Simple base class for AElfred processors.
002// NO WARRANTY! See README, and copyright below.
003// $Id$
004/* Portions of this file are
005 Copyright (c) 2002-2003 The Regents of the University of California.
006 All rights reserved.
007 Permission is hereby granted, without written agreement and without
008 license or royalty fees, to use, copy, modify, and distribute this
009 software and its documentation for any purpose, provided that the above
010 copyright notice and the following two paragraphs appear in all copies
011 of this software.
012
013 IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY
014 FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
015 ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF
016 THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE POSSIBILITY OF
017 SUCH DAMAGE.
018
019 THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
020 INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
021 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE
022 PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND THE UNIVERSITY OF
023 CALIFORNIA HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,
024 ENHANCEMENTS, OR MODIFICATIONS.
025
026 PT_COPYRIGHT_VERSION_2
027 COPYRIGHTENDKEY
028 @ProposedRating Red (cxh)
029 @AcceptedRating Red (cxh)
030 */
031package com.microstar.xml;
032
033import java.io.PrintStream;
034import java.io.PrintWriter;
035import java.io.StringWriter;
036
037/**
038 Convenience exception class for reporting XML parsing errors.
039 <p>This is an exception class that you can use to encapsulate all
040 of the information from &AElig;lfred's <code>error</code> callback.
041 This is not necessary for routine use of &AElig;lfred, but it
042 is used by the optional <code>HandlerBase</code> class.
043
044 <p>Note that the core &AElig;lfred classes do <em>not</em>
045 use this exception.
046
047 <p>JDK1.4 supports exception chaining.  We are implementing a version of
048 exception chaining here ourselves so that we can use JVMs earlier
049 than JDK1.4.
050
051 <p>In this implementation, we have the following differences from
052 the JDK1.4 exception chaining implementation:
053
054 <menu>
055 <li>In this implementation, the detail message includes the detail
056 message from the cause argument.
057 <li>In this implementation, we implement a protected _setCause()
058 method, but not the public initCause() method that JDK1.4 has
059 </menu>
060
061 @author Copyright (c) 1998 by Microstar Software Ltd.
062 @author written by David Megginson &lt;dmeggins@microstar.com&gt;
063 @author Exception Chaining added by Christopher Hylands
064 @version 1.1
065 @since Ptolemy II 0.2
066 @see XmlHandler#error
067 @see HandlerBase
068 */
069@SuppressWarnings("serial")
070public class XmlException extends Exception {
071    /** Construct a new XML parsing exception.
072     * @param message The error message from the parser.
073     * @param systemId The URI of the entity containing the error.
074     */
075    public XmlException(String message, String systemId) {
076        this(message, systemId, -1, -1, null);
077    }
078
079    /** Construct a new XML parsing exception.
080     * @param message The error message from the parser.
081     * @param systemId The URI of the entity containing the error.
082     * @param line The line number where the error appeared.
083     * @param column The column number where the error appeared.
084     */
085    public XmlException(String message, String systemId, int line, int column) {
086        this(message, systemId, line, column, null);
087    }
088
089    /** Construct a new XML parsing exception.
090     * @param message The error message from the parser.
091     * @param systemId The URI of the entity containing the error.
092     * @param line The line number where the error appeared.
093     * @param column The column number where the error appeared.
094     * @param cause The cause of this exception, if any
095     */
096    public XmlException(String message, String systemId, int line, int column,
097            Throwable cause) {
098        _message = message;
099        _systemId = systemId;
100        _line = line;
101        _column = column;
102        _cause = cause;
103    }
104
105    /** Get the cause of this exception.
106     *  @return The cause that was passed in as an argument to the
107     *  constructor, or null of no cause was specified.
108     */
109    @Override
110    public Throwable getCause() {
111        return _cause;
112    }
113
114    /**
115     * Get the error message from the parser.
116     * @return A string describing the error.
117     */
118    @Override
119    public String getMessage() {
120        // Modified by Steve Neuendorffer because the message didn't tell what
121        // the location was.
122        return _message + " in " + _systemId
123                + (_line == -1 ? "unknown line " : " at line " + _line)
124                + (_column == -1 ? " and unknown column "
125                        : " and column " + _column)
126                + (_cause == null ? "" : "\nCaused by:\n " + _cause);
127    }
128
129    /** Get the URI of the entity containing the error.
130     * @return The URI as a string.
131     */
132    public String getSystemId() {
133        return _systemId;
134    }
135
136    /** Get the line number containing the error.
137     * @return The line number as an integer.
138     */
139    public int getLine() {
140        return _line;
141    }
142
143    /** Get the column number containing the error.
144     * @return The column number as an integer.
145     */
146    public int getColumn() {
147        return _column;
148    }
149
150    /** Print the following to stderr:
151     *  this exception, its stack trace and if the cause
152     *  exception is known, print the cause exception and the
153     *  cause stacktrace.
154     */
155    @Override
156    public void printStackTrace() {
157        // Note that chained exceptions are new JDK1.4.
158        // We are implement them ourselves here so that we can
159        // use JVMs earlier than JDK1.4.  The JDK1.4 Throwable.getCause()
160        // documentation states that it is not necessary to overwrite
161        // printStackTrace, but this is only the case when we have a JDK1.4
162        // JVM.
163        printStackTrace(new PrintWriter(System.err));
164    }
165
166    /** Print this exception, its stack trace and if the cause
167     *  exception is known, print the cause exception and the cause
168     *  stacktrace.
169     *  @param printStream The PrintStream to write to.
170     */
171    @Override
172    public void printStackTrace(PrintStream printStream) {
173        printStackTrace(new PrintWriter(printStream));
174    }
175
176    /** Print this exception, its stack trace and if the cause
177     *  exception is known, print the cause exception and the
178     *  cause stacktrace.
179     *  @param printWriter The PrintWriter to write to.
180     */
181    @Override
182    public void printStackTrace(PrintWriter printWriter) {
183        super.printStackTrace(printWriter);
184
185        if (_cause != null) {
186            printWriter.print("Caused by: ");
187            _cause.printStackTrace(printWriter);
188        }
189
190        printWriter.flush();
191    }
192
193    /** Return the stack trace of the given argument as a String.
194     *  This method is useful if we are catching and rethrowing
195     *  a throwable that does not take a throwable cause argument.
196     *  For example, the XML parser exception does not take
197     *  a cause argument, so we call this method instead.
198     *  This method should be used instead of
199     *  Throwable.printStackTrace(), which prints the stack trace
200     *  to stderr, which is likely to be hidden if we are running
201     *  a Ptolemy application from anything but a shell console.
202     *  @param throwable A throwable.
203     *  @return The stack trace of the throwable.
204     */
205    public static String stackTraceToString(Throwable throwable) {
206        StringWriter stringWriter = new StringWriter();
207        PrintWriter printWriter = new PrintWriter(stringWriter);
208        throwable.printStackTrace(printWriter);
209        return stringWriter.toString();
210    }
211
212    ///////////////////////////////////////////////////////////////////
213    ////                         private variables                 ////
214    private String _message;
215
216    // The cause of this exception.
217    private Throwable _cause;
218
219    private String _systemId;
220
221    private int _line = -1;
222
223    private int _column = -1;
224}