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