Index: jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/PathQueryNodeTest.java
===================================================================
--- jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/PathQueryNodeTest.java	(revision 563919)
+++ jackrabbit-core/src/test/java/org/apache/jackrabbit/core/query/PathQueryNodeTest.java	(working copy)
@@ -16,6 +16,8 @@
  */
 package org.apache.jackrabbit.core.query;
 
+import java.util.Arrays;
+
 import junit.framework.TestCase;
 
 import org.apache.jackrabbit.core.query.xpath.XPathQueryBuilder;
@@ -24,44 +26,60 @@
 
 public class PathQueryNodeTest extends TestCase {
 
+    private static final DefaultQueryNodeFactory QUERY_NODE_FACTORY = new DefaultQueryNodeFactory(
+            Arrays.asList(new QName[] { QName.NT_NODETYPE }));
+    
     private static final NamespaceResolver JCR_RESOLVER = new NamespaceResolver() {
         public String getJCRName(QName qName) {
-            return this.getPrefix(qName.getNamespaceURI()) + ":"
-                    + qName.getLocalName();
+            throw new UnsupportedOperationException();
         }
 
         public String getPrefix(String uri) {
-            return QName.NS_JCR_PREFIX;
+            throw new UnsupportedOperationException();
         }
 
         public QName getQName(String jcrName) {
-            return new QName(QName.NS_JCR_URI,
-                    jcrName.substring(jcrName.indexOf(':')));
+            throw new UnsupportedOperationException();
         }
 
         public String getURI(String prefix) {
-            return QName.NS_JCR_URI;
+            if (QName.NS_JCR_PREFIX.equals(prefix))
+                return QName.NS_JCR_URI;
+            if (QName.NS_NT_PREFIX.equals(prefix))
+                return QName.NS_NT_URI;
+            return "";
         }
     };    
     
     public void testNeedsSystemTree() throws Exception {
-        QueryRootNode queryRootNode = XPathQueryBuilder.createQuery("/jcr:root/*", JCR_RESOLVER);
+        QueryRootNode queryRootNode = XPathQueryBuilder.createQuery("/jcr:root/*", JCR_RESOLVER, QUERY_NODE_FACTORY);
         assertTrue(queryRootNode.needsSystemTree());
 
-        queryRootNode = XPathQueryBuilder.createQuery("/jcr:root/test/*", JCR_RESOLVER);
+        queryRootNode = XPathQueryBuilder.createQuery("/jcr:root/test/*", JCR_RESOLVER, QUERY_NODE_FACTORY);
         assertFalse(queryRootNode.needsSystemTree());
 
-        queryRootNode = XPathQueryBuilder.createQuery("*", JCR_RESOLVER);
+        queryRootNode = XPathQueryBuilder.createQuery("*", JCR_RESOLVER, QUERY_NODE_FACTORY);
         assertTrue(queryRootNode.needsSystemTree());
 
-        queryRootNode = XPathQueryBuilder.createQuery("jcr:system/*", JCR_RESOLVER);
+        queryRootNode = XPathQueryBuilder.createQuery("jcr:system/*", JCR_RESOLVER, QUERY_NODE_FACTORY);
         assertTrue(queryRootNode.needsSystemTree());
 
-        queryRootNode = XPathQueryBuilder.createQuery("test//*", JCR_RESOLVER);
+        queryRootNode = XPathQueryBuilder.createQuery("test//*", JCR_RESOLVER, QUERY_NODE_FACTORY);
         assertFalse(queryRootNode.needsSystemTree());
         
-        queryRootNode = XPathQueryBuilder.createQuery("//test/*", JCR_RESOLVER);
+        queryRootNode = XPathQueryBuilder.createQuery("//test/*", JCR_RESOLVER, QUERY_NODE_FACTORY);
         assertTrue(queryRootNode.needsSystemTree());         
     }
     
+    public void testNeedsSystemTreeForAllNodesByNodeType() throws Exception {
+        QueryRootNode queryRootNode = XPathQueryBuilder.createQuery("//element(*, nt:resource)", JCR_RESOLVER, QUERY_NODE_FACTORY);
+        assertFalse(queryRootNode.needsSystemTree());
+
+        queryRootNode = XPathQueryBuilder.createQuery("//element(*, nt:resource)[@jcr:test = 'foo']", JCR_RESOLVER, QUERY_NODE_FACTORY);
+        assertFalse(queryRootNode.needsSystemTree());
+
+        queryRootNode = XPathQueryBuilder.createQuery("//element(*, nt:nodeType)", JCR_RESOLVER, QUERY_NODE_FACTORY);
+        assertTrue(queryRootNode.needsSystemTree());
+    }
+
 }
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryNodeFactory.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryNodeFactory.java	(revision 0)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryNodeFactory.java	(revision 0)
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.query;
+
+import org.apache.jackrabbit.name.QName;
+
+/**
+ * A factory for {@link QueryNode}s.
+ */
+public interface QueryNodeFactory {
+
+    /**
+     * Creates a {@link NodeTypeQueryNode} instance.
+     *
+     * @param parent the parent node.
+     * @param nodeType the name of the node type.
+     * @return a {@link NodeTypeQueryNode}.
+     */
+    public NodeTypeQueryNode createNodeTypeQueryNode(
+            QueryNode parent, QName nodeType);
+
+    /**
+     * Creates a {@link AndQueryNode} instance.
+     *
+     * @param parent the parent node.
+     * @return a {@link AndQueryNode}.
+     */
+    public AndQueryNode createAndQueryNode(
+            QueryNode parent);
+
+    /**
+     * Creates a {@link LocationStepQueryNode} instance.
+     *
+     * @param parent the parent node.
+     * @return a {@link LocationStepQueryNode}.
+     */
+    public LocationStepQueryNode createLocationStepQueryNode(
+            QueryNode parent);
+
+    /**
+     * Creates a {@link DerefQueryNode} instance.
+     *
+     * @param parent the parent node.
+     * @param nameTest the name test on the referenced target node.
+     * @param descendants if the axis is //
+     * @return a {@link DerefQueryNode}.
+     */
+    public DerefQueryNode createDerefQueryNode(
+            QueryNode parent, QName nameTest, boolean descendants);
+
+    /**
+     * Creates a {@link NotQueryNode} instance.
+     *
+     * @param parent the parent node.
+     * @return a {@link NotQueryNode}.
+     */
+    public NotQueryNode createNotQueryNode(
+            QueryNode parent);
+
+    /**
+     * Creates a {@link OrQueryNode} instance.
+     *
+     * @param parent the parent node.
+     * @return a {@link OrQueryNode}.
+     */
+    public OrQueryNode createOrQueryNode(
+            QueryNode parent);
+
+    /**
+     * Creates a {@link RelationQueryNode} instance.
+     *
+     * @param parent the parent node.
+     * @param operation the operation type.
+     * @return a {@link RelationQueryNode}.
+     */
+    public RelationQueryNode createRelationQueryNode(
+            QueryNode parent, int operation);
+
+    /**
+     * Creates a {@link PathQueryNode} instance.
+     *
+     * @param parent the parent node.
+     * @return a {@link PathQueryNode}.
+     */
+    public PathQueryNode createPathQueryNode(
+            QueryNode parent);
+
+    /**
+     * Creates a {@link OrderQueryNode} instance.
+     *
+     * @param parent the parent node.
+     * @return a {@link OrderQueryNode}.
+     */
+    public OrderQueryNode createOrderQueryNode(
+            QueryNode parent);
+
+    /**
+     * Creates a {@link PropertyFunctionQueryNode} instance.
+     *
+     * @param parent the parent node.
+     * @param functionName the name of the function.
+     * @return a {@link PropertyFunctionQueryNode}.
+     */
+    public PropertyFunctionQueryNode createPropertyFunctionQueryNode(
+            QueryNode parent, String functionName);
+
+    /**
+     * Creates a {@link QueryRootNode} instance.
+     *
+     * @return a {@link QueryRootNode}.
+     */
+    public QueryRootNode createQueryRootNode();
+
+    /**
+     * Creates a {@link TextsearchQueryNode} instance.
+     *
+     * @param parent the parent node.
+     * @param query the textsearch statement.
+     * @return a {@link TextsearchQueryNode}.
+     */
+    public TextsearchQueryNode createTextsearchQueryNode(
+            QueryNode parent, String query);
+}
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/PathQueryNode.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/PathQueryNode.java	(revision 563919)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/PathQueryNode.java	(working copy)
@@ -16,6 +16,10 @@
  */
 package org.apache.jackrabbit.core.query;
 
+import java.util.Arrays;
+import java.util.List;
+import java.util.Collections;
+
 import org.apache.jackrabbit.name.QName;
 
 /**
@@ -29,17 +33,24 @@
     private boolean absolute = false;
 
     /**
+     * List of valid node type names under /jcr:system
+     */
+    private final List validJcrSystemNodeTypeNames;
+
+    /**
      * Empty step node array.
      */
     private static final LocationStepQueryNode[] EMPTY = new LocationStepQueryNode[0];
 
     /**
-     * Creates a relative <code>PathQueryNode</code> with no location steps.
+     * Creates a relative <code>PathQueryNode</code> with no location steps and
+     * the list of node types under /jcr:system.
      *
      * @param parent the parent query node.
      */
-    public PathQueryNode(QueryNode parent) {
+    public PathQueryNode(QueryNode parent, List validJcrSystemNodeTypeNames) {
         super(parent);
+        this.validJcrSystemNodeTypeNames = validJcrSystemNodeTypeNames;
     }
 
     /**
@@ -125,10 +136,23 @@
         }
 
         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)
+        if (firstPathStepName == null) {
+            // If the first operand of the path steps is a node type query
+            // we do not need to include the system index if the node type is
+            // none of the node types that may occur in the system index.
+            QueryNode[] pathStepOperands = pathSteps[0].getOperands();
+            if (pathStepOperands.length > 0) {
+                if (pathStepOperands[0] instanceof NodeTypeQueryNode) {
+                    NodeTypeQueryNode nodeTypeQueryNode = (NodeTypeQueryNode) pathStepOperands[0];
+                    if (!validJcrSystemNodeTypeNames.contains(nodeTypeQueryNode.getValue())) {
+                        return false;
+                    }
+                }
+            }
+            // If the first location step has a null name test we need to include
+            // the system tree ("*")
             return true;
+        }
         
         // Calculate the first workspace relative location step
         LocationStepQueryNode firstWorkspaceRelativeStep = pathSteps[0];
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java	(revision 566042)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/QueryImpl.java	(working copy)
@@ -30,6 +30,7 @@
 import org.apache.jackrabbit.core.query.QueryParser;
 import org.apache.jackrabbit.core.query.QueryRootNode;
 import org.apache.jackrabbit.core.query.AndQueryNode;
+import org.apache.jackrabbit.core.query.QueryNodeFactory;
 import org.apache.jackrabbit.name.QName;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -56,15 +57,8 @@
     /**
      * Represents a query that selects all nodes. E.g. in XPath: //*
      */
-    protected static final QueryRootNode ALL_NODES = new QueryRootNode();
+    protected final QueryRootNode allNodesQueryNode;
 
-    static {
-        PathQueryNode pathNode = new PathQueryNode(ALL_NODES);
-        pathNode.addPathStep(new LocationStepQueryNode(pathNode, null, true));
-        pathNode.setAbsolute(true);
-        ALL_NODES.setLocationNode(pathNode);
-    }
-
     /**
      * The root node of the query tree
      */
@@ -105,6 +99,7 @@
      * @param propReg   the property type registry.
      * @param statement the query statement.
      * @param language  the syntax of the query statement.
+     * @param factory   the query node factory.
      * @throws InvalidQueryException if the query statement is invalid according
      *                               to the specified <code>language</code>.
      */
@@ -113,14 +108,23 @@
                      SearchIndex index,
                      PropertyTypeRegistry propReg,
                      String statement,
-                     String language) throws InvalidQueryException {
+                     String language,
+                     QueryNodeFactory factory) throws InvalidQueryException {
         this.session = session;
         this.itemMgr = itemMgr;
         this.index = index;
         this.propReg = propReg;
         // parse query according to language
-        // build query tree
-        this.root = QueryParser.parse(statement, language, session.getNamespaceResolver());
+        // build query tree using the passed factory
+        this.root = QueryParser.parse(statement, language,
+                session.getNamespaceResolver(), factory);
+
+        allNodesQueryNode = new QueryRootNode();
+        PathQueryNode pathNode = factory.createPathQueryNode(allNodesQueryNode);
+        pathNode.addPathStep(new LocationStepQueryNode(pathNode, null, true));
+        pathNode.setAbsolute(true);
+        allNodesQueryNode.setLocationNode(pathNode);
+        
     }
 
     /**
@@ -137,7 +141,7 @@
         }
 
         // check for special query
-        if (ALL_NODES.equals(root)) {
+        if (allNodesQueryNode.equals(root)) {
             return new WorkspaceTraversalResult(session,
                     new QName[] { QName.JCR_PRIMARYTYPE, QName.JCR_PATH, QName.JCR_SCORE },
                     session.getNamespaceResolver());
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java	(revision 566639)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/lucene/SearchIndex.java	(working copy)
@@ -21,6 +21,7 @@
 import org.apache.jackrabbit.core.NodeId;
 import org.apache.jackrabbit.core.NodeIdIterator;
 import org.apache.jackrabbit.core.query.AbstractQueryHandler;
+import org.apache.jackrabbit.core.query.DefaultQueryNodeFactory;
 import org.apache.jackrabbit.core.query.ExecutableQuery;
 import org.apache.jackrabbit.core.query.QueryHandlerContext;
 import org.apache.jackrabbit.core.query.QueryHandler;
@@ -59,6 +60,7 @@
 import javax.xml.parsers.ParserConfigurationException;
 import java.io.IOException;
 import java.io.File;
+import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 import java.util.ArrayList;
@@ -74,6 +76,27 @@
  */
 public class SearchIndex extends AbstractQueryHandler {
 
+    public static final List VALID_SYSTEM_INDEX_NODE_TYPE_NAMES
+        = Collections.unmodifiableList(Arrays.asList(new QName[]{
+            QName.NT_CHILDNODEDEFINITION,
+            QName.NT_FROZENNODE,
+            QName.NT_NODETYPE,
+            QName.NT_PROPERTYDEFINITION,
+            QName.NT_VERSION,
+            QName.NT_VERSIONEDCHILD,
+            QName.NT_VERSIONHISTORY,
+            QName.NT_VERSIONLABELS,
+            QName.REP_NODETYPES,
+            QName.REP_SYSTEM,
+            QName.REP_VERSIONSTORAGE,
+            // Supertypes
+            QName.NT_BASE,
+            QName.MIX_REFERENCEABLE
+        }));
+
+    private static final DefaultQueryNodeFactory DEFAULT_QUERY_NODE_FACTORY = new DefaultQueryNodeFactory(
+            VALID_SYSTEM_INDEX_NODE_TYPE_NAMES);
+
     /** The logger instance for this class */
     private static final Logger log = LoggerFactory.getLogger(SearchIndex.class);
 
@@ -492,12 +515,20 @@
                                              String language)
             throws InvalidQueryException {
         QueryImpl query = new QueryImpl(session, itemMgr, this,
-                getContext().getPropertyTypeRegistry(), statement, language);
+                getContext().getPropertyTypeRegistry(), statement, language, getQueryNodeFactory());
         query.setRespectDocumentOrder(documentOrder);
         return query;
     }
 
     /**
+     * This method returns the QueryNodeFactory used to parse Queries. This method
+     * may be overridden to provide a customized QueryNodeFactory
+     */
+    protected DefaultQueryNodeFactory getQueryNodeFactory() {
+        return DEFAULT_QUERY_NODE_FACTORY;
+    }
+
+    /**
      * Closes this <code>QueryHandler</code> and frees resources attached
      * to this handler.
      */
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryTreeBuilder.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryTreeBuilder.java	(revision 563919)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryTreeBuilder.java	(working copy)
@@ -26,15 +26,19 @@
 public interface QueryTreeBuilder {
 
     /**
-     * Creates a <code>QueryNode</code> tree from a statement.
+     * Creates a <code>QueryNode</code> tree from a statement using the passed
+     * query node factory.
      *
      * @param statement the statement.
      * @param resolver  the namespace resolver to use.
+     * @param factory   the query node factory to use.
      * @return the <code>QueryNode</code> tree for the statement.
      * @throws javax.jcr.query.InvalidQueryException
      *          if the statement is malformed.
      */
-    QueryRootNode createQueryTree(String statement, NamespaceResolver resolver)
+    QueryRootNode createQueryTree(String statement,
+                                  NamespaceResolver resolver,
+                                  QueryNodeFactory factory)
             throws InvalidQueryException;
 
     /**
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/xpath/XPathQueryBuilder.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/xpath/XPathQueryBuilder.java	(revision 563919)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/xpath/XPathQueryBuilder.java	(working copy)
@@ -16,13 +16,11 @@
  */
 package org.apache.jackrabbit.core.query.xpath;
 
-import org.apache.jackrabbit.core.query.AndQueryNode;
 import org.apache.jackrabbit.core.query.DerefQueryNode;
 import org.apache.jackrabbit.core.query.LocationStepQueryNode;
 import org.apache.jackrabbit.core.query.NAryQueryNode;
 import org.apache.jackrabbit.core.query.NodeTypeQueryNode;
 import org.apache.jackrabbit.core.query.NotQueryNode;
-import org.apache.jackrabbit.core.query.OrQueryNode;
 import org.apache.jackrabbit.core.query.OrderQueryNode;
 import org.apache.jackrabbit.core.query.PathQueryNode;
 import org.apache.jackrabbit.core.query.QueryConstants;
@@ -32,6 +30,8 @@
 import org.apache.jackrabbit.core.query.TextsearchQueryNode;
 import org.apache.jackrabbit.core.query.PropertyFunctionQueryNode;
 import org.apache.jackrabbit.core.query.DefaultQueryNodeVisitor;
+import org.apache.jackrabbit.core.query.QueryNodeFactory;
+import org.apache.jackrabbit.core.query.DefaultQueryNodeFactory;
 import org.apache.jackrabbit.name.NameException;
 import org.apache.jackrabbit.name.NamespaceResolver;
 import org.apache.jackrabbit.name.NoPrefixDeclaredException;
@@ -223,7 +223,7 @@
     /**
      * The root <code>QueryNode</code>
      */
-    private final QueryRootNode root = new QueryRootNode();
+    private final QueryRootNode root;
 
     /**
      * The {@link NamespaceResolver} in use
@@ -241,15 +241,25 @@
     private Path.PathBuilder tmpRelPath;
 
     /**
+     * The query node factory.
+     */
+    private final QueryNodeFactory factory;
+
+    /**
      * Creates a new <code>XPathQueryBuilder</code> instance.
      *
      * @param statement the XPath statement.
      * @param resolver  the namespace resolver to use.
+     * @param factory   the query node factory.
      * @throws InvalidQueryException if the XPath statement is malformed.
      */
-    private XPathQueryBuilder(String statement, NamespaceResolver resolver)
+    private XPathQueryBuilder(String statement,
+                              NamespaceResolver resolver,
+                              QueryNodeFactory factory)
             throws InvalidQueryException {
         this.resolver = resolver;
+        this.factory = factory;
+        this.root = factory.createQueryRootNode();
         try {
             // create an XQuery statement because we're actually using an
             // XQuery parser.
@@ -291,17 +301,20 @@
     }
 
     /**
-     * Creates a <code>QueryNode</code> tree from a XPath statement.
+     * Creates a <code>QueryNode</code> tree from a XPath statement using the
+     * passed query node <code>factory</code>.
      *
      * @param statement the XPath statement.
      * @param resolver  the namespace resolver to use.
+     * @param factory   the query node factory.
      * @return the <code>QueryNode</code> tree for the XPath statement.
      * @throws InvalidQueryException if the XPath statement is malformed.
      */
     public static QueryRootNode createQuery(String statement,
-                                            NamespaceResolver resolver)
+                                            NamespaceResolver resolver,
+                                            QueryNodeFactory factory)
             throws InvalidQueryException {
-        return new XPathQueryBuilder(statement, resolver).getRootNode();
+        return new XPathQueryBuilder(statement, resolver, factory).getRootNode();
     }
 
     /**
@@ -365,7 +378,7 @@
                     } else if (queryNode.getType() == QueryNode.TYPE_NOT) {
                         // is null expression
                         RelationQueryNode isNull
-                                = new RelationQueryNode(queryNode,
+                                = factory.createRelationQueryNode(queryNode,
                                         RelationQueryNode.OPERATION_NULL);
                         applyRelativePath(isNull);
                         node.childrenAccept(this, isNull);
@@ -376,7 +389,7 @@
                     } else {
                         // not null expression
                         RelationQueryNode notNull =
-                                new RelationQueryNode(queryNode,
+                                factory.createRelationQueryNode(queryNode,
                                         RelationQueryNode.OPERATION_NOT_NULL);
                         applyRelativePath(notNull);
                         node.childrenAccept(this, notNull);
@@ -390,7 +403,7 @@
                         node.childrenAccept(this, queryNode);
                     } else {
                         // step within a predicate
-                        RelationQueryNode tmp = new RelationQueryNode(
+                        RelationQueryNode tmp = factory.createRelationQueryNode(
                                 null, RelationQueryNode.OPERATION_NOT_NULL);
                         node.childrenAccept(this, tmp);
                         if (tmpRelPath == null) {
@@ -434,7 +447,7 @@
                     String ntName = ((SimpleNode) node.jjtGetChild(0)).getValue();
                     try {
                         QName nt = NameFormat.parse(ntName, resolver);
-                        NodeTypeQueryNode nodeType = new NodeTypeQueryNode(loc, nt);
+                        NodeTypeQueryNode nodeType = factory.createNodeTypeQueryNode(loc, nt);
                         loc.addPredicate(nodeType);
                     } catch (NameException e) {
                         exceptions.add(new InvalidQueryException("Not a valid name: " + ntName));
@@ -443,14 +456,14 @@
                 break;
             case JJTOREXPR:
                 NAryQueryNode parent = (NAryQueryNode) queryNode;
-                QueryNode orQueryNode = new OrQueryNode(parent);
+                QueryNode orQueryNode = factory.createOrQueryNode(parent);
                 parent.addOperand(orQueryNode);
                 // traverse
                 node.childrenAccept(this, orQueryNode);
                 break;
             case JJTANDEXPR:
                 parent = (NAryQueryNode) queryNode;
-                QueryNode andQueryNode = new AndQueryNode(parent);
+                QueryNode andQueryNode = factory.createAndQueryNode(parent);
                 parent.addOperand(andQueryNode);
                 // traverse
                 node.childrenAccept(this, andQueryNode);
@@ -486,7 +499,7 @@
                 queryNode = createFunction(node, queryNode);
                 break;
             case JJTORDERBYCLAUSE:
-                root.setOrderNode(new OrderQueryNode(root));
+                root.setOrderNode(factory.createOrderQueryNode(root));
                 queryNode = root.getOrderNode();
                 node.childrenAccept(this, queryNode);
                 break;
@@ -561,7 +574,9 @@
         for (int i = 0; i < p.jjtGetNumChildren(); i++) {
             SimpleNode c = (SimpleNode) p.jjtGetChild(i);
             if (c == node) {
-                queryNode = new LocationStepQueryNode(parent, null, descendant);
+                queryNode = factory.createLocationStepQueryNode(parent);
+                queryNode.setNameTest(null);
+                queryNode.setIncludeDescendants(descendant);
                 parent.addOperand(queryNode);
                 break;
             }
@@ -670,7 +685,7 @@
             exceptions.add(new InvalidQueryException("Unsupported ComparisonExpr type:" + node.getValue()));
         }
 
-        final RelationQueryNode rqn = new RelationQueryNode(queryNode, type);
+        final RelationQueryNode rqn = factory.createRelationQueryNode(queryNode, type);
 
         // traverse
         node.childrenAccept(this, rqn);
@@ -699,7 +714,7 @@
      * @return the path qurey node
      */
     private PathQueryNode createPathQueryNode(SimpleNode node) {
-        root.setLocationNode(new PathQueryNode(root));
+        root.setLocationNode(factory.createPathQueryNode(root));
         node.childrenAccept(this, root.getLocationNode());
         return root.getLocationNode();
     }
@@ -746,7 +761,7 @@
             if (NameFormat.format(FN_NOT, resolver).equals(fName)
                     || NameFormat.format(FN_NOT_10, resolver).equals(fName)) {
                 if (queryNode instanceof NAryQueryNode) {
-                    QueryNode not = new NotQueryNode(queryNode);
+                    QueryNode not = factory.createNotQueryNode(queryNode);
                     ((NAryQueryNode) queryNode).addOperand(not);
                     // @todo is this needed?
                     queryNode = not;
@@ -791,7 +806,7 @@
                     if (queryNode instanceof NAryQueryNode) {
                         SimpleNode literal = (SimpleNode) node.jjtGetChild(2).jjtGetChild(0);
                         if (literal.getId() == JJTSTRINGLITERAL) {
-                            TextsearchQueryNode contains = new TextsearchQueryNode(
+                            TextsearchQueryNode contains = factory.createTextsearchQueryNode(
                                     queryNode, unescapeQuotes(literal.getValue()));
                             // assign property name
                             SimpleNode path = (SimpleNode) node.jjtGetChild(1);
@@ -809,7 +824,8 @@
                 // check number of arguments
                 if (node.jjtGetNumChildren() == 3) {
                     if (queryNode instanceof NAryQueryNode) {
-                        RelationQueryNode like = new RelationQueryNode(queryNode, RelationQueryNode.OPERATION_LIKE);
+                        RelationQueryNode like = factory.createRelationQueryNode(
+                                queryNode, RelationQueryNode.OPERATION_LIKE);
                         ((NAryQueryNode) queryNode).addOperand(like);
 
                         // assign property name
@@ -889,7 +905,7 @@
                     }
                     if (queryNode.getType() == QueryNode.TYPE_PATH) {
                         PathQueryNode pathNode = (PathQueryNode) queryNode;
-                        DerefQueryNode derefNode = new DerefQueryNode(pathNode, null, false);
+                        DerefQueryNode derefNode = factory.createDerefQueryNode(pathNode, null, false);
 
                         // assign property name
                         node.jjtGetChild(1).jjtAccept(this, derefNode);
@@ -944,7 +960,8 @@
                 if (node.jjtGetNumChildren() == 2) {
                     if (queryNode.getType() == QueryNode.TYPE_RELATION) {
                         RelationQueryNode relNode = (RelationQueryNode) queryNode;
-                        relNode.addOperand(new PropertyFunctionQueryNode(relNode, PropertyFunctionQueryNode.LOWER_CASE));
+                        relNode.addOperand(factory.createPropertyFunctionQueryNode(
+                                relNode, PropertyFunctionQueryNode.LOWER_CASE));
                         // get property name
                         node.jjtGetChild(1).jjtAccept(this, relNode);
                     } else {
@@ -957,7 +974,8 @@
                 if (node.jjtGetNumChildren() == 2) {
                     if (queryNode.getType() == QueryNode.TYPE_RELATION) {
                         RelationQueryNode relNode = (RelationQueryNode) queryNode;
-                        relNode.addOperand(new PropertyFunctionQueryNode(relNode, PropertyFunctionQueryNode.UPPER_CASE));
+                        relNode.addOperand(factory.createPropertyFunctionQueryNode(
+                                relNode, PropertyFunctionQueryNode.UPPER_CASE));
                         // get property name
                         node.jjtGetChild(1).jjtAccept(this, relNode);
                     } else {
@@ -970,7 +988,7 @@
                 if (node.jjtGetNumChildren() == 3) {
                     if (queryNode instanceof NAryQueryNode) {
                         NAryQueryNode parent = (NAryQueryNode) queryNode;
-                        RelationQueryNode rel = new RelationQueryNode(
+                        RelationQueryNode rel = factory.createRelationQueryNode(
                                 parent, RelationQueryNode.OPERATION_SIMILAR);
                         parent.addOperand(rel);
                         // assign path
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/xpath/QueryBuilder.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/xpath/QueryBuilder.java	(revision 563919)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/xpath/QueryBuilder.java	(working copy)
@@ -18,6 +18,7 @@
 
 import org.apache.jackrabbit.core.query.QueryTreeBuilder;
 import org.apache.jackrabbit.core.query.QueryRootNode;
+import org.apache.jackrabbit.core.query.QueryNodeFactory;
 import org.apache.jackrabbit.name.NamespaceResolver;
 
 import javax.jcr.query.InvalidQueryException;
@@ -32,9 +33,10 @@
      * @inheritDoc
      */
     public QueryRootNode createQueryTree(String statement,
-                                         NamespaceResolver resolver)
+                                         NamespaceResolver resolver,
+                                         QueryNodeFactory factory)
             throws InvalidQueryException {
-        return XPathQueryBuilder.createQuery(statement, resolver);
+        return XPathQueryBuilder.createQuery(statement, resolver, factory);
     }
 
     /**
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/DefaultQueryNodeFactory.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/DefaultQueryNodeFactory.java	(revision 0)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/DefaultQueryNodeFactory.java	(revision 0)
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jackrabbit.core.query;
+
+import java.util.List;
+
+import org.apache.jackrabbit.name.QName;
+
+/**
+ * Default implementetation of a {@link QueryNodeFactory}.
+ */
+public class DefaultQueryNodeFactory implements QueryNodeFactory {
+
+    /**
+     * List of valid node type names under /jcr:system
+     */
+    private final List validJcrSystemNodeTypeNames;
+
+    /**
+     * Creates a DefaultQueryNodeFactory with the given node types under
+     * /jcr:system .
+     */
+    public DefaultQueryNodeFactory(List validJcrSystemNodeTypeNames) {
+        super();
+        this.validJcrSystemNodeTypeNames = validJcrSystemNodeTypeNames;
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public NodeTypeQueryNode createNodeTypeQueryNode(QueryNode parent,
+                                                     QName nodeType) {
+        return new NodeTypeQueryNode(parent, nodeType);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public AndQueryNode createAndQueryNode(QueryNode parent) {
+        return new AndQueryNode(parent);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public LocationStepQueryNode createLocationStepQueryNode(QueryNode parent) {
+        return new LocationStepQueryNode(parent);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public DerefQueryNode createDerefQueryNode(QueryNode parent,
+                                               QName nameTest,
+                                               boolean descendants) {
+        return new DerefQueryNode(parent, nameTest, descendants);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public NotQueryNode createNotQueryNode(QueryNode parent) {
+        return new NotQueryNode(parent);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public OrQueryNode createOrQueryNode(QueryNode parent) {
+        return new OrQueryNode(parent);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public RelationQueryNode createRelationQueryNode(QueryNode parent,
+                                                     int operation) {
+        return new RelationQueryNode(parent, operation);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public PathQueryNode createPathQueryNode(QueryNode parent) {
+        return new PathQueryNode(parent, validJcrSystemNodeTypeNames);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public OrderQueryNode createOrderQueryNode(QueryNode parent) {
+        return new OrderQueryNode(parent);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public PropertyFunctionQueryNode createPropertyFunctionQueryNode(
+            QueryNode parent, String functionName) {
+        return new PropertyFunctionQueryNode(parent, functionName);
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public QueryRootNode createQueryRootNode() {
+        return new QueryRootNode();
+    }
+
+    /**
+     * {@inheritDoc}
+     */
+    public TextsearchQueryNode createTextsearchQueryNode(QueryNode parent,
+                                                         String query) {
+        return new TextsearchQueryNode(parent, query);
+    }
+}
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/sql/JCRSQLQueryBuilder.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/sql/JCRSQLQueryBuilder.java	(revision 563919)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/sql/JCRSQLQueryBuilder.java	(working copy)
@@ -30,6 +30,8 @@
 import org.apache.jackrabbit.core.query.RelationQueryNode;
 import org.apache.jackrabbit.core.query.TextsearchQueryNode;
 import org.apache.jackrabbit.core.query.PropertyFunctionQueryNode;
+import org.apache.jackrabbit.core.query.QueryNodeFactory;
+import org.apache.jackrabbit.core.query.DefaultQueryNodeFactory;
 import org.apache.jackrabbit.name.NameException;
 import org.apache.jackrabbit.name.NamespaceResolver;
 import org.apache.jackrabbit.name.QName;
@@ -74,7 +76,6 @@
      */
     private static Map parsers = new ReferenceMap(ReferenceMap.WEAK, ReferenceMap.WEAK);
 
-
     /**
      * The root node of the sql query syntax tree
      */
@@ -93,7 +94,7 @@
     /**
      * Query node to gather the constraints defined in the WHERE clause
      */
-    private final AndQueryNode constraintNode = new AndQueryNode(null);
+    private final AndQueryNode constraintNode;
 
     /**
      * The QName of the node type in the from clause.
@@ -106,26 +107,39 @@
     private final List pathConstraints = new ArrayList();
 
     /**
+     * The query node factory.
+     */
+    private final QueryNodeFactory factory;
+
+    /**
      * Creates a new <code>JCRSQLQueryBuilder</code>.
      *
      * @param statement the root node of the SQL syntax tree.
      * @param resolver  a namespace resolver to use for names in the
      *                  <code>statement</code>.
+     * @param factory   the query node factory.
      */
-    private JCRSQLQueryBuilder(ASTQuery statement, NamespaceResolver resolver) {
+    private JCRSQLQueryBuilder(ASTQuery statement,
+                               NamespaceResolver resolver,
+                               QueryNodeFactory factory) {
         this.stmt = statement;
         this.resolver = resolver;
+        this.factory = factory;
+        this.constraintNode =  factory.createAndQueryNode(null);
     }
 
     /**
-     * Creates a <code>QueryNode</code> tree from a SQL <code>statement</code>.
+     * Creates a <code>QueryNode</code> tree from a SQL <code>statement</code>
+     * using the passed query node <code>factory</code>.
      *
      * @param statement the SQL statement.
      * @param resolver  the namespace resolver to use.
      * @return the <code>QueryNode</code> tree.
      * @throws InvalidQueryException if <code>statement</code> is malformed.
      */
-    public static QueryRootNode createQuery(String statement, NamespaceResolver resolver)
+    public static QueryRootNode createQuery(String statement,
+                                            NamespaceResolver resolver,
+                                            QueryNodeFactory factory)
             throws InvalidQueryException {
         try {
             // get parser
@@ -143,7 +157,7 @@
             // guard against concurrent use within same session
             synchronized (parser) {
                 parser.ReInit(new StringReader(statement));
-                builder = new JCRSQLQueryBuilder(parser.Query(), resolver);
+                builder = new JCRSQLQueryBuilder(parser.Query(), resolver, factory);
             }
             return builder.getRootNode();
         } catch (ParseException e) {
@@ -191,8 +205,8 @@
     }
 
     public Object visit(ASTQuery node, Object data) {
-        root = new QueryRootNode();
-        root.setLocationNode(new PathQueryNode(root));
+        root = factory.createQueryRootNode();
+        root.setLocationNode(factory.createPathQueryNode(root));
 
         // pass to select, from, where, ...
         node.childrenAccept(this, root);
@@ -201,7 +215,10 @@
         PathQueryNode pathNode = root.getLocationNode();
         pathNode.setAbsolute(true);
         if (pathConstraints.size() == 0) {
-            pathNode.addPathStep(new LocationStepQueryNode(pathNode, null, true));
+            LocationStepQueryNode step = factory.createLocationStepQueryNode(pathNode);
+            step.setNameTest(null);
+            step.setIncludeDescendants(true);
+            pathNode.addPathStep(step);
         } else {
             try {
                 while (pathConstraints.size() > 1) {
@@ -231,7 +248,9 @@
             MergingPathQueryNode path = (MergingPathQueryNode) pathConstraints.get(0);
             LocationStepQueryNode[] steps = path.getPathSteps();
             for (int i = 0; i < steps.length; i++) {
-                LocationStepQueryNode step = new LocationStepQueryNode(pathNode, steps[i].getNameTest(), steps[i].getIncludeDescendants());
+                LocationStepQueryNode step = factory.createLocationStepQueryNode(pathNode);
+                step.setNameTest(steps[i].getNameTest());
+                step.setIncludeDescendants(steps[i].getIncludeDescendants());
                 step.setIndex(steps[i].getIndex());
                 pathNode.addPathStep(step);
             }
@@ -247,7 +266,7 @@
             // add node type constraint
             LocationStepQueryNode[] steps = pathNode.getPathSteps();
             NodeTypeQueryNode nodeType
-                    = new NodeTypeQueryNode(steps[steps.length - 1], nodeTypeName);
+                    = factory.createNodeTypeQueryNode(steps[steps.length - 1], nodeTypeName);
             steps[steps.length - 1].addPredicate(nodeType);
         }
 
@@ -351,7 +370,7 @@
             }
 
             if (type == QueryConstants.OPERATION_BETWEEN) {
-                AndQueryNode between = new AndQueryNode(parent);
+                AndQueryNode between = factory.createAndQueryNode(parent);
                 RelationQueryNode rel = createRelationQueryNode(between,
                         identifier, QueryConstants.OPERATION_GE_GENERAL, (ASTLiteral) node.children[1]);
                 node.childrenAccept(this, rel);
@@ -389,7 +408,7 @@
                         identifier, type, pattern);
                 node.childrenAccept(this, predicateNode);
             } else if (type == QueryConstants.OPERATION_IN) {
-                OrQueryNode in = new OrQueryNode(parent);
+                OrQueryNode in = factory.createOrQueryNode(parent);
                 for (int i = 1; i < node.children.length; i++) {
                     RelationQueryNode rel = createRelationQueryNode(in,
                             identifier, QueryConstants.OPERATION_EQ_VALUE, (ASTLiteral) node.children[i]);
@@ -424,7 +443,7 @@
 
     public Object visit(ASTOrExpression node, Object data) {
         NAryQueryNode parent = (NAryQueryNode) data;
-        OrQueryNode orQuery = new OrQueryNode(parent);
+        OrQueryNode orQuery = factory.createOrQueryNode(parent);
         // pass to operands
         node.childrenAccept(this, orQuery);
 
@@ -436,7 +455,7 @@
 
     public Object visit(ASTAndExpression node, Object data) {
         NAryQueryNode parent = (NAryQueryNode) data;
-        AndQueryNode andQuery = new AndQueryNode(parent);
+        AndQueryNode andQuery = factory.createAndQueryNode(parent);
         // pass to operands
         node.childrenAccept(this, andQuery);
 
@@ -446,7 +465,7 @@
 
     public Object visit(ASTNotExpression node, Object data) {
         NAryQueryNode parent = (NAryQueryNode) data;
-        NotQueryNode notQuery = new NotQueryNode(parent);
+        NotQueryNode notQuery = factory.createNotQueryNode(parent);
         // pass to operand
         node.childrenAccept(this, notQuery);
 
@@ -474,7 +493,7 @@
     public Object visit(ASTOrderByClause node, Object data) {
         QueryRootNode root = (QueryRootNode) data;
 
-        OrderQueryNode order = new OrderQueryNode(root);
+        OrderQueryNode order = factory.createOrderQueryNode(root);
         root.setOrderNode(order);
         node.childrenAccept(this, order);
         return root;
@@ -521,7 +540,10 @@
                 builder.addLast(node.getPropertyName());
                 relPath = builder.getPath();
             }
-            parent.addOperand(new TextsearchQueryNode(parent, node.getQuery(), relPath, true));
+            TextsearchQueryNode tsNode = factory.createTextsearchQueryNode(parent, node.getQuery());
+            tsNode.setRelativePath(relPath);
+            tsNode.setReferencesProperty(true);
+            parent.addOperand(tsNode);
         } catch (MalformedPathException e) {
             // path is always valid
         }
@@ -534,7 +556,7 @@
             String msg = "LOWER() function is only supported for String literal";
             throw new IllegalArgumentException(msg);
         }
-        parent.addOperand(new PropertyFunctionQueryNode(parent, PropertyFunctionQueryNode.LOWER_CASE));
+        parent.addOperand(factory.createPropertyFunctionQueryNode(parent, PropertyFunctionQueryNode.LOWER_CASE));
         return parent;
     }
 
@@ -544,7 +566,7 @@
             String msg = "UPPER() function is only supported for String literal";
             throw new IllegalArgumentException(msg);
         }
-        parent.addOperand(new PropertyFunctionQueryNode(parent, PropertyFunctionQueryNode.UPPER_CASE));
+        parent.addOperand(factory.createPropertyFunctionQueryNode(parent, PropertyFunctionQueryNode.UPPER_CASE));
         return parent;
     }
 
@@ -585,18 +607,28 @@
             if (literal.getType() == QueryConstants.TYPE_DATE) {
                 SimpleDateFormat format = new SimpleDateFormat(DATE_PATTERN);
                 Date date = format.parse(stringValue);
-                node = new RelationQueryNode(parent, relPath, date, operationType);
+                node = factory.createRelationQueryNode(parent, operationType);
+                node.setRelativePath(relPath);
+                node.setDateValue(date);
             } else if (literal.getType() == QueryConstants.TYPE_DOUBLE) {
                 double d = Double.parseDouble(stringValue);
-                node = new RelationQueryNode(parent, relPath, d, operationType);
+                node = factory.createRelationQueryNode(parent, operationType);
+                node.setRelativePath(relPath);
+                node.setDoubleValue(d);
             } else if (literal.getType() == QueryConstants.TYPE_LONG) {
                 long l = Long.parseLong(stringValue);
-                node = new RelationQueryNode(parent, relPath, l, operationType);
+                node = factory.createRelationQueryNode(parent, operationType);
+                node.setRelativePath(relPath);
+                node.setLongValue(l);
             } else if (literal.getType() == QueryConstants.TYPE_STRING) {
-                node = new RelationQueryNode(parent, relPath, stringValue, operationType);
+                node = factory.createRelationQueryNode(parent, operationType);
+                node.setRelativePath(relPath);
+                node.setStringValue(stringValue);
             } else if (literal.getType() == QueryConstants.TYPE_TIMESTAMP) {
                 Calendar c = ISO8601.parse(stringValue);
-                node = new RelationQueryNode(parent, relPath, c.getTime(), operationType);
+                node = factory.createRelationQueryNode(parent, operationType);
+                node.setRelativePath(relPath);
+                node.setDateValue(c.getTime());
             }
         } catch (java.text.ParseException e) {
             throw new IllegalArgumentException(e.toString());
@@ -624,7 +656,7 @@
         pathNode.setAbsolute(true);
 
         if (path.equals("/")) {
-            pathNode.addPathStep(new LocationStepQueryNode(pathNode));
+            pathNode.addPathStep(factory.createLocationStepQueryNode(pathNode));
             pathConstraints.add(pathNode);
             return;
         }
@@ -635,13 +667,13 @@
             if (names[i].length() == 0) {
                 if (i == 0) {
                     // root
-                    pathNode.addPathStep(new LocationStepQueryNode(pathNode));
+                    pathNode.addPathStep(factory.createLocationStepQueryNode(pathNode));
                 } else {
                     // descendant '//' -> invalid path
                     // todo throw or ignore?
                     // we currently do not throw and add location step for an
                     // empty name (which is basically the root node)
-                    pathNode.addPathStep(new LocationStepQueryNode(pathNode));
+                    pathNode.addPathStep(factory.createLocationStepQueryNode(pathNode));
                 }
             } else {
                 int idx = names[i].indexOf('[');
@@ -686,7 +718,9 @@
                 }
                 // if name test is % this means also search descendants
                 boolean descendant = name == null;
-                LocationStepQueryNode step = new LocationStepQueryNode(pathNode, qName, descendant);
+                LocationStepQueryNode step = factory.createLocationStepQueryNode(pathNode);
+                step.setNameTest(qName);
+                step.setIncludeDescendants(descendant);
                 if (index > 0) {
                     step.setIndex(index);
                 }
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/sql/QueryBuilder.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/sql/QueryBuilder.java	(revision 563919)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/sql/QueryBuilder.java	(working copy)
@@ -18,6 +18,7 @@
 
 import org.apache.jackrabbit.core.query.QueryTreeBuilder;
 import org.apache.jackrabbit.core.query.QueryRootNode;
+import org.apache.jackrabbit.core.query.QueryNodeFactory;
 import org.apache.jackrabbit.name.NamespaceResolver;
 
 import javax.jcr.query.InvalidQueryException;
@@ -32,9 +33,10 @@
      * @inheritDoc
      */
     public QueryRootNode createQueryTree(String statement,
-                                         NamespaceResolver resolver)
+                                         NamespaceResolver resolver,
+                                         QueryNodeFactory factory)
             throws InvalidQueryException {
-        return JCRSQLQueryBuilder.createQuery(statement, resolver);
+        return JCRSQLQueryBuilder.createQuery(statement, resolver, factory);
     }
 
     /**
Index: jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryParser.java
===================================================================
--- jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryParser.java	(revision 563919)
+++ jackrabbit-core/src/main/java/org/apache/jackrabbit/core/query/QueryParser.java	(working copy)
@@ -41,17 +41,19 @@
      *
      * @param statement the query statement.
      * @param language  the language of the query statement.
+     * @param factory   the query node factory.
      * @return the root node of the generated query tree.
      * @throws InvalidQueryException if an error occurs while parsing the
      *                               statement.
      */
     public static QueryRootNode parse(String statement,
                                       String language,
-                                      NamespaceResolver resolver)
+                                      NamespaceResolver resolver,
+                                      QueryNodeFactory factory)
             throws InvalidQueryException {
 
         QueryTreeBuilder builder = QueryTreeBuilderRegistry.getQueryTreeBuilder(language);
-        return builder.createQueryTree(statement, resolver);
+        return builder.createQueryTree(statement, resolver, factory);
     }
 
     /**
