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