1/*
2 * Copyright (c) 2011, 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.parsers;
22
23import com.sun.org.apache.xerces.internal.impl.Constants;
24import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaValidator;
25import com.sun.org.apache.xerces.internal.impl.xs.XSMessageFormatter;
26import com.sun.org.apache.xerces.internal.util.FeatureState;
27import com.sun.org.apache.xerces.internal.util.PropertyState;
28import com.sun.org.apache.xerces.internal.util.Status;
29import com.sun.org.apache.xerces.internal.util.SymbolTable;
30import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
31import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
32import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
33
34/**
35 * This is the "standard" parser configuration. It extends the DTD
36 * configuration with the standard set of parser components.
37 * The standard set of parser components include those needed
38 * to parse and validate with DTD's, and those needed for XML
39 * Schema.</p>
40 * <p>
41 * In addition to the features and properties recognized by the base
42 * parser configuration, this class recognizes these additional
43 * features and properties:
44 * <ul>
45 * <li>Features
46 *  <ul>
47 *  <li>http://apache.org/xml/features/validation/schema</li>
48 *  <li>http://apache.org/xml/features/validation/schema-full-checking</li>
49 *  <li>http://apache.org/xml/features/validation/schema/normalized-value</li>
50 *  <li>http://apache.org/xml/features/validation/schema/element-default</li>
51 *  </ul>
52 * <li>Properties
53 *  <ul>
54 *   <li>http://apache.org/xml/properties/internal/error-reporter</li>
55 *   <li>http://apache.org/xml/properties/internal/entity-manager</li>
56 *   <li>http://apache.org/xml/properties/internal/document-scanner</li>
57 *   <li>http://apache.org/xml/properties/internal/dtd-scanner</li>
58 *   <li>http://apache.org/xml/properties/internal/grammar-pool</li>
59 *   <li>http://apache.org/xml/properties/internal/validator/dtd</li>
60 *   <li>http://apache.org/xml/properties/internal/datatype-validator-factory</li>
61 *  </ul>
62 * </ul>
63 *
64 * @author Arnaud  Le Hors, IBM
65 * @author Andy Clark, IBM
66 *
67 */
68public class StandardParserConfiguration
69    extends DTDConfiguration {
70
71    //
72    // Constants
73    //
74
75    // feature identifiers
76
77    /** Feature identifier: expose schema normalized value */
78    protected static final String NORMALIZE_DATA =
79    Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_NORMALIZED_VALUE;
80
81
82    /** Feature identifier: send element default value via characters() */
83    protected static final String SCHEMA_ELEMENT_DEFAULT =
84    Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_ELEMENT_DEFAULT;
85
86
87    /** Feature identifier: augment PSVI */
88    protected static final String SCHEMA_AUGMENT_PSVI =
89    Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_AUGMENT_PSVI;
90
91
92    /** feature identifier: XML Schema validation */
93    protected static final String XMLSCHEMA_VALIDATION =
94    Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_VALIDATION_FEATURE;
95
96    /** feature identifier: XML Schema validation -- full checking */
97    protected static final String XMLSCHEMA_FULL_CHECKING =
98    Constants.XERCES_FEATURE_PREFIX + Constants.SCHEMA_FULL_CHECKING;
99
100    /** Feature: generate synthetic annotations */
101    protected static final String GENERATE_SYNTHETIC_ANNOTATIONS =
102        Constants.XERCES_FEATURE_PREFIX + Constants.GENERATE_SYNTHETIC_ANNOTATIONS_FEATURE;
103
104    /** Feature identifier: validate annotations */
105    protected static final String VALIDATE_ANNOTATIONS =
106        Constants.XERCES_FEATURE_PREFIX + Constants.VALIDATE_ANNOTATIONS_FEATURE;
107
108    /** Feature identifier: honour all schemaLocations */
109    protected static final String HONOUR_ALL_SCHEMALOCATIONS =
110        Constants.XERCES_FEATURE_PREFIX + Constants.HONOUR_ALL_SCHEMALOCATIONS_FEATURE;
111
112    /** Feature identifier: whether to ignore xsi:type attributes until a global element declaration is encountered */
113    protected static final String IGNORE_XSI_TYPE =
114        Constants.XERCES_FEATURE_PREFIX + Constants.IGNORE_XSI_TYPE_FEATURE;
115
116    /** Feature identifier: whether to ignore ID/IDREF errors */
117    protected static final String ID_IDREF_CHECKING =
118        Constants.XERCES_FEATURE_PREFIX + Constants.ID_IDREF_CHECKING_FEATURE;
119
120    /** Feature identifier: whether to ignore unparsed entity errors */
121    protected static final String UNPARSED_ENTITY_CHECKING =
122        Constants.XERCES_FEATURE_PREFIX + Constants.UNPARSED_ENTITY_CHECKING_FEATURE;
123
124    /** Feature identifier: whether to ignore identity constraint errors */
125    protected static final String IDENTITY_CONSTRAINT_CHECKING =
126        Constants.XERCES_FEATURE_PREFIX + Constants.IDC_CHECKING_FEATURE;
127
128    /** Feature identifier: namespace growth */
129    protected static final String NAMESPACE_GROWTH =
130        Constants.XERCES_FEATURE_PREFIX + Constants.NAMESPACE_GROWTH_FEATURE;
131
132    /** Feature identifier: tolerate duplicates */
133    protected static final String TOLERATE_DUPLICATES =
134        Constants.XERCES_FEATURE_PREFIX + Constants.TOLERATE_DUPLICATES_FEATURE;
135
136    // property identifiers
137
138    /** Property identifier: XML Schema validator. */
139    protected static final String SCHEMA_VALIDATOR =
140        Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_VALIDATOR_PROPERTY;
141
142    /** Property identifier: schema location. */
143    protected static final String SCHEMA_LOCATION =
144    Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_LOCATION;
145
146    /** Property identifier: no namespace schema location. */
147    protected static final String SCHEMA_NONS_LOCATION =
148    Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_NONS_LOCATION;
149
150    /** Property identifier: Schema DV Factory */
151    protected static final String SCHEMA_DV_FACTORY =
152        Constants.XERCES_PROPERTY_PREFIX + Constants.SCHEMA_DV_FACTORY_PROPERTY;
153
154    /** Property identifier: root type definition. */
155    protected static final String ROOT_TYPE_DEF =
156        Constants.XERCES_PROPERTY_PREFIX + Constants.ROOT_TYPE_DEFINITION_PROPERTY;
157
158    /** Property identifier: root element declaration. */
159    protected static final String ROOT_ELEMENT_DECL =
160        Constants.XERCES_PROPERTY_PREFIX + Constants.ROOT_ELEMENT_DECLARATION_PROPERTY;
161
162    //
163    // Data
164    //
165
166    // components (non-configurable)
167
168    /** XML Schema Validator. */
169    protected XMLSchemaValidator fSchemaValidator;
170
171    //
172    // Constructors
173    //
174
175    /** Default constructor. */
176    public StandardParserConfiguration() {
177        this(null, null, null);
178    } // <init>()
179
180    /**
181     * Constructs a parser configuration using the specified symbol table.
182     *
183     * @param symbolTable The symbol table to use.
184     */
185    public StandardParserConfiguration(SymbolTable symbolTable) {
186        this(symbolTable, null, null);
187    } // <init>(SymbolTable)
188
189    /**
190     * Constructs a parser configuration using the specified symbol table and
191     * grammar pool.
192     * <p>
193     * <strong>REVISIT:</strong>
194     * Grammar pool will be updated when the new validation engine is
195     * implemented.
196     *
197     * @param symbolTable The symbol table to use.
198     * @param grammarPool The grammar pool to use.
199     */
200    public StandardParserConfiguration(SymbolTable symbolTable,
201                                       XMLGrammarPool grammarPool) {
202        this(symbolTable, grammarPool, null);
203    } // <init>(SymbolTable,XMLGrammarPool)
204
205    /**
206     * Constructs a parser configuration using the specified symbol table,
207     * grammar pool, and parent settings.
208     * <p>
209     * <strong>REVISIT:</strong>
210     * Grammar pool will be updated when the new validation engine is
211     * implemented.
212     *
213     * @param symbolTable    The symbol table to use.
214     * @param grammarPool    The grammar pool to use.
215     * @param parentSettings The parent settings.
216     */
217    public StandardParserConfiguration(SymbolTable symbolTable,
218                                       XMLGrammarPool grammarPool,
219                                       XMLComponentManager parentSettings) {
220        super(symbolTable, grammarPool, parentSettings);
221
222        // add default recognized features
223        final String[] recognizedFeatures = {
224            NORMALIZE_DATA,
225            SCHEMA_ELEMENT_DEFAULT,
226            SCHEMA_AUGMENT_PSVI,
227            GENERATE_SYNTHETIC_ANNOTATIONS,
228            VALIDATE_ANNOTATIONS,
229            HONOUR_ALL_SCHEMALOCATIONS,
230            NAMESPACE_GROWTH,
231            TOLERATE_DUPLICATES,
232            // NOTE: These shouldn't really be here but since the XML Schema
233            //       validator is constructed dynamically, its recognized
234            //       features might not have been set and it would cause a
235            //       not-recognized exception to be thrown. -Ac
236            XMLSCHEMA_VALIDATION,
237            XMLSCHEMA_FULL_CHECKING,
238            IGNORE_XSI_TYPE,
239            ID_IDREF_CHECKING,
240            IDENTITY_CONSTRAINT_CHECKING,
241            UNPARSED_ENTITY_CHECKING,
242        };
243        addRecognizedFeatures(recognizedFeatures);
244
245        // set state for default features
246        setFeature(SCHEMA_ELEMENT_DEFAULT, true);
247        setFeature(NORMALIZE_DATA, true);
248        setFeature(SCHEMA_AUGMENT_PSVI, true);
249        setFeature(GENERATE_SYNTHETIC_ANNOTATIONS, false);
250        setFeature(VALIDATE_ANNOTATIONS, false);
251        setFeature(HONOUR_ALL_SCHEMALOCATIONS, false);
252        setFeature(IGNORE_XSI_TYPE, false);
253        setFeature(ID_IDREF_CHECKING, true);
254        setFeature(IDENTITY_CONSTRAINT_CHECKING, true);
255        setFeature(UNPARSED_ENTITY_CHECKING, true);
256        setFeature(NAMESPACE_GROWTH, false);
257        setFeature(TOLERATE_DUPLICATES, false);
258
259        // add default recognized properties
260
261        final String[] recognizedProperties = {
262            // NOTE: These shouldn't really be here but since the XML Schema
263            //       validator is constructed dynamically, its recognized
264            //       properties might not have been set and it would cause a
265            //       not-recognized exception to be thrown. -Ac
266            SCHEMA_LOCATION,
267            SCHEMA_NONS_LOCATION,
268            ROOT_TYPE_DEF,
269            ROOT_ELEMENT_DECL,
270            SCHEMA_DV_FACTORY,
271        };
272
273        addRecognizedProperties(recognizedProperties);
274    } // <init>(SymbolTable,XMLGrammarPool)
275
276    //
277    // Public methods
278    //
279
280    /** Configures the pipeline. */
281    protected void configurePipeline() {
282        super.configurePipeline();
283        if ( getFeature(XMLSCHEMA_VALIDATION )) {
284            // If schema validator was not in the pipeline insert it.
285            if (fSchemaValidator == null) {
286                fSchemaValidator = new XMLSchemaValidator();
287
288                // add schema component
289                fProperties.put(SCHEMA_VALIDATOR, fSchemaValidator);
290                addComponent(fSchemaValidator);
291                 // add schema message formatter
292                if (fErrorReporter.getMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN) == null) {
293                    XSMessageFormatter xmft = new XSMessageFormatter();
294                    fErrorReporter.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN, xmft);
295                }
296
297            }
298            fLastComponent = fSchemaValidator;
299            fNamespaceBinder.setDocumentHandler(fSchemaValidator);
300
301            fSchemaValidator.setDocumentHandler(fDocumentHandler);
302            fSchemaValidator.setDocumentSource(fNamespaceBinder);
303        }
304
305
306    } // configurePipeline()
307
308    // features and properties
309
310    /**
311     * Check a feature. If feature is know and supported, this method simply
312     * returns. Otherwise, the appropriate exception is thrown.
313     *
314     * @param featureId The unique identifier (URI) of the feature.
315     *
316     * @throws XMLConfigurationException Thrown for configuration error.
317     *                                   In general, components should
318     *                                   only throw this exception if
319     *                                   it is <strong>really</strong>
320     *                                   a critical error.
321     */
322    protected FeatureState checkFeature(String featureId)
323        throws XMLConfigurationException {
324
325        //
326        // Xerces Features
327        //
328
329        if (featureId.startsWith(Constants.XERCES_FEATURE_PREFIX)) {
330            final int suffixLength = featureId.length() - Constants.XERCES_FEATURE_PREFIX.length();
331
332            //
333            // http://apache.org/xml/features/validation/schema
334            //   Lets the user turn Schema validation support on/off.
335            //
336            if (suffixLength == Constants.SCHEMA_VALIDATION_FEATURE.length() &&
337                featureId.endsWith(Constants.SCHEMA_VALIDATION_FEATURE)) {
338                return FeatureState.RECOGNIZED;
339            }
340            // activate full schema checking
341            if (suffixLength == Constants.SCHEMA_FULL_CHECKING.length() &&
342                featureId.endsWith(Constants.SCHEMA_FULL_CHECKING)) {
343                return FeatureState.RECOGNIZED;
344            }
345            // Feature identifier: expose schema normalized value
346            //  http://apache.org/xml/features/validation/schema/normalized-value
347            if (suffixLength == Constants.SCHEMA_NORMALIZED_VALUE.length() &&
348                featureId.endsWith(Constants.SCHEMA_NORMALIZED_VALUE)) {
349                return FeatureState.RECOGNIZED;
350            }
351            // Feature identifier: send element default value via characters()
352            // http://apache.org/xml/features/validation/schema/element-default
353            if (suffixLength == Constants.SCHEMA_ELEMENT_DEFAULT.length() &&
354                featureId.endsWith(Constants.SCHEMA_ELEMENT_DEFAULT)) {
355                return FeatureState.RECOGNIZED;
356            }
357        }
358
359        //
360        // Not recognized
361        //
362
363        return super.checkFeature(featureId);
364
365    } // checkFeature(String)
366
367    /**
368     * Check a property. If the property is know and supported, this method
369     * simply returns. Otherwise, the appropriate exception is thrown.
370     *
371     * @param propertyId The unique identifier (URI) of the property
372     *                   being set.
373     *
374     * @throws XMLConfigurationException Thrown for configuration error.
375     *                                   In general, components should
376     *                                   only throw this exception if
377     *                                   it is <strong>really</strong>
378     *                                   a critical error.
379     */
380    protected PropertyState checkProperty(String propertyId)
381        throws XMLConfigurationException {
382
383        //
384        // Xerces Properties
385        //
386
387        if (propertyId.startsWith(Constants.XERCES_PROPERTY_PREFIX)) {
388            final int suffixLength = propertyId.length() - Constants.XERCES_PROPERTY_PREFIX.length();
389
390            if (suffixLength == Constants.SCHEMA_LOCATION.length() &&
391                propertyId.endsWith(Constants.SCHEMA_LOCATION)) {
392                return PropertyState.RECOGNIZED;
393            }
394            if (suffixLength == Constants.SCHEMA_NONS_LOCATION.length() &&
395                propertyId.endsWith(Constants.SCHEMA_NONS_LOCATION)) {
396                return PropertyState.RECOGNIZED;
397            }
398        }
399
400        if (propertyId.startsWith(Constants.JAXP_PROPERTY_PREFIX)) {
401            final int suffixLength = propertyId.length() - Constants.JAXP_PROPERTY_PREFIX.length();
402
403            if (suffixLength == Constants.SCHEMA_SOURCE.length() &&
404                propertyId.endsWith(Constants.SCHEMA_SOURCE)) {
405                return PropertyState.RECOGNIZED;
406            }
407        }
408
409        //
410        // Not recognized
411        //
412
413        return super.checkProperty(propertyId);
414
415    } // checkProperty(String)
416
417} // class StandardParserConfiguration
418