1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * The Apache Software License, Version 1.1
   7  *
   8  *
   9  * Copyright (c) 1999-2003 The Apache Software Foundation.
  10  * All rights reserved.
  11  *
  12  * Redistribution and use in source and binary forms, with or without
  13  * modification, are permitted provided that the following conditions
  14  * are met:
  15  *
  16  * 1. Redistributions of source code must retain the above copyright
  17  *    notice, this list of conditions and the following disclaimer.
  18  *
  19  * 2. Redistributions in binary form must reproduce the above copyright
  20  *    notice, this list of conditions and the following disclaimer in
  21  *    the documentation and/or other materials provided with the
  22  *    distribution.
  23  *
  24  * 3. The end-user documentation included with the redistribution,
  25  *    if any, must include the following acknowledgment:
  26  *       "This product includes software developed by the
  27  *        Apache Software Foundation (http://www.apache.org/)."
  28  *    Alternately, this acknowledgment may appear in the software itself,
  29  *    if and wherever such third-party acknowledgments normally appear.
  30  *
  31  * 4. The names "Xerces" and "Apache Software Foundation" must
  32  *    not be used to endorse or promote products derived from this
  33  *    software without prior written permission. For written
  34  *    permission, please contact apache@apache.org.
  35  *
  36  * 5. Products derived from this software may not be called "Apache",
  37  *    nor may "Apache" appear in their name, without prior written
  38  *    permission of the Apache Software Foundation.
  39  *
  40  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  41  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  42  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  43  * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  44  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  45  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  46  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  47  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  48  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  49  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  50  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  51  * SUCH DAMAGE.
  52  * ====================================================================
  53  *
  54  * This software consists of voluntary contributions made by many
  55  * individuals on behalf of the Apache Software Foundation and was
  56  * originally based on software copyright (c) 1999, International
  57  * Business Machines, Inc., http://www.apache.org.  For more
  58  * information on the Apache Software Foundation, please see
  59  * <http://www.apache.org/>.
  60  */
  61 
  62 package com.sun.org.apache.xerces.internal.impl.dtd;
  63 
  64 import java.io.EOFException;
  65 import java.io.IOException;
  66 import java.io.StringReader;
  67 import java.util.Locale;
  68 
  69 import com.sun.org.apache.xerces.internal.impl.Constants;
  70 import com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl;
  71 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
  72 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
  73 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
  74 
  75 import com.sun.org.apache.xerces.internal.util.Status;
  76 import com.sun.org.apache.xerces.internal.util.SymbolTable;
  77 import com.sun.org.apache.xerces.internal.util.DefaultErrorHandler;
  78 
  79 import com.sun.org.apache.xerces.internal.xni.XNIException;
  80 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
  81 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarLoader;
  82 import com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
  83 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
  84 import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler;
  85 import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
  86 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
  87 
  88 
  89 /**
  90  * The DTD loader. The loader knows how to build grammars from XMLInputSources.
  91  * It extends the DTD processor in order to do this; it's
  92  * a separate class because DTD processors don't need to know how
  93  * to talk to the outside world in their role as instance-document
  94  * helpers.
  95  * <p>
  96  * This component requires the following features and properties.  It
  97  * know ho to set them if no one else does:from the
  98  * <ul>
  99  *  <li>http://xml.org/sax/features/namespaces</li>
 100  *  <li>http://apache.org/xml/properties/internal/symbol-table</li>
 101  *  <li>http://apache.org/xml/properties/internal/error-reporter</li>
 102  *  <li>http://apache.org/xml/properties/internal/grammar-pool</li>
 103  *  <li>http://apache.org/xml/properties/internal/datatype-validator-factory</li>
 104  * </ul>
 105  *
 106  * @xerces.internal
 107  *
 108  * @author Neil Graham, IBM
 109  * @author Michael Glavassevich, IBM
 110  *
 111  * @version $Id: XMLDTDLoader.java,v 1.6 2010-11-01 04:39:42 joehw Exp $
 112  */
 113 public class XMLDTDLoader
 114         extends XMLDTDProcessor
 115         implements XMLGrammarLoader {
 116 
 117     //
 118     // Constants
 119     //
 120 
 121     // feature identifiers
 122 
 123     /** Feature identifier: standard uri conformant feature. */
 124     protected static final String STANDARD_URI_CONFORMANT_FEATURE =
 125         Constants.XERCES_FEATURE_PREFIX + Constants.STANDARD_URI_CONFORMANT_FEATURE;
 126 
 127     /** Feature identifier: balance syntax trees. */
 128     protected static final String BALANCE_SYNTAX_TREES =
 129         Constants.XERCES_FEATURE_PREFIX + Constants.BALANCE_SYNTAX_TREES;
 130 
 131     // recognized features:
 132     private static final String[] LOADER_RECOGNIZED_FEATURES = {
 133         VALIDATION,
 134         WARN_ON_DUPLICATE_ATTDEF,
 135         WARN_ON_UNDECLARED_ELEMDEF,
 136         NOTIFY_CHAR_REFS,
 137         STANDARD_URI_CONFORMANT_FEATURE,
 138         BALANCE_SYNTAX_TREES
 139     };
 140 
 141     // property identifiers
 142 
 143     /** Property identifier: error handler. */
 144     protected static final String ERROR_HANDLER =
 145         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
 146 
 147     /** Property identifier: entity resolver. */
 148     public static final String ENTITY_RESOLVER =
 149         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
 150 
 151     /** Property identifier: locale. */
 152     public static final String LOCALE =
 153         Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY;
 154 
 155     /** Recognized properties. */
 156     private static final String[] LOADER_RECOGNIZED_PROPERTIES = {
 157         SYMBOL_TABLE,
 158         ERROR_REPORTER,
 159         ERROR_HANDLER,
 160         ENTITY_RESOLVER,
 161         GRAMMAR_POOL,
 162         DTD_VALIDATOR,
 163         LOCALE
 164     };
 165 
 166     // enforcing strict uri?
 167     private boolean fStrictURI = false;
 168 
 169     /** Controls whether the DTD grammar produces balanced syntax trees. */
 170     private boolean fBalanceSyntaxTrees = false;
 171 
 172     /** Entity resolver . */
 173     protected XMLEntityResolver fEntityResolver;
 174 
 175     // the scanner we use to actually read the DTD
 176     protected XMLDTDScannerImpl fDTDScanner;
 177 
 178     // the entity manager the scanner needs.
 179     protected XMLEntityManager fEntityManager;
 180 
 181     // what's our Locale?
 182     protected Locale fLocale;
 183 
 184     //
 185     // Constructors
 186     //
 187 
 188     /** Deny default construction; we need a SymtolTable! */
 189     public XMLDTDLoader() {
 190         this(new SymbolTable());
 191     } // <init>()
 192 
 193     public XMLDTDLoader(SymbolTable symbolTable) {
 194         this(symbolTable, null);
 195     } // init(SymbolTable)
 196 
 197     public XMLDTDLoader(SymbolTable symbolTable,
 198                 XMLGrammarPool grammarPool) {
 199         this(symbolTable, grammarPool, null, new XMLEntityManager());
 200     } // init(SymbolTable, XMLGrammarPool)
 201 
 202     XMLDTDLoader(SymbolTable symbolTable,
 203                 XMLGrammarPool grammarPool, XMLErrorReporter errorReporter,
 204                 XMLEntityResolver entityResolver) {
 205         fSymbolTable = symbolTable;
 206         fGrammarPool = grammarPool;
 207         if(errorReporter == null) {
 208             errorReporter = new XMLErrorReporter();
 209             errorReporter.setProperty(ERROR_HANDLER, new DefaultErrorHandler());
 210         }
 211         fErrorReporter = errorReporter;
 212         // Add XML message formatter if there isn't one.
 213         if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
 214             XMLMessageFormatter xmft = new XMLMessageFormatter();
 215             fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
 216             fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
 217         }
 218         fEntityResolver = entityResolver;
 219         if(fEntityResolver instanceof XMLEntityManager) {
 220             fEntityManager = (XMLEntityManager)fEntityResolver;
 221         } else {
 222             fEntityManager = new XMLEntityManager();
 223         }
 224         fEntityManager.setProperty(Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY, errorReporter);
 225         fDTDScanner = createDTDScanner(fSymbolTable, fErrorReporter, fEntityManager);
 226         fDTDScanner.setDTDHandler(this);
 227         fDTDScanner.setDTDContentModelHandler(this);
 228         reset();
 229     } // init(SymbolTable, XMLGrammarPool, XMLErrorReporter, XMLEntityResolver)
 230 
 231     // XMLGrammarLoader methods
 232 
 233     /**
 234      * Returns a list of feature identifiers that are recognized by
 235      * this component. This method may return null if no features
 236      * are recognized by this component.
 237      */
 238     public String[] getRecognizedFeatures() {
 239         return (String[])(LOADER_RECOGNIZED_FEATURES.clone());
 240     } // getRecognizedFeatures():String[]
 241 
 242     /**
 243      * Sets the state of a feature. This method is called by the component
 244      * manager any time after reset when a feature changes state.
 245      * <p>
 246      * <strong>Note:</strong> Components should silently ignore features
 247      * that do not affect the operation of the component.
 248      *
 249      * @param featureId The feature identifier.
 250      * @param state     The state of the feature.
 251      *
 252      * @throws SAXNotRecognizedException The component should not throw
 253      *                                   this exception.
 254      * @throws SAXNotSupportedException The component should not throw
 255      *                                  this exception.
 256      */
 257     public void setFeature(String featureId, boolean state)
 258             throws XMLConfigurationException {
 259         if (featureId.equals(VALIDATION)) {
 260             fValidation = state;
 261         }
 262         else if (featureId.equals(WARN_ON_DUPLICATE_ATTDEF)) {
 263             fWarnDuplicateAttdef = state;
 264         }
 265         else if (featureId.equals(WARN_ON_UNDECLARED_ELEMDEF)) {
 266             fWarnOnUndeclaredElemdef = state;
 267         }
 268         else if (featureId.equals(NOTIFY_CHAR_REFS)) {
 269             fDTDScanner.setFeature(featureId, state);
 270         }
 271         else if (featureId.equals(STANDARD_URI_CONFORMANT_FEATURE)) {
 272             fStrictURI = state;
 273         }
 274         else if (featureId.equals(BALANCE_SYNTAX_TREES)) {
 275             fBalanceSyntaxTrees = state;
 276         }
 277         else {
 278             throw new XMLConfigurationException(Status.NOT_RECOGNIZED, featureId);
 279         }
 280     } // setFeature(String,boolean)
 281 
 282     /**
 283      * Returns a list of property identifiers that are recognized by
 284      * this component. This method may return null if no properties
 285      * are recognized by this component.
 286      */
 287     public String[] getRecognizedProperties() {
 288         return (String[])(LOADER_RECOGNIZED_PROPERTIES.clone());
 289     } // getRecognizedProperties():String[]
 290 
 291     /**
 292      * Returns the state of a property.
 293      *
 294      * @param propertyId The property identifier.
 295      *
 296      * @throws XMLConfigurationException Thrown on configuration error.
 297      */
 298     public Object getProperty(String propertyId)
 299             throws XMLConfigurationException {
 300         if (propertyId.equals(SYMBOL_TABLE)) {
 301             return fSymbolTable;
 302         }
 303         else if (propertyId.equals(ERROR_REPORTER)) {
 304             return fErrorReporter;
 305         }
 306         else if (propertyId.equals(ERROR_HANDLER)) {
 307             return fErrorReporter.getErrorHandler();
 308         }
 309         else if (propertyId.equals(ENTITY_RESOLVER)) {
 310             return fEntityResolver;
 311         }
 312         else if (propertyId.equals(LOCALE)) {
 313             return getLocale();
 314         }
 315         else if (propertyId.equals(GRAMMAR_POOL)) {
 316             return fGrammarPool;
 317         }
 318         else if (propertyId.equals(DTD_VALIDATOR)) {
 319             return fValidator;
 320         }
 321         throw new XMLConfigurationException(Status.NOT_RECOGNIZED, propertyId);
 322     } // getProperty(String):  Object
 323 
 324     /**
 325      * Sets the value of a property. This method is called by the component
 326      * manager any time after reset when a property changes value.
 327      * <p>
 328      * <strong>Note:</strong> Components should silently ignore properties
 329      * that do not affect the operation of the component.
 330      *
 331      * @param propertyId The property identifier.
 332      * @param value      The value of the property.
 333      *
 334      * @throws SAXNotRecognizedException The component should not throw
 335      *                                   this exception.
 336      * @throws SAXNotSupportedException The component should not throw
 337      *                                  this exception.
 338      */
 339     public void setProperty(String propertyId, Object value)
 340             throws XMLConfigurationException {
 341         if (propertyId.equals(SYMBOL_TABLE)) {
 342             fSymbolTable = (SymbolTable)value;
 343             fDTDScanner.setProperty(propertyId, value);
 344             fEntityManager.setProperty(propertyId, value);
 345         }
 346         else if(propertyId.equals(ERROR_REPORTER)) {
 347             fErrorReporter = (XMLErrorReporter)value;
 348             // Add XML message formatter if there isn't one.
 349             if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
 350                 XMLMessageFormatter xmft = new XMLMessageFormatter();
 351                 fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
 352                 fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
 353             }
 354             fDTDScanner.setProperty(propertyId, value);
 355             fEntityManager.setProperty(propertyId, value);
 356         }
 357         else if (propertyId.equals(ERROR_HANDLER)) {
 358             fErrorReporter.setProperty(propertyId, value);
 359         }
 360         else if (propertyId.equals(ENTITY_RESOLVER)) {
 361             fEntityResolver = (XMLEntityResolver)value;
 362             fEntityManager.setProperty(propertyId, value);
 363         }
 364         else if (propertyId.equals(LOCALE)) {
 365             setLocale((Locale) value);
 366         }
 367         else if(propertyId.equals(GRAMMAR_POOL)) {
 368             fGrammarPool = (XMLGrammarPool)value;
 369         }
 370         else {
 371             throw new XMLConfigurationException(Status.NOT_RECOGNIZED, propertyId);
 372         }
 373     } // setProperty(String,Object)
 374 
 375     /**
 376      * Returns the state of a feature.
 377      *
 378      * @param featureId The feature identifier.
 379      *
 380      * @throws XMLConfigurationException Thrown on configuration error.
 381      */
 382     public boolean getFeature(String featureId)
 383             throws XMLConfigurationException {
 384         if (featureId.equals(VALIDATION)) {
 385             return fValidation;
 386         }
 387         else if (featureId.equals(WARN_ON_DUPLICATE_ATTDEF)) {
 388             return fWarnDuplicateAttdef;
 389         }
 390         else if (featureId.equals(WARN_ON_UNDECLARED_ELEMDEF)) {
 391             return fWarnOnUndeclaredElemdef;
 392         }
 393         else if (featureId.equals(NOTIFY_CHAR_REFS)) {
 394             return fDTDScanner.getFeature(featureId);
 395         }
 396         else if (featureId.equals(STANDARD_URI_CONFORMANT_FEATURE)) {
 397             return fStrictURI;
 398         }
 399         else if (featureId.equals(BALANCE_SYNTAX_TREES)) {
 400             return fBalanceSyntaxTrees;
 401         }
 402         throw new XMLConfigurationException(Status.NOT_RECOGNIZED, featureId);
 403     } //getFeature(String):  boolean
 404 
 405     /**
 406      * Set the locale to use for messages.
 407      *
 408      * @param locale The locale object to use for localization of messages.
 409      *
 410      * @exception XNIException Thrown if the parser does not support the
 411      *                         specified locale.
 412      */
 413     public void setLocale(Locale locale) {
 414         fLocale = locale;
 415         fErrorReporter.setLocale(locale);
 416     } // setLocale(Locale)
 417 
 418     /** Return the Locale the XMLGrammarLoader is using. */
 419     public Locale getLocale() {
 420         return fLocale;
 421     } // getLocale():  Locale
 422 
 423 
 424     /**
 425      * Sets the error handler.
 426      *
 427      * @param errorHandler The error handler.
 428      */
 429     public void setErrorHandler(XMLErrorHandler errorHandler) {
 430         fErrorReporter.setProperty(ERROR_HANDLER, errorHandler);
 431     } // setErrorHandler(XMLErrorHandler)
 432 
 433     /** Returns the registered error handler.  */
 434     public XMLErrorHandler getErrorHandler() {
 435         return fErrorReporter.getErrorHandler();
 436     } // getErrorHandler():  XMLErrorHandler
 437 
 438     /**
 439      * Sets the entity resolver.
 440      *
 441      * @param entityResolver The new entity resolver.
 442      */
 443     public void setEntityResolver(XMLEntityResolver entityResolver) {
 444         fEntityResolver = entityResolver;
 445         fEntityManager.setProperty(ENTITY_RESOLVER, entityResolver);
 446     } // setEntityResolver(XMLEntityResolver)
 447 
 448     /** Returns the registered entity resolver.  */
 449     public XMLEntityResolver getEntityResolver() {
 450         return fEntityResolver;
 451     } // getEntityResolver():  XMLEntityResolver
 452 
 453     /**
 454      * Returns a Grammar object by parsing the contents of the
 455      * entity pointed to by source.
 456      *
 457      * @param source        the location of the entity which forms
 458      *                          the starting point of the grammar to be constructed.
 459      * @throws IOException      When a problem is encountered reading the entity
 460      *          XNIException    When a condition arises (such as a FatalError) that requires parsing
 461      *                              of the entity be terminated.
 462      */
 463     public Grammar loadGrammar(XMLInputSource source)
 464             throws IOException, XNIException {
 465         reset();
 466         // First chance checking strict URI
 467         String eid = XMLEntityManager.expandSystemId(source.getSystemId(), source.getBaseSystemId(), fStrictURI);
 468         XMLDTDDescription desc = new XMLDTDDescription(source.getPublicId(), source.getSystemId(), source.getBaseSystemId(), eid, null);
 469         if (!fBalanceSyntaxTrees) {
 470             fDTDGrammar = new DTDGrammar(fSymbolTable, desc);
 471         }
 472         else {
 473             fDTDGrammar = new BalancedDTDGrammar(fSymbolTable, desc);
 474         }
 475         fGrammarBucket = new DTDGrammarBucket();
 476         fGrammarBucket.setStandalone(false);
 477         fGrammarBucket.setActiveGrammar(fDTDGrammar);
 478         // no reason to use grammar bucket's "put" method--we
 479         // know which grammar it is, and we don't know the root name anyway...
 480 
 481         // actually start the parsing!
 482         try {
 483             fDTDScanner.setInputSource(source);
 484             fDTDScanner.scanDTDExternalSubset(true);
 485         } catch (EOFException e) {
 486             // expected behaviour...
 487         }
 488         finally {
 489             // Close all streams opened by the parser.
 490             fEntityManager.closeReaders();
 491         }
 492         if(fDTDGrammar != null && fGrammarPool != null) {
 493             fGrammarPool.cacheGrammars(XMLDTDDescription.XML_DTD, new Grammar[] {fDTDGrammar});
 494         }
 495         return fDTDGrammar;
 496     } // loadGrammar(XMLInputSource):  Grammar
 497 
 498     /**
 499      * Parse a DTD internal and/or external subset and insert the content
 500      * into the existing DTD grammar owned by the given DTDValidator.
 501      */
 502     public void loadGrammarWithContext(XMLDTDValidator validator, String rootName,
 503             String publicId, String systemId, String baseSystemId, String internalSubset)
 504         throws IOException, XNIException {
 505         final DTDGrammarBucket grammarBucket = validator.getGrammarBucket();
 506         final DTDGrammar activeGrammar = grammarBucket.getActiveGrammar();
 507         if (activeGrammar != null && !activeGrammar.isImmutable()) {
 508             fGrammarBucket = grammarBucket;
 509             fEntityManager.setScannerVersion(getScannerVersion());
 510             reset();
 511             try {
 512                 // process internal subset
 513                 if (internalSubset != null) {
 514                     // To get the DTD scanner to end at the right place we have to fool
 515                     // it into thinking that it reached the end of the internal subset
 516                     // in a real document.
 517                     StringBuffer buffer = new StringBuffer(internalSubset.length() + 2);
 518                     buffer.append(internalSubset).append("]>");
 519                     XMLInputSource is = new XMLInputSource(null, baseSystemId,
 520                             null, new StringReader(buffer.toString()), null);
 521                     fEntityManager.startDocumentEntity(is);
 522                     fDTDScanner.scanDTDInternalSubset(true, false, systemId != null);
 523                 }
 524                 // process external subset
 525                 if (systemId != null) {
 526                     XMLDTDDescription desc = new XMLDTDDescription(publicId, systemId, baseSystemId, null, rootName);
 527                     XMLInputSource source = fEntityManager.resolveEntity(desc);
 528                     fDTDScanner.setInputSource(source);
 529                     fDTDScanner.scanDTDExternalSubset(true);
 530                 }
 531             }
 532             catch (EOFException e) {
 533                 // expected behaviour...
 534             }
 535             finally {
 536                 // Close all streams opened by the parser.
 537                 fEntityManager.closeReaders();
 538             }
 539         }
 540     } // loadGrammarWithContext(XMLDTDValidator, String, String, String, String, String)
 541 
 542     // reset all the components that we rely upon
 543     protected void reset() {
 544         super.reset();
 545         fDTDScanner.reset();
 546         fEntityManager.reset();
 547         fErrorReporter.setDocumentLocator(fEntityManager.getEntityScanner());
 548     }
 549 
 550     protected XMLDTDScannerImpl createDTDScanner(SymbolTable symbolTable,
 551             XMLErrorReporter errorReporter, XMLEntityManager entityManager) {
 552         return new XMLDTDScannerImpl(symbolTable, errorReporter, entityManager);
 553     } // createDTDScanner(SymbolTable, XMLErrorReporter, XMLEntityManager) : XMLDTDScannerImpl
 554 
 555     protected short getScannerVersion() {
 556         return Constants.XML_VERSION_1_0;
 557     } // getScannerVersion() : short
 558 
 559 } // class XMLDTDLoader