/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2000-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) 2001, International
* Business Machines, Inc., http://www.apache.org. For more
* information on the Apache Software Foundation, please see
* .
*/
package com.sun.org.apache.xerces.internal.parsers;
import java.io.StringReader;
import java.util.Locale;
import java.util.Stack;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.Locale;
import com.sun.org.apache.xerces.internal.dom.DOMErrorImpl;
import com.sun.org.apache.xerces.internal.dom.DOMMessageFormatter;
import com.sun.org.apache.xerces.internal.dom.DOMStringListImpl;
import org.w3c.dom.DOMError;
import com.sun.org.apache.xerces.internal.impl.Constants;
import com.sun.org.apache.xerces.internal.util.DOMEntityResolverWrapper;
import com.sun.org.apache.xerces.internal.util.DOMErrorHandlerWrapper;
import com.sun.org.apache.xerces.internal.util.SymbolTable;
import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
import org.w3c.dom.DOMConfiguration;
import org.w3c.dom.DOMErrorHandler;
import org.w3c.dom.DOMException;
import org.w3c.dom.Document;
import org.w3c.dom.DOMStringList;
import org.w3c.dom.Node;
import org.w3c.dom.ls.LSException;
import org.w3c.dom.ls.LSParser;
import org.w3c.dom.ls.LSParserFilter;
import org.w3c.dom.ls.LSResourceResolver;
import org.w3c.dom.ls.LSInput;
/**
* This is Xerces DOM Builder class. It uses the abstract DOM
* parser with a document scanner, a dtd scanner, and a validator, as
* well as a grammar pool.
*
* @author Pavani Mukthipudi, Sun Microsystems Inc.
* @author Elena Litani, IBM
* @author Rahul Srivastava, Sun Microsystems Inc.
* @version $Id: DOMParserImpl.java,v 1.25 2004/04/23 16:06:10 mrglavas Exp $
*/
public class DOMParserImpl
extends AbstractDOMParser implements LSParser, DOMConfiguration {
// SAX & Xerces feature ids
/** Feature identifier: namespaces. */
protected static final String NAMESPACES =
Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
/** Feature id: validation. */
protected static final String VALIDATION_FEATURE =
Constants.SAX_FEATURE_PREFIX+Constants.VALIDATION_FEATURE;
/** XML Schema validation */
protected static final String XMLSCHEMA =
Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
/** Dynamic validation */
protected static final String DYNAMIC_VALIDATION =
Constants.XERCES_FEATURE_PREFIX + Constants.DYNAMIC_VALIDATION_FEATURE;
/** Feature identifier: expose schema normalized value */
protected static final String NORMALIZE_DATA =
Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE;
/** Feature identifier: disallow docType Decls. */
protected static final String DISALLOW_DOCTYPE_DECL_FEATURE =
Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE;
// internal properties
protected static final String SYMBOL_TABLE =
Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
protected static final String PSVI_AUGMENT =
Constants.XERCES_FEATURE_PREFIX +Constants.SCHEMA_AUGMENT_PSVI;
Thread currentThread = null;
//
// Data
//
// REVISIT: this value should be null by default and should be set during creation of
// LSParser
protected String fSchemaType = null;
protected boolean fBusy = false;
protected final static boolean DEBUG = false;
private Vector fSchemaLocations = new Vector ();
private String fSchemaLocation = null;
private DOMStringList fRecognizedParameters;
private boolean abortNow = false;
//
// Constructors
//
/**
* Constructs a DOM Builder using the standard parser configuration.
*/
public DOMParserImpl (String configuration, String schemaType) {
this (
(XMLParserConfiguration) ObjectFactory.createObject (
"com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration",
configuration));
if (schemaType != null) {
if (schemaType.equals (Constants.NS_DTD)) {
fConfiguration.setFeature (
Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE,
false);
fConfiguration.setProperty (
Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE,
Constants.NS_DTD);
fSchemaType = Constants.NS_DTD;
}
else if (schemaType.equals (Constants.NS_XMLSCHEMA)) {
// XML Schem validation
fConfiguration.setProperty (
Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE,
Constants.NS_XMLSCHEMA);
}
}
}
/**
* Constructs a DOM Builder using the specified parser configuration.
*/
public DOMParserImpl (XMLParserConfiguration config) {
super (config);
// add recognized features
final String[] domRecognizedFeatures = {
Constants.DOM_CANONICAL_FORM,
Constants.DOM_CDATA_SECTIONS,
Constants.DOM_CHARSET_OVERRIDES_XML_ENCODING,
Constants.DOM_INFOSET,
Constants.DOM_NAMESPACE_DECLARATIONS,
Constants.DOM_SPLIT_CDATA,
Constants.DOM_SUPPORTED_MEDIATYPES_ONLY,
Constants.DOM_CERTIFIED,
Constants.DOM_WELLFORMED,
Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS,
};
fConfiguration.addRecognizedFeatures (domRecognizedFeatures);
// turn off deferred DOM
fConfiguration.setFeature (DEFER_NODE_EXPANSION, false);
// Set values so that the value of the
// infoset parameter is true (its default value).
//
// true: namespace-declarations, well-formed,
// element-content-whitespace, comments, namespaces
//
// false: validate-if-schema, entities,
// datatype-normalization, cdata-sections
fConfiguration.setFeature(Constants.DOM_NAMESPACE_DECLARATIONS, true);
fConfiguration.setFeature(Constants.DOM_WELLFORMED, true);
fConfiguration.setFeature(INCLUDE_COMMENTS_FEATURE, true);
fConfiguration.setFeature(INCLUDE_IGNORABLE_WHITESPACE, true);
fConfiguration.setFeature(NAMESPACES, true);
fConfiguration.setFeature(DYNAMIC_VALIDATION, false);
fConfiguration.setFeature(CREATE_ENTITY_REF_NODES, false);
fConfiguration.setFeature(NORMALIZE_DATA, false);
fConfiguration.setFeature(CREATE_CDATA_NODES_FEATURE, false);
// set other default values
fConfiguration.setFeature (Constants.DOM_CANONICAL_FORM, false);
fConfiguration.setFeature (Constants.DOM_CHARSET_OVERRIDES_XML_ENCODING, true);
fConfiguration.setFeature (Constants.DOM_SPLIT_CDATA, true);
fConfiguration.setFeature (Constants.DOM_SUPPORTED_MEDIATYPES_ONLY, false);
fConfiguration.setFeature (Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS, true);
// REVISIT: by default Xerces assumes that input is certified.
// default is different from the one specified in the DOM spec
fConfiguration.setFeature (Constants.DOM_CERTIFIED, true);
// Xerces datatype-normalization feature is on by default
fConfiguration.setFeature( NORMALIZE_DATA, false );
} // (XMLParserConfiguration)
/**
* Constructs a DOM Builder using the specified symbol table.
*/
public DOMParserImpl(SymbolTable symbolTable) {
this(
(XMLParserConfiguration) ObjectFactory.createObject(
"com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration",
"com.sun.org.apache.xerces.internal.parsers.XIncludeParserConfiguration"));
fConfiguration.setProperty(
Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY,
symbolTable);
} // (SymbolTable)
/**
* Constructs a DOM Builder using the specified symbol table and
* grammar pool.
*/
public DOMParserImpl(SymbolTable symbolTable, XMLGrammarPool grammarPool) {
this(
(XMLParserConfiguration) ObjectFactory.createObject(
"com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration",
"com.sun.org.apache.xerces.internal.parsers.XIncludeParserConfiguration"));
fConfiguration.setProperty(
Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY,
symbolTable);
fConfiguration.setProperty(
Constants.XERCES_PROPERTY_PREFIX
+ Constants.XMLGRAMMAR_POOL_PROPERTY,
grammarPool);
}
/**
* Resets the parser state.
*
* @throws SAXException Thrown on initialization error.
*/
public void reset() {
super.reset();
// DOM Filter
if (fSkippedElemStack!=null) {
fSkippedElemStack.removeAllElements();
}
fSchemaLocations.clear();
fRejectedElement.clear();
fFilterReject = false;
fSchemaType = null;
} // reset()
//
// DOMParser methods
//
public DOMConfiguration getDomConfig (){
return this;
}
/**
* When the application provides a filter, the parser will call out to
* the filter at the completion of the construction of each
* Element
node. The filter implementation can choose to
* remove the element from the document being constructed (unless the
* element is the document element) or to terminate the parse early. If
* the document is being validated when it's loaded the validation
* happens before the filter is called.
*/
public LSParserFilter getFilter() {
return fDOMFilter;
}
/**
* When the application provides a filter, the parser will call out to
* the filter at the completion of the construction of each
* Element
node. The filter implementation can choose to
* remove the element from the document being constructed (unless the
* element is the document element) or to terminate the parse early. If
* the document is being validated when it's loaded the validation
* happens before the filter is called.
*/
public void setFilter(LSParserFilter filter) {
fDOMFilter = filter;
if (fSkippedElemStack == null) {
fSkippedElemStack = new Stack();
}
}
/**
* Set parameters and properties
*/
public void setParameter (String name, Object value) throws DOMException {
// set features
if(value instanceof Boolean){
boolean state = ((Boolean)value).booleanValue ();
try {
if (name.equalsIgnoreCase (Constants.DOM_COMMENTS)) {
fConfiguration.setFeature (INCLUDE_COMMENTS_FEATURE, state);
}
else if (name.equalsIgnoreCase (Constants.DOM_DATATYPE_NORMALIZATION)) {
fConfiguration.setFeature (NORMALIZE_DATA, state);
}
else if (name.equalsIgnoreCase (Constants.DOM_ENTITIES)) {
fConfiguration.setFeature (CREATE_ENTITY_REF_NODES, state);
}
else if (name.equalsIgnoreCase (Constants.DOM_DISALLOW_DOCTYPE)) {
fConfiguration.setFeature (DISALLOW_DOCTYPE_DECL_FEATURE, state);
}
else if (name.equalsIgnoreCase (Constants.DOM_SUPPORTED_MEDIATYPES_ONLY)
|| name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)
|| name.equalsIgnoreCase (Constants.DOM_CHECK_CHAR_NORMALIZATION)
|| name.equalsIgnoreCase (Constants.DOM_CANONICAL_FORM)) {
if (state) { // true is not supported
String msg =
DOMMessageFormatter.formatMessage (
DOMMessageFormatter.DOM_DOMAIN,
"FEATURE_NOT_SUPPORTED",
new Object[] { name });
throw new DOMException (DOMException.NOT_SUPPORTED_ERR, msg);
}
// setting those features to false is no-op
}
else if (name.equalsIgnoreCase (Constants.DOM_NAMESPACES)) {
fConfiguration.setFeature (NAMESPACES, state);
}
else if (name.equalsIgnoreCase (Constants.DOM_INFOSET)) {
// Setting false has no effect.
if (state) {
// true: namespaces, comments, element-content-whitespace
fConfiguration.setFeature(NAMESPACES, true);
fConfiguration.setFeature(INCLUDE_COMMENTS_FEATURE, true);
fConfiguration.setFeature(INCLUDE_IGNORABLE_WHITESPACE, true);
// false: validate-if-schema, entities,
// datatype-normalization, cdata-sections
fConfiguration.setFeature(DYNAMIC_VALIDATION, false);
fConfiguration.setFeature(CREATE_ENTITY_REF_NODES, false);
fConfiguration.setFeature(NORMALIZE_DATA, false);
fConfiguration.setFeature(CREATE_CDATA_NODES_FEATURE, false);
}
}
else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)) {
fConfiguration.setFeature(CREATE_CDATA_NODES_FEATURE, state);
}
else if (name.equalsIgnoreCase (Constants.DOM_NAMESPACE_DECLARATIONS)
|| name.equalsIgnoreCase (Constants.DOM_WELLFORMED)
|| name.equalsIgnoreCase (Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) {
if (!state) { // false is not supported
String msg =
DOMMessageFormatter.formatMessage (
DOMMessageFormatter.DOM_DOMAIN,
"FEATURE_NOT_SUPPORTED",
new Object[] { name });
throw new DOMException (DOMException.NOT_SUPPORTED_ERR, msg);
}
// setting these features to true is no-op
// REVISIT: implement "namespace-declaration" feature
}
else if (name.equalsIgnoreCase (Constants.DOM_VALIDATE)) {
fConfiguration.setFeature (VALIDATION_FEATURE, state);
if (fSchemaType != Constants.NS_DTD) {
fConfiguration.setFeature (XMLSCHEMA, state);
}
if (state){
fConfiguration.setFeature (DYNAMIC_VALIDATION, false);
}
}
else if (name.equalsIgnoreCase (Constants.DOM_VALIDATE_IF_SCHEMA)) {
fConfiguration.setFeature (DYNAMIC_VALIDATION, state);
// Note: validation and dynamic validation are mutually exclusive
if (state){
fConfiguration.setFeature(VALIDATION_FEATURE, false);
}
}
else if (name.equalsIgnoreCase (Constants.DOM_ELEMENT_CONTENT_WHITESPACE)) {
fConfiguration.setFeature (INCLUDE_IGNORABLE_WHITESPACE, state);
}
else if (name.equalsIgnoreCase (Constants.DOM_PSVI)){
//XSModel - turn on PSVI augmentation
fConfiguration.setFeature(PSVI_AUGMENT, true);
fConfiguration.setProperty(DOCUMENT_CLASS_NAME,
"com.sun.org.apache.xerces.internal.dom.PSVIDocumentImpl");
}
else {
// Constants.DOM_CHARSET_OVERRIDES_XML_ENCODING feature,
// Constants.DOM_SPLIT_CDATA feature,
// or any Xerces feature
fConfiguration.setFeature (name.toLowerCase(Locale.ENGLISH), state);
}
}
catch (XMLConfigurationException e) {
String msg =
DOMMessageFormatter.formatMessage (
DOMMessageFormatter.DOM_DOMAIN,
"FEATURE_NOT_FOUND",
new Object[] { name });
throw new DOMException (DOMException.NOT_FOUND_ERR, msg);
}
}
else { // set properties
if (name.equalsIgnoreCase (Constants.DOM_ERROR_HANDLER)) {
if (value instanceof DOMErrorHandler || value == null) {
try {
fErrorHandler = new DOMErrorHandlerWrapper ((DOMErrorHandler) value);
fConfiguration.setProperty (ERROR_HANDLER, fErrorHandler);
}
catch (XMLConfigurationException e) {}
}
else {
// REVISIT: type mismatch
String msg =
DOMMessageFormatter.formatMessage (
DOMMessageFormatter.DOM_DOMAIN,
"TYPE_MISMATCH_ERR",
new Object[] { name });
throw new DOMException (DOMException.NOT_SUPPORTED_ERR, msg);
}
}
else if (name.equalsIgnoreCase (Constants.DOM_RESOURCE_RESOLVER)) {
if (value instanceof LSResourceResolver || value == null) {
try {
fConfiguration.setProperty (ENTITY_RESOLVER, new DOMEntityResolverWrapper ((LSResourceResolver) value));
}
catch (XMLConfigurationException e) {}
}
else {
// REVISIT: type mismatch
String msg =
DOMMessageFormatter.formatMessage (
DOMMessageFormatter.DOM_DOMAIN,
"TYPE_MISMATCH_ERR",
new Object[] { name });
throw new DOMException (DOMException.NOT_SUPPORTED_ERR, msg);
}
}
else if (name.equalsIgnoreCase (Constants.DOM_SCHEMA_LOCATION)) {
if (value instanceof String || value == null) {
try {
if (value == null) {
fConfiguration.setProperty (
Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
null);
}
else if (fSchemaType == Constants.NS_XMLSCHEMA) {
fSchemaLocation = (String)value;
// map DOM schema-location to JAXP schemaSource property
// tokenize location string
StringTokenizer t = new StringTokenizer (fSchemaLocation, " \n\t\r");
if (t.hasMoreTokens ()){
fSchemaLocations.clear ();
fSchemaLocations.add (t.nextToken ());
while (t.hasMoreTokens ()) {
fSchemaLocations.add (t.nextToken ());
}
fConfiguration.setProperty (
Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
fSchemaLocations.toArray ());
}
else {
fConfiguration.setProperty (
Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
value);
}
}
else {
// REVISIT: allow pre-parsing DTD grammars
String msg =
DOMMessageFormatter.formatMessage (
DOMMessageFormatter.DOM_DOMAIN,
"FEATURE_NOT_SUPPORTED",
new Object[] { name });
throw new DOMException (DOMException.NOT_SUPPORTED_ERR, msg);
}
}
catch (XMLConfigurationException e) {}
}
else {
// REVISIT: type mismatch
String msg =
DOMMessageFormatter.formatMessage (
DOMMessageFormatter.DOM_DOMAIN,
"TYPE_MISMATCH_ERR",
new Object[] { name });
throw new DOMException (DOMException.NOT_SUPPORTED_ERR, msg);
}
}
else if (name.equalsIgnoreCase (Constants.DOM_SCHEMA_TYPE)) {
if (value instanceof String || value == null) {
try {
if (value == null) {
// turn off schema feature
fConfiguration.setFeature (
Constants.XERCES_FEATURE_PREFIX
+ Constants.SCHEMA_VALIDATION_FEATURE,
false);
// map to JAXP schemaLanguage
fConfiguration.setProperty ( Constants.JAXP_PROPERTY_PREFIX
+ Constants.SCHEMA_LANGUAGE,
null);
fSchemaType = null;
}
else if (value.equals (Constants.NS_XMLSCHEMA)) {
// turn on schema feature
fConfiguration.setFeature (Constants.XERCES_FEATURE_PREFIX
+ Constants.SCHEMA_VALIDATION_FEATURE,
true);
// map to JAXP schemaLanguage
fConfiguration.setProperty ( Constants.JAXP_PROPERTY_PREFIX
+ Constants.SCHEMA_LANGUAGE,
Constants.NS_XMLSCHEMA);
fSchemaType = Constants.NS_XMLSCHEMA;
}
else if (value.equals (Constants.NS_DTD)) {
// turn off schema feature
fConfiguration.setFeature (
Constants.XERCES_FEATURE_PREFIX
+ Constants.SCHEMA_VALIDATION_FEATURE,
false);
// map to JAXP schemaLanguage
fConfiguration.setProperty ( Constants.JAXP_PROPERTY_PREFIX
+ Constants.SCHEMA_LANGUAGE,
Constants.NS_DTD);
fSchemaType = Constants.NS_DTD;
}
}
catch (XMLConfigurationException e) {}
}
else {
String msg =
DOMMessageFormatter.formatMessage (
DOMMessageFormatter.DOM_DOMAIN,
"TYPE_MISMATCH_ERR",
new Object[] { name });
throw new DOMException (DOMException.NOT_SUPPORTED_ERR, msg);
}
}
else if (name.equalsIgnoreCase (DOCUMENT_CLASS_NAME)) {
fConfiguration.setProperty (DOCUMENT_CLASS_NAME, value);
}
else {
// REVISIT: check if this is a boolean parameter -- type mismatch should be thrown.
//parameter is not recognized
String msg =
DOMMessageFormatter.formatMessage (
DOMMessageFormatter.DOM_DOMAIN,
"FEATURE_NOT_FOUND",
new Object[] { name });
throw new DOMException (DOMException.NOT_FOUND_ERR, msg);
}
}
}
/**
* Look up the value of a feature or a property.
*/
public Object getParameter (String name) throws DOMException {
if (name.equalsIgnoreCase (Constants.DOM_COMMENTS)) {
return (fConfiguration.getFeature (INCLUDE_COMMENTS_FEATURE))
? Boolean.TRUE
: Boolean.FALSE;
}
else if (name.equalsIgnoreCase (Constants.DOM_DATATYPE_NORMALIZATION)) {
return (fConfiguration.getFeature (NORMALIZE_DATA))
? Boolean.TRUE
: Boolean.FALSE;
}
else if (name.equalsIgnoreCase (Constants.DOM_ENTITIES)) {
return (fConfiguration.getFeature (CREATE_ENTITY_REF_NODES))
? Boolean.TRUE
: Boolean.FALSE;
}
else if (name.equalsIgnoreCase (Constants.DOM_NAMESPACES)) {
return (fConfiguration.getFeature (NAMESPACES))
? Boolean.TRUE
: Boolean.FALSE;
}
else if (name.equalsIgnoreCase (Constants.DOM_VALIDATE)) {
return (fConfiguration.getFeature (VALIDATION_FEATURE))
? Boolean.TRUE
: Boolean.FALSE;
}
else if (name.equalsIgnoreCase (Constants.DOM_VALIDATE_IF_SCHEMA)) {
return (fConfiguration.getFeature (DYNAMIC_VALIDATION))
? Boolean.TRUE
: Boolean.FALSE;
}
else if (name.equalsIgnoreCase (Constants.DOM_ELEMENT_CONTENT_WHITESPACE)) {
return (fConfiguration.getFeature (INCLUDE_IGNORABLE_WHITESPACE))
? Boolean.TRUE
: Boolean.FALSE;
}
else if (name.equalsIgnoreCase (Constants.DOM_DISALLOW_DOCTYPE)) {
return (fConfiguration.getFeature (DISALLOW_DOCTYPE_DECL_FEATURE))
? Boolean.TRUE
: Boolean.FALSE;
}
else if (name.equalsIgnoreCase (Constants.DOM_INFOSET)) {
// REVISIT: This is somewhat expensive to compute
// but it's possible that the user has a reference
// to the configuration and is changing the values
// of these features directly on it.
boolean infoset = fConfiguration.getFeature(NAMESPACES) &&
fConfiguration.getFeature(INCLUDE_COMMENTS_FEATURE) &&
fConfiguration.getFeature(INCLUDE_IGNORABLE_WHITESPACE) &&
!fConfiguration.getFeature(DYNAMIC_VALIDATION) &&
!fConfiguration.getFeature(CREATE_ENTITY_REF_NODES) &&
!fConfiguration.getFeature(NORMALIZE_DATA) &&
!fConfiguration.getFeature(CREATE_CDATA_NODES_FEATURE);
return (infoset) ? Boolean.TRUE : Boolean.FALSE;
}
else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)) {
return (fConfiguration.getFeature(CREATE_CDATA_NODES_FEATURE))
? Boolean.TRUE : Boolean.FALSE;
}
else if (name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION ) ||
name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)){
return Boolean.FALSE;
}
else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)
|| name.equalsIgnoreCase (Constants.DOM_WELLFORMED)
|| name.equalsIgnoreCase (Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)
|| name.equalsIgnoreCase (Constants.DOM_CANONICAL_FORM)
|| name.equalsIgnoreCase (Constants.DOM_SUPPORTED_MEDIATYPES_ONLY)
|| name.equalsIgnoreCase (Constants.DOM_SPLIT_CDATA)
|| name.equalsIgnoreCase (Constants.DOM_CHARSET_OVERRIDES_XML_ENCODING)) {
return (fConfiguration.getFeature (name.toLowerCase(Locale.ENGLISH)))
? Boolean.TRUE
: Boolean.FALSE;
}
else if (name.equalsIgnoreCase (Constants.DOM_ERROR_HANDLER)) {
if (fErrorHandler != null) {
return fErrorHandler.getErrorHandler ();
}
return null;
}
else if (name.equalsIgnoreCase (Constants.DOM_RESOURCE_RESOLVER)) {
try {
XMLEntityResolver entityResolver =
(XMLEntityResolver) fConfiguration.getProperty (ENTITY_RESOLVER);
if (entityResolver != null
&& entityResolver instanceof DOMEntityResolverWrapper) {
return ((DOMEntityResolverWrapper) entityResolver).getEntityResolver ();
}
return null;
}
catch (XMLConfigurationException e) {}
}
else if (name.equalsIgnoreCase (Constants.DOM_SCHEMA_TYPE)) {
return fConfiguration.getProperty (
Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE);
}
else if (name.equalsIgnoreCase (Constants.DOM_SCHEMA_LOCATION)) {
return fSchemaLocation;
}
else if (name.equalsIgnoreCase (SYMBOL_TABLE)){
return fConfiguration.getProperty (SYMBOL_TABLE);
}
else if (name.equalsIgnoreCase (DOCUMENT_CLASS_NAME)) {
return fConfiguration.getProperty (DOCUMENT_CLASS_NAME);
}
else {
String msg =
DOMMessageFormatter.formatMessage (
DOMMessageFormatter.DOM_DOMAIN,
"FEATURE_NOT_FOUND",
new Object[] { name });
throw new DOMException (DOMException.NOT_FOUND_ERR, msg);
}
return null;
}
public boolean canSetParameter (String name, Object value) {
if(value instanceof Boolean){
boolean state = ((Boolean)value).booleanValue ();
if ( name.equalsIgnoreCase (Constants.DOM_SUPPORTED_MEDIATYPES_ONLY)
|| name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)
|| name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION )
|| name.equalsIgnoreCase (Constants.DOM_CANONICAL_FORM) ) {
// true is not supported
return (state) ? false : true;
}
else if (name.equalsIgnoreCase (Constants.DOM_NAMESPACE_DECLARATIONS)
|| name.equalsIgnoreCase (Constants.DOM_WELLFORMED)
|| name.equalsIgnoreCase (Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) {
// false is not supported
return (state) ? true : false;
}
else if (name.equalsIgnoreCase (Constants.DOM_CDATA_SECTIONS)
|| name.equalsIgnoreCase (Constants.DOM_CHARSET_OVERRIDES_XML_ENCODING)
|| name.equalsIgnoreCase (Constants.DOM_COMMENTS)
|| name.equalsIgnoreCase (Constants.DOM_DATATYPE_NORMALIZATION)
|| name.equalsIgnoreCase (Constants.DOM_DISALLOW_DOCTYPE)
|| name.equalsIgnoreCase (Constants.DOM_ENTITIES)
|| name.equalsIgnoreCase (Constants.DOM_INFOSET)
|| name.equalsIgnoreCase (Constants.DOM_NAMESPACES)
|| name.equalsIgnoreCase (Constants.DOM_VALIDATE)
|| name.equalsIgnoreCase (Constants.DOM_VALIDATE_IF_SCHEMA)
|| name.equalsIgnoreCase (Constants.DOM_ELEMENT_CONTENT_WHITESPACE)
|| name.equalsIgnoreCase (Constants.DOM_XMLDECL)) {
return true;
}
// Recognize Xerces features.
try {
fConfiguration.getFeature(name.toLowerCase(Locale.ENGLISH));
return true;
}
catch (XMLConfigurationException e) {
return false;
}
}
else { // check properties
if (name.equalsIgnoreCase (Constants.DOM_ERROR_HANDLER)) {
if (value instanceof DOMErrorHandler || value == null) {
return true;
}
return false;
}
else if (name.equalsIgnoreCase (Constants.DOM_RESOURCE_RESOLVER)) {
if (value instanceof LSResourceResolver || value == null) {
return true;
}
return false;
}
else if (name.equalsIgnoreCase (Constants.DOM_SCHEMA_TYPE)) {
if ((value instanceof String
&& (value.equals (Constants.NS_XMLSCHEMA)
|| value.equals (Constants.NS_DTD))) || value == null) {
return true;
}
return false;
}
else if (name.equalsIgnoreCase (Constants.DOM_SCHEMA_LOCATION)) {
if (value instanceof String || value == null)
return true;
return false;
}
else if (name.equalsIgnoreCase (DOCUMENT_CLASS_NAME)){
return true;
}
return false;
}
}
/**
* DOM Level 3 CR - Experimental.
*
* The list of the parameters supported by this
* DOMConfiguration
object and for which at least one value
* can be set by the application. Note that this list can also contain
* parameter names defined outside this specification.
*/
public DOMStringList getParameterNames () {
if (fRecognizedParameters == null){
Vector parameters = new Vector();
// REVISIT: add Xerces recognized properties/features
parameters.add(Constants.DOM_NAMESPACES);
parameters.add(Constants.DOM_CDATA_SECTIONS);
parameters.add(Constants.DOM_CANONICAL_FORM);
parameters.add(Constants.DOM_NAMESPACE_DECLARATIONS);
parameters.add(Constants.DOM_SPLIT_CDATA);
parameters.add(Constants.DOM_ENTITIES);
parameters.add(Constants.DOM_VALIDATE_IF_SCHEMA);
parameters.add(Constants.DOM_VALIDATE);
parameters.add(Constants.DOM_DATATYPE_NORMALIZATION);
parameters.add(Constants.DOM_CHARSET_OVERRIDES_XML_ENCODING);
parameters.add(Constants.DOM_CHECK_CHAR_NORMALIZATION);
parameters.add(Constants.DOM_SUPPORTED_MEDIATYPES_ONLY);
parameters.add(Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS);
parameters.add(Constants.DOM_NORMALIZE_CHARACTERS);
parameters.add(Constants.DOM_WELLFORMED);
parameters.add(Constants.DOM_INFOSET);
parameters.add(Constants.DOM_DISALLOW_DOCTYPE);
parameters.add(Constants.DOM_ELEMENT_CONTENT_WHITESPACE);
parameters.add(Constants.DOM_COMMENTS);
parameters.add(Constants.DOM_ERROR_HANDLER);
parameters.add(Constants.DOM_RESOURCE_RESOLVER);
parameters.add(Constants.DOM_SCHEMA_LOCATION);
parameters.add(Constants.DOM_SCHEMA_TYPE);
fRecognizedParameters = new DOMStringListImpl(parameters);
}
return fRecognizedParameters;
}
/**
* Parse an XML document from a location identified by an URI reference.
* If the URI contains a fragment identifier (see section 4.1 in ), the
* behavior is not defined by this specification.
*
*/
public Document parseURI (String uri) throws LSException {
//If DOMParser insstance is already busy parsing another document when this
// method is called, then raise INVALID_STATE_ERR according to DOM L3 LS spec
if ( fBusy ) {
String msg = DOMMessageFormatter.formatMessage (
DOMMessageFormatter.DOM_DOMAIN,
"INVALID_STATE_ERR",null);
throw new DOMException ( DOMException.INVALID_STATE_ERR,msg);
}
XMLInputSource source = new XMLInputSource (null, uri, null);
try {
//since we are depending on application to handle
//multithreading issues this should be ok.
if(!fBusy)currentThread = Thread.currentThread();
fBusy = true;
parse (source);
fBusy = false;
if(abortNow && currentThread.isInterrupted())
{
//reset interrupt state
abortNow = false;
currentThread.interrupted();
}
} catch (Exception e){
fBusy = false;
// Consume this exception if the user
// issued an interrupt or an abort.
if(abortNow && currentThread.isInterrupted())
{
//reset interrupt state
currentThread.interrupted();
}
if(abortNow){
abortNow = false;
return null;
}
if (e != abort) {
if (fErrorHandler != null) {
DOMErrorImpl error = new DOMErrorImpl ();
error.fException = e;
error.fMessage = e.getMessage ();
error.fSeverity = DOMError.SEVERITY_FATAL_ERROR;
fErrorHandler.getErrorHandler ().handleError (error);
}
if (DEBUG) {
e.printStackTrace ();
}
throw new LSException(LSException.PARSE_ERR, e.getMessage());
}
}
return getDocument ();
}
/**
* Parse an XML document from a resource identified by an
* LSInput
.
*
*/
public Document parse (LSInput is) throws LSException {
// need to wrap the LSInput with an XMLInputSource
XMLInputSource xmlInputSource = dom2xmlInputSource (is);
if ( fBusy ) {
String msg = DOMMessageFormatter.formatMessage (
DOMMessageFormatter.DOM_DOMAIN,
"INVALID_STATE_ERR",null);
throw new DOMException ( DOMException.INVALID_STATE_ERR,msg);
}
try {
//since we are depending on application to handle
//multithreading issues this should be ok.
if(!fBusy)currentThread = Thread.currentThread();
fBusy = true;
parse(xmlInputSource);
fBusy = false;
if(abortNow && currentThread.isInterrupted())
{
//reset interrupt state
abortNow = false;
currentThread.interrupted();
}
} catch (Exception e) {
fBusy = false;
// Consume this exception if the user
// issued an interrupt or an abort.
if(abortNow && currentThread.isInterrupted())
{
//reset interrupt state
currentThread.interrupted();
}
if(abortNow){
abortNow = false;
return null;
}
if (e != abort) {
if (fErrorHandler != null) {
DOMErrorImpl error = new DOMErrorImpl ();
error.fException = e;
error.fMessage = e.getMessage ();
error.fSeverity = DOMError.SEVERITY_FATAL_ERROR;
fErrorHandler.getErrorHandler().handleError (error);
}
if (DEBUG) {
e.printStackTrace ();
}
throw new LSException(LSException.PARSE_ERR, e.getMessage());
}
}
return getDocument ();
}
/**
* Parse an XML document or fragment from a resource identified by an
* LSInput
and insert the content into an existing
* document at the position epcified with the contextNode
* and action
arguments. When parsing the input stream the
* context node is used for resolving unbound namespace prefixes.
*
* @param is The LSInput
from which the source
* document is to be read.
* @param cnode The Node
that is used as the context for
* the data that is being parsed.
* @param action This parameter describes which action should be taken
* between the new set of node being inserted and the existing
* children of the context node. The set of possible actions is
* defined above.
* @exception DOMException
* HIERARCHY_REQUEST_ERR: Thrown if this action results in an invalid
* hierarchy (i.e. a Document with more than one document element).
*/
public Node parseWithContext (LSInput is, Node cnode,
short action) throws DOMException, LSException {
// REVISIT: need to implement.
throw new DOMException(DOMException.NOT_SUPPORTED_ERR, "Not supported");
}
/**
* NON-DOM: convert LSInput to XNIInputSource
*
* @param is
* @return
*/
XMLInputSource dom2xmlInputSource(LSInput is) {
// need to wrap the LSInput with an XMLInputSource
XMLInputSource xis = null;
// check whether there is a Reader
// according to DOM, we need to treat such reader as "UTF-16".
if (is.getCharacterStream () != null) {
xis = new XMLInputSource (is.getPublicId (), is.getSystemId (),
is.getBaseURI (), is.getCharacterStream (),
"UTF-16");
}
// check whether there is an InputStream
else if (is.getByteStream () != null) {
xis = new XMLInputSource (is.getPublicId (), is.getSystemId (),
is.getBaseURI (), is.getByteStream (),
is.getEncoding ());
}
// if there is a string data, use a StringReader
// according to DOM, we need to treat such data as "UTF-16".
else if (is.getStringData () != null && is.getStringData().length() > 0) {
xis = new XMLInputSource (is.getPublicId (), is.getSystemId (),
is.getBaseURI (), new StringReader (is.getStringData ()),
"UTF-16");
}
// otherwise, just use the public/system/base Ids
else if ((is.getSystemId() != null && is.getSystemId().length() > 0) ||
(is.getPublicId() != null && is.getPublicId().length() > 0)) {
xis = new XMLInputSource (is.getPublicId (), is.getSystemId (),
is.getBaseURI ());
}
else {
// all inputs are null
if (fErrorHandler != null) {
DOMErrorImpl error = new DOMErrorImpl();
error.fType = "no-input-specified";
error.fMessage = "no-input-specified";
error.fSeverity = DOMError.SEVERITY_FATAL_ERROR;
fErrorHandler.getErrorHandler().handleError(error);
}
throw new LSException(LSException.PARSE_ERR, "no-input-specified");
}
return xis;
}
/**
* @see org.w3c.dom.ls.LSParser#getAsync()
*/
public boolean getAsync () {
return false;
}
/**
* @see org.w3c.dom.ls.LSParser#getBusy()
*/
public boolean getBusy () {
return fBusy;
}
/**
* @see org.w3c.dom.ls.DOMParser#abort()
*/
public void abort () {
// If parse operation is in progress then reset it
if ( fBusy ) {
fBusy = false;
abortNow = true;
try{
//Revisit : Should we also close all opened readers ?
//Work towards other classes supporting abort instead of
//calling reset.
reset();
//interrupt the thread doing the parse operation.
//come out of all block operations.
// current thread could be blocked on read operation.
if(currentThread != null )currentThread.interrupt();
}catch(Exception ex){
}
}
return; // If not busy then this is noop
}
} // class DOMParserImpl