- /*
- * The Apache Software License, Version 1.1
- *
- *
- * Copyright (c) 1999-2004 The Apache Software Foundation.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in
- * the documentation and/or other materials provided with the
- * distribution.
- *
- * 3. The end-user documentation included with the redistribution,
- * if any, must include the following acknowledgment:
- * "This product includes software developed by the
- * Apache Software Foundation (http://www.apache.org/)."
- * Alternately, this acknowledgment may appear in the software itself,
- * if and wherever such third-party acknowledgments normally appear.
- *
- * 4. The names "Xerces" and "Apache Software Foundation" must
- * not be used to endorse or promote products derived from this
- * software without prior written permission. For written
- * permission, please contact apache@apache.org.
- *
- * 5. Products derived from this software may not be called "Apache",
- * nor may "Apache" appear in their name, without prior written
- * permission of the Apache Software Foundation.
- *
- * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
- * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
- * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
- * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
- * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
- * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- * ====================================================================
- *
- * This software consists of voluntary contributions made by many
- * individuals on behalf of the Apache Software Foundation and was
- * originally based on software copyright (c) 1999, International
- * Business Machines, Inc., http://www.apache.org. For more
- * information on the Apache Software Foundation, please see
- * <http://www.apache.org/>.
- */
-
- package com.sun.org.apache.xerces.internal.impl;
-
- import java.util.Hashtable;
- import java.util.Locale;
-
- import com.sun.org.apache.xerces.internal.util.DefaultErrorHandler;
- import com.sun.org.apache.xerces.internal.util.ErrorHandlerProxy;
- import com.sun.org.apache.xerces.internal.util.MessageFormatter;
- import com.sun.org.apache.xerces.internal.xni.XMLLocator;
- import com.sun.org.apache.xerces.internal.xni.XNIException;
- import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
- import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
- import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
- import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler;
- import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException;
- import org.xml.sax.ErrorHandler;
-
- /**
- * This class is a common element of all parser configurations and is
- * used to report errors that occur. This component can be queried by
- * parser components from the component manager using the following
- * property ID:
- * <pre>
- * http://apache.org/xml/properties/internal/error-reporter
- * </pre>
- * <p>
- * Errors are separated into domains that categorize a class of errors.
- * In a parser configuration, the parser would register a
- * <code>MessageFormatter</code> for each domain that is capable of
- * localizing error messages and formatting them based on information
- * about the error. Any parser component can invent new error domains
- * and register additional message formatters to localize messages in
- * those domains.
- * <p>
- * This component requires the following features and properties from the
- * component manager that uses it:
- * <ul>
- * <li>http://apache.org/xml/properties/internal/error-handler</li>
- * </ul>
- * <p>
- * This component can use the following features and properties but they
- * are not required:
- * <ul>
- * <li>http://apache.org/xml/features/continue-after-fatal-error</li>
- * </ul>
- *
- * @see MessageFormatter
- *
- * @author Eric Ye, IBM
- * @author Andy Clark, IBM
- *
- * @version $Id: XMLErrorReporter.java,v 1.13 2004/01/26 17:28:12 mrglavas Exp $
- */
- public class XMLErrorReporter
- implements XMLComponent {
-
- //
- // Constants
- //
-
- // severity
-
- /**
- * Severity: warning. Warnings represent informational messages only
- * that should not be considered serious enough to stop parsing or
- * indicate an error in the document's validity.
- */
- public static final short SEVERITY_WARNING = 0;
-
- /**
- * Severity: error. Common causes of errors are document structure and/or
- * content that that does not conform to the grammar rules specified for
- * the document. These are typically validation errors.
- */
- public static final short SEVERITY_ERROR = 1;
-
- /**
- * Severity: fatal error. Fatal errors are errors in the syntax of the
- * XML document or invalid byte sequences for a given encoding. The
- * XML 1.0 Specification mandates that errors of this type are not
- * recoverable.
- * <p>
- * <strong>Note:</strong> The parser does have a "continue after fatal
- * error" feature but it should be used with extreme caution and care.
- */
- public static final short SEVERITY_FATAL_ERROR = 2;
-
- // feature identifiers
-
- /** Feature identifier: continue after fatal error. */
- protected static final String CONTINUE_AFTER_FATAL_ERROR =
- Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
-
- // property identifiers
-
- /** Property identifier: error handler. */
- protected static final String ERROR_HANDLER =
- Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
-
- // recognized features and properties
-
- /** Recognized features. */
- private static final String[] RECOGNIZED_FEATURES = {
- CONTINUE_AFTER_FATAL_ERROR,
- };
-
- /** Feature defaults. */
- private static final Boolean[] FEATURE_DEFAULTS = {
- null,
- };
-
- /** Recognized properties. */
- private static final String[] RECOGNIZED_PROPERTIES = {
- ERROR_HANDLER,
- };
-
- /** Property defaults. */
- private static final Object[] PROPERTY_DEFAULTS = {
- null,
- };
-
- //
- // Data
- //
-
- /** The locale to be used to format error messages. */
- protected Locale fLocale;
-
- /** Mapping of Message formatters for domains. */
- protected Hashtable fMessageFormatters;
-
- /** Error handler. */
- protected XMLErrorHandler fErrorHandler;
-
- /** Document locator. */
- protected XMLLocator fLocator;
-
- /** Continue after fatal error feature. */
- protected boolean fContinueAfterFatalError;
-
- /**
- * Default error handler. This error handler is only used in the
- * absence of a registered error handler so that errors are not
- * "swallowed" silently. This is one of the most common "problems"
- * reported by users of the parser.
- */
- protected XMLErrorHandler fDefaultErrorHandler;
-
- //
- // Constructors
- //
-
- /** Constructs an error reporter with a locator. */
- public XMLErrorReporter() {
-
- // REVISIT: [Q] Should the locator be passed to the reportError
- // method? Otherwise, there is no way for a parser
- // component to store information about where an
- // error occurred so as to report it later.
- //
- // An example would be to record the location of
- // IDREFs so that, at the end of the document, if
- // there is no associated ID declared, the error
- // could report the location information of the
- // reference. -Ac
- //
- // NOTE: I added another reportError method that allows the
- // caller to specify the location of the error being
- // reported. -Ac
-
- fMessageFormatters = new Hashtable();
-
- } // <init>()
-
- //
- // Methods
- //
-
- /**
- * Sets the current locale.
- *
- * @param locale The new locale.
- */
- public void setLocale(Locale locale) {
- fLocale = locale;
- } // setLocale(Locale)
-
- /**
- * Gets the current locale.
- *
- * @return the current Locale
- */
- public Locale getLocale() {
- return fLocale ;
- } // getLocale(): Locale
-
- /**
- * Sets the document locator.
- *
- * @param locator The locator.
- */
- public void setDocumentLocator(XMLLocator locator) {
- fLocator = locator;
- } // setDocumentLocator(XMLLocator)
-
- /**
- * Registers a message formatter for the specified domain.
- * <p>
- * <strong>Note:</strong> Registering a message formatter for a domain
- * when there is already a formatter registered will cause the previous
- * formatter to be lost. This method replaces any previously registered
- * message formatter for the specified domain.
- *
- * @param domain
- * @param messageFormatter
- */
- public void putMessageFormatter(String domain,
- MessageFormatter messageFormatter) {
- fMessageFormatters.put(domain, messageFormatter);
- } // putMessageFormatter(String,MessageFormatter)
-
- /**
- * Returns the message formatter associated with the specified domain,
- * or null if no message formatter is registered for that domain.
- *
- * @param domain The domain of the message formatter.
- */
- public MessageFormatter getMessageFormatter(String domain) {
- return (MessageFormatter)fMessageFormatters.get(domain);
- } // getMessageFormatter(String):MessageFormatter
-
- /**
- * Removes the message formatter for the specified domain and
- * returns the removed message formatter.
- *
- * @param domain The domain of the message formatter.
- */
- public MessageFormatter removeMessageFormatter(String domain) {
- return (MessageFormatter) fMessageFormatters.remove(domain);
- } // removeMessageFormatter(String):MessageFormatter
-
- /**
- * Reports an error. The error message passed to the error handler
- * is formatted for the locale by the message formatter installed
- * for the specified error domain.
- *
- * @param domain The error domain.
- * @param key The key of the error message.
- * @param arguments The replacement arguments for the error message,
- * if needed.
- * @param severity The severity of the error.
- *
- * @see #SEVERITY_WARNING
- * @see #SEVERITY_ERROR
- * @see #SEVERITY_FATAL_ERROR
- */
- public void reportError(String domain, String key, Object[] arguments,
- short severity) throws XNIException {
- reportError(fLocator, domain, key, arguments, severity);
- } // reportError(String,String,Object[],short)
-
- /**
- * Reports an error at a specific location.
- *
- * @param location The error location.
- * @param domain The error domain.
- * @param key The key of the error message.
- * @param arguments The replacement arguments for the error message,
- * if needed.
- * @param severity The severity of the error.
- *
- * @see #SEVERITY_WARNING
- * @see #SEVERITY_ERROR
- * @see #SEVERITY_FATAL_ERROR
- */
- public void reportError(XMLLocator location,
- String domain, String key, Object[] arguments,
- short severity) throws XNIException {
-
- // REVISIT: [Q] Should we do anything about invalid severity
- // parameter? -Ac
-
- // format error message and create parse exception
- MessageFormatter messageFormatter = getMessageFormatter(domain);
- String message;
- if (messageFormatter != null) {
- message = messageFormatter.formatMessage(fLocale, key, arguments);
- }
- else {
- StringBuffer str = new StringBuffer();
- str.append(domain);
- str.append('#');
- str.append(key);
- int argCount = arguments != null ? arguments.length : 0;
- if (argCount > 0) {
- str.append('?');
- for (int i = 0; i < argCount; i++) {
- str.append(arguments[i]);
- if (i < argCount -1) {
- str.append('&');
- }
- }
- }
- message = str.toString();
- }
- XMLParseException parseException =
- new XMLParseException(location, message);
-
- // get error handler
- XMLErrorHandler errorHandler = fErrorHandler;
- if (errorHandler == null) {
- if (fDefaultErrorHandler == null) {
- fDefaultErrorHandler = new DefaultErrorHandler();
- }
- errorHandler = fDefaultErrorHandler;
- }
-
- // call error handler
- switch (severity) {
- case SEVERITY_WARNING: {
- errorHandler.warning(domain, key, parseException);
- break;
- }
- case SEVERITY_ERROR: {
- errorHandler.error(domain, key, parseException);
- break;
- }
- case SEVERITY_FATAL_ERROR: {
- errorHandler.fatalError(domain, key, parseException);
- if (!fContinueAfterFatalError) {
- throw parseException;
- }
- break;
- }
- }
-
- } // reportError(XMLLocator,String,String,Object[],short)
-
- //
- // XMLComponent methods
- //
-
- /**
- * Resets the component. The component can query the component manager
- * about any features and properties that affect the operation of the
- * component.
- *
- * @param componentManager The component manager.
- *
- * @throws SAXException Thrown by component on initialization error.
- * For example, if a feature or property is
- * required for the operation of the component, the
- * component manager may throw a
- * SAXNotRecognizedException or a
- * SAXNotSupportedException.
- */
- public void reset(XMLComponentManager componentManager)
- throws XNIException {
-
- // features
- try {
- fContinueAfterFatalError = componentManager.getFeature(CONTINUE_AFTER_FATAL_ERROR);
- }
- catch (XNIException e) {
- fContinueAfterFatalError = false;
- }
-
- // properties
- fErrorHandler = (XMLErrorHandler)componentManager.getProperty(ERROR_HANDLER);
-
- } // reset(XMLComponentManager)
-
- /**
- * Returns a list of feature identifiers that are recognized by
- * this component. This method may return null if no features
- * are recognized by this component.
- */
- public String[] getRecognizedFeatures() {
- return (String[])(RECOGNIZED_FEATURES.clone());
- } // getRecognizedFeatures():String[]
-
- /**
- * Sets the state of a feature. This method is called by the component
- * manager any time after reset when a feature changes state.
- * <p>
- * <strong>Note:</strong> Components should silently ignore features
- * that do not affect the operation of the component.
- *
- * @param featureId The feature identifier.
- * @param state The state of the feature.
- *
- * @throws SAXNotRecognizedException The component should not throw
- * this exception.
- * @throws SAXNotSupportedException The component should not throw
- * this exception.
- */
- public void setFeature(String featureId, boolean state)
- throws XMLConfigurationException {
-
- //
- // Xerces features
- //
-
- if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
- final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
-
- //
- // http://apache.org/xml/features/continue-after-fatal-error
- // Allows the parser to continue after a fatal error.
- // Normally, a fatal error would stop the parse.
- //
- if (suffixLength == Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE.length() &&
- featureId.endsWith(Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE)) {
- fContinueAfterFatalError = state;
- }
- }
-
- } // setFeature(String,boolean)
-
- // return state of given feature or false if unsupported.
- public boolean getFeature(String featureId)
- throws XMLConfigurationException {
-
- //
- // Xerces features
- //
-
- if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
- final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
-
- //
- // http://apache.org/xml/features/continue-after-fatal-error
- // Allows the parser to continue after a fatal error.
- // Normally, a fatal error would stop the parse.
- //
- if (suffixLength == Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE.length() &&
- featureId.endsWith(Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE)) {
- return fContinueAfterFatalError ;
- }
- }
- return false;
-
- } // setFeature(String,boolean)
-
- /**
- * Returns a list of property identifiers that are recognized by
- * this component. This method may return null if no properties
- * are recognized by this component.
- */
- public String[] getRecognizedProperties() {
- return (String[])(RECOGNIZED_PROPERTIES.clone());
- } // getRecognizedProperties():String[]
-
- /**
- * Sets the value of a property. This method is called by the component
- * manager any time after reset when a property changes value.
- * <p>
- * <strong>Note:</strong> Components should silently ignore properties
- * that do not affect the operation of the component.
- *
- * @param propertyId The property identifier.
- * @param value The value of the property.
- *
- * @throws SAXNotRecognizedException The component should not throw
- * this exception.
- * @throws SAXNotSupportedException The component should not throw
- * this exception.
- */
- public void setProperty(String propertyId, Object value)
- throws XMLConfigurationException {
-
- //
- // Xerces properties
- //
-
- if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
- final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
-
- if (suffixLength == Constants.ERROR_HANDLER_PROPERTY.length() &&
- propertyId.endsWith(Constants.ERROR_HANDLER_PROPERTY)) {
- fErrorHandler = (XMLErrorHandler)value;
- }
- }
-
- } // setProperty(String,Object)
-
- /**
- * Returns the default state for a feature, or null if this
- * component does not want to report a default value for this
- * feature.
- *
- * @param featureId The feature identifier.
- *
- * @since Xerces 2.2.0
- */
- public Boolean getFeatureDefault(String featureId) {
- for (int i = 0; i < RECOGNIZED_FEATURES.length; i++) {
- if (RECOGNIZED_FEATURES[i].equals(featureId)) {
- return FEATURE_DEFAULTS[i];
- }
- }
- return null;
- } // getFeatureDefault(String):Boolean
-
- /**
- * Returns the default state for a property, or null if this
- * component does not want to report a default value for this
- * property.
- *
- * @param propertyId The property identifier.
- *
- * @since Xerces 2.2.0
- */
- public Object getPropertyDefault(String propertyId) {
- for (int i = 0; i < RECOGNIZED_PROPERTIES.length; i++) {
- if (RECOGNIZED_PROPERTIES[i].equals(propertyId)) {
- return PROPERTY_DEFAULTS[i];
- }
- }
- return null;
- } // getPropertyDefault(String):Object
-
- /**
- * Get the internal XMLErrrorHandler.
- */
- public XMLErrorHandler getErrorHandler() {
- return fErrorHandler;
- }
-
-
- private ErrorHandler fSaxProxy = null;
-
- /**
- * Gets the internal XMLErrorHandler
- * as SAX ErrorHandler.
- */
- public ErrorHandler getSAXErrorHandler() {
- if( fSaxProxy==null )
- fSaxProxy = new ErrorHandlerProxy() {
- protected XMLErrorHandler getErrorHandler() {
- return fErrorHandler;
- }
- };
- return fSaxProxy;
- }
- } // class XMLErrorReporter