1 /*
   2  * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
   3  */
   4 /*
   5  * Copyright 2001-2004 The Apache Software Foundation.
   6  *
   7  * Licensed under the Apache License, Version 2.0 (the "License");
   8  * you may not use this file except in compliance with the License.
   9  * You may obtain a copy of the License at
  10  *
  11  *      http://www.apache.org/licenses/LICENSE-2.0
  12  *
  13  * Unless required by applicable law or agreed to in writing, software
  14  * distributed under the License is distributed on an "AS IS" BASIS,
  15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  16  * See the License for the specific language governing permissions and
  17  * limitations under the License.
  18  */
  19 
  20 package com.sun.org.apache.xerces.internal.dom;
  21 
  22 import com.sun.org.apache.xerces.internal.impl.Constants;
  23 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
  24 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
  25 import com.sun.org.apache.xerces.internal.impl.dv.DTDDVFactory;
  26 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
  27 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
  28 import com.sun.org.apache.xerces.internal.util.DOMEntityResolverWrapper;
  29 import com.sun.org.apache.xerces.internal.util.DOMErrorHandlerWrapper;
  30 import com.sun.org.apache.xerces.internal.util.MessageFormatter;
  31 import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings;
  32 import com.sun.org.apache.xerces.internal.util.PropertyState;
  33 import com.sun.org.apache.xerces.internal.util.SymbolTable;
  34 import com.sun.org.apache.xerces.internal.utils.ObjectFactory;
  35 import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
  36 import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
  37 import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler;
  38 import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler;
  39 import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
  40 import com.sun.org.apache.xerces.internal.xni.XNIException;
  41 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
  42 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
  43 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
  44 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
  45 import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
  46 import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler;
  47 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
  48 import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
  49 import java.io.IOException;
  50 import java.util.ArrayList;
  51 import java.util.HashMap;
  52 import java.util.Locale;
  53 import java.util.Vector;
  54 import jdk.xml.internal.JdkXmlUtils;
  55 import org.w3c.dom.DOMConfiguration;
  56 import org.w3c.dom.DOMErrorHandler;
  57 import org.w3c.dom.DOMException;
  58 import org.w3c.dom.DOMStringList;
  59 import org.w3c.dom.ls.LSResourceResolver;
  60 
  61 
  62 
  63 /**
  64  * Xerces implementation of DOMConfiguration that maintains a table of recognized parameters.
  65  *
  66  * @xerces.internal
  67  *
  68  * @author Elena Litani, IBM
  69  * @author Neeraj Bajaj, Sun Microsystems.
  70  */
  71 public class DOMConfigurationImpl extends ParserConfigurationSettings
  72     implements XMLParserConfiguration, DOMConfiguration {
  73 
  74     //
  75     // Constants
  76     //
  77 
  78     // feature identifiers
  79 
  80     /** Feature identifier: validation. */
  81     protected static final String XERCES_VALIDATION =
  82         Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
  83 
  84     /** Feature identifier: namespaces. */
  85     protected static final String XERCES_NAMESPACES =
  86         Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
  87 
  88     protected static final String SCHEMA =
  89         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
  90 
  91     protected static final String SCHEMA_FULL_CHECKING =
  92         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING;
  93 
  94     protected static final String DYNAMIC_VALIDATION =
  95         Constants.XERCES_FEATURE_PREFIX + Constants.DYNAMIC_VALIDATION_FEATURE;
  96 
  97     protected static final String NORMALIZE_DATA =
  98         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE;
  99 
 100     /** sending psvi in the pipeline */
 101     protected static final String SEND_PSVI =
 102         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_AUGMENT_PSVI;
 103 
 104     protected final static String DTD_VALIDATOR_FACTORY_PROPERTY =
 105         Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
 106 
 107     /** Feature identifier: namespace growth */
 108     protected static final String NAMESPACE_GROWTH =
 109         Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE;
 110 
 111     protected static final String TOLERATE_DUPLICATES =
 112         Constants.XERCES_FEATURE_PREFIX + Constants.TOLERATE_DUPLICATES_FEATURE;
 113 
 114     // property identifiers
 115 
 116     /** Property identifier: entity manager. */
 117     protected static final String ENTITY_MANAGER =
 118         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
 119 
 120     /** Property identifier: error reporter. */
 121     protected static final String ERROR_REPORTER =
 122         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
 123 
 124     /** Property identifier: xml string. */
 125     protected static final String XML_STRING =
 126         Constants.SAX_PROPERTY_PREFIX + Constants.XML_STRING_PROPERTY;
 127 
 128     /** Property identifier: symbol table. */
 129     protected static final String SYMBOL_TABLE =
 130         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
 131 
 132     /** Property id: Grammar pool*/
 133     protected static final String GRAMMAR_POOL =
 134     Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
 135 
 136     /** Property identifier: error handler. */
 137     protected static final String ERROR_HANDLER =
 138         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
 139 
 140     /** Property identifier: entity resolver. */
 141     protected static final String ENTITY_RESOLVER =
 142         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
 143 
 144     /** Property identifier: JAXP schema language / DOM schema-type. */
 145     protected static final String JAXP_SCHEMA_LANGUAGE =
 146     Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE;
 147 
 148     /** Property identifier: JAXP schema source/ DOM schema-location. */
 149     protected static final String JAXP_SCHEMA_SOURCE =
 150     Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE;
 151 
 152     protected static final String VALIDATION_MANAGER =
 153         Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
 154 
 155     /** Property identifier: Schema DV Factory */
 156     protected static final String SCHEMA_DV_FACTORY =
 157         Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY;
 158 
 159     /** Property identifier: Security manager. */
 160     private static final String SECURITY_MANAGER = Constants.SECURITY_MANAGER;
 161 
 162     /** Property identifier: Security property manager. */
 163     private static final String XML_SECURITY_PROPERTY_MANAGER =
 164             Constants.XML_SECURITY_PROPERTY_MANAGER;
 165 
 166     //
 167     // Data
 168     //
 169     XMLDocumentHandler fDocumentHandler;
 170 
 171     /** Normalization features*/
 172     protected short features = 0;
 173 
 174     protected final static short NAMESPACES          = 0x1<<0;
 175     protected final static short DTNORMALIZATION     = 0x1<<1;
 176     protected final static short ENTITIES            = 0x1<<2;
 177     protected final static short CDATA               = 0x1<<3;
 178     protected final static short SPLITCDATA          = 0x1<<4;
 179     protected final static short COMMENTS            = 0x1<<5;
 180     protected final static short VALIDATE            = 0x1<<6;
 181     protected final static short PSVI                = 0x1<<7;
 182     protected final static short WELLFORMED          = 0x1<<8;
 183     protected final static short NSDECL              = 0x1<<9;
 184 
 185     protected final static short INFOSET_TRUE_PARAMS = NAMESPACES | COMMENTS | WELLFORMED | NSDECL;
 186     protected final static short INFOSET_FALSE_PARAMS = ENTITIES | DTNORMALIZATION | CDATA;
 187     protected final static short INFOSET_MASK = INFOSET_TRUE_PARAMS | INFOSET_FALSE_PARAMS;
 188 
 189     // components
 190 
 191     /** Symbol table. */
 192     protected SymbolTable fSymbolTable;
 193 
 194     /** Components. */
 195     protected ArrayList fComponents;
 196 
 197     protected ValidationManager fValidationManager;
 198 
 199     /** Locale. */
 200     protected Locale fLocale;
 201 
 202     /** Error reporter */
 203     protected XMLErrorReporter fErrorReporter;
 204 
 205     protected final DOMErrorHandlerWrapper fErrorHandlerWrapper =
 206                 new DOMErrorHandlerWrapper();
 207 
 208     // private data
 209 
 210     private DOMStringList fRecognizedParameters;
 211 
 212 
 213     //
 214     // Constructors
 215     //
 216 
 217     /** Default Constructor. */
 218     protected DOMConfigurationImpl() {
 219         this(null, null);
 220     } // <init>()
 221 
 222     /**
 223      * Constructs a parser configuration using the specified symbol table.
 224      *
 225      * @param symbolTable The symbol table to use.
 226      */
 227     protected DOMConfigurationImpl(SymbolTable symbolTable) {
 228         this(symbolTable, null);
 229     } // <init>(SymbolTable)
 230 
 231     /**
 232      * Constructs a parser configuration using the specified symbol table
 233      * and parent settings.
 234      *
 235      * @param symbolTable    The symbol table to use.
 236      * @param parentSettings The parent settings.
 237      */
 238     protected DOMConfigurationImpl(SymbolTable symbolTable,
 239                                     XMLComponentManager parentSettings) {
 240         super(parentSettings);
 241 
 242 
 243         // create table for features and properties
 244         fFeatures = new HashMap();
 245         fProperties = new HashMap();
 246 
 247         // add default recognized features
 248         final String[] recognizedFeatures = {
 249             XERCES_VALIDATION,
 250             XERCES_NAMESPACES,
 251             SCHEMA,
 252             SCHEMA_FULL_CHECKING,
 253             DYNAMIC_VALIDATION,
 254             NORMALIZE_DATA,
 255             SEND_PSVI,
 256             NAMESPACE_GROWTH,
 257             TOLERATE_DUPLICATES,
 258             JdkXmlUtils.OVERRIDE_PARSER
 259         };
 260         addRecognizedFeatures(recognizedFeatures);
 261 
 262         // set state for default features
 263         setFeature(XERCES_VALIDATION, false);
 264         setFeature(SCHEMA, false);
 265         setFeature(SCHEMA_FULL_CHECKING, false);
 266         setFeature(DYNAMIC_VALIDATION, false);
 267         setFeature(NORMALIZE_DATA, false);
 268         setFeature(XERCES_NAMESPACES, true);
 269         setFeature(SEND_PSVI, true);
 270         setFeature(NAMESPACE_GROWTH, false);
 271         setFeature(JdkXmlUtils.OVERRIDE_PARSER, JdkXmlUtils.OVERRIDE_PARSER_DEFAULT);
 272 
 273         // add default recognized properties
 274         final String[] recognizedProperties = {
 275             XML_STRING,
 276             SYMBOL_TABLE,
 277             ERROR_HANDLER,
 278             ENTITY_RESOLVER,
 279             ERROR_REPORTER,
 280             ENTITY_MANAGER,
 281             VALIDATION_MANAGER,
 282             GRAMMAR_POOL,
 283             JAXP_SCHEMA_SOURCE,
 284             JAXP_SCHEMA_LANGUAGE,
 285             DTD_VALIDATOR_FACTORY_PROPERTY,
 286             SCHEMA_DV_FACTORY,
 287             SECURITY_MANAGER,
 288             XML_SECURITY_PROPERTY_MANAGER
 289         };
 290         addRecognizedProperties(recognizedProperties);
 291 
 292         // set default values for normalization features
 293         features |= NAMESPACES;
 294         features |= ENTITIES;
 295         features |= COMMENTS;
 296         features |= CDATA;
 297         features |= SPLITCDATA;
 298         features |= WELLFORMED;
 299         features |= NSDECL;
 300 
 301         if (symbolTable == null) {
 302             symbolTable = new SymbolTable();
 303         }
 304         fSymbolTable = symbolTable;
 305 
 306         fComponents = new ArrayList();
 307 
 308         setProperty(SYMBOL_TABLE, fSymbolTable);
 309         fErrorReporter = new XMLErrorReporter();
 310         setProperty(ERROR_REPORTER, fErrorReporter);
 311         addComponent(fErrorReporter);
 312 
 313         setProperty(DTD_VALIDATOR_FACTORY_PROPERTY, DTDDVFactory.getInstance());
 314 
 315         XMLEntityManager manager =  new XMLEntityManager();
 316         setProperty(ENTITY_MANAGER, manager);
 317         addComponent(manager);
 318 
 319         fValidationManager = createValidationManager();
 320         setProperty(VALIDATION_MANAGER, fValidationManager);
 321 
 322         setProperty(SECURITY_MANAGER, new XMLSecurityManager(true));
 323 
 324         setProperty(Constants.XML_SECURITY_PROPERTY_MANAGER,
 325                 new XMLSecurityPropertyManager());
 326 
 327         // add message formatters
 328         if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
 329             XMLMessageFormatter xmft = new XMLMessageFormatter();
 330             fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
 331             fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
 332         }
 333 
 334         // REVISIT: try to include XML Schema formatter.
 335         //          This is a hack to allow DTD configuration to be build.
 336         //
 337         if (fErrorReporter.getMessageFormatter("http://www.w3.org/TR/xml-schema-1") == null) {
 338             MessageFormatter xmft = null;
 339             try {
 340                xmft = (MessageFormatter)(
 341                     ObjectFactory.newInstance("com.sun.org.apache.xerces.internal.impl.xs.XSMessageFormatter", true));
 342             } catch (Exception exception){
 343             }
 344 
 345              if (xmft !=  null) {
 346                  fErrorReporter.putMessageFormatter("http://www.w3.org/TR/xml-schema-1", xmft);
 347              }
 348         }
 349 
 350 
 351         // set locale
 352         try {
 353             setLocale(Locale.getDefault());
 354         }
 355         catch (XNIException e) {
 356             // do nothing
 357             // REVISIT: What is the right thing to do? -Ac
 358         }
 359 
 360 
 361     } // <init>(SymbolTable)
 362 
 363 
 364     //
 365     // XMLParserConfiguration methods
 366     //
 367 
 368     /**
 369      * Parse an XML document.
 370      * <p>
 371      * The parser can use this method to instruct this configuration
 372      * to begin parsing an XML document from any valid input source
 373      * (a character stream, a byte stream, or a URI).
 374      * <p>
 375      * Parsers may not invoke this method while a parse is in progress.
 376      * Once a parse is complete, the parser may then parse another XML
 377      * document.
 378      * <p>
 379      * This method is synchronous: it will not return until parsing
 380      * has ended.  If a client application wants to terminate
 381      * parsing early, it should throw an exception.
 382      *
 383      * @param source The input source for the top-level of the
 384      *               XML document.
 385      *
 386      * @exception XNIException Any XNI exception, possibly wrapping
 387      *                         another exception.
 388      * @exception IOException  An IO exception from the parser, possibly
 389      *                         from a byte stream or character stream
 390      *                         supplied by the parser.
 391      */
 392     public void parse(XMLInputSource inputSource)
 393         throws XNIException, IOException{
 394         // no-op
 395     }
 396 
 397     /**
 398      * Sets the document handler on the last component in the pipeline
 399      * to receive information about the document.
 400      *
 401      * @param documentHandler   The document handler.
 402      */
 403     public void setDocumentHandler(XMLDocumentHandler documentHandler) {
 404         fDocumentHandler = documentHandler;
 405     } // setDocumentHandler(XMLDocumentHandler)
 406 
 407     /** Returns the registered document handler. */
 408     public XMLDocumentHandler getDocumentHandler() {
 409         return fDocumentHandler;
 410     } // getDocumentHandler():XMLDocumentHandler
 411 
 412     /**
 413      * Sets the DTD handler.
 414      *
 415      * @param dtdHandler The DTD handler.
 416      */
 417     public void setDTDHandler(XMLDTDHandler dtdHandler) {
 418         //no-op
 419     } // setDTDHandler(XMLDTDHandler)
 420 
 421     /** Returns the registered DTD handler. */
 422     public XMLDTDHandler getDTDHandler() {
 423         return null;
 424     } // getDTDHandler():XMLDTDHandler
 425 
 426     /**
 427      * Sets the DTD content model handler.
 428      *
 429      * @param handler The DTD content model handler.
 430      */
 431     public void setDTDContentModelHandler(XMLDTDContentModelHandler handler) {
 432         //no-op
 433 
 434     } // setDTDContentModelHandler(XMLDTDContentModelHandler)
 435 
 436     /** Returns the registered DTD content model handler. */
 437     public XMLDTDContentModelHandler getDTDContentModelHandler() {
 438         return null;
 439     } // getDTDContentModelHandler():XMLDTDContentModelHandler
 440 
 441     /**
 442      * Sets the resolver used to resolve external entities. The EntityResolver
 443      * interface supports resolution of public and system identifiers.
 444      *
 445      * @param resolver The new entity resolver. Passing a null value will
 446      *                 uninstall the currently installed resolver.
 447      */
 448     public void setEntityResolver(XMLEntityResolver resolver) {
 449         if (resolver !=null) {
 450             fProperties.put(ENTITY_RESOLVER, resolver);
 451         }
 452     } // setEntityResolver(XMLEntityResolver)
 453 
 454     /**
 455      * Return the current entity resolver.
 456      *
 457      * @return The current entity resolver, or null if none
 458      *         has been registered.
 459      * @see #setEntityResolver
 460      */
 461     public XMLEntityResolver getEntityResolver() {
 462         return (XMLEntityResolver)fProperties.get(ENTITY_RESOLVER);
 463     } // getEntityResolver():XMLEntityResolver
 464 
 465     /**
 466      * Allow an application to register an error event handler.
 467      *
 468      * <p>If the application does not register an error handler, all
 469      * error events reported by the SAX parser will be silently
 470      * ignored; however, normal processing may not continue.  It is
 471      * highly recommended that all SAX applications implement an
 472      * error handler to avoid unexpected bugs.</p>
 473      *
 474      * <p>Applications may register a new or different handler in the
 475      * middle of a parse, and the SAX parser must begin using the new
 476      * handler immediately.</p>
 477      *
 478      * @param errorHandler The error handler.
 479      * @exception java.lang.NullPointerException If the handler
 480      *            argument is null.
 481      * @see #getErrorHandler
 482      */
 483     public void setErrorHandler(XMLErrorHandler errorHandler) {
 484         if (errorHandler != null) {
 485             fProperties.put(ERROR_HANDLER, errorHandler);
 486         }
 487     } // setErrorHandler(XMLErrorHandler)
 488 
 489     /**
 490      * Return the current error handler.
 491      *
 492      * @return The current error handler, or null if none
 493      *         has been registered.
 494      * @see #setErrorHandler
 495      */
 496     public XMLErrorHandler getErrorHandler() {
 497         return (XMLErrorHandler)fProperties.get(ERROR_HANDLER);
 498     } // getErrorHandler():XMLErrorHandler
 499 
 500     /**
 501      * Set the state of a feature.
 502      *
 503      * Set the state of any feature in a SAX2 parser.  The parser
 504      * might not recognize the feature, and if it does recognize
 505      * it, it might not be able to fulfill the request.
 506      *
 507      * @param featureId The unique identifier (URI) of the feature.
 508      * @param state The requested state of the feature (true or false).
 509      *
 510      * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
 511      *            requested feature is not known.
 512      */
 513     public void setFeature(String featureId, boolean state)
 514         throws XMLConfigurationException {
 515 
 516         // save state if noone "objects"
 517         super.setFeature(featureId, state);
 518 
 519     } // setFeature(String,boolean)
 520 
 521     /**
 522      * setProperty
 523      *
 524      * @param propertyId
 525      * @param value
 526      */
 527     public void setProperty(String propertyId, Object value)
 528         throws XMLConfigurationException {
 529 
 530         // store value if noone "objects"
 531         super.setProperty(propertyId, value);
 532 
 533     } // setProperty(String,Object)
 534 
 535     /**
 536      * Set the locale to use for messages.
 537      *
 538      * @param locale The locale object to use for localization of messages.
 539      *
 540      * @exception XNIException Thrown if the parser does not support the
 541      *                         specified locale.
 542      */
 543     public void setLocale(Locale locale) throws XNIException {
 544         fLocale = locale;
 545         fErrorReporter.setLocale(locale);
 546 
 547     } // setLocale(Locale)
 548 
 549     /** Returns the locale. */
 550     public Locale getLocale() {
 551         return fLocale;
 552     } // getLocale():Locale
 553 
 554     /**
 555      * DOM Level 3 WD - Experimental.
 556      * setParameter
 557      */
 558     public void setParameter(String name, Object value) throws DOMException {
 559         boolean found = true;
 560 
 561         // REVISIT: Recognizes DOM L3 default features only.
 562         //          Does not yet recognize Xerces features.
 563                 if(value instanceof Boolean){
 564                         boolean state = ((Boolean)value).booleanValue();
 565 
 566             if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)) {
 567                 features = (short) (state ? features | COMMENTS : features & ~COMMENTS);
 568             }
 569             else if (name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)) {
 570                 setFeature(NORMALIZE_DATA, state);
 571                 features =
 572                     (short) (state ? features | DTNORMALIZATION : features & ~DTNORMALIZATION);
 573                 if (state) {
 574                     features = (short) (features | VALIDATE);
 575                 }
 576             }
 577             else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACES)) {
 578                 features = (short) (state ? features | NAMESPACES : features & ~NAMESPACES);
 579             }
 580             else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)) {
 581                 features = (short) (state ? features | CDATA : features & ~CDATA);
 582             }
 583             else if (name.equalsIgnoreCase(Constants.DOM_ENTITIES)) {
 584                 features = (short) (state ? features | ENTITIES : features & ~ENTITIES);
 585             }
 586             else if (name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)) {
 587                 features = (short) (state ? features | SPLITCDATA : features & ~SPLITCDATA);
 588             }
 589             else if (name.equalsIgnoreCase(Constants.DOM_VALIDATE)) {
 590                 features = (short) (state ? features | VALIDATE : features & ~VALIDATE);
 591             }
 592             else if (name.equalsIgnoreCase(Constants.DOM_WELLFORMED)) {
 593                 features = (short) (state ? features | WELLFORMED : features & ~WELLFORMED );
 594             }
 595             else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)) {
 596                 features = (short) (state ? features | NSDECL : features & ~NSDECL);
 597             }
 598             else if (name.equalsIgnoreCase(Constants.DOM_INFOSET)) {
 599                 // Setting to false has no effect.
 600                 if (state) {
 601                     features = (short) (features | INFOSET_TRUE_PARAMS);
 602                     features = (short) (features & ~INFOSET_FALSE_PARAMS);
 603                     setFeature(NORMALIZE_DATA, false);
 604                 }
 605             }
 606             else if (name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)
 607                     || name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
 608                     || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
 609                     || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
 610                     ) {
 611                 if (state) { // true is not supported
 612                     String msg =
 613                         DOMMessageFormatter.formatMessage(
 614                             DOMMessageFormatter.DOM_DOMAIN,
 615                             "FEATURE_NOT_SUPPORTED",
 616                             new Object[] { name });
 617                     throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
 618                 }
 619             }
 620                         else if ( name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)) {
 621                 if (!state) { // false is not supported
 622                     String msg =
 623                         DOMMessageFormatter.formatMessage(
 624                             DOMMessageFormatter.DOM_DOMAIN,
 625                             "FEATURE_NOT_SUPPORTED",
 626                             new Object[] { name });
 627                    throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
 628                 }
 629             }
 630             else if (name.equalsIgnoreCase(SEND_PSVI) ){
 631                 // REVISIT: turning augmentation of PSVI is not support,
 632                 // because in this case we won't be able to retrieve element
 633                 // default value.
 634                 if (!state) { // false is not supported
 635                     String msg =
 636                         DOMMessageFormatter.formatMessage(
 637                             DOMMessageFormatter.DOM_DOMAIN,
 638                             "FEATURE_NOT_SUPPORTED",
 639                             new Object[] { name });
 640                     throw new DOMException(DOMException.NOT_SUPPORTED_ERR, msg);
 641                 }
 642             }
 643             else if (name.equalsIgnoreCase(Constants.DOM_PSVI)){
 644                   features = (short) (state ? features | PSVI : features & ~PSVI);
 645             }
 646             else {
 647                 found = false;
 648                 /*
 649                 String msg =
 650                     DOMMessageFormatter.formatMessage(
 651                         DOMMessageFormatter.DOM_DOMAIN,
 652                         "FEATURE_NOT_FOUND",
 653                         new Object[] { name });
 654                 throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
 655                 */
 656             }
 657 
 658         }
 659 
 660                 if (!found || !(value instanceof Boolean))  { // set properties
 661                         found = true;
 662 
 663             if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
 664                 if (value instanceof DOMErrorHandler || value == null) {
 665                     fErrorHandlerWrapper.setErrorHandler((DOMErrorHandler)value);
 666                     setErrorHandler(fErrorHandlerWrapper);
 667                 }
 668 
 669                 else {
 670                     // REVISIT: type mismatch
 671                     String msg =
 672                         DOMMessageFormatter.formatMessage(
 673                             DOMMessageFormatter.DOM_DOMAIN,
 674                             "TYPE_MISMATCH_ERR",
 675                             new Object[] { name });
 676                     throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
 677                 }
 678             }
 679             else if (name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)) {
 680                 if (value instanceof LSResourceResolver || value == null) {
 681                     try {
 682                         setEntityResolver(new DOMEntityResolverWrapper((LSResourceResolver) value));
 683                     }
 684                     catch (XMLConfigurationException e) {}
 685                 }
 686                 else {
 687                     // REVISIT: type mismatch
 688                     String msg =
 689                         DOMMessageFormatter.formatMessage(
 690                             DOMMessageFormatter.DOM_DOMAIN,
 691                             "TYPE_MISMATCH_ERR",
 692                             new Object[] { name });
 693                     throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
 694                 }
 695 
 696             }
 697             else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)) {
 698                 if (value instanceof String || value == null) {
 699                     try {
 700                         // map DOM schema-location to JAXP schemaSource property
 701                         setProperty(
 702                             Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
 703                             value);
 704                     }
 705                     catch (XMLConfigurationException e) {}
 706                 }
 707                 else {
 708                     // REVISIT: type mismatch
 709                     String msg =
 710                         DOMMessageFormatter.formatMessage(
 711                             DOMMessageFormatter.DOM_DOMAIN,
 712                             "TYPE_MISMATCH_ERR",
 713                             new Object[] { name });
 714                     throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
 715                 }
 716 
 717             }
 718             else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) {
 719                 if (value instanceof String || value == null) {
 720                     try {
 721                         if (value == null) {
 722                             setProperty(
 723                                 Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE,
 724                                 null);
 725                         }
 726                         else if (value.equals(Constants.NS_XMLSCHEMA)) {
 727                             // REVISIT: when add support to DTD validation
 728                             setProperty(
 729                                 Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE,
 730                                 Constants.NS_XMLSCHEMA);
 731                         }
 732                         else if (value.equals(Constants.NS_DTD)) {
 733                             // Added support for revalidation against DTDs
 734                                 setProperty(Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE,
 735                                                 Constants.NS_DTD);
 736                         }
 737                     }
 738                     catch (XMLConfigurationException e) {}
 739                 }
 740                 else {
 741                     String msg =
 742                         DOMMessageFormatter.formatMessage(
 743                             DOMMessageFormatter.DOM_DOMAIN,
 744                             "TYPE_MISMATCH_ERR",
 745                             new Object[] { name });
 746                     throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
 747                 }
 748 
 749             }
 750             else if (name.equalsIgnoreCase(SYMBOL_TABLE)){
 751                 // Xerces Symbol Table
 752                 if (value instanceof SymbolTable){
 753                     setProperty(SYMBOL_TABLE, value);
 754                 }
 755                 else {
 756                     // REVISIT: type mismatch
 757                     String msg =
 758                         DOMMessageFormatter.formatMessage(
 759                             DOMMessageFormatter.DOM_DOMAIN,
 760                             "TYPE_MISMATCH_ERR",
 761                             new Object[] { name });
 762                     throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
 763                 }
 764             }
 765             else if (name.equalsIgnoreCase (GRAMMAR_POOL)){
 766                 if (value instanceof XMLGrammarPool){
 767                     setProperty(GRAMMAR_POOL, value);
 768                 }
 769                 else {
 770                     // REVISIT: type mismatch
 771                     String msg =
 772                         DOMMessageFormatter.formatMessage(
 773                             DOMMessageFormatter.DOM_DOMAIN,
 774                             "TYPE_MISMATCH_ERR",
 775                             new Object[] { name });
 776                     throw new DOMException(DOMException.TYPE_MISMATCH_ERR, msg);
 777                 }
 778 
 779             }
 780             else {
 781                 // REVISIT: check if this is a boolean parameter -- type mismatch should be thrown.
 782                 //parameter is not recognized
 783                 String msg =
 784                     DOMMessageFormatter.formatMessage(
 785                         DOMMessageFormatter.DOM_DOMAIN,
 786                         "FEATURE_NOT_FOUND",
 787                         new Object[] { name });
 788                 throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
 789             }
 790         }
 791 
 792     }
 793 
 794 
 795     /**
 796      * DOM Level 3 WD - Experimental.
 797      * getParameter
 798      */
 799         public Object getParameter(String name) throws DOMException {
 800 
 801                 // REVISIT: Recognizes DOM L3 default features only.
 802                 //          Does not yet recognize Xerces features.
 803 
 804                 if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)) {
 805                         return ((features & COMMENTS) != 0) ? Boolean.TRUE : Boolean.FALSE;
 806                 }
 807                 else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACES)) {
 808                         return (features & NAMESPACES) != 0 ? Boolean.TRUE : Boolean.FALSE;
 809                 }
 810                 else if (name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)) {
 811                         // REVISIT: datatype-normalization only takes effect if validation is on
 812                         return (features & DTNORMALIZATION) != 0 ? Boolean.TRUE : Boolean.FALSE;
 813                 }
 814                 else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)) {
 815                         return (features & CDATA) != 0 ? Boolean.TRUE : Boolean.FALSE;
 816                 }
 817                 else if (name.equalsIgnoreCase(Constants.DOM_ENTITIES)) {
 818                         return (features & ENTITIES) != 0 ? Boolean.TRUE : Boolean.FALSE;
 819                 }
 820                 else if (name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)) {
 821                         return (features & SPLITCDATA) != 0 ? Boolean.TRUE : Boolean.FALSE;
 822                 }
 823                 else if (name.equalsIgnoreCase(Constants.DOM_VALIDATE)) {
 824                         return (features & VALIDATE) != 0 ? Boolean.TRUE : Boolean.FALSE;
 825                 }
 826                 else if (name.equalsIgnoreCase(Constants.DOM_WELLFORMED)) {
 827                         return (features & WELLFORMED) != 0 ? Boolean.TRUE : Boolean.FALSE;
 828                 }
 829                 else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)) {
 830                     return (features & NSDECL) != 0 ? Boolean.TRUE : Boolean.FALSE;
 831                 }
 832                 else if (name.equalsIgnoreCase(Constants.DOM_INFOSET)) {
 833                         return (features & INFOSET_MASK) == INFOSET_TRUE_PARAMS ? Boolean.TRUE : Boolean.FALSE;
 834                 }
 835                 else if (name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)
 836                                 || name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
 837                                 || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
 838                                 || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
 839                 ) {
 840                         return Boolean.FALSE;
 841                 }
 842         else if (name.equalsIgnoreCase(SEND_PSVI)) {
 843             return Boolean.TRUE;
 844         }
 845         else if (name.equalsIgnoreCase(Constants.DOM_PSVI)) {
 846             return (features & PSVI) != 0 ? Boolean.TRUE : Boolean.FALSE;
 847         }
 848         else if (name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)) {
 849                         return Boolean.TRUE;
 850                 }
 851                 else if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
 852             return fErrorHandlerWrapper.getErrorHandler();
 853                 }
 854                 else if (name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)) {
 855                         XMLEntityResolver entityResolver = getEntityResolver();
 856                         if (entityResolver != null && entityResolver instanceof DOMEntityResolverWrapper) {
 857                                 return ((DOMEntityResolverWrapper) entityResolver).getEntityResolver();
 858                         }
 859                         return null;
 860                 }
 861                 else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) {
 862                         return getProperty(Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE);
 863                 }
 864                 else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)) {
 865                         return getProperty(Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE);
 866                 }
 867         else if (name.equalsIgnoreCase(SYMBOL_TABLE)){
 868             return getProperty(SYMBOL_TABLE);
 869         }
 870         else if (name.equalsIgnoreCase(GRAMMAR_POOL)){
 871             return getProperty(GRAMMAR_POOL);
 872         }
 873                 else {
 874                         String msg =
 875                                 DOMMessageFormatter.formatMessage(
 876                                         DOMMessageFormatter.DOM_DOMAIN,
 877                                         "FEATURE_NOT_FOUND",
 878                                         new Object[] { name });
 879                         throw new DOMException(DOMException.NOT_FOUND_ERR, msg);
 880                 }
 881 
 882         }
 883 
 884     /**
 885      * DOM Level 3 WD - Experimental.
 886      * Check if setting a parameter to a specific value is supported.
 887      *
 888      * @param name The name of the parameter to check.
 889      *
 890      * @param value An object. if null, the returned value is true.
 891      *
 892      * @return true if the parameter could be successfully set to the
 893      * specified value, or false if the parameter is not recognized or
 894      * the requested value is not supported. This does not change the
 895      * current value of the parameter itself.
 896      */
 897         public boolean canSetParameter(String name, Object value) {
 898 
 899         if (value == null){
 900             //if null, the returned value is true.
 901             //REVISIT: I dont like this --- even for unrecognized parameter it would
 902             //return 'true'. I think it should return false in that case.
 903             // Application will be surprised to find that setParameter throws not
 904             //recognized exception when canSetParameter returns 'true' Then what is the use
 905             //of having canSetParameter ??? - nb.
 906             return true ;
 907         }
 908         if( value instanceof Boolean ){
 909             //features whose parameter value can be set either 'true' or 'false'
 910             // or they accept any boolean value -- so we just need to check that
 911             // its a boolean value..
 912             if (name.equalsIgnoreCase(Constants.DOM_COMMENTS)
 913                 || name.equalsIgnoreCase(Constants.DOM_DATATYPE_NORMALIZATION)
 914                 || name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)
 915                 || name.equalsIgnoreCase(Constants.DOM_ENTITIES)
 916                 || name.equalsIgnoreCase(Constants.DOM_SPLIT_CDATA)
 917                 || name.equalsIgnoreCase(Constants.DOM_NAMESPACES)
 918                 || name.equalsIgnoreCase(Constants.DOM_VALIDATE)
 919                 || name.equalsIgnoreCase(Constants.DOM_WELLFORMED)
 920                 || name.equalsIgnoreCase(Constants.DOM_INFOSET)
 921                 || name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)
 922                 ) {
 923                 return true;
 924             }//features whose parameter value can not be set to 'true'
 925             else if (
 926                 name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)
 927                     || name.equalsIgnoreCase(Constants.DOM_CANONICAL_FORM)
 928                     || name.equalsIgnoreCase(Constants.DOM_VALIDATE_IF_SCHEMA)
 929                     || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION)
 930                     ) {
 931                     return (value.equals(Boolean.TRUE)) ? false : true;
 932             }//features whose parameter value can not be set to 'false'
 933             else if( name.equalsIgnoreCase(Constants.DOM_ELEMENT_CONTENT_WHITESPACE)
 934                     || name.equalsIgnoreCase(SEND_PSVI)
 935                     ) {
 936                     return (value.equals(Boolean.TRUE)) ? true : false;
 937             }// if name is not among the above listed above -- its not recognized. return false
 938             else {
 939                 return false ;
 940             }
 941         }
 942                 else if (name.equalsIgnoreCase(Constants.DOM_ERROR_HANDLER)) {
 943             return (value instanceof DOMErrorHandler) ? true : false ;
 944         }
 945         else if (name.equalsIgnoreCase(Constants.DOM_RESOURCE_RESOLVER)) {
 946             return (value instanceof LSResourceResolver) ? true : false ;
 947         }
 948         else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_LOCATION)) {
 949             return (value instanceof String) ? true : false ;
 950         }
 951         else if (name.equalsIgnoreCase(Constants.DOM_SCHEMA_TYPE)) {
 952             // REVISIT: should null value be supported?
 953             //as of now we are only supporting W3C XML Schema
 954             return ( (value instanceof String) && value.equals(Constants.NS_XMLSCHEMA) ) ? true : false ;
 955         }
 956         else if (name.equalsIgnoreCase(SYMBOL_TABLE)){
 957             // Xerces Symbol Table
 958             return (value instanceof SymbolTable) ? true : false ;
 959         }
 960         else if (name.equalsIgnoreCase (GRAMMAR_POOL)){
 961             return (value instanceof XMLGrammarPool) ? true : false ;
 962         }
 963         else {
 964             //false if the parameter is not recognized or the requested value is not supported.
 965             return false ;
 966         }
 967 
 968         } //canSetParameter
 969 
 970     /**
 971      *  DOM Level 3 CR - Experimental.
 972      *
 973      *  The list of the parameters supported by this
 974      * <code>DOMConfiguration</code> object and for which at least one value
 975      * can be set by the application. Note that this list can also contain
 976      * parameter names defined outside this specification.
 977      */
 978     public DOMStringList getParameterNames() {
 979         if (fRecognizedParameters == null){
 980                         Vector parameters = new Vector();
 981 
 982                         //Add DOM recognized parameters
 983                         //REVISIT: Would have been nice to have a list of
 984                         //recognized paramters.
 985                         parameters.add(Constants.DOM_COMMENTS);
 986                         parameters.add(Constants.DOM_DATATYPE_NORMALIZATION);
 987                         parameters.add(Constants.DOM_CDATA_SECTIONS);
 988                         parameters.add(Constants.DOM_ENTITIES);
 989                         parameters.add(Constants.DOM_SPLIT_CDATA);
 990                         parameters.add(Constants.DOM_NAMESPACES);
 991                         parameters.add(Constants.DOM_VALIDATE);
 992 
 993                         parameters.add(Constants.DOM_INFOSET);
 994                         parameters.add(Constants.DOM_NORMALIZE_CHARACTERS);
 995                         parameters.add(Constants.DOM_CANONICAL_FORM);
 996                         parameters.add(Constants.DOM_VALIDATE_IF_SCHEMA);
 997                         parameters.add(Constants.DOM_CHECK_CHAR_NORMALIZATION);
 998                         parameters.add(Constants.DOM_WELLFORMED);
 999 
1000                         parameters.add(Constants.DOM_NAMESPACE_DECLARATIONS);
1001                         parameters.add(Constants.DOM_ELEMENT_CONTENT_WHITESPACE);
1002 
1003                         parameters.add(Constants.DOM_ERROR_HANDLER);
1004                         parameters.add(Constants.DOM_SCHEMA_TYPE);
1005                         parameters.add(Constants.DOM_SCHEMA_LOCATION);
1006                         parameters.add(Constants.DOM_RESOURCE_RESOLVER);
1007 
1008                         //Add recognized xerces features and properties
1009                         parameters.add(GRAMMAR_POOL);
1010                         parameters.add(SYMBOL_TABLE);
1011                         parameters.add(SEND_PSVI);
1012 
1013                         fRecognizedParameters = new DOMStringListImpl(parameters);
1014 
1015         }
1016 
1017         return fRecognizedParameters;
1018     }//getParameterNames
1019 
1020     //
1021     // Protected methods
1022     //
1023 
1024     /**
1025      * reset all components before parsing
1026      */
1027     protected void reset() throws XNIException {
1028 
1029         if (fValidationManager != null)
1030             fValidationManager.reset();
1031 
1032         int count = fComponents.size();
1033         for (int i = 0; i < count; i++) {
1034             XMLComponent c = (XMLComponent) fComponents.get(i);
1035             c.reset(this);
1036         }
1037 
1038     } // reset()
1039 
1040     /**
1041      * Check a property. If the property is known and supported, this method
1042      * simply returns. Otherwise, the appropriate exception is thrown.
1043      *
1044      * @param propertyId The unique identifier (URI) of the property
1045      *                   being set.
1046      * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
1047      *            requested feature is not known or supported.
1048      */
1049     protected PropertyState checkProperty(String propertyId)
1050         throws XMLConfigurationException {
1051 
1052         // special cases
1053         if (propertyId.startsWith(Constants.SAX_PROPERTY_PREFIX)) {
1054             final int suffixLength = propertyId.length() - Constants.SAX_PROPERTY_PREFIX.length();
1055 
1056             //
1057             // http://xml.org/sax/properties/xml-string
1058             // Value type: String
1059             // Access: read-only
1060             //   Get the literal string of characters associated with the
1061             //   current event.  If the parser recognises and supports this
1062             //   property but is not currently parsing text, it should return
1063             //   null (this is a good way to check for availability before the
1064             //   parse begins).
1065             //
1066             if (suffixLength == Constants.XML_STRING_PROPERTY.length() &&
1067                 propertyId.endsWith(Constants.XML_STRING_PROPERTY)) {
1068                 // REVISIT - we should probably ask xml-dev for a precise
1069                 // definition of what this is actually supposed to return, and
1070                 // in exactly which circumstances.
1071                 return PropertyState.NOT_SUPPORTED;
1072             }
1073         }
1074 
1075         // check property
1076         return super.checkProperty(propertyId);
1077 
1078     } // checkProperty(String)
1079 
1080 
1081     protected void addComponent(XMLComponent component) {
1082 
1083         // don't add a component more than once
1084         if (fComponents.contains(component)) {
1085             return;
1086         }
1087         fComponents.add(component);
1088 
1089         // register component's recognized features
1090         String[] recognizedFeatures = component.getRecognizedFeatures();
1091         addRecognizedFeatures(recognizedFeatures);
1092 
1093         // register component's recognized properties
1094         String[] recognizedProperties = component.getRecognizedProperties();
1095         addRecognizedProperties(recognizedProperties);
1096 
1097     } // addComponent(XMLComponent)
1098 
1099     protected ValidationManager createValidationManager(){
1100         return new ValidationManager();
1101     }
1102 
1103 } // class XMLParser