/* * 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