/*
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
*/
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.sun.org.apache.xerces.internal.impl;
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 java.util.HashMap;
import java.util.Locale;
import java.util.Map;
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:
http://apache.org/xml/properties/internal/error-reporter
Errors are separated into domains that categorize a class of errors.
In a parser configuration, the parser would register a
MessageFormatter
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.
This component requires the following features and properties from the
component manager that uses it:
- http://apache.org/xml/properties/internal/error-handler
This component can use the following features and properties but they
are not required:
- http://apache.org/xml/features/continue-after-fatal-error
Author: Eric Ye, IBM, Andy Clark, IBM See Also: @xerces.internal @LastModified : Nov 2017
/**
* 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>
*
* @xerces.internal
*
* @see MessageFormatter
*
* @author Eric Ye, IBM
* @author Andy Clark, IBM
*
* @LastModified: Nov 2017
*/
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.
/**
* 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.
/**
* 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.
Note: The parser does have a "continue after fatal
error" feature but it should be used with extreme caution and care.
/**
* 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. /** 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. /** Property identifier: error handler. */
protected static final String ERROR_HANDLER =
Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
// recognized features and properties
Recognized features. /** Recognized features. */
private static final String[] RECOGNIZED_FEATURES = {
CONTINUE_AFTER_FATAL_ERROR,
};
Feature defaults. /** Feature defaults. */
private static final Boolean[] FEATURE_DEFAULTS = {
null,
};
Recognized properties. /** Recognized properties. */
private static final String[] RECOGNIZED_PROPERTIES = {
ERROR_HANDLER,
};
Property defaults. /** Property defaults. */
private static final Object[] PROPERTY_DEFAULTS = {
null,
};
//
// Data
//
The locale to be used to format error messages. /** The locale to be used to format error messages. */
protected Locale fLocale;
Mapping of Message formatters for domains. /** Mapping of Message formatters for domains. */
protected Map<String, MessageFormatter> fMessageFormatters;
Error handler. /** Error handler. */
protected XMLErrorHandler fErrorHandler;
Document locator. /** Document locator. */
protected XMLLocator fLocator;
Continue after fatal error feature. /** 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.
/**
* 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;
A SAX proxy to the error handler contained in this error reporter. /** A SAX proxy to the error handler contained in this error reporter. */
private ErrorHandler fSaxProxy = null;
//
// Constructors
//
Constructs an error reporter with a locator. /** 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 HashMap<>();
} // <init>()
//
// Methods
//
Sets the current locale.
Params: - locale – The new locale.
/**
* Sets the current locale.
*
* @param locale The new locale.
*/
public void setLocale(Locale locale) {
fLocale = locale;
} // setLocale(Locale)
Gets the current locale.
Returns: the current Locale
/**
* Gets the current locale.
*
* @return the current Locale
*/
public Locale getLocale() {
return fLocale ;
} // getLocale(): Locale
Sets the document locator.
Params: - locator – The locator.
/**
* 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.
Note: 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.
Params: - domain –
- messageFormatter –
/**
* 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.
Params: - domain – The domain of the message formatter.
/**
* 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 fMessageFormatters.get(domain);
} // getMessageFormatter(String):MessageFormatter
Removes the message formatter for the specified domain and
returns the removed message formatter.
Params: - domain – The domain of the message formatter.
/**
* 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 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.
Params: - domain – The error domain.
- key – The key of the error message.
- arguments – The replacement arguments for the error message,
if needed.
- severity – The severity of the error.
See Also: Returns: The formatted error message.
/**
* 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.
* @return The formatted error message.
*
* @see #SEVERITY_WARNING
* @see #SEVERITY_ERROR
* @see #SEVERITY_FATAL_ERROR
*/
public String reportError(String domain, String key, Object[] arguments,
short severity) throws XNIException {
return reportError(fLocator, domain, key, arguments, severity);
} // reportError(String,String,Object[],short):String
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.
Params: - domain – The error domain.
- key – The key of the error message.
- arguments – The replacement arguments for the error message,
if needed.
- severity – The severity of the error.
- exception – The exception to wrap.
See Also: Returns: The formatted error message.
/**
* 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.
* @param exception The exception to wrap.
* @return The formatted error message.
*
* @see #SEVERITY_WARNING
* @see #SEVERITY_ERROR
* @see #SEVERITY_FATAL_ERROR
*/
public String reportError(String domain, String key, Object[] arguments,
short severity, Exception exception) throws XNIException {
return reportError(fLocator, domain, key, arguments, severity, exception);
} // reportError(String,String,Object[],short,Exception):String
Reports an error at a specific location.
Params: - location – The error location.
- domain – The error domain.
- key – The key of the error message.
- arguments – The replacement arguments for the error message,
if needed.
- severity – The severity of the error.
See Also: Returns: The formatted error message.
/**
* 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.
* @return The formatted error message.
*
* @see #SEVERITY_WARNING
* @see #SEVERITY_ERROR
* @see #SEVERITY_FATAL_ERROR
*/
public String reportError(XMLLocator location,
String domain, String key, Object[] arguments,
short severity) throws XNIException {
return reportError(location, domain, key, arguments, severity, null);
} // reportError(XMLLocator,String,String,Object[],short):String
Reports an error at a specific location.
Params: - location – The error location.
- domain – The error domain.
- key – The key of the error message.
- arguments – The replacement arguments for the error message,
if needed.
- severity – The severity of the error.
- exception – The exception to wrap.
See Also: Returns: The formatted error message.
/**
* 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.
* @param exception The exception to wrap.
* @return The formatted error message.
*
* @see #SEVERITY_WARNING
* @see #SEVERITY_ERROR
* @see #SEVERITY_FATAL_ERROR
*/
public String reportError(XMLLocator location,
String domain, String key, Object[] arguments,
short severity, Exception exception) 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 = (exception != null) ?
new XMLParseException(location, message, exception) :
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;
}
}
return message;
} // reportError(XMLLocator,String,String,Object[],short,Exception):String
//
// XMLComponent methods
//
Resets the component. The component can query the component manager
about any features and properties that affect the operation of the
component.
Params: - 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.
/**
* 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
fContinueAfterFatalError = componentManager.getFeature(CONTINUE_AFTER_FATAL_ERROR, 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.
/**
* 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 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.
Note: Components should silently ignore features
that do not affect the operation of the component.
Params: - featureId – The feature identifier.
- state – The state of the feature.
Throws: - SAXNotRecognizedException – The component should not throw
this exception.
- SAXNotSupportedException – The component should not throw
this exception.
/**
* 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.
/**
* 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 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.
Note: Components should silently ignore properties
that do not affect the operation of the component.
Params: - propertyId – The property identifier.
- value – The value of the property.
Throws: - SAXNotRecognizedException – The component should not throw
this exception.
- SAXNotSupportedException – The component should not throw
this exception.
/**
* 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.
Params: - featureId – The feature identifier.
Since: Xerces 2.2.0
/**
* 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.
Params: - propertyId – The property identifier.
Since: Xerces 2.2.0
/**
* 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.
/**
* Get the internal XMLErrrorHandler.
*/
public XMLErrorHandler getErrorHandler() {
return fErrorHandler;
}
Gets the internal XMLErrorHandler
as SAX ErrorHandler.
/**
* 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