Return-Path: X-Original-To: apmail-jackrabbit-commits-archive@www.apache.org Delivered-To: apmail-jackrabbit-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 26FCE85D3 for ; Tue, 13 Sep 2011 14:42:09 +0000 (UTC) Received: (qmail 46066 invoked by uid 500); 13 Sep 2011 14:42:09 -0000 Delivered-To: apmail-jackrabbit-commits-archive@jackrabbit.apache.org Received: (qmail 46042 invoked by uid 500); 13 Sep 2011 14:42:09 -0000 Mailing-List: contact commits-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@jackrabbit.apache.org Delivered-To: mailing list commits@jackrabbit.apache.org Received: (qmail 46035 invoked by uid 99); 13 Sep 2011 14:42:09 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 13 Sep 2011 14:42:09 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 13 Sep 2011 14:42:03 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id ADF8723888EA; Tue, 13 Sep 2011 14:41:43 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1170199 - in /jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src: main/java/org/apache/jackrabbit/spi2microkernel/ test/java/org/apache/jackrabbit/spi2microkernel/ test/resources/ Date: Tue, 13 Sep 2011 14:41:43 -0000 To: commits@jackrabbit.apache.org From: thomasm@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110913144143.ADF8723888EA@eris.apache.org> Author: thomasm Date: Tue Sep 13 14:41:42 2011 New Revision: 1170199 URL: http://svn.apache.org/viewvc?rev=1170199&view=rev Log: Simple query processor Added: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryProcessor.java jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/QueryTest.java jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/resources/queryPlans.txt Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryInfoImpl.java jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryServiceImpl.java Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryInfoImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryInfoImpl.java?rev=1170199&r1=1170198&r2=1170199&view=diff ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryInfoImpl.java (original) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryInfoImpl.java Tue Sep 13 14:41:42 2011 @@ -18,47 +18,75 @@ */ package org.apache.jackrabbit.spi2microkernel; +import java.util.ArrayList; import javax.jcr.RangeIterator; import org.apache.jackrabbit.spi.Name; +import org.apache.jackrabbit.spi.NodeId; +import org.apache.jackrabbit.spi.QValue; import org.apache.jackrabbit.spi.QueryInfo; +import org.apache.jackrabbit.spi.QueryResultRow; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * A query result. */ public class QueryInfoImpl implements QueryInfo { + static final Logger log = LoggerFactory.getLogger(QueryInfoImpl.class); + + private final String[] columnNames; + private final Name[] selectorNames; + final ArrayList result = new ArrayList(); + + QueryInfoImpl(String[] columnNames, Name[] selectorNames) { + this.columnNames = columnNames; + this.selectorNames = selectorNames; + } + + void addRow(QueryResultRowImpl row) { + result.add(row); + } + @Override public String[] getColumnNames() { - return new String[0]; + return columnNames; + } + + @Override + public Name[] getSelectorNames() { + return selectorNames; } @Override public RangeIterator getRows() { return new RangeIterator() { + int pos = 0; + @Override public long getPosition() { - return 0; + return pos; } @Override public long getSize() { - return 0; + return result.size(); } @Override public void skip(long x) { - // ignore + pos += x; } @Override public boolean hasNext() { - return false; + return pos < result.size(); } @Override - public Object next() { - return null; + public QueryResultRow next() { + return result.get(pos++); } @Override @@ -69,9 +97,34 @@ public class QueryInfoImpl implements Qu }; } - @Override - public Name[] getSelectorNames() { - return new Name[0]; + static class QueryResultRowImpl implements QueryResultRow { + + private final NodeId node; + private final QValue[] values; + + QueryResultRowImpl(NodeId node, QValue[] values) { + this.node = node; + this.values = values; + } + + @Override + public NodeId getNodeId(Name selectorName) { + log.info("getNodeId " + selectorName); + return node; + } + + @Override + public double getScore(Name selectorName) { + log.info("getScore " + selectorName); + return 0.5; + } + + @Override + public QValue[] getValues() { + log.info("getValues"); + return values; + } + } } Added: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryProcessor.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryProcessor.java?rev=1170199&view=auto ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryProcessor.java (added) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QueryProcessor.java Tue Sep 13 14:41:42 2011 @@ -0,0 +1,230 @@ +/* + * 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.spi2microkernel; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.LineNumberReader; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; +import javax.jcr.RepositoryException; +import org.apache.jackrabbit.mk.api.MicroKernel; +import org.apache.jackrabbit.mk.index.Indexer; +import org.apache.jackrabbit.mk.index.PrefixIndex; +import org.apache.jackrabbit.mk.index.PropertyIndex; +import org.apache.jackrabbit.mk.util.PathUtils; +import org.apache.jackrabbit.spi.IdFactory; +import org.apache.jackrabbit.spi.ItemInfo; +import org.apache.jackrabbit.spi.Name; +import org.apache.jackrabbit.spi.NameFactory; +import org.apache.jackrabbit.spi.NodeId; +import org.apache.jackrabbit.spi.PropertyInfo; +import org.apache.jackrabbit.spi.QValue; +import org.apache.jackrabbit.spi.QValueFactory; +import org.apache.jackrabbit.spi.QueryInfo; +import org.apache.jackrabbit.spi.SessionInfo; +import org.apache.jackrabbit.spi.commons.name.NameFactoryImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A tool to run a list of hardcoded queries. + */ +public class QueryProcessor { + + static final Logger log = LoggerFactory.getLogger(QueryProcessor.class); + + final RepositoryServiceImpl rep; + final MicroKernel microKernel; + final Indexer indexer; + final IdFactory idFactory; + final QValueFactory vf; + + private final String QUERY_PLANS = "queryPlans.txt"; + private long lastModified; + + private ArrayList queryPlans = new ArrayList(); + private HashMap indexes = new HashMap(); + + public QueryProcessor(MicroKernel microKernel, Indexer indexer, RepositoryServiceImpl rep) throws RepositoryException { + this.rep = rep; + this.microKernel = microKernel; + this.indexer = indexer; + this.idFactory = rep.getIdFactory(); + this.vf = rep.getQValueFactory(); + } + + public String[] checkQueryStatement(String language, String statement, Map namespaces) { + log.info("checkQueryStatement " + language + " " + statement); + loadQueryPlans(); + return new String[0]; + } + + public QueryInfo executeQuery(SessionInfo sessionInfo, String statement, String language, + Map namespaces, long limit, long offset, Map values) throws RepositoryException { + loadQueryPlans(); + log.info("executeQuery " + language + " " + statement); + for (QueryPlan plan : queryPlans) { + if (plan.matches(language, statement)) { + log.info("using plan " + plan.toString()); + return plan.execute(sessionInfo); + } + } + log.warn("unknown query " + language + " " + statement); + return new QueryInfoImpl(new String[0], new Name[0]); + } + + private void loadQueryPlans() { + long last = new File(QUERY_PLANS).lastModified(); + if (queryPlans.size() != 0 && last == lastModified) { + return; + } + queryPlans.clear(); + try { + lastModified = last; + InputStream in; + if (new File(QUERY_PLANS).exists()) { + in = new FileInputStream(QUERY_PLANS); + } else { + in = getClass().getClassLoader().getResourceAsStream(QUERY_PLANS); + } + LineNumberReader r = new LineNumberReader(new InputStreamReader(in)); + while (true) { + String line = r.readLine(); + if (line == null) { + break; + } else if (line.startsWith("#")) { + continue; + } + if (line.equals("plan")) { + QueryPlan plan = new QueryPlan(); + plan.queryPattern = r.readLine().trim(); + String indexName = r.readLine().trim(); + plan.index = indexes.get(indexName); + plan.propertyValue = r.readLine().trim(); + plan.columnNames = r.readLine().trim().split(","); + plan.selectorNames = new Name[plan.columnNames.length]; + String[] sel = r.readLine().trim().split(","); + NameFactory f = NameFactoryImpl.getInstance(); + for (int i=0; i 1 ? f.create(s[0], s[1]) : f.create(s[0]); + plan.selectorNames[i] = n; + } + queryPlans.add(plan); + log.info("query plan " + plan.toString()); + } else if (line.equals("index")) { + Index index = new Index(); + index.name = r.readLine().trim(); + index.type = r.readLine().trim(); + index.unique = r.readLine().trim().equals("unique"); + if (!indexes.containsKey(index.name)) { + index.open(); + indexes.put(index.name, index); + log.info("index " + index); + } + } + } + r.close(); + } catch (IOException e) { + e.printStackTrace(); + log.warn("loadQueryPlans", e); + } + } + + class Index { + String name; + String type; + boolean unique; + PropertyIndex propertyIndex; + PrefixIndex prefixIndex; + + void open() throws IOException { + if (type.equals("propertyIndex")) { + propertyIndex = indexer.createPropertyIndex(name, unique); + } else if (type.equals("prefixIndex")) { + prefixIndex = indexer.createPrefixIndex(name); + } else { + throw new IOException("Invalid index type: " + type); + } + } + + public String toString() { + return name + " type:" + type + " unique:" + unique; + } + } + + class QueryPlan { + String queryPattern; + Index index; + String propertyValue; + String[] columnNames; + Name[] selectorNames; + + boolean matches(String language, String query) { + return query.trim().matches(queryPattern.trim()); + } + + public String toString() { + return queryPattern + " index:" + index.name + " columnNames:" + Arrays.toString(columnNames) + " propertyNames:" + Arrays.toString(selectorNames) + " propertyValue:" + propertyValue; + } + + public QueryInfo execute(SessionInfo sessionInfo) throws RepositoryException { + QueryInfoImpl result = new QueryInfoImpl(columnNames, selectorNames); + if (index.propertyIndex != null) { + String v = propertyValue.length() == 0 ? null : propertyValue; + Iterator paths = index.propertyIndex.getPaths(v, microKernel + .getHeadRevision()); + while (paths.hasNext()) { + String path = paths.next(); + path = path.substring(PathUtils.getNextSlash(path, 1)); + NodeId node = idFactory.createNodeId((String) null, Paths.stringToPath(path)); + log.info(" row: " + path + " " + node); + Iterator it = rep.getItemInfos(sessionInfo, node); + HashMap values = new HashMap(); + while (it.hasNext()) { + ItemInfo info = it.next(); + if (!info.denotesNode()) { + PropertyInfo p = (PropertyInfo) rep.getItemInfos(sessionInfo, + info.getId()).next(); + String propertyName = p.getPath().getLastElement().getName().toString(); + values.put(propertyName, p.getValues()[0]); + } + } + QValue[] valueList = new QValue[selectorNames.length]; + for (int i = 0; i < selectorNames.length; i++) { + Name selector = selectorNames[i]; + valueList[i] = values.get(selector.toString()); + } + QueryInfoImpl.QueryResultRowImpl row = new QueryInfoImpl.QueryResultRowImpl(node, valueList); + result.addRow(row); + } + } + return result; + } + + } + +} Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryServiceImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryServiceImpl.java?rev=1170199&r1=1170198&r2=1170199&view=diff ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryServiceImpl.java (original) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryServiceImpl.java Tue Sep 13 14:41:42 2011 @@ -189,6 +189,7 @@ public class RepositoryServiceImpl exten private final NodeTypeStore nodeTypeStore; private final String defaultWorkspace; private final String systemWorkspace; + private final QueryProcessor queryProcessor; public RepositoryServiceImpl(MicroKernel microKernel, Map parameters) throws RepositoryException { super(DESCRIPTORS, Collections.emptyMap(), new QNodeTypeDefinition[0]); @@ -215,6 +216,7 @@ public class RepositoryServiceImpl exten jcrUuidIndex = indexer.createPropertyIndex("{jcr}uuid", true); referenceIndex = indexer.createPrefixIndex(Values.typePrefix(PropertyType.REFERENCE)); weakReferenceIndex = indexer.createPrefixIndex(Values.typePrefix(PropertyType.WEAKREFERENCE)); + queryProcessor = new QueryProcessor(microKernel, indexer, this); } catch (MicroKernelException e) { throw new RepositoryException(e.getMessage(), e); @@ -877,17 +879,15 @@ public class RepositoryServiceImpl exten String language, Map namespaces) throws InvalidQueryException, RepositoryException { checkSessionInfo(sessionInfo); - log.warn("checkQueryStatement " + language + " " + statement); - return new String[0]; - // throw new UnsupportedRepositoryOperationException(); + return queryProcessor.checkQueryStatement(statement, language, namespaces); } public QueryInfo executeQuery(SessionInfo sessionInfo, String statement, String language, Map namespaces, long limit, long offset, Map values) throws RepositoryException { checkSessionInfo(sessionInfo); - log.warn("executeQuery " + language + " " + statement); - return new QueryInfoImpl(); + return queryProcessor.executeQuery(sessionInfo, statement, language, namespaces, limit, + offset, values); } } Added: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/QueryTest.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/QueryTest.java?rev=1170199&view=auto ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/QueryTest.java (added) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/QueryTest.java Tue Sep 13 14:41:42 2011 @@ -0,0 +1,112 @@ +/* + * 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.spi2microkernel; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import java.util.Collections; +import java.util.Iterator; +import javax.imageio.spi.ServiceRegistry; +import javax.jcr.Node; +import javax.jcr.NodeIterator; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.RepositoryFactory; +import javax.jcr.Session; +import javax.jcr.query.Query; +import javax.jcr.query.QueryResult; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +public class QueryTest { + private static final String BASE_URL = "fs:target/repository-test/repository"; + private static long counter = System.currentTimeMillis(); + + private Repository repository; + private Session session; + + private static String getMkUrl(boolean clean) { + // XXX: This is a workaround for the missing dispose of the + // microkernel from within the repository. + if (clean) { + counter++; + } + return BASE_URL + counter + (clean ? ";clean" : ""); + } + + @Before + public void setup() throws RepositoryException { + Session s = getSession(); + s.getWorkspace().getNamespaceRegistry().registerNamespace("test", "test"); + s.save(); + } + + @After + public void tearDown() { + if (session != null) { + session.logout(); + session = null; + } + } + + @Test + public void queryTest() throws RepositoryException { + Session s = getSession(); + Node test; + test = s.getRootNode().addNode("test"); + test.setProperty("test:vanityPath", "/a"); + test.setProperty("test:redirect", "/content/a"); + s.save(); + test = s.getRootNode().addNode("test2"); + test.setProperty("test:vanityPath", "/b"); + test.setProperty("test:redirect", "/content/a"); + s.save(); + Query q = s.getWorkspace().getQueryManager().createQuery( + "SELECT test:vanityPath, test:redirect FROM test:VanityPath", Query.JCR_SQL2); + QueryResult res = q.execute(); + NodeIterator it = res.getNodes(); + Node n = it.nextNode(); + assertEquals("/test", n.getPath()); + n = it.nextNode(); + assertEquals("/test2", n.getPath()); + } + + @Test + public void createRepository() throws RepositoryException { + Repository repository = getRepository(); + assertNotNull(repository); + } + + private Session getSession() throws RepositoryException { + if (session == null) { + session = getRepository().login(); + } + return session; + } + + private Repository getRepository() throws RepositoryException { + if (repository == null) { + Iterator factories = ServiceRegistry.lookupProviders(RepositoryFactory.class); + while (repository == null && factories.hasNext()) { + RepositoryFactory factory = factories.next(); + repository = factory.getRepository(Collections.singletonMap( + Spi2MicrokernelRepositoryServiceFactory.PARAM_URL, getMkUrl(false))); + } + } + + return repository; + } + +} Added: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/resources/queryPlans.txt URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/resources/queryPlans.txt?rev=1170199&view=auto ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/resources/queryPlans.txt (added) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/resources/queryPlans.txt Tue Sep 13 14:41:42 2011 @@ -0,0 +1,13 @@ +# vanity urls ====================== +index +{test}vanityPath +propertyIndex +nonUnique + +plan +SELECT test:vanityPath, test:redirect FROM test:VanityPath +{test}vanityPath + +testPath,redirect +test:vanityPath,test:redirect +