1. /*
  2. * The Apache Software License, Version 1.1
  3. *
  4. *
  5. * Copyright (c) 1999-2002 The Apache Software Foundation. All rights
  6. * 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 com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
  59. import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
  60. import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
  61. import com.sun.org.apache.xerces.internal.util.XMLGrammarPoolImpl;
  62. import com.sun.org.apache.xerces.internal.util.ShadowedSymbolTable;
  63. import com.sun.org.apache.xerces.internal.util.SymbolTable;
  64. import com.sun.org.apache.xerces.internal.util.SynchronizedSymbolTable;
  65. /**
  66. * A parser pool that enables caching of grammars. The caching parser
  67. * pool is constructed with a specific symbol table and grammar pool
  68. * that has already been populated with the grammars used by the
  69. * application.
  70. * <p>
  71. * Once the caching parser pool is constructed, specific parser
  72. * instances are created by calling the appropriate factory method
  73. * on the parser pool.
  74. * <p>
  75. * <strong>Note:</strong> There is a performance penalty for using
  76. * a caching parser pool due to thread safety. Access to the symbol
  77. * table and grammar pool must be synchronized to ensure the safe
  78. * operation of the symbol table and grammar pool.
  79. * <p>
  80. * <strong>Note:</strong> If performance is critical, then another
  81. * mechanism needs to be used instead of the caching parser pool.
  82. * One approach would be to create parser instances that do not
  83. * share these structures. Instead, each instance would get its
  84. * own copy to use while parsing. This avoids the synchronization
  85. * overhead at the expense of more memory and the time required
  86. * to copy the structures for each new parser instance. And even
  87. * when a parser instance is re-used, there is a potential for a
  88. * memory leak due to new symbols being added to the symbol table
  89. * over time. In other words, always take caution to make sure
  90. * that your application is thread-safe and avoids leaking memory.
  91. *
  92. * @author Andy Clark, IBM
  93. *
  94. * @version $Id: CachingParserPool.java,v 1.11 2002/06/01 16:36:36 elena Exp $
  95. */
  96. public class CachingParserPool {
  97. //
  98. // Constants
  99. //
  100. /** Default shadow symbol table (false). */
  101. public static final boolean DEFAULT_SHADOW_SYMBOL_TABLE = false;
  102. /** Default shadow grammar pool (false). */
  103. public static final boolean DEFAULT_SHADOW_GRAMMAR_POOL = false;
  104. //
  105. // Data
  106. //
  107. /**
  108. * Symbol table. The symbol table that the caching parser pool is
  109. * constructed with is automatically wrapped in a synchronized
  110. * version for thread-safety.
  111. */
  112. protected SymbolTable fSynchronizedSymbolTable;
  113. /**
  114. * Grammar pool. The grammar pool that the caching parser pool is
  115. * constructed with is automatically wrapped in a synchronized
  116. * version for thread-safety.
  117. */
  118. protected XMLGrammarPool fSynchronizedGrammarPool;
  119. /**
  120. * Shadow the symbol table for new parser instances. If true,
  121. * new parser instances use shadow copies of the main symbol
  122. * table and are not allowed to add new symbols to the main
  123. * symbol table. New symbols are added to the shadow symbol
  124. * table and are local to the parser instance.
  125. */
  126. protected boolean fShadowSymbolTable = DEFAULT_SHADOW_SYMBOL_TABLE;
  127. /**
  128. * Shadow the grammar pool for new parser instances. If true,
  129. * new parser instances use shadow copies of the main grammar
  130. * pool and are not allowed to add new grammars to the main
  131. * grammar pool. New grammars are added to the shadow grammar
  132. * pool and are local to the parser instance.
  133. */
  134. protected boolean fShadowGrammarPool = DEFAULT_SHADOW_GRAMMAR_POOL;
  135. //
  136. // Constructors
  137. //
  138. /** Default constructor. */
  139. public CachingParserPool() {
  140. this(new SymbolTable(), new XMLGrammarPoolImpl());
  141. } // <init>()
  142. /**
  143. * Constructs a caching parser pool with the specified symbol table
  144. * and grammar pool.
  145. *
  146. * @param symbolTable The symbol table.
  147. * @param grammarPool The grammar pool.
  148. */
  149. public CachingParserPool(SymbolTable symbolTable, XMLGrammarPool grammarPool) {
  150. fSynchronizedSymbolTable = new SynchronizedSymbolTable(symbolTable);
  151. fSynchronizedGrammarPool = new SynchronizedGrammarPool(grammarPool);
  152. } // <init>(SymbolTable,XMLGrammarPool)
  153. //
  154. // Public methods
  155. //
  156. /** Returns the symbol table. */
  157. public SymbolTable getSymbolTable() {
  158. return fSynchronizedSymbolTable;
  159. } // getSymbolTable():SymbolTable
  160. /** Returns the grammar pool. */
  161. public XMLGrammarPool getXMLGrammarPool() {
  162. return fSynchronizedGrammarPool;
  163. } // getXMLGrammarPool():XMLGrammarPool
  164. // setters and getters
  165. /**
  166. * Sets whether new parser instance receive shadow copies of the
  167. * main symbol table.
  168. *
  169. * @param shadow If true, new parser instances use shadow copies
  170. * of the main symbol table and are not allowed to
  171. * add new symbols to the main symbol table. New
  172. * symbols are added to the shadow symbol table and
  173. * are local to the parser instance. If false, new
  174. * parser instances are allowed to add new symbols
  175. * to the main symbol table.
  176. */
  177. public void setShadowSymbolTable(boolean shadow) {
  178. fShadowSymbolTable = shadow;
  179. } // setShadowSymbolTable(boolean)
  180. // factory methods
  181. /** Creates a new DOM parser. */
  182. public DOMParser createDOMParser() {
  183. SymbolTable symbolTable = fShadowSymbolTable
  184. ? new ShadowedSymbolTable(fSynchronizedSymbolTable)
  185. : fSynchronizedSymbolTable;
  186. XMLGrammarPool grammarPool = fShadowGrammarPool
  187. ? new ShadowedGrammarPool(fSynchronizedGrammarPool)
  188. : fSynchronizedGrammarPool;
  189. return new DOMParser(symbolTable, grammarPool);
  190. } // createDOMParser():DOMParser
  191. /** Creates a new SAX parser. */
  192. public SAXParser createSAXParser() {
  193. SymbolTable symbolTable = fShadowSymbolTable
  194. ? new ShadowedSymbolTable(fSynchronizedSymbolTable)
  195. : fSynchronizedSymbolTable;
  196. XMLGrammarPool grammarPool = fShadowGrammarPool
  197. ? new ShadowedGrammarPool(fSynchronizedGrammarPool)
  198. : fSynchronizedGrammarPool;
  199. return new SAXParser(symbolTable, grammarPool);
  200. } // createSAXParser():SAXParser
  201. //
  202. // Classes
  203. //
  204. /**
  205. * Synchronized grammar pool.
  206. *
  207. * @author Andy Clark, IBM
  208. */
  209. public static final class SynchronizedGrammarPool
  210. implements XMLGrammarPool {
  211. //
  212. // Data
  213. //
  214. /** Main grammar pool. */
  215. private XMLGrammarPool fGrammarPool;
  216. //
  217. // Constructors
  218. //
  219. /** Constructs a synchronized grammar pool. */
  220. public SynchronizedGrammarPool(XMLGrammarPool grammarPool) {
  221. fGrammarPool = grammarPool;
  222. } // <init>(XMLGrammarPool)
  223. //
  224. // GrammarPool methods
  225. //
  226. // retrieve the initial set of grammars for the validator
  227. // to work with.
  228. // REVISIT: does this need to be synchronized since it's just reading?
  229. // @param grammarType type of the grammars to be retrieved.
  230. // @return the initial grammar set the validator may place in its "bucket"
  231. public Grammar [] retrieveInitialGrammarSet(String grammarType ) {
  232. synchronized (fGrammarPool) {
  233. return fGrammarPool.retrieveInitialGrammarSet(grammarType);
  234. }
  235. } // retrieveInitialGrammarSet(String): Grammar[]
  236. // retrieve a particular grammar.
  237. // REVISIT: does this need to be synchronized since it's just reading?
  238. // @param gDesc description of the grammar to be retrieved
  239. // @return Grammar corresponding to gDesc, or null if none exists.
  240. public Grammar retrieveGrammar(XMLGrammarDescription gDesc) {
  241. synchronized (fGrammarPool) {
  242. return fGrammarPool.retrieveGrammar(gDesc);
  243. }
  244. } // retrieveGrammar(XMLGrammarDesc): Grammar
  245. // give the grammarPool the option of caching these grammars.
  246. // This certainly must be synchronized.
  247. // @param grammarType The type of the grammars to be cached.
  248. // @param grammars the Grammars that may be cached (unordered, Grammars previously
  249. // given to the validator may be included).
  250. public void cacheGrammars(String grammarType, Grammar[] grammars) {
  251. synchronized (fGrammarPool) {
  252. fGrammarPool.cacheGrammars(grammarType, grammars);
  253. }
  254. } // cacheGrammars(String, Grammar[]);
  255. /** lock the grammar pool */
  256. public void lockPool() {
  257. synchronized (fGrammarPool) {
  258. fGrammarPool.lockPool();
  259. }
  260. } // lockPool()
  261. /** clear the grammar pool */
  262. public void clear() {
  263. synchronized (fGrammarPool) {
  264. fGrammarPool.clear();
  265. }
  266. } // lockPool()
  267. /** unlock the grammar pool */
  268. public void unlockPool() {
  269. synchronized (fGrammarPool) {
  270. fGrammarPool.unlockPool();
  271. }
  272. } // unlockPool()
  273. /***
  274. * Methods corresponding to original (pre Xerces2.0.0final)
  275. * grammarPool have been commented out.
  276. */
  277. /**
  278. * Puts the specified grammar into the grammar pool.
  279. *
  280. * @param key Key to associate with grammar.
  281. * @param grammar Grammar object.
  282. */
  283. /******
  284. public void putGrammar(String key, Grammar grammar) {
  285. synchronized (fGrammarPool) {
  286. fGrammarPool.putGrammar(key, grammar);
  287. }
  288. } // putGrammar(String,Grammar)
  289. *******/
  290. /**
  291. * Returns the grammar associated to the specified key.
  292. *
  293. * @param key The key of the grammar.
  294. */
  295. /**********
  296. public Grammar getGrammar(String key) {
  297. synchronized (fGrammarPool) {
  298. return fGrammarPool.getGrammar(key);
  299. }
  300. } // getGrammar(String):Grammar
  301. ***********/
  302. /**
  303. * Removes the grammar associated to the specified key from the
  304. * grammar pool and returns the removed grammar.
  305. *
  306. * @param key The key of the grammar.
  307. */
  308. /**********
  309. public Grammar removeGrammar(String key) {
  310. synchronized (fGrammarPool) {
  311. return fGrammarPool.removeGrammar(key);
  312. }
  313. } // removeGrammar(String):Grammar
  314. ******/
  315. /**
  316. * Returns true if the grammar pool contains a grammar associated
  317. * to the specified key.
  318. *
  319. * @param key The key of the grammar.
  320. */
  321. /**********
  322. public boolean containsGrammar(String key) {
  323. synchronized (fGrammarPool) {
  324. return fGrammarPool.containsGrammar(key);
  325. }
  326. } // containsGrammar(String):boolean
  327. ********/
  328. } // class SynchronizedGrammarPool
  329. /**
  330. * Shadowed grammar pool.
  331. * This class is predicated on the existence of a concrete implementation;
  332. * so using our own doesn't seem to bad an idea.
  333. *
  334. * @author Andy Clark, IBM
  335. * @author Neil Graham, IBM
  336. */
  337. public static final class ShadowedGrammarPool
  338. extends XMLGrammarPoolImpl {
  339. //
  340. // Data
  341. //
  342. /** Main grammar pool. */
  343. private XMLGrammarPool fGrammarPool;
  344. //
  345. // Constructors
  346. //
  347. /** Constructs a shadowed grammar pool. */
  348. public ShadowedGrammarPool(XMLGrammarPool grammarPool) {
  349. fGrammarPool = grammarPool;
  350. } // <init>(GrammarPool)
  351. //
  352. // GrammarPool methods
  353. //
  354. /**
  355. * Retrieve the initial set of grammars for the validator to work with.
  356. * REVISIT: does this need to be synchronized since it's just reading?
  357. *
  358. * @param grammarType Type of the grammars to be retrieved.
  359. * @return The initial grammar set the validator may place in its "bucket"
  360. */
  361. public Grammar [] retrieveInitialGrammarSet(String grammarType ) {
  362. Grammar [] grammars = super.retrieveInitialGrammarSet(grammarType);
  363. if (grammars != null) return grammars;
  364. return fGrammarPool.retrieveInitialGrammarSet(grammarType);
  365. } // retrieveInitialGrammarSet(String): Grammar[]
  366. /**
  367. * Retrieve a particular grammar.
  368. * REVISIT: does this need to be synchronized since it's just reading?
  369. *
  370. * @param gDesc Description of the grammar to be retrieved
  371. * @return Grammar corresponding to gDesc, or null if none exists.
  372. */
  373. public Grammar retrieveGrammar(XMLGrammarDescription gDesc) {
  374. Grammar g = super.retrieveGrammar(gDesc);
  375. if(g != null) return g;
  376. return fGrammarPool.retrieveGrammar(gDesc);
  377. } // retrieveGrammar(XMLGrammarDesc): Grammar
  378. /**
  379. * Give the grammarPool the option of caching these grammars.
  380. * This certainly must be synchronized.
  381. *
  382. * @param grammarType The type of the grammars to be cached.
  383. * @param grammars The Grammars that may be cached (unordered, Grammars previously
  384. * given to the validator may be included).
  385. */
  386. public void cacheGrammars(String grammarType, Grammar[] grammars) {
  387. // better give both grammars a shot...
  388. super.cacheGrammars(grammarType, grammars);
  389. fGrammarPool.cacheGrammars(grammarType, grammars);
  390. } // cacheGrammars(grammarType, Grammar[]);
  391. /**
  392. * Returns the grammar associated to the specified description.
  393. *
  394. * @param desc The description of the grammar.
  395. */
  396. public Grammar getGrammar(XMLGrammarDescription desc) {
  397. if (super.containsGrammar(desc)) {
  398. return super.getGrammar(desc);
  399. }
  400. return null;
  401. } // getGrammar(XMLGrammarDescription):Grammar
  402. /**
  403. * Returns true if the grammar pool contains a grammar associated
  404. * to the specified description.
  405. *
  406. * @param desc The description of the grammar.
  407. */
  408. public boolean containsGrammar(XMLGrammarDescription desc) {
  409. return super.containsGrammar(desc);
  410. } // containsGrammar(XMLGrammarDescription):boolean
  411. } // class ShadowedGrammarPool
  412. } // class CachingParserPool