/**
  * Override SAXParser's setFeature method to track the initial state of features. This keeps us
  * from affecting the performance of the SAXParser when it is created with XMLReaderFactory.
  */
 public synchronized void setFeature(String name, boolean value)
     throws SAXNotRecognizedException, SAXNotSupportedException {
   if (name == null) {
     // TODO: Add localized error message.
     throw new NullPointerException();
   }
   if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
     try {
       fSecurityManager.setSecureProcessing(value);
       setProperty(SECURITY_MANAGER, fSecurityManager);
     } catch (SAXNotRecognizedException exc) {
       // If the property is not supported
       // re-throw the exception if the value is true.
       if (value) {
         throw exc;
       }
     } catch (SAXNotSupportedException exc) {
       // If the property is not supported
       // re-throw the exception if the value is true.
       if (value) {
         throw exc;
       }
     }
     return;
   }
   if (!fInitFeatures.containsKey(name)) {
     boolean current = super.getFeature(name);
     fInitFeatures.put(name, current ? Boolean.TRUE : Boolean.FALSE);
   }
   /** Forward feature to the schema validator if there is one. * */
   if (fSAXParser != null && fSAXParser.fSchemaValidator != null) {
     setSchemaValidatorFeature(name, value);
   }
   super.setFeature(name, value);
 }
    public synchronized Object getProperty(String name)
        throws SAXNotRecognizedException, SAXNotSupportedException {
      if (name == null) {
        // TODO: Add localized error message.
        throw new NullPointerException();
      }
      if (fSAXParser != null && JAXP_SCHEMA_LANGUAGE.equals(name)) {
        // JAXP 1.2 support
        return fSAXParser.schemaLanguage;
      }

      /** Check to see if the property is managed by the security manager * */
      String propertyValue =
          (fSecurityManager != null) ? fSecurityManager.getLimitAsString(name) : null;
      if (propertyValue != null) {
        return propertyValue;
      } else {
        propertyValue = (fSecurityPropertyMgr != null) ? fSecurityPropertyMgr.getValue(name) : null;
        if (propertyValue != null) {
          return propertyValue;
        }
      }

      return super.getProperty(name);
    }
  /** Constructs a component manager suitable for Xerces' schema validator. */
  public XMLSchemaValidatorComponentManager(XSGrammarPoolContainer grammarContainer) {
    // setup components
    fEntityManager = new XMLEntityManager();
    fComponents.put(ENTITY_MANAGER, fEntityManager);

    fErrorReporter = new XMLErrorReporter();
    fComponents.put(ERROR_REPORTER, fErrorReporter);

    fNamespaceContext = new NamespaceSupport();
    fComponents.put(NAMESPACE_CONTEXT, fNamespaceContext);

    fSchemaValidator = new XMLSchemaValidator();
    fComponents.put(SCHEMA_VALIDATOR, fSchemaValidator);

    fValidationManager = new ValidationManager();
    fComponents.put(VALIDATION_MANAGER, fValidationManager);

    // setup other properties
    fComponents.put(ENTITY_RESOLVER, null);
    fComponents.put(ERROR_HANDLER, null);

    fComponents.put(SYMBOL_TABLE, new SymbolTable());

    // setup grammar pool
    fComponents.put(XMLGRAMMAR_POOL, grammarContainer.getGrammarPool());
    fUseGrammarPoolOnly = grammarContainer.isFullyComposed();

    // add schema message formatter to error reporter
    fErrorReporter.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN, new XSMessageFormatter());

    // add all recognized features and properties and apply their defaults
    addRecognizedParamsAndSetDefaults(fEntityManager, grammarContainer);
    addRecognizedParamsAndSetDefaults(fErrorReporter, grammarContainer);
    addRecognizedParamsAndSetDefaults(fSchemaValidator, grammarContainer);

    boolean secureProcessing = grammarContainer.getFeature(XMLConstants.FEATURE_SECURE_PROCESSING);
    if (System.getSecurityManager() != null) {
      _isSecureMode = true;
      secureProcessing = true;
    }

    fInitSecurityManager = (XMLSecurityManager) grammarContainer.getProperty(SECURITY_MANAGER);
    if (fInitSecurityManager != null) {
      fInitSecurityManager.setSecureProcessing(secureProcessing);
    } else {
      fInitSecurityManager = new XMLSecurityManager(secureProcessing);
    }

    setProperty(SECURITY_MANAGER, fInitSecurityManager);

    // pass on properties set on SchemaFactory
    fSecurityPropertyMgr =
        (XMLSecurityPropertyManager)
            grammarContainer.getProperty(Constants.XML_SECURITY_PROPERTY_MANAGER);
    setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr);
  }
 public synchronized boolean getFeature(String name)
     throws SAXNotRecognizedException, SAXNotSupportedException {
   if (name == null) {
     // TODO: Add localized error message.
     throw new NullPointerException();
   }
   if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
     return fSecurityManager.isSecureProcessing();
   }
   return super.getFeature(name);
 }
 /**
  * Returns the state of a feature.
  *
  * @param featureId The feature identifier.
  * @return true if the feature is supported
  * @throws XMLConfigurationException Thrown for configuration error. In general, components should
  *     only throw this exception if it is <strong>really</strong> a critical error.
  */
 public FeatureState getFeatureState(String featureId) throws XMLConfigurationException {
   if (PARSER_SETTINGS.equals(featureId)) {
     return FeatureState.is(fConfigUpdated);
   } else if (VALIDATION.equals(featureId) || SCHEMA_VALIDATION.equals(featureId)) {
     return FeatureState.is(true);
   } else if (USE_GRAMMAR_POOL_ONLY.equals(featureId)) {
     return FeatureState.is(fUseGrammarPoolOnly);
   } else if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(featureId)) {
     return FeatureState.is(fInitSecurityManager.isSecureProcessing());
   } else if (SCHEMA_ELEMENT_DEFAULT.equals(featureId)) {
     return FeatureState.is(
         true); // pre-condition: VALIDATION and SCHEMA_VALIDATION are always true
   }
   return super.getFeatureState(featureId);
 }
  /**
   * Set the value of any property in a SAX2 parser. The parser might not recognize the property,
   * and if it does recognize it, it might not support the requested value.
   *
   * @param propertyId The unique identifier (URI) of the property being set.
   * @param value The value to which the property is being set.
   * @exception SAXNotRecognizedException If the requested property is not known.
   * @exception SAXNotSupportedException If the requested property is known, but the requested value
   *     is not supported.
   */
  public void setProperty(String propertyId, Object value)
      throws SAXNotRecognizedException, SAXNotSupportedException {
    /**
     * It's possible for users to set a security manager through the interface. If it's the old
     * SecurityManager, convert it to the new XMLSecurityManager
     */
    if (propertyId.equals(Constants.SECURITY_MANAGER)) {
      securityManager = XMLSecurityManager.convert(value, securityManager);
      setProperty0(Constants.SECURITY_MANAGER, securityManager);
      return;
    }
    if (propertyId.equals(Constants.XML_SECURITY_PROPERTY_MANAGER)) {
      if (value == null) {
        securityPropertyManager = new XMLSecurityPropertyManager();
      } else {
        securityPropertyManager = (XMLSecurityPropertyManager) value;
      }
      setProperty0(Constants.XML_SECURITY_PROPERTY_MANAGER, securityPropertyManager);
      return;
    }

    if (securityManager == null) {
      securityManager = new XMLSecurityManager(true);
      setProperty0(Constants.SECURITY_MANAGER, securityManager);
    }

    if (securityPropertyManager == null) {
      securityPropertyManager = new XMLSecurityPropertyManager();
      setProperty0(Constants.XML_SECURITY_PROPERTY_MANAGER, securityPropertyManager);
    }
    int index = securityPropertyManager.getIndex(propertyId);

    if (index > -1) {
      /**
       * this is a direct call to this parser, not a subclass since internally the support of this
       * property is done through XMLSecurityPropertyManager
       */
      securityPropertyManager.setValue(
          index, XMLSecurityPropertyManager.State.APIPROPERTY, (String) value);
    } else {
      // check if the property is managed by security manager
      if (!securityManager.setLimit(propertyId, XMLSecurityManager.State.APIPROPERTY, value)) {
        // fall back to the default configuration to handle the property
        setProperty0(propertyId, value);
      }
    }
  }
  /**
   * Sets the state of a property.
   *
   * @param propertyId The unique identifier (URI) of the property.
   * @param value The requested state of the property.
   * @exception XMLConfigurationException If the requested property is not known.
   */
  public void setProperty(String propertyId, Object value) throws XMLConfigurationException {
    if (ENTITY_MANAGER.equals(propertyId)
        || ERROR_REPORTER.equals(propertyId)
        || NAMESPACE_CONTEXT.equals(propertyId)
        || SCHEMA_VALIDATOR.equals(propertyId)
        || SYMBOL_TABLE.equals(propertyId)
        || VALIDATION_MANAGER.equals(propertyId)
        || XMLGRAMMAR_POOL.equals(propertyId)) {
      throw new XMLConfigurationException(Status.NOT_SUPPORTED, propertyId);
    }
    fConfigUpdated = true;
    fEntityManager.setProperty(propertyId, value);
    fErrorReporter.setProperty(propertyId, value);
    fSchemaValidator.setProperty(propertyId, value);
    if (ENTITY_RESOLVER.equals(propertyId)
        || ERROR_HANDLER.equals(propertyId)
        || SECURITY_MANAGER.equals(propertyId)) {
      fComponents.put(propertyId, value);
      return;
    } else if (LOCALE.equals(propertyId)) {
      setLocale((Locale) value);
      fComponents.put(propertyId, value);
      return;
    }

    // check if the property is managed by security manager
    if (fInitSecurityManager == null
        || !fInitSecurityManager.setLimit(
            propertyId, XMLSecurityManager.State.APIPROPERTY, value)) {
      // check if the property is managed by security property manager
      if (fSecurityPropertyMgr == null
          || !fSecurityPropertyMgr.setValue(
              propertyId, XMLSecurityPropertyManager.State.APIPROPERTY, value)) {
        // fall back to the existing property manager
        if (!fInitProperties.containsKey(propertyId)) {
          fInitProperties.put(propertyId, super.getProperty(propertyId));
        }
        super.setProperty(propertyId, value);
      }
    }
  }
  /**
   * Set the state of a feature.
   *
   * @param featureId The unique identifier (URI) of the feature.
   * @param state The requested state of the feature (true or false).
   * @exception XMLConfigurationException If the requested feature is not known.
   */
  public void setFeature(String featureId, boolean value) throws XMLConfigurationException {
    if (PARSER_SETTINGS.equals(featureId)) {
      throw new XMLConfigurationException(Status.NOT_SUPPORTED, featureId);
    } else if (value == false
        && (VALIDATION.equals(featureId) || SCHEMA_VALIDATION.equals(featureId))) {
      throw new XMLConfigurationException(Status.NOT_SUPPORTED, featureId);
    } else if (USE_GRAMMAR_POOL_ONLY.equals(featureId) && value != fUseGrammarPoolOnly) {
      throw new XMLConfigurationException(Status.NOT_SUPPORTED, featureId);
    }
    if (XMLConstants.FEATURE_SECURE_PROCESSING.equals(featureId)) {
      if (_isSecureMode && !value) {
        throw new XMLConfigurationException(
            Status.NOT_ALLOWED, XMLConstants.FEATURE_SECURE_PROCESSING);
      }
      fInitSecurityManager.setSecureProcessing(value);
      setProperty(SECURITY_MANAGER, fInitSecurityManager);

      if (value && Constants.IS_JDK8_OR_ABOVE) {
        fSecurityPropertyMgr.setValue(
            XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD,
            XMLSecurityPropertyManager.State.FSP,
            Constants.EXTERNAL_ACCESS_DEFAULT_FSP);
        fSecurityPropertyMgr.setValue(
            XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA,
            XMLSecurityPropertyManager.State.FSP,
            Constants.EXTERNAL_ACCESS_DEFAULT_FSP);
        setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr);
      }

      return;
    }
    fConfigUpdated = true;
    fEntityManager.setFeature(featureId, value);
    fErrorReporter.setFeature(featureId, value);
    fSchemaValidator.setFeature(featureId, value);
    if (!fInitFeatures.containsKey(featureId)) {
      boolean current = super.getFeature(featureId);
      fInitFeatures.put(featureId, current ? Boolean.TRUE : Boolean.FALSE);
    }
    super.setFeature(featureId, value);
  }
    /**
     * Override SAXParser's setProperty method to track the initial state of properties. This keeps
     * us from affecting the performance of the SAXParser when it is created with XMLReaderFactory.
     */
    public synchronized void setProperty(String name, Object value)
        throws SAXNotRecognizedException, SAXNotSupportedException {
      if (name == null) {
        // TODO: Add localized error message.
        throw new NullPointerException();
      }
      if (fSAXParser != null) {
        // JAXP 1.2 support
        if (JAXP_SCHEMA_LANGUAGE.equals(name)) {
          // The spec says if a schema is given via SAXParserFactory
          // the JAXP 1.2 properties shouldn't be allowed.
          if (fSAXParser.grammar != null) {
            throw new SAXNotSupportedException(
                SAXMessageFormatter.formatMessage(
                    fConfiguration.getLocale(), "schema-already-specified", new Object[] {name}));
          }
          if (W3C_XML_SCHEMA.equals(value)) {
            // None of the properties will take effect till the setValidating(true) has been called
            if (fSAXParser.isValidating()) {
              fSAXParser.schemaLanguage = W3C_XML_SCHEMA;
              setFeature(XMLSCHEMA_VALIDATION_FEATURE, true);
              // this will allow the parser not to emit DTD-related
              // errors, as the spec demands
              if (!fInitProperties.containsKey(JAXP_SCHEMA_LANGUAGE)) {
                fInitProperties.put(JAXP_SCHEMA_LANGUAGE, super.getProperty(JAXP_SCHEMA_LANGUAGE));
              }
              super.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
            }

          } else if (value == null) {
            fSAXParser.schemaLanguage = null;
            setFeature(XMLSCHEMA_VALIDATION_FEATURE, false);
          } else {
            // REVISIT: It would be nice if we could format this message
            // using a user specified locale as we do in the underlying
            // XMLReader -- mrglavas
            throw new SAXNotSupportedException(
                SAXMessageFormatter.formatMessage(
                    fConfiguration.getLocale(), "schema-not-supported", null));
          }
          return;
        } else if (JAXP_SCHEMA_SOURCE.equals(name)) {
          // The spec says if a schema is given via SAXParserFactory
          // the JAXP 1.2 properties shouldn't be allowed.
          if (fSAXParser.grammar != null) {
            throw new SAXNotSupportedException(
                SAXMessageFormatter.formatMessage(
                    fConfiguration.getLocale(), "schema-already-specified", new Object[] {name}));
          }
          String val = (String) getProperty(JAXP_SCHEMA_LANGUAGE);
          if (val != null && W3C_XML_SCHEMA.equals(val)) {
            if (!fInitProperties.containsKey(JAXP_SCHEMA_SOURCE)) {
              fInitProperties.put(JAXP_SCHEMA_SOURCE, super.getProperty(JAXP_SCHEMA_SOURCE));
            }
            super.setProperty(name, value);
          } else {
            throw new SAXNotSupportedException(
                SAXMessageFormatter.formatMessage(
                    fConfiguration.getLocale(),
                    "jaxp-order-not-supported",
                    new Object[] {JAXP_SCHEMA_LANGUAGE, JAXP_SCHEMA_SOURCE}));
          }
          return;
        }
      }
      /** Forward property to the schema validator if there is one. * */
      if (fSAXParser != null && fSAXParser.fSchemaValidator != null) {
        setSchemaValidatorProperty(name, value);
      }

      // check if the property is managed by security manager
      if (fSecurityManager == null
          || !fSecurityManager.setLimit(name, XMLSecurityManager.State.APIPROPERTY, value)) {
        // check if the property is managed by security property manager
        if (fSecurityPropertyMgr == null
            || !fSecurityPropertyMgr.setValue(
                name, XMLSecurityPropertyManager.State.APIPROPERTY, value)) {
          // fall back to the existing property manager
          if (!fInitProperties.containsKey(name)) {
            fInitProperties.put(name, super.getProperty(name));
          }
          super.setProperty(name, value);
        }
      }
    }