SOLR-2718: allow for lazy loaded response writers; clean up test hack for VelocityResponseWriter

git-svn-id: https://svn.apache.org/repos/asf/lucene/dev/trunk@1189958 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Erik Hatcher 2011-10-27 19:30:48 +00:00
parent ca77e0ad54
commit ff8796e5ef
9 changed files with 144 additions and 19 deletions

View File

@ -347,6 +347,9 @@ Other Changes
* SOLR-2588: Moved VelocityResponseWriter back to contrib module in order to
remove it as a mandatory core dependency. (ehatcher)
* SOLR-2718: Add ability to lazy load response writers, defined with startup="lazy".
(ehatcher)
Documentation
----------------------

View File

@ -55,10 +55,7 @@ import org.xml.sax.SAXException;
import javax.xml.parsers.ParserConfigurationException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.*;
import java.util.*;
import java.util.concurrent.*;
import java.util.concurrent.atomic.AtomicInteger;
@ -292,8 +289,8 @@ public final class SolrCore implements SolrInfoMBean {
*
* @see SolrCoreAware
*/
public void registerResponseWriter( String name, QueryResponseWriter responseWriter ){
responseWriters.put(name, responseWriter);
public QueryResponseWriter registerResponseWriter( String name, QueryResponseWriter responseWriter ){
return responseWriters.put(name, responseWriter);
}
public SolrCore reload(SolrResourceLoader resourceLoader) throws IOException,
@ -477,6 +474,10 @@ public final class SolrCore implements SolrInfoMBean {
private UpdateHandler createUpdateHandler(String className, UpdateHandler updateHandler) {
return createReloadedUpdateHandler(className, UpdateHandler.class, "Update Handler", updateHandler);
}
private QueryResponseWriter createQueryResponseWriter(String className) {
return createInstance(className, QueryResponseWriter.class, "Query Response Writer");
}
/**
*
@ -1532,7 +1533,54 @@ public final class SolrCore implements SolrInfoMBean {
/** Configure the query response writers. There will always be a default writer; additional
* writers may also be configured. */
private void initWriters() {
defaultResponseWriter = initPlugins(responseWriters, QueryResponseWriter.class);
// use link map so we iterate in the same order
Map<PluginInfo,QueryResponseWriter> writers = new LinkedHashMap<PluginInfo,QueryResponseWriter>();
for (PluginInfo info : solrConfig.getPluginInfos(QueryResponseWriter.class.getName())) {
try {
QueryResponseWriter writer;
String startup = info.attributes.get("startup") ;
if( startup != null ) {
if( "lazy".equals(startup) ) {
log.info("adding lazy queryResponseWriter: " + info.className);
writer = new LazyQueryResponseWriterWrapper(this, info.className, info.initArgs );
} else {
throw new Exception( "Unknown startup value: '"+startup+"' for: "+info.className );
}
} else {
writer = createQueryResponseWriter(info.className);
}
writers.put(info,writer);
QueryResponseWriter old = registerResponseWriter(info.name, writer);
if(old != null) {
log.warn("Multiple queryResponseWriter registered to the same name: " + info.name + " ignoring: " + old.getClass().getName());
}
if(info.isDefault()){
defaultResponseWriter = writer;
if(defaultResponseWriter != null)
log.warn("Multiple default queryResponseWriter registered ignoring: " + old.getClass().getName());
}
log.info("created "+info.name+": " + info.className);
} catch (Exception ex) {
SolrConfig.severeErrors.add( ex );
SolrException e = new SolrException
(SolrException.ErrorCode.SERVER_ERROR, "QueryResponseWriter init failure", ex);
SolrException.logOnce(log,null,e);
throw e;
}
}
// we've now registered all handlers, time to init them in the same order
for (Map.Entry<PluginInfo,QueryResponseWriter> entry : writers.entrySet()) {
PluginInfo info = entry.getKey();
QueryResponseWriter writer = entry.getValue();
responseWriters.put(info.name, writer);
if (writer instanceof PluginInfoInitialized) {
((PluginInfoInitialized) writer).init(info);
} else{
writer.init(info.initArgs);
}
}
for (Map.Entry<String, QueryResponseWriter> entry : DEFAULT_RESPONSE_WRITERS.entrySet()) {
if(responseWriters.get(entry.getKey()) == null) responseWriters.put(entry.getKey(), entry.getValue());
}
@ -1784,6 +1832,50 @@ public final class SolrCore implements SolrInfoMBean {
return codecProvider;
}
public final class LazyQueryResponseWriterWrapper implements QueryResponseWriter {
private SolrCore _core;
private String _className;
private NamedList _args;
private QueryResponseWriter _writer;
public LazyQueryResponseWriterWrapper(SolrCore core, String className, NamedList args) {
_core = core;
_className = className;
_args = args;
_writer = null;
}
public synchronized QueryResponseWriter getWrappedWriter()
{
if( _writer == null ) {
try {
QueryResponseWriter writer = createQueryResponseWriter(_className);
writer.init( _args );
_writer = writer;
}
catch( Exception ex ) {
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, "lazy loading error", ex );
}
}
return _writer;
}
@Override
public void init(NamedList args) {
// do nothing
}
@Override
public void write(Writer writer, SolrQueryRequest request, SolrQueryResponse response) throws IOException {
getWrappedWriter().write(writer, request, response);
}
@Override
public String getContentType(SolrQueryRequest request, SolrQueryResponse response) {
return getWrappedWriter().getContentType(request, response);
}
}
}

View File

@ -0,0 +1,27 @@
<?xml version="1.0" ?>
<!--
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.
-->
<!-- a basic solrconfig that tests can use when they want simple minimal solrconfig/schema
DO NOT ADD THINGS TO THIS CONFIG! -->
<config>
<luceneMatchVersion>${tests.luceneMatchVersion:LUCENE_CURRENT}</luceneMatchVersion>
<requestHandler name="standard" class="solr.StandardRequestHandler"></requestHandler>
<queryResponseWriter name="velocity" class="solr.VelocityResponseWriter" startup="lazy"/>
</config>

View File

@ -67,7 +67,7 @@
<queryResponseWriter name="standard" class="solr.XMLResponseWriter"/>
<queryResponseWriter name="useless" class="org.apache.solr.OutputWriterTest$UselessOutputWriter"/>
<queryResponseWriter name="useless" class="org.apache.solr.OutputWriterTest$UselessOutputWriter" startup="lazy"/>
<queryResponseWriter name="xslt" class="solr.XSLTResponseWriter"/>

View File

@ -19,12 +19,16 @@ package org.apache.solr;
import java.io.IOException;
import java.io.Writer;
import java.util.List;
import org.apache.solr.common.params.CommonParams;
import org.apache.solr.common.util.NamedList;
import org.apache.solr.core.PluginInfo;
import org.apache.solr.core.SolrCore;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.response.QueryResponseWriter;
import org.apache.solr.response.SolrQueryResponse;
import org.apache.solr.response.XMLResponseWriter;
import org.junit.BeforeClass;
import org.junit.Test;
@ -88,7 +92,15 @@ public class OutputWriterTest extends SolrTestCaseJ4 {
// System.out.println(out);
assertTrue(out.contains("DUMMY"));
}
public void testLazy() {
QueryResponseWriter qrw = h.getCore().getQueryResponseWriter("useless");
assertTrue("Should be a lazy class", qrw instanceof SolrCore.LazyQueryResponseWriterWrapper);
qrw = h.getCore().getQueryResponseWriter("xml");
assertTrue("Should not be a lazy class", qrw instanceof XMLResponseWriter);
}
////////////////////////////////////////////////////////////////////////////
/** An output writer that doesn't do anything useful. */

View File

@ -1585,9 +1585,7 @@
<!--
Custom response writers can be declared as needed...
-->
<!-- The solr.velocity.enabled flag is used by Solr's test cases so that this response writer is not
loaded (causing an error if contrib/velocity has not been built fully) -->
<queryResponseWriter name="velocity" class="solr.VelocityResponseWriter" enable="${solr.velocity.enabled:true}"/>
<queryResponseWriter name="velocity" class="solr.VelocityResponseWriter" startup="lazy"/>
<!-- XSLT response writer transforms the XML output by any xslt file found

View File

@ -55,9 +55,6 @@ public class JettyWebappTest extends LuceneTestCase
System.setProperty("solr.data.dir", dataDir.getCanonicalPath());
String path = ExternalPaths.WEBAPP_HOME;
// disable VelocityResponseWriter from example configuration
System.setProperty("solr.velocity.enabled", "false");
server = new Server(port);
// insecure: only use for tests!!!!
server.setSessionIdManager(new HashSessionIdManager(new Random(random.nextLong())));

View File

@ -47,9 +47,6 @@ abstract public class SolrJettyTestBase extends SolrTestCaseJ4
System.setProperty( "solr.solr.home", solrHome);
System.setProperty( "solr.data.dir", dataDir.getCanonicalPath() );
// disable VelocityResponseWriter from example configuration
System.setProperty("solr.velocity.enabled", "false");
context = context==null ? "/solr" : context;
SolrJettyTestBase.context = context;
jetty = new JettySolrRunner( context, 0, configFile );

View File

@ -103,7 +103,6 @@ public abstract class SolrTestCaseJ4 extends LuceneTestCase {
if (solrHome != null) {
System.setProperty("solr.solr.home", solrHome);
}
System.setProperty("solr.velocity.enabled", "false");
initCore();
}