/**
   * 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);
      }
    }
  }
    /**
     * 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);
        }
      }
    }