Support for customizing the QueryResponseWriter per request - SOLR-16

git-svn-id: https://svn.apache.org/repos/asf/incubator/solr/trunk@409560 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Chris M. Hostetter 2006-05-26 05:44:02 +00:00
parent 15e77d2ef4
commit 2d04fecca2
7 changed files with 172 additions and 19 deletions

View File

@ -12,8 +12,9 @@ New Features
6. The default search field may now be overridden by requests to the
standard request handler using the df query parameter. (Erik Hatcher)
7. Added DisMaxRequestHandler and SolrPluginUtils. (Chris Hostetter)
8. Support for customizing the QueryResponseWriter per request
(Mike Baranczak / SOLR-16 / hossman)
Changes in runtime behavior
1. classes reorganized into different packages, package names changed to Apache
2. force read of document stored fields in QuerySenderListener

View File

@ -218,6 +218,17 @@
</str>
</requestHandler>
<!-- queryResponseWriter plugins... query responses will be written using the
writer specified by the 'wt' request parameter matching the name of a registered
writer.
The "standard" writer is the default and will be used if 'wt' is not specified
in the request. XMLResponseWriter will be used if nothing specified here.
<queryResponseWriter name="standard" class="org.apache.solr.request.XMLResponseWriter"/>
<queryResponseWriter name="custom" class="com.example.MyResponseWriter"/>
-->
<!-- config for the admin interface -->
<admin>
<defaultQuery>solr</defaultQuery>

View File

@ -16,13 +16,17 @@
package org.apache.solr.core;
import java.util.Map;
import java.util.TreeMap;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.BooleanQuery;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.FSDirectory;
import org.apache.solr.request.QueryResponseWriter;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrQueryResponse;
import org.apache.solr.request.XMLResponseWriter;
import org.apache.solr.schema.IndexSchema;
import org.apache.solr.search.SolrIndexSearcher;
import org.apache.solr.update.*;
@ -30,6 +34,7 @@ import org.apache.solr.util.DOMUtil;
import org.apache.solr.util.RefCounted;
import org.apache.solr.util.StrUtils;
import org.apache.solr.util.XML;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xmlpull.v1.XmlPullParser;
@ -52,6 +57,7 @@ import java.util.logging.Logger;
/**
* @author yonik
* @author <a href='mailto:mbaranczak@epublishing.com'> Mike Baranczak </a>
* @version $Id$
*/
@ -196,6 +202,8 @@ public final class SolrCore {
parseListeners();
initIndex();
initWriters();
try {
// Open the searcher *before* the handler so we don't end up opening
@ -937,6 +945,61 @@ public final class SolrCore {
log.severe("Error writing to putput stream: "+ee);
}
}
private QueryResponseWriter defaultResponseWriter;
private Map<String, QueryResponseWriter> responseWriters
= new TreeMap<String, QueryResponseWriter>();
/** Configure the query response writers. There will always be a default writer; additional
* writers may also be configured. */
private void initWriters() {
String xpath = "queryResponseWriter";
NodeList nodes = (NodeList) SolrConfig.config.evaluate(xpath, XPathConstants.NODESET);
int length = nodes.getLength();
for (int i=0; i<length; i++) {
Element elm = (Element) nodes.item(i);
try {
String name = DOMUtil.getAttr(elm,"name", xpath+" config");
String className = DOMUtil.getAttr(elm,"class", xpath+" config");
log.info("adding queryResponseWriter "+name+"="+className);
QueryResponseWriter writer = (QueryResponseWriter) Config.newInstance(className);
responseWriters.put(name, writer);
} catch (Exception ex) {
SolrException.logOnce(log,null, ex);
// if a writer can't be created, skip it and continue
}
}
// configure the default response writer; this one should never be null
if (responseWriters.containsKey("standard")) {
defaultResponseWriter = responseWriters.get("standard");
}
if (defaultResponseWriter == null) {
defaultResponseWriter = new XMLResponseWriter();
}
}
/** Finds a writer by name, or returns the default writer if not found. */
public final QueryResponseWriter getQueryResponseWriter(String writerName) {
if (writerName != null) {
QueryResponseWriter writer = responseWriters.get(writerName);
if (writer != null) {
return writer;
}
}
return defaultResponseWriter;
}
/** Returns the appropriate writer for a request. If the request specifies a writer via the
* 'wt' parameter, attempts to find that one; otherwise return the default writer.
*/
public final QueryResponseWriter getQueryResponseWriter(SolrQueryRequest request) {
return getQueryResponseWriter(request.getParam("wt"));
}
}

View File

@ -51,7 +51,6 @@ import java.util.*;
public class TestHarness {
private SolrCore core;
private XMLResponseWriter xmlwriter = new XMLResponseWriter();
private XPath xpath = XPathFactory.newInstance().newXPath();
private DocumentBuilder builder;
@ -183,12 +182,13 @@ public class TestHarness {
throw rsp.getException();
}
StringWriter writer = new StringWriter(32000);
xmlwriter.write(writer,req,rsp);
StringWriter sw = new StringWriter(32000);
QueryResponseWriter responseWriter = core.getQueryResponseWriter(req);
responseWriter.write(sw,req,rsp);
req.close();
return writer.toString();
return sw.toString();
}

View File

@ -0,0 +1,73 @@
/**
* Copyright 2006 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 org.apache.solr;
import java.io.IOException;
import java.io.Writer;
import org.apache.solr.request.QueryResponseWriter;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrQueryResponse;
import org.apache.solr.util.AbstractSolrTestCase;
import org.apache.solr.util.TestHarness;
/** Tests the ability to configure multiple query output writers, and select those
* at query time.
*
* @author <a href='mailto:mbaranczak@epublishing.com'> Mike Baranczak </a>
*/
public class OutputWriterTest extends AbstractSolrTestCase {
/** The XML string that's output for testing purposes. */
public static final String USELESS_OUTPUT = "useless output";
public String getSchemaFile() { return "solr/crazy-path-to-schema.xml"; }
public String getSolrConfigFile() { return "solr/crazy-path-to-config.xml"; }
public void testOriginalSolrWriter() {
lrf.args.put("wt", "standard");
assertQ(req("foo"), "//response/responseHeader/status");
lrf.args.remove("wt");
assertQ(req("foo"), "//response/responseHeader/status");
}
public void testUselessWriter() throws Exception {
lrf.args.put("wt", "useless");
String out = h.query(req("foo"));
assertEquals(USELESS_OUTPUT, out);
}
////////////////////////////////////////////////////////////////////////////
/** An output writer that doesn't do anything useful. */
public static class UselessOutputWriter implements QueryResponseWriter {
public UselessOutputWriter() {}
public void write(Writer writer, SolrQueryRequest request, SolrQueryResponse response)
throws IOException {
writer.write(USELESS_OUTPUT);
}
}
}

View File

@ -40,8 +40,13 @@
<HashDocSet maxSize="3000" loadFactor="0.75"/>
<boolTofilterOptimizer enabled="true" cacheSize="32" threshold=".05"/>
</query>
<requestHandler name="standard" class="solr.StandardRequestHandler" />
<requestHandler name="crazy_custom_qt" class="solr.StandardRequestHandler" />
<queryResponseWriter name="standard" class="org.apache.solr.request.XMLResponseWriter"/>
<queryResponseWriter name="useless" class="org.apache.solr.OutputWriterTest$UselessOutputWriter"/>
<admin>
<defaultQuery>solr</defaultQuery>

View File

@ -20,7 +20,7 @@ import org.apache.solr.core.Config;
import org.apache.solr.core.SolrCore;
import org.apache.solr.core.SolrException;
import org.apache.solr.request.SolrQueryResponse;
import org.apache.solr.request.XMLResponseWriter;
import org.apache.solr.request.QueryResponseWriter;
import javax.naming.Context;
import javax.naming.InitialContext;
@ -36,17 +36,17 @@ import java.util.logging.Logger;
/**
* @author yonik
* @author <a href='mailto:mbaranczak@epublishing.com'> Mike Baranczak </a>
*/
public class SolrServlet extends HttpServlet {
final Logger log = Logger.getLogger(SolrServlet.class.getName());
SolrCore core;
private static String CONTENT_TYPE="text/xml;charset=UTF-8";
XMLResponseWriter xmlResponseWriter;
public void init() throws ServletException
{
public void init() throws ServletException {
log.info("SolrServlet.init()");
try {
Context c = new InitialContext();
@ -71,7 +71,7 @@ public class SolrServlet extends HttpServlet {
log.info("user.dir=" + System.getProperty("user.dir"));
core = SolrCore.getSolrCore();
xmlResponseWriter=new XMLResponseWriter();
log.info("SolrServlet.init() done");
}
@ -94,14 +94,15 @@ public class SolrServlet extends HttpServlet {
core.execute(solrReq, solrRsp);
if (solrRsp.getException() == null) {
response.setContentType(CONTENT_TYPE);
PrintWriter writer = response.getWriter();
// if (solrReq.getStrParam("version","2").charAt(0) == '1')
xmlResponseWriter.write(writer, solrReq, solrRsp);
PrintWriter out = response.getWriter();
QueryResponseWriter responseWriter = core.getQueryResponseWriter(solrReq);
responseWriter.write(out, solrReq, solrRsp);
} else {
Exception e = solrRsp.getException();
int rc=500;
if (e instanceof SolrException) {
rc=((SolrException)e).code();
rc=((SolrException)e).code();
}
sendErr(rc, SolrException.toStr(e), request, response);
}
@ -115,7 +116,6 @@ public class SolrServlet extends HttpServlet {
// This releases the IndexReader associated with the request
solrReq.close();
}
}
final void sendErr(int rc, String msg, HttpServletRequest request, HttpServletResponse response) {
@ -142,4 +142,4 @@ public class SolrServlet extends HttpServlet {
return request.getParameter(param)!=null ? true : false;
}
}
}