Index: src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java	(revision 544082)
+++ src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java	(working copy)
@@ -651,7 +651,11 @@
                 } catch (NoPrefixDeclaredException e) {
                     // will never happen
                 }
-                sortFields.add(new SortField(prop, SharedFieldSortComparator.PROPERTIES, !orderSpecs[i]));
+                sortFields.add(new SortField(prop,
+                        new SharedFieldSortComparator(FieldNames.PROPERTIES,
+                                false, getContext().getItemStateManager(),
+                                getNamespaceMappings()),
+                        !orderSpecs[i]));
             }
         }
         return (SortField[]) sortFields.toArray(new SortField[sortFields.size()]);
Index: src/main/java/org/apache/jackrabbit/core/query/lucene/SharedFieldSortComparator.java
===================================================================
--- src/main/java/org/apache/jackrabbit/core/query/lucene/SharedFieldSortComparator.java	(revision 544082)
+++ src/main/java/org/apache/jackrabbit/core/query/lucene/SharedFieldSortComparator.java	(working copy)
@@ -22,8 +22,23 @@
 import org.apache.lucene.search.ScoreDocComparator;
 import org.apache.lucene.search.SortComparator;
 import org.apache.lucene.search.SortField;
+import org.apache.jackrabbit.core.state.ItemStateManager;
+import org.apache.jackrabbit.core.state.PropertyState;
+import org.apache.jackrabbit.core.NodeId;
+import org.apache.jackrabbit.core.PropertyId;
+import org.apache.jackrabbit.uuid.UUID;
+import org.apache.jackrabbit.name.NamespaceResolver;
+import org.apache.jackrabbit.name.QName;
+import org.apache.commons.collections.map.LRUMap;
+import org.slf4j.LoggerFactory;
+import org.slf4j.Logger;
 
+import javax.jcr.NamespaceException;
 import java.io.IOException;
+import java.util.List;
+import java.util.ArrayList;
+import java.util.Map;
+import java.util.Collections;
 
 /**
  * Implements a <code>SortComparator</code> which knows how to sort on a lucene
@@ -39,6 +54,11 @@
 public class SharedFieldSortComparator extends SortComparator {
 
     /**
+     * Logger instance for this class.
+     */
+    private static final Logger log = LoggerFactory.getLogger(SharedFieldSortComparator.class);
+
+    /**
      * A <code>SharedFieldSortComparator</code> that is based on
      * {@link FieldNames#PROPERTIES}.
      */
@@ -57,6 +77,17 @@
     private final boolean createComparatorValues;
 
     /**
+     * The shared item state manager. If available will be used to compare
+     * property values.
+     */
+    private final ItemStateManager ism;
+
+    /**
+     * The internal namespace resolver of the search index.
+     */
+    private final NamespaceResolver nsResolver;
+
+    /**
      * Creates a new <code>SharedFieldSortComparator</code> for a given shared
      * field.
      *
@@ -71,13 +102,35 @@
      * field.
      *
      * @param fieldname              the shared field.
-     * @param createComparatorValues if <code>true</code> creates values
-     * for the <code>ScoreDocComparator</code>s.
+     * @param createComparatorValues if <code>true</code> creates values for the
+     *                               <code>ScoreDocComparator</code>s.
      * @see #createComparatorValues
      */
-    public SharedFieldSortComparator(String fieldname, boolean createComparatorValues) {
+    public SharedFieldSortComparator(String fieldname,
+                                     boolean createComparatorValues) {
+        this(fieldname, createComparatorValues, null, null);
+    }
+
+    /**
+     * Creates a new <code>SharedFieldSortComparator</code> for a given shared
+     * field.
+     *
+     * @param fieldname              the shared field.
+     * @param createComparatorValues if <code>true</code> creates values for the
+     *                               <code>ScoreDocComparator</code>s.
+     * @param ism                    the shared item state manager.
+     * @param internalNSResolver     the search index internal namespace
+     *                               resolver.
+     * @see #createComparatorValues
+     */
+    public SharedFieldSortComparator(String fieldname,
+                                     boolean createComparatorValues,
+                                     ItemStateManager ism,
+                                     NamespaceResolver internalNSResolver) {
         this.field = fieldname;
         this.createComparatorValues = createComparatorValues;
+        this.ism = ism;
+        this.nsResolver = internalNSResolver;
     }
 
     /**
@@ -90,46 +143,178 @@
      */
     public ScoreDocComparator newComparator(final IndexReader reader, String propertyName)
             throws IOException {
-        // get the StringIndex for propertyName
-        final FieldCache.StringIndex index
-                = SharedFieldCache.INSTANCE.getStringIndex(reader, field,
-                        FieldNames.createNamedValue(propertyName, ""),
-                        SharedFieldSortComparator.this,
-                        createComparatorValues);
+        if (ism == null) {
+            // do it the old fashioned way
+            final FieldCache.StringIndex index
+                    = SharedFieldCache.INSTANCE.getStringIndex(reader, field,
+                            FieldNames.createNamedValue(propertyName, ""),
+                            SharedFieldSortComparator.this,
+                            createComparatorValues);
+            return new ScoreDocComparator() {
+                public final int compare(final ScoreDoc i, final ScoreDoc j) {
+                    final int fi = index.order[i.doc];
+                    final int fj = index.order[j.doc];
+                    if (fi < fj) {
+                        return -1;
+                    } else if (fi > fj) {
+                        return 1;
+                    } else {
+                        return 0;
+                    }
+                }
 
-        return new ScoreDocComparator() {
-            public final int compare(final ScoreDoc i, final ScoreDoc j) {
-                final int fi = index.order[i.doc];
-                final int fj = index.order[j.doc];
-                if (fi < fj) {
-                    return -1;
-                } else if (fi > fj) {
-                    return 1;
-                } else {
-                    return 0;
+                /**
+                 * Returns an empty if no lookup table is available otherwise
+                 * the index term for the score doc <code>i</code>.
+                 *
+                 * @param i the score doc.
+                 * @return the sort value if available.
+                 */
+                public Comparable sortValue(final ScoreDoc i) {
+                    if (index.lookup != null) {
+                        return index.lookup[index.order[i.doc]];
+                    } else {
+                        // return dummy value
+                        return "";
+                    }
                 }
-            }
 
-            /**
-             * Returns an empty if no lookup table is available otherwise
-             * the index term for the score doc <code>i</code>.
-             *
-             * @param i the score doc.
-             * @return the sort value if available.
-             */
-            public Comparable sortValue(final ScoreDoc i) {
-                if (index.lookup != null) {
-                    return index.lookup[index.order[i.doc]];
-                } else {
-                    // return dummy value
-                    return "";
+                public int sortType() {
+                    return SortField.CUSTOM;
                 }
+            };
+        } else {
+            // get sub readers
+            final List readers = new ArrayList();
+            getIndexReaders(readers, reader);
+
+            // get the StringIndexes for propertyName
+            final FieldCache.StringIndex[] indexes
+                    = new FieldCache.StringIndex[readers.size()];
+            int maxDoc = 0;
+            final int[] starts = new int[readers.size() + 1];
+            for (int i = 0; i < indexes.length; i++) {
+                IndexReader r = (IndexReader) readers.get(i);
+                starts[i] = maxDoc;
+                maxDoc += r.maxDoc();
+                indexes[i] = SharedFieldCache.INSTANCE.getStringIndex(r, field,
+                        FieldNames.createNamedValue(propertyName, ""),
+                        SharedFieldSortComparator.this,
+                        createComparatorValues);
             }
+            starts[readers.size()] = maxDoc;
+            try {
+                String[] parts = propertyName.split(":");
+                final QName propName = new QName(nsResolver.getURI(parts[0]), parts[1]);
+                return new ScoreDocComparator() {
 
-            public int sortType() {
-                return SortField.CUSTOM;
+                    private final Map cache = Collections.synchronizedMap(new LRUMap(1000));
+
+                    public final int compare(final ScoreDoc i, final ScoreDoc j) {
+                        int idx1 = readerIndex(i.doc);
+                        int idx2 = readerIndex(j.doc);
+                        if (idx1 == idx2) {
+                            // same segment
+                            log.debug("same segment");
+                            final int fi = indexes[idx1].order[i.doc - starts[idx1]];
+                            final int fj = indexes[idx2].order[j.doc - starts[idx2]];
+                            if (fi < fj) {
+                                return -1;
+                            } else if (fi > fj) {
+                                return 1;
+                            } else {
+                                return 0;
+                            }
+                        } else {
+                            // different segment, need to compare prop values
+                            log.debug("different segment");
+                            try {
+                                Key k1 = new Key(i.doc, propName);
+                                Comparable c1 = (Comparable) cache.get(k1);
+                                if (c1 == null) {
+                                    UUID uuid1 = UUID.fromString(
+                                            reader.document(i.doc).get(
+                                                    FieldNames.UUID));
+                                    PropertyId id1 = new PropertyId(
+                                            new NodeId(uuid1), propName);
+                                    PropertyState p1 = (PropertyState) ism.getItemState(id1);
+                                    c1 = (Comparable) p1.getValues()[0].internalValue();
+                                    cache.put(k1, c1);
+                                }
+                                Key k2 = new Key(j.doc, propName);
+                                Comparable c2 = (Comparable) cache.get(k2);
+                                if (c2 == null) {
+                                    UUID uuid2 = UUID.fromString(
+                                            reader.document(j.doc).get(
+                                                    FieldNames.UUID));
+                                    PropertyId id2 = new PropertyId(
+                                            new NodeId(uuid2), propName);
+                                    PropertyState p2 = (PropertyState) ism.getItemState(id2);
+                                    c2 = (Comparable) p2.getValues()[0].internalValue();
+                                    cache.put(k2, c2);
+                                }
+                                return c1.compareTo(c2);
+                            } catch (Exception e) {
+                                log.warn("Unable to compare documents", e);
+                                return 0;
+                            }
+                        }
+                    }
+
+                    /**
+                     * Returns an empty string if no lookup table is available
+                     * otherwise the index term for the score doc <code>i</code>.
+                     *
+                     * @param i the score doc.
+                     * @return the sort value if available.
+                     */
+                    public Comparable sortValue(final ScoreDoc i) {
+                        FieldCache.StringIndex index = indexes[readerIndex(i.doc)];
+                        if (index.lookup != null) {
+                            return index.lookup[index.order[i.doc]];
+                        } else {
+                            // return dummy value
+                            return "";
+                        }
+                    }
+
+                    public int sortType() {
+                        return SortField.CUSTOM;
+                    }
+
+                    /**
+                     * Returns the reader index for document <code>n</code>.
+                     *
+                     * @param n document number.
+                     * @return the reader index.
+                     */
+                    private int readerIndex(int n) {
+                        int lo = 0;
+                        int hi = readers.size() - 1;
+
+                        while (hi >= lo) {
+                            int mid = (lo + hi) >> 1;
+                            int midValue = starts[mid];
+                            if (n < midValue) {
+                                hi = mid - 1;
+                            } else if (n > midValue) {
+                                lo = mid + 1;
+                            } else {
+                                while (mid + 1 < readers.size() && starts[mid + 1] == midValue) {
+                                    mid++;
+                                }
+                                return mid;
+                            }
+                        }
+                        return hi;
+                    }
+                };
+            } catch (NamespaceException e) {
+                IOException ex = new IOException(e.getMessage());
+                ex.initCause(e);
+                throw ex;
             }
-        };
+        }
     }
 
     /**
@@ -138,4 +323,47 @@
     protected Comparable getComparable(String termtext) {
         throw new UnsupportedOperationException();
     }
+
+    /**
+     * Checks if <code>reader</code> is of type {@link MultiIndexReader} and if
+     * that's the case calls this method recursively for each reader within the
+     * multi index reader; otherwise the reader is simply added to the list.
+     *
+     * @param readers the list of index readers.
+     * @param reader  the reader to check.
+     */
+    private void getIndexReaders(List readers, IndexReader reader) {
+        if (reader instanceof MultiIndexReader) {
+            IndexReader[] r = ((MultiIndexReader) reader).getIndexReaders();
+            for (int i = 0; i < r.length; i++) {
+                getIndexReaders(readers, r[i]);
+            }
+        } else {
+            readers.add(reader);
+        }
+    }
+
+    private static final class Key {
+
+        public final int doc;
+
+        public final QName propName;
+
+        public Key(int doc, QName propName) {
+            this.doc = doc;
+            this.propName = propName;
+        }
+
+        public int hashCode() {
+            return doc ^ propName.hashCode();
+        }
+
+        public boolean equals(Object obj) {
+            if (obj instanceof Key) {
+                Key other = (Key) obj;
+                return doc == other.doc && propName.equals(other.propName);
+            }
+            return false;
+        }
+    }
 }
