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