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