1 /*
   2  * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Licensed to the Apache Software Foundation (ASF) under one or more
   6  * contributor license agreements.  See the NOTICE file distributed with
   7  * this work for additional information regarding copyright ownership.
   8  * The ASF licenses this file to You under the Apache License, Version 2.0
   9  * (the "License"); you may not use this file except in compliance with
  10  * the License.  You may obtain a copy of the License at
  11  *
  12  *      http://www.apache.org/licenses/LICENSE-2.0
  13  *
  14  * Unless required by applicable law or agreed to in writing, software
  15  * distributed under the License is distributed on an "AS IS" BASIS,
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  17  * See the License for the specific language governing permissions and
  18  * limitations under the License.
  19  */
  20 
  21 package com.sun.org.apache.xerces.internal.parsers;
  22 
  23 import java.io.IOException;
  24 import java.util.ArrayList;
  25 import java.util.HashMap;
  26 import java.util.Locale;
  27 
  28 import com.sun.org.apache.xerces.internal.impl.Constants;
  29 import com.sun.org.apache.xerces.internal.impl.XML11DTDScannerImpl;
  30 import com.sun.org.apache.xerces.internal.impl.XML11DocumentScannerImpl;
  31 import com.sun.org.apache.xerces.internal.impl.XML11NSDocumentScannerImpl;
  32 import com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl;
  33 import com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl;
  34 import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler;
  35 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
  36 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
  37 import com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl;
  38 import com.sun.org.apache.xerces.internal.impl.XMLVersionDetector;
  39 import com.sun.org.apache.xerces.internal.impl.dtd.XML11DTDProcessor;
  40 import com.sun.org.apache.xerces.internal.impl.dtd.XML11DTDValidator;
  41 import com.sun.org.apache.xerces.internal.impl.dtd.XML11NSDTDValidator;
  42 import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDProcessor;
  43 import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator;
  44 import com.sun.org.apache.xerces.internal.impl.dtd.XMLNSDTDValidator;
  45 import com.sun.org.apache.xerces.internal.impl.dv.DTDDVFactory;
  46 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
  47 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
  48 import com.sun.org.apache.xerces.internal.util.FeatureState;
  49 import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings;
  50 import com.sun.org.apache.xerces.internal.util.PropertyState;
  51 import com.sun.org.apache.xerces.internal.util.SymbolTable;
  52 import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler;
  53 import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler;
  54 import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
  55 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
  56 import com.sun.org.apache.xerces.internal.xni.XNIException;
  57 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
  58 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
  59 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
  60 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
  61 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDScanner;
  62 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentScanner;
  63 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
  64 import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
  65 import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler;
  66 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
  67 import com.sun.org.apache.xerces.internal.xni.parser.XMLPullParserConfiguration;
  68 
  69 /**
  70  * This class is the DTD-only parser configuration
  71  * used to parse XML 1.0 and XML 1.1 documents.
  72  *
  73  * <p>
  74  * This class recognizes the following features and properties:
  75  * <ul>
  76  * <li>Features
  77  *  <ul>
  78  *   <li>http://xml.org/sax/features/validation</li>
  79  *   <li>http://xml.org/sax/features/namespaces</li>
  80  *   <li>http://xml.org/sax/features/external-general-entities</li>
  81  *   <li>http://xml.org/sax/features/external-parameter-entities</li>
  82  *   <li>http://apache.org/xml/features/continue-after-fatal-error</li>
  83  *   <li>http://apache.org/xml/features/load-external-dtd</li>
  84  *  </ul>
  85  * <li>Properties
  86  *  <ul>
  87  *   <li>http://xml.org/sax/properties/xml-string</li>
  88  *   <li>http://apache.org/xml/properties/internal/symbol-table</li>
  89  *   <li>http://apache.org/xml/properties/internal/error-handler</li>
  90  *   <li>http://apache.org/xml/properties/internal/entity-resolver</li>
  91  *   <li>http://apache.org/xml/properties/internal/error-reporter</li>
  92  *   <li>http://apache.org/xml/properties/internal/entity-manager</li>
  93  *   <li>http://apache.org/xml/properties/internal/document-scanner</li>
  94  *   <li>http://apache.org/xml/properties/internal/dtd-scanner</li>
  95  *   <li>http://apache.org/xml/properties/internal/grammar-pool</li>
  96  *   <li>http://apache.org/xml/properties/internal/validator/dtd</li>
  97  *   <li>http://apache.org/xml/properties/internal/datatype-validator-factory</li>
  98  *  </ul>
  99  * </ul>
 100  * @author Elena Litani, IBM
 101  * @author Neil Graham, IBM
 102  * @author Michael Glavassevich, IBM
 103  * @author John Kim, IBM
 104  *
 105  */
 106 public class XML11DTDConfiguration extends ParserConfigurationSettings
 107     implements XMLPullParserConfiguration, XML11Configurable {
 108 
 109     //
 110     // Constants
 111     //
 112     protected final static String XML11_DATATYPE_VALIDATOR_FACTORY =
 113         "com.sun.org.apache.xerces.internal.impl.dv.dtd.XML11DTDDVFactoryImpl";
 114 
 115     // feature identifiers
 116 
 117     /** Feature identifier: validation. */
 118     protected static final String VALIDATION =
 119         Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
 120 
 121     /** Feature identifier: namespaces. */
 122     protected static final String NAMESPACES =
 123         Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
 124 
 125     /** Feature identifier: external general entities. */
 126     protected static final String EXTERNAL_GENERAL_ENTITIES =
 127         Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE;
 128 
 129     /** Feature identifier: external parameter entities. */
 130     protected static final String EXTERNAL_PARAMETER_ENTITIES =
 131         Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE;
 132 
 133     /** Feature identifier: continue after fatal error. */
 134     protected static final String CONTINUE_AFTER_FATAL_ERROR =
 135         Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
 136 
 137     /** Feature identifier: load external DTD. */
 138     protected static final String LOAD_EXTERNAL_DTD =
 139         Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE;
 140 
 141     // property identifiers
 142 
 143         /** Property identifier: xml string. */
 144         protected static final String XML_STRING =
 145                 Constants.SAX_PROPERTY_PREFIX + Constants.XML_STRING_PROPERTY;
 146 
 147         /** Property identifier: symbol table. */
 148         protected static final String SYMBOL_TABLE =
 149                 Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
 150 
 151         /** Property identifier: error handler. */
 152         protected static final String ERROR_HANDLER =
 153                 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
 154 
 155         /** Property identifier: entity resolver. */
 156         protected static final String ENTITY_RESOLVER =
 157                 Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
 158 
 159     /** Property identifier: error reporter. */
 160     protected static final String ERROR_REPORTER =
 161         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
 162 
 163     /** Property identifier: entity manager. */
 164     protected static final String ENTITY_MANAGER =
 165         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
 166 
 167     /** Property identifier document scanner: */
 168     protected static final String DOCUMENT_SCANNER =
 169         Constants.XERCES_PROPERTY_PREFIX + Constants.DOCUMENT_SCANNER_PROPERTY;
 170 
 171     /** Property identifier: DTD scanner. */
 172     protected static final String DTD_SCANNER =
 173         Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_SCANNER_PROPERTY;
 174 
 175     /** Property identifier: grammar pool. */
 176     protected static final String XMLGRAMMAR_POOL =
 177         Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
 178 
 179     /** Property identifier: DTD loader. */
 180     protected static final String DTD_PROCESSOR =
 181         Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_PROCESSOR_PROPERTY;
 182 
 183     /** Property identifier: DTD validator. */
 184     protected static final String DTD_VALIDATOR =
 185         Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_VALIDATOR_PROPERTY;
 186 
 187     /** Property identifier: namespace binder. */
 188     protected static final String NAMESPACE_BINDER =
 189         Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_BINDER_PROPERTY;
 190 
 191     /** Property identifier: datatype validator factory. */
 192     protected static final String DATATYPE_VALIDATOR_FACTORY =
 193         Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
 194 
 195     protected static final String VALIDATION_MANAGER =
 196         Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
 197 
 198     /** Property identifier: JAXP schema language / DOM schema-type. */
 199     protected static final String JAXP_SCHEMA_LANGUAGE =
 200         Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE;
 201 
 202     /** Property identifier: JAXP schema source/ DOM schema-location. */
 203     protected static final String JAXP_SCHEMA_SOURCE =
 204         Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
 205 
 206     // debugging
 207 
 208     /** Set to true and recompile to print exception stack trace. */
 209     protected static final boolean PRINT_EXCEPTION_STACK_TRACE = false;
 210 
 211     //
 212     // Data
 213     //
 214     protected SymbolTable fSymbolTable;
 215     protected XMLInputSource fInputSource;
 216     protected ValidationManager fValidationManager;
 217     protected XMLVersionDetector fVersionDetector;
 218     protected XMLLocator fLocator;
 219     protected Locale fLocale;
 220 
 221     /** XML 1.0 Components. */
 222     protected ArrayList fComponents;
 223 
 224     /** XML 1.1. Components. */
 225     protected ArrayList fXML11Components = null;
 226 
 227     /** Common components: XMLEntityManager, XMLErrorReporter */
 228     protected ArrayList fCommonComponents = null;
 229 
 230     /** The document handler. */
 231     protected XMLDocumentHandler fDocumentHandler;
 232 
 233     /** The DTD handler. */
 234     protected XMLDTDHandler fDTDHandler;
 235 
 236     /** The DTD content model handler. */
 237     protected XMLDTDContentModelHandler fDTDContentModelHandler;
 238 
 239     /** Last component in the document pipeline */
 240     protected XMLDocumentSource fLastComponent;
 241 
 242     /**
 243      * True if a parse is in progress. This state is needed because
 244      * some features/properties cannot be set while parsing (e.g.
 245      * validation and namespaces).
 246      */
 247     protected boolean fParseInProgress = false;
 248 
 249     /**
 250      * fConfigUpdated is set to true if there has been any change to the configuration settings,
 251      * i.e a feature or a property was changed.
 252      */
 253     protected boolean fConfigUpdated = false;
 254 
 255     //
 256     // XML 1.0 components
 257     //
 258 
 259     /** The XML 1.0 Datatype validator factory. */
 260     protected DTDDVFactory fDatatypeValidatorFactory;
 261 
 262     /** The XML 1.0 Document scanner that does namespace binding. */
 263     protected XMLNSDocumentScannerImpl fNamespaceScanner;
 264 
 265     /** The XML 1.0 Non-namespace implementation of scanner */
 266     protected XMLDocumentScannerImpl fNonNSScanner;
 267 
 268     /** The XML 1.0 DTD Validator: binds namespaces */
 269     protected XMLDTDValidator fDTDValidator;
 270 
 271     /** The XML 1.0 DTD Validator that does not bind namespaces */
 272     protected XMLDTDValidator fNonNSDTDValidator;
 273 
 274     /** The XML 1.0 DTD scanner. */
 275     protected XMLDTDScanner fDTDScanner;
 276 
 277     /** The XML 1.0 DTD Processor . */
 278     protected XMLDTDProcessor fDTDProcessor;
 279 
 280     //
 281     // XML 1.1 components
 282     //
 283 
 284     /** The XML 1.1 datatype factory. **/
 285     protected DTDDVFactory fXML11DatatypeFactory = null;
 286 
 287     /** The XML 1.1 document scanner that does namespace binding. **/
 288     protected XML11NSDocumentScannerImpl fXML11NSDocScanner = null;
 289 
 290     /** The XML 1.1 document scanner that does not do namespace binding. **/
 291     protected XML11DocumentScannerImpl fXML11DocScanner = null;
 292 
 293     /** The XML 1.1 DTD validator that does namespace binding. **/
 294     protected XML11NSDTDValidator fXML11NSDTDValidator = null;
 295 
 296     /** The XML 1.1 DTD validator that does not do namespace binding. **/
 297     protected XML11DTDValidator fXML11DTDValidator = null;
 298 
 299     /** The XML 1.1 DTD scanner. **/
 300     protected XML11DTDScannerImpl fXML11DTDScanner = null;
 301 
 302     /** The XML 1.1 DTD processor. **/
 303     protected XML11DTDProcessor fXML11DTDProcessor = null;
 304 
 305     //
 306     // Common components
 307     //
 308 
 309     /** Grammar pool. */
 310     protected XMLGrammarPool fGrammarPool;
 311 
 312     /** Error reporter. */
 313     protected XMLErrorReporter fErrorReporter;
 314 
 315     /** Entity manager. */
 316     protected XMLEntityManager fEntityManager;
 317 
 318     /** Current scanner */
 319     protected XMLDocumentScanner fCurrentScanner;
 320 
 321     /** Current Datatype validator factory. */
 322     protected DTDDVFactory fCurrentDVFactory;
 323 
 324     /** Current DTD scanner. */
 325     protected XMLDTDScanner fCurrentDTDScanner;
 326 
 327     /** Flag indiciating whether XML11 components have been initialized. */
 328     private boolean f11Initialized = false;
 329 
 330     //
 331     // Constructors
 332     //
 333 
 334     /** Default constructor. */
 335     public XML11DTDConfiguration() {
 336         this(null, null, null);
 337     } // <init>()
 338 
 339     /**
 340      * Constructs a parser configuration using the specified symbol table.
 341      *
 342      * @param symbolTable The symbol table to use.
 343      */
 344     public XML11DTDConfiguration(SymbolTable symbolTable) {
 345         this(symbolTable, null, null);
 346     } // <init>(SymbolTable)
 347 
 348     /**
 349      * Constructs a parser configuration using the specified symbol table and
 350      * grammar pool.
 351      * <p>
 352      * <strong>REVISIT:</strong>
 353      * Grammar pool will be updated when the new validation engine is
 354      * implemented.
 355      *
 356      * @param symbolTable The symbol table to use.
 357      * @param grammarPool The grammar pool to use.
 358      */
 359     public XML11DTDConfiguration(SymbolTable symbolTable, XMLGrammarPool grammarPool) {
 360         this(symbolTable, grammarPool, null);
 361     } // <init>(SymbolTable,XMLGrammarPool)
 362 
 363     /**
 364      * Constructs a parser configuration using the specified symbol table,
 365      * grammar pool, and parent settings.
 366      * <p>
 367      * <strong>REVISIT:</strong>
 368      * Grammar pool will be updated when the new validation engine is
 369      * implemented.
 370      *
 371      * @param symbolTable    The symbol table to use.
 372      * @param grammarPool    The grammar pool to use.
 373      * @param parentSettings The parent settings.
 374      */
 375     public XML11DTDConfiguration(
 376         SymbolTable symbolTable,
 377         XMLGrammarPool grammarPool,
 378         XMLComponentManager parentSettings) {
 379 
 380                 super(parentSettings);
 381 
 382                 // create a vector to hold all the components in use
 383                 // XML 1.0 specialized components
 384                 fComponents = new ArrayList();
 385                 // XML 1.1 specialized components
 386                 fXML11Components = new ArrayList();
 387                 // Common components for XML 1.1. and XML 1.0
 388                 fCommonComponents = new ArrayList();
 389 
 390                 // create table for features and properties
 391                 fFeatures = new HashMap();
 392                 fProperties = new HashMap();
 393 
 394         // add default recognized features
 395         final String[] recognizedFeatures =
 396             {
 397                 CONTINUE_AFTER_FATAL_ERROR, LOAD_EXTERNAL_DTD, // from XMLDTDScannerImpl
 398                                 VALIDATION,
 399                                 NAMESPACES,
 400                                 EXTERNAL_GENERAL_ENTITIES,
 401                                 EXTERNAL_PARAMETER_ENTITIES,
 402                                 PARSER_SETTINGS
 403                         };
 404         addRecognizedFeatures(recognizedFeatures);
 405                 // set state for default features
 406                 fFeatures.put(VALIDATION, Boolean.FALSE);
 407                 fFeatures.put(NAMESPACES, Boolean.TRUE);
 408                 fFeatures.put(EXTERNAL_GENERAL_ENTITIES, Boolean.TRUE);
 409                 fFeatures.put(EXTERNAL_PARAMETER_ENTITIES, Boolean.TRUE);
 410                 fFeatures.put(CONTINUE_AFTER_FATAL_ERROR, Boolean.FALSE);
 411                 fFeatures.put(LOAD_EXTERNAL_DTD, Boolean.TRUE);
 412                 fFeatures.put(PARSER_SETTINGS, Boolean.TRUE);
 413 
 414         // add default recognized properties
 415         final String[] recognizedProperties =
 416             {
 417                                 SYMBOL_TABLE,
 418                                 ERROR_HANDLER,
 419                                 ENTITY_RESOLVER,
 420                 ERROR_REPORTER,
 421                 ENTITY_MANAGER,
 422                 DOCUMENT_SCANNER,
 423                 DTD_SCANNER,
 424                 DTD_PROCESSOR,
 425                 DTD_VALIDATOR,
 426                                 DATATYPE_VALIDATOR_FACTORY,
 427                                 VALIDATION_MANAGER,
 428                                 XML_STRING,
 429                 XMLGRAMMAR_POOL,
 430                 JAXP_SCHEMA_SOURCE,
 431                 JAXP_SCHEMA_LANGUAGE};
 432         addRecognizedProperties(recognizedProperties);
 433 
 434                 if (symbolTable == null) {
 435                         symbolTable = new SymbolTable();
 436                 }
 437                 fSymbolTable = symbolTable;
 438                 fProperties.put(SYMBOL_TABLE, fSymbolTable);
 439 
 440         fGrammarPool = grammarPool;
 441         if (fGrammarPool != null) {
 442                         fProperties.put(XMLGRAMMAR_POOL, fGrammarPool);
 443         }
 444 
 445         fEntityManager = new XMLEntityManager();
 446                 fProperties.put(ENTITY_MANAGER, fEntityManager);
 447         addCommonComponent(fEntityManager);
 448 
 449         fErrorReporter = new XMLErrorReporter();
 450         fErrorReporter.setDocumentLocator(fEntityManager.getEntityScanner());
 451                 fProperties.put(ERROR_REPORTER, fErrorReporter);
 452         addCommonComponent(fErrorReporter);
 453 
 454         fNamespaceScanner = new XMLNSDocumentScannerImpl();
 455                 fProperties.put(DOCUMENT_SCANNER, fNamespaceScanner);
 456         addComponent((XMLComponent) fNamespaceScanner);
 457 
 458         fDTDScanner = new XMLDTDScannerImpl();
 459                 fProperties.put(DTD_SCANNER, fDTDScanner);
 460         addComponent((XMLComponent) fDTDScanner);
 461 
 462         fDTDProcessor = new XMLDTDProcessor();
 463                 fProperties.put(DTD_PROCESSOR, fDTDProcessor);
 464         addComponent((XMLComponent) fDTDProcessor);
 465 
 466         fDTDValidator = new XMLNSDTDValidator();
 467                 fProperties.put(DTD_VALIDATOR, fDTDValidator);
 468         addComponent(fDTDValidator);
 469 
 470         fDatatypeValidatorFactory = DTDDVFactory.getInstance();
 471                 fProperties.put(DATATYPE_VALIDATOR_FACTORY, fDatatypeValidatorFactory);
 472 
 473         fValidationManager = new ValidationManager();
 474                 fProperties.put(VALIDATION_MANAGER, fValidationManager);
 475 
 476         fVersionDetector = new XMLVersionDetector();
 477 
 478         // add message formatters
 479         if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
 480             XMLMessageFormatter xmft = new XMLMessageFormatter();
 481             fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
 482             fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
 483         }
 484 
 485         // set locale
 486         try {
 487             setLocale(Locale.getDefault());
 488         } catch (XNIException e) {
 489             // do nothing
 490             // REVISIT: What is the right thing to do? -Ac
 491         }
 492 
 493                 fConfigUpdated = false;
 494 
 495     } // <init>(SymbolTable,XMLGrammarPool)
 496 
 497     //
 498     // Public methods
 499     //
 500     /**
 501      * Sets the input source for the document to parse.
 502      *
 503      * @param inputSource The document's input source.
 504      *
 505      * @exception XMLConfigurationException Thrown if there is a
 506      *                        configuration error when initializing the
 507      *                        parser.
 508      * @exception IOException Thrown on I/O error.
 509      *
 510      * @see #parse(boolean)
 511      */
 512     public void setInputSource(XMLInputSource inputSource)
 513         throws XMLConfigurationException, IOException {
 514 
 515         // REVISIT: this method used to reset all the components and
 516         //          construct the pipeline. Now reset() is called
 517         //          in parse (boolean) just before we parse the document
 518         //          Should this method still throw exceptions..?
 519 
 520         fInputSource = inputSource;
 521 
 522     } // setInputSource(XMLInputSource)
 523 
 524     /**
 525      * Set the locale to use for messages.
 526      *
 527      * @param locale The locale object to use for localization of messages.
 528      *
 529      * @exception XNIException Thrown if the parser does not support the
 530      *                         specified locale.
 531      */
 532     public void setLocale(Locale locale) throws XNIException {
 533         fLocale = locale;
 534         fErrorReporter.setLocale(locale);
 535     } // setLocale(Locale)
 536 
 537         /**
 538          * Sets the document handler on the last component in the pipeline
 539          * to receive information about the document.
 540          *
 541          * @param documentHandler   The document handler.
 542          */
 543         public void setDocumentHandler(XMLDocumentHandler documentHandler) {
 544                 fDocumentHandler = documentHandler;
 545                 if (fLastComponent != null) {
 546                         fLastComponent.setDocumentHandler(fDocumentHandler);
 547                         if (fDocumentHandler !=null){
 548                                 fDocumentHandler.setDocumentSource(fLastComponent);
 549                         }
 550                 }
 551         } // setDocumentHandler(XMLDocumentHandler)
 552 
 553         /** Returns the registered document handler. */
 554         public XMLDocumentHandler getDocumentHandler() {
 555                 return fDocumentHandler;
 556         } // getDocumentHandler():XMLDocumentHandler
 557 
 558         /**
 559          * Sets the DTD handler.
 560          *
 561          * @param dtdHandler The DTD handler.
 562          */
 563         public void setDTDHandler(XMLDTDHandler dtdHandler) {
 564                 fDTDHandler = dtdHandler;
 565         } // setDTDHandler(XMLDTDHandler)
 566 
 567         /** Returns the registered DTD handler. */
 568         public XMLDTDHandler getDTDHandler() {
 569                 return fDTDHandler;
 570         } // getDTDHandler():XMLDTDHandler
 571 
 572         /**
 573          * Sets the DTD content model handler.
 574          *
 575          * @param handler The DTD content model handler.
 576          */
 577         public void setDTDContentModelHandler(XMLDTDContentModelHandler handler) {
 578                 fDTDContentModelHandler = handler;
 579         } // setDTDContentModelHandler(XMLDTDContentModelHandler)
 580 
 581         /** Returns the registered DTD content model handler. */
 582         public XMLDTDContentModelHandler getDTDContentModelHandler() {
 583                 return fDTDContentModelHandler;
 584         } // getDTDContentModelHandler():XMLDTDContentModelHandler
 585 
 586         /**
 587          * Sets the resolver used to resolve external entities. The EntityResolver
 588          * interface supports resolution of public and system identifiers.
 589          *
 590          * @param resolver The new entity resolver. Passing a null value will
 591          *                 uninstall the currently installed resolver.
 592          */
 593         public void setEntityResolver(XMLEntityResolver resolver) {
 594                 fProperties.put(ENTITY_RESOLVER, resolver);
 595         } // setEntityResolver(XMLEntityResolver)
 596 
 597         /**
 598          * Return the current entity resolver.
 599          *
 600          * @return The current entity resolver, or null if none
 601          *         has been registered.
 602          * @see #setEntityResolver
 603          */
 604         public XMLEntityResolver getEntityResolver() {
 605                 return (XMLEntityResolver)fProperties.get(ENTITY_RESOLVER);
 606         } // getEntityResolver():XMLEntityResolver
 607 
 608         /**
 609          * Allow an application to register an error event handler.
 610          *
 611          * <p>If the application does not register an error handler, all
 612          * error events reported by the SAX parser will be silently
 613          * ignored; however, normal processing may not continue.  It is
 614          * highly recommended that all SAX applications implement an
 615          * error handler to avoid unexpected bugs.</p>
 616          *
 617          * <p>Applications may register a new or different handler in the
 618          * middle of a parse, and the SAX parser must begin using the new
 619          * handler immediately.</p>
 620          *
 621          * @param errorHandler The error handler.
 622          * @exception java.lang.NullPointerException If the handler
 623          *            argument is null.
 624          * @see #getErrorHandler
 625          */
 626         public void setErrorHandler(XMLErrorHandler errorHandler) {
 627                 fProperties.put(ERROR_HANDLER, errorHandler);
 628         } // setErrorHandler(XMLErrorHandler)
 629 
 630         /**
 631          * Return the current error handler.
 632          *
 633          * @return The current error handler, or null if none
 634          *         has been registered.
 635          * @see #setErrorHandler
 636          */
 637         public XMLErrorHandler getErrorHandler() {
 638                 // REVISIT: Should this be a property?
 639                 return (XMLErrorHandler)fProperties.get(ERROR_HANDLER);
 640         } // getErrorHandler():XMLErrorHandler
 641 
 642 
 643     /**
 644      * If the application decides to terminate parsing before the xml document
 645      * is fully parsed, the application should call this method to free any
 646      * resource allocated during parsing. For example, close all opened streams.
 647      */
 648     public void cleanup() {
 649         fEntityManager.closeReaders();
 650     }
 651 
 652     /**
 653      * Parses the specified input source.
 654      *
 655      * @param source The input source.
 656      *
 657      * @exception XNIException Throws exception on XNI error.
 658      * @exception java.io.IOException Throws exception on i/o error.
 659      */
 660     public void parse(XMLInputSource source) throws XNIException, IOException {
 661 
 662         if (fParseInProgress) {
 663             // REVISIT - need to add new error message
 664             throw new XNIException("FWK005 parse may not be called while parsing.");
 665         }
 666         fParseInProgress = true;
 667 
 668         try {
 669             setInputSource(source);
 670             parse(true);
 671         } catch (XNIException ex) {
 672             if (PRINT_EXCEPTION_STACK_TRACE)
 673                 ex.printStackTrace();
 674             throw ex;
 675         } catch (IOException ex) {
 676             if (PRINT_EXCEPTION_STACK_TRACE)
 677                 ex.printStackTrace();
 678             throw ex;
 679         } catch (RuntimeException ex) {
 680             if (PRINT_EXCEPTION_STACK_TRACE)
 681                 ex.printStackTrace();
 682             throw ex;
 683         } catch (Exception ex) {
 684             if (PRINT_EXCEPTION_STACK_TRACE)
 685                 ex.printStackTrace();
 686             throw new XNIException(ex);
 687         } finally {
 688             fParseInProgress = false;
 689             // close all streams opened by xerces
 690             this.cleanup();
 691         }
 692 
 693     } // parse(InputSource)
 694 
 695     public boolean parse(boolean complete) throws XNIException, IOException {
 696         //
 697         // reset and configure pipeline and set InputSource.
 698         if (fInputSource != null) {
 699             try {
 700                                 fValidationManager.reset();
 701                 fVersionDetector.reset(this);
 702                 resetCommon();
 703 
 704                 short version = fVersionDetector.determineDocVersion(fInputSource);
 705                 if (version == Constants.XML_VERSION_1_1) {
 706                     initXML11Components();
 707                     configureXML11Pipeline();
 708                     resetXML11();
 709                 } else {
 710                     configurePipeline();
 711                     reset();
 712                 }
 713 
 714                 // mark configuration as fixed
 715                 fConfigUpdated = false;
 716 
 717                 // resets and sets the pipeline.
 718                 fVersionDetector.startDocumentParsing((XMLEntityHandler) fCurrentScanner, version);
 719                 fInputSource = null;
 720             } catch (XNIException ex) {
 721                 if (PRINT_EXCEPTION_STACK_TRACE)
 722                     ex.printStackTrace();
 723                 throw ex;
 724             } catch (IOException ex) {
 725                 if (PRINT_EXCEPTION_STACK_TRACE)
 726                     ex.printStackTrace();
 727                 throw ex;
 728             } catch (RuntimeException ex) {
 729                 if (PRINT_EXCEPTION_STACK_TRACE)
 730                     ex.printStackTrace();
 731                 throw ex;
 732             } catch (Exception ex) {
 733                 if (PRINT_EXCEPTION_STACK_TRACE)
 734                     ex.printStackTrace();
 735                 throw new XNIException(ex);
 736             }
 737         }
 738 
 739         try {
 740             return fCurrentScanner.scanDocument(complete);
 741         } catch (XNIException ex) {
 742             if (PRINT_EXCEPTION_STACK_TRACE)
 743                 ex.printStackTrace();
 744             throw ex;
 745         } catch (IOException ex) {
 746             if (PRINT_EXCEPTION_STACK_TRACE)
 747                 ex.printStackTrace();
 748             throw ex;
 749         } catch (RuntimeException ex) {
 750             if (PRINT_EXCEPTION_STACK_TRACE)
 751                 ex.printStackTrace();
 752             throw ex;
 753         } catch (Exception ex) {
 754             if (PRINT_EXCEPTION_STACK_TRACE)
 755                 ex.printStackTrace();
 756             throw new XNIException(ex);
 757         }
 758 
 759     } // parse(boolean):boolean
 760 
 761     /**
 762      * Stops the parsing process.
 763      */
 764     @Override
 765     public boolean stop() {
 766         //no-op. this feature is implemented in the specific SAX parser.
 767         return false;
 768     }
 769 
 770     /**
 771      * Resumes parsing after it was stopped by calling the stop method.
 772      */
 773     @Override
 774     public boolean resume() {
 775         //no-op. this feature is implemented in the specific SAX parser.
 776         return false;
 777     }
 778 
 779     /**
 780      * Returns the state of a feature.
 781      *
 782      * @param featureId The feature identifier.
 783              * @return true if the feature is supported
 784      *
 785      * @throws XMLConfigurationException Thrown for configuration error.
 786      *                                   In general, components should
 787      *                                   only throw this exception if
 788      *                                   it is <strong>really</strong>
 789      *                                   a critical error.
 790      */
 791     public FeatureState getFeatureState(String featureId)
 792             throws XMLConfigurationException {
 793                     // make this feature special
 794     if (featureId.equals(PARSER_SETTINGS)){
 795             return FeatureState.is(fConfigUpdated);
 796     }
 797     return super.getFeatureState(featureId);
 798 
 799     } // getFeature(String):boolean
 800 
 801     /**
 802      * Set the state of a feature.
 803      *
 804      * Set the state of any feature in a SAX2 parser.  The parser
 805      * might not recognize the feature, and if it does recognize
 806      * it, it might not be able to fulfill the request.
 807      *
 808      * @param featureId The unique identifier (URI) of the feature.
 809      * @param state The requested state of the feature (true or false).
 810      *
 811      * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
 812      *            requested feature is not known.
 813      */
 814     public void setFeature(String featureId, boolean state)
 815             throws XMLConfigurationException {
 816             fConfigUpdated = true;
 817             // forward to every XML 1.0 component
 818             int count = fComponents.size();
 819             for (int i = 0; i < count; i++) {
 820                     XMLComponent c = (XMLComponent) fComponents.get(i);
 821                     c.setFeature(featureId, state);
 822             }
 823             // forward it to common components
 824             count = fCommonComponents.size();
 825             for (int i = 0; i < count; i++) {
 826                     XMLComponent c = (XMLComponent) fCommonComponents.get(i);
 827                     c.setFeature(featureId, state);
 828             }
 829 
 830             // forward to every XML 1.1 component
 831             count = fXML11Components.size();
 832             for (int i = 0; i < count; i++) {
 833                     XMLComponent c = (XMLComponent) fXML11Components.get(i);
 834                     try{
 835                             c.setFeature(featureId, state);
 836                     }
 837                     catch (Exception e){
 838                             // no op
 839                     }
 840             }
 841             // save state if noone "objects"
 842             super.setFeature(featureId, state);
 843 
 844     } // setFeature(String,boolean)
 845 
 846     /**
 847      * setProperty
 848      *
 849      * @param propertyId
 850      * @param value
 851      */
 852     public void setProperty(String propertyId, Object value)
 853             throws XMLConfigurationException {
 854             fConfigUpdated = true;
 855             // forward to every XML 1.0 component
 856             int count = fComponents.size();
 857             for (int i = 0; i < count; i++) {
 858                     XMLComponent c = (XMLComponent) fComponents.get(i);
 859                     c.setProperty(propertyId, value);
 860             }
 861             // forward it to every common Component
 862             count = fCommonComponents.size();
 863             for (int i = 0; i < count; i++) {
 864                     XMLComponent c = (XMLComponent) fCommonComponents.get(i);
 865                     c.setProperty(propertyId, value);
 866             }
 867             // forward it to every XML 1.1 component
 868             count = fXML11Components.size();
 869             for (int i = 0; i < count; i++) {
 870                     XMLComponent c = (XMLComponent) fXML11Components.get(i);
 871                     try{
 872                             c.setProperty(propertyId, value);
 873                     }
 874                     catch (Exception e){
 875                             // ignore it
 876                     }
 877             }
 878 
 879             // store value if noone "objects"
 880             super.setProperty(propertyId, value);
 881 
 882     } // setProperty(String,Object)
 883 
 884 
 885     /** Returns the locale. */
 886     public Locale getLocale() {
 887             return fLocale;
 888     } // getLocale():Locale
 889 
 890     /**
 891      * reset all XML 1.0 components before parsing and namespace context
 892      */
 893     protected void reset() throws XNIException {
 894             int count = fComponents.size();
 895             for (int i = 0; i < count; i++) {
 896                     XMLComponent c = (XMLComponent) fComponents.get(i);
 897                     c.reset(this);
 898             }
 899 
 900     } // reset()
 901 
 902     /**
 903      * reset all common components before parsing
 904      */
 905     protected void resetCommon() throws XNIException {
 906             // reset common components
 907             int count = fCommonComponents.size();
 908             for (int i = 0; i < count; i++) {
 909                     XMLComponent c = (XMLComponent) fCommonComponents.get(i);
 910                     c.reset(this);
 911             }
 912 
 913     } // resetCommon()
 914 
 915     /**
 916      * reset all components before parsing and namespace context
 917      */
 918     protected void resetXML11() throws XNIException {
 919             // reset every component
 920             int count = fXML11Components.size();
 921             for (int i = 0; i < count; i++) {
 922                     XMLComponent c = (XMLComponent) fXML11Components.get(i);
 923                     c.reset(this);
 924             }
 925 
 926     } // resetXML11()
 927 
 928     /**
 929      *  Configures the XML 1.1 pipeline.
 930      *  Note: this method also resets the new XML11 components.
 931      */
 932     protected void configureXML11Pipeline() {
 933         if (fCurrentDVFactory != fXML11DatatypeFactory) {
 934             fCurrentDVFactory = fXML11DatatypeFactory;
 935             setProperty(DATATYPE_VALIDATOR_FACTORY, fCurrentDVFactory);
 936         }
 937         if (fCurrentDTDScanner != fXML11DTDScanner) {
 938             fCurrentDTDScanner = fXML11DTDScanner;
 939             setProperty(DTD_SCANNER, fCurrentDTDScanner);
 940                         setProperty(DTD_PROCESSOR, fXML11DTDProcessor);
 941         }
 942 
 943         fXML11DTDScanner.setDTDHandler(fXML11DTDProcessor);
 944         fXML11DTDProcessor.setDTDSource(fXML11DTDScanner);
 945         fXML11DTDProcessor.setDTDHandler(fDTDHandler);
 946         if (fDTDHandler != null) {
 947             fDTDHandler.setDTDSource(fXML11DTDProcessor);
 948         }
 949 
 950         fXML11DTDScanner.setDTDContentModelHandler(fXML11DTDProcessor);
 951         fXML11DTDProcessor.setDTDContentModelSource(fXML11DTDScanner);
 952         fXML11DTDProcessor.setDTDContentModelHandler(fDTDContentModelHandler);
 953         if (fDTDContentModelHandler != null) {
 954             fDTDContentModelHandler.setDTDContentModelSource(fXML11DTDProcessor);
 955         }
 956 
 957         // setup XML 1.1 document pipeline
 958         if (fFeatures.get(NAMESPACES) == Boolean.TRUE) {
 959             if (fCurrentScanner != fXML11NSDocScanner) {
 960                 fCurrentScanner = fXML11NSDocScanner;
 961                 setProperty(DOCUMENT_SCANNER, fXML11NSDocScanner);
 962                 setProperty(DTD_VALIDATOR, fXML11NSDTDValidator);
 963             }
 964 
 965             fXML11NSDocScanner.setDTDValidator(fXML11NSDTDValidator);
 966             fXML11NSDocScanner.setDocumentHandler(fXML11NSDTDValidator);
 967             fXML11NSDTDValidator.setDocumentSource(fXML11NSDocScanner);
 968             fXML11NSDTDValidator.setDocumentHandler(fDocumentHandler);
 969 
 970             if (fDocumentHandler != null) {
 971                 fDocumentHandler.setDocumentSource(fXML11NSDTDValidator);
 972             }
 973             fLastComponent = fXML11NSDTDValidator;
 974 
 975         } else {
 976             // create components
 977             if (fXML11DocScanner == null) {
 978                 // non namespace document pipeline
 979                 fXML11DocScanner = new XML11DocumentScannerImpl();
 980                 addXML11Component(fXML11DocScanner);
 981                 fXML11DTDValidator = new XML11DTDValidator();
 982                 addXML11Component(fXML11DTDValidator);
 983             }
 984             if (fCurrentScanner != fXML11DocScanner) {
 985                 fCurrentScanner = fXML11DocScanner;
 986                 setProperty(DOCUMENT_SCANNER, fXML11DocScanner);
 987                 setProperty(DTD_VALIDATOR, fXML11DTDValidator);
 988             }
 989             fXML11DocScanner.setDocumentHandler(fXML11DTDValidator);
 990             fXML11DTDValidator.setDocumentSource(fXML11DocScanner);
 991             fXML11DTDValidator.setDocumentHandler(fDocumentHandler);
 992 
 993             if (fDocumentHandler != null) {
 994                 fDocumentHandler.setDocumentSource(fXML11DTDValidator);
 995             }
 996             fLastComponent = fXML11DTDValidator;
 997         }
 998 
 999     } // configureXML11Pipeline()
1000 
1001     /** Configures the pipeline. */
1002     protected void configurePipeline() {
1003         if (fCurrentDVFactory != fDatatypeValidatorFactory) {
1004             fCurrentDVFactory = fDatatypeValidatorFactory;
1005             // use XML 1.0 datatype library
1006             setProperty(DATATYPE_VALIDATOR_FACTORY, fCurrentDVFactory);
1007         }
1008 
1009         // setup DTD pipeline
1010         if (fCurrentDTDScanner != fDTDScanner) {
1011             fCurrentDTDScanner = fDTDScanner;
1012             setProperty(DTD_SCANNER, fCurrentDTDScanner);
1013             setProperty(DTD_PROCESSOR, fDTDProcessor);
1014         }
1015         fDTDScanner.setDTDHandler(fDTDProcessor);
1016         fDTDProcessor.setDTDSource(fDTDScanner);
1017         fDTDProcessor.setDTDHandler(fDTDHandler);
1018         if (fDTDHandler != null) {
1019             fDTDHandler.setDTDSource(fDTDProcessor);
1020         }
1021 
1022         fDTDScanner.setDTDContentModelHandler(fDTDProcessor);
1023         fDTDProcessor.setDTDContentModelSource(fDTDScanner);
1024         fDTDProcessor.setDTDContentModelHandler(fDTDContentModelHandler);
1025         if (fDTDContentModelHandler != null) {
1026             fDTDContentModelHandler.setDTDContentModelSource(fDTDProcessor);
1027         }
1028 
1029         // setup document pipeline
1030         if (fFeatures.get(NAMESPACES) == Boolean.TRUE) {
1031             if (fCurrentScanner != fNamespaceScanner) {
1032                 fCurrentScanner = fNamespaceScanner;
1033                 setProperty(DOCUMENT_SCANNER, fNamespaceScanner);
1034                 setProperty(DTD_VALIDATOR, fDTDValidator);
1035             }
1036             fNamespaceScanner.setDTDValidator(fDTDValidator);
1037             fNamespaceScanner.setDocumentHandler(fDTDValidator);
1038             fDTDValidator.setDocumentSource(fNamespaceScanner);
1039             fDTDValidator.setDocumentHandler(fDocumentHandler);
1040             if (fDocumentHandler != null) {
1041                 fDocumentHandler.setDocumentSource(fDTDValidator);
1042             }
1043             fLastComponent = fDTDValidator;
1044         } else {
1045             // create components
1046             if (fNonNSScanner == null) {
1047                 fNonNSScanner = new XMLDocumentScannerImpl();
1048                 fNonNSDTDValidator = new XMLDTDValidator();
1049                 // add components
1050                 addComponent((XMLComponent) fNonNSScanner);
1051                 addComponent((XMLComponent) fNonNSDTDValidator);
1052             }
1053             if (fCurrentScanner != fNonNSScanner) {
1054                 fCurrentScanner = fNonNSScanner;
1055                 setProperty(DOCUMENT_SCANNER, fNonNSScanner);
1056                 setProperty(DTD_VALIDATOR, fNonNSDTDValidator);
1057             }
1058 
1059             fNonNSScanner.setDocumentHandler(fNonNSDTDValidator);
1060             fNonNSDTDValidator.setDocumentSource(fNonNSScanner);
1061             fNonNSDTDValidator.setDocumentHandler(fDocumentHandler);
1062             if (fDocumentHandler != null) {
1063                 fDocumentHandler.setDocumentSource(fNonNSDTDValidator);
1064             }
1065             fLastComponent = fNonNSDTDValidator;
1066         }
1067 
1068     } // configurePipeline()
1069 
1070 
1071     // features and properties
1072 
1073     /**
1074      * Check a feature. If feature is know and supported, this method simply
1075      * returns. Otherwise, the appropriate exception is thrown.
1076      *
1077      * @param featureId The unique identifier (URI) of the feature.
1078      *
1079      * @throws XMLConfigurationException Thrown for configuration error.
1080      *                                   In general, components should
1081      *                                   only throw this exception if
1082      *                                   it is <strong>really</strong>
1083      *                                   a critical error.
1084      */
1085     protected FeatureState checkFeature(String featureId) throws XMLConfigurationException {
1086 
1087         //
1088         // Xerces Features
1089         //
1090 
1091         if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
1092             final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
1093 
1094             //
1095             // http://apache.org/xml/features/validation/dynamic
1096             //   Allows the parser to validate a document only when it
1097             //   contains a grammar. Validation is turned on/off based
1098             //   on each document instance, automatically.
1099             //
1100             if (suffixLength == Constants.DYNAMIC_VALIDATION_FEATURE.length() &&
1101                 featureId.endsWith(Constants.DYNAMIC_VALIDATION_FEATURE)) {
1102                 return FeatureState.RECOGNIZED;
1103             }
1104 
1105             //
1106             // http://apache.org/xml/features/validation/default-attribute-values
1107             //
1108             if (suffixLength == Constants.DEFAULT_ATTRIBUTE_VALUES_FEATURE.length() &&
1109                 featureId.endsWith(Constants.DEFAULT_ATTRIBUTE_VALUES_FEATURE)) {
1110                 // REVISIT
1111                 return FeatureState.NOT_SUPPORTED;
1112             }
1113             //
1114             // http://apache.org/xml/features/validation/default-attribute-values
1115             //
1116             if (suffixLength == Constants.VALIDATE_CONTENT_MODELS_FEATURE.length() &&
1117                 featureId.endsWith(Constants.VALIDATE_CONTENT_MODELS_FEATURE)) {
1118                 // REVISIT
1119                 return FeatureState.NOT_SUPPORTED;
1120             }
1121             //
1122             // http://apache.org/xml/features/validation/nonvalidating/load-dtd-grammar
1123             //
1124             if (suffixLength == Constants.LOAD_DTD_GRAMMAR_FEATURE.length() &&
1125                 featureId.endsWith(Constants.LOAD_DTD_GRAMMAR_FEATURE)) {
1126                 return FeatureState.RECOGNIZED;
1127             }
1128             //
1129             // http://apache.org/xml/features/validation/nonvalidating/load-external-dtd
1130             //
1131             if (suffixLength == Constants.LOAD_EXTERNAL_DTD_FEATURE.length() &&
1132                 featureId.endsWith(Constants.LOAD_EXTERNAL_DTD_FEATURE)) {
1133                 return FeatureState.RECOGNIZED;
1134             }
1135 
1136             //
1137             // http://apache.org/xml/features/validation/default-attribute-values
1138             //
1139             if (suffixLength == Constants.VALIDATE_DATATYPES_FEATURE.length() &&
1140                 featureId.endsWith(Constants.VALIDATE_DATATYPES_FEATURE)) {
1141                 return FeatureState.NOT_SUPPORTED;
1142             }
1143 
1144             // special performance feature: only component manager is allowed to set it.
1145             if (suffixLength == Constants.PARSER_SETTINGS.length() &&
1146                 featureId.endsWith(Constants.PARSER_SETTINGS)) {
1147                 return FeatureState.NOT_SUPPORTED;
1148             }
1149         }
1150 
1151         //
1152         // Not recognized
1153         //
1154 
1155         return super.checkFeature(featureId);
1156 
1157     } // checkFeature(String)
1158 
1159     /**
1160      * Check a property. If the property is know and supported, this method
1161      * simply returns. Otherwise, the appropriate exception is thrown.
1162      *
1163      * @param propertyId The unique identifier (URI) of the property
1164      *                   being set.
1165      *
1166      * @throws XMLConfigurationException Thrown for configuration error.
1167      *                                   In general, components should
1168      *                                   only throw this exception if
1169      *                                   it is <strong>really</strong>
1170      *                                   a critical error.
1171      */
1172     protected PropertyState checkProperty(String propertyId) throws XMLConfigurationException {
1173 
1174         //
1175         // Xerces Properties
1176         //
1177 
1178         if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
1179             final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
1180 
1181             if (suffixLength == Constants.DTD_SCANNER_PROPERTY.length() &&
1182                 propertyId.endsWith(Constants.DTD_SCANNER_PROPERTY)) {
1183                 return PropertyState.RECOGNIZED;
1184             }
1185         }
1186 
1187         // special cases
1188         if (propertyId.startsWith(Constants.SAX_PROPERTY_PREFIX)) {
1189             final int suffixLength = propertyId.length() - Constants.SAX_PROPERTY_PREFIX.length();
1190 
1191             //
1192             // http://xml.org/sax/properties/xml-string
1193             // Value type: String
1194             // Access: read-only
1195             //   Get the literal string of characters associated with the
1196             //   current event.  If the parser recognises and supports this
1197             //   property but is not currently parsing text, it should return
1198             //   null (this is a good way to check for availability before the
1199             //   parse begins).
1200             //
1201             if (suffixLength == Constants.XML_STRING_PROPERTY.length() &&
1202                 propertyId.endsWith(Constants.XML_STRING_PROPERTY)) {
1203                 // REVISIT - we should probably ask xml-dev for a precise
1204                 // definition of what this is actually supposed to return, and
1205                 // in exactly which circumstances.
1206                 return PropertyState.NOT_SUPPORTED;
1207             }
1208         }
1209 
1210         //
1211         // Not recognized
1212         //
1213 
1214         return super.checkProperty(propertyId);
1215 
1216     } // checkProperty(String)
1217 
1218 
1219     /**
1220      * Adds a component to the parser configuration. This method will
1221      * also add all of the component's recognized features and properties
1222      * to the list of default recognized features and properties.
1223      *
1224      * @param component The component to add.
1225      */
1226     protected void addComponent(XMLComponent component) {
1227 
1228         // don't add a component more than once
1229         if (fComponents.contains(component)) {
1230             return;
1231         }
1232         fComponents.add(component);
1233         addRecognizedParamsAndSetDefaults(component);
1234 
1235     } // addComponent(XMLComponent)
1236 
1237     /**
1238      * Adds common component to the parser configuration. This method will
1239      * also add all of the component's recognized features and properties
1240      * to the list of default recognized features and properties.
1241      *
1242      * @param component The component to add.
1243      */
1244     protected void addCommonComponent(XMLComponent component) {
1245 
1246         // don't add a component more than once
1247         if (fCommonComponents.contains(component)) {
1248             return;
1249         }
1250         fCommonComponents.add(component);
1251         addRecognizedParamsAndSetDefaults(component);
1252 
1253     } // addCommonComponent(XMLComponent)
1254 
1255     /**
1256      * Adds an XML 1.1 component to the parser configuration. This method will
1257      * also add all of the component's recognized features and properties
1258      * to the list of default recognized features and properties.
1259      *
1260      * @param component The component to add.
1261      */
1262     protected void addXML11Component(XMLComponent component) {
1263 
1264         // don't add a component more than once
1265         if (fXML11Components.contains(component)) {
1266             return;
1267         }
1268         fXML11Components.add(component);
1269         addRecognizedParamsAndSetDefaults(component);
1270 
1271     } // addXML11Component(XMLComponent)
1272 
1273     /**
1274      * Adds all of the component's recognized features and properties
1275      * to the list of default recognized features and properties, and
1276      * sets default values on the configuration for features and
1277      * properties which were previously absent from the configuration.
1278      *
1279      * @param component The component whose recognized features
1280      * and properties will be added to the configuration
1281      */
1282     protected void addRecognizedParamsAndSetDefaults(XMLComponent component) {
1283 
1284         // register component's recognized features
1285         String[] recognizedFeatures = component.getRecognizedFeatures();
1286         addRecognizedFeatures(recognizedFeatures);
1287 
1288         // register component's recognized properties
1289         String[] recognizedProperties = component.getRecognizedProperties();
1290         addRecognizedProperties(recognizedProperties);
1291 
1292         // set default values
1293         if (recognizedFeatures != null) {
1294             for (int i = 0; i < recognizedFeatures.length; ++i) {
1295                 String featureId = recognizedFeatures[i];
1296                 Boolean state = component.getFeatureDefault(featureId);
1297                 if (state != null) {
1298                     // Do not overwrite values already set on the configuration.
1299                     if (!fFeatures.containsKey(featureId)) {
1300                         fFeatures.put(featureId, state);
1301                         // For newly added components who recognize this feature
1302                         // but did not offer a default value, we need to make
1303                         // sure these components will get an opportunity to read
1304                         // the value before parsing begins.
1305                         fConfigUpdated = true;
1306                     }
1307                 }
1308             }
1309         }
1310         if (recognizedProperties != null) {
1311             for (int i = 0; i < recognizedProperties.length; ++i) {
1312                 String propertyId = recognizedProperties[i];
1313                 Object value = component.getPropertyDefault(propertyId);
1314                 if (value != null) {
1315                     // Do not overwrite values already set on the configuration.
1316                     if (!fProperties.containsKey(propertyId)) {
1317                         fProperties.put(propertyId, value);
1318                         // For newly added components who recognize this property
1319                         // but did not offer a default value, we need to make
1320                         // sure these components will get an opportunity to read
1321                         // the value before parsing begins.
1322                         fConfigUpdated = true;
1323                     }
1324                 }
1325             }
1326         }
1327     }
1328 
1329     private void initXML11Components() {
1330         if (!f11Initialized) {
1331 
1332             // create datatype factory
1333             fXML11DatatypeFactory = DTDDVFactory.getInstance(XML11_DATATYPE_VALIDATOR_FACTORY);
1334 
1335             // setup XML 1.1 DTD pipeline
1336             fXML11DTDScanner = new XML11DTDScannerImpl();
1337             addXML11Component(fXML11DTDScanner);
1338             fXML11DTDProcessor = new XML11DTDProcessor();
1339             addXML11Component(fXML11DTDProcessor);
1340 
1341             // setup XML 1.1. document pipeline - namespace aware
1342             fXML11NSDocScanner = new XML11NSDocumentScannerImpl();
1343             addXML11Component(fXML11NSDocScanner);
1344             fXML11NSDTDValidator = new XML11NSDTDValidator();
1345             addXML11Component(fXML11NSDTDValidator);
1346 
1347             f11Initialized = true;
1348         }
1349     }
1350 
1351 } // class XML11DTDConfiguration