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 Ælfred's <code>error</code> callback. 041 This is not necessary for routine use of Ælfred, but it 042 is used by the optional <code>HandlerBase</code> class. 043 044 <p>Note that the core Æ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 <dmeggins@microstar.com> 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}