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