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.util;
  58. import com.sun.org.apache.xerces.internal.xni.grammars.Grammar;
  59. import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription;
  60. import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool;
  61. /**
  62. * Stores grammars in a pool associated to a specific key. This grammar pool
  63. * implementation stores two types of grammars: those keyed by the root element
  64. * name, and those keyed by the grammar's target namespace.
  65. *
  66. * This is the default implementation of the GrammarPool interface.
  67. * As we move forward, this will become more function-rich and robust.
  68. *
  69. * @author Jeffrey Rodriguez, IBM
  70. * @author Andy Clark, IBM
  71. * @author Neil Graham, IBM
  72. * @author Pavani Mukthipudi, Sun Microsystems
  73. * @author Neeraj Bajaj, SUN Microsystems
  74. *
  75. * @version $Id: XMLGrammarPoolImpl.java,v 1.6 2003/07/30 21:30:04 elena Exp $
  76. */
  77. public class XMLGrammarPoolImpl implements XMLGrammarPool {
  78. //
  79. // Constants
  80. //
  81. /** Default size. */
  82. protected static final int TABLE_SIZE = 11;
  83. //
  84. // Data
  85. //
  86. /** Grammars. */
  87. protected Entry[] fGrammars = null;
  88. // whether this pool is locked
  89. protected boolean fPoolIsLocked;
  90. // the number of grammars in the pool
  91. protected int fGrammarCount = 0;
  92. private static final boolean DEBUG = false ;
  93. //
  94. // Constructors
  95. //
  96. /** Constructs a grammar pool with a default number of buckets. */
  97. public XMLGrammarPoolImpl() {
  98. fGrammars = new Entry[TABLE_SIZE];
  99. fPoolIsLocked = false;
  100. } // <init>()
  101. /** Constructs a grammar pool with a specified number of buckets. */
  102. public XMLGrammarPoolImpl(int initialCapacity) {
  103. fGrammars = new Entry[initialCapacity];
  104. fPoolIsLocked = false;
  105. }
  106. //
  107. // XMLGrammarPool methods
  108. //
  109. /* <p> Retrieve the initial known set of grammars. This method is
  110. * called by a validator before the validation starts. The application
  111. * can provide an initial set of grammars available to the current
  112. * validation attempt. </p>
  113. *
  114. * @param grammarType The type of the grammar, from the
  115. * <code>com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription</code>
  116. * interface.
  117. * @return The set of grammars the validator may put in its "bucket"
  118. */
  119. public Grammar [] retrieveInitialGrammarSet (String grammarType) {
  120. synchronized (fGrammars) {
  121. int grammarSize = fGrammars.length ;
  122. Grammar [] tempGrammars = new Grammar[fGrammarCount];
  123. int pos = 0;
  124. for (int i = 0; i < grammarSize; i++) {
  125. for (Entry e = fGrammars[i]; e != null; e = e.next) {
  126. if (e.desc.getGrammarType().equals(grammarType)) {
  127. tempGrammars[pos++] = e.grammar;
  128. }
  129. }
  130. }
  131. Grammar[] toReturn = new Grammar[pos];
  132. System.arraycopy(tempGrammars, 0, toReturn, 0, pos);
  133. return toReturn;
  134. }
  135. } // retrieveInitialGrammarSet (String): Grammar[]
  136. /* <p> Return the final set of grammars that the validator ended up
  137. * with. This method is called after the validation finishes. The
  138. * application may then choose to cache some of the returned grammars.</p>
  139. * <p>In this implementation, we make our choice based on whether this object
  140. * is "locked"--that is, whether the application has instructed
  141. * us not to accept any new grammars.</p>
  142. *
  143. * @param grammarType The type of the grammars being returned;
  144. * @param grammars An array containing the set of grammars being
  145. * returned; order is not significant.
  146. */
  147. public void cacheGrammars(String grammarType, Grammar[] grammars) {
  148. if(!fPoolIsLocked) {
  149. for (int i = 0; i < grammars.length; i++) {
  150. if(DEBUG) {
  151. System.out.println("CACHED GRAMMAR " + (i+1) ) ;
  152. Grammar temp = grammars[i] ;
  153. //print(temp.getGrammarDescription());
  154. }
  155. putGrammar(grammars[i]);
  156. }
  157. }
  158. } // cacheGrammars(String, Grammar[]);
  159. /* <p> This method requests that the application retrieve a grammar
  160. * corresponding to the given GrammarIdentifier from its cache.
  161. * If it cannot do so it must return null; the parser will then
  162. * call the EntityResolver. </p>
  163. * <strong>An application must not call its EntityResolver itself
  164. * from this method; this may result in infinite recursions.</strong>
  165. *
  166. * This implementation chooses to use the root element name to identify a DTD grammar
  167. * and the target namespace to identify a Schema grammar.
  168. *
  169. * @param desc The description of the Grammar being requested.
  170. * @return The Grammar corresponding to this description or null if
  171. * no such Grammar is known.
  172. */
  173. public Grammar retrieveGrammar(XMLGrammarDescription desc) {
  174. if(DEBUG){
  175. System.out.println("RETRIEVING GRAMMAR FROM THE APPLICATION WITH FOLLOWING DESCRIPTION :");
  176. //print(desc);
  177. }
  178. return getGrammar(desc);
  179. } // retrieveGrammar(XMLGrammarDescription): Grammar
  180. //
  181. // Public methods
  182. //
  183. /**
  184. * Puts the specified grammar into the grammar pool and associates it to
  185. * its root element name or its target namespace.
  186. *
  187. * @param grammar The Grammar.
  188. */
  189. public void putGrammar(Grammar grammar) {
  190. if(!fPoolIsLocked) {
  191. synchronized (fGrammars) {
  192. XMLGrammarDescription desc = grammar.getGrammarDescription();
  193. int hash = hashCode(desc);
  194. int index = (hash & 0x7FFFFFFF) % fGrammars.length;
  195. for (Entry entry = fGrammars[index]; entry != null; entry = entry.next) {
  196. if (entry.hash == hash && equals(entry.desc, desc)) {
  197. entry.grammar = grammar;
  198. return;
  199. }
  200. }
  201. // create a new entry
  202. Entry entry = new Entry(hash, desc, grammar, fGrammars[index]);
  203. fGrammars[index] = entry;
  204. fGrammarCount++;
  205. }
  206. }
  207. } // putGrammar(Grammar)
  208. /**
  209. * Returns the grammar associated to the specified grammar description.
  210. * Currently, the root element name is used as the key for DTD grammars
  211. * and the target namespace is used as the key for Schema grammars.
  212. *
  213. * @param desc The Grammar Description.
  214. */
  215. public Grammar getGrammar(XMLGrammarDescription desc) {
  216. synchronized (fGrammars) {
  217. int hash = hashCode(desc);
  218. int index = (hash & 0x7FFFFFFF) % fGrammars.length;
  219. for (Entry entry = fGrammars[index] ; entry != null ; entry = entry.next) {
  220. if ((entry.hash == hash) && equals(entry.desc, desc)) {
  221. return entry.grammar;
  222. }
  223. }
  224. return null;
  225. }
  226. } // getGrammar(XMLGrammarDescription):Grammar
  227. /**
  228. * Removes the grammar associated to the specified grammar description from the
  229. * grammar pool and returns the removed grammar. Currently, the root element name
  230. * is used as the key for DTD grammars and the target namespace is used
  231. * as the key for Schema grammars.
  232. *
  233. * @param desc The Grammar Description.
  234. * @return The removed grammar.
  235. */
  236. public Grammar removeGrammar(XMLGrammarDescription desc) {
  237. synchronized (fGrammars) {
  238. int hash = hashCode(desc);
  239. int index = (hash & 0x7FFFFFFF) % fGrammars.length;
  240. for (Entry entry = fGrammars[index], prev = null ; entry != null ; prev = entry, entry = entry.next) {
  241. if ((entry.hash == hash) && equals(entry.desc, desc)) {
  242. if (prev != null) {
  243. prev.next = entry.next;
  244. }
  245. else {
  246. fGrammars[index] = entry.next;
  247. }
  248. Grammar tempGrammar = entry.grammar;
  249. entry.grammar = null;
  250. fGrammarCount--;
  251. return tempGrammar;
  252. }
  253. }
  254. return null;
  255. }
  256. } // removeGrammar(XMLGrammarDescription):Grammar
  257. /**
  258. * Returns true if the grammar pool contains a grammar associated
  259. * to the specified grammar description. Currently, the root element name
  260. * is used as the key for DTD grammars and the target namespace is used
  261. * as the key for Schema grammars.
  262. *
  263. * @param desc The Grammar Description.
  264. */
  265. public boolean containsGrammar(XMLGrammarDescription desc) {
  266. synchronized (fGrammars) {
  267. int hash = hashCode(desc);
  268. int index = (hash & 0x7FFFFFFF) % fGrammars.length;
  269. for (Entry entry = fGrammars[index] ; entry != null ; entry = entry.next) {
  270. if ((entry.hash == hash) && equals(entry.desc, desc)) {
  271. return true;
  272. }
  273. }
  274. return false;
  275. }
  276. } // containsGrammar(XMLGrammarDescription):boolean
  277. /* <p> Sets this grammar pool to a "locked" state--i.e.,
  278. * no new grammars will be added until it is "unlocked".
  279. */
  280. public void lockPool() {
  281. fPoolIsLocked = true;
  282. } // lockPool()
  283. /* <p> Sets this grammar pool to an "unlocked" state--i.e.,
  284. * new grammars will be added when putGrammar or cacheGrammars
  285. * are called.
  286. */
  287. public void unlockPool() {
  288. fPoolIsLocked = false;
  289. } // unlockPool()
  290. /*
  291. * <p>This method clears the pool-i.e., removes references
  292. * to all the grammars in it.</p>
  293. */
  294. public void clear() {
  295. for (int i=0; i<fGrammars.length; i++) {
  296. if(fGrammars[i] != null) {
  297. fGrammars[i].clear();
  298. fGrammars[i] = null;
  299. }
  300. }
  301. fGrammarCount = 0;
  302. } // clear()
  303. /**
  304. * This method checks whether two grammars are the same. Currently, we compare
  305. * the root element names for DTD grammars and the target namespaces for Schema grammars.
  306. * The application can override this behaviour and add its own logic.
  307. *
  308. * @param gDesc1 The grammar description
  309. * @param gDesc2 The grammar description of the grammar to be compared to
  310. * @return True if the grammars are equal, otherwise false
  311. */
  312. public boolean equals(XMLGrammarDescription desc1, XMLGrammarDescription desc2) {
  313. return desc1.equals(desc2);
  314. }
  315. /**
  316. * Returns the hash code value for the given grammar description.
  317. *
  318. * @param desc The grammar description
  319. * @return The hash code value
  320. */
  321. public int hashCode(XMLGrammarDescription desc) {
  322. return desc.hashCode();
  323. }
  324. /**
  325. * This class is a grammar pool entry. Each entry acts as a node
  326. * in a linked list.
  327. */
  328. protected static final class Entry {
  329. public int hash;
  330. public XMLGrammarDescription desc;
  331. public Grammar grammar;
  332. public Entry next;
  333. protected Entry(int hash, XMLGrammarDescription desc, Grammar grammar, Entry next) {
  334. this.hash = hash;
  335. this.desc = desc;
  336. this.grammar = grammar;
  337. this.next = next;
  338. }
  339. // clear this entry; useful to promote garbage collection
  340. // since reduces reference count of objects to be destroyed
  341. protected void clear () {
  342. desc = null;
  343. grammar = null;
  344. if(next != null) {
  345. next.clear();
  346. next = null;
  347. }
  348. } // clear()
  349. } // class Entry
  350. /* For DTD build we can't import here XSDDescription. Thus, this method is commented out.. */
  351. /* public void print(XMLGrammarDescription description){
  352. if(description.getGrammarType().equals(XMLGrammarDescription.XML_DTD)){
  353. }
  354. else if(description.getGrammarType().equals(XMLGrammarDescription.XML_SCHEMA)){
  355. XSDDescription schema = (XSDDescription)description ;
  356. System.out.println("Context = " + schema.getContextType());
  357. System.out.println("TargetNamespace = " + schema.getTargetNamespace());
  358. String [] temp = schema.getLocationHints();
  359. for (int i = 0 ; (temp != null && i < temp.length) ; i++){
  360. System.out.println("LocationHint " + i + " = "+ temp[i]);
  361. }
  362. System.out.println("Triggering Component = " + schema.getTriggeringComponent());
  363. System.out.println("EnclosingElementName =" + schema.getEnclosingElementName());
  364. }
  365. }//print
  366. */
  367. } // class XMLGrammarPoolImpl