Added thread-safety around use of core's QueryParser.

Old XML parser constructors use a mode which will synchronize on use of the user-supplied QueryParser. 
New constructors offer alternative option of passing "defaultField" String which is used to create a new single-use QueryParser for each parse operation.

git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@628568 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Mark Harwood 2008-02-17 22:32:58 +00:00
parent 95e2e57c86
commit caed55ef5e
5 changed files with 82 additions and 12 deletions

View File

@ -59,7 +59,28 @@ public class CoreParser implements QueryBuilder
public static int maxNumCachedFilters=20;
/**
* Construct an XML parser that uses a single instance QueryParser for handling
* UserQuery tags - all parse operations are synchronised on this parser
* @param analyzer
* @param parser A QueryParser which will be synchronized on during parse calls.
*/
public CoreParser(Analyzer analyzer, QueryParser parser)
{
this(null,analyzer,parser);
}
/**
* Constructs an XML parser that creates a QueryParser for each UserQuery request.
* @param defaultField The default field name used by QueryParsers constructed for UserQuery tags
* @param analyzer
*/
public CoreParser(String defaultField, Analyzer analyzer)
{
this(defaultField,analyzer,null);
}
protected CoreParser(String defaultField,Analyzer analyzer, QueryParser parser)
{
this.analyzer=analyzer;
this.parser=parser;
@ -72,7 +93,14 @@ public class CoreParser implements QueryBuilder
queryFactory.addBuilder("TermsQuery",new TermsQueryBuilder(analyzer));
queryFactory.addBuilder("MatchAllDocsQuery",new MatchAllDocsQueryBuilder());
queryFactory.addBuilder("BooleanQuery",new BooleanQueryBuilder(queryFactory));
queryFactory.addBuilder("UserQuery",new UserInputQueryBuilder(parser));
if(parser!=null)
{
queryFactory.addBuilder("UserQuery",new UserInputQueryBuilder(parser));
}
else
{
queryFactory.addBuilder("UserQuery",new UserInputQueryBuilder(defaultField,analyzer));
}
queryFactory.addBuilder("FilteredQuery",new FilteredQueryBuilder(filterFactory,queryFactory));
queryFactory.addBuilder("ConstantScoreQuery",new ConstantScoreQueryBuilder(filterFactory));

View File

@ -27,9 +27,29 @@ import org.apache.lucene.xmlparser.builders.TermsFilterBuilder;
public class CorePlusExtensionsParser extends CoreParser
{
/**
* Construct an XML parser that uses a single instance QueryParser for handling
* UserQuery tags - all parse operations are synchronised on this parser
* @param analyzer
* @param parser A QueryParser which will be synchronized on during parse calls.
*/
public CorePlusExtensionsParser(Analyzer analyzer, QueryParser parser)
{
super(analyzer, parser);
this(null,analyzer, parser);
}
/**
* Constructs an XML parser that creates a QueryParser for each UserQuery request.
* @param defaultField The default field name used by QueryParsers constructed for UserQuery tags
* @param analyzer
*/
public CorePlusExtensionsParser(String defaultField,Analyzer analyzer)
{
this(defaultField,analyzer, null);
}
private CorePlusExtensionsParser(String defaultField,Analyzer analyzer, QueryParser parser)
{
super(defaultField,analyzer, parser);
filterFactory.addBuilder("TermsFilter",new TermsFilterBuilder(analyzer));
filterFactory.addBuilder("BooleanFilter",new BooleanFilterBuilder(filterFactory));
filterFactory.addBuilder("DuplicateFilter",new DuplicateFilterBuilder());
@ -39,6 +59,4 @@ public class CorePlusExtensionsParser extends CoreParser
queryFactory.addBuilder("FuzzyLikeThisQuery", new FuzzyLikeThisQueryBuilder(analyzer));
}
}

View File

@ -1,5 +1,6 @@
package org.apache.lucene.xmlparser.builders;
import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.queryParser.ParseException;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Query;
@ -26,17 +27,28 @@ import org.w3c.dom.Element;
*/
/**
* UserInputQueryBuilder uses 1 of 2 strategies for thread-safe parsing:
* 1) Synchronizing access to "parse" calls on a previously supplied QueryParser
* or..
* 2) creating a new QueryParser object for each parse request
* @author maharwood
*/
public class UserInputQueryBuilder implements QueryBuilder {
QueryParser parser;
QueryParser unSafeParser;
private Analyzer analyzer;
private String defaultField;
/**
* @param parser
* @param parser thread un-safe query parser
*/
public UserInputQueryBuilder(QueryParser parser) {
this.parser = parser;
this.unSafeParser = parser;
}
public UserInputQueryBuilder(String defaultField, Analyzer analyzer) {
this.analyzer = analyzer;
this.defaultField = defaultField;
}
/* (non-Javadoc)
@ -45,7 +57,21 @@ public class UserInputQueryBuilder implements QueryBuilder {
public Query getQuery(Element e) throws ParserException {
String text=DOMUtils.getText(e);
try {
Query q = parser.parse(text);
Query q = null;
if(unSafeParser!=null)
{
//synchronize on unsafe parser
synchronized (unSafeParser)
{
q = unSafeParser.parse(text);
}
}
else
{
//Create new parser
QueryParser parser=new QueryParser(defaultField,analyzer);
q = parser.parse(text);
}
q.setBoost(DOMUtils.getAttribute(e,"boost",1.0f));
return q;
} catch (ParseException e1) {

View File

@ -12,7 +12,6 @@ import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
@ -56,7 +55,7 @@ public class TestParser extends TestCase {
super.setUp();
//initialize the parser
builder=new CorePlusExtensionsParser(analyzer,new QueryParser("contents", analyzer));
builder=new CorePlusExtensionsParser("contents",analyzer);
//initialize the index (done once, then cached in static data for use with ALL tests)
if(dir==null)

View File

@ -13,7 +13,6 @@ import org.apache.lucene.analysis.Analyzer;
import org.apache.lucene.analysis.standard.StandardAnalyzer;
import org.apache.lucene.document.Field;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.queryParser.QueryParser;
import org.apache.lucene.search.Hits;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
@ -154,7 +153,7 @@ public class TestQueryTemplateManager extends TestCase {
searcher=new IndexSearcher(dir);
//initialize the parser
builder=new CorePlusExtensionsParser(analyzer,new QueryParser("artist", analyzer));
builder=new CorePlusExtensionsParser("artist", analyzer);
}