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.parsers;
  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.XMLDTDScannerImpl;
  28 import com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl;
  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.XMLNamespaceBinder;
  32 import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDProcessor;
  33 import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDValidator;
  34 import com.sun.org.apache.xerces.internal.impl.dv.DTDDVFactory;
  35 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
  36 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
  37 import com.sun.org.apache.xerces.internal.util.FeatureState;
  38 import com.sun.org.apache.xerces.internal.util.PropertyState;
  39 import com.sun.org.apache.xerces.internal.util.Status;
  40 import com.sun.org.apache.xerces.internal.util.SymbolTable;
  41 import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
  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 
  53 /**
  54  * This is the DTD-only parser configuration.  It extends the basic
  55  * configuration with a standard set of parser components appropriate
  56  * to DTD-centric validation. Since
  57  * the Xerces2 reference implementation document and DTD scanner
  58  * implementations are capable of acting as pull parsers, this
  59  * configuration implements the
  60  * <code>XMLPullParserConfiguration</code> interface.
  61  * <p>
  62  * In addition to the features and properties recognized by the base
  63  * parser configuration, this class recognizes these additional
  64  * features and properties:
  65  * <ul>
  66  * <li>Features
  67  *  <ul>
  68  *   <li>http://apache.org/xml/features/validation/warn-on-duplicate-attdef</li>
  69  *   <li>http://apache.org/xml/features/validation/warn-on-undeclared-elemdef</li>
  70  *   <li>http://apache.org/xml/features/allow-java-encodings</li>
  71  *   <li>http://apache.org/xml/features/continue-after-fatal-error</li>
  72  *   <li>http://apache.org/xml/features/load-external-dtd</li>
  73  *  </ul>
  74  * <li>Properties
  75  *  <ul>
  76  *   <li>http://apache.org/xml/properties/internal/error-reporter</li>
  77  *   <li>http://apache.org/xml/properties/internal/entity-manager</li>
  78  *   <li>http://apache.org/xml/properties/internal/document-scanner</li>
  79  *   <li>http://apache.org/xml/properties/internal/dtd-scanner</li>
  80  *   <li>http://apache.org/xml/properties/internal/grammar-pool</li>
  81  *   <li>http://apache.org/xml/properties/internal/validator/dtd</li>
  82  *   <li>http://apache.org/xml/properties/internal/datatype-validator-factory</li>
  83  *  </ul>
  84  * </ul>
  85  *
  86  * @author Arnaud  Le Hors, IBM
  87  * @author Andy Clark, IBM
  88  * @author Neil Graham, IBM
  89  *
  90  */
  91 public class DTDConfiguration
  92     extends BasicParserConfiguration
  93     implements XMLPullParserConfiguration {
  94 
  95     //
  96     // Constants
  97     //
  98 
  99     // feature identifiers
 100 
 101     /** Feature identifier: warn on duplicate attribute definition. */
 102     protected static final String WARN_ON_DUPLICATE_ATTDEF =
 103         Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
 104 
 105     /** Feature identifier: warn on duplicate entity definition. */
 106     protected static final String WARN_ON_DUPLICATE_ENTITYDEF =
 107         Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ENTITYDEF_FEATURE;
 108 
 109     /** Feature identifier: warn on undeclared element definition. */
 110     protected static final String WARN_ON_UNDECLARED_ELEMDEF =
 111         Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_UNDECLARED_ELEMDEF_FEATURE;
 112 
 113     /** Feature identifier: allow Java encodings. */
 114     protected static final String ALLOW_JAVA_ENCODINGS =
 115         Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
 116 
 117     /** Feature identifier: continue after fatal error. */
 118     protected static final String CONTINUE_AFTER_FATAL_ERROR =
 119         Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
 120 
 121     /** Feature identifier: load external DTD. */
 122     protected static final String LOAD_EXTERNAL_DTD =
 123         Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE;
 124 
 125     /** Feature identifier: notify built-in refereces. */
 126     protected static final String NOTIFY_BUILTIN_REFS =
 127         Constants.XERCES_FEATURE_PREFIX + Constants.NOTIFY_BUILTIN_REFS_FEATURE;
 128 
 129     /** Feature identifier: notify character refereces. */
 130     protected static final String NOTIFY_CHAR_REFS =
 131         Constants.XERCES_FEATURE_PREFIX + Constants.NOTIFY_CHAR_REFS_FEATURE;
 132 
 133 
 134     // property identifiers
 135 
 136     /** Property identifier: error reporter. */
 137     protected static final String ERROR_REPORTER =
 138         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
 139 
 140     /** Property identifier: entity manager. */
 141     protected static final String ENTITY_MANAGER =
 142         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
 143 
 144     /** Property identifier document scanner: */
 145     protected static final String DOCUMENT_SCANNER =
 146         Constants.XERCES_PROPERTY_PREFIX + Constants.DOCUMENT_SCANNER_PROPERTY;
 147 
 148     /** Property identifier: DTD scanner. */
 149     protected static final String DTD_SCANNER =
 150         Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_SCANNER_PROPERTY;
 151 
 152     /** Property identifier: grammar pool. */
 153     protected static final String XMLGRAMMAR_POOL =
 154         Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
 155 
 156     /** Property identifier: DTD loader. */
 157     protected static final String DTD_PROCESSOR =
 158         Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_PROCESSOR_PROPERTY;
 159 
 160     /** Property identifier: DTD validator. */
 161     protected static final String DTD_VALIDATOR =
 162         Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_VALIDATOR_PROPERTY;
 163 
 164     /** Property identifier: namespace binder. */
 165     protected static final String NAMESPACE_BINDER =
 166         Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_BINDER_PROPERTY;
 167 
 168     /** Property identifier: datatype validator factory. */
 169     protected static final String DATATYPE_VALIDATOR_FACTORY =
 170         Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
 171 
 172     protected static final String VALIDATION_MANAGER =
 173         Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
 174 
 175     /** Property identifier: JAXP schema language / DOM schema-type. */
 176     protected static final String JAXP_SCHEMA_LANGUAGE =
 177         Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE;
 178 
 179     /** Property identifier: JAXP schema source/ DOM schema-location. */
 180     protected static final String JAXP_SCHEMA_SOURCE =
 181         Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
 182 
 183     /** Property identifier: locale. */
 184     protected static final String LOCALE =
 185         Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY;
 186 
 187       /** Property identifier: Security property manager. */
 188       protected static final String XML_SECURITY_PROPERTY_MANAGER =
 189               Constants.XML_SECURITY_PROPERTY_MANAGER;
 190 
 191      /** Property identifier: Security manager. */
 192      private static final String SECURITY_MANAGER = Constants.SECURITY_MANAGER;
 193 
 194     // debugging
 195 
 196     /** Set to true and recompile to print exception stack trace. */
 197     protected static final boolean PRINT_EXCEPTION_STACK_TRACE = false;
 198 
 199     //
 200     // Data
 201     //
 202 
 203     // components (non-configurable)
 204 
 205     /** Grammar pool. */
 206     protected XMLGrammarPool fGrammarPool;
 207 
 208     /** Datatype validator factory. */
 209     protected DTDDVFactory fDatatypeValidatorFactory;
 210 
 211     // components (configurable)
 212 
 213     /** Error reporter. */
 214     protected XMLErrorReporter fErrorReporter;
 215 
 216     /** Entity manager. */
 217     protected XMLEntityManager fEntityManager;
 218 
 219     /** Document scanner. */
 220     protected XMLDocumentScanner fScanner;
 221 
 222     /** Input Source */
 223     protected XMLInputSource fInputSource;
 224 
 225     /** DTD scanner. */
 226     protected XMLDTDScanner fDTDScanner;
 227 
 228     /** DTD Processor . */
 229     protected XMLDTDProcessor fDTDProcessor;
 230 
 231     /** DTD Validator. */
 232     protected XMLDTDValidator fDTDValidator;
 233 
 234     /** Namespace binder. */
 235     protected XMLNamespaceBinder fNamespaceBinder;
 236 
 237     protected ValidationManager fValidationManager;
 238     // state
 239 
 240     /** Locator */
 241     protected XMLLocator fLocator;
 242 
 243     /**
 244      * True if a parse is in progress. This state is needed because
 245      * some features/properties cannot be set while parsing (e.g.
 246      * validation and namespaces).
 247      */
 248     protected boolean fParseInProgress = false;
 249 
 250     //
 251     // Constructors
 252     //
 253 
 254     /** Default constructor. */
 255     public DTDConfiguration() {
 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 DTDConfiguration(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 DTDConfiguration(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 DTDConfiguration(SymbolTable symbolTable,
 297                                        XMLGrammarPool grammarPool,
 298                                        XMLComponentManager parentSettings) {
 299         super(symbolTable, parentSettings);
 300 
 301         // add default recognized features
 302         final String[] recognizedFeatures = {
 303             //WARN_ON_DUPLICATE_ATTDEF,     // from XMLDTDScannerImpl
 304             //WARN_ON_UNDECLARED_ELEMDEF,   // from XMLDTDScannerImpl
 305             //ALLOW_JAVA_ENCODINGS,         // from XMLEntityManager
 306             CONTINUE_AFTER_FATAL_ERROR,
 307             LOAD_EXTERNAL_DTD,    // from XMLDTDScannerImpl
 308             //NOTIFY_BUILTIN_REFS,  // from XMLDocumentFragmentScannerImpl
 309             //NOTIFY_CHAR_REFS,         // from XMLDocumentFragmentScannerImpl
 310             //WARN_ON_DUPLICATE_ENTITYDEF,  // from XMLEntityManager
 311         };
 312         addRecognizedFeatures(recognizedFeatures);
 313 
 314         // set state for default features
 315         //setFeature(WARN_ON_DUPLICATE_ATTDEF, false);  // from XMLDTDScannerImpl
 316         //setFeature(WARN_ON_UNDECLARED_ELEMDEF, false);  // from XMLDTDScannerImpl
 317         //setFeature(ALLOW_JAVA_ENCODINGS, false);      // from XMLEntityManager
 318         setFeature(CONTINUE_AFTER_FATAL_ERROR, false);
 319         setFeature(LOAD_EXTERNAL_DTD, true);      // from XMLDTDScannerImpl
 320         //setFeature(NOTIFY_BUILTIN_REFS, false);   // from XMLDocumentFragmentScannerImpl
 321         //setFeature(NOTIFY_CHAR_REFS, false);      // from XMLDocumentFragmentScannerImpl
 322         //setFeature(WARN_ON_DUPLICATE_ENTITYDEF, false);   // from XMLEntityManager
 323 
 324         // add default recognized properties
 325         final String[] recognizedProperties = {
 326             ERROR_REPORTER,
 327             ENTITY_MANAGER,
 328             DOCUMENT_SCANNER,
 329             DTD_SCANNER,
 330             DTD_PROCESSOR,
 331             DTD_VALIDATOR,
 332             NAMESPACE_BINDER,
 333             XMLGRAMMAR_POOL,
 334             DATATYPE_VALIDATOR_FACTORY,
 335             VALIDATION_MANAGER,
 336             JAXP_SCHEMA_SOURCE,
 337             JAXP_SCHEMA_LANGUAGE,
 338             LOCALE,
 339             SECURITY_MANAGER,
 340             XML_SECURITY_PROPERTY_MANAGER
 341         };
 342         addRecognizedProperties(recognizedProperties);
 343 
 344         fGrammarPool = grammarPool;
 345         if(fGrammarPool != null){
 346             setProperty(XMLGRAMMAR_POOL, fGrammarPool);
 347         }
 348 
 349         fEntityManager = createEntityManager();
 350         setProperty(ENTITY_MANAGER, fEntityManager);
 351         addComponent(fEntityManager);
 352 
 353         fErrorReporter = createErrorReporter();
 354         fErrorReporter.setDocumentLocator(fEntityManager.getEntityScanner());
 355         setProperty(ERROR_REPORTER, fErrorReporter);
 356         addComponent(fErrorReporter);
 357 
 358         fScanner = createDocumentScanner();
 359         setProperty(DOCUMENT_SCANNER, fScanner);
 360         if (fScanner instanceof XMLComponent) {
 361             addComponent((XMLComponent)fScanner);
 362         }
 363 
 364         fDTDScanner = createDTDScanner();
 365         if (fDTDScanner != null) {
 366             setProperty(DTD_SCANNER, fDTDScanner);
 367             if (fDTDScanner instanceof XMLComponent) {
 368                 addComponent((XMLComponent)fDTDScanner);
 369             }
 370         }
 371 
 372         fDTDProcessor = createDTDProcessor();
 373         if (fDTDProcessor != null) {
 374             setProperty(DTD_PROCESSOR, fDTDProcessor);
 375             if (fDTDProcessor instanceof XMLComponent) {
 376                 addComponent((XMLComponent)fDTDProcessor);
 377             }
 378         }
 379 
 380         fDTDValidator = createDTDValidator();
 381         if (fDTDValidator != null) {
 382             setProperty(DTD_VALIDATOR, fDTDValidator);
 383             addComponent(fDTDValidator);
 384         }
 385 
 386         fNamespaceBinder = createNamespaceBinder();
 387         if (fNamespaceBinder != null) {
 388             setProperty(NAMESPACE_BINDER, fNamespaceBinder);
 389             addComponent(fNamespaceBinder);
 390         }
 391 
 392         fDatatypeValidatorFactory = createDatatypeValidatorFactory();
 393         if (fDatatypeValidatorFactory != null) {
 394             setProperty(DATATYPE_VALIDATOR_FACTORY,
 395                         fDatatypeValidatorFactory);
 396         }
 397         fValidationManager = createValidationManager();
 398 
 399         if (fValidationManager != null) {
 400             setProperty (VALIDATION_MANAGER, fValidationManager);
 401         }
 402         // add message formatters
 403         if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
 404             XMLMessageFormatter xmft = new XMLMessageFormatter();
 405             fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
 406             fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
 407         }
 408 
 409         // set locale
 410         try {
 411             setLocale(Locale.getDefault());
 412         }
 413         catch (XNIException e) {
 414             // do nothing
 415             // REVISIT: What is the right thing to do? -Ac
 416         }
 417 
 418         setProperty(XML_SECURITY_PROPERTY_MANAGER, new XMLSecurityPropertyManager());
 419     } // <init>(SymbolTable,XMLGrammarPool)
 420 
 421     //
 422     // Public methods
 423     //
 424 
 425     public PropertyState getPropertyState(String propertyId)
 426         throws XMLConfigurationException {
 427         if (LOCALE.equals(propertyId)) {
 428             return PropertyState.is(getLocale());
 429         }
 430         return super.getPropertyState(propertyId);
 431     }
 432 
 433     public void setProperty(String propertyId, Object value)
 434         throws XMLConfigurationException {
 435         if (LOCALE.equals(propertyId)) {
 436             setLocale((Locale) value);
 437         }
 438         super.setProperty(propertyId, value);
 439     }
 440 
 441     /**
 442      * Set the locale to use for messages.
 443      *
 444      * @param locale The locale object to use for localization of messages.
 445      *
 446      * @exception XNIException Thrown if the parser does not support the
 447      *                         specified locale.
 448      */
 449     public void setLocale(Locale locale) throws XNIException {
 450         super.setLocale(locale);
 451         fErrorReporter.setLocale(locale);
 452     } // setLocale(Locale)
 453 
 454     //
 455     // XMLPullParserConfiguration methods
 456     //
 457 
 458     // parsing
 459 
 460     /**
 461      * Sets the input source for the document to parse.
 462      *
 463      * @param inputSource The document's input source.
 464      *
 465      * @exception XMLConfigurationException Thrown if there is a
 466      *                        configuration error when initializing the
 467      *                        parser.
 468      * @exception IOException Thrown on I/O error.
 469      *
 470      * @see #parse(boolean)
 471      */
 472     public void setInputSource(XMLInputSource inputSource)
 473         throws XMLConfigurationException, IOException {
 474 
 475         // REVISIT: this method used to reset all the components and
 476         //          construct the pipeline. Now reset() is called
 477         //          in parse (boolean) just before we parse the document
 478         //          Should this method still throw exceptions..?
 479 
 480         fInputSource = inputSource;
 481 
 482     } // setInputSource(XMLInputSource)
 483 
 484     /**
 485      * Parses the document in a pull parsing fashion.
 486      *
 487      * @param complete True if the pull parser should parse the
 488      *                 remaining document completely.
 489      *
 490      * @return True if there is more document to parse.
 491      *
 492      * @exception XNIException Any XNI exception, possibly wrapping
 493      *                         another exception.
 494      * @exception IOException  An IO exception from the parser, possibly
 495      *                         from a byte stream or character stream
 496      *                         supplied by the parser.
 497      *
 498      * @see #setInputSource
 499      */
 500     public boolean parse(boolean complete) throws XNIException, IOException {
 501         //
 502         // reset and configure pipeline and set InputSource.
 503         if (fInputSource !=null) {
 504             try {
 505                 // resets and sets the pipeline.
 506                 reset();
 507                 fScanner.setInputSource(fInputSource);
 508                 fInputSource = null;
 509             }
 510             catch (XNIException ex) {
 511                 if (PRINT_EXCEPTION_STACK_TRACE)
 512                     ex.printStackTrace();
 513                 throw ex;
 514             }
 515             catch (IOException ex) {
 516                 if (PRINT_EXCEPTION_STACK_TRACE)
 517                     ex.printStackTrace();
 518                 throw ex;
 519             }
 520             catch (RuntimeException ex) {
 521                 if (PRINT_EXCEPTION_STACK_TRACE)
 522                     ex.printStackTrace();
 523                 throw ex;
 524             }
 525             catch (Exception ex) {
 526                 if (PRINT_EXCEPTION_STACK_TRACE)
 527                     ex.printStackTrace();
 528                 throw new XNIException(ex);
 529             }
 530         }
 531 
 532         try {
 533             return fScanner.scanDocument(complete);
 534         }
 535         catch (XNIException ex) {
 536             if (PRINT_EXCEPTION_STACK_TRACE)
 537                 ex.printStackTrace();
 538             throw ex;
 539         }
 540         catch (IOException ex) {
 541             if (PRINT_EXCEPTION_STACK_TRACE)
 542                 ex.printStackTrace();
 543             throw ex;
 544         }
 545         catch (RuntimeException ex) {
 546             if (PRINT_EXCEPTION_STACK_TRACE)
 547                 ex.printStackTrace();
 548             throw ex;
 549         }
 550         catch (Exception ex) {
 551             if (PRINT_EXCEPTION_STACK_TRACE)
 552                 ex.printStackTrace();
 553             throw new XNIException(ex);
 554         }
 555 
 556     } // parse(boolean):boolean
 557 
 558     /**
 559      * If the application decides to terminate parsing before the xml document
 560      * is fully parsed, the application should call this method to free any
 561      * resource allocated during parsing. For example, close all opened streams.
 562      */
 563     public void cleanup() {
 564         fEntityManager.closeReaders();
 565     }
 566 
 567     //
 568     // XMLParserConfiguration methods
 569     //
 570 
 571     /**
 572      * Parses the specified input source.
 573      *
 574      * @param source The input source.
 575      *
 576      * @exception XNIException Throws exception on XNI error.
 577      * @exception java.io.IOException Throws exception on i/o error.
 578      */
 579     public void parse(XMLInputSource source) throws XNIException, IOException {
 580 
 581         if (fParseInProgress) {
 582             // REVISIT - need to add new error message
 583             throw new XNIException("FWK005 parse may not be called while parsing.");
 584         }
 585         fParseInProgress = true;
 586 
 587         try {
 588             setInputSource(source);
 589             parse(true);
 590         }
 591         catch (XNIException ex) {
 592             if (PRINT_EXCEPTION_STACK_TRACE)
 593                 ex.printStackTrace();
 594             throw ex;
 595         }
 596         catch (IOException ex) {
 597             if (PRINT_EXCEPTION_STACK_TRACE)
 598                 ex.printStackTrace();
 599             throw ex;
 600         }
 601         catch (RuntimeException ex) {
 602             if (PRINT_EXCEPTION_STACK_TRACE)
 603                 ex.printStackTrace();
 604             throw ex;
 605         }
 606         catch (Exception ex) {
 607             if (PRINT_EXCEPTION_STACK_TRACE)
 608                 ex.printStackTrace();
 609             throw new XNIException(ex);
 610         }
 611         finally {
 612             fParseInProgress = false;
 613             // close all streams opened by xerces
 614             this.cleanup();
 615         }
 616 
 617     } // parse(InputSource)
 618 
 619     //
 620     // Protected methods
 621     //
 622 
 623     /**
 624      * Reset all components before parsing.
 625      *
 626      * @throws XNIException Thrown if an error occurs during initialization.
 627      */
 628     protected void reset() throws XNIException {
 629 
 630         if (fValidationManager != null)
 631             fValidationManager.reset();
 632         // configure the pipeline and initialize the components
 633         configurePipeline();
 634         super.reset();
 635     } // reset()
 636 
 637     /** Configures the pipeline. */
 638         protected void configurePipeline() {
 639 
 640                 // REVISIT: This should be better designed. In other words, we
 641                 //          need to figure out what is the best way for people to
 642                 //          re-use *most* of the standard configuration but do
 643                 //          things common things such as remove a component (e.g.
 644                 //          the validator), insert a new component (e.g. XInclude),
 645                 //          etc... -Ac
 646 
 647                 // setup document pipeline
 648                 if (fDTDValidator != null) {
 649                         fScanner.setDocumentHandler(fDTDValidator);
 650                         if (fFeatures.get(NAMESPACES) == Boolean.TRUE) {
 651 
 652                                 // filters
 653                                 fDTDValidator.setDocumentHandler(fNamespaceBinder);
 654                                 fDTDValidator.setDocumentSource(fScanner);
 655                                 fNamespaceBinder.setDocumentHandler(fDocumentHandler);
 656                                 fNamespaceBinder.setDocumentSource(fDTDValidator);
 657                                 fLastComponent = fNamespaceBinder;
 658                         }
 659                         else {
 660                                 fDTDValidator.setDocumentHandler(fDocumentHandler);
 661                                 fDTDValidator.setDocumentSource(fScanner);
 662                                 fLastComponent = fDTDValidator;
 663                         }
 664                 }
 665                 else {
 666                         if (fFeatures.get(NAMESPACES) == Boolean.TRUE) {
 667                                 fScanner.setDocumentHandler(fNamespaceBinder);
 668                                 fNamespaceBinder.setDocumentHandler(fDocumentHandler);
 669                                 fNamespaceBinder.setDocumentSource(fScanner);
 670                                 fLastComponent = fNamespaceBinder;
 671                         }
 672                         else {
 673                                 fScanner.setDocumentHandler(fDocumentHandler);
 674                                 fLastComponent = fScanner;
 675                         }
 676                 }
 677 
 678         configureDTDPipeline();
 679         } // configurePipeline()
 680 
 681     protected void configureDTDPipeline (){
 682 
 683         // setup dtd pipeline
 684         if (fDTDScanner != null) {
 685             fProperties.put(DTD_SCANNER, fDTDScanner);
 686             if (fDTDProcessor != null) {
 687                 fProperties.put(DTD_PROCESSOR, fDTDProcessor);
 688                 fDTDScanner.setDTDHandler(fDTDProcessor);
 689                 fDTDProcessor.setDTDSource(fDTDScanner);
 690                 fDTDProcessor.setDTDHandler(fDTDHandler);
 691                 if (fDTDHandler != null) {
 692                     fDTDHandler.setDTDSource(fDTDProcessor);
 693                 }
 694 
 695                 fDTDScanner.setDTDContentModelHandler(fDTDProcessor);
 696                 fDTDProcessor.setDTDContentModelSource(fDTDScanner);
 697                 fDTDProcessor.setDTDContentModelHandler(fDTDContentModelHandler);
 698                 if (fDTDContentModelHandler != null) {
 699                     fDTDContentModelHandler.setDTDContentModelSource(fDTDProcessor);
 700                 }
 701             }
 702             else {
 703                 fDTDScanner.setDTDHandler(fDTDHandler);
 704                 if (fDTDHandler != null) {
 705                     fDTDHandler.setDTDSource(fDTDScanner);
 706                 }
 707                 fDTDScanner.setDTDContentModelHandler(fDTDContentModelHandler);
 708                 if (fDTDContentModelHandler != null) {
 709                     fDTDContentModelHandler.setDTDContentModelSource(fDTDScanner);
 710                 }
 711             }
 712         }
 713 
 714 
 715     }
 716 
 717     // features and properties
 718 
 719     /**
 720      * Check a feature. If feature is know and supported, this method simply
 721      * returns. Otherwise, the appropriate exception is thrown.
 722      *
 723      * @param featureId The unique identifier (URI) of the feature.
 724      *
 725      * @throws XMLConfigurationException Thrown for configuration error.
 726      *                                   In general, components should
 727      *                                   only throw this exception if
 728      *                                   it is <strong>really</strong>
 729      *                                   a critical error.
 730      */
 731     protected FeatureState checkFeature(String featureId)
 732         throws XMLConfigurationException {
 733 
 734         //
 735         // Xerces Features
 736         //
 737 
 738         if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
 739             final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
 740 
 741             //
 742             // http://apache.org/xml/features/validation/dynamic
 743             //   Allows the parser to validate a document only when it
 744             //   contains a grammar. Validation is turned on/off based
 745             //   on each document instance, automatically.
 746             //
 747             if (suffixLength == Constants.DYNAMIC_VALIDATION_FEATURE.length() &&
 748                 featureId.endsWith(Constants.DYNAMIC_VALIDATION_FEATURE)) {
 749                 return FeatureState.RECOGNIZED;
 750             }
 751 
 752             //
 753             // http://apache.org/xml/features/validation/default-attribute-values
 754             //
 755             if (suffixLength == Constants.DEFAULT_ATTRIBUTE_VALUES_FEATURE.length() &&
 756                 featureId.endsWith(Constants.DEFAULT_ATTRIBUTE_VALUES_FEATURE)) {
 757                 // REVISIT
 758                 return FeatureState.NOT_SUPPORTED;
 759             }
 760             //
 761             // http://apache.org/xml/features/validation/default-attribute-values
 762             //
 763             if (suffixLength == Constants.VALIDATE_CONTENT_MODELS_FEATURE.length() &&
 764                 featureId.endsWith(Constants.VALIDATE_CONTENT_MODELS_FEATURE)) {
 765                 // REVISIT
 766                 return FeatureState.NOT_SUPPORTED;
 767             }
 768             //
 769             // http://apache.org/xml/features/validation/nonvalidating/load-dtd-grammar
 770             //
 771             if (suffixLength == Constants.LOAD_DTD_GRAMMAR_FEATURE.length() &&
 772                 featureId.endsWith(Constants.LOAD_DTD_GRAMMAR_FEATURE)) {
 773                 return FeatureState.RECOGNIZED;
 774             }
 775             //
 776             // http://apache.org/xml/features/validation/nonvalidating/load-external-dtd
 777             //
 778             if (suffixLength == Constants.LOAD_EXTERNAL_DTD_FEATURE.length() &&
 779                 featureId.endsWith(Constants.LOAD_EXTERNAL_DTD_FEATURE)) {
 780                 return FeatureState.RECOGNIZED;
 781             }
 782 
 783             //
 784             // http://apache.org/xml/features/validation/default-attribute-values
 785             //
 786             if (suffixLength == Constants.VALIDATE_DATATYPES_FEATURE.length() &&
 787                 featureId.endsWith(Constants.VALIDATE_DATATYPES_FEATURE)) {
 788                 return FeatureState.NOT_SUPPORTED;
 789             }
 790         }
 791 
 792         //
 793         // Not recognized
 794         //
 795 
 796         return super.checkFeature(featureId);
 797 
 798     } // checkFeature(String)
 799 
 800     /**
 801      * Check a property. If the property is know and supported, this method
 802      * simply returns. Otherwise, the appropriate exception is thrown.
 803      *
 804      * @param propertyId The unique identifier (URI) of the property
 805      *                   being set.
 806      *
 807      * @throws XMLConfigurationException Thrown for configuration error.
 808      *                                   In general, components should
 809      *                                   only throw this exception if
 810      *                                   it is <strong>really</strong>
 811      *                                   a critical error.
 812      */
 813     protected PropertyState checkProperty(String propertyId)
 814         throws XMLConfigurationException {
 815 
 816         //
 817         // Xerces Properties
 818         //
 819 
 820         if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
 821             final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
 822 
 823             if (suffixLength == Constants.DTD_SCANNER_PROPERTY.length() &&
 824                 propertyId.endsWith(Constants.DTD_SCANNER_PROPERTY)) {
 825                 return PropertyState.RECOGNIZED;
 826             }
 827         }
 828 
 829         //
 830         // Not recognized
 831         //
 832 
 833         return super.checkProperty(propertyId);
 834 
 835     } // checkProperty(String)
 836 
 837     // factory methods
 838 
 839     /** Creates an entity manager. */
 840     protected XMLEntityManager createEntityManager() {
 841         return new XMLEntityManager();
 842     } // createEntityManager():XMLEntityManager
 843 
 844     /** Creates an error reporter. */
 845     protected XMLErrorReporter createErrorReporter() {
 846         return new XMLErrorReporter();
 847     } // createErrorReporter():XMLErrorReporter
 848 
 849     /** Create a document scanner. */
 850     protected XMLDocumentScanner createDocumentScanner() {
 851         return new XMLDocumentScannerImpl();
 852     } // createDocumentScanner():XMLDocumentScanner
 853 
 854     /** Create a DTD scanner. */
 855     protected XMLDTDScanner createDTDScanner() {
 856         return new XMLDTDScannerImpl();
 857     } // createDTDScanner():XMLDTDScanner
 858 
 859     /** Create a DTD loader . */
 860     protected XMLDTDProcessor createDTDProcessor() {
 861         return new XMLDTDProcessor();
 862     } // createDTDProcessor():XMLDTDProcessor
 863 
 864     /** Create a DTD validator. */
 865     protected XMLDTDValidator createDTDValidator() {
 866         return new XMLDTDValidator();
 867     } // createDTDValidator():XMLDTDValidator
 868 
 869     /** Create a namespace binder. */
 870     protected XMLNamespaceBinder createNamespaceBinder() {
 871         return new XMLNamespaceBinder();
 872     } // createNamespaceBinder():XMLNamespaceBinder
 873 
 874     /** Create a datatype validator factory. */
 875     protected DTDDVFactory createDatatypeValidatorFactory() {
 876         return DTDDVFactory.getInstance();
 877     } // createDatatypeValidatorFactory():DatatypeValidatorFactory
 878     protected ValidationManager createValidationManager(){
 879         return new ValidationManager();
 880     }
 881 
 882 } // class DTDConfiguration