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