Save This Page
Home » Xerces-J-src.2.9.1 » org.apache.xerces » impl » [javadoc | source]
    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   package org.apache.xerces.impl;
   19   
   20   import java.util.Hashtable;
   21   import java.util.Locale;
   22   
   23   import org.apache.xerces.util.DefaultErrorHandler;
   24   import org.apache.xerces.util.ErrorHandlerProxy;
   25   import org.apache.xerces.util.MessageFormatter;
   26   import org.apache.xerces.xni.XMLLocator;
   27   import org.apache.xerces.xni.XNIException;
   28   import org.apache.xerces.xni.parser.XMLComponent;
   29   import org.apache.xerces.xni.parser.XMLComponentManager;
   30   import org.apache.xerces.xni.parser.XMLConfigurationException;
   31   import org.apache.xerces.xni.parser.XMLErrorHandler;
   32   import org.apache.xerces.xni.parser.XMLParseException;
   33   import org.xml.sax.ErrorHandler;
   34   
   35   /**
   36    * This class is a common element of all parser configurations and is
   37    * used to report errors that occur. This component can be queried by
   38    * parser components from the component manager using the following
   39    * property ID:
   40    * <pre>
   41    *   http://apache.org/xml/properties/internal/error-reporter
   42    * </pre>
   43    * <p>
   44    * Errors are separated into domains that categorize a class of errors.
   45    * In a parser configuration, the parser would register a
   46    * <code>MessageFormatter</code> for each domain that is capable of
   47    * localizing error messages and formatting them based on information 
   48    * about the error. Any parser component can invent new error domains
   49    * and register additional message formatters to localize messages in
   50    * those domains.
   51    * <p>
   52    * This component requires the following features and properties from the
   53    * component manager that uses it:
   54    * <ul>
   55    *  <li>http://apache.org/xml/properties/internal/error-handler</li>
   56    * </ul>
   57    * <p>
   58    * This component can use the following features and properties but they
   59    * are not required:
   60    * <ul>
   61    *  <li>http://apache.org/xml/features/continue-after-fatal-error</li>
   62    * </ul>
   63    * 
   64    * @xerces.internal
   65    *
   66    * @see MessageFormatter
   67    *
   68    * @author Eric Ye, IBM
   69    * @author Andy Clark, IBM
   70    *
   71    * @version $Id: XMLErrorReporter.java 575002 2007-09-12 16:02:04Z mrglavas $
   72    */
   73   public class XMLErrorReporter
   74       implements XMLComponent {
   75   
   76       //
   77       // Constants
   78       //
   79   
   80       // severity
   81   
   82       /** 
   83        * Severity: warning. Warnings represent informational messages only
   84        * that should not be considered serious enough to stop parsing or 
   85        * indicate an error in the document's validity.
   86        */
   87       public static final short SEVERITY_WARNING = 0;
   88   
   89       /**
   90        * Severity: error. Common causes of errors are document structure and/or
   91        * content that that does not conform to the grammar rules specified for
   92        * the document. These are typically validation errors.
   93        */
   94       public static final short SEVERITY_ERROR = 1;
   95   
   96       /** 
   97        * Severity: fatal error. Fatal errors are errors in the syntax of the
   98        * XML document or invalid byte sequences for a given encoding. The
   99        * XML 1.0 Specification mandates that errors of this type are not
  100        * recoverable.
  101        * <p>
  102        * <strong>Note:</strong> The parser does have a "continue after fatal
  103        * error" feature but it should be used with extreme caution and care.
  104        */
  105       public static final short SEVERITY_FATAL_ERROR = 2;
  106       
  107       // feature identifiers
  108   
  109       /** Feature identifier: continue after fatal error. */
  110       protected static final String CONTINUE_AFTER_FATAL_ERROR =
  111           Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
  112   
  113       // property identifiers
  114   
  115       /** Property identifier: error handler. */
  116       protected static final String ERROR_HANDLER =
  117           Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
  118   
  119       // recognized features and properties
  120   
  121       /** Recognized features. */
  122       private static final String[] RECOGNIZED_FEATURES = {
  123           CONTINUE_AFTER_FATAL_ERROR,
  124       };
  125   
  126       /** Feature defaults. */
  127       private static final Boolean[] FEATURE_DEFAULTS = {
  128           null,
  129       };
  130   
  131       /** Recognized properties. */
  132       private static final String[] RECOGNIZED_PROPERTIES = {
  133           ERROR_HANDLER,
  134       };
  135   
  136       /** Property defaults. */
  137       private static final Object[] PROPERTY_DEFAULTS = {
  138           null,
  139       };
  140   
  141       //
  142       // Data
  143       //
  144   
  145       /** The locale to be used to format error messages. */
  146       protected Locale fLocale;
  147   
  148       /** Mapping of Message formatters for domains. */
  149       protected Hashtable fMessageFormatters;
  150   
  151       /** Error handler. */
  152       protected XMLErrorHandler fErrorHandler;
  153   
  154       /** Document locator. */
  155       protected XMLLocator fLocator;
  156   
  157       /** Continue after fatal error feature. */
  158       protected boolean fContinueAfterFatalError;
  159   
  160       /** 
  161        * Default error handler. This error handler is only used in the
  162        * absence of a registered error handler so that errors are not
  163        * "swallowed" silently. This is one of the most common "problems"
  164        * reported by users of the parser.
  165        */
  166       protected XMLErrorHandler fDefaultErrorHandler;
  167       
  168       /** A SAX proxy to the error handler contained in this error reporter. */
  169       private ErrorHandler fSaxProxy = null;
  170   
  171       //
  172       // Constructors
  173       //
  174   
  175       /** Constructs an error reporter with a locator. */
  176       public XMLErrorReporter() {
  177   
  178           // REVISIT: [Q] Should the locator be passed to the reportError
  179           //              method? Otherwise, there is no way for a parser
  180           //              component to store information about where an
  181           //              error occurred so as to report it later. 
  182           //
  183           //              An example would be to record the location of
  184           //              IDREFs so that, at the end of the document, if
  185           //              there is no associated ID declared, the error
  186           //              could report the location information of the
  187           //              reference. -Ac
  188           //
  189           // NOTE: I added another reportError method that allows the
  190           //       caller to specify the location of the error being
  191           //       reported. -Ac
  192   
  193           fMessageFormatters = new Hashtable();
  194   
  195       } // <init>()
  196   
  197       //
  198       // Methods
  199       //
  200   
  201       /**
  202        * Sets the current locale.
  203        * 
  204        * @param locale The new locale.
  205        */
  206       public void setLocale(Locale locale) {
  207           fLocale = locale;
  208       } // setLocale(Locale)
  209   
  210       /**
  211        * Gets the current locale.
  212        * 
  213        * @return the current Locale
  214        */
  215       public Locale getLocale() {
  216           return fLocale ;
  217       } // getLocale():  Locale
  218   
  219       /**
  220        * Sets the document locator.
  221        *
  222        * @param locator The locator.
  223        */
  224       public void setDocumentLocator(XMLLocator locator) {
  225           fLocator = locator;
  226       } // setDocumentLocator(XMLLocator)
  227   
  228       /**
  229        * Registers a message formatter for the specified domain.
  230        * <p>
  231        * <strong>Note:</strong> Registering a message formatter for a domain
  232        * when there is already a formatter registered will cause the previous
  233        * formatter to be lost. This method replaces any previously registered
  234        * message formatter for the specified domain.
  235        * 
  236        * @param domain 
  237        * @param messageFormatter 
  238        */
  239       public void putMessageFormatter(String domain, 
  240                                       MessageFormatter messageFormatter) {
  241           fMessageFormatters.put(domain, messageFormatter);
  242       } // putMessageFormatter(String,MessageFormatter)
  243   
  244       /**
  245        * Returns the message formatter associated with the specified domain,
  246        * or null if no message formatter is registered for that domain.
  247        * 
  248        * @param domain The domain of the message formatter.
  249        */
  250       public MessageFormatter getMessageFormatter(String domain) {
  251           return (MessageFormatter)fMessageFormatters.get(domain);
  252       } // getMessageFormatter(String):MessageFormatter
  253   
  254       /**
  255        * Removes the message formatter for the specified domain and
  256        * returns the removed message formatter.
  257        * 
  258        * @param domain The domain of the message formatter.
  259        */
  260       public MessageFormatter removeMessageFormatter(String domain) {
  261           return (MessageFormatter) fMessageFormatters.remove(domain);
  262       } // removeMessageFormatter(String):MessageFormatter
  263   
  264       /**
  265        * Reports an error. The error message passed to the error handler
  266        * is formatted for the locale by the message formatter installed
  267        * for the specified error domain.
  268        * 
  269        * @param domain    The error domain.
  270        * @param key       The key of the error message.
  271        * @param arguments The replacement arguments for the error message,
  272        *                  if needed.
  273        * @param severity  The severity of the error.
  274        *
  275        * @see #SEVERITY_WARNING
  276        * @see #SEVERITY_ERROR
  277        * @see #SEVERITY_FATAL_ERROR
  278        */
  279       public void reportError(String domain, String key, Object[] arguments, 
  280                               short severity) throws XNIException {
  281           reportError(fLocator, domain, key, arguments, severity);
  282       } // reportError(String,String,Object[],short)
  283       
  284       /**
  285        * Reports an error. The error message passed to the error handler
  286        * is formatted for the locale by the message formatter installed
  287        * for the specified error domain.
  288        * 
  289        * @param domain    The error domain.
  290        * @param key       The key of the error message.
  291        * @param arguments The replacement arguments for the error message,
  292        *                  if needed.
  293        * @param severity  The severity of the error.
  294        * @param exception The exception to wrap.
  295        *
  296        * @see #SEVERITY_WARNING
  297        * @see #SEVERITY_ERROR
  298        * @see #SEVERITY_FATAL_ERROR
  299        */
  300       public void reportError(String domain, String key, Object[] arguments, 
  301               short severity, Exception exception) throws XNIException {
  302           reportError(fLocator, domain, key, arguments, severity, exception);
  303       } // reportError(String,String,Object[],short,Exception)
  304       
  305       /**
  306        * Reports an error at a specific location.
  307        * 
  308        * @param location  The error location.
  309        * @param domain    The error domain.
  310        * @param key       The key of the error message.
  311        * @param arguments The replacement arguments for the error message,
  312        *                  if needed.
  313        * @param severity  The severity of the error.
  314        *
  315        * @see #SEVERITY_WARNING
  316        * @see #SEVERITY_ERROR
  317        * @see #SEVERITY_FATAL_ERROR
  318        */
  319       public void reportError(XMLLocator location,
  320               String domain, String key, Object[] arguments, 
  321               short severity) throws XNIException {
  322           reportError(location, domain, key, arguments, severity, null);
  323       } // reportError(XMLLocator,String,String,Object[],short)
  324   
  325       /**
  326        * Reports an error at a specific location.
  327        * 
  328        * @param location  The error location.
  329        * @param domain    The error domain.
  330        * @param key       The key of the error message.
  331        * @param arguments The replacement arguments for the error message,
  332        *                  if needed.
  333        * @param severity  The severity of the error.
  334        * @param exception The exception to wrap.
  335        *
  336        * @see #SEVERITY_WARNING
  337        * @see #SEVERITY_ERROR
  338        * @see #SEVERITY_FATAL_ERROR
  339        */
  340       public void reportError(XMLLocator location,
  341                               String domain, String key, Object[] arguments, 
  342                               short severity, Exception exception) throws XNIException {
  343   
  344           // REVISIT: [Q] Should we do anything about invalid severity
  345           //              parameter? -Ac
  346           
  347           // format error message and create parse exception
  348           MessageFormatter messageFormatter = getMessageFormatter(domain);
  349           String message;
  350           if (messageFormatter != null) {
  351               message = messageFormatter.formatMessage(fLocale, key, arguments);
  352           }
  353           else {
  354               StringBuffer str = new StringBuffer();
  355               str.append(domain);
  356               str.append('#');
  357               str.append(key);
  358               int argCount = arguments != null ? arguments.length : 0;
  359               if (argCount > 0) {
  360                   str.append('?');
  361                   for (int i = 0; i < argCount; i++) {
  362                       str.append(arguments[i]);
  363                       if (i < argCount -1) {
  364                           str.append('&');
  365                       }
  366                   }
  367               }
  368               message = str.toString();
  369           }
  370           XMLParseException parseException = (exception != null) ?
  371               new XMLParseException(location, message, exception) :
  372               new XMLParseException(location, message);
  373   
  374           // get error handler
  375           XMLErrorHandler errorHandler = fErrorHandler;
  376           if (errorHandler == null) {
  377               if (fDefaultErrorHandler == null) {
  378                   fDefaultErrorHandler = new DefaultErrorHandler();
  379               }
  380               errorHandler = fDefaultErrorHandler;
  381           }
  382   
  383           // call error handler
  384           switch (severity) {
  385               case SEVERITY_WARNING: {
  386                   errorHandler.warning(domain, key, parseException);
  387                   break;
  388               }
  389               case SEVERITY_ERROR: {
  390                   errorHandler.error(domain, key, parseException);
  391                   break;
  392               }
  393               case SEVERITY_FATAL_ERROR: {
  394                   errorHandler.fatalError(domain, key, parseException);
  395                   if (!fContinueAfterFatalError) {
  396                       throw parseException;
  397                   }
  398                   break;
  399               }
  400           }
  401   
  402       } // reportError(XMLLocator,String,String,Object[],short,Exception)
  403   
  404       //
  405       // XMLComponent methods
  406       //
  407   
  408       /**
  409        * Resets the component. The component can query the component manager
  410        * about any features and properties that affect the operation of the
  411        * component.
  412        * 
  413        * @param componentManager The component manager.
  414        *
  415        * @throws SAXException Thrown by component on initialization error.
  416        *                      For example, if a feature or property is
  417        *                      required for the operation of the component, the
  418        *                      component manager may throw a 
  419        *                      SAXNotRecognizedException or a
  420        *                      SAXNotSupportedException.
  421        */
  422       public void reset(XMLComponentManager componentManager)
  423           throws XNIException {
  424   
  425           // features
  426           try {
  427               fContinueAfterFatalError = componentManager.getFeature(CONTINUE_AFTER_FATAL_ERROR);
  428           }
  429           catch (XNIException e) {
  430               fContinueAfterFatalError = false;
  431           }
  432   
  433           // properties
  434           fErrorHandler = (XMLErrorHandler)componentManager.getProperty(ERROR_HANDLER);
  435   
  436       } // reset(XMLComponentManager)
  437   
  438       /**
  439        * Returns a list of feature identifiers that are recognized by
  440        * this component. This method may return null if no features
  441        * are recognized by this component.
  442        */
  443       public String[] getRecognizedFeatures() {
  444           return (String[])(RECOGNIZED_FEATURES.clone());
  445       } // getRecognizedFeatures():String[]
  446   
  447       /**
  448        * Sets the state of a feature. This method is called by the component
  449        * manager any time after reset when a feature changes state. 
  450        * <p>
  451        * <strong>Note:</strong> Components should silently ignore features
  452        * that do not affect the operation of the component.
  453        * 
  454        * @param featureId The feature identifier.
  455        * @param state     The state of the feature.
  456        *
  457        * @throws SAXNotRecognizedException The component should not throw
  458        *                                   this exception.
  459        * @throws SAXNotSupportedException The component should not throw
  460        *                                  this exception.
  461        */
  462       public void setFeature(String featureId, boolean state)
  463           throws XMLConfigurationException {
  464   
  465           //
  466           // Xerces features
  467           //
  468   
  469           if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
  470               final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
  471               
  472               //
  473               // http://apache.org/xml/features/continue-after-fatal-error
  474               //   Allows the parser to continue after a fatal error.
  475               //   Normally, a fatal error would stop the parse.
  476               //
  477               if (suffixLength == Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE.length() && 
  478                   featureId.endsWith(Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE)) {
  479                   fContinueAfterFatalError = state;
  480               }
  481           }
  482   
  483       } // setFeature(String,boolean)
  484   
  485       // return state of given feature or false if unsupported.
  486       public boolean getFeature(String featureId)
  487           throws XMLConfigurationException {
  488   
  489           //
  490           // Xerces features
  491           //
  492   
  493           if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
  494           	final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
  495           	
  496               //
  497               // http://apache.org/xml/features/continue-after-fatal-error
  498               //   Allows the parser to continue after a fatal error.
  499               //   Normally, a fatal error would stop the parse.
  500               //
  501               if (suffixLength == Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE.length() && 
  502                   featureId.endsWith(Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE)) {
  503                   return fContinueAfterFatalError ;
  504               }
  505           }
  506           return false;
  507   
  508       } // setFeature(String,boolean)
  509   
  510       /**
  511        * Returns a list of property identifiers that are recognized by
  512        * this component. This method may return null if no properties
  513        * are recognized by this component.
  514        */
  515       public String[] getRecognizedProperties() {
  516           return (String[])(RECOGNIZED_PROPERTIES.clone());
  517       } // getRecognizedProperties():String[]
  518   
  519       /**
  520        * Sets the value of a property. This method is called by the component
  521        * manager any time after reset when a property changes value. 
  522        * <p>
  523        * <strong>Note:</strong> Components should silently ignore properties
  524        * that do not affect the operation of the component.
  525        * 
  526        * @param propertyId The property identifier.
  527        * @param value      The value of the property.
  528        *
  529        * @throws SAXNotRecognizedException The component should not throw
  530        *                                   this exception.
  531        * @throws SAXNotSupportedException The component should not throw
  532        *                                  this exception.
  533        */
  534       public void setProperty(String propertyId, Object value)
  535           throws XMLConfigurationException {
  536   
  537           //
  538           // Xerces properties
  539           //
  540   
  541           if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
  542               final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
  543   
  544               if (suffixLength == Constants.ERROR_HANDLER_PROPERTY.length() && 
  545                   propertyId.endsWith(Constants.ERROR_HANDLER_PROPERTY)) {
  546                   fErrorHandler = (XMLErrorHandler)value;
  547               }
  548           }
  549   
  550       } // setProperty(String,Object)
  551       
  552       /** 
  553        * Returns the default state for a feature, or null if this
  554        * component does not want to report a default value for this
  555        * feature.
  556        *
  557        * @param featureId The feature identifier.
  558        *
  559        * @since Xerces 2.2.0
  560        */
  561       public Boolean getFeatureDefault(String featureId) {
  562           for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
  563               if (RECOGNIZED_FEATURES[i].equals(featureId)) {
  564                   return FEATURE_DEFAULTS[i];
  565               }
  566           }
  567           return null;
  568       } // getFeatureDefault(String):Boolean
  569   
  570       /** 
  571        * Returns the default state for a property, or null if this
  572        * component does not want to report a default value for this
  573        * property. 
  574        *
  575        * @param propertyId The property identifier.
  576        *
  577        * @since Xerces 2.2.0
  578        */
  579       public Object getPropertyDefault(String propertyId) {
  580           for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
  581               if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
  582                   return PROPERTY_DEFAULTS[i];
  583               }
  584           }
  585           return null;
  586       } // getPropertyDefault(String):Object
  587   
  588       /**
  589        * Get the internal XMLErrrorHandler.
  590        */
  591       public XMLErrorHandler getErrorHandler() {
  592           return fErrorHandler;
  593       }
  594       
  595       /**
  596        * Gets the internal XMLErrorHandler
  597        * as SAX ErrorHandler.
  598        */
  599       public ErrorHandler getSAXErrorHandler() {
  600           if (fSaxProxy == null) {
  601               fSaxProxy = new ErrorHandlerProxy() {
  602                   protected XMLErrorHandler getErrorHandler() {
  603                       return fErrorHandler;
  604                   }
  605               };
  606           }
  607           return fSaxProxy;
  608       }
  609       
  610   } // class XMLErrorReporter

Save This Page
Home » Xerces-J-src.2.9.1 » org.apache.xerces » impl » [javadoc | source]