mirror of https://github.com/apache/lucene.git
Changes to improve server-side speed and thread safety by caching reusable, compiled stylesheets.
git-svn-id: https://svn.apache.org/repos/asf/lucene/java/trunk@503500 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
842995a83c
commit
0149b5f82f
|
@ -4,6 +4,7 @@ import java.io.ByteArrayOutputStream;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilder;
|
||||
|
@ -11,7 +12,9 @@ import javax.xml.parsers.DocumentBuilderFactory;
|
|||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.Result;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.Templates;
|
||||
import javax.xml.transform.Transformer;
|
||||
import javax.xml.transform.TransformerConfigurationException;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.TransformerFactory;
|
||||
import javax.xml.transform.dom.DOMResult;
|
||||
|
@ -21,6 +24,7 @@ import javax.xml.transform.stream.StreamResult;
|
|||
import org.w3c.dom.Document;
|
||||
import org.w3c.dom.Element;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -43,49 +47,136 @@ import org.xml.sax.SAXException;
|
|||
* and changing how user input is turned into Lucene queries.
|
||||
* Database applications often adopt similar practices by externalizing SQL in template files that can
|
||||
* be easily changed/optimized by a DBA.
|
||||
* The static methods can be used on their own or by creating an instance of this class you can store and
|
||||
* re-use compiled stylesheets for fast use (e.g. in a server environment)
|
||||
* @author Mark Harwood
|
||||
*/
|
||||
public class QueryTemplateManager
|
||||
{
|
||||
static DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance ();
|
||||
static TransformerFactory tFactory = TransformerFactory.newInstance();
|
||||
|
||||
HashMap compiledTemplatesCache=new HashMap();
|
||||
Templates defaultCompiledTemplates=null;
|
||||
|
||||
|
||||
public static String getQueryAsXmlString(Properties formProperties, String templateName) throws SAXException, IOException, ParserConfigurationException, TransformerException
|
||||
public QueryTemplateManager()
|
||||
{
|
||||
return getQueryAsXmlString(formProperties,
|
||||
getDOMSource(QueryTemplateManager.class.getResourceAsStream(templateName)));
|
||||
|
||||
}
|
||||
public QueryTemplateManager(InputStream xslIs) throws TransformerConfigurationException, ParserConfigurationException, SAXException, IOException
|
||||
{
|
||||
addDefaultQueryTemplate(xslIs);
|
||||
}
|
||||
public void addDefaultQueryTemplate(InputStream xslIs) throws TransformerConfigurationException, ParserConfigurationException, SAXException, IOException
|
||||
{
|
||||
defaultCompiledTemplates=getTemplates(xslIs);
|
||||
}
|
||||
public void addQueryTemplate(String name, InputStream xslIs) throws TransformerConfigurationException, ParserConfigurationException, SAXException, IOException
|
||||
{
|
||||
compiledTemplatesCache.put(name,getTemplates(xslIs));
|
||||
}
|
||||
public String getQueryAsXmlString(Properties formProperties,String queryTemplateName) throws SAXException, IOException, ParserConfigurationException, TransformerException
|
||||
{
|
||||
Templates ts=(Templates) compiledTemplatesCache.get(queryTemplateName);
|
||||
return getQueryAsXmlString(formProperties, ts);
|
||||
}
|
||||
|
||||
public static String getQueryAsXmlString(Properties formProperties, Source xslDs) throws SAXException, IOException, ParserConfigurationException, TransformerException
|
||||
public Document getQueryAsDOM(Properties formProperties,String queryTemplateName) throws SAXException, IOException, ParserConfigurationException, TransformerException
|
||||
{
|
||||
Templates ts=(Templates) compiledTemplatesCache.get(queryTemplateName);
|
||||
return getQueryAsDOM(formProperties, ts);
|
||||
}
|
||||
public String getQueryAsXmlString(Properties formProperties) throws SAXException, IOException, ParserConfigurationException, TransformerException
|
||||
{
|
||||
return getQueryAsXmlString(formProperties, defaultCompiledTemplates);
|
||||
}
|
||||
|
||||
public Document getQueryAsDOM(Properties formProperties) throws SAXException, IOException, ParserConfigurationException, TransformerException
|
||||
{
|
||||
return getQueryAsDOM(formProperties, defaultCompiledTemplates);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fast means of constructing query using a precompiled stylesheet
|
||||
*/
|
||||
public static String getQueryAsXmlString(Properties formProperties, Templates template) throws SAXException, IOException, ParserConfigurationException, TransformerException
|
||||
{
|
||||
ByteArrayOutputStream baos=new ByteArrayOutputStream();
|
||||
StreamResult result=new StreamResult(baos);
|
||||
transformCriteria(formProperties,xslDs,result);
|
||||
return baos.toString();
|
||||
transformCriteria(formProperties,template,result);
|
||||
return baos.toString();
|
||||
}
|
||||
|
||||
public static Document getQueryAsDOM(Properties formProperties, String templateName) throws SAXException, IOException, ParserConfigurationException, TransformerException
|
||||
/**
|
||||
* Slow means of constructing query parsing a stylesheet from an input stream
|
||||
*/
|
||||
public static String getQueryAsXmlString(Properties formProperties, InputStream xslIs) throws SAXException, IOException, ParserConfigurationException, TransformerException
|
||||
{
|
||||
return getQueryAsDOM(formProperties, getDOMSource(QueryTemplateManager.class.getResourceAsStream(templateName)));
|
||||
ByteArrayOutputStream baos=new ByteArrayOutputStream();
|
||||
StreamResult result=new StreamResult(baos);
|
||||
transformCriteria(formProperties,xslIs,result);
|
||||
return baos.toString();
|
||||
}
|
||||
public static Document getQueryAsDOM(Properties formProperties, InputStream xslIs) throws SAXException, IOException, ParserConfigurationException, TransformerException
|
||||
{
|
||||
return getQueryAsDOM(formProperties, getDOMSource(xslIs));
|
||||
}
|
||||
|
||||
|
||||
public static Document getQueryAsDOM(Properties formProperties, Source xslDs) throws SAXException, IOException, ParserConfigurationException, TransformerException
|
||||
|
||||
|
||||
/**
|
||||
* Fast means of constructing query using a cached,precompiled stylesheet
|
||||
*/
|
||||
public static Document getQueryAsDOM(Properties formProperties, Templates template) throws SAXException, IOException, ParserConfigurationException, TransformerException
|
||||
{
|
||||
DOMResult result=new DOMResult();
|
||||
transformCriteria(formProperties,xslDs,result);
|
||||
transformCriteria(formProperties,template,result);
|
||||
return (Document)result.getNode();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Slow means of constructing query - parses stylesheet from input stream
|
||||
*/
|
||||
public static Document getQueryAsDOM(Properties formProperties, InputStream xslIs) throws SAXException, IOException, ParserConfigurationException, TransformerException
|
||||
{
|
||||
DOMResult result=new DOMResult();
|
||||
transformCriteria(formProperties,xslIs,result);
|
||||
return (Document)result.getNode();
|
||||
}
|
||||
|
||||
public static void transformCriteria(Properties formProperties, Source xslDs, Result result) throws SAXException, IOException, ParserConfigurationException, TransformerException
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Slower transformation using an uncompiled stylesheet (suitable for development environment)
|
||||
*/
|
||||
public static void transformCriteria(Properties formProperties, InputStream xslIs, Result result) throws SAXException, IOException, ParserConfigurationException, TransformerException
|
||||
{
|
||||
dbf.setNamespaceAware(true);
|
||||
DocumentBuilder builder = dbf.newDocumentBuilder();
|
||||
org.w3c.dom.Document xslDoc = builder.parse(xslIs);
|
||||
DOMSource ds = new DOMSource(xslDoc);
|
||||
|
||||
Transformer transformer = tFactory.newTransformer(xslDs);
|
||||
Transformer transformer =null;
|
||||
synchronized (tFactory)
|
||||
{
|
||||
transformer = tFactory.newTransformer(ds);
|
||||
}
|
||||
transformCriteria(formProperties,transformer,result);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fast transformation using a pre-compiled stylesheet (suitable for production environments)
|
||||
*/
|
||||
public static void transformCriteria(Properties formProperties, Templates template, Result result) throws SAXException, IOException, ParserConfigurationException, TransformerException
|
||||
{
|
||||
transformCriteria(formProperties,template.newTransformer(),result);
|
||||
}
|
||||
|
||||
|
||||
|
||||
public static void transformCriteria(Properties formProperties, Transformer transformer, Result result) throws SAXException, IOException, ParserConfigurationException, TransformerException
|
||||
{
|
||||
dbf.setNamespaceAware(true);
|
||||
|
||||
//Create an XML document representing the search index document.
|
||||
DocumentBuilder db = dbf.newDocumentBuilder ();
|
||||
org.w3c.dom.Document doc = db.newDocument ();
|
||||
|
@ -107,11 +198,15 @@ public class QueryTemplateManager
|
|||
transformer.transform(xml,result);
|
||||
}
|
||||
|
||||
public static DOMSource getDOMSource(InputStream xslIs) throws ParserConfigurationException, SAXException, IOException
|
||||
/**
|
||||
* Parses a query stylesheet for repeated use
|
||||
*/
|
||||
public static Templates getTemplates(InputStream xslIs) throws ParserConfigurationException, SAXException, IOException, TransformerConfigurationException
|
||||
{
|
||||
dbf.setNamespaceAware(true);
|
||||
DocumentBuilder builder = dbf.newDocumentBuilder();
|
||||
org.w3c.dom.Document xslDoc = builder.parse(xslIs);
|
||||
return new DOMSource(xslDoc);
|
||||
DOMSource ds = new DOMSource(xslDoc);
|
||||
return tFactory.newTemplates(ds);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,15 +1,11 @@
|
|||
package org.apache.lucene.xmlparser;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Properties;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.xml.parsers.ParserConfigurationException;
|
||||
import javax.xml.transform.Source;
|
||||
import javax.xml.transform.TransformerException;
|
||||
import javax.xml.transform.dom.DOMSource;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
|
@ -24,6 +20,7 @@ import org.apache.lucene.search.Query;
|
|||
import org.apache.lucene.store.RAMDirectory;
|
||||
import org.w3c.dom.Document;
|
||||
import org.xml.sax.SAXException;
|
||||
|
||||
/**
|
||||
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
* contributor license agreements. See the NOTICE file distributed with
|
||||
|
@ -49,7 +46,6 @@ public class TestQueryTemplateManager extends TestCase {
|
|||
|
||||
CoreParser builder;
|
||||
Analyzer analyzer=new StandardAnalyzer();
|
||||
HashMap templates=new HashMap();
|
||||
private IndexSearcher searcher;
|
||||
|
||||
//A collection of documents' field values for use in our tests
|
||||
|
@ -66,26 +62,31 @@ public class TestQueryTemplateManager extends TestCase {
|
|||
// a choice of query style template to use in the test, with expected number of hits
|
||||
String queryForms[]=
|
||||
{
|
||||
"artist=Fugazi \texpectedMatches=2 \ttemplate=albumBooleanQuery.xsl",
|
||||
"artist=Fugazi \treleaseDate=1990 \texpectedMatches=1 \ttemplate=albumBooleanQuery.xsl",
|
||||
"artist=Buckley \tgenre=rock \texpectedMatches=1 \ttemplate=albumFilteredQuery.xsl",
|
||||
"artist=Buckley \tgenre=electronic \texpectedMatches=0 \ttemplate=albumFilteredQuery.xsl",
|
||||
"queryString=artist:buckly~ NOT genre:electronic \texpectedMatches=1 \ttemplate=albumLuceneClassicQuery.xsl"
|
||||
"artist=Fugazi \texpectedMatches=2 \ttemplate=albumBooleanQuery",
|
||||
"artist=Fugazi \treleaseDate=1990 \texpectedMatches=1 \ttemplate=albumBooleanQuery",
|
||||
"artist=Buckley \tgenre=rock \texpectedMatches=1 \ttemplate=albumFilteredQuery",
|
||||
"artist=Buckley \tgenre=electronic \texpectedMatches=0 \ttemplate=albumFilteredQuery",
|
||||
"queryString=artist:buckly~ NOT genre:electronic \texpectedMatches=1 \ttemplate=albumLuceneClassicQuery"
|
||||
};
|
||||
|
||||
|
||||
public void testFormTransforms() throws SAXException, IOException, ParserConfigurationException, TransformerException, ParserException
|
||||
{
|
||||
//Cache all the query templates we will be referring to.
|
||||
QueryTemplateManager qtm=new QueryTemplateManager();
|
||||
qtm.addQueryTemplate("albumBooleanQuery", getClass().getResourceAsStream("albumBooleanQuery.xsl"));
|
||||
qtm.addQueryTemplate("albumFilteredQuery", getClass().getResourceAsStream("albumFilteredQuery.xsl"));
|
||||
qtm.addQueryTemplate("albumLuceneClassicQuery", getClass().getResourceAsStream("albumLuceneClassicQuery.xsl"));
|
||||
//Run all of our test queries
|
||||
for (int i = 0; i < queryForms.length; i++)
|
||||
{
|
||||
Properties queryFormProperties=getPropsFromString(queryForms[i]);
|
||||
|
||||
//Get the required query XSL template for this test
|
||||
Source template=getTemplate(queryFormProperties.getProperty("template"));
|
||||
// Templates template=getTemplate(queryFormProperties.getProperty("template"));
|
||||
|
||||
//Transform the queryFormProperties into a Lucene XML query
|
||||
Document doc=QueryTemplateManager.getQueryAsDOM(queryFormProperties,template);
|
||||
Document doc=qtm.getQueryAsDOM(queryFormProperties,queryFormProperties.getProperty("template"));
|
||||
|
||||
//Parse the XML query using the XML parser
|
||||
Query q=builder.getQuery(doc.getDocumentElement());
|
||||
|
@ -100,20 +101,6 @@ public class TestQueryTemplateManager extends TestCase {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
private Source getTemplate(String templateName) throws ParserConfigurationException, SAXException, IOException
|
||||
{
|
||||
Source result=(Source) templates.get(templateName);
|
||||
if(result==null)
|
||||
{
|
||||
//Not yet loaded - load the stylesheet
|
||||
result=QueryTemplateManager.getDOMSource(getClass().getResourceAsStream(templateName));
|
||||
templates.put(templateName,result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//Helper method to construct Lucene query forms used in our test
|
||||
Properties getPropsFromString(String nameValuePairs)
|
||||
{
|
||||
|
|
Loading…
Reference in New Issue