/*
 * Copyright (c) 2007, 2015, Oracle and/or its affiliates. All rights reserved.
 */
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.sun.org.apache.xerces.internal.jaxp;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.validation.Schema;
import javax.xml.XMLConstants;

import com.sun.org.apache.xerces.internal.dom.DOMImplementationImpl;
import com.sun.org.apache.xerces.internal.dom.DOMMessageFormatter;
import com.sun.org.apache.xerces.internal.impl.Constants;
import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator;
import com.sun.org.apache.xerces.internal.jaxp.validation.XSGrammarPoolContainer;
import com.sun.org.apache.xerces.internal.parsers.DOMParser;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager.Property;
import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager.State;
import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
import org.w3c.dom.DOMImplementation;
import org.w3c.dom.Document;
import org.xml.sax.EntityResolver;
import org.xml.sax.ErrorHandler;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;

Author:Rajiv Mordani, Edwin Goei
/** * @author Rajiv Mordani * @author Edwin Goei */
public class DocumentBuilderImpl extends DocumentBuilder implements JAXPConstants {
Feature identifier: namespaces.
/** Feature identifier: namespaces. */
private static final String NAMESPACES_FEATURE = Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
Feature identifier: include ignorable white space.
/** Feature identifier: include ignorable white space. */
private static final String INCLUDE_IGNORABLE_WHITESPACE = Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_IGNORABLE_WHITESPACE;
Feature identifier: create entiry ref nodes feature.
/** Feature identifier: create entiry ref nodes feature. */
private static final String CREATE_ENTITY_REF_NODES_FEATURE = Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_ENTITY_REF_NODES_FEATURE;
Feature identifier: include comments feature.
/** Feature identifier: include comments feature. */
private static final String INCLUDE_COMMENTS_FEATURE = Constants.XERCES_FEATURE_PREFIX + Constants.INCLUDE_COMMENTS_FEATURE;
Feature identifier: create cdata nodes feature.
/** Feature identifier: create cdata nodes feature. */
private static final String CREATE_CDATA_NODES_FEATURE = Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_CDATA_NODES_FEATURE;
Feature identifier: XInclude processing
/** Feature identifier: XInclude processing */
private static final String XINCLUDE_FEATURE = Constants.XERCES_FEATURE_PREFIX + Constants.XINCLUDE_FEATURE;
feature identifier: XML Schema validation
/** feature identifier: XML Schema validation */
private static final String XMLSCHEMA_VALIDATION_FEATURE = Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
Feature identifier: validation
/** Feature identifier: validation */
private static final String VALIDATION_FEATURE = Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
Property identifier: security manager.
/** Property identifier: security manager. */
private static final String SECURITY_MANAGER = Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
Property identifier: Security property manager.
/** Property identifier: Security property manager. */
private static final String XML_SECURITY_PROPERTY_MANAGER = Constants.XML_SECURITY_PROPERTY_MANAGER;
property identifier: access external dtd.
/** property identifier: access external dtd. */
public static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD;
Property identifier: access to external schema
/** Property identifier: access to external schema */
public static final String ACCESS_EXTERNAL_SCHEMA = XMLConstants.ACCESS_EXTERNAL_SCHEMA; private final DOMParser domParser; private final Schema grammar; private final XMLComponent fSchemaValidator; private final XMLComponentManager fSchemaValidatorComponentManager; private final ValidationManager fSchemaValidationManager; private final UnparsedEntityHandler fUnparsedEntityHandler;
Initial ErrorHandler
/** Initial ErrorHandler */
private final ErrorHandler fInitErrorHandler;
Initial EntityResolver
/** Initial EntityResolver */
private final EntityResolver fInitEntityResolver; private XMLSecurityManager fSecurityManager; private XMLSecurityPropertyManager fSecurityPropertyMgr; DocumentBuilderImpl(DocumentBuilderFactoryImpl dbf, Map<String, Object> dbfAttrs, Map<String, Boolean> features) throws SAXNotRecognizedException, SAXNotSupportedException { this(dbf, dbfAttrs, features, false); } DocumentBuilderImpl(DocumentBuilderFactoryImpl dbf, Map<String, Object> dbfAttrs, Map<String, Boolean> features, boolean secureProcessing) throws SAXNotRecognizedException, SAXNotSupportedException { domParser = new DOMParser(); // If validating, provide a default ErrorHandler that prints // validation errors with a warning telling the user to set an // ErrorHandler if (dbf.isValidating()) { fInitErrorHandler = new DefaultValidationErrorHandler(domParser.getXMLParserConfiguration().getLocale()); setErrorHandler(fInitErrorHandler); } else { fInitErrorHandler = domParser.getErrorHandler(); } domParser.setFeature(VALIDATION_FEATURE, dbf.isValidating()); // "namespaceAware" == SAX Namespaces feature domParser.setFeature(NAMESPACES_FEATURE, dbf.isNamespaceAware()); // Set various parameters obtained from DocumentBuilderFactory domParser.setFeature(INCLUDE_IGNORABLE_WHITESPACE, !dbf.isIgnoringElementContentWhitespace()); domParser.setFeature(CREATE_ENTITY_REF_NODES_FEATURE, !dbf.isExpandEntityReferences()); domParser.setFeature(INCLUDE_COMMENTS_FEATURE, !dbf.isIgnoringComments()); domParser.setFeature(CREATE_CDATA_NODES_FEATURE, !dbf.isCoalescing()); // Avoid setting the XInclude processing feature if the value is false. // This will keep the configuration from throwing an exception if it // does not support XInclude. if (dbf.isXIncludeAware()) { domParser.setFeature(XINCLUDE_FEATURE, true); } fSecurityPropertyMgr = new XMLSecurityPropertyManager(); domParser.setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr); fSecurityManager = new XMLSecurityManager(secureProcessing); domParser.setProperty(SECURITY_MANAGER, fSecurityManager); if (secureProcessing) { /** * If secure processing is explicitly set on the factory, the * access properties will be set unless the corresponding * System Properties or jaxp.properties are set */ if (features != null) { Boolean temp = features.get(XMLConstants.FEATURE_SECURE_PROCESSING); if (temp != null && temp) { fSecurityPropertyMgr.setValue(Property.ACCESS_EXTERNAL_DTD, State.FSP, Constants.EXTERNAL_ACCESS_DEFAULT_FSP); fSecurityPropertyMgr.setValue(Property.ACCESS_EXTERNAL_SCHEMA, State.FSP, Constants.EXTERNAL_ACCESS_DEFAULT_FSP); } } } this.grammar = dbf.getSchema(); if (grammar != null) { XMLParserConfiguration config = domParser.getXMLParserConfiguration(); XMLComponent validatorComponent = null; /** For Xerces grammars, use built-in schema validator. **/ if (grammar instanceof XSGrammarPoolContainer) { validatorComponent = new XMLSchemaValidator(); fSchemaValidationManager = new ValidationManager(); fUnparsedEntityHandler = new UnparsedEntityHandler(fSchemaValidationManager); config.setDTDHandler(fUnparsedEntityHandler); fUnparsedEntityHandler.setDTDHandler(domParser); domParser.setDTDSource(fUnparsedEntityHandler); fSchemaValidatorComponentManager = new SchemaValidatorConfiguration(config, (XSGrammarPoolContainer) grammar, fSchemaValidationManager); } /** For third party grammars, use the JAXP validator component. **/ else { validatorComponent = new JAXPValidatorComponent(grammar.newValidatorHandler()); fSchemaValidationManager = null; fUnparsedEntityHandler = null; fSchemaValidatorComponentManager = config; } config.addRecognizedFeatures(validatorComponent.getRecognizedFeatures()); config.addRecognizedProperties(validatorComponent.getRecognizedProperties()); setFeatures(features); // Must set before calling setDocumentHandler() config.setDocumentHandler((XMLDocumentHandler) validatorComponent); ((XMLDocumentSource)validatorComponent).setDocumentHandler(domParser); domParser.setDocumentSource((XMLDocumentSource) validatorComponent); fSchemaValidator = validatorComponent; } else { fSchemaValidationManager = null; fUnparsedEntityHandler = null; fSchemaValidatorComponentManager = null; fSchemaValidator = null; setFeatures(features); } //setAttribute override those that may be set by other means setDocumentBuilderFactoryAttributes(dbfAttrs); // Initial EntityResolver fInitEntityResolver = domParser.getEntityResolver(); } private void setFeatures( Map<String, Boolean> features) throws SAXNotSupportedException, SAXNotRecognizedException { if (features != null) { for (Map.Entry<String, Boolean> entry : features.entrySet()) { domParser.setFeature(entry.getKey(), entry.getValue()); } } }
Set any DocumentBuilderFactory attributes of our underlying DOMParser Note: code does not handle possible conflicts between DOMParser attribute names and JAXP specific attribute names, eg. DocumentBuilderFactory.setValidating()
/** * Set any DocumentBuilderFactory attributes of our underlying DOMParser * * Note: code does not handle possible conflicts between DOMParser * attribute names and JAXP specific attribute names, * eg. DocumentBuilderFactory.setValidating() */
private void setDocumentBuilderFactoryAttributes( Map<String, Object> dbfAttrs) throws SAXNotSupportedException, SAXNotRecognizedException { if (dbfAttrs == null) { // Nothing to do return; } for (Map.Entry<String, Object> entry : dbfAttrs.entrySet()) { String name = entry.getKey(); Object val = entry.getValue(); if (val instanceof Boolean) { // Assume feature domParser.setFeature(name, (Boolean)val); } else { // Assume property if (JAXP_SCHEMA_LANGUAGE.equals(name)) { // JAXP 1.2 support //None of the properties will take effect till the setValidating(true) has been called if ( W3C_XML_SCHEMA.equals(val) ) { if( isValidating() ) { domParser.setFeature(XMLSCHEMA_VALIDATION_FEATURE, true); // this should allow us not to emit DTD errors, as expected by the // spec when schema validation is enabled domParser.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA); } } } else if(JAXP_SCHEMA_SOURCE.equals(name)){ if( isValidating() ) { String value=(String)dbfAttrs.get(JAXP_SCHEMA_LANGUAGE); if(value !=null && W3C_XML_SCHEMA.equals(value)){ domParser.setProperty(name, val); }else{ throw new IllegalArgumentException( DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "jaxp-order-not-supported", new Object[] {JAXP_SCHEMA_LANGUAGE, JAXP_SCHEMA_SOURCE})); } } } else { //check if the property is managed by security manager if (fSecurityManager == null || !fSecurityManager.setLimit(name, XMLSecurityManager.State.APIPROPERTY, val)) { //check if the property is managed by security property manager if (fSecurityPropertyMgr == null || !fSecurityPropertyMgr.setValue(name, XMLSecurityPropertyManager.State.APIPROPERTY, val)) { //fall back to the existing property manager domParser.setProperty(name, val); } } } } } }
Non-preferred: use the getDOMImplementation() method instead of this one to get a DOM Level 2 DOMImplementation object and then use DOM Level 2 methods to create a DOM Document object.
/** * Non-preferred: use the getDOMImplementation() method instead of this * one to get a DOM Level 2 DOMImplementation object and then use DOM * Level 2 methods to create a DOM Document object. */
public Document newDocument() { return new com.sun.org.apache.xerces.internal.dom.DocumentImpl(); } public DOMImplementation getDOMImplementation() { return DOMImplementationImpl.getDOMImplementation(); } public Document parse(InputSource is) throws SAXException, IOException { if (is == null) { throw new IllegalArgumentException( DOMMessageFormatter.formatMessage(DOMMessageFormatter.DOM_DOMAIN, "jaxp-null-input-source", null)); } if (fSchemaValidator != null) { if (fSchemaValidationManager != null) { fSchemaValidationManager.reset(); fUnparsedEntityHandler.reset(); } resetSchemaValidator(); } domParser.parse(is); Document doc = domParser.getDocument(); domParser.dropDocumentReferences(); return doc; } public boolean isNamespaceAware() { try { return domParser.getFeature(NAMESPACES_FEATURE); } catch (SAXException x) { throw new IllegalStateException(x.getMessage()); } } public boolean isValidating() { try { return domParser.getFeature(VALIDATION_FEATURE); } catch (SAXException x) { throw new IllegalStateException(x.getMessage()); } }
Gets the XInclude processing mode for this parser
Returns:the state of XInclude processing mode
/** * Gets the XInclude processing mode for this parser * @return the state of XInclude processing mode */
public boolean isXIncludeAware() { try { return domParser.getFeature(XINCLUDE_FEATURE); } catch (SAXException exc) { return false; } } public void setEntityResolver(EntityResolver er) { domParser.setEntityResolver(er); } public void setErrorHandler(ErrorHandler eh) { domParser.setErrorHandler(eh); } public Schema getSchema() { return grammar; } public void reset() { /** Restore the initial error handler. **/ if (domParser.getErrorHandler() != fInitErrorHandler) { domParser.setErrorHandler(fInitErrorHandler); } /** Restore the initial entity resolver. **/ if (domParser.getEntityResolver() != fInitEntityResolver) { domParser.setEntityResolver(fInitEntityResolver); } } // package private DOMParser getDOMParser() { return domParser; } private void resetSchemaValidator() throws SAXException { try { fSchemaValidator.reset(fSchemaValidatorComponentManager); } // This should never be thrown from the schema validator. catch (XMLConfigurationException e) { throw new SAXException(e); } } }