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