001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.xerces.parsers;
019:
020: import java.io.IOException;
021:
022: import org.apache.xerces.impl.Constants;
023: import org.apache.xerces.impl.dtd.DTDGrammar;
024: import org.apache.xerces.impl.dtd.XMLDTDLoader;
025: import org.apache.xerces.impl.xs.SchemaGrammar;
026: import org.apache.xerces.impl.xs.XMLSchemaLoader;
027: import org.apache.xerces.impl.xs.XSMessageFormatter;
028: import org.apache.xerces.util.SymbolTable;
029: import org.apache.xerces.util.SynchronizedSymbolTable;
030: import org.apache.xerces.util.XMLGrammarPoolImpl;
031: import org.apache.xerces.xni.XNIException;
032: import org.apache.xerces.xni.grammars.Grammar;
033: import org.apache.xerces.xni.grammars.XMLGrammarDescription;
034: import org.apache.xerces.xni.grammars.XMLGrammarPool;
035: import org.apache.xerces.xni.parser.XMLComponentManager;
036: import org.apache.xerces.xni.parser.XMLConfigurationException;
037: import org.apache.xerces.xni.parser.XMLEntityResolver;
038: import org.apache.xerces.xni.parser.XMLInputSource;
039:
040: /**
041: * <p> This configuration provides a generic way of using
042: * Xerces's grammar caching facilities. It extends the
043: * XIncludeAwareParserConfiguration and thus may validate documents
044: * according to XML schemas or DTD's. It also allows the user to
045: * preparse a grammar, and to lock the grammar pool
046: * implementation such that no more grammars will be added.</p>
047: * <p> Using the org.apache.xerces.xni.parser property, an
048: * application may instantiate a Xerces SAX or DOM parser with
049: * this configuration. When invoked in this manner, the default
050: * behaviour will be elicited; to use this configuration's
051: * specific facilities, the user will need to reference it
052: * directly.</p>
053: * <p>
054: * In addition to the features and properties recognized by the base
055: * parser configuration, this class recognizes these additional
056: * features and properties:
057: * <ul>
058: * </ul>
059: *
060: * @author Neil Graham, IBM
061: *
062: * @version $Id: XMLGrammarCachingConfiguration.java 447239 2006-09-18 05:08:26Z mrglavas $
063: */
064: public class XMLGrammarCachingConfiguration extends
065: XIncludeAwareParserConfiguration {
066:
067: //
068: // Constants
069: //
070:
071: // a larg(ish) prime to use for a symbol table to be shared
072: // among
073: // potentially man parsers. Start one as close to 2K (20
074: // times larger than normal) and see what happens...
075: public static final int BIG_PRIME = 2039;
076:
077: // the static symbol table to be shared amongst parsers
078: protected static final SynchronizedSymbolTable fStaticSymbolTable = new SynchronizedSymbolTable(
079: BIG_PRIME);
080:
081: // the Grammar Pool to be shared similarly
082: protected static final XMLGrammarPoolImpl fStaticGrammarPool = new XMLGrammarPoolImpl();
083:
084: // schema full checking constant
085: protected static final String SCHEMA_FULL_CHECKING = Constants.XERCES_FEATURE_PREFIX
086: + Constants.SCHEMA_FULL_CHECKING;
087:
088: // Data
089:
090: // variables needed for caching schema grammars.
091: protected XMLSchemaLoader fSchemaLoader;
092:
093: // the DTD grammar loader
094: protected XMLDTDLoader fDTDLoader;
095:
096: //
097: // Constructors
098: //
099:
100: /** Default constructor. */
101: public XMLGrammarCachingConfiguration() {
102: this (fStaticSymbolTable, fStaticGrammarPool, null);
103: } // <init>()
104:
105: /**
106: * Constructs a parser configuration using the specified symbol table.
107: *
108: * @param symbolTable The symbol table to use.
109: */
110: public XMLGrammarCachingConfiguration(SymbolTable symbolTable) {
111: this (symbolTable, fStaticGrammarPool, null);
112: } // <init>(SymbolTable)
113:
114: /**
115: * Constructs a parser configuration using the specified symbol table and
116: * grammar pool.
117: * <p>
118: * <strong>REVISIT:</strong>
119: * Grammar pool will be updated when the new validation engine is
120: * implemented.
121: *
122: * @param symbolTable The symbol table to use.
123: * @param grammarPool The grammar pool to use.
124: */
125: public XMLGrammarCachingConfiguration(SymbolTable symbolTable,
126: XMLGrammarPool grammarPool) {
127: this (symbolTable, grammarPool, null);
128: } // <init>(SymbolTable,XMLGrammarPool)
129:
130: /**
131: * Constructs a parser configuration using the specified symbol table,
132: * grammar pool, and parent settings.
133: * <p>
134: * <strong>REVISIT:</strong>
135: * Grammar pool will be updated when the new validation engine is
136: * implemented.
137: *
138: * @param symbolTable The symbol table to use.
139: * @param grammarPool The grammar pool to use.
140: * @param parentSettings The parent settings.
141: */
142: public XMLGrammarCachingConfiguration(SymbolTable symbolTable,
143: XMLGrammarPool grammarPool,
144: XMLComponentManager parentSettings) {
145: super (symbolTable, grammarPool, parentSettings);
146:
147: // REVISIT: may need to add some features/properties
148: // specific to this configuration at some point...
149:
150: // add default recognized features
151: // set state for default features
152: // add default recognized properties
153: // create and register missing components
154: fSchemaLoader = new XMLSchemaLoader(fSymbolTable);
155: fSchemaLoader.setProperty(XMLGRAMMAR_POOL, fGrammarPool);
156:
157: // and set up the DTD loader too:
158: fDTDLoader = new XMLDTDLoader(fSymbolTable, fGrammarPool);
159: } // <init>(SymbolTable,XMLGrammarPool, XMLComponentManager)
160:
161: //
162: // Public methods
163: //
164:
165: /*
166: * lock the XMLGrammarPoolImpl object so that it does not
167: * accept any more grammars from the validators.
168: */
169: public void lockGrammarPool() {
170: fGrammarPool.lockPool();
171: } // lockGrammarPool()
172:
173: /*
174: * clear the XMLGrammarPoolImpl object so that it does not
175: * contain any more grammars.
176: */
177: public void clearGrammarPool() {
178: fGrammarPool.clear();
179: } // clearGrammarPool()
180:
181: /*
182: * unlock the XMLGrammarPoolImpl object so that it
183: * accepts more grammars from the validators.
184: */
185: public void unlockGrammarPool() {
186: fGrammarPool.unlockPool();
187: } // unlockGrammarPool()
188:
189: /**
190: * Parse a grammar from a location identified by an URI.
191: * This method also adds this grammar to the XMLGrammarPool
192: *
193: * @param type The type of the grammar to be constructed
194: * @param uri The location of the grammar to be constructed.
195: * <strong>The parser will not expand this URI or make it
196: * available to the EntityResolver</strong>
197: * @return The newly created <code>Grammar</code>.
198: * @exception XNIException thrown on an error in grammar
199: * construction
200: * @exception IOException thrown if an error is encountered
201: * in reading the file
202: */
203: public Grammar parseGrammar(String type, String uri)
204: throws XNIException, IOException {
205: XMLInputSource source = new XMLInputSource(null, uri, null);
206: return parseGrammar(type, source);
207:
208: }
209:
210: /**
211: * Parse a grammar from a location identified by an
212: * XMLInputSource.
213: * This method also adds this grammar to the XMLGrammarPool
214: *
215: * @param type The type of the grammar to be constructed
216: * @param is The XMLInputSource containing this grammar's
217: * information
218: * <strong>If a URI is included in the systemId field, the parser will not expand this URI or make it
219: * available to the EntityResolver</strong>
220: * @return The newly created <code>Grammar</code>.
221: * @exception XNIException thrown on an error in grammar
222: * construction
223: * @exception IOException thrown if an error is encountered
224: * in reading the file
225: */
226: public Grammar parseGrammar(String type, XMLInputSource is)
227: throws XNIException, IOException {
228: if (type.equals(XMLGrammarDescription.XML_SCHEMA)) {
229: // by default, make all XMLGrammarPoolImpl's schema grammars available to fSchemaHandler
230: return parseXMLSchema(is);
231: } else if (type.equals(XMLGrammarDescription.XML_DTD)) {
232: return parseDTD(is);
233: }
234: // don't know this grammar...
235: return null;
236: } // parseGrammar(String, XMLInputSource): Grammar
237:
238: //
239: // Protected methods
240: //
241:
242: // features and properties
243:
244: /**
245: * Check a feature. If feature is known and supported, this method simply
246: * returns. Otherwise, the appropriate exception is thrown.
247: *
248: * @param featureId The unique identifier (URI) of the feature.
249: *
250: * @throws XMLConfigurationException Thrown for configuration error.
251: * In general, components should
252: * only throw this exception if
253: * it is <strong>really</strong>
254: * a critical error.
255: */
256: protected void checkFeature(String featureId)
257: throws XMLConfigurationException {
258:
259: super .checkFeature(featureId);
260:
261: } // checkFeature(String)
262:
263: /**
264: * Check a property. If the property is known and supported, this method
265: * simply returns. Otherwise, the appropriate exception is thrown.
266: *
267: * @param propertyId The unique identifier (URI) of the property
268: * being set.
269: *
270: * @throws XMLConfigurationException Thrown for configuration error.
271: * In general, components should
272: * only throw this exception if
273: * it is <strong>really</strong>
274: * a critical error.
275: */
276: protected void checkProperty(String propertyId)
277: throws XMLConfigurationException {
278: super .checkProperty(propertyId);
279:
280: } // checkProperty(String)
281:
282: // package-protected methods
283:
284: /* This method parses an XML Schema document.
285: * It requires a GrammarBucket parameter so that DOMASBuilder can
286: * extract the info it needs.
287: * Therefore, bucket must not be null!
288: */
289: SchemaGrammar parseXMLSchema(XMLInputSource is) throws IOException {
290: XMLEntityResolver resolver = getEntityResolver();
291: if (resolver != null) {
292: fSchemaLoader.setEntityResolver(resolver);
293: }
294: if (fErrorReporter
295: .getMessageFormatter(XSMessageFormatter.SCHEMA_DOMAIN) == null) {
296: fErrorReporter.putMessageFormatter(
297: XSMessageFormatter.SCHEMA_DOMAIN,
298: new XSMessageFormatter());
299: }
300: fSchemaLoader.setProperty(ERROR_REPORTER, fErrorReporter);
301:
302: String propPrefix = Constants.XERCES_PROPERTY_PREFIX;
303: String propName = propPrefix + Constants.SCHEMA_LOCATION;
304: fSchemaLoader.setProperty(propName, getProperty(propName));
305: propName = propPrefix + Constants.SCHEMA_NONS_LOCATION;
306: fSchemaLoader.setProperty(propName, getProperty(propName));
307: propName = Constants.JAXP_PROPERTY_PREFIX
308: + Constants.SCHEMA_SOURCE;
309: fSchemaLoader.setProperty(propName, getProperty(propName));
310: fSchemaLoader.setFeature(SCHEMA_FULL_CHECKING,
311: getFeature(SCHEMA_FULL_CHECKING));
312:
313: // Should check whether the grammar with this namespace is already in
314: // the grammar resolver. But since we don't know the target namespace
315: // of the document here, we leave such check to XSDHandler
316: SchemaGrammar grammar = (SchemaGrammar) fSchemaLoader
317: .loadGrammar(is);
318: // by default, hand it off to the grammar pool
319: if (grammar != null) {
320: fGrammarPool.cacheGrammars(
321: XMLGrammarDescription.XML_SCHEMA,
322: new Grammar[] { grammar });
323: }
324:
325: return grammar;
326:
327: } // parseXMLSchema(XMLInputSource) : SchemaGrammar
328:
329: /* This method parses an external DTD entity.
330: */
331: DTDGrammar parseDTD(XMLInputSource is) throws IOException {
332: XMLEntityResolver resolver = getEntityResolver();
333: if (resolver != null) {
334: fDTDLoader.setEntityResolver(resolver);
335: }
336: fDTDLoader.setProperty(ERROR_REPORTER, fErrorReporter);
337:
338: // Should check whether the grammar with this namespace is already in
339: // the grammar resolver. But since we don't know the target namespace
340: // of the document here, we leave such check to the application...
341: DTDGrammar grammar = (DTDGrammar) fDTDLoader.loadGrammar(is);
342: // by default, hand it off to the grammar pool
343: if (grammar != null) {
344: fGrammarPool.cacheGrammars(XMLGrammarDescription.XML_DTD,
345: new Grammar[] { grammar });
346: }
347:
348: return grammar;
349:
350: } // parseXMLDTD(XMLInputSource) : DTDGrammar
351:
352: } // class XMLGrammarCachingConfiguration
|