Index: src/java/org/apache/lucene/search/FieldCacheImpl.java
===================================================================
--- src/java/org/apache/lucene/search/FieldCacheImpl.java	(revision 514680)
+++ src/java/org/apache/lucene/search/FieldCacheImpl.java	(working copy)
@@ -21,12 +21,14 @@
 import org.apache.lucene.index.TermDocs;
 import org.apache.lucene.index.TermEnum;
 import org.apache.lucene.search.FieldCache.StringIndex; // required by GCJ
+import org.apache.lucene.document.Field;
 
 import java.io.IOException;
 import java.util.Locale;
 import java.util.Map;
 import java.util.WeakHashMap;
 import java.util.HashMap;
+import java.util.Arrays;
 
 /**
  * Expert: The default cache implementation, storing all values in memory.
@@ -99,7 +101,32 @@
       }
     };
 
-  /** The internal cache. Maps Entry to array of interpreted term values. **/
+
+
+
+  class FieldEntry implements Comparable {
+    String val;
+    int ind;
+    FieldEntry(int ind, String val)
+    {
+        this.ind = ind;
+        this.val = val;
+    }
+    public String getVal()
+    {
+        return val;
+    }
+    public int getInd()
+    {
+        return ind;
+    }
+    public int compareTo(Object obj)
+    {
+        return val.compareToIgnoreCase(((FieldEntry)obj).getVal());
+    }
+  }
+
+ /** The internal cache. Maps Entry to array of interpreted term values. **/
   final Map cache = new WeakHashMap();
 
   /** See if an object is in the cache. */
@@ -224,22 +251,36 @@
     Object ret = lookup (reader, field, SortField.STRING, null);
     if (ret == null) {
       final String[] retArray = new String[reader.maxDoc()];
-      TermDocs termDocs = reader.termDocs();
-      TermEnum termEnum = reader.terms (new Term (field, ""));
-      try {
-        do {
-          Term term = termEnum.term();
-          if (term==null || term.field() != field) break;
-          String termval = term.text();
-          termDocs.seek (termEnum);
-          while (termDocs.next()) {
-            retArray[termDocs.doc()] = termval;
-          }
-        } while (termEnum.next());
-      } finally {
-        termDocs.close();
-        termEnum.close();
+      Field docField = getField(reader, field);
+      if (docField != null && docField.isStored() && docField.isTokenized()) {
+        for (int i=0; i<reader.maxDoc(); i++) {
+          String fieldValue = null;
+          if (!reader.isDeleted(i))
+            fieldValue = reader.document(i).get(field);
+          else
+            fieldValue = "";
+          retArray[i] = fieldValue;     
+        }
       }
+      else {
+        TermDocs termDocs = reader.termDocs();
+        TermEnum termEnum = reader.terms (new Term (field, ""));
+        try {
+          do {
+            Term term = termEnum.term();
+            if (term==null || term.field() != field) break;
+            String termval = term.text();
+            termDocs.seek (termEnum);
+            while (termDocs.next()) {
+              retArray[termDocs.doc()] = termval;
+            }
+          } while (termEnum.next());
+        } finally {
+          termDocs.close();
+          termEnum.close();
+        }
+      }
+    
       store (reader, field, SortField.STRING, null, retArray);
       return retArray;
     }
@@ -254,56 +295,97 @@
     if (ret == null) {
       final int[] retArray = new int[reader.maxDoc()];
       String[] mterms = new String[reader.maxDoc()+1];
-      TermDocs termDocs = reader.termDocs();
-      TermEnum termEnum = reader.terms (new Term (field, ""));
-      int t = 0;  // current term number
+      
+      Field docField = getField(reader, field);
+      if (docField != null && docField.isStored() && docField.isTokenized()) {
+        // Fill entries
+        FieldEntry[] entries = new FieldEntry[reader.maxDoc()];
+        for (int i=0; i<reader.maxDoc(); i++) {
+          String fieldValue;
+          if (!reader.isDeleted(i))
+            fieldValue = reader.document(i).get(field);
+          else
+            fieldValue = "";
+          entries[i] = new FieldEntry (i,fieldValue);     
+        }
 
-      // an entry for documents that have no terms in this field
-      // should a document with no terms be at top or bottom?
-      // this puts them at the top - if it is changed, FieldDocSortedHitQueue
-      // needs to change as well.
-      mterms[t++] = null;
+        Arrays.sort(entries);
+        for (int i=0;i<reader.maxDoc();i++)
+        {
+          int ind = entries[i].getInd();
+          retArray[ind] = i;
+          mterms[ind]=entries[i].getVal();
+        }
+      }
+      else
+      {
+        if (retArray.length > 0)
+        {
+          TermDocs termDocs = reader.termDocs();
+          TermEnum termEnum = reader.terms(new Term(field, ""));
+          int t = 0; // current term number
 
-      try {
-        do {
-          Term term = termEnum.term();
-          if (term==null || term.field() != field) break;
+          // an entry for documents that have no terms in this field
+          // should a document with no terms be at top or bottom?
+          // this puts them at the top - if it is changed, FieldDocSortedHitQueue
+          // needs to change as well.
+          mterms[t++] = null;
 
-          // store term text
-          // we expect that there is at most one term per document
-          if (t >= mterms.length) throw new RuntimeException ("there are more terms than " +
-                  "documents in field \"" + field + "\", but it's impossible to sort on " +
-                  "tokenized fields");
-          mterms[t] = term.text();
+          try
+          {
+            if (termEnum.term() == null)
+            {
+              throw new RuntimeException("no terms in field " + field);
+            }
+            do
+            {
+              Term term = termEnum.term();
+              if (term.field() != field)
+                break;
 
-          termDocs.seek (termEnum);
-          while (termDocs.next()) {
-            retArray[termDocs.doc()] = t;
+              // store term text
+              // we expect that there is at most one term per document
+              if (t >= mterms.length)
+                throw new RuntimeException("there are more terms than documents in field \"" + field +
+                "\"");
+              mterms[t] = term.text();
+              termDocs.seek(termEnum);
+              while (termDocs.next())
+              {
+                retArray[termDocs.doc()] = t;
+              }
+
+              t++;
+            }
+            while (termEnum.next());
           }
+          finally
+          {
+            termDocs.close();
+            termEnum.close();
+          }
 
-          t++;
-        } while (termEnum.next());
-      } finally {
-        termDocs.close();
-        termEnum.close();
+          if (t == 0)
+          {
+            // if there are no terms, make the term array
+            // have a single null entry
+            mterms = new String[1];
+          }
+          else if (t < mterms.length)
+          {
+            // if there are less terms than documents,
+            // trim off the dead array space
+            String[] terms = new String[t];
+            System.arraycopy(mterms, 0, terms, 0, t);
+            mterms = terms;
+          }
+        }
       }
-
-      if (t == 0) {
-        // if there are no terms, make the term array
-        // have a single null entry
-        mterms = new String[1];
-      } else if (t < mterms.length) {
-        // if there are less terms than documents,
-        // trim off the dead array space
-        String[] terms = new String[t];
-        System.arraycopy (mterms, 0, terms, 0, t);
-        mterms = terms;
-      }
-
       StringIndex value = new StringIndex (retArray, mterms);
       store (reader, field, STRING_INDEX, null, value);
       return value;
     }
+
     return (StringIndex) ret;
   }
 
@@ -398,5 +480,18 @@
     return (Comparable[]) ret;
   }
 
+  /**
+  * Returns the field in the first not-deleted document
+  * @return a Field object or null of the field is not found
+  */
+  private Field getField(IndexReader reader, String field) throws IOException{
+    for (int i=0; i<reader.maxDoc(); i++) {
+      if (!reader.isDeleted(i)) {
+        return reader.document(i).getField(field);
+      }
+    }
+    return null; 
+  }
+
 }
 
