SOLR-9572: config API to show expanded useParams for request handlers inline

This commit is contained in:
Noble Paul 2016-09-28 11:30:03 +05:30
parent 9f35a6b829
commit 09890f7f93
6 changed files with 138 additions and 26 deletions

View File

@ -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
----------------------

View File

@ -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;
}

View File

@ -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<String, Object> m = getConfigDetails();
resp.add("config", makeMap(parts.get(1), m.get(parts.get(1))));
Map<String, Object> m = getConfigDetails(parts.get(1), req);
Map<String, Object> 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<String, Object> getConfigDetails() {
Map<String, Object> map = req.getCore().getSolrConfig().toMap(new LinkedHashMap<>());
private Map<String, Object> getConfigDetails(String componentType, SolrQueryRequest req) {
String componentName = componentType == null ? null : req.getParams().get("componentName");
boolean showParams = req.getParams().getBool("expandParams", false);
Map<String, Object> 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<PluginInfo> plugins = req.getCore().getImplicitHandlers();
List<PluginInfo> 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<String, Object> m = expandUseParams(req, e.getValue());
e.setValue(m);
}
}
return map;
}
private Map<String, Object> expandUseParams(SolrQueryRequest req,
Object plugin) {
Map<String, Object> 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<String> 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.<String, String>builder()
.put("componentName", "")
.put("expandParams", "")
.build());
pluginInfo.put("_effectiveParams_",
SolrParams.wrapDefaults(mask, r.getParams()));
}
return pluginInfo;
}
private void handlePOST() throws IOException {
List<CommandOperation> 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;

View File

@ -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" +

View File

@ -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<String, Object> map) {
toNamedList().forEach((k, v) -> {
if (v == null || "".equals(v)) return;
map.put(k, v);
});
return map;
}
}

View File

@ -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<T> implements Cloneable, Serializable, Iterable<Map.Entry
//TODO implement more efficiently
return NamedList.this.asMap(1).entrySet();
}
@Override
public void forEach(BiConsumer action) {
NamedList.this.forEach(action);
}
};
}
@ -791,4 +797,11 @@ public class NamedList<T> implements Cloneable, Serializable, Iterable<Map.Entry
NamedList<?> nl = (NamedList<?>) obj;
return this.nvPairs.equals(nl.nvPairs);
}
public void forEach(BiConsumer<String, T> action) {
int sz = size();
for (int i = 0; i < sz; i++) {
action.accept(getName(i), getVal(i));
}
}
}