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.
414 lines
17 KiB
414 lines
17 KiB
/*
|
|
* 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 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 java.io.IOException;
|
|
import java.util.Map;
|
|
import javax.xml.XMLConstants;
|
|
import javax.xml.parsers.DocumentBuilder;
|
|
import javax.xml.validation.Schema;
|
|
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
|
|
* @author Edwin Goei
|
|
* @version $Id: DocumentBuilderImpl.java,v 1.8 2010-11-01 04:40:06 joehw Exp $
|
|
*/
|
|
public class DocumentBuilderImpl extends DocumentBuilder
|
|
implements JAXPConstants
|
|
{
|
|
/** Feature identifier: namespaces. */
|
|
private static final String NAMESPACES_FEATURE =
|
|
Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
|
|
|
|
/** 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. */
|
|
private static final String CREATE_ENTITY_REF_NODES_FEATURE =
|
|
Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_ENTITY_REF_NODES_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. */
|
|
private static final String CREATE_CDATA_NODES_FEATURE =
|
|
Constants.XERCES_FEATURE_PREFIX + Constants.CREATE_CDATA_NODES_FEATURE;
|
|
|
|
/** Feature identifier: XInclude processing */
|
|
private static final String XINCLUDE_FEATURE =
|
|
Constants.XERCES_FEATURE_PREFIX + Constants.XINCLUDE_FEATURE;
|
|
|
|
/** feature identifier: XML Schema validation */
|
|
private static final String XMLSCHEMA_VALIDATION_FEATURE =
|
|
Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
|
|
|
|
/** Feature identifier: validation */
|
|
private static final String VALIDATION_FEATURE =
|
|
Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
|
|
|
|
/** Property identifier: security manager. */
|
|
private static final String SECURITY_MANAGER =
|
|
Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
|
|
|
|
/** Property identifier: Security property manager. */
|
|
private static final String XML_SECURITY_PROPERTY_MANAGER =
|
|
Constants.XML_SECURITY_PROPERTY_MANAGER;
|
|
|
|
/** property identifier: access external dtd. */
|
|
public static final String ACCESS_EXTERNAL_DTD = XMLConstants.ACCESS_EXTERNAL_DTD;
|
|
|
|
/** 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 */
|
|
private final ErrorHandler fInitErrorHandler;
|
|
|
|
/** 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) {
|
|
if (temp && Constants.IS_JDK8_OR_ABOVE) {
|
|
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()
|
|
*/
|
|
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.
|
|
*/
|
|
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
|
|
* @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);
|
|
}
|
|
}
|
|
}
|