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