Index: lucene.cpp
===================================================================
--- lucene.cpp	(revision 296)
+++ lucene.cpp	(working copy)
@@ -155,6 +155,7 @@
 #include "org/apache/lucene/search/CachingWrapperFilter.h"
 #include "org/apache/lucene/search/QueryFilter.h"
 #include "org/apache/lucene/search/RangeFilter.h"
+#include "org/apache/lucene/search/PrefixFilter.h"
 #include "org/apache/lucene/search/FilteredQuery.h"
 #include "org/apache/lucene/search/RangeQuery.h"
 #include "org/apache/lucene/search/ConstantScoreQuery.h"
@@ -3631,6 +3632,24 @@
 DECLARE_TYPE(RangeFilter, j_rangefilter, Filter,
              org::apache::lucene::search::RangeFilter, j_rangefilter_init);
 
+/* PrefixFilter */
+
+class j_prefixfilter {
+public:
+    PyObject_HEAD
+    org::apache::lucene::search::PrefixFilter *object;
+};
+
+static int j_prefixfilter_init(j_prefixfilter *self,
+                              PyObject *args, PyObject *kwds);
+
+static PyMethodDef j_prefixfilter_methods[] = {
+    { NULL, NULL, 0, NULL }
+};
+
+DECLARE_TYPE(PrefixFilter, j_prefixfilter, Filter,
+             org::apache::lucene::search::PrefixFilter, j_prefixfilter_init);
+
 /* FuzzyTermEnum */
 
 class j_fuzzytermenum {
@@ -11198,7 +11217,36 @@
     return PyErr_SetArgsError(type, "More", args);
 }
 
+/* PrefixFilter */
 
+static int j_prefixfilter_init(j_prefixfilter *self,
+                              PyObject *args, PyObject *kwds)
+{
+    org::apache::lucene::search::PrefixFilter *filter;
+    org::apache::lucene::index::Term *term;
+
+    if (!parseArgs(args, "J",
+                   &org::apache::lucene::index::Term::class$, &term))
+    {
+        INT_CALL(filter = new org::apache::lucene::search::PrefixFilter(term));
+        self->object = filter;
+    }
+    else
+    {
+        PyErr_SetArgsError((PyObject *) self, "__init__", args);
+        return -1;
+    }
+    
+    if (self->object)
+    {
+        refObject(self->object);
+        return 0;
+    }
+    
+    return -1;
+}
+
+
 /* FuzzyTermEnum */
 
 static int j_fuzzytermenum_init(j_fuzzytermenum *self,
@@ -13419,6 +13467,7 @@
     INSTALL_TYPE(CachingWrapperFilter, m);
     INSTALL_TYPE(QueryFilter, m);
     INSTALL_TYPE(RangeFilter, m);
+    INSTALL_TYPE(PrefixFilter, m);
     INSTALL_TYPE(FuzzyTermEnum, m);
     INSTALL_TYPE(WildcardTermEnum, m);
     INSTALL_TYPE(FilteredQuery, m);
Index: Makefile
===================================================================
--- Makefile	(revision 296)
+++ Makefile	(working copy)
@@ -437,6 +438,7 @@
 	$(MAKE) $(LUCENE_JAR)
 
 $(LUCENE_JAR): $(LUCENE) patches.lucene
+	cp unreleased/org/apache/solr/search/PrefixFilter.java lucene-java-$(LUCENE_VER)/src/java/org/apache/lucene/search/; true
 	cd $(LUCENE); patch -Nup1 < ../patches.lucene; echo ok
 	cd $(LUCENE); $(ANT) -Dversion=$(LUCENE_VER)
 	cd $(LUCENE)/build/classes/java; \
Index: unreleased/org/apache/solr/search/PrefixFilter.java
===================================================================
--- unreleased/org/apache/solr/search/PrefixFilter.java	(revision 0)
+++ unreleased/org/apache/solr/search/PrefixFilter.java	(revision 0)
@@ -0,0 +1,80 @@
+package org.apache.lucene.search;
+
+import org.apache.lucene.search.Filter;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.TermEnum;
+import org.apache.lucene.index.TermDocs;
+
+import java.util.BitSet;
+import java.io.IOException;
+
+/**
+ * @author yonik
+ * @version $Id$
+ */
+public class PrefixFilter extends Filter {
+  protected final Term prefix;
+
+  PrefixFilter(Term prefix) {
+    this.prefix = prefix;
+  }
+
+  Term getPrefix() { return prefix; }
+
+  public BitSet bits(IndexReader reader) throws IOException {
+    final BitSet bitSet = new BitSet(reader.maxDoc());
+    new PrefixGenerator(prefix) {
+      public void handleDoc(int doc) {
+        bitSet.set(doc);
+      }
+    }.generate(reader);
+    return bitSet;
+  }
+}
+
+// keep this protected until I decide if it's a good way
+// to separate id generation from collection (or should
+// I just reuse hitcollector???)
+interface IdGenerator {
+  public void generate(IndexReader reader) throws IOException;
+  public void handleDoc(int doc);
+}
+
+
+abstract class PrefixGenerator implements IdGenerator {
+  protected final Term prefix;
+
+  PrefixGenerator(Term prefix) {
+    this.prefix = prefix;
+  }
+
+  public void generate(IndexReader reader) throws IOException {
+    TermEnum enumerator = reader.terms(prefix);
+    TermDocs termDocs = reader.termDocs();
+
+    try {
+
+      String prefixText = prefix.text();
+      String prefixField = prefix.field();
+      do {
+        Term term = enumerator.term();
+        if (term != null &&
+            term.text().startsWith(prefixText) &&
+            term.field() == prefixField)
+        {
+          termDocs.seek(term);
+          while (termDocs.next()) {
+            handleDoc(termDocs.doc());
+          }
+        } else {
+          break;
+        }
+      } while (enumerator.next());
+    } finally {
+      termDocs.close();
+      enumerator.close();
+    }
+  }
+}
+
Index: unreleased/org/apache/solr/search/PrefixFilter.java
===================================================================
--- unreleased/org/apache/solr/search/PrefixFilter.java	(revision 0)
+++ unreleased/org/apache/solr/search/PrefixFilter.java	(revision 0)
@@ -0,0 +1,80 @@
+package org.apache.lucene.search;
+
+import org.apache.lucene.search.Filter;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.TermEnum;
+import org.apache.lucene.index.TermDocs;
+
+import java.util.BitSet;
+import java.io.IOException;
+
+/**
+ * @author yonik
+ * @version $Id$
+ */
+public class PrefixFilter extends Filter {
+  protected final Term prefix;
+
+  PrefixFilter(Term prefix) {
+    this.prefix = prefix;
+  }
+
+  Term getPrefix() { return prefix; }
+
+  public BitSet bits(IndexReader reader) throws IOException {
+    final BitSet bitSet = new BitSet(reader.maxDoc());
+    new PrefixGenerator(prefix) {
+      public void handleDoc(int doc) {
+        bitSet.set(doc);
+      }
+    }.generate(reader);
+    return bitSet;
+  }
+}
+
+// keep this protected until I decide if it's a good way
+// to separate id generation from collection (or should
+// I just reuse hitcollector???)
+interface IdGenerator {
+  public void generate(IndexReader reader) throws IOException;
+  public void handleDoc(int doc);
+}
+
+
+abstract class PrefixGenerator implements IdGenerator {
+  protected final Term prefix;
+
+  PrefixGenerator(Term prefix) {
+    this.prefix = prefix;
+  }
+
+  public void generate(IndexReader reader) throws IOException {
+    TermEnum enumerator = reader.terms(prefix);
+    TermDocs termDocs = reader.termDocs();
+
+    try {
+
+      String prefixText = prefix.text();
+      String prefixField = prefix.field();
+      do {
+        Term term = enumerator.term();
+        if (term != null &&
+            term.text().startsWith(prefixText) &&
+            term.field() == prefixField)
+        {
+          termDocs.seek(term);
+          while (termDocs.next()) {
+            handleDoc(termDocs.doc());
+          }
+        } else {
+          break;
+        }
+      } while (enumerator.next());
+    } finally {
+      termDocs.close();
+      enumerator.close();
+    }
+  }
+}
+
