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 5A97581E1 for ; Thu, 18 Aug 2011 18:10:44 +0000 (UTC) Received: (qmail 20324 invoked by uid 500); 18 Aug 2011 18:10:44 -0000 Delivered-To: apmail-jackrabbit-commits-archive@jackrabbit.apache.org Received: (qmail 20184 invoked by uid 500); 18 Aug 2011 18:10:43 -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 20176 invoked by uid 99); 18 Aug 2011 18:10:43 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 18 Aug 2011 18:10:43 +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; Thu, 18 Aug 2011 18:10:40 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 1876E23889E5; Thu, 18 Aug 2011 18:10:18 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1159334 - in /jackrabbit/sandbox/jackrabbit-mk: jackrabbit-jcr-commons/ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/jackrabbit/ jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/jackrabbit/user/ jack... Date: Thu, 18 Aug 2011 18:10:17 -0000 To: commits@jackrabbit.apache.org From: mduerig@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110818181018.1876E23889E5@eris.apache.org> Author: mduerig Date: Thu Aug 18 18:10:16 2011 New Revision: 1159334 URL: http://svn.apache.org/viewvc?rev=1159334&view=rev Log: Microkernel based Jackrabbit prototype (WIP) - cleanup: typos, redundant declarations etc. Added: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/jackrabbit/ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/jackrabbit/user/ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/jackrabbit/user/AuthorizableQueryManager.java Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr-commons/pom.xml jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/Jcr2spiRepositoryFactory.java jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QBinaryValue.java jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryFactoryImpl.java jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryServiceImpl.java jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/SubscriptionImpl.java jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/util/Values.java jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/resources/org/apache/jackrabbit/spi2microkernel/default-nodetypes.cnd jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/MicrokernelTest.java jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/RepositoryTest.java jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/tck/RepositoryStubImpl.java jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/tck/TestContentLoader.java jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/util/Loop.java Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr-commons/pom.xml URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr-commons/pom.xml?rev=1159334&r1=1159333&r2=1159334&view=diff ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr-commons/pom.xml (original) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr-commons/pom.xml Thu Aug 18 18:10:16 2011 @@ -59,6 +59,18 @@ javax.jcr jcr + + + org.apache.jackrabbit + jackrabbit-api + 2.3-SNAPSHOT + true + junit junit Added: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/jackrabbit/user/AuthorizableQueryManager.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/jackrabbit/user/AuthorizableQueryManager.java?rev=1159334&view=auto ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/jackrabbit/user/AuthorizableQueryManager.java (added) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr-commons/src/main/java/org/apache/jackrabbit/commons/jackrabbit/user/AuthorizableQueryManager.java Thu Aug 18 18:10:16 2011 @@ -0,0 +1,745 @@ +/* + * 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.commons.jackrabbit.user; + +import org.apache.jackrabbit.api.security.user.Authorizable; +import org.apache.jackrabbit.api.security.user.Group; +import org.apache.jackrabbit.api.security.user.Query; +import org.apache.jackrabbit.api.security.user.QueryBuilder; +import org.apache.jackrabbit.api.security.user.User; +import org.apache.jackrabbit.api.security.user.UserManager; +import org.apache.jackrabbit.commons.json.JsonHandler; +import org.apache.jackrabbit.commons.json.JsonParser; + +import javax.jcr.RepositoryException; +import javax.jcr.Value; +import javax.jcr.ValueFactory; +import java.io.IOException; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Stack; + +/** + * This class handles the translation of queries for users and groups from a + * JSON format to the query model of Jackrabbit's user groups search + * (see {@link org.apache.jackrabbit.api.security.user.UserManager#findAuthorizables(org.apache.jackrabbit.api.security.user.Query) + * UserManager#findAuthorizables(Query)}). + * + * The JSON query format is defined as follows: + *
+{
+  ( selector: "authorizable" | "user" | "group" )?        // Defaults to "authorizable", see QueryBuilder#setSelector()
+
+  (
+    scope:                                                // See QueryBuilder#setScope()
+    {
+      groupName: /* group name (String) * /
+      ( declaredOnly: true | false )                      // Defaults to true
+    }
+  ) ?                                                     // Defaults to all
+
+  ( condition: [ CONJUNCTION+ ] ) ?                       // Defaults to a 'true' condition, see QueryBuilder#setCondition()
+
+  (
+    order | sort:                                         // See QueryBuilder#setOrder()
+    {
+      property: /* relative path (String) * /
+      ( direction: "asc" | "desc" )                       // Defaults to "asc"
+    }
+  ) ?                                                     // Defaults to document order
+
+  (
+    limit:                                                // See QueryBuilder#setLimit()
+    {
+      offset: /* Positive Integer * /                     // Takes precedence over bound if both are given
+      bound:  /* String, Number, Boolean * /
+      max:    /* Positive Integer or -1 * /               // Defaults to no limit (-1)
+    }
+  ) ?                                                     // Defaults to all
+}
+
+CONJUNCTION ::= COMPOUND | PRIMITIVE
+COMPOUND    ::= [ PRIMITIVE+ ]
+PRIMITIVE   ::= { ATOM | NEGATION }
+NEGATION    ::= not: { ATOM }                             // See QueryBuilder#not()
+ATOM        ::= named: /* pattern * /                     // Users, groups of that name. See QueryBuilder#nameMatches()
+            |   exists: /* relative path * /              // See QueryBuilder#exists()
+            |   impersonates: /* authorizable name * /    // See QueryBuilder#impersonates()
+            |   RELOP:
+                {
+                  property: /* relative path * /
+                  value: /* String, Number, Boolean * /   // According to the type of the property
+                }
+            |   like:                                     // See QueryBuilder#like()
+                {
+                  property: /* relative path * /
+                  pattern: /* pattern * /
+                }
+            |   contains:                                 // See QueryBuilder#contains()
+                {
+                  property: /* relative path * /
+                  expression: /* search expression * /
+                }
+RELOP       ::= neq | eq | lt | le | gt | ge              // See QueryBuilder#neq(), QueryBuilder#eq(), ...
+
+ * + *
    + *
  • A relative path refers to a property or a child node of an user or a group. Property names need to be + * prefixed with the at (@) character. Invalid JCR characters need proper escaping. The current path is denoted + * by a dot (.).
  • + *
  • In a 'pattern' the percent character (%) represents any string of zero or more characters and the underscore + * character (_) represents any single character. Any literal use of these characters and the backslash + * character (\) must be escaped with a backslash character. The pattern is matched against + * Authorizable#getID() and Authorizable#getPrincipal().
  • + *
  • The syntax of 'expression' is [-]value { [OR] [-]value }.
  • + *
+ */ +public class AuthorizableQueryManager { + + /** + * Constant defining the default maximal size of the result set. + */ + public static final int MAX_RESULT_COUNT = 2000; + + private final UserManager userManager; + private final ValueFactory valueFactory; + + public AuthorizableQueryManager(UserManager userManager, ValueFactory valueFactory) { + this.userManager = userManager; + this.valueFactory = valueFactory; + } + + public Iterator execute(final String query) throws RepositoryException, IOException { + try { + return userManager.findAuthorizables(new Query() { + public void build(QueryBuilder builder) { + try { + // Must request more than MAX_RESULT_COUNT records explicitly + builder.setLimit(0, MAX_RESULT_COUNT); + new QueryTranslator(builder).translate(query); + } catch (IOException e) { + throw new IllegalArgumentException(e); + } + } + }); + } catch (IllegalArgumentException e) { + Throwable cause = e.getCause(); + if (cause instanceof IOException) { + throw (IOException) cause; + } else { + throw e; + } + } + } + + //------------------------------------------------------------< private >--- + + private class QueryTranslator implements JsonHandler { + private final QueryBuilder queryBuilder; + private final Stack handlers = new Stack(); + + public QueryTranslator(QueryBuilder queryBuilder) { + this.queryBuilder = queryBuilder; + handlers.push(new HandlerBase() { + @Override + public void object() { + handlers.push(new ClausesHandler()); + } + }); + } + + public void translate(String query) throws IOException { + new JsonParser(this).parse(query); + if (handlers.size() != 1) { + throw new IOException("Missing closing parenthesis"); + } + } + + public void object() throws IOException { + handlers.peek().object(); + } + + public void endObject() throws IOException { + handlers.peek().endObject(); + } + + public void array() throws IOException { + handlers.peek().array(); + } + + public void endArray() throws IOException { + handlers.peek().endArray(); + } + + public void key(String s) throws IOException { + handlers.peek().key(s); + } + + public void value(String s) throws IOException { + handlers.peek().value(s); + } + + public void value(boolean b) throws IOException { + handlers.peek().value(b); + } + + public void value(long l) throws IOException { + handlers.peek().value(l); + } + + public void value(double v) throws IOException { + handlers.peek().value(v); + } + + private Value valueFor(String s) { + return valueFactory.createValue(s); + } + + private Value valueFor(boolean b) { + return valueFactory.createValue(b); + } + + private Value valueFor(long l) { + return valueFactory.createValue(l); + } + + private Value valueFor(double v) { + return valueFactory.createValue(v); + } + + //----------------------------------------------------< HandlerBase >--- + + private class HandlerBase implements JsonHandler { + + public void object() throws IOException { + throw new IOException("Syntax error: '{'"); + } + + public void endObject() throws IOException { + throw new IOException("Syntax error: '}'"); + } + + public void array() throws IOException { + throw new IOException("Syntax error: '['"); + } + + public void endArray() throws IOException { + throw new IOException("Syntax error: ']'"); + } + + public void key(String s) throws IOException { + throw new IOException("Syntax error: key '" + s + '\''); + } + + public void value(String s) throws IOException { + throw new IOException("Syntax error: string '" + s + '\''); + } + + public void value(boolean b) throws IOException { + throw new IOException("Syntax error: boolean '" + b + '\''); + } + + public void value(long l) throws IOException { + throw new IOException("Syntax error: long '" + l + '\''); + } + + public void value(double v) throws IOException { + throw new IOException("Syntax error: double '" + v + '\''); + } + } + + //-------------------------------------------------< ClausesHandler >--- + + private class ClausesHandler extends HandlerBase { + private String currentKey; + + @Override + public void object() throws IOException { + handlers.push(handlerFor(currentKey)); + } + + @Override + public void endObject() throws IOException { + handlers.pop(); + } + + @Override + public void array() throws IOException { + handlers.push(handlerFor(currentKey)); + } + + @Override + public void endArray() throws IOException { + handlers.pop(); + } + + @Override + public void key(String s) throws IOException { + currentKey = s; + } + + @Override + public void value(String s) throws IOException { + if ("selector".equals(currentKey)) { + queryBuilder.setSelector(selectorFor(s)); + } else { + throw new IOException("String value '" + s + "' is invalid for '" + currentKey + '\''); + } + } + + private Class selectorFor(String selector) throws IOException { + if ("user".equals(selector)) { + return User.class; + } else if ("group".equals(selector)) { + return Group.class; + } else if ("authorizable".equals(selector)) { + return Authorizable.class; + } else { + throw new IOException("Invalid selector '" + selector + '\''); + } + } + + private JsonHandler handlerFor(String key) throws IOException { + if ("scope".equals(key)) { + return new ScopeHandler(); + } else if ("condition".equals(key)) { + return new ConditionHandler(); + } else if ("order".equals(key) || "sort".equals(key)) { + return new OrderHandler(); + } else if ("limit".equals(key)) { + return new LimitHandler(); + } else { + throw new IOException("Invalid clause '" + key + '\''); + } + } + } + + //---------------------------------------------------< ScopeHandler >--- + + private class ScopeHandler extends HandlerBase { + private String currentKey; + private String groupName; + private Boolean declaredOnly; + + @Override + public void endObject() throws IOException { + if (groupName == null) { + throw new IOException("Missing groupName"); + } else { + queryBuilder.setScope(groupName, declaredOnly == null ? true : declaredOnly); + } + handlers.pop(); + } + + @Override + public void key(String s) throws IOException { + currentKey = s; + } + + @Override + public void value(String s) throws IOException { + if ("groupName".equals(currentKey)) { + groupName = s; + } else { + throw new IOException("Unexpected: '" + currentKey + ':' + s + '\''); + } + } + + @Override + public void value(boolean b) throws IOException { + if ("declaredOnly".equals(currentKey)) { + declaredOnly = b; + } else { + throw new IOException("Unexpected: '" + currentKey + ':' + b + '\''); + } + } + } + + //-----------------------------------------------< ConditionHandler >--- + + private class ConditionHandler extends HandlerBase { + private final List memberHandlers = new ArrayList(); + + @Override + public void object() throws IOException { + PrimitiveHandler memberHandler = new PrimitiveHandler(); + memberHandlers.add(memberHandler); + handlers.push(memberHandler); + } + + @Override + public void array() throws IOException { + CompoundHandler memberHandler = new CompoundHandler(); + memberHandlers.add(memberHandler); + handlers.push(memberHandler); + } + + @Override + public void endArray() throws IOException { + if (memberHandlers.isEmpty()) { + throw new IOException("Empty search term"); + } + + Iterator memberHandler = memberHandlers.iterator(); + T condition = memberHandler.next().getCondition(); + while (memberHandler.hasNext()) { + condition = queryBuilder.and(condition, memberHandler.next().getCondition()); + } + + queryBuilder.setCondition(condition); + + handlers.pop(); + } + + } + + //--------------------------------------------------< ConditionBase >--- + + private abstract class ConditionBase extends HandlerBase { + public abstract T getCondition(); + } + + //------------------------------------------------< CompoundHandler >--- + + private class CompoundHandler extends ConditionBase { + private final List memberHandlers = new ArrayList(); + + @Override + public void object() throws IOException { + PrimitiveHandler memberHandler = new PrimitiveHandler(); + memberHandlers.add(memberHandler); + handlers.push(memberHandler); + } + + @Override + public void endArray() throws IOException { + if (memberHandlers.isEmpty()) { + throw new IOException("Empty search term"); + } + + handlers.pop(); + } + + @Override + public T getCondition() { + Iterator memberHandler = memberHandlers.iterator(); + T condition = memberHandler.next().getCondition(); + while (memberHandler.hasNext()) { + condition = queryBuilder.or(condition, memberHandler.next().getCondition()); + } + + return condition; + } + } + + //-----------------------------------------------< PrimitiveHandler >--- + + private class PrimitiveHandler extends ConditionBase { + private String currentKey; + private ConditionBase relOp; + private ConditionBase not; + private T condition; + + @Override + public void object() throws IOException { + if (hasCondition()) { + throw new IOException("Condition on '" + currentKey + "' not allowed since another " + + "condition is already set"); + } + + if ("not".equals(currentKey)) { + not = new PrimitiveHandler(); + handlers.push(not); + } else { + relOp = new RelOpHandler(currentKey); + handlers.push(relOp); + } + } + + @Override + public void endObject() throws IOException { + if (!hasCondition()) { + throw new IOException("Missing term"); + } + + if (relOp != null) { + condition = relOp.getCondition(); + } else if (condition == null) { + condition = queryBuilder.not(not.getCondition()); + } + + handlers.pop(); + } + + @Override + public void key(String s) throws IOException { + currentKey = s; + } + + @Override + public void value(String s) throws IOException { + if (hasCondition()) { + throw new IOException("Condition on '" + currentKey + "' not allowed since another " + + "condition is already set"); + } + + if ("named".equals(currentKey)) { + condition = queryBuilder.nameMatches(s); + } else if ("exists".equals(currentKey)) { + condition = queryBuilder.exists(s); + } else if ("impersonates".equals(currentKey)) { + condition = queryBuilder.impersonates(s); + } else { + throw new IOException("Invalid condition '" + currentKey + '\''); + } + } + + private boolean hasCondition() { + return condition != null || relOp != null || not != null; + } + + @Override + public T getCondition() { + return condition; + } + } + + //---------------------------------------------------< RelOpHandler >--- + + private class RelOpHandler extends ConditionBase { + private final String op; + + private String currentKey; + private String property; + private String pattern; + private String expression; + private Value value; + private T condition; + + public RelOpHandler(String op) { + this.op = op; + } + + @Override + public void endObject() throws IOException { + if (property == null) { + throw new IOException("Property not set for condition '" + op + '\''); + } + + if ("like".equals(op)) { + if (pattern == null) { + throw new IOException("Pattern not set for 'like' condition"); + } + condition = queryBuilder.like(property, pattern); + } else if ("contains".equals(op)) { + if (expression == null) { + throw new IOException("Expression not set for 'contains' condition"); + } + condition = queryBuilder.contains(property, expression); + } else { + if (value == null) { + throw new IOException("Value not set for '" + op + "' condition"); + } + + if ("eq".equals(op)) { + condition = queryBuilder.eq(property, value); + } else if ("neq".equals(op)) { + condition = queryBuilder.neq(property, value); + } else if ("lt".equals(op)) { + condition = queryBuilder.lt(property, value); + } else if ("le".equals(op)) { + condition = queryBuilder.le(property, value); + } else if ("ge".equals(op)) { + condition = queryBuilder.ge(property, value); + } else if ("gt".equals(op)) { + condition = queryBuilder.gt(property, value); + } else { + throw new IOException("Invalid condition: '" + op + '\''); + } + } + + handlers.pop(); + } + + @Override + public void key(String s) throws IOException { + currentKey = s; + } + + @Override + public void value(String s) throws IOException { + if ("property".equals(currentKey)) { + property = s; + } else if ("pattern".equals(currentKey)) { + pattern = s; + } else if ("expression".equals(currentKey)) { + expression = s; + } else if ("value".equals(currentKey)) { + value = valueFor(s); + } else { + throw new IOException("Expected one of 'property', 'pattern', 'expression', 'value' " + + "but found '" + currentKey + '\''); + } + } + + @Override + public void value(boolean b) throws IOException { + if ("value".equals(currentKey)) { + value = valueFor(b); + } else { + throw new IOException("Expected 'value', found '" + currentKey + '\''); + } + } + + @Override + public void value(long l) throws IOException { + if ("value".equals(currentKey)) { + value = valueFor(l); + } else { + throw new IOException("Expected 'value', found '" + currentKey + '\''); + } + } + + @Override + public void value(double v) throws IOException { + if ("value".equals(currentKey)) { + value = valueFor(v); + } else { + throw new IOException("Expected 'value', found '" + currentKey + '\''); + } + } + + @Override + public T getCondition() { + return condition; + } + } + + //---------------------------------------------------< OrderHandler >--- + + private class OrderHandler extends HandlerBase { + private String currentKey; + private String property; + private QueryBuilder.Direction direction; + + @Override + public void endObject() throws IOException { + if (property == null) { + throw new IOException("Missing property"); + } else { + queryBuilder.setSortOrder(property, direction == null + ? QueryBuilder.Direction.ASCENDING + : direction, true); + } + handlers.pop(); + } + + @Override + public void key(String s) throws IOException { + currentKey = s; + } + + @Override + public void value(String s) throws IOException { + if ("property".equals(currentKey)) { + property = s; + } else if ("direction".equals(currentKey)) { + direction = directionFor(s); + } else { + throw new IOException("Unexpected: '" + currentKey + ':' + s + '\''); + } + } + + private QueryBuilder.Direction directionFor(String direction) throws IOException { + if ("asc".equals(direction)) { + return QueryBuilder.Direction.ASCENDING; + } else if ("desc".equals(direction)) { + return QueryBuilder.Direction.DESCENDING; + } else { + throw new IOException("Invalid direction '" + direction + '\''); + } + } + } + + //---------------------------------------------------< LimitHandler >--- + + private class LimitHandler extends HandlerBase { + private String currentKey; + private Long offset; + private Value bound; + private Long max; + + @Override + public void endObject() throws IOException { + if (offset != null) { + queryBuilder.setLimit(offset, max == null ? -1 : max); + } else if (bound != null) { + queryBuilder.setLimit(bound, max == null ? -1 : max); + } else { + throw new IOException("Missing bound or offset"); + } + handlers.pop(); + } + + @Override + public void key(String s) throws IOException { + currentKey = s; + } + + @Override + public void value(String s) throws IOException { + if ("bound".equals(currentKey)) { + bound = valueFor(s); + } else { + throw new IOException("Unexpected: '" + currentKey + ':' + s + '\''); + } + } + + @Override + public void value(boolean b) throws IOException { + if ("bound".equals(currentKey)) { + bound = valueFor(b); + } else { + throw new IOException("Unexpected: '" + currentKey + ':' + b + '\''); + } + } + + @Override + public void value(long l) throws IOException { + if ("bound".equals(currentKey)) { + bound = valueFor(l); + } else if ("offset".equals(currentKey)) { + offset = l; + } else if ("max".equals(currentKey)) { + max = l; + } else { + throw new IOException("Unexpected: '" + currentKey + ':' + l + '\''); + } + } + + @Override + public void value(double v) throws IOException { + if ("bound".equals(currentKey)) { + bound = valueFor(v); + } else { + throw new IOException("Unexpected: '" + currentKey + ':' + v + '\''); + } + } + } + } +} Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/Jcr2spiRepositoryFactory.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/Jcr2spiRepositoryFactory.java?rev=1159334&r1=1159333&r2=1159334&view=diff ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/Jcr2spiRepositoryFactory.java (original) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/Jcr2spiRepositoryFactory.java Thu Aug 18 18:10:16 2011 @@ -16,12 +16,6 @@ */ package org.apache.jackrabbit.jcr2spi; -import java.util.Map; - -import javax.jcr.Repository; -import javax.jcr.RepositoryException; -import javax.jcr.RepositoryFactory; - import org.apache.jackrabbit.jcr2spi.config.CacheBehaviour; import org.apache.jackrabbit.jcr2spi.config.RepositoryConfig; import org.apache.jackrabbit.spi.RepositoryService; @@ -31,6 +25,11 @@ import org.apache.jackrabbit.spi.commons import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import javax.jcr.Repository; +import javax.jcr.RepositoryException; +import javax.jcr.RepositoryFactory; +import java.util.Map; + /** * This implementation of {@link RepositoryFactory} is capable of returning the various * SPI implementations of the Apache Jackrabbit project: @@ -235,7 +234,7 @@ public class Jcr2spiRepositoryFactory im super(); this.serviceFactory = serviceFactory; this.cacheBehaviour = getCacheBehaviour(parameters); - this.itemCacheSize = getItemChacheSize(parameters); + this.itemCacheSize = getItemCacheSize(parameters); this.pollTimeOut = getPollTimeout(parameters); this.parameters = parameters; } @@ -295,21 +294,21 @@ public class Jcr2spiRepositoryFactory im } } - private static int getItemChacheSize(Map parameters) throws RepositoryException { + private static int getItemCacheSize(Map parameters) throws RepositoryException { Object paramItemCacheSize = parameters.get(PARAM_ITEM_CACHE_SIZE); - log.debug("Setting ItemChacheSize from {}", PARAM_ITEM_CACHE_SIZE); + log.debug("Setting ItemCacheSize from {}", PARAM_ITEM_CACHE_SIZE); if (paramItemCacheSize == null) { log.debug("{} not set, defaulting to {}", PARAM_ITEM_CACHE_SIZE, DEFAULT_ITEM_CACHE_SIZE); return DEFAULT_ITEM_CACHE_SIZE; } else if (paramItemCacheSize instanceof Integer) { - log.debug("Setting ItemChacheSize to {}", paramItemCacheSize); + log.debug("Setting ItemCacheSize to {}", paramItemCacheSize); return (Integer) paramItemCacheSize; } else if (paramItemCacheSize instanceof String) { try { - log.debug("Setting ItemChacheSize to {}", paramItemCacheSize); + log.debug("Setting ItemCacheSize to {}", paramItemCacheSize); return Integer.parseInt((String) paramItemCacheSize); } catch (NumberFormatException e) { Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QBinaryValue.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QBinaryValue.java?rev=1159334&r1=1159333&r2=1159334&view=diff ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QBinaryValue.java (original) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/QBinaryValue.java Thu Aug 18 18:10:16 2011 @@ -42,8 +42,6 @@ public class QBinaryValue implements QVa private final String blobId; private final MicroKernel microKernel; - private long length = -1; - public QBinaryValue(String blobId, MicroKernel microKernel) { this.blobId = blobId; this.microKernel = microKernel; @@ -63,16 +61,16 @@ public class QBinaryValue implements QVa public InputStream getStream() throws RepositoryException { return new InputStream(){ int pos; - byte[] buf = new byte[65536]; + final byte[] buf = new byte[65536]; @Override - public int read() throws IOException { + public int read() { int r = microKernel.read(blobId, pos++, buf, 0, 1); return r == -1 ? -1 : buf[0]; } @Override - public int read(byte[] b, int off, int len) throws IOException { + public int read(byte[] b, int off, int len) { if (b == null) { throw new NullPointerException(); } Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryFactoryImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryFactoryImpl.java?rev=1159334&r1=1159333&r2=1159334&view=diff ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryFactoryImpl.java (original) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/RepositoryFactoryImpl.java Thu Aug 18 18:10:16 2011 @@ -29,7 +29,6 @@ import java.util.Map; public class RepositoryFactoryImpl implements RepositoryFactory { @Override - @SuppressWarnings("unchecked") public Repository getRepository(Map parameters) { if (parameters == null || parameters.isEmpty()) { return null; 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=1159334&r1=1159333&r2=1159334&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 Thu Aug 18 18:10:16 2011 @@ -265,13 +265,13 @@ public class RepositoryServiceImpl exten private String key; @Override - public boolean startObjectEntry(String key) throws ParseException, IOException { + public boolean startObjectEntry(String key) { this.key = key; return true; } @Override - public boolean startObject() throws ParseException, IOException { + public boolean startObject() { if (key != null) { workspaces.add(key); } @@ -279,7 +279,7 @@ public class RepositoryServiceImpl exten } @Override - public boolean endObjectEntry() throws ParseException, IOException { + public boolean endObjectEntry() { key = null; return true; } @@ -717,7 +717,7 @@ public class RepositoryServiceImpl exten public void commit() throws RepositoryException { sessionState(sessionInfo).commitWithLock(new Callable() { @Override - public String call() throws RepositoryException { + public String call() { String rev = microKernel.getHeadRevision(); return microKernel.commit("/", jsop.toString(), rev, ((SessionInfoImpl) sessionInfo).getUserData()); } Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/SubscriptionImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/SubscriptionImpl.java?rev=1159334&r1=1159333&r2=1159334&view=diff ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/SubscriptionImpl.java (original) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/SubscriptionImpl.java Thu Aug 18 18:10:16 2011 @@ -73,7 +73,7 @@ public class SubscriptionImpl implements waitForCommit = new WaitForCommit(); } - public void setEventFilters(EventFilter[] eventFilters) throws RepositoryException { + public void setEventFilters(EventFilter[] eventFilters) { synchronized (eventSources) { eventSources.add(new EventSource(eventFilters, sessionState)); } @@ -368,7 +368,7 @@ public class SubscriptionImpl implements else { if (jsopTokenizer.getTokenType() == '[') { // skip over array - while(jsopTokenizer.read() != ']'); + while(jsopTokenizer.read() != ']') {} } Name name = path.getName(); Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/util/Values.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/util/Values.java?rev=1159334&r1=1159333&r2=1159334&view=diff ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/util/Values.java (original) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/java/org/apache/jackrabbit/spi2microkernel/util/Values.java Thu Aug 18 18:10:16 2011 @@ -444,7 +444,7 @@ public final class Values { return FACTORY.create(sessionInfo.getUserID(), PropertyType.STRING); } else { - IllegalStateException e = new IllegalStateException("No default valur for property " + propertyName); + IllegalStateException e = new IllegalStateException("No default value for property " + propertyName); log.debug(e.getMessage(), e); throw e; } Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/resources/org/apache/jackrabbit/spi2microkernel/default-nodetypes.cnd URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/resources/org/apache/jackrabbit/spi2microkernel/default-nodetypes.cnd?rev=1159334&r1=1159333&r2=1159334&view=diff ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/resources/org/apache/jackrabbit/spi2microkernel/default-nodetypes.cnd (original) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/main/resources/org/apache/jackrabbit/spi2microkernel/default-nodetypes.cnd Thu Aug 18 18:10:16 2011 @@ -29,7 +29,7 @@ /** * nt:base is an abstract primary node type that is the base type for all other - * primary node types. It is the only primary node type without supertypes. + * primary node types. It is the only primary node type without super types. * * @since 1.0 */ @@ -44,7 +44,7 @@ //------------------------------------------------------------------------------ /** - * This abstract node type serves as the supertype of nt:file and nt:folder. + * This abstract node type serves as the super type of nt:file and nt:folder. * @since 1.0 */ [nt:hierarchyNode] > mix:created @@ -92,7 +92,7 @@ /** * This node type may be used to represent the content of a file. In particular, - * the jcr:content subnode of an nt:file node will often be an nt:resource. + * the jcr:content sub node of an nt:file node will often be an nt:resource. * * @since 1.0 */ @@ -136,9 +136,9 @@ * The following is not yet implemented in Jackrabbit: * "Since the properties are protected, their values * are controlled by the repository, which should set them appropriately upon a - * significant modification of the subgraph of a node with this mixin. What + * significant modification of the sub graph of a node with this mixin. What * constitutes a significant modification will depend on the semantics of the various - * parts of a node's subgraph and is implementation-dependent" + * parts of a node's sub graph and is implementation-dependent" * * Jackrabbit initializes the properties to the current date and user in the * case they are newly created. @@ -166,7 +166,7 @@ - jcr:language (STRING) /** - * This mixin node type can be used to provide standardized mimetype and + * This mixin node type can be used to provide standardized mime type and * encoding properties to a node. If a node of this type has a primary item * that is a single-value BINARY property then jcr:mimeType property indicates * the media type applicable to the contents of that property and, if that Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/MicrokernelTest.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/MicrokernelTest.java?rev=1159334&r1=1159333&r2=1159334&view=diff ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/MicrokernelTest.java (original) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/MicrokernelTest.java Thu Aug 18 18:10:16 2011 @@ -172,10 +172,10 @@ public class MicrokernelTest { String head = mk.getHeadRevision(); String node = "reorderNode_" + System.currentTimeMillis(); head = mk.commit("/", "+\"" + node + "\" : {\"a\":{}, \"b\":{}, \"c\":{}}", head, ""); - System.out.println(mk.getNodes("/" + node, head).replaceAll("\"", "").replaceAll(":childNodeCount:.", "")); + System.out.println(mk.getNodes('/' + node, head).replaceAll("\"", "").replaceAll(":childNodeCount:.", "")); head = mk.commit("/", ">\"" + node + "/a\" : \"" + node + "/c\" \"#before\"", head, ""); - System.out.println(mk.getNodes("/" + node, head).replaceAll("\"", "").replaceAll(":childNodeCount:.", "")); + System.out.println(mk.getNodes('/' + node, head).replaceAll("\"", "").replaceAll(":childNodeCount:.", "")); } @Test Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/RepositoryTest.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/RepositoryTest.java?rev=1159334&r1=1159333&r2=1159334&view=diff ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/RepositoryTest.java (original) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/RepositoryTest.java Thu Aug 18 18:10:16 2011 @@ -120,7 +120,7 @@ public class RepositoryTest { String head = mk.getHeadRevision(); if (mk.nodeExists("/default/{}" + testNode, head)) { - mk.commit("/default", "-\"{}" + testNode + "\"", head, ""); + mk.commit("/default", "-\"{}" + testNode + '\"', head, ""); } } finally { @@ -886,8 +886,8 @@ public class RepositoryTest { parentNode.setProperty("multi string2", values); parentNode.getSession().save(); - values[0] = getSession().getValueFactory().createValue("eins"); - values[1] = getSession().getValueFactory().createValue("zwei"); + values[0] = getSession().getValueFactory().createValue("three"); + values[1] = getSession().getValueFactory().createValue("four"); parentNode.setProperty("multi string2", values); parentNode.getSession().save(); Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/tck/RepositoryStubImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/tck/RepositoryStubImpl.java?rev=1159334&r1=1159333&r2=1159334&view=diff ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/tck/RepositoryStubImpl.java (original) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/tck/RepositoryStubImpl.java Thu Aug 18 18:10:16 2011 @@ -106,7 +106,7 @@ public class RepositoryStubImpl extends private static void loadTestContent(Repository rep) throws Exception { Session session = rep.login(); try { - new TestContentLoader().loadTestContent(session); + TestContentLoader.loadTestContent(session); } finally { session.logout(); Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/tck/TestContentLoader.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/tck/TestContentLoader.java?rev=1159334&r1=1159333&r2=1159334&view=diff ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/tck/TestContentLoader.java (original) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/tck/TestContentLoader.java Thu Aug 18 18:10:16 2011 @@ -37,13 +37,14 @@ import java.util.Collection; * Test Content Loader. */ public class TestContentLoader { + private TestContentLoader() {} /** * The encoding of the test resources. */ private static final String ENCODING = "UTF-8"; - public void loadTestContent(Session session) throws RepositoryException, IOException { + public static void loadTestContent(Session session) throws RepositoryException, IOException { Workspace workspace = session.getWorkspace(); Collection workspaces = Arrays.asList(workspace.getAccessibleWorkspaceNames()); @@ -109,7 +110,7 @@ public class TestContentLoader { /** * Creates a node with a RetentionPolicy */ - private static void addRetentionTestData(Node node) throws RepositoryException { + private static void addRetentionTestData(Node node) { // RetentionPolicy rp = RetentionPolicyImpl.createRetentionPolicy("testRetentionPolicy", node.getSession()); // node.getSession().getRetentionManager().setRetentionPolicy(node.getPath(), rp); } @@ -184,11 +185,11 @@ public class TestContentLoader { transition.setProperty("from", "identity"); transition.setProperty("to", "identity"); - Node lifecycle = getOrAddNode(node, "node"); +// Node lifecycle = getOrAddNode(node, "node"); // ((NodeImpl) lifecycle).assignLifecyclePolicy(policy, "identity"); } - private void addExportTestData(Node node) throws RepositoryException, IOException { + private static void addExportTestData(Node node) throws RepositoryException, IOException { getOrAddNode(node, "invalidXmlName").setProperty("propName", "some text"); // three nodes which should be serialized as xml text in docView export @@ -256,4 +257,4 @@ public class TestContentLoader { resource.setProperty("jcr:lastModified", Calendar.getInstance()); } -} \ No newline at end of file +} Modified: jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/util/Loop.java URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/util/Loop.java?rev=1159334&r1=1159333&r2=1159334&view=diff ============================================================================== --- jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/util/Loop.java (original) +++ jackrabbit/sandbox/jackrabbit-mk/jackrabbit-spi2microkernel/src/test/java/org/apache/jackrabbit/spi2microkernel/util/Loop.java Thu Aug 18 18:10:16 2011 @@ -23,7 +23,7 @@ package org.apache.jackrabbit.spi2microk */ public abstract class Loop { - public Loop() { + protected Loop() { // loop at most 500 times with 10 milliseconds delay for (int i = 0; i < 500; i++) { try {