blob: 31cd71648f7e2d51ca794777b9ab9ef3534edd96 [file] [log] [blame]
/*
* 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