You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by cm...@apache.org on 2013/08/11 14:19:39 UTC

svn commit: r1512909 [25/38] - in /lucene/dev/branches/lucene4956: ./ dev-tools/ dev-tools/eclipse/ dev-tools/idea/.idea/libraries/ dev-tools/idea/lucene/suggest/ dev-tools/idea/solr/contrib/dataimporthandler/ dev-tools/idea/solr/core/src/test/ dev-too...

Modified: lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/ConfigSolrXml.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/ConfigSolrXml.java?rev=1512909&r1=1512908&r2=1512909&view=diff
==============================================================================
--- lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/ConfigSolrXml.java (original)
+++ lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/ConfigSolrXml.java Sun Aug 11 12:19:13 2013
@@ -17,51 +17,43 @@ package org.apache.solr.core;
  * limitations under the License.
  */
 
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-
-import javax.xml.parsers.ParserConfigurationException;
-
-import org.apache.commons.io.IOUtils;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.util.PropertiesUtil;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.xml.sax.SAXException;
+
+import java.io.IOException;
 
 
 /**
  *
  */
 public class ConfigSolrXml extends ConfigSolr {
+
   protected static Logger log = LoggerFactory.getLogger(ConfigSolrXml.class);
 
-  private SolrCoreDiscoverer solrCoreDiscoverer = new SolrCoreDiscoverer();
-  private final Map<String, CoreDescriptor> coreDescriptorMap;
+  private final CoresLocator coresLocator;
 
-  public ConfigSolrXml(Config config, CoreContainer container)
-      throws ParserConfigurationException, IOException, SAXException {
+  public ConfigSolrXml(Config config) {
     super(config);
-    checkForIllegalConfig();
-    
-    fillPropMap();
-    
-    String coreRoot = get(CfgProp.SOLR_COREROOTDIRECTORY, (container == null ? config.getResourceLoader().getInstanceDir() : container.getSolrHome()));
-    coreDescriptorMap = solrCoreDiscoverer.discover(container, new File(coreRoot));
+    try {
+      checkForIllegalConfig();
+      fillPropMap();
+      config.substituteProperties();
+      log.info("Config-defined core root directory: {}", get(CfgProp.SOLR_COREROOTDIRECTORY, ""));
+      String coreRoot = get(CfgProp.SOLR_COREROOTDIRECTORY, config.getResourceLoader().getInstanceDir());
+      coresLocator = new CorePropertiesLocator(coreRoot);
+    }
+    catch (IOException e) {
+      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
+    }
   }
   
   private void checkForIllegalConfig() throws IOException {
     
     // Do sanity checks - we don't want to find old style config
     failIfFound("solr/@coreLoadThreads");
-    failIfFound("solr/@persist");
+    failIfFound("solr/@persistent");
     failIfFound("solr/@sharedLib");
     failIfFound("solr/@zkHost");
     
@@ -77,6 +69,7 @@ public class ConfigSolrXml extends Confi
     failIfFound("solr/cores/@hostContext");
     failIfFound("solr/cores/@hostPort");
     failIfFound("solr/cores/@leaderVoteWait");
+    failIfFound("solr/cores/@genericCoreNodeNames");
     failIfFound("solr/cores/@managementPath");
     failIfFound("solr/cores/@shareSchema");
     failIfFound("solr/cores/@transientCacheSize");
@@ -118,6 +111,7 @@ public class ConfigSolrXml extends Confi
     propMap.put(CfgProp.SOLR_HOSTCONTEXT, doSub("solr/solrcloud/str[@name='hostContext']"));
     propMap.put(CfgProp.SOLR_HOSTPORT, doSub("solr/solrcloud/int[@name='hostPort']"));
     propMap.put(CfgProp.SOLR_LEADERVOTEWAIT, doSub("solr/solrcloud/int[@name='leaderVoteWait']"));
+    propMap.put(CfgProp.SOLR_GENERICCORENODENAMES, doSub("solr/solrcloud/bool[@name='genericCoreNodeNames']"));
     propMap.put(CfgProp.SOLR_MANAGEMENTPATH, doSub("solr/str[@name='managementPath']"));
     propMap.put(CfgProp.SOLR_SHAREDLIB, doSub("solr/str[@name='sharedLib']"));
     propMap.put(CfgProp.SOLR_SHARESCHEMA, doSub("solr/str[@name='shareSchema']"));
@@ -129,69 +123,31 @@ public class ConfigSolrXml extends Confi
     propMap.put(CfgProp.SOLR_LOGGING_ENABLED, doSub("solr/logging/str[@name='enabled']"));
     propMap.put(CfgProp.SOLR_LOGGING_WATCHER_SIZE, doSub("solr/logging/watcher/int[@name='size']"));
     propMap.put(CfgProp.SOLR_LOGGING_WATCHER_THRESHOLD, doSub("solr/logging/watcher/int[@name='threshold']"));
-    propMap.put(CfgProp.SOLR_SHARDHANDLERFACTORY_CLASS, doSub("solr/shardHandlerFactory/@class"));
-    propMap.put(CfgProp.SOLR_SHARDHANDLERFACTORY_NAME, doSub("solr/shardHandlerFactory/@name"));
-    propMap.put(CfgProp.SOLR_SHARDHANDLERFACTORY_CONNTIMEOUT, doSub("solr/shardHandlerFactory/int[@name='connTimeout']"));
-    propMap.put(CfgProp.SOLR_SHARDHANDLERFACTORY_SOCKETTIMEOUT, doSub("solr/shardHandlerFactory/int[@name='socketTimeout']"));
   }
 
-
-
   @Override
-  public Map<String,String> readCoreAttributes(String coreName) {
-    Map<String,String> attrs = new HashMap<String,String>();
-    
-    return attrs; // this is a no-op.... intentionally
+  public String getDefaultCoreName() {
+    return "collection1";
   }
 
   @Override
-  public List<String> getAllCoreNames() {
-    List<String> ret = new ArrayList<String>(coreDescriptorMap.keySet());
-    
-    return ret;
-  }
-  
-  @Override
-  public String getProperty(String coreName, String property, String defaultVal) {
-    CoreDescriptor cd = coreDescriptorMap.get(coreName);
-    if (cd == null) return defaultVal;
-
-    return cd.getProperty(property, defaultVal);
+  public boolean isPersistent() {
+    return true;
   }
 
   @Override
-  public Properties readCoreProperties(String coreName) {
-    CoreDescriptor cd = coreDescriptorMap.get(coreName);
-    if (cd == null) return null;
-    return new Properties(cd.getCoreProperties());
+  protected String getShardHandlerFactoryConfigPath() {
+    return "solr/shardHandlerFactory";
   }
 
-  static Properties getCoreProperties(String instanceDir, CoreDescriptor dcore) {
-    String file = dcore.getPropertiesName();
-    if (file == null) file = "conf" + File.separator + "solrcore.properties";
-    File corePropsFile = new File(file);
-    if (!corePropsFile.isAbsolute()) {
-      corePropsFile = new File(instanceDir, file);
-    }
-    Properties p = dcore.getCoreProperties();
-    if (corePropsFile.exists() && corePropsFile.isFile()) {
-      p = new Properties(dcore.getCoreProperties());
-      InputStream is = null;
-      try {
-        is = new FileInputStream(corePropsFile);
-        p.load(is);
-      } catch (IOException e) {
-        log.warn("Error loading properties ", e);
-      } finally {
-        IOUtils.closeQuietly(is);
-      }
-    }
-    return p;
+  @Override
+  public String getAdminPath() {
+    return DEFAULT_CORE_ADMIN_PATH;
   }
 
   @Override
-  public void substituteProperties() {
-    config.substituteProperties();
+  public CoresLocator getCoresLocator() {
+    return coresLocator;
   }
 
 }

Modified: lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/ConfigSolrXmlOld.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/ConfigSolrXmlOld.java?rev=1512909&r1=1512908&r2=1512909&view=diff
==============================================================================
--- lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/ConfigSolrXmlOld.java (original)
+++ lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/ConfigSolrXmlOld.java Sun Aug 11 12:19:13 2013
@@ -17,10 +17,18 @@ package org.apache.solr.core;
  * limitations under the License.
  */
 
+import org.apache.solr.common.SolrException;
+import org.apache.solr.util.DOMUtil;
+import org.apache.solr.util.PropertiesUtil;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+import javax.xml.xpath.XPathConstants;
+import javax.xml.xpath.XPathExpressionException;
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
-import java.io.InputStream;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -30,40 +38,44 @@ import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 
-import javax.xml.parsers.ParserConfigurationException;
-import javax.xml.xpath.XPathConstants;
-import javax.xml.xpath.XPathExpressionException;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.util.DOMUtil;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.w3c.dom.NamedNodeMap;
-import org.w3c.dom.Node;
-import org.w3c.dom.NodeList;
-import org.xml.sax.SAXException;
-
 
 /**
  *
  */
 public class ConfigSolrXmlOld extends ConfigSolr {
+
   protected static Logger log = LoggerFactory.getLogger(ConfigSolrXmlOld.class);
 
   private NodeList coreNodes = null;
+  
+  private final CoresLocator persistor;
 
-  public ConfigSolrXmlOld(Config config, CoreContainer container)
-      throws ParserConfigurationException, IOException, SAXException {
+  @Override
+  protected String getShardHandlerFactoryConfigPath() {
+    return "solr/cores/shardHandlerFactory";
+  }
 
+  public ConfigSolrXmlOld(Config config, File configFile, String originalXML) {
     super(config);
-    checkForIllegalConfig(container);
-    
-    fillPropMap();
-    initCoreList(container);
+    try {
+      checkForIllegalConfig();
+      fillPropMap();
+      config.substituteProperties();
+      initCoreList();
+      this.persistor = isPersistent() ? new SolrXMLCoresLocator(configFile, originalXML, this)
+                                      : new SolrXMLCoresLocator.NonPersistingLocator(configFile, originalXML, this);
+    }
+    catch (IOException e) {
+      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
+    }
+  }
+
+  @Override
+  public CoresLocator getCoresLocator() {
+    return this.persistor;
   }
   
-  private void checkForIllegalConfig(CoreContainer container) throws IOException {
+  private void checkForIllegalConfig() throws IOException {
     // Do sanity checks - we don't want to find new style
     // config
     failIfFound("solr/str[@name='adminHandler']");
@@ -75,6 +87,7 @@ public class ConfigSolrXmlOld extends Co
     failIfFound("solr/solrcloud/str[@name='hostContext']");
     failIfFound("solr/solrcloud/int[@name='hostPort']");
     failIfFound("solr/solrcloud/int[@name='leaderVoteWait']");
+    failIfFound("solr/solrcloud/int[@name='genericCoreNodeNames']");
     failIfFound("solr/str[@name='managementPath']");
     failIfFound("solr/str[@name='sharedLib']");
     failIfFound("solr/str[@name='shareSchema']");
@@ -96,6 +109,16 @@ public class ConfigSolrXmlOld extends Co
           " solr.xml may be a mix of old and new style formats.");
     }
   }
+
+  @Override
+  public boolean isPersistent() {
+    return config.getBool("solr/@persistent", false);
+  }
+
+  @Override
+  public String getDefaultCoreName() {
+    return get(CfgProp.SOLR_CORES_DEFAULT_CORE_NAME, DEFAULT_DEFAULT_CORE_NAME);
+  }
   
   private void fillPropMap() {
     
@@ -127,6 +150,8 @@ public class ConfigSolrXmlOld extends Co
         config.getVal("solr/cores/@hostPort", false));
     propMap.put(CfgProp.SOLR_LEADERVOTEWAIT,
         config.getVal("solr/cores/@leaderVoteWait", false));
+    propMap.put(CfgProp.SOLR_GENERICCORENODENAMES,
+        config.getVal("solr/cores/@genericCoreNodeNames", false));
     propMap.put(CfgProp.SOLR_MANAGEMENTPATH,
         config.getVal("solr/cores/@managementPath", false));
     propMap.put(CfgProp.SOLR_SHARESCHEMA,
@@ -135,15 +160,7 @@ public class ConfigSolrXmlOld extends Co
         config.getVal("solr/cores/@transientCacheSize", false));
     propMap.put(CfgProp.SOLR_ZKCLIENTTIMEOUT,
         config.getVal("solr/cores/@zkClientTimeout", false));
-    propMap.put(CfgProp.SOLR_SHARDHANDLERFACTORY_CLASS,
-        config.getVal("solr/shardHandlerFactory/@class", false));
-    propMap.put(CfgProp.SOLR_SHARDHANDLERFACTORY_NAME,
-        config.getVal("solr/shardHandlerFactory/@name", false));
-    propMap.put(CfgProp.SOLR_SHARDHANDLERFACTORY_CONNTIMEOUT,
-        config.getVal("solr/shardHandlerFactory/int[@connTimeout]", false));
-    propMap.put(CfgProp.SOLR_SHARDHANDLERFACTORY_SOCKETTIMEOUT,
-        config.getVal("solr/shardHandlerFactory/int[@socketTimeout]", false));
-    
+
     // These have no counterpart in 5.0, asking, for any of these in Solr 5.0
     // will result in an error being
     // thrown.
@@ -156,7 +173,7 @@ public class ConfigSolrXmlOld extends Co
     
   }
 
-  private void initCoreList(CoreContainer container) throws IOException {
+  private void initCoreList() throws IOException {
     
     coreNodes = (NodeList) config.evaluate("solr/cores/core",
         XPathConstants.NODESET);
@@ -168,7 +185,9 @@ public class ConfigSolrXmlOld extends Co
     for (int idx = 0; idx < coreNodes.getLength(); ++idx) {
       Node node = coreNodes.item(idx);
       String name = DOMUtil.getAttr(node, CoreDescriptor.CORE_NAME, null);
+
       String dataDir = DOMUtil.getAttr(node, CoreDescriptor.CORE_DATADIR, null);
+      if (dataDir != null) dataDir = PropertiesUtil.substituteProperty(dataDir, null);
       if (name != null) {
         if (!names.contains(name)) {
           names.add(name);
@@ -180,52 +199,34 @@ public class ConfigSolrXmlOld extends Co
       }
 
       String instDir = DOMUtil.getAttr(node, CoreDescriptor.CORE_INSTDIR, null);
-      if (dataDir != null && instDir != null) { // this won't load anyway if instDir not specified.
+      if (instDir != null) instDir = PropertiesUtil.substituteProperty(instDir, null);
 
-        String absData = new File(instDir, dataDir).getCanonicalPath();
-        if (!dirs.containsKey(absData)) {
-          dirs.put(absData, name);
-        } else {
-          String msg = String
-              .format(
-                  Locale.ROOT,
-                  "More than one core points to data dir %s. They are in %s and %s",
-                  absData, dirs.get(absData), name);
-          log.warn(msg);
+      if (dataDir != null) {
+        String absData = null;
+        File dataFile = new File(dataDir);
+        if (dataFile.isAbsolute()) {
+          absData = dataFile.getCanonicalPath();
+        } else if (instDir != null) {
+          File instFile = new File(instDir);
+          absData = new File(instFile, dataDir).getCanonicalPath();
         }
-      }
-    }
-    
-  }
-
-  @Override
-  public Map<String, String> readCoreAttributes(String coreName) {
-    Map<String, String> attrs = new HashMap<String, String>();
-
-    synchronized (coreNodes) {
-      for (int idx = 0; idx < coreNodes.getLength(); ++idx) {
-        Node node = coreNodes.item(idx);
-        if (coreName.equals(DOMUtil.getAttr(node, CoreDescriptor.CORE_NAME, null))) {
-          NamedNodeMap attributes = node.getAttributes();
-          for (int i = 0; i < attributes.getLength(); i++) {
-            Node attribute = attributes.item(i);
-            String val = attribute.getNodeValue();
-            if (CoreDescriptor.CORE_DATADIR.equals(attribute.getNodeName()) ||
-                CoreDescriptor.CORE_INSTDIR.equals(attribute.getNodeName())) {
-              if (val.indexOf('$') == -1) {
-                val = (val != null && !val.endsWith("/")) ? val + '/' : val;
-              }
-            }
-            attrs.put(attribute.getNodeName(), val);
+        if (absData != null) {
+          if (!dirs.containsKey(absData)) {
+            dirs.put(absData, name);
+          } else {
+            String msg = String
+                .format(
+                    Locale.ROOT,
+                    "More than one core points to data dir %s. They are in %s and %s",
+                    absData, dirs.get(absData), name);
+            log.warn(msg);
           }
-          return attrs;
         }
       }
     }
-    return attrs;
+    
   }
 
-  @Override
   public List<String> getAllCoreNames() {
     List<String> ret = new ArrayList<String>();
     
@@ -239,7 +240,6 @@ public class ConfigSolrXmlOld extends Co
     return ret;
   }
 
-  @Override
   public String getProperty(String coreName, String property, String defaultVal) {
     
     synchronized (coreNodes) {
@@ -247,7 +247,10 @@ public class ConfigSolrXmlOld extends Co
         Node node = coreNodes.item(idx);
         if (coreName.equals(DOMUtil.getAttr(node, CoreDescriptor.CORE_NAME,
             null))) {
-          return DOMUtil.getAttr(node, property, defaultVal);
+          String propVal = DOMUtil.getAttr(node, property);
+          if (propVal == null)
+            propVal = defaultVal;
+          return PropertiesUtil.substituteProperty(propVal, null);
         }
       }
     }
@@ -255,64 +258,34 @@ public class ConfigSolrXmlOld extends Co
     
   }
 
-  @Override
-  public Properties readCoreProperties(String coreName) {
-    
+  public Properties getCoreProperties(String coreName) {
     synchronized (coreNodes) {
-      for (int idx = 0; idx < coreNodes.getLength(); ++idx) {
+      for (int idx = 0; idx < coreNodes.getLength(); idx++) {
         Node node = coreNodes.item(idx);
-        if (coreName.equals(DOMUtil.getAttr(node, CoreDescriptor.CORE_NAME,
-            null))) {
+        if (coreName.equals(DOMUtil.getAttr(node, CoreDescriptor.CORE_NAME, null))) {
           try {
             return readProperties(node);
           } catch (XPathExpressionException e) {
-            return null;
+            SolrException.log(log, e);
           }
         }
       }
     }
-    
-    return null;
+    return new Properties();
   }
 
-  static Properties getCoreProperties(String instanceDir, CoreDescriptor dcore) {
-    String file = dcore.getPropertiesName();
-    if (file == null) file = "conf" + File.separator + "solrcore.properties";
-    File corePropsFile = new File(file);
-    if (!corePropsFile.isAbsolute()) {
-      corePropsFile = new File(instanceDir, file);
-    }
-    Properties p = dcore.getCoreProperties();
-    if (corePropsFile.exists() && corePropsFile.isFile()) {
-      p = new Properties(dcore.getCoreProperties());
-      InputStream is = null;
-      try {
-        is = new FileInputStream(corePropsFile);
-        p.load(is);
-      } catch (IOException e) {
-        log.warn("Error loading properties ", e);
-      } finally {
-        IOUtils.closeQuietly(is);
-      }
-    }
-    return p;
-  }
+  public static final String DEFAULT_DEFAULT_CORE_NAME = "collection1";
 
   public static final String DEF_SOLR_XML = "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\n"
-      + "<solr persistent=\"false\">\n"
-      + "  <cores adminPath=\"/admin/cores\" defaultCoreName=\""
-      + CoreContainer.DEFAULT_DEFAULT_CORE_NAME
-      + "\""
-      + " host=\"${host:}\" hostPort=\"${hostPort:}\" hostContext=\"${hostContext:}\" zkClientTimeout=\"${zkClientTimeout:15000}\""
-      + ">\n"
-      + "    <core name=\""
-      + CoreContainer.DEFAULT_DEFAULT_CORE_NAME
-      + "\" shard=\"${shard:}\" collection=\"${collection:}\" instanceDir=\"collection1\" />\n"
-      + "  </cores>\n" + "</solr>";
-
-  @Override
-  public void substituteProperties() {
-    config.substituteProperties();
-  }
+        + "<solr persistent=\"false\">\n"
+        + "  <cores adminPath=\"/admin/cores\" defaultCoreName=\""
+        + DEFAULT_DEFAULT_CORE_NAME
+        + "\""
+        + " host=\"${host:}\" hostPort=\"${hostPort:}\" hostContext=\"${hostContext:}\" zkClientTimeout=\"${zkClientTimeout:15000}\""
+        + ">\n"
+        + "    <core name=\""
+        + DEFAULT_DEFAULT_CORE_NAME
+        + "\" shard=\"${shard:}\" collection=\"${collection:collection1}\" instanceDir=\"collection1\" />\n"
+        + "  </cores>\n" + "</solr>";
 
 }

Modified: lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/CoreContainer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/CoreContainer.java?rev=1512909&r1=1512908&r2=1512909&view=diff
==============================================================================
--- lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/CoreContainer.java (original)
+++ lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/CoreContainer.java Sun Aug 11 12:19:13 2013
@@ -17,7 +17,7 @@
 
 package org.apache.solr.core;
 
-import org.apache.commons.io.IOUtils;
+import com.google.common.collect.Maps;
 import org.apache.solr.cloud.ZkController;
 import org.apache.solr.cloud.ZkSolrResourceLoader;
 import org.apache.solr.common.SolrException;
@@ -26,7 +26,7 @@ import org.apache.solr.common.cloud.ZooK
 import org.apache.solr.common.util.ExecutorUtil;
 import org.apache.solr.handler.admin.CollectionsHandler;
 import org.apache.solr.handler.admin.CoreAdminHandler;
-import org.apache.solr.handler.component.HttpShardHandlerFactory;
+import org.apache.solr.handler.admin.InfoHandler;
 import org.apache.solr.handler.component.ShardHandlerFactory;
 import org.apache.solr.logging.LogWatcher;
 import org.apache.solr.logging.jul.JulWatcher;
@@ -34,31 +34,15 @@ import org.apache.solr.schema.IndexSchem
 import org.apache.solr.schema.IndexSchemaFactory;
 import org.apache.solr.util.DefaultSolrThreadFactory;
 import org.apache.solr.util.FileUtils;
-import org.apache.solr.util.PropertiesUtil;
-import org.apache.solr.util.plugin.PluginInfoInitialized;
 import org.apache.zookeeper.KeeperException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
-import org.w3c.dom.Document;
-import org.w3c.dom.Node;
-import org.xml.sax.InputSource;
-
-import javax.xml.transform.Transformer;
-import javax.xml.transform.TransformerException;
-import javax.xml.transform.TransformerFactory;
-import javax.xml.transform.dom.DOMResult;
-import javax.xml.transform.dom.DOMSource;
-import javax.xml.xpath.XPathExpressionException;
-import java.io.ByteArrayInputStream;
+
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.InputStream;
 import java.text.SimpleDateFormat;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
-import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -71,361 +55,206 @@ import java.util.concurrent.CompletionSe
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorCompletionService;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 import java.util.concurrent.Future;
-import java.util.concurrent.LinkedBlockingQueue;
-import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.TimeUnit;
+
+import static com.google.common.base.Preconditions.checkNotNull;
 
 
 /**
  *
  * @since solr 1.3
  */
-public class CoreContainer
-{
-  private static final String LEADER_VOTE_WAIT = "180000";  // 3 minutes
-  private static final int CORE_LOAD_THREADS = 3;
-
-  private static final int DEFAULT_ZK_CLIENT_TIMEOUT = 15000;
-  public static final String DEFAULT_DEFAULT_CORE_NAME = "collection1";
-  private static final boolean DEFAULT_SHARE_SCHEMA = false;
-
-  protected static Logger log = LoggerFactory.getLogger(CoreContainer.class);
+public class CoreContainer {
 
+  protected static final Logger log = LoggerFactory.getLogger(CoreContainer.class);
 
   private final SolrCores solrCores = new SolrCores(this);
 
   protected final Map<String,Exception> coreInitFailures =
     Collections.synchronizedMap(new LinkedHashMap<String,Exception>());
-  
-  protected boolean persistent = false;
-  protected String adminPath = null;
-  protected volatile String managementPath = null;
 
   protected CoreAdminHandler coreAdminHandler = null;
   protected CollectionsHandler collectionsHandler = null;
-  protected File configFile = null;
-  protected String libDir = null;
-  protected SolrResourceLoader loader = null;
+  private InfoHandler infoHandler;
+
   protected Properties containerProperties;
+
   protected Map<String ,IndexSchema> indexSchemaCache;
-  protected String adminHandler;
   protected boolean shareSchema;
-  protected Integer zkClientTimeout;
-  protected String solrHome;
-  protected String defaultCoreName = null;
 
   protected ZkContainer zkSys = new ZkContainer();
-
   private ShardHandlerFactory shardHandlerFactory;
+
   protected LogWatcher logging = null;
-  private String zkHost;
-  private int transientCacheSize = Integer.MAX_VALUE;
 
-  private int coreLoadThreads;
   private CloserThread backgroundCloser = null;
-  protected volatile ConfigSolr cfg;
-  private Config origCfg;
-  
+  protected final ConfigSolr cfg;
+  protected final SolrResourceLoader loader;
+
+  protected final String solrHome;
+
+  protected final CoresLocator coresLocator;
+
   {
     log.info("New CoreContainer " + System.identityHashCode(this));
   }
 
   /**
-   * Deprecated
-   * @deprecated use the single arg constructor with locateSolrHome()
-   * @see SolrResourceLoader#locateSolrHome
+   * Create a new CoreContainer using system properties to detect the solr home
+   * directory.  The container's cores are not loaded.
+   * @see #load()
    */
-  @Deprecated
   public CoreContainer() {
-    this(SolrResourceLoader.locateSolrHome());
+    this(new SolrResourceLoader(SolrResourceLoader.locateSolrHome()));
   }
 
   /**
-   * Initalize CoreContainer directly from the constructor
+   * Create a new CoreContainer using the given SolrResourceLoader.  The container's
+   * cores are not loaded.
+   * @param loader the SolrResourceLoader
+   * @see #load()
    */
-  public CoreContainer(String dir, File configFile) throws FileNotFoundException {
-    this(dir);
-    this.load(dir, configFile);
+  public CoreContainer(SolrResourceLoader loader) {
+    this(loader, ConfigSolr.fromSolrHome(loader, loader.getInstanceDir()));
   }
 
   /**
-   * Minimal CoreContainer constructor.
-   * @param loader the CoreContainer resource loader
+   * Create a new CoreContainer using the given solr home directory.  The container's
+   * cores are not loaded.
+   * @param solrHome a String containing the path to the solr home directory
+   * @see #load()
    */
-  public CoreContainer(SolrResourceLoader loader) {
-    this(loader.getInstanceDir());
-    this.loader = loader;
+  public CoreContainer(String solrHome) {
+    this(new SolrResourceLoader(solrHome));
   }
 
-  public CoreContainer(String solrHome) {
-    this.solrHome = solrHome;
+  /**
+   * Create a new CoreContainer using the given SolrResourceLoader,
+   * configuration and CoresLocator.  The container's cores are
+   * not loaded.
+   * @param loader the SolrResourceLoader
+   * @param config a ConfigSolr representation of this container's configuration
+   * @see #load()
+   */
+  public CoreContainer(SolrResourceLoader loader, ConfigSolr config) {
+    this.loader = checkNotNull(loader);
+    this.solrHome = loader.getInstanceDir();
+    this.cfg = checkNotNull(config);
+    this.coresLocator = config.getCoresLocator();
+  }
+
+  public CoreContainer(SolrResourceLoader loader, ConfigSolr config, CoresLocator locator) {
+    this.loader = checkNotNull(loader);
+    this.solrHome = loader.getInstanceDir();
+    this.cfg = checkNotNull(config);
+    this.coresLocator = locator;
+  }
+
+  /**
+   * Create a new CoreContainer and load its cores
+   * @param solrHome the solr home directory
+   * @param configFile the file containing this container's configuration
+   * @return a loaded CoreContainer
+   */
+  public static CoreContainer createAndLoad(String solrHome, File configFile) {
+    SolrResourceLoader loader = new SolrResourceLoader(solrHome);
+    CoreContainer cc = new CoreContainer(loader, ConfigSolr.fromFile(loader, configFile));
+    cc.load();
+    return cc;
   }
   
   public Properties getContainerProperties() {
     return containerProperties;
   }
 
-  // Helper class to initialize the CoreContainer
-  public static class Initializer {
-
-    // core container instantiation
-    public CoreContainer initialize() throws FileNotFoundException {
-      CoreContainer cores = null;
-      String solrHome = SolrResourceLoader.locateSolrHome();
-      // ContainerConfigFilename could  could be a properties file
-      File fconf = new File(solrHome, "solr.xml");
-
-      log.info("looking for solr config file: " + fconf.getAbsolutePath());
-      cores = new CoreContainer(solrHome);
-
-      // first we find zkhost, then we check for solr.xml in zk
-      // 1. look for zkhost from sys prop 2. look for zkhost in {solr.home}/solr.properties
-      
-      // Either we have a config file or not.
-      
-      if (fconf.exists()) {
-        cores.load(solrHome, fconf);
-      } else {
-        // Back compart support
-        log.info("no solr.xml found. using default old-style solr.xml");
-        try {
-          cores.load(solrHome, new ByteArrayInputStream(ConfigSolrXmlOld.DEF_SOLR_XML.getBytes("UTF-8")), null);
-        } catch (Exception e) {
-          throw new SolrException(ErrorCode.SERVER_ERROR,
-              "CoreContainer.Initialize failed when trying to load default solr.xml file", e);
-        }
-        cores.configFile = fconf;
-      }
-      
-      return cores;
-    }
-  }
-
-
   //-------------------------------------------------------------------
   // Initialization / Cleanup
   //-------------------------------------------------------------------
-  
-  /**
-   * Load a config file listing the available solr cores.
-   * @param dir the home directory of all resources.
-   * @param configFile the configuration file
-   */
-  public void load(String dir, File configFile) throws FileNotFoundException {
-    this.configFile = configFile;
-    InputStream in = new FileInputStream(configFile);
-    try {
-      this.load(dir, in,  configFile.getName());
-    } finally {
-      IOUtils.closeQuietly(in);
-    }
-  } 
 
   /**
-   * Load a config file listing the available solr cores.
-   * 
-   * @param dir the home directory of all resources.
-   * @param is the configuration file InputStream. May be a properties file or an xml file
+   * Load the cores defined for this CoreContainer
    */
+  public void load()  {
 
-  // Let's keep this ugly boolean out of public circulation.
-  protected void load(String dir, InputStream is, String fileName)  {
-    ThreadPoolExecutor coreLoadExecutor = null;
-    if (null == dir) {
-      // don't rely on SolrResourceLoader(), determine explicitly first
-      dir = SolrResourceLoader.locateSolrHome();
-    }
-    log.info("Loading CoreContainer using Solr Home: '{}'", dir);
-    
-    this.loader = new SolrResourceLoader(dir);
-    solrHome = loader.getInstanceDir();
-
-    try {
-      Config config = new Config(loader, null, new InputSource(is), null, false);
-
-      // old style defines cores in solr.xml, new style disovers them by 
-      // directory structure
-      boolean oldStyle = (config.getNode("solr/cores", false) != null);
-      
-      if (oldStyle) {
-        // ConfigSolr handles keep orig values around for non solrcore level items,
-        // but this is still how original core lvl attributes are kept around
-        this.origCfg = new Config(loader, null, copyDoc(config.getDocument()));
-        
-        this.cfg = new ConfigSolrXmlOld(config, this);
-      } else {
-        this.cfg = new ConfigSolrXml(config, this);
-
-      }
-    } catch (Exception e) {
-      throw new SolrException(ErrorCode.SERVER_ERROR, "", e);
-    }
-    // Since the cores var is now initialized to null, let's set it up right
-    // now.
-    cfg.substituteProperties();
+    log.info("Loading cores into CoreContainer [instanceDir={}]", loader.getInstanceDir());
 
     // add the sharedLib to the shared resource loader before initializing cfg based plugins
-    libDir = cfg.get(ConfigSolr.CfgProp.SOLR_SHAREDLIB , null);
+    String libDir = cfg.getSharedLibDirectory();
     if (libDir != null) {
-      File f = FileUtils.resolvePath(new File(dir), libDir);
+      File f = FileUtils.resolvePath(new File(solrHome), libDir);
       log.info("loading shared library: " + f.getAbsolutePath());
       loader.addToClassLoader(libDir, null, false);
       loader.reloadLuceneSPI();
     }
 
-    shardHandlerFactory = initShardHandler(cfg);
+    shardHandlerFactory = ShardHandlerFactory.newInstance(cfg.getShardHandlerFactoryPluginInfo(), loader);
 
-    solrCores.allocateLazyCores(cfg, loader);
+    solrCores.allocateLazyCores(cfg.getTransientCacheSize(), loader);
 
-    logging = JulWatcher.newRegisteredLogWatcher(cfg, loader);
+    logging = JulWatcher.newRegisteredLogWatcher(cfg.getLogWatcherConfig(), loader);
 
-    if (cfg instanceof ConfigSolrXmlOld) { //TODO: Remove for 5.0
-      String dcoreName = cfg.get(ConfigSolr.CfgProp.SOLR_CORES_DEFAULT_CORE_NAME, null);
-      if (dcoreName != null && !dcoreName.isEmpty()) {
-        defaultCoreName = dcoreName;
-      }
-      persistent = cfg.getBool(ConfigSolr.CfgProp.SOLR_PERSISTENT, false);
-      adminPath = cfg.get(ConfigSolr.CfgProp.SOLR_ADMINPATH, "/admin/cores");
-    } else {
-      adminPath = "/admin/cores";
-      defaultCoreName = DEFAULT_DEFAULT_CORE_NAME;
-    }
-    zkHost = cfg.get(ConfigSolr.CfgProp.SOLR_ZKHOST, null);
-    coreLoadThreads = cfg.getInt(ConfigSolr.CfgProp.SOLR_CORELOADTHREADS, CORE_LOAD_THREADS);
-    
-
-    shareSchema = cfg.getBool(ConfigSolr.CfgProp.SOLR_SHARESCHEMA, DEFAULT_SHARE_SCHEMA);
-    zkClientTimeout = cfg.getInt(ConfigSolr.CfgProp.SOLR_ZKCLIENTTIMEOUT, DEFAULT_ZK_CLIENT_TIMEOUT);
-    
-    int distribUpdateConnTimeout = cfg.getInt(ConfigSolr.CfgProp.SOLR_DISTRIBUPDATECONNTIMEOUT, 0);
-    int distribUpdateSoTimeout = cfg.getInt(ConfigSolr.CfgProp.SOLR_DISTRIBUPDATESOTIMEOUT, 0);
-
-    // Note: initZooKeeper will apply hardcoded default if cloud mode
-    String hostPort = cfg.get(ConfigSolr.CfgProp.SOLR_HOSTPORT, null);
-    // Note: initZooKeeper will apply hardcoded default if cloud mode
-    String hostContext = cfg.get(ConfigSolr.CfgProp.SOLR_HOSTCONTEXT, null);
-
-    String host = cfg.get(ConfigSolr.CfgProp.SOLR_HOST, null);
-    
-    String leaderVoteWait = cfg.get(ConfigSolr.CfgProp.SOLR_LEADERVOTEWAIT, LEADER_VOTE_WAIT);
-
-    adminHandler = cfg.get(ConfigSolr.CfgProp.SOLR_ADMINHANDLER, null);
-    managementPath = cfg.get(ConfigSolr.CfgProp.SOLR_MANAGEMENTPATH, null);
-
-    transientCacheSize = cfg.getInt(ConfigSolr.CfgProp.SOLR_TRANSIENTCACHESIZE, Integer.MAX_VALUE);
+    shareSchema = cfg.hasSchemaCache();
 
     if (shareSchema) {
       indexSchemaCache = new ConcurrentHashMap<String,IndexSchema>();
     }
 
-    zkClientTimeout = Integer.parseInt(System.getProperty("zkClientTimeout",
-        Integer.toString(zkClientTimeout)));
-    zkSys.initZooKeeper(this, solrHome, zkHost, zkClientTimeout, hostPort, hostContext, host, leaderVoteWait, distribUpdateConnTimeout, distribUpdateSoTimeout);
-    
-    if (isZooKeeperAware() && coreLoadThreads <= 1) {
-      throw new SolrException(ErrorCode.SERVER_ERROR,
-          "SolrCloud requires a value of at least 2 in solr.xml for coreLoadThreads");
-    }
-    
-    if (adminPath != null) {
-      if (adminHandler == null) {
-        coreAdminHandler = new CoreAdminHandler(this);
-      } else {
-        coreAdminHandler = this.createMultiCoreHandler(adminHandler);
-      }
-    }
-    
+    zkSys.initZooKeeper(this, solrHome, cfg);
+
     collectionsHandler = new CollectionsHandler(this);
+    infoHandler = new InfoHandler(this);
+    coreAdminHandler = createMultiCoreHandler(cfg.getCoreAdminHandlerClass());
+
     containerProperties = cfg.getSolrProperties("solr");
 
     // setup executor to load cores in parallel
-    coreLoadExecutor = new ThreadPoolExecutor(coreLoadThreads, coreLoadThreads, 1,
-        TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>(),
+    ExecutorService coreLoadExecutor = Executors.newFixedThreadPool(cfg.getCoreLoadThreadCount(),
         new DefaultSolrThreadFactory("coreLoadExecutor"));
+
     try {
       CompletionService<SolrCore> completionService = new ExecutorCompletionService<SolrCore>(
           coreLoadExecutor);
+
       Set<Future<SolrCore>> pending = new HashSet<Future<SolrCore>>();
 
-      List<String> allCores = cfg.getAllCoreNames();
+      List<CoreDescriptor> cds = coresLocator.discover(this);
+      checkForDuplicateCoreNames(cds);
 
-      for (String oneCoreName : allCores) {
+      for (final CoreDescriptor cd : cds) {
 
+        final String name = cd.getName();
         try {
-          String rawName = cfg.getProperty(oneCoreName, CoreDescriptor.CORE_NAME, null);
-
-          if (null == rawName) {
-            throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
-                "Each core in solr.xml must have a 'name'");
-          }
-          final String name = rawName;
-          final CoreDescriptor p = new CoreDescriptor(this, name,
-              cfg.getProperty(oneCoreName, CoreDescriptor.CORE_INSTDIR, null));
-          
-          // deal with optional settings
-          String opt = cfg.getProperty(oneCoreName, CoreDescriptor.CORE_CONFIG, null);
-          
-          if (opt != null) {
-            p.setConfigName(opt);
-          }
-          opt = cfg.getProperty(oneCoreName, CoreDescriptor.CORE_SCHEMA, null);
-          if (opt != null) {
-            p.setSchemaName(opt);
-          }
-          
-          if (zkSys.getZkController() != null) {
-            opt = cfg.getProperty(oneCoreName, CoreDescriptor.CORE_SHARD, null);
-            if (opt != null && opt.length() > 0) {
-              p.getCloudDescriptor().setShardId(opt);
-            }
-            opt = cfg.getProperty(oneCoreName, CoreDescriptor.CORE_COLLECTION, null);
-            if (opt != null) {
-              p.getCloudDescriptor().setCollectionName(opt);
-            }
-            opt = cfg.getProperty(oneCoreName, CoreDescriptor.CORE_ROLES, null);
-            if (opt != null) {
-              p.getCloudDescriptor().setRoles(opt);
-            }
 
-            opt = cfg.getProperty(oneCoreName, CoreDescriptor.CORE_NODE_NAME, null);
-            if (opt != null && opt.length() > 0) {
-              p.getCloudDescriptor().setCoreNodeName(opt);
-            }
-          }
-          opt = cfg.getProperty(oneCoreName, CoreDescriptor.CORE_PROPERTIES, null);
-          if (opt != null) {
-            p.setPropertiesName(opt);
-          }
-          opt = cfg.getProperty(oneCoreName, CoreDescriptor.CORE_DATADIR, null);
-          if (opt != null) {
-            p.setDataDir(opt);
-          }
-          
-          p.setCoreProperties(cfg.readCoreProperties(oneCoreName));
-          
-          opt = cfg.getProperty(oneCoreName, CoreDescriptor.CORE_LOADONSTARTUP, null);
-          if (opt != null) {
-            p.setLoadOnStartup(("true".equalsIgnoreCase(opt) || "on"
-                .equalsIgnoreCase(opt)) ? true : false);
-          }
-          
-          opt = cfg.getProperty(oneCoreName, CoreDescriptor.CORE_TRANSIENT, null);
-          if (opt != null) {
-            p.setTransient(("true".equalsIgnoreCase(opt) || "on"
-                .equalsIgnoreCase(opt)) ? true : false);
+          if (cd.isTransient() || ! cd.isLoadOnStartup()) {
+            // Store it away for later use. includes non-transient but not
+            // loaded at startup cores.
+            solrCores.putDynamicDescriptor(name, cd);
           }
-          
-          if (p.isLoadOnStartup()) { // The normal case
+          if (cd.isLoadOnStartup()) { // The normal case
 
             Callable<SolrCore> task = new Callable<SolrCore>() {
               @Override
               public SolrCore call() {
                 SolrCore c = null;
                 try {
-                  c = create(p);
-                  registerCore(p.isTransient(), name, c, false);
+                  if (zkSys.getZkController() != null) {
+                    preRegisterInZk(cd);
+                  }
+                  c = create(cd);
+                  registerCore(cd.isTransient(), name, c, false);
                 } catch (Throwable t) {
+                  if (isZooKeeperAware()) {
+                    try {
+                      zkSys.zkController.unregister(name, cd);
+                    } catch (InterruptedException e) {
+                      Thread.currentThread().interrupt();
+                      SolrException.log(log, null, e);
+                    } catch (KeeperException e) {
+                      SolrException.log(log, null, e);
+                    }
+                  }
                   SolrException.log(log, null, t);
                   if (c != null) {
                     c.close();
@@ -436,16 +265,12 @@ public class CoreContainer
             };
             pending.add(completionService.submit(task));
 
-          } else {
-            // Store it away for later use. includes non-transient but not
-            // loaded at startup cores.
-            solrCores.putDynamicDescriptor(rawName, p);
           }
         } catch (Throwable ex) {
           SolrException.log(log, null, ex);
         }
       }
-      
+
       while (pending != null && pending.size() > 0) {
         try {
 
@@ -462,7 +287,7 @@ public class CoreContainer
           } catch (ExecutionException e) {
             SolrException.log(SolrCore.log, "Error loading core", e);
           }
-          
+
         } catch (InterruptedException e) {
           throw new SolrException(SolrException.ErrorCode.SERVICE_UNAVAILABLE,
               "interrupted while loading core", e);
@@ -479,40 +304,16 @@ public class CoreContainer
       }
     }
   }
-  
-  private ShardHandlerFactory initShardHandler(ConfigSolr configSolr) {
-    PluginInfo info = null;
-    Node shfn = configSolr.getConfig().getNode("solr/cores/shardHandlerFactory", false);
 
-    if (shfn != null) {
-      info = new PluginInfo(shfn, "shardHandlerFactory", false, true);
-    } else {
-      Map m = new HashMap();
-      m.put("class", HttpShardHandlerFactory.class.getName());
-      info = new PluginInfo("shardHandlerFactory", m, null, Collections.<PluginInfo>emptyList());
-    }
-
-    ShardHandlerFactory fac;
-    try {
-       fac = configSolr.getConfig().getResourceLoader().findClass(info.className, ShardHandlerFactory.class).newInstance();
-    } catch (Exception e) {
-      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
-                              "Error instantiating shardHandlerFactory class " + info.className);
-    }
-    if (fac instanceof PluginInfoInitialized) {
-      ((PluginInfoInitialized) fac).init(info);
-    }
-    return fac;
-  }
-
-  // To make this available to TestHarness.
-  protected void initShardHandler() {
-    if (cfg != null) {
-      initShardHandler(cfg);
-    } else {
-      // Cough! Hack! But tests run this way.
-      HttpShardHandlerFactory fac = new HttpShardHandlerFactory();
-      shardHandlerFactory = fac;
+  private static void checkForDuplicateCoreNames(List<CoreDescriptor> cds) {
+    Map<String, String> addedCores = Maps.newHashMap();
+    for (CoreDescriptor cd : cds) {
+      final String name = cd.getName();
+      if (addedCores.containsKey(name))
+        throw new SolrException(ErrorCode.SERVER_ERROR,
+            String.format(Locale.ROOT, "Found multiple cores with the name [%s], with instancedirs [%s] and [%s]",
+                name, addedCores.get(name), cd.getInstanceDir()));
+      addedCores.put(name, cd.getInstanceDir());
     }
   }
 
@@ -610,6 +411,10 @@ public class CoreContainer
     }
   }
 
+  public CoresLocator getCoresLocator() {
+    return coresLocator;
+  }
+
   protected SolrCore registerCore(boolean isTransientCore, String name, SolrCore core, boolean returnPrevNotClosed) {
     if( core == null ) {
       throw new RuntimeException( "Can not register a null core." );
@@ -619,22 +424,6 @@ public class CoreContainer
         name.indexOf( '\\' ) >= 0 ){
       throw new RuntimeException( "Invalid core name: "+name );
     }
-
-    if (zkSys.getZkController() != null) {
-      // this happens before we can receive requests
-      try {
-        zkSys.getZkController().preRegister(core);
-      } catch (KeeperException e) {
-        log.error("", e);
-        throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
-            "", e);
-      } catch (InterruptedException e) {
-        Thread.currentThread().interrupt();
-        log.error("", e);
-        throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
-            "", e);
-      }
-    }
     
     SolrCore old = null;
 
@@ -653,7 +442,6 @@ public class CoreContainer
       */
 
     core.setName(name);
-    core.getCoreDescriptor().putProperty(CoreDescriptor.CORE_NAME, name);
 
     synchronized (coreInitFailures) {
       coreInitFailures.remove(name);
@@ -692,7 +480,7 @@ public class CoreContainer
     SolrResourceLoader solrLoader = null;
 
     SolrConfig config = null;
-    solrLoader = new SolrResourceLoader(instanceDir, loader.getClassLoader(), ConfigSolrXml.getCoreProperties(instanceDir, dcore));
+    solrLoader = new SolrResourceLoader(instanceDir, loader.getClassLoader(), dcore.getCoreProperties());
     try {
       config = new SolrConfig(solrLoader, dcore.getConfigName(), null);
     } catch (Exception e) {
@@ -714,11 +502,11 @@ public class CoreContainer
             schemaFile.lastModified()));
         schema = indexSchemaCache.get(key);
         if (schema == null) {
-          log.info("creating new schema object for core: " + dcore.getProperty(CoreDescriptor.CORE_NAME));
+          log.info("creating new schema object for core: " + dcore.getName());
           schema = IndexSchemaFactory.buildIndexSchema(dcore.getSchemaName(), config);
           indexSchemaCache.put(key, schema);
         } else {
-          log.info("re-using schema object for core: " + dcore.getProperty(CoreDescriptor.CORE_NAME));
+          log.info("re-using schema object for core: " + dcore.getName());
         }
       }
     }
@@ -843,7 +631,7 @@ public class CoreContainer
     try {
       name = checkDefault(name);
 
-      SolrCore core = solrCores.getCore(name);
+      SolrCore core = solrCores.getCoreFromAnyList(name, false);
       if (core == null)
         throw new SolrException( SolrException.ErrorCode.BAD_REQUEST, "No such core: " + name );
 
@@ -857,7 +645,8 @@ public class CoreContainer
                  cd.getName(), instanceDir.getAbsolutePath());
         SolrResourceLoader solrLoader;
         if(zkSys.getZkController() == null) {
-          solrLoader = new SolrResourceLoader(instanceDir.getAbsolutePath(), loader.getClassLoader(), ConfigSolrXml.getCoreProperties(instanceDir.getAbsolutePath(), cd));
+          solrLoader = new SolrResourceLoader(instanceDir.getAbsolutePath(), loader.getClassLoader(),
+                                                cd.getCoreProperties());
         } else {
           try {
             String collection = cd.getCloudDescriptor().getCollectionName();
@@ -870,7 +659,7 @@ public class CoreContainer
                                            "Could not find config name for collection:" + collection);
             }
             solrLoader = new ZkSolrResourceLoader(instanceDir.getAbsolutePath(), zkConfigName, loader.getClassLoader(),
-                ConfigSolrXml.getCoreProperties(instanceDir.getAbsolutePath(), cd), zkSys.getZkController());
+                cd.getCoreProperties(), zkSys.getZkController());
           } catch (KeeperException e) {
             log.error("", e);
             throw new ZooKeeperException(SolrException.ErrorCode.SERVER_ERROR,
@@ -899,7 +688,7 @@ public class CoreContainer
 
   //5.0 remove all checkDefaults?
   private String checkDefault(String name) {
-    return (null == name || name.isEmpty()) ? defaultCoreName : name;
+    return (null == name || name.isEmpty()) ? getDefaultCoreName() : name;
   } 
 
   /**
@@ -913,15 +702,18 @@ public class CoreContainer
     n1 = checkDefault(n1);
     solrCores.swap(n0, n1);
 
+    coresLocator.persist(this, solrCores.getCoreDescriptor(n0), solrCores.getCoreDescriptor(n1));
+
     log.info("swapped: "+n0 + " with " + n1);
   }
   
   /** Removes and returns registered core w/o decrementing it's reference count */
   public SolrCore remove( String name ) {
-    name = checkDefault(name);    
-
-    return solrCores.remove(name, true);
-
+    name = checkDefault(name);
+    CoreDescriptor cd = solrCores.getCoreDescriptor(name);
+    SolrCore removed = solrCores.remove(name, true);
+    coresLocator.delete(this, cd);
+    return removed;
   }
 
   public void rename(String name, String toName) {
@@ -930,7 +722,8 @@ public class CoreContainer
       if (core != null) {
         registerCore(false, toName, core, false);
         name = checkDefault(name);
-        solrCores.remove(name, false);
+        SolrCore old = solrCores.remove(name, false);
+        coresLocator.rename(this, old.getCoreDescriptor(), core.getCoreDescriptor());
       }
     } finally {
       if (core != null) {
@@ -938,6 +731,24 @@ public class CoreContainer
       }
     }
   }
+
+  /**
+   * Get the CoreDescriptors for all cores managed by this container
+   * @return a List of CoreDescriptors
+   */
+  public List<CoreDescriptor> getCoreDescriptors() {
+    return solrCores.getCoreDescriptors();
+  }
+
+  public CoreDescriptor getCoreDescriptor(String coreName) {
+    // TODO make this less hideous!
+    for (CoreDescriptor cd : getCoreDescriptors()) {
+      if (cd.getName().equals(coreName))
+        return cd;
+    }
+    return null;
+  }
+
   /** 
    * Gets a core by name and increase its refcount.
    *
@@ -951,10 +762,9 @@ public class CoreContainer
     name = checkDefault(name);
 
     // Do this in two phases since we don't want to lock access to the cores over a load.
-    SolrCore core = solrCores.getCoreFromAnyList(name);
+    SolrCore core = solrCores.getCoreFromAnyList(name, true);
 
     if (core != null) {
-      core.open();
       return core;
     }
 
@@ -981,6 +791,9 @@ public class CoreContainer
                                  // the wait as a consequence of shutting down.
     try {
       if (core == null) {
+        if (zkSys.getZkController() != null) {
+          preRegisterInZk(desc);
+        }
         core = create(desc); // This should throw an error if it fails.
         core.open();
         registerCore(desc.isTransient(), name, core, false);
@@ -988,6 +801,19 @@ public class CoreContainer
         core.open();
       }
     } catch(Exception ex){
+      // remains to be seen how transient cores and such
+      // will work in SolrCloud mode, but just to be future 
+      // proof...
+      if (isZooKeeperAware()) {
+        try {
+          getZkController().unregister(name, desc);
+        } catch (InterruptedException e) {
+          Thread.currentThread().interrupt();
+          SolrException.log(log, null, e);
+        } catch (KeeperException e) {
+          SolrException.log(log, null, e);
+        }
+      }
       throw recordAndThrow(name, "Unable to create core: " + name, ex);
     } finally {
       solrCores.removeFromPendingOps(name);
@@ -1013,54 +839,42 @@ public class CoreContainer
     return collectionsHandler;
   }
   
+  public InfoHandler getInfoHandler() {
+    return infoHandler;
+  }
+  
   /**
    * the default core name, or null if there is no default core name
    */
   public String getDefaultCoreName() {
-    return defaultCoreName;
+    return cfg.getDefaultCoreName();
   }
   
   // all of the following properties aren't synchronized
   // but this should be OK since they normally won't be changed rapidly
   @Deprecated
   public boolean isPersistent() {
-    return persistent;
-  }
-  
-  @Deprecated
-  public void setPersistent(boolean persistent) {
-    this.persistent = persistent;
+    return cfg.isPersistent();
   }
   
   public String getAdminPath() {
-    return adminPath;
+    return cfg.getAdminPath();
   }
 
-  public String getManagementPath() {
-    return managementPath;
-  }
-  
   /**
-   * Sets the alternate path for multicore handling:
+   * Gets the alternate path for multicore handling:
    * This is used in case there is a registered unnamed core (aka name is "") to
    * declare an alternate way of accessing named cores.
    * This can also be used in a pseudo single-core environment so admins can prepare
    * a new version before swapping.
    */
-  public void setManagementPath(String path) {
-    this.managementPath = path;
+  public String getManagementPath() {
+    return cfg.getManagementPath();
   }
-  
+
   public LogWatcher getLogging() {
     return logging;
   }
-  public void setLogging(LogWatcher v) {
-    logging = v;
-  }
-  
-  public File getConfigFile() {
-    return configFile;
-  }
 
   /**
    * Determines whether the core is already loaded or not but does NOT load the core
@@ -1070,12 +884,6 @@ public class CoreContainer
     return solrCores.isLoaded(name);
   }
 
-  /** Persists the cores config file in cores.xml. */
-  @Deprecated
-  public void persist() {
-    persistFile(configFile);
-  }
-
   /**
    * Gets a solr core descriptor for a core that is not loaded. Note that if the caller calls this on a
    * loaded core, the unloaded descriptor will be returned.
@@ -1087,86 +895,14 @@ public class CoreContainer
     return solrCores.getUnloadedCoreDescriptor(cname);
   }
 
-  /** Persists the cores config file in a user provided file. */
-  @Deprecated
-  public void persistFile(File file) {
-    assert file != null;
-    // only the old solrxml persists
-    if (cfg != null && !(cfg instanceof ConfigSolrXmlOld)) return;
-
-    log.info("Persisting cores config to " + (file == null ? configFile : file));
-
-    
-    // <solr attrib="value">
-    Map<String,String> rootSolrAttribs = new HashMap<String,String>();
-    if (libDir != null) rootSolrAttribs.put("sharedLib", libDir);
-    rootSolrAttribs.put("persistent", Boolean.toString(isPersistent()));
-    
-    // <solr attrib="value"> <cores attrib="value">
-    Map<String,String> coresAttribs = new HashMap<String,String>();
-    addCoresAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_ADMINPATH, "adminPath", this.adminPath, null);
-    addCoresAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_ADMINHANDLER, "adminHandler", this.adminHandler, null);
-    addCoresAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_SHARESCHEMA,"shareSchema",
-        Boolean.toString(this.shareSchema),
-        Boolean.toString(DEFAULT_SHARE_SCHEMA));
-    addCoresAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_HOST, "host", zkSys.getHost(), null);
-
-    if (! (null == defaultCoreName || defaultCoreName.equals("")) ) {
-      coresAttribs.put("defaultCoreName", defaultCoreName);
-    }
-
-    addCoresAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_HOSTPORT, "hostPort",zkSys.getHostPort(), null);
-    addCoresAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_ZKCLIENTTIMEOUT, "zkClientTimeout",
-        intToString(this.zkClientTimeout),
-        Integer.toString(DEFAULT_ZK_CLIENT_TIMEOUT));
-    addCoresAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_HOSTCONTEXT, "hostContext",
-        zkSys.getHostContext(), null);
-    addCoresAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_LEADERVOTEWAIT, "leaderVoteWait",
-        zkSys.getLeaderVoteWait(), LEADER_VOTE_WAIT);
-    addCoresAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_CORELOADTHREADS, "coreLoadThreads",
-        Integer.toString(this.coreLoadThreads), Integer.toString(CORE_LOAD_THREADS));
-    if (transientCacheSize != Integer.MAX_VALUE) { // This test
-    // is a consequence of testing. I really hate it.
-      addCoresAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_TRANSIENTCACHESIZE, "transientCacheSize",
-          Integer.toString(this.transientCacheSize), Integer.toString(Integer.MAX_VALUE));
-    }
-
-    try {
-      solrCores.persistCores(origCfg, containerProperties, rootSolrAttribs, coresAttribs, file, configFile, loader);
-    } catch (XPathExpressionException e) {
-      throw new SolrException(ErrorCode.SERVER_ERROR, null, e);
-    }
-
-  }
-  private String intToString(Integer integer) {
-    if (integer == null) return null;
-    return Integer.toString(integer);
-  }
-
-  private void addCoresAttrib(Map<String,String> coresAttribs, ConfigSolr.CfgProp prop,
-                              String attribName, String attribValue, String defaultValue) {
-    if (cfg == null) {
-      coresAttribs.put(attribName, attribValue);
-      return;
-    }
-    
-    if (attribValue != null) {
-      String origValue = cfg.getOrigProp(prop, null);
-      
-      if (origValue == null && defaultValue != null && attribValue.equals(defaultValue)) return;
-
-      if (attribValue.equals(PropertiesUtil.substituteProperty(origValue, loader.getCoreProperties()))) {
-        coresAttribs.put(attribName, origValue);
-      } else {
-        coresAttribs.put(attribName, attribValue);
-      }
-    }
+  public void preRegisterInZk(final CoreDescriptor p) {
+    zkSys.getZkController().preRegister(p);
   }
 
   public String getSolrHome() {
     return solrHome;
   }
-  
+
   public boolean isZooKeeperAware() {
     return zkSys.getZkController() != null;
   }
@@ -1198,14 +934,7 @@ public class CoreContainer
     return solrCores.getCoreToOrigName(core);
   }
   
-  private Document copyDoc(Document document) throws TransformerException {
-    TransformerFactory tfactory = TransformerFactory.newInstance();
-    Transformer tx   = tfactory.newTransformer();
-    DOMSource source = new DOMSource(document);
-    DOMResult result = new DOMResult();
-    tx.transform(source,result);
-    return (Document)result.getNode();
-  }
+
 }
 
 class CloserThread extends Thread {

Modified: lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/CoreDescriptor.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/CoreDescriptor.java?rev=1512909&r1=1512908&r2=1512909&view=diff
==============================================================================
--- lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/CoreDescriptor.java (original)
+++ lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/CoreDescriptor.java Sun Aug 11 12:19:13 2013
@@ -17,12 +17,22 @@
 
 package org.apache.solr.core;
 
-import java.util.Properties;
-import java.io.File;
-
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
 import org.apache.commons.lang.StringUtils;
 import org.apache.solr.cloud.CloudDescriptor;
-import org.apache.solr.core.ConfigSolr.CfgProp;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.util.IOUtils;
+import org.apache.solr.util.PropertiesUtil;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.Locale;
+import java.util.Properties;
+
+import static com.google.common.base.Preconditions.checkNotNull;
 
 /**
  * A Solr core descriptor
@@ -34,7 +44,8 @@ public class CoreDescriptor {
   // Properties file name constants
   public static final String CORE_NAME = "name";
   public static final String CORE_CONFIG = "config";
-  public static final String CORE_INSTDIR = "instanceDir"; // should probably be removed after 4x
+  public static final String CORE_INSTDIR = "instanceDir";
+  public static final String CORE_ABS_INSTDIR = "absoluteInstDir";
   public static final String CORE_DATADIR = "dataDir";
   public static final String CORE_ULOGDIR = "ulogDir";
   public static final String CORE_SCHEMA = "schema";
@@ -46,150 +57,210 @@ public class CoreDescriptor {
   public static final String CORE_TRANSIENT = "transient";
   public static final String CORE_NODE_NAME = "coreNodeName";
 
-  static final String[] standardPropNames = {
+  public static final String DEFAULT_EXTERNAL_PROPERTIES_FILE = "conf" + File.separator + "solrcore.properties";
+
+  /**
+   * Get the standard properties in persistable form
+   * @return the standard core properties in persistable form
+   */
+  public Properties getPersistableStandardProperties() {
+    return originalCoreProperties;
+  }
+
+  /**
+   * Get user-defined core properties in persistable form
+   * @return user-defined core properties in persistable form
+   */
+  public Properties getPersistableUserProperties() {
+    return originalExtraProperties;
+  }
+
+  private static ImmutableMap<String, String> defaultProperties = ImmutableMap.of(
+      CORE_CONFIG, "solrconfig.xml",
+      CORE_SCHEMA, "schema.xml",
+      CORE_DATADIR, "data" + File.separator,
+      CORE_TRANSIENT, "false",
+      CORE_LOADONSTARTUP, "true"
+  );
+
+  private static ImmutableList<String> requiredProperties = ImmutableList.of(
+      CORE_NAME, CORE_INSTDIR, CORE_ABS_INSTDIR
+  );
+
+  public static ImmutableList<String> standardPropNames = ImmutableList.of(
       CORE_NAME,
       CORE_CONFIG,
       CORE_INSTDIR,
       CORE_DATADIR,
       CORE_ULOGDIR,
       CORE_SCHEMA,
+      CORE_PROPERTIES,
+      CORE_LOADONSTARTUP,
+      CORE_TRANSIENT,
+      // cloud props
       CORE_SHARD,
       CORE_COLLECTION,
       CORE_ROLES,
-      CORE_PROPERTIES,
-      CORE_LOADONSTARTUP,
-      CORE_TRANSIENT
-  };
-
-  // As part of moving away from solr.xml (see SOLR-4196), it's _much_ easier to keep these as properties than set
-  // them individually.
-  private Properties coreProperties = new Properties();
-
-  private boolean loadedImplicit = false;
+      CORE_NODE_NAME,
+      CloudDescriptor.NUM_SHARDS,
+      CloudDescriptor.SHARD_STATE
+  );
 
   private final CoreContainer coreContainer;
 
-  private CloudDescriptor cloudDesc;
-
-  private CoreDescriptor(CoreContainer cont) {
-    // Just a place to put initialization since it's a pain to add to the descriptor in every c'tor.
-    this.coreContainer = cont;
-    coreProperties.put(CORE_LOADONSTARTUP, "true");
-    coreProperties.put(CORE_TRANSIENT, "false");
+  private final CloudDescriptor cloudDesc;
 
-  }
-  
-  public CoreDescriptor(CoreContainer container, String name, String instanceDir) {
-    this(container);
-    doInit(name, instanceDir);
-  }
+  /** The original standard core properties, before substitution */
+  protected final Properties originalCoreProperties = new Properties();
 
+  /** The original extra core properties, before substitution */
+  protected final Properties originalExtraProperties = new Properties();
 
-  public CoreDescriptor(CoreDescriptor descr) {
-    this(descr.coreContainer);
-    coreProperties.put(CORE_INSTDIR, descr.getInstanceDir());
-    coreProperties.put(CORE_CONFIG, descr.getConfigName());
-    coreProperties.put(CORE_SCHEMA, descr.getSchemaName());
-    coreProperties.put(CORE_NAME, descr.getName());
-    coreProperties.put(CORE_DATADIR, descr.getDataDir());
-  }
+  /** The properties for this core, as available through getProperty() */
+  protected final Properties coreProperties = new Properties();
 
   /**
-   * CoreDescriptor - create a core descriptor given default properties from a core.properties file. This will be
-   * used in the "solr.xml-less (See SOLR-4196) world where there are no &lt;core&gt; &lt;/core&gt; tags at all, thus  much
-   * of the initialization that used to be done when reading solr.xml needs to be done here instead, particularly
-   * setting any defaults (e.g. schema.xml, directories, whatever).
-   *
-   * @param container - the CoreContainer that holds all the information about our cores, loaded, lazy etc.
-   * @param propsIn - A properties structure "core.properties" found while walking the file tree to discover cores.
-   *                  Any properties set in this param will overwrite the any defaults.
+   * Create a new CoreDescriptor.
+   * @param container       the CoreDescriptor's container
+   * @param name            the CoreDescriptor's name
+   * @param instanceDir     a String containing the instanceDir
+   * @param coreProps       a Properties object of the properties for this core
    */
-  public CoreDescriptor(CoreContainer container, Properties propsIn) {
-    this(container);
+  public CoreDescriptor(CoreContainer container, String name, String instanceDir,
+                        Properties coreProps) {
 
-    // Set some default, normalize a directory or two
-    doInit(propsIn.getProperty(CORE_NAME), propsIn.getProperty(CORE_INSTDIR));
+    this.coreContainer = container;
 
-    coreProperties.putAll(propsIn);
-  }
+    originalCoreProperties.setProperty(CORE_NAME, name);
+    originalCoreProperties.setProperty(CORE_INSTDIR, instanceDir);
 
-  private void doInit(String name, String instanceDir) {
-    if (name == null) {
-      throw new RuntimeException("Core needs a name");
-    }
+    Properties containerProperties = container.getContainerProperties();
+    name = PropertiesUtil.substituteProperty(checkPropertyIsNotEmpty(name, CORE_NAME),
+                                             containerProperties);
+    instanceDir = PropertiesUtil.substituteProperty(checkPropertyIsNotEmpty(instanceDir, CORE_INSTDIR),
+                                                    containerProperties);
 
+    coreProperties.putAll(defaultProperties);
     coreProperties.put(CORE_NAME, name);
+    coreProperties.put(CORE_INSTDIR, instanceDir);
+    coreProperties.put(CORE_ABS_INSTDIR, convertToAbsolute(instanceDir, container.getSolrHome()));
+
+    for (String propname : coreProps.stringPropertyNames()) {
+
+      String propvalue = coreProps.getProperty(propname);
 
-    if(coreContainer != null && coreContainer.getZkController() != null) {
-      this.cloudDesc = new CloudDescriptor();
-      // cloud collection defaults to core name
-      cloudDesc.setCollectionName(name);
+      if (isUserDefinedProperty(propname))
+        originalExtraProperties.put(propname, propvalue);
+      else
+        originalCoreProperties.put(propname, propvalue);
+
+      if (!requiredProperties.contains(propname))   // Required props are already dealt with
+        coreProperties.setProperty(propname,
+            PropertiesUtil.substituteProperty(propvalue, containerProperties));
     }
 
-    if (instanceDir == null) {
-      throw new NullPointerException("Missing required \'instanceDir\'");
+    loadExtraProperties();
+
+    // TODO maybe make this a CloudCoreDescriptor subclass?
+    if (container.isZooKeeperAware()) {
+      cloudDesc = new CloudDescriptor(name, coreProperties);
+    }
+    else {
+      cloudDesc = null;
     }
-    instanceDir = SolrResourceLoader.normalizeDir(instanceDir);
-    coreProperties.put(CORE_INSTDIR, instanceDir);
-    coreProperties.put(CORE_CONFIG, getDefaultConfigName());
-    coreProperties.put(CORE_SCHEMA, getDefaultSchemaName());
   }
 
-  public Properties initImplicitProperties() {
-
-    Properties implicitProperties = new Properties();
-    if (coreContainer != null && coreContainer.getContainerProperties() != null){
-      implicitProperties.putAll(coreContainer.getContainerProperties());
+  /**
+   * Load properties specified in an external properties file.
+   *
+   * The file to load can be specified in a {@code properties} property on
+   * the original Properties object used to create this CoreDescriptor.  If
+   * this has not been set, then we look for {@code conf/solrcore.properties}
+   * underneath the instance dir.
+   *
+   * File paths are taken as read from the core's instance directory
+   * if they are not absolute.
+   */
+  protected void loadExtraProperties() {
+    String filename = coreProperties.getProperty(CORE_PROPERTIES, DEFAULT_EXTERNAL_PROPERTIES_FILE);
+    File propertiesFile = resolvePaths(filename);
+    if (propertiesFile.exists()) {
+      FileInputStream in = null;
+      try {
+        in = new FileInputStream(propertiesFile);
+        Properties externalProps = new Properties();
+        externalProps.load(new InputStreamReader(in, "UTF-8"));
+        coreProperties.putAll(externalProps);
+      } catch (IOException e) {
+        String message = String.format(Locale.ROOT, "Could not load properties from %s: %s:",
+            propertiesFile.getAbsoluteFile(), e.toString());
+        throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, message);
+      } finally {
+        IOUtils.closeQuietly(in);
+      }
     }
-    implicitProperties.setProperty("solr.core.name", getName());
-    implicitProperties.setProperty("solr.core.instanceDir", getInstanceDir());
-    implicitProperties.setProperty("solr.core.dataDir", getDataDir());
-    implicitProperties.setProperty("solr.core.configName", getConfigName());
-    implicitProperties.setProperty("solr.core.schemaName", getSchemaName());
-    return implicitProperties;
   }
 
-  /**@return the default config name. */
-  public String getDefaultConfigName() {
-    return "solrconfig.xml";
+  protected File resolvePaths(String filepath) {
+    File file = new File(filepath);
+    if (file.isAbsolute())
+      return file;
+    return new File(getInstanceDir(), filepath);
   }
 
-  /**@return the default schema name. */
-  public String getDefaultSchemaName() {
-    return "schema.xml";
+  /**
+   * Is this property a Solr-standard property, or is it an extra property
+   * defined per-core by the user?
+   * @param propName the Property name
+   * @return @{code true} if this property is user-defined
+   */
+  protected static boolean isUserDefinedProperty(String propName) {
+    return !standardPropNames.contains(propName);
   }
 
-  /**@return the default data directory. */
-  public String getDefaultDataDir() {
-    return "data" + File.separator;
+  public static String checkPropertyIsNotEmpty(String value, String propName) {
+    if (StringUtils.isEmpty(value)) {
+      String message = String.format(Locale.ROOT, "Cannot create core with empty %s value", propName);
+      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, message);
+    }
+    return value;
   }
 
-  public String getPropertiesName() {
-    return coreProperties.getProperty(CORE_PROPERTIES);
+  /**
+   * Create a new CoreDescriptor with a given name and instancedir
+   * @param container     the CoreDescriptor's container
+   * @param name          the CoreDescriptor's name
+   * @param instanceDir   the CoreDescriptor's instancedir
+   */
+  public CoreDescriptor(CoreContainer container, String name, String instanceDir) {
+    this(container, name, instanceDir, new Properties());
   }
 
-  public void setPropertiesName(String propertiesName) {
-    coreProperties.put(CORE_PROPERTIES, propertiesName);
+  /**
+   * Create a new CoreDescriptor using the properties of an existing one
+   * @param coreName the new CoreDescriptor's name
+   * @param other    the CoreDescriptor to copy
+   */
+  public CoreDescriptor(String coreName, CoreDescriptor other) {
+    this.coreContainer = other.coreContainer;
+    this.originalExtraProperties.putAll(other.originalExtraProperties);
+    this.originalCoreProperties.putAll(other.originalCoreProperties);
+    this.coreProperties.putAll(other.coreProperties);
+    this.coreProperties.setProperty(CORE_NAME, coreName);
+    this.originalCoreProperties.setProperty(CORE_NAME, coreName);
+    this.cloudDesc = other.cloudDesc;
   }
 
-  public String getDataDir() {
-    String dataDir = coreProperties.getProperty(CORE_DATADIR);
-    if (dataDir == null) dataDir = getDefaultDataDir();
-    return dataDir;
+  public String getPropertiesName() {
+    return coreProperties.getProperty(CORE_PROPERTIES);
   }
 
-  public void setDataDir(String s) {
-    // normalize zero length to null.
-    if (StringUtils.isBlank(s)) {
-      coreProperties.remove(s);
-    } else {
-      coreProperties.put(CORE_DATADIR, s);
-    }
+  public String getDataDir() {
+    return coreProperties.getProperty(CORE_DATADIR);
   }
   
   public boolean usingDefaultDataDir() {
-    // DO NOT use the getDataDir method here since it'll assign something regardless.
-    return coreProperties.getProperty(CORE_DATADIR) == null;
+    return defaultProperties.get(CORE_DATADIR).equals(coreProperties.getProperty(CORE_DATADIR));
   }
 
   /**@return the core instance directory. */
@@ -197,37 +268,20 @@ public class CoreDescriptor {
     return coreProperties.getProperty(CORE_INSTDIR);
   }
 
+  private static String convertToAbsolute(String instDir, String solrHome) {
+    checkNotNull(instDir);
+    File f = new File(instDir);
+    if (f.isAbsolute())
+      return SolrResourceLoader.normalizeDir(instDir);
+    return SolrResourceLoader.normalizeDir(solrHome + SolrResourceLoader.normalizeDir(instDir));
+  }
+
   /**
    *
    * @return the core instance directory, prepended with solr_home if not an absolute path.
    */
   public String getInstanceDir() {
-    String instDir = coreProperties.getProperty(CORE_INSTDIR);
-    if (instDir == null) return null;
-
-    if (new File(instDir).isAbsolute()) {
-      return SolrResourceLoader.normalizeDir(
-          SolrResourceLoader.normalizeDir(instDir));
-    }
-
-    if (coreContainer == null) return null;
-    if( coreContainer.cfg != null) {
-      String coreRootDir = coreContainer.cfg.get(
-          CfgProp.SOLR_COREROOTDIRECTORY, null);
-      if (coreRootDir != null) {
-        return SolrResourceLoader.normalizeDir(coreRootDir
-            + SolrResourceLoader.normalizeDir(instDir));
-      }
-    }
-    return SolrResourceLoader.normalizeDir(coreContainer.getSolrHome() +
-        SolrResourceLoader.normalizeDir(instDir));
-  }
-
-  /**Sets the core configuration resource name. */
-  public void setConfigName(String name) {
-    if (name == null || name.length() == 0)
-      throw new IllegalArgumentException("name can not be null or empty");
-    coreProperties.put(CORE_CONFIG, name);
+    return coreProperties.getProperty(CORE_ABS_INSTDIR);
   }
 
   /**@return the core configuration resource name. */
@@ -235,13 +289,6 @@ public class CoreDescriptor {
     return coreProperties.getProperty(CORE_CONFIG);
   }
 
-  /**Sets the core schema resource name. */
-  public void setSchemaName(String name) {
-    if (name == null || name.length() == 0)
-      throw new IllegalArgumentException("name can not be null or empty");
-    coreProperties.put(CORE_SCHEMA, name);
-  }
-
   /**@return the core schema resource name. */
   public String getSchemaName() {
     return coreProperties.getProperty(CORE_SCHEMA);
@@ -252,95 +299,57 @@ public class CoreDescriptor {
     return coreProperties.getProperty(CORE_NAME);
   }
 
-  public CoreContainer getCoreContainer() {
-    return coreContainer;
+  public String getCollectionName() {
+    return cloudDesc == null ? null : cloudDesc.getCollectionName();
   }
 
-  Properties getCoreProperties() {
-    return coreProperties;
-  }
-
-  /**
-   * Set this core's properties. Please note that some implicit values will be added to the
-   * Properties instance passed into this method. This means that the Properties instance
-   * sent to this method will have different (less) key/value pairs than the Properties
-   * instance returned by #getCoreProperties method.
-   *
-   * Under any circumstance, the properties passed in will override any already present.Merge
-   */
-  public void setCoreProperties(Properties coreProperties) {
-    if (! loadedImplicit) {
-      loadedImplicit = true;
-      Properties p = initImplicitProperties();
-      this.coreProperties.putAll(p);
-      // The caller presumably wants whatever properties passed in to override the current core props, so just add them.
-      if (coreProperties != null) {
-        this.coreProperties.putAll(coreProperties);
-      }
-    }
+  public CoreContainer getCoreContainer() {
+    return coreContainer;
   }
 
   public CloudDescriptor getCloudDescriptor() {
     return cloudDesc;
   }
-  
-  public void setCloudDescriptor(CloudDescriptor cloudDesc) {
-    this.cloudDesc = cloudDesc;
-  }
+
   public boolean isLoadOnStartup() {
     String tmp = coreProperties.getProperty(CORE_LOADONSTARTUP, "false");
     return Boolean.parseBoolean(tmp);
   }
 
-  public void setLoadOnStartup(boolean loadOnStartup) {
-    coreProperties.put(CORE_LOADONSTARTUP, Boolean.toString(loadOnStartup));
-  }
-
   public boolean isTransient() {
     String tmp = coreProperties.getProperty(CORE_TRANSIENT, "false");
-    return (Boolean.parseBoolean(tmp));
-  }
-
-  public void setTransient(boolean isTransient) {
-    coreProperties.put(CORE_TRANSIENT, Boolean.toString(isTransient));
+    return PropertiesUtil.toBoolean(tmp);
   }
 
   public String getUlogDir() {
     return coreProperties.getProperty(CORE_ULOGDIR);
   }
 
-  public void setUlogDir(String ulogDir) {
-    coreProperties.put(CORE_ULOGDIR, ulogDir);
-  }
-
   /**
-   * Reads a property defined in the core.properties file that's replacing solr.xml (if present).
+   * Returns a specific property defined on this CoreDescriptor
    * @param prop    - value to read from the properties structure.
    * @param defVal  - return if no property found.
    * @return associated string. May be null.
    */
-  public String getProperty(String prop, String defVal) {
+  public String getCoreProperty(String prop, String defVal) {
     return coreProperties.getProperty(prop, defVal);
   }
 
   /**
-   * gReads a property defined in the core.properties file that's replacing solr.xml (if present).
-   * @param prop  value to read from the properties structure.
-   * @return associated string. May be null.
+   * Returns all properties defined on this CoreDescriptor
+   * @return all properties defined on this CoreDescriptor
    */
-  public String getProperty(String prop) {
-    return coreProperties.getProperty(prop);
+  public Properties getCoreProperties() {
+    return coreProperties;
   }
-  /**
-   * This will eventually replace _all_ of the setters. Puts a value in the "new" (obsoleting solr.xml JIRAs) properties
-   * structures.
-   *
-   * Will replace any currently-existing property with the key "prop".
-   *
-   * @param prop - property name
-   * @param val  - property value
-   */
-  public void putProperty(String prop, String val) {
-    coreProperties.put(prop, val);
+
+  @Override
+  public String toString() {
+    return new StringBuilder("CoreDescriptor[name=")
+        .append(this.getName())
+        .append(";instanceDir=")
+        .append(this.getInstanceDir())
+        .append("]")
+        .toString();
   }
 }

Modified: lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java?rev=1512909&r1=1512908&r2=1512909&view=diff
==============================================================================
--- lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java (original)
+++ lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java Sun Aug 11 12:19:13 2013
@@ -167,7 +167,6 @@ public abstract class DirectoryFactory i
    */
   public abstract void release(Directory directory) throws IOException;
   
-  
   /**
    * Normalize a given path.
    * 
@@ -229,5 +228,21 @@ public abstract class DirectoryFactory i
     }
     return isSuccess;
   }
-  
+
+  /**
+   * If your implementation can count on delete-on-last-close semantics
+   * or throws an exception when trying to remove a file in use, return
+   * false (eg NFS). Otherwise, return true. Defaults to returning false.
+   * 
+   * @return true if factory impl requires that Searcher's explicitly
+   * reserve commit points.
+   */
+  public boolean searchersReserveCommitPoints() {
+    return false;
+  }
+
+  public String getDataHome(CoreDescriptor cd) throws IOException {
+    // by default, we go off the instance directory
+    return normalize(SolrResourceLoader.normalizeDir(cd.getInstanceDir()) + cd.getDataDir());
+  }
 }

Modified: lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/EphemeralDirectoryFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/EphemeralDirectoryFactory.java?rev=1512909&r1=1512908&r2=1512909&view=diff
==============================================================================
--- lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/EphemeralDirectoryFactory.java (original)
+++ lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/EphemeralDirectoryFactory.java Sun Aug 11 12:19:13 2013
@@ -51,4 +51,16 @@ public abstract class EphemeralDirectory
   public boolean isAbsolute(String path) {
     return true;
   }
+  
+  
+  @Override
+  public void remove(Directory dir) throws IOException {
+    // ram dir does not persist its dir anywhere
+  }
+  
+  @Override
+  public void remove(String path) throws IOException {
+    // ram dir does not persist its dir anywhere
+  }
+
 }

Modified: lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/IndexDeletionPolicyWrapper.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/IndexDeletionPolicyWrapper.java?rev=1512909&r1=1512908&r2=1512909&view=diff
==============================================================================
--- lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/IndexDeletionPolicyWrapper.java (original)
+++ lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/IndexDeletionPolicyWrapper.java Sun Aug 11 12:19:13 2013
@@ -100,7 +100,7 @@ public final class IndexDeletionPolicyWr
     }
   }
 
-  private List<IndexCommitWrapper> wrap(List<IndexCommit> list) {
+  private List<IndexCommitWrapper> wrap(List<? extends IndexCommit> list) {
     List<IndexCommitWrapper> result = new ArrayList<IndexCommitWrapper>();
     for (IndexCommit indexCommit : list) result.add(new IndexCommitWrapper(indexCommit));
     return result;
@@ -130,7 +130,7 @@ public final class IndexDeletionPolicyWr
    * Internal use for Lucene... do not explicitly call.
    */
   @Override
-  public void onInit(List list) throws IOException {
+  public void onInit(List<? extends IndexCommit> list) throws IOException {
     List<IndexCommitWrapper> wrapperList = wrap(list);
     deletionPolicy.onInit(wrapperList);
     updateCommitPoints(wrapperList);
@@ -141,7 +141,7 @@ public final class IndexDeletionPolicyWr
    * Internal use for Lucene... do not explicitly call.
    */
   @Override
-  public void onCommit(List list) throws IOException {
+  public void onCommit(List<? extends IndexCommit> list) throws IOException {
     List<IndexCommitWrapper> wrapperList = wrap(list);
     deletionPolicy.onCommit(wrapperList);
     updateCommitPoints(wrapperList);

Modified: lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/IndexReaderFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/IndexReaderFactory.java?rev=1512909&r1=1512908&r2=1512909&view=diff
==============================================================================
--- lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/IndexReaderFactory.java (original)
+++ lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/IndexReaderFactory.java Sun Aug 11 12:19:13 2013
@@ -27,12 +27,8 @@ import org.apache.solr.util.plugin.Named
  * Factory used to build a new IndexReader instance.
  */
 public abstract class IndexReaderFactory implements NamedListInitializedPlugin {
-  protected int termInfosIndexDivisor = 1;//IndexReader.DEFAULT_TERMS_INDEX_DIVISOR;  Set this once Lucene makes this public.
   /**
-   * Potentially initializes {@link #termInfosIndexDivisor}.  Overriding classes should call super.init() in order
-   * to make sure termInfosIndexDivisor is set.
-   * <p>
-   * <code>init</code> will be called just once, immediately after creation.
+   * init will be called just once, immediately after creation.
    * <p>
    * The args are user-level initialization parameters that may be specified
    * when declaring an indexReaderFactory in solrconfig.xml
@@ -40,18 +36,10 @@ public abstract class IndexReaderFactory
    */
   @Override
   public void init(NamedList args) {
-    Integer v = (Integer)args.get("setTermIndexDivisor");
-    if (v != null) {
-      termInfosIndexDivisor = v.intValue();
-    }
-  }
-
-  /**
-   *
-   * @return The setting of {@link #termInfosIndexDivisor} 
-   */
-  public int getTermInfosIndexDivisor() {
-    return termInfosIndexDivisor;
+   Object v = args.get("setTermIndexDivisor");
+   if (v != null) {
+     throw new IllegalArgumentException("Illegal parameter 'setTermIndexDivisor'");
+   }
   }
 
   /**

Modified: lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/JmxMonitoredMap.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/JmxMonitoredMap.java?rev=1512909&r1=1512908&r2=1512909&view=diff
==============================================================================
--- lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/JmxMonitoredMap.java (original)
+++ lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/JmxMonitoredMap.java Sun Aug 11 12:19:13 2013
@@ -190,6 +190,11 @@ public class JmxMonitoredMap<K, V> exten
     return ObjectName.getInstance(jmxRootName, map);
   }
 
+  /** For test verification */
+  public MBeanServer getServer() {
+    return server;
+  }
+
   /**
    * DynamicMBean is used to dynamically expose all SolrInfoMBean
    * getStatistics() NameList keys as String getters.
@@ -210,7 +215,6 @@ public class JmxMonitoredMap<K, V> exten
       staticStats.add("version");
       staticStats.add("description");
       staticStats.add("category");
-      staticStats.add("sourceId");
       staticStats.add("source");
       this.coreHashCode = coreHashCode;
     }

Modified: lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/RequestHandlers.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/RequestHandlers.java?rev=1512909&r1=1512908&r2=1512909&view=diff
==============================================================================
--- lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/RequestHandlers.java (original)
+++ lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/RequestHandlers.java Sun Aug 11 12:19:13 2013
@@ -79,11 +79,10 @@ public final class RequestHandlers {
   /**
    * @return a Map of all registered handlers of the specified type.
    */
-  public Map<String,SolrRequestHandler> getAll(Class clazz) {
-    Map<String,SolrRequestHandler> result 
-      = new HashMap<String,SolrRequestHandler>(7);
+  public <T extends SolrRequestHandler> Map<String,T> getAll(Class<T> clazz) {
+    Map<String,T> result = new HashMap<String,T>(7);
     for (Map.Entry<String,SolrRequestHandler> e : handlers.entrySet()) {
-      if(clazz.isInstance(e.getValue())) result.put(e.getKey(), e.getValue());
+      if(clazz.isInstance(e.getValue())) result.put(e.getKey(), clazz.cast(e.getValue()));
     }
     return result;
   }

Modified: lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/SolrConfig.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/SolrConfig.java?rev=1512909&r1=1512908&r2=1512909&view=diff
==============================================================================
--- lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/SolrConfig.java (original)
+++ lucene/dev/branches/lucene4956/solr/core/src/java/org/apache/solr/core/SolrConfig.java Sun Aug 11 12:19:13 2013
@@ -124,8 +124,8 @@ public class SolrConfig extends Config {
 
     // Old indexDefaults and mainIndex sections are deprecated and fails fast for luceneMatchVersion=>LUCENE_40.
     // For older solrconfig.xml's we allow the old sections, but never mixed with the new <indexConfig>
-    boolean hasDeprecatedIndexConfig = get("indexDefaults/text()", null) != null || get("mainIndex/text()", null) != null;
-    boolean hasNewIndexConfig = get("indexConfig/text()", null) != null; 
+    boolean hasDeprecatedIndexConfig = (getNode("indexDefaults", false) != null) || (getNode("mainIndex", false) != null);
+    boolean hasNewIndexConfig = getNode("indexConfig", false) != null; 
     if(hasDeprecatedIndexConfig){
       if(luceneMatchVersion.onOrAfter(Version.LUCENE_40)) {
         throw new SolrException(ErrorCode.FORBIDDEN, "<indexDefaults> and <mainIndex> configuration sections are discontinued. Use <indexConfig> instead.");