1 package org.apache.lucene.xmlparser; 2 3 import java.io.ByteArrayOutputStream; 4 import java.io.IOException; 5 import java.io.InputStream; 6 import java.util.Enumeration; 7 import java.util.HashMap; 8 import java.util.Properties; 9 10 import javax.xml.parsers.DocumentBuilder; 11 import javax.xml.parsers.DocumentBuilderFactory; 12 import javax.xml.parsers.ParserConfigurationException; 13 import javax.xml.transform.Result; 14 import javax.xml.transform.Source; 15 import javax.xml.transform.Templates; 16 import javax.xml.transform.Transformer; 17 import javax.xml.transform.TransformerConfigurationException; 18 import javax.xml.transform.TransformerException; 19 import javax.xml.transform.TransformerFactory; 20 import javax.xml.transform.dom.DOMResult; 21 import javax.xml.transform.dom.DOMSource; 22 import javax.xml.transform.stream.StreamResult; 23 24 import org.w3c.dom.Document; 25 import org.w3c.dom.Element; 26 import org.xml.sax.SAXException; 27 28 /** 29 * Licensed to the Apache Software Foundation (ASF) under one or more 30 * contributor license agreements. See the NOTICE file distributed with 31 * this work for additional information regarding copyright ownership. 32 * The ASF licenses this file to You under the Apache License, Version 2.0 33 * (the "License"); you may not use this file except in compliance with 34 * the License. You may obtain a copy of the License at 35 * 36 * http://www.apache.org/licenses/LICENSE-2.0 37 * 38 * Unless required by applicable law or agreed to in writing, software 39 * distributed under the License is distributed on an "AS IS" BASIS, 40 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 41 * See the License for the specific language governing permissions and 42 * limitations under the License. 43 */ 44 /** 45 * Provides utilities for turning query form input (such as from a web page or Swing gui) into 46 * Lucene XML queries by using XSL templates. This approach offers a convenient way of externalizing 47 * and changing how user input is turned into Lucene queries. 48 * Database applications often adopt similar practices by externalizing SQL in template files that can 49 * be easily changed/optimized by a DBA. 50 * The static methods can be used on their own or by creating an instance of this class you can store and 51 * re-use compiled stylesheets for fast use (e.g. in a server environment) 52 */ 53 public class QueryTemplateManager 54 { 55 static DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance (); 56 static TransformerFactory tFactory = TransformerFactory.newInstance(); 57 58 HashMap<String,Templates> compiledTemplatesCache=new HashMap<String,Templates>(); 59 Templates defaultCompiledTemplates=null; 60 61 62 public QueryTemplateManager() 63 { 64 65 } 66 public QueryTemplateManager(InputStream xslIs) throws TransformerConfigurationException, ParserConfigurationException, SAXException, IOException 67 { 68 addDefaultQueryTemplate(xslIs); 69 } 70 public void addDefaultQueryTemplate(InputStream xslIs) throws TransformerConfigurationException, ParserConfigurationException, SAXException, IOException 71 { 72 defaultCompiledTemplates=getTemplates(xslIs); 73 } 74 public void addQueryTemplate(String name, InputStream xslIs) throws TransformerConfigurationException, ParserConfigurationException, SAXException, IOException 75 { 76 compiledTemplatesCache.put(name,getTemplates(xslIs)); 77 } 78 public String getQueryAsXmlString(Properties formProperties,String queryTemplateName) throws SAXException, IOException, ParserConfigurationException, TransformerException 79 { 80 Templates ts= compiledTemplatesCache.get(queryTemplateName); 81 return getQueryAsXmlString(formProperties, ts); 82 } 83 84 public Document getQueryAsDOM(Properties formProperties,String queryTemplateName) throws SAXException, IOException, ParserConfigurationException, TransformerException 85 { 86 Templates ts= compiledTemplatesCache.get(queryTemplateName); 87 return getQueryAsDOM(formProperties, ts); 88 } 89 public String getQueryAsXmlString(Properties formProperties) throws SAXException, IOException, ParserConfigurationException, TransformerException 90 { 91 return getQueryAsXmlString(formProperties, defaultCompiledTemplates); 92 } 93 94 public Document getQueryAsDOM(Properties formProperties) throws SAXException, IOException, ParserConfigurationException, TransformerException 95 { 96 return getQueryAsDOM(formProperties, defaultCompiledTemplates); 97 } 98 99 100 /** 101 * Fast means of constructing query using a precompiled stylesheet 102 */ 103 public static String getQueryAsXmlString(Properties formProperties, Templates template) throws SAXException, IOException, ParserConfigurationException, TransformerException 104 { 105 ByteArrayOutputStream baos=new ByteArrayOutputStream(); 106 StreamResult result=new StreamResult(baos); 107 transformCriteria(formProperties,template,result); 108 return baos.toString(); 109 } 110 111 /** 112 * Slow means of constructing query parsing a stylesheet from an input stream 113 */ 114 public static String getQueryAsXmlString(Properties formProperties, InputStream xslIs) throws SAXException, IOException, ParserConfigurationException, TransformerException 115 { 116 ByteArrayOutputStream baos=new ByteArrayOutputStream(); 117 StreamResult result=new StreamResult(baos); 118 transformCriteria(formProperties,xslIs,result); 119 return baos.toString(); 120 } 121 122 123 /** 124 * Fast means of constructing query using a cached,precompiled stylesheet 125 */ 126 public static Document getQueryAsDOM(Properties formProperties, Templates template) throws SAXException, IOException, ParserConfigurationException, TransformerException 127 { 128 DOMResult result=new DOMResult(); 129 transformCriteria(formProperties,template,result); 130 return (Document)result.getNode(); 131 } 132 133 134 /** 135 * Slow means of constructing query - parses stylesheet from input stream 136 */ 137 public static Document getQueryAsDOM(Properties formProperties, InputStream xslIs) throws SAXException, IOException, ParserConfigurationException, TransformerException 138 { 139 DOMResult result=new DOMResult(); 140 transformCriteria(formProperties,xslIs,result); 141 return (Document)result.getNode(); 142 } 143 144 145 146 147 /** 148 * Slower transformation using an uncompiled stylesheet (suitable for development environment) 149 */ 150 public static void transformCriteria(Properties formProperties, InputStream xslIs, Result result) throws SAXException, IOException, ParserConfigurationException, TransformerException 151 { 152 dbf.setNamespaceAware(true); 153 DocumentBuilder builder = dbf.newDocumentBuilder(); 154 org.w3c.dom.Document xslDoc = builder.parse(xslIs); 155 DOMSource ds = new DOMSource(xslDoc); 156 157 Transformer transformer =null; 158 synchronized (tFactory) 159 { 160 transformer = tFactory.newTransformer(ds); 161 } 162 transformCriteria(formProperties,transformer,result); 163 } 164 165 /** 166 * Fast transformation using a pre-compiled stylesheet (suitable for production environments) 167 */ 168 public static void transformCriteria(Properties formProperties, Templates template, Result result) throws SAXException, IOException, ParserConfigurationException, TransformerException 169 { 170 transformCriteria(formProperties,template.newTransformer(),result); 171 } 172 173 174 175 public static void transformCriteria(Properties formProperties, Transformer transformer, Result result) throws SAXException, IOException, ParserConfigurationException, TransformerException 176 { 177 dbf.setNamespaceAware(true); 178 179 //Create an XML document representing the search index document. 180 DocumentBuilder db = dbf.newDocumentBuilder (); 181 org.w3c.dom.Document doc = db.newDocument (); 182 Element root = doc.createElement ("Document"); 183 doc.appendChild (root); 184 185 Enumeration keysEnum = formProperties.keys(); 186 while(keysEnum.hasMoreElements()) 187 { 188 String propName=(String) keysEnum.nextElement(); 189 String value=formProperties.getProperty(propName); 190 if((value!=null)&&(value.length()>0)) 191 { 192 DOMUtils.insertChild(root,propName,value); 193 } 194 } 195 //Use XSLT to to transform into an XML query string using the queryTemplate 196 DOMSource xml=new DOMSource(doc); 197 transformer.transform(xml,result); 198 } 199 200 /** 201 * Parses a query stylesheet for repeated use 202 */ 203 public static Templates getTemplates(InputStream xslIs) throws ParserConfigurationException, SAXException, IOException, TransformerConfigurationException 204 { 205 dbf.setNamespaceAware(true); 206 DocumentBuilder builder = dbf.newDocumentBuilder(); 207 org.w3c.dom.Document xslDoc = builder.parse(xslIs); 208 DOMSource ds = new DOMSource(xslDoc); 209 return tFactory.newTemplates(ds); 210 } 211 }