1/*
2 * reserved comment block
3 * DO NOT REMOVE OR ALTER!
4 */
5/*
6 * Licensed to the Apache Software Foundation (ASF) under one or more
7 * contributor license agreements.  See the NOTICE file distributed with
8 * this work for additional information regarding copyright ownership.
9 * The ASF licenses this file to You under the Apache License, Version 2.0
10 * (the "License"); you may not use this file except in compliance with
11 * the License.  You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 */
21
22package com.sun.org.apache.xerces.internal.parsers;
23
24import com.sun.org.apache.xerces.internal.impl.Constants;
25import com.sun.org.apache.xerces.internal.util.FeatureState;
26import com.sun.org.apache.xerces.internal.util.NamespaceSupport;
27import com.sun.org.apache.xerces.internal.util.SymbolTable;
28import com.sun.org.apache.xerces.internal.xinclude.XIncludeHandler;
29import com.sun.org.apache.xerces.internal.xinclude.XIncludeNamespaceSupport;
30import com.sun.org.apache.xerces.internal.xni.NamespaceContext;
31import com.sun.org.apache.xerces.internal.xni.XMLDocumentHandler;
32import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
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;
36
37/**
38 * This class is the configuration used to parse XML 1.0 and XML 1.1 documents
39 * and provides support for XInclude. This is the default Xerces configuration.
40 *
41 * @author Michael Glavassevich, IBM
42 *
43 */
44public class XIncludeAwareParserConfiguration extends XML11Configuration {
45
46    /** Feature identifier: allow notation and unparsed entity events to be sent out of order. */
47    protected static final String ALLOW_UE_AND_NOTATION_EVENTS =
48        Constants.SAX_FEATURE_PREFIX + Constants.ALLOW_DTD_EVENTS_AFTER_ENDDTD_FEATURE;
49
50    /** Feature identifier: fixup base URIs. */
51    protected static final String XINCLUDE_FIXUP_BASE_URIS =
52        Constants.XERCES_FEATURE_PREFIX + Constants.XINCLUDE_FIXUP_BASE_URIS_FEATURE;
53
54    /** Feature identifier: fixup language. */
55    protected static final String XINCLUDE_FIXUP_LANGUAGE =
56        Constants.XERCES_FEATURE_PREFIX + Constants.XINCLUDE_FIXUP_LANGUAGE_FEATURE;
57
58    /** Feature identifier: XInclude processing */
59    protected static final String XINCLUDE_FEATURE =
60        Constants.XERCES_FEATURE_PREFIX + Constants.XINCLUDE_FEATURE;
61
62    /** Property identifier: error reporter. */
63    protected static final String XINCLUDE_HANDLER =
64        Constants.XERCES_PROPERTY_PREFIX + Constants.XINCLUDE_HANDLER_PROPERTY;
65
66    /** Property identifier: error reporter. */
67    protected static final String NAMESPACE_CONTEXT =
68        Constants.XERCES_PROPERTY_PREFIX + Constants.NAMESPACE_CONTEXT_PROPERTY;
69
70    //
71    // Components
72    //
73
74    /** XInclude handler. */
75    protected XIncludeHandler fXIncludeHandler;
76
77    /** Non-XInclude NamespaceContext. */
78    protected NamespaceSupport fNonXIncludeNSContext;
79
80    /** XInclude NamespaceContext. */
81    protected XIncludeNamespaceSupport fXIncludeNSContext;
82
83    /** Current NamespaceContext. */
84    protected NamespaceContext fCurrentNSContext;
85
86    /** Flag indicating whether XInclude processsing is enabled. */
87    protected boolean fXIncludeEnabled = false;
88
89    /** Default constructor. */
90    public XIncludeAwareParserConfiguration() {
91        this(null, null, null);
92    } // <init>()
93
94    /**
95     * Constructs a parser configuration using the specified symbol table.
96     *
97     * @param symbolTable The symbol table to use.
98     */
99    public XIncludeAwareParserConfiguration(SymbolTable symbolTable) {
100        this(symbolTable, null, null);
101    } // <init>(SymbolTable)
102
103    /**
104     * Constructs a parser configuration using the specified symbol table and
105     * grammar pool.
106     * <p>
107     *
108     * @param symbolTable The symbol table to use.
109     * @param grammarPool The grammar pool to use.
110     */
111    public XIncludeAwareParserConfiguration(
112            SymbolTable symbolTable,
113            XMLGrammarPool grammarPool) {
114        this(symbolTable, grammarPool, null);
115    } // <init>(SymbolTable,XMLGrammarPool)
116
117    /**
118     * Constructs a parser configuration using the specified symbol table,
119     * grammar pool, and parent settings.
120     * <p>
121     *
122     * @param symbolTable    The symbol table to use.
123     * @param grammarPool    The grammar pool to use.
124     * @param parentSettings The parent settings.
125     */
126    public XIncludeAwareParserConfiguration(
127            SymbolTable symbolTable,
128            XMLGrammarPool grammarPool,
129            XMLComponentManager parentSettings) {
130        super(symbolTable, grammarPool, parentSettings);
131
132        final String[] recognizedFeatures = {
133                ALLOW_UE_AND_NOTATION_EVENTS,
134                XINCLUDE_FIXUP_BASE_URIS,
135                XINCLUDE_FIXUP_LANGUAGE
136        };
137        addRecognizedFeatures(recognizedFeatures);
138
139        // add default recognized properties
140        final String[] recognizedProperties =
141        { XINCLUDE_HANDLER, NAMESPACE_CONTEXT };
142        addRecognizedProperties(recognizedProperties);
143
144        setFeature(ALLOW_UE_AND_NOTATION_EVENTS, true);
145        setFeature(XINCLUDE_FIXUP_BASE_URIS, true);
146        setFeature(XINCLUDE_FIXUP_LANGUAGE, true);
147
148        fNonXIncludeNSContext = new NamespaceSupport();
149        fCurrentNSContext = fNonXIncludeNSContext;
150        setProperty(NAMESPACE_CONTEXT, fNonXIncludeNSContext);
151    }
152
153
154    /** Configures the pipeline. */
155    protected void configurePipeline() {
156        super.configurePipeline();
157        if (fXIncludeEnabled) {
158            // If the XInclude handler was not in the pipeline insert it.
159            if (fXIncludeHandler == null) {
160                fXIncludeHandler = new XIncludeHandler();
161                // add XInclude component
162                setProperty(XINCLUDE_HANDLER, fXIncludeHandler);
163                addCommonComponent(fXIncludeHandler);
164                fXIncludeHandler.reset(this);
165            }
166            // Setup NamespaceContext
167            if (fCurrentNSContext != fXIncludeNSContext) {
168                if (fXIncludeNSContext == null) {
169                    fXIncludeNSContext = new XIncludeNamespaceSupport();
170                }
171                fCurrentNSContext = fXIncludeNSContext;
172                setProperty(NAMESPACE_CONTEXT, fXIncludeNSContext);
173            }
174            //configure DTD pipeline
175            fDTDScanner.setDTDHandler(fDTDProcessor);
176            fDTDProcessor.setDTDSource(fDTDScanner);
177            fDTDProcessor.setDTDHandler(fXIncludeHandler);
178            fXIncludeHandler.setDTDSource(fDTDProcessor);
179            fXIncludeHandler.setDTDHandler(fDTDHandler);
180            if (fDTDHandler != null) {
181                fDTDHandler.setDTDSource(fXIncludeHandler);
182            }
183
184            // configure XML document pipeline: insert after DTDValidator and
185            // before XML Schema validator
186            XMLDocumentSource prev = null;
187            if (fFeatures.get(XMLSCHEMA_VALIDATION) == Boolean.TRUE) {
188                // we don't have to worry about fSchemaValidator being null, since
189                // super.configurePipeline() instantiated it if the feature was set
190                prev = fSchemaValidator.getDocumentSource();
191            }
192            // Otherwise, insert after the last component in the pipeline
193            else {
194                prev = fLastComponent;
195                fLastComponent = fXIncludeHandler;
196            }
197
198            XMLDocumentHandler next = prev.getDocumentHandler();
199            prev.setDocumentHandler(fXIncludeHandler);
200            fXIncludeHandler.setDocumentSource(prev);
201            if (next != null) {
202                fXIncludeHandler.setDocumentHandler(next);
203                next.setDocumentSource(fXIncludeHandler);
204            }
205        }
206        else {
207            // Setup NamespaceContext
208            if (fCurrentNSContext != fNonXIncludeNSContext) {
209                fCurrentNSContext = fNonXIncludeNSContext;
210                setProperty(NAMESPACE_CONTEXT, fNonXIncludeNSContext);
211            }
212        }
213    } // configurePipeline()
214
215    protected void configureXML11Pipeline() {
216        super.configureXML11Pipeline();
217        if (fXIncludeEnabled) {
218            // If the XInclude handler was not in the pipeline insert it.
219            if (fXIncludeHandler == null) {
220                fXIncludeHandler = new XIncludeHandler();
221                // add XInclude component
222                setProperty(XINCLUDE_HANDLER, fXIncludeHandler);
223                addCommonComponent(fXIncludeHandler);
224                fXIncludeHandler.reset(this);
225            }
226            // Setup NamespaceContext
227            if (fCurrentNSContext != fXIncludeNSContext) {
228                if (fXIncludeNSContext == null) {
229                    fXIncludeNSContext = new XIncludeNamespaceSupport();
230                }
231                fCurrentNSContext = fXIncludeNSContext;
232                setProperty(NAMESPACE_CONTEXT, fXIncludeNSContext);
233            }
234            // configure XML 1.1. DTD pipeline
235            fXML11DTDScanner.setDTDHandler(fXML11DTDProcessor);
236            fXML11DTDProcessor.setDTDSource(fXML11DTDScanner);
237            fXML11DTDProcessor.setDTDHandler(fXIncludeHandler);
238            fXIncludeHandler.setDTDSource(fXML11DTDProcessor);
239            fXIncludeHandler.setDTDHandler(fDTDHandler);
240            if (fDTDHandler != null) {
241                fDTDHandler.setDTDSource(fXIncludeHandler);
242            }
243
244            // configure XML document pipeline: insert after DTDValidator and
245            // before XML Schema validator
246            XMLDocumentSource prev = null;
247            if (fFeatures.get(XMLSCHEMA_VALIDATION) == Boolean.TRUE) {
248                // we don't have to worry about fSchemaValidator being null, since
249                // super.configurePipeline() instantiated it if the feature was set
250                prev = fSchemaValidator.getDocumentSource();
251            }
252            // Otherwise, insert after the last component in the pipeline
253            else {
254                prev = fLastComponent;
255                fLastComponent = fXIncludeHandler;
256            }
257
258            XMLDocumentHandler next = prev.getDocumentHandler();
259            prev.setDocumentHandler(fXIncludeHandler);
260            fXIncludeHandler.setDocumentSource(prev);
261            if (next != null) {
262                fXIncludeHandler.setDocumentHandler(next);
263                next.setDocumentSource(fXIncludeHandler);
264            }
265        }
266        else {
267            // Setup NamespaceContext
268            if (fCurrentNSContext != fNonXIncludeNSContext) {
269                fCurrentNSContext = fNonXIncludeNSContext;
270                setProperty(NAMESPACE_CONTEXT, fNonXIncludeNSContext);
271            }
272        }
273    } // configureXML11Pipeline()
274
275    public FeatureState getFeatureState(String featureId)
276        throws XMLConfigurationException {
277        if (featureId.equals(PARSER_SETTINGS)) {
278            return FeatureState.is(fConfigUpdated);
279        }
280        else if (featureId.equals(XINCLUDE_FEATURE)) {
281            return FeatureState.is(fXIncludeEnabled);
282        }
283        return super.getFeatureState0(featureId);
284
285    } // getFeature(String):boolean
286
287    public void setFeature(String featureId, boolean state)
288        throws XMLConfigurationException {
289        if (featureId.equals(XINCLUDE_FEATURE)) {
290            fXIncludeEnabled = state;
291            fConfigUpdated = true;
292            return;
293        }
294        super.setFeature(featureId,state);
295    }
296
297}
298