You are viewing a plain text version of this content. The canonical link for it is here.
Posted to solr-commits@lucene.apache.org by ry...@apache.org on 2008/10/14 02:24:05 UTC

svn commit: r704288 - in /lucene/solr/trunk: ./ client/java/solrj/src/org/apache/solr/client/solrj/request/ client/java/solrj/test/org/apache/solr/client/solrj/ example/solr/conf/velocity/ lib/ src/java/org/apache/solr/handler/ src/java/org/apache/solr...

Author: ryan
Date: Mon Oct 13 17:24:04 2008
New Revision: 704288

URL: http://svn.apache.org/viewvc?rev=704288&view=rev
Log:
SOLR-793: Add 'commitWithin' argument to the update add command.  This behaves similar to the global autoCommit maxTime argument except that it is set for each request.
    

Added:
    lucene/solr/trunk/SOLR-620.patch
    lucene/solr/trunk/SOLR-657.patch
    lucene/solr/trunk/SOLR-793-commitWithin.patch
    lucene/solr/trunk/SOLR-793-commitWithin2.patch
    lucene/solr/trunk/example/solr/conf/velocity/
    lucene/solr/trunk/example/solr/conf/velocity/default.vm
    lucene/solr/trunk/lib/commons-collections-3.2.jar   (with props)
    lucene/solr/trunk/lib/commons-lang-2.4.jar   (with props)
    lucene/solr/trunk/lib/velocity-1.6-dev.jar   (with props)
    lucene/solr/trunk/src/java/org/apache/solr/request/VelocityResponseWriter.java
Modified:
    lucene/solr/trunk/CHANGES.txt
    lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/request/UpdateRequest.java
    lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/SolrExampleTests.java
    lucene/solr/trunk/src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java
    lucene/solr/trunk/src/java/org/apache/solr/update/AddUpdateCommand.java
    lucene/solr/trunk/src/java/org/apache/solr/update/DirectUpdateHandler2.java

Modified: lucene/solr/trunk/CHANGES.txt
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/CHANGES.txt?rev=704288&r1=704287&r2=704288&view=diff
==============================================================================
--- lucene/solr/trunk/CHANGES.txt (original)
+++ lucene/solr/trunk/CHANGES.txt Mon Oct 13 17:24:04 2008
@@ -49,6 +49,10 @@
  4. SOLR-658: Allow Solr to load index from arbitrary directory in dataDir
     (Noble Paul, Akshay Ukey via shalin)
     
+ 5. SOLR-793: Add 'commitWithin' argument to the update add command.  This behaves
+    similar to the global autoCommit maxTime argument except that it is set for 
+    each request.  (ryan)
+    
 
 Optimizations
 ----------------------

Added: lucene/solr/trunk/SOLR-620.patch
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/SOLR-620.patch?rev=704288&view=auto
==============================================================================
--- lucene/solr/trunk/SOLR-620.patch (added)
+++ lucene/solr/trunk/SOLR-620.patch Mon Oct 13 17:24:04 2008
@@ -0,0 +1,287 @@
+Index: src/java/org/apache/solr/request/VelocityResponseWriter.java
+===================================================================
+--- src/java/org/apache/solr/request/VelocityResponseWriter.java	(Revision 0)
++++ src/java/org/apache/solr/request/VelocityResponseWriter.java	(Revision 0)
+@@ -0,0 +1,222 @@
++/**
++ * Licensed to the Apache Software Foundation (ASF) under one or more
++ * contributor license agreements.  See the NOTICE file distributed with
++ * this work for additional information regarding copyright ownership.
++ * The ASF licenses this file to You under the Apache License, Version 2.0
++ * (the "License"); you may not use this file except in compliance with
++ * the License.  You may obtain a copy of the License at
++ *
++ *     http://www.apache.org/licenses/LICENSE-2.0
++ *
++ * Unless required by applicable law or agreed to in writing, software
++ * distributed under the License is distributed on an "AS IS" BASIS,
++ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
++ * See the License for the specific language governing permissions and
++ * limitations under the License.
++ */
++
++package org.apache.solr.request;
++
++import java.io.File;
++import java.io.IOException;
++import java.io.StringWriter;
++import java.io.Writer;
++import java.util.Iterator;
++
++import org.apache.lucene.document.Document;
++import org.apache.lucene.index.CorruptIndexException;
++import org.apache.lucene.search.Searcher;
++import org.apache.solr.client.solrj.SolrResponse;
++import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
++import org.apache.solr.common.SolrDocument;
++import org.apache.solr.common.util.NamedList;
++import org.apache.solr.search.DocSlice;
++import org.apache.solr.update.DocumentBuilder;
++import org.apache.velocity.Template;
++import org.apache.velocity.VelocityContext;
++import org.apache.velocity.app.VelocityEngine;
++
++/**
++ * <p> A response writer that uses velocity template for response creation.
++ *     Possible request parameters: </p>
++ * <ul>
++ *     <li> 
++ *         <b>vl.template:</b> 
++ *     	   The name of the template file without .vm suffix. </li>
++ *     <li> 
++ *         <b>vl.json:</b> 
++ *         A name of a Javascript method. If set, the response is wrapped into this object. 
++ *         useful for JSON requests. 
++ *     </li>
++ *     <li> 
++ *         <b>vl.content:</b> 
++ *         Specify a custom content type for the response. Default is "text/html" for standard requests,
++ *         and "text/x-json" for JSON requests.  
++ *     </li>
++ *     <li> 
++ *         <b>vl.response:</b> 
++ *         To provide an implementation of  {@link SolrResponse} inside the template,
++ *     	   specify the class name of the implementation. For convenience, it looks 
++ *         inside the package "org.apache.solr.client.solrj.response", so you only 
++ *         have to choose  eg. <i>QueryResponse, LikeResponse, MultiCoreResponse</i>.
++ *     	   Custom classes may be accessed using the full qualified class name, 
++ *         eg. <i>my.custom.package.CustomResponse</i>	
++ *     </li>
++ * </ul>
++ */
++public class VelocityResponseWriter implements QueryResponseWriter {
++
++	private static final String PARAMETER_TEMPLATE="vl.template";
++	private static final String PARAMETER_JSON="vl.json";
++	private static final String PARAMETER_RESPONSE="vl.response";
++	private static final String PARAMETER_CONTENT_TYPE="vl.content";
++	
++	public void write(Writer writer, SolrQueryRequest request,
++			SolrQueryResponse response) throws IOException {
++		
++		// init velocity and get template
++		VelocityEngine engine = new VelocityEngine();
++		File baseDir = new File(request.getCore().getResourceLoader().getConfigDir(), "velocity");
++		engine.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, baseDir.getAbsolutePath());
++		engine.setProperty(VelocityEngine.RESOURCE_LOADER, "file");
++		Template template;
++		try {
++			template = engine.getTemplate(request.getParams().get(PARAMETER_TEMPLATE, "default") + ".vm");
++		} catch (Exception e) {
++			throw new IOException(e.getMessage());
++		}
++		
++		// put raw response into context
++		VelocityContext context = new VelocityContext();
++		context.put("rawResponse", new RawResponseHelper(request, response));
++		
++		// convert response if a class is specified
++		if (request.getParams().get(PARAMETER_RESPONSE) != null) {
++			String className = request.getParams().get(PARAMETER_RESPONSE);
++			
++			// create SolrResponse using reflection
++			SolrResponse solrResponse;
++			Object object;
++			try {
++				object = request.getCore().getResourceLoader().newInstance(className, "client.solrj.response.");
++			} catch (RuntimeException e) {
++				throw new IOException("Unable to resolve response class \"" + className + "\": " + e.getMessage());
++			}
++			if (!(object instanceof SolrResponse)) {
++				throw new IOException("Class \"" + className + "\" doesn't implement SolrResponse!");
++			}
++			solrResponse = (SolrResponse) object;
++			
++			// inject the request into the response
++			solrResponse.setResponse(new EmbeddedSolrServer(request.getCore()).getParsedResponse(request, response));
++			
++			// put it into the context
++			context.put("response", solrResponse);
++		}
++		
++		// create output, optionally wrap it into a json object
++		if (isWrappedResponse(request)) {
++			StringWriter stringWriter = new StringWriter();
++			template.merge(context, stringWriter);
++			writer.write(request.getParams().get(PARAMETER_JSON) + "(");
++			writer.write(getJSONWrap(stringWriter.toString()));
++			writer.write(')');
++		} else {
++			template.merge(context, writer);
++		}
++
++	}
++
++	public String getContentType(SolrQueryRequest request,
++			SolrQueryResponse response) {
++		if (request.getParams().get(PARAMETER_CONTENT_TYPE) != null) {
++			return request.getParams().get(PARAMETER_CONTENT_TYPE);
++		}
++		if (isWrappedResponse(request)) {
++			return JSONResponseWriter.CONTENT_TYPE_JSON_UTF8;
++		}
++		return "text/html";
++	}
++
++	public void init(NamedList args) {
++		// TODO
++	}
++	
++	private boolean isWrappedResponse(SolrQueryRequest request) {
++		return request.getParams().get(PARAMETER_JSON) != null;
++	}
++	
++	public String getJSONWrap(String xmlResult) {
++		// escape the double quotes and backslashes
++		String replace1 = xmlResult.replaceAll("\\\\", "\\\\\\\\");
++		replace1 = replace1.replaceAll("\\n", "\\\\n");
++		replace1 = replace1.replaceAll("\\r", "\\\\r");
++		String replaced = replace1.replaceAll("\"", "\\\\\"");
++		// wrap it in a JSON object
++		return "{\"result\":\"" + replaced + "\"}";
++	}
++
++	/**
++	 * A helper class that provides convenient methods for the raw solr response.
++	 */
++	public class RawResponseHelper {
++
++		private Searcher searcher;
++		private SolrQueryResponse response;
++		private SolrQueryRequest request;
++
++		public RawResponseHelper(SolrQueryRequest request,
++				SolrQueryResponse response) {
++			this.searcher = request.getSearcher();
++			this.response = response;
++			this.request = request;
++		}
++
++		public Iterator<SolrDocument> getResultIterator() {
++			final Iterator<Integer> iterator = ((DocSlice) response.getValues()
++					.get("response")).iterator();
++			return new Iterator<SolrDocument>() {
++
++				public boolean hasNext() {
++					return iterator.hasNext();
++				}
++
++				public SolrDocument next() {
++					Document document = null;
++					SolrDocument solrDocument = new SolrDocument();
++					try {
++						document = searcher.doc(iterator.next());
++						new DocumentBuilder(request.getSchema()).loadStoredFields(solrDocument, document);
++					} catch (CorruptIndexException e) {
++						throw new RuntimeException("Error converting lucene document into solr document!");
++					} catch (IOException e) {
++						throw new RuntimeException("Error converting lucene document into solr document!");
++					}
++					
++					return solrDocument;
++				}
++
++				public void remove() {
++
++				}
++
++			};
++		}
++		
++		public String getRequestParameter(String param) {
++			return request.getParams().get(param);
++		}
++		
++		public SolrQueryRequest getRequest() {
++			return request;
++		}
++		
++		public SolrQueryResponse getResponse() {
++			return response;
++		}
++		
++		
++	}
++	
++	
++}
+Index: example/solr/conf/solrconfig.xml
+===================================================================
+--- example/solr/conf/solrconfig.xml	(Revision 679745)
++++ example/solr/conf/solrconfig.xml	(Arbeitskopie)
+@@ -726,7 +726,9 @@
+    -->
+   <queryResponseWriter name="xslt" class="org.apache.solr.request.XSLTResponseWriter">
+     <int name="xsltCacheLifetimeSeconds">5</int>
+-  </queryResponseWriter> 
++  </queryResponseWriter>
++
++  <queryResponseWriter name="velocity" class="org.apache.solr.request.VelocityResponseWriter"/>
+     
+   <!-- config for the admin interface --> 
+   <admin>
+Index: example/solr/conf/velocity/default.vm
+===================================================================
+--- example/solr/conf/velocity/default.vm	(Revision 0)
++++ example/solr/conf/velocity/default.vm	(Revision 0)
+@@ -0,0 +1,40 @@
++#set($iterator=$rawResponse.getResultIterator())
++#set($request=$rawResponse.request)
++#set($core=$request.core)
++#set($schema=$core.schema)
++
++<html>
++  <title>Default VelocityResponseWriter Response</title>
++  <body>
++  
++    <p>
++      A default response using only the raw solr response. The "rawResponse" object is a helper that provides access to the
++      SolrQueryRequest, SolrQueryResponse, as well as convenience methods like getResultIterator() and getRequestParam()
++    </p>
++    <p>
++      If you want to use an instance of SolrResponse of solrj inside a template, use eg. vl.response=QueryResponse. 
++      This object then is avalaible as "response" in the context.
++    </p>
++    <hr/>
++  
++    #foreach($document in $iterator)
++        #foreach($field in $document.getFieldNames())
++          <p>$field: $document.getFieldValue($field)</p>
++        #end
++    <hr/>
++    #end
++
++    <pre>
++      header = $rawResponse.$response.responseHeader
++
++      values = $rawResponse.$response.values
++
++      request = $request
++
++      core = $core
++
++      schema = $schema
++    </pre>
++
++  </body>
++</html>

Added: lucene/solr/trunk/SOLR-657.patch
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/SOLR-657.patch?rev=704288&view=auto
==============================================================================
--- lucene/solr/trunk/SOLR-657.patch (added)
+++ lucene/solr/trunk/SOLR-657.patch Mon Oct 13 17:24:04 2008
@@ -0,0 +1,675 @@
+diff --git a/src/java/org/apache/solr/analysis/SynonymFilterFactory.java b/src/java/org/apache/solr/analysis/SynonymFilterFactory.java
+index 41cee1f..6cc6c4a 100644
+--- a/src/java/org/apache/solr/analysis/SynonymFilterFactory.java
++++ b/src/java/org/apache/solr/analysis/SynonymFilterFactory.java
+@@ -134,7 +134,7 @@ public class SynonymFilterFactory extends BaseTokenFilterFactory implements Reso
+     List<String> tokList = new ArrayList<String>();
+     try {
+       for( Token token = ts.next(); token != null; token = ts.next() ){
+-        String text = token.termText();
++        String text = new String(token.termBuffer(), 0, token.termLength());
+         if( text.length() > 0 )
+           tokList.add( text );
+       }
+diff --git a/src/java/org/apache/solr/core/QuerySenderListener.java b/src/java/org/apache/solr/core/QuerySenderListener.java
+index 78777cf..f24c532 100644
+--- a/src/java/org/apache/solr/core/QuerySenderListener.java
++++ b/src/java/org/apache/solr/core/QuerySenderListener.java
+@@ -20,6 +20,7 @@ package org.apache.solr.core;
+ import org.apache.solr.search.SolrIndexSearcher;
+ import org.apache.solr.search.DocList;
+ import org.apache.solr.search.DocIterator;
++import org.apache.solr.common.params.CommonParams;
+ import org.apache.solr.common.util.NamedList;
+ import org.apache.solr.request.LocalSolrQueryRequest;
+ import org.apache.solr.request.SolrQueryResponse;
+@@ -47,7 +48,7 @@ class QuerySenderListener extends AbstractSolrEventListener {
+         };
+ 
+         SolrQueryResponse rsp = new SolrQueryResponse();
+-        core.execute(req,rsp);
++        core.execute(core.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
+diff --git a/src/java/org/apache/solr/core/SolrCore.java b/src/java/org/apache/solr/core/SolrCore.java
+index 0f1e656..c2f2169 100644
+--- a/src/java/org/apache/solr/core/SolrCore.java
++++ b/src/java/org/apache/solr/core/SolrCore.java
+@@ -38,7 +38,7 @@ import org.apache.solr.schema.IndexSchema;
+ import org.apache.solr.search.QParserPlugin;
+ import org.apache.solr.search.SolrIndexSearcher;
+ import org.apache.solr.search.ValueSourceParser;
+-import org.apache.solr.update.DirectUpdateHandler;
++import org.apache.solr.update.DirectUpdateHandler2;
+ import org.apache.solr.update.SolrIndexWriter;
+ import org.apache.solr.update.UpdateHandler;
+ import org.apache.solr.update.processor.LogUpdateProcessorFactory;
+@@ -470,7 +470,7 @@ public final class SolrCore implements SolrInfoMBean {
+         getSearcher(false,false,null);
+   
+         updateHandler = createUpdateHandler(
+-          solrConfig.get("updateHandler/@class", DirectUpdateHandler.class.getName())
++          solrConfig.get("updateHandler/@class", DirectUpdateHandler2.class.getName())
+         );
+ 
+         infoRegistry.put("updateHandler", updateHandler);
+@@ -1190,8 +1190,8 @@ public final class SolrCore implements SolrInfoMBean {
+ 
+   public void execute(SolrRequestHandler handler, SolrQueryRequest req, SolrQueryResponse rsp) {
+     if (handler==null) {
+-      log.warning(logid+"Null Request Handler '" + req.getQueryType() +"' :" + req);
+-      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,"Null Request Handler '" + req.getQueryType() + "'", true);
++      log.warning(logid+"Null Request Handler '" + req.getParams().get(CommonParams.QT) +"' :" + req);
++      throw new SolrException(SolrException.ErrorCode.BAD_REQUEST,"Null Request Handler '" + req.getParams().get(CommonParams.QT) + "'", true);
+     }
+     // setup response header and handle request
+     final NamedList<Object> responseHeader = new SimpleOrderedMap<Object>();
+@@ -1320,7 +1320,7 @@ public final class SolrCore implements SolrInfoMBean {
+    * 'wt' parameter, attempts to find that one; otherwise return the default writer.
+    */
+   public final QueryResponseWriter getQueryResponseWriter(SolrQueryRequest request) {
+-    return getQueryResponseWriter(request.getParam("wt")); 
++    return getQueryResponseWriter(request.getParams().get(CommonParams.WT)); 
+   }
+ 
+   private final Map<String, QParserPlugin> qParserPlugins = new HashMap<String, QParserPlugin>();
+diff --git a/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java b/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
+index 046cbc2..ead5c65 100644
+--- a/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
++++ b/src/java/org/apache/solr/handler/admin/LukeRequestHandler.java
+@@ -376,7 +376,7 @@ public class LukeRequestHandler extends RequestHandlerBase
+     finfo.add("fields", fields);
+     finfo.add("dynamicFields", dynamicFields);
+     finfo.add("uniqueKeyField", uniqueField.getName());
+-    finfo.add("defaultSearchField", schema.getDefaultSearchFieldName());
++    finfo.add("defaultSearchField", schema.getSolrQueryParser(null).getField());
+     finfo.add("types", types);
+     return finfo;
+   }
+diff --git a/src/java/org/apache/solr/handler/admin/SystemInfoHandler.java b/src/java/org/apache/solr/handler/admin/SystemInfoHandler.java
+index ba2adda..51ad696 100644
+--- a/src/java/org/apache/solr/handler/admin/SystemInfoHandler.java
++++ b/src/java/org/apache/solr/handler/admin/SystemInfoHandler.java
+@@ -73,7 +73,7 @@ public class SystemInfoHandler extends RequestHandlerBase
+     SimpleOrderedMap<Object> info = new SimpleOrderedMap<Object>();
+     
+     IndexSchema schema = core.getSchema();
+-    info.add( "schema", schema != null ? schema.getName():"no schema!" );
++    info.add( "schema", schema != null ? schema.getSchemaName():"no schema!" );
+     
+     // Host
+     InetAddress addr = InetAddress.getLocalHost();
+diff --git a/src/java/org/apache/solr/handler/component/QueryElevationComponent.java b/src/java/org/apache/solr/handler/component/QueryElevationComponent.java
+index 5cbd5f6..a12d140 100644
+--- a/src/java/org/apache/solr/handler/component/QueryElevationComponent.java
++++ b/src/java/org/apache/solr/handler/component/QueryElevationComponent.java
+@@ -299,7 +299,7 @@ public class QueryElevationComponent extends SearchComponent implements SolrCore
+     TokenStream tokens = analyzer.tokenStream( null, new StringReader( query ) );
+     Token token = tokens.next();
+     while( token != null ) {
+-      norm.append( token.termText() );
++      norm.append( new String(token.termBuffer(), 0, token.termLength()) );
+       token = tokens.next();
+     }
+     return norm.toString();
+diff --git a/src/java/org/apache/solr/request/TextResponseWriter.java b/src/java/org/apache/solr/request/TextResponseWriter.java
+index f7a21c6..b377650 100644
+--- a/src/java/org/apache/solr/request/TextResponseWriter.java
++++ b/src/java/org/apache/solr/request/TextResponseWriter.java
+@@ -18,6 +18,7 @@
+ package org.apache.solr.request;
+ 
+ import org.apache.lucene.document.Document;
++import org.apache.solr.common.params.CommonParams;
+ import org.apache.solr.common.util.NamedList;
+ import org.apache.solr.common.util.FastWriter;
+ import org.apache.solr.common.SolrDocument;
+@@ -54,7 +55,7 @@ public abstract class TextResponseWriter {
+     this.schema = req.getSchema();
+     this.req = req;
+     this.rsp = rsp;
+-    String indent = req.getParam("indent");
++    String indent = req.getParams().get("indent");
+     if (indent != null && !"".equals(indent) && !"off".equals(indent)) {
+       doIndent=true;
+     }
+diff --git a/src/java/org/apache/solr/request/XMLWriter.java b/src/java/org/apache/solr/request/XMLWriter.java
+index 1735159..c6f5a05 100644
+--- a/src/java/org/apache/solr/request/XMLWriter.java
++++ b/src/java/org/apache/solr/request/XMLWriter.java
+@@ -19,6 +19,7 @@ package org.apache.solr.request;
+ 
+ import org.apache.solr.common.SolrDocument;
+ import org.apache.solr.common.SolrDocumentList;
++import org.apache.solr.common.params.CommonParams;
+ import org.apache.solr.common.util.NamedList;
+ import org.apache.solr.common.util.XML;
+ import org.apache.solr.search.SolrIndexSearcher;
+@@ -61,18 +62,18 @@ final public class XMLWriter {
+ 
+   public static void writeResponse(Writer writer, SolrQueryRequest req, SolrQueryResponse rsp) throws IOException {
+ 
+-    String ver = req.getParam("version");
++    String ver = req.getParams().get(CommonParams.VERSION);
+ 
+     writer.write(XML_START1);
+ 
+-    String stylesheet = req.getParam("stylesheet");
++    String stylesheet = req.getParams().get("stylesheet");
+     if (stylesheet != null && stylesheet.length() > 0) {
+       writer.write(XML_STYLESHEET);
+       writer.write(stylesheet);
+       writer.write(XML_STYLESHEET_END);
+     }
+ 
+-    String noSchema = req.getParam("noSchema");
++    String noSchema = req.getParams().get("noSchema");
+     // todo - change when schema becomes available?
+     if (false && noSchema == null)
+       writer.write(XML_START2_SCHEMA);
+@@ -87,7 +88,7 @@ final public class XMLWriter {
+     XMLWriter xw = new XMLWriter(writer, req.getSchema(), req, ver);
+     xw.defaultFieldList = rsp.getReturnFields();
+ 
+-    String indent = req.getParam("indent");
++    String indent = req.getParams().get("indent");
+     if (indent != null) {
+       if ("".equals(indent) || "off".equals(indent)) {
+         xw.setIndent(false);
+diff --git a/src/java/org/apache/solr/search/FieldQParserPlugin.java b/src/java/org/apache/solr/search/FieldQParserPlugin.java
+index ed3c5ba..1dca87a 100644
+--- a/src/java/org/apache/solr/search/FieldQParserPlugin.java
++++ b/src/java/org/apache/solr/search/FieldQParserPlugin.java
+@@ -97,7 +97,7 @@ public class FieldQParserPlugin extends QParserPlugin {
+           return null;
+         else if (lst.size() == 1) {
+           t = lst.get(0);
+-          return new TermQuery(new Term(field, t.termText()));
++          return new TermQuery(new Term(field, new String(t.termBuffer(), 0, t.termLength())));
+         } else {
+           if (severalTokensAtSamePosition) {
+             if (positionCount == 1) {
+@@ -106,7 +106,7 @@ public class FieldQParserPlugin extends QParserPlugin {
+               for (int i = 0; i < lst.size(); i++) {
+                 t = (org.apache.lucene.analysis.Token) lst.get(i);
+                 TermQuery currentQuery = new TermQuery(
+-                        new Term(field, t.termText()));
++                        new Term(field, new String(t.termBuffer(), 0, t.termLength())));
+                 q.add(currentQuery, BooleanClause.Occur.SHOULD);
+               }
+               return q;
+@@ -122,7 +122,7 @@ public class FieldQParserPlugin extends QParserPlugin {
+                   mpq.add((Term[])multiTerms.toArray(new Term[0]));
+                   multiTerms.clear();
+                 }
+-                multiTerms.add(new Term(field, t.termText()));
++                multiTerms.add(new Term(field, new String(t.termBuffer(), 0, t.termLength())));
+               }
+               mpq.add((Term[])multiTerms.toArray(new Term[0]));
+               return mpq;
+@@ -132,7 +132,8 @@ public class FieldQParserPlugin extends QParserPlugin {
+             PhraseQuery q = new PhraseQuery();
+             q.setSlop(phraseSlop);
+             for (int i = 0; i < lst.size(); i++) {
+-              q.add(new Term(field, lst.get(i).termText()));
++              Token token = lst.get(i);
++              q.add(new Term(field, new String(token.termBuffer(), 0, token.termLength())));
+             }
+             return q;
+           }
+diff --git a/src/java/org/apache/solr/search/LuceneQParserPlugin.java b/src/java/org/apache/solr/search/LuceneQParserPlugin.java
+index 33a1fbe..5ae9cd6 100755
+--- a/src/java/org/apache/solr/search/LuceneQParserPlugin.java
++++ b/src/java/org/apache/solr/search/LuceneQParserPlugin.java
+@@ -61,7 +61,7 @@ class LuceneQParser extends QParser {
+ 
+     String defaultField = getParam(CommonParams.DF);
+     if (defaultField==null) {
+-      defaultField = getReq().getSchema().getDefaultSearchFieldName();
++      defaultField = getReq().getSchema().getSolrQueryParser(null).getField();
+     }
+     lparser = new SolrQueryParser(this, defaultField);
+ 
+@@ -71,7 +71,7 @@ class LuceneQParser extends QParser {
+       lparser.setDefaultOperator("AND".equals(opParam) ? QueryParser.Operator.AND : QueryParser.Operator.OR);
+     } else {
+       // try to get default operator from schema
+-          String operator = getReq().getSchema().getQueryParserDefaultOperator();
++          String operator = getReq().getSchema().getSolrQueryParser(null).getField();
+       lparser.setDefaultOperator("AND".equals(operator) ?
+                           QueryParser.Operator.AND : QueryParser.Operator.OR);
+     }
+diff --git a/src/java/org/apache/solr/search/LuceneQueryOptimizer.java b/src/java/org/apache/solr/search/LuceneQueryOptimizer.java
+index df9020f..758c351 100644
+--- a/src/java/org/apache/solr/search/LuceneQueryOptimizer.java
++++ b/src/java/org/apache/solr/search/LuceneQueryOptimizer.java
+@@ -97,7 +97,7 @@ if (c.query instanceof TermQuery) {
+         filter = (Filter)cache.get(filterQuery);
+       }
+       if (filter == null) {                       // miss
+-        filter = new QueryFilter(filterQuery);    // construct new entry
++        filter = new CachingWrapperFilter(new QueryWrapperFilter(filterQuery)); // construct new entry
+         synchronized (cache) {
+           cache.put(filterQuery, filter);         // cache it
+         }
+diff --git a/src/java/org/apache/solr/util/HighlightingUtils.java b/src/java/org/apache/solr/util/HighlightingUtils.java
+index b2a5aae..04ac761 100644
+--- a/src/java/org/apache/solr/util/HighlightingUtils.java
++++ b/src/java/org/apache/solr/util/HighlightingUtils.java
+@@ -325,7 +325,7 @@ class MultiValueTokenStream extends TokenStream {
+     }
+     // create an modified token which is the offset into the concatenated
+     // string of all values
+-    Token offsetToken = new Token(nextToken.termText(), 
++    Token offsetToken = new Token(new String(nextToken.termBuffer(), 0, nextToken.termLength()), 
+                                   nextToken.startOffset() + curOffset,
+                                   nextToken.endOffset() + curOffset);
+     offsetToken.setPositionIncrement(nextToken.getPositionIncrement() + extra*10);
+diff --git a/src/java/org/apache/solr/util/SolrPluginUtils.java b/src/java/org/apache/solr/util/SolrPluginUtils.java
+index c0b5b0b..eef0904 100644
+--- a/src/java/org/apache/solr/util/SolrPluginUtils.java
++++ b/src/java/org/apache/solr/util/SolrPluginUtils.java
+@@ -180,7 +180,7 @@ public class SolrPluginUtils {
+   public static int setReturnFields(SolrQueryRequest req,
+                                     SolrQueryResponse res) {
+ 
+-    return setReturnFields(req.getParam(FL), res);
++    return setReturnFields(req.getParams().get(org.apache.solr.common.params.CommonParams.FL), res);
+   }
+ 
+   /**
+@@ -382,14 +382,14 @@ public class SolrPluginUtils {
+                                           DocList results)
+     throws IOException {
+ 
+-    String debug = req.getParam(org.apache.solr.common.params.CommonParams.DEBUG_QUERY);
++    String debug = req.getParams().get(org.apache.solr.common.params.CommonParams.DEBUG_QUERY);
+ 
+     NamedList dbg = null;
+     if (debug!=null) {
+       dbg = new SimpleOrderedMap();
+ 
+       /* userQuery may have been pre-processes .. expose that */
+-      dbg.add("rawquerystring", req.getQueryString());
++      dbg.add("rawquerystring", req.getParams().get(org.apache.solr.common.params.CommonParams.Q));
+       dbg.add("querystring", userQuery);
+ 
+       /* QueryParsing.toString isn't perfect, use it to see converted
+@@ -401,7 +401,7 @@ public class SolrPluginUtils {
+ 
+       dbg.add("explain", getExplainList
+               (query, results, req.getSearcher(), req.getSchema()));
+-      String otherQueryS = req.getParam("explainOther");
++      String otherQueryS = req.getParams().get(org.apache.solr.common.params.CommonParams.EXPLAIN_OTHER);
+       if (otherQueryS != null && otherQueryS.length() > 0) {
+         DocList otherResults = doSimpleQuery
+           (otherQueryS,req.getSearcher(), req.getSchema(),0,10);
+@@ -804,7 +804,7 @@ public class SolrPluginUtils {
+    */
+   public static Sort getSort(SolrQueryRequest req) {
+ 
+-    String sort = req.getParam(org.apache.solr.common.params.CommonParams.SORT);
++    String sort = req.getParams().get(org.apache.solr.common.params.CommonParams.SORT);
+     if (null == sort || sort.equals("")) {
+       return null;
+     }
+diff --git a/src/java/org/apache/solr/util/SuggestMissingFactories.java b/src/java/org/apache/solr/util/SuggestMissingFactories.java
+index 9556c1e..b8d0625 100644
+--- a/src/java/org/apache/solr/util/SuggestMissingFactories.java
++++ b/src/java/org/apache/solr/util/SuggestMissingFactories.java
+@@ -131,7 +131,7 @@ class FindClasses {
+     try {
+       for (int i =0; i < jars.length; i++) {
+         jarFiles[i] = new JarFile(jars[i]);
+-        urls[i] = jars[i].toURL();
++        urls[i] = jars[i].toURI().toURL();
+       }
+     } catch (MalformedURLException e) {
+       throw new RuntimeException
+diff --git a/src/java/org/apache/solr/util/TestHarness.java b/src/java/org/apache/solr/util/TestHarness.java
+index 35ed671..7a81034 100644
+--- a/src/java/org/apache/solr/util/TestHarness.java
++++ b/src/java/org/apache/solr/util/TestHarness.java
+@@ -17,6 +17,7 @@
+ 
+ package org.apache.solr.util;
+ 
++import org.apache.solr.common.params.CommonParams;
+ import org.apache.solr.common.util.NamedList;
+ import org.apache.solr.common.util.XML;
+ import org.apache.solr.core.SolrConfig;
+@@ -117,7 +118,7 @@ public class TestHarness {
+       public TestHarness( String dataDirectory,
+                           SolrConfig solrConfig,
+                           String schemaFile) {
+-     this( dataDirectory, solrConfig, new IndexSchema(solrConfig, schemaFile));
++     this( dataDirectory, solrConfig, new IndexSchema(solrConfig, schemaFile, null));
+    }
+    /**
+     * @param dataDirectory path for index data, will not be cleaned up
+@@ -300,7 +301,7 @@ public class TestHarness {
+    * @see LocalSolrQueryRequest
+    */
+   public String query(SolrQueryRequest req) throws IOException, Exception {
+-    return query(req.getQueryType(), req);
++    return query(req.getParams().get(CommonParams.QT), req);
+   }
+ 
+   /**
+diff --git a/src/test/org/apache/solr/BasicFunctionalityTest.java b/src/test/org/apache/solr/BasicFunctionalityTest.java
+index cf91a02..ce45cd2 100644
+--- a/src/test/org/apache/solr/BasicFunctionalityTest.java
++++ b/src/test/org/apache/solr/BasicFunctionalityTest.java
+@@ -21,6 +21,7 @@ import org.apache.lucene.document.*;
+ import org.apache.lucene.search.Query;
+ import org.apache.lucene.search.BooleanQuery;
+ import org.apache.solr.common.params.AppendedSolrParams;
++import org.apache.solr.common.params.CommonParams;
+ import org.apache.solr.common.params.DefaultSolrParams;
+ import org.apache.solr.common.params.MapSolrParams;
+ import org.apache.solr.common.params.SolrParams;
+@@ -297,14 +298,14 @@ public class BasicFunctionalityTest extends AbstractSolrTestCase {
+     args.put("string", "string value");
+     args.put("array", new String[] {"array", "value"});
+     SolrQueryRequest req = new LocalSolrQueryRequest(null, null, null, 0, 20, args);
+-    assertEquals("string value", req.getParam("string"));
+-    assertEquals("array", req.getParam("array"));
++    assertEquals("string value", req.getParams().get("string"));
++    assertEquals("array", req.getParams().get("array"));
+ 
+-    String[] stringParams = req.getParams("string");
++    String[] stringParams = req.getParams().getParams("string");
+     assertEquals(1, stringParams.length);
+     assertEquals("string value", stringParams[0]);
+ 
+-    String[] arrayParams = req.getParams("array");
++    String[] arrayParams = req.getParams().getParams("array");
+     assertEquals(2, arrayParams.length);
+     assertEquals("array", arrayParams[0]);
+     assertEquals("value", arrayParams[1]);
+@@ -337,7 +338,7 @@ public class BasicFunctionalityTest extends AbstractSolrTestCase {
+   
+   public void testTermVectorFields() {
+     
+-    IndexSchema ischema = new IndexSchema(solrConfig, getSchemaFile());
++    IndexSchema ischema = new IndexSchema(solrConfig, getSchemaFile(), null);
+     SchemaField f; // Solr field type
+     Field luf; // Lucene field
+ 
+@@ -506,7 +507,7 @@ public class BasicFunctionalityTest extends AbstractSolrTestCase {
+   }   
+   public void testCompressableFieldType() {
+     
+-    IndexSchema ischema = new IndexSchema(solrConfig, getSchemaFile());
++    IndexSchema ischema = new IndexSchema(solrConfig, getSchemaFile(), null);
+     SchemaField f; // Solr field type
+     Field luf; // Lucene field
+ 
+@@ -538,7 +539,7 @@ public class BasicFunctionalityTest extends AbstractSolrTestCase {
+    
+     SolrQueryRequest req = req("q", "title:keyword", "fl", "id,title,test_hlt");
+     SolrQueryResponse rsp = new SolrQueryResponse();
+-    core.execute(req, rsp);
++    core.execute(core.getRequestHandler(req.getParams().get(CommonParams.QT)), req, rsp);
+ 
+     DocList dl = (DocList) rsp.getValues().get("response");
+     org.apache.lucene.document.Document d = req.getSearcher().doc(dl.iterator().nextDoc());
+@@ -558,7 +559,7 @@ public class BasicFunctionalityTest extends AbstractSolrTestCase {
+     
+     SolrQueryRequest req = req("q", "title:keyword", "fl", "id,title");
+     SolrQueryResponse rsp = new SolrQueryResponse();
+-    core.execute(req, rsp);
++    core.execute(core.getRequestHandler(req.getParams().get(CommonParams.QT)), req, rsp);
+ 
+     DocList dl = (DocList) rsp.getValues().get("response");
+     DocIterator di = dl.iterator();    
+diff --git a/src/test/org/apache/solr/analysis/BaseTokenTestCase.java b/src/test/org/apache/solr/analysis/BaseTokenTestCase.java
+index 2487ca3..322b19f 100644
+--- a/src/test/org/apache/solr/analysis/BaseTokenTestCase.java
++++ b/src/test/org/apache/solr/analysis/BaseTokenTestCase.java
+@@ -37,10 +37,10 @@ public abstract class BaseTokenTestCase extends AnalysisTestCase
+     StringBuffer out = new StringBuffer();
+     Token t = in.next();
+     if (null != t)
+-      out.append(t.termText());
++      out.append(new String(t.termBuffer(), 0, t.termLength()));
+     
+     for (t = in.next(); null != t; t = in.next()) {
+-      out.append(" ").append(t.termText());
++      out.append(" ").append(new String(t.termBuffer(), 0, t.termLength()));
+     }
+     in.close();
+     return out.toString();
+@@ -49,7 +49,7 @@ public abstract class BaseTokenTestCase extends AnalysisTestCase
+   public List<String> tok2str(Iterable<Token> tokLst) {
+     ArrayList<String> lst = new ArrayList<String>();
+     for ( Token t : tokLst ) {
+-      lst.add( t.termText());
++      lst.add( new String(t.termBuffer(), 0, t.termLength()));
+     }
+     return lst;
+   }
+@@ -70,7 +70,7 @@ public abstract class BaseTokenTestCase extends AnalysisTestCase
+     for (Iterator iter = a.iterator(); iter.hasNext();) {
+       Token tok = (Token)iter.next();
+       pos += tok.getPositionIncrement();
+-      if (!tokAt(b, tok.termText(), pos
++      if (!tokAt(b, new String(tok.termBuffer(), 0, tok.termLength()), pos
+               , checkOff ? tok.startOffset() : -1
+               , checkOff ? tok.endOffset() : -1
+               )) 
+@@ -85,7 +85,7 @@ public abstract class BaseTokenTestCase extends AnalysisTestCase
+     for (Iterator iter = lst.iterator(); iter.hasNext();) {
+       Token tok = (Token)iter.next();
+       pos += tok.getPositionIncrement();
+-      if (pos==tokPos && tok.termText().equals(val)
++      if (pos==tokPos && new String(tok.termBuffer(), 0, tok.termLength()).equals(val)
+           && (startOff==-1 || tok.startOffset()==startOff)
+           && (endOff  ==-1 || tok.endOffset()  ==endOff  )
+            )
+diff --git a/src/test/org/apache/solr/analysis/TestBufferedTokenStream.java b/src/test/org/apache/solr/analysis/TestBufferedTokenStream.java
+index 6226a10..b24c2a4 100644
+--- a/src/test/org/apache/solr/analysis/TestBufferedTokenStream.java
++++ b/src/test/org/apache/solr/analysis/TestBufferedTokenStream.java
+@@ -33,9 +33,9 @@ public class TestBufferedTokenStream extends BaseTokenTestCase {
+   public static class AB_Q_Stream extends BufferedTokenStream {
+     public AB_Q_Stream(TokenStream input) {super(input);}
+     protected Token process(Token t) throws IOException {
+-      if ("A".equals(t.termText())) {
++      if ("A".equals(new String(t.termBuffer(), 0, t.termLength()))) {
+         Token t2 = read();
+-        if (t2!=null && "B".equals(t2.termText())) t.setTermText("Q");
++        if (t2!=null && "B".equals(new String(t2.termBuffer(), 0, t2.termLength()))) t.setTermText("Q");
+         if (t2!=null) pushBack(t2);
+       }
+       return t;
+@@ -46,7 +46,8 @@ public class TestBufferedTokenStream extends BaseTokenTestCase {
+   public static class AB_AAB_Stream extends BufferedTokenStream {
+     public AB_AAB_Stream(TokenStream input) {super(input);}
+     protected Token process(Token t) throws IOException {
+-      if ("A".equals(t.termText()) && "B".equals(peek(1).termText()))
++      if ("A".equals(new String(t.termBuffer(), 0, t.termLength())) && 
++          "B".equals(new String(peek(1).termBuffer(), 0, peek(1).termLength())))
+         write(t);
+       return t;
+     }
+diff --git a/src/test/org/apache/solr/analysis/TestPatternTokenizerFactory.java b/src/test/org/apache/solr/analysis/TestPatternTokenizerFactory.java
+index 4ddeaf3..4727a6a 100644
+--- a/src/test/org/apache/solr/analysis/TestPatternTokenizerFactory.java
++++ b/src/test/org/apache/solr/analysis/TestPatternTokenizerFactory.java
+@@ -65,7 +65,7 @@ public class TestPatternTokenizerFactory extends AnalysisTestCase
+         int i=0;
+         for( Token t = stream.next(); null != t; t = stream.next() ) 
+         {
+-          assertEquals( "split: "+test[1] + " "+i, split[i++], t.termText() );
++          assertEquals( "split: "+test[1] + " "+i, split[i++], new String(t.termBuffer(), 0, t.termLength()) );
+         }
+       }
+     } 
+diff --git a/src/test/org/apache/solr/analysis/TestSynonymMap.java b/src/test/org/apache/solr/analysis/TestSynonymMap.java
+index fb627db..e0bd7c8 100644
+--- a/src/test/org/apache/solr/analysis/TestSynonymMap.java
++++ b/src/test/org/apache/solr/analysis/TestSynonymMap.java
+@@ -259,7 +259,7 @@ public class TestSynonymMap extends AnalysisTestCase {
+     Token[] tokens = ((SynonymMap)map.submap.get( src )).synonyms;
+     boolean inc = false;
+     for( Token token : tokens ){
+-      if( exp.equals( token.termText() ) )
++      if( exp.equals( new String(token.termBuffer(), 0, token.termLength()) ) )
+         inc = true;
+     }
+     assertTrue( inc );
+diff --git a/src/test/org/apache/solr/analysis/TestWordDelimiterFilter.java b/src/test/org/apache/solr/analysis/TestWordDelimiterFilter.java
+index 0b34fdc..1b8084e 100644
+--- a/src/test/org/apache/solr/analysis/TestWordDelimiterFilter.java
++++ b/src/test/org/apache/solr/analysis/TestWordDelimiterFilter.java
+@@ -147,17 +147,18 @@ public class TestWordDelimiterFilter extends AbstractSolrTestCase {
+ 
+     int i=0;
+     for(Token t; (t=wdf.next())!=null;) {
+-      if (t.termText().equals("foo")) {
++      String termText = new String(t.termBuffer(), 0, t.termLength());
++      if (termText.equals("foo")) {
+         assertEquals(5, t.startOffset());
+         assertEquals(8, t.endOffset());
+         i++;
+       }
+-      if (t.termText().equals("bar")) {
++      if (termText.equals("bar")) {
+         assertEquals(9, t.startOffset());
+         assertEquals(12, t.endOffset());
+         i++;
+       }
+-      if (t.termText().equals("foobar")) {
++      if (termText.equals("foobar")) {
+         assertEquals(5, t.startOffset());
+         assertEquals(12, t.endOffset());
+         i++;
+diff --git a/src/test/org/apache/solr/highlight/HighlighterConfigTest.java b/src/test/org/apache/solr/highlight/HighlighterConfigTest.java
+index a0e58db..e38ff63 100644
+--- a/src/test/org/apache/solr/highlight/HighlighterConfigTest.java
++++ b/src/test/org/apache/solr/highlight/HighlighterConfigTest.java
+@@ -35,7 +35,7 @@ public class HighlighterConfigTest extends AbstractSolrTestCase {
+ 	  
+ 	  public void testConfig()
+ 	  {
+-	    SolrHighlighter highlighter = SolrCore.getSolrCore().getHighlighter();
++	    SolrHighlighter highlighter = h.getCore().getHighlighter();
+ 	    System.out.println( "highlighter" );
+ 
+ 	    assertTrue( highlighter instanceof DummyHighlighter );
+diff --git a/src/test/org/apache/solr/highlight/HighlighterTest.java b/src/test/org/apache/solr/highlight/HighlighterTest.java
+index fab092a..2ebeb9f 100755
+--- a/src/test/org/apache/solr/highlight/HighlighterTest.java
++++ b/src/test/org/apache/solr/highlight/HighlighterTest.java
+@@ -54,7 +54,7 @@ public class HighlighterTest extends AbstractSolrTestCase {
+   
+   public void testConfig()
+   {
+-    SolrHighlighter highlighter = SolrCore.getSolrCore().getHighlighter();
++    SolrHighlighter highlighter = h.getCore().getHighlighter();
+     System.out.println( "highlighter" );
+ 
+     // Make sure we loaded the one formatter
+diff --git a/src/test/org/apache/solr/schema/DateFieldTest.java b/src/test/org/apache/solr/schema/DateFieldTest.java
+index 785db52..d672023 100644
+--- a/src/test/org/apache/solr/schema/DateFieldTest.java
++++ b/src/test/org/apache/solr/schema/DateFieldTest.java
+@@ -99,11 +99,10 @@ public class DateFieldTest extends LegacyDateFieldTest {
+   }
+   
+   public void testFormatter() {
+-    DateFormat fmt = f.getThreadLocalDateFormat();
+-    assertEquals("1970-01-01T00:00:00.005", fmt.format(new Date(5)));
+-    assertEquals("1970-01-01T00:00:00",     fmt.format(new Date(0)));
+-    assertEquals("1970-01-01T00:00:00.37",  fmt.format(new Date(370)));
+-    assertEquals("1970-01-01T00:00:00.9",   fmt.format(new Date(900)));
++    assertEquals("1970-01-01T00:00:00.005", f.formatDate(new Date(5)));
++    assertEquals("1970-01-01T00:00:00",     f.formatDate(new Date(0)));
++    assertEquals("1970-01-01T00:00:00.37",  f.formatDate(new Date(370)));
++    assertEquals("1970-01-01T00:00:00.9",   f.formatDate(new Date(900)));
+ 
+   }
+ 
+diff --git a/src/test/org/apache/solr/schema/LegacyDateFieldTest.java b/src/test/org/apache/solr/schema/LegacyDateFieldTest.java
+index 201db56..4d3e6bb 100644
+--- a/src/test/org/apache/solr/schema/LegacyDateFieldTest.java
++++ b/src/test/org/apache/solr/schema/LegacyDateFieldTest.java
+@@ -95,11 +95,10 @@ public class LegacyDateFieldTest extends TestCase {
+     assertItoR("1995-12-31T23:59:59Z",     "1995-12-31T23:59:59");
+   }
+   public void testFormatter() {
+-    DateFormat fmt = f.getThreadLocalDateFormat();
+-    assertEquals("1970-01-01T00:00:00.005", fmt.format(new Date(5)));
++    assertEquals("1970-01-01T00:00:00.005", f.formatDate(new Date(5)));
+     // all of this is broken behavior
+-    assertEquals("1970-01-01T00:00:00.000", fmt.format(new Date(0)));
+-    assertEquals("1970-01-01T00:00:00.370", fmt.format(new Date(370)));
+-    assertEquals("1970-01-01T00:00:00.900", fmt.format(new Date(900)));
++    assertEquals("1970-01-01T00:00:00.000", f.formatDate(new Date(0)));
++    assertEquals("1970-01-01T00:00:00.370", f.formatDate(new Date(370)));
++    assertEquals("1970-01-01T00:00:00.900", f.formatDate(new Date(900)));
+   }
+ }
+diff --git a/src/test/org/apache/solr/servlet/SolrRequestParserTest.java b/src/test/org/apache/solr/servlet/SolrRequestParserTest.java
+index f2f2ac7..ad9bc47 100644
+--- a/src/test/org/apache/solr/servlet/SolrRequestParserTest.java
++++ b/src/test/org/apache/solr/servlet/SolrRequestParserTest.java
+@@ -56,7 +56,7 @@ public class SolrRequestParserTest extends AbstractSolrTestCase {
+     String body2 = "qwertasdfgzxcvb";
+     String body3 = "1234567890";
+     
+-    SolrCore core = SolrCore.getSolrCore();
++    SolrCore core = h.getCore();
+     
+     Map<String,String[]> args = new HashMap<String, String[]>();
+     args.put( CommonParams.STREAM_BODY, new String[] {body1} );
+@@ -110,7 +110,7 @@ public class SolrRequestParserTest extends AbstractSolrTestCase {
+       return;
+     }
+ 
+-    SolrCore core = SolrCore.getSolrCore();
++    SolrCore core = h.getCore();
+     
+     Map<String,String[]> args = new HashMap<String, String[]>();
+     args.put( CommonParams.STREAM_URL, new String[] {url} );
+diff --git a/src/test/org/apache/solr/update/DirectUpdateHandlerTest.java b/src/test/org/apache/solr/update/DirectUpdateHandlerTest.java
+index 93d2921..eeee6a7 100644
+--- a/src/test/org/apache/solr/update/DirectUpdateHandlerTest.java
++++ b/src/test/org/apache/solr/update/DirectUpdateHandlerTest.java
+@@ -37,7 +37,7 @@ public class DirectUpdateHandlerTest extends AbstractSolrTestCase {
+ 
+   public void testRequireUniqueKey() throws Exception 
+   {
+-    SolrCore core = SolrCore.getSolrCore();
++    SolrCore core = h.getCore();
+     
+     UpdateHandler updater = core.getUpdateHandler();
+     
+diff --git a/src/test/org/apache/solr/update/DocumentBuilderTest.java b/src/test/org/apache/solr/update/DocumentBuilderTest.java
+index 0174501..45f14a3 100644
+--- a/src/test/org/apache/solr/update/DocumentBuilderTest.java
++++ b/src/test/org/apache/solr/update/DocumentBuilderTest.java
+@@ -51,7 +51,7 @@ public class DocumentBuilderTest extends AbstractSolrTestCase {
+ 
+   public void testNullField() 
+   {
+-    SolrCore core = SolrCore.getSolrCore();
++    SolrCore core = h.getCore();
+     
+     // make sure a null value is not indexed
+     SolrInputDocument doc = new SolrInputDocument();
+diff --git a/src/test/org/apache/solr/util/SolrPluginUtilsTest.java b/src/test/org/apache/solr/util/SolrPluginUtilsTest.java
+index 4bbc2fd..0098635 100644
+--- a/src/test/org/apache/solr/util/SolrPluginUtilsTest.java
++++ b/src/test/org/apache/solr/util/SolrPluginUtilsTest.java
+@@ -133,7 +133,7 @@ public class SolrPluginUtilsTest extends AbstractSolrTestCase {
+     assertTrue(t+" sanity test isn't TermQuery: " + out.getClass(),
+                out instanceof TermQuery);
+     assertEquals(t+" sanity test is wrong field",
+-                 h.getCore().getSchema().getDefaultSearchFieldName(),
++                 h.getCore().getSchema().getSolrQueryParser(null).getField(),
+                  ((TermQuery)out).getTerm().field());
+ 
+     t = "subject:XXXXXXXX";

Added: lucene/solr/trunk/SOLR-793-commitWithin.patch
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/SOLR-793-commitWithin.patch?rev=704288&view=auto
==============================================================================
--- lucene/solr/trunk/SOLR-793-commitWithin.patch (added)
+++ lucene/solr/trunk/SOLR-793-commitWithin.patch Mon Oct 13 17:24:04 2008
@@ -0,0 +1,221 @@
+Index: src/java/org/apache/solr/update/AddUpdateCommand.java
+===================================================================
+--- src/java/org/apache/solr/update/AddUpdateCommand.java	(revision 701732)
++++ src/java/org/apache/solr/update/AddUpdateCommand.java	(working copy)
+@@ -42,6 +42,10 @@
+    public boolean allowDups;
+    public boolean overwritePending;
+    public boolean overwriteCommitted;
++   
++   
++   public int commitWithin = -1;
++   
+ 
+    /** Reset state to reuse this object with a different document in the same request */
+    public void clear() {
+Index: src/java/org/apache/solr/update/DirectUpdateHandler2.java
+===================================================================
+--- src/java/org/apache/solr/update/DirectUpdateHandler2.java	(revision 701732)
++++ src/java/org/apache/solr/update/DirectUpdateHandler2.java	(working copy)
+@@ -198,7 +198,7 @@
+       synchronized (this) {
+         // adding document -- prep writer
+         openWriter();
+-        tracker.addedDocument();
++        tracker.addedDocument( cmd.commitWithin );
+       } // end synchronized block
+ 
+       // this is the only unsynchronized code in the iwAccess block, which
+@@ -424,7 +424,7 @@
+       SolrCore.log.info("AutoCommit: " + this);
+     }
+ 
+-    /** schedeule individual commits */
++    /** schedule individual commits */
+     public synchronized void scheduleCommitWithin(long commitMaxTime) 
+     {
+       // Check if there is a commit already scheduled for longer then this time
+@@ -443,30 +443,22 @@
+     
+     /** Indicate that documents have been added
+      */
+-    public void addedDocument() {
++    public void addedDocument( int commitWithin ) {
+       docsSinceCommit++;
+       lastAddedTime = System.currentTimeMillis();
+       // maxDocs-triggered autoCommit
+       if( docsUpperBound > 0 && (docsSinceCommit > docsUpperBound) ) {
+-        if (pending != null && 
+-            pending.getDelay(TimeUnit.MILLISECONDS) > DOC_COMMIT_DELAY_MS) {
+-          // another commit is pending, but too far away (probably due to
+-          // maxTime)
+-          pending.cancel(false);
+-          pending = null;
+-        }
+-        if (pending == null) {
+-          // 1/4 second seems fast enough for anyone using maxDocs
+-          pending = scheduler.schedule(this, DOC_COMMIT_DELAY_MS, 
+-                                       TimeUnit.MILLISECONDS);
+-        }
++        scheduleCommitWithin( DOC_COMMIT_DELAY_MS );
+       }
++      
+       // maxTime-triggered autoCommit
+-      if( pending == null && timeUpperBound > 0 ) { 
+-        // Don't start a new event if one is already waiting 
+-        pending = scheduler.schedule( this, timeUpperBound, TimeUnit.MILLISECONDS );
++      long ctime = timeUpperBound;
++      if( commitWithin > 0 && (ctime < 0 || commitWithin < ctime) ) {
++        ctime = commitWithin;
+       }
+-      
++      if( ctime > 0 ) {
++        scheduleCommitWithin( ctime );
++      }
+     }
+ 
+     /** Inform tracker that a commit has occurred, cancel any pending commits */
+Index: src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java
+===================================================================
+--- src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java	(revision 701732)
++++ src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java	(working copy)
+@@ -19,6 +19,7 @@
+ 
+ import java.io.IOException;
+ import java.io.Reader;
++import java.io.StringReader;
+ import java.io.Writer;
+ import java.io.File;
+ import java.util.HashMap;
+@@ -72,6 +73,7 @@
+   public static final String WAIT_FLUSH = "waitFlush";
+   
+   public static final String OVERWRITE = "overwrite";
++  public static final String COMMIT_WITHIN = "commitWithin"; 
+   public static final String OVERWRITE_COMMITTED = "overwriteCommitted"; // @Deprecated
+   public static final String OVERWRITE_PENDING = "overwritePending";  // @Deprecated
+   public static final String ALLOW_DUPS = "allowDups"; 
+@@ -120,6 +122,12 @@
+       for( ContentStream stream : req.getContentStreams() ) {
+         Reader reader = stream.getReader();
+         try {
++          if( log.isTraceEnabled() ) {
++            String body = IOUtils.toString( reader );
++            log.trace( "body", body );
++            reader = new StringReader( body );
++          }
++          
+           XMLStreamReader parser = inputFactory.createXMLStreamReader(reader);
+           this.processUpdate( processor, parser );
+         }
+@@ -169,6 +177,8 @@
+                 overwrite = StrUtils.parseBoolean(attrVal);
+               } else if (ALLOW_DUPS.equals(attrName)) {
+                 overwrite = !StrUtils.parseBoolean(attrVal);
++              } else if ( COMMIT_WITHIN.equals(attrName) ) {
++                addCmd.commitWithin = Integer.parseInt( attrVal );
+               } else if ( OVERWRITE_PENDING.equals(attrName) ) {
+                 overwritePending = StrUtils.parseBoolean(attrVal);
+               } else if ( OVERWRITE_COMMITTED.equals(attrName) ) {
+Index: client/java/solrj/test/org/apache/solr/client/solrj/SolrExampleTests.java
+===================================================================
+--- client/java/solrj/test/org/apache/solr/client/solrj/SolrExampleTests.java	(revision 701732)
++++ client/java/solrj/test/org/apache/solr/client/solrj/SolrExampleTests.java	(working copy)
+@@ -29,6 +29,7 @@
+ import org.apache.solr.client.solrj.request.DirectXmlRequest;
+ import org.apache.solr.client.solrj.request.LukeRequest;
+ import org.apache.solr.client.solrj.request.SolrPing;
++import org.apache.solr.client.solrj.request.UpdateRequest;
+ import org.apache.solr.client.solrj.response.LukeResponse;
+ import org.apache.solr.client.solrj.response.QueryResponse;
+ import org.apache.solr.client.solrj.response.FacetField;
+@@ -149,8 +150,8 @@
+     Assert.assertEquals(2, response.getResults().getNumFound() );
+     Assert.assertFalse(query.getFilterQueries() == query2.getFilterQueries());
+   }
+-  
+ 
++
+   /**
+    * query the example
+    */
+@@ -195,8 +196,40 @@
+     rsp = server.query( query );
+     Assert.assertEquals( 2, rsp.getResults().getNumFound() );
+     System.out.println( rsp.getResults() );
++    
+   }
+   
++  /**
++   * query the example
++   */
++  public void testCommitWithin() throws Exception
++  {    
++    // make sure it is empty...
++    SolrServer server = getSolrServer();
++    QueryResponse rsp = server.query( new SolrQuery( "*:*") );
++    Assert.assertEquals( 0, rsp.getResults().getNumFound() );
++
++    // Now try a timed commit...
++    SolrInputDocument doc3 = new SolrInputDocument();
++    doc3.addField( "id", "id3", 1.0f );
++    doc3.addField( "name", "doc3", 1.0f );
++    doc3.addField( "price", 10 );
++    UpdateRequest up = new UpdateRequest();
++    up.add( doc3 );
++    up.setCommitWithin( 5 );
++    up.process( server );
++    
++    rsp = server.query( new SolrQuery( "*:*") );
++    Assert.assertEquals( 0, rsp.getResults().getNumFound() );
++    
++    Thread.sleep( 500 ); // wait 1/2 seconds...
++
++    // now check that it comes out...
++    rsp = server.query( new SolrQuery( "id:id3") );
++    Assert.assertEquals( 1, rsp.getResults().getNumFound() );
++  }
++  
++  
+   protected void assertNumFound( String query, int num ) throws SolrServerException, IOException
+   {
+     QueryResponse rsp = getSolrServer().query( new SolrQuery( query ) );
+Index: client/java/solrj/src/org/apache/solr/client/solrj/request/UpdateRequest.java
+===================================================================
+--- client/java/solrj/src/org/apache/solr/client/solrj/request/UpdateRequest.java	(revision 701732)
++++ client/java/solrj/src/org/apache/solr/client/solrj/request/UpdateRequest.java	(working copy)
+@@ -51,6 +51,7 @@
+   private List<String> deleteQuery = null;
+ 
+   private ModifiableSolrParams params;
++  private int commitWithin = -1;
+   
+   public UpdateRequest()
+   {
+@@ -163,7 +164,12 @@
+   public String getXML() throws IOException {
+     StringWriter writer = new StringWriter();
+     if( documents != null && documents.size() > 0 ) {
+-      writer.write("<add>");
++      if( commitWithin > 0 ) {
++        writer.write("<add commitWithin=\""+commitWithin+"\">");
++      }
++      else {
++        writer.write("<add>");
++      }
+       for (SolrInputDocument doc : documents ) {
+         if( doc != null ) {
+           ClientUtils.writeXML( doc, writer );
+@@ -245,4 +251,12 @@
+   public void setWaitSearcher(boolean waitSearcher) {
+     setParam( UpdateParams.WAIT_SEARCHER, waitSearcher+"" );
+   }
++
++  public int getCommitWithin() {
++    return commitWithin;
++  }
++
++  public void setCommitWithin(int commitWithin) {
++    this.commitWithin = commitWithin;
++  }
+ }

Added: lucene/solr/trunk/SOLR-793-commitWithin2.patch
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/SOLR-793-commitWithin2.patch?rev=704288&view=auto
==============================================================================
--- lucene/solr/trunk/SOLR-793-commitWithin2.patch (added)
+++ lucene/solr/trunk/SOLR-793-commitWithin2.patch Mon Oct 13 17:24:04 2008
@@ -0,0 +1,221 @@
+Index: src/java/org/apache/solr/update/AddUpdateCommand.java
+===================================================================
+--- src/java/org/apache/solr/update/AddUpdateCommand.java	(revision 701732)
++++ src/java/org/apache/solr/update/AddUpdateCommand.java	(working copy)
+@@ -42,6 +42,10 @@
+    public boolean allowDups;
+    public boolean overwritePending;
+    public boolean overwriteCommitted;
++   
++   
++   public int commitWithin = -1;
++   
+ 
+    /** Reset state to reuse this object with a different document in the same request */
+    public void clear() {
+Index: src/java/org/apache/solr/update/DirectUpdateHandler2.java
+===================================================================
+--- src/java/org/apache/solr/update/DirectUpdateHandler2.java	(revision 701732)
++++ src/java/org/apache/solr/update/DirectUpdateHandler2.java	(working copy)
+@@ -198,7 +198,7 @@
+       synchronized (this) {
+         // adding document -- prep writer
+         openWriter();
+-        tracker.addedDocument();
++        tracker.addedDocument( cmd.commitWithin );
+       } // end synchronized block
+ 
+       // this is the only unsynchronized code in the iwAccess block, which
+@@ -424,7 +424,7 @@
+       SolrCore.log.info("AutoCommit: " + this);
+     }
+ 
+-    /** schedeule individual commits */
++    /** schedule individual commits */
+     public synchronized void scheduleCommitWithin(long commitMaxTime) 
+     {
+       // Check if there is a commit already scheduled for longer then this time
+@@ -443,30 +443,22 @@
+     
+     /** Indicate that documents have been added
+      */
+-    public void addedDocument() {
++    public void addedDocument( int commitWithin ) {
+       docsSinceCommit++;
+       lastAddedTime = System.currentTimeMillis();
+       // maxDocs-triggered autoCommit
+       if( docsUpperBound > 0 && (docsSinceCommit > docsUpperBound) ) {
+-        if (pending != null && 
+-            pending.getDelay(TimeUnit.MILLISECONDS) > DOC_COMMIT_DELAY_MS) {
+-          // another commit is pending, but too far away (probably due to
+-          // maxTime)
+-          pending.cancel(false);
+-          pending = null;
+-        }
+-        if (pending == null) {
+-          // 1/4 second seems fast enough for anyone using maxDocs
+-          pending = scheduler.schedule(this, DOC_COMMIT_DELAY_MS, 
+-                                       TimeUnit.MILLISECONDS);
+-        }
++        scheduleCommitWithin( DOC_COMMIT_DELAY_MS );
+       }
++      
+       // maxTime-triggered autoCommit
+-      if( pending == null && timeUpperBound > 0 ) { 
+-        // Don't start a new event if one is already waiting 
+-        pending = scheduler.schedule( this, timeUpperBound, TimeUnit.MILLISECONDS );
++      long ctime = timeUpperBound;
++      if( commitWithin > 0 && (ctime < 0 || commitWithin < ctime) ) {
++        ctime = commitWithin;
+       }
+-      
++      if( ctime > 0 ) {
++        scheduleCommitWithin( ctime );
++      }
+     }
+ 
+     /** Inform tracker that a commit has occurred, cancel any pending commits */
+Index: src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java
+===================================================================
+--- src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java	(revision 701732)
++++ src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java	(working copy)
+@@ -19,6 +19,7 @@
+ 
+ import java.io.IOException;
+ import java.io.Reader;
++import java.io.StringReader;
+ import java.io.Writer;
+ import java.io.File;
+ import java.util.HashMap;
+@@ -72,6 +73,7 @@
+   public static final String WAIT_FLUSH = "waitFlush";
+   
+   public static final String OVERWRITE = "overwrite";
++  public static final String COMMIT_WITHIN = "commitWithin"; 
+   public static final String OVERWRITE_COMMITTED = "overwriteCommitted"; // @Deprecated
+   public static final String OVERWRITE_PENDING = "overwritePending";  // @Deprecated
+   public static final String ALLOW_DUPS = "allowDups"; 
+@@ -120,6 +122,12 @@
+       for( ContentStream stream : req.getContentStreams() ) {
+         Reader reader = stream.getReader();
+         try {
++          if( log.isTraceEnabled() ) {
++            String body = IOUtils.toString( reader );
++            log.trace( "body", body );
++            reader = new StringReader( body );
++          }
++          
+           XMLStreamReader parser = inputFactory.createXMLStreamReader(reader);
+           this.processUpdate( processor, parser );
+         }
+@@ -169,6 +177,8 @@
+                 overwrite = StrUtils.parseBoolean(attrVal);
+               } else if (ALLOW_DUPS.equals(attrName)) {
+                 overwrite = !StrUtils.parseBoolean(attrVal);
++              } else if ( COMMIT_WITHIN.equals(attrName) ) {
++                addCmd.commitWithin = Integer.parseInt( attrVal );
+               } else if ( OVERWRITE_PENDING.equals(attrName) ) {
+                 overwritePending = StrUtils.parseBoolean(attrVal);
+               } else if ( OVERWRITE_COMMITTED.equals(attrName) ) {
+Index: client/java/solrj/test/org/apache/solr/client/solrj/SolrExampleTests.java
+===================================================================
+--- client/java/solrj/test/org/apache/solr/client/solrj/SolrExampleTests.java	(revision 701732)
++++ client/java/solrj/test/org/apache/solr/client/solrj/SolrExampleTests.java	(working copy)
+@@ -29,6 +29,7 @@
+ import org.apache.solr.client.solrj.request.DirectXmlRequest;
+ import org.apache.solr.client.solrj.request.LukeRequest;
+ import org.apache.solr.client.solrj.request.SolrPing;
++import org.apache.solr.client.solrj.request.UpdateRequest;
+ import org.apache.solr.client.solrj.response.LukeResponse;
+ import org.apache.solr.client.solrj.response.QueryResponse;
+ import org.apache.solr.client.solrj.response.FacetField;
+@@ -149,8 +150,8 @@
+     Assert.assertEquals(2, response.getResults().getNumFound() );
+     Assert.assertFalse(query.getFilterQueries() == query2.getFilterQueries());
+   }
+-  
+ 
++
+   /**
+    * query the example
+    */
+@@ -195,8 +196,40 @@
+     rsp = server.query( query );
+     Assert.assertEquals( 2, rsp.getResults().getNumFound() );
+     System.out.println( rsp.getResults() );
++    
+   }
+   
++  /**
++   * query the example
++   */
++  public void testCommitWithin() throws Exception
++  {    
++    // make sure it is empty...
++    SolrServer server = getSolrServer();
++    QueryResponse rsp = server.query( new SolrQuery( "*:*") );
++    Assert.assertEquals( 0, rsp.getResults().getNumFound() );
++
++    // Now try a timed commit...
++    SolrInputDocument doc3 = new SolrInputDocument();
++    doc3.addField( "id", "id3", 1.0f );
++    doc3.addField( "name", "doc3", 1.0f );
++    doc3.addField( "price", 10 );
++    UpdateRequest up = new UpdateRequest();
++    up.add( doc3 );
++    up.setCommitWithin( 5 );
++    up.process( server );
++    
++    rsp = server.query( new SolrQuery( "*:*") );
++    Assert.assertEquals( 0, rsp.getResults().getNumFound() );
++    
++    Thread.sleep( 500 ); // wait 1/2 seconds...
++
++    // now check that it comes out...
++    rsp = server.query( new SolrQuery( "id:id3") );
++    Assert.assertEquals( 1, rsp.getResults().getNumFound() );
++  }
++  
++  
+   protected void assertNumFound( String query, int num ) throws SolrServerException, IOException
+   {
+     QueryResponse rsp = getSolrServer().query( new SolrQuery( query ) );
+Index: client/java/solrj/src/org/apache/solr/client/solrj/request/UpdateRequest.java
+===================================================================
+--- client/java/solrj/src/org/apache/solr/client/solrj/request/UpdateRequest.java	(revision 701732)
++++ client/java/solrj/src/org/apache/solr/client/solrj/request/UpdateRequest.java	(working copy)
+@@ -51,6 +51,7 @@
+   private List<String> deleteQuery = null;
+ 
+   private ModifiableSolrParams params;
++  private int commitWithin = -1;
+   
+   public UpdateRequest()
+   {
+@@ -163,7 +164,12 @@
+   public String getXML() throws IOException {
+     StringWriter writer = new StringWriter();
+     if( documents != null && documents.size() > 0 ) {
+-      writer.write("<add>");
++      if( commitWithin > 0 ) {
++        writer.write("<add commitWithin=\""+commitWithin+"\">");
++      }
++      else {
++        writer.write("<add>");
++      }
+       for (SolrInputDocument doc : documents ) {
+         if( doc != null ) {
+           ClientUtils.writeXML( doc, writer );
+@@ -245,4 +251,12 @@
+   public void setWaitSearcher(boolean waitSearcher) {
+     setParam( UpdateParams.WAIT_SEARCHER, waitSearcher+"" );
+   }
++
++  public int getCommitWithin() {
++    return commitWithin;
++  }
++
++  public void setCommitWithin(int commitWithin) {
++    this.commitWithin = commitWithin;
++  }
+ }

Modified: lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/request/UpdateRequest.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/request/UpdateRequest.java?rev=704288&r1=704287&r2=704288&view=diff
==============================================================================
--- lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/request/UpdateRequest.java (original)
+++ lucene/solr/trunk/client/java/solrj/src/org/apache/solr/client/solrj/request/UpdateRequest.java Mon Oct 13 17:24:04 2008
@@ -51,6 +51,7 @@
   private List<String> deleteQuery = null;
 
   private ModifiableSolrParams params;
+  private int commitWithin = -1;
   
   public UpdateRequest()
   {
@@ -163,7 +164,12 @@
   public String getXML() throws IOException {
     StringWriter writer = new StringWriter();
     if( documents != null && documents.size() > 0 ) {
-      writer.write("<add>");
+      if( commitWithin > 0 ) {
+        writer.write("<add commitWithin=\""+commitWithin+"\">");
+      }
+      else {
+        writer.write("<add>");
+      }
       for (SolrInputDocument doc : documents ) {
         if( doc != null ) {
           ClientUtils.writeXML( doc, writer );
@@ -245,4 +251,12 @@
   public void setWaitSearcher(boolean waitSearcher) {
     setParam( UpdateParams.WAIT_SEARCHER, waitSearcher+"" );
   }
+
+  public int getCommitWithin() {
+    return commitWithin;
+  }
+
+  public void setCommitWithin(int commitWithin) {
+    this.commitWithin = commitWithin;
+  }
 }

Modified: lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/SolrExampleTests.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/SolrExampleTests.java?rev=704288&r1=704287&r2=704288&view=diff
==============================================================================
--- lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/SolrExampleTests.java (original)
+++ lucene/solr/trunk/client/java/solrj/test/org/apache/solr/client/solrj/SolrExampleTests.java Mon Oct 13 17:24:04 2008
@@ -29,6 +29,7 @@
 import org.apache.solr.client.solrj.request.DirectXmlRequest;
 import org.apache.solr.client.solrj.request.LukeRequest;
 import org.apache.solr.client.solrj.request.SolrPing;
+import org.apache.solr.client.solrj.request.UpdateRequest;
 import org.apache.solr.client.solrj.response.LukeResponse;
 import org.apache.solr.client.solrj.response.QueryResponse;
 import org.apache.solr.client.solrj.response.FacetField;
@@ -149,7 +150,7 @@
     Assert.assertEquals(2, response.getResults().getNumFound() );
     Assert.assertFalse(query.getFilterQueries() == query2.getFilterQueries());
   }
-  
+
 
   /**
    * query the example
@@ -195,8 +196,42 @@
     rsp = server.query( query );
     Assert.assertEquals( 2, rsp.getResults().getNumFound() );
     System.out.println( rsp.getResults() );
+    
+  }
+  
+  /**
+   * query the example
+   */
+  public void testCommitWithin() throws Exception
+  {    
+    // make sure it is empty...
+    SolrServer server = getSolrServer();
+    server.deleteByQuery( "*:*" );// delete everything!
+    server.commit();
+    QueryResponse rsp = server.query( new SolrQuery( "*:*") );
+    Assert.assertEquals( 0, rsp.getResults().getNumFound() );
+
+    // Now try a timed commit...
+    SolrInputDocument doc3 = new SolrInputDocument();
+    doc3.addField( "id", "id3", 1.0f );
+    doc3.addField( "name", "doc3", 1.0f );
+    doc3.addField( "price", 10 );
+    UpdateRequest up = new UpdateRequest();
+    up.add( doc3 );
+    up.setCommitWithin( 10 );
+    up.process( server );
+    
+    rsp = server.query( new SolrQuery( "*:*") );
+    Assert.assertEquals( 0, rsp.getResults().getNumFound() );
+    
+    Thread.sleep( 500 ); // wait 1/2 seconds...
+
+    // now check that it comes out...
+    rsp = server.query( new SolrQuery( "id:id3") );
+    Assert.assertEquals( 1, rsp.getResults().getNumFound() );
   }
   
+  
   protected void assertNumFound( String query, int num ) throws SolrServerException, IOException
   {
     QueryResponse rsp = getSolrServer().query( new SolrQuery( query ) );

Added: lucene/solr/trunk/example/solr/conf/velocity/default.vm
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/example/solr/conf/velocity/default.vm?rev=704288&view=auto
==============================================================================
--- lucene/solr/trunk/example/solr/conf/velocity/default.vm (added)
+++ lucene/solr/trunk/example/solr/conf/velocity/default.vm Mon Oct 13 17:24:04 2008
@@ -0,0 +1,40 @@
+#set($iterator=$rawResponse.getResultIterator())
+#set($request=$rawResponse.request)
+#set($core=$request.core)
+#set($schema=$core.schema)
+
+<html>
+  <title>Default VelocityResponseWriter Response</title>
+  <body>
+  
+    <p>
+      A default response using only the raw solr response. The "rawResponse" object is a helper that provides access to the
+      SolrQueryRequest, SolrQueryResponse, as well as convenience methods like getResultIterator() and getRequestParam()
+    </p>
+    <p>
+      If you want to use an instance of SolrResponse of solrj inside a template, use eg. vl.response=QueryResponse. 
+      This object then is avalaible as "response" in the context.
+    </p>
+    <hr/>
+  
+    #foreach($document in $iterator)
+        #foreach($field in $document.getFieldNames())
+          <p>$field: $document.getFieldValue($field)</p>
+        #end
+    <hr/>
+    #end
+
+    <pre>
+      header = $rawResponse.$response.responseHeader
+
+      values = $rawResponse.$response.values
+
+      request = $request
+
+      core = $core
+
+      schema = $schema
+    </pre>
+
+  </body>
+</html>

Added: lucene/solr/trunk/lib/commons-collections-3.2.jar
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/lib/commons-collections-3.2.jar?rev=704288&view=auto
==============================================================================
Binary file - no diff available.

Propchange: lucene/solr/trunk/lib/commons-collections-3.2.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: lucene/solr/trunk/lib/commons-lang-2.4.jar
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/lib/commons-lang-2.4.jar?rev=704288&view=auto
==============================================================================
Binary file - no diff available.

Propchange: lucene/solr/trunk/lib/commons-lang-2.4.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: lucene/solr/trunk/lib/velocity-1.6-dev.jar
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/lib/velocity-1.6-dev.jar?rev=704288&view=auto
==============================================================================
Binary file - no diff available.

Propchange: lucene/solr/trunk/lib/velocity-1.6-dev.jar
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Modified: lucene/solr/trunk/src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java?rev=704288&r1=704287&r2=704288&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/handler/XmlUpdateRequestHandler.java Mon Oct 13 17:24:04 2008
@@ -19,6 +19,7 @@
 
 import java.io.IOException;
 import java.io.Reader;
+import java.io.StringReader;
 import java.io.Writer;
 import java.io.File;
 import java.util.HashMap;
@@ -72,6 +73,7 @@
   public static final String WAIT_FLUSH = "waitFlush";
   
   public static final String OVERWRITE = "overwrite";
+  public static final String COMMIT_WITHIN = "commitWithin"; 
   public static final String OVERWRITE_COMMITTED = "overwriteCommitted"; // @Deprecated
   public static final String OVERWRITE_PENDING = "overwritePending";  // @Deprecated
   public static final String ALLOW_DUPS = "allowDups"; 
@@ -120,6 +122,12 @@
       for( ContentStream stream : req.getContentStreams() ) {
         Reader reader = stream.getReader();
         try {
+          if( log.isTraceEnabled() ) {
+            String body = IOUtils.toString( reader );
+            log.trace( "body", body );
+            reader = new StringReader( body );
+          }
+          
           XMLStreamReader parser = inputFactory.createXMLStreamReader(reader);
           this.processUpdate( processor, parser );
         }
@@ -169,6 +177,8 @@
                 overwrite = StrUtils.parseBoolean(attrVal);
               } else if (ALLOW_DUPS.equals(attrName)) {
                 overwrite = !StrUtils.parseBoolean(attrVal);
+              } else if ( COMMIT_WITHIN.equals(attrName) ) {
+                addCmd.commitWithin = Integer.parseInt( attrVal );
               } else if ( OVERWRITE_PENDING.equals(attrName) ) {
                 overwritePending = StrUtils.parseBoolean(attrVal);
               } else if ( OVERWRITE_COMMITTED.equals(attrName) ) {

Added: lucene/solr/trunk/src/java/org/apache/solr/request/VelocityResponseWriter.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/request/VelocityResponseWriter.java?rev=704288&view=auto
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/request/VelocityResponseWriter.java (added)
+++ lucene/solr/trunk/src/java/org/apache/solr/request/VelocityResponseWriter.java Mon Oct 13 17:24:04 2008
@@ -0,0 +1,222 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.solr.request;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.util.Iterator;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.CorruptIndexException;
+import org.apache.lucene.search.Searcher;
+import org.apache.solr.client.solrj.SolrResponse;
+import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
+import org.apache.solr.common.SolrDocument;
+import org.apache.solr.common.util.NamedList;
+import org.apache.solr.search.DocSlice;
+import org.apache.solr.update.DocumentBuilder;
+import org.apache.velocity.Template;
+import org.apache.velocity.VelocityContext;
+import org.apache.velocity.app.VelocityEngine;
+
+/**
+ * <p> A response writer that uses velocity template for response creation.
+ *     Possible request parameters: </p>
+ * <ul>
+ *     <li> 
+ *         <b>vl.template:</b> 
+ *     	   The name of the template file without .vm suffix. </li>
+ *     <li> 
+ *         <b>vl.json:</b> 
+ *         A name of a Javascript method. If set, the response is wrapped into this object. 
+ *         useful for JSON requests. 
+ *     </li>
+ *     <li> 
+ *         <b>vl.content:</b> 
+ *         Specify a custom content type for the response. Default is "text/html" for standard requests,
+ *         and "text/x-json" for JSON requests.  
+ *     </li>
+ *     <li> 
+ *         <b>vl.response:</b> 
+ *         To provide an implementation of  {@link SolrResponse} inside the template,
+ *     	   specify the class name of the implementation. For convenience, it looks 
+ *         inside the package "org.apache.solr.client.solrj.response", so you only 
+ *         have to choose  eg. <i>QueryResponse, LikeResponse, MultiCoreResponse</i>.
+ *     	   Custom classes may be accessed using the full qualified class name, 
+ *         eg. <i>my.custom.package.CustomResponse</i>	
+ *     </li>
+ * </ul>
+ */
+public class VelocityResponseWriter implements QueryResponseWriter {
+
+	private static final String PARAMETER_TEMPLATE="vl.template";
+	private static final String PARAMETER_JSON="vl.json";
+	private static final String PARAMETER_RESPONSE="vl.response";
+	private static final String PARAMETER_CONTENT_TYPE="vl.content";
+	
+	public void write(Writer writer, SolrQueryRequest request,
+			SolrQueryResponse response) throws IOException {
+		
+		// init velocity and get template
+		VelocityEngine engine = new VelocityEngine();
+		File baseDir = new File(request.getCore().getResourceLoader().getConfigDir(), "velocity");
+		engine.setProperty(VelocityEngine.FILE_RESOURCE_LOADER_PATH, baseDir.getAbsolutePath());
+		engine.setProperty(VelocityEngine.RESOURCE_LOADER, "file");
+		Template template;
+		try {
+			template = engine.getTemplate(request.getParams().get(PARAMETER_TEMPLATE, "default") + ".vm");
+		} catch (Exception e) {
+			throw new IOException(e.getMessage());
+		}
+		
+		// put raw response into context
+		VelocityContext context = new VelocityContext();
+		context.put("rawResponse", new RawResponseHelper(request, response));
+		
+		// convert response if a class is specified
+		if (request.getParams().get(PARAMETER_RESPONSE) != null) {
+			String className = request.getParams().get(PARAMETER_RESPONSE);
+			
+			// create SolrResponse using reflection
+			SolrResponse solrResponse;
+			Object object;
+			try {
+				object = request.getCore().getResourceLoader().newInstance(className, "client.solrj.response.");
+			} catch (RuntimeException e) {
+				throw new IOException("Unable to resolve response class \"" + className + "\": " + e.getMessage());
+			}
+			if (!(object instanceof SolrResponse)) {
+				throw new IOException("Class \"" + className + "\" doesn't implement SolrResponse!");
+			}
+			solrResponse = (SolrResponse) object;
+			
+			// inject the request into the response
+			solrResponse.setResponse(new EmbeddedSolrServer(request.getCore()).getParsedResponse(request, response));
+			
+			// put it into the context
+			context.put("response", solrResponse);
+		}
+		
+		// create output, optionally wrap it into a json object
+		if (isWrappedResponse(request)) {
+			StringWriter stringWriter = new StringWriter();
+			template.merge(context, stringWriter);
+			writer.write(request.getParams().get(PARAMETER_JSON) + "(");
+			writer.write(getJSONWrap(stringWriter.toString()));
+			writer.write(')');
+		} else {
+			template.merge(context, writer);
+		}
+
+	}
+
+	public String getContentType(SolrQueryRequest request,
+			SolrQueryResponse response) {
+		if (request.getParams().get(PARAMETER_CONTENT_TYPE) != null) {
+			return request.getParams().get(PARAMETER_CONTENT_TYPE);
+		}
+		if (isWrappedResponse(request)) {
+			return JSONResponseWriter.CONTENT_TYPE_JSON_UTF8;
+		}
+		return "text/html";
+	}
+
+	public void init(NamedList args) {
+		// TODO
+	}
+	
+	private boolean isWrappedResponse(SolrQueryRequest request) {
+		return request.getParams().get(PARAMETER_JSON) != null;
+	}
+	
+	public String getJSONWrap(String xmlResult) {
+		// escape the double quotes and backslashes
+		String replace1 = xmlResult.replaceAll("\\\\", "\\\\\\\\");
+		replace1 = replace1.replaceAll("\\n", "\\\\n");
+		replace1 = replace1.replaceAll("\\r", "\\\\r");
+		String replaced = replace1.replaceAll("\"", "\\\\\"");
+		// wrap it in a JSON object
+		return "{\"result\":\"" + replaced + "\"}";
+	}
+
+	/**
+	 * A helper class that provides convenient methods for the raw solr response.
+	 */
+	public class RawResponseHelper {
+
+		private Searcher searcher;
+		private SolrQueryResponse response;
+		private SolrQueryRequest request;
+
+		public RawResponseHelper(SolrQueryRequest request,
+				SolrQueryResponse response) {
+			this.searcher = request.getSearcher();
+			this.response = response;
+			this.request = request;
+		}
+
+		public Iterator<SolrDocument> getResultIterator() {
+			final Iterator<Integer> iterator = ((DocSlice) response.getValues()
+					.get("response")).iterator();
+			return new Iterator<SolrDocument>() {
+
+				public boolean hasNext() {
+					return iterator.hasNext();
+				}
+
+				public SolrDocument next() {
+					Document document = null;
+					SolrDocument solrDocument = new SolrDocument();
+					try {
+						document = searcher.doc(iterator.next());
+						new DocumentBuilder(request.getSchema()).loadStoredFields(solrDocument, document);
+					} catch (CorruptIndexException e) {
+						throw new RuntimeException("Error converting lucene document into solr document!");
+					} catch (IOException e) {
+						throw new RuntimeException("Error converting lucene document into solr document!");
+					}
+					
+					return solrDocument;
+				}
+
+				public void remove() {
+
+				}
+
+			};
+		}
+		
+		public String getRequestParameter(String param) {
+			return request.getParams().get(param);
+		}
+		
+		public SolrQueryRequest getRequest() {
+			return request;
+		}
+		
+		public SolrQueryResponse getResponse() {
+			return response;
+		}
+		
+		
+	}
+	
+	
+}

Modified: lucene/solr/trunk/src/java/org/apache/solr/update/AddUpdateCommand.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/update/AddUpdateCommand.java?rev=704288&r1=704287&r2=704288&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/update/AddUpdateCommand.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/update/AddUpdateCommand.java Mon Oct 13 17:24:04 2008
@@ -42,6 +42,10 @@
    public boolean allowDups;
    public boolean overwritePending;
    public boolean overwriteCommitted;
+   
+   
+   public int commitWithin = -1;
+   
 
    /** Reset state to reuse this object with a different document in the same request */
    public void clear() {

Modified: lucene/solr/trunk/src/java/org/apache/solr/update/DirectUpdateHandler2.java
URL: http://svn.apache.org/viewvc/lucene/solr/trunk/src/java/org/apache/solr/update/DirectUpdateHandler2.java?rev=704288&r1=704287&r2=704288&view=diff
==============================================================================
--- lucene/solr/trunk/src/java/org/apache/solr/update/DirectUpdateHandler2.java (original)
+++ lucene/solr/trunk/src/java/org/apache/solr/update/DirectUpdateHandler2.java Mon Oct 13 17:24:04 2008
@@ -198,7 +198,7 @@
       synchronized (this) {
         // adding document -- prep writer
         openWriter();
-        tracker.addedDocument();
+        tracker.addedDocument( cmd.commitWithin );
       } // end synchronized block
 
       // this is the only unsynchronized code in the iwAccess block, which
@@ -424,7 +424,7 @@
       SolrCore.log.info("AutoCommit: " + this);
     }
 
-    /** schedeule individual commits */
+    /** schedule individual commits */
     public synchronized void scheduleCommitWithin(long commitMaxTime) 
     {
       // Check if there is a commit already scheduled for longer then this time
@@ -443,30 +443,19 @@
     
     /** Indicate that documents have been added
      */
-    public void addedDocument() {
+    public void addedDocument( int commitWithin ) {
       docsSinceCommit++;
       lastAddedTime = System.currentTimeMillis();
       // maxDocs-triggered autoCommit
       if( docsUpperBound > 0 && (docsSinceCommit > docsUpperBound) ) {
-        if (pending != null && 
-            pending.getDelay(TimeUnit.MILLISECONDS) > DOC_COMMIT_DELAY_MS) {
-          // another commit is pending, but too far away (probably due to
-          // maxTime)
-          pending.cancel(false);
-          pending = null;
-        }
-        if (pending == null) {
-          // 1/4 second seems fast enough for anyone using maxDocs
-          pending = scheduler.schedule(this, DOC_COMMIT_DELAY_MS, 
-                                       TimeUnit.MILLISECONDS);
-        }
+        scheduleCommitWithin( DOC_COMMIT_DELAY_MS );
       }
+      
       // maxTime-triggered autoCommit
-      if( pending == null && timeUpperBound > 0 ) { 
-        // Don't start a new event if one is already waiting 
-        pending = scheduler.schedule( this, timeUpperBound, TimeUnit.MILLISECONDS );
+      long ctime = (commitWithin>0) ? commitWithin : timeUpperBound;
+      if( ctime > 0 ) {
+        scheduleCommitWithin( ctime );
       }
-      
     }
 
     /** Inform tracker that a commit has occurred, cancel any pending commits */