You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-commits@lucene.apache.org by mh...@apache.org on 2007/02/04 23:51:29 UTC

svn commit: r503500 - in /lucene/java/trunk/contrib/xml-query-parser/src: java/org/apache/lucene/xmlparser/QueryTemplateManager.java test/org/apache/lucene/xmlparser/TestQueryTemplateManager.java

Author: mharwood
Date: Sun Feb  4 14:51:28 2007
New Revision: 503500

URL: http://svn.apache.org/viewvc?view=rev&rev=503500
Log:
Changes to improve server-side speed and thread safety by caching reusable, compiled stylesheets.

Modified:
    lucene/java/trunk/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/QueryTemplateManager.java
    lucene/java/trunk/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/TestQueryTemplateManager.java

Modified: lucene/java/trunk/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/QueryTemplateManager.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/QueryTemplateManager.java?view=diff&rev=503500&r1=503499&r2=503500
==============================================================================
--- lucene/java/trunk/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/QueryTemplateManager.java (original)
+++ lucene/java/trunk/contrib/xml-query-parser/src/java/org/apache/lucene/xmlparser/QueryTemplateManager.java Sun Feb  4 14:51:28 2007
@@ -4,6 +4,7 @@
 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.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 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 @@
  * 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 QueryTemplateManager()
+	{
+		
+	}
+	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, String templateName) 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, 
-				getDOMSource(QueryTemplateManager.class.getResourceAsStream(templateName)));
+		return getQueryAsXmlString(formProperties, defaultCompiledTemplates);
 	}
 	
-	public static String getQueryAsXmlString(Properties formProperties, Source xslDs) throws SAXException, IOException, ParserConfigurationException, TransformerException
+	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
+			
+
+	/**
+	 * Fast means of constructing query using a cached,precompiled stylesheet  
+	 */	
+	public static Document getQueryAsDOM(Properties formProperties, Templates template) throws SAXException, IOException, ParserConfigurationException, TransformerException
 	{
-		return getQueryAsDOM(formProperties, getDOMSource(xslIs));
+  		DOMResult result=new DOMResult();
+  		transformCriteria(formProperties,template,result);
+  		return (Document)result.getNode();
 	}
+
 	
-	
-	public static Document getQueryAsDOM(Properties formProperties, Source xslDs) throws SAXException, IOException, ParserConfigurationException, TransformerException
+	/**
+	 * 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,xslDs,result);
+  		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 @@
 		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);
 	}
 }

Modified: lucene/java/trunk/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/TestQueryTemplateManager.java
URL: http://svn.apache.org/viewvc/lucene/java/trunk/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/TestQueryTemplateManager.java?view=diff&rev=503500&r1=503499&r2=503500
==============================================================================
--- lucene/java/trunk/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/TestQueryTemplateManager.java (original)
+++ lucene/java/trunk/contrib/xml-query-parser/src/test/org/apache/lucene/xmlparser/TestQueryTemplateManager.java Sun Feb  4 14:51:28 2007
@@ -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.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 @@
 
 	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 @@
 	// 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 @@
 		}
 	}
 	
-		
-	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)
 	{