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