Index: src/test/org/apache/lucene/index/DocHelper.java
===================================================================
--- src/test/org/apache/lucene/index/DocHelper.java	(revision 723418)
+++ src/test/org/apache/lucene/index/DocHelper.java	(working copy)
@@ -30,7 +30,7 @@
 import org.apache.lucene.search.Similarity;
 import org.apache.lucene.store.Directory;
 
-class DocHelper {
+public class DocHelper {
   public static final String FIELD_1_TEXT = "field one text";
   public static final String TEXT_FIELD_1_KEY = "textField1";
   public static Field textField1 = new Field(TEXT_FIELD_1_KEY, FIELD_1_TEXT,
Index: src/test/org/apache/lucene/util/TestSerialization.java
===================================================================
--- src/test/org/apache/lucene/util/TestSerialization.java	(revision 0)
+++ src/test/org/apache/lucene/util/TestSerialization.java	(revision 0)
@@ -0,0 +1,122 @@
+package org.apache.lucene.util;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+import org.apache.lucene.document.Document;
+import org.apache.lucene.index.DocHelper;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.search.BooleanClause;
+import org.apache.lucene.search.BooleanQuery;
+import org.apache.lucene.search.ConstantScoreRangeQuery;
+import org.apache.lucene.search.DefaultSimilarity;
+import org.apache.lucene.search.RangeFilter;
+import org.apache.lucene.search.RangeQuery;
+import org.apache.lucene.search.TermQuery;
+import org.apache.lucene.search.function.CustomScoreQuery;
+import org.apache.lucene.search.function.OrdFieldSource;
+import org.apache.lucene.search.function.ValueSourceQuery;
+
+public class TestSerialization extends LuceneTestCase
+{
+  public static File tempDir = new File(System.getProperty("java.io.tmpdir"));
+  
+  /**
+   * Term uses Externalization
+   * @throws IOException
+   */
+  public void testSerializeTerm() throws Exception {
+    File termFile = new File(tempDir, "term.obj");
+    FileOutputStream fileOut = new FileOutputStream(termFile);
+    ObjectOutputStream objOut = new ObjectOutputStream(fileOut);
+    objOut.writeObject(new Term("date", "01/01/2001"));
+    objOut.close();
+    
+    ObjectInputStream objIn = new ObjectInputStream(new FileInputStream(termFile));
+    Term readTerm = (Term)objIn.readObject();
+    assertEquals(readTerm.field(), "date");
+    assertEquals(readTerm.text(), "01/01/2001");
+  }
+  
+  public static void serialize(Object object, File file) throws IOException {
+    ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream(file));
+    objOut.writeObject(object);
+    objOut.close();
+  }
+  
+  public static Object deserialize(File file) throws Exception {
+    ObjectInputStream objIn = new ObjectInputStream(new FileInputStream(file));
+    return objIn.readObject();
+  }
+  
+  public void testSerializeFunctions() throws Exception {
+    File file = new File(tempDir, "function.obj");
+    ValueSourceQuery vsq = new ValueSourceQuery(new OrdFieldSource("field"));
+    CustomScoreQuery csq = new CustomScoreQuery(new TermQuery(new Term("field", "value1")), new ValueSourceQuery[] {vsq});
+    
+    serialize(csq, file);
+    CustomScoreQuery readcsq = (CustomScoreQuery)deserialize(file);
+    assertEquals(csq, readcsq);
+  }
+  
+  // TODO: test weights, explanation, topdocs
+  public void testSerializeQueries() throws Exception {
+    File queryFile = new File(tempDir, "query.obj");
+    BooleanQuery bq2 = new BooleanQuery();
+    bq2.add(new TermQuery(new Term("field", "value1")), BooleanClause.Occur.SHOULD);
+    bq2.add(new TermQuery(new Term("field", "value2")), BooleanClause.Occur.SHOULD);
+    BooleanQuery nested2 = new BooleanQuery();
+    nested2.add(new TermQuery(new Term("field", "nestedvalue1")), BooleanClause.Occur.SHOULD);
+    nested2.add(new TermQuery(new Term("field", "nestedvalue2")), BooleanClause.Occur.SHOULD);
+    nested2.add(new RangeQuery("field", "0000", "0010", true, false), BooleanClause.Occur.SHOULD);
+    nested2.add(new ConstantScoreRangeQuery("field", "0000", "0010", true, false), BooleanClause.Occur.SHOULD);
+    bq2.add(nested2, BooleanClause.Occur.SHOULD);
+    
+    ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream(queryFile));
+    objOut.writeObject(bq2);
+    DefaultSimilarity ds = new DefaultSimilarity();
+    ds.setDiscountOverlaps(true);
+    objOut.writeObject(ds);
+    RangeQuery rq = new RangeQuery("field", "0000", "0010", true, false);
+    objOut.writeObject(rq);
+    objOut.close();
+    
+    ObjectInputStream objIn = new ObjectInputStream(new FileInputStream(queryFile));
+    BooleanQuery readbq = (BooleanQuery)objIn.readObject();
+    DefaultSimilarity readds = (DefaultSimilarity)objIn.readObject();
+    RangeQuery readrq = (RangeQuery)objIn.readObject();
+      
+    //System.out.println("rq: "+rq+"\nreadrq: "+readrq);
+    assertEquals(readrq, rq);
+    assertEquals(readbq, bq2);
+    assertEquals(ds, readds);
+  }
+  
+  public void testSerializeFilters() throws Exception {
+    File file = new File(tempDir, "filters.obj");
+    RangeFilter rangeFilter = new RangeFilter("field", "0000", "0010",
+                                              true, true);
+    serialize(rangeFilter, file);
+    
+    RangeFilter readrf = (RangeFilter)deserialize(file);
+    assertEquals(readrf, rangeFilter);
+  }
+  
+  public void testSerializeDocument() throws Exception {
+    File docsFile = new File(tempDir, "docs.obj");
+    Document doc = new Document();
+    DocHelper.setupDoc(doc);
+    ObjectOutputStream objOut = new ObjectOutputStream(new FileOutputStream(docsFile));
+    objOut.writeObject(doc);
+    objOut.close();
+    
+    ObjectInputStream objIn = new ObjectInputStream(new FileInputStream(docsFile));
+    Document readdoc = (Document)objIn.readObject();
+    //System.out.println("d1: "+doc+" d2: "+readdoc);
+    assertEquals(readdoc, doc);
+  }
+}

Property changes on: src/test/org/apache/lucene/util/TestSerialization.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + "Date Rev Author URL Id"
Name: svn:eol-style
   + native

Index: src/java/org/apache/lucene/search/MultiTermQuery.java
===================================================================
--- src/java/org/apache/lucene/search/MultiTermQuery.java	(revision 723418)
+++ src/java/org/apache/lucene/search/MultiTermQuery.java	(working copy)
@@ -25,7 +25,11 @@
 import org.apache.lucene.index.TermDocs;
 import org.apache.lucene.index.TermEnum;
 import org.apache.lucene.util.OpenBitSet;
+import org.apache.lucene.util.SerializeUtils;
 import org.apache.lucene.util.ToStringUtils;
+import java.io.Externalizable;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 
 /**
  * A {@link Query} that matches documents containing a subset of terms provided
@@ -42,7 +46,8 @@
  * The pattern Term may be null. A query that uses a null pattern Term should
  * override equals and hashcode.
  */
-public abstract class MultiTermQuery extends Query {
+public abstract class MultiTermQuery extends Query implements Externalizable {
+  private static final long serialVersionUID = 10L;
   protected Term term;
   protected boolean constantScoreRewrite = false;
 
@@ -70,7 +75,21 @@
   protected Filter getFilter() {
     return new MultiTermFilter(this);
   }
-
+  
+  public void writeExternal(ObjectOutput out) throws IOException {
+    SerializeUtils.writeVLong(out, serialVersionUID);
+    super.writeExternal(out);
+    out.writeObject(term);
+    out.writeBoolean(constantScoreRewrite);
+  }
+  
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    long svuid = SerializeUtils.readVLong(in);
+    super.readExternal(in);
+    term = (Term)in.readObject();
+    constantScoreRewrite = in.readBoolean();
+  }
+  
   public Query rewrite(IndexReader reader) throws IOException {
     if (!constantScoreRewrite) {
       FilteredTermEnum enumerator = getEnum(reader);
Index: src/java/org/apache/lucene/search/ConstantScoreQuery.java
===================================================================
--- src/java/org/apache/lucene/search/ConstantScoreQuery.java	(revision 723418)
+++ src/java/org/apache/lucene/search/ConstantScoreQuery.java	(working copy)
@@ -30,6 +30,7 @@
  * @version $Id$
  */
 public class ConstantScoreQuery extends Query {
+  private static final long serialVersionUID = 10L;
   protected final Filter filter;
 
   public ConstantScoreQuery(Filter filter) {
Index: src/java/org/apache/lucene/search/FuzzyQuery.java
===================================================================
--- src/java/org/apache/lucene/search/FuzzyQuery.java	(revision 723418)
+++ src/java/org/apache/lucene/search/FuzzyQuery.java	(working copy)
@@ -28,7 +28,7 @@
  * is based on the Levenshtein (edit distance) algorithm.
  */
 public class FuzzyQuery extends MultiTermQuery {
-  
+  private static final long serialVersionUID = 10L;
   public final static float defaultMinSimilarity = 0.5f;
   public final static int defaultPrefixLength = 0;
   
Index: src/java/org/apache/lucene/search/Filter.java
===================================================================
--- src/java/org/apache/lucene/search/Filter.java	(revision 723418)
+++ src/java/org/apache/lucene/search/Filter.java	(working copy)
@@ -31,6 +31,7 @@
  *  in order to work with Lucene 3.0.
  */
 public abstract class Filter implements java.io.Serializable {
+  private static final long serialVersionUID = 10L;
   /**
    * @return A BitSet with true for documents which should be permitted in
    * search results, and false for those that should not.
Index: src/java/org/apache/lucene/search/FieldCacheRangeFilter.java
===================================================================
--- src/java/org/apache/lucene/search/FieldCacheRangeFilter.java	(revision 723418)
+++ src/java/org/apache/lucene/search/FieldCacheRangeFilter.java	(working copy)
@@ -43,6 +43,7 @@
  */
 
 public class FieldCacheRangeFilter extends Filter {
+  private static final long serialVersionUID = 10L;
   private String field;
   private String lowerVal;
   private String upperVal;
Index: src/java/org/apache/lucene/search/RangeFilter.java
===================================================================
--- src/java/org/apache/lucene/search/RangeFilter.java	(revision 723418)
+++ src/java/org/apache/lucene/search/RangeFilter.java	(working copy)
@@ -18,8 +18,13 @@
  */
 
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.util.SerializeUtils;
 
 import java.io.IOException;
+import java.io.Externalizable;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 import java.util.BitSet;
 import java.text.Collator;
 
@@ -35,8 +40,8 @@
  * If you construct a large number of range filters with different ranges but on the 
  * same field, {@link FieldCacheRangeFilter} may have significantly better performance. 
  */
-public class RangeFilter extends Filter {
-    
+public class RangeFilter extends Filter implements Externalizable {
+    private static final long serialVersionUID = 10L;
     private String fieldName;
     private String lowerTerm;
     private String upperTerm;
@@ -44,7 +49,8 @@
     private boolean includeUpper;
     private Collator collator;
     private RangeQuery rangeQuery;
-
+    
+    public RangeFilter() {}
   /**
      * @param fieldName The field this range applies to
      * @param lowerTerm The lower bound on this range
@@ -156,7 +162,29 @@
         buffer.append(includeUpper ? "]" : "}");
         return buffer.toString();
     }
-
+    
+    public void writeExternal(ObjectOutput out) throws IOException {
+      SerializeUtils.writeVLong(out, serialVersionUID);
+      out.writeUTF(fieldName);
+      out.writeUTF(lowerTerm);
+      out.writeUTF(upperTerm);
+      out.writeBoolean(includeLower);
+      out.writeBoolean(includeUpper);
+      out.writeObject(collator);
+      out.writeObject(rangeQuery);
+    }
+    
+    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+      long svuid = SerializeUtils.readVLong(in);
+      fieldName = in.readUTF();
+      lowerTerm = in.readUTF();
+      upperTerm = in.readUTF();
+      includeLower = in.readBoolean();
+      includeUpper = in.readBoolean();
+      collator = (Collator)in.readObject();
+      rangeQuery = (RangeQuery)in.readObject();
+    }
+    
     /** Returns true if <code>o</code> is equal to this. */
     public boolean equals(Object o) {
         if (this == o) return true;
Index: src/java/org/apache/lucene/search/TopFieldDocs.java
===================================================================
--- src/java/org/apache/lucene/search/TopFieldDocs.java	(revision 723418)
+++ src/java/org/apache/lucene/search/TopFieldDocs.java	(working copy)
@@ -29,7 +29,7 @@
  */
 public class TopFieldDocs
 extends TopDocs {
-
+    private static final long serialVersionUID = 10L;
 	/** The fields which were used to sort results by. */
 	public SortField[] fields;
         
Index: src/java/org/apache/lucene/search/RangeQuery.java
===================================================================
--- src/java/org/apache/lucene/search/RangeQuery.java	(revision 723418)
+++ src/java/org/apache/lucene/search/RangeQuery.java	(working copy)
@@ -17,11 +17,15 @@
  * limitations under the License.
  */
 
+import java.io.Externalizable;
 import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 import java.text.Collator;
 
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.util.SerializeUtils;
 
 /**
  * A Query that matches documents within an exclusive range. A RangeQuery
@@ -37,15 +41,17 @@
  *
  * @version $Id$
  */
-public class RangeQuery extends MultiTermQuery {
+public class RangeQuery extends MultiTermQuery implements Externalizable {
+  private static final long serialVersionUID = 10L;
   private Term lowerTerm;
   private Term upperTerm;
   private Collator collator;
   private String field;
   private boolean includeLower;
   private boolean includeUpper;
-
-
+  
+  public RangeQuery() {}
+  
   /**
    * Constructs a query selecting all terms greater/equal than <code>lowerTerm</code>
    * but less/equal than <code>upperTerm</code>. 
@@ -195,6 +201,28 @@
       return buffer.toString();
   }
 
+  public void writeExternal(ObjectOutput out) throws IOException {
+    SerializeUtils.writeVLong(out, serialVersionUID);
+    super.writeExternal(out);
+    out.writeObject(lowerTerm);
+    out.writeObject(upperTerm);
+    out.writeObject(collator);
+    out.writeUTF(field);
+    out.writeBoolean(includeLower);
+    out.writeBoolean(includeUpper);
+  }
+  
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    long svuid = SerializeUtils.readVLong(in);
+    super.readExternal(in);
+    lowerTerm = (Term)in.readObject();
+    upperTerm = (Term)in.readObject();
+    collator = (Collator)in.readObject();
+    field = in.readUTF().intern();
+    includeLower = in.readBoolean();
+    includeUpper = in.readBoolean();
+  }
+  
   /** Returns true iff <code>o</code> is equal to this. */
   public boolean equals(Object o) {
     if (this == o) return true;
Index: src/java/org/apache/lucene/search/ConstantScoreRangeQuery.java
===================================================================
--- src/java/org/apache/lucene/search/ConstantScoreRangeQuery.java	(revision 723418)
+++ src/java/org/apache/lucene/search/ConstantScoreRangeQuery.java	(working copy)
@@ -35,7 +35,10 @@
  */
 public class ConstantScoreRangeQuery extends RangeQuery
 {
-
+  private static final long serialVersionUID = 10L;
+  
+  public ConstantScoreRangeQuery() {}
+  
   public ConstantScoreRangeQuery(String fieldName, String lowerVal, String upperVal, boolean includeLower, boolean includeUpper)
   {
     super(fieldName, lowerVal, upperVal, includeLower, includeUpper);
Index: src/java/org/apache/lucene/search/function/IntFieldSource.java
===================================================================
--- src/java/org/apache/lucene/search/function/IntFieldSource.java	(revision 723418)
+++ src/java/org/apache/lucene/search/function/IntFieldSource.java	(working copy)
@@ -40,6 +40,7 @@
  *
  */
 public class IntFieldSource extends FieldCacheSource {
+  private static final long serialVersionUID = 10L;
   private FieldCache.IntParser parser;
 
   /**
Index: src/java/org/apache/lucene/search/function/ValueSourceQuery.java
===================================================================
--- src/java/org/apache/lucene/search/function/ValueSourceQuery.java	(revision 723418)
+++ src/java/org/apache/lucene/search/function/ValueSourceQuery.java	(working copy)
@@ -18,10 +18,15 @@
  */
 
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.Term;
 import org.apache.lucene.search.*;
+import org.apache.lucene.util.SerializeUtils;
 import org.apache.lucene.util.ToStringUtils;
 
+import java.io.Externalizable;
 import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 import java.util.Set;
 
 /**
@@ -38,9 +43,12 @@
  * The APIs introduced here might change in the future and will not be 
  * supported anymore in such a case.</font>
  */
-public class ValueSourceQuery extends Query {
+public class ValueSourceQuery extends Query implements Externalizable {
+  private static final long serialVersionUID = 10L;
   ValueSource valSrc;
-
+  
+  public ValueSourceQuery() {}
+  
   /**
    * Create a value source query
    * @param valSrc provides the values defines the function to be used for scoring
@@ -48,7 +56,19 @@
   public ValueSourceQuery(ValueSource valSrc) {
     this.valSrc=valSrc;
   }
-
+  
+  public void writeExternal(ObjectOutput out) throws IOException {
+    SerializeUtils.writeVLong(out, serialVersionUID);
+    super.writeExternal(out);
+    out.writeObject(valSrc);
+  }
+  
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    long svuid = SerializeUtils.readVLong(in);
+    super.readExternal(in);
+    valSrc = (ValueSource)in.readObject();
+  }
+  
   /*(non-Javadoc) @see org.apache.lucene.search.Query#rewrite(org.apache.lucene.index.IndexReader) */
   public Query rewrite(IndexReader reader) throws IOException {
     return this;
@@ -59,15 +79,30 @@
     // no terms involved here
   }
 
-  private class ValueSourceWeight implements Weight {
+  private class ValueSourceWeight implements Weight, Externalizable {
     Similarity similarity;
     float queryNorm;
     float queryWeight;
-
+    
+    public ValueSourceWeight() {}
+    
     public ValueSourceWeight(Searcher searcher) {
       this.similarity = getSimilarity(searcher);
     }
-
+    
+    public void writeExternal(ObjectOutput out) throws IOException {
+      SerializeUtils.writeVLong(out, serialVersionUID);
+      out.writeObject(similarity);
+      out.writeFloat(queryNorm);
+    }
+    
+    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+      long svuid = SerializeUtils.readVLong(in);
+      similarity = (Similarity)in.readObject();
+      queryNorm = in.readFloat();
+      queryWeight = in.readFloat();
+    }
+    
     /*(non-Javadoc) @see org.apache.lucene.search.Weight#getQuery() */
     public Query getQuery() {
       return ValueSourceQuery.this;
Index: src/java/org/apache/lucene/search/function/ShortFieldSource.java
===================================================================
--- src/java/org/apache/lucene/search/function/ShortFieldSource.java	(revision 723418)
+++ src/java/org/apache/lucene/search/function/ShortFieldSource.java	(working copy)
@@ -38,6 +38,7 @@
  * on the field.
  */
 public class ShortFieldSource extends FieldCacheSource {
+  private static final long serialVersionUID = 10L;
   private FieldCache.ShortParser parser;
 
   /**
Index: src/java/org/apache/lucene/search/function/FieldScoreQuery.java
===================================================================
--- src/java/org/apache/lucene/search/function/FieldScoreQuery.java	(revision 723418)
+++ src/java/org/apache/lucene/search/function/FieldScoreQuery.java	(working copy)
@@ -58,7 +58,7 @@
  * supported anymore in such a case.</font>
  */
 public class FieldScoreQuery extends ValueSourceQuery {
-
+  private static final long serialVersionUID = 10L;
   /**
    * Type of score field, indicating how field values are interpreted/parsed.  
    * <p>
Index: src/java/org/apache/lucene/search/function/ReverseOrdFieldSource.java
===================================================================
--- src/java/org/apache/lucene/search/function/ReverseOrdFieldSource.java	(revision 723418)
+++ src/java/org/apache/lucene/search/function/ReverseOrdFieldSource.java	(working copy)
@@ -48,6 +48,7 @@
  */
 
 public class ReverseOrdFieldSource extends ValueSource {
+  private static final long serialVersionUID = 10L;
   public String field;
 
   /** 
Index: src/java/org/apache/lucene/search/function/ByteFieldSource.java
===================================================================
--- src/java/org/apache/lucene/search/function/ByteFieldSource.java	(revision 723418)
+++ src/java/org/apache/lucene/search/function/ByteFieldSource.java	(working copy)
@@ -38,6 +38,7 @@
  * on the field. 
  */
 public class ByteFieldSource extends FieldCacheSource {
+  private static final long serialVersionUID = 10L;
   private FieldCache.ByteParser parser;
 
   /**
Index: src/java/org/apache/lucene/search/function/FieldCacheSource.java
===================================================================
--- src/java/org/apache/lucene/search/function/FieldCacheSource.java	(revision 723418)
+++ src/java/org/apache/lucene/search/function/FieldCacheSource.java	(working copy)
@@ -41,6 +41,7 @@
  *
  */
 public abstract class FieldCacheSource extends ValueSource {
+  private static final long serialVersionUID = 10L;
   private String field;
 
   /**
Index: src/java/org/apache/lucene/search/function/OrdFieldSource.java
===================================================================
--- src/java/org/apache/lucene/search/function/OrdFieldSource.java	(revision 723418)
+++ src/java/org/apache/lucene/search/function/OrdFieldSource.java	(working copy)
@@ -47,6 +47,7 @@
  */
 
 public class OrdFieldSource extends ValueSource {
+  private static final long serialVersionUID = 10L;
   protected String field;
 
   /** 
Index: src/java/org/apache/lucene/search/function/FloatFieldSource.java
===================================================================
--- src/java/org/apache/lucene/search/function/FloatFieldSource.java	(revision 723418)
+++ src/java/org/apache/lucene/search/function/FloatFieldSource.java	(working copy)
@@ -39,6 +39,7 @@
  *
  */
 public class FloatFieldSource extends FieldCacheSource {
+  private static final long serialVersionUID = 10L;
   private FieldCache.FloatParser parser;
 
   /**
Index: src/java/org/apache/lucene/search/function/CustomScoreQuery.java
===================================================================
--- src/java/org/apache/lucene/search/function/CustomScoreQuery.java	(revision 723418)
+++ src/java/org/apache/lucene/search/function/CustomScoreQuery.java	(working copy)
@@ -18,9 +18,14 @@
  */
 
 import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.text.Collator;
 import java.util.Set;
+import java.io.Externalizable;
 
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.Term;
 import org.apache.lucene.search.ComplexExplanation;
 import org.apache.lucene.search.Explanation;
 import org.apache.lucene.search.Query;
@@ -28,6 +33,7 @@
 import org.apache.lucene.search.Searcher;
 import org.apache.lucene.search.Similarity;
 import org.apache.lucene.search.Weight;
+import org.apache.lucene.util.SerializeUtils;
 import org.apache.lucene.util.ToStringUtils;
 
 /**
@@ -45,11 +51,13 @@
  * The APIs introduced here might change in the future and will not be 
  * supported anymore in such a case.</font>
  */
-public class CustomScoreQuery extends Query {
-
+public class CustomScoreQuery extends Query implements Externalizable {
+  private static final long serialVersionUID = 10L;
   private Query subQuery;
   private ValueSourceQuery[] valSrcQueries; // never null (empty array if there are no valSrcQueries).
   private boolean strict = false; // if true, valueSource part of query does not take part in weights normalization.  
+   
+  public CustomScoreQuery() {}
   
   /**
    * Create a CustomScoreQuery over input subQuery.
@@ -87,7 +95,23 @@
         valSrcQueries : new ValueSourceQuery[0];
     if (subQuery == null) throw new IllegalArgumentException("<subquery> must not be null!");
   }
-
+  
+  public void writeExternal(ObjectOutput out) throws IOException {
+    SerializeUtils.writeVLong(out, serialVersionUID);
+    super.writeExternal(out);
+    out.writeObject(subQuery);
+    out.writeObject(valSrcQueries);
+    out.writeBoolean(strict);
+  }
+  
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    long svuid = SerializeUtils.readVLong(in);
+    super.readExternal(in);
+    subQuery = (Query)in.readObject();
+    valSrcQueries = (ValueSourceQuery[])in.readObject();
+    strict = in.readBoolean();
+  }
+  
   /*(non-Javadoc) @see org.apache.lucene.search.Query#rewrite(org.apache.lucene.index.IndexReader) */
   public Query rewrite(IndexReader reader) throws IOException {
     subQuery = subQuery.rewrite(reader);
@@ -271,7 +295,7 @@
 
   //=========================== W E I G H T ============================
   
-  private class CustomWeight implements Weight {
+  private class CustomWeight implements Weight, Externalizable {
     Similarity similarity;
     Weight subQueryWeight;
     Weight[] valSrcWeights;
@@ -287,7 +311,23 @@
       }
       this.qStrict = strict;
     }
-
+    
+    public void writeExternal(ObjectOutput out) throws IOException {
+      SerializeUtils.writeVLong(out, serialVersionUID);
+      out.writeObject(similarity);
+      out.writeObject(subQueryWeight);
+      out.writeObject(valSrcWeights);
+      out.writeBoolean(qStrict);
+    }
+    
+    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+      long svuid = SerializeUtils.readVLong(in);
+      similarity = (Similarity)in.readObject();
+      subQueryWeight = (Weight)in.readObject();
+      valSrcWeights = (Weight[])in.readObject();
+      qStrict = in.readBoolean();
+    }
+    
     /*(non-Javadoc) @see org.apache.lucene.search.Weight#getQuery() */
     public Query getQuery() {
       return CustomScoreQuery.this;
Index: src/java/org/apache/lucene/search/function/ValueSource.java
===================================================================
--- src/java/org/apache/lucene/search/function/ValueSource.java	(revision 723418)
+++ src/java/org/apache/lucene/search/function/ValueSource.java	(working copy)
@@ -39,7 +39,7 @@
  *
  */
 public abstract class ValueSource implements Serializable {
-
+  private static final long serialVersionUID = 10L;
   /**
    * Return the DocValues used by the function query.
    * @param reader the IndexReader used to read these values.
Index: src/java/org/apache/lucene/search/BooleanQuery.java
===================================================================
--- src/java/org/apache/lucene/search/BooleanQuery.java	(revision 723418)
+++ src/java/org/apache/lucene/search/BooleanQuery.java	(working copy)
@@ -18,18 +18,22 @@
  */
 
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.util.SerializeUtils;
 import org.apache.lucene.util.ToStringUtils;
 import org.apache.lucene.search.BooleanClause.Occur;
 
+import java.io.Externalizable;
 import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 import java.util.*;
 
 /** A Query that matches documents matching boolean combinations of other
   * queries, e.g. {@link TermQuery}s, {@link PhraseQuery}s or other
   * BooleanQuerys.
   */
-public class BooleanQuery extends Query {
-
+public class BooleanQuery extends Query implements Externalizable {
+  private static final long serialVersionUID = 10L;
   
   private static int maxClauseCount = 1024;
 
@@ -173,7 +177,7 @@
   /** Returns the list of clauses in this query. */
   public List clauses() { return clauses; }
 
-  private class BooleanWeight implements Weight {
+  private class BooleanWeight implements Weight, Externalizable {
     protected Similarity similarity;
     protected ArrayList weights;
 
@@ -186,7 +190,19 @@
         weights.add(c.getQuery().createWeight(searcher));
       }
     }
-
+    
+    public void writeExternal(ObjectOutput out) throws IOException {
+      SerializeUtils.writeVLong(out, serialVersionUID);
+      out.writeObject(similarity);
+      out.writeObject(weights);
+    }
+    
+    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+      long svuid = SerializeUtils.readVLong(in);
+      similarity = (Similarity)in.readObject();
+      weights = (ArrayList)in.readObject();
+    }
+    
     public Query getQuery() { return BooleanQuery.this; }
     public float getValue() { return getBoost(); }
 
@@ -456,6 +472,28 @@
 
     return buffer.toString();
   }
+  
+  public void writeExternal(ObjectOutput out) throws IOException {
+    SerializeUtils.writeVLong(out, serialVersionUID);
+    super.writeExternal(out);
+    SerializeUtils.writeVInt(out, clauses.size());
+    for (int x=0; x < clauses.size(); x++) {
+      out.writeObject(clauses.get(x));
+    }
+    out.writeBoolean(disableCoord);
+    SerializeUtils.writeVInt(out, minNrShouldMatch);
+  }
+  
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    long svuid = SerializeUtils.readVLong(in);
+    super.readExternal(in);
+    int csize = SerializeUtils.readVInt(in);
+    for (int x=0; x < csize; x++) {
+      clauses.add(in.readObject());
+    }
+    disableCoord = in.readBoolean();
+    minNrShouldMatch = SerializeUtils.readVInt(in);
+  }
 
   /** Returns true iff <code>o</code> is equal to this. */
   public boolean equals(Object o) {
Index: src/java/org/apache/lucene/search/Query.java
===================================================================
--- src/java/org/apache/lucene/search/Query.java	(revision 723418)
+++ src/java/org/apache/lucene/search/Query.java	(working copy)
@@ -18,12 +18,17 @@
  */
 
 import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Externalizable;
 
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
 
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.index.Term;
+import org.apache.lucene.util.SerializeUtils;
 
 /** The abstract base class for queries.
     <p>Instantiable subclasses are:
@@ -44,7 +49,8 @@
     <li>{@link org.apache.lucene.queryParser.QueryParser QueryParser}
     </ul>
 */
-public abstract class Query implements java.io.Serializable, Cloneable {
+public abstract class Query implements Externalizable, Cloneable {
+  private static final long serialVersionUID = 10L;
   private float boost = 1.0f;                     // query boost factor
 
   /** Sets the boost for this query clause to <code>b</code>.  Documents
@@ -74,7 +80,20 @@
    * </ul>
    */
   public abstract String toString(String field);
-
+  
+  /** For Externalizable */
+  public Query() {}
+  
+  public void writeExternal(ObjectOutput out) throws IOException {
+    SerializeUtils.writeVLong(out, serialVersionUID);
+    out.writeFloat(boost);
+  }
+  
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    long svuid = SerializeUtils.readVLong(in);
+    boost = in.readFloat();
+  }
+  
   /** Prints a query to a string. */
   public String toString() {
     return toString("");
Index: src/java/org/apache/lucene/search/PhraseQuery.java
===================================================================
--- src/java/org/apache/lucene/search/PhraseQuery.java	(revision 723418)
+++ src/java/org/apache/lucene/search/PhraseQuery.java	(working copy)
@@ -32,6 +32,7 @@
  * <p>This query may be combined with other terms or queries with a {@link BooleanQuery}.
  */
 public class PhraseQuery extends Query {
+  private static final long serialVersionUID = 10L;
   private String field;
   private ArrayList terms = new ArrayList(4);
   private ArrayList positions = new ArrayList(4);
Index: src/java/org/apache/lucene/search/FieldDoc.java
===================================================================
--- src/java/org/apache/lucene/search/FieldDoc.java	(revision 723418)
+++ src/java/org/apache/lucene/search/FieldDoc.java	(working copy)
@@ -40,7 +40,7 @@
  */
 public class FieldDoc
 extends ScoreDoc {
-
+    private static final long serialVersionUID = 10L;
 	/** Expert: The values which are used to sort the referenced document.
 	 * The order of these will match the original sort criteria given by a
 	 * Sort object.  Each Object will be either an Integer, Float or String,
Index: src/java/org/apache/lucene/search/TopDocs.java
===================================================================
--- src/java/org/apache/lucene/search/TopDocs.java	(revision 723418)
+++ src/java/org/apache/lucene/search/TopDocs.java	(working copy)
@@ -17,9 +17,17 @@
  * limitations under the License.
  */
 
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
+import org.apache.lucene.util.SerializeUtils;
+
 /** Expert: Returned by low-level search implementations.
  * @see Searcher#search(Query,Filter,int) */
-public class TopDocs implements java.io.Serializable {
+public class TopDocs implements Externalizable {
+  private static final long serialVersionUID = 10L;
   /** Expert: The total number of hits for the query.
    * @see Hits#length()
   */
@@ -34,6 +42,20 @@
       return maxScore;
   }
   
+  public void writeExternal(ObjectOutput out) throws IOException {
+    SerializeUtils.writeVLong(out, serialVersionUID);
+    SerializeUtils.writeVInt(out, totalHits);
+    out.writeObject(scoreDocs);
+    out.writeFloat(maxScore);
+  }
+  
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    long svuid = SerializeUtils.readVLong(in);
+    totalHits = SerializeUtils.readVInt(in);
+    scoreDocs = (ScoreDoc[])in.readObject();
+    maxScore = in.readFloat();
+  }
+  
   /** Expert: Sets the maximum score value encountered. */
   public void setMaxScore(float maxScore) {
       this.maxScore=maxScore;
Index: src/java/org/apache/lucene/search/Explanation.java
===================================================================
--- src/java/org/apache/lucene/search/Explanation.java	(revision 723418)
+++ src/java/org/apache/lucene/search/Explanation.java	(working copy)
@@ -17,10 +17,17 @@
  * limitations under the License.
  */
 
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Externalizable;
 import java.util.ArrayList;
 
+import org.apache.lucene.util.SerializeUtils;
+
 /** Expert: Describes the score computation for document and query. */
-public class Explanation implements java.io.Serializable {
+public class Explanation implements Externalizable {
+  private static final long serialVersionUID = 10L;
   private float value;                            // the value of this node
   private String description;                     // what it represents
   private ArrayList details;                      // sub-explanations
@@ -44,8 +51,20 @@
     return (0.0f < getValue());
   }
 
-
+  public void writeExternal(ObjectOutput out) throws IOException {
+    SerializeUtils.writeVLong(out, serialVersionUID);
+    out.writeFloat(value);
+    out.writeUTF(description);
+    out.writeObject(details);
+  }
   
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    long svuid = SerializeUtils.readVLong(in);
+    value = in.readFloat();
+    description = in.readUTF();
+    details = (ArrayList)in.readObject();
+  }
+  
   /** The value assigned to this explanation node. */
   public float getValue() { return value; }
   /** Sets the value assigned to this explanation node. */
Index: src/java/org/apache/lucene/search/Sort.java
===================================================================
--- src/java/org/apache/lucene/search/Sort.java	(revision 723418)
+++ src/java/org/apache/lucene/search/Sort.java	(working copy)
@@ -99,7 +99,7 @@
  */
 public class Sort
 implements Serializable {
-
+  private static final long serialVersionUID = 10L;
   /**
    * Represents sorting by computed relevance. Using this sort criteria returns
    * the same results as calling
Index: src/java/org/apache/lucene/search/SortField.java
===================================================================
--- src/java/org/apache/lucene/search/SortField.java	(revision 723418)
+++ src/java/org/apache/lucene/search/SortField.java	(working copy)
@@ -32,7 +32,7 @@
  */
 public class SortField
 implements Serializable {
-
+  private static final long serialVersionUID = 10L;
   /** Sort by document score (relevancy).  Sort values are Float and higher
    * values are at the front. */
   public static final int SCORE = 0;
Index: src/java/org/apache/lucene/search/TermQuery.java
===================================================================
--- src/java/org/apache/lucene/search/TermQuery.java	(revision 723418)
+++ src/java/org/apache/lucene/search/TermQuery.java	(working copy)
@@ -18,26 +18,36 @@
  */
 
 import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 import java.util.Set;
+import java.io.Externalizable;
 
 import org.apache.lucene.index.Term;
 import org.apache.lucene.index.TermDocs;
 import org.apache.lucene.index.IndexReader;
+import org.apache.lucene.search.BooleanClause.Occur;
+import org.apache.lucene.util.SerializeUtils;
 import org.apache.lucene.util.ToStringUtils;
 
 /** A Query that matches documents containing a term.
   This may be combined with other terms with a {@link BooleanQuery}.
   */
 public class TermQuery extends Query {
+  private static final long serialVersionUID = 10L;
   private Term term;
-
-  private class TermWeight implements Weight {
+  
+  public TermQuery() {}
+  
+  private class TermWeight implements Weight, Externalizable {
     private Similarity similarity;
     private float value;
     private float idf;
     private float queryNorm;
     private float queryWeight;
-
+    
+    public TermWeight() {}
+    
     public TermWeight(Searcher searcher)
       throws IOException {
       this.similarity = getSimilarity(searcher);
@@ -48,7 +58,25 @@
 
     public Query getQuery() { return TermQuery.this; }
     public float getValue() { return value; }
-
+    
+    public void writeExternal(ObjectOutput out) throws IOException {
+      SerializeUtils.writeVLong(out, serialVersionUID);
+      out.writeObject(similarity);
+      out.writeFloat(value);
+      out.writeFloat(idf);
+      out.writeFloat(queryNorm);
+      out.writeFloat(queryWeight);
+    }
+    
+    public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+      long svuid = SerializeUtils.readVLong(in);
+      similarity = (Similarity)in.readObject();
+      value = in.readFloat();
+      idf = in.readFloat();
+      queryNorm = in.readFloat();
+      queryWeight = in.readFloat();
+    }
+    
     public float sumOfSquaredWeights() {
       queryWeight = idf * getBoost();             // compute query weight
       return queryWeight * queryWeight;           // square it
@@ -149,7 +177,17 @@
   public void extractTerms(Set terms) {
     terms.add(getTerm());
   }
-
+  
+  public void writeExternal(ObjectOutput out) throws IOException {
+    SerializeUtils.writeVLong(out, serialVersionUID);
+    out.writeObject(term);
+  }
+  
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    long svuid = SerializeUtils.readVLong(in);
+    term = (Term)in.readObject();
+  }
+  
   /** Prints a user-readable version of this query. */
   public String toString(String field) {
     StringBuffer buffer = new StringBuffer();
Index: src/java/org/apache/lucene/search/ScoreDoc.java
===================================================================
--- src/java/org/apache/lucene/search/ScoreDoc.java	(revision 723418)
+++ src/java/org/apache/lucene/search/ScoreDoc.java	(working copy)
@@ -20,6 +20,7 @@
 /** Expert: Returned by low-level search implementations.
  * @see TopDocs */
 public class ScoreDoc implements java.io.Serializable {
+  private static final long serialVersionUID = 10L;
   /** Expert: The score of this document for the query. */
   public float score;
 
Index: src/java/org/apache/lucene/search/ComplexExplanation.java
===================================================================
--- src/java/org/apache/lucene/search/ComplexExplanation.java	(revision 723418)
+++ src/java/org/apache/lucene/search/ComplexExplanation.java	(working copy)
@@ -20,6 +20,7 @@
 /** Expert: Describes the score computation for document and query, and
  * can distinguish a match independent of a positive value. */
 public class ComplexExplanation extends Explanation {
+  private static final long serialVersionUID = 10L;
   private Boolean match;
   
   public ComplexExplanation() {
Index: src/java/org/apache/lucene/search/BooleanClause.java
===================================================================
--- src/java/org/apache/lucene/search/BooleanClause.java	(revision 723418)
+++ src/java/org/apache/lucene/search/BooleanClause.java	(working copy)
@@ -1,7 +1,13 @@
 package org.apache.lucene.search;
 
 import org.apache.lucene.util.Parameter;
+import org.apache.lucene.util.SerializeUtils;
 
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
 /**
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -20,8 +26,12 @@
  */
 
 /** A clause in a BooleanQuery. */
-public class BooleanClause implements java.io.Serializable {
+public class BooleanClause implements Externalizable {
+  private static final long serialVersionUID = 10L;
   
+  /** For Externalizable */
+  public BooleanClause() {}
+  
   /** Specifies how clauses are to occur in matching documents. */
   public static final class Occur extends Parameter implements java.io.Serializable {
     
@@ -29,7 +39,7 @@
       // typesafe enum pattern, no public constructor
       super(name);
     }
-
+    
     public String toString() {
       if (this == MUST) return "+";
       if (this == MUST_NOT) return "-";
@@ -102,6 +112,18 @@
     return this.query.equals(other.query)
       && this.occur.equals(other.occur);
   }
+  
+  public void writeExternal(ObjectOutput out) throws IOException {
+    SerializeUtils.writeVLong(out, serialVersionUID);
+    out.writeObject(query);
+    out.writeObject(occur);
+  }
+  
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    long svuid = SerializeUtils.readVLong(in);
+    query = (Query)in.readObject();
+    occur = (Occur)in.readObject();
+  }
 
   /** Returns a hash code value for this object.*/
   public int hashCode() {
Index: src/java/org/apache/lucene/search/DefaultSimilarity.java
===================================================================
--- src/java/org/apache/lucene/search/DefaultSimilarity.java	(revision 723418)
+++ src/java/org/apache/lucene/search/DefaultSimilarity.java	(working copy)
@@ -1,6 +1,12 @@
 package org.apache.lucene.search;
 
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Externalizable;
+
 import org.apache.lucene.index.FieldInvertState;
+import org.apache.lucene.util.SerializeUtils;
 
 /**
  * Licensed to the Apache Software Foundation (ASF) under one or more
@@ -20,8 +26,8 @@
  */
 
 /** Expert: Default scoring implementation. */
-public class DefaultSimilarity extends Similarity {
-
+public class DefaultSimilarity extends Similarity implements Externalizable {
+  private static final long serialVersionUID = 10L;
   /** Implemented as
    *  <code>state.getBoost()*lengthNorm(numTerms)</code>, where
    *  <code>numTerms</code> is {@link FieldInvertState#getLength()} if {@link
@@ -72,7 +78,17 @@
 
   // Default false
   protected boolean discountOverlaps;
-
+  
+  public void writeExternal(ObjectOutput out) throws IOException {
+    SerializeUtils.writeVLong(out, serialVersionUID);
+    out.writeBoolean(discountOverlaps);
+  }
+  
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    long svuid = SerializeUtils.readVLong(in);
+    discountOverlaps = in.readBoolean();
+  }
+  
   /** Determines whether overlap tokens (Tokens with
    *  0 position increment) are ignored when computing
    *  norm.  By default this is false, meaning overlap
@@ -87,6 +103,20 @@
     discountOverlaps = v;
   }
 
+  public boolean equals(Object obj)
+  {
+    if (this == obj)
+      return true;
+    if (obj == null)
+      return false;
+    if (getClass() != obj.getClass())
+      return false;
+    DefaultSimilarity other = (DefaultSimilarity) obj;
+    if (discountOverlaps != other.discountOverlaps)
+      return false;
+    return true;
+  }
+
   /** @see #setDiscountOverlaps */
   public boolean getDiscountOverlaps() {
     return discountOverlaps;
Index: src/java/org/apache/lucene/index/Payload.java
===================================================================
--- src/java/org/apache/lucene/index/Payload.java	(revision 723418)
+++ src/java/org/apache/lucene/index/Payload.java	(working copy)
@@ -35,6 +35,7 @@
  *
  */
 public class Payload implements Serializable, Cloneable {
+  private static final long serialVersionUID = 10L;
   /** the byte array containing the payload data */
   protected byte[] data;
     
Index: src/java/org/apache/lucene/index/Term.java
===================================================================
--- src/java/org/apache/lucene/index/Term.java	(revision 723418)
+++ src/java/org/apache/lucene/index/Term.java	(working copy)
@@ -1,5 +1,12 @@
 package org.apache.lucene.index;
 
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Externalizable;
+
+import org.apache.lucene.util.SerializeUtils;
+
 /**
  * Licensed to the Apache Software Foundation (ASF) under one or more
  * contributor license agreements.  See the NOTICE file distributed with
@@ -25,10 +32,13 @@
   Note that terms may represent more than words from text fields, but also
   things like dates, email addresses, urls, etc.  */
 
-public final class Term implements Comparable, java.io.Serializable {
+public final class Term implements Comparable, Externalizable {
+  private static final long serialVersionUID = 10L;
   String field;
   String text;
-
+  
+  public Term() {}
+  
   /** Constructs a Term with the given field and text.
    * <p>Note that a null field or null text value results in undefined
    * behavior for most Lucene APIs that accept a Term parameter. */
@@ -113,10 +123,15 @@
 
   public final String toString() { return field + ":" + text; }
 
-  private void readObject(java.io.ObjectInputStream in)
-    throws java.io.IOException, ClassNotFoundException
-  {
-      in.defaultReadObject();
-      field = field.intern();
+  public void writeExternal(ObjectOutput out) throws IOException {
+    SerializeUtils.writeVLong(out, serialVersionUID);
+    out.writeUTF(field);
+    out.writeUTF(text);
   }
+  
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    long serialVersionUID = SerializeUtils.readVLong(in);
+	field = in.readUTF().intern();
+	text = in.readUTF();
+  }
 }
Index: src/java/org/apache/lucene/util/SerializeUtils.java
===================================================================
--- src/java/org/apache/lucene/util/SerializeUtils.java	(revision 0)
+++ src/java/org/apache/lucene/util/SerializeUtils.java	(revision 0)
@@ -0,0 +1,172 @@
+package org.apache.lucene.util;
+
+import java.io.DataInput;
+import java.io.DataOutput;
+import java.io.IOException;
+
+/**
+ * From Hadoop WriteableUtils
+ *
+ */
+public class SerializeUtils
+{
+  
+  /**
+   * Reads a zero-compressed encoded integer from input stream and returns it.
+   * @param stream Binary input stream
+   * @throws java.io.IOException 
+   * @return deserialized integer from stream.
+   */
+  public static int readVInt(DataInput stream) throws IOException {
+    return (int) readVLong(stream);
+  }
+  
+  /**
+   * Serializes an integer to a binary stream with zero-compressed encoding.
+   * For -120 <= i <= 127, only one byte is used with the actual value.
+   * For other values of i, the first byte value indicates whether the
+   * integer is positive or negative, and the number of bytes that follow.
+   * If the first byte value v is between -121 and -124, the following integer
+   * is positive, with number of bytes that follow are -(v+120).
+   * If the first byte value v is between -125 and -128, the following integer
+   * is negative, with number of bytes that follow are -(v+124). Bytes are
+   * stored in the high-non-zero-byte-first order.
+   *
+   * @param stream Binary output stream
+   * @param i Integer to be serialized
+   * @throws java.io.IOException 
+   */
+  public static void writeVInt(DataOutput stream, int i) throws IOException {
+    writeVLong(stream, i);
+  }
+
+  /**
+   * Given the first byte of a vint/vlong, determine the sign
+   * 
+   * @param value
+   *          the first byte
+   * @return is the value negative
+   */
+  public static boolean isNegativeVInt(byte value)
+  {
+    return value < -120 || (value >= -112 && value < 0);
+  }
+
+  /**
+   * Serializes a long to a binary stream with zero-compressed encoding. For -112 <= i <=
+   * 127, only one byte is used with the actual value. For other values of i, the first
+   * byte value indicates whether the long is positive or negative, and the number of
+   * bytes that follow. If the first byte value v is between -113 and -120, the following
+   * long is positive, with number of bytes that follow are -(v+112). If the first byte
+   * value v is between -121 and -128, the following long is negative, with number of
+   * bytes that follow are -(v+120). Bytes are stored in the high-non-zero-byte-first
+   * order.
+   * 
+   * @param stream
+   *          Binary output stream
+   * @param i
+   *          Long to be serialized
+   * @throws java.io.IOException
+   */
+  public static void writeVLong(DataOutput stream, long i) throws IOException
+  {
+    if (i >= -112 && i <= 127)
+    {
+      stream.writeByte((byte) i);
+      return;
+    }
+
+    int len = -112;
+    if (i < 0)
+    {
+      i ^= -1L; // take one's complement'
+      len = -120;
+    }
+
+    long tmp = i;
+    while (tmp != 0)
+    {
+      tmp = tmp >> 8;
+      len--;
+    }
+
+    stream.writeByte((byte) len);
+
+    len = (len < -120) ? -(len + 120) : -(len + 112);
+
+    for (int idx = len; idx != 0; idx--)
+    {
+      int shiftbits = (idx - 1) * 8;
+      long mask = 0xFFL << shiftbits;
+      stream.writeByte((byte) ((i & mask) >> shiftbits));
+    }
+  }
+
+  /**
+   * Reads a zero-compressed encoded long from input stream and returns it.
+   * 
+   * @param stream
+   *          Binary input stream
+   * @throws java.io.IOException
+   * @return deserialized long from stream.
+   */
+  public static long readVLong(DataInput stream) throws IOException
+  {
+    byte firstByte = stream.readByte();
+    int len = decodeVIntSize(firstByte);
+    if (len == 1)
+    {
+      return firstByte;
+    }
+    long i = 0;
+    for (int idx = 0; idx < len - 1; idx++)
+    {
+      byte b = stream.readByte();
+      i = i << 8;
+      i = i | (b & 0xFF);
+    }
+    return (isNegativeVInt(firstByte) ? (i ^ -1L) : i);
+  }
+
+  /**
+   * Parse the first byte of a vint/vlong to determine the number of bytes
+   * 
+   * @param value
+   *          the first byte of the vint/vlong
+   * @return the total number of bytes (1 to 9)
+   */
+  public static int decodeVIntSize(byte value)
+  {
+    if (value >= -112)
+    {
+      return 1;
+    }
+    else if (value < -120)
+    {
+      return -119 - value;
+    }
+    return -111 - value;
+  }
+
+  /**
+   * Get the encoded length if an integer is stored in a variable-length format
+   * 
+   * @return the encoded length
+   */
+  public static int getVIntSize(long i)
+  {
+    if (i >= -112 && i <= 127)
+    {
+      return 1;
+    }
+
+    if (i < 0)
+    {
+      i ^= -1L; // take one's complement'
+    }
+    // find the number of bytes with non-leading zeros
+    int dataBits = Long.SIZE - Long.numberOfLeadingZeros(i);
+    // find the number of data bytes + length byte
+    return (dataBits + 7) / 8 + 1;
+  }
+}

Property changes on: src/java/org/apache/lucene/util/SerializeUtils.java
___________________________________________________________________
Name: svn:mime-type
   + text/plain
Name: svn:keywords
   + "Date Rev Author URL Id"
Name: svn:eol-style
   + native

Index: src/java/org/apache/lucene/util/Parameter.java
===================================================================
--- src/java/org/apache/lucene/util/Parameter.java	(revision 723418)
+++ src/java/org/apache/lucene/util/Parameter.java	(working copy)
@@ -18,16 +18,20 @@
  */
 
 import java.io.ObjectStreamException;
-import java.io.Serializable;
 import java.io.StreamCorruptedException;
 import java.util.HashMap;
 import java.util.Map;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 
 /**
  * A serializable Enum class.
  */
-public abstract class Parameter implements Serializable
+public abstract class Parameter implements java.io.Serializable
 {
+  private static final long serialVersionUID = 10L;
   static Map allParameters = new HashMap();
   
   private String name;
@@ -46,7 +50,20 @@
     
     allParameters.put(key, this);
   }
+  /**
+  public void writeExternal(ObjectOutput out) throws IOException {
+    SerializeUtils.writeVLong(out, serialVersionUID);
+    out.writeUTF(name);
+  }
   
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    long svuid = SerializeUtils.readVLong(in);
+    name = in.readUTF();
+    Object par = allParameters.get(makeKey(name));
+    if(par == null)
+      throw new StreamCorruptedException("Unknown parameter value: " + name);
+  }
+  **/
   private String makeKey(String name){
     return getClass() + " " + name;
   }
Index: src/java/org/apache/lucene/document/SetBasedFieldSelector.java
===================================================================
--- src/java/org/apache/lucene/document/SetBasedFieldSelector.java	(revision 723418)
+++ src/java/org/apache/lucene/document/SetBasedFieldSelector.java	(working copy)
@@ -1,5 +1,8 @@
 package org.apache.lucene.document;
 
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 import java.util.Set;
 /**
  * Copyright 2004 The Apache Software Foundation
@@ -17,12 +20,14 @@
  * limitations under the License.
  */
 
+import org.apache.lucene.util.SerializeUtils;
+
 /**
  * Declare what fields to load normally and what fields to load lazily
  *
  **/
 public class SetBasedFieldSelector implements FieldSelector {
-  
+  private static final long serialVersionUID = 10L;
   private Set fieldsToLoad;
   private Set lazyFieldsToLoad;
   
@@ -57,4 +62,16 @@
     }                                           
     return result;
   }
+  
+  public void writeExternal(ObjectOutput out) throws IOException {
+    SerializeUtils.writeVLong(out, serialVersionUID);
+    out.writeObject(fieldsToLoad);
+    out.writeObject(lazyFieldsToLoad);
+  }
+  
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    long svuid = SerializeUtils.readVLong(in);
+    fieldsToLoad = (Set)in.readObject();
+    lazyFieldsToLoad = (Set)in.readObject();
+  }
 }
\ No newline at end of file
Index: src/java/org/apache/lucene/document/Field.java
===================================================================
--- src/java/org/apache/lucene/document/Field.java	(revision 723418)
+++ src/java/org/apache/lucene/document/Field.java	(working copy)
@@ -20,8 +20,13 @@
 import org.apache.lucene.analysis.TokenStream;
 import org.apache.lucene.index.IndexWriter;   // for javadoc
 import org.apache.lucene.util.Parameter;
+import org.apache.lucene.util.SerializeUtils;
 
 import java.io.Reader;
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
 import java.io.Serializable;
 
 /**
@@ -32,7 +37,8 @@
   index, so that they may be returned with hits on the document.
   */
 
-public final class Field extends AbstractField implements Fieldable, Serializable {
+public final class Field extends AbstractField implements Fieldable, Externalizable {
+  private static final long serialVersionUID = 10L;
   
   /** Specifies whether and how a field should be stored. */
   public static final class Store extends Parameter implements Serializable {
@@ -234,8 +240,13 @@
   public void setValue(TokenStream value) {
     fieldsData = value;
   }
-
+  
   /**
+   * No argument constructor for Externalizable based serialization
+   */
+  public Field() {}
+  
+  /**
    * Create a field by specifying its name, value and how it will
    * be saved in the index. Term vectors will not be stored in the index.
    * 
@@ -473,4 +484,18 @@
     
     setStoreTermVector(TermVector.NO);
   }
+  
+  public boolean equals(Object o) {
+    return super.equals(o);
+  }
+  
+  public void writeExternal(ObjectOutput out) throws IOException {
+    SerializeUtils.writeVLong(out, serialVersionUID);
+    super.writeExternal(out);
+  }
+  
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    long svuid = SerializeUtils.readVLong(in);
+    super.readExternal(in);
+  }
 }
Index: src/java/org/apache/lucene/document/AbstractField.java
===================================================================
--- src/java/org/apache/lucene/document/AbstractField.java	(revision 723418)
+++ src/java/org/apache/lucene/document/AbstractField.java	(working copy)
@@ -15,13 +15,21 @@
  * limitations under the License.
  */
 
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+import java.io.Serializable;
+import java.io.NotSerializableException;
+import java.util.Arrays;
 
+import org.apache.lucene.util.SerializeUtils;
 /**
  *
  *
  **/
-public abstract class AbstractField implements Fieldable {
-
+public abstract class AbstractField implements Fieldable, Externalizable {
+  private static final long serialVersionUID = 10L;
   protected String name = "body";
   protected boolean storeTermVector = false;
   protected boolean storeOffsetWithTermVector = false;
@@ -44,7 +52,7 @@
   protected AbstractField()
   {
   }
-
+  
   protected AbstractField(String name, Field.Store store, Field.Index index, Field.TermVector termVector) {
     if (name == null)
       throw new NullPointerException("name cannot be null");
@@ -282,7 +290,75 @@
   public boolean isLazy() {
     return lazy;
   }
-
+  
+  public boolean equals(Object o) {
+    AbstractField other = (AbstractField)o;
+    return (storeTermVector == other.storeTermVector 
+        && storeOffsetWithTermVector == other.storeOffsetWithTermVector
+        && storePositionWithTermVector == other.storePositionWithTermVector
+        && omitNorms == other.omitNorms
+        && isStored == other.isStored
+        && isIndexed == other.isIndexed
+        && isTokenized == other.isTokenized
+        && isBinary == other.isBinary
+        && isCompressed == other.isCompressed
+        && lazy == other.lazy
+        && omitTf == other.omitTf
+        && boost == other.boost
+        && binaryLength == other.binaryLength
+        && binaryOffset == other.binaryOffset
+        && equalsFieldData(fieldsData, other.fieldsData));
+  }
+  
+  private static boolean equalsFieldData(Object o1, Object o2) {
+    if (o1 instanceof String && o2 instanceof String) {
+      return o1.equals(o2);
+    } else if (o1 instanceof byte[] && o2 instanceof byte[]) {
+      return Arrays.equals((byte[])o1, (byte[])o2);
+    }
+    return true;
+  }
+  
+  public void writeExternal(ObjectOutput out) throws IOException {
+    SerializeUtils.writeVLong(out, serialVersionUID);
+    out.writeUTF(name);
+    out.writeBoolean(storeTermVector);
+    out.writeBoolean(storeOffsetWithTermVector);
+    out.writeBoolean(storePositionWithTermVector);
+    out.writeBoolean(omitNorms);
+    out.writeBoolean(isStored);
+    out.writeBoolean(isIndexed);
+    out.writeBoolean(isTokenized);
+    out.writeBoolean(isBinary);
+    out.writeBoolean(isCompressed);
+    out.writeBoolean(lazy);
+    out.writeBoolean(omitTf);
+    out.writeFloat(boost);
+    SerializeUtils.writeVInt(out, binaryLength);
+    SerializeUtils.writeVInt(out, binaryOffset);
+    out.writeObject(fieldsData);
+  }
+  
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    long svuid = SerializeUtils.readVLong(in);
+    name = in.readUTF().intern();
+    storeTermVector = in.readBoolean();
+    storeOffsetWithTermVector = in.readBoolean();
+    storePositionWithTermVector = in.readBoolean();
+    omitNorms = in.readBoolean();
+    isStored = in.readBoolean();
+    isIndexed = in.readBoolean();
+    isTokenized = in.readBoolean();
+    isBinary = in.readBoolean();
+    isCompressed = in.readBoolean();
+    lazy = in.readBoolean();
+    omitTf = in.readBoolean();
+    boost = in.readFloat();
+    binaryLength = SerializeUtils.readVInt(in);
+    binaryOffset = SerializeUtils.readVInt(in);
+    fieldsData = in.readObject();
+  }
+  
   /** Prints a Field for human consumption. */
   public final String toString() {
     StringBuffer result = new StringBuffer();
Index: src/java/org/apache/lucene/document/Document.java
===================================================================
--- src/java/org/apache/lucene/document/Document.java	(revision 723418)
+++ src/java/org/apache/lucene/document/Document.java	(working copy)
@@ -18,8 +18,14 @@
  */
 
 import java.util.*;             // for javadoc
+import java.io.Externalizable;
+import java.io.IOException;
+import java.io.ObjectInput;
+import java.io.ObjectOutput;
+
 import org.apache.lucene.search.ScoreDoc; // for javadoc
 import org.apache.lucene.search.Searcher;  // for javadoc
+import org.apache.lucene.util.SerializeUtils;
 import org.apache.lucene.index.IndexReader;  // for javadoc
 
 /** Documents are the unit of indexing and search.
@@ -36,14 +42,14 @@
  * IndexReader#document(int)}.
  */
 
-public final class Document implements java.io.Serializable {
+public final class Document implements Externalizable {
+  private static final long serialVersionUID = 10L;
   List fields = new ArrayList();
   private float boost = 1.0f;
 
   /** Constructs a new document with no fields. */
   public Document() {}
-
-
+  
   /** Sets a boost factor for hits on any field of this document.  This value
    * will be multiplied into the score of all hits on this document.
    *
@@ -315,6 +321,28 @@
     return null;
   }
   
+  public void writeExternal(ObjectOutput out) throws IOException {
+    SerializeUtils.writeVLong(out, serialVersionUID);
+    SerializeUtils.writeVInt(out, fields.size());
+    for (int x=0; x < fields.size(); x++) {
+      out.writeObject(fields.get(x));
+    }
+  }
+  
+  public void readExternal(ObjectInput in) throws IOException, ClassNotFoundException {
+    long svuid = SerializeUtils.readVLong(in);
+    int fsize = SerializeUtils.readVInt(in);
+    for (int x=0; x < fsize; x++) {
+      fields.add(in.readObject());
+    }
+  }
+  
+  public boolean equals(Object o) {
+    Document other = (Document)o;
+    return (boost == other.boost
+        && fields.equals(other.fields));
+  }
+  
   /** Prints the fields of a document for human consumption. */
   public final String toString() {
     StringBuffer buffer = new StringBuffer();
