mirror of https://github.com/apache/lucene.git
SOLR-7915: Provide pluggable context tool support for VelocityResponseWriter
git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1700691 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
cf3644e72b
commit
06c9ed5c5d
|
@ -144,6 +144,8 @@ New Features
|
||||||
|
|
||||||
* SOLR-4316: Add a collections dropdown to angular admin UI (Upayavira, Shalin Shekhar Mangar)
|
* SOLR-4316: Add a collections dropdown to angular admin UI (Upayavira, Shalin Shekhar Mangar)
|
||||||
|
|
||||||
|
* SOLR-7915: Provide pluggable context tool support for VelocityResponseWriter (Erik Hatcher)
|
||||||
|
|
||||||
Bug Fixes
|
Bug Fixes
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
|
|
|
@ -25,7 +25,9 @@ import java.io.StringWriter;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.ResourceBundle;
|
import java.util.ResourceBundle;
|
||||||
|
|
||||||
|
@ -45,7 +47,6 @@ import org.apache.velocity.runtime.RuntimeConstants;
|
||||||
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
|
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
|
||||||
import org.apache.velocity.tools.ConversionUtils;
|
import org.apache.velocity.tools.ConversionUtils;
|
||||||
import org.apache.velocity.tools.generic.ComparisonDateTool;
|
import org.apache.velocity.tools.generic.ComparisonDateTool;
|
||||||
import org.apache.velocity.tools.generic.ContextTool;
|
|
||||||
import org.apache.velocity.tools.generic.DisplayTool;
|
import org.apache.velocity.tools.generic.DisplayTool;
|
||||||
import org.apache.velocity.tools.generic.EscapeTool;
|
import org.apache.velocity.tools.generic.EscapeTool;
|
||||||
import org.apache.velocity.tools.generic.ListTool;
|
import org.apache.velocity.tools.generic.ListTool;
|
||||||
|
@ -84,6 +85,7 @@ public class VelocityResponseWriter implements QueryResponseWriter, SolrCoreAwar
|
||||||
private static final Logger log = LoggerFactory.getLogger(VelocityResponseWriter.class);
|
private static final Logger log = LoggerFactory.getLogger(VelocityResponseWriter.class);
|
||||||
private static final SolrVelocityLogger velocityLogger = new SolrVelocityLogger(log);
|
private static final SolrVelocityLogger velocityLogger = new SolrVelocityLogger(log);
|
||||||
private Properties velocityInitProps = new Properties();
|
private Properties velocityInitProps = new Properties();
|
||||||
|
private Map<String,String> customTools = new HashMap<String,String>();
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init(NamedList args) {
|
public void init(NamedList args) {
|
||||||
|
@ -112,6 +114,14 @@ public class VelocityResponseWriter implements QueryResponseWriter, SolrCoreAwar
|
||||||
solrResourceLoaderEnabled = (null == srle ? true : srle);
|
solrResourceLoaderEnabled = (null == srle ? true : srle);
|
||||||
|
|
||||||
initPropertiesFileName = (String) args.get(PROPERTIES_FILE);
|
initPropertiesFileName = (String) args.get(PROPERTIES_FILE);
|
||||||
|
|
||||||
|
NamedList tools = (NamedList)args.get("tools");
|
||||||
|
if (tools != null) {
|
||||||
|
for(Object t : tools) {
|
||||||
|
Map.Entry tool = (Map.Entry)t;
|
||||||
|
customTools.put(tool.getKey().toString(), tool.getValue().toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -183,10 +193,8 @@ public class VelocityResponseWriter implements QueryResponseWriter, SolrCoreAwar
|
||||||
private VelocityContext createContext(SolrQueryRequest request, SolrQueryResponse response) {
|
private VelocityContext createContext(SolrQueryRequest request, SolrQueryResponse response) {
|
||||||
VelocityContext context = new VelocityContext();
|
VelocityContext context = new VelocityContext();
|
||||||
|
|
||||||
context.put("request", request);
|
|
||||||
|
|
||||||
// Register useful Velocity "tools"
|
// Register useful Velocity "tools"
|
||||||
context.put("log", log); // TODO: add test
|
context.put("log", log); // TODO: add test; TODO: should this be overridable with a custom "log" named tool?
|
||||||
context.put("esc", new EscapeTool());
|
context.put("esc", new EscapeTool());
|
||||||
context.put("date", new ComparisonDateTool());
|
context.put("date", new ComparisonDateTool());
|
||||||
context.put("list", new ListTool());
|
context.put("list", new ListTool());
|
||||||
|
@ -198,6 +206,25 @@ public class VelocityResponseWriter implements QueryResponseWriter, SolrCoreAwar
|
||||||
request.getCore().getSolrConfig().getResourceLoader().getClassLoader(),
|
request.getCore().getSolrConfig().getResourceLoader().getClassLoader(),
|
||||||
request.getParams().get(LOCALE)));
|
request.getParams().get(LOCALE)));
|
||||||
|
|
||||||
|
/*
|
||||||
|
// Custom tools, specified in config as:
|
||||||
|
<queryResponseWriter name="velocityWithCustomTools" class="solr.VelocityResponseWriter">
|
||||||
|
<lst name="tools">
|
||||||
|
<str name="mytool">com.example.solr.velocity.MyTool</str>
|
||||||
|
</lst>
|
||||||
|
</queryResponseWriter>
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
// Custom tools can override any of the built-in tools provided above, by registering one with the same name
|
||||||
|
for(String name : customTools.keySet()) {
|
||||||
|
context.put(name, SolrCore.createInstance(customTools.get(name), Object.class, "VrW custom tool", request.getCore(), request.getCore().getResourceLoader()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// custom tools _cannot_ override context objects added below, like $request and $response
|
||||||
|
// TODO: at least log a warning when one of the *fixed* tools classes in name with a custom one, currently silently ignored
|
||||||
|
|
||||||
|
|
||||||
// Turn the SolrQueryResponse into a SolrResponse.
|
// Turn the SolrQueryResponse into a SolrResponse.
|
||||||
// QueryResponse has lots of conveniences suitable for a view
|
// QueryResponse has lots of conveniences suitable for a view
|
||||||
// Problem is, which SolrResponse class to use?
|
// Problem is, which SolrResponse class to use?
|
||||||
|
@ -221,6 +248,8 @@ public class VelocityResponseWriter implements QueryResponseWriter, SolrCoreAwar
|
||||||
rsp = new SolrResponseBase();
|
rsp = new SolrResponseBase();
|
||||||
rsp.setResponse(parsedResponse);
|
rsp.setResponse(parsedResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
context.put("request", request);
|
||||||
context.put("response", rsp);
|
context.put("response", rsp);
|
||||||
|
|
||||||
return context;
|
return context;
|
||||||
|
|
|
@ -35,4 +35,20 @@
|
||||||
<queryResponseWriter name="velocityWithInitProps" class="solr.VelocityResponseWriter">
|
<queryResponseWriter name="velocityWithInitProps" class="solr.VelocityResponseWriter">
|
||||||
<str name="init.properties.file">velocity-init.properties</str>
|
<str name="init.properties.file">velocity-init.properties</str>
|
||||||
</queryResponseWriter>
|
</queryResponseWriter>
|
||||||
|
|
||||||
|
<queryResponseWriter name="velocityWithCustomTools" class="solr.VelocityResponseWriter">
|
||||||
|
<!-- Enable params resource loader to make tests leaner, no external template needed -->
|
||||||
|
<bool name="params.resource.loader.enabled">true</bool>
|
||||||
|
|
||||||
|
<lst name="tools">
|
||||||
|
<!-- how someone would typically add a custom tool, with a custom, non-clashing name -->
|
||||||
|
<str name="mytool">org.apache.solr.velocity.MockTool</str>
|
||||||
|
|
||||||
|
<!-- override the $log context object -->
|
||||||
|
<str name="log">org.apache.solr.velocity.MockTool</str>
|
||||||
|
|
||||||
|
<!-- Try to override response, but ignored -->
|
||||||
|
<str name="response">org.apache.solr.velocity.MockTool</str>
|
||||||
|
</lst>
|
||||||
|
</queryResponseWriter>
|
||||||
</config>
|
</config>
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
$!mytool.star("foo")
|
|
@ -0,0 +1,34 @@
|
||||||
|
package org.apache.solr.velocity;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file distributed with
|
||||||
|
* this work for additional information regarding copyright ownership.
|
||||||
|
* The ASF licenses this file to You 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import org.apache.solr.core.SolrCore;
|
||||||
|
|
||||||
|
public class MockTool {
|
||||||
|
private final SolrCore core;
|
||||||
|
|
||||||
|
public MockTool(SolrCore core) {
|
||||||
|
this.core = core;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String star(String str) {
|
||||||
|
return "** " + str + " **";
|
||||||
|
}
|
||||||
|
|
||||||
|
public SolrCore getCore() { return core; }
|
||||||
|
}
|
|
@ -119,6 +119,29 @@ public class VelocityResponseWriterTest extends SolrTestCaseJ4 {
|
||||||
assertEquals("", h.query(req("q","*:*", "wt","velocityWithInitProps",VelocityResponseWriter.TEMPLATE,"foreach")));
|
assertEquals("", h.query(req("q","*:*", "wt","velocityWithInitProps",VelocityResponseWriter.TEMPLATE,"foreach")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCustomTools() throws Exception {
|
||||||
|
assertEquals("", h.query(req("q","*:*", "wt","velocity",VelocityResponseWriter.TEMPLATE,"custom_tool")));
|
||||||
|
assertEquals("** LATERALUS **", h.query(req("q","*:*", "wt","velocityWithCustomTools",VelocityResponseWriter.TEMPLATE,"t",
|
||||||
|
SolrParamResourceLoader.TEMPLATE_PARAM_PREFIX+"t", "$mytool.star(\"LATERALUS\")")));
|
||||||
|
|
||||||
|
// Does $log get overridden?
|
||||||
|
assertEquals("** log overridden **", h.query(req("q","*:*", "wt","velocityWithCustomTools",VelocityResponseWriter.TEMPLATE,"t",
|
||||||
|
SolrParamResourceLoader.TEMPLATE_PARAM_PREFIX+"t", "$log.star(\"log overridden\")")));
|
||||||
|
|
||||||
|
// Does $response get overridden? actual blank response because of the bang on $! reference that silences bogus $-references
|
||||||
|
assertEquals("", h.query(req("q","*:*", "wt","velocityWithCustomTools",VelocityResponseWriter.TEMPLATE,"t",
|
||||||
|
SolrParamResourceLoader.TEMPLATE_PARAM_PREFIX+"t", "$!response.star(\"response overridden??\")")));
|
||||||
|
|
||||||
|
// Custom tools can also have a SolrCore-arg constructor because they are instantiated with SolrCore.createInstance
|
||||||
|
// TODO: do we really need to support this? no great loss, as a custom tool could take a SolrCore object as a parameter to
|
||||||
|
// TODO: any method, so one could do $mytool.my_method($request.core)
|
||||||
|
// I'm currently inclined to make this feature undocumented/unsupported, as we may want to instantiate classes
|
||||||
|
// in a different manner that only supports no-arg constructors, commented (passing) test case out
|
||||||
|
// assertEquals("collection1", h.query(req("q","*:*", "wt","velocityWithCustomTools",VelocityResponseWriter.TEMPLATE,"t",
|
||||||
|
// SolrParamResourceLoader.TEMPLATE_PARAM_PREFIX+"t", "$mytool.core.name")));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLocaleFeature() throws Exception {
|
public void testLocaleFeature() throws Exception {
|
||||||
assertEquals("Color", h.query(req("q", "*:*", "wt", "velocity", VelocityResponseWriter.TEMPLATE, "locale",
|
assertEquals("Color", h.query(req("q", "*:*", "wt", "velocity", VelocityResponseWriter.TEMPLATE, "locale",
|
||||||
|
|
Loading…
Reference in New Issue