1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Copyright 2001-2004 The Apache Software Foundation.
   6  *
   7  * Licensed under the Apache License, Version 2.0 (the "License");
   8  * you may not use this file except in compliance with the License.
   9  * You may obtain a copy of the License at
  10  *
  11  *      http://www.apache.org/licenses/LICENSE-2.0
  12  *
  13  * Unless required by applicable law or agreed to in writing, software
  14  * distributed under the License is distributed on an "AS IS" BASIS,
  15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16  * See the License for the specific language governing permissions and
  17  * limitations under the License.
  18  */
  19 
  20 package com.sun.org.apache.xerces.internal.impl.xs.opti;
  21 
  22 import java.io.IOException;
  23 import java.util.Locale;
  24 
  25 import com.sun.org.apache.xerces.internal.impl.Constants;
  26 import com.sun.org.apache.xerces.internal.impl.XML11DTDScannerImpl;
  27 import com.sun.org.apache.xerces.internal.impl.XML11NSDocumentScannerImpl;
  28 import com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl;
  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.impl.xs.XSMessageFormatter;
  38 import com.sun.org.apache.xerces.internal.parsers.BasicParserConfiguration;
  39 import com.sun.org.apache.xerces.internal.util.FeatureState;
  40 import com.sun.org.apache.xerces.internal.util.PropertyState;
  41 import com.sun.org.apache.xerces.internal.util.SymbolTable;
  42 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
  43 import com.sun.org.apache.xerces.internal.xni.XNIException;
  44 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
  45 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
  46 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
  47 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
  48 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDScanner;
  49 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentScanner;
  50 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
  51 import com.sun.org.apache.xerces.internal.xni.parser.XMLPullParserConfiguration;
  52 import jdk.xml.internal.JdkXmlUtils;
  53 
  54 /**
  55  * @xerces.internal
  56  *
  57  * @author Rahul Srivastava, Sun Microsystems Inc.
  58  *
  59  */
  60 public class SchemaParsingConfig extends BasicParserConfiguration
  61     implements XMLPullParserConfiguration {
  62 
  63     //
  64     // Constants
  65     //
  66 
  67     protected final static String XML11_DATATYPE_VALIDATOR_FACTORY =
  68         "com.sun.org.apache.xerces.internal.impl.dv.dtd.XML11DTDDVFactoryImpl";
  69 
  70     // feature identifiers
  71 
  72     /** Feature identifier: warn on duplicate attribute definition. */
  73     protected static final String WARN_ON_DUPLICATE_ATTDEF =
  74         Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
  75 
  76     /** Feature identifier: warn on duplicate entity definition. */
  77     //  protected static final String WARN_ON_DUPLICATE_ENTITYDEF = Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ENTITYDEF_FEATURE;
  78 
  79     /** Feature identifier: warn on undeclared element definition. */
  80     protected static final String WARN_ON_UNDECLARED_ELEMDEF =
  81         Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_UNDECLARED_ELEMDEF_FEATURE;
  82 
  83     /** Feature identifier: allow Java encodings. */
  84     protected static final String ALLOW_JAVA_ENCODINGS =
  85         Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
  86 
  87     /** Feature identifier: continue after fatal error. */
  88     protected static final String CONTINUE_AFTER_FATAL_ERROR =
  89         Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
  90 
  91     /** Feature identifier: load external DTD. */
  92     protected static final String LOAD_EXTERNAL_DTD =
  93         Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE;
  94 
  95     /** Feature identifier: notify built-in refereces. */
  96     protected static final String NOTIFY_BUILTIN_REFS =
  97         Constants.XERCES_FEATURE_PREFIX + Constants.NOTIFY_BUILTIN_REFS_FEATURE;
  98 
  99     /** Feature identifier: notify character refereces. */
 100     protected static final String NOTIFY_CHAR_REFS =
 101         Constants.XERCES_FEATURE_PREFIX + Constants.NOTIFY_CHAR_REFS_FEATURE;
 102 
 103     /** Feature identifier: expose schema normalized value */
 104     protected static final String NORMALIZE_DATA =
 105         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE;
 106 
 107     /** Feature identifier: send element default value via characters() */
 108     protected static final String SCHEMA_ELEMENT_DEFAULT =
 109         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_ELEMENT_DEFAULT;
 110 
 111     /** Feature identifier: generate synthetic annotations. */
 112     protected static final String GENERATE_SYNTHETIC_ANNOTATIONS =
 113         Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE;
 114 
 115 
 116     // property identifiers
 117 
 118     /** Property identifier: error reporter. */
 119     protected static final String ERROR_REPORTER =
 120         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
 121 
 122     /** Property identifier: entity manager. */
 123     protected static final String ENTITY_MANAGER =
 124         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
 125 
 126     /** Property identifier document scanner: */
 127     protected static final String DOCUMENT_SCANNER =
 128         Constants.XERCES_PROPERTY_PREFIX + Constants.DOCUMENT_SCANNER_PROPERTY;
 129 
 130     /** Property identifier: DTD scanner. */
 131     protected static final String DTD_SCANNER =
 132         Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_SCANNER_PROPERTY;
 133 
 134     /** Property identifier: grammar pool. */
 135     protected static final String XMLGRAMMAR_POOL =
 136         Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
 137 
 138     /** Property identifier: DTD validator. */
 139     protected static final String DTD_VALIDATOR =
 140         Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_VALIDATOR_PROPERTY;
 141 
 142     /** Property identifier: namespace binder. */
 143     protected static final String NAMESPACE_BINDER =
 144         Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_BINDER_PROPERTY;
 145 
 146     /** Property identifier: datatype validator factory. */
 147     protected static final String DATATYPE_VALIDATOR_FACTORY =
 148         Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
 149 
 150     protected static final String VALIDATION_MANAGER =
 151         Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
 152 
 153     /** Property identifier: XML Schema validator. */
 154     protected static final String SCHEMA_VALIDATOR =
 155         Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_VALIDATOR_PROPERTY;
 156 
 157     /** Property identifier: locale. */
 158     protected static final String LOCALE =
 159         Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY;
 160 
 161 
 162     // debugging
 163 
 164     /** Set to true and recompile to print exception stack trace. */
 165     private static final boolean PRINT_EXCEPTION_STACK_TRACE = false;
 166 
 167     //
 168     // Data
 169     //
 170 
 171     //
 172     // XML 1.0 components
 173     //
 174 
 175     /** The XML 1.0 Datatype validator factory. */
 176     protected final DTDDVFactory fDatatypeValidatorFactory;
 177 
 178     /** The XML 1.0 Document scanner. */
 179     protected final XMLNSDocumentScannerImpl fNamespaceScanner;
 180 
 181     /** The XML 1.0 DTD scanner. */
 182     protected final XMLDTDScannerImpl fDTDScanner;
 183 
 184     //
 185     // XML 1.1 components
 186     //
 187 
 188     /** The XML 1.1 Datatype validator factory. */
 189     protected DTDDVFactory fXML11DatatypeFactory = null;
 190 
 191     /** The XML 1.1 Document scanner. */
 192     protected XML11NSDocumentScannerImpl fXML11NSDocScanner = null;
 193 
 194     /** The XML 1.1 DTD scanner. **/
 195     protected XML11DTDScannerImpl fXML11DTDScanner = null;
 196 
 197     // common components (non-configurable)
 198 
 199     /** Current Datatype validator factory. */
 200     protected DTDDVFactory fCurrentDVFactory;
 201 
 202     /** Current scanner */
 203     protected XMLDocumentScanner fCurrentScanner;
 204 
 205     /** Current DTD scanner. */
 206     protected XMLDTDScanner fCurrentDTDScanner;
 207 
 208     /** Grammar pool. */
 209     protected XMLGrammarPool fGrammarPool;
 210 
 211     /** XML version detector. */
 212     protected final XMLVersionDetector fVersionDetector;
 213 
 214     // common components (configurable)
 215 
 216     /** Error reporter. */
 217     protected final XMLErrorReporter fErrorReporter;
 218 
 219     /** Entity manager. */
 220     protected final XMLEntityManager fEntityManager;
 221 
 222     /** Input Source */
 223     protected XMLInputSource fInputSource;
 224 
 225     protected final ValidationManager fValidationManager;
 226     // state
 227 
 228     /** Locator */
 229     protected XMLLocator fLocator;
 230 
 231     /**
 232      * True if a parse is in progress. This state is needed because
 233      * some features/properties cannot be set while parsing (e.g.
 234      * validation and namespaces).
 235      */
 236     protected boolean fParseInProgress = false;
 237 
 238     /**
 239      * fConfigUpdated is set to true if there has been any change to the configuration settings,
 240      * i.e a feature or a property was changed.
 241      */
 242     protected boolean fConfigUpdated = false;
 243 
 244     /** Flag indiciating whether XML11 components have been initialized. */
 245     private boolean f11Initialized = false;
 246 
 247     //
 248     // Constructors
 249     //
 250 
 251     /** Default constructor. */
 252     public SchemaParsingConfig() {
 253         this(null, null, null);
 254     } // <init>()
 255 
 256     /**
 257      * Constructs a parser configuration using the specified symbol table.
 258      *
 259      * @param symbolTable The symbol table to use.
 260      */
 261     public SchemaParsingConfig(SymbolTable symbolTable) {
 262         this(symbolTable, null, null);
 263     } // <init>(SymbolTable)
 264 
 265     /**
 266      * Constructs a parser configuration using the specified symbol table and
 267      * grammar pool.
 268      * <p>
 269      * <strong>REVISIT:</strong>
 270      * Grammar pool will be updated when the new validation engine is
 271      * implemented.
 272      *
 273      * @param symbolTable The symbol table to use.
 274      * @param grammarPool The grammar pool to use.
 275      */
 276     public SchemaParsingConfig(SymbolTable symbolTable,
 277             XMLGrammarPool grammarPool) {
 278         this(symbolTable, grammarPool, null);
 279     } // <init>(SymbolTable,XMLGrammarPool)
 280 
 281     /**
 282      * Constructs a parser configuration using the specified symbol table,
 283      * grammar pool, and parent settings.
 284      * <p>
 285      * <strong>REVISIT:</strong>
 286      * Grammar pool will be updated when the new validation engine is
 287      * implemented.
 288      *
 289      * @param symbolTable    The symbol table to use.
 290      * @param grammarPool    The grammar pool to use.
 291      * @param parentSettings The parent settings.
 292      */
 293     public SchemaParsingConfig(SymbolTable symbolTable,
 294             XMLGrammarPool grammarPool,
 295             XMLComponentManager parentSettings) {
 296         super(symbolTable, parentSettings);
 297 
 298         // add default recognized features
 299         final String[] recognizedFeatures = {
 300             PARSER_SETTINGS, WARN_ON_DUPLICATE_ATTDEF,   WARN_ON_UNDECLARED_ELEMDEF,
 301             ALLOW_JAVA_ENCODINGS,       CONTINUE_AFTER_FATAL_ERROR,
 302             LOAD_EXTERNAL_DTD,          NOTIFY_BUILTIN_REFS,
 303             NOTIFY_CHAR_REFS, GENERATE_SYNTHETIC_ANNOTATIONS,
 304             JdkXmlUtils.OVERRIDE_PARSER
 305         };
 306         addRecognizedFeatures(recognizedFeatures);
 307         fFeatures.put(PARSER_SETTINGS, Boolean.TRUE);
 308         // set state for default features
 309         fFeatures.put(WARN_ON_DUPLICATE_ATTDEF, Boolean.FALSE);
 310         //setFeature(WARN_ON_DUPLICATE_ENTITYDEF, false);
 311         fFeatures.put(WARN_ON_UNDECLARED_ELEMDEF, Boolean.FALSE);
 312         fFeatures.put(ALLOW_JAVA_ENCODINGS, Boolean.FALSE);
 313         fFeatures.put(CONTINUE_AFTER_FATAL_ERROR, Boolean.FALSE);
 314         fFeatures.put(LOAD_EXTERNAL_DTD, Boolean.TRUE);
 315         fFeatures.put(NOTIFY_BUILTIN_REFS, Boolean.FALSE);
 316         fFeatures.put(NOTIFY_CHAR_REFS, Boolean.FALSE);
 317         fFeatures.put(GENERATE_SYNTHETIC_ANNOTATIONS, Boolean.FALSE);
 318         fFeatures.put(JdkXmlUtils.OVERRIDE_PARSER, JdkXmlUtils.OVERRIDE_PARSER_DEFAULT);
 319 
 320         // add default recognized properties
 321         final String[] recognizedProperties = {
 322             ERROR_REPORTER,
 323             ENTITY_MANAGER,
 324             DOCUMENT_SCANNER,
 325             DTD_SCANNER,
 326             DTD_VALIDATOR,
 327             NAMESPACE_BINDER,
 328             XMLGRAMMAR_POOL,
 329             DATATYPE_VALIDATOR_FACTORY,
 330             VALIDATION_MANAGER,
 331             GENERATE_SYNTHETIC_ANNOTATIONS,
 332             LOCALE
 333         };
 334         addRecognizedProperties(recognizedProperties);
 335 
 336         fGrammarPool = grammarPool;
 337         if (fGrammarPool != null) {
 338             setProperty(XMLGRAMMAR_POOL, fGrammarPool);
 339         }
 340 
 341         fEntityManager = new XMLEntityManager();
 342         fProperties.put(ENTITY_MANAGER, fEntityManager);
 343         addComponent(fEntityManager);
 344 
 345         fErrorReporter = new XMLErrorReporter();
 346         fErrorReporter.setDocumentLocator(fEntityManager.getEntityScanner());
 347         fProperties.put(ERROR_REPORTER, fErrorReporter);
 348         addComponent(fErrorReporter);
 349 
 350         fNamespaceScanner = new XMLNSDocumentScannerImpl();
 351         fProperties.put(DOCUMENT_SCANNER, fNamespaceScanner);
 352         addRecognizedParamsAndSetDefaults(fNamespaceScanner);
 353 
 354         fDTDScanner = new XMLDTDScannerImpl();
 355         fProperties.put(DTD_SCANNER, fDTDScanner);
 356         addRecognizedParamsAndSetDefaults(fDTDScanner);
 357 
 358         fDatatypeValidatorFactory = DTDDVFactory.getInstance();
 359         fProperties.put(DATATYPE_VALIDATOR_FACTORY,
 360                 fDatatypeValidatorFactory);
 361 
 362         fValidationManager = new ValidationManager();
 363         fProperties.put(VALIDATION_MANAGER, fValidationManager);
 364 
 365         fVersionDetector = new XMLVersionDetector();
 366 
 367         // add message formatters
 368         if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
 369             XMLMessageFormatter xmft = new XMLMessageFormatter();
 370             fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
 371             fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
 372         }
 373 
 374         if (fErrorReporter.getMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN) == null) {
 375             XSMessageFormatter xmft = new XSMessageFormatter();
 376             fErrorReporter.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN, xmft);
 377         }
 378 
 379         // set locale
 380         try {
 381             setLocale(Locale.getDefault());
 382         }
 383         catch (XNIException e) {
 384             // do nothing
 385             // REVISIT: What is the right thing to do? -Ac
 386         }
 387 
 388     } // <init>(SymbolTable,XMLGrammarPool)
 389 
 390     //
 391     // Public methods
 392     //
 393 
 394     /**
 395      * Returns the state of a feature.
 396      *
 397      * @param featureId The feature identifier.
 398      * @return true if the feature is supported
 399      *
 400      * @throws XMLConfigurationException Thrown for configuration error.
 401      *                                   In general, components should
 402      *                                   only throw this exception if
 403      *                                   it is <strong>really</strong>
 404      *                                   a critical error.
 405      */
 406     public FeatureState getFeatureState(String featureId)
 407         throws XMLConfigurationException {
 408         // make this feature special
 409         if (featureId.equals(PARSER_SETTINGS)) {
 410             return FeatureState.is(fConfigUpdated);
 411         }
 412         return super.getFeatureState(featureId);
 413 
 414     } // getFeature(String):boolean
 415 
 416     /**
 417      * Set the state of a feature.
 418      *
 419      * Set the state of any feature in a SAX2 parser.  The parser
 420      * might not recognize the feature, and if it does recognize
 421      * it, it might not be able to fulfill the request.
 422      *
 423      * @param featureId The unique identifier (URI) of the feature.
 424      * @param state The requested state of the feature (true or false).
 425      *
 426      * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
 427      *            requested feature is not known.
 428      */
 429     public void setFeature(String featureId, boolean state)
 430         throws XMLConfigurationException {
 431 
 432         fConfigUpdated = true;
 433 
 434         // forward to every XML 1.0 component
 435         fNamespaceScanner.setFeature(featureId, state);
 436         fDTDScanner.setFeature(featureId, state);
 437 
 438         // forward to every XML 1.1 component
 439         if (f11Initialized) {
 440             try {
 441                 fXML11DTDScanner.setFeature(featureId, state);
 442             }
 443             // ignore the exception.
 444             catch (Exception e) {}
 445             try {
 446                 fXML11NSDocScanner.setFeature(featureId, state);
 447             }
 448             // ignore the exception
 449             catch (Exception e) {}
 450         }
 451 
 452         // save state if noone "objects"
 453         super.setFeature(featureId, state);
 454 
 455     } // setFeature(String,boolean)
 456 
 457     /**
 458      * Returns the value of a property.
 459      *
 460      * @param propertyId The property identifier.
 461      * @return the value of the property
 462      *
 463      * @throws XMLConfigurationException Thrown for configuration error.
 464      *                                   In general, components should
 465      *                                   only throw this exception if
 466      *                                   it is <strong>really</strong>
 467      *                                   a critical error.
 468      */
 469     public PropertyState getPropertyState(String propertyId)
 470         throws XMLConfigurationException {
 471         if (LOCALE.equals(propertyId)) {
 472             return PropertyState.is(getLocale());
 473         }
 474         return super.getPropertyState(propertyId);
 475     }
 476 
 477     /**
 478      * setProperty
 479      *
 480      * @param propertyId
 481      * @param value
 482      */
 483     public void setProperty(String propertyId, Object value)
 484         throws XMLConfigurationException {
 485 
 486         fConfigUpdated = true;
 487         if (LOCALE.equals(propertyId)) {
 488             setLocale((Locale) value);
 489         }
 490 
 491         // forward to every XML 1.0 component
 492         fNamespaceScanner.setProperty(propertyId, value);
 493         fDTDScanner.setProperty(propertyId, value);
 494 
 495         // forward to every XML 1.1 component
 496         if (f11Initialized) {
 497             try {
 498                 fXML11DTDScanner.setProperty(propertyId, value);
 499             }
 500             // ignore the exception.
 501             catch (Exception e) {}
 502             try {
 503                 fXML11NSDocScanner.setProperty(propertyId, value);
 504             }
 505             // ignore the exception
 506             catch (Exception e) {}
 507         }
 508 
 509         // store value if noone "objects"
 510         super.setProperty(propertyId, value);
 511 
 512     } // setProperty(String,Object)
 513 
 514     /**
 515      * Set the locale to use for messages.
 516      *
 517      * @param locale The locale object to use for localization of messages.
 518      *
 519      * @exception XNIException Thrown if the parser does not support the
 520      *                         specified locale.
 521      */
 522     public void setLocale(Locale locale) throws XNIException {
 523         super.setLocale(locale);
 524         fErrorReporter.setLocale(locale);
 525     } // setLocale(Locale)
 526 
 527     //
 528     // XMLPullParserConfiguration methods
 529     //
 530 
 531     // parsing
 532 
 533     /**
 534      * Sets the input source for the document to parse.
 535      *
 536      * @param inputSource The document's input source.
 537      *
 538      * @exception XMLConfigurationException Thrown if there is a
 539      *                        configuration error when initializing the
 540      *                        parser.
 541      * @exception IOException Thrown on I/O error.
 542      *
 543      * @see #parse(boolean)
 544      */
 545     public void setInputSource(XMLInputSource inputSource)
 546     throws XMLConfigurationException, IOException {
 547 
 548         // REVISIT: this method used to reset all the components and
 549         //          construct the pipeline. Now reset() is called
 550         //          in parse (boolean) just before we parse the document
 551         //          Should this method still throw exceptions..?
 552 
 553         fInputSource = inputSource;
 554 
 555     } // setInputSource(XMLInputSource)
 556 
 557     /**
 558      * Parses the document in a pull parsing fashion.
 559      *
 560      * @param complete True if the pull parser should parse the
 561      *                 remaining document completely.
 562      *
 563      * @return True if there is more document to parse.
 564      *
 565      * @exception XNIException Any XNI exception, possibly wrapping
 566      *                         another exception.
 567      * @exception IOException  An IO exception from the parser, possibly
 568      *                         from a byte stream or character stream
 569      *                         supplied by the parser.
 570      *
 571      * @see #setInputSource
 572      */
 573     public boolean parse(boolean complete) throws XNIException, IOException {
 574         //
 575         // reset and configure pipeline and set InputSource.
 576         if (fInputSource != null) {
 577             try {
 578                 fValidationManager.reset();
 579                 fVersionDetector.reset(this);
 580                 reset();
 581 
 582                 short version = fVersionDetector.determineDocVersion(fInputSource);
 583                 // XML 1.0
 584                 if (version == Constants.XML_VERSION_1_0) {
 585                     configurePipeline();
 586                     resetXML10();
 587                 }
 588                 // XML 1.1
 589                 else if (version == Constants.XML_VERSION_1_1) {
 590                     initXML11Components();
 591                     configureXML11Pipeline();
 592                     resetXML11();
 593                 }
 594                 // Unrecoverable error reported during version detection
 595                 else {
 596                    return false;
 597                 }
 598 
 599                 // mark configuration as fixed
 600                 fConfigUpdated = false;
 601 
 602                 // resets and sets the pipeline.
 603                 fVersionDetector.startDocumentParsing((XMLEntityHandler) fCurrentScanner, version);
 604                 fInputSource = null;
 605             }
 606             catch (XNIException ex) {
 607                 if (PRINT_EXCEPTION_STACK_TRACE)
 608                     ex.printStackTrace();
 609                 throw ex;
 610             }
 611             catch (IOException ex) {
 612                 if (PRINT_EXCEPTION_STACK_TRACE)
 613                     ex.printStackTrace();
 614                 throw ex;
 615             }
 616             catch (RuntimeException ex) {
 617                 if (PRINT_EXCEPTION_STACK_TRACE)
 618                     ex.printStackTrace();
 619                 throw ex;
 620             }
 621             catch (Exception ex) {
 622                 if (PRINT_EXCEPTION_STACK_TRACE)
 623                     ex.printStackTrace();
 624                 throw new XNIException(ex);
 625             }
 626         }
 627 
 628         try {
 629             return fCurrentScanner.scanDocument(complete);
 630         }
 631         catch (XNIException ex) {
 632             if (PRINT_EXCEPTION_STACK_TRACE)
 633                 ex.printStackTrace();
 634             throw ex;
 635         }
 636         catch (IOException ex) {
 637             if (PRINT_EXCEPTION_STACK_TRACE)
 638                 ex.printStackTrace();
 639             throw ex;
 640         }
 641         catch (RuntimeException ex) {
 642             if (PRINT_EXCEPTION_STACK_TRACE)
 643                 ex.printStackTrace();
 644             throw ex;
 645         }
 646         catch (Exception ex) {
 647             if (PRINT_EXCEPTION_STACK_TRACE)
 648                 ex.printStackTrace();
 649             throw new XNIException(ex);
 650         }
 651 
 652     } // parse(boolean):boolean
 653 
 654     /**
 655      * If the application decides to terminate parsing before the xml document
 656      * is fully parsed, the application should call this method to free any
 657      * resource allocated during parsing. For example, close all opened streams.
 658      */
 659     public void cleanup() {
 660         fEntityManager.closeReaders();
 661     }
 662 
 663     //
 664     // XMLParserConfiguration methods
 665     //
 666 
 667     /**
 668      * Parses the specified input source.
 669      *
 670      * @param source The input source.
 671      *
 672      * @exception XNIException Throws exception on XNI error.
 673      * @exception java.io.IOException Throws exception on i/o error.
 674      */
 675     public void parse(XMLInputSource source) throws XNIException, IOException {
 676 
 677         if (fParseInProgress) {
 678             // REVISIT - need to add new error message
 679             throw new XNIException("FWK005 parse may not be called while parsing.");
 680         }
 681         fParseInProgress = true;
 682 
 683         try {
 684             setInputSource(source);
 685             parse(true);
 686         }
 687         catch (XNIException ex) {
 688             if (PRINT_EXCEPTION_STACK_TRACE)
 689                 ex.printStackTrace();
 690             throw ex;
 691         }
 692         catch (IOException ex) {
 693             if (PRINT_EXCEPTION_STACK_TRACE)
 694                 ex.printStackTrace();
 695             throw ex;
 696         }
 697         catch (RuntimeException ex) {
 698             if (PRINT_EXCEPTION_STACK_TRACE)
 699                 ex.printStackTrace();
 700             throw ex;
 701         }
 702         catch (Exception ex) {
 703             if (PRINT_EXCEPTION_STACK_TRACE)
 704                 ex.printStackTrace();
 705             throw new XNIException(ex);
 706         }
 707         finally {
 708             fParseInProgress = false;
 709             // close all streams opened by xerces
 710             this.cleanup();
 711         }
 712 
 713     } // parse(InputSource)
 714 
 715     //
 716     // Protected methods
 717     //
 718 
 719     /**
 720      * Reset all components before parsing.
 721      *
 722      * @throws XNIException Thrown if an error occurs during initialization.
 723      */
 724     public void reset() throws XNIException {
 725 
 726         // initialize the common components
 727         super.reset();
 728 
 729     } // reset()
 730 
 731     /** Configures the XML 1.0 pipeline. */
 732     protected void configurePipeline() {
 733 
 734         if (fCurrentDVFactory != fDatatypeValidatorFactory) {
 735             fCurrentDVFactory = fDatatypeValidatorFactory;
 736             // use XML 1.0 datatype library
 737             setProperty(DATATYPE_VALIDATOR_FACTORY, fCurrentDVFactory);
 738         }
 739 
 740         // setup document pipeline
 741         if (fCurrentScanner != fNamespaceScanner) {
 742             fCurrentScanner = fNamespaceScanner;
 743             setProperty(DOCUMENT_SCANNER, fCurrentScanner);
 744         }
 745         fNamespaceScanner.setDocumentHandler(fDocumentHandler);
 746         if (fDocumentHandler != null) {
 747             fDocumentHandler.setDocumentSource(fNamespaceScanner);
 748         }
 749         fLastComponent = fNamespaceScanner;
 750 
 751         // setup dtd pipeline
 752         if (fCurrentDTDScanner != fDTDScanner) {
 753             fCurrentDTDScanner = fDTDScanner;
 754             setProperty(DTD_SCANNER, fCurrentDTDScanner);
 755         }
 756         fDTDScanner.setDTDHandler(fDTDHandler);
 757         if (fDTDHandler != null) {
 758             fDTDHandler.setDTDSource(fDTDScanner);
 759         }
 760         fDTDScanner.setDTDContentModelHandler(fDTDContentModelHandler);
 761         if (fDTDContentModelHandler != null) {
 762             fDTDContentModelHandler.setDTDContentModelSource(fDTDScanner);
 763         }
 764 
 765     } // configurePipeline()
 766 
 767     /** Configures the XML 1.1 pipeline. */
 768     protected void configureXML11Pipeline() {
 769 
 770         if (fCurrentDVFactory != fXML11DatatypeFactory) {
 771             fCurrentDVFactory = fXML11DatatypeFactory;
 772             // use XML 1.1 datatype library
 773             setProperty(DATATYPE_VALIDATOR_FACTORY, fCurrentDVFactory);
 774         }
 775 
 776         // setup document pipeline
 777         if (fCurrentScanner != fXML11NSDocScanner) {
 778             fCurrentScanner = fXML11NSDocScanner;
 779             setProperty(DOCUMENT_SCANNER, fCurrentScanner);
 780         }
 781         fXML11NSDocScanner.setDocumentHandler(fDocumentHandler);
 782         if (fDocumentHandler != null) {
 783             fDocumentHandler.setDocumentSource(fXML11NSDocScanner);
 784         }
 785         fLastComponent = fXML11NSDocScanner;
 786 
 787         // setup dtd pipeline
 788         if (fCurrentDTDScanner != fXML11DTDScanner) {
 789             fCurrentDTDScanner = fXML11DTDScanner;
 790             setProperty(DTD_SCANNER, fCurrentDTDScanner);
 791         }
 792         fXML11DTDScanner.setDTDHandler(fDTDHandler);
 793         if (fDTDHandler != null) {
 794             fDTDHandler.setDTDSource(fXML11DTDScanner);
 795         }
 796         fXML11DTDScanner.setDTDContentModelHandler(fDTDContentModelHandler);
 797         if (fDTDContentModelHandler != null) {
 798             fDTDContentModelHandler.setDTDContentModelSource(fXML11DTDScanner);
 799         }
 800 
 801     } // configureXML11Pipeline()
 802 
 803     // features and properties
 804 
 805     /**
 806      * Check a feature. If feature is know and supported, this method simply
 807      * returns. Otherwise, the appropriate exception is thrown.
 808      *
 809      * @param featureId The unique identifier (URI) of the feature.
 810      *
 811      * @throws XMLConfigurationException Thrown for configuration error.
 812      *                                   In general, components should
 813      *                                   only throw this exception if
 814      *                                   it is <strong>really</strong>
 815      *                                   a critical error.
 816      */
 817     protected FeatureState checkFeature(String featureId)
 818         throws XMLConfigurationException {
 819 
 820         //
 821         // Xerces Features
 822         //
 823 
 824         if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
 825             final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
 826 
 827             //
 828             // http://apache.org/xml/features/validation/dynamic
 829             //   Allows the parser to validate a document only when it
 830             //   contains a grammar. Validation is turned on/off based
 831             //   on each document instance, automatically.
 832             //
 833             if (suffixLength == Constants.DYNAMIC_VALIDATION_FEATURE.length() &&
 834                     featureId.endsWith(Constants.DYNAMIC_VALIDATION_FEATURE)) {
 835                 return FeatureState.RECOGNIZED;
 836             }
 837             //
 838             // http://apache.org/xml/features/validation/default-attribute-values
 839             //
 840             if (suffixLength == Constants.DEFAULT_ATTRIBUTE_VALUES_FEATURE.length() &&
 841                     featureId.endsWith(Constants.DEFAULT_ATTRIBUTE_VALUES_FEATURE)) {
 842                 // REVISIT
 843                 return FeatureState.NOT_SUPPORTED;
 844             }
 845             //
 846             // http://apache.org/xml/features/validation/default-attribute-values
 847             //
 848             if (suffixLength == Constants.VALIDATE_CONTENT_MODELS_FEATURE.length() &&
 849                     featureId.endsWith(Constants.VALIDATE_CONTENT_MODELS_FEATURE)) {
 850                 // REVISIT
 851                 return FeatureState.NOT_SUPPORTED;
 852             }
 853             //
 854             // http://apache.org/xml/features/validation/nonvalidating/load-dtd-grammar
 855             //
 856             if (suffixLength == Constants.LOAD_DTD_GRAMMAR_FEATURE.length() &&
 857                     featureId.endsWith(Constants.LOAD_DTD_GRAMMAR_FEATURE)) {
 858                 return FeatureState.RECOGNIZED;
 859             }
 860             //
 861             // http://apache.org/xml/features/validation/nonvalidating/load-external-dtd
 862             //
 863             if (suffixLength == Constants.LOAD_EXTERNAL_DTD_FEATURE.length() &&
 864                     featureId.endsWith(Constants.LOAD_EXTERNAL_DTD_FEATURE)) {
 865                 return FeatureState.RECOGNIZED;
 866             }
 867 
 868             //
 869             // http://apache.org/xml/features/validation/default-attribute-values
 870             //
 871             if (suffixLength == Constants.VALIDATE_DATATYPES_FEATURE.length() &&
 872                     featureId.endsWith(Constants.VALIDATE_DATATYPES_FEATURE)) {
 873                 return FeatureState.NOT_SUPPORTED;
 874             }
 875         }
 876 
 877         //
 878         // Not recognized
 879         //
 880 
 881         return super.checkFeature(featureId);
 882 
 883     } // checkFeature(String)
 884 
 885     /**
 886      * Check a property. If the property is know and supported, this method
 887      * simply returns. Otherwise, the appropriate exception is thrown.
 888      *
 889      * @param propertyId The unique identifier (URI) of the property
 890      *                   being set.
 891      *
 892      * @throws XMLConfigurationException Thrown for configuration error.
 893      *                                   In general, components should
 894      *                                   only throw this exception if
 895      *                                   it is <strong>really</strong>
 896      *                                   a critical error.
 897      */
 898     protected PropertyState checkProperty(String propertyId)
 899         throws XMLConfigurationException {
 900 
 901         //
 902         // Xerces Properties
 903         //
 904 
 905         if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
 906             final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
 907 
 908             if (suffixLength == Constants.DTD_SCANNER_PROPERTY.length() &&
 909                     propertyId.endsWith(Constants.DTD_SCANNER_PROPERTY)) {
 910                 return PropertyState.RECOGNIZED;
 911             }
 912         }
 913 
 914         if (propertyId.startsWith(Constants.JAXP_PROPERTY_PREFIX)) {
 915             final int suffixLength = propertyId.length() - Constants.JAXP_PROPERTY_PREFIX.length();
 916 
 917             if (suffixLength == Constants.SCHEMA_SOURCE.length() &&
 918                     propertyId.endsWith(Constants.SCHEMA_SOURCE)) {
 919                 return PropertyState.RECOGNIZED;
 920             }
 921         }
 922 
 923         //
 924         // Not recognized
 925         //
 926 
 927         return super.checkProperty(propertyId);
 928 
 929     } // checkProperty(String)
 930 
 931     /**
 932      * Adds all of the component's recognized features and properties
 933      * to the list of default recognized features and properties, and
 934      * sets default values on the configuration for features and
 935      * properties which were previously absent from the configuration.
 936      *
 937      * @param component The component whose recognized features
 938      * and properties will be added to the configuration
 939      */
 940     private void addRecognizedParamsAndSetDefaults(XMLComponent component) {
 941 
 942         // register component's recognized features
 943         String[] recognizedFeatures = component.getRecognizedFeatures();
 944         addRecognizedFeatures(recognizedFeatures);
 945 
 946         // register component's recognized properties
 947         String[] recognizedProperties = component.getRecognizedProperties();
 948         addRecognizedProperties(recognizedProperties);
 949 
 950         // set default values
 951         if (recognizedFeatures != null) {
 952             for (int i = 0; i < recognizedFeatures.length; ++i) {
 953                 String featureId = recognizedFeatures[i];
 954                 Boolean state = component.getFeatureDefault(featureId);
 955                 if (state != null) {
 956                     // Do not overwrite values already set on the configuration.
 957                     if (!fFeatures.containsKey(featureId)) {
 958                         fFeatures.put(featureId, state);
 959                         // For newly added components who recognize this feature
 960                         // but did not offer a default value, we need to make
 961                         // sure these components will get an opportunity to read
 962                         // the value before parsing begins.
 963                         fConfigUpdated = true;
 964                     }
 965                 }
 966             }
 967         }
 968         if (recognizedProperties != null) {
 969             for (int i = 0; i < recognizedProperties.length; ++i) {
 970                 String propertyId = recognizedProperties[i];
 971                 Object value = component.getPropertyDefault(propertyId);
 972                 if (value != null) {
 973                     // Do not overwrite values already set on the configuration.
 974                     if (!fProperties.containsKey(propertyId)) {
 975                         fProperties.put(propertyId, value);
 976                         // For newly added components who recognize this property
 977                         // but did not offer a default value, we need to make
 978                         // sure these components will get an opportunity to read
 979                         // the value before parsing begins.
 980                         fConfigUpdated = true;
 981                     }
 982                 }
 983             }
 984         }
 985     }
 986 
 987     /**
 988      * Reset all XML 1.0 components before parsing
 989      */
 990     protected final void resetXML10() throws XNIException {
 991         // Reset XML 1.0 components
 992         fNamespaceScanner.reset(this);
 993         fDTDScanner.reset(this);
 994     } // resetXML10()
 995 
 996     /**
 997      * Reset all XML 1.1 components before parsing
 998      */
 999     protected final void resetXML11() throws XNIException {
1000         // Reset XML 1.1 components
1001         fXML11NSDocScanner.reset(this);
1002         fXML11DTDScanner.reset(this);
1003     } // resetXML11()
1004 
1005     //
1006     // other methods
1007     //
1008 
1009     /** */
1010     public void resetNodePool() {
1011         // REVISIT: to implement: introduce a node pool to reuse DTM nodes.
1012         //          reset this pool here.
1013     }
1014 
1015     private void initXML11Components() {
1016         if (!f11Initialized) {
1017             // create datatype factory
1018             fXML11DatatypeFactory = DTDDVFactory.getInstance(XML11_DATATYPE_VALIDATOR_FACTORY);
1019 
1020             // setup XML 1.1 DTD pipeline
1021             fXML11DTDScanner = new XML11DTDScannerImpl();
1022             addRecognizedParamsAndSetDefaults(fXML11DTDScanner);
1023 
1024             // setup XML 1.1. document pipeline - namespace aware
1025             fXML11NSDocScanner = new XML11NSDocumentScannerImpl();
1026             addRecognizedParamsAndSetDefaults(fXML11NSDocScanner);
1027 
1028             f11Initialized = true;
1029         }
1030     }
1031 }