You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
431 lines
15 KiB
431 lines
15 KiB
/*
|
|
* Copyright (c) 2007, 2018, Oracle and/or its affiliates. All rights reserved.
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*/
|
|
/*
|
|
* Copyright 1999-2002,2004 The Apache Software Foundation.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
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.
|
|
* <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 Andy Clark, IBM
|
|
*
|
|
*/
|
|
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());
|
|
} // <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, XMLGrammarPool grammarPool) {
|
|
fSynchronizedSymbolTable = new SynchronizedSymbolTable(symbolTable);
|
|
fSynchronizedGrammarPool = new SynchronizedGrammarPool(grammarPool);
|
|
} // <init>(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;
|
|
} // <init>(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;
|
|
} // <init>(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
|