You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by th...@apache.org on 2011/10/27 17:00:16 UTC

svn commit: r1189796 [1/2] - in /jackrabbit/sandbox/microkernel/src: main/java/org/apache/jackrabbit/mk/ main/java/org/apache/jackrabbit/mk/index/ main/java/org/apache/jackrabbit/mk/json/ main/java/org/apache/jackrabbit/mk/mem/ main/java/org/apache/jac...

Author: thomasm
Date: Thu Oct 27 15:00:15 2011
New Revision: 1189796

URL: http://svn.apache.org/viewvc?rev=1189796&view=rev
Log:
Speed up Jsop generation and tokenizing.

Added:
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopReader.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopStream.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopWriter.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/Wrapper.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/WrapperBase.java
    jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/json/JsopStreamTest.java
Modified:
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/MicroKernelImpl.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/BTree.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/BTreeLeaf.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/BTreeNode.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/Indexer.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopBuilder.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopTokenizer.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeImpl.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeList.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListLarge.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListSmall.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/SecurityWrapper.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/VirtualRepositoryWrapper.java
    jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/MoveNodeTest.java
    jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/json/JsopTest.java
    jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/wrapper/TestSecurityWrapper.java

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/MicroKernelImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/MicroKernelImpl.java?rev=1189796&r1=1189795&r2=1189796&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/MicroKernelImpl.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/MicroKernelImpl.java Thu Oct 27 15:00:15 2011
@@ -210,28 +210,28 @@ public class MicroKernelImpl implements 
 
             if (node1 == null) {
                 if (node2 != null) {
-                    buff.appendTag("+ ").key(path).object();
+                    buff.tag('+').key(path).object();
                     toJson(buff, node2, Integer.MAX_VALUE, 0, -1, false);
                     return buff.endObject().newline().toString();
                 } else {
                     throw new MicroKernelException("path doesn't exist in the specified revisions: " + path);
                 }
             } else if (node2 == null) {
-                buff.appendTag("- ");
+                buff.tag('-');
                 buff.value(path);
                 return buff.newline().toString();
             }
 
             NodeUtils.diff(path, node1, node2, true, rep.getPersistenceManager(), new NodeDiffHandler() {
                 public void propAdded(String nodePath, String propName, String value) {
-                    buff.appendTag("+ ").
+                    buff.tag('+').
                             key(PathUtils.concat(nodePath, propName)).
                             encodedValue(value).
                             newline();
                 }
 
                 public void propChanged(String nodePath, String propName, String oldValue, String newValue) {
-                    buff.appendTag("^ ").
+                    buff.tag('^').
                             key(PathUtils.concat(nodePath, propName)).
                             encodedValue(newValue).
                             newline();
@@ -241,15 +241,15 @@ public class MicroKernelImpl implements 
                     // since property and node deletions can't be distinguished
                     // using the "- <path>" notation we're representing
                     // property deletions as "^ <path>:null"
-                    buff.appendTag("^ ").
+                    buff.tag('^').
                             key(PathUtils.concat(nodePath, propName)).
-                            encodedValue("null").
+                            value(null).
                             newline();
                 }
 
                 public void childNodeAdded(String nodePath, String childName, String id) {
                     addedNodes.put(id, PathUtils.concat(nodePath, childName));
-                    buff.appendTag("+ ").
+                    buff.tag('+').
                             key(PathUtils.concat(nodePath, childName)).object();
                     try {
                         toJson(buff, rep.getPersistenceManager().getNode(id), Integer.MAX_VALUE, 0, -1, false);
@@ -261,7 +261,7 @@ public class MicroKernelImpl implements 
 
                 public void childNodeDeleted(String nodePath, String childName, String id) {
                     removedNodes.put(id, PathUtils.concat(nodePath, childName));
-                    buff.appendTag("- ");
+                    buff.tag('-');
                     buff.value(PathUtils.concat(nodePath, childName));
                     buff.newline();
                 }
@@ -285,27 +285,27 @@ public class MicroKernelImpl implements 
                 // TODO refactor code, avoid duplication
                 NodeUtils.diff(path, node1, node2, true, rep.getPersistenceManager(), new NodeDiffHandler() {
                     public void propAdded(String nodePath, String propName, String value) {
-                        buff.appendTag("+ ").
+                        buff.tag('+').
                                 key(PathUtils.concat(nodePath, propName)).
                                 encodedValue(value).
-                                appendTag("\n");
+                                newline();
                     }
 
                     public void propChanged(String nodePath, String propName, String oldValue, String newValue) {
-                        buff.appendTag("^ ").
+                        buff.tag('^').
                                 key(PathUtils.concat(nodePath, propName)).
                                 encodedValue(newValue).
-                                appendTag("\n");
+                                newline();
                     }
 
                     public void propDeleted(String nodePath, String propName, String value) {
                         // since property and node deletions can't be distinguished
                         // using the "- <path>" notation we're representing
                         // property deletions as "^ <path>:null"
-                        buff.appendTag("^ ").
+                        buff.tag('^').
                                 key(PathUtils.concat(nodePath, propName)).
-                                encodedValue("null").
-                                appendTag("\n");
+                                value(null).
+                                newline();
                     }
 
                     public void childNodeAdded(String nodePath, String childName, String id) {
@@ -313,14 +313,14 @@ public class MicroKernelImpl implements 
                             // moved node, will be processed separately
                             return;
                         }
-                        buff.appendTag("+ ").
+                        buff.tag('+').
                                 key(PathUtils.concat(nodePath, childName)).object();
                         try {
                             toJson(buff, rep.getPersistenceManager().getNode(id), Integer.MAX_VALUE, 0, -1, false);
                         } catch (Exception e) {
                             buff.value("ERROR: failed to retrieve node " + id);
                         }
-                        buff.endObject().appendTag("\n");
+                        buff.endObject().newline();
                     }
 
                     public void childNodeDeleted(String nodePath, String childName, String id) {
@@ -328,9 +328,9 @@ public class MicroKernelImpl implements 
                             // moved node, will be processed separately
                             return;
                         }
-                        buff.appendTag("- ");
+                        buff.tag('-');
                         buff.value(PathUtils.concat(nodePath, childName));
-                        buff.appendTag("\n");
+                        buff.newline();
                     }
 
                     public void childNodeChanged(String nodePath, String childName, String oldId, String newId) {
@@ -339,7 +339,7 @@ public class MicroKernelImpl implements 
                 });
                 // finally process moved nodes
                 for (Map.Entry<String, String> entry : addedNodes.entrySet()) {
-                    buff.appendTag("> ").
+                    buff.tag('>').
                             // path/to/deleted/node
                                     key(removedNodes.get(entry.getKey())).
                             // path/to/added/node

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/BTree.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/BTree.java?rev=1189796&r1=1189795&r2=1189796&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/BTree.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/BTree.java Thu Oct 27 15:00:15 2011
@@ -39,7 +39,7 @@ public class BTree {
         this.unique = unique;
         if (!indexer.nodeExists(name)) {
             JsopBuilder jsop = new JsopBuilder();
-            jsop.appendTag("+ ").key(name).encodedValue("{}");
+            jsop.tag('+').key(name).object().endObject();
             indexer.commit(jsop.toString());
         }
     }
@@ -128,7 +128,7 @@ public class BTree {
     void bufferSetArray(String path, String propertyName, String[] data) {
         JsopBuilder jsop = new JsopBuilder();
         path = PathUtils.concat(name, path);
-        jsop.appendTag("^ ").key(PathUtils.concat(path, propertyName));
+        jsop.tag('^').key(PathUtils.concat(path, propertyName));
         if (data.length == 0) {
             jsop.value(null);
         } else {
@@ -144,14 +144,14 @@ public class BTree {
 
     void bufferMove(String path, String newPath) {
         JsopBuilder jsop = new JsopBuilder();
-        jsop.appendTag("> ").key(path).value(newPath);
+        jsop.tag('>').key(path).value(newPath);
         jsop.newline();
         indexer.buffer(jsop.toString());
     }
 
     void bufferDelete(String path) {
         JsopBuilder jsop = new JsopBuilder();
-        jsop.appendTag("- ").value(PathUtils.concat(name, path));
+        jsop.tag('-').value(PathUtils.concat(name, path));
         jsop.newline();
         indexer.buffer(jsop.toString());
     }

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/BTreeLeaf.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/BTreeLeaf.java?rev=1189796&r1=1189795&r2=1189796&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/BTreeLeaf.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/BTreeLeaf.java Thu Oct 27 15:00:15 2011
@@ -70,7 +70,7 @@ class BTreeLeaf extends BTreePage {
     void writeCreate() {
         tree.modified(this);
         JsopBuilder jsop = new JsopBuilder();
-        jsop.appendTag("+ ").key(PathUtils.concat(tree.getName(), getPath())).object();
+        jsop.tag('+').key(PathUtils.concat(tree.getName(), getPath())).object();
         jsop.key("keys").array();
         for (String k : keys) {
             jsop.value(k);

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/BTreeNode.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/BTreeNode.java?rev=1189796&r1=1189795&r2=1189796&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/BTreeNode.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/BTreeNode.java Thu Oct 27 15:00:15 2011
@@ -102,7 +102,7 @@ class BTreeNode extends BTreePage {
     void writeCreate() {
         tree.modified(this);
         JsopBuilder jsop = new JsopBuilder();
-        jsop.appendTag("+ ").key(PathUtils.concat(tree.getName(), getPath())).object();
+        jsop.tag('+').key(PathUtils.concat(tree.getName(), getPath())).object();
         jsop.key("keys").array();
         for (String k : keys) {
             jsop.value(k);

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/Indexer.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/Indexer.java?rev=1189796&r1=1189795&r2=1189796&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/Indexer.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/index/Indexer.java Thu Oct 27 15:00:15 2011
@@ -58,7 +58,7 @@ public class Indexer {
         readRevision = revision;
         if (!mk.nodeExists(indexRootNode, revision)) {
             JsopBuilder jsop = new JsopBuilder();
-            jsop.appendTag("+ ").key(PathUtils.relativize("/", indexRootNode)).encodedValue("{}");
+            jsop.tag('+').key(PathUtils.relativize("/", indexRootNode)).object().endObject();
             revision = mk.commit("/", jsop.toString(), revision, null);
         } else {
             String node = mk.getNodes(indexRootNode, revision, 0, 0, Integer.MAX_VALUE);
@@ -280,7 +280,7 @@ public class Indexer {
         } while (t.matches(','));
         readRevision = toRevision;
         JsopBuilder jsop = new JsopBuilder();
-        jsop.appendTag("^ ").key("rev").value(readRevision);
+        jsop.tag('^').key("rev").value(readRevision);
         buffer(jsop.toString());
         commitChanges();
     }

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopBuilder.java?rev=1189796&r1=1189795&r2=1189796&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopBuilder.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopBuilder.java Thu Oct 27 15:00:15 2011
@@ -24,7 +24,7 @@ import org.apache.jackrabbit.mk.Constant
  * but only if the last appended token was '}', ']', or a value. There is no
  * limit to the number of nesting levels.
  */
-public class JsopBuilder {
+public class JsopBuilder implements JsopWriter {
 
     private StringBuilder buff = new StringBuilder();
     private boolean needComma;
@@ -43,6 +43,29 @@ public class JsopBuilder {
     }
 
     /**
+     * Append all entries of the given buffer.
+     *
+     * @param buffer the buffer
+     * @return this
+     */
+    public JsopBuilder append(JsopWriter buffer) {
+        appendTag(buffer.toString());
+        return this;
+    }
+
+    /**
+     * Append a Jsop tag character.
+     *
+     * @param string the string to append
+     * @return this
+     */
+    public JsopBuilder tag(char tag) {
+        buff.append(tag);
+        needComma = false;
+        return this;
+    }
+
+    /**
      * Append an (already formatted) Jsop tag. This will allow to append
      * non-Json data. This method resets the comma flag, so no comma is added
      * before the next key or value.
@@ -50,7 +73,7 @@ public class JsopBuilder {
      * @param string the string to append
      * @return this
      */
-    public JsopBuilder appendTag(String string) {
+    private JsopBuilder appendTag(String string) {
         buff.append(string);
         needComma = false;
         return this;

Added: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopReader.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopReader.java?rev=1189796&view=auto
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopReader.java (added)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopReader.java Thu Oct 27 15:00:15 2011
@@ -0,0 +1,35 @@
+/*
+ * 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.mk.json;
+
+public interface JsopReader {
+
+    String read(int type);
+
+    String readString();
+
+    int read();
+
+    boolean matches(int type);
+
+    String readRawValue();
+
+    String getToken();
+
+    int getTokenType();
+
+}

Added: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopStream.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopStream.java?rev=1189796&view=auto
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopStream.java (added)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopStream.java Thu Oct 27 15:00:15 2011
@@ -0,0 +1,279 @@
+/*
+ * 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.mk.json;
+
+/**
+ * A fast Jsop writer / reader.
+ */
+public class JsopStream implements JsopReader, JsopWriter {
+
+    private boolean needComma;
+    private int len, pos, valuesLen;
+    private int[] tokens = new int[10];
+    private Object[] values = new Object[10];
+
+    // write
+
+    public JsopStream append(JsopWriter w) {
+        JsopStream s = (JsopStream) w;
+        for (int i = s.pos; i < s.len; i++) {
+            int token = s.tokens[i];
+            switch (token & 255) {
+            case JsopTokenizer.STRING:
+            case JsopTokenizer.NUMBER:
+            case JsopTokenizer.IDENTIFIER:
+            case JsopTokenizer.COMMENT:
+                Object o = s.values[token >> 8];
+                addToken((token & 255) + addValue(o));
+                break;
+            default:
+                addToken(token);
+            }
+        }
+        return this;
+    }
+
+    private void addToken(int x) {
+        if (tokens.length < len + 1) {
+            growTokens();
+        }
+        tokens[len++] = x;
+    }
+
+    private int addValue(Object x) {
+        if (values.length < valuesLen + 1) {
+            growValues();
+        }
+        values[valuesLen] = x;
+        return valuesLen++ << 8;
+    }
+
+    private void growTokens() {
+        int[] t2 = new int[tokens.length * 2];
+        System.arraycopy(tokens, 0, t2, 0, len);
+        tokens = t2;
+    }
+
+    private void growValues() {
+        Object[] v2 = new Object[values.length * 2];
+        System.arraycopy(values, 0, v2, 0, valuesLen);
+        values = v2;
+    }
+
+    public JsopStream tag(char tag) {
+        addToken(tag);
+        needComma = false;
+        return this;
+    }
+
+    public JsopStream array() {
+        optionalComma();
+        addToken('[');
+        needComma = false;
+        return this;
+    }
+
+    public JsopStream encodedValue(String raw) {
+        optionalComma();
+        addToken(JsopTokenizer.COMMENT + addValue(raw));
+        needComma = true;
+        return this;
+    }
+
+    public JsopStream endArray() {
+        addToken(']');
+        needComma = true;
+        return this;
+    }
+
+    public JsopStream endObject() {
+        addToken('}');
+        needComma = true;
+        return this;
+    }
+
+    public JsopStream key(String key) {
+        optionalComma();
+        addToken(JsopTokenizer.STRING + addValue(key));
+        addToken(':');
+        needComma = false;
+        return this;
+    }
+
+    public JsopStream newline() {
+        return this;
+    }
+
+    public JsopStream object() {
+        optionalComma();
+        addToken('{');
+        needComma = false;
+        return this;
+    }
+
+    public JsopStream value(String value) {
+        optionalComma();
+        if (value == null) {
+            addToken(JsopTokenizer.NULL);
+        } else {
+            addToken(JsopTokenizer.STRING + addValue(value));
+        }
+        needComma = true;
+        return this;
+    }
+
+    public JsopStream value(long x) {
+        optionalComma();
+        addToken(JsopTokenizer.NUMBER + addValue(Long.valueOf(x)));
+        needComma = true;
+        return this;
+    }
+
+    public JsopStream value(boolean b) {
+        optionalComma();
+        addToken(b ? JsopTokenizer.TRUE : JsopTokenizer.FALSE);
+        needComma = true;
+        return this;
+    }
+
+    public void reset() {
+        needComma = false;
+        len = 0;
+    }
+
+    public void setLineLength(int i) {
+        // ignore
+    }
+
+    private void optionalComma() {
+        if (needComma) {
+            addToken(',');
+        }
+    }
+
+    // read
+
+    public String getToken() {
+        int x = tokens[pos - 1];
+        switch (x & 255) {
+        case JsopTokenizer.STRING:
+        case JsopTokenizer.NUMBER:
+        case JsopTokenizer.IDENTIFIER:
+        case JsopTokenizer.COMMENT:
+            return values[x >> 8].toString();
+        case JsopTokenizer.TRUE:
+            return "true";
+        case JsopTokenizer.FALSE:
+            return "false";
+        case JsopTokenizer.NULL:
+            return "null";
+        }
+        return Character.toString((char) (x & 255));
+    }
+
+    public int getTokenType() {
+        return getType(pos - 1);
+    }
+
+    public boolean matches(int type) {
+        if (getType(pos) == type) {
+            pos++;
+            return true;
+        }
+        return false;
+    }
+
+    private int getType(int pos) {
+        return tokens[pos] & 255;
+    }
+
+    public String read(int type) {
+        if (matches(type)) {
+            return getToken();
+        }
+        throw new IllegalArgumentException("expected: " + type + " got: " + tokens[pos]);
+    }
+
+    public int read() {
+        return getType(pos++);
+    }
+
+    public String readRawValue() {
+        int x = tokens[pos++];
+        switch (x & 255) {
+        case JsopTokenizer.COMMENT:
+        case JsopTokenizer.NUMBER:
+        case JsopTokenizer.IDENTIFIER:
+            return values[x >> 8].toString();
+        case JsopTokenizer.STRING:
+            return JsopBuilder.encode(values[x >> 8].toString());
+        case JsopTokenizer.TRUE:
+            return "true";
+        case JsopTokenizer.FALSE:
+            return "false";
+        case JsopTokenizer.NULL:
+            return "null";
+        }
+        return Character.toString((char) (x & 255));
+    }
+
+    public String readString() {
+        return read(JsopTokenizer.STRING);
+    }
+
+    public String toString() {
+        JsopBuilder buff = new JsopBuilder();
+        for (int i = 0; i < len; i++) {
+            int x = tokens[i];
+            switch (x & 255) {
+            case '{':
+                buff.object();
+                break;
+            case '}':
+                buff.endObject();
+                break;
+            case '[':
+                buff.array();
+                break;
+            case ']':
+                buff.endArray();
+                break;
+            case JsopTokenizer.STRING:
+                buff.value(values[x >> 8].toString());
+                break;
+            case JsopTokenizer.TRUE:
+                buff.value(true);
+                break;
+            case JsopTokenizer.FALSE:
+                buff.value(false);
+                break;
+            case JsopTokenizer.NULL:
+                buff.value(null);
+                break;
+            case JsopTokenizer.IDENTIFIER:
+            case JsopTokenizer.NUMBER:
+            case JsopTokenizer.COMMENT:
+                buff.encodedValue(values[x >> 8].toString());
+                break;
+            default:
+                buff.tag((char) (x & 255));
+            }
+        }
+        return buff.toString();
+    }
+
+}

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopTokenizer.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopTokenizer.java?rev=1189796&r1=1189795&r2=1189796&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopTokenizer.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopTokenizer.java Thu Oct 27 15:00:15 2011
@@ -19,13 +19,13 @@ package org.apache.jackrabbit.mk.json;
 /**
  * A tokenizer for Json and Jsop strings.
  */
-public class JsopTokenizer {
+public class JsopTokenizer implements JsopReader {
 
-    public static final int STRING = 0, NUMBER = 1, TRUE = 2, FALSE = 3, NULL = 4;
-    public static final int IDENTIFIER = 5, COMMENT = 6, ERROR = 7, END = 8;
+    public static final int END = 0, STRING = 1, NUMBER = 2, TRUE = 3, FALSE = 4, NULL = 5;
+    public static final int ERROR = 6, IDENTIFIER = 7, COMMENT = 8;
 
     private static final String[] TYPE = {
-            "string", "number", "true", "false", "null", "error", "end"
+            "end", "string", "number", "true", "false", "null", "error"
     };
 
     private final String jsop;
@@ -338,7 +338,7 @@ public class JsopTokenizer {
     }
 
     private static String getTokenType(int type) {
-        return type <= END ? TYPE[type] : "'" + (char) type + "'";
+        return type <= COMMENT ? TYPE[type] : "'" + (char) type + "'";
     }
 
     private static IllegalArgumentException getFormatException(String s, int i, String expected) {

Added: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopWriter.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopWriter.java?rev=1189796&view=auto
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopWriter.java (added)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/JsopWriter.java Thu Oct 27 15:00:15 2011
@@ -0,0 +1,49 @@
+/*
+ * 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.mk.json;
+
+public interface JsopWriter {
+
+    JsopWriter array();
+
+    JsopWriter object();
+
+    JsopWriter key(String key);
+
+    JsopWriter value(String value);
+
+    JsopWriter encodedValue(String raw);
+
+    JsopWriter endObject();
+
+    JsopWriter endArray();
+
+    JsopWriter tag(char tag);
+
+    JsopWriter append(JsopWriter diff);
+
+    JsopWriter value(long x);
+
+    JsopWriter value(boolean b);
+
+    JsopWriter newline();
+
+    void reset();
+
+    void setLineLength(int i);
+
+}

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java?rev=1189796&r1=1189795&r2=1189796&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/MemoryKernelImpl.java Thu Oct 27 15:00:15 2011
@@ -22,13 +22,17 @@ import org.apache.jackrabbit.mk.blobs.Fi
 import org.apache.jackrabbit.mk.blobs.MemoryBlobStore;
 import org.apache.jackrabbit.mk.fs.FileUtils;
 import org.apache.jackrabbit.mk.json.JsopBuilder;
+import org.apache.jackrabbit.mk.json.JsopReader;
+import org.apache.jackrabbit.mk.json.JsopStream;
 import org.apache.jackrabbit.mk.json.JsopTokenizer;
+import org.apache.jackrabbit.mk.json.JsopWriter;
 import org.apache.jackrabbit.mk.server.Server;
 import org.apache.jackrabbit.mk.util.AscendingClock;
 import org.apache.jackrabbit.mk.util.Cache;
 import org.apache.jackrabbit.mk.util.CommitGate;
 import org.apache.jackrabbit.mk.util.ExceptionFactory;
 import org.apache.jackrabbit.mk.util.PathUtils;
+import org.apache.jackrabbit.mk.wrapper.WrapperBase;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -59,7 +63,7 @@ Node structure:
  * An in-memory implementation.
  * Useful for testing.
  */
-public class MemoryKernelImpl implements MicroKernel {
+public class MemoryKernelImpl extends WrapperBase implements MicroKernel {
 
     private static final int MAX_REVISIONS_PER_NODE = 100;
     private static final HashMap<String, MemoryKernelImpl> INSTANCES = new HashMap<String, MemoryKernelImpl>();
@@ -71,7 +75,6 @@ public class MemoryKernelImpl implements
     private final Cache<Long, Revision> revisionCache = Cache.newInstance(null, 1024 * 1024);
     private volatile long headRevId;
     private NodeMap nodeMap;
-    private String lastJournalRevRange, lastJournal;
     private Server server;
     private boolean disposed;
 
@@ -163,7 +166,7 @@ public class MemoryKernelImpl implements
         }
     }
 
-    public synchronized String commit(String rootPath, String jsonDiff, String revisionId, String message) {
+    public synchronized String commitStream(String rootPath, JsopReader jsonDiff, String revisionId, String message) {
         // TODO do we really need 'path'? store the path is in the diff instead
         // TODO what is the exact meaning of 'revisionId'? is it allowed to commit
         // using an old revision, if yes when is it allowed, or how is it different from using head?
@@ -181,13 +184,12 @@ public class MemoryKernelImpl implements
         }
     }
 
-    private String doCommit(String rootPath, String jsonDiff, String revisionId, String message) {
+    private String doCommit(String rootPath, JsopReader t, String revisionId, String message) {
         long oldRevision = headRevId, rev = headRevId + 1;
         NodeImpl root = nodeMap.getNode(nodeMap.getRootId());
         NodeImpl head = root.getNode("head"), oldHead = head;
         NodeImpl data = head.getNode("data");
-        JsopBuilder diff = new JsopBuilder();
-        JsopTokenizer t = new JsopTokenizer(jsonDiff);
+        JsopWriter diff = new JsopBuilder();
         while (true) {
             int r = t.read();
             if (r == JsopTokenizer.END) {
@@ -198,7 +200,7 @@ public class MemoryKernelImpl implements
             switch (r) {
             case '+':
                 t.read(':');
-                diff.appendTag("+ ").key(path);
+                diff.tag('+').key(path);
                 if (t.matches('{')) {
                     NodeImpl n = NodeImpl.parse(nodeMap, t, rev);
                     data = data.cloneAndAddChildNode(from, false, null, n, rev);
@@ -216,7 +218,7 @@ public class MemoryKernelImpl implements
                 diff.newline();
                 break;
             case '-':
-                diff.appendTag("- ").value(path).newline();
+                diff.tag('-').value(path).newline();
                 data = data.cloneAndRemoveChildNode(from, rev);
                 break;
             case '^':
@@ -225,15 +227,15 @@ public class MemoryKernelImpl implements
                 String value;
                 if (t.matches(JsopTokenizer.NULL)) {
                     value = null;
-                    diff.appendTag("^ ").key(path).value(null);
+                    diff.tag('^').key(path).value(null);
                 } else {
                     value = t.readRawValue().trim();
                     String nodeName = PathUtils.getParentPath(from);
                     String propertyName = PathUtils.getName(from);
                     if (isConfigChange || data.getNode(nodeName).hasProperty(propertyName)) {
-                        diff.appendTag("^ ");
+                        diff.tag('^');
                     } else {
-                        diff.appendTag("+ ");
+                        diff.tag('+');
                     }
                     diff.key(path).encodedValue(value);
                 }
@@ -248,7 +250,7 @@ public class MemoryKernelImpl implements
                 break;
             case '>':
                 t.read(':');
-                diff.appendTag("> ").key(path);
+                diff.tag('>').key(path);
                 String name = PathUtils.getName(from);
                 String position, target, to;
                 boolean rename;
@@ -343,7 +345,7 @@ public class MemoryKernelImpl implements
         return Revision.formatId(headRevId);
     }
 
-    public String getRevisions(long since, int maxEntries) {
+    public JsopReader getRevisionsStream(long since, int maxEntries) {
         NodeImpl node = getRoot();
         ArrayList<Revision> revisions = new ArrayList<Revision>();
         Revision r = Revision.get(node.getNode("head"));
@@ -362,27 +364,21 @@ public class MemoryKernelImpl implements
                 }
             }
         }
-        JsopBuilder buff = new JsopBuilder().array();
+        JsopStream buff = new JsopStream().array();
         Collections.sort(revisions);
         for (Revision rev : revisions) {
             if (rev.getTime() > since) {
                 buff.encodedValue(rev.toString());
             }
         }
-        return buff.endArray().toString();
+        return buff.endArray();
     }
 
     public String waitForCommit(String oldHeadRevision, long maxWaitMillis) throws InterruptedException {
         return gate.waitForCommit(oldHeadRevision, maxWaitMillis);
     }
 
-    public String getJournal(String fromRevisionId, String toRevisionId) {
-    	String revRange = fromRevisionId + "-" + toRevisionId;
-    	synchronized (this) {
-    	    if (revRange.equals(lastJournalRevRange)) {
-    	        return lastJournal;
-    	    }
-    	}
+    public JsopReader getJournalStream(String fromRevisionId, String toRevisionId) {
         long fromRev = Revision.parseId(fromRevisionId);
         long toRev = Revision.parseId(toRevisionId);
         NodeImpl node = getRoot();
@@ -402,28 +398,23 @@ public class MemoryKernelImpl implements
             }
         }
         Collections.sort(revisions);
-        JsopBuilder buff = new JsopBuilder().array().newline();
+        JsopStream buff = new JsopStream().array().newline();
         for (Revision rev : revisions) {
             if (rev.getId() >= fromRev && rev.getId() <= toRev) {
                 rev.appendJournal(buff);
             }
         }
-        synchronized (this) {
-            lastJournalRevRange = revRange;
-            lastJournal = buff.endArray().toString();
-        }
-        return lastJournal;
+        return buff.endArray();
     }
 
-    public String diff(String fromRevisionId, String toRevisionId, String path) {
+    public JsopReader diffStream(String fromRevisionId, String toRevisionId, String path) {
         // TODO implement if required
-        return "";
+        return new JsopStream();
     }
 
     /**
      * Get the nodes. The following prefixes are supported:
-     * <ul><li>:pretty - beautify (format) the result
-     * </li><li>:root - get the root node (including all old revisions)
+     * <ul><li>:root - get the root node (including all old revisions)
      * </li><li>:info - get internal info such as the node count
      * </li></ul>
      *
@@ -431,11 +422,11 @@ public class MemoryKernelImpl implements
      * @param revisionId the revision
      * @return the json string
      */
-    public String getNodes(String path, String revisionId) {
-        return getNodes(path, revisionId, 1, 0, -1);
+    public JsopReader getNodesStream(String path, String revisionId) {
+        return getNodesStream(path, revisionId, 1, 0, -1);
     }
 
-    public String getNodes(String path, String revisionId, int depth, long offset, int count) {
+    public JsopReader getNodesStream(String path, String revisionId, int depth, long offset, int count) {
         // TODO offset > 0 should mean the properties are not included
         if (count < 0) {
             count = nodeMap.getMaxMemoryChildren();
@@ -445,11 +436,7 @@ public class MemoryKernelImpl implements
         }
         NodeImpl n;
         if (path.startsWith("/:")) {
-            if (path.startsWith("/:pretty")) {
-                return JsopBuilder.prettyPrint(
-                        getNodes("/" + PathUtils.relativize("/:pretty", path),
-                                revisionId, depth, offset, count));
-            } else if (path.startsWith("/:root")) {
+            if (path.startsWith("/:root")) {
                 n = getRoot().getNode(PathUtils.relativize("/:root", path));
             } else if (path.startsWith("/:info")) {
                 n = nodeMap.getInfo(PathUtils.relativize("/:info", path));
@@ -462,9 +449,9 @@ public class MemoryKernelImpl implements
         if (n == null) {
             throw ExceptionFactory.get("Path not found: " + path);
         }
-        JsopBuilder json = new JsopBuilder();
+        JsopStream json = new JsopStream();
         n.append(json, depth, offset, count, true);
-        return json.toString();
+        return json;
     }
 
     private NodeImpl getRevision(String revisionId) {

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeImpl.java?rev=1189796&r1=1189795&r2=1189796&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeImpl.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeImpl.java Thu Oct 27 15:00:15 2011
@@ -21,7 +21,9 @@ import java.util.Arrays;
 import java.util.Iterator;
 import org.apache.jackrabbit.mk.Constants;
 import org.apache.jackrabbit.mk.json.JsopBuilder;
+import org.apache.jackrabbit.mk.json.JsopReader;
 import org.apache.jackrabbit.mk.json.JsopTokenizer;
+import org.apache.jackrabbit.mk.json.JsopWriter;
 import org.apache.jackrabbit.mk.util.Cache;
 import org.apache.jackrabbit.mk.util.ExceptionFactory;
 import org.apache.jackrabbit.mk.util.PathUtils;
@@ -222,7 +224,7 @@ public class NodeImpl implements Cache.V
         return propertyValuePairs[index + 1];
     }
 
-    public void append(JsopBuilder json, int depth, long offset, int count, boolean childNodeCount) {
+    public void append(JsopWriter json, int depth, long offset, int count, boolean childNodeCount) {
         json.object();
         String[] pv = propertyValuePairs;
         if (pv != null) {
@@ -348,11 +350,11 @@ public class NodeImpl implements Cache.V
         return pairs;
     }
 
-    public static NodeImpl parse(NodeMap map, JsopTokenizer t, long revId) {
+    public static NodeImpl parse(NodeMap map, JsopReader t, long revId) {
         return parse(map, t, revId, null);
     }
 
-    public static NodeImpl parse(NodeMap map, JsopTokenizer t, long revId, String path) {
+    public static NodeImpl parse(NodeMap map, JsopReader t, long revId, String path) {
         NodeImpl node = new NodeImpl(map, revId);
         if (path != null) {
             node.setPath(path);
@@ -419,9 +421,9 @@ public class NodeImpl implements Cache.V
     }
 
     public String asString() {
-        JsopBuilder json = new JsopBuilder();
+        JsopWriter json = new JsopBuilder();
         json.setLineLength(120);
-        json.encodedValue(map.formatId(id)).appendTag("=");
+        json.encodedValue(map.formatId(id)).tag('=');
         json.object();
         String[] pv = propertyValuePairs;
         if (pv != null) {

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeList.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeList.java?rev=1189796&r1=1189795&r2=1189796&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeList.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeList.java Thu Oct 27 15:00:15 2011
@@ -17,7 +17,7 @@
 package org.apache.jackrabbit.mk.mem;
 
 import java.util.Iterator;
-import org.apache.jackrabbit.mk.json.JsopBuilder;
+import org.apache.jackrabbit.mk.json.JsopWriter;
 import org.apache.jackrabbit.mk.mem.NodeImpl.ChildVisitor;
 
 /**
@@ -43,7 +43,7 @@ interface NodeList {
 
     void visit(ChildVisitor v);
 
-    void append(JsopBuilder json, NodeMap map);
+    void append(JsopWriter json, NodeMap map);
 
     byte[] getNameFilter(NodeMap map);
 

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListLarge.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListLarge.java?rev=1189796&r1=1189795&r2=1189796&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListLarge.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListLarge.java Thu Oct 27 15:00:15 2011
@@ -18,8 +18,8 @@ package org.apache.jackrabbit.mk.mem;
 
 import java.util.ArrayList;
 import java.util.Iterator;
-import org.apache.jackrabbit.mk.json.JsopBuilder;
 import org.apache.jackrabbit.mk.json.JsopTokenizer;
+import org.apache.jackrabbit.mk.json.JsopWriter;
 import org.apache.jackrabbit.mk.mem.NodeImpl.ChildVisitor;
 import org.apache.jackrabbit.mk.util.ExceptionFactory;
 import org.apache.jackrabbit.mk.util.IOUtils;
@@ -230,7 +230,7 @@ public class NodeListLarge implements No
         }
     }
 
-    public void append(JsopBuilder json, NodeMap map) {
+    public void append(JsopWriter json, NodeMap map) {
         for (Child c : children) {
             json.key(":children");
             long x = c.id;

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListSmall.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListSmall.java?rev=1189796&r1=1189795&r2=1189796&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListSmall.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/NodeListSmall.java Thu Oct 27 15:00:15 2011
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.mk.mem;
 import java.util.Arrays;
 import java.util.Iterator;
 import org.apache.jackrabbit.mk.json.JsopBuilder;
+import org.apache.jackrabbit.mk.json.JsopWriter;
 import org.apache.jackrabbit.mk.mem.NodeImpl.ChildVisitor;
 import org.apache.jackrabbit.mk.util.ExceptionFactory;
 import org.apache.jackrabbit.mk.util.IOUtils;
@@ -142,7 +143,7 @@ public class NodeListSmall implements No
     }
 
     public String toString() {
-        JsopBuilder json = new JsopBuilder();
+        JsopWriter json = new JsopBuilder();
         json.object();
         for (int i = 0; i < size; i++) {
             json.key(names[i]).value(children[i]);
@@ -165,7 +166,7 @@ public class NodeListSmall implements No
         }
     }
 
-    public void append(JsopBuilder json, NodeMap map) {
+    public void append(JsopWriter json, NodeMap map) {
         for (int i = 0; i < size; i++) {
             json.key(names[i]);
             long x = children[i];

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java?rev=1189796&r1=1189795&r2=1189796&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/mem/Revision.java Thu Oct 27 15:00:15 2011
@@ -17,6 +17,7 @@
 package org.apache.jackrabbit.mk.mem;
 
 import org.apache.jackrabbit.mk.json.JsopBuilder;
+import org.apache.jackrabbit.mk.json.JsopWriter;
 import org.apache.jackrabbit.mk.util.Cache;
 import org.apache.jackrabbit.mk.json.JsopTokenizer;
 
@@ -115,7 +116,7 @@ public class Revision implements Compara
         return head.setChild("commit", commit, id);
     }
 
-    void appendJournal(JsopBuilder buff) {
+    void appendJournal(JsopWriter buff) {
         buff.object().
             key("id").value(Revision.formatId(id)).
             key("ts").value(time).

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/SecurityWrapper.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/SecurityWrapper.java?rev=1189796&r1=1189795&r2=1189796&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/SecurityWrapper.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/SecurityWrapper.java Thu Oct 27 15:00:15 2011
@@ -20,8 +20,10 @@ import java.io.InputStream;
 import org.apache.jackrabbit.mk.MicroKernelFactory;
 import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.mk.api.MicroKernelException;
-import org.apache.jackrabbit.mk.json.JsopBuilder;
+import org.apache.jackrabbit.mk.json.JsopReader;
+import org.apache.jackrabbit.mk.json.JsopStream;
 import org.apache.jackrabbit.mk.json.JsopTokenizer;
+import org.apache.jackrabbit.mk.json.JsopWriter;
 import org.apache.jackrabbit.mk.mem.NodeImpl;
 import org.apache.jackrabbit.mk.mem.NodeMap;
 import org.apache.jackrabbit.mk.util.ExceptionFactory;
@@ -39,9 +41,9 @@ import org.apache.jackrabbit.mk.util.Sim
  * This implementation is not meant for production, it is only used to find
  * (performance and other) problems when using such an approach.
  */
-public class SecurityWrapper implements MicroKernel {
+public class SecurityWrapper extends WrapperBase implements MicroKernel {
 
-    private final MicroKernel mk;
+    private final Wrapper mk;
     private final boolean admin, write;
     private final String[] userRights;
     private final NodeMap map = new NodeMap();
@@ -51,7 +53,7 @@ public class SecurityWrapper implements 
     private SecurityWrapper(MicroKernel mk, String[] rights) {
         // TODO reduce or eliminate json parsing + building
         // TODO make the index secure mechanism
-        this.mk = mk;
+        this.mk = WrapperBase.wrap(mk);
         this.userRights = rights;
         boolean isAdmin = false, canWrite = false;
         for (String r : rights) {
@@ -83,7 +85,7 @@ public class SecurityWrapper implements 
         try {
             String role = mk.getNodes("/:user/" + user, mk.getHeadRevision());
             NodeMap map = new NodeMap();
-            JsopTokenizer t = new JsopTokenizer(role);
+            JsopReader t = new JsopTokenizer(role);
             t.read('{');
             NodeImpl n = NodeImpl.parse(map, t, 0);
             String password = JsopTokenizer.decodeQuoted(n.getProperty("password"));
@@ -98,12 +100,12 @@ public class SecurityWrapper implements 
         }
     }
 
-    public String commit(String rootPath, String jsonDiff, String revisionId, String message) {
+    public String commitStream(String rootPath, JsopReader jsonDiff, String revisionId, String message) {
         checkRights(rootPath, true);
         if (!admin) {
             verifyDiff(jsonDiff, revisionId, rootPath, null);
         }
-        return mk.commit(rootPath, jsonDiff, revisionId, message);
+        return mk.commitStream(rootPath, jsonDiff, revisionId, message);
     }
 
     public void dispose() {
@@ -114,18 +116,17 @@ public class SecurityWrapper implements 
         return mk.getHeadRevision();
     }
 
-    public String getJournal(String fromRevisionId, String toRevisionId) {
+    public JsopReader getJournalStream(String fromRevisionId, String toRevisionId) {
         rightsRevision = getHeadRevision();
-        String journal = mk.getJournal(fromRevisionId, toRevisionId);
+        JsopReader t = mk.getJournalStream(fromRevisionId, toRevisionId);
         if (admin) {
-            return journal;
+            return t;
         }
-        JsopTokenizer t = new JsopTokenizer(journal);
         t.read('[');
         if (t.matches(']')) {
-            return journal;
+            return new JsopTokenizer("[]");
         }
-        JsopBuilder buff = new JsopBuilder();
+        JsopStream buff = new JsopStream();
         buff.array();
         String revision = fromRevisionId;
         do {
@@ -143,11 +144,11 @@ public class SecurityWrapper implements 
                 } else if (key.equals("changes")) {
                     t.read();
                     String value = t.getToken();
-                    value = filterDiff(value, revision);
+                    value = filterDiff(new JsopTokenizer(value), revision).toString();
                     buff.value(value);
                 } else {
                     String raw = t.readRawValue();
-                    System.out.println(key + ":" + raw);
+                    //System.out.println(key + ":" + raw);
                     buff.encodedValue(raw);
                 }
             } while (t.matches(','));
@@ -155,26 +156,25 @@ public class SecurityWrapper implements 
             t.read('}');
         } while (t.matches(','));
         buff.endArray();
-        return buff.toString();
+        return buff;
     }
 
-    public String diff(String fromRevisionId, String toRevisionId, String path) {
+    public JsopReader diffStream(String fromRevisionId, String toRevisionId, String path) {
         rightsRevision = getHeadRevision();
-        String diff = mk.diff(fromRevisionId, toRevisionId, path);
+        JsopReader diff = mk.diffStream(fromRevisionId, toRevisionId, path);
         if (admin) {
             return diff;
         }
         return filterDiff(diff, toRevisionId);
     }
 
-    private String filterDiff(String jsonDiff, String revisionId) {
-        JsopBuilder buff = new JsopBuilder();
-        verifyDiff(jsonDiff, revisionId, null, buff);
-        return buff.toString();
+    private JsopReader filterDiff(JsopReader t, String revisionId) {
+        JsopStream buff = new JsopStream();
+        verifyDiff(t, revisionId, null, buff);
+        return buff;
     }
 
-    private void verifyDiff(String jsonDiff, String revisionId, String rootPath, JsopBuilder diff) {
-        JsopTokenizer t = new JsopTokenizer(jsonDiff);
+    private void verifyDiff(JsopReader t, String revisionId, String rootPath, JsopWriter diff) {
         while (true) {
             int r = t.read();
             if (r == JsopTokenizer.END) {
@@ -192,7 +192,7 @@ public class SecurityWrapper implements 
                 if (t.matches('{')) {
                     NodeImpl n = NodeImpl.parse(map, t, 0);
                     if (checkDiff(path, diff)) {
-                        diff.appendTag("+ ").key(path);
+                        diff.tag('+').key(path);
                         n = filterAccess(path, n);
                         n.append(diff, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, false);
                         diff.newline();
@@ -202,7 +202,7 @@ public class SecurityWrapper implements 
                     String nodeName = PathUtils.getParentPath(path);
                     if (checkDiff(nodeName, diff)) {
                         if (checkPropertyRights(path)) {
-                            diff.appendTag("+ ").key(path);
+                            diff.tag('+').key(path);
                             diff.encodedValue(value);
                             diff.newline();
                         }
@@ -211,7 +211,7 @@ public class SecurityWrapper implements 
                 break;
             case '-':
                 if (checkDiff(path, diff)) {
-                    diff.appendTag("- ").value(path);
+                    diff.tag('-').value(path);
                     diff.newline();
                 }
                 break;
@@ -221,7 +221,7 @@ public class SecurityWrapper implements 
                 if (t.matches(JsopTokenizer.NULL)) {
                     if (checkDiff(path, diff)) {
                         if (checkPropertyRights(path)) {
-                            diff.appendTag("^ ").key(path).value(null);
+                            diff.tag('^').key(path).value(null);
                             diff.newline();
                         }
                     }
@@ -230,7 +230,7 @@ public class SecurityWrapper implements 
                     String nodeName = PathUtils.getParentPath(path);
                     if (checkDiff(nodeName, diff)) {
                         if (checkPropertyRights(path)) {
-                            diff.appendTag("^ ").key(path).encodedValue(value);
+                            diff.tag('^').key(path).encodedValue(value);
                             diff.newline();
                         }
                     }
@@ -256,7 +256,7 @@ public class SecurityWrapper implements 
                         target = PathUtils.getParentPath(to);
                     }
                     if (checkDiff(target, diff)) {
-                        diff.appendTag("> ").key(path);
+                        diff.tag('>').key(path);
                         diff.object().key(position);
                         diff.value(to).endObject();
                         diff.newline();
@@ -267,7 +267,7 @@ public class SecurityWrapper implements 
                         to = PathUtils.concat(rootPath, to);
                     }
                     if (checkDiff(to, diff)) {
-                        diff.appendTag("> ").key(path);
+                        diff.tag('>').key(path);
                         diff.value(to);
                         diff.newline();
                     }
@@ -279,7 +279,7 @@ public class SecurityWrapper implements 
         }
     }
 
-    private boolean checkDiff(String path, JsopBuilder target) {
+    private boolean checkDiff(String path, JsopWriter target) {
         if (checkRights(path, target == null)) {
             return target != null;
         } else if (target == null) {
@@ -292,24 +292,23 @@ public class SecurityWrapper implements 
         return mk.getLength(blobId);
     }
 
-    public String getNodes(String path, String revisionId) {
-        return getNodes(path, revisionId, 1, 0, -1);
+    public JsopReader getNodesStream(String path, String revisionId) {
+        return getNodesStream(path, revisionId, 1, 0, -1);
     }
 
-    public String getNodes(String path, String revisionId, int depth, long offset, int count) {
+    public JsopReader getNodesStream(String path, String revisionId, int depth, long offset, int count) {
         rightsRevision = getHeadRevision();
         if (!checkRights(path, false)) {
             throw ExceptionFactory.get("Node not found: " + path);
         }
-        String json = mk.getNodes(path, revisionId, depth, offset, count);
+        JsopReader t = mk.getNodesStream(path, revisionId, depth, offset, count);
         if (admin) {
-            return json;
+            return t;
         }
-        JsopTokenizer t = new JsopTokenizer(json);
         t.read('{');
         NodeImpl n = NodeImpl.parse(map, t, 0);
         n = filterAccess(path, n);
-        JsopBuilder buff = new JsopBuilder();
+        JsopStream buff = new JsopStream();
         if (n == null) {
             throw ExceptionFactory.get("Node not found: " + path);
         } else {
@@ -317,11 +316,11 @@ public class SecurityWrapper implements 
             // when count and offset are used
             n.append(buff, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, true);
         }
-        return buff.toString();
+        return buff;
     }
 
-    public String getRevisions(long since, int maxEntries) {
-        return mk.getRevisions(since, maxEntries);
+    public JsopReader getRevisionsStream(long since, int maxEntries) {
+        return mk.getRevisionsStream(since, maxEntries);
     }
 
     public boolean nodeExists(String path, String revisionId) {
@@ -392,7 +391,7 @@ public class SecurityWrapper implements 
             if (n == null) {
                 if (mk.nodeExists(path, rightsRevision)) {
                     String json = mk.getNodes(path, rightsRevision, 0, 0, 0);
-                    JsopTokenizer t = new JsopTokenizer(json);
+                    JsopReader t = new JsopTokenizer(json);
                     t.read('{');
                     n = NodeImpl.parse(map, t, 0);
                 } else {

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/VirtualRepositoryWrapper.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/VirtualRepositoryWrapper.java?rev=1189796&r1=1189795&r2=1189796&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/VirtualRepositoryWrapper.java (original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/VirtualRepositoryWrapper.java Thu Oct 27 15:00:15 2011
@@ -24,7 +24,9 @@ import org.apache.jackrabbit.mk.MicroKer
 import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.mk.api.MicroKernelException;
 import org.apache.jackrabbit.mk.json.JsopBuilder;
+import org.apache.jackrabbit.mk.json.JsopReader;
 import org.apache.jackrabbit.mk.json.JsopTokenizer;
+import org.apache.jackrabbit.mk.json.JsopWriter;
 import org.apache.jackrabbit.mk.mem.NodeImpl;
 import org.apache.jackrabbit.mk.mem.NodeMap;
 import org.apache.jackrabbit.mk.util.ExceptionFactory;
@@ -36,7 +38,7 @@ import org.apache.jackrabbit.mk.util.Pat
  * All mounted repositories contains the configuration as follows:
  * /:mount/rep1 { url: "mk:...", paths: "/a,/b" }.
  */
-public class VirtualRepositoryWrapper implements MicroKernel {
+public class VirtualRepositoryWrapper extends WrapperBase implements MicroKernel {
 
     private static final String PREFIX = "virtual:";
     private static final String MOUNT = "/:mount";
@@ -44,7 +46,7 @@ public class VirtualRepositoryWrapper im
     /**
      * The 'main' (wrapped) implementation.
      */
-    private final MicroKernel mk;
+    private final Wrapper mk;
 
     /**
      * Path map.
@@ -56,13 +58,13 @@ public class VirtualRepositoryWrapper im
      * Pending commit map.
      * Key: mount name, value: the builder that contains the pending commit.
      */
-    private final HashMap<String, JsopBuilder> builders = new HashMap<String, JsopBuilder>();
+    private final HashMap<String, JsopWriter> builders = new HashMap<String, JsopWriter>();
 
     /**
      * Mount map.
      * Key: mount name, value: microkernel implementation.
      */
-    private final HashMap<String, MicroKernel> mounts = new HashMap<String, MicroKernel>();
+    private final HashMap<String, Wrapper> mounts = new HashMap<String, Wrapper>();
 
     /**
      * Head revision map.
@@ -73,7 +75,7 @@ public class VirtualRepositoryWrapper im
     private final NodeMap map = new NodeMap();
 
     private VirtualRepositoryWrapper(MicroKernel mk) {
-        this.mk = mk;
+        this.mk = WrapperBase.wrap(mk);
     }
 
     public static synchronized VirtualRepositoryWrapper get(String url) {
@@ -85,7 +87,7 @@ public class VirtualRepositoryWrapper im
             if (mk.nodeExists(MOUNT, head)) {
                 String mounts = mk.getNodes(MOUNT, head);
                 NodeMap map = new NodeMap();
-                JsopTokenizer t = new JsopTokenizer(mounts);
+                JsopReader t = new JsopTokenizer(mounts);
                 t.read('{');
                 NodeImpl n = NodeImpl.parse(map, t, 0);
                 for (long pos = 0;; pos++) {
@@ -109,14 +111,13 @@ public class VirtualRepositoryWrapper im
 
     private void addMount(String mount, String url, String[] paths) {
         MicroKernel mk = MicroKernelFactory.getInstance(url);
-        mounts.put(mount, mk);
+        mounts.put(mount, WrapperBase.wrap(mk));
         for (String p : paths) {
             dir.put(p, mount);
         }
     }
 
-    public String commit(String rootPath, String jsonDiff, String revisionId, String message) {
-        JsopTokenizer t = new JsopTokenizer(jsonDiff);
+    public String commitStream(String rootPath, JsopReader t, String revisionId, String message) {
         while (true) {
             int r = t.read();
             if (r == JsopTokenizer.END) {
@@ -128,21 +129,21 @@ public class VirtualRepositoryWrapper im
                 t.read(':');
                 if (t.matches('{')) {
                     NodeImpl n = NodeImpl.parse(map, t, 0);
-                    JsopBuilder diff = new JsopBuilder();
-                    diff.appendTag("+ ").key(path);
+                    JsopWriter diff = new JsopBuilder();
+                    diff.tag('+').key(path);
                     n.append(diff, Integer.MAX_VALUE, 0, Integer.MAX_VALUE, false);
                     buffer(path, diff);
                 } else {
                     String value = t.readRawValue().trim();
-                    JsopBuilder diff = new JsopBuilder();
-                    diff.appendTag("+ ").key(path);
+                    JsopWriter diff = new JsopBuilder();
+                    diff.tag('+').key(path);
                     diff.encodedValue(value);
                     buffer(path, diff);
                 }
                 break;
             case '-': {
-                JsopBuilder diff = new JsopBuilder();
-                diff.appendTag("- ").value(path);
+                JsopWriter diff = new JsopBuilder();
+                diff.tag('-').value(path);
                 buffer(path, diff);
                 break;
             }
@@ -150,19 +151,19 @@ public class VirtualRepositoryWrapper im
                 t.read(':');
                 String value;
                 if (t.matches(JsopTokenizer.NULL)) {
-                    JsopBuilder diff = new JsopBuilder();
-                    diff.appendTag("^ ").key(path).value(null);
+                    JsopWriter diff = new JsopBuilder();
+                    diff.tag('^').key(path).value(null);
                     buffer(path, diff);
                 } else {
                     value = t.readRawValue().trim();
-                    JsopBuilder diff = new JsopBuilder();
-                    diff.appendTag("^ ").key(path).encodedValue(value);
+                    JsopWriter diff = new JsopBuilder();
+                    diff.tag('^').key(path).encodedValue(value);
                     buffer(path, diff);
                 }
                 break;
             case '>': {
                 t.read(':');
-                JsopBuilder diff = new JsopBuilder();
+                JsopWriter diff = new JsopBuilder();
                 if (t.matches('{')) {
                     String position = t.readString();
                     t.read(':');
@@ -171,7 +172,7 @@ public class VirtualRepositoryWrapper im
                     if (!PathUtils.isAbsolute(to)) {
                         to = PathUtils.concat(rootPath, to);
                     }
-                    diff.appendTag("> ").key(path);
+                    diff.tag('>').key(path);
                     diff.object().key(position);
                     diff.value(to).endObject();
                 } else {
@@ -179,7 +180,7 @@ public class VirtualRepositoryWrapper im
                     if (!PathUtils.isAbsolute(to)) {
                         to = PathUtils.concat(rootPath, to);
                     }
-                    diff.appendTag("> ").key(path);
+                    diff.tag('>').key(path);
                     diff.value(to);
                 }
                 buffer(path, diff);
@@ -190,7 +191,7 @@ public class VirtualRepositoryWrapper im
             }
         }
         String revision = null;
-        for (Entry<String, JsopBuilder> e : builders.entrySet()) {
+        for (Entry<String, JsopWriter> e : builders.entrySet()) {
             String mount = e.getKey();
             MicroKernel m = mounts.get(mount);
             String jsop = e.getValue().toString();
@@ -216,19 +217,19 @@ public class VirtualRepositoryWrapper im
         return null;
     }
 
-    private void buffer(String path, JsopBuilder diff) {
+    private void buffer(String path, JsopWriter diff) {
         String mount = getMount("/" + path);
         if (mount == null) {
             for (String m : mounts.keySet()) {
-                getBuilder(m).appendTag(diff.toString()).newline();
+                getBuilder(m).append(diff).newline();
             }
         } else {
-            getBuilder(mount).appendTag(diff.toString()).newline();
+            getBuilder(mount).append(diff).newline();
         }
     }
 
-    private JsopBuilder getBuilder(String mount) {
-        JsopBuilder builder = builders.get(mount);
+    private JsopWriter getBuilder(String mount) {
+        JsopWriter builder = builders.get(mount);
         if (builder == null) {
             builder = new JsopBuilder();
             builders.put(mount, builder);
@@ -246,7 +247,7 @@ public class VirtualRepositoryWrapper im
         StringBuilder buff = new StringBuilder();
         if (revisions.size() != mounts.size()) {
             revisions.clear();
-            for (Entry<String, MicroKernel> e : mounts.entrySet()) {
+            for (Entry<String, Wrapper> e : mounts.entrySet()) {
                 String m = e.getKey();
                 String r = e.getValue().getHeadRevision();
                 revisions.put(m, r);
@@ -263,30 +264,30 @@ public class VirtualRepositoryWrapper im
         return buff.toString();
     }
 
-    public String getJournal(String fromRevisionId, String toRevisionId) {
-        return mk.getJournal(fromRevisionId, toRevisionId);
+    public JsopReader getJournalStream(String fromRevisionId, String toRevisionId) {
+        return mk.getJournalStream(fromRevisionId, toRevisionId);
     }
 
-    public String diff(String fromRevisionId, String toRevisionId, String path) throws MicroKernelException {
-        return mk.diff(fromRevisionId, toRevisionId, path);
+    public JsopReader diffStream(String fromRevisionId, String toRevisionId, String path) throws MicroKernelException {
+        return mk.diffStream(fromRevisionId, toRevisionId, path);
     }
 
     public long getLength(String blobId) {
         return mk.getLength(blobId);
     }
 
-    public String getNodes(String path, String revisionId) {
-        return getNodes(path, revisionId, 1, 0, -1);
+    public JsopReader getNodesStream(String path, String revisionId) {
+        return getNodesStream(path, revisionId, 1, 0, -1);
     }
 
-    public String getNodes(String path, String revisionId, int depth, long offset, int count) {
+    public JsopReader getNodesStream(String path, String revisionId, int depth, long offset, int count) {
         String mount = getMount(path);
         if (mount == null) {
             throw ExceptionFactory.get("Not mapped: " + path);
         }
         String rev = getRevision(mount, revisionId);
-        MicroKernel mk = mounts.get(mount);
-        return mk.getNodes(path, rev, depth, offset, count);
+        Wrapper mk = mounts.get(mount);
+        return mk.getNodesStream(path, rev, depth, offset, count);
     }
 
     private String getRevision(String mount, String revisionId) {
@@ -298,8 +299,8 @@ public class VirtualRepositoryWrapper im
         throw ExceptionFactory.get("Unknown revision: " + revisionId + " mount: " + mount);
     }
 
-    public String getRevisions(long since, int maxEntries) {
-        return mk.getRevisions(since, maxEntries);
+    public JsopReader getRevisionsStream(long since, int maxEntries) {
+        return mk.getRevisionsStream(since, maxEntries);
     }
 
     public boolean nodeExists(String path, String revisionId) {

Added: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/Wrapper.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/Wrapper.java?rev=1189796&view=auto
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/Wrapper.java (added)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/Wrapper.java Thu Oct 27 15:00:15 2011
@@ -0,0 +1,37 @@
+/*
+ * 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.mk.wrapper;
+
+import org.apache.jackrabbit.mk.api.MicroKernel;
+import org.apache.jackrabbit.mk.api.MicroKernelException;
+import org.apache.jackrabbit.mk.json.JsopReader;
+
+public interface Wrapper extends MicroKernel {
+
+    JsopReader getRevisionsStream(long since, int maxEntries) throws MicroKernelException;
+
+    JsopReader getJournalStream(String fromRevisionId, String toRevisionId) throws MicroKernelException;
+
+    JsopReader getNodesStream(String path, String revisionId) throws MicroKernelException;
+
+    JsopReader getNodesStream(String path, String revisionId, int depth, long offset, int count) throws MicroKernelException;
+
+    String commitStream(String path, JsopReader jsonDiff, String revisionId, String message) throws MicroKernelException;
+
+    JsopReader diffStream(String fromRevisionId, String toRevisionId, String path);
+
+}

Added: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/WrapperBase.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/WrapperBase.java?rev=1189796&view=auto
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/WrapperBase.java (added)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/wrapper/WrapperBase.java Thu Oct 27 15:00:15 2011
@@ -0,0 +1,138 @@
+/*
+ * 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.mk.wrapper;
+
+import java.io.InputStream;
+import org.apache.jackrabbit.mk.api.MicroKernel;
+import org.apache.jackrabbit.mk.api.MicroKernelException;
+import org.apache.jackrabbit.mk.json.JsopReader;
+import org.apache.jackrabbit.mk.json.JsopTokenizer;
+
+public abstract class WrapperBase implements MicroKernel, Wrapper {
+
+    public final String commit(String path, String jsonDiff, String revisionId, String message) {
+        return commitStream(path, new JsopTokenizer(jsonDiff), revisionId, message);
+    }
+
+    public final String getJournal(String fromRevisionId, String toRevisionId) {
+        return getJournalStream(fromRevisionId, toRevisionId).toString();
+    }
+
+    public final String getNodes(String path, String revisionId) {
+        return getNodesStream(path, revisionId).toString();
+    }
+
+    public final String getNodes(String path, String revisionId, int depth, long offset, int count) {
+        return getNodesStream(path, revisionId, depth, offset, count).toString();
+    }
+
+    public final String diff(String fromRevisionId, String toRevisionId, String path) {
+        return diffStream(fromRevisionId, toRevisionId, path).toString();
+    }
+
+    public final String getRevisions(long since, int maxEntries) {
+        return getRevisionsStream(since, maxEntries).toString();
+    }
+
+    public static Wrapper wrap(final MicroKernel mk) {
+        if (mk instanceof Wrapper) {
+            return (Wrapper) mk;
+        }
+        return new Wrapper() {
+
+            MicroKernel wrapped = mk;
+
+            public String commitStream(String path, JsopReader jsonDiff, String revisionId, String message) {
+                return wrapped.commit(path, jsonDiff.toString(), revisionId, message);
+            }
+
+            public JsopReader getJournalStream(String fromRevisionId, String toRevisionId) {
+                return new JsopTokenizer(wrapped.getJournal(fromRevisionId, toRevisionId));
+            }
+
+            public JsopReader getNodesStream(String path, String revisionId) {
+                return new JsopTokenizer(wrapped.getNodes(path, revisionId));
+            }
+
+            public JsopReader getNodesStream(String path, String revisionId, int depth, long offset, int count) {
+                return new JsopTokenizer(wrapped.getNodes(path, revisionId, depth, offset, count));
+            }
+
+            public JsopReader getRevisionsStream(long since, int maxEntries) {
+                return new JsopTokenizer(wrapped.getRevisions(since, maxEntries));
+            }
+
+            public JsopReader diffStream(String fromRevisionId, String toRevisionId, String path) {
+                return new JsopTokenizer(wrapped.diff(fromRevisionId, toRevisionId, path));
+            }
+
+            public String commit(String path, String jsonDiff, String revisionId, String message) {
+                return wrapped.commit(path, jsonDiff, revisionId, message);
+            }
+
+            public String diff(String fromRevisionId, String toRevisionId, String path) {
+                return wrapped.diff(fromRevisionId, toRevisionId, path);
+            }
+
+            public void dispose() {
+                wrapped.dispose();
+            }
+
+            public String getHeadRevision() throws MicroKernelException {
+                return wrapped.getHeadRevision();
+            }
+
+            public String getJournal(String fromRevisionId, String toRevisionId) {
+                return wrapped.getJournal(fromRevisionId, toRevisionId);
+            }
+
+            public long getLength(String blobId) {
+                return wrapped.getLength(blobId);
+            }
+
+            public String getNodes(String path, String revisionId) {
+                return wrapped.getNodes(path, revisionId);
+            }
+
+            public String getNodes(String path, String revisionId, int depth, long offset, int count) {
+                return wrapped.getNodes(path, revisionId, depth, offset, count);
+            }
+
+            public String getRevisions(long since, int maxEntries) {
+                return wrapped.getRevisions(since, maxEntries);
+            }
+
+            public boolean nodeExists(String path, String revisionId) {
+                return wrapped.nodeExists(path, revisionId);
+            }
+
+            public int read(String blobId, long pos, byte[] buff, int off, int length) {
+                return wrapped.read(blobId, pos, buff, off, length);
+            }
+
+            public String waitForCommit(String oldHeadRevision, long maxWaitMillis) throws InterruptedException {
+                return wrapped.waitForCommit(oldHeadRevision, maxWaitMillis);
+            }
+
+            public String write(InputStream in) {
+                return wrapped.write(in);
+            }
+
+        };
+    }
+
+}

Modified: jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/MoveNodeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/MoveNodeTest.java?rev=1189796&r1=1189795&r2=1189796&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/MoveNodeTest.java (original)
+++ jackrabbit/sandbox/microkernel/src/test/java/org/apache/jackrabbit/mk/MoveNodeTest.java Thu Oct 27 15:00:15 2011
@@ -55,7 +55,7 @@ public class MoveNodeTest extends MultiM
         // add a property /test/c
         commit("/", "+ \"test/c\": 123");
         Assert.assertEquals("{c:123,a,b,c}", getNode("/test"));
-        assertJournal("+ \"/test/c\":123");
+        assertJournal("+\"/test/c\":123");
 
         // duplicate add property should fail
         try {
@@ -81,12 +81,12 @@ public class MoveNodeTest extends MultiM
         // rename /test/b
         commit("/", "> \"test/b\": \"test/b1\"");
         Assert.assertEquals("{a,b1,c}", getNode("/test"));
-        assertJournal("> \"/test/b\":\"/test/b1\"");
+        assertJournal(">\"/test/b\":\"/test/b1\"");
 
         // and back
         commit("/", "> \"test/b1\": \"test/b\"");
         Assert.assertEquals("{a,b,c}", getNode("/test"));
-        assertJournal("> \"/test/b1\":\"/test/b\"");
+        assertJournal(">\"/test/b1\":\"/test/b\"");
     }
 
     @Test
@@ -98,12 +98,12 @@ public class MoveNodeTest extends MultiM
         // order c before b
         commit("/", "> \"test/c\": {\"before\": \"test/b\"}");
         Assert.assertEquals("{a,c,b}", getNode("/test"));
-        assertJournal("> \"/test/c\":{\"before\":\"/test/b\"}");
+        assertJournal(">\"/test/c\":{\"before\":\"/test/b\"}");
 
         // and now b before a
         commit("/", "> \"test/b\": {\"before\": \"test/a\"}");
         Assert.assertEquals("{b,a,c}", getNode("/test"));
-        assertJournal("> \"/test/b\":{\"before\":\"/test/a\"}");
+        assertJournal(">\"/test/b\":{\"before\":\"/test/a\"}");
     }
 
     @Test
@@ -115,17 +115,17 @@ public class MoveNodeTest extends MultiM
         // order a after b
         commit("/", "> \"test/a\": {\"after\": \"test/b\"}");
         Assert.assertEquals("{b,a,c}", getNode("/test"));
-        assertJournal("> \"/test/a\":{\"after\":\"/test/b\"}");
+        assertJournal(">\"/test/a\":{\"after\":\"/test/b\"}");
 
         // and now a after c
         commit("/", "> \"test/a\": {\"after\": \"test/c\"}");
         Assert.assertEquals("{b,c,a}", getNode("/test"));
-        assertJournal("> \"/test/a\":{\"after\":\"/test/c\"}");
+        assertJournal(">\"/test/a\":{\"after\":\"/test/c\"}");
 
         // and now a after a (a no-op)
         commit("/", "> \"test/a\": {\"after\": \"test/a\"}");
         Assert.assertEquals("{b,c,a}", getNode("/test"));
-        assertJournal("> \"/test/a\":{\"after\":\"/test/a\"}");
+        assertJournal(">\"/test/a\":{\"after\":\"/test/a\"}");
     }
 
     @Test
@@ -138,13 +138,13 @@ public class MoveNodeTest extends MultiM
         commit("/", "> \"test/a\": {\"first\": \"test2\"}");
         Assert.assertEquals("{b,c}", getNode("/test"));
         Assert.assertEquals("{a}", getNode("/test2"));
-        assertJournal("> \"/test/a\":{\"first\":\"/test2\"}");
+        assertJournal(">\"/test/a\":{\"first\":\"/test2\"}");
 
         // move /test/c to /test2
         commit("/", "> \"test/c\": {\"first\": \"test2\"}");
         Assert.assertEquals("{b}", getNode("/test"));
         Assert.assertEquals("{c,a}", getNode("/test2"));
-        assertJournal("> \"/test/c\":{\"first\":\"/test2\"}");
+        assertJournal(">\"/test/c\":{\"first\":\"/test2\"}");
     }
 
     @Test
@@ -157,13 +157,15 @@ public class MoveNodeTest extends MultiM
         commit("/", "> \"test/b\": \"test_b\"");
         Assert.assertEquals("{a,c}", getNode("/test"));
         Assert.assertEquals("{}", getNode("/test_b"));
-        assertJournal("> \"/test/b\":\"/test_b\"");
+        assertJournal(">\"/test/b\":\"/test_b\"");
 
         // move /test/a to /test_a, combined with adding a property
         commit("/", "> \"test/a\": \"test_a\" ^ \"test_a/x\": 1");
         Assert.assertEquals("{c}", getNode("/test"));
         Assert.assertEquals("{x:1}", getNode("/test_a"));
-        assertJournal("> \"/test/a\":\"/test_a\"\n+ \"/test_a/x\":1");
+        assertJournal(
+                ">\"/test/a\":\"/test_a\"\n"+
+                "+\"/test_a/x\":1");
     }
 
     @Test
@@ -176,13 +178,13 @@ public class MoveNodeTest extends MultiM
         commit("/", "> \"test/b\": {\"first\": \"test2\"}");
         Assert.assertEquals("{a,c}", getNode("/test"));
         Assert.assertEquals("{b}", getNode("/test2"));
-        assertJournal("> \"/test/b\":{\"first\":\"/test2\"}");
+        assertJournal(">\"/test/b\":{\"first\":\"/test2\"}");
 
         // move /test/c to /test2, before b
         commit("/", "> \"test/c\": {\"before\": \"test2/b\"}");
         Assert.assertEquals("{a}", getNode("/test"));
         Assert.assertEquals("{c,b}", getNode("/test2"));
-        assertJournal("> \"/test/c\":{\"before\":\"/test2/b\"}");
+        assertJournal(">\"/test/c\":{\"before\":\"/test2/b\"}");
     }
 
     @Test
@@ -195,19 +197,19 @@ public class MoveNodeTest extends MultiM
         commit("/", "> \"test/c\": \"test2/c\"");
         Assert.assertEquals("{a,b}", getNode("/test"));
         Assert.assertEquals("{c}", getNode("/test2"));
-        assertJournal("> \"/test/c\":\"/test2/c\"");
+        assertJournal(">\"/test/c\":\"/test2/c\"");
 
         // move /test/a to /test2, after c
         commit("/", "> \"test/a\": {\"after\": \"test2/c\"}");
         Assert.assertEquals("{b}", getNode("/test"));
         Assert.assertEquals("{c,a}", getNode("/test2"));
-        assertJournal("> \"/test/a\":{\"after\":\"/test2/c\"}");
+        assertJournal(">\"/test/a\":{\"after\":\"/test2/c\"}");
 
         // move /test/b to /test2, after c
         commit("/", "> \"test/b\": {\"after\": \"test2/c\"}");
         Assert.assertEquals("{}", getNode("/test"));
         Assert.assertEquals("{c,b,a}", getNode("/test2"));
-        assertJournal("> \"/test/b\":{\"after\":\"/test2/c\"}");
+        assertJournal(">\"/test/b\":{\"after\":\"/test2/c\"}");
     }
 
     @Test
@@ -220,13 +222,13 @@ public class MoveNodeTest extends MultiM
         commit("/", "> \"test/b\": {\"last\": \"test2\"}");
         Assert.assertEquals("{a,c}", getNode("/test"));
         Assert.assertEquals("{b}", getNode("/test2"));
-        assertJournal("> \"/test/b\":{\"last\":\"/test2\"}");
+        assertJournal(">\"/test/b\":{\"last\":\"/test2\"}");
 
         // move /test/c to /test2, as last
         commit("/", "> \"test/c\": {\"last\": \"test2\"}");
         Assert.assertEquals("{a}", getNode("/test"));
         Assert.assertEquals("{b,c}", getNode("/test2"));
-        assertJournal("> \"/test/c\":{\"last\":\"/test2\"}");
+        assertJournal(">\"/test/c\":{\"last\":\"/test2\"}");
     }
 
     @Test
@@ -235,19 +237,19 @@ public class MoveNodeTest extends MultiM
         commit("/", "> \"test/b\": \"/test2/b\"");
         Assert.assertEquals("{a,c}", getNode("/test"));
         Assert.assertEquals("{b}", getNode("/test2"));
-        assertJournal("> \"/test/b\":\"/test2/b\"");
+        assertJournal(">\"/test/b\":\"/test2/b\"");
 
         // move /test/a to /test2
         commit("/", "> \"test/a\": \"test2/a1\"");
         Assert.assertEquals("{c}", getNode("/test"));
         Assert.assertEquals("{b,a1}", getNode("/test2"));
-        assertJournal("> \"/test/a\":\"/test2/a1\"");
+        assertJournal(">\"/test/a\":\"/test2/a1\"");
 
         // move /test/c to /test2
         commit("/", "> \"test/c\": \"test2/c\"");
         Assert.assertEquals("{}", getNode("/test"));
         Assert.assertEquals("{b,a1,c}", getNode("/test2"));
-        assertJournal("> \"/test/c\":\"/test2/c\"");
+        assertJournal(">\"/test/c\":\"/test2/c\"");
     }
 
     private void commit(String root, String diff) {