You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@lucene.apache.org by mi...@apache.org on 2015/02/09 00:53:25 UTC

svn commit: r1658277 [17/38] - in /lucene/dev/branches/lucene6005: ./ dev-tools/ dev-tools/idea/solr/contrib/dataimporthandler/ dev-tools/idea/solr/contrib/velocity/ dev-tools/maven/lucene/replicator/ dev-tools/maven/solr/ dev-tools/maven/solr/contrib/...

Modified: lucene/dev/branches/lucene6005/solr/contrib/velocity/src/java/org/apache/solr/response/VelocityResponseWriter.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/contrib/velocity/src/java/org/apache/solr/response/VelocityResponseWriter.java?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/contrib/velocity/src/java/org/apache/solr/response/VelocityResponseWriter.java (original)
+++ lucene/dev/branches/lucene6005/solr/contrib/velocity/src/java/org/apache/solr/response/VelocityResponseWriter.java Sun Feb  8 23:53:14 2015
@@ -17,46 +17,187 @@
 
 package org.apache.solr.response;
 
+import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.StringWriter;
 import java.io.Writer;
 import java.nio.charset.StandardCharsets;
+import java.util.ArrayList;
+import java.util.Locale;
 import java.util.Properties;
+import java.util.ResourceBundle;
 
+import org.apache.commons.lang.StringUtils;
 import org.apache.solr.client.solrj.SolrResponse;
 import org.apache.solr.client.solrj.response.QueryResponse;
 import org.apache.solr.client.solrj.response.SolrResponseBase;
+import org.apache.solr.common.params.CommonParams;
 import org.apache.solr.common.util.NamedList;
+import org.apache.solr.core.SolrCore;
 import org.apache.solr.request.SolrQueryRequest;
+import org.apache.solr.util.plugin.SolrCoreAware;
 import org.apache.velocity.Template;
 import org.apache.velocity.VelocityContext;
 import org.apache.velocity.app.VelocityEngine;
 import org.apache.velocity.runtime.RuntimeConstants;
+import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
+import org.apache.velocity.tools.ConversionUtils;
 import org.apache.velocity.tools.generic.ComparisonDateTool;
+import org.apache.velocity.tools.generic.ContextTool;
 import org.apache.velocity.tools.generic.DisplayTool;
 import org.apache.velocity.tools.generic.EscapeTool;
 import org.apache.velocity.tools.generic.ListTool;
 import org.apache.velocity.tools.generic.MathTool;
 import org.apache.velocity.tools.generic.NumberTool;
+import org.apache.velocity.tools.generic.ResourceTool;
 import org.apache.velocity.tools.generic.SortTool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
-public class VelocityResponseWriter implements QueryResponseWriter {
+public class VelocityResponseWriter implements QueryResponseWriter, SolrCoreAware {
+  // init param names, these are _only_ loaded at init time (no per-request control of these)
+  //   - multiple different named writers could be created with different init params
+  public static final String TEMPLATE_BASE_DIR = "template.base.dir";
+  public static final String PARAMS_RESOURCE_LOADER_ENABLED = "params.resource.loader.enabled";
+  public static final String SOLR_RESOURCE_LOADER_ENABLED = "solr.resource.loader.enabled";
+  public static final String PROPERTIES_FILE = "init.properties.file";
+
+  // request param names
+  public static final String TEMPLATE = "v.template";
+  public static final String LAYOUT = "v.layout";
+  public static final String LAYOUT_ENABLED = "v.layout.enabled";
+  public static final String CONTENT_TYPE = "v.contentType";
+  public static final String JSON = "v.json";
+  public static final String LOCALE = "v.locale";
+
+  public static final String TEMPLATE_EXTENSION = ".vm";
+  public static final String DEFAULT_CONTENT_TYPE = "text/html;charset=UTF-8";
+  public static final String JSON_CONTENT_TYPE = "application/json;charset=UTF-8";
+
+  private File fileResourceLoaderBaseDir;
+  private boolean paramsResourceLoaderEnabled;
+  private boolean solrResourceLoaderEnabled;
+  private String initPropertiesFileName;  // used just to hold from init() to inform()
+
+  private static final Logger log = LoggerFactory.getLogger(VelocityResponseWriter.class);
+  private static final SolrVelocityLogger velocityLogger = new SolrVelocityLogger(log);
+  private Properties velocityInitProps = new Properties();
 
-  // TODO: maybe pass this Logger to the template for logging from there?
-//  private static final Logger log = LoggerFactory.getLogger(VelocityResponseWriter.class);
+  @Override
+  public void init(NamedList args) {
+    fileResourceLoaderBaseDir = null;
+    String templateBaseDir = (String) args.get(TEMPLATE_BASE_DIR);
+
+    if (templateBaseDir != null && !templateBaseDir.isEmpty()) {
+      fileResourceLoaderBaseDir = new File(templateBaseDir).getAbsoluteFile();
+      if (!fileResourceLoaderBaseDir.exists()) { // "*not* exists" condition!
+        log.warn(TEMPLATE_BASE_DIR + " specified does not exist: " + fileResourceLoaderBaseDir);
+        fileResourceLoaderBaseDir = null;
+      } else {
+        if (!fileResourceLoaderBaseDir.isDirectory()) { // "*not* a directory" condition
+          log.warn(TEMPLATE_BASE_DIR + " specified is not a directory: " + fileResourceLoaderBaseDir);
+          fileResourceLoaderBaseDir = null;
+        }
+      }
+    }
+
+    // params resource loader: off by default
+    Boolean prle = args.getBooleanArg(PARAMS_RESOURCE_LOADER_ENABLED);
+    paramsResourceLoaderEnabled = (null == prle ? false : prle);
+
+    // solr resource loader: on by default
+    Boolean srle = args.getBooleanArg(SOLR_RESOURCE_LOADER_ENABLED);
+    solrResourceLoaderEnabled = (null == srle ? true : srle);
+
+    initPropertiesFileName = (String) args.get(PROPERTIES_FILE);
+  }
+
+  @Override
+  public void inform(SolrCore core) {
+    // need to leverage SolrResourceLoader, so load init.properties.file here instead of init()
+    if (initPropertiesFileName != null) {
+      InputStream is = null;
+      try {
+        velocityInitProps.load(new InputStreamReader(core.getResourceLoader().openResource(initPropertiesFileName), StandardCharsets.UTF_8));
+      } catch (IOException e) {
+        log.warn("Error loading " + PROPERTIES_FILE + " specified property file: " + initPropertiesFileName, e);
+      }
+    }
+  }
+
+  @Override
+  public String getContentType(SolrQueryRequest request, SolrQueryResponse response) {
+    String contentType = request.getParams().get(CONTENT_TYPE);
+
+    // Use the v.contentType specified, or either of the default content types depending on the presence of v.json
+    return (contentType != null) ? contentType : ((request.getParams().get(JSON) == null) ? DEFAULT_CONTENT_TYPE : JSON_CONTENT_TYPE);
+  }
 
   @Override
   public void write(Writer writer, SolrQueryRequest request, SolrQueryResponse response) throws IOException {
-    VelocityEngine engine = getEngine(request);  // TODO: have HTTP headers available for configuring engine
+    VelocityEngine engine = createEngine(request);  // TODO: have HTTP headers available for configuring engine
 
     Template template = getTemplate(engine, request);
 
+    VelocityContext context = createContext(request, response);
+    context.put("engine", engine);  // for $engine.resourceExists(...)
+
+    String layoutTemplate = request.getParams().get(LAYOUT);
+    boolean layoutEnabled = request.getParams().getBool(LAYOUT_ENABLED, true) && layoutTemplate != null;
+
+    String jsonWrapper = request.getParams().get(JSON);
+    boolean wrapResponse = layoutEnabled || jsonWrapper != null;
+
+    // create output
+    if (!wrapResponse) {
+      // straight-forward template/context merge to output
+      template.merge(context, writer);
+    }
+    else {
+      // merge to a string buffer, then wrap with layout and finally as JSON
+      StringWriter stringWriter = new StringWriter();
+      template.merge(context, stringWriter);
+
+      if (layoutEnabled) {
+        context.put("content", stringWriter.toString());
+        stringWriter = new StringWriter();
+        try {
+          engine.getTemplate(layoutTemplate + TEMPLATE_EXTENSION).merge(context, stringWriter);
+        } catch (Exception e) {
+          throw new IOException(e.getMessage());
+        }
+      }
+
+      if (jsonWrapper != null) {
+        writer.write(jsonWrapper + "(");
+        writer.write(getJSONWrap(stringWriter.toString()));
+        writer.write(')');
+      } else {  // using a layout, but not JSON wrapping
+        writer.write(stringWriter.toString());
+      }
+    }
+  }
+
+  private VelocityContext createContext(SolrQueryRequest request, SolrQueryResponse response) {
     VelocityContext context = new VelocityContext();
 
     context.put("request", request);
 
+    // Register useful Velocity "tools"
+    context.put("log", log);   // TODO: add test
+    context.put("esc", new EscapeTool());
+    context.put("date", new ComparisonDateTool());
+    context.put("list", new ListTool());
+    context.put("math", new MathTool());
+    context.put("number", new NumberTool());
+    context.put("sort", new SortTool());
+    context.put("display", new DisplayTool());
+    context.put("resource", new SolrVelocityResourceTool(
+        request.getCore().getSolrConfig().getResourceLoader().getClassLoader(),
+        request.getParams().get(LOCALE)));
+
     // Turn the SolrQueryResponse into a SolrResponse.
     // QueryResponse has lots of conveniences suitable for a view
     // Problem is, which SolrResponse class to use?
@@ -65,14 +206,15 @@ public class VelocityResponseWriter impl
     // create a new instance.  But for now the implementation simply
     // uses QueryResponse, and if it chokes in a known way, fall back
     // to bare bones SolrResponseBase.
-    // TODO: Can this writer know what the handler class is?  With echoHandler=true it can get its string name at least
+    // Can this writer know what the handler class is?  With echoHandler=true it can get its string name at least
     SolrResponse rsp = new QueryResponse();
     NamedList<Object> parsedResponse = BinaryResponseWriter.getParsedResponse(request, response);
     try {
       rsp.setResponse(parsedResponse);
 
       // page only injected if QueryResponse works
-      context.put("page", new PageTool(request, response));  // page tool only makes sense for a SearchHandler request... *sigh*
+      context.put("page", new PageTool(request, response));  // page tool only makes sense for a SearchHandler request
+      context.put("debug",((QueryResponse)rsp).getDebugMap());
     } catch (ClassCastException e) {
       // known edge case where QueryResponse's extraction assumes "response" is a SolrDocumentList
       // (AnalysisRequestHandler emits a "response")
@@ -81,81 +223,69 @@ public class VelocityResponseWriter impl
     }
     context.put("response", rsp);
 
-    // Velocity context tools - TODO: make these pluggable
-    context.put("esc", new EscapeTool());
-    context.put("date", new ComparisonDateTool());
-    context.put("list", new ListTool());
-    context.put("math", new MathTool());
-    context.put("number", new NumberTool());
-    context.put("sort", new SortTool());
-    context.put("display", new DisplayTool());
-
-    context.put("engine", engine);  // for $engine.resourceExists(...)
-
-    String layout_template = request.getParams().get("v.layout");
-    String json_wrapper = request.getParams().get("v.json");
-    boolean wrap_response = (layout_template != null) || (json_wrapper != null);
-
-    // create output, optionally wrap it into a json object
-    if (wrap_response) {
-      StringWriter stringWriter = new StringWriter();
-      template.merge(context, stringWriter);
-
-      if (layout_template != null) {
-        context.put("content", stringWriter.toString());
-        stringWriter = new StringWriter();
-        try {
-          engine.getTemplate(layout_template + ".vm").merge(context, stringWriter);
-        } catch (Exception e) {
-          throw new IOException(e.getMessage());
-        }
-      }
-
-      if (json_wrapper != null) {
-        writer.write(request.getParams().get("v.json") + "(");
-        writer.write(getJSONWrap(stringWriter.toString()));
-        writer.write(')');
-      } else {  // using a layout, but not JSON wrapping
-        writer.write(stringWriter.toString());
-      }
-    } else {
-      template.merge(context, writer);
-    }
+    return context;
   }
 
-  private VelocityEngine getEngine(SolrQueryRequest request) {
+  private VelocityEngine createEngine(SolrQueryRequest request) {
     VelocityEngine engine = new VelocityEngine();
 
-    engine.setProperty("params.resource.loader.instance", new SolrParamResourceLoader(request));
-    SolrVelocityResourceLoader resourceLoader =
-        new SolrVelocityResourceLoader(request.getCore().getSolrConfig().getResourceLoader());
-    engine.setProperty("solr.resource.loader.instance", resourceLoader);
-    engine.setProperty(RuntimeConstants.RESOURCE_LOADER, "params,solr");
+    // route all Velocity logging through Solr's logging facility
+    engine.setProperty(RuntimeConstants.RUNTIME_LOG_LOGSYSTEM, velocityLogger);
 
-    // TODO: Externalize Velocity properties
-    String propFile = request.getParams().get("v.properties");
-    try {
-      Properties props = new Properties();
-      // Don't create a separate velocity log file by default.
-      props.put(RuntimeConstants.RUNTIME_LOG, "");
-
-      if (propFile == null) {
-        engine.init(props);
-      } else {
-        InputStream is = null;
-        try {
-          is = resourceLoader.getResourceStream(propFile);
-          props.load(new InputStreamReader(is, StandardCharsets.UTF_8));
-          engine.init(props);
-        }
-        finally {
-          if (is != null) is.close();
-        }
-      }
+    // Set some engine properties that improve the experience
+    //   - these could be considered in the future for parameterization, but can also be overridden by using
+    //     the init.properties.file setting.  (TODO: add a test for this properties set here overridden)
+
+    // load the built-in _macros.vm first, then load VM_global_library.vm for legacy (pre-5.0) support,
+    // and finally allow macros.vm to have the final say and override anything defined in the preceding files.
+    engine.setProperty(RuntimeConstants.VM_LIBRARY, "_macros.vm,VM_global_library.vm,macros.vm");
+
+    // Standard templates autoload, but not the macro one(s), by default, so let's just make life
+    // easier, and consistent, for macro development too.
+    engine.setProperty(RuntimeConstants.VM_LIBRARY_AUTORELOAD, "true");
+
+    /*
+      Set up Velocity resource loader(s)
+       terminology note: "resource loader" is overloaded here, there is Solr's resource loader facility for plugins,
+       and there are Velocity template resource loaders.  It's confusing, they overlap: there is a Velocity resource
+       loader that loads templates from Solr's resource loader (SolrVelocityResourceLoader).
+
+      The Velocity resource loader order is [params,][file,][solr], intentionally ordered in this manner, and each
+      one optional and individually enable-able.  By default, only "solr" (resource loader) is used, parsing templates
+      from a velocity/ sub-tree in either the classpath or under conf/.
+
+      A common usage would be to enable the file template loader, keeping the solr loader enabled; the Velocity resource
+      loader path would then be "file,solr" (params is disabled by default).  The basic browse templates are built into
+      this plugin, but can be individually overridden by placing a same-named template in the template.base.dir specified
+      directory.
+     */
+    ArrayList<String> loaders = new ArrayList<String>();
+    if (paramsResourceLoaderEnabled) {
+      loaders.add("params");
+      engine.setProperty("params.resource.loader.instance", new SolrParamResourceLoader(request));
     }
-    catch (Exception e) {
-      throw new RuntimeException(e);
+    if (fileResourceLoaderBaseDir != null) {
+      loaders.add("file");
+      engine.setProperty(RuntimeConstants.FILE_RESOURCE_LOADER_PATH, fileResourceLoaderBaseDir.getAbsolutePath());
     }
+    if (solrResourceLoaderEnabled) {
+      // The solr resource loader serves templates under a velocity/ subtree from <lib>, conf/,
+      // or SolrCloud's configuration tree.  Or rather the other way around, other resource loaders are rooted
+      // from the top, whereas this is velocity/ sub-tree rooted.
+      loaders.add("solr");
+      engine.setProperty("solr.resource.loader.instance", new SolrVelocityResourceLoader(request.getCore().getSolrConfig().getResourceLoader()));
+    }
+
+    // Always have the built-in classpath loader.  This is needed when using VM_LIBRARY macros, as they are required
+    // to be present if specified, and we want to have a nice macros facility built-in for users to use easily, and to
+    // extend in custom ways.
+    loaders.add("builtin");
+    engine.setProperty("builtin.resource.loader.instance", new ClasspathResourceLoader());
+
+    engine.setProperty(RuntimeConstants.RESOURCE_LOADER, StringUtils.join(loaders,','));
+
+    // bring in any custom properties too
+    engine.init(velocityInitProps);
 
     return engine;
   }
@@ -163,18 +293,19 @@ public class VelocityResponseWriter impl
   private Template getTemplate(VelocityEngine engine, SolrQueryRequest request) throws IOException {
     Template template;
 
-    String template_name = request.getParams().get("v.template");
-    String qt = request.getParams().get("qt");
+    String templateName = request.getParams().get(TEMPLATE);
+
+    String qt = request.getParams().get(CommonParams.QT);
     String path = (String) request.getContext().get("path");
-    if (template_name == null && path != null) {
-      template_name = path;
+    if (templateName == null && path != null) {
+      templateName = path;
     }  // TODO: path is never null, so qt won't get picked up  maybe special case for '/select' to use qt, otherwise use path?
-    if (template_name == null && qt != null) {
-      template_name = qt;
+    if (templateName == null && qt != null) {
+      templateName = qt;
     }
-    if (template_name == null) template_name = "index";
+    if (templateName == null) templateName = "index";
     try {
-      template = engine.getTemplate(template_name + ".vm");
+      template = engine.getTemplate(templateName + TEMPLATE_EXTENSION);
     } catch (Exception e) {
       throw new IOException(e.getMessage());
     }
@@ -182,12 +313,7 @@ public class VelocityResponseWriter impl
     return template;
   }
 
-  @Override
-  public String getContentType(SolrQueryRequest request, SolrQueryResponse response) {
-    return request.getParams().get("v.contentType", "text/html;charset=UTF-8");
-  }
-
-  private String getJSONWrap(String xmlResult) {  // TODO: maybe noggit or Solr's JSON utilities can make this cleaner?
+  private String getJSONWrap(String xmlResult) {  // maybe noggit or Solr's JSON utilities can make this cleaner?
     // escape the double quotes and backslashes
     String replace1 = xmlResult.replaceAll("\\\\", "\\\\\\\\");
     replace1 = replace1.replaceAll("\\n", "\\\\n");
@@ -197,7 +323,34 @@ public class VelocityResponseWriter impl
     return "{\"result\":\"" + replaced + "\"}";
   }
 
-  @Override
-  public void init(NamedList args) {
+  // see: http://svn.apache.org/repos/asf/velocity/tools/branches/2.0.x/src/main/java/org/apache/velocity/tools/generic/ResourceTool.java
+  private class SolrVelocityResourceTool extends ResourceTool {
+
+    private final Locale locale;
+    private ClassLoader solrClassLoader;
+
+    public SolrVelocityResourceTool(ClassLoader cl, String localeString) {
+      this.solrClassLoader = cl;
+      Locale l = toLocale(localeString);
+      this.locale = (l == null ? Locale.ROOT : l);
+    }
+
+    @Override
+    protected ResourceBundle getBundle(String baseName, Object loc) {
+      // resource bundles for this tool must be in velocity "package"
+      return ResourceBundle.getBundle("velocity." + baseName, locale, solrClassLoader);
+    }
+
+    // Why did Velocity Tools make this private?  Copied from ResourceTools.java
+    private Locale toLocale(Object obj) {
+      if (obj == null) {
+        return null;
+      }
+      if (obj instanceof Locale) {
+        return (Locale) obj;
+      }
+      String s = String.valueOf(obj);
+      return ConversionUtils.toLocale(s);
+    }
   }
 }

Modified: lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/browse.vm
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/browse.vm?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/browse.vm (original)
+++ lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/browse.vm Sun Feb  8 23:53:14 2015
@@ -1,4 +1,8 @@
-#set($params = $request.params)
+#*
+  - Make search box bigger
+  - Add in pivot and other facets?
+  - Work on template default selection logic
+*#
 
 ## Show Error Message, if any
 <div class="error">
@@ -7,11 +11,11 @@
 
 <div class="query-box">
   <form id="query-form" action="#{url_for_home}" method="GET">
-    Find:
-    <input type="text" id="q" name="q" value="$!esc.html($params.get('q'))"/>
+    $resource.find:
+    <input type="text" id="q" name="q" value="$!esc.html($request.params.get('q'))"/>
     <input type="submit"/>
 
-    #if($request.params.get('debugQuery'))
+    #if($debug) ## TODO: this would automatically happen when arbitrary parameters are kept on URLs
       <input type="hidden" name="debug" value="true"/>
     #end
     #foreach($fq in $request.params.getParams('fq'))
@@ -19,7 +23,7 @@
     #end
 
     <div class="constraints">
-      #foreach($fq in $params.getParams('fq'))
+      #foreach($fq in $request.params.getParams('fq'))
         #set($previous_fq_count=$velocityCount - 1)
         #if($fq != '')
           &gt;
@@ -29,7 +33,7 @@
     </div>
 
     <div class="parsed_query_header">
-      #if($request.params.get('debugQuery'))
+      #if($debug)
         <a href="#" onclick='jQuery(this).siblings("div").toggle(); return false;'>toggle parsed query</a>
         <div class="parsed_query" style="display:none">$response.response.debug.parsedquery</div>
       #end
@@ -46,11 +50,10 @@
   <span>
     <span class="results-found">$page.results_found</span>
     results found in
-    ${response.responseHeader.QTime} ms
+    ${response.responseHeader.QTime}ms
   </span>
 
-  Page <span class="page-num">$page.current_page_number</span>
-    of <span class="page-count">$page.page_count</span>
+  $resource.page_of.insert($page.current_page_number,$page.page_count)
 </div>
 
 ## Render Results, actual matching docs
@@ -59,13 +62,12 @@
 </div>
 
 <div class="pagination">
-  #link_to_previous_page("previous")
+  #link_to_previous_page
 
   <span class="results-found">$page.results_found</span>
   results found.
 
-  Page <span class="page-num">$page.current_page_number</span>
-    of <span class="page-count">$page.page_count</span>
+  $resource.page_of.insert($page.current_page_number,$page.page_count)
 
-  #link_to_next_page("next")
+  #link_to_next_page
 </div>

Modified: lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/error.vm
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/error.vm?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/error.vm (original)
+++ lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/error.vm Sun Feb  8 23:53:14 2015
@@ -1,10 +1,3 @@
-#**
- *  Show Error Message, if any
- *#
-
-## Show Error Message, if any
-## Usually rendered inside div class=error
-
 #if( $response.response.error.code )
   <h1>ERROR $response.response.error.code</h1>
   $response.response.error.msg

Modified: lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/footer.vm
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/footer.vm?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/footer.vm (original)
+++ lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/footer.vm Sun Feb  8 23:53:14 2015
@@ -2,14 +2,14 @@
 <div>
   <span>Options:</span>
 
-  #if($request.params.get('debugQuery'))
+  #if($debug)
     <a href="#url_for_home?#q#if($list.size($request.params.getParams('fq')) > 0)&#fqs($request.params.getParams('fq'))#end">
       disable debug</a>
   #else
     <a href="#url_for_lens&debug=true&fl=*,score">enable debug</a>
   #end
   -
-  <a href="#url_for_lens&wt=xml#if($request.params.get('debugQuery'))&debug=true#end">XML results</a>
+  <a href="#url_for_lens&wt=xml#if($debug)&debug=true#end">XML results</a> ## TODO: Add links for other formats, maybe dynamically?
 
 </div>
 

Modified: lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/head.vm
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/head.vm?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/head.vm (original)
+++ lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/head.vm Sun Feb  8 23:53:14 2015
@@ -3,9 +3,12 @@
  *#
 
   <title>Solr browse: #core_name</title>
+
   <meta http-equiv="content-type" content="text/html; charset=UTF-8"/>
+
   <link rel="icon" type="image/x-icon" href="#{url_root}/img/favicon.ico"/>
   <link rel="shortcut icon" type="image/x-icon" href="#{url_root}/img/favicon.ico"/>
+
   <script type="text/javascript" src="#{url_root}/js/lib/jquery-1.7.2.min.js"></script>
 
   <style>
@@ -17,17 +20,6 @@
     #head{
       width: 100%;
     }
-    .array-field {
-      border: 2px solid #474747;
-      background: #FFE9D8;
-      padding: 5px;
-      margin: 5px;
-    }
-
-    .array-field-list li {
-      list-style: circle;
-      margin-left: 20px;
-    }
 
     .parsed_query_header {
       font-family: Helvetica, Arial, sans-serif;
@@ -47,7 +39,11 @@
     }
 
     a {
-      color: #43a4b1;
+      color: #305CB3;
+    }
+
+    em {
+      color: #FF833D;
     }
 
     .facets {
@@ -61,7 +57,7 @@
     }
 
     .facets h2 {
-      background: #EA897E;
+      background: #D9411E;
       padding: 2px 5px;
     }
 
@@ -82,18 +78,9 @@
       font-weight: bold;
     }
 
-    .highlight {
-      color: white;
-      background-color: gray;
-      border: 1px black solid;
-    }
-
-    .highlight-box {
-      margin-left: 15px;
-    }
-
     .field-name {
       font-weight: bold;
+      // align="right" valign="top"
     }
 
     .highlighted-facet-field {

Modified: lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/hit.vm
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/hit.vm?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/hit.vm (original)
+++ lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/hit.vm Sun Feb  8 23:53:14 2015
@@ -1,24 +1,27 @@
-#set($docId = $doc.getFieldValue('id'))
+#set($docId = $doc.getFirstValue($request.schema.uniqueKeyField.name))
+
 
 <div class="result-document">
 
   <table>
     #foreach( $fieldName in $doc.fieldNames )
-      #foreach( $value in $doc.getFieldValues($fieldName) )
         <tr>
-          <th align="right" valign="top">
-            #if( $foreach.count == 1 )
-              $fieldName:
-            #end
+          <th align="right" valign="top" style="field-name">
+            $esc.html($fieldName):
           </th>
 
           <td align="left" valign="top">
-            $esc.html($value) <br/>
+            #field($fieldName)
           </td>
         </tr>
-      #end
     #end
   </table>
 
+  #if($debug)
+    <a href="#" onclick='jQuery(this).siblings("pre").toggle(); return false;'>toggle explain</a>
 
+    <pre style="display:none">
+      $response.getExplainMap().get($docId)
+    </pre>
+  #end
 </div>

Modified: lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/layout.vm
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/layout.vm?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/layout.vm (original)
+++ lucene/dev/branches/lucene6005/solr/contrib/velocity/src/resources/velocity/layout.vm Sun Feb  8 23:53:14 2015
@@ -5,7 +5,7 @@
   <body>
     <div id="admin"><a href="#url_root/#/#core_name">Solr Admin</a></div>
     <div id="head">
-      <a href="#url_for_home#if($request.params.get('debugQuery'))?debugQuery=true#end"><img src="#{url_root}/img/solr.svg" id="logo"/></a>
+      <a href="#url_for_home#if($debug)?debug=true#end"><img src="#{url_root}/img/solr.svg" id="logo"/></a>
     </div>
 
     <div id="content">

Modified: lucene/dev/branches/lucene6005/solr/contrib/velocity/src/test-files/velocity/solr/collection1/conf/solrconfig.xml
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/contrib/velocity/src/test-files/velocity/solr/collection1/conf/solrconfig.xml?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/contrib/velocity/src/test-files/velocity/solr/collection1/conf/solrconfig.xml (original)
+++ lucene/dev/branches/lucene6005/solr/contrib/velocity/src/test-files/velocity/solr/collection1/conf/solrconfig.xml Sun Feb  8 23:53:14 2015
@@ -16,65 +16,12 @@
  limitations under the License.
 -->
 
-<!-- 
-     For more details about configurations options that may appear in
-     this file, see http://wiki.apache.org/solr/SolrConfigXml. 
--->
 <config>
   <luceneMatchVersion>${tests.luceneMatchVersion:LATEST}</luceneMatchVersion>
-  <indexConfig>
-    <useCompoundFile>${useCompoundFile:false}</useCompoundFile>
-  </indexConfig>
-
-  <lib dir="../../contrib/velocity/lib" />
-  <lib dir="../../dist/" regex="solr-velocity-\d.*\.jar" />
-  <dataDir>${solr.data.dir:}</dataDir>
-
-
-  <directoryFactory name="DirectoryFactory"
-                    class="${solr.directoryFactory:solr.StandardDirectoryFactory}"/>
-
-  <updateHandler class="solr.DirectUpdateHandler2">
-  </updateHandler>
-  
-  <query>
-    <maxBooleanClauses>1024</maxBooleanClauses>
-    <filterCache class="solr.FastLRUCache"
-                 size="512"
-                 initialSize="512"
-                 autowarmCount="0"/>
-    <queryResultCache class="solr.LRUCache"
-                     size="512"
-                     initialSize="512"
-                     autowarmCount="0"/>
-    <documentCache class="solr.LRUCache"
-                   size="512"
-                   initialSize="512"
-                   autowarmCount="0"/>
-    <enableLazyFieldLoading>true</enableLazyFieldLoading>
-
-   <queryResultWindowSize>20</queryResultWindowSize>
-   <queryResultMaxDocsCached>200</queryResultMaxDocsCached>
-    <listener event="newSearcher" class="solr.QuerySenderListener">
-      <arr name="queries">
-      </arr>
-    </listener>
-    <listener event="firstSearcher" class="solr.QuerySenderListener">
-      <arr name="queries">
-        <lst>
-          <str name="q">static firstSearcher warming in solrconfig.xml</str>
-        </lst>
-      </arr>
-    </listener>
-    <useColdSearcher>false</useColdSearcher>
-    <maxWarmingSearchers>2</maxWarmingSearchers>
-
-  </query>
-  <requestDispatcher handleSelect="true" >
-    <requestParsers enableRemoteStreaming="true"
-                    multipartUploadLimitInKB="2048000" />
-    <httpCaching never304="true" />
-  </requestDispatcher>
+
+  <!--<lib dir="../../contrib/velocity/lib" />-->
+  <!--<lib dir="../../dist/" regex="solr-velocity-\d.*\.jar" />-->
+
 
   <requestHandler name="search" class="solr.SearchHandler" default="true">
      <lst name="defaults">
@@ -83,13 +30,9 @@
      </lst>
     </requestHandler>
 
-  <requestHandler name="/update" class="solr.UpdateRequestHandler"  />
-
   <queryResponseWriter name="velocity" class="solr.VelocityResponseWriter"/>
 
-  <!-- Legacy config for the admin interface -->
-  <admin>
-    <defaultQuery>*:*</defaultQuery>
-  </admin>
-
+  <queryResponseWriter name="velocityWithInitProps" class="solr.VelocityResponseWriter">
+    <str name="init.properties.file">velocity-init.properties</str>
+  </queryResponseWriter>
 </config>

Modified: lucene/dev/branches/lucene6005/solr/contrib/velocity/src/test/org/apache/solr/velocity/VelocityResponseWriterTest.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/contrib/velocity/src/test/org/apache/solr/velocity/VelocityResponseWriterTest.java?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/contrib/velocity/src/test/org/apache/solr/velocity/VelocityResponseWriterTest.java (original)
+++ lucene/dev/branches/lucene6005/solr/contrib/velocity/src/test/org/apache/solr/velocity/VelocityResponseWriterTest.java Sun Feb  8 23:53:14 2015
@@ -18,27 +18,39 @@
 package org.apache.solr.velocity;
 
 import org.apache.solr.SolrTestCaseJ4;
+import org.apache.solr.common.util.NamedList;
 import org.apache.solr.response.QueryResponseWriter;
+import org.apache.solr.response.SolrParamResourceLoader;
 import org.apache.solr.response.SolrQueryResponse;
 import org.apache.solr.response.VelocityResponseWriter;
 import org.apache.solr.request.SolrQueryRequest;
 import org.junit.BeforeClass;
 import org.junit.Test;
 
+import java.io.IOException;
 import java.io.StringWriter;
 
 public class VelocityResponseWriterTest extends SolrTestCaseJ4 {
   @BeforeClass
   public static void beforeClass() throws Exception {
     initCore("solrconfig.xml", "schema.xml", getFile("velocity/solr").getAbsolutePath());
+    System.out.println(getFile("velocity/solr").getAbsolutePath());
   }
 
   @Test
-  public void testCustomParamTemplate() throws Exception {
-    // This test doesn't use the Solr core, just the response writer directly
+  public void testVelocityResponseWriterRegistered() {
+    QueryResponseWriter writer = h.getCore().getQueryResponseWriter("velocity");
+    assertTrue("VrW registered check", writer instanceof VelocityResponseWriter);
+  }
 
+  @Test
+  public void testCustomParamTemplate() throws Exception {
     org.apache.solr.response.VelocityResponseWriter vrw = new VelocityResponseWriter();
-    SolrQueryRequest req = req("v.template","custom", "v.template.custom","$response.response.response_data");
+    NamedList<String> nl = new NamedList<String>();
+    nl.add(VelocityResponseWriter.PARAMS_RESOURCE_LOADER_ENABLED, "true");
+    vrw.init(nl);
+    SolrQueryRequest req = req(VelocityResponseWriter.TEMPLATE,"custom",
+        SolrParamResourceLoader.TEMPLATE_PARAM_PREFIX+"custom","$response.response.response_data");
     SolrQueryResponse rsp = new SolrQueryResponse();
     StringWriter buf = new StringWriter();
     rsp.add("response_data", "testing");
@@ -47,14 +59,118 @@ public class VelocityResponseWriterTest
   }
 
   @Test
-  public void testVelocityResponseWriterRegistered() {
-    QueryResponseWriter writer = h.getCore().getQueryResponseWriter("velocity");
+  public void testParamResourceLoaderDisabled() throws Exception {
+    VelocityResponseWriter vrw = new VelocityResponseWriter();
+    // by default param resource loader is disabled, no need to set it here
+    SolrQueryRequest req = req(VelocityResponseWriter.TEMPLATE,"custom",
+        SolrParamResourceLoader.TEMPLATE_PARAM_PREFIX+"custom","$response.response.response_data");
+    SolrQueryResponse rsp = new SolrQueryResponse();
+    StringWriter buf = new StringWriter();
+    try {
+      vrw.write(buf, req, rsp);
+      fail("Should have thrown exception due to missing template");
+    } catch (IOException e) {
+      // expected exception
+    }
+  }
 
-    assertTrue("VrW registered check", writer instanceof VelocityResponseWriter);
+  @Test
+  public void testFileResourceLoader() throws Exception {
+    VelocityResponseWriter vrw = new VelocityResponseWriter();
+    NamedList<String> nl = new NamedList<String>();
+    nl.add("template.base.dir", getFile("velocity").getAbsolutePath());
+    vrw.init(nl);
+    SolrQueryRequest req = req(VelocityResponseWriter.TEMPLATE,"file");
+    SolrQueryResponse rsp = new SolrQueryResponse();
+    StringWriter buf = new StringWriter();
+    vrw.write(buf, req, rsp);
+    assertEquals("testing", buf.toString());
   }
 
   @Test
   public void testSolrResourceLoaderTemplate() throws Exception {
-    assertEquals("0", h.query(req("q","*:*", "wt","velocity","v.template","numFound")));
+    assertEquals("0", h.query(req("q","*:*", "wt","velocity",VelocityResponseWriter.TEMPLATE,"numFound")));
   }
+
+  @Test
+  public void testMacros() throws Exception {
+    // tests that a macro in a custom macros.vm is visible
+    assertEquals("test_macro_SUCCESS", h.query(req("q","*:*", "wt","velocity",VelocityResponseWriter.TEMPLATE,"test_macro_visible")));
+
+    // tests that a builtin (_macros.vm) macro, #url_root in this case, can be overridden in a custom macros.vm
+    // the macro is also defined in VM_global_library.vm, which should also be overridden by macros.vm
+    assertEquals("Loaded from: macros.vm", h.query(req("q","*:*", "wt","velocity",VelocityResponseWriter.TEMPLATE,"test_macro_overridden")));
+
+    // tests that macros defined in VM_global_library.vm are visible.  This file was where macros in pre-5.0 versions were defined
+    assertEquals("legacy_macro_SUCCESS", h.query(req("q","*:*", "wt","velocity",VelocityResponseWriter.TEMPLATE,"test_macro_legacy_support")));
+  }
+
+  @Test
+  public void testInitProps() throws Exception {
+    // The test init properties file turns off being able to use $foreach.index (the implicit loop counter)
+    // The foreach.vm template uses $!foreach.index, with ! suppressing the literal "$foreach.index" output
+
+    assertEquals("01", h.query(req("q","*:*", "wt","velocity",VelocityResponseWriter.TEMPLATE,"foreach")));
+    assertEquals("", h.query(req("q","*:*", "wt","velocityWithInitProps",VelocityResponseWriter.TEMPLATE,"foreach")));
+  }
+
+  @Test
+  public void testLocaleFeature() throws Exception {
+    assertEquals("Color", h.query(req("q", "*:*", "wt", "velocity", VelocityResponseWriter.TEMPLATE, "locale",
+        VelocityResponseWriter.LOCALE,"en_US")));
+    assertEquals("Colour", h.query(req("q", "*:*", "wt", "velocity", VelocityResponseWriter.TEMPLATE, "locale",
+        VelocityResponseWriter.LOCALE,"en_UK")));
+  }
+
+  @Test
+  public void testLayoutFeature() throws Exception {
+    assertEquals("{{{0}}}", h.query(req("q","*:*", "wt","velocity",
+        VelocityResponseWriter.TEMPLATE,"numFound", VelocityResponseWriter.LAYOUT,"layout")));
+
+    // even with v.layout specified, layout can be disabled explicitly
+    assertEquals("0", h.query(req("q","*:*", "wt","velocity",
+        VelocityResponseWriter.TEMPLATE,"numFound",
+        VelocityResponseWriter.LAYOUT,"layout",
+        VelocityResponseWriter.LAYOUT_ENABLED,"false")));
+  }
+
+  @Test
+  public void testJSONWrapper() throws Exception {
+    assertEquals("foo({\"result\":\"0\"})", h.query(req("q", "*:*", "wt", "velocity",
+        VelocityResponseWriter.TEMPLATE, "numFound",
+        VelocityResponseWriter.JSON,"foo")));
+
+    // Now with layout, for good measure
+    assertEquals("foo({\"result\":\"{{{0}}}\"})", h.query(req("q", "*:*", "wt", "velocity",
+        VelocityResponseWriter.TEMPLATE, "numFound",
+        VelocityResponseWriter.JSON,"foo",
+        VelocityResponseWriter.LAYOUT,"layout")));
+  }
+
+  @Test
+  public void testContentType() throws Exception {
+    VelocityResponseWriter vrw = new VelocityResponseWriter();
+    NamedList<String> nl = new NamedList<String>();
+    vrw.init(nl);
+    SolrQueryResponse rsp = new SolrQueryResponse();
+
+    // with v.json=wrf, content type should default to application/json
+    assertEquals("application/json;charset=UTF-8",
+        vrw.getContentType(req(VelocityResponseWriter.TEMPLATE, "numFound",
+            VelocityResponseWriter.JSON, "wrf"), rsp));
+
+    // with no v.json specified, the default text/html should be returned
+    assertEquals("text/html;charset=UTF-8",
+        vrw.getContentType(req(VelocityResponseWriter.TEMPLATE, "numFound"), rsp));
+
+    // if v.contentType is specified, that should be used, even if v.json is specified
+    assertEquals("text/plain",
+        vrw.getContentType(req(VelocityResponseWriter.TEMPLATE, "numFound",
+            VelocityResponseWriter.CONTENT_TYPE,"text/plain"), rsp));
+    assertEquals("text/plain",
+        vrw.getContentType(req(VelocityResponseWriter.TEMPLATE, "numFound",
+            VelocityResponseWriter.JSON,"wrf",
+            VelocityResponseWriter.CONTENT_TYPE,"text/plain"), rsp));
+  }
+
 }

Modified: lucene/dev/branches/lucene6005/solr/core/build.xml
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/core/build.xml?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/core/build.xml (original)
+++ lucene/dev/branches/lucene6005/solr/core/build.xml Sun Feb  8 23:53:14 2015
@@ -63,7 +63,7 @@
   <target name="resolve" depends="ivy-availability-check,ivy-fail,ivy-configure">
     <sequential>
       <ivy:retrieve conf="compile,compile.hadoop" type="jar,bundle" sync="${ivy.sync}" log="download-only" symlink="${ivy.symlink}"/>
-      <ivy:retrieve conf="test,test.DfsMiniCluster" type="jar,bundle,test" sync="${ivy.sync}" log="download-only" symlink="${ivy.symlink}"
+      <ivy:retrieve conf="test,test.DfsMiniCluster,test.MiniKdc" type="jar,bundle,test" sync="${ivy.sync}" log="download-only" symlink="${ivy.symlink}"
                     pattern="${test.lib.dir}/[artifact]-[revision](-[classifier]).[ext]"/>
     </sequential>
   </target>

Modified: lucene/dev/branches/lucene6005/solr/core/ivy.xml
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/core/ivy.xml?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/core/ivy.xml (original)
+++ lucene/dev/branches/lucene6005/solr/core/ivy.xml Sun Feb  8 23:53:14 2015
@@ -19,13 +19,14 @@
 <ivy-module version="2.0"  xmlns:maven="http://ant.apache.org/ivy/maven">
   <info organisation="org.apache.solr" module="core"/>
   
-  <configurations defaultconfmapping="compile->master;compile.hadoop->master;test->master;test.DfsMiniCluster->master">
+  <configurations defaultconfmapping="compile->master;compile.hadoop->master;test->master;test.DfsMiniCluster->master;test.MiniKdc->master">
     <!-- artifacts in the "compile" and "compile.hadoop" configurations will go into solr/core/lib/ -->
     <conf name="compile" transitive="false"/>
     <conf name="compile.hadoop" transitive="false"/>
-    <!-- artifacts in the "test" and "test.DfsMiniCluster" configuration will go into solr/core/test-lib/ -->
+    <!-- artifacts in the "test", "test.DfsMiniCluster", and "test.MiniKdc" configuration will go into solr/core/test-lib/ -->
     <conf name="test" transitive="false"/>
     <conf name="test.DfsMiniCluster" transitive="false"/>
+    <conf name="test.MiniKdc" transitive="false"/>
   </configurations>
 
   <dependencies>
@@ -46,7 +47,6 @@
     <dependency org="log4j" name="log4j" rev="${/log4j/log4j}" conf="compile"/>
     <dependency org="org.slf4j" name="slf4j-log4j12" rev="${/org.slf4j/slf4j-log4j12}" conf="compile"/>
 
-    <dependency org="javax.servlet" name="javax.servlet-api" rev="${/javax.servlet/javax.servlet-api}" conf="test"/>
     <dependency org="org.easymock" name="easymock" rev="${/org.easymock/easymock}" conf="test"/>
     <dependency org="cglib" name="cglib-nodep" rev="${/cglib/cglib-nodep}" conf="test"/>
     <dependency org="org.objenesis" name="objenesis" rev="${/org.objenesis/objenesis}" conf="test"/>
@@ -62,6 +62,8 @@
     <dependency org="org.apache.hadoop" name="hadoop-annotations" rev="${/org.apache.hadoop/hadoop-annotations}" conf="compile.hadoop"/>
     <dependency org="org.apache.hadoop" name="hadoop-auth" rev="${/org.apache.hadoop/hadoop-auth}" conf="compile.hadoop"/>
     <dependency org="commons-configuration" name="commons-configuration" rev="${/commons-configuration/commons-configuration}" conf="compile.hadoop"/>
+    <dependency org="commons-collections" name="commons-collections" rev="${/commons-collections/commons-collections}" conf="compile.hadoop"/>
+    
     <dependency org="com.google.protobuf" name="protobuf-java" rev="${/com.google.protobuf/protobuf-java}" conf="compile.hadoop"/>
     <dependency org="com.googlecode.concurrentlinkedhashmap" name="concurrentlinkedhashmap-lru" rev="${/com.googlecode.concurrentlinkedhashmap/concurrentlinkedhashmap-lru}" conf="compile.hadoop"/>
 
@@ -75,8 +77,13 @@
     <dependency org="org.mortbay.jetty" name="jetty" rev="${/org.mortbay.jetty/jetty}" conf="test.DfsMiniCluster"/>
     <dependency org="org.mortbay.jetty" name="jetty-util" rev="${/org.mortbay.jetty/jetty-util}" conf="test.DfsMiniCluster"/>
     <dependency org="com.sun.jersey" name="jersey-core" rev="${/com.sun.jersey/jersey-core}" conf="test.DfsMiniCluster"/>
+    <dependency org="com.sun.jersey" name="jersey-server" rev="${/com.sun.jersey/jersey-server}" conf="test.DfsMiniCluster"/>
     <dependency org="commons-collections" name="commons-collections" rev="${/commons-collections/commons-collections}" conf="test.DfsMiniCluster"/>
 
+    <!-- Hadoop MiniKdc Dependencies-->
+    <dependency org="org.apache.hadoop" name="hadoop-minikdc" rev="${/org.apache.hadoop/hadoop-minikdc}" conf="test.MiniKdc"/>
+    <dependency org="org.apache.directory.server" name="apacheds-all" rev="${/org.apache.directory.server/apacheds-all}" conf="test.MiniKdc"/>
+
     <exclude org="*" ext="*" matcher="regexp" type="${ivy.exclude.types}"/> 
   </dependencies>
 </ivy-module>

Modified: lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/analysis/SolrAnalyzer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/analysis/SolrAnalyzer.java?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/analysis/SolrAnalyzer.java (original)
+++ lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/analysis/SolrAnalyzer.java Sun Feb  8 23:53:14 2015
@@ -17,10 +17,9 @@
 
 package org.apache.solr.analysis;
 
-import org.apache.lucene.analysis.*;
+import org.apache.lucene.analysis.Analyzer;
 
 import java.io.Reader;
-import java.io.IOException;
 
 /**
  *
@@ -37,14 +36,8 @@ public abstract class SolrAnalyzer exten
     return posIncGap;
   }
 
-  /** wrap the reader in a CharStream, if appropriate */
-  @Deprecated
-  public Reader charStream(Reader reader) {
-    return reader;
-  }
-
   @Override
   protected Reader initReader(String fieldName, Reader reader) {
-    return charStream(reader);
+    return reader;
   }
 }

Modified: lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java (original)
+++ lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/client/solrj/embedded/EmbeddedSolrServer.java Sun Feb  8 23:53:14 2015
@@ -17,6 +17,7 @@
 
 package org.apache.solr.client.solrj.embedded;
 
+import com.google.common.base.Strings;
 import org.apache.solr.client.solrj.SolrClient;
 import org.apache.solr.client.solrj.SolrRequest;
 import org.apache.solr.client.solrj.SolrServerException;
@@ -30,7 +31,6 @@ import org.apache.solr.common.params.Sol
 import org.apache.solr.common.util.JavaBinCodec;
 import org.apache.solr.common.util.NamedList;
 import org.apache.solr.core.CoreContainer;
-import org.apache.solr.core.CoreDescriptor;
 import org.apache.solr.core.SolrCore;
 import org.apache.solr.request.SolrQueryRequest;
 import org.apache.solr.request.SolrRequestHandler;
@@ -62,25 +62,10 @@ public class EmbeddedSolrServer extends
   
   /**
    * Use the other constructor using a CoreContainer and a name.
-   * @deprecated use {@link #EmbeddedSolrServer(CoreContainer, String)} instead.
    */
-  @Deprecated
   public EmbeddedSolrServer(SolrCore core)
   {
-    if ( core == null ) {
-      throw new NullPointerException("SolrCore instance required");
-    }
-    CoreDescriptor dcore = core.getCoreDescriptor();
-    if (dcore == null)
-      throw new NullPointerException("CoreDescriptor required");
-    
-    CoreContainer cores = dcore.getCoreContainer();
-    if (cores == null)
-      throw new NullPointerException("CoreContainer required");
-    
-    coreName = dcore.getName();
-    coreContainer = cores;
-    _parser = new SolrRequestParsers( null );
+    this(core.getCoreDescriptor().getCoreContainer(), core.getName());
   }
     
   /**
@@ -93,8 +78,10 @@ public class EmbeddedSolrServer extends
     if ( coreContainer == null ) {
       throw new NullPointerException("CoreContainer instance required");
     }
+    if (Strings.isNullOrEmpty(coreName))
+      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, "Core name cannot be empty");
     this.coreContainer = coreContainer;
-    this.coreName = coreName == null? "" : coreName;
+    this.coreName = coreName;
     _parser = new SolrRequestParsers( null );
   }
   
@@ -129,10 +116,8 @@ public class EmbeddedSolrServer extends
         }
       }
       // Perhaps the path is to manage the cores
-      if( handler == null &&
-          coreContainer != null &&
-          path.equals( coreContainer.getAdminPath() ) ) {
-        handler = coreContainer.getMultiCoreHandler();
+      if (handler == null) {
+        handler = coreContainer.getRequestHandler(path);
       }
     }
     if( handler == null ) {
@@ -210,16 +195,11 @@ public class EmbeddedSolrServer extends
       }
       
       // Now write it out
-      NamedList<Object> normalized = getParsedResponse(req, rsp);
+      NamedList<Object> normalized = BinaryResponseWriter.getParsedResponse(req, rsp);
       return normalized;
-    }
-    catch( IOException iox ) {
+    } catch( IOException | SolrException iox ) {
       throw iox;
-    }
-    catch( SolrException sx ) {
-      throw sx;
-    }
-    catch( Exception ex ) {
+    } catch( Exception ex ) {
       throw new SolrServerException( ex );
     }
     finally {
@@ -230,22 +210,10 @@ public class EmbeddedSolrServer extends
   }
   
   /**
-   * Returns a response object equivalent to what you get from the XML/JSON/javabin parser. Documents
-   * become SolrDocuments, DocList becomes SolrDocumentList etc.
-   * 
-   * @deprecated use {@link BinaryResponseWriter#getParsedResponse(SolrQueryRequest, SolrQueryResponse)}
-   */
-  @Deprecated
-  public NamedList<Object> getParsedResponse( SolrQueryRequest req, SolrQueryResponse rsp )
-  {
-    return BinaryResponseWriter.getParsedResponse(req, rsp);
-  }
-  
-  /**
    * Shutdown all cores within the EmbeddedSolrServer instance
    */
   @Override
-  public void shutdown() {
+  public void close() throws IOException {
     coreContainer.shutdown();
   }
   

Modified: lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java (original)
+++ lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/client/solrj/embedded/JettySolrRunner.java Sun Feb  8 23:53:14 2015
@@ -19,17 +19,18 @@ package org.apache.solr.client.solrj.emb
 
 import org.apache.solr.servlet.SolrDispatchFilter;
 import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.LowResourceMonitor;
+import org.eclipse.jetty.server.SecureRequestCustomizer;
 import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.bio.SocketConnector;
-import org.eclipse.jetty.server.handler.GzipHandler;
-import org.eclipse.jetty.server.nio.SelectChannelConnector;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
 import org.eclipse.jetty.server.session.HashSessionIdManager;
-import org.eclipse.jetty.server.ssl.SslConnector;
-import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
-import org.eclipse.jetty.server.ssl.SslSocketConnector;
 import org.eclipse.jetty.servlet.FilterHolder;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.servlets.GzipFilter;
 import org.eclipse.jetty.util.component.LifeCycle;
 import org.eclipse.jetty.util.log.Logger;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
@@ -62,6 +63,9 @@ import java.util.concurrent.atomic.Atomi
  * @since solr 1.3
  */
 public class JettySolrRunner {
+
+  private static final AtomicLong JETTY_ID_COUNTER = new AtomicLong();
+
   Server server;
 
   FilterHolder dispatchFilter;
@@ -71,6 +75,7 @@ public class JettySolrRunner {
 
   private String solrConfigFilename;
   private String schemaFilename;
+  private final String coreRootDirectory;
 
   private boolean waitOnSolr = false;
 
@@ -89,6 +94,8 @@ public class JettySolrRunner {
 
   private String coreNodeName;
 
+  private final String name;
+
   /** Maps servlet holders (i.e. factories: class + init params) to path specs */
   private SortedMap<ServletHolder,String> extraServlets = new TreeMap<>();
   private SortedMap<Class,String> extraRequestFilters;
@@ -147,12 +154,16 @@ public class JettySolrRunner {
 
   public JettySolrRunner(String solrHome, String context, int port) {
     this.init(solrHome, context, port, true);
+    this.name = "jetty-" + JETTY_ID_COUNTER.incrementAndGet();
+    this.coreRootDirectory = System.getProperty("coreRootDirectory", null);
   }
 
   public JettySolrRunner(String solrHome, String context, int port, String solrConfigFilename, String schemaFileName) {
     this.init(solrHome, context, port, true);
     this.solrConfigFilename = solrConfigFilename;
     this.schemaFilename = schemaFileName;
+    this.name = "jetty-" + JETTY_ID_COUNTER.incrementAndGet();
+    this.coreRootDirectory = System.getProperty("coreRootDirectory", null);
   }
   
   public JettySolrRunner(String solrHome, String context, int port,
@@ -160,6 +171,8 @@ public class JettySolrRunner {
     this.init(solrHome, context, port, stopAtShutdown);
     this.solrConfigFilename = solrConfigFilename;
     this.schemaFilename = schemaFileName;
+    this.name = "jetty-" + JETTY_ID_COUNTER.incrementAndGet();
+    this.coreRootDirectory = System.getProperty("coreRootDirectory", null);
   }
 
   /**
@@ -197,23 +210,20 @@ public class JettySolrRunner {
     this.schemaFilename = schemaFileName;
     this.sslConfig = sslConfig;
 
+    this.name = "jetty-" + JETTY_ID_COUNTER.incrementAndGet();
+    this.coreRootDirectory = System.getProperty("coreRootDirectory", null);
+
     this.init(solrHome, context, port, stopAtShutdown);
   }
   
   private void init(String solrHome, String context, int port, boolean stopAtShutdown) {
     this.context = context;
-    server = new Server(port);
 
     this.solrHome = solrHome;
     this.stopAtShutdown = stopAtShutdown;
-    server.setStopAtShutdown(stopAtShutdown);
-    if (!stopAtShutdown) {
-      server.setGracefulShutdown(0);
-    }
+
     System.setProperty("solr.solr.home", solrHome);
     if (System.getProperty("jetty.testMode") != null) {
-      final String connectorName = System.getProperty("tests.jettyConnector", "SelectChannel");
-
       // if this property is true, then jetty will be configured to use SSL
       // leveraging the same system properties as java to specify
       // the keystore/truststore if they are set unless specific config
@@ -227,52 +237,56 @@ public class JettySolrRunner {
       final SslContextFactory sslcontext = new SslContextFactory(false);
       sslInit(useSsl, sslcontext);
 
-      final Connector connector;
-      if ("SelectChannel".equals(connectorName)) {
-        final SelectChannelConnector c = useSsl
-          ? new SslSelectChannelConnector(sslcontext)
-          : new SelectChannelConnector();
-        c.setReuseAddress(true);
-        c.setLowResourcesMaxIdleTime(1500);
-        c.setSoLingerTime(0);
-        connector = c;
-      } else if ("Socket".equals(connectorName)) {
-        final SocketConnector c = useSsl
-          ? new SslSocketConnector(sslcontext)
-          : new SocketConnector();
-        c.setReuseAddress(true);
-        c.setSoLingerTime(0);
-        connector = c;
+      QueuedThreadPool qtp = new QueuedThreadPool();
+      qtp.setMaxThreads(10000);
+      qtp.setIdleTimeout((int) TimeUnit.SECONDS.toMillis(5));
+      qtp.setStopTimeout((int) TimeUnit.MINUTES.toMillis(1));
+
+      server = new Server(qtp);
+      server.setStopAtShutdown(stopAtShutdown);
+      server.manage(qtp);
+
+      ServerConnector connector;
+      if (useSsl) {
+        HttpConfiguration configuration = new HttpConfiguration();
+        configuration.setSecureScheme("https");
+        configuration.addCustomizer(new SecureRequestCustomizer());
+        connector = new ServerConnector(server, new SslConnectionFactory(sslcontext, "http/1.1"),
+            new HttpConnectionFactory(configuration));
       } else {
-        throw new IllegalArgumentException("Illegal value for system property 'tests.jettyConnector': " + connectorName);
+        connector = new ServerConnector(server, new HttpConnectionFactory());
       }
 
+      connector.setReuseAddress(true);
+      connector.setSoLingerTime(0);
       connector.setPort(port);
       connector.setHost("127.0.0.1");
 
-      // Connectors by default inherit server's thread pool.
-      QueuedThreadPool qtp = new QueuedThreadPool();
-      qtp.setMaxThreads(10000);
-      qtp.setMaxIdleTimeMs((int) TimeUnit.MILLISECONDS.toMillis(200));
-      qtp.setMaxStopTimeMs((int) TimeUnit.MINUTES.toMillis(1));
-      server.setThreadPool(qtp);
+      // Enable Low Resources Management
+      LowResourceMonitor lowResources = new LowResourceMonitor(server);
+      lowResources.setLowResourcesIdleTimeout(1500);
+      lowResources.setMaxConnections(10000);
+      server.addBean(lowResources);
 
       server.setConnectors(new Connector[] {connector});
       server.setSessionIdManager(new HashSessionIdManager(new Random()));
     } else {
-      if (server.getThreadPool() == null) {
-        // Connectors by default inherit server's thread pool.
-        QueuedThreadPool qtp = new QueuedThreadPool();
-        qtp.setMaxThreads(10000);
-        qtp.setMaxIdleTimeMs((int) TimeUnit.SECONDS.toMillis(5));
-        qtp.setMaxStopTimeMs((int) TimeUnit.SECONDS.toMillis(1));
-        server.setThreadPool(qtp);
-      }
+      ServerConnector connector = new ServerConnector(server, new HttpConnectionFactory());
+      connector.setPort(port);
+
+      QueuedThreadPool qtp = new QueuedThreadPool();
+      qtp.setMaxThreads(10000);
+      qtp.setIdleTimeout((int) TimeUnit.SECONDS.toMillis(5));
+      qtp.setStopTimeout((int) TimeUnit.SECONDS.toMillis(1));
+
+      server = new Server(qtp);
+      server.setStopAtShutdown(stopAtShutdown);
+      server.manage(qtp);
     }
 
     // Initialize the servlets
-    final ServletContextHandler root = new ServletContextHandler(server,context,ServletContextHandler.SESSIONS);
-    root.setHandler(new GzipHandler());
+    final ServletContextHandler root = new ServletContextHandler(server, context, ServletContextHandler.SESSIONS);
+    root.addFilter(GzipFilter.class, "*", EnumSet.of(DispatcherType.REQUEST));
     server.addLifeCycleListener(new LifeCycle.Listener() {
 
       @Override
@@ -299,6 +313,8 @@ public class JettySolrRunner {
             solrConfigFilename);
         if (schemaFilename != null) System.setProperty("schema", 
             schemaFilename);
+        if (coreRootDirectory != null)
+          System.setProperty("coreRootDirectory", coreRootDirectory);
 //        SolrDispatchFilter filter = new SolrDispatchFilter();
 //        FilterHolder fh = new FilterHolder(filter);
         debugFilter = root.addFilter(DebugFilter.class, "*", EnumSet.of(DispatcherType.REQUEST) );
@@ -309,11 +325,11 @@ public class JettySolrRunner {
               EnumSet.of(DispatcherType.REQUEST)));
           }
         }
-        dispatchFilter = root.addFilter(SolrDispatchFilter.class, "*", EnumSet.of(DispatcherType.REQUEST) );
         for (ServletHolder servletHolder : extraServlets.keySet()) {
           String pathSpec = extraServlets.get(servletHolder);
           root.addServlet(servletHolder, pathSpec);
         }
+        dispatchFilter = root.addFilter(SolrDispatchFilter.class, "*", EnumSet.of(DispatcherType.REQUEST) );
         if (solrConfigFilename != null) System.clearProperty("solrconfig");
         if (schemaFilename != null) System.clearProperty("schema");
         System.clearProperty("solr.solr.home");
@@ -339,7 +355,7 @@ public class JettySolrRunner {
         sslcontext.setKeyStorePassword(sslConfig.getKeyStorePassword());
       }
       if (null != sslConfig.getTrustStore()) {
-        sslcontext.setTrustStore(System
+        sslcontext.setTrustStorePath(System
             .getProperty(sslConfig.getTrustStore()));
       }
       if (null != sslConfig.getTrustStorePassword()) {
@@ -359,7 +375,7 @@ public class JettySolrRunner {
             (System.getProperty("javax.net.ssl.keyStorePassword"));
         }
         if (null != System.getProperty("javax.net.ssl.trustStore")) {
-          sslcontext.setTrustStore
+          sslcontext.setTrustStorePath
             (System.getProperty("javax.net.ssl.trustStore"));
         }
         if (null != System.getProperty("javax.net.ssl.trustStorePassword")) {
@@ -464,7 +480,7 @@ public class JettySolrRunner {
     if (0 == conns.length) {
       throw new RuntimeException("Jetty Server has no Connectors");
     }
-    return (proxyPort != -1) ? proxyPort : conns[0].getLocalPort();
+    return (proxyPort != -1) ? proxyPort : ((ServerConnector) conns[0]).getLocalPort();
   }
   
   /**
@@ -489,7 +505,7 @@ public class JettySolrRunner {
   }
 
   /**
-   * Returns a base URL consisting of the protocal, host, and port for a 
+   * Returns a base URL consisting of the protocol, host, and port for a
    * Connector in use by the Jetty Server contained in this runner.
    */
   public URL getBaseUrl() {
@@ -499,12 +515,12 @@ public class JettySolrRunner {
       if (0 == conns.length) {
         throw new IllegalStateException("Jetty Server has no Connectors");
       }
-      Connector c = conns[0];
+      ServerConnector c = (ServerConnector) conns[0];
       if (c.getLocalPort() < 0) {
         throw new IllegalStateException("Jetty Connector is not open: " + 
                                         c.getLocalPort());
       }
-      protocol = (c instanceof SslConnector) ? "https" : "http";
+      protocol = c.getDefaultProtocol().equals("SSL-http/1.1")  ? "https" : "http";
       return new URL(protocol, c.getHost(), c.getLocalPort(), context);
 
     } catch (MalformedURLException e) {
@@ -615,6 +631,11 @@ class NoLog implements Logger {
   }
 
   @Override
+  public void debug(String s, long l) {
+
+  }
+
+  @Override
   public String getName() {
     return toString();
   }

Modified: lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/CloudDescriptor.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/CloudDescriptor.java?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/CloudDescriptor.java (original)
+++ lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/CloudDescriptor.java Sun Feb  8 23:53:14 2015
@@ -17,6 +17,7 @@ package org.apache.solr.cloud;
  * limitations under the License.
  */
 
+import com.google.common.base.Strings;
 import org.apache.solr.common.cloud.Slice;
 import org.apache.solr.common.cloud.ZkStateReader;
 import org.apache.solr.common.params.SolrParams;
@@ -49,10 +50,14 @@ public class CloudDescriptor {
   public CloudDescriptor(String coreName, Properties props, CoreDescriptor cd) {
     this.cd = cd;
     this.shardId = props.getProperty(CoreDescriptor.CORE_SHARD, null);
+    if (Strings.isNullOrEmpty(shardId))
+      this.shardId = null;
     // If no collection name is specified, we default to the core name
     this.collectionName = props.getProperty(CoreDescriptor.CORE_COLLECTION, coreName);
     this.roles = props.getProperty(CoreDescriptor.CORE_ROLES, null);
     this.nodeName = props.getProperty(CoreDescriptor.CORE_NODE_NAME);
+    if (Strings.isNullOrEmpty(nodeName))
+      this.nodeName = null;
     this.numShards = PropertiesUtil.toInteger(props.getProperty(CloudDescriptor.NUM_SHARDS), null);
   }
   

Modified: lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/DistributedQueue.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/DistributedQueue.java?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/DistributedQueue.java (original)
+++ lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/DistributedQueue.java Sun Feb  8 23:53:14 2015
@@ -122,10 +122,13 @@ public class DistributedQueue {
     for (String childName : childNames) {
       if (childName != null) {
         try {
-          ZkNodeProps message = ZkNodeProps.load(zookeeper.getData(dir + "/" + childName, null, null, true));
-          if (message.containsKey(OverseerCollectionProcessor.ASYNC)) {
-            LOG.info(">>>> {}", message.get(OverseerCollectionProcessor.ASYNC));
-            if(message.get(OverseerCollectionProcessor.ASYNC).equals(requestId)) return true;
+          byte[] data = zookeeper.getData(dir + "/" + childName, null, null, true);
+          if (data != null) {
+            ZkNodeProps message = ZkNodeProps.load(data);
+            if (message.containsKey(OverseerCollectionProcessor.ASYNC)) {
+              LOG.debug(">>>> {}", message.get(OverseerCollectionProcessor.ASYNC));
+              if(message.get(OverseerCollectionProcessor.ASYNC).equals(requestId)) return true;
+            }
           }
         } catch (KeeperException.NoNodeException e) {
           // Another client removed the node first, try next

Modified: lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/LeaderInitiatedRecoveryThread.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/LeaderInitiatedRecoveryThread.java?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/LeaderInitiatedRecoveryThread.java (original)
+++ lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/LeaderInitiatedRecoveryThread.java Sun Feb  8 23:53:14 2015
@@ -113,9 +113,8 @@ public class LeaderInitiatedRecoveryThre
       } else {
         log.info("Asking core={} coreNodeName={} on " + recoveryUrl + " to recover", coreNeedingRecovery, replicaCoreNodeName);
       }
-      
-      HttpSolrClient client = new HttpSolrClient(recoveryUrl);
-      try {
+
+      try (HttpSolrClient client = new HttpSolrClient(recoveryUrl)) {
         client.setSoTimeout(60000);
         client.setConnectionTimeout(15000);
         try {
@@ -139,8 +138,6 @@ public class LeaderInitiatedRecoveryThre
             continueTrying = false;
           }                                                
         }
-      } finally {
-        client.shutdown();
       }
       
       // wait a few seconds
@@ -193,7 +190,7 @@ public class LeaderInitiatedRecoveryThre
 
         // additional safeguard against the replica trying to be in the active state
         // before acknowledging the leader initiated recovery command
-        if (continueTrying && collection != null && shardId != null) {
+        if (collection != null && shardId != null) {
           try {
             // call out to ZooKeeper to get the leader-initiated recovery state
             String lirState = 
@@ -218,20 +215,25 @@ public class LeaderInitiatedRecoveryThre
               List<ZkCoreNodeProps> replicaProps = 
                   zkStateReader.getReplicaProps(collection, shardId, leaderCoreNodeName);
               if (replicaProps != null && replicaProps.size() > 0) {
-                String replicaState = replicaProps.get(0).getState();
-                if (ZkStateReader.ACTIVE.equals(replicaState)) {
-                  // replica published its state as "active", 
-                  // which is bad if lirState is still "down"
-                  if (ZkStateReader.DOWN.equals(lirState)) {
-                    // OK, so the replica thinks it is active, but it never ack'd the leader initiated recovery
-                    // so its state cannot be trusted and it needs to be told to recover again ... and we keep looping here
-                    log.warn("Replica core={} coreNodeName={} set to active but the leader thinks it should be in recovery;"
-                        + " forcing it back to down state to re-run the leader-initiated recovery process; props: "+replicaProps.get(0), coreNeedingRecovery, replicaCoreNodeName);
-                    zkController.ensureReplicaInLeaderInitiatedRecovery(collection, 
-                        shardId, replicaUrl, nodeProps, true); // force republish state to "down"
+                for (ZkCoreNodeProps prop : replicaProps) {
+                  if (replicaCoreNodeName.equals(((Replica) prop.getNodeProps()).getName())) {
+                    String replicaState = prop.getState();
+                    if (ZkStateReader.ACTIVE.equals(replicaState)) {
+                      // replica published its state as "active",
+                      // which is bad if lirState is still "down"
+                      if (ZkStateReader.DOWN.equals(lirState)) {
+                        // OK, so the replica thinks it is active, but it never ack'd the leader initiated recovery
+                        // so its state cannot be trusted and it needs to be told to recover again ... and we keep looping here
+                        log.warn("Replica core={} coreNodeName={} set to active but the leader thinks it should be in recovery;"
+                            + " forcing it back to down state to re-run the leader-initiated recovery process; props: "+replicaProps.get(0), coreNeedingRecovery, replicaCoreNodeName);
+                        zkController.ensureReplicaInLeaderInitiatedRecovery(collection,
+                            shardId, replicaUrl, nodeProps, true); // force republish state to "down"
+                      }
+                    }
+                    break;
                   }
-                }                    
-              }                    
+                }
+              }
             }                  
           } catch (Exception ignoreMe) {
             log.warn("Failed to determine state of core={} coreNodeName={} due to: "+ignoreMe, coreNeedingRecovery, replicaCoreNodeName);

Modified: lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/Overseer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/Overseer.java?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/Overseer.java (original)
+++ lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/Overseer.java Sun Feb  8 23:53:14 2015
@@ -58,7 +58,7 @@ import org.apache.solr.common.params.Col
 import org.apache.solr.core.ConfigSolr;
 import org.apache.solr.handler.component.ShardHandler;
 import org.apache.solr.update.UpdateShardHandler;
-import org.apache.solr.util.IOUtils;
+import org.apache.solr.common.util.IOUtils;
 import org.apache.solr.util.stats.Clock;
 import org.apache.solr.util.stats.Timer;
 import org.apache.solr.util.stats.TimerContext;

Modified: lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/OverseerAutoReplicaFailoverThread.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/OverseerAutoReplicaFailoverThread.java?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/OverseerAutoReplicaFailoverThread.java (original)
+++ lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/OverseerAutoReplicaFailoverThread.java Sun Feb  8 23:53:14 2015
@@ -17,19 +17,8 @@ package org.apache.solr.cloud;
  * limitations under the License.
  */
 
-import java.io.Closeable;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import java.util.TreeMap;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.TimeUnit;
-
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
 import org.apache.solr.client.solrj.impl.HttpSolrClient;
 import org.apache.solr.client.solrj.request.CoreAdminRequest.Create;
 import org.apache.solr.common.SolrException;
@@ -44,8 +33,19 @@ import org.apache.solr.update.UpdateShar
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.cache.Cache;
-import com.google.common.cache.CacheBuilder;
+import java.io.Closeable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.TreeMap;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.TimeUnit;
 
 
 // TODO: how to tmp exclude nodes?
@@ -85,6 +85,7 @@ public class OverseerAutoReplicaFailover
   private volatile boolean isClosed;
   private ZkStateReader zkStateReader;
   private final Cache<String,Long> baseUrlForBadNodes;
+  private Set<String> liveNodes = Collections.EMPTY_SET;
 
   private final int workLoopDelay;
   private final int waitAfterExpiration;
@@ -151,11 +152,13 @@ public class OverseerAutoReplicaFailover
       return;
     }
     if (clusterState != null) {
-      if (lastClusterStateVersion == clusterState.getZkClusterStateVersion() && baseUrlForBadNodes.size() == 0) {
+      if (lastClusterStateVersion == clusterState.getZkClusterStateVersion() && baseUrlForBadNodes.size() == 0 &&
+          liveNodes.equals(clusterState.getLiveNodes())) {
         // nothing has changed, no work to do
         return;
       }
-      
+
+      liveNodes = clusterState.getLiveNodes();
       lastClusterStateVersion = clusterState.getZkClusterStateVersion();
       Set<String> collections = clusterState.getCollections();
       for (final String collection : collections) {
@@ -418,12 +421,11 @@ public class OverseerAutoReplicaFailover
   private boolean createSolrCore(final String collection,
       final String createUrl, final String dataDir, final String ulogDir,
       final String coreNodeName, final String coreName) {
-    HttpSolrClient server = null;
-    try {
+
+    try (HttpSolrClient client = new HttpSolrClient(createUrl)) {
       log.debug("create url={}", createUrl);
-      server = new HttpSolrClient(createUrl);
-      server.setConnectionTimeout(30000);
-      server.setSoTimeout(60000);
+      client.setConnectionTimeout(30000);
+      client.setSoTimeout(60000);
       Create createCmd = new Create();
       createCmd.setCollection(collection);
       createCmd.setCoreNodeName(coreNodeName);
@@ -432,14 +434,10 @@ public class OverseerAutoReplicaFailover
       createCmd.setCoreName(coreName);
       createCmd.setDataDir(dataDir);
       createCmd.setUlogDir(ulogDir);
-      server.request(createCmd);
+      client.request(createCmd);
     } catch (Exception e) {
       SolrException.log(log, "Exception trying to create new replica on " + createUrl, e);
       return false;
-    } finally {
-      if (server != null) {
-        server.shutdown();
-      }
     }
     return true;
   }

Modified: lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionProcessor.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionProcessor.java?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionProcessor.java (original)
+++ lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/OverseerCollectionProcessor.java Sun Feb  8 23:53:14 2015
@@ -1161,7 +1161,7 @@ public class OverseerCollectionProcessor
 
   private void deleteCollection(ZkNodeProps message, NamedList results)
       throws KeeperException, InterruptedException {
-    String collection = message.getStr("name");
+    final String collection = message.getStr("name");
     try {
       ModifiableSolrParams params = new ModifiableSolrParams();
       params.set(CoreAdminParams.ACTION, CoreAdminAction.UNLOAD.toString());
@@ -1181,7 +1181,7 @@ public class OverseerCollectionProcessor
       boolean removed = false;
       while (System.nanoTime() < timeout) {
         Thread.sleep(100);
-        removed = !zkStateReader.getClusterState().hasCollection(message.getStr(collection));
+        removed = !zkStateReader.getClusterState().hasCollection(collection);
         if (removed) {
           Thread.sleep(500); // just a bit of time so it's more likely other
                              // readers see on return
@@ -1190,7 +1190,7 @@ public class OverseerCollectionProcessor
       }
       if (!removed) {
         throw new SolrException(ErrorCode.SERVER_ERROR,
-            "Could not fully remove collection: " + message.getStr("name"));
+            "Could not fully remove collection: " + collection);
       }
       
     } finally {
@@ -1801,19 +1801,14 @@ public class OverseerCollectionProcessor
 
 
   static UpdateResponse softCommit(String url) throws SolrServerException, IOException {
-    HttpSolrClient client = null;
-    try {
-      client = new HttpSolrClient(url);
+
+    try (HttpSolrClient client = new HttpSolrClient(url)) {
       client.setConnectionTimeout(30000);
       client.setSoTimeout(120000);
       UpdateRequest ureq = new UpdateRequest();
       ureq.setParams(new ModifiableSolrParams());
       ureq.setAction(AbstractUpdateRequest.ACTION.COMMIT, false, true, true);
       return ureq.process(client);
-    } finally {
-      if (client != null) {
-        client.shutdown();
-      }
     }
   }
   
@@ -2318,6 +2313,13 @@ public class OverseerCollectionProcessor
     if (clusterState.hasCollection(collectionName)) {
       throw new SolrException(ErrorCode.BAD_REQUEST, "collection already exists: " + collectionName);
     }
+
+    String configName = getConfigName(collectionName, message);
+    if (configName == null) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "No config set found to associate with the collection.");
+    } else if (!validateConfig(configName)) {
+      throw new SolrException(ErrorCode.BAD_REQUEST, "Can not find the specified config set: " + configName);
+    }
     
     try {
       // look at the replication factor and see if it matches reality
@@ -2385,7 +2387,7 @@ public class OverseerCollectionProcessor
       }
       boolean isLegacyCloud =  Overseer.isLegacy(zkStateReader.getClusterProps());
 
-      String configName = createConfNode(collectionName, message, isLegacyCloud);
+      createConfNode(configName, collectionName, isLegacyCloud);
 
       Overseer.getInQueue(zkStateReader.getZkClient()).offer(ZkStateReader.toJSON(message));
 
@@ -2621,24 +2623,38 @@ public class OverseerCollectionProcessor
     } while (srsp != null);
   }
 
-  private String createConfNode(String coll, ZkNodeProps message, boolean isLegacyCloud) throws KeeperException, InterruptedException {
+  private String getConfigName(String coll, ZkNodeProps message) throws KeeperException, InterruptedException {
     String configName = message.getStr(OverseerCollectionProcessor.COLL_CONF);
-    if(configName == null){
+    
+    if (configName == null) {
       // if there is only one conf, use that
-      List<String> configNames=null;
+      List<String> configNames = null;
       try {
         configNames = zkStateReader.getZkClient().getChildren(ZkController.CONFIGS_ZKNODE, null, true);
         if (configNames != null && configNames.size() == 1) {
           configName = configNames.get(0);
           // no config set named, but there is only 1 - use it
           log.info("Only one config set found in zk - using it:" + configName);
+        } else if (configNames.contains(coll)) {
+          configName = coll;
         }
       } catch (KeeperException.NoNodeException e) {
 
       }
-
     }
+    return configName;
+  }
+  
+  private boolean validateConfig(String configName) throws KeeperException, InterruptedException {
+    return zkStateReader.getZkClient().exists(ZkController.CONFIGS_ZKNODE + "/" + configName, true);
+  }
 
+  /**
+   * This doesn't validate the config (path) itself and is just responsible for creating the confNode.
+   * That check should be done before the config node is created.
+   */
+  private void createConfNode(String configName, String coll, boolean isLegacyCloud) throws KeeperException, InterruptedException {
+    
     if (configName != null) {
       String collDir = ZkStateReader.COLLECTIONS_ZKNODE + "/" + coll;
       log.info("creating collections conf node {} ", collDir);
@@ -2655,7 +2671,6 @@ public class OverseerCollectionProcessor
         throw new SolrException(ErrorCode.BAD_REQUEST,"Unable to get config name");
       }
     }
-    return configName;
 
   }
 

Modified: lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java (original)
+++ lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/RecoveryStrategy.java Sun Feb  8 23:53:14 2015
@@ -200,17 +200,14 @@ public class RecoveryStrategy extends Th
 
   private void commitOnLeader(String leaderUrl) throws SolrServerException,
       IOException {
-    HttpSolrClient server = new HttpSolrClient(leaderUrl);
-    try {
-      server.setConnectionTimeout(30000);
+    try (HttpSolrClient client = new HttpSolrClient(leaderUrl)) {
+      client.setConnectionTimeout(30000);
       UpdateRequest ureq = new UpdateRequest();
       ureq.setParams(new ModifiableSolrParams());
       ureq.getParams().set(DistributedUpdateProcessor.COMMIT_END_POINT, true);
       ureq.getParams().set(UpdateParams.OPEN_SEARCHER, false);
       ureq.setAction(AbstractUpdateRequest.ACTION.COMMIT, false, true).process(
-          server);
-    } finally {
-      server.shutdown();
+          client);
     }
   }
 
@@ -594,9 +591,9 @@ public class RecoveryStrategy extends Th
   
   private void sendPrepRecoveryCmd(String leaderBaseUrl, String leaderCoreName, Slice slice)
       throws SolrServerException, IOException, InterruptedException, ExecutionException {
-    HttpSolrClient server = new HttpSolrClient(leaderBaseUrl);
-    try {
-      server.setConnectionTimeout(30000);
+
+    try (HttpSolrClient client = new HttpSolrClient(leaderBaseUrl)) {
+      client.setConnectionTimeout(30000);
       WaitForState prepCmd = new WaitForState();
       prepCmd.setCoreName(leaderCoreName);
       prepCmd.setNodeName(zkController.getNodeName());
@@ -607,14 +604,12 @@ public class RecoveryStrategy extends Th
       if (!Slice.CONSTRUCTION.equals(slice.getState()) && !Slice.RECOVERY.equals(slice.getState())) {
         prepCmd.setOnlyIfLeaderActive(true);
       }
-      HttpUriRequestResponse mrr = server.httpUriRequest(prepCmd);
+      HttpUriRequestResponse mrr = client.httpUriRequest(prepCmd);
       prevSendPreRecoveryHttpUriRequest = mrr.httpUriRequest;
       
       log.info("Sending prep recovery command to {}; {}", leaderBaseUrl, prepCmd.toString());
       
       mrr.future.get();
-    } finally {
-      server.shutdown();
     }
   }
 

Modified: lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/SolrZkServer.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/SolrZkServer.java?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/SolrZkServer.java (original)
+++ lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/SolrZkServer.java Sun Feb  8 23:53:14 2015
@@ -91,12 +91,9 @@ public class SolrZkServer {
       if (zkProps.getClientPortAddress() == null) {
         zkProps.setClientPort(Integer.parseInt(solrPort)+1000);
       }
-    } catch (QuorumPeerConfig.ConfigException e) {
+    } catch (QuorumPeerConfig.ConfigException | IOException e) {
       if (zkRun != null)
         throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
-    } catch (IOException e) {
-      if (zkRun != null)
-      throw new SolrException(SolrException.ErrorCode.SERVER_ERROR, e);
     }
   }
 
@@ -186,9 +183,7 @@ class SolrZkServerProps extends QuorumPe
 
       return cfg;
 
-    } catch (IOException e) {
-      throw new ConfigException("Error processing " + path, e);
-    } catch (IllegalArgumentException e) {
+    } catch (IOException | IllegalArgumentException e) {
       throw new ConfigException("Error processing " + path, e);
     }
   }

Modified: lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/SyncStrategy.java
URL: http://svn.apache.org/viewvc/lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/SyncStrategy.java?rev=1658277&r1=1658276&r2=1658277&view=diff
==============================================================================
--- lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/SyncStrategy.java (original)
+++ lucene/dev/branches/lucene6005/solr/core/src/java/org/apache/solr/cloud/SyncStrategy.java Sun Feb  8 23:53:14 2015
@@ -267,8 +267,8 @@ public class SyncStrategy {
         recoverRequestCmd.setAction(CoreAdminAction.REQUESTRECOVERY);
         recoverRequestCmd.setCoreName(coreName);
         
-        HttpSolrClient client = new HttpSolrClient(baseUrl, SyncStrategy.this.client);
-        try {
+        ;
+        try (HttpSolrClient client = new HttpSolrClient(baseUrl, SyncStrategy.this.client)) {
           client.setConnectionTimeout(30000);
           client.setSoTimeout(120000);
           client.request(recoverRequestCmd);
@@ -277,8 +277,6 @@ public class SyncStrategy {
           if (t instanceof Error) {
             throw (Error) t;
           }
-        } finally {
-          client.shutdown();
         }
       }
     };