1 /*
2  * Copyright (c) 2011, 2017, Oracle and/or its affiliates. All rights reserved.
3  */
4 /*
5  * Licensed to the Apache Software Foundation (ASF) under one or more
6  * contributor license agreements.  See the NOTICE file distributed with
7  * this work for additional information regarding copyright ownership.
8  * The ASF licenses this file to You under the Apache License, Version 2.0
9  * (the "License"); you may not use this file except in compliance with
10  * the License.  You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  */
20 
21 package com.sun.org.apache.xerces.internal.parsers;
22 
23 import com.sun.org.apache.xerces.internal.dom.DOMErrorImpl;
24 import com.sun.org.apache.xerces.internal.dom.DOMMessageFormatter;
25 import com.sun.org.apache.xerces.internal.dom.DOMStringListImpl;
26 import com.sun.org.apache.xerces.internal.impl.Constants;
27 import com.sun.org.apache.xerces.internal.util.DOMEntityResolverWrapper;
28 import com.sun.org.apache.xerces.internal.util.DOMErrorHandlerWrapper;
29 import com.sun.org.apache.xerces.internal.util.DOMUtil;
30 import com.sun.org.apache.xerces.internal.util.SymbolTable;
31 import com.sun.org.apache.xerces.internal.util.XMLSymbols;
32 import com.sun.org.apache.xerces.internal.xni.Augmentations;
33 import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
34 import com.sun.org.apache.xerces.internal.xni.QName;
35 import com.sun.org.apache.xerces.internal.xni.XMLAttributes;
36 import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler;
37 import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler;
38 import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
39 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
40 import com.sun.org.apache.xerces.internal.xni.XMLResourceIdentifier;
41 import com.sun.org.apache.xerces.internal.xni.XMLString;
42 import com.sun.org.apache.xerces.internal.xni.XNIException;
43 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
44 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
45 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDContentModelSource;
46 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDSource;
47 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
48 import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
49 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
50 import com.sun.org.apache.xerces.internal.xni.parser.XMLParseException;
51 import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
52 import java.io.StringReader;
53 import java.util.ArrayList;
54 import java.util.List;
55 import java.util.Locale;
56 import java.util.Stack;
57 import java.util.StringTokenizer;
58 import org.w3c.dom.DOMConfiguration;
59 import org.w3c.dom.DOMError;
60 import org.w3c.dom.DOMErrorHandler;
61 import org.w3c.dom.DOMException;
62 import org.w3c.dom.DOMStringList;
63 import org.w3c.dom.Document;
64 import org.w3c.dom.Node;
65 import org.w3c.dom.ls.LSException;
66 import org.w3c.dom.ls.LSInput;
67 import org.w3c.dom.ls.LSParser;
68 import org.w3c.dom.ls.LSParserFilter;
69 import org.w3c.dom.ls.LSResourceResolver;
70 import org.xml.sax.SAXException;
71 
72 
73 /**
74  * This is Xerces DOM Builder class. It uses the abstract DOM
75  * parser with a document scanner, a dtd scanner, and a validator, as
76  * well as a grammar pool.
77  *
78  * @author Pavani Mukthipudi, Sun Microsystems Inc.
79  * @author Elena Litani, IBM
80  * @author Rahul Srivastava, Sun Microsystems Inc.
81  * @LastModified: Oct 2017
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      */
DOMParserImpl(XMLParserConfiguration config, String schemaType)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      */
DOMParserImpl(XMLParserConfiguration config)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      */
DOMParserImpl(SymbolTable symbolTable)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      */
DOMParserImpl(SymbolTable symbolTable, XMLGrammarPool grammarPool)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      */
reset()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 
getDomConfig()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      */
getFilter()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      */
setFilter(LSParserFilter filter)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      */
setParameter(String name, Object value)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      */
getParameter(String name)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 
canSetParameter(String name, Object value)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      */
getParameterNames()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      */
parseURI(String uri)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      */
parse(LSInput is)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 
restoreHandlers()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      */
parseWithContext(LSInput is, Node cnode, short action)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      */
dom2xmlInputSource(LSInput is)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      */
getAsync()1106     public boolean getAsync () {
1107         return false;
1108     }
1109 
1110     /**
1111      * @see org.w3c.dom.ls.LSParser#getBusy()
1112      */
getBusy()1113     public boolean getBusy () {
1114         return fBusy;
1115     }
1116 
1117     /**
1118      * @see org.w3c.dom.ls.LSParser#abort()
1119      */
abort()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      */
startElement(QName element, XMLAttributes attributes, Augmentations augs)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 
startDocument(XMLLocator locator, String encoding, NamespaceContext namespaceContext, Augmentations augs)1174         public void startDocument(XMLLocator locator, String encoding, NamespaceContext namespaceContext, Augmentations augs) throws XNIException {
1175             throw Abort.INSTANCE;
1176         }
1177 
xmlDecl(String version, String encoding, String standalone, Augmentations augs)1178         public void xmlDecl(String version, String encoding, String standalone, Augmentations augs) throws XNIException {
1179             throw Abort.INSTANCE;
1180         }
1181 
doctypeDecl(String rootElement, String publicId, String systemId, Augmentations augs)1182         public void doctypeDecl(String rootElement, String publicId, String systemId, Augmentations augs) throws XNIException {
1183             throw Abort.INSTANCE;
1184         }
1185 
comment(XMLString text, Augmentations augs)1186         public void comment(XMLString text, Augmentations augs) throws XNIException {
1187             throw Abort.INSTANCE;
1188         }
1189 
processingInstruction(String target, XMLString data, Augmentations augs)1190         public void processingInstruction(String target, XMLString data, Augmentations augs) throws XNIException {
1191             throw Abort.INSTANCE;
1192         }
1193 
startElement(QName element, XMLAttributes attributes, Augmentations augs)1194         public void startElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException {
1195             throw Abort.INSTANCE;
1196         }
1197 
emptyElement(QName element, XMLAttributes attributes, Augmentations augs)1198         public void emptyElement(QName element, XMLAttributes attributes, Augmentations augs) throws XNIException {
1199             throw Abort.INSTANCE;
1200         }
1201 
startGeneralEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augs)1202         public void startGeneralEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augs) throws XNIException {
1203             throw Abort.INSTANCE;
1204         }
1205 
textDecl(String version, String encoding, Augmentations augs)1206         public void textDecl(String version, String encoding, Augmentations augs) throws XNIException {
1207             throw Abort.INSTANCE;
1208         }
1209 
endGeneralEntity(String name, Augmentations augs)1210         public void endGeneralEntity(String name, Augmentations augs) throws XNIException {
1211             throw Abort.INSTANCE;
1212         }
1213 
characters(XMLString text, Augmentations augs)1214         public void characters(XMLString text, Augmentations augs) throws XNIException {
1215             throw Abort.INSTANCE;
1216         }
1217 
ignorableWhitespace(XMLString text, Augmentations augs)1218         public void ignorableWhitespace(XMLString text, Augmentations augs) throws XNIException {
1219             throw Abort.INSTANCE;
1220         }
1221 
endElement(QName element, Augmentations augs)1222         public void endElement(QName element, Augmentations augs) throws XNIException {
1223             throw Abort.INSTANCE;
1224         }
1225 
startCDATA(Augmentations augs)1226         public void startCDATA(Augmentations augs) throws XNIException {
1227             throw Abort.INSTANCE;
1228         }
1229 
endCDATA(Augmentations augs)1230         public void endCDATA(Augmentations augs) throws XNIException {
1231             throw Abort.INSTANCE;
1232         }
1233 
endDocument(Augmentations augs)1234         public void endDocument(Augmentations augs) throws XNIException {
1235             throw Abort.INSTANCE;
1236         }
1237 
setDocumentSource(XMLDocumentSource source)1238         public void setDocumentSource(XMLDocumentSource source) {
1239             documentSource = source;
1240         }
1241 
getDocumentSource()1242         public XMLDocumentSource getDocumentSource() {
1243             return documentSource;
1244         }
1245 
startDTD(XMLLocator locator, Augmentations augmentations)1246         public void startDTD(XMLLocator locator, Augmentations augmentations) throws XNIException {
1247             throw Abort.INSTANCE;
1248         }
1249 
startParameterEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augmentations)1250         public void startParameterEntity(String name, XMLResourceIdentifier identifier, String encoding, Augmentations augmentations) throws XNIException {
1251             throw Abort.INSTANCE;
1252         }
1253 
endParameterEntity(String name, Augmentations augmentations)1254         public void endParameterEntity(String name, Augmentations augmentations) throws XNIException {
1255             throw Abort.INSTANCE;
1256         }
1257 
startExternalSubset(XMLResourceIdentifier identifier, Augmentations augmentations)1258         public void startExternalSubset(XMLResourceIdentifier identifier, Augmentations augmentations) throws XNIException {
1259             throw Abort.INSTANCE;
1260         }
1261 
endExternalSubset(Augmentations augmentations)1262         public void endExternalSubset(Augmentations augmentations) throws XNIException {
1263             throw Abort.INSTANCE;
1264         }
1265 
elementDecl(String name, String contentModel, Augmentations augmentations)1266         public void elementDecl(String name, String contentModel, Augmentations augmentations) throws XNIException {
1267             throw Abort.INSTANCE;
1268         }
1269 
startAttlist(String elementName, Augmentations augmentations)1270         public void startAttlist(String elementName, Augmentations augmentations) throws XNIException {
1271             throw Abort.INSTANCE;
1272         }
1273 
attributeDecl(String elementName, String attributeName, String type, String[] enumeration, String defaultType, XMLString defaultValue, XMLString nonNormalizedDefaultValue, Augmentations augmentations)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 
endAttlist(Augmentations augmentations)1278         public void endAttlist(Augmentations augmentations) throws XNIException {
1279             throw Abort.INSTANCE;
1280         }
1281 
internalEntityDecl(String name, XMLString text, XMLString nonNormalizedText, Augmentations augmentations)1282         public void internalEntityDecl(String name, XMLString text, XMLString nonNormalizedText, Augmentations augmentations) throws XNIException {
1283             throw Abort.INSTANCE;
1284         }
1285 
externalEntityDecl(String name, XMLResourceIdentifier identifier, Augmentations augmentations)1286         public void externalEntityDecl(String name, XMLResourceIdentifier identifier, Augmentations augmentations) throws XNIException {
1287             throw Abort.INSTANCE;
1288         }
1289 
unparsedEntityDecl(String name, XMLResourceIdentifier identifier, String notation, Augmentations augmentations)1290         public void unparsedEntityDecl(String name, XMLResourceIdentifier identifier, String notation, Augmentations augmentations) throws XNIException {
1291             throw Abort.INSTANCE;
1292         }
1293 
notationDecl(String name, XMLResourceIdentifier identifier, Augmentations augmentations)1294         public void notationDecl(String name, XMLResourceIdentifier identifier, Augmentations augmentations) throws XNIException {
1295             throw Abort.INSTANCE;
1296         }
1297 
startConditional(short type, Augmentations augmentations)1298         public void startConditional(short type, Augmentations augmentations) throws XNIException {
1299             throw Abort.INSTANCE;
1300         }
1301 
ignoredCharacters(XMLString text, Augmentations augmentations)1302         public void ignoredCharacters(XMLString text, Augmentations augmentations) throws XNIException {
1303             throw Abort.INSTANCE;
1304         }
1305 
endConditional(Augmentations augmentations)1306         public void endConditional(Augmentations augmentations) throws XNIException {
1307             throw Abort.INSTANCE;
1308         }
1309 
endDTD(Augmentations augmentations)1310         public void endDTD(Augmentations augmentations) throws XNIException {
1311             throw Abort.INSTANCE;
1312         }
1313 
setDTDSource(XMLDTDSource source)1314         public void setDTDSource(XMLDTDSource source) {
1315             dtdSource = source;
1316         }
1317 
getDTDSource()1318         public XMLDTDSource getDTDSource() {
1319             return dtdSource;
1320         }
1321 
startContentModel(String elementName, Augmentations augmentations)1322         public void startContentModel(String elementName, Augmentations augmentations) throws XNIException {
1323             throw Abort.INSTANCE;
1324         }
1325 
any(Augmentations augmentations)1326         public void any(Augmentations augmentations) throws XNIException {
1327             throw Abort.INSTANCE;
1328         }
1329 
empty(Augmentations augmentations)1330         public void empty(Augmentations augmentations) throws XNIException {
1331             throw Abort.INSTANCE;
1332         }
1333 
startGroup(Augmentations augmentations)1334         public void startGroup(Augmentations augmentations) throws XNIException {
1335             throw Abort.INSTANCE;
1336         }
1337 
pcdata(Augmentations augmentations)1338         public void pcdata(Augmentations augmentations) throws XNIException {
1339             throw Abort.INSTANCE;
1340         }
1341 
element(String elementName, Augmentations augmentations)1342         public void element(String elementName, Augmentations augmentations) throws XNIException {
1343             throw Abort.INSTANCE;
1344         }
1345 
separator(short separator, Augmentations augmentations)1346         public void separator(short separator, Augmentations augmentations) throws XNIException {
1347             throw Abort.INSTANCE;
1348         }
1349 
occurrence(short occurrence, Augmentations augmentations)1350         public void occurrence(short occurrence, Augmentations augmentations) throws XNIException {
1351             throw Abort.INSTANCE;
1352         }
1353 
endGroup(Augmentations augmentations)1354         public void endGroup(Augmentations augmentations) throws XNIException {
1355             throw Abort.INSTANCE;
1356         }
1357 
endContentModel(Augmentations augmentations)1358         public void endContentModel(Augmentations augmentations) throws XNIException {
1359             throw Abort.INSTANCE;
1360         }
1361 
setDTDContentModelSource(XMLDTDContentModelSource source)1362         public void setDTDContentModelSource(XMLDTDContentModelSource source) {
1363             dtdContentSource = source;
1364         }
1365 
getDTDContentModelSource()1366         public XMLDTDContentModelSource getDTDContentModelSource() {
1367             return dtdContentSource;
1368         }
1369 
1370     }
1371 
newFeatureNotFoundError(String name)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 
newTypeMismatchError(String name)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
1391