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