You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1393 lines
57 KiB
1393 lines
57 KiB
/*
|
|
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*/
|
|
/*
|
|
* Copyright 2000-2005 The Apache Software Foundation.
|
|
*
|
|
* Licensed 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.parsers;
|
|
|
|
import java.io.StringReader;
|
|
import java.util.Locale;
|
|
import java.util.Stack;
|
|
import java.util.StringTokenizer;
|
|
import java.util.Vector;
|
|
|
|
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 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.DOMUtil;
|
|
import com.sun.org.apache.xerces.internal.util.SymbolTable;
|
|
import com.sun.org.apache.xerces.internal.util.XMLSymbols;
|
|
import com.sun.org.apache.xerces.internal.xni.Augmentations;
|
|
import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
|
|
import com.sun.org.apache.xerces.internal.xni.QName;
|
|
import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
|
|
import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler;
|
|
import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler;
|
|
import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
|
|
import com.sun.org.apache.xerces.internal.xni.XMLLocator;
|
|
import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
|
|
import com.sun.org.apache.xerces.internal.xni.XMLString;
|
|
import com.sun.org.apache.xerces.internal.xni.XNIException;
|
|
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.XMLDTDContentModelSource;
|
|
import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource;
|
|
import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
|
|
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.XMLParseException;
|
|
import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
|
|
import com.sun.org.apache.xerces.internal.parsers.XIncludeAwareParserConfiguration;
|
|
import org.w3c.dom.DOMConfiguration;
|
|
import org.w3c.dom.DOMError;
|
|
import org.w3c.dom.DOMErrorHandler;
|
|
import org.w3c.dom.DOMException;
|
|
import org.w3c.dom.DOMStringList;
|
|
import org.w3c.dom.Document;
|
|
import org.w3c.dom.Node;
|
|
import org.w3c.dom.ls.LSException;
|
|
import org.w3c.dom.ls.LSInput;
|
|
import org.w3c.dom.ls.LSParser;
|
|
import org.w3c.dom.ls.LSParserFilter;
|
|
import org.w3c.dom.ls.LSResourceResolver;
|
|
import org.xml.sax.SAXException;
|
|
|
|
|
|
/**
|
|
* 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.8 2010-11-01 04:40:09 joehw 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;
|
|
|
|
/** XML Schema full checking */
|
|
protected static final String XMLSCHEMA_FULL_CHECKING =
|
|
Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING;
|
|
|
|
/** 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;
|
|
|
|
/** Feature identifier: namespace growth */
|
|
protected static final String NAMESPACE_GROWTH =
|
|
Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE;
|
|
|
|
/** Feature identifier: tolerate duplicates */
|
|
protected static final String TOLERATE_DUPLICATES =
|
|
Constants.XERCES_FEATURE_PREFIX + Constants.TOLERATE_DUPLICATES_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;
|
|
|
|
|
|
//
|
|
// Data
|
|
//
|
|
|
|
/** Include namespace declaration attributes in the document. **/
|
|
protected boolean fNamespaceDeclarations = true;
|
|
|
|
// REVISIT: this value should be null by default and should be set during creation of
|
|
// LSParser
|
|
protected String fSchemaType = null;
|
|
|
|
protected boolean fBusy = false;
|
|
|
|
private boolean abortNow = false;
|
|
|
|
private Thread currentThread;
|
|
|
|
protected final static boolean DEBUG = false;
|
|
|
|
private Vector fSchemaLocations = new Vector ();
|
|
private String fSchemaLocation = null;
|
|
private DOMStringList fRecognizedParameters;
|
|
|
|
private AbortHandler abortHandler = null;
|
|
|
|
//
|
|
// Constructors
|
|
//
|
|
|
|
/**
|
|
* Constructs a DOM Builder using the standard parser configuration.
|
|
*/
|
|
public DOMParserImpl (XMLParserConfiguration config, String schemaType) {
|
|
this (config);
|
|
if (schemaType != null) {
|
|
if (schemaType.equals (Constants.NS_DTD)) {
|
|
//Schema validation is false by default and hence there is no
|
|
//need to set it to false here. Also, schema validation is
|
|
//not a recognized feature for DTDConfiguration's and so
|
|
//setting this feature here would result in a Configuration
|
|
//Exception.
|
|
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(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
|
|
// This is a recognized feature only for XML Schemas. If the
|
|
// configuration doesn't support this feature, ignore it.
|
|
try {
|
|
fConfiguration.setFeature ( NORMALIZE_DATA, false );
|
|
}
|
|
catch (XMLConfigurationException exc) {}
|
|
|
|
} // <init>(XMLParserConfiguration)
|
|
|
|
/**
|
|
* Constructs a DOM Builder using the specified symbol table.
|
|
*/
|
|
public DOMParserImpl (SymbolTable symbolTable) {
|
|
this (new XIncludeAwareParserConfiguration());
|
|
fConfiguration.setProperty (
|
|
Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY,
|
|
symbolTable);
|
|
} // <init>(SymbolTable)
|
|
|
|
|
|
/**
|
|
* Constructs a DOM Builder using the specified symbol table and
|
|
* grammar pool.
|
|
*/
|
|
public DOMParserImpl (SymbolTable symbolTable, XMLGrammarPool grammarPool) {
|
|
this (new XIncludeAwareParserConfiguration());
|
|
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 ();
|
|
|
|
// get state of namespace-declarations parameter.
|
|
fNamespaceDeclarations =
|
|
fConfiguration.getFeature(Constants.DOM_NAMESPACE_DECLARATIONS);
|
|
|
|
// DOM Filter
|
|
if (fSkippedElemStack!=null) {
|
|
fSkippedElemStack.removeAllElements ();
|
|
}
|
|
fSchemaLocations.clear ();
|
|
fRejectedElementDepth = 0;
|
|
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
|
|
* <code>Element</code> 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
|
|
* <code>Element</code> 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, namespace-declarations,
|
|
// comments, element-content-whitespace
|
|
fConfiguration.setFeature(NAMESPACES, true);
|
|
fConfiguration.setFeature(Constants.DOM_NAMESPACE_DECLARATIONS, 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)) {
|
|
fConfiguration.setFeature(Constants.DOM_NAMESPACE_DECLARATIONS, state);
|
|
}
|
|
else if (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);
|
|
fConfiguration.setFeature (XMLSCHEMA_FULL_CHECKING, 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
|
|
String normalizedName;
|
|
if (name.equals(NAMESPACE_GROWTH)) {
|
|
normalizedName = NAMESPACE_GROWTH;
|
|
}
|
|
else if (name.equals(TOLERATE_DUPLICATES)) {
|
|
normalizedName = TOLERATE_DUPLICATES;
|
|
}
|
|
else {
|
|
normalizedName = name.toLowerCase(Locale.ENGLISH);
|
|
}
|
|
fConfiguration.setFeature (normalizedName, 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.TYPE_MISMATCH_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.TYPE_MISMATCH_ERR, msg);
|
|
}
|
|
|
|
}
|
|
else if (name.equalsIgnoreCase (Constants.DOM_SCHEMA_LOCATION)) {
|
|
if (value instanceof String || value == null) {
|
|
try {
|
|
if (value == null) {
|
|
fSchemaLocation = null;
|
|
fConfiguration.setProperty (
|
|
Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
|
|
null);
|
|
}
|
|
else {
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
catch (XMLConfigurationException e) {}
|
|
}
|
|
else {
|
|
// REVISIT: type mismatch
|
|
String msg =
|
|
DOMMessageFormatter.formatMessage (
|
|
DOMMessageFormatter.DOM_DOMAIN,
|
|
"TYPE_MISMATCH_ERR",
|
|
new Object[] { name });
|
|
throw new DOMException (DOMException.TYPE_MISMATCH_ERR, msg);
|
|
}
|
|
|
|
}
|
|
else if (name.equalsIgnoreCase (Constants.DOM_SCHEMA_TYPE)) {
|
|
if (value instanceof String || value == null) {
|
|
try {
|
|
if (value == null) {
|
|
// turn off schema features
|
|
fConfiguration.setFeature (XMLSCHEMA, false);
|
|
fConfiguration.setFeature (XMLSCHEMA_FULL_CHECKING, 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 features
|
|
fConfiguration.setFeature (XMLSCHEMA, true);
|
|
fConfiguration.setFeature (XMLSCHEMA_FULL_CHECKING, 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 features
|
|
fConfiguration.setFeature (XMLSCHEMA, false);
|
|
fConfiguration.setFeature (XMLSCHEMA_FULL_CHECKING, 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.TYPE_MISMATCH_ERR, msg);
|
|
}
|
|
|
|
}
|
|
else if (name.equalsIgnoreCase (DOCUMENT_CLASS_NAME)) {
|
|
fConfiguration.setProperty (DOCUMENT_CLASS_NAME, value);
|
|
}
|
|
else {
|
|
// Try to set the property.
|
|
String normalizedName = name.toLowerCase(Locale.ENGLISH);
|
|
try {
|
|
fConfiguration.setProperty(normalizedName, value);
|
|
return;
|
|
}
|
|
catch (XMLConfigurationException e) {}
|
|
|
|
// If this is a boolean parameter a type mismatch should be thrown.
|
|
try {
|
|
if (name.equals(NAMESPACE_GROWTH)) {
|
|
normalizedName = NAMESPACE_GROWTH;
|
|
}
|
|
else if (name.equals(TOLERATE_DUPLICATES)) {
|
|
normalizedName = TOLERATE_DUPLICATES;
|
|
}
|
|
fConfiguration.getFeature(normalizedName);
|
|
throw newTypeMismatchError(name);
|
|
|
|
}
|
|
catch (XMLConfigurationException e) {}
|
|
|
|
// Parameter is not recognized
|
|
throw newFeatureNotFoundError(name);
|
|
}
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 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(Constants.DOM_NAMESPACE_DECLARATIONS) &&
|
|
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 {
|
|
// This could be a recognized feature or property.
|
|
String normalizedName;
|
|
|
|
if (name.equals(NAMESPACE_GROWTH)) {
|
|
normalizedName = NAMESPACE_GROWTH;
|
|
}
|
|
else if (name.equals(TOLERATE_DUPLICATES)) {
|
|
normalizedName = TOLERATE_DUPLICATES;
|
|
}
|
|
else {
|
|
normalizedName = name.toLowerCase(Locale.ENGLISH);
|
|
}
|
|
try {
|
|
return fConfiguration.getFeature(normalizedName)
|
|
? Boolean.TRUE : Boolean.FALSE;
|
|
}
|
|
catch (XMLConfigurationException e) {}
|
|
|
|
// This isn't a feature; perhaps it's a property
|
|
try {
|
|
return fConfiguration.getProperty(normalizedName);
|
|
}
|
|
catch (XMLConfigurationException e) {}
|
|
|
|
throw newFeatureNotFoundError(name);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
public boolean canSetParameter (String name, Object value) {
|
|
if (value == null){
|
|
return true;
|
|
}
|
|
|
|
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_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_NAMESPACE_DECLARATIONS)
|
|
|| 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 {
|
|
String normalizedName;
|
|
if (name.equalsIgnoreCase(NAMESPACE_GROWTH)) {
|
|
normalizedName = NAMESPACE_GROWTH;
|
|
}
|
|
else if (name.equalsIgnoreCase(TOLERATE_DUPLICATES)) {
|
|
normalizedName = TOLERATE_DUPLICATES;
|
|
}
|
|
else {
|
|
normalizedName = name.toLowerCase(Locale.ENGLISH);
|
|
}
|
|
fConfiguration.getFeature(normalizedName);
|
|
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
|
|
* <code>DOMConfiguration</code> 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 {
|
|
currentThread = Thread.currentThread();
|
|
fBusy = true;
|
|
parse (source);
|
|
fBusy = false;
|
|
if (abortNow && currentThread.isInterrupted()) {
|
|
//reset interrupt state
|
|
abortNow = false;
|
|
Thread.interrupted();
|
|
}
|
|
} catch (Exception e){
|
|
fBusy = false;
|
|
if (abortNow && currentThread.isInterrupted()) {
|
|
Thread.interrupted();
|
|
}
|
|
if (abortNow) {
|
|
abortNow = false;
|
|
restoreHandlers();
|
|
return null;
|
|
}
|
|
// Consume this exception if the user
|
|
// issued an interrupt or an abort.
|
|
if (e != Abort.INSTANCE) {
|
|
if (!(e instanceof XMLParseException) && 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 (LSException) DOMUtil.createLSException(LSException.PARSE_ERR, e).fillInStackTrace();
|
|
}
|
|
}
|
|
Document doc = getDocument();
|
|
dropDocumentReferences();
|
|
return doc;
|
|
}
|
|
|
|
/**
|
|
* Parse an XML document from a resource identified by an
|
|
* <code>LSInput</code>.
|
|
*
|
|
*/
|
|
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 {
|
|
currentThread = Thread.currentThread();
|
|
fBusy = true;
|
|
parse (xmlInputSource);
|
|
fBusy = false;
|
|
if (abortNow && currentThread.isInterrupted()) {
|
|
//reset interrupt state
|
|
abortNow = false;
|
|
Thread.interrupted();
|
|
}
|
|
} catch (Exception e) {
|
|
fBusy = false;
|
|
if (abortNow && currentThread.isInterrupted()) {
|
|
Thread.interrupted();
|
|
}
|
|
if (abortNow) {
|
|
abortNow = false;
|
|
restoreHandlers();
|
|
return null;
|
|
}
|
|
// Consume this exception if the user
|
|
// issued an interrupt or an abort.
|
|
if (e != Abort.INSTANCE) {
|
|
if (!(e instanceof XMLParseException) && 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 (LSException) DOMUtil.createLSException(LSException.PARSE_ERR, e).fillInStackTrace();
|
|
}
|
|
}
|
|
Document doc = getDocument();
|
|
dropDocumentReferences();
|
|
return doc;
|
|
}
|
|
|
|
|
|
private void restoreHandlers() {
|
|
fConfiguration.setDocumentHandler(this);
|
|
fConfiguration.setDTDHandler(this);
|
|
fConfiguration.setDTDContentModelHandler(this);
|
|
}
|
|
|
|
/**
|
|
* Parse an XML document or fragment from a resource identified by an
|
|
* <code>LSInput</code> and insert the content into an existing
|
|
* document at the position epcified with the <code>contextNode</code>
|
|
* and <code>action</code> arguments. When parsing the input stream the
|
|
* context node is used for resolving unbound namespace prefixes.
|
|
*
|
|
* @param is The <code>LSInput</code> from which the source
|
|
* document is to be read.
|
|
* @param cnode The <code>Node</code> 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;
|
|
if(currentThread != null) {
|
|
abortNow = true;
|
|
if (abortHandler == null) {
|
|
abortHandler = new AbortHandler();
|
|
}
|
|
fConfiguration.setDocumentHandler(abortHandler);
|
|
fConfiguration.setDTDHandler(abortHandler);
|
|
fConfiguration.setDTDContentModelHandler(abortHandler);
|
|
|
|
if(currentThread == Thread.currentThread())
|
|
throw Abort.INSTANCE;
|
|
|
|
currentThread.interrupt();
|
|
}
|
|
}
|
|
return; // If not busy then this is noop
|
|
}
|
|
|
|
/**
|
|
* The start of an element. If the document specifies the start element
|
|
* by using an empty tag, then the startElement method will immediately
|
|
* be followed by the endElement method, with no intervening methods.
|
|
* Overriding the parent to handle DOM_NAMESPACE_DECLARATIONS=false.
|
|
*
|
|
* @param element The name of the element.
|
|
* @param attributes The element attributes.
|
|
* @param augs Additional information that may include infoset augmentations
|
|
*
|
|
* @throws XNIException Thrown by handler to signal an error.
|
|
*/
|
|
public void startElement (QName element, XMLAttributes attributes, Augmentations augs) {
|
|
// namespace declarations parameter has no effect if namespaces is false.
|
|
if (!fNamespaceDeclarations && fNamespaceAware) {
|
|
int len = attributes.getLength();
|
|
for (int i = len - 1; i >= 0; --i) {
|
|
if (XMLSymbols.PREFIX_XMLNS == attributes.getPrefix(i) ||
|
|
XMLSymbols.PREFIX_XMLNS == attributes.getQName(i)) {
|
|
attributes.removeAttributeAt(i);
|
|
}
|
|
}
|
|
}
|
|
super.startElement(element, attributes, augs);
|
|
}
|
|
|
|
private class AbortHandler implements XMLDocumentHandler, XMLDTDHandler, XMLDTDContentModelHandler {
|
|
|
|
private XMLDocumentSource documentSource;
|
|
private XMLDTDContentModelSource dtdContentSource;
|
|
private XMLDTDSource dtdSource;
|
|
|
|
public void startDocument(XMLLocator locator, String encoding, NamespaceContext namespaceContext, Augmentations augs) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void xmlDecl(String version, String encoding, String standalone, Augmentations augs) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void doctypeDecl(String rootElement, String publicId, String systemId, Augmentations augs) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void comment(XMLString text, Augmentations augs) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void processingInstruction(String target, XMLString data, Augmentations augs) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void startElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void startGeneralEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augs) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void textDecl(String version, String encoding, Augmentations augs) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void endGeneralEntity(String name, Augmentations augs) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void characters(XMLString text, Augmentations augs) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void endElement(QName element, Augmentations augs) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void startCDATA(Augmentations augs) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void endCDATA(Augmentations augs) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void endDocument(Augmentations augs) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void setDocumentSource(XMLDocumentSource source) {
|
|
documentSource = source;
|
|
}
|
|
|
|
public XMLDocumentSource getDocumentSource() {
|
|
return documentSource;
|
|
}
|
|
|
|
public void startDTD(XMLLocator locator, Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void startParameterEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void endParameterEntity(String name, Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void startExternalSubset(XMLResourceIdentifier identifier, Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void endExternalSubset(Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void elementDecl(String name, String contentModel, Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void startAttlist(String elementName, Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void attributeDecl(String elementName, String attributeName, String type, String[] enumeration, String defaultType, XMLString defaultValue, XMLString nonNormalizedDefaultValue, Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void endAttlist(Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void internalEntityDecl(String name, XMLString text, XMLString nonNormalizedText, Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void externalEntityDecl(String name, XMLResourceIdentifier identifier, Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void unparsedEntityDecl(String name, XMLResourceIdentifier identifier, String notation, Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void notationDecl(String name, XMLResourceIdentifier identifier, Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void startConditional(short type, Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void ignoredCharacters(XMLString text, Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void endConditional(Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void endDTD(Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void setDTDSource(XMLDTDSource source) {
|
|
dtdSource = source;
|
|
}
|
|
|
|
public XMLDTDSource getDTDSource() {
|
|
return dtdSource;
|
|
}
|
|
|
|
public void startContentModel(String elementName, Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void any(Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void empty(Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void startGroup(Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void pcdata(Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void element(String elementName, Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void separator(short separator, Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void occurrence(short occurrence, Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void endGroup(Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void endContentModel(Augmentations augmentations) throws XNIException {
|
|
throw Abort.INSTANCE;
|
|
}
|
|
|
|
public void setDTDContentModelSource(XMLDTDContentModelSource source) {
|
|
dtdContentSource = source;
|
|
}
|
|
|
|
public XMLDTDContentModelSource getDTDContentModelSource() {
|
|
return dtdContentSource;
|
|
}
|
|
|
|
}
|
|
|
|
private static DOMException newFeatureNotFoundError(String name) {
|
|
String msg =
|
|
DOMMessageFormatter.formatMessage (
|
|
DOMMessageFormatter.DOM_DOMAIN,
|
|
"FEATURE_NOT_FOUND",
|
|
new Object[] { name });
|
|
return new DOMException (DOMException.NOT_FOUND_ERR, msg);
|
|
}
|
|
|
|
private static DOMException newTypeMismatchError(String name) {
|
|
String msg =
|
|
DOMMessageFormatter.formatMessage (
|
|
DOMMessageFormatter.DOM_DOMAIN,
|
|
"TYPE_MISMATCH_ERR",
|
|
new Object[] { name });
|
|
return new DOMException (DOMException.TYPE_MISMATCH_ERR, msg);
|
|
}
|
|
|
|
} // class DOMParserImpl
|