lucene-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From no...@apache.org
Subject svn commit: r1669368 [1/2] - in /lucene/dev/trunk/solr: ./ core/src/java/org/apache/solr/core/ core/src/java/org/apache/solr/handler/ core/src/test/org/apache/solr/core/ solrj/src/java/org/apache/solr/common/util/
Date Thu, 26 Mar 2015 16:39:14 GMT
Author: noble
Date: Thu Mar 26 16:39:14 2015
New Revision: 1669368

URL: http://svn.apache.org/r1669368
Log:
SOLR-7226: Make /query/* jmx/* , requestDispatcher/*, <listener> <initParams> properties in solrconfig.xml editable

Modified:
    lucene/dev/trunk/solr/CHANGES.txt
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigOverlay.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/PluginBag.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrConfig.java
    lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestConfigOverlay.java
    lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestSolrConfigHandler.java
    lucene/dev/trunk/solr/solrj/src/java/org/apache/solr/common/util/StrUtils.java

Modified: lucene/dev/trunk/solr/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/CHANGES.txt?rev=1669368&r1=1669367&r2=1669368&view=diff
==============================================================================
--- lucene/dev/trunk/solr/CHANGES.txt (original)
+++ lucene/dev/trunk/solr/CHANGES.txt Thu Mar 26 16:39:14 2015
@@ -221,6 +221,11 @@ New Features
   Example: q=price:[ ${low:0} TO ${high} ]&low=100&high=200
   (yonik)
 
+* SOLR-7226: Make /query/* jmx/* , requestDispatcher/*, <listener> <initParams>
+  properties in solrconfig.xml editable (Noble Paul)
+
+
+
 
 Bug Fixes
 ----------------------

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigOverlay.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigOverlay.java?rev=1669368&r1=1669367&r2=1669368&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigOverlay.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/ConfigOverlay.java Thu Mar 26 16:39:14 2015
@@ -19,7 +19,6 @@ package org.apache.solr.core;
 
 import java.io.IOException;
 import java.io.StringReader;
-import java.text.MessageFormat;
 import java.util.Collections;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
@@ -30,39 +29,39 @@ import org.apache.solr.common.SolrExcept
 import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.solr.common.params.CoreAdminParams;
 import org.apache.solr.common.util.StrUtils;
-import org.apache.solr.request.SolrRequestHandler;
 import org.noggit.CharArr;
 import org.noggit.JSONParser;
 import org.noggit.JSONWriter;
 import org.noggit.ObjectBuilder;
 
-/**This class encapsulates the config overlay json file. It is immutable
+/**
+ * This class encapsulates the config overlay json file. It is immutable
  * and any edit operations performed on tbhis gives a new copy of the object
  * with the changed value
- *
  */
-public class ConfigOverlay implements MapSerializable{
-  private final int znodeVersion ;
+public class ConfigOverlay implements MapSerializable {
+  private final int znodeVersion;
   private final Map<String, Object> data;
-  private Map<String,Object> props;
-  private Map<String,Object> userProps;
+  private Map<String, Object> props;
+  private Map<String, Object> userProps;
 
-  public ConfigOverlay(Map<String,Object> jsonObj, int znodeVersion){
-    if(jsonObj == null) jsonObj= Collections.EMPTY_MAP;
+  public ConfigOverlay(Map<String, Object> jsonObj, int znodeVersion) {
+    if (jsonObj == null) jsonObj = Collections.EMPTY_MAP;
     this.znodeVersion = znodeVersion;
     data = Collections.unmodifiableMap(jsonObj);
     props = (Map<String, Object>) data.get("props");
-    if(props == null) props= Collections.EMPTY_MAP;
+    if (props == null) props = Collections.EMPTY_MAP;
     userProps = (Map<String, Object>) data.get("userProps");
-    if(userProps == null) userProps= Collections.EMPTY_MAP;
+    if (userProps == null) userProps = Collections.EMPTY_MAP;
   }
-  public Object getXPathProperty(String xpath){
-    return getXPathProperty(xpath,true);
+
+  public Object getXPathProperty(String xpath) {
+    return getXPathProperty(xpath, true);
   }
 
   public Object getXPathProperty(String xpath, boolean onlyPrimitive) {
     List<String> hierarchy = checkEditable(xpath, true, false);
-    if(hierarchy == null) return null;
+    if (hierarchy == null) return null;
     return getObjectByPath(props, onlyPrimitive, hierarchy);
   }
 
@@ -70,10 +69,10 @@ public class ConfigOverlay implements Ma
     Map obj = root;
     for (int i = 0; i < hierarchy.size(); i++) {
       String s = hierarchy.get(i);
-      if(i < hierarchy.size()-1){
+      if (i < hierarchy.size() - 1) {
         if (!(obj.get(s) instanceof Map)) return null;
         obj = (Map) obj.get(s);
-        if(obj == null) return null;
+        if (obj == null) return null;
       } else {
         Object val = obj.get(s);
         if (onlyPrimitive && val instanceof Map) {
@@ -86,15 +85,16 @@ public class ConfigOverlay implements Ma
     return false;
   }
 
-  public ConfigOverlay setUserProperty(String key, Object val){
+  public ConfigOverlay setUserProperty(String key, Object val) {
     Map copy = new LinkedHashMap(userProps);
-    copy.put(key,val);
+    copy.put(key, val);
     Map<String, Object> jsonObj = new LinkedHashMap<>(this.data);
     jsonObj.put("userProps", copy);
     return new ConfigOverlay(jsonObj, znodeVersion);
   }
-  public ConfigOverlay unsetUserProperty(String key){
-    if(!userProps.containsKey(key)) return this;
+
+  public ConfigOverlay unsetUserProperty(String key) {
+    if (!userProps.containsKey(key)) return this;
     Map copy = new LinkedHashMap(userProps);
     copy.remove(key);
     Map<String, Object> jsonObj = new LinkedHashMap<>(this.data);
@@ -103,18 +103,18 @@ public class ConfigOverlay implements Ma
   }
 
   public ConfigOverlay setProperty(String name, Object val) {
-    List<String> hierarchy  = checkEditable(name,false, true);
+    List<String> hierarchy = checkEditable(name, false, true);
     Map deepCopy = getDeepCopy(props);
     Map obj = deepCopy;
     for (int i = 0; i < hierarchy.size(); i++) {
       String s = hierarchy.get(i);
-      if (i < hierarchy.size()-1) {
-        if(obj.get(s) == null || (!(obj.get(s) instanceof Map))) {
+      if (i < hierarchy.size() - 1) {
+        if (obj.get(s) == null || (!(obj.get(s) instanceof Map))) {
           obj.put(s, new LinkedHashMap<>());
         }
         obj = (Map) obj.get(s);
       } else {
-        obj.put(s,val);
+        obj.put(s, val);
       }
     }
 
@@ -125,7 +125,6 @@ public class ConfigOverlay implements Ma
   }
 
 
-
   private Map getDeepCopy(Map map) {
     return (Map) ZkStateReader.fromJSON(ZkStateReader.toJSON(map));
   }
@@ -134,8 +133,9 @@ public class ConfigOverlay implements Ma
 
   private List<String> checkEditable(String propName, boolean isXPath, boolean failOnError) {
     LinkedList<String> hierarchy = new LinkedList<>();
-    if(!isEditableProp(propName, isXPath,hierarchy)) {
-      if(failOnError) throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, StrUtils.formatString( NOT_EDITABLE,propName));
+    if (!isEditableProp(propName, isXPath, hierarchy)) {
+      if (failOnError)
+        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, StrUtils.formatString(NOT_EDITABLE, propName));
       else return null;
     }
     return hierarchy;
@@ -143,13 +143,13 @@ public class ConfigOverlay implements Ma
   }
 
   public ConfigOverlay unsetProperty(String name) {
-    List<String> hierarchy  = checkEditable(name,false, true);
+    List<String> hierarchy = checkEditable(name, false, true);
     Map deepCopy = getDeepCopy(props);
     Map obj = deepCopy;
     for (int i = 0; i < hierarchy.size(); i++) {
       String s = hierarchy.get(i);
-      if (i < hierarchy.size()-1) {
-        if(obj.get(s) == null || (!(obj.get(s) instanceof Map))) {
+      if (i < hierarchy.size() - 1) {
+        if (obj.get(s) == null || (!(obj.get(s) instanceof Map))) {
           return this;
         }
         obj = (Map) obj.get(s);
@@ -169,7 +169,7 @@ public class ConfigOverlay implements Ma
   }
 
 
-  public int getZnodeVersion(){
+  public int getZnodeVersion() {
     return znodeVersion;
   }
 
@@ -187,65 +187,129 @@ public class ConfigOverlay implements Ma
 
   public static final String RESOURCE_NAME = "configoverlay.json";
 
-  private static final Long XML_ATTR = 0L;
-  private static final Long XML_NODE = 1L;
+  private static final Long STR_ATTR = 0L;
+  private static final Long STR_NODE = 1L;
+  private static final Long BOOL_ATTR = 10L;
+  private static final Long BOOL_NODE = 11L;
+  private static final Long INT_ATTR = 20L;
+  private static final Long INT_NODE = 21L;
+  private static final Long FLOAT_ATTR = 30L;
+  private static final Long FLOAT_NODE = 31L;
+
+  private static Map editable_prop_map;
+  //The path maps to the xml xpath and value of 1 means it is a tag with a string value and value
+  // of 0 means it is an attribute with string value
+  public static final String MAPPING = "{" +
+      "  updateHandler:{" +
+      "    autoCommit:{" +
+      "      maxDocs:20," +
+      "      maxTime:20," +
+      "      openSearcher:11}," +
+      "    autoSoftCommit:{" +
+      "      maxDocs:20," +
+      "      maxTime:20}," +
+      "    commitWithin:{softCommit:11}," +
+      "    commitIntervalLowerBound:21," +
+      "    indexWriter:{closeWaitsForMerges:11}}," +
+      "  query:{" +
+      "    filterCache:{" +
+      "      class:0," +
+      "      size:0," +
+      "      initialSize:20," +
+      "      autowarmCount:20," +
+      "      regenerator:0}," +
+      "    queryResultCache:{" +
+      "      class:0," +
+      "      size:20," +
+      "      initialSize:20," +
+      "      autowarmCount:20," +
+      "      regenerator:0}," +
+      "    documentCache:{" +
+      "      class:0," +
+      "      size:20," +
+      "      initialSize:20," +
+      "      autowarmCount:20," +
+      "      regenerator:0}," +
+      "    fieldValueCache:{" +
+      "      class:0," +
+      "      size:20," +
+      "      initialSize:20," +
+      "      autowarmCount:20," +
+      "      regenerator:0}," +
+      "    useFilterForSortedQuery:1," +
+      "    queryResultWindowSize:1," +
+      "    queryResultMaxDocsCached:1," +
+      "    enableLazyFieldLoading:1," +
+      "    boolTofilterOptimizer:1," +
+      "    maxBooleanClauses:1}," +
+      "  jmx:{" +
+      "    agentId:0," +
+      "    serviceUrl:0," +
+      "    rootName:0}," +
+      "  requestDispatcher:{" +
+      "    handleSelect:0," +
+      "    requestParsers:{" +
+      "      multipartUploadLimitInKB:0," +
+      "      formdataUploadLimitInKB:0," +
+      "      enableRemoteStreaming:0," +
+      "      addHttpRequestToContext:0}}}";
 
-  private static Map editable_prop_map ;
-  public static final String MAPPING = "{ updateHandler : {" +
-      "                 autoCommit : { maxDocs:1, maxTime:1, openSearcher:1 }," +
-      "                 autoSoftCommit : { maxDocs:1, maxTime :1}," +
-      "                 commitWithin : {softCommit:1}," +
-      "                 commitIntervalLowerBound:1," +
-      "                 indexWriter : {closeWaitsForMerges:1}" +
-      "                 }," +
-      " query : {" +
-      "          filterCache : {class:0, size:0, initialSize:0 , autowarmCount:0 , regenerator:0}," +
-      "          queryResultCache :{class:0, size:0, initialSize:0,autowarmCount:0,regenerator:0}," +
-      "          documentCache :{class:0, size:0, initialSize:0 ,autowarmCount:0,regenerator:0}," +
-      "          fieldValueCache :{class:0, size:0, initialSize:0 ,autowarmCount:0,regenerator:0}" +
-      "}}";
-  static{
+  static {
     try {
-      editable_prop_map =  (Map)new ObjectBuilder(new JSONParser(new StringReader(
+      editable_prop_map = (Map) new ObjectBuilder(new JSONParser(new StringReader(
           MAPPING))).getObject();
     } catch (IOException e) {
       throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "error parsing mapping ", e);
     }
   }
 
-
   public static boolean isEditableProp(String path, boolean isXpath, List<String> hierarchy) {
-    List<String> parts = StrUtils.splitSmart(path, isXpath? '/':'.');
+    return !(checkEditable(path, isXpath, hierarchy) == null);
+  }
+
+
+  public static Class checkEditable(String path, boolean isXpath, List<String> hierarchy) {
+    List<String> parts = StrUtils.splitSmart(path, isXpath ? '/' : '.');
     Object obj = editable_prop_map;
     for (int i = 0; i < parts.size(); i++) {
       String part = parts.get(i);
       boolean isAttr = isXpath && part.startsWith("@");
-      if(isAttr){
+      if (isAttr) {
         part = part.substring(1);
       }
-      if(hierarchy != null) hierarchy.add(part);
-      if(obj ==null) return false;
-      if(i == parts.size()-1) {
+      if (hierarchy != null) hierarchy.add(part);
+      if (obj == null) return null;
+      if (i == parts.size() - 1) {
         if (obj instanceof Map) {
           Map map = (Map) obj;
-          if(isXpath && isAttr){
-            return XML_ATTR.equals(map.get(part));
-          } else {
-             return XML_ATTR.equals( map.get(part)) || XML_NODE.equals(map.get(part));
-          }
+          Object o = map.get(part);
+          return checkType(o, isXpath, isAttr);
         }
-        return false;
+        return null;
       }
       obj = ((Map) obj).get(part);
     }
-    return false;
+    return null;
   }
 
+  static Class[] types = new Class[]{String.class, Boolean.class, Integer.class, Float.class};
+
+  private static Class checkType(Object o, boolean isXpath, boolean isAttr) {
+    if (o instanceof Long) {
+      Long aLong = (Long) o;
+      int ten = aLong.intValue() / 10;
+      int one = aLong.intValue() % 10;
+      if (isXpath && isAttr && one != 0) return null;
+      return types[ten];
+    } else {
+      return null;
+    }
+  }
 
   public Map<String, String> getEditableSubProperties(String xpath) {
-    Object o = getObjectByPath(props,false,StrUtils.splitSmart(xpath,'/'));
+    Object o = getObjectByPath(props, false, StrUtils.splitSmart(xpath, '/'));
     if (o instanceof Map) {
-      return  (Map) o;
+      return (Map) o;
     } else {
       return null;
     }
@@ -258,34 +322,39 @@ public class ConfigOverlay implements Ma
   @Override
   public Map<String, Object> toMap() {
     Map result = new LinkedHashMap();
-    result.put(ZNODEVER,znodeVersion);
+    result.put(ZNODEVER, znodeVersion);
     result.putAll(data);
     return result;
   }
-  public Map<String, Map> getNamedPlugins(String typ){
+
+  public Map<String, Map> getNamedPlugins(String typ) {
     Map<String, Map> reqHandlers = (Map<String, Map>) data.get(typ);
-    if(reqHandlers == null) return Collections.EMPTY_MAP;
+    if (reqHandlers == null) return Collections.EMPTY_MAP;
     return Collections.unmodifiableMap(reqHandlers);
   }
 
 
   public ConfigOverlay addNamedPlugin(Map<String, Object> info, String typ) {
-    Map dataCopy =  RequestParams.getDeepCopy(data, 4);
+    Map dataCopy = RequestParams.getDeepCopy(data, 4);
     Map reqHandler = (Map) dataCopy.get(typ);
-    if(reqHandler== null) dataCopy.put(typ, reqHandler = new LinkedHashMap());
-    reqHandler.put(info.get(CoreAdminParams.NAME) , info);
+    if (reqHandler == null) dataCopy.put(typ, reqHandler = new LinkedHashMap());
+    reqHandler.put(info.get(CoreAdminParams.NAME), info);
     return new ConfigOverlay(dataCopy, this.znodeVersion);
   }
 
   public ConfigOverlay deleteNamedPlugin(String name, String typ) {
-    Map dataCopy =  RequestParams.getDeepCopy(data,4);
+    Map dataCopy = RequestParams.getDeepCopy(data, 4);
     Map reqHandler = (Map) dataCopy.get(typ);
-    if(reqHandler==null) return this;
+    if (reqHandler == null) return this;
     reqHandler.remove(name);
-    return new ConfigOverlay(dataCopy,this.znodeVersion);
+    return new ConfigOverlay(dataCopy, this.znodeVersion);
 
   }
+
   public static final String ZNODEVER = "znodeVersion";
   public static final String NAME = "overlay";
 
+  public static void main(String[] args) {
+  }
+
 }

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/PluginBag.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/PluginBag.java?rev=1669368&r1=1669367&r2=1669368&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/PluginBag.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/PluginBag.java Thu Mar 26 16:39:14 2015
@@ -20,7 +20,6 @@ package org.apache.solr.core;
 
 import java.io.IOException;
 import java.nio.ByteBuffer;
-import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
@@ -57,7 +56,9 @@ public class PluginBag<T> implements Aut
   private SolrCore core;
   private final SolrConfig.SolrPluginInfo meta;
 
-  /** Pass needThreadSafety=true if plugins can be added and removed concurrently with lookups. */
+  /**
+   * Pass needThreadSafety=true if plugins can be added and removed concurrently with lookups.
+   */
   public PluginBag(Class<T> klass, SolrCore core, boolean needThreadSafety) {
     this.core = core;
     this.klass = klass;
@@ -72,12 +73,14 @@ public class PluginBag<T> implements Aut
     }
   }
 
-  /** Constructs a non-threadsafe plugin registry */
+  /**
+   * Constructs a non-threadsafe plugin registry
+   */
   public PluginBag(Class<T> klass, SolrCore core) {
     this(klass, core, false);
   }
 
-  static void initInstance(Object inst, PluginInfo info, SolrCore core) {
+  static void initInstance(Object inst, PluginInfo info) {
     if (inst instanceof PluginInfoInitialized) {
       ((PluginInfoInitialized) inst).init(info);
     } else if (inst instanceof NamedListInitializedPlugin) {
@@ -94,16 +97,16 @@ public class PluginBag<T> implements Aut
 
   }
 
-  PluginHolder<T> createPlugin(PluginInfo info, SolrCore core) {
+  PluginHolder<T> createPlugin(PluginInfo info) {
     if ("true".equals(String.valueOf(info.attributes.get("runtimeLib")))) {
-      log.info(" {} : '{}'  created with runtimeLib=true ", meta.tag, info.name);
+      log.info(" {} : '{}'  created with runtimeLib=true ", meta.getCleanTag(), info.name);
       return new LazyPluginHolder<>(meta, info, core, core.getMemClassLoader());
     } else if ("lazy".equals(info.attributes.get("startup")) && meta.options.contains(SolrConfig.PluginOpts.LAZY)) {
-      log.info("{} : '{}' created with startup=lazy ", meta.tag, info.name);
+      log.info("{} : '{}' created with startup=lazy ", meta.getCleanTag(), info.name);
       return new LazyPluginHolder<T>(meta, info, core, core.getResourceLoader());
     } else {
-      T inst = core.createInstance(info.className, (Class<T>) meta.clazz, meta.tag, null, core.getResourceLoader());
-      initInstance(inst, info, core);
+      T inst = core.createInstance(info.className, (Class<T>) meta.clazz, meta.getCleanTag(), null, core.getResourceLoader());
+      initInstance(inst, info);
       return new PluginHolder<>(info, inst);
     }
   }
@@ -164,7 +167,7 @@ public class PluginBag<T> implements Aut
 
   void setDefault(String def) {
     if (!registry.containsKey(def)) return;
-    if (this.def != null) log.warn("Multiple defaults for : " + meta.tag);
+    if (this.def != null) log.warn("Multiple defaults for : " + meta.getCleanTag());
     this.def = def;
   }
 
@@ -197,11 +200,11 @@ public class PluginBag<T> implements Aut
   void init(Map<String, T> defaults, SolrCore solrCore, List<PluginInfo> infos) {
     core = solrCore;
     for (PluginInfo info : infos) {
-      PluginHolder<T> o = createPlugin(info, solrCore);
+      PluginHolder<T> o = createPlugin(info);
       String name = info.name;
       if (meta.clazz.equals(SolrRequestHandler.class)) name = RequestHandlers.normalize(info.name);
       PluginHolder<T> old = put(name, o);
-      if (old != null) log.warn("Multiple entries of {} with name {}", meta.tag, name);
+      if (old != null) log.warn("Multiple entries of {} with name {}", meta.getCleanTag(), name);
     }
     for (Map.Entry<String, T> e : defaults.entrySet()) {
       if (!contains(e.getKey())) {
@@ -238,7 +241,7 @@ public class PluginBag<T> implements Aut
       try {
         e.getValue().close();
       } catch (Exception exp) {
-        log.error("Error closing plugin " + e.getKey() + " of type : " + meta.tag, exp);
+        log.error("Error closing plugin " + e.getKey() + " of type : " + meta.getCleanTag(), exp);
       }
     }
   }
@@ -331,14 +334,14 @@ public class PluginBag<T> implements Aut
 
     private synchronized boolean createInst() {
       if (lazyInst != null) return false;
-      log.info("Going to create a new {} with {} ", pluginMeta.tag, pluginInfo.toString());
+      log.info("Going to create a new {} with {} ", pluginMeta.getCleanTag(), pluginInfo.toString());
       if (resourceLoader instanceof MemClassLoader) {
         MemClassLoader loader = (MemClassLoader) resourceLoader;
         loader.loadJars();
       }
       Class<T> clazz = (Class<T>) pluginMeta.clazz;
-      T localInst = core.createInstance(pluginInfo.className, clazz, pluginMeta.tag, null, resourceLoader);
-      initInstance(localInst, pluginInfo, core);
+      T localInst = core.createInstance(pluginInfo.className, clazz, pluginMeta.getCleanTag(), null, resourceLoader);
+      initInstance(localInst, pluginInfo);
       if (localInst instanceof SolrCoreAware) {
         SolrResourceLoader.assertAwareCompatibility(SolrCoreAware.class, localInst);
         ((SolrCoreAware) localInst).inform(core);

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrConfig.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrConfig.java?rev=1669368&r1=1669367&r2=1669368&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrConfig.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/core/SolrConfig.java Thu Mar 26 16:39:14 2015
@@ -73,6 +73,7 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
+import java.util.UUID;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
@@ -81,6 +82,7 @@ import static org.apache.solr.core.SolrC
 import static org.apache.solr.core.SolrConfig.PluginOpts.NOOP;
 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;
 
 
 /**
@@ -88,22 +90,23 @@ import static org.apache.solr.core.SolrC
  * configuration data for a a Solr instance -- typically found in
  * "solrconfig.xml".
  */
-public class SolrConfig extends Config implements MapSerializable{
+public class SolrConfig extends Config implements MapSerializable {
 
   public static final Logger log = LoggerFactory.getLogger(SolrConfig.class);
-  
+
   public static final String DEFAULT_CONF_FILE = "solrconfig.xml";
   private RequestParams requestParams;
 
   public static enum PluginOpts {
-    MULTI_OK, 
+    MULTI_OK,
     REQUIRE_NAME,
+    REQUIRE_NAME_IN_OVERLAY,
     REQUIRE_CLASS,
     LAZY,
     // EnumSet.of and/or EnumSet.copyOf(Collection) are anoying
     // because of type determination
     NOOP
-    }
+  }
 
   private int multipartUploadLimitKB;
 
@@ -116,49 +119,56 @@ public class SolrConfig extends Config i
   private boolean addHttpRequestToContext;
 
   private final SolrRequestParsers solrRequestParsers;
-  
-  /** Creates a default instance from the solrconfig.xml. */
+
+  /**
+   * Creates a default instance from the solrconfig.xml.
+   */
   public SolrConfig()
-  throws ParserConfigurationException, IOException, SAXException {
-    this( (SolrResourceLoader) null, DEFAULT_CONF_FILE, null );
+      throws ParserConfigurationException, IOException, SAXException {
+    this((SolrResourceLoader) null, DEFAULT_CONF_FILE, null);
   }
-  
-  /** Creates a configuration instance from a configuration name.
+
+  /**
+   * Creates a configuration instance from a configuration name.
    * A default resource loader will be created (@see SolrResourceLoader)
-   *@param name the configuration name used by the loader
+   *
+   * @param name the configuration name used by the loader
    */
   public SolrConfig(String name)
-  throws ParserConfigurationException, IOException, SAXException {
-    this( (SolrResourceLoader) null, name, null);
+      throws ParserConfigurationException, IOException, SAXException {
+    this((SolrResourceLoader) null, name, null);
   }
 
-  /** Creates a configuration instance from a configuration name and stream.
+  /**
+   * Creates a configuration instance from a configuration name and stream.
    * A default resource loader will be created (@see SolrResourceLoader).
    * If the stream is null, the resource loader will open the configuration stream.
    * If the stream is not null, no attempt to load the resource will occur (the name is not used).
-   *@param name the configuration name
-   *@param is the configuration stream
+   *
+   * @param name the configuration name
+   * @param is   the configuration stream
    */
   public SolrConfig(String name, InputSource is)
-  throws ParserConfigurationException, IOException, SAXException {
-    this( (SolrResourceLoader) null, name, is );
+      throws ParserConfigurationException, IOException, SAXException {
+    this((SolrResourceLoader) null, name, is);
   }
-  
-  /** Creates a configuration instance from an instance directory, configuration name and stream.
-   *@param instanceDir the directory used to create the resource loader
-   *@param name the configuration name used by the loader if the stream is null
-   *@param is the configuration stream 
+
+  /**
+   * Creates a configuration instance from an instance directory, configuration name and stream.
+   *
+   * @param instanceDir the directory used to create the resource loader
+   * @param name        the configuration name used by the loader if the stream is null
+   * @param is          the configuration stream
    */
   public SolrConfig(String instanceDir, String name, InputSource is)
-  throws ParserConfigurationException, IOException, SAXException {
+      throws ParserConfigurationException, IOException, SAXException {
     this(new SolrResourceLoader(instanceDir), name, is);
   }
 
   public static SolrConfig readFromResourceLoader(SolrResourceLoader loader, String name) {
     try {
       return new SolrConfig(loader, name, null);
-    }
-    catch (Exception e) {
+    } catch (Exception e) {
       String resource;
       if (loader instanceof ZkSolrResourceLoader) {
         resource = name;
@@ -168,16 +178,18 @@ public class SolrConfig extends Config i
       throw new SolrException(ErrorCode.SERVER_ERROR, "Error loading solr config from " + resource, e);
     }
   }
-  
-   /** Creates a configuration instance from a resource loader, a configuration name and a stream.
+
+  /**
+   * Creates a configuration instance from a resource loader, a configuration name and a stream.
    * If the stream is null, the resource loader will open the configuration stream.
    * If the stream is not null, no attempt to load the resource will occur (the name is not used).
-   *@param loader the resource loader
-   *@param name the configuration name
-   *@param is the configuration stream
+   *
+   * @param loader the resource loader
+   * @param name   the configuration name
+   * @param is     the configuration stream
    */
   public SolrConfig(SolrResourceLoader loader, String name, InputSource is)
-  throws ParserConfigurationException, IOException, SAXException {
+      throws ParserConfigurationException, IOException, SAXException {
     super(loader, name, is, "/config/");
     getOverlay();//just in case it is not initialized
     getRequestParams();
@@ -188,7 +200,7 @@ public class SolrConfig extends Config i
     // Old indexDefaults and mainIndex sections are deprecated and fails fast for luceneMatchVersion=>LUCENE_4_0_0.
     // For older solrconfig.xml's we allow the old sections, but never mixed with the new <indexConfig>
     boolean hasDeprecatedIndexConfig = (getNode("indexDefaults", false) != null) || (getNode("mainIndex", false) != null);
-    if(hasDeprecatedIndexConfig){
+    if (hasDeprecatedIndexConfig) {
       throw new SolrException(ErrorCode.FORBIDDEN, "<indexDefaults> and <mainIndex> configuration sections are discontinued. Use <indexConfig> instead.");
     } else {
       defaultIndexConfig = mainIndexConfig = null;
@@ -207,9 +219,9 @@ public class SolrConfig extends Config i
 
     // Warn about deprecated / discontinued parameters
     // boolToFilterOptimizer has had no effect since 3.1
-    if(get("query/boolTofilterOptimizer", null) != null)
+    if (get("query/boolTofilterOptimizer", null) != null)
       log.warn("solrconfig.xml: <boolTofilterOptimizer> is currently not implemented and has no effect.");
-    if(get("query/HashDocSet", null) != null)
+    if (get("query/HashDocSet", null) != null)
       log.warn("solrconfig.xml: <HashDocSet> is deprecated and no longer recommended used.");
 
 // TODO: Old code - in case somebody wants to re-enable. Also see SolrIndexSearcher#search()
@@ -228,62 +240,62 @@ public class SolrConfig extends Config i
     documentCacheConfig = CacheConfig.getConfig(this, "query/documentCache");
     CacheConfig conf = CacheConfig.getConfig(this, "query/fieldValueCache");
     if (conf == null) {
-      Map<String,String> args = new HashMap<>();
-      args.put("name","fieldValueCache");
-      args.put("size","10000");
-      args.put("initialSize","10");
-      args.put("showItems","-1");
+      Map<String, String> args = new HashMap<>();
+      args.put("name", "fieldValueCache");
+      args.put("size", "10000");
+      args.put("initialSize", "10");
+      args.put("showItems", "-1");
       conf = new CacheConfig(FastLRUCache.class, args, null);
     }
     fieldValueCacheConfig = conf;
-    unlockOnStartup = getBool(indexConfigPrefix+"/unlockOnStartup", false);
-    useColdSearcher = getBool("query/useColdSearcher",false);
+    unlockOnStartup = getBool(indexConfigPrefix + "/unlockOnStartup", false);
+    useColdSearcher = getBool("query/useColdSearcher", false);
     dataDir = get("dataDir", null);
-    if (dataDir != null && dataDir.length()==0) dataDir=null;
+    if (dataDir != null && dataDir.length() == 0) dataDir = null;
 
     userCacheConfigs = CacheConfig.getMultipleConfigs(this, "query/cache");
 
     org.apache.solr.search.SolrIndexSearcher.initRegenerators(this);
 
-    hashSetInverseLoadFactor = 1.0f / getFloat("//HashDocSet/@loadFactor",0.75f);
-    hashDocSetMaxSize= getInt("//HashDocSet/@maxSize",3000);
+    hashSetInverseLoadFactor = 1.0f / getFloat("//HashDocSet/@loadFactor", 0.75f);
+    hashDocSetMaxSize = getInt("//HashDocSet/@maxSize", 3000);
 
     httpCachingConfig = new HttpCachingConfig(this);
 
     Node jmx = getNode("jmx", false);
     if (jmx != null) {
       jmxConfig = new JmxConfiguration(true,
-                                       get("jmx/@agentId", null),
-                                       get("jmx/@serviceUrl", null),
-                                       get("jmx/@rootName", null));
+          get("jmx/@agentId", null),
+          get("jmx/@serviceUrl", null),
+          get("jmx/@rootName", null));
 
     } else {
       jmxConfig = new JmxConfiguration(false, null, null, null);
     }
-     maxWarmingSearchers = getInt("query/maxWarmingSearchers",Integer.MAX_VALUE);
+    maxWarmingSearchers = getInt("query/maxWarmingSearchers", Integer.MAX_VALUE);
     slowQueryThresholdMillis = getInt("query/slowQueryThresholdMillis", -1);
     for (SolrPluginInfo plugin : plugins) loadPluginInfo(plugin);
-     updateHandlerInfo = loadUpdatehandlerInfo();
-     
-     multipartUploadLimitKB = getInt( 
-         "requestDispatcher/requestParsers/@multipartUploadLimitInKB", 2048 );
-     
-     formUploadLimitKB = getInt( 
-         "requestDispatcher/requestParsers/@formdataUploadLimitInKB", 2048 );
-     
-     enableRemoteStreams = getBool( 
-         "requestDispatcher/requestParsers/@enableRemoteStreaming", false ); 
- 
-     // Let this filter take care of /select?xxx format
-     handleSelect = getBool( 
-         "requestDispatcher/@handleSelect", true ); 
-     
-     addHttpRequestToContext = getBool( 
-         "requestDispatcher/requestParsers/@addHttpRequestToContext", false );
-
-    List<PluginInfo> argsInfos =  pluginStore.get(InitParams.class.getName()) ;
-    if(argsInfos!=null){
-      Map<String,InitParams> argsMap = new HashMap<>();
+    updateHandlerInfo = loadUpdatehandlerInfo();
+
+    multipartUploadLimitKB = getInt(
+        "requestDispatcher/requestParsers/@multipartUploadLimitInKB", 2048);
+
+    formUploadLimitKB = getInt(
+        "requestDispatcher/requestParsers/@formdataUploadLimitInKB", 2048);
+
+    enableRemoteStreams = getBool(
+        "requestDispatcher/requestParsers/@enableRemoteStreaming", false);
+
+    // Let this filter take care of /select?xxx format
+    handleSelect = getBool(
+        "requestDispatcher/@handleSelect", true);
+
+    addHttpRequestToContext = getBool(
+        "requestDispatcher/requestParsers/@addHttpRequestToContext", false);
+
+    List<PluginInfo> argsInfos = getPluginInfos(InitParams.class.getName());
+    if (argsInfos != null) {
+      Map<String, InitParams> argsMap = new HashMap<>();
       for (PluginInfo p : argsInfos) {
         InitParams args = new InitParams(p);
         argsMap.put(args.name == null ? String.valueOf(args.hashCode()) : args.name, args);
@@ -296,7 +308,7 @@ public class SolrConfig extends Config i
     Config.log.info("Loaded SolrConfig: " + name);
   }
 
-  public static final  List<SolrPluginInfo> plugins = ImmutableList.<SolrPluginInfo>builder()
+  public static final List<SolrPluginInfo> plugins = ImmutableList.<SolrPluginInfo>builder()
       .add(new SolrPluginInfo(SolrRequestHandler.class, SolrRequestHandler.TYPE, REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK, LAZY))
       .add(new SolrPluginInfo(QParserPlugin.class, "queryParser", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK))
       .add(new SolrPluginInfo(QueryResponseWriter.class, "queryResponseWriter", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK, LAZY))
@@ -304,36 +316,38 @@ public class SolrConfig extends Config i
       .add(new SolrPluginInfo(TransformerFactory.class, "transformer", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK))
       .add(new SolrPluginInfo(SearchComponent.class, "searchComponent", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK))
       .add(new SolrPluginInfo(UpdateRequestProcessorFactory.class, "updateProcessor", REQUIRE_NAME, REQUIRE_CLASS, MULTI_OK))
-      // TODO: WTF is up with queryConverter???
-      // it aparently *only* works as a singleton? - SOLR-4304
-      // and even then -- only if there is a single SpellCheckComponent
-      // because of queryConverter.setIndexAnalyzer
+          // TODO: WTF is up with queryConverter???
+          // it aparently *only* works as a singleton? - SOLR-4304
+          // and even then -- only if there is a single SpellCheckComponent
+          // because of queryConverter.setIndexAnalyzer
       .add(new SolrPluginInfo(QueryConverter.class, "queryConverter", REQUIRE_NAME, REQUIRE_CLASS))
       .add(new SolrPluginInfo(PluginBag.RuntimeLib.class, "runtimeLib", REQUIRE_NAME, MULTI_OK))
-      // this is hackish, since it picks up all SolrEventListeners,
-      // regardless of when/how/why they are used (or even if they are
-      // declared outside of the appropriate context) but there's no nice
-      // way around that in the PluginInfo framework
-      .add(new SolrPluginInfo(SolrEventListener.class, "//listener", REQUIRE_CLASS, MULTI_OK))
+          // this is hackish, since it picks up all SolrEventListeners,
+          // regardless of when/how/why they are used (or even if they are
+          // declared outside of the appropriate context) but there's no nice
+          // way around that in the PluginInfo framework
+      .add(new SolrPluginInfo(InitParams.class, InitParams.TYPE, MULTI_OK, REQUIRE_NAME_IN_OVERLAY))
+      .add(new SolrPluginInfo(SolrEventListener.class, "//listener", REQUIRE_CLASS, MULTI_OK, REQUIRE_NAME_IN_OVERLAY))
+
       .add(new SolrPluginInfo(DirectoryFactory.class, "directoryFactory", REQUIRE_CLASS))
       .add(new SolrPluginInfo(IndexDeletionPolicy.class, "indexConfig/deletionPolicy", REQUIRE_CLASS))
       .add(new SolrPluginInfo(CodecFactory.class, "codecFactory", REQUIRE_CLASS))
       .add(new SolrPluginInfo(IndexReaderFactory.class, "indexReaderFactory", REQUIRE_CLASS))
-      .add(new SolrPluginInfo(UpdateRequestProcessorChain.class,"updateRequestProcessorChain", MULTI_OK))
-      .add(new SolrPluginInfo(UpdateLog.class,"updateHandler/updateLog"))
+      .add(new SolrPluginInfo(UpdateRequestProcessorChain.class, "updateRequestProcessorChain", MULTI_OK))
+      .add(new SolrPluginInfo(UpdateLog.class, "updateHandler/updateLog"))
       .add(new SolrPluginInfo(IndexSchemaFactory.class, "schemaFactory", REQUIRE_CLASS))
       .add(new SolrPluginInfo(RestManager.class, "restManager"))
-      .add(new SolrPluginInfo(InitParams.class, InitParams.TYPE, MULTI_OK))
       .add(new SolrPluginInfo(StatsCache.class, "statsCache", REQUIRE_CLASS))
       .build();
   public static final Map<String, SolrPluginInfo> classVsSolrPluginInfo;
+
   static {
     Map<String, SolrPluginInfo> map = new HashMap<>();
     for (SolrPluginInfo plugin : plugins) map.put(plugin.clazz.getName(), plugin);
     classVsSolrPluginInfo = Collections.unmodifiableMap(map);
   }
 
-  public static class SolrPluginInfo{
+  public static class SolrPluginInfo {
 
     public final Class clazz;
     public final String tag;
@@ -343,17 +357,26 @@ public class SolrConfig extends Config i
     private SolrPluginInfo(Class clz, String tag, PluginOpts... opts) {
       this.clazz = clz;
       this.tag = tag;
-      this.options=  opts == null? Collections.EMPTY_SET :  EnumSet.of(NOOP, opts);
+      this.options = opts == null ? Collections.EMPTY_SET : EnumSet.of(NOOP, opts);
+    }
+
+    public String getCleanTag() {
+      return tag.replaceAll("/", "");
+    }
+
+    public String getTagCleanLower() {
+      return getCleanTag().toLowerCase(Locale.ROOT);
+
     }
   }
 
-  public static  ConfigOverlay getConfigOverlay(SolrResourceLoader loader) {
+  public static ConfigOverlay getConfigOverlay(SolrResourceLoader loader) {
     InputStream in = null;
     try {
       in = loader.openResource(ConfigOverlay.RESOURCE_NAME);
     } catch (IOException e) {
       //no problem no overlay.json file
-      return new ConfigOverlay(Collections.EMPTY_MAP,-1);
+      return new ConfigOverlay(Collections.EMPTY_MAP, -1);
     }
 
     try {
@@ -363,27 +386,29 @@ public class SolrConfig extends Config i
         log.info("config overlay loaded . version : {} ", version);
       }
       Map m = (Map) ObjectBuilder.getVal(new JSONParser(new InputStreamReader(in, StandardCharsets.UTF_8)));
-      return new ConfigOverlay(m,version);
+      return new ConfigOverlay(m, version);
     } catch (Exception e) {
-      throw new SolrException(ErrorCode.SERVER_ERROR,"Error reading config overlay",e);
+      throw new SolrException(ErrorCode.SERVER_ERROR, "Error reading config overlay", e);
     }
 
   }
 
-  private Map<String,InitParams> initParams = Collections.emptyMap();
+  private Map<String, InitParams> initParams = Collections.emptyMap();
+
   public Map<String, InitParams> getInitParams() {
     return initParams;
   }
+
   protected UpdateHandlerInfo loadUpdatehandlerInfo() {
-    return new UpdateHandlerInfo(get("updateHandler/@class",null),
-            getInt("updateHandler/autoCommit/maxDocs",-1),
-            getInt("updateHandler/autoCommit/maxTime",-1),
-            getBool("updateHandler/indexWriter/closeWaitsForMerges",true),
-            getBool("updateHandler/autoCommit/openSearcher",true),
-            getInt("updateHandler/commitIntervalLowerBound",-1),
-            getInt("updateHandler/autoSoftCommit/maxDocs",-1),
-            getInt("updateHandler/autoSoftCommit/maxTime",-1),
-            getBool("updateHandler/commitWithin/softCommit",true));
+    return new UpdateHandlerInfo(get("updateHandler/@class", null),
+        getInt("updateHandler/autoCommit/maxDocs", -1),
+        getInt("updateHandler/autoCommit/maxTime", -1),
+        getBool("updateHandler/indexWriter/closeWaitsForMerges", true),
+        getBool("updateHandler/autoCommit/openSearcher", true),
+        getInt("updateHandler/commitIntervalLowerBound", -1),
+        getInt("updateHandler/autoSoftCommit/maxDocs", -1),
+        getInt("updateHandler/autoSoftCommit/maxTime", -1),
+        getBool("updateHandler/commitWithin/softCommit", true));
   }
 
   private void loadPluginInfo(SolrPluginInfo pluginInfo) {
@@ -392,37 +417,37 @@ public class SolrConfig extends Config i
 
     List<PluginInfo> result = readPluginInfos(pluginInfo.tag, requireName, requireClass);
 
-    if (1 < result.size() && ! pluginInfo.options.contains(MULTI_OK)) {
-        throw new SolrException
+    if (1 < result.size() && !pluginInfo.options.contains(MULTI_OK)) {
+      throw new SolrException
           (SolrException.ErrorCode.SERVER_ERROR,
-           "Found " + result.size() + " configuration sections when at most "
-           + "1 is allowed matching expression: " + pluginInfo.tag);
+              "Found " + result.size() + " configuration sections when at most "
+                  + "1 is allowed matching expression: " + pluginInfo.getCleanTag());
     }
-    if(!result.isEmpty()) pluginStore.put(pluginInfo.clazz.getName(),result);
+    if (!result.isEmpty()) pluginStore.put(pluginInfo.clazz.getName(), result);
   }
 
   public List<PluginInfo> readPluginInfos(String tag, boolean requireName, boolean requireClass) {
     ArrayList<PluginInfo> result = new ArrayList<>();
     NodeList nodes = (NodeList) evaluate(tag, XPathConstants.NODESET);
-    for (int i=0; i<nodes.getLength(); i++) {
+    for (int i = 0; i < nodes.getLength(); i++) {
       PluginInfo pluginInfo = new PluginInfo(nodes.item(i), "[solrconfig.xml] " + tag, requireName, requireClass);
-      if(pluginInfo.isEnabled()) result.add(pluginInfo);
+      if (pluginInfo.isEnabled()) result.add(pluginInfo);
     }
     return result;
   }
-  
+
   public SolrRequestParsers getRequestParsers() {
     return solrRequestParsers;
   }
 
   /* The set of materialized parameters: */
   public final int booleanQueryMaxClauseCount;
-// SolrIndexSearcher - nutch optimizer -- Disabled since 3.1
+  // SolrIndexSearcher - nutch optimizer -- Disabled since 3.1
 //  public final boolean filtOptEnabled;
 //  public final int filtOptCacheSize;
 //  public final float filtOptThreshold;
   // SolrIndexSearcher - caches configurations
-  public final CacheConfig filterCacheConfig ;
+  public final CacheConfig filterCacheConfig;
   public final CacheConfig queryResultCacheConfig;
   public final CacheConfig documentCacheConfig;
   public final CacheConfig fieldValueCacheConfig;
@@ -443,7 +468,7 @@ public class SolrConfig extends Config i
   // IndexConfig settings
   public final SolrIndexConfig indexConfig;
 
-  protected UpdateHandlerInfo updateHandlerInfo ;
+  protected UpdateHandlerInfo updateHandlerInfo;
 
   private Map<String, List<PluginInfo>> pluginStore = new LinkedHashMap<>();
 
@@ -453,23 +478,24 @@ public class SolrConfig extends Config i
   public final Version luceneMatchVersion;
   protected String dataDir;
   public final int slowQueryThresholdMillis;  // threshold above which a query is considered slow
-  
+
   //JMX configuration
   public final JmxConfiguration jmxConfig;
-  
+
   private final HttpCachingConfig httpCachingConfig;
+
   public HttpCachingConfig getHttpCachingConfig() {
     return httpCachingConfig;
   }
 
-  public static class JmxConfiguration implements MapSerializable{
+  public static class JmxConfiguration implements MapSerializable {
     public boolean enabled = false;
     public String agentId;
     public String serviceUrl;
     public String rootName;
 
-    public JmxConfiguration(boolean enabled, 
-                            String agentId, 
+    public JmxConfiguration(boolean enabled,
+                            String agentId,
                             String serviceUrl,
                             String rootName) {
       this.enabled = enabled;
@@ -479,180 +505,217 @@ public class SolrConfig extends Config i
 
       if (agentId != null && serviceUrl != null) {
         throw new SolrException
-          (SolrException.ErrorCode.SERVER_ERROR,
-           "Incorrect JMX Configuration in solrconfig.xml, "+
-           "both agentId and serviceUrl cannot be specified at the same time");
+            (SolrException.ErrorCode.SERVER_ERROR,
+                "Incorrect JMX Configuration in solrconfig.xml, " +
+                    "both agentId and serviceUrl cannot be specified at the same time");
       }
-      
+
     }
 
     @Override
     public Map<String, Object> toMap() {
       LinkedHashMap map = new LinkedHashMap();
-      map.put("agentId",agentId);
-      map.put("serviceUrl",serviceUrl);
-      map.put("rootName",rootName);
+      map.put("agentId", agentId);
+      map.put("serviceUrl", serviceUrl);
+      map.put("rootName", rootName);
       return map;
     }
   }
 
-  public static class HttpCachingConfig implements MapSerializable{
+  public static class HttpCachingConfig implements MapSerializable {
 
-    /** config xpath prefix for getting HTTP Caching options */
+    /**
+     * config xpath prefix for getting HTTP Caching options
+     */
     private final static String CACHE_PRE
-      = "requestDispatcher/httpCaching/";
-    
-    /** For extracting Expires "ttl" from <cacheControl> config */
+        = "requestDispatcher/httpCaching/";
+
+    /**
+     * For extracting Expires "ttl" from <cacheControl> config
+     */
     private final static Pattern MAX_AGE
-      = Pattern.compile("\\bmax-age=(\\d+)");
+        = Pattern.compile("\\bmax-age=(\\d+)");
 
     @Override
     public Map<String, Object> toMap() {
-      return ZkNodeProps.makeMap("never304",never304,
-          "etagSeed",etagSeed,
-          "lastModFrom",lastModFrom.name().toLowerCase(Locale.ROOT),
-          "cacheControl",cacheControlHeader);
+      return ZkNodeProps.makeMap("never304", never304,
+          "etagSeed", etagSeed,
+          "lastModFrom", lastModFrom.name().toLowerCase(Locale.ROOT),
+          "cacheControl", cacheControlHeader);
     }
 
     public static enum LastModFrom {
       OPENTIME, DIRLASTMOD, BOGUS;
 
-      /** Input must not be null */
+      /**
+       * Input must not be null
+       */
       public static LastModFrom parse(final String s) {
         try {
           return valueOf(s.toUpperCase(Locale.ROOT));
         } catch (Exception e) {
-          log.warn( "Unrecognized value for lastModFrom: " + s, e);
+          log.warn("Unrecognized value for lastModFrom: " + s, e);
           return BOGUS;
         }
       }
     }
-    
+
     private final boolean never304;
     private final String etagSeed;
     private final String cacheControlHeader;
     private final Long maxAge;
     private final LastModFrom lastModFrom;
-    
+
     private HttpCachingConfig(SolrConfig conf) {
 
-      never304 = conf.getBool(CACHE_PRE+"@never304", false);
-      
-      etagSeed = conf.get(CACHE_PRE+"@etagSeed", "Solr");
-      
-
-      lastModFrom = LastModFrom.parse(conf.get(CACHE_PRE+"@lastModFrom",
-                                               "openTime"));
-      
-      cacheControlHeader = conf.get(CACHE_PRE+"cacheControl",null);
+      never304 = conf.getBool(CACHE_PRE + "@never304", false);
+
+      etagSeed = conf.get(CACHE_PRE + "@etagSeed", "Solr");
+
+
+      lastModFrom = LastModFrom.parse(conf.get(CACHE_PRE + "@lastModFrom",
+          "openTime"));
+
+      cacheControlHeader = conf.get(CACHE_PRE + "cacheControl", null);
 
       Long tmp = null; // maxAge
       if (null != cacheControlHeader) {
-        try { 
+        try {
           final Matcher ttlMatcher = MAX_AGE.matcher(cacheControlHeader);
           final String ttlStr = ttlMatcher.find() ? ttlMatcher.group(1) : null;
           tmp = (null != ttlStr && !"".equals(ttlStr))
-            ? Long.valueOf(ttlStr)
-            : null;
+              ? Long.valueOf(ttlStr)
+              : null;
         } catch (Exception e) {
-          log.warn( "Ignoring exception while attempting to " +
-                    "extract max-age from cacheControl config: " +
-                    cacheControlHeader, e);
+          log.warn("Ignoring exception while attempting to " +
+              "extract max-age from cacheControl config: " +
+              cacheControlHeader, e);
         }
       }
       maxAge = tmp;
 
     }
-    
-    public boolean isNever304() { return never304; }
-    public String getEtagSeed() { return etagSeed; }
-    /** null if no Cache-Control header */
-    public String getCacheControlHeader() { return cacheControlHeader; }
-    /** null if no max age limitation */
-    public Long getMaxAge() { return maxAge; }
-    public LastModFrom getLastModFrom() { return lastModFrom; }
+
+    public boolean isNever304() {
+      return never304;
+    }
+
+    public String getEtagSeed() {
+      return etagSeed;
+    }
+
+    /**
+     * null if no Cache-Control header
+     */
+    public String getCacheControlHeader() {
+      return cacheControlHeader;
+    }
+
+    /**
+     * null if no max age limitation
+     */
+    public Long getMaxAge() {
+      return maxAge;
+    }
+
+    public LastModFrom getLastModFrom() {
+      return lastModFrom;
+    }
   }
 
-  public static class UpdateHandlerInfo implements MapSerializable{
+  public static class UpdateHandlerInfo implements MapSerializable {
     public final String className;
-    public final int autoCommmitMaxDocs,autoCommmitMaxTime,commitIntervalLowerBound,
-        autoSoftCommmitMaxDocs,autoSoftCommmitMaxTime;
+    public final int autoCommmitMaxDocs, autoCommmitMaxTime, commitIntervalLowerBound,
+        autoSoftCommmitMaxDocs, autoSoftCommmitMaxTime;
     public final boolean indexWriterCloseWaitsForMerges;
     public final boolean openSearcher;  // is opening a new searcher part of hard autocommit?
     public final boolean commitWithinSoftCommit;
 
     /**
-     * @param autoCommmitMaxDocs set -1 as default
-     * @param autoCommmitMaxTime set -1 as default
+     * @param autoCommmitMaxDocs       set -1 as default
+     * @param autoCommmitMaxTime       set -1 as default
      * @param commitIntervalLowerBound set -1 as default
      */
     public UpdateHandlerInfo(String className, int autoCommmitMaxDocs, int autoCommmitMaxTime, boolean indexWriterCloseWaitsForMerges, boolean openSearcher, int commitIntervalLowerBound,
-        int autoSoftCommmitMaxDocs, int autoSoftCommmitMaxTime, boolean commitWithinSoftCommit) {
+                             int autoSoftCommmitMaxDocs, int autoSoftCommmitMaxTime, boolean commitWithinSoftCommit) {
       this.className = className;
       this.autoCommmitMaxDocs = autoCommmitMaxDocs;
       this.autoCommmitMaxTime = autoCommmitMaxTime;
       this.indexWriterCloseWaitsForMerges = indexWriterCloseWaitsForMerges;
       this.openSearcher = openSearcher;
       this.commitIntervalLowerBound = commitIntervalLowerBound;
-      
+
       this.autoSoftCommmitMaxDocs = autoSoftCommmitMaxDocs;
       this.autoSoftCommmitMaxTime = autoSoftCommmitMaxTime;
-      
+
       this.commitWithinSoftCommit = commitWithinSoftCommit;
     }
 
 
-
     @Override
     public Map<String, Object> toMap() {
       LinkedHashMap result = new LinkedHashMap();
-      result.put("class",className);
-      result.put("autoCommmitMaxDocs",autoCommmitMaxDocs);
-      result.put("indexWriterCloseWaitsForMerges",indexWriterCloseWaitsForMerges);
-      result.put("openSearcher",openSearcher);
-      result.put("commitIntervalLowerBound",commitIntervalLowerBound);
-      result.put("commitWithinSoftCommit",commitWithinSoftCommit);
+      result.put("class", className);
+      result.put("autoCommmitMaxDocs", autoCommmitMaxDocs);
+      result.put("indexWriterCloseWaitsForMerges", indexWriterCloseWaitsForMerges);
+      result.put("openSearcher", openSearcher);
+      result.put("commitIntervalLowerBound", commitIntervalLowerBound);
+      result.put("commitWithinSoftCommit", commitWithinSoftCommit);
       result.put("autoCommit", ZkNodeProps.makeMap(
           "maxDocs", autoCommmitMaxDocs,
-          "maxTime",autoCommmitMaxTime,
+          "maxTime", autoCommmitMaxTime,
           "commitIntervalLowerBound", commitIntervalLowerBound
       ));
-      result.put("autoSoftCommit" ,
+      result.put("autoSoftCommit",
           ZkNodeProps.makeMap("maxDocs", autoSoftCommmitMaxDocs,
-              "maxTime",autoSoftCommmitMaxTime));
+              "maxTime", autoSoftCommmitMaxTime));
       return result;
     }
   }
 
 //  public Map<String, List<PluginInfo>> getUpdateProcessorChainInfo() { return updateProcessorChainInfo; }
 
-  public UpdateHandlerInfo getUpdateHandlerInfo() { return updateHandlerInfo; }
+  public UpdateHandlerInfo getUpdateHandlerInfo() {
+    return updateHandlerInfo;
+  }
 
-  public String getDataDir() { return dataDir; }
+  public String getDataDir() {
+    return dataDir;
+  }
 
-  /**SolrConfig keeps a repository of plugins by the type. The known interfaces are the types.
+  /**
+   * SolrConfig keeps a repository of plugins by the type. The known interfaces are the types.
+   *
    * @param type The key is FQN of the plugin class there are a few  known types : SolrFormatter, SolrFragmenter
-   * SolrRequestHandler,QParserPlugin, QueryResponseWriter,ValueSourceParser,
-   * SearchComponent, QueryConverter, SolrEventListener, DirectoryFactory,
-   * IndexDeletionPolicy, IndexReaderFactory, {@link TransformerFactory}
+   *             SolrRequestHandler,QParserPlugin, QueryResponseWriter,ValueSourceParser,
+   *             SearchComponent, QueryConverter, SolrEventListener, DirectoryFactory,
+   *             IndexDeletionPolicy, IndexReaderFactory, {@link TransformerFactory}
    */
   public List<PluginInfo> getPluginInfos(String type) {
     List<PluginInfo> result = pluginStore.get(type);
     SolrPluginInfo info = classVsSolrPluginInfo.get(type);
-    if (info != null && info.options.contains(REQUIRE_NAME)) {
-      Map<String, Map> infos = overlay.getNamedPlugins(info.tag);
+    if (info != null &&
+        (info.options.contains(REQUIRE_NAME) || info.options.contains(REQUIRE_NAME_IN_OVERLAY))) {
+      Map<String, Map> infos = overlay.getNamedPlugins(info.getCleanTag());
       if (!infos.isEmpty()) {
         LinkedHashMap<String, PluginInfo> map = new LinkedHashMap<>();
-        if (result != null) for (PluginInfo pluginInfo : result) map.put(pluginInfo.name, pluginInfo);
+        if (result != null) for (PluginInfo pluginInfo : result) {
+          //just create a UUID for the time being so that map key is not null
+          String name = pluginInfo.name == null ?
+              UUID.randomUUID().toString().toLowerCase(Locale.ROOT) :
+              pluginInfo.name;
+          map.put(name, pluginInfo);
+        }
         for (Map.Entry<String, Map> e : infos.entrySet()) {
-          map.put(e.getKey(), new PluginInfo(info.tag, e.getValue()));
+          map.put(e.getKey(), new PluginInfo(info.getCleanTag(), e.getValue()));
         }
         result = new ArrayList<>(map.values());
       }
     }
     return result == null ? Collections.<PluginInfo>emptyList() : result;
   }
-  public PluginInfo getPluginInfo(String  type){
+
+  public PluginInfo getPluginInfo(String type) {
     List<PluginInfo> result = pluginStore.get(type);
     if (result == null || result.isEmpty()) {
       return null;
@@ -662,9 +725,9 @@ public class SolrConfig extends Config i
     }
 
     throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
-                            "Multiple plugins configured for type: " + type);
+        "Multiple plugins configured for type: " + type);
   }
-  
+
   private void initLibs() {
     NodeList nodes = (NodeList) evaluate("lib", XPathConstants.NODESET);
     if (nodes == null || nodes.getLength() == 0) return;
@@ -728,23 +791,36 @@ public class SolrConfig extends Config i
 
   @Override
   public int getInt(String path, int def) {
-    Object v = overlay.getXPathProperty(path);
-
     Object val = overlay.getXPathProperty(path);
     if (val != null) return Integer.parseInt(val.toString());
     return super.getInt(path, def);
   }
+
   @Override
   public boolean getBool(String path, boolean def) {
     Object val = overlay.getXPathProperty(path);
     if (val != null) return Boolean.parseBoolean(val.toString());
     return super.getBool(path, def);
   }
+
+  @Override
+  public String get(String path) {
+    Object val = overlay.getXPathProperty(path, true);
+    return val != null ? val.toString() : super.get(path);
+  }
+
+  @Override
+  public String get(String path, String def) {
+    Object val = overlay.getXPathProperty(path, true);
+    return val != null ? val.toString() : super.get(path, def);
+
+  }
+
   @Override
   public Map<String, Object> toMap() {
     LinkedHashMap result = new LinkedHashMap();
-    if(getZnodeVersion() > -1) result.put("znodeVersion",getZnodeVersion());
-    result.put("luceneMatchVersion",luceneMatchVersion);
+    if (getZnodeVersion() > -1) result.put("znodeVersion", getZnodeVersion());
+    result.put("luceneMatchVersion", luceneMatchVersion);
     result.put("updateHandler", getUpdateHandlerInfo().toMap());
     Map m = new LinkedHashMap();
     result.put("query", m);
@@ -753,22 +829,22 @@ public class SolrConfig extends Config i
     m.put("queryResultMaxDocsCached", queryResultMaxDocsCached);
     m.put("enableLazyFieldLoading", enableLazyFieldLoading);
     m.put("maxBooleanClauses", booleanQueryMaxClauseCount);
-
+    if (jmxConfig != null) result.put("jmx", jmxConfig.toMap());
     for (SolrPluginInfo plugin : plugins) {
       List<PluginInfo> infos = getPluginInfos(plugin.clazz.getName());
-      if(infos == null || infos.isEmpty()) continue;
-      String tag = plugin.tag;
-      tag = tag.replace("/","");
-      if(plugin.options.contains(PluginOpts.REQUIRE_NAME)){
+      if (infos == null || infos.isEmpty()) continue;
+      String tag = plugin.getCleanTag();
+      tag = tag.replace("/", "");
+      if (plugin.options.contains(PluginOpts.REQUIRE_NAME)) {
         LinkedHashMap items = new LinkedHashMap();
         for (PluginInfo info : infos) items.put(info.name, info.toMap());
         for (Map.Entry e : overlay.getNamedPlugins(plugin.tag).entrySet()) items.put(e.getKey(), e.getValue());
         result.put(tag, items);
       } else {
-        if(plugin.options.contains(MULTI_OK)){
+        if (plugin.options.contains(MULTI_OK)) {
           ArrayList<Map> l = new ArrayList<>();
           for (PluginInfo info : infos) l.add(info.toMap());
-          result.put(tag,l);
+          result.put(tag, l);
         } else {
           result.put(tag, infos.get(0).toMap());
         }
@@ -778,16 +854,16 @@ public class SolrConfig extends Config i
     }
 
 
-    addCacheConfig(m,filterCacheConfig,queryResultCacheConfig,documentCacheConfig,fieldValueCacheConfig);
-    if(jmxConfig != null) result.put("jmx",jmxConfig.toMap());
+    addCacheConfig(m, filterCacheConfig, queryResultCacheConfig, documentCacheConfig, fieldValueCacheConfig);
+    if (jmxConfig != null) result.put("jmx", jmxConfig.toMap());
     m = new LinkedHashMap();
     result.put("requestDispatcher", m);
-    m.put("handleSelect",handleSelect);
-    if(httpCachingConfig!=null) m.put("httpCaching", httpCachingConfig.toMap());
-    m.put("requestParsers", ZkNodeProps.makeMap("multipartUploadLimitKB",multipartUploadLimitKB,
-        "formUploadLimitKB",formUploadLimitKB,
-        "addHttpRequestToContext",addHttpRequestToContext));
-    if(indexConfig != null) result.put("indexConfig",indexConfig.toMap());
+    m.put("handleSelect", handleSelect);
+    if (httpCachingConfig != null) m.put("httpCaching", httpCachingConfig.toMap());
+    m.put("requestParsers", ZkNodeProps.makeMap("multipartUploadLimitKB", multipartUploadLimitKB,
+        "formUploadLimitKB", formUploadLimitKB,
+        "addHttpRequestToContext", addHttpRequestToContext));
+    if (indexConfig != null) result.put("indexConfig", indexConfig.toMap());
 
     //TODO there is more to add
 
@@ -795,38 +871,39 @@ public class SolrConfig extends Config i
   }
 
   private void addCacheConfig(Map queryMap, CacheConfig... cache) {
-    if(cache==null)return;
-    for (CacheConfig config : cache) if(config !=null) queryMap.put(config.getNodeName(),config.toMap());
+    if (cache == null) return;
+    for (CacheConfig config : cache) if (config != null) queryMap.put(config.getNodeName(), config.toMap());
 
   }
 
   @Override
   protected Properties getSubstituteProperties() {
     Map<String, Object> p = getOverlay().getUserProps();
-    if(p==null || p.isEmpty()) return super.getSubstituteProperties();
+    if (p == null || p.isEmpty()) return super.getSubstituteProperties();
     Properties result = new Properties(super.getSubstituteProperties());
     result.putAll(p);
     return result;
   }
+
   private ConfigOverlay overlay;
 
   public ConfigOverlay getOverlay() {
-    if(overlay ==null) {
+    if (overlay == null) {
       overlay = getConfigOverlay(getResourceLoader());
     }
     return overlay;
   }
 
   public RequestParams getRequestParams() {
-    if(requestParams == null){
+    if (requestParams == null) {
       return refreshRequestParams();
     }
     return requestParams;
   }
 
 
-  public RequestParams refreshRequestParams(){
-    requestParams = RequestParams.getFreshRequestParams(getResourceLoader(),requestParams);
+  public RequestParams refreshRequestParams() {
+    requestParams = RequestParams.getFreshRequestParams(getResourceLoader(), requestParams);
     log.info("current version of requestparams : {}", requestParams.getZnodeVersion());
     return requestParams;
   }

Modified: lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java?rev=1669368&r1=1669367&r2=1669368&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java (original)
+++ lucene/dev/trunk/solr/core/src/java/org/apache/solr/handler/SolrConfigHandler.java Thu Mar 26 16:39:14 2015
@@ -19,7 +19,6 @@ package org.apache.solr.handler;
 
 
 import java.io.IOException;
-import java.text.MessageFormat;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
@@ -57,9 +56,11 @@ import org.slf4j.LoggerFactory;
 
 import static java.util.Collections.singletonList;
 import static org.apache.solr.common.params.CoreAdminParams.NAME;
+import static org.apache.solr.common.util.StrUtils.formatString;
 import static org.apache.solr.core.ConfigOverlay.NOT_EDITABLE;
 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;
 import static org.apache.solr.schema.FieldType.CLASS_NAME;
 
 public class SolrConfigHandler extends RequestHandlerBase {
@@ -70,9 +71,8 @@ public class SolrConfigHandler extends R
   static {
     Map<String, SolrConfig.SolrPluginInfo> map = new HashMap<>();
     for (SolrConfig.SolrPluginInfo plugin : SolrConfig.plugins) {
-      if (plugin.options.contains(REQUIRE_NAME)) {
-        map.put(plugin.tag.toLowerCase(Locale.ROOT), plugin);
-
+      if (plugin.options.contains(REQUIRE_NAME) || plugin.options.contains(REQUIRE_NAME_IN_OVERLAY)) {
+        map.put(plugin.getCleanTag().toLowerCase(Locale.ROOT), plugin);
       }
     }
     namedPlugins = Collections.unmodifiableMap(map);
@@ -252,7 +252,7 @@ public class SolrConfigHandler extends R
             if (op.hasError()) break;
             for (String s : name) {
               if (params.getParams(s) == null) {
-                op.addError(StrUtils.formatString("can't delete . No such params ''{0}'' exist", s));
+                op.addError(formatString("can't delete . No such params ''{0}'' exist", s));
               }
               params = params.setParams(s, null);
             }
@@ -302,19 +302,19 @@ public class SolrConfigHandler extends R
           default: {
             List<String> pcs = StrUtils.splitSmart(op.name.toLowerCase(Locale.ROOT), '-');
             if (pcs.size() != 2) {
-              op.addError(StrUtils.formatString("Unknown operation ''{0}'' ", op.name));
+              op.addError(formatString("Unknown operation ''{0}'' ", op.name));
             } else {
               String prefix = pcs.get(0);
               String name = pcs.get(1);
               if (cmdPrefixes.contains(prefix) && namedPlugins.containsKey(name)) {
                 SolrConfig.SolrPluginInfo info = namedPlugins.get(name);
                 if ("delete".equals(prefix)) {
-                  overlay = deleteNamedComponent(op, overlay, info.tag);
+                  overlay = deleteNamedComponent(op, overlay, info.getCleanTag());
                 } else {
                   overlay = updateNamedPlugin(info, op, overlay, prefix.equals("create") || prefix.equals("add"));
                 }
               } else {
-                op.addError(StrUtils.formatString("Unknown operation ''{0}'' ", op.name));
+                op.addError(formatString("Unknown operation ''{0}'' ", op.name));
               }
             }
           }
@@ -347,7 +347,7 @@ public class SolrConfigHandler extends R
       if (overlay.getNamedPlugins(typ).containsKey(name)) {
         return overlay.deleteNamedPlugin(name, typ);
       } else {
-        op.addError(StrUtils.formatString("NO such {0} ''{1}'' ", typ, name));
+        op.addError(formatString("NO such {0} ''{1}'' ", typ, name));
         return overlay;
       }
     }
@@ -360,18 +360,18 @@ public class SolrConfigHandler extends R
       op.getMap(PluginInfo.APPENDS, null);
       if (op.hasError()) return overlay;
       if (!verifyClass(op, clz, info.clazz)) return overlay;
-      if (overlay.getNamedPlugins(info.tag).containsKey(name)) {
+      if (overlay.getNamedPlugins(info.getCleanTag()).containsKey(name)) {
         if (isCeate) {
-          op.addError(StrUtils.formatString(" ''{0}'' already exists . Do an ''{1}'' , if you want to change it ", name, "update-" + info.tag.toLowerCase(Locale.ROOT)));
+          op.addError(formatString(" ''{0}'' already exists . Do an ''{1}'' , if you want to change it ", name, "update-" + info.getTagCleanLower()));
           return overlay;
         } else {
-          return overlay.addNamedPlugin(op.getDataMap(), info.tag);
+          return overlay.addNamedPlugin(op.getDataMap(), info.getCleanTag());
         }
       } else {
         if (isCeate) {
-          return overlay.addNamedPlugin(op.getDataMap(), info.tag);
+          return overlay.addNamedPlugin(op.getDataMap(), info.getCleanTag());
         } else {
-          op.addError(StrUtils.formatString(" ''{0}'' does not exist . Do an ''{1}'' , if you want to create it ", name, "create-" + info.tag.toLowerCase(Locale.ROOT)));
+          op.addError(formatString(" ''{0}'' does not exist . Do an ''{1}'' , if you want to create it ", name, "create-" + info.getTagCleanLower()));
           return overlay;
         }
       }
@@ -379,7 +379,7 @@ public class SolrConfigHandler extends R
 
     private boolean verifyClass(CommandOperation op, String clz, Class expected) {
       if (clz == null) return true;
-      if ( !"true".equals(String.valueOf(op.getStr("runtimeLib", null)))) {
+      if (!"true".equals(String.valueOf(op.getStr("runtimeLib", null)))) {
         //this is not dynamically loaded so we can verify the class right away
         try {
           req.getCore().createInitInstance(new PluginInfo(SolrRequestHandler.TYPE, op.getDataMap()), expected, clz, "");
@@ -408,7 +408,7 @@ public class SolrConfigHandler extends R
       if (op.hasError()) return overlay;
       for (String o : name) {
         if (!overlay.getUserProps().containsKey(o)) {
-          op.addError(StrUtils.formatString("No such property ''{0}''", name));
+          op.addError(formatString("No such property ''{0}''", name));
         } else {
           overlay = overlay.unsetUserProperty(o);
         }
@@ -423,7 +423,7 @@ public class SolrConfigHandler extends R
 
       for (String o : name) {
         if (!ConfigOverlay.isEditableProp(o, false, null)) {
-          op.addError(StrUtils.formatString(NOT_EDITABLE, name));
+          op.addError(formatString(NOT_EDITABLE, name));
         } else {
           overlay = overlay.unsetProperty(o);
         }
@@ -437,10 +437,42 @@ public class SolrConfigHandler extends R
       for (Map.Entry<String, Object> e : m.entrySet()) {
         String name = e.getKey();
         Object val = e.getValue();
-        if (!ConfigOverlay.isEditableProp(name, false, null)) {
-          op.addError(StrUtils.formatString(NOT_EDITABLE, name));
+        Class typ = ConfigOverlay.checkEditable(name, false, null);
+        if (typ == null) {
+          op.addError(formatString(NOT_EDITABLE, name));
           continue;
         }
+
+        if (val != null) {
+          if (typ == String.class) val = val.toString();
+          String typeErr = "Property {0} must be of {1} type ";
+          if (typ == Boolean.class) {
+            try {
+              val = Boolean.parseBoolean(val.toString());
+            } catch (Exception exp) {
+              op.addError(formatString(typeErr, name, typ.getSimpleName()));
+              continue;
+            }
+          } else if (typ == Integer.class) {
+            try {
+              val = Integer.parseInt(val.toString());
+            } catch (Exception exp) {
+              op.addError(formatString(typeErr, typ.getSimpleName()));
+              continue;
+            }
+
+          } else if (typ == Float.class) {
+            try {
+              val = Float.parseFloat(val.toString());
+            } catch (Exception exp) {
+              op.addError(formatString(typeErr, typ.getSimpleName()));
+              continue;
+            }
+
+          }
+        }
+
+
         overlay = overlay.setProperty(name, val);
       }
       return overlay;
@@ -459,7 +491,7 @@ public class SolrConfigHandler extends R
           c == '.'
           ) continue;
       else {
-        return StrUtils.formatString("''{0}'' name should only have chars [a-zA-Z_-.0-9] ", s);
+        return formatString("''{0}'' name should only have chars [a-zA-Z_-.0-9] ", s);
       }
     }
     return null;
@@ -487,7 +519,7 @@ public class SolrConfigHandler extends R
 
   static {
     for (SolrConfig.SolrPluginInfo solrPluginInfo : SolrConfig.plugins)
-      subPaths.add("/" + solrPluginInfo.tag.replaceAll("/", ""));
+      subPaths.add("/" + solrPluginInfo.getCleanTag());
 
   }
 

Modified: lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestConfigOverlay.java
URL: http://svn.apache.org/viewvc/lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestConfigOverlay.java?rev=1669368&r1=1669367&r2=1669368&view=diff
==============================================================================
--- lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestConfigOverlay.java (original)
+++ lucene/dev/trunk/solr/core/src/test/org/apache/solr/core/TestConfigOverlay.java Thu Mar 26 16:39:14 2015
@@ -42,6 +42,21 @@ public class TestConfigOverlay extends L
     assertTrue(isEditableProp("updateHandler.autoCommit.maxTime", false, null));
     assertTrue(isEditableProp("updateHandler.commitWithin.softCommit", false, null));
     assertTrue(isEditableProp("updateHandler.indexWriter.closeWaitsForMerges", false, null));
+    assertTrue(isEditableProp("query.useFilterForSortedQuery", false, null));
+    assertTrue(isEditableProp("query.queryResultWindowSize", false, null));
+    assertTrue(isEditableProp("query.queryResultMaxDocsCached", false, null));
+    assertTrue(isEditableProp("query.enableLazyFieldLoading", false, null));
+    assertTrue(isEditableProp("query.boolTofilterOptimizer", false, null));
+    assertTrue(isEditableProp("jmx.agentId", false, null));
+    assertTrue(isEditableProp("jmx.serviceUrl", false, null));
+    assertTrue(isEditableProp("jmx.rootName", false, null));
+
+    assertTrue(isEditableProp("requestDispatcher.requestParsers.multipartUploadLimitInKB", false, null));
+    assertTrue(isEditableProp("requestDispatcher.requestParsers.formdataUploadLimitInKB", false, null));
+    assertTrue(isEditableProp("requestDispatcher.requestParsers.enableRemoteStreaming", false, null));
+    assertTrue(isEditableProp("requestDispatcher.requestParsers.addHttpRequestToContext", false, null));
+
+    assertTrue(isEditableProp("requestDispatcher.handleSelect", false, null));
 
     assertTrue(isEditableProp("updateHandler/commitIntervalLowerBound", true, null));
     assertFalse(isEditableProp("updateHandler/commitIntervalLowerBound1", true, null));



Mime
View raw message