1/*
2 * Copyright (c) 2010, 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
21package com.sun.org.apache.xerces.internal.jaxp;
22
23import com.sun.org.apache.xerces.internal.impl.Constants;
24import com.sun.org.apache.xerces.internal.impl.validation.ValidationManager;
25import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator;
26import com.sun.org.apache.xerces.internal.jaxp.validation.XSGrammarPoolContainer;
27import com.sun.org.apache.xerces.internal.util.SAXMessageFormatter;
28import com.sun.org.apache.xerces.internal.util.Status;
29import com.sun.org.apache.xerces.internal.utils.XMLSecurityManager;
30import com.sun.org.apache.xerces.internal.utils.XMLSecurityPropertyManager;
31import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
32import com.sun.org.apache.xerces.internal.xni.parser.XMLComponent;
33import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
34import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
35import com.sun.org.apache.xerces.internal.xni.parser.XMLDocumentSource;
36import com.sun.org.apache.xerces.internal.xni.parser.XMLParserConfiguration;
37import com.sun.org.apache.xerces.internal.xs.AttributePSVI;
38import com.sun.org.apache.xerces.internal.xs.ElementPSVI;
39import com.sun.org.apache.xerces.internal.xs.PSVIProvider;
40import java.io.IOException;
41import java.util.HashMap;
42import java.util.Iterator;
43import java.util.Locale;
44import java.util.Map;
45import javax.xml.XMLConstants;
46import javax.xml.validation.Schema;
47import org.xml.sax.EntityResolver;
48import org.xml.sax.ErrorHandler;
49import org.xml.sax.HandlerBase;
50import org.xml.sax.InputSource;
51import org.xml.sax.Parser;
52import org.xml.sax.SAXException;
53import org.xml.sax.SAXNotRecognizedException;
54import org.xml.sax.SAXNotSupportedException;
55import org.xml.sax.XMLReader;
56import org.xml.sax.helpers.DefaultHandler;
57
58/**
59 * This is the implementation specific class for the
60 * <code>javax.xml.parsers.SAXParser</code>.
61 *
62 * @author Rajiv Mordani
63 * @author Edwin Goei
64 *
65 */
66@SuppressWarnings("deprecation")
67public class SAXParserImpl extends javax.xml.parsers.SAXParser
68    implements JAXPConstants, PSVIProvider {
69
70    /** Feature identifier: namespaces. */
71    private static final String NAMESPACES_FEATURE =
72        Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACES_FEATURE;
73
74    /** Feature identifier: namespace prefixes. */
75    private static final String NAMESPACE_PREFIXES_FEATURE =
76        Constants.SAX_FEATURE_PREFIX + Constants.NAMESPACE_PREFIXES_FEATURE;
77
78    /** Feature identifier: validation. */
79    private static final String VALIDATION_FEATURE =
80        Constants.SAX_FEATURE_PREFIX + Constants.VALIDATION_FEATURE;
81
82    /** Feature identifier: XML Schema validation */
83    private static final String XMLSCHEMA_VALIDATION_FEATURE =
84        Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
85
86    /** Feature identifier: XInclude processing */
87    private static final String XINCLUDE_FEATURE =
88        Constants.XERCES_FEATURE_PREFIX + Constants.XINCLUDE_FEATURE;
89
90    /** Property identifier: security manager. */
91    private static final String SECURITY_MANAGER =
92        Constants.XERCES_PROPERTY_PREFIX + Constants.SECURITY_MANAGER_PROPERTY;
93
94    /** Property identifier: Security property manager. */
95    private static final String XML_SECURITY_PROPERTY_MANAGER =
96            Constants.XML_SECURITY_PROPERTY_MANAGER;
97
98    private final JAXPSAXParser xmlReader;
99    private String schemaLanguage = null;     // null means DTD
100    private final Schema grammar;
101
102    private final XMLComponent fSchemaValidator;
103    private final XMLComponentManager fSchemaValidatorComponentManager;
104    private final ValidationManager fSchemaValidationManager;
105    private final UnparsedEntityHandler fUnparsedEntityHandler;
106
107    /** Initial ErrorHandler */
108    private final ErrorHandler fInitErrorHandler;
109
110    /** Initial EntityResolver */
111    private final EntityResolver fInitEntityResolver;
112
113    private final XMLSecurityManager fSecurityManager;
114    private final XMLSecurityPropertyManager fSecurityPropertyMgr;
115
116    /**
117     * Create a SAX parser with the associated features
118     * @param features Map of SAX features, may be null
119     */
120    SAXParserImpl(SAXParserFactoryImpl spf, Map<String, Boolean> features)
121        throws SAXException {
122        this(spf, features, false);
123    }
124
125    /**
126     * Create a SAX parser with the associated features
127     * @param features Map of SAX features, may be null
128     */
129    SAXParserImpl(SAXParserFactoryImpl spf, Map<String, Boolean> features, boolean secureProcessing)
130        throws SAXException
131    {
132        fSecurityManager = new XMLSecurityManager(secureProcessing);
133        fSecurityPropertyMgr = new XMLSecurityPropertyManager();
134        // Instantiate a SAXParser directly and not through SAX so that we use the right ClassLoader
135        xmlReader = new JAXPSAXParser(this, fSecurityPropertyMgr, fSecurityManager);
136
137        // JAXP "namespaceAware" == SAX Namespaces feature
138        // Note: there is a compatibility problem here with default values:
139        // JAXP default is false while SAX 2 default is true!
140        xmlReader.setFeature0(NAMESPACES_FEATURE, spf.isNamespaceAware());
141
142        // SAX "namespaces" and "namespace-prefixes" features should not
143        // both be false.  We make them opposite for backward compatibility
144        // since JAXP 1.0 apps may want to receive xmlns* attributes.
145        xmlReader.setFeature0(NAMESPACE_PREFIXES_FEATURE, !spf.isNamespaceAware());
146
147        // Avoid setting the XInclude processing feature if the value is false.
148        // This will keep the configuration from throwing an exception if it
149        // does not support XInclude.
150        if (spf.isXIncludeAware()) {
151            xmlReader.setFeature0(XINCLUDE_FEATURE, true);
152        }
153
154        xmlReader.setProperty0(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr);
155
156        xmlReader.setProperty0(SECURITY_MANAGER, fSecurityManager);
157
158        if (secureProcessing) {
159            /**
160             * By default, secure processing is set, no external access is allowed.
161             * However, we need to check if it is actively set on the factory since we
162             * allow the use of the System Property or jaxp.properties to override
163             * the default value
164             */
165            if (features != null) {
166
167                Boolean temp = features.get(XMLConstants.FEATURE_SECURE_PROCESSING);
168                if (temp != null && temp) {
169                    fSecurityPropertyMgr.setValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_DTD,
170                            XMLSecurityPropertyManager.State.FSP, Constants.EXTERNAL_ACCESS_DEFAULT_FSP);
171                    fSecurityPropertyMgr.setValue(XMLSecurityPropertyManager.Property.ACCESS_EXTERNAL_SCHEMA,
172                            XMLSecurityPropertyManager.State.FSP, Constants.EXTERNAL_ACCESS_DEFAULT_FSP);
173                }
174            }
175        }
176
177        // Set application's features, followed by validation features.
178        setFeatures(features);
179
180        // If validating, provide a default ErrorHandler that prints
181        // validation errors with a warning telling the user to set an
182        // ErrorHandler.
183        if (spf.isValidating()) {
184            fInitErrorHandler = new DefaultValidationErrorHandler(xmlReader.getLocale());
185            xmlReader.setErrorHandler(fInitErrorHandler);
186        }
187        else {
188            fInitErrorHandler = xmlReader.getErrorHandler();
189        }
190        xmlReader.setFeature0(VALIDATION_FEATURE, spf.isValidating());
191
192        // Get the Schema object from the factory
193        this.grammar = spf.getSchema();
194        if (grammar != null) {
195            XMLParserConfiguration config = xmlReader.getXMLParserConfiguration();
196            XMLComponent validatorComponent = null;
197            /** For Xerces grammars, use built-in schema validator. **/
198            if (grammar instanceof XSGrammarPoolContainer) {
199                validatorComponent = new XMLSchemaValidator();
200                fSchemaValidationManager = new ValidationManager();
201                fUnparsedEntityHandler = new UnparsedEntityHandler(fSchemaValidationManager);
202                config.setDTDHandler(fUnparsedEntityHandler);
203                fUnparsedEntityHandler.setDTDHandler(xmlReader);
204                xmlReader.setDTDSource(fUnparsedEntityHandler);
205                fSchemaValidatorComponentManager = new SchemaValidatorConfiguration(config,
206                        (XSGrammarPoolContainer) grammar, fSchemaValidationManager);
207            }
208            /** For third party grammars, use the JAXP validator component. **/
209            else {
210                validatorComponent = new JAXPValidatorComponent(grammar.newValidatorHandler());
211                fSchemaValidationManager = null;
212                fUnparsedEntityHandler = null;
213                fSchemaValidatorComponentManager = config;
214            }
215            config.addRecognizedFeatures(validatorComponent.getRecognizedFeatures());
216            config.addRecognizedProperties(validatorComponent.getRecognizedProperties());
217            config.setDocumentHandler((XMLDocumentHandler) validatorComponent);
218            ((XMLDocumentSource)validatorComponent).setDocumentHandler(xmlReader);
219            xmlReader.setDocumentSource((XMLDocumentSource) validatorComponent);
220            fSchemaValidator = validatorComponent;
221        }
222        else {
223            fSchemaValidationManager = null;
224            fUnparsedEntityHandler = null;
225            fSchemaValidatorComponentManager = null;
226            fSchemaValidator = null;
227        }
228
229        // Initial EntityResolver
230        fInitEntityResolver = xmlReader.getEntityResolver();
231    }
232
233    /**
234     * Set any features of our XMLReader based on any features set on the
235     * SAXParserFactory.
236     *
237     * XXX Does not handle possible conflicts between SAX feature names and
238     * JAXP specific feature names, eg. SAXParserFactory.isValidating()
239     */
240    private void setFeatures(Map<String, Boolean> features)
241        throws SAXNotSupportedException, SAXNotRecognizedException {
242        if (features != null) {
243            for (Map.Entry<String, Boolean> entry : features.entrySet()) {
244                xmlReader.setFeature0(entry.getKey(), entry.getValue());
245            }
246        }
247    }
248
249    public Parser getParser() throws SAXException {
250        // Xerces2 AbstractSAXParser implements SAX1 Parser
251        // assert(xmlReader instanceof Parser);
252        return (Parser) xmlReader;
253    }
254
255    /**
256     * Returns the XMLReader that is encapsulated by the implementation of
257     * this class.
258     */
259    public XMLReader getXMLReader() {
260        return xmlReader;
261    }
262
263    public boolean isNamespaceAware() {
264        try {
265            return xmlReader.getFeature(NAMESPACES_FEATURE);
266        }
267        catch (SAXException x) {
268            throw new IllegalStateException(x.getMessage());
269        }
270    }
271
272    public boolean isValidating() {
273        try {
274            return xmlReader.getFeature(VALIDATION_FEATURE);
275        }
276        catch (SAXException x) {
277            throw new IllegalStateException(x.getMessage());
278        }
279    }
280
281    /**
282     * Gets the XInclude processing mode for this parser
283     * @return the state of XInclude processing mode
284     */
285    public boolean isXIncludeAware() {
286        try {
287            return xmlReader.getFeature(XINCLUDE_FEATURE);
288        }
289        catch (SAXException exc) {
290            return false;
291        }
292    }
293
294    /**
295     * Sets the particular property in the underlying implementation of
296     * org.xml.sax.XMLReader.
297     */
298    public void setProperty(String name, Object value)
299        throws SAXNotRecognizedException, SAXNotSupportedException {
300        xmlReader.setProperty(name, value);
301    }
302
303    /**
304     * returns the particular property requested for in the underlying
305     * implementation of org.xml.sax.XMLReader.
306     */
307    public Object getProperty(String name)
308        throws SAXNotRecognizedException, SAXNotSupportedException {
309        return xmlReader.getProperty(name);
310    }
311
312    public void parse(InputSource is, DefaultHandler dh)
313        throws SAXException, IOException {
314        if (is == null) {
315            throw new IllegalArgumentException();
316        }
317        if (dh != null) {
318            xmlReader.setContentHandler(dh);
319            xmlReader.setEntityResolver(dh);
320            xmlReader.setErrorHandler(dh);
321            xmlReader.setDTDHandler(dh);
322            xmlReader.setDocumentHandler(null);
323        }
324        xmlReader.parse(is);
325    }
326
327    public void parse(InputSource is, HandlerBase hb)
328        throws SAXException, IOException {
329        if (is == null) {
330            throw new IllegalArgumentException();
331        }
332        if (hb != null) {
333            xmlReader.setDocumentHandler(hb);
334            xmlReader.setEntityResolver(hb);
335            xmlReader.setErrorHandler(hb);
336            xmlReader.setDTDHandler(hb);
337            xmlReader.setContentHandler(null);
338        }
339        xmlReader.parse(is);
340    }
341
342    public Schema getSchema() {
343        return grammar;
344    }
345
346    public void reset() {
347        try {
348            /** Restore initial values of features and properties. **/
349            xmlReader.restoreInitState();
350        }
351        catch (SAXException exc) {
352            // This should never happen. We only store recognized
353            // features and properties in the hash maps. For now
354            // just ignore it.
355        }
356        /** Restore various handlers. **/
357        xmlReader.setContentHandler(null);
358        xmlReader.setDTDHandler(null);
359        if (xmlReader.getErrorHandler() != fInitErrorHandler) {
360            xmlReader.setErrorHandler(fInitErrorHandler);
361        }
362        if (xmlReader.getEntityResolver() != fInitEntityResolver) {
363            xmlReader.setEntityResolver(fInitEntityResolver);
364        }
365    }
366
367    /*
368     * PSVIProvider methods
369     */
370
371    public ElementPSVI getElementPSVI() {
372        return ((PSVIProvider)xmlReader).getElementPSVI();
373    }
374
375    public AttributePSVI getAttributePSVI(int index) {
376        return ((PSVIProvider)xmlReader).getAttributePSVI(index);
377    }
378
379    public AttributePSVI getAttributePSVIByName(String uri, String localname) {
380        return ((PSVIProvider)xmlReader).getAttributePSVIByName(uri, localname);
381    }
382
383    /**
384     * Extension of SAXParser. This class tracks changes to
385     * features and properties to allow the parser to be reset to
386     * its initial state.
387     */
388    public static class JAXPSAXParser extends com.sun.org.apache.xerces.internal.parsers.SAXParser {
389
390        private final HashMap fInitFeatures = new HashMap();
391        private final HashMap fInitProperties = new HashMap();
392        private final SAXParserImpl fSAXParser;
393        private XMLSecurityManager fSecurityManager;
394        private XMLSecurityPropertyManager fSecurityPropertyMgr;
395
396
397        public JAXPSAXParser() {
398            this(null, null, null);
399        }
400
401        JAXPSAXParser(SAXParserImpl saxParser, XMLSecurityPropertyManager securityPropertyMgr,
402                XMLSecurityManager securityManager) {
403            super();
404            fSAXParser = saxParser;
405            fSecurityManager = securityManager;
406            fSecurityPropertyMgr = securityPropertyMgr;
407            /**
408             * This class may be used directly. So initialize the security manager if
409             * it is null.
410             */
411            if (fSecurityManager == null) {
412                fSecurityManager = new XMLSecurityManager(true);
413                try {
414                    super.setProperty(SECURITY_MANAGER, fSecurityManager);
415                } catch (SAXException e) {
416                    throw new UnsupportedOperationException(
417                    SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
418                    "property-not-recognized", new Object [] {SECURITY_MANAGER}), e);
419                }
420            }
421            if (fSecurityPropertyMgr == null) {
422                fSecurityPropertyMgr = new XMLSecurityPropertyManager();
423                try {
424                    super.setProperty(XML_SECURITY_PROPERTY_MANAGER, fSecurityPropertyMgr);
425                } catch (SAXException e) {
426                    throw new UnsupportedOperationException(
427                    SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
428                    "property-not-recognized", new Object [] {SECURITY_MANAGER}), e);
429                }
430            }
431        }
432
433        /**
434         * Override SAXParser's setFeature method to track the initial state
435         * of features. This keeps us from affecting the performance of the
436         * SAXParser when it is created with XMLReaderFactory.
437         */
438        public synchronized void setFeature(String name, boolean value)
439            throws SAXNotRecognizedException, SAXNotSupportedException {
440            if (name == null) {
441                // TODO: Add localized error message.
442                throw new NullPointerException();
443            }
444            if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
445                try {
446                    fSecurityManager.setSecureProcessing(value);
447                    setProperty(SECURITY_MANAGER, fSecurityManager);
448                }
449                catch (SAXNotRecognizedException exc) {
450                    // If the property is not supported
451                    // re-throw the exception if the value is true.
452                    if (value) {
453                        throw exc;
454                    }
455                }
456                catch (SAXNotSupportedException exc) {
457                    // If the property is not supported
458                    // re-throw the exception if the value is true.
459                    if (value) {
460                        throw exc;
461                    }
462                }
463                return;
464            }
465            if (!fInitFeatures.containsKey(name)) {
466                boolean current = super.getFeature(name);
467                fInitFeatures.put(name, current ? Boolean.TRUE : Boolean.FALSE);
468            }
469            /** Forward feature to the schema validator if there is one. **/
470            if (fSAXParser != null && fSAXParser.fSchemaValidator != null) {
471                setSchemaValidatorFeature(name, value);
472            }
473            super.setFeature(name, value);
474        }
475
476        public synchronized boolean getFeature(String name)
477            throws SAXNotRecognizedException, SAXNotSupportedException {
478            if (name == null) {
479                // TODO: Add localized error message.
480                throw new NullPointerException();
481            }
482            if (name.equals(XMLConstants.FEATURE_SECURE_PROCESSING)) {
483                return fSecurityManager.isSecureProcessing();
484            }
485            return super.getFeature(name);
486        }
487
488        /**
489         * Override SAXParser's setProperty method to track the initial state
490         * of properties. This keeps us from affecting the performance of the
491         * SAXParser when it is created with XMLReaderFactory.
492         */
493        public synchronized void setProperty(String name, Object value)
494            throws SAXNotRecognizedException, SAXNotSupportedException {
495            if (name == null) {
496                // TODO: Add localized error message.
497                throw new NullPointerException();
498            }
499            if (fSAXParser != null) {
500                // JAXP 1.2 support
501                if (JAXP_SCHEMA_LANGUAGE.equals(name)) {
502                    // The spec says if a schema is given via SAXParserFactory
503                    // the JAXP 1.2 properties shouldn't be allowed.
504                    if (fSAXParser.grammar != null) {
505                        throw new SAXNotSupportedException(
506                                SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), "schema-already-specified", new Object[] {name}));
507                    }
508                    if ( W3C_XML_SCHEMA.equals(value) ) {
509                        //None of the properties will take effect till the setValidating(true) has been called
510                        if( fSAXParser.isValidating() ) {
511                            fSAXParser.schemaLanguage = W3C_XML_SCHEMA;
512                            setFeature(XMLSCHEMA_VALIDATION_FEATURE, true);
513                            // this will allow the parser not to emit DTD-related
514                            // errors, as the spec demands
515                            if (!fInitProperties.containsKey(JAXP_SCHEMA_LANGUAGE)) {
516                                fInitProperties.put(JAXP_SCHEMA_LANGUAGE, super.getProperty(JAXP_SCHEMA_LANGUAGE));
517                            }
518                            super.setProperty(JAXP_SCHEMA_LANGUAGE, W3C_XML_SCHEMA);
519                        }
520
521                    }
522                    else if (value == null) {
523                        fSAXParser.schemaLanguage = null;
524                        setFeature(XMLSCHEMA_VALIDATION_FEATURE, false);
525                    }
526                    else {
527                        // REVISIT: It would be nice if we could format this message
528                        // using a user specified locale as we do in the underlying
529                        // XMLReader -- mrglavas
530                        throw new SAXNotSupportedException(
531                            SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), "schema-not-supported", null));
532                    }
533                    return;
534                }
535                else if (JAXP_SCHEMA_SOURCE.equals(name)) {
536                    // The spec says if a schema is given via SAXParserFactory
537                    // the JAXP 1.2 properties shouldn't be allowed.
538                    if (fSAXParser.grammar != null) {
539                        throw new SAXNotSupportedException(
540                                SAXMessageFormatter.formatMessage(fConfiguration.getLocale(), "schema-already-specified", new Object[] {name}));
541                    }
542                    String val = (String)getProperty(JAXP_SCHEMA_LANGUAGE);
543                    if ( val != null && W3C_XML_SCHEMA.equals(val) ) {
544                        if (!fInitProperties.containsKey(JAXP_SCHEMA_SOURCE)) {
545                            fInitProperties.put(JAXP_SCHEMA_SOURCE, super.getProperty(JAXP_SCHEMA_SOURCE));
546                        }
547                        super.setProperty(name, value);
548                    }
549                    else {
550                        throw new SAXNotSupportedException(
551                            SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
552                            "jaxp-order-not-supported",
553                            new Object[] {JAXP_SCHEMA_LANGUAGE, JAXP_SCHEMA_SOURCE}));
554                    }
555                    return;
556                }
557            }
558            /** Forward property to the schema validator if there is one. **/
559            if (fSAXParser != null && fSAXParser.fSchemaValidator != null) {
560                setSchemaValidatorProperty(name, value);
561            }
562
563            //check if the property is managed by security manager
564            if (fSecurityManager == null ||
565                    !fSecurityManager.setLimit(name, XMLSecurityManager.State.APIPROPERTY, value)) {
566                //check if the property is managed by security property manager
567                if (fSecurityPropertyMgr == null ||
568                        !fSecurityPropertyMgr.setValue(name, XMLSecurityPropertyManager.State.APIPROPERTY, value)) {
569                    //fall back to the existing property manager
570                    if (!fInitProperties.containsKey(name)) {
571                        fInitProperties.put(name, super.getProperty(name));
572                    }
573                    super.setProperty(name, value);
574                }
575            }
576
577        }
578
579        public synchronized Object getProperty(String name)
580            throws SAXNotRecognizedException, SAXNotSupportedException {
581            if (name == null) {
582                // TODO: Add localized error message.
583                throw new NullPointerException();
584            }
585            if (fSAXParser != null && JAXP_SCHEMA_LANGUAGE.equals(name)) {
586                // JAXP 1.2 support
587                return fSAXParser.schemaLanguage;
588            }
589
590            /** Check to see if the property is managed by the security manager **/
591            String propertyValue = (fSecurityManager != null) ?
592                    fSecurityManager.getLimitAsString(name) : null;
593            if (propertyValue != null) {
594                return propertyValue;
595            } else {
596                propertyValue = (fSecurityPropertyMgr != null) ?
597                    fSecurityPropertyMgr.getValue(name) : null;
598                if (propertyValue != null) {
599                    return propertyValue;
600                }
601            }
602
603            return super.getProperty(name);
604        }
605
606        synchronized void restoreInitState()
607            throws SAXNotRecognizedException, SAXNotSupportedException {
608            Iterator iter;
609            if (!fInitFeatures.isEmpty()) {
610                iter = fInitFeatures.entrySet().iterator();
611                while (iter.hasNext()) {
612                    Map.Entry entry = (Map.Entry) iter.next();
613                    String name = (String) entry.getKey();
614                    boolean value = ((Boolean) entry.getValue()).booleanValue();
615                    super.setFeature(name, value);
616                }
617                fInitFeatures.clear();
618            }
619            if (!fInitProperties.isEmpty()) {
620                iter = fInitProperties.entrySet().iterator();
621                while (iter.hasNext()) {
622                    Map.Entry entry = (Map.Entry) iter.next();
623                    String name = (String) entry.getKey();
624                    Object value = entry.getValue();
625                    super.setProperty(name, value);
626                }
627                fInitProperties.clear();
628            }
629        }
630
631        public void parse(InputSource inputSource)
632            throws SAXException, IOException {
633            if (fSAXParser != null && fSAXParser.fSchemaValidator != null) {
634                if (fSAXParser.fSchemaValidationManager != null) {
635                    fSAXParser.fSchemaValidationManager.reset();
636                    fSAXParser.fUnparsedEntityHandler.reset();
637                }
638                resetSchemaValidator();
639            }
640            super.parse(inputSource);
641        }
642
643        public void parse(String systemId)
644            throws SAXException, IOException {
645            if (fSAXParser != null && fSAXParser.fSchemaValidator != null) {
646                if (fSAXParser.fSchemaValidationManager != null) {
647                    fSAXParser.fSchemaValidationManager.reset();
648                    fSAXParser.fUnparsedEntityHandler.reset();
649                }
650                resetSchemaValidator();
651            }
652            super.parse(systemId);
653        }
654
655        XMLParserConfiguration getXMLParserConfiguration() {
656            return fConfiguration;
657        }
658
659        void setFeature0(String name, boolean value)
660            throws SAXNotRecognizedException, SAXNotSupportedException {
661            super.setFeature(name, value);
662        }
663
664        boolean getFeature0(String name)
665            throws SAXNotRecognizedException, SAXNotSupportedException {
666            return super.getFeature(name);
667        }
668
669        void setProperty0(String name, Object value)
670            throws SAXNotRecognizedException, SAXNotSupportedException {
671            super.setProperty(name, value);
672        }
673
674        Object getProperty0(String name)
675            throws SAXNotRecognizedException, SAXNotSupportedException {
676            return super.getProperty(name);
677        }
678
679        Locale getLocale() {
680            return fConfiguration.getLocale();
681        }
682
683        private void setSchemaValidatorFeature(String name, boolean value)
684            throws SAXNotRecognizedException, SAXNotSupportedException {
685            try {
686                fSAXParser.fSchemaValidator.setFeature(name, value);
687            }
688            // This should never be thrown from the schema validator.
689            catch (XMLConfigurationException e) {
690                String identifier = e.getIdentifier();
691                if (e.getType() == Status.NOT_RECOGNIZED) {
692                    throw new SAXNotRecognizedException(
693                        SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
694                        "feature-not-recognized", new Object [] {identifier}));
695                }
696                else {
697                    throw new SAXNotSupportedException(
698                        SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
699                        "feature-not-supported", new Object [] {identifier}));
700                }
701            }
702        }
703
704        private void setSchemaValidatorProperty(String name, Object value)
705            throws SAXNotRecognizedException, SAXNotSupportedException {
706            try {
707                fSAXParser.fSchemaValidator.setProperty(name, value);
708            }
709            // This should never be thrown from the schema validator.
710            catch (XMLConfigurationException e) {
711                String identifier = e.getIdentifier();
712                if (e.getType() == Status.NOT_RECOGNIZED) {
713                    throw new SAXNotRecognizedException(
714                        SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
715                        "property-not-recognized", new Object [] {identifier}));
716                }
717                else {
718                    throw new SAXNotSupportedException(
719                        SAXMessageFormatter.formatMessage(fConfiguration.getLocale(),
720                        "property-not-supported", new Object [] {identifier}));
721                }
722            }
723        }
724
725        private void resetSchemaValidator() throws SAXException {
726            try {
727                fSAXParser.fSchemaValidator.reset(fSAXParser.fSchemaValidatorComponentManager);
728            }
729            // This should never be thrown from the schema validator.
730            catch (XMLConfigurationException e) {
731                throw new SAXException(e);
732            }
733        }
734    }
735}
736