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