/* * The Apache Software License, Version 1.1 * * * Copyright (c) 1999-2002 The Apache Software Foundation. All rights * reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in * the documentation and/or other materials provided with the * distribution. * * 3. The end-user documentation included with the redistribution, * if any, must include the following acknowledgment: * "This product includes software developed by the * Apache Software Foundation (http://www.apache.org/)." * Alternately, this acknowledgment may appear in the software itself, * if and wherever such third-party acknowledgments normally appear. * * 4. The names "Xerces" and "Apache Software Foundation" must * not be used to endorse or promote products derived from this * software without prior written permission. For written * permission, please contact apache@apache.org. * * 5. Products derived from this software may not be called "Apache", * nor may "Apache" appear in their name, without prior written * permission of the Apache Software Foundation. * * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * ==================================================================== * * This software consists of voluntary contributions made by many * individuals on behalf of the Apache Software Foundation and was * originally based on software copyright (c) 1999, International * Business Machines, Inc., http://www.apache.org. For more * information on the Apache Software Foundation, please see * . */ package com.sun.org.apache.xerces.internal.parsers; import com.sun.org.apache.xerces.internal.xni.grammars.Grammar; import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarPool; import com.sun.org.apache.xerces.internal.xni.grammars.XMLGrammarDescription; import com.sun.org.apache.xerces.internal.util.XMLGrammarPoolImpl; import com.sun.org.apache.xerces.internal.util.ShadowedSymbolTable; import com.sun.org.apache.xerces.internal.util.SymbolTable; import com.sun.org.apache.xerces.internal.util.SynchronizedSymbolTable; /** * A parser pool that enables caching of grammars. The caching parser * pool is constructed with a specific symbol table and grammar pool * that has already been populated with the grammars used by the * application. *

* Once the caching parser pool is constructed, specific parser * instances are created by calling the appropriate factory method * on the parser pool. *

* Note: There is a performance penalty for using * a caching parser pool due to thread safety. Access to the symbol * table and grammar pool must be synchronized to ensure the safe * operation of the symbol table and grammar pool. *

* Note: If performance is critical, then another * mechanism needs to be used instead of the caching parser pool. * One approach would be to create parser instances that do not * share these structures. Instead, each instance would get its * own copy to use while parsing. This avoids the synchronization * overhead at the expense of more memory and the time required * to copy the structures for each new parser instance. And even * when a parser instance is re-used, there is a potential for a * memory leak due to new symbols being added to the symbol table * over time. In other words, always take caution to make sure * that your application is thread-safe and avoids leaking memory. * * @author Andy Clark, IBM * * @version $Id: CachingParserPool.java,v 1.11 2002/06/01 16:36:36 elena Exp $ */ public class CachingParserPool { // // Constants // /** Default shadow symbol table (false). */ public static final boolean DEFAULT_SHADOW_SYMBOL_TABLE = false; /** Default shadow grammar pool (false). */ public static final boolean DEFAULT_SHADOW_GRAMMAR_POOL = false; // // Data // /** * Symbol table. The symbol table that the caching parser pool is * constructed with is automatically wrapped in a synchronized * version for thread-safety. */ protected SymbolTable fSynchronizedSymbolTable; /** * Grammar pool. The grammar pool that the caching parser pool is * constructed with is automatically wrapped in a synchronized * version for thread-safety. */ protected XMLGrammarPool fSynchronizedGrammarPool; /** * Shadow the symbol table for new parser instances. If true, * new parser instances use shadow copies of the main symbol * table and are not allowed to add new symbols to the main * symbol table. New symbols are added to the shadow symbol * table and are local to the parser instance. */ protected boolean fShadowSymbolTable = DEFAULT_SHADOW_SYMBOL_TABLE; /** * Shadow the grammar pool for new parser instances. If true, * new parser instances use shadow copies of the main grammar * pool and are not allowed to add new grammars to the main * grammar pool. New grammars are added to the shadow grammar * pool and are local to the parser instance. */ protected boolean fShadowGrammarPool = DEFAULT_SHADOW_GRAMMAR_POOL; // // Constructors // /** Default constructor. */ public CachingParserPool() { this(new SymbolTable(), new XMLGrammarPoolImpl()); } // () /** * Constructs a caching parser pool with the specified symbol table * and grammar pool. * * @param symbolTable The symbol table. * @param grammarPool The grammar pool. */ public CachingParserPool(SymbolTable symbolTable, XMLGrammarPool grammarPool) { fSynchronizedSymbolTable = new SynchronizedSymbolTable(symbolTable); fSynchronizedGrammarPool = new SynchronizedGrammarPool(grammarPool); } // (SymbolTable,XMLGrammarPool) // // Public methods // /** Returns the symbol table. */ public SymbolTable getSymbolTable() { return fSynchronizedSymbolTable; } // getSymbolTable():SymbolTable /** Returns the grammar pool. */ public XMLGrammarPool getXMLGrammarPool() { return fSynchronizedGrammarPool; } // getXMLGrammarPool():XMLGrammarPool // setters and getters /** * Sets whether new parser instance receive shadow copies of the * main symbol table. * * @param shadow If true, new parser instances use shadow copies * of the main symbol table and are not allowed to * add new symbols to the main symbol table. New * symbols are added to the shadow symbol table and * are local to the parser instance. If false, new * parser instances are allowed to add new symbols * to the main symbol table. */ public void setShadowSymbolTable(boolean shadow) { fShadowSymbolTable = shadow; } // setShadowSymbolTable(boolean) // factory methods /** Creates a new DOM parser. */ public DOMParser createDOMParser() { SymbolTable symbolTable = fShadowSymbolTable ? new ShadowedSymbolTable(fSynchronizedSymbolTable) : fSynchronizedSymbolTable; XMLGrammarPool grammarPool = fShadowGrammarPool ? new ShadowedGrammarPool(fSynchronizedGrammarPool) : fSynchronizedGrammarPool; return new DOMParser(symbolTable, grammarPool); } // createDOMParser():DOMParser /** Creates a new SAX parser. */ public SAXParser createSAXParser() { SymbolTable symbolTable = fShadowSymbolTable ? new ShadowedSymbolTable(fSynchronizedSymbolTable) : fSynchronizedSymbolTable; XMLGrammarPool grammarPool = fShadowGrammarPool ? new ShadowedGrammarPool(fSynchronizedGrammarPool) : fSynchronizedGrammarPool; return new SAXParser(symbolTable, grammarPool); } // createSAXParser():SAXParser // // Classes // /** * Synchronized grammar pool. * * @author Andy Clark, IBM */ public static final class SynchronizedGrammarPool implements XMLGrammarPool { // // Data // /** Main grammar pool. */ private XMLGrammarPool fGrammarPool; // // Constructors // /** Constructs a synchronized grammar pool. */ public SynchronizedGrammarPool(XMLGrammarPool grammarPool) { fGrammarPool = grammarPool; } // (XMLGrammarPool) // // GrammarPool methods // // retrieve the initial set of grammars for the validator // to work with. // REVISIT: does this need to be synchronized since it's just reading? // @param grammarType type of the grammars to be retrieved. // @return the initial grammar set the validator may place in its "bucket" public Grammar [] retrieveInitialGrammarSet(String grammarType ) { synchronized (fGrammarPool) { return fGrammarPool.retrieveInitialGrammarSet(grammarType); } } // retrieveInitialGrammarSet(String): Grammar[] // retrieve a particular grammar. // REVISIT: does this need to be synchronized since it's just reading? // @param gDesc description of the grammar to be retrieved // @return Grammar corresponding to gDesc, or null if none exists. public Grammar retrieveGrammar(XMLGrammarDescription gDesc) { synchronized (fGrammarPool) { return fGrammarPool.retrieveGrammar(gDesc); } } // retrieveGrammar(XMLGrammarDesc): Grammar // give the grammarPool the option of caching these grammars. // This certainly must be synchronized. // @param grammarType The type of the grammars to be cached. // @param grammars the Grammars that may be cached (unordered, Grammars previously // given to the validator may be included). public void cacheGrammars(String grammarType, Grammar[] grammars) { synchronized (fGrammarPool) { fGrammarPool.cacheGrammars(grammarType, grammars); } } // cacheGrammars(String, Grammar[]); /** lock the grammar pool */ public void lockPool() { synchronized (fGrammarPool) { fGrammarPool.lockPool(); } } // lockPool() /** clear the grammar pool */ public void clear() { synchronized (fGrammarPool) { fGrammarPool.clear(); } } // lockPool() /** unlock the grammar pool */ public void unlockPool() { synchronized (fGrammarPool) { fGrammarPool.unlockPool(); } } // unlockPool() /*** * Methods corresponding to original (pre Xerces2.0.0final) * grammarPool have been commented out. */ /** * Puts the specified grammar into the grammar pool. * * @param key Key to associate with grammar. * @param grammar Grammar object. */ /****** public void putGrammar(String key, Grammar grammar) { synchronized (fGrammarPool) { fGrammarPool.putGrammar(key, grammar); } } // putGrammar(String,Grammar) *******/ /** * Returns the grammar associated to the specified key. * * @param key The key of the grammar. */ /********** public Grammar getGrammar(String key) { synchronized (fGrammarPool) { return fGrammarPool.getGrammar(key); } } // getGrammar(String):Grammar ***********/ /** * Removes the grammar associated to the specified key from the * grammar pool and returns the removed grammar. * * @param key The key of the grammar. */ /********** public Grammar removeGrammar(String key) { synchronized (fGrammarPool) { return fGrammarPool.removeGrammar(key); } } // removeGrammar(String):Grammar ******/ /** * Returns true if the grammar pool contains a grammar associated * to the specified key. * * @param key The key of the grammar. */ /********** public boolean containsGrammar(String key) { synchronized (fGrammarPool) { return fGrammarPool.containsGrammar(key); } } // containsGrammar(String):boolean ********/ } // class SynchronizedGrammarPool /** * Shadowed grammar pool. * This class is predicated on the existence of a concrete implementation; * so using our own doesn't seem to bad an idea. * * @author Andy Clark, IBM * @author Neil Graham, IBM */ public static final class ShadowedGrammarPool extends XMLGrammarPoolImpl { // // Data // /** Main grammar pool. */ private XMLGrammarPool fGrammarPool; // // Constructors // /** Constructs a shadowed grammar pool. */ public ShadowedGrammarPool(XMLGrammarPool grammarPool) { fGrammarPool = grammarPool; } // (GrammarPool) // // GrammarPool methods // /** * Retrieve the initial set of grammars for the validator to work with. * REVISIT: does this need to be synchronized since it's just reading? * * @param grammarType Type of the grammars to be retrieved. * @return The initial grammar set the validator may place in its "bucket" */ public Grammar [] retrieveInitialGrammarSet(String grammarType ) { Grammar [] grammars = super.retrieveInitialGrammarSet(grammarType); if (grammars != null) return grammars; return fGrammarPool.retrieveInitialGrammarSet(grammarType); } // retrieveInitialGrammarSet(String): Grammar[] /** * Retrieve a particular grammar. * REVISIT: does this need to be synchronized since it's just reading? * * @param gDesc Description of the grammar to be retrieved * @return Grammar corresponding to gDesc, or null if none exists. */ public Grammar retrieveGrammar(XMLGrammarDescription gDesc) { Grammar g = super.retrieveGrammar(gDesc); if(g != null) return g; return fGrammarPool.retrieveGrammar(gDesc); } // retrieveGrammar(XMLGrammarDesc): Grammar /** * Give the grammarPool the option of caching these grammars. * This certainly must be synchronized. * * @param grammarType The type of the grammars to be cached. * @param grammars The Grammars that may be cached (unordered, Grammars previously * given to the validator may be included). */ public void cacheGrammars(String grammarType, Grammar[] grammars) { // better give both grammars a shot... super.cacheGrammars(grammarType, grammars); fGrammarPool.cacheGrammars(grammarType, grammars); } // cacheGrammars(grammarType, Grammar[]); /** * Returns the grammar associated to the specified description. * * @param desc The description of the grammar. */ public Grammar getGrammar(XMLGrammarDescription desc) { if (super.containsGrammar(desc)) { return super.getGrammar(desc); } return null; } // getGrammar(XMLGrammarDescription):Grammar /** * Returns true if the grammar pool contains a grammar associated * to the specified description. * * @param desc The description of the grammar. */ public boolean containsGrammar(XMLGrammarDescription desc) { return super.containsGrammar(desc); } // containsGrammar(XMLGrammarDescription):boolean } // class ShadowedGrammarPool } // class CachingParserPool