1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 2000-2005 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.parsers;
  22 
  23 import java.io.StringReader;
  24 import java.util.Locale;
  25 import java.util.Stack;
  26 import java.util.StringTokenizer;
  27 import java.util.Vector;
  28 
  29 import com.sun.org.apache.xerces.internal.dom.DOMErrorImpl;
  30 import com.sun.org.apache.xerces.internal.dom.DOMMessageFormatter;
  31 import com.sun.org.apache.xerces.internal.dom.DOMStringListImpl;
  32 import com.sun.org.apache.xerces.internal.impl.Constants;
  33 import com.sun.org.apache.xerces.internal.util.DOMEntityResolverWrapper;
  34 import com.sun.org.apache.xerces.internal.util.DOMErrorHandlerWrapper;
  35 import com.sun.org.apache.xerces.internal.util.DOMUtil;
  36 import com.sun.org.apache.xerces.internal.util.SymbolTable;
  37 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
  38 import com.sun.org.apache.xerces.internal.xni.Augmentations;
  39 import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
  40 import com.sun.org.apache.xerces.internal.xni.QName;
  41 import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
  42 import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler;
  43 import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler;
  44 import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
  45 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
  46 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
  47 import com.sun.org.apache.xerces.internal.xni.XMLString;
  48 import com.sun.org.apache.xerces.internal.xni.XNIException;
  49 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
  50 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
  51 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDContentModelSource;
  52 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource;
  53 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
  54 import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
  55 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
  56 import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException;
  57 import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
  58 import com.sun.org.apache.xerces.internal.parsers.XIncludeAwareParserConfiguration;
  59 import org.w3c.dom.DOMConfiguration;
  60 import org.w3c.dom.DOMError;
  61 import org.w3c.dom.DOMErrorHandler;
  62 import org.w3c.dom.DOMException;
  63 import org.w3c.dom.DOMStringList;
  64 import org.w3c.dom.Document;
  65 import org.w3c.dom.Node;
  66 import org.w3c.dom.ls.LSException;
  67 import org.w3c.dom.ls.LSInput;
  68 import org.w3c.dom.ls.LSParser;
  69 import org.w3c.dom.ls.LSParserFilter;
  70 import org.w3c.dom.ls.LSResourceResolver;
  71 import org.xml.sax.SAXException;
  72 
  73 
  74 /**
  75  * This is Xerces DOM Builder class. It uses the abstract DOM
  76  * parser with a document scanner, a dtd scanner, and a validator, as
  77  * well as a grammar pool.
  78  *
  79  * @author Pavani Mukthipudi, Sun Microsystems Inc.
  80  * @author Elena Litani, IBM
  81  * @author Rahul Srivastava, Sun Microsystems Inc.
  82  * @version $Id: DOMParserImpl.java,v 1.8 2010-11-01 04:40:09 joehw Exp $
  83  */
  84 
  85 
  86 public class DOMParserImpl
  87 extends AbstractDOMParser implements LSParser, DOMConfiguration {
  88 
  89 
  90 
  91     // SAX & Xerces feature ids
  92 
  93     /** Feature identifier: namespaces. */
  94     protected static final String NAMESPACES =
  95     Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
  96 
  97     /** Feature id: validation. */
  98     protected static final String VALIDATION_FEATURE =
  99     Constants.SAX_FEATURE_PREFIX+Constants.VALIDATION_FEATURE;
 100 
 101     /** XML Schema validation */
 102     protected static final String XMLSCHEMA =
 103     Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
 104 
 105     /** XML Schema full checking */
 106     protected static final String XMLSCHEMA_FULL_CHECKING =
 107     Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING;
 108 
 109     /** Dynamic validation */
 110     protected static final String DYNAMIC_VALIDATION =
 111     Constants.XERCES_FEATURE_PREFIX + Constants.DYNAMIC_VALIDATION_FEATURE;
 112 
 113     /** Feature identifier: expose schema normalized value */
 114     protected static final String NORMALIZE_DATA =
 115     Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE;
 116 
 117     /** Feature identifier: disallow docType Decls. */
 118     protected static final String DISALLOW_DOCTYPE_DECL_FEATURE =
 119         Constants.XERCES_FEATURE_PREFIX + Constants.DISALLOW_DOCTYPE_DECL_FEATURE;
 120 
 121     /** Feature identifier: namespace growth */
 122     protected static final String NAMESPACE_GROWTH =
 123         Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE;
 124 
 125     /** Feature identifier: tolerate duplicates */
 126     protected static final String TOLERATE_DUPLICATES =
 127         Constants.XERCES_FEATURE_PREFIX + Constants.TOLERATE_DUPLICATES_FEATURE;
 128 
 129     // internal properties
 130     protected static final String SYMBOL_TABLE =
 131     Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
 132 
 133     protected static final String PSVI_AUGMENT =
 134     Constants.XERCES_FEATURE_PREFIX +Constants.SCHEMA_AUGMENT_PSVI;
 135 
 136 
 137     //
 138     // Data
 139     //
 140 
 141     /** Include namespace declaration attributes in the document. **/
 142     protected boolean fNamespaceDeclarations = true;
 143 
 144     // REVISIT: this value should be null by default and should be set during creation of
 145     //          LSParser
 146     protected String fSchemaType = null;
 147 
 148     protected boolean fBusy = false;
 149 
 150     private boolean abortNow = false;
 151 
 152     private Thread currentThread;
 153 
 154     protected final static boolean DEBUG = false;
 155 
 156     private Vector fSchemaLocations = new Vector ();
 157     private String fSchemaLocation = null;
 158         private DOMStringList fRecognizedParameters;
 159 
 160     private AbortHandler abortHandler = null;
 161 
 162     //
 163     // Constructors
 164     //
 165 
 166     /**
 167      * Constructs a DOM Builder using the standard parser configuration.
 168      */
 169     public DOMParserImpl (XMLParserConfiguration config, String schemaType) {
 170         this (config);
 171         if (schemaType != null) {
 172             if (schemaType.equals (Constants.NS_DTD)) {
 173                 //Schema validation is false by default and hence there is no
 174                 //need to set it to false here.  Also, schema validation is
 175                 //not a recognized feature for DTDConfiguration's and so
 176                 //setting this feature here would result in a Configuration
 177                 //Exception.
 178                 fConfiguration.setProperty (
 179                 Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE,
 180                 Constants.NS_DTD);
 181                 fSchemaType = Constants.NS_DTD;
 182             }
 183             else if (schemaType.equals (Constants.NS_XMLSCHEMA)) {
 184                 // XML Schem validation
 185                 fConfiguration.setProperty (
 186                 Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE,
 187                 Constants.NS_XMLSCHEMA);
 188             }
 189         }
 190 
 191     }
 192 
 193     /**
 194      * Constructs a DOM Builder using the specified parser configuration.
 195      */
 196     public DOMParserImpl (XMLParserConfiguration config) {
 197         super (config);
 198 
 199         // add recognized features
 200         final String[] domRecognizedFeatures = {
 201             Constants.DOM_CANONICAL_FORM,
 202             Constants.DOM_CDATA_SECTIONS,
 203             Constants.DOM_CHARSET_OVERRIDES_XML_ENCODING,
 204             Constants.DOM_INFOSET,
 205             Constants.DOM_NAMESPACE_DECLARATIONS,
 206             Constants.DOM_SPLIT_CDATA,
 207             Constants.DOM_SUPPORTED_MEDIATYPES_ONLY,
 208             Constants.DOM_CERTIFIED,
 209             Constants.DOM_WELLFORMED,
 210             Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS,
 211         };
 212 
 213         fConfiguration.addRecognizedFeatures (domRecognizedFeatures);
 214 
 215         // turn off deferred DOM
 216         fConfiguration.setFeature (DEFER_NODE_EXPANSION, false);
 217 
 218         // Set values so that the value of the
 219         // infoset parameter is true (its default value).
 220         //
 221         // true: namespace-declarations, well-formed,
 222         // element-content-whitespace, comments, namespaces
 223         //
 224         // false: validate-if-schema, entities,
 225         // datatype-normalization, cdata-sections
 226 
 227         fConfiguration.setFeature(Constants.DOM_NAMESPACE_DECLARATIONS, true);
 228         fConfiguration.setFeature(Constants.DOM_WELLFORMED, true);
 229         fConfiguration.setFeature(INCLUDE_COMMENTS_FEATURE, true);
 230         fConfiguration.setFeature(INCLUDE_IGNORABLE_WHITESPACE, true);
 231         fConfiguration.setFeature(NAMESPACES, true);
 232 
 233         fConfiguration.setFeature(DYNAMIC_VALIDATION, false);
 234         fConfiguration.setFeature(CREATE_ENTITY_REF_NODES, false);
 235         fConfiguration.setFeature(CREATE_CDATA_NODES_FEATURE, false);
 236 
 237         // set other default values
 238         fConfiguration.setFeature (Constants.DOM_CANONICAL_FORM, false);
 239         fConfiguration.setFeature (Constants.DOM_CHARSET_OVERRIDES_XML_ENCODING, true);
 240         fConfiguration.setFeature (Constants.DOM_SPLIT_CDATA, true);
 241         fConfiguration.setFeature (Constants.DOM_SUPPORTED_MEDIATYPES_ONLY, false);
 242         fConfiguration.setFeature (Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS, true);
 243 
 244         // REVISIT: by default Xerces assumes that input is certified.
 245         //          default is different from the one specified in the DOM spec
 246         fConfiguration.setFeature (Constants.DOM_CERTIFIED, true);
 247 
 248         // Xerces datatype-normalization feature is on by default
 249         // This is a recognized feature only for XML Schemas. If the
 250         // configuration doesn't support this feature, ignore it.
 251         try {
 252             fConfiguration.setFeature ( NORMALIZE_DATA, false );
 253         }
 254         catch (XMLConfigurationException exc) {}
 255 
 256     } // <init>(XMLParserConfiguration)
 257 
 258     /**
 259      * Constructs a DOM Builder using the specified symbol table.
 260      */
 261     public DOMParserImpl (SymbolTable symbolTable) {
 262         this (new XIncludeAwareParserConfiguration());
 263         fConfiguration.setProperty (
 264         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY,
 265         symbolTable);
 266     } // <init>(SymbolTable)
 267 
 268 
 269     /**
 270      * Constructs a DOM Builder using the specified symbol table and
 271      * grammar pool.
 272      */
 273     public DOMParserImpl (SymbolTable symbolTable, XMLGrammarPool grammarPool) {
 274         this (new XIncludeAwareParserConfiguration());
 275         fConfiguration.setProperty (
 276         Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY,
 277         symbolTable);
 278         fConfiguration.setProperty (
 279         Constants.XERCES_PROPERTY_PREFIX
 280         + Constants.XMLGRAMMAR_POOL_PROPERTY,
 281         grammarPool);
 282     }
 283 
 284     /**
 285      * Resets the parser state.
 286      *
 287      * @throws SAXException Thrown on initialization error.
 288      */
 289     public void reset () {
 290         super.reset ();
 291 
 292         // get state of namespace-declarations parameter.
 293         fNamespaceDeclarations =
 294             fConfiguration.getFeature(Constants.DOM_NAMESPACE_DECLARATIONS);
 295 
 296         // DOM Filter
 297         if (fSkippedElemStack!=null) {
 298             fSkippedElemStack.removeAllElements ();
 299         }
 300         fSchemaLocations.clear ();
 301         fRejectedElementDepth = 0;
 302         fFilterReject = false;
 303         fSchemaType = null;
 304 
 305     } // reset()
 306 
 307     //
 308     // DOMParser methods
 309     //
 310 
 311     public DOMConfiguration getDomConfig (){
 312         return this;
 313     }
 314 
 315 
 316     /**
 317      *  When the application provides a filter, the parser will call out to
 318      * the filter at the completion of the construction of each
 319      * <code>Element</code> node. The filter implementation can choose to
 320      * remove the element from the document being constructed (unless the
 321      * element is the document element) or to terminate the parse early. If
 322      * the document is being validated when it's loaded the validation
 323      * happens before the filter is called.
 324      */
 325     public LSParserFilter getFilter () {
 326         return fDOMFilter;
 327     }
 328 
 329     /**
 330      *  When the application provides a filter, the parser will call out to
 331      * the filter at the completion of the construction of each
 332      * <code>Element</code> node. The filter implementation can choose to
 333      * remove the element from the document being constructed (unless the
 334      * element is the document element) or to terminate the parse early. If
 335      * the document is being validated when it's loaded the validation
 336      * happens before the filter is called.
 337      */
 338     public void setFilter (LSParserFilter filter) {
 339         fDOMFilter = filter;
 340         if (fSkippedElemStack == null) {
 341             fSkippedElemStack = new Stack ();
 342         }
 343     }
 344 
 345     /**
 346      * Set parameters and properties
 347      */
 348     public void setParameter (String name, Object value) throws DOMException {
 349         // set features
 350 
 351         if(value instanceof Boolean){
 352             boolean state = ((Boolean)value).booleanValue ();
 353             try {
 354                 if (name.equalsIgnoreCase (Constants.DOM_COMMENTS)) {
 355                     fConfiguration.setFeature (INCLUDE_COMMENTS_FEATURE, state);
 356                 }
 357                 else if (name.equalsIgnoreCase (Constants.DOM_DATATYPE_NORMALIZATION)) {
 358                     fConfiguration.setFeature (NORMALIZE_DATA, state);
 359                 }
 360                 else if (name.equalsIgnoreCase (Constants.DOM_ENTITIES)) {
 361                     fConfiguration.setFeature (CREATE_ENTITY_REF_NODES, state);
 362                 }
 363                 else if (name.equalsIgnoreCase (Constants.DOM_DISALLOW_DOCTYPE)) {
 364                     fConfiguration.setFeature (DISALLOW_DOCTYPE_DECL_FEATURE, state);
 365                 }
 366                 else if (name.equalsIgnoreCase (Constants.DOM_SUPPORTED_MEDIATYPES_ONLY)
 367                 || name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)
 368                 || name.equalsIgnoreCase (Constants.DOM_CHECK_CHAR_NORMALIZATION)
 369                 || name.equalsIgnoreCase (Constants.DOM_CANONICAL_FORM)) {
 370                     if (state) { // true is not supported
 371                         String msg =
 372                         DOMMessageFormatter.formatMessage (
 373                         DOMMessageFormatter.DOM_DOMAIN,
 374                         "FEATURE_NOT_SUPPORTED",
 375                         new Object[] { name });
 376                         throw new DOMException (DOMException.NOT_SUPPORTED_ERR, msg);
 377                     }
 378                     // setting those features to false is no-op
 379                 }
 380                 else if (name.equalsIgnoreCase (Constants.DOM_NAMESPACES)) {
 381                     fConfiguration.setFeature (NAMESPACES, state);
 382                 }
 383                 else if (name.equalsIgnoreCase (Constants.DOM_INFOSET)) {
 384                     // Setting false has no effect.
 385                     if (state) {
 386                         // true: namespaces, namespace-declarations,
 387                         // comments, element-content-whitespace
 388                         fConfiguration.setFeature(NAMESPACES, true);
 389                         fConfiguration.setFeature(Constants.DOM_NAMESPACE_DECLARATIONS, true);
 390                         fConfiguration.setFeature(INCLUDE_COMMENTS_FEATURE, true);
 391                         fConfiguration.setFeature(INCLUDE_IGNORABLE_WHITESPACE, true);
 392 
 393                         // false: validate-if-schema, entities,
 394                         // datatype-normalization, cdata-sections
 395                         fConfiguration.setFeature(DYNAMIC_VALIDATION, false);
 396                         fConfiguration.setFeature(CREATE_ENTITY_REF_NODES, false);
 397                         fConfiguration.setFeature(NORMALIZE_DATA, false);
 398                         fConfiguration.setFeature(CREATE_CDATA_NODES_FEATURE, false);
 399                     }
 400                 }
 401                 else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)) {
 402                     fConfiguration.setFeature(CREATE_CDATA_NODES_FEATURE, state);
 403                 }
 404                 else if (name.equalsIgnoreCase (Constants.DOM_NAMESPACE_DECLARATIONS)) {
 405                     fConfiguration.setFeature(Constants.DOM_NAMESPACE_DECLARATIONS, state);
 406                 }
 407                 else if (name.equalsIgnoreCase (Constants.DOM_WELLFORMED)
 408                 || name.equalsIgnoreCase (Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) {
 409                     if (!state) { // false is not supported
 410                         String msg =
 411                         DOMMessageFormatter.formatMessage (
 412                         DOMMessageFormatter.DOM_DOMAIN,
 413                         "FEATURE_NOT_SUPPORTED",
 414                         new Object[] { name });
 415                         throw new DOMException (DOMException.NOT_SUPPORTED_ERR, msg);
 416                     }
 417                     // setting these features to true is no-op
 418                     // REVISIT: implement "namespace-declaration" feature
 419                 }
 420                 else if (name.equalsIgnoreCase (Constants.DOM_VALIDATE)) {
 421                     fConfiguration.setFeature (VALIDATION_FEATURE, state);
 422                     if (fSchemaType != Constants.NS_DTD) {
 423                         fConfiguration.setFeature (XMLSCHEMA, state);
 424                         fConfiguration.setFeature (XMLSCHEMA_FULL_CHECKING, state);
 425                     }
 426                     if (state){
 427                         fConfiguration.setFeature (DYNAMIC_VALIDATION, false);
 428                     }
 429                 }
 430                 else if (name.equalsIgnoreCase (Constants.DOM_VALIDATE_IF_SCHEMA)) {
 431                     fConfiguration.setFeature (DYNAMIC_VALIDATION, state);
 432                     // Note: validation and dynamic validation are mutually exclusive
 433                     if (state){
 434                         fConfiguration.setFeature (VALIDATION_FEATURE, false);
 435                     }
 436                 }
 437                 else if (name.equalsIgnoreCase (Constants.DOM_ELEMENT_CONTENT_WHITESPACE)) {
 438                     fConfiguration.setFeature (INCLUDE_IGNORABLE_WHITESPACE, state);
 439                 }
 440                 else if (name.equalsIgnoreCase (Constants.DOM_PSVI)){
 441                     //XSModel - turn on PSVI augmentation
 442                     fConfiguration.setFeature (PSVI_AUGMENT, true);
 443                     fConfiguration.setProperty (DOCUMENT_CLASS_NAME,
 444                     "com.sun.org.apache.xerces.internal.dom.PSVIDocumentImpl");
 445                 }
 446                 else {
 447                     // Constants.DOM_CHARSET_OVERRIDES_XML_ENCODING feature,
 448                     // Constants.DOM_SPLIT_CDATA feature,
 449                     // or any Xerces feature
 450                     String normalizedName;
 451                     if (name.equals(NAMESPACE_GROWTH)) {
 452                         normalizedName = NAMESPACE_GROWTH;
 453                     }
 454                     else if (name.equals(TOLERATE_DUPLICATES)) {
 455                         normalizedName = TOLERATE_DUPLICATES;
 456                     }
 457                     else {
 458                         normalizedName = name.toLowerCase(Locale.ENGLISH);
 459                     }
 460                     fConfiguration.setFeature (normalizedName, state);
 461                 }
 462 
 463             }
 464             catch (XMLConfigurationException e) {
 465                 String msg =
 466                 DOMMessageFormatter.formatMessage (
 467                 DOMMessageFormatter.DOM_DOMAIN,
 468                 "FEATURE_NOT_FOUND",
 469                 new Object[] { name });
 470                 throw new DOMException (DOMException.NOT_FOUND_ERR, msg);
 471             }
 472         }
 473         else { // set properties
 474             if (name.equalsIgnoreCase (Constants.DOM_ERROR_HANDLER)) {
 475                 if (value instanceof DOMErrorHandler || value == null) {
 476                     try {
 477                         fErrorHandler = new DOMErrorHandlerWrapper ((DOMErrorHandler) value);
 478                         fConfiguration.setProperty (ERROR_HANDLER, fErrorHandler);
 479                     }
 480                     catch (XMLConfigurationException e) {}
 481                 }
 482                 else {
 483                     // REVISIT: type mismatch
 484                     String msg =
 485                     DOMMessageFormatter.formatMessage (
 486                     DOMMessageFormatter.DOM_DOMAIN,
 487                     "TYPE_MISMATCH_ERR",
 488                     new Object[] { name });
 489                     throw new DOMException (DOMException.TYPE_MISMATCH_ERR, msg);
 490                 }
 491 
 492             }
 493             else if (name.equalsIgnoreCase (Constants.DOM_RESOURCE_RESOLVER)) {
 494                 if (value instanceof LSResourceResolver || value == null) {
 495                     try {
 496                         fConfiguration.setProperty (ENTITY_RESOLVER, new DOMEntityResolverWrapper ((LSResourceResolver) value));
 497                     }
 498                     catch (XMLConfigurationException e) {}
 499                 }
 500                 else {
 501                     // REVISIT: type mismatch
 502                     String msg =
 503                     DOMMessageFormatter.formatMessage (
 504                     DOMMessageFormatter.DOM_DOMAIN,
 505                     "TYPE_MISMATCH_ERR",
 506                     new Object[] { name });
 507                     throw new DOMException (DOMException.TYPE_MISMATCH_ERR, msg);
 508                 }
 509 
 510             }
 511             else if (name.equalsIgnoreCase (Constants.DOM_SCHEMA_LOCATION)) {
 512                 if (value instanceof String || value == null) {
 513                     try {
 514                         if (value == null) {
 515                             fSchemaLocation = null;
 516                             fConfiguration.setProperty (
 517                                 Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
 518                                 null);
 519                         }
 520                         else {
 521                             fSchemaLocation = (String)value;
 522                             // map DOM schema-location to JAXP schemaSource property
 523                             // tokenize location string
 524                             StringTokenizer t = new StringTokenizer (fSchemaLocation, " \n\t\r");
 525                             if (t.hasMoreTokens ()){
 526                                 fSchemaLocations.clear ();
 527                                 fSchemaLocations.add (t.nextToken ());
 528                                 while (t.hasMoreTokens ()) {
 529                                     fSchemaLocations.add (t.nextToken ());
 530                                 }
 531                                 fConfiguration.setProperty (
 532                                 Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
 533                                 fSchemaLocations.toArray ());
 534                             }
 535                             else {
 536                                 fConfiguration.setProperty (
 537                                 Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_SOURCE,
 538                                 value);
 539                             }
 540                         }
 541                     }
 542                     catch (XMLConfigurationException e) {}
 543                 }
 544                 else {
 545                     // REVISIT: type mismatch
 546                     String msg =
 547                     DOMMessageFormatter.formatMessage (
 548                     DOMMessageFormatter.DOM_DOMAIN,
 549                     "TYPE_MISMATCH_ERR",
 550                     new Object[] { name });
 551                     throw new DOMException (DOMException.TYPE_MISMATCH_ERR, msg);
 552                 }
 553 
 554             }
 555             else if (name.equalsIgnoreCase (Constants.DOM_SCHEMA_TYPE)) {
 556                 if (value instanceof String || value == null) {
 557                     try {
 558                         if (value == null) {
 559                             // turn off schema features
 560                             fConfiguration.setFeature (XMLSCHEMA, false);
 561                             fConfiguration.setFeature (XMLSCHEMA_FULL_CHECKING, false);
 562                             // map to JAXP schemaLanguage
 563                             fConfiguration.setProperty ( Constants.JAXP_PROPERTY_PREFIX
 564                             + Constants.SCHEMA_LANGUAGE,
 565                             null);
 566                             fSchemaType = null;
 567                         }
 568                         else if (value.equals (Constants.NS_XMLSCHEMA)) {
 569                             // turn on schema features
 570                             fConfiguration.setFeature (XMLSCHEMA, true);
 571                             fConfiguration.setFeature (XMLSCHEMA_FULL_CHECKING, true);
 572                             // map to JAXP schemaLanguage
 573                             fConfiguration.setProperty ( Constants.JAXP_PROPERTY_PREFIX
 574                             + Constants.SCHEMA_LANGUAGE,
 575                             Constants.NS_XMLSCHEMA);
 576                             fSchemaType = Constants.NS_XMLSCHEMA;
 577                         }
 578                         else if (value.equals (Constants.NS_DTD)) {
 579                             // turn off schema features
 580                             fConfiguration.setFeature (XMLSCHEMA, false);
 581                             fConfiguration.setFeature (XMLSCHEMA_FULL_CHECKING, false);
 582                             // map to JAXP schemaLanguage
 583                             fConfiguration.setProperty ( Constants.JAXP_PROPERTY_PREFIX
 584                             + Constants.SCHEMA_LANGUAGE,
 585                             Constants.NS_DTD);
 586                             fSchemaType = Constants.NS_DTD;
 587                         }
 588                     }
 589                     catch (XMLConfigurationException e) {}
 590                 }
 591                 else {
 592                     String msg =
 593                     DOMMessageFormatter.formatMessage (
 594                     DOMMessageFormatter.DOM_DOMAIN,
 595                     "TYPE_MISMATCH_ERR",
 596                     new Object[] { name });
 597                     throw new DOMException (DOMException.TYPE_MISMATCH_ERR, msg);
 598                 }
 599 
 600             }
 601             else if (name.equalsIgnoreCase (DOCUMENT_CLASS_NAME)) {
 602                 fConfiguration.setProperty (DOCUMENT_CLASS_NAME, value);
 603             }
 604             else {
 605                 // Try to set the property.
 606                 String normalizedName = name.toLowerCase(Locale.ENGLISH);
 607                 try {
 608                     fConfiguration.setProperty(normalizedName, value);
 609                     return;
 610                 }
 611                 catch (XMLConfigurationException e) {}
 612 
 613                 // If this is a boolean parameter a type mismatch should be thrown.
 614                 try {
 615                     if (name.equals(NAMESPACE_GROWTH)) {
 616                         normalizedName = NAMESPACE_GROWTH;
 617                     }
 618                     else if (name.equals(TOLERATE_DUPLICATES)) {
 619                         normalizedName = TOLERATE_DUPLICATES;
 620                     }
 621                     fConfiguration.getFeature(normalizedName);
 622                     throw newTypeMismatchError(name);
 623 
 624                 }
 625                 catch (XMLConfigurationException e) {}
 626 
 627                 // Parameter is not recognized
 628                 throw newFeatureNotFoundError(name);
 629             }
 630         }
 631     }
 632 
 633     /**
 634      * Look up the value of a feature or a property.
 635      */
 636     public Object getParameter (String name) throws DOMException {
 637         if (name.equalsIgnoreCase (Constants.DOM_COMMENTS)) {
 638             return (fConfiguration.getFeature (INCLUDE_COMMENTS_FEATURE))
 639             ? Boolean.TRUE
 640             : Boolean.FALSE;
 641         }
 642         else if (name.equalsIgnoreCase (Constants.DOM_DATATYPE_NORMALIZATION)) {
 643             return (fConfiguration.getFeature (NORMALIZE_DATA))
 644             ? Boolean.TRUE
 645             : Boolean.FALSE;
 646         }
 647         else if (name.equalsIgnoreCase (Constants.DOM_ENTITIES)) {
 648             return (fConfiguration.getFeature (CREATE_ENTITY_REF_NODES))
 649             ? Boolean.TRUE
 650             : Boolean.FALSE;
 651         }
 652         else if (name.equalsIgnoreCase (Constants.DOM_NAMESPACES)) {
 653             return (fConfiguration.getFeature (NAMESPACES))
 654             ? Boolean.TRUE
 655             : Boolean.FALSE;
 656         }
 657         else if (name.equalsIgnoreCase (Constants.DOM_VALIDATE)) {
 658             return (fConfiguration.getFeature (VALIDATION_FEATURE))
 659             ? Boolean.TRUE
 660             : Boolean.FALSE;
 661         }
 662         else if (name.equalsIgnoreCase (Constants.DOM_VALIDATE_IF_SCHEMA)) {
 663             return (fConfiguration.getFeature (DYNAMIC_VALIDATION))
 664             ? Boolean.TRUE
 665             : Boolean.FALSE;
 666         }
 667         else if (name.equalsIgnoreCase (Constants.DOM_ELEMENT_CONTENT_WHITESPACE)) {
 668             return (fConfiguration.getFeature (INCLUDE_IGNORABLE_WHITESPACE))
 669             ? Boolean.TRUE
 670             : Boolean.FALSE;
 671         }
 672         else if (name.equalsIgnoreCase (Constants.DOM_DISALLOW_DOCTYPE)) {
 673             return (fConfiguration.getFeature (DISALLOW_DOCTYPE_DECL_FEATURE))
 674             ? Boolean.TRUE
 675             : Boolean.FALSE;
 676         }
 677         else if (name.equalsIgnoreCase (Constants.DOM_INFOSET)) {
 678             // REVISIT: This is somewhat expensive to compute
 679             // but it's possible that the user has a reference
 680             // to the configuration and is changing the values
 681             // of these features directly on it.
 682             boolean infoset = fConfiguration.getFeature(NAMESPACES) &&
 683                 fConfiguration.getFeature(Constants.DOM_NAMESPACE_DECLARATIONS) &&
 684                 fConfiguration.getFeature(INCLUDE_COMMENTS_FEATURE) &&
 685                 fConfiguration.getFeature(INCLUDE_IGNORABLE_WHITESPACE) &&
 686                 !fConfiguration.getFeature(DYNAMIC_VALIDATION) &&
 687                 !fConfiguration.getFeature(CREATE_ENTITY_REF_NODES) &&
 688                 !fConfiguration.getFeature(NORMALIZE_DATA) &&
 689                 !fConfiguration.getFeature(CREATE_CDATA_NODES_FEATURE);
 690             return (infoset) ? Boolean.TRUE : Boolean.FALSE;
 691         }
 692         else if (name.equalsIgnoreCase(Constants.DOM_CDATA_SECTIONS)) {
 693             return (fConfiguration.getFeature(CREATE_CDATA_NODES_FEATURE))
 694                 ? Boolean.TRUE : Boolean.FALSE;
 695         }
 696         else if (name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION ) ||
 697                  name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)){
 698             return Boolean.FALSE;
 699         }
 700         else if (name.equalsIgnoreCase(Constants.DOM_NAMESPACE_DECLARATIONS)
 701         || name.equalsIgnoreCase (Constants.DOM_WELLFORMED)
 702         || name.equalsIgnoreCase (Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)
 703         || name.equalsIgnoreCase (Constants.DOM_CANONICAL_FORM)
 704         || name.equalsIgnoreCase (Constants.DOM_SUPPORTED_MEDIATYPES_ONLY)
 705         || name.equalsIgnoreCase (Constants.DOM_SPLIT_CDATA)
 706         || name.equalsIgnoreCase (Constants.DOM_CHARSET_OVERRIDES_XML_ENCODING)) {
 707             return (fConfiguration.getFeature (name.toLowerCase(Locale.ENGLISH)))
 708             ? Boolean.TRUE
 709             : Boolean.FALSE;
 710         }
 711         else if (name.equalsIgnoreCase (Constants.DOM_ERROR_HANDLER)) {
 712             if (fErrorHandler != null) {
 713                 return fErrorHandler.getErrorHandler ();
 714             }
 715             return null;
 716         }
 717         else if (name.equalsIgnoreCase (Constants.DOM_RESOURCE_RESOLVER)) {
 718             try {
 719                 XMLEntityResolver entityResolver =
 720                 (XMLEntityResolver) fConfiguration.getProperty (ENTITY_RESOLVER);
 721                 if (entityResolver != null
 722                 && entityResolver instanceof DOMEntityResolverWrapper) {
 723                     return ((DOMEntityResolverWrapper) entityResolver).getEntityResolver ();
 724                 }
 725                 return null;
 726             }
 727             catch (XMLConfigurationException e) {}
 728         }
 729         else if (name.equalsIgnoreCase (Constants.DOM_SCHEMA_TYPE)) {
 730             return fConfiguration.getProperty (
 731             Constants.JAXP_PROPERTY_PREFIX + Constants.SCHEMA_LANGUAGE);
 732         }
 733         else if (name.equalsIgnoreCase (Constants.DOM_SCHEMA_LOCATION)) {
 734             return fSchemaLocation;
 735         }
 736         else if (name.equalsIgnoreCase (SYMBOL_TABLE)){
 737             return fConfiguration.getProperty (SYMBOL_TABLE);
 738         }
 739         else if (name.equalsIgnoreCase (DOCUMENT_CLASS_NAME)) {
 740             return fConfiguration.getProperty (DOCUMENT_CLASS_NAME);
 741         }
 742         else {
 743             // This could be a recognized feature or property.
 744             String normalizedName;
 745 
 746             if (name.equals(NAMESPACE_GROWTH)) {
 747                 normalizedName = NAMESPACE_GROWTH;
 748             }
 749             else if (name.equals(TOLERATE_DUPLICATES)) {
 750                 normalizedName = TOLERATE_DUPLICATES;
 751             }
 752             else {
 753                 normalizedName = name.toLowerCase(Locale.ENGLISH);
 754             }
 755             try {
 756                 return fConfiguration.getFeature(normalizedName)
 757                     ? Boolean.TRUE : Boolean.FALSE;
 758             }
 759             catch (XMLConfigurationException e) {}
 760 
 761             // This isn't a feature; perhaps it's a property
 762             try {
 763                 return fConfiguration.getProperty(normalizedName);
 764             }
 765             catch (XMLConfigurationException e) {}
 766 
 767             throw newFeatureNotFoundError(name);
 768         }
 769         return null;
 770     }
 771 
 772     public boolean canSetParameter (String name, Object value) {
 773         if (value == null){
 774                 return true;
 775         }
 776 
 777         if(value instanceof Boolean){
 778             boolean state = ((Boolean)value).booleanValue ();
 779             if ( name.equalsIgnoreCase (Constants.DOM_SUPPORTED_MEDIATYPES_ONLY)
 780             || name.equalsIgnoreCase(Constants.DOM_NORMALIZE_CHARACTERS)
 781             || name.equalsIgnoreCase(Constants.DOM_CHECK_CHAR_NORMALIZATION )
 782             || name.equalsIgnoreCase (Constants.DOM_CANONICAL_FORM) ) {
 783                 // true is not supported
 784                 return (state) ? false : true;
 785             }
 786             else if (name.equalsIgnoreCase (Constants.DOM_WELLFORMED)
 787             || name.equalsIgnoreCase (Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS)) {
 788                 // false is not supported
 789                 return (state) ? true : false;
 790             }
 791             else if (name.equalsIgnoreCase (Constants.DOM_CDATA_SECTIONS)
 792             || name.equalsIgnoreCase (Constants.DOM_CHARSET_OVERRIDES_XML_ENCODING)
 793             || name.equalsIgnoreCase (Constants.DOM_COMMENTS)
 794             || name.equalsIgnoreCase (Constants.DOM_DATATYPE_NORMALIZATION)
 795             || name.equalsIgnoreCase (Constants.DOM_DISALLOW_DOCTYPE)
 796             || name.equalsIgnoreCase (Constants.DOM_ENTITIES)
 797             || name.equalsIgnoreCase (Constants.DOM_INFOSET)
 798             || name.equalsIgnoreCase (Constants.DOM_NAMESPACES)
 799             || name.equalsIgnoreCase (Constants.DOM_NAMESPACE_DECLARATIONS)
 800             || name.equalsIgnoreCase (Constants.DOM_VALIDATE)
 801             || name.equalsIgnoreCase (Constants.DOM_VALIDATE_IF_SCHEMA)
 802             || name.equalsIgnoreCase (Constants.DOM_ELEMENT_CONTENT_WHITESPACE)
 803             || name.equalsIgnoreCase (Constants.DOM_XMLDECL)) {
 804                 return true;
 805             }
 806 
 807             // Recognize Xerces features.
 808             try {
 809                 String normalizedName;
 810                 if (name.equalsIgnoreCase(NAMESPACE_GROWTH)) {
 811                     normalizedName = NAMESPACE_GROWTH;
 812                 }
 813                 else if (name.equalsIgnoreCase(TOLERATE_DUPLICATES)) {
 814                     normalizedName = TOLERATE_DUPLICATES;
 815                 }
 816                 else {
 817                     normalizedName = name.toLowerCase(Locale.ENGLISH);
 818                 }
 819                 fConfiguration.getFeature(normalizedName);
 820                 return true;
 821             }
 822             catch (XMLConfigurationException e) {
 823                 return false;
 824             }
 825         }
 826         else { // check properties
 827             if (name.equalsIgnoreCase (Constants.DOM_ERROR_HANDLER)) {
 828                 if (value instanceof DOMErrorHandler || value == null) {
 829                     return true;
 830                 }
 831                 return false;
 832             }
 833             else if (name.equalsIgnoreCase (Constants.DOM_RESOURCE_RESOLVER)) {
 834                 if (value instanceof LSResourceResolver || value == null) {
 835                     return true;
 836                 }
 837                 return false;
 838             }
 839             else if (name.equalsIgnoreCase (Constants.DOM_SCHEMA_TYPE)) {
 840                 if ((value instanceof String
 841                 && (value.equals (Constants.NS_XMLSCHEMA)
 842                 || value.equals (Constants.NS_DTD))) || value == null) {
 843                     return true;
 844                 }
 845                 return false;
 846             }
 847             else if (name.equalsIgnoreCase (Constants.DOM_SCHEMA_LOCATION)) {
 848                 if (value instanceof String || value == null)
 849                     return true;
 850                 return false;
 851             }
 852             else if (name.equalsIgnoreCase (DOCUMENT_CLASS_NAME)){
 853                 return true;
 854             }
 855             return false;
 856         }
 857     }
 858 
 859     /**
 860      *  DOM Level 3 CR - Experimental.
 861      *
 862      *  The list of the parameters supported by this
 863      * <code>DOMConfiguration</code> object and for which at least one value
 864      * can be set by the application. Note that this list can also contain
 865      * parameter names defined outside this specification.
 866      */
 867     public DOMStringList getParameterNames () {
 868         if (fRecognizedParameters == null){
 869             Vector parameters = new Vector();
 870 
 871             // REVISIT: add Xerces recognized properties/features
 872             parameters.add(Constants.DOM_NAMESPACES);
 873             parameters.add(Constants.DOM_CDATA_SECTIONS);
 874             parameters.add(Constants.DOM_CANONICAL_FORM);
 875             parameters.add(Constants.DOM_NAMESPACE_DECLARATIONS);
 876             parameters.add(Constants.DOM_SPLIT_CDATA);
 877 
 878             parameters.add(Constants.DOM_ENTITIES);
 879             parameters.add(Constants.DOM_VALIDATE_IF_SCHEMA);
 880             parameters.add(Constants.DOM_VALIDATE);
 881             parameters.add(Constants.DOM_DATATYPE_NORMALIZATION);
 882 
 883             parameters.add(Constants.DOM_CHARSET_OVERRIDES_XML_ENCODING);
 884             parameters.add(Constants.DOM_CHECK_CHAR_NORMALIZATION);
 885             parameters.add(Constants.DOM_SUPPORTED_MEDIATYPES_ONLY);
 886             parameters.add(Constants.DOM_IGNORE_UNKNOWN_CHARACTER_DENORMALIZATIONS);
 887 
 888             parameters.add(Constants.DOM_NORMALIZE_CHARACTERS);
 889             parameters.add(Constants.DOM_WELLFORMED);
 890             parameters.add(Constants.DOM_INFOSET);
 891             parameters.add(Constants.DOM_DISALLOW_DOCTYPE);
 892             parameters.add(Constants.DOM_ELEMENT_CONTENT_WHITESPACE);
 893             parameters.add(Constants.DOM_COMMENTS);
 894 
 895             parameters.add(Constants.DOM_ERROR_HANDLER);
 896             parameters.add(Constants.DOM_RESOURCE_RESOLVER);
 897             parameters.add(Constants.DOM_SCHEMA_LOCATION);
 898             parameters.add(Constants.DOM_SCHEMA_TYPE);
 899 
 900             fRecognizedParameters = new DOMStringListImpl(parameters);
 901 
 902         }
 903 
 904         return fRecognizedParameters;
 905     }
 906 
 907     /**
 908      * Parse an XML document from a location identified by an URI reference.
 909      * If the URI contains a fragment identifier (see section 4.1 in ), the
 910      * behavior is not defined by this specification.
 911      *
 912      */
 913     public Document parseURI (String uri) throws LSException {
 914 
 915         //If DOMParser insstance is already busy parsing another document when this
 916         // method is called, then raise INVALID_STATE_ERR according to DOM L3 LS spec
 917         if ( fBusy ) {
 918             String msg = DOMMessageFormatter.formatMessage (
 919             DOMMessageFormatter.DOM_DOMAIN,
 920             "INVALID_STATE_ERR",null);
 921             throw new DOMException ( DOMException.INVALID_STATE_ERR,msg);
 922         }
 923 
 924         XMLInputSource source = new XMLInputSource (null, uri, null);
 925         try {
 926             currentThread = Thread.currentThread();
 927                         fBusy = true;
 928             parse (source);
 929             fBusy = false;
 930             if (abortNow && currentThread.isInterrupted()) {
 931                 //reset interrupt state
 932                 abortNow = false;
 933                 Thread.interrupted();
 934             }
 935         } catch (Exception e){
 936             fBusy = false;
 937             if (abortNow && currentThread.isInterrupted()) {
 938                 Thread.interrupted();
 939             }
 940             if (abortNow) {
 941                 abortNow = false;
 942                 restoreHandlers();
 943                 return null;
 944             }
 945             // Consume this exception if the user
 946             // issued an interrupt or an abort.
 947             if (e != Abort.INSTANCE) {
 948                 if (!(e instanceof XMLParseException) && fErrorHandler != null) {
 949                     DOMErrorImpl error = new DOMErrorImpl ();
 950                     error.fException = e;
 951                     error.fMessage = e.getMessage ();
 952                     error.fSeverity = DOMError.SEVERITY_FATAL_ERROR;
 953                     fErrorHandler.getErrorHandler ().handleError (error);
 954                 }
 955                 if (DEBUG) {
 956                     e.printStackTrace ();
 957                 }
 958                 throw (LSException) DOMUtil.createLSException(LSException.PARSE_ERR, e).fillInStackTrace();
 959             }
 960         }
 961         Document doc = getDocument();
 962         dropDocumentReferences();
 963         return doc;
 964     }
 965 
 966     /**
 967      * Parse an XML document from a resource identified by an
 968      * <code>LSInput</code>.
 969      *
 970      */
 971     public Document parse (LSInput is) throws LSException {
 972 
 973         // need to wrap the LSInput with an XMLInputSource
 974         XMLInputSource xmlInputSource = dom2xmlInputSource (is);
 975         if ( fBusy ) {
 976             String msg = DOMMessageFormatter.formatMessage (
 977             DOMMessageFormatter.DOM_DOMAIN,
 978             "INVALID_STATE_ERR",null);
 979             throw new DOMException ( DOMException.INVALID_STATE_ERR,msg);
 980         }
 981 
 982         try {
 983             currentThread = Thread.currentThread();
 984                         fBusy = true;
 985             parse (xmlInputSource);
 986             fBusy = false;
 987             if (abortNow && currentThread.isInterrupted()) {
 988                 //reset interrupt state
 989                 abortNow = false;
 990                 Thread.interrupted();
 991             }
 992         } catch (Exception e) {
 993             fBusy = false;
 994             if (abortNow && currentThread.isInterrupted()) {
 995                 Thread.interrupted();
 996             }
 997             if (abortNow) {
 998                 abortNow = false;
 999                 restoreHandlers();
1000                 return null;
1001             }
1002             // Consume this exception if the user
1003             // issued an interrupt or an abort.
1004             if (e != Abort.INSTANCE) {
1005                 if (!(e instanceof XMLParseException) && fErrorHandler != null) {
1006                    DOMErrorImpl error = new DOMErrorImpl ();
1007                    error.fException = e;
1008                    error.fMessage = e.getMessage ();
1009                    error.fSeverity = DOMError.SEVERITY_FATAL_ERROR;
1010                    fErrorHandler.getErrorHandler().handleError (error);
1011                 }
1012                 if (DEBUG) {
1013                    e.printStackTrace ();
1014                 }
1015                 throw (LSException) DOMUtil.createLSException(LSException.PARSE_ERR, e).fillInStackTrace();
1016             }
1017         }
1018         Document doc = getDocument();
1019         dropDocumentReferences();
1020         return doc;
1021     }
1022 
1023 
1024     private void restoreHandlers() {
1025         fConfiguration.setDocumentHandler(this);
1026         fConfiguration.setDTDHandler(this);
1027         fConfiguration.setDTDContentModelHandler(this);
1028     }
1029 
1030     /**
1031      *  Parse an XML document or fragment from a resource identified by an
1032      * <code>LSInput</code> and insert the content into an existing
1033      * document at the position epcified with the <code>contextNode</code>
1034      * and <code>action</code> arguments. When parsing the input stream the
1035      * context node is used for resolving unbound namespace prefixes.
1036      *
1037      * @param is  The <code>LSInput</code> from which the source
1038      *   document is to be read.
1039      * @param cnode  The <code>Node</code> that is used as the context for
1040      *   the data that is being parsed.
1041      * @param action This parameter describes which action should be taken
1042      *   between the new set of node being inserted and the existing
1043      *   children of the context node. The set of possible actions is
1044      *   defined above.
1045      * @exception DOMException
1046      *   HIERARCHY_REQUEST_ERR: Thrown if this action results in an invalid
1047      *   hierarchy (i.e. a Document with more than one document element).
1048      */
1049     public Node parseWithContext (LSInput is, Node cnode,
1050     short action) throws DOMException, LSException {
1051         // REVISIT: need to implement.
1052         throw new DOMException (DOMException.NOT_SUPPORTED_ERR, "Not supported");
1053     }
1054 
1055 
1056     /**
1057      * NON-DOM: convert LSInput to XNIInputSource
1058      *
1059      * @param is
1060      * @return
1061      */
1062     XMLInputSource dom2xmlInputSource (LSInput is) {
1063         // need to wrap the LSInput with an XMLInputSource
1064         XMLInputSource xis = null;
1065         // check whether there is a Reader
1066         // according to DOM, we need to treat such reader as "UTF-16".
1067         if (is.getCharacterStream () != null) {
1068             xis = new XMLInputSource (is.getPublicId (), is.getSystemId (),
1069             is.getBaseURI (), is.getCharacterStream (),
1070             "UTF-16");
1071         }
1072         // check whether there is an InputStream
1073         else if (is.getByteStream () != null) {
1074             xis = new XMLInputSource (is.getPublicId (), is.getSystemId (),
1075             is.getBaseURI (), is.getByteStream (),
1076             is.getEncoding ());
1077         }
1078         // if there is a string data, use a StringReader
1079         // according to DOM, we need to treat such data as "UTF-16".
1080         else if (is.getStringData () != null && is.getStringData().length() > 0) {
1081             xis = new XMLInputSource (is.getPublicId (), is.getSystemId (),
1082             is.getBaseURI (), new StringReader (is.getStringData ()),
1083             "UTF-16");
1084         }
1085         // otherwise, just use the public/system/base Ids
1086         else if ((is.getSystemId() != null && is.getSystemId().length() > 0) ||
1087             (is.getPublicId() != null && is.getPublicId().length() > 0)) {
1088             xis = new XMLInputSource (is.getPublicId (), is.getSystemId (),
1089             is.getBaseURI ());
1090         }
1091         else {
1092             // all inputs are null
1093             if (fErrorHandler != null) {
1094                 DOMErrorImpl error = new DOMErrorImpl();
1095                 error.fType = "no-input-specified";
1096                 error.fMessage = "no-input-specified";
1097                 error.fSeverity = DOMError.SEVERITY_FATAL_ERROR;
1098                 fErrorHandler.getErrorHandler().handleError(error);
1099             }
1100             throw new LSException(LSException.PARSE_ERR, "no-input-specified");
1101         }
1102         return xis;
1103     }
1104 
1105     /**
1106      * @see org.w3c.dom.ls.LSParser#getAsync()
1107      */
1108     public boolean getAsync () {
1109         return false;
1110     }
1111 
1112     /**
1113      * @see org.w3c.dom.ls.LSParser#getBusy()
1114      */
1115     public boolean getBusy () {
1116         return fBusy;
1117     }
1118 
1119     /**
1120      * @see org.w3c.dom.ls.DOMParser#abort()
1121      */
1122     public void abort () {
1123         // If parse operation is in progress then reset it
1124         if ( fBusy ) {
1125             fBusy = false;
1126             if(currentThread != null) {
1127                 abortNow = true;
1128                 if (abortHandler == null) {
1129                     abortHandler = new AbortHandler();
1130                 }
1131                 fConfiguration.setDocumentHandler(abortHandler);
1132                 fConfiguration.setDTDHandler(abortHandler);
1133                 fConfiguration.setDTDContentModelHandler(abortHandler);
1134 
1135                 if(currentThread == Thread.currentThread())
1136                     throw Abort.INSTANCE;
1137 
1138                 currentThread.interrupt();
1139             }
1140         }
1141         return; // If not busy then this is noop
1142     }
1143 
1144     /**
1145      * The start of an element. If the document specifies the start element
1146      * by using an empty tag, then the startElement method will immediately
1147      * be followed by the endElement method, with no intervening methods.
1148      * Overriding the parent to handle DOM_NAMESPACE_DECLARATIONS=false.
1149      *
1150      * @param element    The name of the element.
1151      * @param attributes The element attributes.
1152      * @param augs     Additional information that may include infoset augmentations
1153      *
1154      * @throws XNIException Thrown by handler to signal an error.
1155      */
1156     public void startElement (QName element, XMLAttributes attributes, Augmentations augs) {
1157         // namespace declarations parameter has no effect if namespaces is false.
1158         if (!fNamespaceDeclarations && fNamespaceAware) {
1159             int len = attributes.getLength();
1160             for (int i = len - 1; i >= 0; --i) {
1161                 if (XMLSymbols.PREFIX_XMLNS == attributes.getPrefix(i) ||
1162                     XMLSymbols.PREFIX_XMLNS == attributes.getQName(i)) {
1163                     attributes.removeAttributeAt(i);
1164                 }
1165             }
1166         }
1167         super.startElement(element, attributes, augs);
1168     }
1169 
1170     private class AbortHandler implements XMLDocumentHandler, XMLDTDHandler, XMLDTDContentModelHandler  {
1171 
1172         private XMLDocumentSource documentSource;
1173         private XMLDTDContentModelSource dtdContentSource;
1174         private XMLDTDSource dtdSource;
1175 
1176         public void startDocument(XMLLocator locator, String encoding, NamespaceContext namespaceContext, Augmentations augs) throws XNIException {
1177             throw Abort.INSTANCE;
1178         }
1179 
1180         public void xmlDecl(String version, String encoding, String standalone, Augmentations augs) throws XNIException {
1181             throw Abort.INSTANCE;
1182         }
1183 
1184         public void doctypeDecl(String rootElement, String publicId, String systemId, Augmentations augs) throws XNIException {
1185             throw Abort.INSTANCE;
1186         }
1187 
1188         public void comment(XMLString text, Augmentations augs) throws XNIException {
1189             throw Abort.INSTANCE;
1190         }
1191 
1192         public void processingInstruction(String target, XMLString data, Augmentations augs) throws XNIException {
1193             throw Abort.INSTANCE;
1194         }
1195 
1196         public void startElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException {
1197             throw Abort.INSTANCE;
1198         }
1199 
1200         public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException {
1201             throw Abort.INSTANCE;
1202         }
1203 
1204         public void startGeneralEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augs) throws XNIException {
1205             throw Abort.INSTANCE;
1206         }
1207 
1208         public void textDecl(String version, String encoding, Augmentations augs) throws XNIException {
1209             throw Abort.INSTANCE;
1210         }
1211 
1212         public void endGeneralEntity(String name, Augmentations augs) throws XNIException {
1213             throw Abort.INSTANCE;
1214         }
1215 
1216         public void characters(XMLString text, Augmentations augs) throws XNIException {
1217             throw Abort.INSTANCE;
1218         }
1219 
1220         public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
1221             throw Abort.INSTANCE;
1222         }
1223 
1224         public void endElement(QName element, Augmentations augs) throws XNIException {
1225             throw Abort.INSTANCE;
1226         }
1227 
1228         public void startCDATA(Augmentations augs) throws XNIException {
1229             throw Abort.INSTANCE;
1230         }
1231 
1232         public void endCDATA(Augmentations augs) throws XNIException {
1233             throw Abort.INSTANCE;
1234         }
1235 
1236         public void endDocument(Augmentations augs) throws XNIException {
1237             throw Abort.INSTANCE;
1238         }
1239 
1240         public void setDocumentSource(XMLDocumentSource source) {
1241             documentSource = source;
1242         }
1243 
1244         public XMLDocumentSource getDocumentSource() {
1245             return documentSource;
1246         }
1247 
1248         public void startDTD(XMLLocator locator, Augmentations augmentations) throws XNIException {
1249             throw Abort.INSTANCE;
1250         }
1251 
1252         public void startParameterEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augmentations) throws XNIException {
1253             throw Abort.INSTANCE;
1254         }
1255 
1256         public void endParameterEntity(String name, Augmentations augmentations) throws XNIException {
1257             throw Abort.INSTANCE;
1258         }
1259 
1260         public void startExternalSubset(XMLResourceIdentifier identifier, Augmentations augmentations) throws XNIException {
1261             throw Abort.INSTANCE;
1262         }
1263 
1264         public void endExternalSubset(Augmentations augmentations) throws XNIException {
1265             throw Abort.INSTANCE;
1266         }
1267 
1268         public void elementDecl(String name, String contentModel, Augmentations augmentations) throws XNIException {
1269             throw Abort.INSTANCE;
1270         }
1271 
1272         public void startAttlist(String elementName, Augmentations augmentations) throws XNIException {
1273             throw Abort.INSTANCE;
1274         }
1275 
1276         public void attributeDecl(String elementName, String attributeName, String type, String[] enumeration, String defaultType, XMLString defaultValue, XMLString nonNormalizedDefaultValue, Augmentations augmentations) throws XNIException {
1277             throw Abort.INSTANCE;
1278         }
1279 
1280         public void endAttlist(Augmentations augmentations) throws XNIException {
1281             throw Abort.INSTANCE;
1282         }
1283 
1284         public void internalEntityDecl(String name, XMLString text, XMLString nonNormalizedText, Augmentations augmentations) throws XNIException {
1285             throw Abort.INSTANCE;
1286         }
1287 
1288         public void externalEntityDecl(String name, XMLResourceIdentifier identifier, Augmentations augmentations) throws XNIException {
1289             throw Abort.INSTANCE;
1290         }
1291 
1292         public void unparsedEntityDecl(String name, XMLResourceIdentifier identifier, String notation, Augmentations augmentations) throws XNIException {
1293             throw Abort.INSTANCE;
1294         }
1295 
1296         public void notationDecl(String name, XMLResourceIdentifier identifier, Augmentations augmentations) throws XNIException {
1297             throw Abort.INSTANCE;
1298         }
1299 
1300         public void startConditional(short type, Augmentations augmentations) throws XNIException {
1301             throw Abort.INSTANCE;
1302         }
1303 
1304         public void ignoredCharacters(XMLString text, Augmentations augmentations) throws XNIException {
1305             throw Abort.INSTANCE;
1306         }
1307 
1308         public void endConditional(Augmentations augmentations) throws XNIException {
1309             throw Abort.INSTANCE;
1310         }
1311 
1312         public void endDTD(Augmentations augmentations) throws XNIException {
1313             throw Abort.INSTANCE;
1314         }
1315 
1316         public void setDTDSource(XMLDTDSource source) {
1317             dtdSource = source;
1318         }
1319 
1320         public XMLDTDSource getDTDSource() {
1321             return dtdSource;
1322         }
1323 
1324         public void startContentModel(String elementName, Augmentations augmentations) throws XNIException {
1325             throw Abort.INSTANCE;
1326         }
1327 
1328         public void any(Augmentations augmentations) throws XNIException {
1329             throw Abort.INSTANCE;
1330         }
1331 
1332         public void empty(Augmentations augmentations) throws XNIException {
1333             throw Abort.INSTANCE;
1334         }
1335 
1336         public void startGroup(Augmentations augmentations) throws XNIException {
1337             throw Abort.INSTANCE;
1338         }
1339 
1340         public void pcdata(Augmentations augmentations) throws XNIException {
1341             throw Abort.INSTANCE;
1342         }
1343 
1344         public void element(String elementName, Augmentations augmentations) throws XNIException {
1345             throw Abort.INSTANCE;
1346         }
1347 
1348         public void separator(short separator, Augmentations augmentations) throws XNIException {
1349             throw Abort.INSTANCE;
1350         }
1351 
1352         public void occurrence(short occurrence, Augmentations augmentations) throws XNIException {
1353             throw Abort.INSTANCE;
1354         }
1355 
1356         public void endGroup(Augmentations augmentations) throws XNIException {
1357             throw Abort.INSTANCE;
1358         }
1359 
1360         public void endContentModel(Augmentations augmentations) throws XNIException {
1361             throw Abort.INSTANCE;
1362         }
1363 
1364         public void setDTDContentModelSource(XMLDTDContentModelSource source) {
1365             dtdContentSource = source;
1366         }
1367 
1368         public XMLDTDContentModelSource getDTDContentModelSource() {
1369             return dtdContentSource;
1370         }
1371 
1372     }
1373 
1374     private static DOMException newFeatureNotFoundError(String name) {
1375         String msg =
1376             DOMMessageFormatter.formatMessage (
1377                     DOMMessageFormatter.DOM_DOMAIN,
1378                     "FEATURE_NOT_FOUND",
1379                     new Object[] { name });
1380         return new DOMException (DOMException.NOT_FOUND_ERR, msg);
1381     }
1382 
1383     private static DOMException newTypeMismatchError(String name) {
1384         String msg =
1385             DOMMessageFormatter.formatMessage (
1386                     DOMMessageFormatter.DOM_DOMAIN,
1387                     "TYPE_MISMATCH_ERR",
1388                     new Object[] { name });
1389         return new DOMException (DOMException.TYPE_MISMATCH_ERR, msg);
1390     }
1391 
1392 } // class DOMParserImpl