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/05/30 09:53:46 UTC

svn commit: r1487777 [38/50] - in /lucene/dev/branches/security: ./ dev-tools/ dev-tools/eclipse/dot.settings/ dev-tools/idea/.idea/ dev-tools/idea/.idea/libraries/ dev-tools/idea/lucene/replicator/ dev-tools/maven/ dev-tools/maven/lucene/ dev-tools/ma...

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=1487777&r1=1487776&r2=1487777&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 Thu May 30 07:53:18 2013
@@ -18,6 +18,7 @@ package org.apache.solr.core;
 
 import org.apache.lucene.index.IndexCommit;
 import org.apache.lucene.index.IndexDeletionPolicy;
+import org.apache.lucene.index.IndexWriter;
 import org.apache.lucene.store.Directory;
 import org.apache.solr.update.SolrIndexWriter;
 
@@ -32,11 +33,15 @@ import java.util.concurrent.atomic.Atomi
  * Provides features for looking up IndexCommit given a version. Allows reserving index
  * commit points for certain amounts of time to support features such as index replication
  * or snapshooting directly out of a live index directory.
- *
+ * <p/>
+ * <b>NOTE</b>: The {@link #clone()} method returns <tt>this</tt> in order to make
+ * this {@link IndexDeletionPolicy} instance trackable across {@link IndexWriter}
+ * instantiations. This is correct because each core has its own
+ * {@link IndexDeletionPolicy} and never has more than one open {@link IndexWriter}.
  *
  * @see org.apache.lucene.index.IndexDeletionPolicy
  */
-public class IndexDeletionPolicyWrapper implements IndexDeletionPolicy {
+public final class IndexDeletionPolicyWrapper extends IndexDeletionPolicy {
   private final IndexDeletionPolicy deletionPolicy;
   private volatile Map<Long, IndexCommit> solrVersionVsCommits = new ConcurrentHashMap<Long, IndexCommit>();
   private final Map<Long, Long> reserves = new ConcurrentHashMap<Long,Long>();
@@ -232,7 +237,9 @@ public class IndexDeletionPolicyWrapper 
         map.put(wrapper.delegate.getGeneration(), wrapper.delegate);
     }
     solrVersionVsCommits = map;
-    latestCommit = ((list.get(list.size() - 1)).delegate);
+    if (!list.isEmpty()) {
+      latestCommit = ((list.get(list.size() - 1)).delegate);
+    }
   }
 
   public static long getCommitTimestamp(IndexCommit commit) throws IOException {
@@ -244,5 +251,11 @@ public class IndexDeletionPolicyWrapper 
       return 0;
     }
   }
+
+  @Override
+  public IndexDeletionPolicy clone() {
+    // see class-level javadocs
+    return this;
+  }
 }
 

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/IndexReaderFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/IndexReaderFactory.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/IndexReaderFactory.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/IndexReaderFactory.java Thu May 30 07:53:18 2013
@@ -19,7 +19,6 @@ package org.apache.solr.core;
 import java.io.IOException;
 
 import org.apache.lucene.index.DirectoryReader;
-import org.apache.lucene.index.IndexReader;
 import org.apache.lucene.store.Directory;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.util.plugin.NamedListInitializedPlugin;
@@ -61,7 +60,7 @@ public abstract class IndexReaderFactory
    * @param indexDir indexDir index location
    * @param core {@link SolrCore} instance where this reader will be used. NOTE:
    * this SolrCore instance may not be fully configured yet, but basic things like
-   * {@link SolrCore#getCoreDescriptor()}, {@link SolrCore#getSchema()} and
+   * {@link SolrCore#getCoreDescriptor()}, {@link SolrCore#getLatestSchema()} and
    * {@link SolrCore#getSolrConfig()} are valid.
    * @return An IndexReader instance
    * @throws IOException If there is a low-level I/O error.

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/JmxMonitoredMap.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/JmxMonitoredMap.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/JmxMonitoredMap.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/JmxMonitoredMap.java Thu May 30 07:53:18 2013
@@ -210,7 +210,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/security/solr/core/src/java/org/apache/solr/core/MMapDirectoryFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/MMapDirectoryFactory.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/MMapDirectoryFactory.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/MMapDirectoryFactory.java Thu May 30 07:53:18 2013
@@ -66,4 +66,9 @@ public class MMapDirectoryFactory extend
     }
     return mapDirectory;
   }
+  
+  @Override
+  public boolean isAbsolute(String path) {
+    return new File(path).isAbsolute();
+  }
 }

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/NIOFSDirectoryFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/NIOFSDirectoryFactory.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/NIOFSDirectoryFactory.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/NIOFSDirectoryFactory.java Thu May 30 07:53:18 2013
@@ -16,13 +16,12 @@ package org.apache.solr.core;
  * limitations under the License.
  */
 
-import org.apache.lucene.store.Directory;
-import org.apache.lucene.store.NIOFSDirectory;
-import org.apache.solr.core.DirectoryFactory.DirContext;
-
 import java.io.File;
 import java.io.IOException;
 
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.NIOFSDirectory;
+
 
 /**
  * Factory to instantiate {@link org.apache.lucene.store.NIOFSDirectory}
@@ -35,4 +34,9 @@ public class NIOFSDirectoryFactory exten
     return new NIOFSDirectory(new File(path));
   }
   
+  @Override
+  public boolean isAbsolute(String path) {
+    return new File(path).isAbsolute();
+  }
+  
 }

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/NRTCachingDirectoryFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/NRTCachingDirectoryFactory.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/NRTCachingDirectoryFactory.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/NRTCachingDirectoryFactory.java Thu May 30 07:53:18 2013
@@ -25,7 +25,6 @@ import org.apache.lucene.store.FSDirecto
 import org.apache.lucene.store.NRTCachingDirectory;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.NamedList;
-import org.apache.solr.core.DirectoryFactory.DirContext;
 
 /**
  * Factory to instantiate {@link org.apache.lucene.store.NRTCachingDirectory}
@@ -54,5 +53,10 @@ public class NRTCachingDirectoryFactory 
   protected Directory create(String path, DirContext dirContext) throws IOException {
     return new NRTCachingDirectory(FSDirectory.open(new File(path)), maxMergeSizeMB, maxCachedMB);
   }
+  
+  @Override
+  public boolean isAbsolute(String path) {
+    return new File(path).isAbsolute();
+  }
 
 }

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/QuerySenderListener.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/QuerySenderListener.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/QuerySenderListener.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/QuerySenderListener.java Thu May 30 07:53:18 2013
@@ -42,7 +42,7 @@ public class QuerySenderListener extends
   public void newSearcher(SolrIndexSearcher newSearcher, SolrIndexSearcher currentSearcher) {
     final SolrIndexSearcher searcher = newSearcher;
     log.info("QuerySenderListener sending requests to " + newSearcher);
-    List<NamedList> allLists = (List<NamedList>)args.get("queries");
+    List<NamedList> allLists = (List<NamedList>)getArgs().get("queries");
     if (allLists == null) return;
     for (NamedList nlst : allLists) {
       SolrQueryRequest req = null;
@@ -54,14 +54,14 @@ public class QuerySenderListener extends
         if (params.get("distrib") == null) {
           params.add("distrib", false);
         }
-        req = new LocalSolrQueryRequest(core,params) {
+        req = new LocalSolrQueryRequest(getCore(),params) {
           @Override public SolrIndexSearcher getSearcher() { return searcher; }
           @Override public void close() { }
         };
 
         SolrQueryResponse rsp = new SolrQueryResponse();
         SolrRequestInfo.setRequestInfo(new SolrRequestInfo(req, rsp));
-        core.execute(core.getRequestHandler(req.getParams().get(CommonParams.QT)), req, rsp);
+        getCore().execute(getCore().getRequestHandler(req.getParams().get(CommonParams.QT)), req, rsp);
 
         // Retrieve the Document instances (not just the ids) to warm
         // the OS disk cache, and any Solr document cache.  Only the top

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SchemaCodecFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SchemaCodecFactory.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SchemaCodecFactory.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SchemaCodecFactory.java Thu May 30 07:53:18 2013
@@ -4,9 +4,9 @@ import org.apache.lucene.codecs.Codec;
 import org.apache.lucene.codecs.DocValuesFormat;
 import org.apache.lucene.codecs.PostingsFormat;
 import org.apache.lucene.codecs.lucene42.Lucene42Codec;
-import org.apache.solr.schema.IndexSchema;
-import org.apache.solr.schema.SchemaAware;
+import org.apache.solr.common.util.NamedList;
 import org.apache.solr.schema.SchemaField;
+import org.apache.solr.util.plugin.SolrCoreAware;
 
 /*
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -31,8 +31,10 @@ import org.apache.solr.schema.SchemaFiel
  * schema configuration.
  * @lucene.experimental
  */
-public class SchemaCodecFactory extends CodecFactory implements SchemaAware {
+public class SchemaCodecFactory extends CodecFactory implements SolrCoreAware {
   private Codec codec;
+  private volatile SolrCore core;
+  
   // TODO: we need to change how solr does this?
   // rather than a string like "Pulsing" you need to be able to pass parameters
   // and everything to a field in the schema, e.g. we should provide factories for 
@@ -42,11 +44,17 @@ public class SchemaCodecFactory extends 
   // how it constructs this from the XML... i don't care.
 
   @Override
-  public void inform(final IndexSchema schema) {
+  public void inform(SolrCore core) {
+    this.core = core;
+  }
+
+  @Override
+  public void init(NamedList args) {
+    super.init(args);
     codec = new Lucene42Codec() {
       @Override
       public PostingsFormat getPostingsFormatForField(String field) {
-        final SchemaField fieldOrNull = schema.getFieldOrNull(field);
+        final SchemaField fieldOrNull = core.getLatestSchema().getFieldOrNull(field);
         if (fieldOrNull == null) {
           throw new IllegalArgumentException("no such field " + field);
         }
@@ -58,7 +66,7 @@ public class SchemaCodecFactory extends 
       }
       @Override
       public DocValuesFormat getDocValuesFormatForField(String field) {
-        final SchemaField fieldOrNull = schema.getFieldOrNull(field);
+        final SchemaField fieldOrNull = core.getLatestSchema().getFieldOrNull(field);
         if (fieldOrNull == null) {
           throw new IllegalArgumentException("no such field " + field);
         }
@@ -73,7 +81,7 @@ public class SchemaCodecFactory extends 
 
   @Override
   public Codec getCodec() {
-    assert codec != null : "inform must be called first";
+    assert core != null : "inform must be called first";
     return codec;
   }
 }

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SimpleFSDirectoryFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SimpleFSDirectoryFactory.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SimpleFSDirectoryFactory.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SimpleFSDirectoryFactory.java Thu May 30 07:53:18 2013
@@ -16,13 +16,12 @@ package org.apache.solr.core;
  * limitations under the License.
  */
 
-import org.apache.lucene.store.Directory;
-import org.apache.lucene.store.SimpleFSDirectory;
-import org.apache.solr.core.DirectoryFactory.DirContext;
-
 import java.io.File;
 import java.io.IOException;
 
+import org.apache.lucene.store.Directory;
+import org.apache.lucene.store.SimpleFSDirectory;
+
 
 /**
  * Factory to instantiate {@link org.apache.lucene.store.SimpleFSDirectory}
@@ -35,4 +34,8 @@ public class SimpleFSDirectoryFactory ex
     return new SimpleFSDirectory(new File(path));
   }
 
+  @Override
+  public boolean isAbsolute(String path) {
+    return new File(path).isAbsolute();
+  }
 }

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrConfig.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrConfig.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrConfig.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/SolrConfig.java Thu May 30 07:53:18 2013
@@ -19,7 +19,9 @@ package org.apache.solr.core;
 
 import org.apache.solr.common.SolrException;
 import org.apache.solr.common.SolrException.ErrorCode;
+import org.apache.solr.schema.IndexSchemaFactory;
 import org.apache.solr.util.DOMUtil;
+import org.apache.solr.util.FileUtils;
 import org.apache.solr.util.RegexFileFilter;
 import org.apache.solr.handler.component.SearchComponent;
 import org.apache.solr.request.SolrRequestHandler;
@@ -49,6 +51,7 @@ import org.xml.sax.SAXException;
 import javax.xml.parsers.ParserConfigurationException;
 import javax.xml.xpath.XPathConstants;
 
+import java.io.File;
 import java.util.*;
 import java.util.regex.Pattern;
 import java.util.regex.Matcher;
@@ -140,11 +143,10 @@ public class SolrConfig extends Config {
       defaultIndexConfig = mainIndexConfig = null;
       indexConfigPrefix = "indexConfig";
     }
+    reopenReaders = getBool(indexConfigPrefix+"/reopenReaders", true);
     // Parse indexConfig section, using mainIndex as backup in case old config is used
     indexConfig = new SolrIndexConfig(this, "indexConfig", mainIndexConfig);
-
-    reopenReaders = getBool(indexConfigPrefix+"/reopenReaders", true);
-    
+   
     booleanQueryMaxClauseCount = getInt("query/maxBooleanClauses", BooleanQuery.getMaxClauseCount());
     log.info("Using Lucene MatchVersion: " + luceneMatchVersion);
 
@@ -214,9 +216,9 @@ public class SolrConfig extends Config {
      loadPluginInfo(QueryConverter.class,"queryConverter",true, true);
 
      // this is hackish, since it picks up all SolrEventListeners,
-     // regardless of when/how/why thye are used (or even if they are 
+     // regardless of when/how/why they are used (or even if they are 
      // declared outside of the appropriate context) but there's no nice 
-     // way arround that in the PluginInfo framework
+     // way around that in the PluginInfo framework
      loadPluginInfo(SolrEventListener.class, "//listener",false, true);
 
      loadPluginInfo(DirectoryFactory.class,"directoryFactory",false, true);
@@ -225,6 +227,7 @@ public class SolrConfig extends Config {
      loadPluginInfo(IndexReaderFactory.class,"indexReaderFactory",false, true);
      loadPluginInfo(UpdateRequestProcessorChain.class,"updateRequestProcessorChain",false, false);
      loadPluginInfo(UpdateLog.class,"updateHandler/updateLog",false, false);
+     loadPluginInfo(IndexSchemaFactory.class,"schemaFactory",false, true);
 
      updateHandlerInfo = loadUpdatehandlerInfo();
 
@@ -451,6 +454,7 @@ public class SolrConfig extends Config {
     if (nodes == null || nodes.getLength() == 0) return;
     
     log.info("Adding specified lib dirs to ClassLoader");
+    SolrResourceLoader loader = getResourceLoader();
     
     try {
       for (int i = 0; i < nodes.getLength(); i++) {
@@ -459,19 +463,25 @@ public class SolrConfig extends Config {
         String baseDir = DOMUtil.getAttr(node, "dir");
         String path = DOMUtil.getAttr(node, "path");
         if (null != baseDir) {
-          // :TODO: add support for a simpler 'glob' mutually eclusive of regex
+          // :TODO: add support for a simpler 'glob' mutually exclusive of regex
           String regex = DOMUtil.getAttr(node, "regex");
           FileFilter filter = (null == regex) ? null : new RegexFileFilter(regex);
-          getResourceLoader().addToClassLoader(baseDir, filter);
+          loader.addToClassLoader(baseDir, filter, false);
         } else if (null != path) {
-          getResourceLoader().addToClassLoader(path);
+          final File file = FileUtils.resolvePath(new File(loader.getInstanceDir()), path);
+          loader.addToClassLoader(file.getParent(), new FileFilter() {
+            @Override
+            public boolean accept(File pathname) {
+              return pathname.equals(file);
+            }
+          }, false);
         } else {
           throw new RuntimeException(
               "lib: missing mandatory attributes: 'dir' or 'path'");
         }
       }
     } finally {
-      getResourceLoader().reloadLuceneSPI();
+      loader.reloadLuceneSPI();
     }
   }
 }

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=1487777&r1=1487776&r2=1487777&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 Thu May 30 07:53:18 2013
@@ -62,6 +62,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.cloud.Slice;
 import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.params.CommonParams.EchoParamStyle;
 import org.apache.solr.common.params.SolrParams;
@@ -90,12 +91,14 @@ import org.apache.solr.response.PythonRe
 import org.apache.solr.response.QueryResponseWriter;
 import org.apache.solr.response.RawResponseWriter;
 import org.apache.solr.response.RubyResponseWriter;
+import org.apache.solr.response.SchemaXmlResponseWriter;
 import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.response.XMLResponseWriter;
 import org.apache.solr.response.transform.TransformerFactory;
 import org.apache.solr.schema.FieldType;
 import org.apache.solr.schema.IndexSchema;
-import org.apache.solr.schema.SchemaAware;
+import org.apache.solr.schema.IndexSchemaFactory;
+import org.apache.solr.schema.SimilarityFactory;
 import org.apache.solr.search.QParserPlugin;
 import org.apache.solr.search.SolrFieldCacheMBean;
 import org.apache.solr.search.SolrIndexSearcher;
@@ -145,7 +148,7 @@ public final class SolrCore implements S
 
   private final SolrConfig solrConfig;
   private final SolrResourceLoader resourceLoader;
-  private final IndexSchema schema;
+  private volatile IndexSchema schema;
   private final String dataDir;
   private final UpdateHandler updateHandler;
   private final SolrCoreState solrCoreState;
@@ -204,16 +207,19 @@ public final class SolrCore implements S
    * @since solr 1.3
    */
   public String getSchemaResource() {
-    return schema.getResourceName();
+    return getLatestSchema().getResourceName();
   }
 
-  /**
-   * Gets the schema object used by this core instance.
-   */
-  public IndexSchema getSchema() { 
+  /** @return the latest snapshot of the schema used by this core instance. */
+  public IndexSchema getLatestSchema() { 
     return schema;
   }
   
+  /** Sets the latest schema snapshot to be used by this core instance. */
+  public void setLatestSchema(IndexSchema replacementSchema) {
+    schema = replacementSchema;
+  }
+  
   public String getDataDir() {
     return dataDir;
   }
@@ -392,11 +398,9 @@ public final class SolrCore implements S
   public SolrCore reload(SolrResourceLoader resourceLoader, SolrCore prev) throws IOException,
       ParserConfigurationException, SAXException {
     
-    SolrConfig config = new SolrConfig(resourceLoader,
-        getSolrConfig().getName(), null);
+    SolrConfig config = new SolrConfig(resourceLoader, getSolrConfig().getName(), null);
     
-    IndexSchema schema = new IndexSchema(config,
-        getSchema().getResourceName(), null);
+    IndexSchema schema = IndexSchemaFactory.buildIndexSchema(getLatestSchema().getResourceName(), config);
     
     solrCoreState.increfSolrCoreState();
     
@@ -406,10 +410,10 @@ public final class SolrCore implements S
     }
     
     SolrCore core = new SolrCore(getName(), getDataDir(), config,
-        schema, coreDescriptor, updateHandler, prev);
+        schema, coreDescriptor, updateHandler, this.solrDelPolicy, prev);
     core.solrDelPolicy = this.solrDelPolicy;
     
-    core.getUpdateHandler().getSolrCoreState().newIndexWriter(core, false, false);
+    core.getUpdateHandler().getSolrCoreState().newIndexWriter(core, false);
     
     core.getSearcher(true, false, null, true);
     
@@ -419,7 +423,8 @@ public final class SolrCore implements S
 
   // gets a non-caching searcher
   public SolrIndexSearcher newSearcher(String name) throws IOException {
-    return new SolrIndexSearcher(this, getNewIndexDir(), schema, getSolrConfig().indexConfig, name, false, directoryFactory);
+    return new SolrIndexSearcher(this, getNewIndexDir(), getLatestSchema(), getSolrConfig().indexConfig, 
+                                 name, false, directoryFactory);
   }
 
 
@@ -459,7 +464,7 @@ public final class SolrCore implements S
       boolean indexExists = getDirectoryFactory().exists(indexDir);
       boolean firstTime;
       synchronized (SolrCore.class) {
-        firstTime = dirs.add(new File(indexDir).getCanonicalPath());
+        firstTime = dirs.add(getDirectoryFactory().normalize(indexDir));
       }
       boolean removeLocks = solrConfig.unlockOnStartup;
 
@@ -485,7 +490,6 @@ public final class SolrCore implements S
                   "Index locked for write for core " + name);
             }
             
-            directoryFactory.release(dir);
           }
         } finally {
           directoryFactory.release(dir);
@@ -497,7 +501,8 @@ public final class SolrCore implements S
         log.warn(logid+"Solr index directory '" + new File(indexDir) + "' doesn't exist."
                 + " Creating new index...");
 
-        SolrIndexWriter writer = SolrIndexWriter.create("SolrCore.initIndex", indexDir, getDirectoryFactory(), true, schema, solrConfig.indexConfig, solrDelPolicy, codec, false);
+        SolrIndexWriter writer = SolrIndexWriter.create("SolrCore.initIndex", indexDir, getDirectoryFactory(), true, 
+                                                        getLatestSchema(), solrConfig.indexConfig, solrDelPolicy, codec);
         writer.close();
       }
 
@@ -616,7 +621,7 @@ public final class SolrCore implements S
    * @since solr 1.3
    */
   public SolrCore(String name, String dataDir, SolrConfig config, IndexSchema schema, CoreDescriptor cd) {
-    this(name, dataDir, config, schema, cd, null, null);
+    this(name, dataDir, config, schema, cd, null, null, null);
   }
 
 
@@ -652,32 +657,40 @@ public final class SolrCore implements S
    *
    *@since solr 1.3
    */
-  public SolrCore(String name, String dataDir, SolrConfig config, IndexSchema schema, CoreDescriptor cd, UpdateHandler updateHandler, SolrCore prev) {
+  public SolrCore(String name, String dataDir, SolrConfig config, IndexSchema schema, CoreDescriptor cd, UpdateHandler updateHandler, IndexDeletionPolicyWrapper delPolicy, SolrCore prev) {
     coreDescriptor = cd;
     this.setName( name );
     resourceLoader = config.getResourceLoader();
-    if (dataDir == null){
-      if(cd.usingDefaultDataDir()) {
-        dataDir = config.getDataDir();
-      }
-      if(dataDir == null) {
+    this.solrConfig = config;
+    
+    if (updateHandler == null) {
+      initDirectoryFactory();
+    }
+    
+    if (dataDir == null) {
+      if (cd.usingDefaultDataDir()) dataDir = config.getDataDir();
+      if (dataDir == null) {
         dataDir = cd.getDataDir();
+        try {
+          if (!directoryFactory.isAbsolute(dataDir)) {
+            dataDir = directoryFactory.normalize(SolrResourceLoader
+                .normalizeDir(cd.getInstanceDir()) + dataDir);
+          }
+        } catch (IOException e) {
+          throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, null, e);
+        }
       }
     }
 
     dataDir = SolrResourceLoader.normalizeDir(dataDir);
     log.info(logid+"Opening new SolrCore at " + resourceLoader.getInstanceDir() + ", dataDir="+dataDir);
 
-    if (schema==null) {
-      schema = new IndexSchema(config, IndexSchema.DEFAULT_SCHEMA_FILE, null);
-    }
-
     if (null != cd && null != cd.getCloudDescriptor()) {
       // we are evidently running in cloud mode.  
       //
       // In cloud mode, version field is required for correct consistency
       // ideally this check would be more fine grained, and individual features
-      // would assert it when they initialize, but DistribuedUpdateProcessor
+      // would assert it when they initialize, but DistributedUpdateProcessor
       // is currently a big ball of wax that does more then just distributing
       // updates (ie: partial document updates), so it needs to work in no cloud
       // mode as well, and can't assert version field support on init.
@@ -701,9 +714,17 @@ public final class SolrCore implements S
 
     infoRegistry.put("fieldCache", new SolrFieldCacheMBean());
 
+    if (schema==null) {
+      schema = IndexSchemaFactory.buildIndexSchema(IndexSchema.DEFAULT_SCHEMA_FILE, config);
+    }
     this.schema = schema;
+    final SimilarityFactory similarityFactory = schema.getSimilarityFactory(); 
+    if (similarityFactory instanceof SolrCoreAware) {
+      // Similarity needs SolrCore before inform() is called on all registered SolrCoreAware listeners below
+      ((SolrCoreAware)similarityFactory).inform(this);
+    }
+
     this.dataDir = dataDir;
-    this.solrConfig = config;
     this.startTime = System.currentTimeMillis();
     this.maxWarmingSearchers = config.maxWarmingSearchers;
 
@@ -715,8 +736,10 @@ public final class SolrCore implements S
       
       initListeners();
       
-      if (updateHandler == null) {
+      if (delPolicy == null) {
         initDeletionPolicy();
+      } else {
+        this.solrDelPolicy = delPolicy;
       }
       
       this.codec = initCodec(solrConfig, schema);
@@ -823,6 +846,12 @@ public final class SolrCore implements S
     // from the core.
     resourceLoader.inform(infoRegistry);
     
+    CoreContainer cc = cd.getCoreContainer();
+    
+    if (cc != null && cc.isZooKeeperAware() && Slice.CONSTRUCTION.equals(cd.getCloudDescriptor().getShardState())) {
+      // set update log to buffer before publishing the core
+      getUpdateHandler().getUpdateLog().bufferUpdates();
+    }
     // For debugging   
 //    numOpens.incrementAndGet();
 //    openHandles.put(this, new RuntimeException("unclosed core - name:" + getName() + " refs: " + refCount.get()));
@@ -842,8 +871,10 @@ public final class SolrCore implements S
         }
       };
     }
-    if (factory instanceof SchemaAware) {
-      ((SchemaAware)factory).inform(schema);
+    if (factory instanceof SolrCoreAware) {
+      // CodecFactory needs SolrCore before inform() is called on all registered
+      // SolrCoreAware listeners, at the end of the SolrCore constructor
+      ((SolrCoreAware)factory).inform(this);
     } else {
       for (FieldType ft : schema.getFieldTypes().values()) {
         if (null != ft.getPostingsFormat()) {
@@ -939,6 +970,7 @@ public final class SolrCore implements S
     if (count > 0) return; // close is called often, and only actually closes if nothing is using it.
     if (count < 0) {
       log.error("Too many close [count:{}] on {}. Please report this exception to solr-user@lucene.apache.org", count, this );
+      assert false : "Too many closes on SolrCore";
       return;
     }
     log.info(logid+" CLOSING SolrCore " + this);
@@ -969,12 +1001,13 @@ public final class SolrCore implements S
       SolrException.log(log,e);
     }
     
+    boolean coreStateClosed = false;
     try {
       if (solrCoreState != null) {
         if (updateHandler instanceof IndexWriterCloser) {
-          solrCoreState.decrefSolrCoreState((IndexWriterCloser) updateHandler);
+          coreStateClosed = solrCoreState.decrefSolrCoreState((IndexWriterCloser) updateHandler);
         } else {
-          solrCoreState.decrefSolrCoreState(null);
+          coreStateClosed = solrCoreState.decrefSolrCoreState(null);
         }
       }
     } catch (Throwable e) {
@@ -1000,13 +1033,12 @@ public final class SolrCore implements S
       SolrException.log(log,e);
     }
     
-    if (solrCoreState != null) { // bad startup case
-      if (solrCoreState.getSolrCoreStateRefCnt() == 0) {
-        try {
-          directoryFactory.close();
-        } catch (Throwable t) {
-          SolrException.log(log, t);
-        }
+    if (coreStateClosed) {
+      
+      try {
+        directoryFactory.close();
+      } catch (Throwable t) {
+        SolrException.log(log, t);
       }
       
     }
@@ -1349,20 +1381,24 @@ public final class SolrCore implements S
         DirectoryReader newReader;
         DirectoryReader currentReader = newestSearcher.get().getIndexReader();
 
-        if (updateHandlerReopens) {
-          // SolrCore.verbose("start reopen from",previousSearcher,"writer=",writer);
-          RefCounted<IndexWriter> writer = getUpdateHandler().getSolrCoreState().getIndexWriter(this);
-          try {
-            newReader = DirectoryReader.openIfChanged(currentReader, writer.get(), true);
-          } finally {
+        // SolrCore.verbose("start reopen from",previousSearcher,"writer=",writer);
+        
+        RefCounted<IndexWriter> writer = getUpdateHandler().getSolrCoreState()
+            .getIndexWriter(null);
+        try {
+          if (writer != null) {
+            newReader = DirectoryReader.openIfChanged(currentReader,
+                writer.get(), true);
+          } else {
+            // verbose("start reopen without writer, reader=", currentReader);
+            newReader = DirectoryReader.openIfChanged(currentReader);
+            
+            // verbose("reopen result", newReader);
+          }
+        } finally {
+          if (writer != null) {
             writer.decref();
           }
-
-        } else {
-          // verbose("start reopen without writer, reader=", currentReader);
-          newReader = DirectoryReader.openIfChanged(currentReader);
-     
-          // verbose("reopen result", newReader);
         }
 
         if (newReader == null) {
@@ -1377,7 +1413,8 @@ public final class SolrCore implements S
         }
 
        // for now, turn off caches if this is for a realtime reader (caches take a little while to instantiate)
-        tmp = new SolrIndexSearcher(this, newIndexDir, schema, (realtime ? "realtime":"main"), newReader, true, !realtime, true, directoryFactory);
+        tmp = new SolrIndexSearcher(this, newIndexDir, getLatestSchema(), getSolrConfig().indexConfig, 
+            (realtime ? "realtime":"main"), newReader, true, !realtime, true, directoryFactory);
 
       } else {
         // newestSearcher == null at this point
@@ -1387,11 +1424,13 @@ public final class SolrCore implements S
           // so that we pick up any uncommitted changes and so we don't go backwards
           // in time on a core reload
           DirectoryReader newReader = newReaderCreator.call();
-          tmp = new SolrIndexSearcher(this, newIndexDir, schema, (realtime ? "realtime":"main"), newReader, true, !realtime, true, directoryFactory);
+          tmp = new SolrIndexSearcher(this, newIndexDir, getLatestSchema(), getSolrConfig().indexConfig, 
+              (realtime ? "realtime":"main"), newReader, true, !realtime, true, directoryFactory);
         } else {
          // normal open that happens at startup
         // verbose("non-reopen START:");
-        tmp = new SolrIndexSearcher(this, newIndexDir, schema, getSolrConfig().indexConfig, "main", true, directoryFactory);
+        tmp = new SolrIndexSearcher(this, newIndexDir, getLatestSchema(), getSolrConfig().indexConfig,
+                                    "main", true, directoryFactory);
         // verbose("non-reopen DONE: searcher=",tmp);
         }
       }
@@ -1885,6 +1924,7 @@ public final class SolrCore implements S
     m.put("raw", new RawResponseWriter());
     m.put("javabin", new BinaryResponseWriter());
     m.put("csv", new CSVResponseWriter());
+    m.put("schema.xml", new SchemaXmlResponseWriter());
     DEFAULT_RESPONSE_WRITERS = Collections.unmodifiableMap(m);
   }
   

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=1487777&r1=1487776&r2=1487777&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 Thu May 30 07:53:18 2013
@@ -41,7 +41,7 @@ import java.util.Locale;
  *
  * @see org.apache.lucene.index.IndexDeletionPolicy
  */
-public class SolrDeletionPolicy implements IndexDeletionPolicy, NamedListInitializedPlugin {
+public class SolrDeletionPolicy extends IndexDeletionPolicy implements NamedListInitializedPlugin {
   public static Logger log = LoggerFactory.getLogger(SolrCore.class);
 
   private String maxCommitAge = null;
@@ -73,46 +73,19 @@ public class SolrDeletionPolicy implemen
     }
   }
 
-  static String str(IndexCommit commit) {
-    StringBuilder sb = new StringBuilder();
-    try {
-      sb.append("commit{");
-
-      Directory dir = commit.getDirectory();
-
-      if (dir instanceof FSDirectory) {
-        FSDirectory fsd = (FSDirectory) dir;
-        sb.append("dir=").append(fsd.getDirectory());
-      } else {
-        sb.append("dir=").append(dir);
-      }
-
-      sb.append(",segFN=").append(commit.getSegmentsFileName());
-      sb.append(",generation=").append(commit.getGeneration());
-      sb.append(",filenames=").append(commit.getFileNames());
-    } catch (Exception e) {
-      sb.append(e);
-    }
-    return sb.toString();
-  }
-
-  static String str(List commits) {
-    StringBuilder sb = new StringBuilder();
-    sb.append("num=").append(commits.size());
-
-    for (IndexCommit commit : (List<IndexCommit>) commits) {
-      sb.append("\n\t");
-      sb.append(str(commit));
-    }
-    return sb.toString();
-  }
-
   /**
    * Internal use for Lucene... do not explicitly call.
    */
   @Override
   public void onInit(List commits) throws IOException {
-    log.info("SolrDeletionPolicy.onInit: commits:" + str(commits));
+    // SOLR-4547: log basic data at INFO, add filenames at DEBUG.
+    if (commits.isEmpty()) {
+      return;
+    }
+    log.info("SolrDeletionPolicy.onInit: commits: {}",
+        new CommitsLoggingInfo(commits));
+    log.debug("SolrDeletionPolicy.onInit: commits: {}",
+        new CommitsLoggingDebug(commits));
     updateCommits((List<IndexCommit>) commits);
   }
 
@@ -121,10 +94,61 @@ public class SolrDeletionPolicy implemen
    */
   @Override
   public void onCommit(List commits) throws IOException {
-    log.info("SolrDeletionPolicy.onCommit: commits:" + str(commits));
+    // 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);
   }
 
+  private static class CommitsLoggingInfo {
+    private List<IndexCommit> commits;
+
+    public CommitsLoggingInfo(List<IndexCommit> commits) {
+      this.commits = commits;
+    }
+
+    public final String toString() {
+      StringBuilder sb = new StringBuilder();
+      sb.append("num=").append(commits.size());
+      for (IndexCommit c : commits) {
+        sb.append("\n\tcommit{");
+        appendDetails(sb, c);
+        sb.append("}");
+      }
+      // add an end brace
+      return sb.toString();
+    }
+
+    protected void appendDetails(StringBuilder sb, IndexCommit c) {
+      Directory dir = c.getDirectory();
+      if (dir instanceof FSDirectory) {
+        FSDirectory fsd = (FSDirectory) dir;
+        sb.append("dir=").append(fsd.getDirectory());
+      } else {
+        sb.append("dir=").append(dir);
+      }
+      sb.append(",segFN=").append(c.getSegmentsFileName());
+      sb.append(",generation=").append(c.getGeneration());
+    }
+  }
+
+  private static class CommitsLoggingDebug extends CommitsLoggingInfo {
+    public CommitsLoggingDebug(List<IndexCommit> commits) {
+      super(commits);
+    }
+
+    protected void appendDetails(StringBuilder sb, IndexCommit c) {
+      super.appendDetails(sb, c);
+      try {
+        sb.append(",filenames=");
+        sb.append(c.getFileNames());
+      } catch (IOException e) {
+        sb.append(e);
+      }
+    }
+  }
 
   private void updateCommits(List<IndexCommit> commits) {
     // to be safe, we should only call delete on a commit point passed to us
@@ -135,12 +159,10 @@ public class SolrDeletionPolicy implemen
     synchronized (this) {
       long maxCommitAgeTimeStamp = -1L;
       IndexCommit newest = commits.get(commits.size() - 1);
-      try {
-        log.info("newest commit = " + newest.getGeneration() + newest.getFileNames().toString());
-      } catch (IOException e1) {
-        throw new RuntimeException();
-      }
-
+      // SOLR-4547: Removed the filenames from this log entry because this
+      // method is only called from methods that have just logged them
+      // at DEBUG.
+      log.info("newest commit generation = " + newest.getGeneration());
       int singleSegKept = (newest.getSegmentCount() == 1) ? 1 : 0;
       int totalKept = 1;
 

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=1487777&r1=1487776&r2=1487777&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 Thu May 30 07:53:18 2013
@@ -17,6 +17,7 @@
 
 package org.apache.solr.core;
 
+import java.io.Closeable;
 import java.io.File;
 import java.io.FileFilter;
 import java.io.FileInputStream;
@@ -37,10 +38,13 @@ import org.apache.lucene.analysis.util.T
 import org.apache.lucene.codecs.Codec;
 import org.apache.lucene.codecs.PostingsFormat;
 import org.apache.lucene.codecs.DocValuesFormat;
+import org.apache.lucene.util.IOUtils;
 import org.apache.lucene.analysis.util.WordlistLoader;
 import org.apache.solr.common.ResourceLoader;
 import org.apache.solr.handler.admin.CoreAdminHandler;
 import org.apache.solr.handler.component.ShardHandlerFactory;
+import org.apache.solr.schema.ManagedIndexSchemaFactory;
+import org.apache.solr.schema.SimilarityFactory;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -66,7 +70,7 @@ import org.apache.solr.search.QParserPlu
 /**
  * @since solr 1.3
  */ 
-public class SolrResourceLoader implements ResourceLoader
+public class SolrResourceLoader implements ResourceLoader,Closeable
 {
   public static final Logger log = LoggerFactory.getLogger(SolrResourceLoader.class);
 
@@ -111,7 +115,7 @@ public class SolrResourceLoader implemen
     }
     
     this.classLoader = createClassLoader(null, parent);
-    addToClassLoader("./lib/", null);
+    addToClassLoader("./lib/", null, true);
     reloadLuceneSPI();
     this.coreProperties = coreProperties;
   }
@@ -135,46 +139,41 @@ public class SolrResourceLoader implemen
    * only be called prior to using this ResourceLoader to get any resources, otherwise
    * it's behavior will be non-deterministic. You also have to {link @reloadLuceneSPI}
    * before using this ResourceLoader.
+   * 
+   * <p>This method will quietly ignore missing or non-directory <code>baseDir</code>
+   *  folder. 
    *
    * @param baseDir base directory whose children (either jars or directories of
    *                classes) will be in the classpath, will be resolved relative
    *                the instance dir.
    * @param filter The filter files must satisfy, if null all files will be accepted.
+   * @param quiet  Be quiet if baseDir does not point to a directory or if no file is 
+   *               left after applying the filter. 
    */
-  void addToClassLoader(final String baseDir, final FileFilter filter) {
+  void addToClassLoader(final String baseDir, final FileFilter filter, boolean quiet) {
     File base = FileUtils.resolvePath(new File(getInstanceDir()), baseDir);
-    this.classLoader = replaceClassLoader(classLoader, base, filter);
-  }
-  
-  /**
-   * Adds the specific file/dir specified to the ClassLoader used by this
-   * ResourceLoader.  This method <b>MUST</b>
-   * only be called prior to using this ResourceLoader to get any resources, otherwise
-   * it's behavior will be non-deterministic. You also have to {link #reloadLuceneSPI()}
-   * before using this ResourceLoader.
-   *
-   * @param path A jar file (or directory of classes) to be added to the classpath,
-   *             will be resolved relative the instance dir.
-   */
-  void addToClassLoader(final String path) {
-    final File file = FileUtils.resolvePath(new File(getInstanceDir()), path);
-    if (file.canRead()) {
-      this.classLoader = replaceClassLoader(classLoader, file.getParentFile(),
-                                            new FileFilter() {
-                                              @Override
-                                              public boolean accept(File pathname) {
-                                                return pathname.equals(file);
-                                              }
-                                            });
+    if (base != null && base.exists() && base.isDirectory()) {
+      File[] files = base.listFiles(filter);
+      if (files == null || files.length == 0) {
+        if (!quiet) {
+          log.warn("No files added to classloader from lib: "
+                   + baseDir + " (resolved as: " + base.getAbsolutePath() + ").");
+        }
+      } else {
+        this.classLoader = replaceClassLoader(classLoader, base, filter);
+      }
     } else {
-      log.error("Can't find (or read) file to add to classloader: " + file);
+      if (!quiet) {
+        log.warn("Can't find (or read) directory to add to classloader: "
+            + baseDir + " (resolved as: " + base.getAbsolutePath() + ").");
+      }
     }
   }
   
   /**
    * Reloads all Lucene SPI implementations using the new classloader.
-   * This method must be called after {@link #addToClassLoader(String)}
-   * and {@link #addToClassLoader(String,FileFilter)} before using
+   * This method must be called after {@link #addToClassLoader(String, FileFilter, boolean)}
+   * and {@link #addToClassLoader(String,FileFilter,boolean)} before using
    * this ResourceLoader.
    */
   void reloadLuceneSPI() {
@@ -209,7 +208,9 @@ public class SolrResourceLoader implemen
           SolrException.log(log, "Can't add element to classloader: " + files[j], e);
         }
       }
-      return URLClassLoader.newInstance(elements, oldLoader.getParent());
+      ClassLoader oldParent = oldLoader.getParent();
+      IOUtils.closeWhileHandlingException(oldLoader); // best effort
+      return URLClassLoader.newInstance(elements, oldParent);
     }
     // are we still here?
     return oldLoader;
@@ -372,7 +373,12 @@ public class SolrResourceLoader implemen
   // Using this pattern, legacy analysis components from previous Solr versions are identified and delegated to SPI loader:
   private static final Pattern legacyAnalysisPattern = 
       Pattern.compile("((\\Q"+base+".analysis.\\E)|(\\Q"+project+".\\E))([\\p{L}_$][\\p{L}\\p{N}_$]+?)(TokenFilter|Filter|Tokenizer|CharFilter)Factory");
-      
+
+  @Override
+  public <T> Class<? extends T> findClass(String cname, Class<T> expectedType) {
+    return findClass(cname, expectedType, empty);
+  }
+  
   /**
    * This method loads a class either with it's FQN or a short-name (solr.class-simplename or class-simplename).
    * It tries to load the class with the name that is given first and if it fails, it tries all the known
@@ -381,7 +387,7 @@ public class SolrResourceLoader implemen
    * is loaded using a shortname.
    *
    * @param cname The name or the short name of the class.
-   * @param subpackages the packages to be tried if the cnams starts with solr.
+   * @param subpackages the packages to be tried if the cname starts with solr.
    * @return the loaded class. An exception is thrown if it fails
    */
   public <T> Class<? extends T> findClass(String cname, Class<T> expectedType, String... subpackages) {
@@ -707,11 +713,14 @@ public class SolrResourceLoader implemen
     awareCompatibility = new HashMap<Class, Class[]>();
     awareCompatibility.put( 
       SolrCoreAware.class, new Class[] {
-        SolrRequestHandler.class,
+        CodecFactory.class,
+        ManagedIndexSchemaFactory.class,
         QueryResponseWriter.class,
         SearchComponent.class,
-        UpdateRequestProcessorFactory.class,
-        ShardHandlerFactory.class
+        ShardHandlerFactory.class,
+        SimilarityFactory.class,
+        SolrRequestHandler.class,
+        UpdateRequestProcessorFactory.class
       }
     );
 
@@ -750,4 +759,9 @@ public class SolrResourceLoader implemen
     }
     throw new SolrException( SolrException.ErrorCode.SERVER_ERROR, builder.toString() );
   }
+
+  @Override
+  public void close() throws IOException {
+    IOUtils.close(classLoader);
+  }
 }

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/StandardDirectoryFactory.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/StandardDirectoryFactory.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/StandardDirectoryFactory.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/core/StandardDirectoryFactory.java Thu May 30 07:53:18 2013
@@ -25,6 +25,7 @@ import org.apache.lucene.store.FSDirecto
 import org.apache.lucene.store.IOContext;
 import org.apache.lucene.store.NRTCachingDirectory;
 import org.apache.lucene.store.RateLimitedDirectoryWrapper;
+import org.apache.solr.core.CachingDirectoryFactory.CacheValue;
 
 /**
  * Directory provider which mimics original Solr 
@@ -43,7 +44,16 @@ public class StandardDirectoryFactory ex
   
   @Override
   public String normalize(String path) throws IOException {
-    return new File(path).getCanonicalPath();
+    String cpath = new File(path).getCanonicalPath();
+    
+    return super.normalize(cpath);
+  }
+  
+  @Override
+  public boolean exists(String path) throws IOException {
+    // we go by the persistent storage ... 
+    File dirFile = new File(path);
+    return dirFile.canRead() && dirFile.list().length > 0;
   }
   
   public boolean isPersistent() {
@@ -51,20 +61,14 @@ public class StandardDirectoryFactory ex
   }
   
   @Override
-  public void remove(Directory dir) throws IOException {
-    CacheValue val = byDirectoryCache.get(dir);
-    if (val == null) {
-      throw new IllegalArgumentException("Unknown directory " + dir);
-    }
-    File dirFile = new File(val.path);
-    FileUtils.deleteDirectory(dirFile);
+  public boolean isAbsolute(String path) {
+    // back compat
+    return new File(path).isAbsolute();
   }
   
-
   @Override
-  public void remove(String path) throws IOException {
-    String fullPath = new File(path).getAbsolutePath();
-    File dirFile = new File(fullPath);
+  protected void removeDirectory(CacheValue cacheValue) throws IOException {
+    File dirFile = new File(cacheValue.path);
     FileUtils.deleteDirectory(dirFile);
   }
   

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/AnalysisRequestHandlerBase.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/AnalysisRequestHandlerBase.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/AnalysisRequestHandlerBase.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/AnalysisRequestHandlerBase.java Thu May 30 07:53:18 2013
@@ -211,7 +211,7 @@ public abstract class AnalysisRequestHan
     final AttributeSource[] tokens = tokenList.toArray(new AttributeSource[tokenList.size()]);
     
     // sort the tokens by absoulte position
-    ArrayUtil.mergeSort(tokens, new Comparator<AttributeSource>() {
+    ArrayUtil.timSort(tokens, new Comparator<AttributeSource>() {
       @Override
       public int compare(AttributeSource a, AttributeSource b) {
         return arrayCompare(

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/FieldAnalysisRequestHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/FieldAnalysisRequestHandler.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/FieldAnalysisRequestHandler.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/FieldAnalysisRequestHandler.java Thu May 30 07:53:18 2013
@@ -30,9 +30,10 @@ import org.apache.solr.schema.FieldType;
 import org.apache.solr.schema.IndexSchema;
 import org.apache.commons.io.IOUtils;
 
-import java.util.*;
 import java.io.Reader;
 import java.io.IOException;
+import java.util.Arrays;
+import java.util.Set;
 
 /**
  * Provides the ability to specify multiple field types and field names in the same request. Expected parameters:
@@ -96,7 +97,7 @@ public class FieldAnalysisRequestHandler
   @Override
   protected NamedList doAnalysis(SolrQueryRequest req) throws Exception {
     FieldAnalysisRequest analysisRequest = resolveAnalysisRequest(req);
-    IndexSchema indexSchema = req.getCore().getSchema();
+    IndexSchema indexSchema = req.getSchema();
     return handleAnalysisRequest(analysisRequest, indexSchema);
   }
 

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/ReplicationHandler.java Thu May 30 07:53:18 2013
@@ -78,7 +78,7 @@ import org.slf4j.LoggerFactory;
 
 /**
  * <p> A Handler which provides a REST API for replication and serves replication requests from Slaves. <p/> </p>
- * <p>When running on the master, it provides the following commands <ol> <li>Get the current replicatable index version
+ * <p>When running on the master, it provides the following commands <ol> <li>Get the current replicable index version
  * (command=indexversion)</li> <li>Get the list of files for a given index version
  * (command=filelist&amp;indexversion=&lt;VERSION&gt;)</li> <li>Get full or a part (chunk) of a given index or a config
  * file (command=filecontent&amp;file=&lt;FILE_NAME&gt;) You can optionally specify an offset and length to get that
@@ -96,6 +96,38 @@ public class ReplicationHandler extends 
   private static final Logger LOG = LoggerFactory.getLogger(ReplicationHandler.class.getName());
   SolrCore core;
 
+  private static final class CommitVersionInfo {
+    public final long version;
+    public final long generation;
+    private CommitVersionInfo(long g, long v) {
+      generation = g;
+      version = v;
+    }
+    /**
+     * builds a CommitVersionInfo data for the specified IndexCommit.  
+     * Will never be null, ut version and generation may be zero if 
+     * there are problems extracting them from the commit data
+     */
+    public static CommitVersionInfo build(IndexCommit commit) {
+      long generation = commit.getGeneration();
+      long version = 0;
+      try {
+        final Map<String,String> commitData = commit.getUserData();
+        String commitTime = commitData.get(SolrIndexWriter.COMMIT_TIME_MSEC_KEY);
+        if (commitTime != null) {
+          try {
+            version = Long.parseLong(commitTime);
+          } catch (NumberFormatException e) {
+            LOG.warn("Version in commitData was not formated correctly: " + commitTime, e);
+          }
+        }
+      } catch (IOException e) {
+        LOG.warn("Unable to get version from commitData, commit: " + commit, e);
+      }
+      return new CommitVersionInfo(generation, version);
+    }
+  }
+
   private SnapPuller snapPuller;
 
   private ReentrantLock snapPullLock = new ReentrantLock();
@@ -180,12 +212,16 @@ public class ReplicationHandler extends 
         return;
       }
       final SolrParams paramsCopy = new ModifiableSolrParams(solrParams);
-      new Thread() {
+      Thread puller = new Thread("explicit-fetchindex-cmd") {
         @Override
         public void run() {
           doFetch(paramsCopy, false);
         }
-      }.start();
+      };
+      puller.start();
+      if (solrParams.getBool(WAIT, false)) {
+        puller.join();
+      }
       rsp.add(STATUS, OK_STATUS);
     } else if (command.equalsIgnoreCase(CMD_DISABLE_POLL)) {
       if (snapPuller != null){
@@ -497,23 +533,20 @@ public class ReplicationHandler extends 
     return "$URL$";
   }
 
-  private long[] getIndexVersion() {
-    long version[] = new long[2];
+  /** 
+   * returns the CommitVersionInfo for the current searcher, or null on error.
+   */
+  private CommitVersionInfo getIndexVersion() {
+    CommitVersionInfo v = null;
     RefCounted<SolrIndexSearcher> searcher = core.getSearcher();
     try {
-      final IndexCommit commit = searcher.get().getIndexReader().getIndexCommit();
-      final Map<String,String> commitData = commit.getUserData();
-      String commitTime = commitData.get(SolrIndexWriter.COMMIT_TIME_MSEC_KEY);
-      if (commitTime != null) {
-        version[0] = Long.parseLong(commitTime);
-      }
-      version[1] = commit.getGeneration();
+      v = CommitVersionInfo.build(searcher.get().getIndexReader().getIndexCommit());
     } catch (IOException e) {
-      LOG.warn("Unable to get index version : ", e);
+      LOG.warn("Unable to get index commit: ", e);
     } finally {
       searcher.decref();
     }
-    return version;
+    return v;
   }
 
   @Override
@@ -522,9 +555,9 @@ public class ReplicationHandler extends 
     NamedList list = super.getStatistics();
     if (core != null) {
       list.add("indexSize", NumberUtils.readableSize(getIndexSize()));
-      long[] versionGen = getIndexVersion();
-      list.add("indexVersion", versionGen[0]);
-      list.add(GENERATION, versionGen[1]);
+      CommitVersionInfo vInfo = getIndexVersion();
+      list.add("indexVersion", null == vInfo ? 0 : vInfo.version);
+      list.add(GENERATION, null == vInfo ? 0 : vInfo.generation);
 
       list.add("indexPath", core.getIndexDir());
       list.add("isMaster", String.valueOf(isMaster));
@@ -578,10 +611,10 @@ public class ReplicationHandler extends 
     details.add(CMD_SHOW_COMMITS, getCommits());
     details.add("isMaster", String.valueOf(isMaster));
     details.add("isSlave", String.valueOf(isSlave));
-    long[] versionAndGeneration = getIndexVersion();
-    details.add("indexVersion", versionAndGeneration[0]);
-    details.add(GENERATION, versionAndGeneration[1]);
-
+    CommitVersionInfo vInfo = getIndexVersion();
+    details.add("indexVersion", null == vInfo ? 0 : vInfo.version);
+    details.add(GENERATION, null == vInfo ? 0 : vInfo.generation);
+    
     IndexCommit commit = indexCommitPoint;  // make a copy so it won't change
 
     if (isMaster) {
@@ -591,7 +624,9 @@ public class ReplicationHandler extends 
     }
 
     if (isMaster && commit != null) {
-      master.add("replicatableGeneration", commit.getGeneration());
+      CommitVersionInfo repCommitInfo = CommitVersionInfo.build(commit);
+      master.add("replicableVersion", repCommitInfo.version);
+      master.add("replicableGeneration", repCommitInfo.generation);
     }
 
     SnapPuller snapPuller = tempSnapPuller;
@@ -1298,4 +1333,15 @@ public class ReplicationHandler extends 
   public static final String NUMBER_BACKUPS_TO_KEEP_REQUEST_PARAM = "numberToKeep";
   
   public static final String NUMBER_BACKUPS_TO_KEEP_INIT_PARAM = "maxNumberOfBackups";
+
+  /** 
+   * Boolean param for tests that can be specified when using 
+   * {@link #CMD_FETCH_INDEX} to force the current request to block until 
+   * the fetch is complete.  <b>NOTE:</b> This param is not advised for 
+   * non-test code, since the the durration of the fetch for non-trivial
+   * indexes will likeley cause the request to time out.
+   *
+   * @lucene.internal
+   */
+  public static final String WAIT = "wait";
 }

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=1487777&r1=1487776&r2=1487777&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 Thu May 30 07:53:18 2013
@@ -84,7 +84,6 @@ import org.apache.solr.common.params.Sol
 import org.apache.solr.common.util.ExecutorUtil;
 import org.apache.solr.common.util.FastInputStream;
 import org.apache.solr.common.util.NamedList;
-import org.apache.solr.core.CachingDirectoryFactory.CloseListener;
 import org.apache.solr.core.DirectoryFactory;
 import org.apache.solr.core.DirectoryFactory.DirContext;
 import org.apache.solr.core.IndexDeletionPolicyWrapper;
@@ -219,6 +218,7 @@ public class SnapPuller {
           return;
         }
         try {
+          LOG.debug("Polling for index modifications");
           executorStartTime = System.currentTimeMillis();
           replicationHandler.doFetch(null, false);
         } catch (Exception e) {
@@ -382,10 +382,9 @@ public class SnapPuller {
 
       tmpIndexDir = core.getDirectoryFactory().get(tmpIndex, DirContext.DEFAULT, core.getSolrConfig().indexConfig.lockType);
       
-      // make sure it's the newest known index dir...
-      indexDirPath = core.getNewIndexDir();
+      // cindex dir...
+      indexDirPath = core.getIndexDir();
       indexDir = core.getDirectoryFactory().get(indexDirPath, DirContext.DEFAULT, core.getSolrConfig().indexConfig.lockType);
-      Directory oldDirectory = null;
 
       try {
         
@@ -407,6 +406,16 @@ public class SnapPuller {
             successfulInstall = moveIndexFiles(tmpIndexDir, indexDir);
           }
           if (successfulInstall) {
+            if (isFullCopyNeeded) {
+              // let the system know we are changing dir's and the old one
+              // may be closed
+              if (indexDir != null) {
+                LOG.info("removing old index directory " + indexDir);
+                core.getDirectoryFactory().doneWithDirectory(indexDir);
+                core.getDirectoryFactory().remove(indexDir);
+              }
+            }
+            
             LOG.info("Configuration files are modified, core will be reloaded");
             logReplicationTimeAndConfFiles(modifiedConfFiles, successfulInstall);//write to a file time of replication and conf files.
             reloadCore();
@@ -416,12 +425,6 @@ public class SnapPuller {
           if (isFullCopyNeeded) {
             successfulInstall = modifyIndexProps(tmpIdxDirName);
             deleteTmpIdxDir =  false;
-            RefCounted<IndexWriter> iw = core.getUpdateHandler().getSolrCoreState().getIndexWriter(core);
-            try {
-               oldDirectory = iw.get().getDirectory();
-            } finally {
-              iw.decref();
-            }
           } else {
             successfulInstall = moveIndexFiles(tmpIndexDir, indexDir);
           }
@@ -429,39 +432,16 @@ public class SnapPuller {
             logReplicationTimeAndConfFiles(modifiedConfFiles, successfulInstall);
           }
         }
-        
-        if (isFullCopyNeeded) {
-          // we have to do this before commit
-          final Directory freezeIndexDir = indexDir;
-          final String freezeIndexDirPath = indexDirPath;
-          core.getDirectoryFactory().addCloseListener(oldDirectory, new CloseListener(){
-
-            @Override
-            public void preClose() {
-              LOG.info("removing old index files " + freezeIndexDir);
-              if (core.getDirectoryFactory().exists(freezeIndexDirPath)) {
-                DirectoryFactory.empty(freezeIndexDir);
-              }
-            }
-            
-            @Override
-            public void postClose() {
-              LOG.info("removing old index directory " + freezeIndexDir);
-              try {
-                core.getDirectoryFactory().remove(freezeIndexDir);
-              } catch (IOException e) {
-                SolrException.log(LOG, "Error removing directory " + freezeIndexDir, e);
-              }
-            }
-            
-          });
-        }
 
         if (successfulInstall) {
           if (isFullCopyNeeded) {
             // let the system know we are changing dir's and the old one
             // may be closed
-            core.getDirectoryFactory().doneWithDirectory(oldDirectory);
+            if (indexDir != null) {
+              LOG.info("removing old index directory " + indexDir);
+              core.getDirectoryFactory().doneWithDirectory(indexDir);
+              core.getDirectoryFactory().remove(indexDir);
+            }
           }
           openNewWriterAndSearcher(isFullCopyNeeded);
         }
@@ -477,13 +457,6 @@ public class SnapPuller {
         throw new InterruptedException("Index fetch interrupted");
       } catch (Exception e) {
         throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Index fetch failed : ", e);
-      } finally {
-        if (deleteTmpIdxDir) {
-          LOG.info("removing temporary index download directory files " + tmpIndexDir);
-          if (tmpIndex != null && core.getDirectoryFactory().exists(tmpIndex)) {
-            DirectoryFactory.empty(tmpIndexDir);
-          }
-        } 
       }
     } finally {
       try {
@@ -500,16 +473,19 @@ public class SnapPuller {
         stop = false;
         fsyncException = null;
       } finally {
-        if (tmpIndexDir != null) {
-          core.getDirectoryFactory().release(tmpIndexDir);
-        }
         if (deleteTmpIdxDir && tmpIndexDir != null) {
           try {
+            core.getDirectoryFactory().doneWithDirectory(tmpIndexDir);
             core.getDirectoryFactory().remove(tmpIndexDir);
           } catch (IOException e) {
             SolrException.log(LOG, "Error removing directory " + tmpIndexDir, e);
           }
         }
+        
+        if (tmpIndexDir != null) {
+          core.getDirectoryFactory().release(tmpIndexDir);
+        }
+        
         if (indexDir != null) {
           core.getDirectoryFactory().release(indexDir);
         }
@@ -643,13 +619,11 @@ public class SnapPuller {
     SolrQueryRequest req = new LocalSolrQueryRequest(solrCore,
         new ModifiableSolrParams());
     // reboot the writer on the new index and get a new searcher
-    solrCore.getUpdateHandler().newIndexWriter(isFullCopyNeeded, false);
+    solrCore.getUpdateHandler().newIndexWriter(isFullCopyNeeded);
     
     RefCounted<SolrIndexSearcher> searcher = null;
     IndexCommit commitPoint;
     try {
-      // first try to open an NRT searcher so that the new
-      // IndexWriter is registered with the reader
       Future[] waitSearcher = new Future[1];
       searcher = solrCore.getSearcher(true, true, waitSearcher, true);
       if (waitSearcher[0] != null) {
@@ -674,13 +648,14 @@ public class SnapPuller {
     
   }
 
-
   /**
    * All the files are copied to a temp dir first
    */
   private String createTempindexDir(SolrCore core, String tmpIdxDirName) {
-    File tmpIdxDir = new File(core.getDataDir(), tmpIdxDirName);
-    return tmpIdxDir.toString();
+    // TODO: there should probably be a DirectoryFactory#concatPath(parent, name)
+    // or something
+    String tmpIdxDir = core.getDataDir() + tmpIdxDirName;
+    return tmpIdxDir;
   }
 
   private void reloadCore() {
@@ -690,7 +665,7 @@ public class SnapPuller {
         try {
           solrCore.getCoreDescriptor().getCoreContainer().reload(solrCore.getName());
         } catch (Exception e) {
-          LOG.error("Could not restart core ", e);
+          LOG.error("Could not reload core ", e);
         }
       }
     }.start();
@@ -823,21 +798,53 @@ public class SnapPuller {
   }
 
   /**
+   * Make file list 
+   */
+  private List<File> makeTmpConfDirFileList(File dir, List<File> fileList) {
+    File[] files = dir.listFiles();
+    for (File file : files) {
+      if (file.isFile()) {
+        fileList.add(file);
+      } else if (file.isDirectory()) {
+        fileList = makeTmpConfDirFileList(file, fileList);
+      }
+    }
+    return fileList;
+  }
+  
+  /**
    * The conf files are copied to the tmp dir to the conf dir. A backup of the old file is maintained
    */
   private void copyTmpConfFiles2Conf(File tmpconfDir) {
+    boolean status = false;
     File confDir = new File(solrCore.getResourceLoader().getConfigDir());
-    for (File file : tmpconfDir.listFiles()) {
-      File oldFile = new File(confDir, file.getName());
+    for (File file : makeTmpConfDirFileList(tmpconfDir, new ArrayList<File>())) {
+      File oldFile = new File(confDir, file.getPath().substring(tmpconfDir.getPath().length(), file.getPath().length()));
+      if (!oldFile.getParentFile().exists()) {
+        status = oldFile.getParentFile().mkdirs();
+        if (status) {
+        } else {
+          throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
+                  "Unable to mkdirs: " + oldFile.getParentFile());
+        }
+      }
       if (oldFile.exists()) {
-        File backupFile = new File(confDir, oldFile.getName() + "." + getDateAsStr(new Date(oldFile.lastModified())));
-        boolean status = oldFile.renameTo(backupFile);
+        File backupFile = new File(oldFile.getPath() + "." + getDateAsStr(new Date(oldFile.lastModified())));
+        if (!backupFile.getParentFile().exists()) {
+          status = backupFile.getParentFile().mkdirs();
+          if (status) {
+          } else {
+            throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
+                    "Unable to mkdirs: " + backupFile.getParentFile());
+          }
+        }
+        status = oldFile.renameTo(backupFile);
         if (!status) {
           throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,
                   "Unable to rename: " + oldFile + " to: " + backupFile);
         }
       }
-      boolean status = file.renameTo(oldFile);
+      status = file.renameTo(oldFile);
       if (status) {
       } else {
         throw new SolrException(SolrException.ErrorCode.SERVER_ERROR,

Modified: lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java?rev=1487777&r1=1487776&r2=1487777&view=diff
==============================================================================
--- lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java (original)
+++ lucene/dev/branches/security/solr/core/src/java/org/apache/solr/handler/admin/CollectionsHandler.java Thu May 30 07:53:18 2013
@@ -40,6 +40,7 @@ import org.apache.solr.common.params.Cor
 import org.apache.solr.common.params.ModifiableSolrParams;
 import org.apache.solr.common.params.SolrParams;
 import org.apache.solr.common.util.NamedList;
+import org.apache.solr.common.util.SimpleOrderedMap;
 import org.apache.solr.core.CoreContainer;
 import org.apache.solr.handler.RequestHandlerBase;
 import org.apache.solr.request.SolrQueryRequest;
@@ -102,28 +103,42 @@ public class CollectionsHandler extends 
     if (a != null) {
       action = CollectionAction.get(a);
     }
-    if (action != null) {
-      switch (action) {
-        case CREATE: {
-          this.handleCreateAction(req, rsp);
-          break;
-        }
-        case DELETE: {
-          this.handleDeleteAction(req, rsp);
-          break;
-        }
-        case RELOAD: {
-          this.handleReloadAction(req, rsp);
-          break;
-        }
-        case SYNCSHARD: {
-          this.handleSyncShardAction(req, rsp);
+    if (action == null) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Unknown action: " + a);
+    }
+    
+    switch (action) {
+      case CREATE: {
+        this.handleCreateAction(req, rsp);
+        break;
+      }
+      case DELETE: {
+        this.handleDeleteAction(req, rsp);
+        break;
+      }
+      case RELOAD: {
+        this.handleReloadAction(req, rsp);
+        break;
+      }
+      case SYNCSHARD: {
+        this.handleSyncShardAction(req, rsp);
+        break;
+      }
+      case CREATEALIAS: {
+        this.handleCreateAliasAction(req, rsp);
+        break;
+      }
+      case DELETEALIAS: {
+        this.handleDeleteAliasAction(req, rsp);
+        break;
+      }
+        case SPLITSHARD:  {
+          this.handleSplitShardAction(req, rsp);
           break;
         }
-        
-        default: {
+
+      default: {
           throw new RuntimeException("Unknown action: " + action);
-        }
       }
     }
 
@@ -141,6 +156,11 @@ public class CollectionsHandler extends 
     if (event.getBytes() != null) {
       SolrResponse response = SolrResponse.deserialize(event.getBytes());
       rsp.getValues().addAll(response.getResponse());
+      SimpleOrderedMap exp = (SimpleOrderedMap) response.getResponse().get("exception");
+      if (exp != null) {
+        Integer code = (Integer) exp.get("rspCode");
+        rsp.setException(new SolrException(code != null && code != -1 ? ErrorCode.getErrorCode(code) : ErrorCode.SERVER_ERROR, (String)exp.get("msg")));
+      }
     } else {
       if (System.currentTimeMillis() - time >= DEFAULT_ZK_TIMEOUT) {
         throw new SolrException(ErrorCode.SERVER_ERROR, operation
@@ -187,7 +207,30 @@ public class CollectionsHandler extends 
     reqSyncShard.setCoreName(nodeProps.getCoreName());
     server.request(reqSyncShard);
   }
-
+  
+  private void handleCreateAliasAction(SolrQueryRequest req,
+      SolrQueryResponse rsp) throws Exception {
+    log.info("Create alias action : " + req.getParamString());
+    String name = req.getParams().required().get("name");
+    String collections = req.getParams().required().get("collections");
+    
+    ZkNodeProps m = new ZkNodeProps(Overseer.QUEUE_OPERATION,
+        OverseerCollectionProcessor.CREATEALIAS, "name", name, "collections",
+        collections);
+    
+    handleResponse(OverseerCollectionProcessor.CREATEALIAS, m, rsp);
+  }
+  
+  private void handleDeleteAliasAction(SolrQueryRequest req,
+      SolrQueryResponse rsp) throws Exception {
+    log.info("Delete alias action : " + req.getParamString());
+    String name = req.getParams().required().get("name");
+    
+    ZkNodeProps m = new ZkNodeProps(Overseer.QUEUE_OPERATION,
+        OverseerCollectionProcessor.DELETEALIAS, "name", name);
+    
+    handleResponse(OverseerCollectionProcessor.CREATEALIAS, m, rsp);
+  }
 
   private void handleDeleteAction(SolrQueryRequest req, SolrQueryResponse rsp) throws KeeperException, InterruptedException {
     log.info("Deleting Collection : " + req.getParamString());
@@ -200,7 +243,6 @@ public class CollectionsHandler extends 
     handleResponse(OverseerCollectionProcessor.DELETECOLLECTION, m, rsp);
   }
 
-
   // very simple currently, you can pass a template collection, and the new collection is created on
   // every node the template collection is on
   // there is a lot more to add - you should also be able to create with an explicit server list
@@ -239,6 +281,26 @@ public class CollectionsHandler extends 
     handleResponse(OverseerCollectionProcessor.CREATECOLLECTION, m, rsp);
   }
 
+  private void handleSplitShardAction(SolrQueryRequest req, SolrQueryResponse rsp) throws KeeperException, InterruptedException {
+    log.info("Splitting shard : " + req.getParamString());
+    String name = req.getParams().required().get("collection");
+    // TODO : add support for multiple shards
+    String shard = req.getParams().required().get("shard");
+    // TODO : add support for shard range
+
+    Map<String,Object> props = new HashMap<String,Object>();
+    props.put(Overseer.QUEUE_OPERATION, OverseerCollectionProcessor.SPLITSHARD);
+    props.put("collection", name);
+    props.put(ZkStateReader.SHARD_ID_PROP, shard);
+
+    ZkNodeProps m = new ZkNodeProps(props);
+
+    // todo remove this hack
+    DEFAULT_ZK_TIMEOUT *= 5;
+    handleResponse(OverseerCollectionProcessor.SPLITSHARD, m, rsp);
+    DEFAULT_ZK_TIMEOUT /= 5;
+  }
+
   public static ModifiableSolrParams params(String... params) {
     ModifiableSolrParams msp = new ModifiableSolrParams();
     for (int i=0; i<params.length; i+=2) {