Home | History | Annotate | Download | only in utils
      1 /*
      2  * Licensed to the Apache Software Foundation (ASF) under one
      3  * or more contributor license agreements. See the NOTICE file
      4  * distributed with this work for additional information
      5  * regarding copyright ownership. The ASF licenses this file
      6  * to you under the Apache License, Version 2.0 (the  "License");
      7  * you may not use this file except in compliance with the License.
      8  * You may obtain a copy of the License at
      9  *
     10  *     http://www.apache.org/licenses/LICENSE-2.0
     11  *
     12  * Unless required by applicable law or agreed to in writing, software
     13  * distributed under the License is distributed on an "AS IS" BASIS,
     14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     15  * See the License for the specific language governing permissions and
     16  * limitations under the License.
     17  */
     18 /*
     19  * $Id: DefaultErrorHandler.java 524806 2007-04-02 15:51:39Z zongaro $
     20  */
     21 package org.apache.xml.utils;
     22 
     23 import java.io.PrintStream;
     24 import java.io.PrintWriter;
     25 
     26 import javax.xml.transform.ErrorListener;
     27 import javax.xml.transform.SourceLocator;
     28 import javax.xml.transform.TransformerException;
     29 
     30 import org.apache.xml.res.XMLErrorResources;
     31 import org.apache.xml.res.XMLMessages;
     32 
     33 import org.xml.sax.ErrorHandler;
     34 import org.xml.sax.SAXException;
     35 import org.xml.sax.SAXParseException;
     36 
     37 
     38 /**
     39  * Implement SAX error handler for default reporting.
     40  * @xsl.usage general
     41  */
     42 public class DefaultErrorHandler implements ErrorHandler, ErrorListener
     43 {
     44   PrintWriter m_pw;
     45 
     46   /**
     47    * if this flag is set to true, we will rethrow the exception on
     48    * the error() and fatalError() methods. If it is false, the errors
     49    * are reported to System.err.
     50    */
     51   boolean m_throwExceptionOnError = true;
     52 
     53   /**
     54    * Constructor DefaultErrorHandler
     55    */
     56   public DefaultErrorHandler(PrintWriter pw)
     57   {
     58     m_pw = pw;
     59   }
     60 
     61   /**
     62    * Constructor DefaultErrorHandler
     63    */
     64   public DefaultErrorHandler(PrintStream pw)
     65   {
     66     m_pw = new PrintWriter(pw, true);
     67   }
     68 
     69   /**
     70    * Constructor DefaultErrorHandler
     71    */
     72   public DefaultErrorHandler()
     73   {
     74     this(true);
     75   }
     76 
     77   /**
     78    * Constructor DefaultErrorHandler
     79    */
     80   public DefaultErrorHandler(boolean throwExceptionOnError)
     81   {
     82     // Defer creation of a PrintWriter until it's actually needed
     83     m_throwExceptionOnError = throwExceptionOnError;
     84   }
     85 
     86   /**
     87    * Retrieve <code>java.io.PrintWriter</code> to which errors are being
     88    * directed.
     89    * @return The <code>PrintWriter</code> installed via the constructor
     90    *         or the default <code>PrintWriter</code>
     91    */
     92   public PrintWriter getErrorWriter() {
     93     // Defer creating the java.io.PrintWriter until an error needs to be
     94     // reported.
     95     if (m_pw == null) {
     96       m_pw = new PrintWriter(System.err, true);
     97     }
     98     return m_pw;
     99   }
    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 }
    364