SOLR-1326 New interface PluginInfoInitialized

git-svn-id: https://svn.apache.org/repos/asf/lucene/solr/trunk@817165 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Noble Paul 2009-09-21 05:58:02 +00:00
parent 60f17a9c59
commit da926570a1
9 changed files with 144 additions and 103 deletions

View File

@ -313,7 +313,9 @@ New Features
to allow more efficient bulk queries (those that retrieve many or all
documents). (Brian Whitman via yonik)
78. SOLR-1321: Add better support for efficient wildcard handling (Andrzej Bialecki, Robert Muir, gsingers)
78. SOLR-1321: Add better support for efficient wildcard handling (Andrzej Bialecki, Robert Muir, gsingers)
79. SOLR-1326 : New interface PluginInfoInitialized for all types of plugin (noble)
Optimizations
----------------------
@ -1583,7 +1585,7 @@ New Features
36. SOLR-386: Abstracted SolrHighlighter and moved existing implementation
to DefaultSolrHighlighter. Adjusted SolrCore and solrconfig.xml so
that highlighter is configurable via a class attribute. Allows users
to use their own highlighter implementation. (Tricia Williams via klaas)
to use their own highlighter implementation. (Tricia Williams via klaas)
Changes in runtime behavior
1. Highlighting using DisMax will only pick up terms from the main

View File

@ -20,28 +20,31 @@ import org.apache.solr.common.util.NamedList;
import org.apache.solr.common.util.DOMUtil;
import org.w3c.dom.Node;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpressionException;
import java.util.*;
import static java.util.Collections.unmodifiableList;
import static java.util.Collections.unmodifiableMap;
/**
* An Object which represents a Plugin of any type
* @version $Id$
*/
public class PluginInfo {
public final String startup, name, className, type;
public final boolean isDefault;
public final String name, className, type;
public final NamedList initArgs;
public final Map<String, String> attributes;
public final List<PluginInfo> children;
public PluginInfo(String type, String startup, String name, String className,
boolean isdefault, NamedList initArgs, Map<String, String> otherAttrs) {
public PluginInfo(String type, Map<String, String> attrs ,NamedList initArgs, List<PluginInfo> children) {
this.type = type;
this.startup = startup;
this.name = name;
this.className = className;
this.isDefault = isdefault;
this.name = attrs.get("name");
this.className = attrs.get("class");
this.initArgs = initArgs;
attributes = otherAttrs == null ? Collections.<String, String>emptyMap() : otherAttrs;
attributes = attrs == null ? Collections.<String, String>emptyMap() : unmodifiableMap(attrs);
this.children = children == null ? Collections.<PluginInfo>emptyList(): unmodifiableList(children);
}
@ -49,8 +52,6 @@ public class PluginInfo {
type = node.getNodeName();
name = DOMUtil.getAttr(node, "name", requireName ? err : null);
className = DOMUtil.getAttr(node, "class", requireClass ? err : null);
isDefault = Boolean.parseBoolean(DOMUtil.getAttr(node, "default", null));
startup = DOMUtil.getAttr(node, "startup", null);
initArgs = DOMUtil.childNodesToNamedList(node);
Map<String, String> m = new HashMap<String, String>();
NamedNodeMap nnm = node.getAttributes();
@ -58,17 +59,32 @@ public class PluginInfo {
String name = nnm.item(i).getNodeName();
m.put(name, nnm.item(i).getNodeValue());
}
attributes = Collections.unmodifiableMap(m);
attributes = unmodifiableMap(m);
children = loadSubPlugins(node);
}
private List<PluginInfo> loadSubPlugins(Node node) {
List<PluginInfo> children = null;
try {
//if there is another sub tag with a 'class' attribute that has to be another plugin
NodeList nodes = (NodeList) Config.xpathFactory.newXPath().evaluate("*[@class]",node, XPathConstants.NODESET);
if(nodes.getLength() > 0){
children = new ArrayList<PluginInfo>(nodes.getLength());
for (int i=0; i<nodes.getLength(); i++) {
PluginInfo pluginInfo = new PluginInfo(nodes.item(i), null, false, false);
if (pluginInfo.isEnabled()) children.add(pluginInfo);
}
}
} catch (XPathExpressionException e) { }
return children == null ? Collections.<PluginInfo>emptyList(): unmodifiableList(children);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder("{");
if (type != null) sb.append("type = " + type + ",");
if (name != null) sb.append("name = " + name + ",");
if (className != null) sb.append("class = " + className + ",");
if (isDefault) sb.append("default = " + isDefault + ",");
if (startup != null) sb.append("startup = " + startup + ",");
if (initArgs.size() > 0) sb.append("args = " + initArgs);
sb.append("}");
return sb.toString();
@ -79,4 +95,7 @@ public class PluginInfo {
return enable == null || Boolean.parseBoolean(enable);
}
public boolean isDefault() {
return Boolean.parseBoolean(attributes.get("default"));
}
}

View File

@ -24,6 +24,7 @@ import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrQueryResponse;
import org.apache.solr.request.SolrRequestHandler;
import org.apache.solr.util.plugin.SolrCoreAware;
import org.apache.solr.util.plugin.PluginInfoInitialized;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -139,23 +140,28 @@ final class RequestHandlers {
for (PluginInfo info : config.getPluginInfos(SolrRequestHandler.class.getName())) {
try {
SolrRequestHandler requestHandler;
if( info.startup != null ) {
if( "lazy".equals(info.startup ) ) {
String startup = info.attributes.get("startup") ;
if( startup != null ) {
if( "lazy".equals(startup) ) {
log.info("adding lazy requestHandler: " + info.className);
requestHandler = new LazyRequestHandlerWrapper( core, info.className, info.initArgs );
} else {
throw new Exception( "Unknown startup value: '"+info.startup+"' for: "+info.className );
throw new Exception( "Unknown startup value: '"+startup+"' for: "+info.className );
}
} else {
requestHandler = core.createRequestHandler(info.className);
}
handlers.put(info,requestHandler);
requestHandler.init(info.initArgs);
if (requestHandler instanceof PluginInfoInitialized) {
((PluginInfoInitialized) requestHandler).init(info);
} else{
requestHandler.init(info.initArgs);
}
SolrRequestHandler old = register(info.name, requestHandler);
if(old != null) {
log.warn("Multiple requestHandler registered to the same name: " + info.name + " ignoring: " + old.getClass().getName());
}
if(info.isDefault){
if(info.isDefault()){
old = register("",requestHandler);
if(old != null)
log.warn("Multiple default requestHandler registered" + " ignoring: " + old.getClass().getName());

View File

@ -32,6 +32,7 @@ import org.apache.solr.search.FastLRUCache;
import org.apache.solr.search.QParserPlugin;
import org.apache.solr.search.ValueSourceParser;
import org.apache.solr.update.SolrIndexConfig;
import org.apache.solr.update.processor.UpdateRequestProcessorChain;
import org.apache.solr.spelling.QueryConverter;
import org.apache.solr.highlight.SolrFormatter;
import org.apache.solr.highlight.SolrFragmenter;
@ -191,7 +192,7 @@ public class SolrConfig extends Config {
loadPluginInfo(DirectoryFactory.class,"directoryFactory",false, true);
loadPluginInfo(IndexDeletionPolicy.class,"mainIndex/deletionPolicy",false, true);
loadPluginInfo(IndexReaderFactory.class,"indexReaderFactory",false, true);
updateProcessorChainInfo = loadUpdateProcessorInfo();
loadPluginInfo(UpdateRequestProcessorChain.class,"updateRequestProcessorChain",false, false);
updateHandlerInfo = loadUpdatehandlerInfo();
loadHighLightingPlugins();
@ -218,39 +219,6 @@ public class SolrConfig extends Config {
getInt("updateHandler/commitIntervalLowerBound",-1));
}
protected Map<String, List<PluginInfo>> loadUpdateProcessorInfo() {
HashMap<String, List<PluginInfo>> chains = new HashMap<String, List<PluginInfo>>();
NodeList nodes = (NodeList) evaluate("updateRequestProcessorChain", XPathConstants.NODESET);
if (nodes != null) {
boolean requireName = nodes.getLength() > 1;
for (int i = 0; i < nodes.getLength(); i++) {
Node node = nodes.item(i);
String name = DOMUtil.getAttr(node,"name", requireName ? "[solrconfig.xml] updateRequestProcessorChain":null);
boolean isDefault = "true".equals( DOMUtil.getAttr(node,"default", null ) );
XPath xpath = getXPath();
try {
NodeList nl = (NodeList) xpath.evaluate("processor",node, XPathConstants.NODESET);
if((nl.getLength() <1)) {
throw new RuntimeException( "updateRequestProcessorChain require at least one processor");
}
ArrayList<PluginInfo> result = new ArrayList<PluginInfo>();
for (int j=0; j<nl.getLength(); j++) {
PluginInfo pluginInfo = new PluginInfo(nl.item(j), "[solrconfig.xml] processor", false, true);
if(pluginInfo.isEnabled()) result.add(pluginInfo);
}
chains.put(name,result);
if(isDefault || nodes.getLength() == 1) chains.put(null,result);
} catch (XPathExpressionException e) {
throw new SolrException( SolrException.ErrorCode.SERVER_ERROR,"Error reading processors",e,false);
}
}
}
return chains.isEmpty() ?
Collections.<String, List<PluginInfo>>emptyMap():
Collections.unmodifiableMap(chains);
}
private void loadPluginInfo(Class clazz, String tag, boolean requireName, boolean requireClass) {
ArrayList<PluginInfo> result = new ArrayList<PluginInfo>();
NodeList nodes = (NodeList) evaluate(tag, XPathConstants.NODESET);
@ -286,11 +254,6 @@ public class SolrConfig extends Config {
public final SolrIndexConfig defaultIndexConfig;
public final SolrIndexConfig mainIndexConfig;
// protected PluginInfo deletionPolicyInfo;
// protected PluginInfo indexReaderFactoryInfo;
// protected PluginInfo directoryfactoryInfo;
protected Map<String ,List<PluginInfo>> updateProcessorChainInfo ;
protected UpdateHandlerInfo updateHandlerInfo ;
protected String highLghtingClass;
@ -451,7 +414,7 @@ public class SolrConfig extends Config {
}
}
public Map<String, List<PluginInfo>> getUpdateProcessorChainInfo() { return updateProcessorChainInfo; }
// public Map<String, List<PluginInfo>> getUpdateProcessorChainInfo() { return updateProcessorChainInfo; }
public UpdateHandlerInfo getUpdateHandlerInfo() { return updateHandlerInfo; }

View File

@ -47,6 +47,7 @@ import org.apache.solr.update.processor.UpdateRequestProcessorFactory;
import org.apache.solr.util.RefCounted;
import org.apache.solr.util.plugin.NamedListInitializedPlugin;
import org.apache.solr.util.plugin.SolrCoreAware;
import org.apache.solr.util.plugin.PluginInfoInitialized;
import org.apache.commons.io.IOUtils;
import org.xml.sax.SAXException;
@ -428,6 +429,16 @@ public final class SolrCore implements SolrInfoMBean {
}
}
public <T extends Object> T createInitInstance(PluginInfo info,Class<T> cast, String msg, String defClassName){
T o = createInstance(info.className == null ? defClassName : info.className,cast, msg);
if (o instanceof PluginInfoInitialized) {
((PluginInfoInitialized) o).init(info);
} else if (o instanceof NamedListInitializedPlugin) {
((NamedListInitializedPlugin) o).init(info.initArgs);
}
return o;
}
public SolrEventListener createEventListener(String className) {
return createInstance(className, SolrEventListener.class, "Event Listener");
}
@ -590,40 +601,18 @@ public final class SolrCore implements SolrInfoMBean {
* Load the request processors
*/
private Map<String,UpdateRequestProcessorChain> loadUpdateProcessorChains() {
final Map<String, UpdateRequestProcessorChain> map = new HashMap<String, UpdateRequestProcessorChain>();
UpdateRequestProcessorChain def = null;
Map<String, List<PluginInfo>> infos = solrConfig.getUpdateProcessorChainInfo();
if (!infos.isEmpty()) {
boolean defaultProcessed = false;
List<PluginInfo> defProcessorChainInfo = infos.get(null);// this is the default one
for (Map.Entry<String, List<PluginInfo>> e : solrConfig.getUpdateProcessorChainInfo().entrySet()) {
List<PluginInfo> processorsInfo = e.getValue();
if (processorsInfo == defProcessorChainInfo && defaultProcessed) {
map.put(e.getKey(), def);
continue;
}
UpdateRequestProcessorFactory[] chain = new UpdateRequestProcessorFactory[processorsInfo.size()];
for (int i = 0; i < processorsInfo.size(); i++) {
PluginInfo info = processorsInfo.get(i);
chain[i] = createInstance(info.className, UpdateRequestProcessorFactory.class, null);
chain[i].init(info.initArgs);
}
UpdateRequestProcessorChain processorChain = new UpdateRequestProcessorChain(chain);
map.put(e.getKey(), processorChain);
if (e.getKey() == null || processorsInfo == defProcessorChainInfo) { //this is the default one
defaultProcessed = true;
def = processorChain;
}
}
}
Map<String, UpdateRequestProcessorChain> map = new HashMap<String, UpdateRequestProcessorChain>();
UpdateRequestProcessorChain def = initPlugins(map,UpdateRequestProcessorChain.class, UpdateRequestProcessorChain.class.getName());
if(def == null){
def = map.get(null);
}
if (def == null) {
// construct the default chain
UpdateRequestProcessorFactory[] factories = new UpdateRequestProcessorFactory[]{
new RunUpdateProcessorFactory(),
new LogUpdateProcessorFactory()
};
def = new UpdateRequestProcessorChain(factories);
def = new UpdateRequestProcessorChain(factories, this);
}
map.put(null, def);
map.put("", def);
@ -1467,21 +1456,27 @@ public final class SolrCore implements SolrInfoMBean {
}
}
public <T> T initPlugins(Map<String ,T> registry, Class<T> type){
public <T> T initPlugins(Map<String ,T> registry, Class<T> type, String defClassName){
T def = null;
for (PluginInfo info : solrConfig.getPluginInfos(type.getName())) {
T o = createInstance(info.className,type, type.getSimpleName());
if (o instanceof NamedListInitializedPlugin) {
T o = createInitInstance(info,type, type.getSimpleName(), defClassName);
if (o instanceof PluginInfoInitialized) {
((PluginInfoInitialized) o).init(info);
}else if (o instanceof NamedListInitializedPlugin) {
((NamedListInitializedPlugin) o).init(info.initArgs);
}
registry.put(info.name, o);
if(info.isDefault){
if(info.isDefault()){
def = o;
}
}
}
return def;
}
public <T> T initPlugins(Map<String, T> registry, Class<T> type) {
return initPlugins(registry, type, null);
}
public ValueSourceParser getValueSourceParser(String parserName) {
return valueSourceParsers.get(parserName);
}

View File

@ -67,7 +67,7 @@ public class DefaultSolrHighlighter extends SolrHighlighter
for (PluginInfo info : config.getPluginInfos(SolrFragmenter.class.getName())) {
SolrFragmenter fragmenter = (SolrFragmenter) loader.newInstance(info.className);
fragmenter.init(info.initArgs);
if(info.isDefault) frag = fragmenter;
if(info.isDefault()) frag = fragmenter;
fragmenters.put(info.name,fragmenter);
}
@ -82,7 +82,7 @@ public class DefaultSolrHighlighter extends SolrHighlighter
SolrFormatter formatter = (SolrFormatter) loader.newInstance(info.className);
formatter.init(info.initArgs);
formatters.put(info.name, formatter);
if(info.isDefault) fmt = formatter;
if(info.isDefault()) fmt = formatter;
}
if( fmt == null ) {
fmt = new HtmlFormatter();

View File

@ -19,6 +19,11 @@ package org.apache.solr.update.processor;
import org.apache.solr.request.SolrQueryRequest;
import org.apache.solr.request.SolrQueryResponse;
import org.apache.solr.util.plugin.PluginInfoInitialized;
import org.apache.solr.core.PluginInfo;
import org.apache.solr.core.SolrCore;
import java.util.ArrayList;
/**
* Manages a chain of UpdateRequestProcessorFactories.
@ -39,12 +44,32 @@ import org.apache.solr.request.SolrQueryResponse;
* @see UpdateRequestProcessorFactory
* @since solr 1.3
*/
public final class UpdateRequestProcessorChain
public final class UpdateRequestProcessorChain implements PluginInfoInitialized
{
final UpdateRequestProcessorFactory[] chain;
public UpdateRequestProcessorChain( UpdateRequestProcessorFactory[] chain ) {
private UpdateRequestProcessorFactory[] chain;
private final SolrCore solrCore;
public UpdateRequestProcessorChain(SolrCore solrCore) {
this.solrCore = solrCore;
}
public void init(PluginInfo info) {
ArrayList<UpdateRequestProcessorFactory> list = new ArrayList<UpdateRequestProcessorFactory>();
for (PluginInfo child : info.children) {
if("processor".equals(child.type)){
UpdateRequestProcessorFactory factory = solrCore.createInitInstance(child, UpdateRequestProcessorFactory.class, null,null);
list.add(factory);
}
}
if(list.isEmpty()){
throw new RuntimeException( "updateRequestProcessorChain require at least one processor");
}
chain = list.toArray(new UpdateRequestProcessorFactory[list.size()]);
}
public UpdateRequestProcessorChain( UpdateRequestProcessorFactory[] chain , SolrCore solrCore) {
this.chain = chain;
this.solrCore = solrCore;
}
public UpdateRequestProcessor createProcessor(SolrQueryRequest req, SolrQueryResponse rsp)

View File

@ -0,0 +1,31 @@
/**
* 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.
*/
package org.apache.solr.util.plugin;
import org.apache.solr.core.PluginInfo;
/**
* A plugin that can be initialized with a PluginInfo
*
* @version $Id$
* @since solr 1.4
*/
public interface PluginInfoInitialized {
public void init(PluginInfo info);
}

View File

@ -38,13 +38,13 @@ public class UpdateRequestProcessorFactoryTest extends AbstractSolrTestCase {
UpdateRequestProcessorChain chained = core.getUpdateProcessingChain( "standard" );
// Make sure it got 3 items and configured the Log chain ok
assertEquals( 3, chained.chain.length );
LogUpdateProcessorFactory log = (LogUpdateProcessorFactory)chained.chain[0];
assertEquals( 3, chained.getFactories().length );
LogUpdateProcessorFactory log = (LogUpdateProcessorFactory)chained.getFactories()[0];
assertEquals( 100, log.maxNumToLog );
UpdateRequestProcessorChain custom = core.getUpdateProcessingChain( null );
CustomUpdateRequestProcessorFactory link = (CustomUpdateRequestProcessorFactory) custom.chain[0];
CustomUpdateRequestProcessorFactory link = (CustomUpdateRequestProcessorFactory) custom.getFactories()[0];
assertEquals( custom, core.getUpdateProcessingChain( "" ) );
assertEquals( custom, core.getUpdateProcessingChain( "custom" ) );