content: /*
   * 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 mf.org.apache.xerces.parsers;
  
  import java.io.IOException;
  import java.util.Locale;
  
  import mf.org.apache.xerces.impl.Constants;
  import mf.org.apache.xerces.impl.XMLDTDScannerImpl;
  import mf.org.apache.xerces.impl.XMLDocumentScannerImpl;
  import mf.org.apache.xerces.impl.XMLEntityManager;
  import mf.org.apache.xerces.impl.XMLErrorReporter;
  import mf.org.apache.xerces.impl.XMLNSDocumentScannerImpl;
  import mf.org.apache.xerces.impl.dv.DTDDVFactory;
  import mf.org.apache.xerces.impl.msg.XMLMessageFormatter;
  import mf.org.apache.xerces.impl.validation.ValidationManager;
  import mf.org.apache.xerces.util.SymbolTable;
  import mf.org.apache.xerces.xni.XMLLocator;
  import mf.org.apache.xerces.xni.XNIException;
  import mf.org.apache.xerces.xni.grammars.XMLGrammarPool;
  import mf.org.apache.xerces.xni.parser.XMLComponent;
  import mf.org.apache.xerces.xni.parser.XMLComponentManager;
  import mf.org.apache.xerces.xni.parser.XMLConfigurationException;
  import mf.org.apache.xerces.xni.parser.XMLDTDScanner;
  import mf.org.apache.xerces.xni.parser.XMLDocumentScanner;
  import mf.org.apache.xerces.xni.parser.XMLInputSource;
  import mf.org.apache.xerces.xni.parser.XMLPullParserConfiguration;
  
  
  /**
   * This is the non validating parser configuration. It extends the basic
   * configuration with the set of following parser components:
   * Document scanner, DTD scanner, namespace binder, document handler.
   * <p/>
   * Xerces parser that uses this configuration is <strong>not</strong> <a href="http://www.w3.org/TR/REC-xml#sec-conformance">conformant</a>
   * non-validating XML processor, since conformant non-validating processor is required
   * to process "all the declarations they read in the internal DTD subset ... must use the information in those declarations to normalize attribute values,
   * include the replacement text of internal entities, and supply default attribute values".
   *
   * @author Elena Litani, IBM
   * @version $Id: NonValidatingConfiguration.java 713638 2008-11-13 04:42:18Z mrglavas $
   */
  public class NonValidatingConfiguration
          extends BasicParserConfiguration
          implements XMLPullParserConfiguration {
  
      //
      // Constants
      //
  
      // feature identifiers
  
      /**
       * Feature identifier: warn on duplicate attribute definition.
       */
      protected static final String WARN_ON_DUPLICATE_ATTDEF =
              Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
  
      /**
       * Feature identifier: warn on duplicate entity definition.
       */
      protected static final String WARN_ON_DUPLICATE_ENTITYDEF =
              Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ENTITYDEF_FEATURE;
  
      /**
       * Feature identifier: warn on undeclared element definition.
       */
      protected static final String WARN_ON_UNDECLARED_ELEMDEF =
              Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_UNDECLARED_ELEMDEF_FEATURE;
  
      /**
       * Feature identifier: allow Java encodings.
       */
      protected static final String ALLOW_JAVA_ENCODINGS =
              Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
  
      /**
       * Feature identifier: continue after fatal error.
       */
      protected static final String CONTINUE_AFTER_FATAL_ERROR =
              Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
  
      /**
       * Feature identifier: load external DTD.
       */
      protected static final String LOAD_EXTERNAL_DTD =
              Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE;
  
      /**
       * Feature identifier: notify built-in refereces.
       */
      protected static final String NOTIFY_BUILTIN_REFS =
              Constants.XERCES_FEATURE_PREFIX + Constants.NOTIFY_BUILTIN_REFS_FEATURE;
  
      /**
       * Feature identifier: notify character refereces.
       */
      protected static final String NOTIFY_CHAR_REFS =
              Constants.XERCES_FEATURE_PREFIX + Constants.NOTIFY_CHAR_REFS_FEATURE;
  
  
      /**
       * Feature identifier: expose schema normalized value
       */
      protected static final String NORMALIZE_DATA =
              Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE;
  
  
      /**
       * Feature identifier: send element default value via characters()
       */
      protected static final String SCHEMA_ELEMENT_DEFAULT =
              Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_ELEMENT_DEFAULT;
  
      // property identifiers
  
      /**
       * Property identifier: error reporter.
       */
      protected static final String ERROR_REPORTER =
              Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
  
      /**
       * Property identifier: entity manager.
       */
      protected static final String ENTITY_MANAGER =
              Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
  
      /**
       * Property identifier document scanner:
       */
      protected static final String DOCUMENT_SCANNER =
              Constants.XERCES_PROPERTY_PREFIX + Constants.DOCUMENT_SCANNER_PROPERTY;
  
      /**
       * Property identifier: DTD scanner.
       */
      protected static final String DTD_SCANNER =
              Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_SCANNER_PROPERTY;
  
      /**
       * Property identifier: grammar pool.
       */
      protected static final String XMLGRAMMAR_POOL =
              Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
  
      /**
       * Property identifier: DTD validator.
       */
      protected static final String DTD_VALIDATOR =
              Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_VALIDATOR_PROPERTY;
  
      /**
       * Property identifier: namespace binder.
       */
      protected static final String NAMESPACE_BINDER =
              Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_BINDER_PROPERTY;
  
      /**
       * Property identifier: datatype validator factory.
       */
      protected static final String DATATYPE_VALIDATOR_FACTORY =
              Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
  
      protected static final String VALIDATION_MANAGER =
              Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
  
      /**
       * Property identifier: XML Schema validator.
       */
      protected static final String SCHEMA_VALIDATOR =
              Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_VALIDATOR_PROPERTY;
  
      /**
       * Property identifier: locale.
       */
      protected static final String LOCALE =
              Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY;
  
  
      // debugging
  
      /**
       * Set to true and recompile to print exception stack trace.
       */
      private static final boolean PRINT_EXCEPTION_STACK_TRACE = false;
  
      //
      // Data
      //
  
      // components (non-configurable)
  
      /**
       * Grammar pool.
       */
      protected XMLGrammarPool fGrammarPool;
  
      /**
       * Datatype validator factory.
       */
      protected DTDDVFactory fDatatypeValidatorFactory;
  
      // components (configurable)
  
      /**
       * Error reporter.
       */
      protected XMLErrorReporter fErrorReporter;
  
      /**
       * Entity manager.
       */
      protected XMLEntityManager fEntityManager;
  
      /**
       * Document scanner.
       */
      protected XMLDocumentScanner fScanner;
  
      /**
       * Input Source
       */
      protected XMLInputSource fInputSource;
  
      /**
       * DTD scanner.
       */
      protected XMLDTDScanner fDTDScanner;
  
  
      protected ValidationManager fValidationManager;
  
      // private data
      /**
       * fConfigUpdated is set to true if there has been any change to the configuration settings,
       * i.e a feature or a property was changed.
       */
      protected boolean fConfigUpdated = false;
      /**
       * Locator
       */
      protected XMLLocator fLocator;
      /**
       * True if a parse is in progress. This state is needed because
       * some features/properties cannot be set while parsing (e.g.
       * validation and namespaces).
       */
      protected boolean fParseInProgress = false;
  
  
      // state
      /**
       * Document scanner that does namespace binding.
       */
      private XMLNSDocumentScannerImpl fNamespaceScanner;
      /**
       * Default Xerces implementation of scanner
       */
      private XMLDocumentScannerImpl fNonNSScanner;
  
      //
      // Constructors
      //
  
      /**
       * Default constructor.
       */
      public NonValidatingConfiguration() {
          this(null, null, null);
      } // <init>()
  
      /**
       * Constructs a parser configuration using the specified symbol table.
       *
       * @param symbolTable The symbol table to use.
       */
      public NonValidatingConfiguration(SymbolTable symbolTable) {
          this(symbolTable, null, null);
      } // <init>(SymbolTable)
  
      /**
       * Constructs a parser configuration using the specified symbol table and
       * grammar pool.
       * <p/>
       * <strong>REVISIT:</strong>
       * Grammar pool will be updated when the new validation engine is
       * implemented.
       *
       * @param symbolTable The symbol table to use.
       * @param grammarPool The grammar pool to use.
       */
      public NonValidatingConfiguration(SymbolTable symbolTable,
                                        XMLGrammarPool grammarPool) {
          this(symbolTable, grammarPool, null);
      } // <init>(SymbolTable,XMLGrammarPool)
  
      /**
       * Constructs a parser configuration using the specified symbol table,
       * grammar pool, and parent settings.
       * <p/>
       * <strong>REVISIT:</strong>
       * Grammar pool will be updated when the new validation engine is
       * implemented.
       *
       * @param symbolTable    The symbol table to use.
       * @param grammarPool    The grammar pool to use.
       * @param parentSettings The parent settings.
       */
      public NonValidatingConfiguration(SymbolTable symbolTable,
                                        XMLGrammarPool grammarPool,
                                        XMLComponentManager parentSettings) {
          super(symbolTable, parentSettings);
  
          // add default recognized features
          final String[] recognizedFeatures = {
                  PARSER_SETTINGS,
                  NAMESPACES,
                  //WARN_ON_DUPLICATE_ATTDEF,     // from XMLDTDScannerImpl
                  //WARN_ON_UNDECLARED_ELEMDEF,   // from XMLDTDScannerImpl
                  //ALLOW_JAVA_ENCODINGS,         // from XMLEntityManager
                  CONTINUE_AFTER_FATAL_ERROR,
                  //LOAD_EXTERNAL_DTD,    // from XMLDTDScannerImpl
                  //NOTIFY_BUILTIN_REFS,  // from XMLDocumentFragmentScannerImpl
                  //NOTIFY_CHAR_REFS,		// from XMLDocumentFragmentScannerImpl
                  //WARN_ON_DUPLICATE_ENTITYDEF   // from XMLEntityManager
          };
          addRecognizedFeatures(recognizedFeatures);
  
          // set state for default features
          //setFeature(WARN_ON_DUPLICATE_ATTDEF, false);  // from XMLDTDScannerImpl
          //setFeature(WARN_ON_UNDECLARED_ELEMDEF, false);    // from XMLDTDScannerImpl
          //setFeature(ALLOW_JAVA_ENCODINGS, false);      // from XMLEntityManager
          fFeatures.put(CONTINUE_AFTER_FATAL_ERROR, Boolean.FALSE);
          fFeatures.put(PARSER_SETTINGS, Boolean.TRUE);
          fFeatures.put(NAMESPACES, Boolean.TRUE);
          //setFeature(LOAD_EXTERNAL_DTD, true);      // from XMLDTDScannerImpl
          //setFeature(NOTIFY_BUILTIN_REFS, false);   // from XMLDocumentFragmentScannerImpl
          //setFeature(NOTIFY_CHAR_REFS, false);      // from XMLDocumentFragmentScannerImpl
          //setFeature(WARN_ON_DUPLICATE_ENTITYDEF, false);   // from XMLEntityManager
  
          // add default recognized properties
          final String[] recognizedProperties = {
                  ERROR_REPORTER,
                  ENTITY_MANAGER,
                  DOCUMENT_SCANNER,
                  DTD_SCANNER,
                  DTD_VALIDATOR,
                  NAMESPACE_BINDER,
                  XMLGRAMMAR_POOL,
                  DATATYPE_VALIDATOR_FACTORY,
                  VALIDATION_MANAGER,
                  LOCALE
          };
          addRecognizedProperties(recognizedProperties);
  
          fGrammarPool = grammarPool;
          if (fGrammarPool != null) {
              fProperties.put(XMLGRAMMAR_POOL, fGrammarPool);
          }
  
          fEntityManager = createEntityManager();
          fProperties.put(ENTITY_MANAGER, fEntityManager);
          addComponent(fEntityManager);
  
          fErrorReporter = createErrorReporter();
          fErrorReporter.setDocumentLocator(fEntityManager.getEntityScanner());
          fProperties.put(ERROR_REPORTER, fErrorReporter);
          addComponent(fErrorReporter);
  
          // this configuration delays creation of the scanner
          // till it is known if namespace processing should be performed
  
          fDTDScanner = createDTDScanner();
          if (fDTDScanner != null) {
              fProperties.put(DTD_SCANNER, fDTDScanner);
              if (fDTDScanner instanceof XMLComponent) {
                  addComponent((XMLComponent) fDTDScanner);
              }
          }
  
          fDatatypeValidatorFactory = createDatatypeValidatorFactory();
          if (fDatatypeValidatorFactory != null) {
              fProperties.put(DATATYPE_VALIDATOR_FACTORY,
                      fDatatypeValidatorFactory);
          }
          fValidationManager = createValidationManager();
  
          if (fValidationManager != null) {
              fProperties.put(VALIDATION_MANAGER, fValidationManager);
          }
          // add message formatters
          if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
              XMLMessageFormatter xmft = new XMLMessageFormatter();
              fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
              fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
          }
  
          fConfigUpdated = false;
  
          // set locale
          try {
              setLocale(Locale.getDefault());
          } catch (XNIException e) {
              // do nothing
              // REVISIT: What is the right thing to do? -Ac
          }
  
      } // <init>(SymbolTable,XMLGrammarPool)
  
      //
      // Public methods
      //
      @Override
      public void setFeature(String featureId, boolean state)
              throws XMLConfigurationException {
          fConfigUpdated = true;
          super.setFeature(featureId, state);
      }
  
      @Override
      public Object getProperty(String propertyId)
              throws XMLConfigurationException {
          if (LOCALE.equals(propertyId)) {
              return getLocale();
          }
          return super.getProperty(propertyId);
      }
  
      @Override
      public void setProperty(String propertyId, Object value)
              throws XMLConfigurationException {
          fConfigUpdated = true;
          if (LOCALE.equals(propertyId)) {
              setLocale((Locale) value);
          }
          super.setProperty(propertyId, value);
      }
  
      /**
       * Set the locale to use for messages.
       *
       * @param locale The locale object to use for localization of messages.
       * @throws XNIException Thrown if the parser does not support the
       *                      specified locale.
       */
      @Override
      public void setLocale(Locale locale) throws XNIException {
          super.setLocale(locale);
          fErrorReporter.setLocale(locale);
      } // setLocale(Locale)
  
      @Override
      public boolean getFeature(String featureId)
              throws XMLConfigurationException {
          // make this feature special
          if (featureId.equals(PARSER_SETTINGS)) {
              return fConfigUpdated;
          }
          return super.getFeature(featureId);
  
      } // getFeature(String):boolean
      //
      // XMLPullParserConfiguration methods
      //
  
      // parsing
  
      /**
       * Sets the input source for the document to parse.
       *
       * @param inputSource The document's input source.
       * @throws XMLConfigurationException Thrown if there is a
       *                                   configuration error when initializing the
       *                                   parser.
       * @throws IOException               Thrown on I/O error.
       * @see #parse(boolean)
       */
      @Override
      public void setInputSource(XMLInputSource inputSource)
              throws XMLConfigurationException, IOException {
  
          // REVISIT: this method used to reset all the components and
          //          construct the pipeline. Now reset() is called
          //          in parse (boolean) just before we parse the document
          //          Should this method still throw exceptions..?
  
          fInputSource = inputSource;
  
      } // setInputSource(XMLInputSource)
  
      /**
       * Parses the document in a pull parsing fashion.
       *
       * @param complete True if the pull parser should parse the
       *                 remaining document completely.
       * @return True if there is more document to parse.
       * @throws XNIException Any XNI exception, possibly wrapping
       *                      another exception.
       * @throws IOException  An IO exception from the parser, possibly
       *                      from a byte stream or character stream
       *                      supplied by the parser.
       * @see #setInputSource
       */
      @Override
      public boolean parse(boolean complete) throws XNIException, IOException {
          //
          // reset and configure pipeline and set InputSource.
          if (fInputSource != null) {
              try {
                  // resets and sets the pipeline.
                  reset();
                  fScanner.setInputSource(fInputSource);
                  fInputSource = null;
              } catch (XNIException ex) {
                  if (PRINT_EXCEPTION_STACK_TRACE)
                      ex.printStackTrace();
                  throw ex;
              } catch (IOException ex) {
                  if (PRINT_EXCEPTION_STACK_TRACE)
                      ex.printStackTrace();
                  throw ex;
              } catch (RuntimeException ex) {
                  if (PRINT_EXCEPTION_STACK_TRACE)
                      ex.printStackTrace();
                  throw ex;
              } catch (Exception ex) {
                  if (PRINT_EXCEPTION_STACK_TRACE)
                      ex.printStackTrace();
                  throw new XNIException(ex);
              }
          }
  
          try {
              return fScanner.scanDocument(complete);
          } catch (XNIException ex) {
              if (PRINT_EXCEPTION_STACK_TRACE)
                  ex.printStackTrace();
              throw ex;
          } catch (IOException ex) {
              if (PRINT_EXCEPTION_STACK_TRACE)
                  ex.printStackTrace();
              throw ex;
          } catch (RuntimeException ex) {
              if (PRINT_EXCEPTION_STACK_TRACE)
                  ex.printStackTrace();
              throw ex;
          } catch (Exception ex) {
              if (PRINT_EXCEPTION_STACK_TRACE)
                  ex.printStackTrace();
              throw new XNIException(ex);
          }
  
      } // parse(boolean):boolean
  
      /**
       * If the application decides to terminate parsing before the xml document
       * is fully parsed, the application should call this method to free any
       * resource allocated during parsing. For example, close all opened streams.
       */
      @Override
      public void cleanup() {
          fEntityManager.closeReaders();
      }
  
      //
      // XMLParserConfiguration methods
      //
  
      /**
       * Parses the specified input source.
       *
       * @param source The input source.
       * @throws XNIException        Throws exception on XNI error.
       * @throws java.io.IOException Throws exception on i/o error.
       */
      @Override
      public void parse(XMLInputSource source) throws XNIException, IOException {
  
          if (fParseInProgress) {
              // REVISIT - need to add new error message
              throw new XNIException("FWK005 parse may not be called while parsing.");
          }
          fParseInProgress = true;
  
          try {
              setInputSource(source);
              parse(true);
          } catch (XNIException ex) {
              if (PRINT_EXCEPTION_STACK_TRACE)
                  ex.printStackTrace();
              throw ex;
          } catch (IOException ex) {
              if (PRINT_EXCEPTION_STACK_TRACE)
                  ex.printStackTrace();
              throw ex;
          } catch (RuntimeException ex) {
              if (PRINT_EXCEPTION_STACK_TRACE)
                  ex.printStackTrace();
              throw ex;
          } catch (Exception ex) {
              if (PRINT_EXCEPTION_STACK_TRACE)
                  ex.printStackTrace();
              throw new XNIException(ex);
          } finally {
              fParseInProgress = false;
              // close all streams opened by xerces
              this.cleanup();
          }
  
      } // parse(InputSource)
  
      //
      // Protected methods
      //
  
      /**
       * Reset all components before parsing.
       *
       * @throws XNIException Thrown if an error occurs during initialization.
       */
      @Override
      protected void reset() throws XNIException {
  
          if (fValidationManager != null)
              fValidationManager.reset();
          // configure the pipeline and initialize the components
          configurePipeline();
          super.reset();
  
      } // reset()
  
      /**
       * Configures the pipeline.
       */
      protected void configurePipeline() {
          // create appropriate scanner
          // and register it as one of the components.
          if (fFeatures.get(NAMESPACES) == Boolean.TRUE) {
              if (fNamespaceScanner == null) {
                  fNamespaceScanner = new XMLNSDocumentScannerImpl();
                  addComponent(fNamespaceScanner);
              }
              fProperties.put(DOCUMENT_SCANNER, fNamespaceScanner);
              fNamespaceScanner.setDTDValidator(null);
              fScanner = fNamespaceScanner;
          } else {
              if (fNonNSScanner == null) {
                  fNonNSScanner = new XMLDocumentScannerImpl();
                  addComponent(fNonNSScanner);
              }
              fProperties.put(DOCUMENT_SCANNER, fNonNSScanner);
              fScanner = fNonNSScanner;
          }
  
          fScanner.setDocumentHandler(fDocumentHandler);
          fLastComponent = fScanner;
          // setup dtd pipeline
          if (fDTDScanner != null) {
              fDTDScanner.setDTDHandler(fDTDHandler);
              fDTDScanner.setDTDContentModelHandler(fDTDContentModelHandler);
          }
  
  
      } // configurePipeline()
  
      // features and properties
  
      /**
       * Check a feature. If feature is know and supported, this method simply
       * returns. Otherwise, the appropriate exception is thrown.
       *
       * @param featureId The unique identifier (URI) of the feature.
       * @throws XMLConfigurationException Thrown for configuration error.
       *                                   In general, components should
       *                                   only throw this exception if
       *                                   it is <strong>really</strong>
       *                                   a critical error.
       */
      @Override
      protected void checkFeature(String featureId)
              throws XMLConfigurationException {
  
          //
          // Xerces Features
          //
  
          if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
              final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
  
              //
              // http://apache.org/xml/features/validation/dynamic
              //   Allows the parser to validate a document only when it
              //   contains a grammar. Validation is turned on/off based
              //   on each document instance, automatically.
              //
              if (suffixLength == Constants.DYNAMIC_VALIDATION_FEATURE.length() &&
                      featureId.endsWith(Constants.DYNAMIC_VALIDATION_FEATURE)) {
                  return;
              }
              //
              // http://apache.org/xml/features/validation/default-attribute-values
              //
              if (suffixLength == Constants.DEFAULT_ATTRIBUTE_VALUES_FEATURE.length() &&
                      featureId.endsWith(Constants.DEFAULT_ATTRIBUTE_VALUES_FEATURE)) {
                  // REVISIT
                  short type = XMLConfigurationException.NOT_SUPPORTED;
                  throw new XMLConfigurationException(type, featureId);
              }
              //
              // http://apache.org/xml/features/validation/default-attribute-values
              //
              if (suffixLength == Constants.VALIDATE_CONTENT_MODELS_FEATURE.length() &&
                      featureId.endsWith(Constants.VALIDATE_CONTENT_MODELS_FEATURE)) {
                  // REVISIT
                  short type = XMLConfigurationException.NOT_SUPPORTED;
                  throw new XMLConfigurationException(type, featureId);
              }
              //
              // http://apache.org/xml/features/validation/nonvalidating/load-dtd-grammar
              //
              if (suffixLength == Constants.LOAD_DTD_GRAMMAR_FEATURE.length() &&
                      featureId.endsWith(Constants.LOAD_DTD_GRAMMAR_FEATURE)) {
                  return;
              }
              //
              // http://apache.org/xml/features/validation/nonvalidating/load-external-dtd
              //
              if (suffixLength == Constants.LOAD_EXTERNAL_DTD_FEATURE.length() &&
                      featureId.endsWith(Constants.LOAD_EXTERNAL_DTD_FEATURE)) {
                  return;
              }
  
              //
              // http://apache.org/xml/features/validation/default-attribute-values
              //
              if (suffixLength == Constants.VALIDATE_DATATYPES_FEATURE.length() &&
                      featureId.endsWith(Constants.VALIDATE_DATATYPES_FEATURE)) {
                  short type = XMLConfigurationException.NOT_SUPPORTED;
                  throw new XMLConfigurationException(type, featureId);
              }
          }
  
          //
          // Not recognized
          //
  
          super.checkFeature(featureId);
  
      } // checkFeature(String)
  
      /**
       * Check a property. If the property is know and supported, this method
       * simply returns. Otherwise, the appropriate exception is thrown.
       *
       * @param propertyId The unique identifier (URI) of the property
       *                   being set.
       * @throws XMLConfigurationException Thrown for configuration error.
       *                                   In general, components should
       *                                   only throw this exception if
       *                                   it is <strong>really</strong>
       *                                   a critical error.
       */
      @Override
      protected void checkProperty(String propertyId)
              throws XMLConfigurationException {
  
          //
          // Xerces Properties
          //
  
          if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
              final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
  
              if (suffixLength == Constants.DTD_SCANNER_PROPERTY.length() &&
                      propertyId.endsWith(Constants.DTD_SCANNER_PROPERTY)) {
                  return;
              }
          }
  
          if (propertyId.startsWith(Constants.JAXP_PROPERTY_PREFIX)) {
              final int suffixLength = propertyId.length() - Constants.JAXP_PROPERTY_PREFIX.length();
  
              if (suffixLength == Constants.SCHEMA_SOURCE.length() &&
                      propertyId.endsWith(Constants.SCHEMA_SOURCE)) {
                  return;
              }
          }
  
          //
          // Not recognized
          //
  
          super.checkProperty(propertyId);
  
      } // checkProperty(String)
  
      // factory methods
  
      /**
       * Creates an entity manager.
       */
      protected XMLEntityManager createEntityManager() {
          return new XMLEntityManager();
      } // createEntityManager():XMLEntityManager
  
      /**
       * Creates an error reporter.
       */
      protected XMLErrorReporter createErrorReporter() {
          return new XMLErrorReporter();
      } // createErrorReporter():XMLErrorReporter
  
      /**
       * Create a document scanner.
       */
      protected XMLDocumentScanner createDocumentScanner() {
          return null;
      } // createDocumentScanner():XMLDocumentScanner
  
      /**
       * Create a DTD scanner.
       */
      protected XMLDTDScanner createDTDScanner() {
          return new XMLDTDScannerImpl();
      } // createDTDScanner():XMLDTDScanner
  
      /**
       * Create a datatype validator factory.
       */
      protected DTDDVFactory createDatatypeValidatorFactory() {
          return DTDDVFactory.getInstance();
      } // createDatatypeValidatorFactory():DatatypeValidatorFactory
  
      protected ValidationManager createValidationManager() {
          return new ValidationManager();
      }
  
  } // class NonValidatingConfiguration
  