1 /*
2  * Copyright (c) 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.impl.Constants;
24 import com.sun.org.apache.xerces.internal.impl.XML11DTDScannerImpl;
25 import com.sun.org.apache.xerces.internal.impl.XML11DocumentScannerImpl;
26 import com.sun.org.apache.xerces.internal.impl.XML11NSDocumentScannerImpl;
27 import com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl;
28 import com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl;
29 import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler;
30 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
31 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
32 import com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl;
33 import com.sun.org.apache.xerces.internal.impl.XMLVersionDetector;
34 import com.sun.org.apache.xerces.internal.impl.dv.DTDDVFactory;
35 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
36 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
37 import com.sun.org.apache.xerces.internal.util.FeatureState;
38 import com.sun.org.apache.xerces.internal.util.ParserConfigurationSettings;
39 import com.sun.org.apache.xerces.internal.util.PropertyState;
40 import com.sun.org.apache.xerces.internal.util.Status;
41 import com.sun.org.apache.xerces.internal.util.SymbolTable;
42 import com.sun.org.apache.xerces.internal.xni.XMLDTDContentModelHandler;
43 import com.sun.org.apache.xerces.internal.xni.XMLDTDHandler;
44 import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
45 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
46 import com.sun.org.apache.xerces.internal.xni.XNIException;
47 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
48 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
49 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
50 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
51 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDScanner;
52 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentScanner;
53 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
54 import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
55 import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler;
56 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
57 import com.sun.org.apache.xerces.internal.xni.parser.XMLPullParserConfiguration;
58 import java.io.IOException;
59 import java.util.ArrayList;
60 import java.util.HashMap;
61 import java.util.List;
62 import java.util.Locale;
63 
64 /**
65  * This class is the non vlaidating parser configuration
66  * used to parse XML 1.0 and XML 1.1 documents.
67  *
68  * Xerces parser that uses this configuration is <strong>not</strong>
69  * <a href="http://www.w3.org/TR/REC-xml#sec-conformance">conformant</a>
70  * non-validating XML processor, since conformant non-validating processor is
71  * required to process "all the declarations they read in the internal DTD subset
72  * ... must use the information in those declarations to normalize attribute values,
73  * include the replacement text of internal entities, and supply default attribute values".
74 
75  * @author Elena Litani, IBM
76  * @author John Kim, IBM
77  * @author Michael Glavassevich, IBM
78  *
79  * @LastModified: Oct 2017
80  */
81 public class XML11NonValidatingConfiguration extends ParserConfigurationSettings
82     implements XMLPullParserConfiguration, XML11Configurable {
83 
84     //
85     // Constants
86     //
87     protected final static String XML11_DATATYPE_VALIDATOR_FACTORY =
88         "com.sun.org.apache.xerces.internal.impl.dv.dtd.XML11DTDDVFactoryImpl";
89 
90     // feature identifiers
91 
92     /** Feature identifier: validation. */
93     protected static final String VALIDATION =
94         Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
95 
96     /** Feature identifier: namespaces. */
97     protected static final String NAMESPACES =
98         Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
99 
100     /** Feature identifier: external general entities. */
101     protected static final String EXTERNAL_GENERAL_ENTITIES =
102         Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_GENERAL_ENTITIES_FEATURE;
103 
104     /** Feature identifier: external parameter entities. */
105     protected static final String EXTERNAL_PARAMETER_ENTITIES =
106         Constants.SAX_FEATURE_PREFIX + Constants.EXTERNAL_PARAMETER_ENTITIES_FEATURE;
107 
108 
109     /** Feature identifier: continue after fatal error. */
110     protected static final String CONTINUE_AFTER_FATAL_ERROR =
111         Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
112 
113 
114     // property identifiers
115 
116         /** Property identifier: xml string. */
117         protected static final String XML_STRING =
118                 Constants.SAX_PROPERTY_PREFIX + Constants.XML_STRING_PROPERTY;
119 
120         /** Property identifier: symbol table. */
121         protected static final String SYMBOL_TABLE =
122                 Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
123 
124         /** Property identifier: error handler. */
125         protected static final String ERROR_HANDLER =
126                 Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
127 
128         /** Property identifier: entity resolver. */
129         protected static final String ENTITY_RESOLVER =
130                 Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
131 
132     /** Property identifier: error reporter. */
133     protected static final String ERROR_REPORTER =
134         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
135 
136     /** Property identifier: entity manager. */
137     protected static final String ENTITY_MANAGER =
138         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
139 
140     /** Property identifier document scanner: */
141     protected static final String DOCUMENT_SCANNER =
142         Constants.XERCES_PROPERTY_PREFIX + Constants.DOCUMENT_SCANNER_PROPERTY;
143 
144     /** Property identifier: DTD scanner. */
145     protected static final String DTD_SCANNER =
146         Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_SCANNER_PROPERTY;
147 
148     /** Property identifier: grammar pool. */
149     protected static final String XMLGRAMMAR_POOL =
150         Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
151 
152     /** Property identifier: DTD validator. */
153     protected static final String DTD_VALIDATOR =
154         Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_VALIDATOR_PROPERTY;
155 
156     /** Property identifier: namespace binder. */
157     protected static final String NAMESPACE_BINDER =
158         Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_BINDER_PROPERTY;
159 
160     /** Property identifier: datatype validator factory. */
161     protected static final String DATATYPE_VALIDATOR_FACTORY =
162         Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
163 
164     protected static final String VALIDATION_MANAGER =
165         Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
166 
167     // debugging
168 
169     /** Set to true and recompile to print exception stack trace. */
170     protected static final boolean PRINT_EXCEPTION_STACK_TRACE = false;
171 
172     //
173     // Data
174     //
175     protected SymbolTable fSymbolTable;
176     protected XMLInputSource fInputSource;
177     protected ValidationManager fValidationManager;
178     protected XMLVersionDetector fVersionDetector;
179     protected XMLLocator fLocator;
180     protected Locale fLocale;
181 
182     /** XML 1.0 Components. */
183     protected List<XMLComponent> fComponents;
184 
185     /** XML 1.1. Components. */
186     protected List<XMLComponent> fXML11Components = null;
187 
188     /** Common components: XMLEntityManager, XMLErrorReporter */
189     protected List<XMLComponent> fCommonComponents = null;
190 
191     /** The document handler. */
192     protected XMLDocumentHandler fDocumentHandler;
193 
194     /** The DTD handler. */
195     protected XMLDTDHandler fDTDHandler;
196 
197     /** The DTD content model handler. */
198     protected XMLDTDContentModelHandler fDTDContentModelHandler;
199 
200     /** Last component in the document pipeline */
201     protected XMLDocumentSource fLastComponent;
202 
203     /**
204      * True if a parse is in progress. This state is needed because
205      * some features/properties cannot be set while parsing (e.g.
206      * namespaces).
207      */
208     protected boolean fParseInProgress = false;
209 
210     /** fConfigUpdated is set to true if there has been any change to the configuration settings,
211      * i.e a feature or a property was changed.
212      */
213     protected boolean fConfigUpdated = false;
214 
215     //
216     // XML 1.0 components
217     //
218 
219     /** The XML 1.0 Datatype validator factory. */
220     protected DTDDVFactory fDatatypeValidatorFactory;
221 
222     /** The XML 1.0 Document scanner that does namespace binding. */
223     protected XMLNSDocumentScannerImpl fNamespaceScanner;
224 
225     /** The XML 1.0 Non-namespace implementation of scanner */
226     protected XMLDocumentScannerImpl fNonNSScanner;
227 
228     /** The XML 1.0 DTD scanner. */
229     protected XMLDTDScanner fDTDScanner;
230 
231     //
232     // XML 1.1 components
233     //
234 
235     /** The XML 1.1 datatype factory. **/
236     protected DTDDVFactory fXML11DatatypeFactory = null;
237 
238     /** The XML 1.1 document scanner that does namespace binding. **/
239     protected XML11NSDocumentScannerImpl fXML11NSDocScanner = null;
240 
241     /** The XML 1.1 document scanner that does not do namespace binding. **/
242     protected XML11DocumentScannerImpl fXML11DocScanner = null;
243 
244     /** The XML 1.1 DTD scanner. **/
245     protected XML11DTDScannerImpl fXML11DTDScanner = null;
246 
247     //
248     // Common components
249     //
250 
251     /** Grammar pool. */
252     protected XMLGrammarPool fGrammarPool;
253 
254     /** Error reporter. */
255     protected XMLErrorReporter fErrorReporter;
256 
257     /** Entity manager. */
258     protected XMLEntityManager fEntityManager;
259 
260     /** Current scanner */
261     protected XMLDocumentScanner fCurrentScanner;
262 
263     /** Current Datatype validator factory. */
264     protected DTDDVFactory fCurrentDVFactory;
265 
266     /** Current DTD scanner. */
267     protected XMLDTDScanner fCurrentDTDScanner;
268 
269 
270     /** Flag indiciating whether XML11 components have been initialized. */
271     private boolean f11Initialized = false;
272 
273     //
274     // Constructors
275     //
276 
277     /** Default constructor. */
XML11NonValidatingConfiguration()278     public XML11NonValidatingConfiguration() {
279         this(null, null, null);
280     } // <init>()
281 
282     /**
283      * Constructs a parser configuration using the specified symbol table.
284      *
285      * @param symbolTable The symbol table to use.
286      */
XML11NonValidatingConfiguration(SymbolTable symbolTable)287     public XML11NonValidatingConfiguration(SymbolTable symbolTable) {
288         this(symbolTable, null, null);
289     } // <init>(SymbolTable)
290 
291     /**
292      * Constructs a parser configuration using the specified symbol table and
293      * grammar pool.
294      * <p>
295      * <strong>REVISIT:</strong>
296      * Grammar pool will be updated when the new validation engine is
297      * implemented.
298      *
299      * @param symbolTable The symbol table to use.
300      * @param grammarPool The grammar pool to use.
301      */
XML11NonValidatingConfiguration(SymbolTable symbolTable, XMLGrammarPool grammarPool)302     public XML11NonValidatingConfiguration(SymbolTable symbolTable, XMLGrammarPool grammarPool) {
303         this(symbolTable, grammarPool, null);
304     } // <init>(SymbolTable,XMLGrammarPool)
305 
306     /**
307      * Constructs a parser configuration using the specified symbol table,
308      * grammar pool, and parent settings.
309      * <p>
310      * <strong>REVISIT:</strong>
311      * Grammar pool will be updated when the new validation engine is
312      * implemented.
313      *
314      * @param symbolTable    The symbol table to use.
315      * @param grammarPool    The grammar pool to use.
316      * @param parentSettings The parent settings.
317      */
XML11NonValidatingConfiguration( SymbolTable symbolTable, XMLGrammarPool grammarPool, XMLComponentManager parentSettings)318     public XML11NonValidatingConfiguration(
319         SymbolTable symbolTable,
320         XMLGrammarPool grammarPool,
321         XMLComponentManager parentSettings) {
322 
323                 super(parentSettings);
324 
325                 // create a vector to hold all the components in use
326                 // XML 1.0 specialized components
327                 fComponents = new ArrayList<>();
328                 // XML 1.1 specialized components
329                 fXML11Components = new ArrayList<>();
330                 // Common components for XML 1.1. and XML 1.0
331                 fCommonComponents = new ArrayList<>();
332 
333                 // create table for features and properties
334                 fFeatures = new HashMap<>();
335                 fProperties = new HashMap<>();
336 
337         // add default recognized features
338         final String[] recognizedFeatures =
339             {
340                 CONTINUE_AFTER_FATAL_ERROR, // from XMLDTDScannerImpl
341                                 VALIDATION,
342                                 NAMESPACES,
343                                 EXTERNAL_GENERAL_ENTITIES,
344                                 EXTERNAL_PARAMETER_ENTITIES,
345                                 PARSER_SETTINGS
346                         };
347         addRecognizedFeatures(recognizedFeatures);
348 
349                 // set state for default features
350                 fFeatures.put(VALIDATION, Boolean.FALSE);
351                 fFeatures.put(NAMESPACES, Boolean.TRUE);
352                 fFeatures.put(EXTERNAL_GENERAL_ENTITIES, Boolean.TRUE);
353                 fFeatures.put(EXTERNAL_PARAMETER_ENTITIES, Boolean.TRUE);
354                 fFeatures.put(CONTINUE_AFTER_FATAL_ERROR, Boolean.FALSE);
355                 fFeatures.put(PARSER_SETTINGS, Boolean.TRUE);
356 
357         // add default recognized properties
358         final String[] recognizedProperties =
359             {
360                 XML_STRING,
361                 SYMBOL_TABLE,
362                                 ERROR_HANDLER,
363                                 ENTITY_RESOLVER,
364                 ERROR_REPORTER,
365                 ENTITY_MANAGER,
366                 DOCUMENT_SCANNER,
367                 DTD_SCANNER,
368                 DTD_VALIDATOR,
369                                 DATATYPE_VALIDATOR_FACTORY,
370                                 VALIDATION_MANAGER,
371                                 XML_STRING,
372                 XMLGRAMMAR_POOL, };
373         addRecognizedProperties(recognizedProperties);
374 
375                 if (symbolTable == null) {
376                         symbolTable = new SymbolTable();
377                 }
378                 fSymbolTable = symbolTable;
379                 fProperties.put(SYMBOL_TABLE, fSymbolTable);
380 
381         fGrammarPool = grammarPool;
382         if (fGrammarPool != null) {
383                         fProperties.put(XMLGRAMMAR_POOL, fGrammarPool);
384         }
385 
386         fEntityManager = new XMLEntityManager();
387                 fProperties.put(ENTITY_MANAGER, fEntityManager);
388         addCommonComponent(fEntityManager);
389 
390         fErrorReporter = new XMLErrorReporter();
391         fErrorReporter.setDocumentLocator(fEntityManager.getEntityScanner());
392                 fProperties.put(ERROR_REPORTER, fErrorReporter);
393         addCommonComponent(fErrorReporter);
394 
395         fNamespaceScanner = new XMLNSDocumentScannerImpl();
396                 fProperties.put(DOCUMENT_SCANNER, fNamespaceScanner);
397         addComponent((XMLComponent) fNamespaceScanner);
398 
399         fDTDScanner = new XMLDTDScannerImpl();
400                 fProperties.put(DTD_SCANNER, fDTDScanner);
401         addComponent((XMLComponent) fDTDScanner);
402 
403         fDatatypeValidatorFactory = DTDDVFactory.getInstance();
404                 fProperties.put(DATATYPE_VALIDATOR_FACTORY, fDatatypeValidatorFactory);
405 
406         fValidationManager = new ValidationManager();
407                 fProperties.put(VALIDATION_MANAGER, fValidationManager);
408 
409         fVersionDetector = new XMLVersionDetector();
410 
411         // add message formatters
412         if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
413             XMLMessageFormatter xmft = new XMLMessageFormatter();
414             fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
415             fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
416         }
417 
418         // set locale
419         try {
420             setLocale(Locale.getDefault());
421         } catch (XNIException e) {
422             // do nothing
423             // REVISIT: What is the right thing to do? -Ac
424         }
425 
426                 fConfigUpdated = false;
427 
428     } // <init>(SymbolTable,XMLGrammarPool)
429 
430     /**
431      * Sets the input source for the document to parse.
432      *
433      * @param inputSource The document's input source.
434      *
435      * @exception XMLConfigurationException Thrown if there is a
436      *                        configuration error when initializing the
437      *                        parser.
438      * @exception IOException Thrown on I/O error.
439      *
440      * @see #parse(boolean)
441      */
setInputSource(XMLInputSource inputSource)442     public void setInputSource(XMLInputSource inputSource)
443         throws XMLConfigurationException, IOException {
444 
445         // REVISIT: this method used to reset all the components and
446         //          construct the pipeline. Now reset() is called
447         //          in parse (boolean) just before we parse the document
448         //          Should this method still throw exceptions..?
449 
450         fInputSource = inputSource;
451 
452     } // setInputSource(XMLInputSource)
453 
454     /**
455      * Set the locale to use for messages.
456      *
457      * @param locale The locale object to use for localization of messages.
458      *
459      * @exception XNIException Thrown if the parser does not support the
460      *                         specified locale.
461      */
setLocale(Locale locale)462     public void setLocale(Locale locale) throws XNIException {
463         fLocale = locale;
464         fErrorReporter.setLocale(locale);
465     } // setLocale(Locale)
466 
467         /**
468          * Sets the document handler on the last component in the pipeline
469          * to receive information about the document.
470          *
471          * @param documentHandler   The document handler.
472          */
setDocumentHandler(XMLDocumentHandler documentHandler)473         public void setDocumentHandler(XMLDocumentHandler documentHandler) {
474                 fDocumentHandler = documentHandler;
475                 if (fLastComponent != null) {
476                         fLastComponent.setDocumentHandler(fDocumentHandler);
477                         if (fDocumentHandler !=null){
478                                 fDocumentHandler.setDocumentSource(fLastComponent);
479                         }
480                 }
481         } // setDocumentHandler(XMLDocumentHandler)
482 
483         /** Returns the registered document handler. */
getDocumentHandler()484         public XMLDocumentHandler getDocumentHandler() {
485                 return fDocumentHandler;
486         } // getDocumentHandler():XMLDocumentHandler
487 
488         /**
489          * Sets the DTD handler.
490          *
491          * @param dtdHandler The DTD handler.
492          */
setDTDHandler(XMLDTDHandler dtdHandler)493         public void setDTDHandler(XMLDTDHandler dtdHandler) {
494                 fDTDHandler = dtdHandler;
495         } // setDTDHandler(XMLDTDHandler)
496 
497         /** Returns the registered DTD handler. */
getDTDHandler()498         public XMLDTDHandler getDTDHandler() {
499                 return fDTDHandler;
500         } // getDTDHandler():XMLDTDHandler
501 
502         /**
503          * Sets the DTD content model handler.
504          *
505          * @param handler The DTD content model handler.
506          */
setDTDContentModelHandler(XMLDTDContentModelHandler handler)507         public void setDTDContentModelHandler(XMLDTDContentModelHandler handler) {
508                 fDTDContentModelHandler = handler;
509         } // setDTDContentModelHandler(XMLDTDContentModelHandler)
510 
511         /** Returns the registered DTD content model handler. */
getDTDContentModelHandler()512         public XMLDTDContentModelHandler getDTDContentModelHandler() {
513                 return fDTDContentModelHandler;
514         } // getDTDContentModelHandler():XMLDTDContentModelHandler
515 
516         /**
517          * Sets the resolver used to resolve external entities. The EntityResolver
518          * interface supports resolution of public and system identifiers.
519          *
520          * @param resolver The new entity resolver. Passing a null value will
521          *                 uninstall the currently installed resolver.
522          */
setEntityResolver(XMLEntityResolver resolver)523         public void setEntityResolver(XMLEntityResolver resolver) {
524                 fProperties.put(ENTITY_RESOLVER, resolver);
525         } // setEntityResolver(XMLEntityResolver)
526 
527         /**
528          * Return the current entity resolver.
529          *
530          * @return The current entity resolver, or null if none
531          *         has been registered.
532          * @see #setEntityResolver
533          */
getEntityResolver()534         public XMLEntityResolver getEntityResolver() {
535                 return (XMLEntityResolver)fProperties.get(ENTITY_RESOLVER);
536         } // getEntityResolver():XMLEntityResolver
537 
538         /**
539          * Allow an application to register an error event handler.
540          *
541          * <p>If the application does not register an error handler, all
542          * error events reported by the SAX parser will be silently
543          * ignored; however, normal processing may not continue.  It is
544          * highly recommended that all SAX applications implement an
545          * error handler to avoid unexpected bugs.</p>
546          *
547          * <p>Applications may register a new or different handler in the
548          * middle of a parse, and the SAX parser must begin using the new
549          * handler immediately.</p>
550          *
551          * @param errorHandler The error handler.
552          * @exception java.lang.NullPointerException If the handler
553          *            argument is null.
554          * @see #getErrorHandler
555          */
setErrorHandler(XMLErrorHandler errorHandler)556         public void setErrorHandler(XMLErrorHandler errorHandler) {
557                 fProperties.put(ERROR_HANDLER, errorHandler);
558         } // setErrorHandler(XMLErrorHandler)
559 
560         /**
561          * Return the current error handler.
562          *
563          * @return The current error handler, or null if none
564          *         has been registered.
565          * @see #setErrorHandler
566          */
getErrorHandler()567         public XMLErrorHandler getErrorHandler() {
568                 // REVISIT: Should this be a property?
569                 return (XMLErrorHandler)fProperties.get(ERROR_HANDLER);
570         } // getErrorHandler():XMLErrorHandler
571 
572 
573     /**
574      * If the application decides to terminate parsing before the xml document
575      * is fully parsed, the application should call this method to free any
576      * resource allocated during parsing. For example, close all opened streams.
577      */
cleanup()578     public void cleanup() {
579         fEntityManager.closeReaders();
580     }
581 
582     /**
583      * Parses the specified input source.
584      *
585      * @param source The input source.
586      *
587      * @exception XNIException Throws exception on XNI error.
588      * @exception java.io.IOException Throws exception on i/o error.
589      */
parse(XMLInputSource source)590     public void parse(XMLInputSource source) throws XNIException, IOException {
591 
592         if (fParseInProgress) {
593             // REVISIT - need to add new error message
594             throw new XNIException("FWK005 parse may not be called while parsing.");
595         }
596         fParseInProgress = true;
597 
598         try {
599             setInputSource(source);
600             parse(true);
601         } catch (XNIException ex) {
602             if (PRINT_EXCEPTION_STACK_TRACE)
603                 ex.printStackTrace();
604             throw ex;
605         } catch (IOException ex) {
606             if (PRINT_EXCEPTION_STACK_TRACE)
607                 ex.printStackTrace();
608             throw ex;
609         } catch (RuntimeException ex) {
610             if (PRINT_EXCEPTION_STACK_TRACE)
611                 ex.printStackTrace();
612             throw ex;
613         } catch (Exception ex) {
614             if (PRINT_EXCEPTION_STACK_TRACE)
615                 ex.printStackTrace();
616             throw new XNIException(ex);
617         } finally {
618             fParseInProgress = false;
619             // close all streams opened by xerces
620             this.cleanup();
621         }
622 
623     } // parse(InputSource)
624 
parse(boolean complete)625     public boolean parse(boolean complete) throws XNIException, IOException {
626         //
627         // reset and configure pipeline and set InputSource.
628         if (fInputSource != null) {
629             try {
630                                 fValidationManager.reset();
631                 fVersionDetector.reset(this);
632                 resetCommon();
633 
634                 short version = fVersionDetector.determineDocVersion(fInputSource);
635                 if (version == Constants.XML_VERSION_1_1) {
636                     initXML11Components();
637                     configureXML11Pipeline();
638                     resetXML11();
639                 } else {
640                     configurePipeline();
641                     reset();
642                 }
643 
644                 // mark configuration as fixed
645                 fConfigUpdated = false;
646 
647                 // resets and sets the pipeline.
648                 fVersionDetector.startDocumentParsing((XMLEntityHandler) fCurrentScanner, version);
649                 fInputSource = null;
650             } catch (XNIException ex) {
651                 if (PRINT_EXCEPTION_STACK_TRACE)
652                     ex.printStackTrace();
653                 throw ex;
654             } catch (IOException ex) {
655                 if (PRINT_EXCEPTION_STACK_TRACE)
656                     ex.printStackTrace();
657                 throw ex;
658             } catch (RuntimeException ex) {
659                 if (PRINT_EXCEPTION_STACK_TRACE)
660                     ex.printStackTrace();
661                 throw ex;
662             } catch (Exception ex) {
663                 if (PRINT_EXCEPTION_STACK_TRACE)
664                     ex.printStackTrace();
665                 throw new XNIException(ex);
666             }
667         }
668 
669         try {
670             return fCurrentScanner.scanDocument(complete);
671         } catch (XNIException ex) {
672             if (PRINT_EXCEPTION_STACK_TRACE)
673                 ex.printStackTrace();
674             throw ex;
675         } catch (IOException ex) {
676             if (PRINT_EXCEPTION_STACK_TRACE)
677                 ex.printStackTrace();
678             throw ex;
679         } catch (RuntimeException ex) {
680             if (PRINT_EXCEPTION_STACK_TRACE)
681                 ex.printStackTrace();
682             throw ex;
683         } catch (Exception ex) {
684             if (PRINT_EXCEPTION_STACK_TRACE)
685                 ex.printStackTrace();
686             throw new XNIException(ex);
687         }
688 
689     } // parse(boolean):boolean
690 
691         /**
692          * Returns the state of a feature.
693          *
694          * @param featureId The feature identifier.
695                  * @return true if the feature is supported
696          *
697          * @throws XMLConfigurationException Thrown for configuration error.
698          *                                   In general, components should
699          *                                   only throw this exception if
700          *                                   it is <strong>really</strong>
701          *                                   a critical error.
702          */
getFeatureState(String featureId)703         public FeatureState getFeatureState(String featureId)
704                 throws XMLConfigurationException {
705                         // make this feature special
706         if (featureId.equals(PARSER_SETTINGS)){
707                 return FeatureState.is(fConfigUpdated);
708         }
709         return super.getFeatureState(featureId);
710 
711         } // getFeature(String):boolean
712 
713         /**
714          * Set the state of a feature.
715          *
716          * Set the state of any feature in a SAX2 parser.  The parser
717          * might not recognize the feature, and if it does recognize
718          * it, it might not be able to fulfill the request.
719          *
720          * @param featureId The unique identifier (URI) of the feature.
721          * @param state The requested state of the feature (true or false).
722          *
723          * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
724          *            requested feature is not known.
725          */
setFeature(String featureId, boolean state)726         public void setFeature(String featureId, boolean state)
727                 throws XMLConfigurationException {
728                 fConfigUpdated = true;
729                 // forward to every XML 1.0 component
730                 for (XMLComponent c : fComponents) {
731                     c.setFeature(featureId, state);
732                 }
733                 // forward it to common components
734                 for (XMLComponent c : fCommonComponents) {
735                     c.setFeature(featureId, state);
736                 }
737                 // forward to every XML 1.1 component
738                 for (XMLComponent c : fXML11Components) {
739                     try {
740                         c.setFeature(featureId, state);
741                     }
742                     catch (Exception e){
743                         // no op
744                     }
745                 }
746                 // save state if noone "objects"
747                 super.setFeature(featureId, state);
748 
749         } // setFeature(String,boolean)
750 
751         /**
752          * setProperty
753          *
754          * @param propertyId
755          * @param value
756          */
setProperty(String propertyId, Object value)757         public void setProperty(String propertyId, Object value)
758                 throws XMLConfigurationException {
759                 fConfigUpdated = true;
760                 // forward to every XML 1.0 component
761                 for (XMLComponent c : fComponents) {
762                     c.setProperty(propertyId, value);
763                 }
764                 // forward it to every common Component
765                 for (XMLComponent c : fCommonComponents) {
766                     c.setProperty(propertyId, value);
767                 }
768                 // forward it to every XML 1.1 component
769                 for (XMLComponent c : fXML11Components) {
770                     try {
771                         c.setProperty(propertyId, value);
772                     }
773                     catch (Exception e){
774                         // no op
775                     }
776                 }
777                 // store value if noone "objects"
778                 super.setProperty(propertyId, value);
779 
780         } // setProperty(String,Object)
781 
782 
783         /** Returns the locale. */
getLocale()784         public Locale getLocale() {
785                 return fLocale;
786         } // getLocale():Locale
787 
788         /**
789          * reset all XML 1.0 components before parsing and namespace context
790          */
reset()791         protected void reset() throws XNIException {
792             for (XMLComponent c : fComponents) {
793                 c.reset(this);
794             }
795         } // reset()
796 
797         /**
798          * reset all common components before parsing
799          */
resetCommon()800         protected void resetCommon() throws XNIException {
801             // reset common components
802             for (XMLComponent c : fCommonComponents) {
803                 c.reset(this);
804             }
805         } // resetCommon()
806 
807 
808         /**
809          * reset all components before parsing and namespace context
810          */
resetXML11()811         protected void resetXML11() throws XNIException {
812             // reset every component
813             for (XMLComponent c : fXML11Components) {
814                 c.reset(this);
815             }
816         } // resetXML11()
817 
818 
819     /**
820      *  Configures the XML 1.1 pipeline.
821      *  Note: this method also resets the new XML11 components.
822      */
configureXML11Pipeline()823     protected void configureXML11Pipeline() {
824         if (fCurrentDVFactory != fXML11DatatypeFactory) {
825             fCurrentDVFactory = fXML11DatatypeFactory;
826             setProperty(DATATYPE_VALIDATOR_FACTORY, fCurrentDVFactory);
827         }
828 
829         // setup DTD pipeline
830         if (fCurrentDTDScanner != fXML11DTDScanner) {
831             fCurrentDTDScanner = fXML11DTDScanner;
832             setProperty(DTD_SCANNER, fCurrentDTDScanner);
833         }
834         fXML11DTDScanner.setDTDHandler(fDTDHandler);
835         fXML11DTDScanner.setDTDContentModelHandler(fDTDContentModelHandler);
836 
837         // setup XML 1.1 document pipeline
838         if (fFeatures.get(NAMESPACES) == Boolean.TRUE) {
839             if (fCurrentScanner != fXML11NSDocScanner) {
840                 fCurrentScanner = fXML11NSDocScanner;
841                 setProperty(DOCUMENT_SCANNER, fXML11NSDocScanner);
842             }
843 
844             fXML11NSDocScanner.setDTDValidator(null);
845             fXML11NSDocScanner.setDocumentHandler(fDocumentHandler);
846             if (fDocumentHandler != null) {
847                 fDocumentHandler.setDocumentSource(fXML11NSDocScanner);
848             }
849             fLastComponent = fXML11NSDocScanner;
850 
851         } else {
852                         // create components
853                           if (fXML11DocScanner == null) {
854                                         // non namespace document pipeline
855                                         fXML11DocScanner = new XML11DocumentScannerImpl();
856                                         addXML11Component(fXML11DocScanner);
857                           }
858             if (fCurrentScanner != fXML11DocScanner) {
859                 fCurrentScanner = fXML11DocScanner;
860                 setProperty(DOCUMENT_SCANNER, fXML11DocScanner);
861             }
862             fXML11DocScanner.setDocumentHandler(fDocumentHandler);
863 
864             if (fDocumentHandler != null) {
865                 fDocumentHandler.setDocumentSource(fXML11DocScanner);
866             }
867             fLastComponent = fXML11DocScanner;
868         }
869 
870     } // configureXML11Pipeline()
871 
872     /** Configures the pipeline. */
configurePipeline()873     protected void configurePipeline() {
874         if (fCurrentDVFactory != fDatatypeValidatorFactory) {
875             fCurrentDVFactory = fDatatypeValidatorFactory;
876             // use XML 1.0 datatype library
877             setProperty(DATATYPE_VALIDATOR_FACTORY, fCurrentDVFactory);
878         }
879 
880         // setup DTD pipeline
881         if (fCurrentDTDScanner != fDTDScanner) {
882             fCurrentDTDScanner = fDTDScanner;
883             setProperty(DTD_SCANNER, fCurrentDTDScanner);
884         }
885         fDTDScanner.setDTDHandler(fDTDHandler);
886         fDTDScanner.setDTDContentModelHandler(fDTDContentModelHandler);
887 
888         // setup document pipeline
889         if (fFeatures.get(NAMESPACES) == Boolean.TRUE) {
890             if (fCurrentScanner != fNamespaceScanner) {
891                 fCurrentScanner = fNamespaceScanner;
892                 setProperty(DOCUMENT_SCANNER, fNamespaceScanner);
893             }
894             fNamespaceScanner.setDTDValidator(null);
895             fNamespaceScanner.setDocumentHandler(fDocumentHandler);
896             if (fDocumentHandler != null) {
897                 fDocumentHandler.setDocumentSource(fNamespaceScanner);
898             }
899             fLastComponent = fNamespaceScanner;
900         } else {
901             // create components
902             if (fNonNSScanner == null) {
903                 fNonNSScanner = new XMLDocumentScannerImpl();
904                 // add components
905                 addComponent((XMLComponent) fNonNSScanner);
906 
907             }
908             if (fCurrentScanner != fNonNSScanner) {
909                 fCurrentScanner = fNonNSScanner;
910                 setProperty(DOCUMENT_SCANNER, fNonNSScanner);
911 
912             }
913 
914             fNonNSScanner.setDocumentHandler(fDocumentHandler);
915             if (fDocumentHandler != null) {
916                 fDocumentHandler.setDocumentSource(fNonNSScanner);
917             }
918             fLastComponent = fNonNSScanner;
919         }
920 
921     } // configurePipeline()
922 
923 
924     // features and properties
925 
926     /**
927      * Check a feature. If feature is know and supported, this method simply
928      * returns. Otherwise, the appropriate exception is thrown.
929      *
930      * @param featureId The unique identifier (URI) of the feature.
931      *
932      * @throws XMLConfigurationException Thrown for configuration error.
933      *                                   In general, components should
934      *                                   only throw this exception if
935      *                                   it is <strong>really</strong>
936      *                                   a critical error.
937      */
checkFeature(String featureId)938     protected FeatureState checkFeature(String featureId) throws XMLConfigurationException {
939 
940         //
941         // Xerces Features
942         //
943 
944         if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
945             final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
946 
947             //
948             // http://apache.org/xml/features/validation/dynamic
949             //   Allows the parser to validate a document only when it
950             //   contains a grammar. Validation is turned on/off based
951             //   on each document instance, automatically.
952             //
953             if (suffixLength == Constants.DYNAMIC_VALIDATION_FEATURE.length() &&
954                 featureId.endsWith(Constants.DYNAMIC_VALIDATION_FEATURE)) {
955                 return FeatureState.RECOGNIZED;
956             }
957 
958             //
959             // http://apache.org/xml/features/validation/default-attribute-values
960             //
961             if (suffixLength == Constants.DEFAULT_ATTRIBUTE_VALUES_FEATURE.length() &&
962                 featureId.endsWith(Constants.DEFAULT_ATTRIBUTE_VALUES_FEATURE)) {
963                 // REVISIT
964                 return FeatureState.NOT_SUPPORTED;
965             }
966             //
967             // http://apache.org/xml/features/validation/default-attribute-values
968             //
969             if (suffixLength == Constants.VALIDATE_CONTENT_MODELS_FEATURE.length() &&
970                 featureId.endsWith(Constants.VALIDATE_CONTENT_MODELS_FEATURE)) {
971                 // REVISIT
972                 return FeatureState.NOT_SUPPORTED;
973             }
974             //
975             // http://apache.org/xml/features/validation/nonvalidating/load-dtd-grammar
976             //
977             if (suffixLength == Constants.LOAD_DTD_GRAMMAR_FEATURE.length() &&
978                 featureId.endsWith(Constants.LOAD_DTD_GRAMMAR_FEATURE)) {
979                 return FeatureState.RECOGNIZED;
980             }
981             //
982             // http://apache.org/xml/features/validation/nonvalidating/load-external-dtd
983             //
984             if (suffixLength == Constants.LOAD_EXTERNAL_DTD_FEATURE.length() &&
985                 featureId.endsWith(Constants.LOAD_EXTERNAL_DTD_FEATURE)) {
986                 return FeatureState.RECOGNIZED;
987             }
988 
989             //
990             // http://apache.org/xml/features/validation/default-attribute-values
991             //
992             if (suffixLength == Constants.VALIDATE_DATATYPES_FEATURE.length() &&
993                 featureId.endsWith(Constants.VALIDATE_DATATYPES_FEATURE)) {
994                 return FeatureState.NOT_SUPPORTED;
995             }
996 
997             // special performance feature: only component manager is allowed to set it.
998             if (suffixLength == Constants.PARSER_SETTINGS.length() &&
999                 featureId.endsWith(Constants.PARSER_SETTINGS)) {
1000                 return FeatureState.NOT_SUPPORTED;
1001             }
1002         }
1003 
1004         //
1005         // Not recognized
1006         //
1007 
1008         return super.checkFeature(featureId);
1009 
1010     } // checkFeature(String)
1011 
1012     /**
1013      * Check a property. If the property is know and supported, this method
1014      * simply returns. Otherwise, the appropriate exception is thrown.
1015      *
1016      * @param propertyId The unique identifier (URI) of the property
1017      *                   being set.
1018      *
1019      * @throws XMLConfigurationException Thrown for configuration error.
1020      *                                   In general, components should
1021      *                                   only throw this exception if
1022      *                                   it is <strong>really</strong>
1023      *                                   a critical error.
1024      */
checkProperty(String propertyId)1025     protected PropertyState checkProperty(String propertyId) throws XMLConfigurationException {
1026 
1027         //
1028         // Xerces Properties
1029         //
1030 
1031         if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
1032             final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
1033 
1034             if (suffixLength == Constants.DTD_SCANNER_PROPERTY.length() &&
1035                 propertyId.endsWith(Constants.DTD_SCANNER_PROPERTY)) {
1036                 return PropertyState.RECOGNIZED;
1037             }
1038         }
1039 
1040         if (propertyId.startsWith(Constants.JAXP_PROPERTY_PREFIX)) {
1041             final int suffixLength = propertyId.length() - Constants.JAXP_PROPERTY_PREFIX.length();
1042 
1043             if (suffixLength == Constants.SCHEMA_SOURCE.length() &&
1044                 propertyId.endsWith(Constants.SCHEMA_SOURCE)) {
1045                 return PropertyState.RECOGNIZED;
1046             }
1047         }
1048 
1049         // special cases
1050         if (propertyId.startsWith(Constants.SAX_PROPERTY_PREFIX)) {
1051             final int suffixLength = propertyId.length() - Constants.SAX_PROPERTY_PREFIX.length();
1052 
1053             //
1054             // http://xml.org/sax/properties/xml-string
1055             // Value type: String
1056             // Access: read-only
1057             //   Get the literal string of characters associated with the
1058             //   current event.  If the parser recognises and supports this
1059             //   property but is not currently parsing text, it should return
1060             //   null (this is a good way to check for availability before the
1061             //   parse begins).
1062             //
1063             if (suffixLength == Constants.XML_STRING_PROPERTY.length() &&
1064                 propertyId.endsWith(Constants.XML_STRING_PROPERTY)) {
1065                 // REVISIT - we should probably ask xml-dev for a precise
1066                 // definition of what this is actually supposed to return, and
1067                 // in exactly which circumstances.
1068                 return PropertyState.NOT_SUPPORTED;
1069             }
1070         }
1071 
1072         //
1073         // Not recognized
1074         //
1075 
1076         return super.checkProperty(propertyId);
1077 
1078     } // checkProperty(String)
1079 
1080 
1081     /**
1082      * Adds a component to the parser configuration. This method will
1083      * also add all of the component's recognized features and properties
1084      * to the list of default recognized features and properties.
1085      *
1086      * @param component The component to add.
1087      */
addComponent(XMLComponent component)1088     protected void addComponent(XMLComponent component) {
1089 
1090         // don't add a component more than once
1091         if (fComponents.contains(component)) {
1092             return;
1093         }
1094         fComponents.add(component);
1095         addRecognizedParamsAndSetDefaults(component);
1096 
1097     } // addComponent(XMLComponent)
1098 
1099     /**
1100      * Adds common component to the parser configuration. This method will
1101      * also add all of the component's recognized features and properties
1102      * to the list of default recognized features and properties.
1103      *
1104      * @param component The component to add.
1105      */
addCommonComponent(XMLComponent component)1106     protected void addCommonComponent(XMLComponent component) {
1107 
1108         // don't add a component more than once
1109         if (fCommonComponents.contains(component)) {
1110             return;
1111         }
1112         fCommonComponents.add(component);
1113         addRecognizedParamsAndSetDefaults(component);
1114 
1115     } // addCommonComponent(XMLComponent)
1116 
1117     /**
1118      * Adds an XML 1.1 component to the parser configuration. This method will
1119      * also add all of the component's recognized features and properties
1120      * to the list of default recognized features and properties.
1121      *
1122      * @param component The component to add.
1123      */
addXML11Component(XMLComponent component)1124     protected void addXML11Component(XMLComponent component) {
1125 
1126         // don't add a component more than once
1127         if (fXML11Components.contains(component)) {
1128             return;
1129         }
1130         fXML11Components.add(component);
1131         addRecognizedParamsAndSetDefaults(component);
1132 
1133     } // addXML11Component(XMLComponent)
1134 
1135     /**
1136      * Adds all of the component's recognized features and properties
1137      * to the list of default recognized features and properties, and
1138      * sets default values on the configuration for features and
1139      * properties which were previously absent from the configuration.
1140      *
1141      * @param component The component whose recognized features
1142      * and properties will be added to the configuration
1143      */
addRecognizedParamsAndSetDefaults(XMLComponent component)1144     protected void addRecognizedParamsAndSetDefaults(XMLComponent component) {
1145 
1146         // register component's recognized features
1147         String[] recognizedFeatures = component.getRecognizedFeatures();
1148         addRecognizedFeatures(recognizedFeatures);
1149 
1150         // register component's recognized properties
1151         String[] recognizedProperties = component.getRecognizedProperties();
1152         addRecognizedProperties(recognizedProperties);
1153 
1154         // set default values
1155         if (recognizedFeatures != null) {
1156             for (int i = 0; i < recognizedFeatures.length; ++i) {
1157                 String featureId = recognizedFeatures[i];
1158                 Boolean state = component.getFeatureDefault(featureId);
1159                 if (state != null) {
1160                     // Do not overwrite values already set on the configuration.
1161                     if (!fFeatures.containsKey(featureId)) {
1162                         fFeatures.put(featureId, state);
1163                         // For newly added components who recognize this feature
1164                         // but did not offer a default value, we need to make
1165                         // sure these components will get an opportunity to read
1166                         // the value before parsing begins.
1167                         fConfigUpdated = true;
1168                     }
1169                 }
1170             }
1171         }
1172         if (recognizedProperties != null) {
1173             for (int i = 0; i < recognizedProperties.length; ++i) {
1174                 String propertyId = recognizedProperties[i];
1175                 Object value = component.getPropertyDefault(propertyId);
1176                 if (value != null) {
1177                     // Do not overwrite values already set on the configuration.
1178                     if (!fProperties.containsKey(propertyId)) {
1179                         fProperties.put(propertyId, value);
1180                         // For newly added components who recognize this property
1181                         // but did not offer a default value, we need to make
1182                         // sure these components will get an opportunity to read
1183                         // the value before parsing begins.
1184                         fConfigUpdated = true;
1185                     }
1186                 }
1187             }
1188         }
1189     }
1190 
initXML11Components()1191     private void initXML11Components() {
1192         if (!f11Initialized) {
1193 
1194             // create datatype factory
1195             fXML11DatatypeFactory = DTDDVFactory.getInstance(XML11_DATATYPE_VALIDATOR_FACTORY);
1196 
1197             // setup XML 1.1 DTD pipeline
1198             fXML11DTDScanner = new XML11DTDScannerImpl();
1199             addXML11Component(fXML11DTDScanner);
1200 
1201             // setup XML 1.1. document pipeline - namespace aware
1202             fXML11NSDocScanner = new XML11NSDocumentScannerImpl();
1203             addXML11Component(fXML11NSDocScanner);
1204 
1205             f11Initialized = true;
1206         }
1207     }
1208 
1209 } // class XML11NonValidatingConfiguration
1210