jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ste...@apache.org
Subject svn commit: r1097528 - in /jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk: MicroKernelImpl.java json/ json/DiffHandler.java json/DiffParser.java store/CommitBuilder.java
Date Thu, 28 Apr 2011 16:16:20 GMT
Author: stefan
Date: Thu Apr 28 16:16:20 2011
New Revision: 1097528

URL: http://svn.apache.org/viewvc?rev=1097528&view=rev
Log:
MicroKernel prototype (WIP)

Added:
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/DiffHandler.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/DiffParser.java
Modified:
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/MicroKernelImpl.java
    jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/store/CommitBuilder.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=1097528&r1=1097527&r2=1097528&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 Apr 28 16:16:20 2011
@@ -18,11 +18,21 @@ package org.apache.jackrabbit.mk;
 
 import org.apache.jackrabbit.mk.api.MicroKernel;
 import org.apache.jackrabbit.mk.api.MicroKernelException;
+import org.apache.jackrabbit.mk.json.DiffHandler;
+import org.apache.jackrabbit.mk.json.DiffParser;
 import org.apache.jackrabbit.mk.store.Commit;
+import org.apache.jackrabbit.mk.store.CommitBuilder;
 import org.apache.jackrabbit.mk.store.Node;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.ContainerFactory;
+import org.json.simple.parser.JSONParser;
 
 import java.io.InputStream;
 import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
@@ -140,7 +150,8 @@ public class MicroKernelImpl implements 
 
         try {
             StringBuffer buf = new StringBuffer();
-            toJson(rep.getNode(revisionId, path), depth, buf);
+            String name =  path.substring(path.lastIndexOf('/') + 1);
+            toJson(rep.getNode(revisionId, path), name, depth, buf);
             return buf.toString();
         } catch (Exception e) {
             throw new MicroKernelException(e);
@@ -152,9 +163,28 @@ public class MicroKernelImpl implements 
             throw new IllegalStateException("this instance has already been disposed");
         }
 
-        // todo implement
-
-        return null;
+        try {
+            Node node = rep.getNode(revisionId, path);
+            StringBuffer buf = new StringBuffer();
+            buf.append('[');
+            long pos = 0;
+            for (Map.Entry<String, String> entry : node.getChildNodeEntries().entrySet())
{
+                if (pos < offset) {
+                    pos++;
+                    continue;
+                }
+                if (pos - offset > count) {
+                    break;
+                }
+                toJson(rep.getStore().getNode(entry.getValue()), entry.getKey(), depth, buf);
+                buf.append(',');
+                pos++;
+            }
+            buf.append(']');
+            return buf.toString();
+        } catch (Exception e) {
+            throw new MicroKernelException(e);
+        }
     }
 
     public long getChildNodeCount(String path, String revisionId) throws MicroKernelException
{
@@ -169,14 +199,66 @@ public class MicroKernelImpl implements 
         }
     }
 
-    public String commit(String path, String jsonDiff, String revisionId) throws MicroKernelException
{
+    public String commit(final String path, String jsonDiff, String revisionId) throws MicroKernelException
{
         if (rep == null) {
             throw new IllegalStateException("this instance has already been disposed");
         }
 
-        // todo implement
+        String newHeadRev;
+        try {
+            final CommitBuilder cb = rep.getCommitBuilder(revisionId);
+            final JSONParser jsonParser = new JSONParser();
+            final ContainerFactory containerFactory = new ContainerFactory() {
+                public List creatArrayContainer() {
+                    return new LinkedList();
+                }
 
-        return null;
+                public Map createObjectContainer() {
+                    return new LinkedHashMap();
+                }
+            };
+
+            DiffHandler handler = new DiffHandler() {
+
+                public void addNode(String nodeName, String jsonObject) throws Exception
{
+                    Object obj = jsonParser.parse(jsonObject, containerFactory);
+                    if (!(obj instanceof JSONObject)) {
+                        throw new Exception("illegal json object format: " + jsonObject);
+                    }
+                    JSONObject jsonNode = (JSONObject) obj;
+                    Map<String, String> props = new HashMap<String, String>();
+
+                    for (Iterator it = jsonNode.entrySet().iterator(); it.hasNext(); ) {
+                        Map.Entry entry = (Map.Entry) it.next();
+                        if (! (entry.getValue() instanceof JSONObject)) {
+                            props.put((String) entry.getKey(), entry.getValue().toString());
+                        }
+                    }
+                    cb.addNode(path, nodeName, props);
+                    // todo support nested json objects
+                }
+
+                public void setProperty(String propName, String propValue) throws Exception
{
+                    cb.setProperty(path, propName, propValue);
+                }
+
+                public void remove(String nodeName) throws Exception {
+                    cb.removeNode(nodeName);
+                }
+
+                public void move(String nodeName, String targetPath) throws Exception {
+                    cb.moveNode((path.equals("/") ? path : path + "/") + nodeName, targetPath);
+                }
+            };
+            DiffParser parser = new DiffParser(handler);
+            parser.parse(jsonDiff);
+
+            newHeadRev = cb.doCommit();
+        } catch (Exception e) {
+            throw new MicroKernelException(e);
+        }
+
+        return newHeadRev;
     }
 
     public long getLength(String blobId) throws MicroKernelException {
@@ -211,14 +293,15 @@ public class MicroKernelImpl implements 
 
     //-------------------------------------------------------< implementation >
 
-    void toJson(Node node, int depth, StringBuffer buf) throws Exception {
+    void toJson(Node node, String name, int depth, StringBuffer buf) throws Exception {
         buf.append("{");
+        buf.append("\":name\":\"" + name + "\",");
         for (Map.Entry prop : node.getProperties().entrySet()) {
             buf.append('"');
             buf.append(prop.getKey());
             buf.append("\":\"");
             buf.append(prop.getValue());
-            buf.append("\",");
+            buf.append("\"");
         }
 
         buf.append("\":childNodeCount\":\"");
@@ -230,10 +313,11 @@ public class MicroKernelImpl implements 
             buf.append(',');
             for (Map.Entry<String, String> child : node.getChildNodeEntries().entrySet())
{
                 buf.append('"');
-                buf.append(child.getKey());
+                String childName = child.getKey();
+                buf.append(childName);
                 buf.append("\":");
                 String childId = child.getValue();
-                toJson(rep.getStore().getNode(childId), depth, buf);
+                toJson(rep.getStore().getNode(childId), childName, depth, buf);
             }
         }
         buf.append("}");

Added: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/DiffHandler.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/DiffHandler.java?rev=1097528&view=auto
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/DiffHandler.java
(added)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/DiffHandler.java
Thu Apr 28 16:16:20 2011
@@ -0,0 +1,34 @@
+/*
+ * 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;
+
+/**
+ * <code>DiffHandler</code>...
+ *
+ * copied from http://svn.apache.org/repos/asf/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffHandler.java
+ * with minor modifications
+ */
+public interface DiffHandler {
+
+    void addNode(String nodeName, String jsonObject) throws Exception;
+
+    void setProperty(String propName, String propValue) throws Exception;
+
+    void remove(String nodeName) throws Exception;
+
+    void move(String nodeName, String targetPath) throws Exception;
+}

Added: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/DiffParser.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/DiffParser.java?rev=1097528&view=auto
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/DiffParser.java
(added)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/json/DiffParser.java
Thu Apr 28 16:16:20 2011
@@ -0,0 +1,241 @@
+/*
+ * 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;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+
+/** <code>DiffParser</code>...
+ *
+ * copied from http://svn.apache.org/repos/asf/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/server/remoting/davex/DiffParser.java
+ * with minor modifications
+ */
+public class DiffParser {
+
+    // TODO: review again: currently all line-sep. chars before an diff-char are
+    // TODO: ignored unless they are escaped in way the handler understands (e.g.
+    // TODO: JSON does: \\r for \r).
+    // TODO: in contrast line sep. at the end of the string are treated as value.
+    // TODO: ... similar: line sep. following by non-diff symbol.
+
+    private final DiffHandler handler;
+
+    private static final int EOF = -1;
+
+    private static final char SYMBOL_ADD_NODE = '+';
+    private static final char SYMBOL_MOVE = '>';
+    private static final char SYMBOL_REMOVE = '-';
+    private static final char SYMBOL_SET_PROPERTY = '^';
+
+    private static final int STATE_START_LINE = 0;
+    private static final int STATE_START_TARGET = 1;
+    private static final int STATE_TARGET = 2;
+    private static final int STATE_START_VALUE = 3;
+    private static final int STATE_VALUE = 4;
+
+    /**
+     *
+     * @param handler
+     */
+    public DiffParser(DiffHandler handler) {
+        this.handler = handler;
+    }
+
+    /**
+     *
+     * @param str
+     * @throws IOException
+     * @throws Exception
+     */
+    public void parse(String str) throws IOException, Exception {
+        parse(new BufferedReader(new StringReader(str)));
+    }
+
+    /**
+     *
+     * @param input
+     * @param charSetName
+     * @throws IOException
+     * @throws Exception
+     */
+    public void parse(InputStream input, String charSetName) throws IOException, Exception
{
+        parse(new BufferedReader(new InputStreamReader(input, charSetName)));
+    }
+
+    /**
+     *
+     * @param reader
+     * @throws IOException
+     * @throws Exception
+     */
+    public void parse(Reader reader) throws IOException, Exception {
+        int action = -1;
+        String path = null;
+
+        StringBuffer lineSeparator = null;
+        StringBuffer bf = null;
+
+        int state = STATE_START_LINE;
+        int next = reader.read();
+
+        while (next != EOF) {
+            switch (state) {
+                case STATE_START_LINE:
+                    if (isSymbol(next)) {
+                        // notify the last action read
+                        if (action > -1) {
+                            informAction(action, path, bf);
+                        }
+                        // ... and  start recording the next action
+                        action = next;
+                        bf = null;
+                        lineSeparator = null;
+                        state = STATE_START_TARGET;
+                    } else if (isLineSeparator(next)) {
+                        // still line-separator -> append c to the lineSeparator
+                        // buffer and keep state set to STATE_START_LINE
+                        if (lineSeparator == null) {
+                            throw new Exception("Invalid start of new line.");
+                        } else {
+                            lineSeparator.append((char) next);
+                        }
+                    } else if (lineSeparator != null && bf != null) {
+                        // append the collected return/linefeed chars as part
+                        // of the value read and continued reading value.
+                        bf.append(lineSeparator);
+                        bf.append((char) next);
+                        lineSeparator = null;
+                        state = STATE_VALUE;
+                    } else {
+                        throw new Exception("Invalid start of new line.");
+                    }
+                    break;
+
+                case STATE_START_TARGET:
+                    if (Character.isWhitespace((char) next) || next == ':') {
+                        throw new Exception("Invalid start of target path '" + next + "'");
+                    }
+                    bf = new StringBuffer();
+                    bf.append((char) next);
+                    state = STATE_TARGET;
+                    break;
+
+                case STATE_TARGET:
+                    if (Character.isWhitespace((char) next) && endsWithDelim(bf))
{
+                        // a sequence of 'wsp:wsp' indicates the delimiter between
+                        // the target path and the diff value.
+                        path = bf.substring(0, bf.lastIndexOf(":")).trim();
+                        state = STATE_START_VALUE;
+                        // reset buffer
+                        bf = null;
+                    } else {
+                        // continue reading the path into the buffer.
+                        bf.append((char) next);
+                    }
+                    break;
+
+                case STATE_START_VALUE:
+                    if (isLineSeparator(next)) {
+                        lineSeparator = new StringBuffer();
+                        lineSeparator.append((char) next);
+                        bf = new StringBuffer();
+                        state = STATE_START_LINE;
+                    } else {
+                        bf = new StringBuffer();
+                        bf.append((char) next);
+                        state = STATE_VALUE;
+                    }
+                    break;
+
+                case STATE_VALUE:
+                    if (isLineSeparator(next)) {
+                        lineSeparator = new StringBuffer();
+                        lineSeparator.append((char) next);
+                        state = STATE_START_LINE;
+                    } else {
+                        bf.append((char) next);
+                        // keep state set to STATE_VALUE
+                    }
+                    break;
+
+            }
+            // read the next character.
+            next = reader.read();
+        }
+
+        // a diff ending after a command or within the target is invalid.
+        if (state == STATE_START_TARGET || state == STATE_TARGET) {
+            throw new Exception("Invalid end of DIFF string: missing separator and value.");
+        }
+        if (state == STATE_START_VALUE ) {
+            // line separator AND buffer must be null
+            if (!(lineSeparator == null && bf == null)) {
+                throw new Exception("Invalid end of DIFF string.");
+            }
+        }
+
+        // append eventual remaining line-separators to the value
+        if (lineSeparator != null) {
+            bf.append(lineSeparator);
+        }
+        // notify the last action read
+        informAction(action, path, bf);
+    }
+
+    private void informAction(int action, String path, StringBuffer diffVal) throws Exception
{
+        if (path == null) {
+            throw new Exception("Missing path for action " + action + "(diffValue = '"+ diffVal
+"')");
+        }
+        String value = (diffVal == null) ? null : diffVal.toString();
+        switch (action) {
+            case SYMBOL_ADD_NODE:
+                handler.addNode(path, value);
+                break;
+            case SYMBOL_SET_PROPERTY:
+                handler.setProperty(path, value);
+                break;
+            case SYMBOL_MOVE:
+                handler.move(path, value);
+                break;
+            case SYMBOL_REMOVE:
+                handler.remove(path);
+                break;
+            default:
+                throw new Exception("Invalid action " + action);
+        }
+    }
+
+    private static boolean isSymbol(int c) {
+        return c == SYMBOL_ADD_NODE || c == SYMBOL_SET_PROPERTY || c == SYMBOL_MOVE || c
== SYMBOL_REMOVE;
+    }
+
+    private static boolean isLineSeparator(int c) {
+        return c == '\n' || c == '\r';
+
+    }
+    private static boolean endsWithDelim(StringBuffer bf) {
+        if (bf.length() < 2) {
+            return false;
+        } else {
+            return ':' == bf.charAt(bf.length()-1) && Character.isWhitespace(bf.charAt(bf.length()-2));
+        }
+    }
+}

Modified: jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/store/CommitBuilder.java
URL: http://svn.apache.org/viewvc/jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/store/CommitBuilder.java?rev=1097528&r1=1097527&r2=1097528&view=diff
==============================================================================
--- jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/store/CommitBuilder.java
(original)
+++ jackrabbit/sandbox/microkernel/src/main/java/org/apache/jackrabbit/mk/store/CommitBuilder.java
Thu Apr 28 16:16:20 2011
@@ -137,7 +137,12 @@ public class CommitBuilder {
         changeLog.add(new SetProperty(nodePath, propName, propValue));
     }
 
+    public void setProperty(String nodePath, String propName, String[] propValues) throws
Exception {
+        // todo support MVPs
+    }
+
     public void setProperties(String nodePath, Map<String, String> properties) throws
Exception {
+        // todo support MVPs
         MutableNode node = getOrCreateStagedNode(nodePath);
 
         node.getProperties().clear();



Mime
View raw message