001 /* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 /* 019 * $Id: DefaultErrorHandler.java 524806 2007-04-02 15:51:39Z zongaro $ 020 */ 021 package org.apache.xml.utils; 022 023 import java.io.PrintStream; 024 import java.io.PrintWriter; 025 026 import javax.xml.transform.ErrorListener; 027 import javax.xml.transform.SourceLocator; 028 import javax.xml.transform.TransformerException; 029 030 import org.apache.xml.res.XMLErrorResources; 031 import org.apache.xml.res.XMLMessages; 032 033 import org.xml.sax.ErrorHandler; 034 import org.xml.sax.SAXException; 035 import org.xml.sax.SAXParseException; 036 037 038 /** 039 * Implement SAX error handler for default reporting. 040 * @xsl.usage general 041 */ 042 public class DefaultErrorHandler implements ErrorHandler, ErrorListener 043 { 044 PrintWriter m_pw; 045 046 /** 047 * if this flag is set to true, we will rethrow the exception on 048 * the error() and fatalError() methods. If it is false, the errors 049 * are reported to System.err. 050 */ 051 boolean m_throwExceptionOnError = true; 052 053 /** 054 * Constructor DefaultErrorHandler 055 */ 056 public DefaultErrorHandler(PrintWriter pw) 057 { 058 m_pw = pw; 059 } 060 061 /** 062 * Constructor DefaultErrorHandler 063 */ 064 public DefaultErrorHandler(PrintStream pw) 065 { 066 m_pw = new PrintWriter(pw, true); 067 } 068 069 /** 070 * Constructor DefaultErrorHandler 071 */ 072 public DefaultErrorHandler() 073 { 074 this(true); 075 } 076 077 /** 078 * Constructor DefaultErrorHandler 079 */ 080 public DefaultErrorHandler(boolean throwExceptionOnError) 081 { 082 // Defer creation of a PrintWriter until it's actually needed 083 m_throwExceptionOnError = throwExceptionOnError; 084 } 085 086 /** 087 * Retrieve <code>java.io.PrintWriter</code> to which errors are being 088 * directed. 089 * @return The <code>PrintWriter</code> installed via the constructor 090 * or the default <code>PrintWriter</code> 091 */ 092 public PrintWriter getErrorWriter() { 093 // Defer creating the java.io.PrintWriter until an error needs to be 094 // reported. 095 if (m_pw == null) { 096 m_pw = new PrintWriter(System.err, true); 097 } 098 return m_pw; 099 } 100 101 /** 102 * Receive notification of a warning. 103 * 104 * <p>SAX parsers will use this method to report conditions that 105 * are not errors or fatal errors as defined by the XML 1.0 106 * recommendation. The default behaviour is to take no action.</p> 107 * 108 * <p>The SAX parser must continue to provide normal parsing events 109 * after invoking this method: it should still be possible for the 110 * application to process the document through to the end.</p> 111 * 112 * @param exception The warning information encapsulated in a 113 * SAX parse exception. 114 * @throws SAXException Any SAX exception, possibly 115 * wrapping another exception. 116 */ 117 public void warning(SAXParseException exception) throws SAXException 118 { 119 PrintWriter pw = getErrorWriter(); 120 121 printLocation(pw, exception); 122 pw.println("Parser warning: " + exception.getMessage()); 123 } 124 125 /** 126 * Receive notification of a recoverable error. 127 * 128 * <p>This corresponds to the definition of "error" in section 1.2 129 * of the W3C XML 1.0 Recommendation. For example, a validating 130 * parser would use this callback to report the violation of a 131 * validity constraint. The default behaviour is to take no 132 * action.</p> 133 * 134 * <p>The SAX parser must continue to provide normal parsing events 135 * after invoking this method: it should still be possible for the 136 * application to process the document through to the end. If the 137 * application cannot do so, then the parser should report a fatal 138 * error even if the XML 1.0 recommendation does not require it to 139 * do so.</p> 140 * 141 * @param exception The error information encapsulated in a 142 * SAX parse exception. 143 * @throws SAXException Any SAX exception, possibly 144 * wrapping another exception. 145 */ 146 public void error(SAXParseException exception) throws SAXException 147 { 148 //printLocation(exception); 149 // getErrorWriter().println(exception.getMessage()); 150 151 throw exception; 152 } 153 154 /** 155 * Receive notification of a non-recoverable error. 156 * 157 * <p>This corresponds to the definition of "fatal error" in 158 * section 1.2 of the W3C XML 1.0 Recommendation. For example, a 159 * parser would use this callback to report the violation of a 160 * well-formedness constraint.</p> 161 * 162 * <p>The application must assume that the document is unusable 163 * after the parser has invoked this method, and should continue 164 * (if at all) only for the sake of collecting addition error 165 * messages: in fact, SAX parsers are free to stop reporting any 166 * other events once this method has been invoked.</p> 167 * 168 * @param exception The error information encapsulated in a 169 * SAX parse exception. 170 * @throws SAXException Any SAX exception, possibly 171 * wrapping another exception. 172 */ 173 public void fatalError(SAXParseException exception) throws SAXException 174 { 175 // printLocation(exception); 176 // getErrorWriter().println(exception.getMessage()); 177 178 throw exception; 179 } 180 181 /** 182 * Receive notification of a warning. 183 * 184 * <p>SAX parsers will use this method to report conditions that 185 * are not errors or fatal errors as defined by the XML 1.0 186 * recommendation. The default behaviour is to take no action.</p> 187 * 188 * <p>The SAX parser must continue to provide normal parsing events 189 * after invoking this method: it should still be possible for the 190 * application to process the document through to the end.</p> 191 * 192 * @param exception The warning information encapsulated in a 193 * SAX parse exception. 194 * @throws javax.xml.transform.TransformerException Any SAX exception, possibly 195 * wrapping another exception. 196 * @see javax.xml.transform.TransformerException 197 */ 198 public void warning(TransformerException exception) throws TransformerException 199 { 200 PrintWriter pw = getErrorWriter(); 201 202 printLocation(pw, exception); 203 pw.println(exception.getMessage()); 204 } 205 206 /** 207 * Receive notification of a recoverable error. 208 * 209 * <p>This corresponds to the definition of "error" in section 1.2 210 * of the W3C XML 1.0 Recommendation. For example, a validating 211 * parser would use this callback to report the violation of a 212 * validity constraint. The default behaviour is to take no 213 * action.</p> 214 * 215 * <p>The SAX parser must continue to provide normal parsing events 216 * after invoking this method: it should still be possible for the 217 * application to process the document through to the end. If the 218 * application cannot do so, then the parser should report a fatal 219 * error even if the XML 1.0 recommendation does not require it to 220 * do so.</p> 221 * 222 * @param exception The error information encapsulated in a 223 * SAX parse exception. 224 * @throws javax.xml.transform.TransformerException Any SAX exception, possibly 225 * wrapping another exception. 226 * @see javax.xml.transform.TransformerException 227 */ 228 public void error(TransformerException exception) throws TransformerException 229 { 230 // If the m_throwExceptionOnError flag is true, rethrow the exception. 231 // Otherwise report the error to System.err. 232 if (m_throwExceptionOnError) 233 throw exception; 234 else 235 { 236 PrintWriter pw = getErrorWriter(); 237 238 printLocation(pw, exception); 239 pw.println(exception.getMessage()); 240 } 241 } 242 243 /** 244 * Receive notification of a non-recoverable error. 245 * 246 * <p>This corresponds to the definition of "fatal error" in 247 * section 1.2 of the W3C XML 1.0 Recommendation. For example, a 248 * parser would use this callback to report the violation of a 249 * well-formedness constraint.</p> 250 * 251 * <p>The application must assume that the document is unusable 252 * after the parser has invoked this method, and should continue 253 * (if at all) only for the sake of collecting addition error 254 * messages: in fact, SAX parsers are free to stop reporting any 255 * other events once this method has been invoked.</p> 256 * 257 * @param exception The error information encapsulated in a 258 * SAX parse exception. 259 * @throws javax.xml.transform.TransformerException Any SAX exception, possibly 260 * wrapping another exception. 261 * @see javax.xml.transform.TransformerException 262 */ 263 public void fatalError(TransformerException exception) throws TransformerException 264 { 265 // If the m_throwExceptionOnError flag is true, rethrow the exception. 266 // Otherwise report the error to System.err. 267 if (m_throwExceptionOnError) 268 throw exception; 269 else 270 { 271 PrintWriter pw = getErrorWriter(); 272 273 printLocation(pw, exception); 274 pw.println(exception.getMessage()); 275 } 276 } 277 278 public static void ensureLocationSet(TransformerException exception) 279 { 280 // SourceLocator locator = exception.getLocator(); 281 SourceLocator locator = null; 282 Throwable cause = exception; 283 284 // Try to find the locator closest to the cause. 285 do 286 { 287 if(cause instanceof SAXParseException) 288 { 289 locator = new SAXSourceLocator((SAXParseException)cause); 290 } 291 else if (cause instanceof TransformerException) 292 { 293 SourceLocator causeLocator = ((TransformerException)cause).getLocator(); 294 if(null != causeLocator) 295 locator = causeLocator; 296 } 297 298 if(cause instanceof TransformerException) 299 cause = ((TransformerException)cause).getCause(); 300 else if(cause instanceof SAXException) 301 cause = ((SAXException)cause).getException(); 302 else 303 cause = null; 304 } 305 while(null != cause); 306 307 exception.setLocator(locator); 308 } 309 310 public static void printLocation(PrintStream pw, TransformerException exception) 311 { 312 printLocation(new PrintWriter(pw), exception); 313 } 314 315 public static void printLocation(java.io.PrintStream pw, org.xml.sax.SAXParseException exception) 316 { 317 printLocation(new PrintWriter(pw), exception); 318 } 319 320 public static void printLocation(PrintWriter pw, Throwable exception) 321 { 322 SourceLocator locator = null; 323 Throwable cause = exception; 324 325 // Try to find the locator closest to the cause. 326 do 327 { 328 if(cause instanceof SAXParseException) 329 { 330 locator = new SAXSourceLocator((SAXParseException)cause); 331 } 332 else if (cause instanceof TransformerException) 333 { 334 SourceLocator causeLocator = ((TransformerException)cause).getLocator(); 335 if(null != causeLocator) 336 locator = causeLocator; 337 } 338 if(cause instanceof TransformerException) 339 cause = ((TransformerException)cause).getCause(); 340 else if(cause instanceof WrappedRuntimeException) 341 cause = ((WrappedRuntimeException)cause).getException(); 342 else if(cause instanceof SAXException) 343 cause = ((SAXException)cause).getException(); 344 else 345 cause = null; 346 } 347 while(null != cause); 348 349 if(null != locator) 350 { 351 // getErrorWriter().println("Parser fatal error: "+exception.getMessage()); 352 String id = (null != locator.getPublicId() ) 353 ? locator.getPublicId() 354 : (null != locator.getSystemId()) 355 ? locator.getSystemId() : XMLMessages.createXMLMessage(XMLErrorResources.ER_SYSTEMID_UNKNOWN, null); //"SystemId Unknown"; 356 357 pw.print(id + "; " +XMLMessages.createXMLMessage("line", null) + locator.getLineNumber() 358 + "; " +XMLMessages.createXMLMessage("column", null) + locator.getColumnNumber()+"; "); 359 } 360 else 361 pw.print("("+XMLMessages.createXMLMessage(XMLErrorResources.ER_LOCATION_UNKNOWN, null)+")"); 362 } 363 }