You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by ja...@apache.org on 2013/07/04 01:26:45 UTC

svn commit: r1499601 [13/20] - in /lucene/dev/branches/security: ./ dev-tools/ dev-tools/eclipse/ dev-tools/idea/.idea/libraries/ dev-tools/idea/solr/core/src/test/ dev-tools/maven/ dev-tools/maven/lucene/ dev-tools/maven/lucene/analysis/stempel/ dev-t...

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/CoreContainer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/CoreContainer.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/CoreContainer.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/CoreContainer.java Wed Jul  3 23:26:32 2013
@@ -17,7 +17,6 @@
 
 package org.apache.solr.core;
 
-import org.apache.commons.io.IOUtils;
 import org.apache.solr.cloud.ZkController;
 import org.apache.solr.cloud.ZkSolrResourceLoader;
 import org.apache.solr.common.SolrException;
@@ -39,21 +38,10 @@ import org.apache.solr.util.plugin.Plugi
 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;
@@ -76,6 +64,8 @@ import java.util.concurrent.LinkedBlocki
 import java.util.concurrent.ThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
+import static com.google.common.base.Preconditions.checkNotNull;
+
 
 /**
  *
@@ -104,16 +94,16 @@ public class CoreContainer
 
   protected CoreAdminHandler coreAdminHandler = null;
   protected CollectionsHandler collectionsHandler = null;
-  protected File configFile = null;
   protected String libDir = null;
-  protected SolrResourceLoader loader = null;
+
   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 int distribUpdateConnTimeout = 0;
+  protected int distribUpdateSoTimeout = 0;
 
   protected ZkContainer zkSys = new ZkContainer();
 
@@ -124,151 +114,90 @@ public class CoreContainer
 
   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;
   
   {
     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());
   }
 
   /**
-   * 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.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), ConfigSolr.fromSolrHome(solrHome));
   }
 
-  public CoreContainer(String solrHome) {
-    this.solrHome = solrHome;
+  /**
+   * Create a new CoreContainer using the given SolrResourceLoader and
+   * configuration.  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);
+  }
+
+  /**
+   * 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) {
+    CoreContainer cc = new CoreContainer(new SolrResourceLoader(solrHome), ConfigSolr.fromFile(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);
+    log.info("Loading cores into CoreContainer [instanceDir={}]", loader.getInstanceDir());
 
-      // 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();
+    ThreadPoolExecutor coreLoadExecutor = null;
 
     // add the sharedLib to the shared resource loader before initializing cfg based plugins
     libDir = cfg.get(ConfigSolr.CfgProp.SOLR_SHAREDLIB , null);
     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();
@@ -298,8 +227,8 @@ public class CoreContainer
     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);
+    distribUpdateConnTimeout = cfg.getInt(ConfigSolr.CfgProp.SOLR_DISTRIBUPDATECONNTIMEOUT, 0);
+    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);
@@ -315,13 +244,15 @@ public class CoreContainer
 
     transientCacheSize = cfg.getInt(ConfigSolr.CfgProp.SOLR_TRANSIENTCACHESIZE, Integer.MAX_VALUE);
 
+    boolean genericCoreNodeNames = cfg.getBool(ConfigSolr.CfgProp.SOLR_GENERICCORENODENAMES, false);
+
     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);
+    zkSys.initZooKeeper(this, solrHome, zkHost, zkClientTimeout, hostPort, hostContext, host, leaderVoteWait, genericCoreNodeNames, distribUpdateConnTimeout, distribUpdateSoTimeout);
     
     if (isZooKeeperAware() && coreLoadThreads <= 1) {
       throw new SolrException(ErrorCode.SERVER_ERROR,
@@ -415,7 +346,13 @@ public class CoreContainer
             p.setTransient(("true".equalsIgnoreCase(opt) || "on"
                 .equalsIgnoreCase(opt)) ? true : false);
           }
-          
+
+          if (p.isTransient() || ! p.isLoadOnStartup()) {
+            // Store it away for later use. includes non-transient but not
+            // loaded at startup cores.
+            solrCores.putDynamicDescriptor(rawName, p);
+          }
+
           if (p.isLoadOnStartup()) { // The normal case
 
             Callable<SolrCore> task = new Callable<SolrCore>() {
@@ -423,6 +360,9 @@ public class CoreContainer
               public SolrCore call() {
                 SolrCore c = null;
                 try {
+                  if (zkSys.getZkController() != null) {
+                    preRegisterInZk(p);
+                  }
                   c = create(p);
                   registerCore(p.isTransient(), name, c, false);
                 } catch (Throwable t) {
@@ -446,10 +386,6 @@ 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);
@@ -629,22 +565,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.getCoreDescriptor());
-      } 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;
 
@@ -853,7 +773,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 );
 
@@ -961,10 +881,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;
     }
 
@@ -991,6 +910,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);
@@ -1082,7 +1004,7 @@ public class CoreContainer
   }
   
   public File getConfigFile() {
-    return configFile;
+    return new File(solrHome, ConfigSolr.SOLR_XML_FILE);
   }
 
   /**
@@ -1096,7 +1018,7 @@ public class CoreContainer
   /** Persists the cores config file in cores.xml. */
   @Deprecated
   public void persist() {
-    persistFile(configFile);
+    persistFile(getConfigFile());
   }
 
   /**
@@ -1117,45 +1039,82 @@ public class CoreContainer
     // only the old solrxml persists
     if (cfg != null && !(cfg instanceof ConfigSolrXmlOld)) return;
 
-    log.info("Persisting cores config to " + (file == null ? configFile : file));
+    log.info("Persisting cores config to " + (file == null ? getConfigFile() : 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()));
-    
+
+    addAttrib(rootSolrAttribs, ConfigSolr.CfgProp.SOLR_SHAREDLIB, "sharedLib", this.libDir);
+    addAttrib(rootSolrAttribs, ConfigSolr.CfgProp.SOLR_PERSISTENT, "persistent",
+        Boolean.toString(isPersistent()), "false");
+    addAttrib(rootSolrAttribs, ConfigSolr.CfgProp.SOLR_CORELOADTHREADS, "coreLoadThreads",
+        Integer.toString(this.coreLoadThreads), Integer.toString(CORE_LOAD_THREADS));
+    addAttrib(rootSolrAttribs, ConfigSolr.CfgProp.SOLR_ZKHOST, "zkHost", this.zkHost);
+
     // <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",
+    addAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_ADMINPATH, "adminPath", this.adminPath, this.getAdminPath());
+    addAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_ADMINHANDLER, "adminHandler", this.adminHandler);
+    addAttrib(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);
+    addAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_HOST, "host", zkSys.getHost());
 
     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",
+    addAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_HOSTPORT, "hostPort", zkSys.getHostPort());
+    addAttrib(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",
+    addAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_HOSTCONTEXT, "hostContext",
+        zkSys.getHostContext());
+    addAttrib(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));
+    addAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_GENERICCORENODENAMES, "genericCoreNodeNames",
+        Boolean.toString(zkSys.getGenericCoreNodeNames()), "false");
     if (transientCacheSize != Integer.MAX_VALUE) { // This test
     // is a consequence of testing. I really hate it.
-      addCoresAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_TRANSIENTCACHESIZE, "transientCacheSize",
+      addAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_TRANSIENTCACHESIZE, "transientCacheSize",
           Integer.toString(this.transientCacheSize), Integer.toString(Integer.MAX_VALUE));
     }
+    addAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_DISTRIBUPDATECONNTIMEOUT, "distribUpdateConnTimeout",
+        Integer.toString(this.distribUpdateConnTimeout), Integer.toString(this.distribUpdateConnTimeout));
+    addAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_DISTRIBUPDATESOTIMEOUT, "distribUpdateSoTimeout",
+        Integer.toString(this.distribUpdateSoTimeout), Integer.toString(this.distribUpdateSoTimeout));
+    addAttrib(coresAttribs, ConfigSolr.CfgProp.SOLR_MANAGEMENTPATH, "managementPath",
+        this.managementPath);
+
+    // don't forget the logging stuff
+    Map<String, String> loggingAttribs = new HashMap<String, String>();
+    addAttrib(loggingAttribs, ConfigSolr.CfgProp.SOLR_LOGGING_CLASS, "class",
+        cfg.get(ConfigSolr.CfgProp.SOLR_LOGGING_CLASS, null));
+    addAttrib(loggingAttribs, ConfigSolr.CfgProp.SOLR_LOGGING_ENABLED, "enabled",
+        cfg.get(ConfigSolr.CfgProp.SOLR_LOGGING_ENABLED, null));
+
+    Map<String, String> watcherAttribs = new HashMap<String, String>();
+    addAttrib(watcherAttribs, ConfigSolr.CfgProp.SOLR_LOGGING_WATCHER_SIZE, "size",
+        cfg.get(ConfigSolr.CfgProp.SOLR_LOGGING_WATCHER_SIZE, null));
+    addAttrib(watcherAttribs, ConfigSolr.CfgProp.SOLR_LOGGING_WATCHER_THRESHOLD, "threshold",
+        cfg.get(ConfigSolr.CfgProp.SOLR_LOGGING_WATCHER_THRESHOLD, null));
+
+
+    Map<String, String> shardHandlerAttrib = new HashMap<String, String>();
+    addAttrib(shardHandlerAttrib, ConfigSolr.CfgProp.SOLR_SHARDHANDLERFACTORY_CLASS, "class",
+        cfg.get(ConfigSolr.CfgProp.SOLR_SHARDHANDLERFACTORY_CLASS, null));
+    addAttrib(shardHandlerAttrib, ConfigSolr.CfgProp.SOLR_SHARDHANDLERFACTORY_NAME, "name",
+        cfg.get(ConfigSolr.CfgProp.SOLR_SHARDHANDLERFACTORY_NAME, null));
+
+    Map<String, String> shardHandlerProps = new HashMap<String, String>();
+    addAttrib(shardHandlerProps, ConfigSolr.CfgProp.SOLR_SHARDHANDLERFACTORY_CONNTIMEOUT, "connTimeout",
+        cfg.get(ConfigSolr.CfgProp.SOLR_SHARDHANDLERFACTORY_CONNTIMEOUT, null));
+    addAttrib(shardHandlerProps, ConfigSolr.CfgProp.SOLR_SHARDHANDLERFACTORY_SOCKETTIMEOUT, "socketTimeout",
+        cfg.get(ConfigSolr.CfgProp.SOLR_SHARDHANDLERFACTORY_SOCKETTIMEOUT, null));
 
     try {
-      solrCores.persistCores(origCfg, containerProperties, rootSolrAttribs, coresAttribs, file, configFile, loader);
+      solrCores.persistCores(cfg.config.getOriginalConfig(), containerProperties, rootSolrAttribs,coresAttribs,
+          loggingAttribs, watcherAttribs, shardHandlerAttrib, shardHandlerProps, file, loader);
     } catch (XPathExpressionException e) {
       throw new SolrException(ErrorCode.SERVER_ERROR, null, e);
     }
@@ -1166,30 +1125,39 @@ public class CoreContainer
     return Integer.toString(integer);
   }
 
-  private void addCoresAttrib(Map<String,String> coresAttribs, ConfigSolr.CfgProp prop,
-                              String attribName, String attribValue, String defaultValue) {
+  private void addAttrib(Map<String, String> attribs, ConfigSolr.CfgProp prop,
+                         String attribName, String attribValue) {
+    addAttrib(attribs, prop, attribName, attribValue, null);
+  }
+
+    private void addAttrib(Map<String, String> attribs, ConfigSolr.CfgProp prop,
+                         String attribName, String attribValue, String defaultValue) {
     if (cfg == null) {
-      coresAttribs.put(attribName, attribValue);
+      attribs.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);
+        attribs.put(attribName, origValue);
       } else {
-        coresAttribs.put(attribName, attribValue);
+        attribs.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;
   }
@@ -1221,14 +1189,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/security/solr/core/src/java/org/apache/solr/core/CoreDescriptor.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/CoreDescriptor.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/CoreDescriptor.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/CoreDescriptor.java Wed Jul  3 23:26:32 2013
@@ -65,6 +65,9 @@ public class CoreDescriptor {
   // them individually.
   private Properties coreProperties = new Properties();
 
+  //TODO: 5.0 remove this, this is solely a hack for persistence.
+  private Properties createdProperties = new Properties();
+
   private boolean loadedImplicit = false;
 
   private final CoreContainer coreContainer;
@@ -280,6 +283,14 @@ public class CoreDescriptor {
     }
   }
 
+  public void addCreatedProperty(String key, String value) {
+    createdProperties.put(key, value);
+  }
+
+  public final Properties getCreatedProperties() {
+    return createdProperties;
+  }
+
   public CloudDescriptor getCloudDescriptor() {
     return cloudDesc;
   }

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/DirectoryFactory.java Wed Jul  3 23:26:32 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/security/solr/core/src/java/org/apache/solr/core/EphemeralDirectoryFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/EphemeralDirectoryFactory.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/EphemeralDirectoryFactory.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/EphemeralDirectoryFactory.java Wed Jul  3 23:26:32 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/security/solr/core/src/java/org/apache/solr/core/IndexDeletionPolicyWrapper.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/IndexDeletionPolicyWrapper.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/IndexDeletionPolicyWrapper.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/IndexDeletionPolicyWrapper.java Wed Jul  3 23:26:32 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/security/solr/core/src/java/org/apache/solr/core/SolrCore.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrCore.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrCore.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrCore.java Wed Jul  3 23:26:32 2013
@@ -18,8 +18,10 @@
 package org.apache.solr.core;
 
 import java.io.File;
+import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 import java.io.Writer;
 import java.lang.reflect.Constructor;
 import java.net.URL;
@@ -62,6 +64,7 @@ import org.apache.lucene.store.IndexInpu
 import org.apache.lucene.store.LockObtainFailedException;
 import org.apache.solr.cloud.CloudDescriptor;
 import org.apache.solr.common.SolrException;
+import org.apache.solr.common.SolrException.ErrorCode;
 import org.apache.solr.common.cloud.Slice;
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.CommonParams.EchoParamStyle;
@@ -670,11 +673,10 @@ public final class SolrCore implements S
     if (dataDir == null) {
       if (cd.usingDefaultDataDir()) dataDir = config.getDataDir();
       if (dataDir == null) {
-        dataDir = cd.getDataDir();
         try {
+          dataDir = cd.getDataDir();
           if (!directoryFactory.isAbsolute(dataDir)) {
-            dataDir = directoryFactory.normalize(SolrResourceLoader
-                .normalizeDir(cd.getInstanceDir()) + dataDir);
+            dataDir = directoryFactory.getDataHome(cd);
           }
         } catch (IOException e) {
           throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, null, e);
@@ -745,7 +747,6 @@ public final class SolrCore implements S
       this.codec = initCodec(solrConfig, schema);
       
       if (updateHandler == null) {
-        initDirectoryFactory();
         solrCoreState = new DefaultSolrCoreState(getDirectoryFactory());
       } else {
         solrCoreState = updateHandler.getSolrCoreState();
@@ -848,15 +849,63 @@ public final class SolrCore implements S
     
     CoreContainer cc = cd.getCoreContainer();
     
+    if (cc != null) {
+      if (cc.cfg != null && cc.cfg instanceof ConfigSolrXml) {
+        writePropFile(cd, cc);
+      }
+    }
+
     if (cc != null && cc.isZooKeeperAware() && Slice.CONSTRUCTION.equals(cd.getCloudDescriptor().getShardState())) {
       // set update log to buffer before publishing the core
       getUpdateHandler().getUpdateLog().bufferUpdates();
+      
+      cd.getCloudDescriptor().setShardState(null);
+      cd.getCloudDescriptor().setShardRange(null);
+      
     }
     // For debugging   
 //    numOpens.incrementAndGet();
 //    openHandles.put(this, new RuntimeException("unclosed core - name:" + getName() + " refs: " + refCount.get()));
   }
 
+  private void writePropFile(CoreDescriptor cd, CoreContainer cc) {
+    File propFile = new File(cd.getInstanceDir(), "core.properties");
+    if (!propFile.exists()) {
+      propFile.getParentFile().mkdirs();
+      Properties props = new Properties();
+      props.put("name", cd.getName());
+      if (cc.isZooKeeperAware()) {
+        String collection = cd.getCloudDescriptor().getCollectionName();
+        if (collection != null) {
+          props.put("collection", collection);
+        }
+        String coreNodeName = cd.getCloudDescriptor().getCoreNodeName();
+        if (coreNodeName != null) {
+          props.put("coreNodeName", coreNodeName);
+        }
+        String roles = cd.getCloudDescriptor().getRoles();
+        if (roles != null) {
+          props.put("roles", roles);
+        }
+        String shardId = cd.getCloudDescriptor().getShardId();
+        if (shardId != null) {
+          props.put("shard", shardId);
+        }
+      }
+      OutputStream out = null;
+      try {
+        out = new FileOutputStream(propFile);
+        props.store(out, "");
+      } catch (IOException e) {
+        throw new SolrException(ErrorCode.SERVER_ERROR, null, e);
+      } finally {
+        if (out != null) {
+          IOUtils.closeQuietly(out);
+        }
+      }
+    }
+  }
+    
   private Codec initCodec(SolrConfig solrConfig, final IndexSchema schema) {
     final PluginInfo info = solrConfig.getPluginInfo(CodecFactory.class.getName());
     final CodecFactory factory;
@@ -1352,6 +1401,10 @@ public final class SolrCore implements S
    * This method acquires openSearcherLock - do not call with searckLock held!
    */
   public RefCounted<SolrIndexSearcher>  openNewSearcher(boolean updateHandlerReopens, boolean realtime) {
+    if (isClosed()) { // catch some errors quicker
+      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "openNewSearcher called on closed core");
+    }
+
     SolrIndexSearcher tmp;
     RefCounted<SolrIndexSearcher> newestSearcher = null;
     boolean nrt = solrConfig.reopenReaders && updateHandlerReopens;

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrCores.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrCores.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrCores.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrCores.java Wed Jul  3 23:26:32 2013
@@ -17,8 +17,18 @@ package org.apache.solr.core;
  * limitations under the License.
  */
 
+import org.apache.commons.lang.StringUtils;
+import org.apache.solr.cloud.CloudDescriptor;
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.params.CoreAdminParams;
+import org.apache.solr.core.SolrXMLSerializer.SolrCoreXMLDef;
+import org.apache.solr.util.DOMUtil;
+import org.w3c.dom.Node;
+
+import javax.xml.xpath.XPathExpressionException;
 import java.io.File;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.HashMap;
 import java.util.HashSet;
@@ -30,15 +40,6 @@ import java.util.Set;
 import java.util.TreeSet;
 import java.util.concurrent.ConcurrentHashMap;
 
-import javax.xml.xpath.XPathExpressionException;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.solr.cloud.CloudDescriptor;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.core.SolrXMLSerializer.SolrCoreXMLDef;
-import org.apache.solr.util.DOMUtil;
-import org.w3c.dom.Node;
-
 
 class SolrCores {
   private static SolrXMLSerializer SOLR_XML_SERIALIZER = new SolrXMLSerializer();
@@ -99,70 +100,34 @@ class SolrCores {
   // We are shutting down. You can't hold the lock on the various lists of cores while they shut down, so we need to
   // make a temporary copy of the names and shut them down outside the lock.
   protected void close() {
-    List<String> coreNames;
-    List<String> transientNames;
-    List<SolrCore> pendingToClose;
+    Collection<SolrCore> coreList = new ArrayList<SolrCore>();
 
     // It might be possible for one of the cores to move from one list to another while we're closing them. So
     // loop through the lists until they're all empty. In particular, the core could have moved from the transient
     // list to the pendingCloses list.
 
-    while (true) {
+    do {
+      coreList.clear();
       synchronized (modifyLock) {
-        coreNames = new ArrayList<String>(cores.keySet());
-        transientNames = new ArrayList<String>(transientCores.keySet());
-        pendingToClose = new ArrayList<SolrCore>(pendingCloses);
-      }
+        // make a copy of the cores then clear the map so the core isn't handed out to a request again
+        coreList.addAll(cores.values());
+        cores.clear();
 
-      if (coreNames.size() == 0 && transientNames.size() == 0 && pendingToClose.size() == 0) break;
-
-      for (String coreName : coreNames) {
-        SolrCore core = cores.get(coreName);
-        if (core == null) {
-          CoreContainer.log.info("Core " + coreName + " moved from core container list before closing.");
-        } else {
-          try {
-            core.close();
-          } catch (Throwable t) {
-            SolrException.log(CoreContainer.log, "Error shutting down core", t);
-          } finally {
-            synchronized (modifyLock) {
-              cores.remove(coreName);
-            }
-          }
-        }
-      }
+        coreList.addAll(transientCores.values());
+        transientCores.clear();
 
-      for (String coreName : transientNames) {
-        SolrCore core = transientCores.get(coreName);
-        if (core == null) {
-          CoreContainer.log.info("Core " + coreName + " moved from transient core container list before closing.");
-        } else {
-          try {
-            core.close();
-          } catch (Throwable t) {
-            SolrException.log(CoreContainer.log, "Error shutting down core", t);
-          } finally {
-            synchronized (modifyLock) {
-              transientCores.remove(coreName);
-            }
-          }
-        }
+        coreList.addAll(pendingCloses);
+        pendingCloses.clear();
       }
 
-      // We might have some cores that we were _thinking_ about shutting down, so take care of those too.
-      for (SolrCore core : pendingToClose) {
+      for (SolrCore core : coreList) {
         try {
           core.close();
         } catch (Throwable t) {
           SolrException.log(CoreContainer.log, "Error shutting down core", t);
-        } finally {
-          synchronized (modifyLock) {
-            pendingCloses.remove(core);
-          }
         }
       }
-    }
+    } while (coreList.size() > 0);
   }
 
   //WARNING! This should be the _only_ place you put anything into the list of transient cores!
@@ -246,10 +211,18 @@ class SolrCores {
     synchronized (modifyLock) {
       SolrCore c0 = cores.get(n0);
       SolrCore c1 = cores.get(n1);
-      if (c0 == null)
-        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "No such core: " + n0);
-      if (c1 == null)
-        throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "No such core: " + n1);
+      if (c0 == null) { // Might be an unloaded transient core
+        c0 = container.getCore(n0);
+        if (c0 == null) {
+          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "No such core: " + n0);
+        }
+      }
+      if (c1 == null) { // Might be an unloaded transient core
+        c1 = container.getCore(n1);
+        if (c1 == null) {
+          throw new SolrException(SolrException.ErrorCode.BAD_REQUEST, "No such core: " + n1);
+        }
+      }
       cores.put(n0, c1);
       cores.put(n1, c0);
 
@@ -299,20 +272,20 @@ class SolrCores {
     }
   }
 
-  protected SolrCore getCoreFromAnyList(String name) {
-    SolrCore core;
-
+  /* If you don't increment the reference count, someone could close the core before you use it. */
+  protected SolrCore  getCoreFromAnyList(String name, boolean incRefCount) {
     synchronized (modifyLock) {
-      core = cores.get(name);
-      if (core != null) {
-        return core;
+      SolrCore core = cores.get(name);
+
+      if (core == null) {
+        core = transientCores.get(name);
       }
 
-      if (dynamicDescriptors.size() == 0) {
-        return null; // Nobody even tried to define any transient cores, so we're done.
+      if (core != null && incRefCount) {
+        core.open();
       }
-      // Now look for already loaded transient cores.
-      return transientCores.get(name);
+
+      return core;
     }
   }
 
@@ -351,15 +324,17 @@ class SolrCores {
       return coreToOrigName.get(solrCore);
     }
   }
-  
+
   public void persistCores(Config cfg, Properties containerProperties,
       Map<String,String> rootSolrAttribs, Map<String,String> coresAttribs,
-      File file, File configFile, SolrResourceLoader loader) throws XPathExpressionException {
+      Map<String, String> loggingAttribs, Map<String,String> watcherAttribs,
+      Map<String, String> shardHandlerAttrib, Map<String,String> shardHandlerProps,
+      File file, SolrResourceLoader loader) throws XPathExpressionException {
+
 
-    
     List<SolrXMLSerializer.SolrCoreXMLDef> solrCoreXMLDefs = new ArrayList<SolrXMLSerializer.SolrCoreXMLDef>();
     synchronized (modifyLock) {
-      
+
       persistCores(cfg, cores, loader, solrCoreXMLDefs);
       persistCores(cfg, transientCores, loader, solrCoreXMLDefs);
       // add back all the cores that aren't loaded, either in cores or transient
@@ -384,9 +359,13 @@ class SolrCores {
       solrXMLDef.containerProperties = containerProperties;
       solrXMLDef.solrAttribs = rootSolrAttribs;
       solrXMLDef.coresAttribs = coresAttribs;
+      solrXMLDef.loggingAttribs = loggingAttribs;
+      solrXMLDef.watcherAttribs = watcherAttribs;
+      solrXMLDef.shardHandlerAttribs = shardHandlerAttrib;
+      solrXMLDef.shardHandlerProps = shardHandlerProps;
       SOLR_XML_SERIALIZER.persistFile(file, solrXMLDef);
     }
-    
+
   }
   // Wait here until any pending operations (load, unload or reload) are completed on this core.
   protected SolrCore waitAddPendingCoreOps(String name) {
@@ -419,7 +398,7 @@ class SolrCores {
         if (! pendingCoreOps.add(name)) {
           CoreContainer.log.warn("Replaced an entry in pendingCoreOps {}, we should not be doing this", name);
         }
-        return getCoreFromAnyList(name); // we might have been _unloading_ the core, so return the core if it was loaded.
+        return getCoreFromAnyList(name, false); // we might have been _unloading_ the core, so return the core if it was loaded.
       }
     }
     return null;
@@ -442,95 +421,162 @@ class SolrCores {
       addCoreToPersistList(cfg, loader, solrCore.getCoreDescriptor(), getCoreToOrigName(solrCore), solrCoreXMLDefs);
     }
   }
-  
-  private void addCoreProperty(Map<String,String> coreAttribs, SolrResourceLoader loader, Node node, String name,
+
+  private void addCoreProperty(Map<String,String> propMap, SolrResourceLoader loader, Node node, String name,
+                               String value) {
+    addCoreProperty(propMap, loader, node, name, value, null);
+  }
+
+  private void addCoreProperty(Map<String,String> propMap, SolrResourceLoader loader, Node node, String name,
       String value, String defaultValue) {
-    
+
     if (node == null) {
-      coreAttribs.put(name, value);
+      propMap.put(name, value);
       return;
     }
-    
+
     if (node != null) {
       String rawAttribValue = DOMUtil.getAttr(node, name, null);
 
+      if (rawAttribValue == null) {
+        return; // It was never in the original definition.
+      }
+
       if (value == null) {
-        coreAttribs.put(name, rawAttribValue);
+        propMap.put(name, rawAttribValue);
         return;
       }
-      if (rawAttribValue == null && defaultValue != null && value.equals(defaultValue)) {
+
+      // There are some _really stupid_ additions/subtractions of the slash that we should look out for. I'm (EOE)
+      // ashamed of this but it fixes some things and we're throwing persistence away anyway (although
+      // maybe not for core.properties files).
+      String defComp = regularizeAttr(defaultValue);
+
+      if (defComp != null && regularizeAttr(value).equals(defComp)) {
         return;
       }
-      if (rawAttribValue != null && value.equals(DOMUtil.substituteProperty(rawAttribValue, loader.getCoreProperties()))){
-        coreAttribs.put(name, rawAttribValue);
+      String rawComp = regularizeAttr(rawAttribValue);
+      if (rawComp != null && regularizeAttr(value).equals(
+          regularizeAttr(DOMUtil.substituteProperty(rawAttribValue, loader.getCoreProperties())))) {
+        propMap.put(name, rawAttribValue);
       } else {
-        coreAttribs.put(name, value);
+        propMap.put(name, value);
       }
     }
-
   }
 
+  protected String regularizeAttr(String path) {
+    if (path == null)
+      return null;
+    path = path.replace('/', File.separatorChar);
+    path = path.replace('\\', File.separatorChar);
+    if (path.endsWith(File.separator)) {
+      path = path.substring(0, path.length() - 1);
+    }
+    return path;
+  }
   protected void addCoreToPersistList(Config cfg, SolrResourceLoader loader,
       CoreDescriptor dcore, String origCoreName,
       List<SolrCoreXMLDef> solrCoreXMLDefs) throws XPathExpressionException {
-    
-    String coreName = dcore.getProperty(CoreDescriptor.CORE_NAME);
-    
+
     Map<String,String> coreAttribs = new HashMap<String,String>();
+    Properties newProps = new Properties();
+
+    // This is simple, just take anything sent in and saved away in at core creation and write it out.
+    if (dcore.getCreatedProperties().size() > 0) {
+      final List<String> stdNames = new ArrayList<String>(Arrays.asList(CoreDescriptor.standardPropNames));
+      coreAttribs.put(CoreDescriptor.CORE_NAME, dcore.getName()); // NOTE: may have been swapped or renamed!
+      for (String key : dcore.getCreatedProperties().stringPropertyNames()) {
+        if (! stdNames.contains(key) && ! key.startsWith(CoreAdminParams.PROPERTY_PREFIX)) continue;
+        if (key.indexOf(CoreAdminParams.PROPERTY_PREFIX) == 0) {
+          newProps.put(key.substring(CoreAdminParams.PROPERTY_PREFIX.length()), dcore.getCreatedProperties().getProperty(key));
+        } else if (! CoreDescriptor.CORE_NAME.equals(key)) {
+          coreAttribs.put(key, dcore.getCreatedProperties().getProperty(key));
+        }
+      }
+      // Insure instdir is persisted if it's the default since it's checked at startup even if not specified on the
+      // create command.
+      if (! dcore.getCreatedProperties().containsKey(CoreDescriptor.CORE_INSTDIR)) {
+        coreAttribs.put(CoreDescriptor.CORE_INSTDIR, dcore.getRawInstanceDir());
+      }
+    } else {
+
+      String coreName = dcore.getProperty(CoreDescriptor.CORE_NAME);
+
+      CloudDescriptor cd = dcore.getCloudDescriptor();
+      String collection = null;
+      if (cd != null) collection = cd.getCollectionName();
+
+      if (origCoreName == null) {
+        origCoreName = coreName;
+      }
+
+      Node node = null;
+      if (cfg != null) {
+        node = cfg.getNode("/solr/cores/core[@name='" + origCoreName + "']",
+            false);
+      }
+
+      coreAttribs.put(CoreDescriptor.CORE_NAME, coreName);
+      //coreAttribs.put(CoreDescriptor.CORE_INSTDIR, dcore.getRawInstanceDir());
+      addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_INSTDIR, dcore.getRawInstanceDir(), null);
+
+      addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_COLLECTION,
+          StringUtils.isNotBlank(collection) ? collection : dcore.getName());
+
+      addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_DATADIR,
+          dcore.getDataDir());
+      addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_ULOGDIR,
+          dcore.getUlogDir());
+      addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_TRANSIENT,
+          Boolean.toString(dcore.isTransient()));
+      addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_LOADONSTARTUP,
+          Boolean.toString(dcore.isLoadOnStartup()));
+      addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_CONFIG,
+          dcore.getConfigName());
+      addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_SCHEMA,
+          dcore.getSchemaName());
+
+      addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_COLLECTION,
+          collection, dcore.getName());
+
+      String shard = null;
+      String roles = null;
+      String node_name = null;
+      if (cd != null) {
+        shard = cd.getShardId();
+        roles = cd.getRoles();
+        node_name = cd.getCoreNodeName();
+      }
+      addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_SHARD,
+          shard);
+
+      addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_ROLES,
+          roles);
+
+      addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_NODE_NAME,
+          node_name);
+
+
+      for (Object key : dcore.getCoreProperties().keySet()) {
+
+        if (cfg != null) {
+          Node propNode = cfg.getNode("/solr/cores/core[@name='" + origCoreName + "']/property[@name='" + key + "']",
+              false);
+
+          if (propNode != null) { // This means it was in the original DOM element, so just copy it.
+            newProps.put(DOMUtil.getAttr(propNode, "name", null), DOMUtil.getAttr(propNode, "value", null));
+          }
+        }
+      }
+    }
+
 
-    CloudDescriptor cd = dcore.getCloudDescriptor();
-    String collection = null;
-    if (cd != null) collection = cd.getCollectionName();
-
-    if (origCoreName == null) {
-      origCoreName = coreName;
-    }
-    
-    Properties properties = dcore.getCoreProperties();
-    Node node = null;
-    if (cfg != null) {
-      node = cfg.getNode("/solr/cores/core[@name='" + origCoreName + "']",
-          false);
-    }
-    
-    coreAttribs.put(CoreDescriptor.CORE_NAME, coreName);
-    
-    addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_INSTDIR, dcore.getRawInstanceDir(), null);
-
-    coreAttribs.put(CoreDescriptor.CORE_COLLECTION,
-        StringUtils.isNotBlank(collection) ? collection : dcore.getName());
-    
-    addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_DATADIR, dcore.getDataDir(), null);
-    addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_ULOGDIR, dcore.getUlogDir(), null);
-    addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_TRANSIENT, Boolean.toString(dcore.isTransient()), null);
-    addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_LOADONSTARTUP, Boolean.toString(dcore.isLoadOnStartup()), null);
-    
-    addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_COLLECTION,
-        collection, dcore.getName());
-    
-    String shard = null;
-    String roles = null;
-    if (cd != null) {
-      shard = cd.getShardId();
-      roles = cd.getRoles();
-    }
-    addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_SHARD,
-        shard, null);
-    
-    addCoreProperty(coreAttribs, loader, node, CoreDescriptor.CORE_ROLES,
-        roles, null);
-
-    coreAttribs.put(CoreDescriptor.CORE_LOADONSTARTUP,
-        Boolean.toString(dcore.isLoadOnStartup()));
-    coreAttribs.put(CoreDescriptor.CORE_TRANSIENT,
-        Boolean.toString(dcore.isTransient()));
-    
 
     SolrXMLSerializer.SolrCoreXMLDef solrCoreXMLDef = new SolrXMLSerializer.SolrCoreXMLDef();
     solrCoreXMLDef.coreAttribs = coreAttribs;
-    solrCoreXMLDef.coreProperties = properties;
+    solrCoreXMLDef.coreProperties = newProps;
     solrCoreXMLDefs.add(solrCoreXMLDef);
-
   }
 
   protected Object getModifyLock() {

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrDeletionPolicy.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrDeletionPolicy.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrDeletionPolicy.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrDeletionPolicy.java Wed Jul  3 23:26:32 2013
@@ -77,7 +77,7 @@ public class SolrDeletionPolicy extends 
    * Internal use for Lucene... do not explicitly call.
    */
   @Override
-  public void onInit(List commits) throws IOException {
+  public void onInit(List<? extends IndexCommit> commits) throws IOException {
     // SOLR-4547: log basic data at INFO, add filenames at DEBUG.
     if (commits.isEmpty()) {
       return;
@@ -86,26 +86,26 @@ public class SolrDeletionPolicy extends 
         new CommitsLoggingInfo(commits));
     log.debug("SolrDeletionPolicy.onInit: commits: {}",
         new CommitsLoggingDebug(commits));
-    updateCommits((List<IndexCommit>) commits);
+    updateCommits(commits);
   }
 
   /**
    * Internal use for Lucene... do not explicitly call.
    */
   @Override
-  public void onCommit(List commits) throws IOException {
+  public void onCommit(List<? extends IndexCommit> commits) throws IOException {
     // SOLR-4547: log basic data at INFO, add filenames at DEBUG.
     log.info("SolrDeletionPolicy.onCommit: commits: {}",
         new CommitsLoggingInfo(commits));
     log.debug("SolrDeletionPolicy.onCommit: commits: {}",
         new CommitsLoggingDebug(commits));
-    updateCommits((List<IndexCommit>) commits);
+    updateCommits(commits);
   }
 
   private static class CommitsLoggingInfo {
-    private List<IndexCommit> commits;
+    private List<? extends IndexCommit> commits;
 
-    public CommitsLoggingInfo(List<IndexCommit> commits) {
+    public CommitsLoggingInfo(List<? extends IndexCommit> commits) {
       this.commits = commits;
     }
 
@@ -135,7 +135,7 @@ public class SolrDeletionPolicy extends 
   }
 
   private static class CommitsLoggingDebug extends CommitsLoggingInfo {
-    public CommitsLoggingDebug(List<IndexCommit> commits) {
+    public CommitsLoggingDebug(List<? extends IndexCommit> commits) {
       super(commits);
     }
 
@@ -150,7 +150,7 @@ public class SolrDeletionPolicy extends 
     }
   }
 
-  private void updateCommits(List<IndexCommit> commits) {
+  private void updateCommits(List<? extends IndexCommit> commits) {
     // to be safe, we should only call delete on a commit point passed to us
     // in this specific call (may be across diff IndexWriter instances).
     // this will happen rarely, so just synchronize everything

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrResourceLoader.java Wed Jul  3 23:26:32 2013
@@ -17,55 +17,57 @@
 
 package org.apache.solr.core;
 
-import java.io.Closeable;
-import java.io.File;
-import java.io.FileFilter;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLClassLoader;
-import java.util.*;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
 import org.apache.lucene.analysis.util.CharFilterFactory;
 import org.apache.lucene.analysis.util.ResourceLoaderAware;
 import org.apache.lucene.analysis.util.TokenFilterFactory;
 import org.apache.lucene.analysis.util.TokenizerFactory;
+import org.apache.lucene.analysis.util.WordlistLoader;
 import org.apache.lucene.codecs.Codec;
-import org.apache.lucene.codecs.PostingsFormat;
 import org.apache.lucene.codecs.DocValuesFormat;
+import org.apache.lucene.codecs.PostingsFormat;
 import org.apache.lucene.util.IOUtils;
-import org.apache.lucene.analysis.util.WordlistLoader;
 import org.apache.solr.common.ResourceLoader;
+import org.apache.solr.common.SolrException;
 import org.apache.solr.handler.admin.CoreAdminHandler;
+import org.apache.solr.handler.component.SearchComponent;
 import org.apache.solr.handler.component.ShardHandlerFactory;
+import org.apache.solr.request.SolrRequestHandler;
+import org.apache.solr.response.QueryResponseWriter;
+import org.apache.solr.schema.FieldType;
 import org.apache.solr.schema.ManagedIndexSchemaFactory;
 import org.apache.solr.schema.SimilarityFactory;
+import org.apache.solr.search.QParserPlugin;
+import org.apache.solr.update.processor.UpdateRequestProcessorFactory;
+import org.apache.solr.util.FileUtils;
+import org.apache.solr.util.plugin.SolrCoreAware;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.nio.charset.CharacterCodingException;
-import java.nio.charset.Charset;
-import java.lang.reflect.Constructor;
-
 import javax.naming.Context;
 import javax.naming.InitialContext;
 import javax.naming.NamingException;
 import javax.naming.NoInitialContextException;
-
-import org.apache.solr.util.FileUtils;
-import org.apache.solr.common.SolrException;
-import org.apache.solr.handler.component.SearchComponent;
-import org.apache.solr.request.SolrRequestHandler;
-import org.apache.solr.response.QueryResponseWriter;
-import org.apache.solr.schema.FieldType;
-import org.apache.solr.update.processor.UpdateRequestProcessorFactory;
-import org.apache.solr.util.plugin.SolrCoreAware;
-import org.apache.solr.search.QParserPlugin;
+import java.io.Closeable;
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 /**
  * @since solr 1.3

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrXMLSerializer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrXMLSerializer.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrXMLSerializer.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrXMLSerializer.java Wed Jul  3 23:26:32 2013
@@ -17,6 +17,11 @@ package org.apache.solr.core;
  * limitations under the License.
  */
 
+import org.apache.solr.common.SolrException;
+import org.apache.solr.common.util.XML;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.io.BufferedWriter;
 import java.io.File;
 import java.io.FileInputStream;
@@ -30,11 +35,6 @@ import java.util.Map;
 import java.util.Properties;
 import java.util.Set;
 
-import org.apache.solr.common.SolrException;
-import org.apache.solr.common.util.XML;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
 public class SolrXMLSerializer {
   protected static Logger log = LoggerFactory
       .getLogger(SolrXMLSerializer.class);
@@ -62,6 +62,41 @@ public class SolrXMLSerializer {
     if (containerProperties != null && !containerProperties.isEmpty()) {
       writeProperties(w, containerProperties, "  ");
     }
+
+    // Output logging section if any
+    if (solrXMLDef.loggingAttribs.size() > 0 || solrXMLDef.watcherAttribs.size() > 0) {
+      w.write(INDENT + "<logging");
+      for (Map.Entry<String, String> ent : solrXMLDef.loggingAttribs.entrySet()) {
+        writeAttribute(w, ent.getKey(), ent.getValue());
+      }
+      w.write(">\n");
+
+      if (solrXMLDef.watcherAttribs.size() > 0) {
+        w.write(INDENT + INDENT + "<watcher");
+        for (Map.Entry<String, String> ent : solrXMLDef.watcherAttribs.entrySet()) {
+          writeAttribute(w, ent.getKey(), ent.getValue());
+        }
+        w.write("/>\n");
+      }
+      w.write(INDENT + "</logging>\n");
+    }
+
+    // Output shard handler section if any
+    if (solrXMLDef.shardHandlerAttribs.size() > 0 || solrXMLDef.shardHandlerProps.size() > 0) {
+      w.write(INDENT + "<shardHandlerFactory");
+      for (Map.Entry<String, String> ent : solrXMLDef.shardHandlerAttribs.entrySet()) {
+        writeAttribute(w, ent.getKey(), ent.getValue());
+      }
+      w.write(">\n");
+      if (solrXMLDef.shardHandlerProps.size() > 0) {
+        for (Map.Entry<String, String> ent : solrXMLDef.shardHandlerProps.entrySet()) {
+          w.write(INDENT + INDENT + "<int name=\"" + ent.getKey() + "\"" + ">" + ent.getValue() + "</int>\n");
+        }
+      }
+      w.write(INDENT + "</shardHandlerFactory>\n");
+    }
+
+
     w.write(INDENT + "<cores");
     Map<String,String> coresAttribs = solrXMLDef.coresAttribs;
     Set<String> coreAttribKeys = coresAttribs.keySet();
@@ -116,7 +151,7 @@ public class SolrXMLSerializer {
   }
   
   void persistFile(File file, SolrXMLDef solrXMLDef) {
-    log.info("Persisting cores config to " + file);
+    log.info("Persisting cores config to " + file.getAbsolutePath());
     
     File tmpFile = null;
     try {
@@ -198,6 +233,10 @@ public class SolrXMLSerializer {
     Properties containerProperties;
     Map<String,String> solrAttribs;
     Map<String,String> coresAttribs;
+    Map<String, String> loggingAttribs;
+    Map<String, String> watcherAttribs;
+    Map<String, String> shardHandlerAttribs;
+    Map<String, String> shardHandlerProps;
     List<SolrCoreXMLDef> coresDefs;
   }
   

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/ZkContainer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/ZkContainer.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/ZkContainer.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/ZkContainer.java Wed Jul  3 23:26:32 2013
@@ -50,6 +50,7 @@ public class ZkContainer {
   private String hostContext;
   private String host;
   private String leaderVoteWait;
+  private Boolean genericCoreNodeNames;
   private int distribUpdateConnTimeout;
 
   public SolrZkServer getZkServer() {
@@ -75,6 +76,10 @@ public class ZkContainer {
   public String getLeaderVoteWait() {
     return leaderVoteWait;
   }
+  
+  public boolean getGenericCoreNodeNames() {
+    return genericCoreNodeNames;
+  }
 
   public int getDistribUpdateConnTimeout() {
     return distribUpdateConnTimeout;
@@ -90,7 +95,7 @@ public class ZkContainer {
     
   }
   
-  public void initZooKeeper(final CoreContainer cc, String solrHome, String zkHost, int zkClientTimeout, String hostPort, String hostContext, String host, String leaderVoteWait, int distribUpdateConnTimeout, int distribUpdateSoTimeout) {
+  public void initZooKeeper(final CoreContainer cc, String solrHome, String zkHost, int zkClientTimeout, String hostPort, String hostContext, String host, String leaderVoteWait, boolean genericCoreNodeNames, int distribUpdateConnTimeout, int distribUpdateSoTimeout) {
     ZkController zkController = null;
     
     // if zkHost sys property is not set, we are not using ZooKeeper
@@ -108,6 +113,7 @@ public class ZkContainer {
     this.hostContext = hostContext;
     this.host = host;
     this.leaderVoteWait = leaderVoteWait;
+    this.genericCoreNodeNames = genericCoreNodeNames;
     this.distribUpdateConnTimeout = distribUpdateConnTimeout;
     this.distribUpdateSoTimeout = distribUpdateSoTimeout;
     
@@ -163,7 +169,7 @@ public class ZkContainer {
         }
         zkController = new ZkController(cc, zookeeperHost, zkClientTimeout,
             zkClientConnectTimeout, host, hostPort, hostContext,
-            leaderVoteWait, distribUpdateConnTimeout, distribUpdateSoTimeout,
+            leaderVoteWait, genericCoreNodeNames, distribUpdateConnTimeout, distribUpdateSoTimeout,
             new CurrentCoreDescriptorProvider() {
 
               @Override

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/DocumentAnalysisRequestHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/DocumentAnalysisRequestHandler.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/DocumentAnalysisRequestHandler.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/DocumentAnalysisRequestHandler.java Wed Jul  3 23:26:32 2013
@@ -35,6 +35,7 @@ import org.apache.solr.request.SolrQuery
 import org.apache.solr.schema.FieldType;
 import org.apache.solr.schema.IndexSchema;
 import org.apache.solr.schema.SchemaField;
+import org.apache.solr.util.EmptyEntityResolver;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -90,6 +91,8 @@ public class DocumentAnalysisRequestHand
     super.init(args);
 
     inputFactory = XMLInputFactory.newInstance();
+    EmptyEntityResolver.configureXMLInputFactory(inputFactory);
+    inputFactory.setXMLReporter(xmllog);
     try {
       // The java 1.6 bundled stax parser (sjsxp) does not currently have a thread-safe
       // XMLInputFactory, as that implementation tries to cache and reuse the
@@ -103,7 +106,6 @@ public class DocumentAnalysisRequestHand
       // isimplementation specific.
       log.debug("Unable to set the 'reuse-instance' property for the input factory: " + inputFactory);
     }
-    inputFactory.setXMLReporter(xmllog);
   }
 
   /**

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/SnapPuller.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/SnapPuller.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/SnapPuller.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/SnapPuller.java Wed Jul  3 23:26:32 2013
@@ -318,20 +318,25 @@ public class SnapPuller {
       long latestVersion = (Long) response.get(CMD_INDEX_VERSION);
       long latestGeneration = (Long) response.get(GENERATION);
 
-      IndexCommit commit;
-      RefCounted<SolrIndexSearcher> searcherRefCounted = null;
-      try {
-        searcherRefCounted = core.getNewestSearcher(false);
-        if (searcherRefCounted == null) {
-          SolrException.log(LOG, "No open searcher found - fetch aborted");
-          return false;
+      // TODO: make sure that getLatestCommit only returns commit points for the main index (i.e. no side-car indexes)
+      IndexCommit commit = core.getDeletionPolicy().getLatestCommit();
+      if (commit == null) {
+        // Presumably the IndexWriter hasn't been opened yet, and hence the deletion policy hasn't been updated with commit points
+        RefCounted<SolrIndexSearcher> searcherRefCounted = null;
+        try {
+          searcherRefCounted = core.getNewestSearcher(false);
+          if (searcherRefCounted == null) {
+            LOG.warn("No open searcher found - fetch aborted");
+            return false;
+          }
+          commit = searcherRefCounted.get().getIndexReader().getIndexCommit();
+        } finally {
+          if (searcherRefCounted != null)
+            searcherRefCounted.decref();
         }
-        commit = searcherRefCounted.get().getIndexReader().getIndexCommit();
-      } finally {
-        if (searcherRefCounted != null)
-          searcherRefCounted.decref();
       }
-      
+
+
       if (latestVersion == 0L) {
         if (forceReplication && commit.getGeneration() != 0) {
           // since we won't get the files for an empty index,
@@ -403,7 +408,14 @@ public class SnapPuller {
             successfulInstall = modifyIndexProps(tmpIdxDirName);
             deleteTmpIdxDir  =  false;
           } else {
-            successfulInstall = moveIndexFiles(tmpIndexDir, indexDir);
+            solrCore.getUpdateHandler().getSolrCoreState()
+                .closeIndexWriter(core, true);
+            try {
+              successfulInstall = moveIndexFiles(tmpIndexDir, indexDir);
+            } finally {
+              solrCore.getUpdateHandler().getSolrCoreState()
+                  .openIndexWriter(core);
+            }
           }
           if (successfulInstall) {
             if (isFullCopyNeeded) {
@@ -426,7 +438,12 @@ public class SnapPuller {
             successfulInstall = modifyIndexProps(tmpIdxDirName);
             deleteTmpIdxDir =  false;
           } else {
-            successfulInstall = moveIndexFiles(tmpIndexDir, indexDir);
+            solrCore.getUpdateHandler().getSolrCoreState().closeIndexWriter(core, true);
+            try {
+              successfulInstall = moveIndexFiles(tmpIndexDir, indexDir);
+            } finally {
+              solrCore.getUpdateHandler().getSolrCoreState().openIndexWriter(core);
+            }
           }
           if (successfulInstall) {
             logReplicationTimeAndConfFiles(modifiedConfFiles, successfulInstall);
@@ -443,7 +460,11 @@ public class SnapPuller {
               core.getDirectoryFactory().remove(indexDir);
             }
           }
-          openNewWriterAndSearcher(isFullCopyNeeded);
+          if (isFullCopyNeeded) {
+            solrCore.getUpdateHandler().newIndexWriter(isFullCopyNeeded);
+          }
+          
+          openNewSearcherAndUpdateCommitPoint(isFullCopyNeeded);
         }
         
         replicationStartTime = 0;
@@ -615,11 +636,9 @@ public class SnapPuller {
     return sb;
   }
 
-  private void openNewWriterAndSearcher(boolean isFullCopyNeeded) throws IOException {
+  private void openNewSearcherAndUpdateCommitPoint(boolean isFullCopyNeeded) throws IOException {
     SolrQueryRequest req = new LocalSolrQueryRequest(solrCore,
         new ModifiableSolrParams());
-    // reboot the writer on the new index and get a new searcher
-    solrCore.getUpdateHandler().newIndexWriter(isFullCopyNeeded);
     
     RefCounted<SolrIndexSearcher> searcher = null;
     IndexCommit commitPoint;

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/admin/CoreAdminHandler.java Wed Jul  3 23:26:32 2013
@@ -17,19 +17,6 @@
 
 package org.apache.solr.handler.admin;
 
-import java.io.File;
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.Future;
-
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang.StringUtils;
 import org.apache.lucene.index.DirectoryReader;
@@ -57,8 +44,8 @@ import org.apache.solr.core.CloseHook;
 import org.apache.solr.core.CoreContainer;
 import org.apache.solr.core.CoreDescriptor;
 import org.apache.solr.core.DirectoryFactory;
-import org.apache.solr.core.SolrCore;
 import org.apache.solr.core.DirectoryFactory.DirContext;
+import org.apache.solr.core.SolrCore;
 import org.apache.solr.handler.RequestHandlerBase;
 import org.apache.solr.request.LocalSolrQueryRequest;
 import org.apache.solr.request.SolrQueryRequest;
@@ -75,6 +62,19 @@ import org.apache.zookeeper.KeeperExcept
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import java.io.File;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Future;
+
 /**
  *
  * @since solr 1.3
@@ -498,14 +498,18 @@ public class CoreAdminHandler extends Re
       Iterator<String> parameterNamesIterator = params.getParameterNamesIterator();
       while (parameterNamesIterator.hasNext()) {
           String parameterName = parameterNamesIterator.next();
+          String parameterValue = params.get(parameterName);
+          dcore.addCreatedProperty(parameterName, parameterValue); // Need this junk for silly persistence
+
           if(parameterName.startsWith(CoreAdminParams.PROPERTY_PREFIX)) {
-              String parameterValue = params.get(parameterName);
-              String propertyName = parameterName.substring(CoreAdminParams.PROPERTY_PREFIX.length()); // skip prefix
-              coreProperties.put(propertyName, parameterValue);
+            String propertyName = parameterName.substring(CoreAdminParams.PROPERTY_PREFIX.length()); // skip prefix
+            coreProperties.put(propertyName, parameterValue);
           }
       }
       dcore.setCoreProperties(coreProperties);
-      
+      if (coreContainer.getZkController() != null) {
+        coreContainer.preRegisterInZk(dcore);
+      }
       SolrCore core = coreContainer.create(dcore);
 
       coreContainer.register(name, core, false);
@@ -522,9 +526,24 @@ public class CoreAdminHandler extends Re
           SolrException.log(log, null, e);
         }
       }
+      
+      Throwable tc = ex;
+      Throwable c = null;
+      do {
+        tc = tc.getCause();
+        if (tc != null) {
+          c = tc;
+        }
+      } while (tc != null);
+      
+      String rootMsg = "";
+      if (c != null) {
+        rootMsg = " Caused by: " + c.getMessage();
+      }
+      
       throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,
                               "Error CREATEing SolrCore '" + name + "': " +
-                              ex.getMessage(), ex);
+                              ex.getMessage() + rootMsg, ex);
     }
   }
 
@@ -713,7 +732,9 @@ public class CoreAdminHandler extends Re
     boolean doPersist = false;
     String fileName = params.get(CoreAdminParams.FILE);
     if (fileName != null) {
-      File file = new File(coreContainer.getConfigFile().getParentFile(), fileName);
+      File file = new File(fileName);
+      if (!file.isAbsolute())
+        file = new File(coreContainer.getConfigFile().getParentFile(), fileName);
       coreContainer.persistFile(file);
       rsp.add("saved", file.getAbsolutePath());
       doPersist = false;

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/component/HttpShardHandler.java Wed Jul  3 23:26:32 2013
@@ -362,20 +362,18 @@ public class HttpShardHandler extends Sh
             Map<String, Replica> sliceShards = slice.getReplicasMap();
 
             // For now, recreate the | delimited list of equivalent servers
-            Set<String> liveNodes = clusterState.getLiveNodes();
             StringBuilder sliceShardsStr = new StringBuilder();
             boolean first = true;
-            for (ZkNodeProps nodeProps : sliceShards.values()) {
-              ZkCoreNodeProps coreNodeProps = new ZkCoreNodeProps(nodeProps);
-              if (!liveNodes.contains(coreNodeProps.getNodeName())
-                  || !coreNodeProps.getState().equals(
+            for (Replica replica : sliceShards.values()) {
+              if (!clusterState.liveNodesContain(replica.getNodeName())
+                  || !replica.getStr(ZkStateReader.STATE_PROP).equals(
                       ZkStateReader.ACTIVE)) continue;
               if (first) {
                 first = false;
               } else {
                 sliceShardsStr.append('|');
               }
-              String url = coreNodeProps.getCoreUrl();
+              String url = ZkCoreNodeProps.getCoreUrl(replica);
               if (url.startsWith("http://"))
                 url = url.substring(7);
               sliceShardsStr.append(url);

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/component/StatsValuesFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/component/StatsValuesFactory.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/component/StatsValuesFactory.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/component/StatsValuesFactory.java Wed Jul  3 23:26:32 2013
@@ -49,9 +49,7 @@ public class StatsValuesFactory {
     if (DoubleField.class.isInstance(fieldType) ||
         IntField.class.isInstance(fieldType) ||
         LongField.class.isInstance(fieldType) ||
-        ShortField.class.isInstance(fieldType) ||
         FloatField.class.isInstance(fieldType) ||
-        ByteField.class.isInstance(fieldType) ||
         TrieField.class.isInstance(fieldType) ||
         SortableDoubleField.class.isInstance(fieldType) ||
         SortableIntField.class.isInstance(fieldType) ||

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/loader/JsonLoader.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/loader/JsonLoader.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/loader/JsonLoader.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/loader/JsonLoader.java Wed Jul  3 23:26:32 2013
@@ -19,15 +19,20 @@ package org.apache.solr.handler.loader;
 import java.io.IOException;
 import java.io.Reader;
 import java.io.StringReader;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 
 import org.apache.commons.io.IOUtils;
+import org.apache.solr.common.params.SolrParams;
+import org.apache.solr.common.params.UpdateParams;
 import org.noggit.JSONParser;
 import org.noggit.ObjectBuilder;
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrInputDocument;
 import org.apache.solr.common.SolrInputField;
-import org.apache.solr.common.params.*;
 import org.apache.solr.common.util.ContentStream;
 import org.apache.solr.handler.RequestHandlerUtils;
 import org.apache.solr.handler.UpdateRequestHandler;
@@ -512,11 +517,13 @@ public class JsonLoader extends ContentS
         case JSONParser.STRING:
           return parser.getString();
         case JSONParser.LONG:
+          return parser.getLong();
         case JSONParser.NUMBER:
+          return parser.getDouble();
         case JSONParser.BIGNUMBER:
           return parser.getNumberChars().toString();
         case JSONParser.BOOLEAN:
-          return Boolean.toString(parser.getBoolean()); // for legacy reasons, single values s are expected to be strings
+          return parser.getBoolean();
         case JSONParser.NULL:
           parser.getNull();
           return null;

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/highlight/PostingsSolrHighlighter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/highlight/PostingsSolrHighlighter.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/highlight/PostingsSolrHighlighter.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/highlight/PostingsSolrHighlighter.java Wed Jul  3 23:26:32 2013
@@ -67,6 +67,7 @@ import org.apache.solr.util.plugin.Plugi
  *       &lt;str name="hl.bs.variant"&gt;&lt;/str&gt;
  *       &lt;str name="hl.bs.type"&gt;SENTENCE&lt;/str&gt;
  *       &lt;int name="hl.maxAnalyzedChars"&gt;10000&lt;/int&gt;
+ *       &lt;str name="hl.multiValuedSeparatorChar"&gt; &lt;/str&gt;
  *     &lt;/lst&gt;
  *   &lt;/requestHandler&gt;
  * </pre>
@@ -96,6 +97,7 @@ import org.apache.solr.util.plugin.Plugi
  *    <li>hl.bs.country (string) specifies country code for BreakIterator. default is empty string (root locale)
  *    <li>hl.bs.variant (string) specifies country code for BreakIterator. default is empty string (root locale)
  *    <li>hl.maxAnalyzedChars specifies how many characters at most will be processed in a document.
+ *    <li>hl.multiValuedSeparatorChar specifies the logical separator between values for multi-valued fields.
  *        NOTE: currently hl.maxAnalyzedChars cannot yet be specified per-field
  *  </ul>
  *  
@@ -167,6 +169,15 @@ public class PostingsSolrHighlighter ext
           String type = params.getFieldParam(field, HighlightParams.BS_TYPE);
           return parseBreakIterator(type, locale);
         }
+
+        @Override
+        protected char getMultiValuedSeparator(String field) {
+          String sep = params.getFieldParam(field, HighlightParams.MULTI_VALUED_SEPARATOR, " ");
+          if (sep.length() != 1) {
+            throw new IllegalArgumentException(HighlightParams.MULTI_VALUED_SEPARATOR + " must be exactly one character.");
+          }
+          return sep.charAt(0);
+        }
       };
       
       Map<String,String[]> snippets = highlighter.highlightFields(fieldNames, query, searcher, docIDs, maxPassages);

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/logging/LogWatcher.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/logging/LogWatcher.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/logging/LogWatcher.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/logging/LogWatcher.java Wed Jul  3 23:26:32 2013
@@ -137,7 +137,7 @@ public abstract class LogWatcher<E> {
       v.size = config.getInt(ConfigSolr.CfgProp.SOLR_LOGGING_WATCHER_SIZE, 50);
       v.threshold = config.get(ConfigSolr.CfgProp.SOLR_LOGGING_WATCHER_THRESHOLD, null);
       if (v.size > 0) {
-        log.info("Registering Log Listener");
+        log.info("Registering Log Listener [{}]", logWatcher.getName());
         logWatcher.registerListener(v);
       }
     }

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/request/SolrQueryRequest.java Wed Jul  3 23:26:32 2013
@@ -73,6 +73,9 @@ public interface SolrQueryRequest {
 
   /** The schema snapshot from core.getLatestSchema() at request creation. */
   public IndexSchema getSchema();
+  
+  /** Replaces the current schema snapshot with the latest from the core. */
+  public void updateSchemaToLatest();
 
   /**
    * Returns a string representing all the important parameters.

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/request/SolrQueryRequestBase.java Wed Jul  3 23:26:32 2013
@@ -42,8 +42,8 @@ import java.util.HashMap;
  */
 public abstract class SolrQueryRequestBase implements SolrQueryRequest {
   protected final SolrCore core;
-  protected final IndexSchema schema;
   protected final SolrParams origParams;
+  protected volatile IndexSchema schema;
   protected SolrParams params;
   protected Map<Object,Object> context;
   protected Iterable<ContentStream> streams;
@@ -112,6 +112,11 @@ public abstract class SolrQueryRequestBa
     return schema;
   }
 
+  @Override
+  public void updateSchemaToLatest() {
+    schema = core.getLatestSchema();
+  }
+
   /**
    * Frees resources associated with this request, this method <b>must</b>
    * be called when the object is no longer in use.

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/response/BinaryResponseWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/response/BinaryResponseWriter.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/response/BinaryResponseWriter.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/response/BinaryResponseWriter.java Wed Jul  3 23:26:32 2013
@@ -260,11 +260,9 @@ public class BinaryResponseWriter implem
     KNOWN_TYPES.add(BCDIntField.class);
     KNOWN_TYPES.add(BCDLongField.class);
     KNOWN_TYPES.add(BCDStrField.class);
-    KNOWN_TYPES.add(ByteField.class);
     KNOWN_TYPES.add(DateField.class);
     KNOWN_TYPES.add(DoubleField.class);
     KNOWN_TYPES.add(FloatField.class);
-    KNOWN_TYPES.add(ShortField.class);
     KNOWN_TYPES.add(IntField.class);
     KNOWN_TYPES.add(LongField.class);
     KNOWN_TYPES.add(SortableLongField.class);

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/DateField.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/DateField.java?rev=1499601&r1=1499600&r2=1499601&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/DateField.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/schema/DateField.java Wed Jul  3 23:26:32 2013
@@ -111,7 +111,7 @@ import java.util.*;
  * @see <a href="http://www.w3.org/TR/xmlschema-2/#dateTime">XML schema part 2</a>
  * @deprecated {@link TrieDateField} is recomended for all new schemas
  */
-public class DateField extends PrimitiveFieldType {
+public class DateField extends PrimitiveFieldType implements DateValueFieldType {
 
   public static TimeZone UTC = TimeZone.getTimeZone("UTC");