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