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