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 java.io.IOException;
25
26import com.sun.org.apache.xerces.internal.impl.Constants;
27import com.sun.org.apache.xerces.internal.impl.dtd.DTDGrammar;
28import com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDLoader;
29import com.sun.org.apache.xerces.internal.impl.xs.SchemaGrammar;
30import com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader;
31import com.sun.org.apache.xerces.internal.impl.xs.XSMessageFormatter;
32import com.sun.org.apache.xerces.internal.util.SymbolTable;
33import com.sun.org.apache.xerces.internal.util.SynchronizedSymbolTable;
34import com.sun.org.apache.xerces.internal.util.XMLGrammarPoolImpl;
35import com.sun.org.apache.xerces.internal.xni.XNIException;
36import com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
37import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
38import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
39import com.sun.org.apache.xerces.internal.xni.parser.XMLComponentManager;
40import com.sun.org.apache.xerces.internal.xni.parser.XMLConfigurationException;
41import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
42import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
43
44/**
45 * <p> This configuration provides a generic way of using
46 * Xerces's grammar caching facilities.  It extends the
47 * XIncludeAwareParserConfiguration and thus may validate documents
48 * according to XML schemas or DTD's.  It also allows the user to
49 * preparse a grammar, and to lock the grammar pool
50 * implementation such that no more grammars will be added.</p>
51 * <p> Using the com.sun.org.apache.xerces.internal.xni.parser property, an
52 * application may instantiate a Xerces SAX or DOM parser with
53 * this configuration.  When invoked in this manner, the default
54 * behaviour will be elicited; to use this configuration's
55 * specific facilities, the user will need to reference it
56 * directly.</p>
57 * <p>
58 * In addition to the features and properties recognized by the base
59 * parser configuration, this class recognizes these additional
60 * features and properties:
61 * <ul>
62 * </ul>
63 *
64 * @author Neil Graham, IBM
65 *
66 */
67public class XMLGrammarCachingConfiguration
68    extends XIncludeAwareParserConfiguration {
69
70    //
71    // Constants
72    //
73
74    // a larg(ish) prime to use for a symbol table to be shared
75    // among
76    // potentially man parsers.  Start one as close to 2K (20
77    // times larger than normal) and see what happens...
78    public static final int BIG_PRIME = 2039;
79
80    // the static symbol table to be shared amongst parsers
81    protected static final SynchronizedSymbolTable fStaticSymbolTable =
82            new SynchronizedSymbolTable(BIG_PRIME);
83
84    // the Grammar Pool to be shared similarly
85    protected static final XMLGrammarPoolImpl fStaticGrammarPool =
86            new XMLGrammarPoolImpl();
87
88    // schema full checking constant
89    protected static final String SCHEMA_FULL_CHECKING =
90            Constants.XERCES_FEATURE_PREFIX+Constants.SCHEMA_FULL_CHECKING;
91
92    // Data
93
94    // variables needed for caching schema grammars.
95    protected XMLSchemaLoader fSchemaLoader;
96
97    // the DTD grammar loader
98    protected XMLDTDLoader fDTDLoader;
99
100    //
101    // Constructors
102    //
103
104    /** Default constructor. */
105    public XMLGrammarCachingConfiguration() {
106        this(fStaticSymbolTable, fStaticGrammarPool, null);
107    } // <init>()
108
109    /**
110     * Constructs a parser configuration using the specified symbol table.
111     *
112     * @param symbolTable The symbol table to use.
113     */
114    public XMLGrammarCachingConfiguration(SymbolTable symbolTable) {
115        this(symbolTable, fStaticGrammarPool, null);
116    } // <init>(SymbolTable)
117
118    /**
119     * Constructs a parser configuration using the specified symbol table and
120     * grammar pool.
121     * <p>
122     * <strong>REVISIT:</strong>
123     * Grammar pool will be updated when the new validation engine is
124     * implemented.
125     *
126     * @param symbolTable The symbol table to use.
127     * @param grammarPool The grammar pool to use.
128     */
129    public XMLGrammarCachingConfiguration(SymbolTable symbolTable,
130                                       XMLGrammarPool grammarPool) {
131        this(symbolTable, grammarPool, null);
132    } // <init>(SymbolTable,XMLGrammarPool)
133
134    /**
135     * Constructs a parser configuration using the specified symbol table,
136     * grammar pool, and parent settings.
137     * <p>
138     * <strong>REVISIT:</strong>
139     * Grammar pool will be updated when the new validation engine is
140     * implemented.
141     *
142     * @param symbolTable    The symbol table to use.
143     * @param grammarPool    The grammar pool to use.
144     * @param parentSettings The parent settings.
145     */
146    public XMLGrammarCachingConfiguration(SymbolTable symbolTable,
147                                       XMLGrammarPool grammarPool,
148                                       XMLComponentManager parentSettings) {
149        super(symbolTable, grammarPool, parentSettings);
150
151        // REVISIT:  may need to add some features/properties
152        // specific to this configuration at some point...
153
154        // add default recognized features
155        // set state for default features
156        // add default recognized properties
157        // create and register missing components
158        fSchemaLoader = new XMLSchemaLoader(fSymbolTable);
159        fSchemaLoader.setProperty(XMLGRAMMAR_POOL, fGrammarPool);
160
161        // and set up the DTD loader too:
162        fDTDLoader = new XMLDTDLoader(fSymbolTable, fGrammarPool);
163    } // <init>(SymbolTable,XMLGrammarPool, XMLComponentManager)
164
165    //
166    // Public methods
167    //
168
169    /*
170     * lock the XMLGrammarPoolImpl object so that it does not
171     * accept any more grammars from the validators.
172     */
173    public void lockGrammarPool() {
174        fGrammarPool.lockPool();
175    } // lockGrammarPool()
176
177    /*
178     * clear the XMLGrammarPoolImpl object so that it does not
179     * contain any more grammars.
180     */
181    public void clearGrammarPool() {
182        fGrammarPool.clear();
183    } // clearGrammarPool()
184
185    /*
186     * unlock the XMLGrammarPoolImpl object so that it
187     * accepts more grammars from the validators.
188     */
189    public void unlockGrammarPool() {
190        fGrammarPool.unlockPool();
191    } // unlockGrammarPool()
192
193    /**
194     * Parse a grammar from a location identified by an URI.
195     * This method also adds this grammar to the XMLGrammarPool
196     *
197     * @param type The type of the grammar to be constructed
198     * @param uri The location of the grammar to be constructed.
199     * <strong>The parser will not expand this URI or make it
200     * available to the EntityResolver</strong>
201     * @return The newly created <code>Grammar</code>.
202     * @exception XNIException thrown on an error in grammar
203     * construction
204     * @exception IOException thrown if an error is encountered
205     * in reading the file
206     */
207    public Grammar parseGrammar(String type, String uri)
208                              throws XNIException, IOException {
209        XMLInputSource source = new XMLInputSource(null, uri, null, false);
210        return parseGrammar(type, source);
211
212    }
213
214    /**
215     * Parse a grammar from a location identified by an
216     * XMLInputSource.
217     * This method also adds this grammar to the XMLGrammarPool
218     *
219     * @param type The type of the grammar to be constructed
220     * @param is The XMLInputSource containing this grammar's
221     * information
222     * <strong>If a URI is included in the systemId field, the parser will not expand this URI or make it
223     * available to the EntityResolver</strong>
224     * @return The newly created <code>Grammar</code>.
225     * @exception XNIException thrown on an error in grammar
226     * construction
227     * @exception IOException thrown if an error is encountered
228     * in reading the file
229     */
230    public Grammar parseGrammar(String type, XMLInputSource
231                is) throws XNIException, IOException {
232        if(type.equals(XMLGrammarDescription.XML_SCHEMA)) {
233            // by default, make all XMLGrammarPoolImpl's schema grammars available to fSchemaHandler
234            return parseXMLSchema(is);
235        } else if(type.equals(XMLGrammarDescription.XML_DTD)) {
236            return parseDTD(is);
237        }
238        // don't know this grammar...
239        return null;
240    } // parseGrammar(String, XMLInputSource):  Grammar
241
242    //
243    // Protected methods
244    //
245
246    // package-protected methods
247
248    /* This method parses an XML Schema document.
249     * It requires a GrammarBucket parameter so that DOMASBuilder can
250     * extract the info it needs.
251     * Therefore, bucket must not be null!
252     */
253    SchemaGrammar parseXMLSchema(XMLInputSource is)
254                throws IOException {
255        XMLEntityResolver resolver = getEntityResolver();
256        if(resolver != null) {
257            fSchemaLoader.setEntityResolver(resolver);
258        }
259        if (fErrorReporter.getMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN) == null) {
260            fErrorReporter.putMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN, new XSMessageFormatter());
261        }
262        fSchemaLoader.setProperty(ERROR_REPORTER, fErrorReporter);
263
264        String propPrefix = Constants.XERCES_PROPERTY_PREFIX;
265        String propName = propPrefix + Constants.SCHEMA_LOCATION;
266        fSchemaLoader.setProperty(propName, getProperty(propName));
267        propName = propPrefix + Constants.SCHEMA_NONS_LOCATION;
268        fSchemaLoader.setProperty(propName, getProperty(propName));
269        propName = Constants.JAXP_PROPERTY_PREFIX+Constants.SCHEMA_SOURCE;
270        fSchemaLoader.setProperty(propName, getProperty(propName));
271        fSchemaLoader.setFeature(SCHEMA_FULL_CHECKING, getFeature(SCHEMA_FULL_CHECKING));
272
273        // Should check whether the grammar with this namespace is already in
274        // the grammar resolver. But since we don't know the target namespace
275        // of the document here, we leave such check to XSDHandler
276        SchemaGrammar grammar = (SchemaGrammar)fSchemaLoader.loadGrammar(is);
277        // by default, hand it off to the grammar pool
278        if (grammar != null) {
279            fGrammarPool.cacheGrammars(XMLGrammarDescription.XML_SCHEMA,
280                                      new Grammar[]{grammar});
281        }
282
283        return grammar;
284
285    } // parseXMLSchema(XMLInputSource) :  SchemaGrammar
286
287    /* This method parses an external DTD entity.
288     */
289    DTDGrammar parseDTD(XMLInputSource is)
290                throws IOException {
291        XMLEntityResolver resolver = getEntityResolver();
292        if(resolver != null) {
293            fDTDLoader.setEntityResolver(resolver);
294        }
295        fDTDLoader.setProperty(ERROR_REPORTER, fErrorReporter);
296
297        // Should check whether the grammar with this namespace is already in
298        // the grammar resolver. But since we don't know the target namespace
299        // of the document here, we leave such check to the application...
300        DTDGrammar grammar = (DTDGrammar)fDTDLoader.loadGrammar(is);
301        // by default, hand it off to the grammar pool
302        if (grammar != null) {
303            fGrammarPool.cacheGrammars(XMLGrammarDescription.XML_DTD,
304                                      new Grammar[]{grammar});
305        }
306
307        return grammar;
308
309    } // parseXMLDTD(XMLInputSource) :  DTDGrammar
310
311
312} // class XMLGrammarCachingConfiguration
313