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