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