From 09890f7f93cb85bc2c6b57b9337f8bb95addee60 Mon Sep 17 00:00:00 2001 From: Noble Paul Date: Wed, 28 Sep 2016 11:30:03 +0530 Subject: [PATCH] SOLR-9572: config API to show expanded useParams for request handlers inline --- solr/CHANGES.txt | 1 + .../solr/handler/RequestHandlerBase.java | 23 +++-- .../solr/handler/SolrConfigHandler.java | 90 +++++++++++++++++-- .../apache/solr/handler/TestReqParamsAPI.java | 15 ++++ .../apache/solr/common/params/SolrParams.java | 22 +++-- .../apache/solr/common/util/NamedList.java | 13 +++ 6 files changed, 138 insertions(+), 26 deletions(-) diff --git a/solr/CHANGES.txt b/solr/CHANGES.txt index 9073e8f5bf6..ccf1e298932 100644 --- a/solr/CHANGES.txt +++ b/solr/CHANGES.txt @@ -104,6 +104,7 @@ New Features * SOLR-9557: Every implicit requesthandler now has a default 'useParams' attribute (noble) +* SOLR-9572: config API to show expanded useParams for request handlers inline (noble) Bug Fixes ---------------------- diff --git a/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java b/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java index d28957c9617..4ecf01c2c86 100644 --- a/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java +++ b/solr/core/src/java/org/apache/solr/handler/RequestHandlerBase.java @@ -115,18 +115,9 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo // Copied from StandardRequestHandler if( args != null ) { - Object o = args.get("defaults"); - if (o != null && o instanceof NamedList) { - defaults = SolrParams.toSolrParams((NamedList)o); - } - o = args.get("appends"); - if (o != null && o instanceof NamedList) { - appends = SolrParams.toSolrParams((NamedList)o); - } - o = args.get("invariants"); - if (o != null && o instanceof NamedList) { - invariants = SolrParams.toSolrParams((NamedList)o); - } + defaults = getSolrParamsFromNamedList(args, "defaults"); + appends = getSolrParamsFromNamedList(args, "appends"); + invariants = getSolrParamsFromNamedList(args, "invariants"); } if (initArgs != null) { @@ -136,6 +127,14 @@ public abstract class RequestHandlerBase implements SolrRequestHandler, SolrInfo } + public static SolrParams getSolrParamsFromNamedList(NamedList args, String key) { + Object o = args.get(key); + if (o != null && o instanceof NamedList) { + return SolrParams.toSolrParams((NamedList) o); + } + return null; + } + public NamedList getInitArgs() { return initArgs; } diff --git a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java index 07bca7d16eb..b6cb596f693 100644 --- a/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java +++ b/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java @@ -37,6 +37,7 @@ import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import org.apache.solr.client.solrj.SolrClient; import org.apache.solr.client.solrj.SolrRequest; @@ -63,6 +64,7 @@ import org.apache.solr.core.RequestParams; import org.apache.solr.core.SolrConfig; import org.apache.solr.core.SolrCore; import org.apache.solr.core.SolrResourceLoader; +import org.apache.solr.request.LocalSolrQueryRequest; import org.apache.solr.request.SolrQueryRequest; import org.apache.solr.request.SolrRequestHandler; import org.apache.solr.response.SolrQueryResponse; @@ -72,6 +74,7 @@ import org.apache.solr.security.PermissionNameProvider; import org.apache.solr.util.CommandOperation; import org.apache.solr.util.DefaultSolrThreadFactory; import org.apache.solr.util.RTimer; +import org.apache.solr.util.SolrPluginUtils; import org.apache.solr.util.plugin.SolrCoreAware; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -84,6 +87,10 @@ import static org.apache.solr.common.util.StrUtils.formatString; import static org.apache.solr.core.ConfigOverlay.NOT_EDITABLE; import static org.apache.solr.core.ConfigOverlay.ZNODEVER; import static org.apache.solr.core.ConfigSetProperties.IMMUTABLE_CONFIGSET_ARG; +import static org.apache.solr.core.PluginInfo.APPENDS; +import static org.apache.solr.core.PluginInfo.DEFAULTS; +import static org.apache.solr.core.PluginInfo.INVARIANTS; +import static org.apache.solr.core.RequestParams.USEPARAM; import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_CLASS; import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_NAME; import static org.apache.solr.core.SolrConfig.PluginOpts.REQUIRE_NAME_IN_OVERLAY; @@ -165,7 +172,7 @@ public class SolrConfigHandler extends RequestHandlerBase implements SolrCoreAwa private void handleGET() { if (parts.size() == 1) { //this is the whole config. sent out the whole payload - resp.add("config", getConfigDetails()); + resp.add("config", getConfigDetails(null, req)); } else { if (ConfigOverlay.NAME.equals(parts.get(1))) { resp.add(ConfigOverlay.NAME, req.getCore().getSolrConfig().getOverlay()); @@ -225,28 +232,95 @@ public class SolrConfigHandler extends RequestHandlerBase implements SolrCoreAwa } } else { - Map m = getConfigDetails(); - resp.add("config", makeMap(parts.get(1), m.get(parts.get(1)))); + Map m = getConfigDetails(parts.get(1), req); + Map val = makeMap(parts.get(1), m.get(parts.get(1))); + String componentName = req.getParams().get("componentName"); + if (componentName != null) { + Map map = (Map) val.get(parts.get(1)); + if (map != null) { + val.put(parts.get(1), makeMap(componentName, map.get(componentName))); + } + } + + resp.add("config", val); } } } } - private Map getConfigDetails() { - Map map = req.getCore().getSolrConfig().toMap(new LinkedHashMap<>()); + private Map getConfigDetails(String componentType, SolrQueryRequest req) { + String componentName = componentType == null ? null : req.getParams().get("componentName"); + boolean showParams = req.getParams().getBool("expandParams", false); + Map map = this.req.getCore().getSolrConfig().toMap(new LinkedHashMap<>()); + if (componentType != null && !SolrRequestHandler.TYPE.equals(componentType)) return map; Map reqHandlers = (Map) map.get(SolrRequestHandler.TYPE); if (reqHandlers == null) map.put(SolrRequestHandler.TYPE, reqHandlers = new LinkedHashMap<>()); - List plugins = req.getCore().getImplicitHandlers(); + List plugins = this.req.getCore().getImplicitHandlers(); for (PluginInfo plugin : plugins) { if (SolrRequestHandler.TYPE.equals(plugin.type)) { if (!reqHandlers.containsKey(plugin.name)) { - reqHandlers.put(plugin.name, plugin.toMap(new LinkedHashMap<>())); + reqHandlers.put(plugin.name, plugin); } } } + if (!showParams) return map; + for (Object o : reqHandlers.entrySet()) { + Map.Entry e = (Map.Entry) o; + if (componentName == null || e.getKey().equals(componentName)) { + Map m = expandUseParams(req, e.getValue()); + e.setValue(m); + } + } + return map; } + private Map expandUseParams(SolrQueryRequest req, + Object plugin) { + + Map pluginInfo = null; + if (plugin instanceof Map) { + pluginInfo = (Map) plugin; + } else if (plugin instanceof PluginInfo) { + pluginInfo = ((PluginInfo) plugin).toMap(new LinkedHashMap<>()); + } + String useParams = (String) pluginInfo.get(USEPARAM); + String useparamsInReq = req.getOriginalParams().get(USEPARAM); + if (useParams != null || useparamsInReq != null) { + Map m = new LinkedHashMap<>(); + pluginInfo.put("_useParamsExpanded_", m); + List params = new ArrayList<>(); + if (useParams != null) params.addAll(StrUtils.splitSmart(useParams, ',')); + if (useparamsInReq != null) params.addAll(StrUtils.splitSmart(useparamsInReq, ',')); + for (String param : params) { + RequestParams.ParamSet p = this.req.getCore().getSolrConfig().getRequestParams().getParams(param); + if (p != null) { + m.put(param, p); + } else { + m.put(param, "[NOT AVAILABLE]"); + } + } + + + LocalSolrQueryRequest r = new LocalSolrQueryRequest(req.getCore(), req.getOriginalParams()); + r.getContext().put(USEPARAM, useParams); + NamedList nl = new PluginInfo(SolrRequestHandler.TYPE, pluginInfo).initArgs; + SolrPluginUtils.setDefaults(r, + getSolrParamsFromNamedList(nl, DEFAULTS), + getSolrParamsFromNamedList(nl, APPENDS), + getSolrParamsFromNamedList(nl, INVARIANTS)); + //SolrParams.wrapDefaults(maskUseParams, req.getParams()) + + MapSolrParams mask = new MapSolrParams(ImmutableMap.builder() + .put("componentName", "") + .put("expandParams", "") + .build()); + pluginInfo.put("_effectiveParams_", + SolrParams.wrapDefaults(mask, r.getParams())); + } + return pluginInfo; + } + private void handlePOST() throws IOException { List ops = CommandOperation.readCommands(req.getContentStreams(), resp); @@ -444,7 +518,7 @@ public class SolrConfigHandler extends RequestHandlerBase implements SolrCoreAwa private ConfigOverlay updateNamedPlugin(SolrConfig.SolrPluginInfo info, CommandOperation op, ConfigOverlay overlay, boolean isCeate) { String name = op.getStr(NAME); String clz = info.options.contains(REQUIRE_CLASS) ? op.getStr(CLASS_NAME) : op.getStr(CLASS_NAME, null); - op.getMap(PluginInfo.DEFAULTS, null); + op.getMap(DEFAULTS, null); op.getMap(PluginInfo.INVARIANTS, null); op.getMap(PluginInfo.APPENDS, null); if (op.hasError()) return overlay; diff --git a/solr/core/src/test/org/apache/solr/handler/TestReqParamsAPI.java b/solr/core/src/test/org/apache/solr/handler/TestReqParamsAPI.java index dde81f7d2a5..5c2f67d40a6 100644 --- a/solr/core/src/test/org/apache/solr/handler/TestReqParamsAPI.java +++ b/solr/core/src/test/org/apache/solr/handler/TestReqParamsAPI.java @@ -192,6 +192,21 @@ public class TestReqParamsAPI extends SolrCloudTestCase { compareValues(result, "A val", asList("params", "a")); compareValues(result, Arrays.asList("val 1", "val 2"), asList("params", "d")); compareValues(result, "20", asList("params", "i")); + + result = TestSolrConfigHandler.testForResponseElement(null, + urls.get(random().nextInt(urls.size())), + "/config/requestHandler?componentName=/dump1&expandParams=true&wt=json&useParams=y&c=CC", + cloudClient, + asList("config", "requestHandler","/dump1","_useParamsExpanded_","x", "a"), + "A val", + 5); + compareValues(result, "B val", asList("config", "requestHandler","/dump1","_useParamsExpanded_","x", "b")); + compareValues(result, "CY val", asList("config", "requestHandler","/dump1","_useParamsExpanded_","y", "c")); + compareValues(result, "BY val", asList("config", "requestHandler","/dump1","_useParamsExpanded_","y", "b")); + compareValues(result, "A val", asList("config", "requestHandler","/dump1","_effectiveParams_", "a")); + compareValues(result, "BY val", asList("config", "requestHandler","/dump1","_effectiveParams_", "b")); + compareValues(result, "CC", asList("config", "requestHandler","/dump1","_effectiveParams_", "c")); + payload = " {\n" + " 'update' : {'y': {\n" + " 'c':'CY val modified',\n" + diff --git a/solr/solrj/src/java/org/apache/solr/common/params/SolrParams.java b/solr/solrj/src/java/org/apache/solr/common/params/SolrParams.java index aac7598b42d..0b74c1486e3 100644 --- a/solr/solrj/src/java/org/apache/solr/common/params/SolrParams.java +++ b/solr/solrj/src/java/org/apache/solr/common/params/SolrParams.java @@ -16,11 +16,6 @@ */ package org.apache.solr.common.params; -import org.apache.solr.common.SolrException; -import org.apache.solr.common.util.NamedList; -import org.apache.solr.common.util.SimpleOrderedMap; -import org.apache.solr.common.util.StrUtils; - import java.io.IOException; import java.io.Serializable; import java.io.UnsupportedEncodingException; @@ -35,11 +30,17 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import org.apache.solr.common.MapSerializable; +import org.apache.solr.common.SolrException; +import org.apache.solr.common.util.NamedList; +import org.apache.solr.common.util.SimpleOrderedMap; +import org.apache.solr.common.util.StrUtils; + /** SolrParams hold request parameters. * * */ -public abstract class SolrParams implements Serializable { +public abstract class SolrParams implements Serializable, MapSerializable { /** returns the String value of a param, or null if not set */ public abstract String get(String param); @@ -446,4 +447,13 @@ public abstract class SolrParams implements Serializable { throw new AssertionError(e); } } + + @Override + public Map toMap(Map map) { + toNamedList().forEach((k, v) -> { + if (v == null || "".equals(v)) return; + map.put(k, v); + }); + return map; + } } diff --git a/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java b/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java index fb0a67729a6..979c67ae799 100644 --- a/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java +++ b/solr/solrj/src/java/org/apache/solr/common/util/NamedList.java @@ -26,6 +26,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.BiConsumer; import org.apache.solr.common.SolrException; @@ -474,6 +475,11 @@ public class NamedList implements Cloneable, Serializable, Iterable implements Cloneable, Serializable, Iterable nl = (NamedList) obj; return this.nvPairs.equals(nl.nvPairs); } + + public void forEach(BiConsumer action) { + int sz = size(); + for (int i = 0; i < sz; i++) { + action.accept(getName(i), getVal(i)); + } + } }