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.impl.xs.opti;
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.XML11NSDocumentScannerImpl;
26 import com.sun.org.apache.xerces.internal.impl.XMLDTDScannerImpl;
27 import com.sun.org.apache.xerces.internal.impl.XMLEntityHandler;
28 import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
29 import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
30 import com.sun.org.apache.xerces.internal.impl.XMLNSDocumentScannerImpl;
31 import com.sun.org.apache.xerces.internal.impl.XMLVersionDetector;
32 import com.sun.org.apache.xerces.internal.impl.dv.DTDDVFactory;
33 import com.sun.org.apache.xerces.internal.impl.msg.XMLMessageFormatter;
34 import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
35 import com.sun.org.apache.xerces.internal.impl.xs.XSMessageFormatter;
36 import com.sun.org.apache.xerces.internal.parsers.BasicParserConfiguration;
37 import com.sun.org.apache.xerces.internal.util.FeatureState;
38 import com.sun.org.apache.xerces.internal.util.PropertyState;
39 import com.sun.org.apache.xerces.internal.util.SymbolTable;
40 import com.sun.org.apache.xerces.internal.xni.XMLLocator;
41 import com.sun.org.apache.xerces.internal.xni.XNIException;
42 import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
43 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
44 import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
45 import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
46 import com.sun.org.apache.xerces.internal.xni.parser.XMLDTDScanner;
47 import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentScanner;
48 import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
49 import com.sun.org.apache.xerces.internal.xni.parser.XMLPullParserConfiguration;
50 import java.io.IOException;
51 import java.util.Locale;
52 import javax.xml.XMLConstants;
53 import jdk.xml.internal.JdkXmlUtils;
54 import jdk.xml.internal.SecuritySupport;
55 
56 /**
57  * @xerces.internal
58  *
59  * @author Rahul Srivastava, Sun Microsystems Inc.
60  *
61  * @LastModified: Sep 2017
62  */
63 public class SchemaParsingConfig extends BasicParserConfiguration
64     implements XMLPullParserConfiguration {
65 
66     //
67     // Constants
68     //
69 
70     protected final static String XML11_DATATYPE_VALIDATOR_FACTORY =
71         "com.sun.org.apache.xerces.internal.impl.dv.dtd.XML11DTDDVFactoryImpl";
72 
73     // feature identifiers
74 
75     /** Feature identifier: warn on duplicate attribute definition. */
76     protected static final String WARN_ON_DUPLICATE_ATTDEF =
77         Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ATTDEF_FEATURE;
78 
79     /** Feature identifier: warn on duplicate entity definition. */
80     //  protected static final String WARN_ON_DUPLICATE_ENTITYDEF = Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_DUPLICATE_ENTITYDEF_FEATURE;
81 
82     /** Feature identifier: warn on undeclared element definition. */
83     protected static final String WARN_ON_UNDECLARED_ELEMDEF =
84         Constants.XERCES_FEATURE_PREFIX + Constants.WARN_ON_UNDECLARED_ELEMDEF_FEATURE;
85 
86     /** Feature identifier: allow Java encodings. */
87     protected static final String ALLOW_JAVA_ENCODINGS =
88         Constants.XERCES_FEATURE_PREFIX + Constants.ALLOW_JAVA_ENCODINGS_FEATURE;
89 
90     /** Feature identifier: continue after fatal error. */
91     protected static final String CONTINUE_AFTER_FATAL_ERROR =
92         Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
93 
94     /** Feature identifier: load external DTD. */
95     protected static final String LOAD_EXTERNAL_DTD =
96         Constants.XERCES_FEATURE_PREFIX + Constants.LOAD_EXTERNAL_DTD_FEATURE;
97 
98     /** Feature identifier: notify built-in refereces. */
99     protected static final String NOTIFY_BUILTIN_REFS =
100         Constants.XERCES_FEATURE_PREFIX + Constants.NOTIFY_BUILTIN_REFS_FEATURE;
101 
102     /** Feature identifier: notify character refereces. */
103     protected static final String NOTIFY_CHAR_REFS =
104         Constants.XERCES_FEATURE_PREFIX + Constants.NOTIFY_CHAR_REFS_FEATURE;
105 
106     /** Feature identifier: expose schema normalized value */
107     protected static final String NORMALIZE_DATA =
108         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE;
109 
110     /** Feature identifier: send element default value via characters() */
111     protected static final String SCHEMA_ELEMENT_DEFAULT =
112         Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_ELEMENT_DEFAULT;
113 
114     /** Feature identifier: generate synthetic annotations. */
115     protected static final String GENERATE_SYNTHETIC_ANNOTATIONS =
116         Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE;
117 
118 
119     // property identifiers
120 
121     /** Property identifier: error reporter. */
122     protected static final String ERROR_REPORTER =
123         Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
124 
125     /** Property identifier: entity manager. */
126     protected static final String ENTITY_MANAGER =
127         Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_MANAGER_PROPERTY;
128 
129     /** Property identifier document scanner: */
130     protected static final String DOCUMENT_SCANNER =
131         Constants.XERCES_PROPERTY_PREFIX + Constants.DOCUMENT_SCANNER_PROPERTY;
132 
133     /** Property identifier: DTD scanner. */
134     protected static final String DTD_SCANNER =
135         Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_SCANNER_PROPERTY;
136 
137     /** Property identifier: grammar pool. */
138     protected static final String XMLGRAMMAR_POOL =
139         Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
140 
141     /** Property identifier: DTD validator. */
142     protected static final String DTD_VALIDATOR =
143         Constants.XERCES_PROPERTY_PREFIX + Constants.DTD_VALIDATOR_PROPERTY;
144 
145     /** Property identifier: namespace binder. */
146     protected static final String NAMESPACE_BINDER =
147         Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_BINDER_PROPERTY;
148 
149     /** Property identifier: datatype validator factory. */
150     protected static final String DATATYPE_VALIDATOR_FACTORY =
151         Constants.XERCES_PROPERTY_PREFIX + Constants.DATATYPE_VALIDATOR_FACTORY_PROPERTY;
152 
153     protected static final String VALIDATION_MANAGER =
154         Constants.XERCES_PROPERTY_PREFIX + Constants.VALIDATION_MANAGER_PROPERTY;
155 
156     /** Property identifier: XML Schema validator. */
157     protected static final String SCHEMA_VALIDATOR =
158         Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_VALIDATOR_PROPERTY;
159 
160     /** Property identifier: locale. */
161     protected static final String LOCALE =
162         Constants.XERCES_PROPERTY_PREFIX + Constants.LOCALE_PROPERTY;
163 
164 
165     // debugging
166 
167     /** Set to true and recompile to print exception stack trace. */
168     private static final boolean PRINT_EXCEPTION_STACK_TRACE = false;
169 
170     //
171     // Data
172     //
173 
174     //
175     // XML 1.0 components
176     //
177 
178     /** The XML 1.0 Datatype validator factory. */
179     protected final DTDDVFactory fDatatypeValidatorFactory;
180 
181     /** The XML 1.0 Document scanner. */
182     protected final XMLNSDocumentScannerImpl fNamespaceScanner;
183 
184     /** The XML 1.0 DTD scanner. */
185     protected final XMLDTDScannerImpl fDTDScanner;
186 
187     //
188     // XML 1.1 components
189     //
190 
191     /** The XML 1.1 Datatype validator factory. */
192     protected DTDDVFactory fXML11DatatypeFactory = null;
193 
194     /** The XML 1.1 Document scanner. */
195     protected XML11NSDocumentScannerImpl fXML11NSDocScanner = null;
196 
197     /** The XML 1.1 DTD scanner. **/
198     protected XML11DTDScannerImpl fXML11DTDScanner = null;
199 
200     // common components (non-configurable)
201 
202     /** Current Datatype validator factory. */
203     protected DTDDVFactory fCurrentDVFactory;
204 
205     /** Current scanner */
206     protected XMLDocumentScanner fCurrentScanner;
207 
208     /** Current DTD scanner. */
209     protected XMLDTDScanner fCurrentDTDScanner;
210 
211     /** Grammar pool. */
212     protected XMLGrammarPool fGrammarPool;
213 
214     /** XML version detector. */
215     protected final XMLVersionDetector fVersionDetector;
216 
217     // common components (configurable)
218 
219     /** Error reporter. */
220     protected final XMLErrorReporter fErrorReporter;
221 
222     /** Entity manager. */
223     protected final XMLEntityManager fEntityManager;
224 
225     /** Input Source */
226     protected XMLInputSource fInputSource;
227 
228     protected final ValidationManager fValidationManager;
229     // state
230 
231     /** Locator */
232     protected XMLLocator fLocator;
233 
234     /**
235      * True if a parse is in progress. This state is needed because
236      * some features/properties cannot be set while parsing (e.g.
237      * validation and namespaces).
238      */
239     protected boolean fParseInProgress = false;
240 
241     /**
242      * fConfigUpdated is set to true if there has been any change to the configuration settings,
243      * i.e a feature or a property was changed.
244      */
245     protected boolean fConfigUpdated = false;
246 
247     /** Flag indiciating whether XML11 components have been initialized. */
248     private boolean f11Initialized = false;
249 
250     //
251     // Constructors
252     //
253 
254     /** Default constructor. */
SchemaParsingConfig()255     public SchemaParsingConfig() {
256         this(null, null, null);
257     } // <init>()
258 
259     /**
260      * Constructs a parser configuration using the specified symbol table.
261      *
262      * @param symbolTable The symbol table to use.
263      */
SchemaParsingConfig(SymbolTable symbolTable)264     public SchemaParsingConfig(SymbolTable symbolTable) {
265         this(symbolTable, null, null);
266     } // <init>(SymbolTable)
267 
268     /**
269      * Constructs a parser configuration using the specified symbol table and
270      * grammar pool.
271      * <p>
272      * <strong>REVISIT:</strong>
273      * Grammar pool will be updated when the new validation engine is
274      * implemented.
275      *
276      * @param symbolTable The symbol table to use.
277      * @param grammarPool The grammar pool to use.
278      */
SchemaParsingConfig(SymbolTable symbolTable, XMLGrammarPool grammarPool)279     public SchemaParsingConfig(SymbolTable symbolTable,
280             XMLGrammarPool grammarPool) {
281         this(symbolTable, grammarPool, null);
282     } // <init>(SymbolTable,XMLGrammarPool)
283 
284     /**
285      * Constructs a parser configuration using the specified symbol table,
286      * grammar pool, and parent settings.
287      * <p>
288      * <strong>REVISIT:</strong>
289      * Grammar pool will be updated when the new validation engine is
290      * implemented.
291      *
292      * @param symbolTable    The symbol table to use.
293      * @param grammarPool    The grammar pool to use.
294      * @param parentSettings The parent settings.
295      */
SchemaParsingConfig(SymbolTable symbolTable, XMLGrammarPool grammarPool, XMLComponentManager parentSettings)296     public SchemaParsingConfig(SymbolTable symbolTable,
297             XMLGrammarPool grammarPool,
298             XMLComponentManager parentSettings) {
299         super(symbolTable, parentSettings);
300 
301         // add default recognized features
302         final String[] recognizedFeatures = {
303             PARSER_SETTINGS, WARN_ON_DUPLICATE_ATTDEF,   WARN_ON_UNDECLARED_ELEMDEF,
304             ALLOW_JAVA_ENCODINGS,       CONTINUE_AFTER_FATAL_ERROR,
305             LOAD_EXTERNAL_DTD,          NOTIFY_BUILTIN_REFS,
306             NOTIFY_CHAR_REFS, GENERATE_SYNTHETIC_ANNOTATIONS,
307             XMLConstants.USE_CATALOG,
308             JdkXmlUtils.OVERRIDE_PARSER
309         };
310         addRecognizedFeatures(recognizedFeatures);
311         fFeatures.put(PARSER_SETTINGS, Boolean.TRUE);
312         // set state for default features
313         fFeatures.put(WARN_ON_DUPLICATE_ATTDEF, Boolean.FALSE);
314         //setFeature(WARN_ON_DUPLICATE_ENTITYDEF, false);
315         fFeatures.put(WARN_ON_UNDECLARED_ELEMDEF, Boolean.FALSE);
316         fFeatures.put(ALLOW_JAVA_ENCODINGS, Boolean.FALSE);
317         fFeatures.put(CONTINUE_AFTER_FATAL_ERROR, Boolean.FALSE);
318         fFeatures.put(LOAD_EXTERNAL_DTD, Boolean.TRUE);
319         fFeatures.put(NOTIFY_BUILTIN_REFS, Boolean.FALSE);
320         fFeatures.put(NOTIFY_CHAR_REFS, Boolean.FALSE);
321         fFeatures.put(GENERATE_SYNTHETIC_ANNOTATIONS, Boolean.FALSE);
322         fFeatures.put(XMLConstants.USE_CATALOG, JdkXmlUtils.USE_CATALOG_DEFAULT);
323         fFeatures.put(JdkXmlUtils.OVERRIDE_PARSER, JdkXmlUtils.OVERRIDE_PARSER_DEFAULT);
324 
325         // add default recognized properties
326         final String[] recognizedProperties = {
327             ERROR_REPORTER,
328             ENTITY_MANAGER,
329             DOCUMENT_SCANNER,
330             DTD_SCANNER,
331             DTD_VALIDATOR,
332             NAMESPACE_BINDER,
333             XMLGRAMMAR_POOL,
334             DATATYPE_VALIDATOR_FACTORY,
335             VALIDATION_MANAGER,
336             GENERATE_SYNTHETIC_ANNOTATIONS,
337             LOCALE,
338             JdkXmlUtils.CATALOG_DEFER,
339             JdkXmlUtils.CATALOG_FILES,
340             JdkXmlUtils.CATALOG_PREFER,
341             JdkXmlUtils.CATALOG_RESOLVE,
342             JdkXmlUtils.CDATA_CHUNK_SIZE
343         };
344         addRecognizedProperties(recognizedProperties);
345 
346         fGrammarPool = grammarPool;
347         if (fGrammarPool != null) {
348             setProperty(XMLGRAMMAR_POOL, fGrammarPool);
349         }
350 
351         fEntityManager = new XMLEntityManager();
352         fProperties.put(ENTITY_MANAGER, fEntityManager);
353         addComponent(fEntityManager);
354 
355         fErrorReporter = new XMLErrorReporter();
356         fErrorReporter.setDocumentLocator(fEntityManager.getEntityScanner());
357         fProperties.put(ERROR_REPORTER, fErrorReporter);
358         addComponent(fErrorReporter);
359 
360         fNamespaceScanner = new XMLNSDocumentScannerImpl();
361         fProperties.put(DOCUMENT_SCANNER, fNamespaceScanner);
362         addRecognizedParamsAndSetDefaults(fNamespaceScanner);
363 
364         fDTDScanner = new XMLDTDScannerImpl();
365         fProperties.put(DTD_SCANNER, fDTDScanner);
366         addRecognizedParamsAndSetDefaults(fDTDScanner);
367 
368         fDatatypeValidatorFactory = DTDDVFactory.getInstance();
369         fProperties.put(DATATYPE_VALIDATOR_FACTORY,
370                 fDatatypeValidatorFactory);
371 
372         fValidationManager = new ValidationManager();
373         fProperties.put(VALIDATION_MANAGER, fValidationManager);
374         fProperties.put(JdkXmlUtils.CDATA_CHUNK_SIZE, JdkXmlUtils.CDATA_CHUNK_SIZE_DEFAULT);
375 
376         fVersionDetector = new XMLVersionDetector();
377 
378         // add message formatters
379         if (fErrorReporter.getMessageFormatter(XMLMessageFormatter.XML_DOMAIN) == null) {
380             XMLMessageFormatter xmft = new XMLMessageFormatter();
381             fErrorReporter.putMessageFormatter(XMLMessageFormatter.XML_DOMAIN, xmft);
382             fErrorReporter.putMessageFormatter(XMLMessageFormatter.XMLNS_DOMAIN, xmft);
383         }
384 
385         if (fErrorReporter.getMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN) == null) {
386             XSMessageFormatter xmft = new XSMessageFormatter();
387             fErrorReporter.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN, xmft);
388         }
389 
390         // set locale
391         try {
392             setLocale(Locale.getDefault());
393         }
394         catch (XNIException e) {
395             // do nothing
396             // REVISIT: What is the right thing to do? -Ac
397         }
398 
399     } // <init>(SymbolTable,XMLGrammarPool)
400 
401     //
402     // Public methods
403     //
404 
405     /**
406      * Returns the state of a feature.
407      *
408      * @param featureId The feature identifier.
409      * @return true if the feature is supported
410      *
411      * @throws XMLConfigurationException Thrown for configuration error.
412      *                                   In general, components should
413      *                                   only throw this exception if
414      *                                   it is <strong>really</strong>
415      *                                   a critical error.
416      */
getFeatureState(String featureId)417     public FeatureState getFeatureState(String featureId)
418         throws XMLConfigurationException {
419         // make this feature special
420         if (featureId.equals(PARSER_SETTINGS)) {
421             return FeatureState.is(fConfigUpdated);
422         }
423         return super.getFeatureState(featureId);
424 
425     } // getFeature(String):boolean
426 
427     /**
428      * Set the state of a feature.
429      *
430      * Set the state of any feature in a SAX2 parser.  The parser
431      * might not recognize the feature, and if it does recognize
432      * it, it might not be able to fulfill the request.
433      *
434      * @param featureId The unique identifier (URI) of the feature.
435      * @param state The requested state of the feature (true or false).
436      *
437      * @exception com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException If the
438      *            requested feature is not known.
439      */
setFeature(String featureId, boolean state)440     public void setFeature(String featureId, boolean state)
441         throws XMLConfigurationException {
442 
443         fConfigUpdated = true;
444 
445         // forward to every XML 1.0 component
446         fNamespaceScanner.setFeature(featureId, state);
447         fDTDScanner.setFeature(featureId, state);
448 
449         // forward to every XML 1.1 component
450         if (f11Initialized) {
451             try {
452                 fXML11DTDScanner.setFeature(featureId, state);
453             }
454             // ignore the exception.
455             catch (Exception e) {}
456             try {
457                 fXML11NSDocScanner.setFeature(featureId, state);
458             }
459             // ignore the exception
460             catch (Exception e) {}
461         }
462 
463         // save state if noone "objects"
464         super.setFeature(featureId, state);
465 
466     } // setFeature(String,boolean)
467 
468     /**
469      * Returns the value of a property.
470      *
471      * @param propertyId The property identifier.
472      * @return the value of the property
473      *
474      * @throws XMLConfigurationException Thrown for configuration error.
475      *                                   In general, components should
476      *                                   only throw this exception if
477      *                                   it is <strong>really</strong>
478      *                                   a critical error.
479      */
getPropertyState(String propertyId)480     public PropertyState getPropertyState(String propertyId)
481         throws XMLConfigurationException {
482         if (LOCALE.equals(propertyId)) {
483             return PropertyState.is(getLocale());
484         }
485         return super.getPropertyState(propertyId);
486     }
487 
488     /**
489      * setProperty
490      *
491      * @param propertyId
492      * @param value
493      */
setProperty(String propertyId, Object value)494     public void setProperty(String propertyId, Object value)
495         throws XMLConfigurationException {
496 
497         fConfigUpdated = true;
498         if (LOCALE.equals(propertyId)) {
499             setLocale((Locale) value);
500         }
501 
502         // forward to every XML 1.0 component
503         fNamespaceScanner.setProperty(propertyId, value);
504         fDTDScanner.setProperty(propertyId, value);
505 
506         // forward to every XML 1.1 component
507         if (f11Initialized) {
508             try {
509                 fXML11DTDScanner.setProperty(propertyId, value);
510             }
511             // ignore the exception.
512             catch (Exception e) {}
513             try {
514                 fXML11NSDocScanner.setProperty(propertyId, value);
515             }
516             // ignore the exception
517             catch (Exception e) {}
518         }
519 
520         // store value if noone "objects"
521         super.setProperty(propertyId, value);
522 
523     } // setProperty(String,Object)
524 
525     /**
526      * Set the locale to use for messages.
527      *
528      * @param locale The locale object to use for localization of messages.
529      *
530      * @exception XNIException Thrown if the parser does not support the
531      *                         specified locale.
532      */
setLocale(Locale locale)533     public void setLocale(Locale locale) throws XNIException {
534         super.setLocale(locale);
535         fErrorReporter.setLocale(locale);
536     } // setLocale(Locale)
537 
538     //
539     // XMLPullParserConfiguration methods
540     //
541 
542     // parsing
543 
544     /**
545      * Sets the input source for the document to parse.
546      *
547      * @param inputSource The document's input source.
548      *
549      * @exception XMLConfigurationException Thrown if there is a
550      *                        configuration error when initializing the
551      *                        parser.
552      * @exception IOException Thrown on I/O error.
553      *
554      * @see #parse(boolean)
555      */
setInputSource(XMLInputSource inputSource)556     public void setInputSource(XMLInputSource inputSource)
557     throws XMLConfigurationException, IOException {
558 
559         // REVISIT: this method used to reset all the components and
560         //          construct the pipeline. Now reset() is called
561         //          in parse (boolean) just before we parse the document
562         //          Should this method still throw exceptions..?
563 
564         fInputSource = inputSource;
565 
566     } // setInputSource(XMLInputSource)
567 
568     /**
569      * Parses the document in a pull parsing fashion.
570      *
571      * @param complete True if the pull parser should parse the
572      *                 remaining document completely.
573      *
574      * @return True if there is more document to parse.
575      *
576      * @exception XNIException Any XNI exception, possibly wrapping
577      *                         another exception.
578      * @exception IOException  An IO exception from the parser, possibly
579      *                         from a byte stream or character stream
580      *                         supplied by the parser.
581      *
582      * @see #setInputSource
583      */
parse(boolean complete)584     public boolean parse(boolean complete) throws XNIException, IOException {
585         //
586         // reset and configure pipeline and set InputSource.
587         if (fInputSource != null) {
588             try {
589                 fValidationManager.reset();
590                 fVersionDetector.reset(this);
591                 reset();
592 
593                 short version = fVersionDetector.determineDocVersion(fInputSource);
594                 // XML 1.0
595                 if (version == Constants.XML_VERSION_1_0) {
596                     configurePipeline();
597                     resetXML10();
598                 }
599                 // XML 1.1
600                 else if (version == Constants.XML_VERSION_1_1) {
601                     initXML11Components();
602                     configureXML11Pipeline();
603                     resetXML11();
604                 }
605                 // Unrecoverable error reported during version detection
606                 else {
607                    return false;
608                 }
609 
610                 // mark configuration as fixed
611                 fConfigUpdated = false;
612 
613                 // resets and sets the pipeline.
614                 fVersionDetector.startDocumentParsing((XMLEntityHandler) fCurrentScanner, version);
615                 fInputSource = null;
616             }
617             catch (XNIException ex) {
618                 if (PRINT_EXCEPTION_STACK_TRACE)
619                     ex.printStackTrace();
620                 throw ex;
621             }
622             catch (IOException ex) {
623                 if (PRINT_EXCEPTION_STACK_TRACE)
624                     ex.printStackTrace();
625                 throw ex;
626             }
627             catch (RuntimeException ex) {
628                 if (PRINT_EXCEPTION_STACK_TRACE)
629                     ex.printStackTrace();
630                 throw ex;
631             }
632             catch (Exception ex) {
633                 if (PRINT_EXCEPTION_STACK_TRACE)
634                     ex.printStackTrace();
635                 throw new XNIException(ex);
636             }
637         }
638 
639         try {
640             return fCurrentScanner.scanDocument(complete);
641         }
642         catch (XNIException ex) {
643             if (PRINT_EXCEPTION_STACK_TRACE)
644                 ex.printStackTrace();
645             throw ex;
646         }
647         catch (IOException ex) {
648             if (PRINT_EXCEPTION_STACK_TRACE)
649                 ex.printStackTrace();
650             throw ex;
651         }
652         catch (RuntimeException ex) {
653             if (PRINT_EXCEPTION_STACK_TRACE)
654                 ex.printStackTrace();
655             throw ex;
656         }
657         catch (Exception ex) {
658             if (PRINT_EXCEPTION_STACK_TRACE)
659                 ex.printStackTrace();
660             throw new XNIException(ex);
661         }
662 
663     } // parse(boolean):boolean
664 
665     /**
666      * If the application decides to terminate parsing before the xml document
667      * is fully parsed, the application should call this method to free any
668      * resource allocated during parsing. For example, close all opened streams.
669      */
cleanup()670     public void cleanup() {
671         fEntityManager.closeReaders();
672     }
673 
674     //
675     // XMLParserConfiguration methods
676     //
677 
678     /**
679      * Parses the specified input source.
680      *
681      * @param source The input source.
682      *
683      * @exception XNIException Throws exception on XNI error.
684      * @exception java.io.IOException Throws exception on i/o error.
685      */
parse(XMLInputSource source)686     public void parse(XMLInputSource source) throws XNIException, IOException {
687 
688         if (fParseInProgress) {
689             // REVISIT - need to add new error message
690             throw new XNIException("FWK005 parse may not be called while parsing.");
691         }
692         fParseInProgress = true;
693 
694         try {
695             setInputSource(source);
696             parse(true);
697         }
698         catch (XNIException ex) {
699             if (PRINT_EXCEPTION_STACK_TRACE)
700                 ex.printStackTrace();
701             throw ex;
702         }
703         catch (IOException ex) {
704             if (PRINT_EXCEPTION_STACK_TRACE)
705                 ex.printStackTrace();
706             throw ex;
707         }
708         catch (RuntimeException ex) {
709             if (PRINT_EXCEPTION_STACK_TRACE)
710                 ex.printStackTrace();
711             throw ex;
712         }
713         catch (Exception ex) {
714             if (PRINT_EXCEPTION_STACK_TRACE)
715                 ex.printStackTrace();
716             throw new XNIException(ex);
717         }
718         finally {
719             fParseInProgress = false;
720             // close all streams opened by xerces
721             this.cleanup();
722         }
723 
724     } // parse(InputSource)
725 
726     //
727     // Protected methods
728     //
729 
730     /**
731      * Reset all components before parsing.
732      *
733      * @throws XNIException Thrown if an error occurs during initialization.
734      */
reset()735     public void reset() throws XNIException {
736 
737         // initialize the common components
738         super.reset();
739 
740     } // reset()
741 
742     /** Configures the XML 1.0 pipeline. */
configurePipeline()743     protected void configurePipeline() {
744 
745         if (fCurrentDVFactory != fDatatypeValidatorFactory) {
746             fCurrentDVFactory = fDatatypeValidatorFactory;
747             // use XML 1.0 datatype library
748             setProperty(DATATYPE_VALIDATOR_FACTORY, fCurrentDVFactory);
749         }
750 
751         // setup document pipeline
752         if (fCurrentScanner != fNamespaceScanner) {
753             fCurrentScanner = fNamespaceScanner;
754             setProperty(DOCUMENT_SCANNER, fCurrentScanner);
755         }
756         fNamespaceScanner.setDocumentHandler(fDocumentHandler);
757         if (fDocumentHandler != null) {
758             fDocumentHandler.setDocumentSource(fNamespaceScanner);
759         }
760         fLastComponent = fNamespaceScanner;
761 
762         // setup dtd pipeline
763         if (fCurrentDTDScanner != fDTDScanner) {
764             fCurrentDTDScanner = fDTDScanner;
765             setProperty(DTD_SCANNER, fCurrentDTDScanner);
766         }
767         fDTDScanner.setDTDHandler(fDTDHandler);
768         if (fDTDHandler != null) {
769             fDTDHandler.setDTDSource(fDTDScanner);
770         }
771         fDTDScanner.setDTDContentModelHandler(fDTDContentModelHandler);
772         if (fDTDContentModelHandler != null) {
773             fDTDContentModelHandler.setDTDContentModelSource(fDTDScanner);
774         }
775 
776     } // configurePipeline()
777 
778     /** Configures the XML 1.1 pipeline. */
configureXML11Pipeline()779     protected void configureXML11Pipeline() {
780 
781         if (fCurrentDVFactory != fXML11DatatypeFactory) {
782             fCurrentDVFactory = fXML11DatatypeFactory;
783             // use XML 1.1 datatype library
784             setProperty(DATATYPE_VALIDATOR_FACTORY, fCurrentDVFactory);
785         }
786 
787         // setup document pipeline
788         if (fCurrentScanner != fXML11NSDocScanner) {
789             fCurrentScanner = fXML11NSDocScanner;
790             setProperty(DOCUMENT_SCANNER, fCurrentScanner);
791         }
792         fXML11NSDocScanner.setDocumentHandler(fDocumentHandler);
793         if (fDocumentHandler != null) {
794             fDocumentHandler.setDocumentSource(fXML11NSDocScanner);
795         }
796         fLastComponent = fXML11NSDocScanner;
797 
798         // setup dtd pipeline
799         if (fCurrentDTDScanner != fXML11DTDScanner) {
800             fCurrentDTDScanner = fXML11DTDScanner;
801             setProperty(DTD_SCANNER, fCurrentDTDScanner);
802         }
803         fXML11DTDScanner.setDTDHandler(fDTDHandler);
804         if (fDTDHandler != null) {
805             fDTDHandler.setDTDSource(fXML11DTDScanner);
806         }
807         fXML11DTDScanner.setDTDContentModelHandler(fDTDContentModelHandler);
808         if (fDTDContentModelHandler != null) {
809             fDTDContentModelHandler.setDTDContentModelSource(fXML11DTDScanner);
810         }
811 
812     } // configureXML11Pipeline()
813 
814     // features and properties
815 
816     /**
817      * Check a feature. If feature is know and supported, this method simply
818      * returns. Otherwise, the appropriate exception is thrown.
819      *
820      * @param featureId The unique identifier (URI) of the feature.
821      *
822      * @throws XMLConfigurationException Thrown for configuration error.
823      *                                   In general, components should
824      *                                   only throw this exception if
825      *                                   it is <strong>really</strong>
826      *                                   a critical error.
827      */
checkFeature(String featureId)828     protected FeatureState checkFeature(String featureId)
829         throws XMLConfigurationException {
830 
831         //
832         // Xerces Features
833         //
834 
835         if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
836             final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
837 
838             //
839             // http://apache.org/xml/features/validation/dynamic
840             //   Allows the parser to validate a document only when it
841             //   contains a grammar. Validation is turned on/off based
842             //   on each document instance, automatically.
843             //
844             if (suffixLength == Constants.DYNAMIC_VALIDATION_FEATURE.length() &&
845                     featureId.endsWith(Constants.DYNAMIC_VALIDATION_FEATURE)) {
846                 return FeatureState.RECOGNIZED;
847             }
848             //
849             // http://apache.org/xml/features/validation/default-attribute-values
850             //
851             if (suffixLength == Constants.DEFAULT_ATTRIBUTE_VALUES_FEATURE.length() &&
852                     featureId.endsWith(Constants.DEFAULT_ATTRIBUTE_VALUES_FEATURE)) {
853                 // REVISIT
854                 return FeatureState.NOT_SUPPORTED;
855             }
856             //
857             // http://apache.org/xml/features/validation/default-attribute-values
858             //
859             if (suffixLength == Constants.VALIDATE_CONTENT_MODELS_FEATURE.length() &&
860                     featureId.endsWith(Constants.VALIDATE_CONTENT_MODELS_FEATURE)) {
861                 // REVISIT
862                 return FeatureState.NOT_SUPPORTED;
863             }
864             //
865             // http://apache.org/xml/features/validation/nonvalidating/load-dtd-grammar
866             //
867             if (suffixLength == Constants.LOAD_DTD_GRAMMAR_FEATURE.length() &&
868                     featureId.endsWith(Constants.LOAD_DTD_GRAMMAR_FEATURE)) {
869                 return FeatureState.RECOGNIZED;
870             }
871             //
872             // http://apache.org/xml/features/validation/nonvalidating/load-external-dtd
873             //
874             if (suffixLength == Constants.LOAD_EXTERNAL_DTD_FEATURE.length() &&
875                     featureId.endsWith(Constants.LOAD_EXTERNAL_DTD_FEATURE)) {
876                 return FeatureState.RECOGNIZED;
877             }
878 
879             //
880             // http://apache.org/xml/features/validation/default-attribute-values
881             //
882             if (suffixLength == Constants.VALIDATE_DATATYPES_FEATURE.length() &&
883                     featureId.endsWith(Constants.VALIDATE_DATATYPES_FEATURE)) {
884                 return FeatureState.NOT_SUPPORTED;
885             }
886         }
887 
888         //
889         // Not recognized
890         //
891 
892         return super.checkFeature(featureId);
893 
894     } // checkFeature(String)
895 
896     /**
897      * Check a property. If the property is know and supported, this method
898      * simply returns. Otherwise, the appropriate exception is thrown.
899      *
900      * @param propertyId The unique identifier (URI) of the property
901      *                   being set.
902      *
903      * @throws XMLConfigurationException Thrown for configuration error.
904      *                                   In general, components should
905      *                                   only throw this exception if
906      *                                   it is <strong>really</strong>
907      *                                   a critical error.
908      */
checkProperty(String propertyId)909     protected PropertyState checkProperty(String propertyId)
910         throws XMLConfigurationException {
911 
912         //
913         // Xerces Properties
914         //
915 
916         if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
917             final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
918 
919             if (suffixLength == Constants.DTD_SCANNER_PROPERTY.length() &&
920                     propertyId.endsWith(Constants.DTD_SCANNER_PROPERTY)) {
921                 return PropertyState.RECOGNIZED;
922             }
923         }
924 
925         if (propertyId.startsWith(Constants.JAXP_PROPERTY_PREFIX)) {
926             final int suffixLength = propertyId.length() - Constants.JAXP_PROPERTY_PREFIX.length();
927 
928             if (suffixLength == Constants.SCHEMA_SOURCE.length() &&
929                     propertyId.endsWith(Constants.SCHEMA_SOURCE)) {
930                 return PropertyState.RECOGNIZED;
931             }
932         }
933 
934         //
935         // Not recognized
936         //
937 
938         return super.checkProperty(propertyId);
939 
940     } // checkProperty(String)
941 
942     /**
943      * Adds all of the component's recognized features and properties
944      * to the list of default recognized features and properties, and
945      * sets default values on the configuration for features and
946      * properties which were previously absent from the configuration.
947      *
948      * @param component The component whose recognized features
949      * and properties will be added to the configuration
950      */
addRecognizedParamsAndSetDefaults(XMLComponent component)951     private void addRecognizedParamsAndSetDefaults(XMLComponent component) {
952 
953         // register component's recognized features
954         String[] recognizedFeatures = component.getRecognizedFeatures();
955         addRecognizedFeatures(recognizedFeatures);
956 
957         // register component's recognized properties
958         String[] recognizedProperties = component.getRecognizedProperties();
959         addRecognizedProperties(recognizedProperties);
960 
961         // set default values
962         if (recognizedFeatures != null) {
963             for (int i = 0; i < recognizedFeatures.length; ++i) {
964                 String featureId = recognizedFeatures[i];
965                 Boolean state = component.getFeatureDefault(featureId);
966                 if (state != null) {
967                     // Do not overwrite values already set on the configuration.
968                     if (!fFeatures.containsKey(featureId)) {
969                         fFeatures.put(featureId, state);
970                         // For newly added components who recognize this feature
971                         // but did not offer a default value, we need to make
972                         // sure these components will get an opportunity to read
973                         // the value before parsing begins.
974                         fConfigUpdated = true;
975                     }
976                 }
977             }
978         }
979         if (recognizedProperties != null) {
980             for (int i = 0; i < recognizedProperties.length; ++i) {
981                 String propertyId = recognizedProperties[i];
982                 Object value = component.getPropertyDefault(propertyId);
983                 if (value != null) {
984                     // Do not overwrite values already set on the configuration.
985                     if (!fProperties.containsKey(propertyId)) {
986                         fProperties.put(propertyId, value);
987                         // For newly added components who recognize this property
988                         // but did not offer a default value, we need to make
989                         // sure these components will get an opportunity to read
990                         // the value before parsing begins.
991                         fConfigUpdated = true;
992                     }
993                 }
994             }
995         }
996     }
997 
998     /**
999      * Reset all XML 1.0 components before parsing
1000      */
resetXML10()1001     protected final void resetXML10() throws XNIException {
1002         // Reset XML 1.0 components
1003         fNamespaceScanner.reset(this);
1004         fDTDScanner.reset(this);
1005     } // resetXML10()
1006 
1007     /**
1008      * Reset all XML 1.1 components before parsing
1009      */
resetXML11()1010     protected final void resetXML11() throws XNIException {
1011         // Reset XML 1.1 components
1012         fXML11NSDocScanner.reset(this);
1013         fXML11DTDScanner.reset(this);
1014     } // resetXML11()
1015 
1016     //
1017     // other methods
1018     //
1019 
1020     /** */
resetNodePool()1021     public void resetNodePool() {
1022         // REVISIT: to implement: introduce a node pool to reuse DTM nodes.
1023         //          reset this pool here.
1024     }
1025 
initXML11Components()1026     private void initXML11Components() {
1027         if (!f11Initialized) {
1028             // create datatype factory
1029             fXML11DatatypeFactory = DTDDVFactory.getInstance(XML11_DATATYPE_VALIDATOR_FACTORY);
1030 
1031             // setup XML 1.1 DTD pipeline
1032             fXML11DTDScanner = new XML11DTDScannerImpl();
1033             addRecognizedParamsAndSetDefaults(fXML11DTDScanner);
1034 
1035             // setup XML 1.1. document pipeline - namespace aware
1036             fXML11NSDocScanner = new XML11NSDocumentScannerImpl();
1037             addRecognizedParamsAndSetDefaults(fXML11NSDocScanner);
1038 
1039             f11Initialized = true;
1040         }
1041     }
1042 }
1043