Index: src/main/java/org/apache/jackrabbit/core/query/DerefQueryNode.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/query/DerefQueryNode.java (revision 538490) +++ src/main/java/org/apache/jackrabbit/core/query/DerefQueryNode.java (working copy) @@ -83,4 +83,14 @@ } return false; } + + /** + * {@inheritDoc} + */ + public boolean needsSystemTree() { + // Always return true since we don't know if the referenced nodes path + // is a child of /jcr:system + return true; + } + } Index: src/main/java/org/apache/jackrabbit/core/query/ExactQueryNode.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/query/ExactQueryNode.java (revision 538490) +++ src/main/java/org/apache/jackrabbit/core/query/ExactQueryNode.java (working copy) @@ -93,4 +93,11 @@ } return false; } + + /** + * {@inheritDoc} + */ + public boolean needsSystemTree() { + return false; + } } Index: src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java (revision 538490) +++ src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java (working copy) @@ -241,4 +241,15 @@ return (QName[]) selectProps.toArray(new QName[selectProps.size()]); } + + /** + * Returns true if this query node needs items under + * /jcr:system to be queried. + * + * @return true if this query node needs content under + * /jcr:system to be queried; false otherwise. + */ + protected boolean needsSystemTree() { + return this.root.needsSystemTree(); + } } Index: src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java (revision 540953) +++ src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java (working copy) @@ -519,7 +519,7 @@ checkOpen(); SortField[] sortFields = createSortFields(orderProps, orderSpecs); - IndexReader reader = getIndexReader(); + IndexReader reader = getIndexReader(queryImpl.needsSystemTree()); IndexSearcher searcher = new IndexSearcher(reader); Hits hits; if (sortFields.length > 0) { @@ -611,9 +611,14 @@ * @throws IOException the index reader cannot be obtained. */ public IndexReader getIndexReader() throws IOException { + return getIndexReader(true); + } + + private IndexReader getIndexReader(boolean includeSystemIndex) + throws IOException { QueryHandler parentHandler = getContext().getParentHandler(); IndexReader parentReader = null; - if (parentHandler instanceof SearchIndex) { + if (parentHandler instanceof SearchIndex && includeSystemIndex) { parentReader = ((SearchIndex) parentHandler).index.getIndexReader(); } Index: src/main/java/org/apache/jackrabbit/core/query/NAryQueryNode.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/query/NAryQueryNode.java (revision 538490) +++ src/main/java/org/apache/jackrabbit/core/query/NAryQueryNode.java (working copy) @@ -18,6 +18,7 @@ import java.util.ArrayList; import java.util.Arrays; +import java.util.Iterator; import java.util.List; /** @@ -146,4 +147,20 @@ } return false; } + + /** + * {@inheritDoc} + */ + public boolean needsSystemTree() { + if (operands == null) { + return false; + } + for (Iterator iter = operands.iterator(); iter.hasNext();) { + QueryNode queryNode = (QueryNode) iter.next(); + if (queryNode.needsSystemTree()) + return true; + } + return false; + } + } Index: src/main/java/org/apache/jackrabbit/core/query/OrderQueryNode.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/query/OrderQueryNode.java (revision 538490) +++ src/main/java/org/apache/jackrabbit/core/query/OrderQueryNode.java (working copy) @@ -188,4 +188,12 @@ return false; } } + + /** + * {@inheritDoc} + */ + public boolean needsSystemTree() { + return false; + } + } Index: src/main/java/org/apache/jackrabbit/core/query/PathQueryNode.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/query/PathQueryNode.java (revision 538490) +++ src/main/java/org/apache/jackrabbit/core/query/PathQueryNode.java (working copy) @@ -16,6 +16,8 @@ */ package org.apache.jackrabbit.core.query; +import org.apache.jackrabbit.name.QName; + /** * Implements a query node that defines a path restriction. */ @@ -110,4 +112,45 @@ } return false; } + + + /** + * {@inheritDoc} + */ + public boolean needsSystemTree() { + + LocationStepQueryNode[] pathSteps = getPathSteps(); + if (pathSteps == null || pathSteps.length == 0) { + return true; + } + + QName firstPathStepName = pathSteps[0].getNameTest(); + // If the first location step has a null name test we need to include + // the system tree ("*") + if (firstPathStepName == null) + return true; + + // Calculate the first workspace relative location step + LocationStepQueryNode firstWorkspaceRelativeStep = pathSteps[0]; + if (firstPathStepName.equals(QName.ROOT)) { + // path starts with "/jcr:root" + if (pathSteps.length > 1) { + firstWorkspaceRelativeStep = pathSteps[1]; + } + } + + // First path step starts with "//" + if (firstWorkspaceRelativeStep.getIncludeDescendants()) + return true; + + // If the first workspace relative location step is jcr:system we need + // to include the system tree + QName firstWorkspaceRelativeName = firstWorkspaceRelativeStep.getNameTest(); + if (firstWorkspaceRelativeName == null + || firstWorkspaceRelativeName.equals(QName.JCR_SYSTEM)) { + return true; + } + + return super.needsSystemTree(); + } } Index: src/main/java/org/apache/jackrabbit/core/query/PropertyFunctionQueryNode.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/query/PropertyFunctionQueryNode.java (revision 538490) +++ src/main/java/org/apache/jackrabbit/core/query/PropertyFunctionQueryNode.java (working copy) @@ -112,4 +112,12 @@ public String getFunctionName() { return functionName; } + + /** + * {@inheritDoc} + */ + public boolean needsSystemTree() { + return false; + } + } Index: src/main/java/org/apache/jackrabbit/core/query/QueryNode.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/query/QueryNode.java (revision 538490) +++ src/main/java/org/apache/jackrabbit/core/query/QueryNode.java (working copy) @@ -125,4 +125,13 @@ * this; false otherwise. */ public abstract boolean equals(Object obj); + + /** + * Returns true if this query node needs items under + * /jcr:system to be queried. + * + * @return true if this query node needs content under + * /jcr:system to be queried; false otherwise. + */ + public abstract boolean needsSystemTree(); } Index: src/main/java/org/apache/jackrabbit/core/query/QueryRootNode.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/query/QueryRootNode.java (revision 538490) +++ src/main/java/org/apache/jackrabbit/core/query/QueryRootNode.java (working copy) @@ -133,4 +133,12 @@ } return false; } + + /** + * {@inheritDoc} + */ + public boolean needsSystemTree() { + return (locationNode != null && locationNode.needsSystemTree()) || (orderNode != null && orderNode.needsSystemTree()); + } + } Index: src/main/java/org/apache/jackrabbit/core/query/TextsearchQueryNode.java =================================================================== --- src/main/java/org/apache/jackrabbit/core/query/TextsearchQueryNode.java (revision 538490) +++ src/main/java/org/apache/jackrabbit/core/query/TextsearchQueryNode.java (working copy) @@ -209,4 +209,12 @@ } return false; } + + /** + * {@inheritDoc} + */ + public boolean needsSystemTree() { + return false; + } + } Index: src/test/java/org/apache/jackrabbit/core/query/PathQueryNodeTest.java =================================================================== --- src/test/java/org/apache/jackrabbit/core/query/PathQueryNodeTest.java (revision 0) +++ src/test/java/org/apache/jackrabbit/core/query/PathQueryNodeTest.java (revision 0) @@ -0,0 +1,51 @@ +package org.apache.jackrabbit.core.query; + +import junit.framework.TestCase; + +import org.apache.jackrabbit.core.query.xpath.XPathQueryBuilder; +import org.apache.jackrabbit.name.NamespaceResolver; +import org.apache.jackrabbit.name.QName; + +public class PathQueryNodeTest extends TestCase { + + private static final NamespaceResolver JCR_RESOLVER = new NamespaceResolver() { + public String getJCRName(QName qName) { + return this.getPrefix(qName.getNamespaceURI()) + ":" + + qName.getLocalName(); + } + + public String getPrefix(String uri) { + return QName.NS_JCR_PREFIX; + } + + public QName getQName(String jcrName) { + return new QName(QName.NS_JCR_URI, + jcrName.substring(jcrName.indexOf(':'))); + } + + public String getURI(String prefix) { + return QName.NS_JCR_URI; + } + }; + + public void testNeedsSystemTree() throws Exception { + QueryRootNode queryRootNode = XPathQueryBuilder.createQuery("/jcr:root/*", JCR_RESOLVER); + assertTrue(queryRootNode.needsSystemTree()); + + queryRootNode = XPathQueryBuilder.createQuery("/jcr:root/test/*", JCR_RESOLVER); + assertFalse(queryRootNode.needsSystemTree()); + + queryRootNode = XPathQueryBuilder.createQuery("*", JCR_RESOLVER); + assertTrue(queryRootNode.needsSystemTree()); + + queryRootNode = XPathQueryBuilder.createQuery("jcr:system/*", JCR_RESOLVER); + assertTrue(queryRootNode.needsSystemTree()); + + queryRootNode = XPathQueryBuilder.createQuery("test//*", JCR_RESOLVER); + assertFalse(queryRootNode.needsSystemTree()); + + queryRootNode = XPathQueryBuilder.createQuery("//test/*", JCR_RESOLVER); + assertTrue(queryRootNode.needsSystemTree()); + } + +}