1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 2001, 2002 The Apache Software Foundation.
  6. * All rights reserved.
  7. *
  8. * Redistribution and use in source and binary forms, with or without
  9. * modification, are permitted provided that the following conditions
  10. * are met:
  11. *
  12. * 1. Redistributions of source code must retain the above copyright
  13. * notice, this list of conditions and the following disclaimer.
  14. *
  15. * 2. Redistributions in binary form must reproduce the above copyright
  16. * notice, this list of conditions and the following disclaimer in
  17. * the documentation and/or other materials provided with the
  18. * distribution.
  19. *
  20. * 3. The end-user documentation included with the redistribution,
  21. * if any, must include the following acknowledgment:
  22. * "This product includes software developed by the
  23. * Apache Software Foundation (http://www.apache.org/)."
  24. * Alternately, this acknowledgment may appear in the software itself,
  25. * if and wherever such third-party acknowledgments normally appear.
  26. *
  27. * 4. The names "Xerces" and "Apache Software Foundation" must
  28. * not be used to endorse or promote products derived from this
  29. * software without prior written permission. For written
  30. * permission, please contact apache@apache.org.
  31. *
  32. * 5. Products derived from this software may not be called "Apache",
  33. * nor may "Apache" appear in their name, without prior written
  34. * permission of the Apache Software Foundation.
  35. *
  36. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
  37. * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
  38. * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  39. * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
  40. * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  41. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  42. * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
  43. * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
  44. * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
  45. * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
  46. * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  47. * SUCH DAMAGE.
  48. * ====================================================================
  49. *
  50. * This software consists of voluntary contributions made by many
  51. * individuals on behalf of the Apache Software Foundation and was
  52. * originally based on software copyright (c) 1999, International
  53. * Business Machines, Inc., http://www.apache.org. For more
  54. * information on the Apache Software Foundation, please see
  55. * <http://www.apache.org/>.
  56. */
  57. package com.sun.org.apache.xerces.internal.parsers;
  58. import java.io.IOException;
  59. import java.util.Enumeration;
  60. import java.util.Hashtable;
  61. import java.util.Locale;
  62. import com.sun.org.apache.xerces.internal.impl.Constants;
  63. import com.sun.org.apache.xerces.internal.impl.XMLEntityManager;
  64. import com.sun.org.apache.xerces.internal.impl.XMLErrorReporter;
  65. import com.sun.org.apache.xerces.internal.util.SymbolTable;
  66. import com.sun.org.apache.xerces.internal.xni.XNIException;
  67. import com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
  68. import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
  69. import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarLoader;
  70. import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
  71. import com.sun.org.apache.xerces.internal.xni.parser.XMLEntityResolver;
  72. import com.sun.org.apache.xerces.internal.xni.parser.XMLErrorHandler;
  73. import com.sun.org.apache.xerces.internal.xni.parser.XMLInputSource;
  74. /**
  75. * <p> This class provides an easy way for a user to preparse grammars
  76. * of various types. By default, it knows how to preparse external
  77. * DTD's and schemas; it provides an easy way for user applications to
  78. * register classes that know how to parse additional grammar types.
  79. * By default, it does no grammar caching; but it provides ways for
  80. * user applications to do so.
  81. *
  82. * @author Neil Graham, IBM
  83. *
  84. * @version $Id: XMLGrammarPreparser.java,v 1.8 2004/02/17 07:14:49 neeraj Exp $
  85. */
  86. public class XMLGrammarPreparser {
  87. //
  88. // Constants
  89. //
  90. // feature: continue-after-fatal-error
  91. private final static String CONTINUE_AFTER_FATAL_ERROR =
  92. Constants.XERCES_FEATURE_PREFIX + Constants.CONTINUE_AFTER_FATAL_ERROR_FEATURE;
  93. /** Property identifier: symbol table. */
  94. protected static final String SYMBOL_TABLE =
  95. Constants.XERCES_PROPERTY_PREFIX + Constants.SYMBOL_TABLE_PROPERTY;
  96. /** Property identifier: error reporter. */
  97. protected static final String ERROR_REPORTER =
  98. Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_REPORTER_PROPERTY;
  99. /** Property identifier: error handler. */
  100. protected static final String ERROR_HANDLER =
  101. Constants.XERCES_PROPERTY_PREFIX + Constants.ERROR_HANDLER_PROPERTY;
  102. /** Property identifier: entity resolver. */
  103. protected static final String ENTITY_RESOLVER =
  104. Constants.XERCES_PROPERTY_PREFIX + Constants.ENTITY_RESOLVER_PROPERTY;
  105. /** Property identifier: grammar pool . */
  106. protected static final String GRAMMAR_POOL =
  107. Constants.XERCES_PROPERTY_PREFIX + Constants.XMLGRAMMAR_POOL_PROPERTY;
  108. // the "built-in" grammar loaders
  109. private static final Hashtable KNOWN_LOADERS = new Hashtable();
  110. static {
  111. KNOWN_LOADERS.put(XMLGrammarDescription.XML_SCHEMA,
  112. "com.sun.org.apache.xerces.internal.impl.xs.XMLSchemaLoader");
  113. KNOWN_LOADERS.put(XMLGrammarDescription.XML_DTD,
  114. "com.sun.org.apache.xerces.internal.impl.dtd.XMLDTDLoader");
  115. }
  116. /** Recognized properties. */
  117. private static final String[] RECOGNIZED_PROPERTIES = {
  118. SYMBOL_TABLE,
  119. ERROR_REPORTER,
  120. ERROR_HANDLER,
  121. ENTITY_RESOLVER,
  122. GRAMMAR_POOL,
  123. };
  124. // Data
  125. protected SymbolTable fSymbolTable;
  126. protected XMLErrorReporter fErrorReporter;
  127. protected XMLEntityResolver fEntityResolver;
  128. protected XMLGrammarPool fGrammarPool;
  129. protected Locale fLocale;
  130. // Hashtable holding our loaders
  131. private Hashtable fLoaders;
  132. //
  133. // Constructors
  134. //
  135. /** Default constructor. */
  136. public XMLGrammarPreparser() {
  137. this(new SymbolTable());
  138. } // <init>()
  139. /**
  140. * Constructs a preparser using the specified symbol table.
  141. *
  142. * @param symbolTable The symbol table to use.
  143. */
  144. public XMLGrammarPreparser (SymbolTable symbolTable) {
  145. fSymbolTable = symbolTable;
  146. fLoaders = new Hashtable();
  147. setLocale(Locale.getDefault());
  148. fErrorReporter = new XMLErrorReporter();
  149. fErrorReporter.setLocale(fLocale);
  150. fEntityResolver = new XMLEntityManager();
  151. // those are all the basic properties...
  152. } // <init>(SymbolTable)
  153. //
  154. // Public methods
  155. //
  156. /*
  157. * Register a type of grammar to make it preparsable. If
  158. * the second parameter is null, the parser will use its built-in
  159. * facilities for that grammar type.
  160. * This should be called by the application immediately
  161. * after creating this object and before initializing any properties/features.
  162. * @param type URI identifying the type of the grammar
  163. * @param loader an object capable of preparsing that type; null if the ppreparser should use built-in knowledge.
  164. * @return true if successful; false if no built-in knowledge of
  165. * the type or if unable to instantiate the string we know about
  166. */
  167. public boolean registerPreparser(String grammarType, XMLGrammarLoader loader) {
  168. if(loader == null) { // none specified!
  169. if(KNOWN_LOADERS.containsKey(grammarType)) {
  170. // got one; just instantiate it...
  171. String loaderName = (String)KNOWN_LOADERS.get(grammarType);
  172. try {
  173. ClassLoader cl = ObjectFactory.findClassLoader();
  174. XMLGrammarLoader gl = (XMLGrammarLoader)(ObjectFactory.newInstance(loaderName, cl, true));
  175. fLoaders.put(grammarType, gl);
  176. } catch (Exception e) {
  177. return false;
  178. }
  179. return true;
  180. }
  181. return false;
  182. }
  183. // were given one
  184. fLoaders.put(grammarType, loader);
  185. return true;
  186. } // registerPreparser(String, XMLGrammarLoader): boolean
  187. /**
  188. * Parse a grammar from a location identified by an
  189. * XMLInputSource.
  190. * This method also adds this grammar to the XMLGrammarPool
  191. *
  192. * @param type The type of the grammar to be constructed
  193. * @param source The XMLInputSource containing this grammar's
  194. * information
  195. * <strong>If a URI is included in the systemId field, 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 preparseGrammar(String type, XMLInputSource
  204. is) throws XNIException, IOException {
  205. if(fLoaders.containsKey(type)) {
  206. XMLGrammarLoader gl = (XMLGrammarLoader)fLoaders.get(type);
  207. // make sure gl's been set up with all the "basic" properties:
  208. gl.setProperty(SYMBOL_TABLE, fSymbolTable);
  209. gl.setProperty(ENTITY_RESOLVER, fEntityResolver);
  210. gl.setProperty(ERROR_REPORTER, fErrorReporter);
  211. // potentially, not all will support this one...
  212. if(fGrammarPool != null) {
  213. try {
  214. gl.setProperty(GRAMMAR_POOL, fGrammarPool);
  215. } catch(Exception e) {
  216. // too bad...
  217. }
  218. }
  219. return gl.loadGrammar(is);
  220. }
  221. return null;
  222. } // preparseGrammar(String, XMLInputSource): Grammar
  223. /**
  224. * Set the locale to use for messages.
  225. *
  226. * @param locale The locale object to use for localization of messages.
  227. *
  228. * @exception XNIException Thrown if the parser does not support the
  229. * specified locale.
  230. */
  231. public void setLocale(Locale locale) {
  232. fLocale = locale;
  233. } // setLocale(Locale)
  234. /** Return the Locale the XMLGrammarLoader is using. */
  235. public Locale getLocale() {
  236. return fLocale;
  237. } // getLocale(): Locale
  238. /**
  239. * Sets the error handler.
  240. *
  241. * @param errorHandler The error handler.
  242. */
  243. public void setErrorHandler(XMLErrorHandler errorHandler) {
  244. fErrorReporter.setProperty(ERROR_HANDLER, errorHandler);
  245. } // setErrorHandler(XMLErrorHandler)
  246. /** Returns the registered error handler. */
  247. public XMLErrorHandler getErrorHandler() {
  248. return fErrorReporter.getErrorHandler();
  249. } // getErrorHandler(): XMLErrorHandler
  250. /**
  251. * Sets the entity resolver.
  252. *
  253. * @param entityResolver The new entity resolver.
  254. */
  255. public void setEntityResolver(XMLEntityResolver entityResolver) {
  256. fEntityResolver = entityResolver;
  257. } // setEntityResolver(XMLEntityResolver)
  258. /** Returns the registered entity resolver. */
  259. public XMLEntityResolver getEntityResolver() {
  260. return fEntityResolver;
  261. } // getEntityResolver(): XMLEntityResolver
  262. /**
  263. * Sets the grammar pool.
  264. *
  265. * @param grammarPool The new grammar pool.
  266. */
  267. public void setGrammarPool(XMLGrammarPool grammarPool) {
  268. fGrammarPool = grammarPool;
  269. } // setGrammarPool(XMLGrammarPool)
  270. /** Returns the registered grammar pool. */
  271. public XMLGrammarPool getGrammarPool() {
  272. return fGrammarPool;
  273. } // getGrammarPool(): XMLGrammarPool
  274. // it's possible the application may want access to a certain loader to do
  275. // some custom work.
  276. public XMLGrammarLoader getLoader(String type) {
  277. return (XMLGrammarLoader)fLoaders.get(type);
  278. } // getLoader(String): XMLGrammarLoader
  279. // set a feature. This method tries to set it on all
  280. // registered loaders; it eats any resulting exceptions. If
  281. // an app needs to know if a particular feature is supported
  282. // by a grammar loader of a particular type, it will have
  283. // to retrieve that loader and use the loader's setFeature method.
  284. public void setFeature(String featureId, boolean value) {
  285. Enumeration loaders = fLoaders.elements();
  286. while(loaders.hasMoreElements()){
  287. XMLGrammarLoader gl = (XMLGrammarLoader)loaders.nextElement();
  288. try {
  289. gl.setFeature(featureId, value);
  290. } catch(Exception e) {
  291. // eat it up...
  292. }
  293. }
  294. // since our error reporter is a property we set later,
  295. // make sure features it understands are also set.
  296. if(featureId.equals(CONTINUE_AFTER_FATAL_ERROR)) {
  297. fErrorReporter.setFeature(CONTINUE_AFTER_FATAL_ERROR, value);
  298. }
  299. } //setFeature(String, boolean)
  300. // set a property. This method tries to set it on all
  301. // registered loaders; it eats any resulting exceptions. If
  302. // an app needs to know if a particular property is supported
  303. // by a grammar loader of a particular type, it will have
  304. // to retrieve that loader and use the loader's setProperty method.
  305. // <p> <strong>An application should use the explicit method
  306. // in this class to set "standard" properties like error handler etc.</strong>
  307. public void setProperty(String propId, Object value) {
  308. Enumeration loaders = fLoaders.elements();
  309. while(loaders.hasMoreElements()){
  310. XMLGrammarLoader gl = (XMLGrammarLoader)loaders.nextElement();
  311. try {
  312. gl.setProperty(propId, value);
  313. } catch(Exception e) {
  314. // eat it up...
  315. }
  316. }
  317. } //setProperty(String, Object)
  318. // get status of feature in a particular loader. This
  319. // catches no exceptions--including NPE's--so the application had
  320. // better make sure the loader exists and knows about this feature.
  321. // @param type type of grammar to look for the feature in.
  322. // @param featureId the feature string to query.
  323. // @return the value of the feature.
  324. public boolean getFeature(String type, String featureId) {
  325. XMLGrammarLoader gl = (XMLGrammarLoader)fLoaders.get(type);
  326. return gl.getFeature(featureId);
  327. } // getFeature (String, String): boolean
  328. // get status of property in a particular loader. This
  329. // catches no exceptions--including NPE's--so the application had
  330. // better make sure the loader exists and knows about this property.
  331. // <strong>For standard properties--that will be supported
  332. // by all loaders--the specific methods should be queried!</strong>
  333. // @param type type of grammar to look for the property in.
  334. // @param propertyId the property string to query.
  335. // @return the value of the property.
  336. public Object getProperty(String type, String propertyId) {
  337. XMLGrammarLoader gl = (XMLGrammarLoader)fLoaders.get(type);
  338. return gl.getProperty(propertyId);
  339. } // getProperty(String, String): Object
  340. } // class XMLGrammarPreparser