content: /*
   *  This file is part of AndroidIDE.
   *
   *  AndroidIDE is free software: you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation, either version 3 of the License, or
   *  (at your option) any later version.
   *
   *  AndroidIDE is distributed in the hope that it will be useful,
   *  but WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   *  GNU General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License
   *   along with AndroidIDE.  If not, see <https://www.gnu.org/licenses/>.
   */
  
  /*
   * reserved comment block
   * DO NOT REMOVE OR ALTER!
   */
  /*
   * 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 jaxp.sun.org.apache.xerces.internal.jaxp;
  
  import java.io.IOException;
  import java.util.Hashtable;
  import java.util.Iterator;
  import java.util.Map;
  
  import jaxp.xml.parsers.DocumentBuilder;
  import jaxp.xml.validation.Schema;
  import jaxp.xml.XMLConstants;
  
  import jaxp.sun.org.apache.xerces.internal.dom.DOMImplementationImpl;
  import jaxp.sun.org.apache.xerces.internal.dom.DOMMessageFormatter;
  import jaxp.sun.org.apache.xerces.internal.impl.Constants;
  import jaxp.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
  import jaxp.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator;
  import jaxp.sun.org.apache.xerces.internal.jaxp.validation.XSGrammarPoolContainer;
  import jaxp.sun.org.apache.xerces.internal.parsers.DOMParser;
  import jaxp.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
  import jaxp.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
  import jaxp.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager.Property;
  import jaxp.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager.State;
  import jaxp.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
  import jaxp.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
  import jaxp.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
  import jaxp.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
  import jaxp.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
  import jaxp.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
  
  import jaxp.sun.org.apache.xerces.internal.dom.DocumentImpl;
  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, Hashtable dbfAttrs, Hashtable features)
          throws SAXNotRecognizedException, SAXNotSupportedException {
          this(dbf, dbfAttrs, features, false);
      }
  
      DocumentBuilderImpl(DocumentBuilderFactoryImpl dbf, Hashtable dbfAttrs, Hashtable 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) {
                  Object temp = features.get(XMLConstants.FEATURE_SECURE_PROCESSING);
                  if (temp != null) {
                      boolean value = ((Boolean) temp).booleanValue();
                      if (value && 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(Hashtable features)
          throws SAXNotSupportedException, SAXNotRecognizedException {
          if (features != null) {
              Iterator entries = features.entrySet().iterator();
              while (entries.hasNext()) {
                  Map.Entry entry = (Map.Entry) entries.next();
                  String feature = (String) entry.getKey();
                  boolean value = ((Boolean) entry.getValue()).booleanValue();
                  domParser.setFeature(feature, value);
          }
      }
      }
  
      /**
       * 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(Hashtable dbfAttrs)
          throws SAXNotSupportedException, SAXNotRecognizedException
      {
          if (dbfAttrs == null) {
              // Nothing to do
              return;
          }
  
          Iterator entries = dbfAttrs.entrySet().iterator();
          while (entries.hasNext()) {
              Map.Entry entry = (Map.Entry) entries.next();
              String name = (String) entry.getKey();
              Object val = entry.getValue();
              if (val instanceof Boolean) {
                  // Assume feature
                  domParser.setFeature(name, ((Boolean)val).booleanValue());
              } 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 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);
          }
      }
  }
  