| /* |
| * The Apache Software License, Version 1.1 |
| * |
| * |
| * Copyright (c) 1999,2000 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 |
| * <http://www.apache.org/>. |
| */ |
| |
| package org.apache.xerces.parsers; |
| |
| import org.apache.xerces.impl.validation.Grammar; |
| import org.apache.xerces.impl.validation.GrammarPool; |
| |
| import org.apache.xerces.util.SymbolTable; |
| |
| /** |
| * 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. |
| * <p> |
| * Once the caching parser pool is constructed, specific parser |
| * instances are created by calling the appropriate factory method |
| * on the parser pool. |
| * <p> |
| * <strong>Note:</strong> 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. |
| * <p> |
| * <strong>Note:</strong> 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 Stubs generated by DesignDoc on Mon Sep 11 11:10:57 PDT 2000 |
| * @author Andy Clark, IBM |
| * |
| * @version $Id$ |
| */ |
| 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 GrammarPool 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 GrammarPool()); |
| } // <init>() |
| |
| /** |
| * 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, GrammarPool grammarPool) { |
| fSynchronizedSymbolTable = new SynchronizedSymbolTable(symbolTable); |
| fSynchronizedGrammarPool = new SynchronizedGrammarPool(grammarPool); |
| } // <init>(SymbolTable,GrammarPool) |
| |
| // |
| // Public methods |
| // |
| |
| /** Returns the symbol table. */ |
| public SymbolTable getSymbolTable() { |
| return fSynchronizedSymbolTable; |
| } // getSymbolTable():SymbolTable |
| |
| /** Returns the grammar pool. */ |
| public GrammarPool getGrammarPool() { |
| return fSynchronizedGrammarPool; |
| } // getGrammarPool():GrammarPool |
| |
| // 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; |
| GrammarPool 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; |
| GrammarPool grammarPool = fShadowGrammarPool |
| ? new ShadowedGrammarPool(fSynchronizedGrammarPool) |
| : fSynchronizedGrammarPool; |
| return new SAXParser(symbolTable, grammarPool); |
| } // createSAXParser():SAXParser |
| |
| // |
| // Classes |
| // |
| |
| /** |
| * Synchronized symbol table. |
| * |
| * @author Andy Clark, IBM |
| */ |
| public static final class SynchronizedSymbolTable |
| extends SymbolTable { |
| |
| // |
| // Data |
| // |
| |
| /** Main symbol table. */ |
| protected SymbolTable fSymbolTable; |
| |
| // |
| // Constructors |
| // |
| |
| /** Constructs a synchronized symbol table. */ |
| public SynchronizedSymbolTable(SymbolTable symbolTable) { |
| fSymbolTable = symbolTable; |
| } // <init>(SymbolTable) |
| |
| // |
| // SymbolTable methods |
| // |
| |
| /** |
| * Adds the specified symbol to the symbol table and returns a |
| * reference to the unique symbol. If the symbol already exists, |
| * the previous symbol reference is returned instead, in order |
| * guarantee that symbol references remain unique. |
| * |
| * @param symbol The new symbol. |
| */ |
| public String addSymbol(String symbol) { |
| |
| synchronized (fSymbolTable) { |
| return fSymbolTable.addSymbol(symbol); |
| } |
| |
| } // addSymbol(String) |
| |
| /** |
| * Adds the specified symbol to the symbol table and returns a |
| * reference to the unique symbol. If the symbol already exists, |
| * the previous symbol reference is returned instead, in order |
| * guarantee that symbol references remain unique. |
| * |
| * @param buffer The buffer containing the new symbol. |
| * @param offset The offset into the buffer of the new symbol. |
| * @param length The length of the new symbol in the buffer. |
| */ |
| public String addSymbol(char[] buffer, int offset, int length) { |
| |
| synchronized (fSymbolTable) { |
| return fSymbolTable.addSymbol(buffer, offset, length); |
| } |
| |
| } // addSymbol(char[],int,int):String |
| |
| /** |
| * Returns true if the symbol table already contains the specified |
| * symbol. |
| * |
| * @param symbol The symbol to look for. |
| */ |
| public boolean containsSymbol(String symbol) { |
| |
| synchronized (fSymbolTable) { |
| return fSymbolTable.containsSymbol(symbol); |
| } |
| |
| } // containsSymbol(String):boolean |
| |
| /** |
| * Returns true if the symbol table already contains the specified |
| * symbol. |
| * |
| * @param buffer The buffer containing the symbol to look for. |
| * @param offset The offset into the buffer. |
| * @param length The length of the symbol in the buffer. |
| */ |
| public boolean containsSymbol(char[] buffer, int offset, int length) { |
| |
| synchronized (fSymbolTable) { |
| return fSymbolTable.containsSymbol(buffer, offset, length); |
| } |
| |
| } // containsSymbol(char[],int,int):boolean |
| |
| } // class SynchronizedSymbolTable |
| |
| /** |
| * Shadowed symbol table. |
| * |
| * @author Andy Clark, IBM |
| */ |
| public static final class ShadowedSymbolTable |
| extends SymbolTable { |
| |
| // |
| // Data |
| // |
| |
| /** Main symbol table. */ |
| protected SymbolTable fSymbolTable; |
| |
| // |
| // Constructors |
| // |
| |
| /** Constructs a shadow of the specified symbol table. */ |
| public ShadowedSymbolTable(SymbolTable symbolTable) { |
| fSymbolTable = symbolTable; |
| } // <init>(SymbolTable) |
| |
| // |
| // SymbolTable methods |
| // |
| |
| /** |
| * Adds the specified symbol to the symbol table and returns a |
| * reference to the unique symbol. If the symbol already exists, |
| * the previous symbol reference is returned instead, in order |
| * guarantee that symbol references remain unique. |
| * |
| * @param symbol The new symbol. |
| */ |
| public String addSymbol(String symbol) { |
| |
| if (fSymbolTable.containsSymbol(symbol)) { |
| return fSymbolTable.addSymbol(symbol); |
| } |
| return super.addSymbol(symbol); |
| |
| } // addSymbol(String) |
| |
| /** |
| * Adds the specified symbol to the symbol table and returns a |
| * reference to the unique symbol. If the symbol already exists, |
| * the previous symbol reference is returned instead, in order |
| * guarantee that symbol references remain unique. |
| * |
| * @param buffer The buffer containing the new symbol. |
| * @param offset The offset into the buffer of the new symbol. |
| * @param length The length of the new symbol in the buffer. |
| */ |
| public String addSymbol(char[] buffer, int offset, int length) { |
| |
| if (fSymbolTable.containsSymbol(buffer, offset, length)) { |
| return fSymbolTable.addSymbol(buffer, offset, length); |
| } |
| return super.addSymbol(buffer, offset, length); |
| |
| } // addSymbol(char[],int,int):String |
| |
| /** |
| * Returns a hashcode value for the specified symbol. The value |
| * returned by this method must be identical to the value returned |
| * by the <code>hash(char[],int,int)</code> method when called |
| * with the character array that comprises the symbol string. |
| * |
| * @param symbol The symbol to hash. |
| */ |
| public int hash(String symbol) { |
| return fSymbolTable.hash(symbol); |
| } // hash(String):int |
| |
| /** |
| * Returns a hashcode value for the specified symbol information. |
| * The value returned by this method must be identical to the value |
| * returned by the <code>hash(String)</code> method when called |
| * with the string object created from the symbol information. |
| * |
| * @param buffer The character buffer containing the symbol. |
| * @param offset The offset into the character buffer of the start |
| * of the symbol. |
| * @param length The length of the symbol. |
| */ |
| public int hash(char[] buffer, int offset, int length) { |
| return fSymbolTable.hash(buffer, offset, length); |
| } // hash(char[],int,int):int |
| |
| } // class ShadowedSymbolTable |
| |
| /** |
| * Synchronized grammar pool. |
| * |
| * @author Andy Clark, IBM |
| */ |
| public static final class SynchronizedGrammarPool |
| extends GrammarPool { |
| |
| // |
| // Data |
| // |
| |
| /** Main grammar pool. */ |
| private GrammarPool fGrammarPool; |
| |
| // |
| // Constructors |
| // |
| |
| /** Constructs a synchronized grammar pool. */ |
| public SynchronizedGrammarPool(GrammarPool grammarPool) { |
| fGrammarPool = grammarPool; |
| } // <init>(GrammarPool) |
| |
| // |
| // GrammarPool methods |
| // |
| |
| /** |
| * 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. |
| * |
| * @author Andy Clark, IBM |
| */ |
| public static final class ShadowedGrammarPool |
| extends GrammarPool { |
| |
| // |
| // Data |
| // |
| |
| /** Main grammar pool. */ |
| private GrammarPool fGrammarPool; |
| |
| // |
| // Constructors |
| // |
| |
| /** Constructs a shadowed grammar pool. */ |
| public ShadowedGrammarPool(GrammarPool grammarPool) { |
| fGrammarPool = grammarPool; |
| } // <init>(GrammarPool) |
| |
| // |
| // GrammarPool methods |
| // |
| |
| /** |
| * Returns the grammar associated to the specified key. |
| * |
| * @param key The key of the grammar. |
| */ |
| public Grammar getGrammar(String key) { |
| |
| if (super.containsGrammar(key)) { |
| return super.getGrammar(key); |
| } |
| return fGrammarPool.getGrammar(key); |
| |
| } // getGrammar(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) { |
| return super.containsGrammar(key) || fGrammarPool.containsGrammar(key); |
| } // containsGrammar(String):boolean |
| |
| } // class ShadowedGrammarPool |
| |
| } // class CachingParserPool |