jackrabbit-oak-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mdue...@apache.org
Subject svn commit: r1407119 [6/9] - in /jackrabbit/oak/trunk: ./ oak-core/src/main/java/org/apache/jackrabbit/oak/security/user/ oak-it/mk/src/main/java/org/apache/jackrabbit/mk/test/ oak-mk-perf/ oak-mk-perf/src/main/java/org/apache/jackrabbit/mk/tasks/ oak-...
Date Thu, 08 Nov 2012 15:18:02 GMT
Modified: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/NodeImpl.java?rev=1407119&r1=1407118&r2=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/NodeImpl.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/NodeImpl.java Thu Nov  8 15:17:50 2012
@@ -16,72 +16,40 @@
  */
 package org.apache.jackrabbit.mongomk.impl.model;
 
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.HashMap;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.jackrabbit.mk.model.ChildNodeEntry;
+import org.apache.jackrabbit.mk.model.NodeDiffHandler;
 import org.apache.jackrabbit.mk.util.RangeIterator;
 import org.apache.jackrabbit.mongomk.api.model.Node;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 
-
 /**
  * Implementation of {@link Node}.
- *
- * @author <a href="mailto:pmarx@adobe.com>Philipp Marx</a>
  */
 public class NodeImpl implements Node {
 
     private static final List<Node> EMPTY = Collections.emptyList();
 
-    private long childCount;
-    private Map<String, Node> children;
-    private String name;
+    private Map<String, Node> childEntries;
     private String path;
-    private Map<String, Object> properties;
+    private Map<String, String> properties;
     private Long revisionId;
 
     /**
      * Constructs a new {@code NodeImpl}.
-     */
-    public NodeImpl() {
-    }
-
-    /**
-     * Constructs a new {@code NodeImpl}.
      *
      * @param path The path.
      */
     public NodeImpl(String path) {
-        this(path, (Set<Node>) null, null);
-    }
-
-    /**
-     * Constructs a new {@code NodeImpl}.
-     *
-     * @param path The path.
-     * @param children The children.
-     */
-    public NodeImpl(String path, Node[] children) {
-        this(path, new HashSet<Node>(Arrays.asList(children)), null);
-    }
-
-    /**
-     * Constructs a new {@code NodeImpl}.
-     *
-     * @param path The path.
-     * @param children The children.
-     * @param properties The properties.
-     */
-    public NodeImpl(String path, Set<Node> children, Map<String, Object> properties) {
-        setPath(path);
-        setChildren(children);
-        setProperties(properties);
+        this.path = path;
+        this.childEntries = new HashMap<String, Node>();
+        this.properties = new HashMap<String, String>();
     }
 
     /**
@@ -89,90 +57,53 @@ public class NodeImpl implements Node {
      *
      * @param child The {@code node} to add.
      */
-    public void addChild(Node child) {
-        if (children == null) {
-            children = new HashMap<String, Node>();
-        }
-
-        children.put(child.getName(), child);
+    public void addChildNodeEntry(Node child) {
+        String childName = PathUtils.getName(child.getPath());
+        childEntries.put(childName, child);
     }
 
     @Override
-    public long getChildCount() {
-        return childCount;
-    }
-
-    /**
-     * Sets the child count.
-     *
-     * @param childCount The child count.
-     */
-    public void setChildCount(long childCount) {
-        this.childCount = childCount;
+    public Node getChildNodeEntry(String name) {
+        return childEntries.get(name);
     }
 
     @Override
-    public Set<Node> getChildren() {
-        return this.children != null? Collections.unmodifiableSet(new HashSet<Node>(this.children.values()))
-                : null;
+    public int getChildNodeCount() {
+        return childEntries.size();
     }
 
-    /**
-     * Sets the children.
-     *
-     * @param children The children or null.
-     */
-    public void setChildren(Set<Node> children) {
-        if (children == null) {
-            this.children = null;
-            return;
-        }
-
-        this.children = new HashMap<String, Node>();
-        for (Node child : children) {
-            this.children.put(child.getName(), child);
-        }
-    }
-
-    public Iterator<Node> getChildEntries(int offset, int count) {
+    @Override
+    public Iterator<Node> getChildNodeEntries(int offset, int count) {
         if (offset < 0 || count < -1) {
             throw new IllegalArgumentException();
         }
 
-        if (children == null) {
-            return EMPTY.iterator();
-        }
-
         if (offset == 0 && count == -1) {
-            return children.values().iterator();
+            return childEntries.values().iterator();
         }
 
-        if (offset >= children.size() || count == 0) {
+        if (offset >= childEntries.size() || count == 0) {
             return EMPTY.iterator();
         }
 
-        if (count == -1 || (offset + count) > children.size()) {
-            count = children.size() - offset;
+        if (count == -1 || (offset + count) > childEntries.size()) {
+            count = childEntries.size() - offset;
         }
 
-        return new RangeIterator<Node>(children.values().iterator(), offset, count);
+        return new RangeIterator<Node>(childEntries.values().iterator(), offset, count);
     }
 
-    @Override
-    public Set<Node> getDescendants(boolean includeThis) {
-        Set<Node> descendants = new HashSet<Node>();
-        if (includeThis) {
-            descendants.add(this);
-        }
-
-        getDescendantsRecursive(this, descendants);
+    public void removeChildNodeEntry(String name) {
+        childEntries.remove(name);
+    }
 
-        return Collections.unmodifiableSet(descendants);
+    public void addProperty(String key, String value) {
+        properties.put(key, value);
     }
 
     @Override
-    public String getName() {
-        return name;
+    public Map<String, String> getProperties() {
+        return properties;
     }
 
     @Override
@@ -180,53 +111,77 @@ public class NodeImpl implements Node {
         return path;
     }
 
-    /**
-     * Sets the path of this node which will automatically set the name of the node as well.
-     *
-     * @param path The path.
-     */
-    public void setPath(String path) {
-        this.path = path;
-        name = PathUtils.getName(path);
+    @Override
+    public Long getRevisionId() {
+        return revisionId;
     }
 
-    @Override
-    public Map<String, Object> getProperties() {
-        return this.properties != null? Collections.unmodifiableMap(this.properties) : null;
+    public void setRevisionId(Long revisionId) {
+        this.revisionId = revisionId;
     }
 
-    /**
-     * Sets the properties of this node.
-     *
-     * @param properties The properties.
-     */
-    public void setProperties(Map<String, Object> properties) {
-        if (properties != null) {
-            properties = new HashMap<String, Object>(properties);
+    @Override
+    public void diff(Node other, NodeDiffHandler handler) {
+
+        // Note: Most of this functionality is mirrored from AbstractNode with
+        // the hopes that the two functionality can be consolidated at some point.
+
+        // Compare properties
+        Map<String, String> oldProps = getProperties();
+        Map<String, String> newProps = other.getProperties();
+
+        for (Map.Entry<String, String> entry : oldProps.entrySet()) {
+            String name = entry.getKey();
+            Object val = oldProps.get(name);
+            Object newVal = newProps.get(name);
+            if (newVal == null) {
+                handler.propDeleted(name, val.toString());
+            } else {
+                if (!val.equals(newVal)) {
+                    handler.propChanged(name, val.toString(), newVal.toString());
+                }
+            }
         }
 
-        this.properties = properties;
-    }
+        for (Map.Entry<String, String> entry : newProps.entrySet()) {
+            String name = entry.getKey();
+            if (!oldProps.containsKey(name)) {
+                handler.propAdded(name, entry.getValue().toString());
+            }
+        }
 
-    @Override
-    public Long getRevisionId() {
-        return revisionId;
-    }
+        // Compare child node entries
+        for (Iterator<Node> it = getChildNodeEntries(0, -1); it.hasNext(); ) {
+            Node child = it.next();
+            String childName = PathUtils.getName(child.getPath());
+            Node newChild = other.getChildNodeEntry(childName);
+            if (newChild == null) {
+                handler.childNodeDeleted(new ChildNodeEntry(childName, null));
+            } else {
+                if (!child.equals(newChild)) {
+                    handler.childNodeChanged(new ChildNodeEntry(childName, null),
+                            null /*newId*/);
+                }
+            }
+        }
 
-    @Override
-    public void setRevisionId(Long revisionId) {
-        this.revisionId = revisionId;
+        for (Iterator<Node> it = other.getChildNodeEntries(0, -1); it.hasNext(); ) {
+            Node child = it.next();
+            String childName = PathUtils.getName(child.getPath());
+            if (getChildNodeEntry(childName) == null) {
+                handler.childNodeAdded(new ChildNodeEntry(childName, null));
+            }
+        }
     }
 
     @Override
     public int hashCode() {
         final int prime = 31;
         int result = 1;
-        result = (prime * result) + ((this.children == null) ? 0 : this.children.hashCode());
-        result = (prime * result) + ((this.name == null) ? 0 : this.name.hashCode());
-        result = (prime * result) + ((this.path == null) ? 0 : this.path.hashCode());
-        result = (prime * result) + ((this.properties == null) ? 0 : this.properties.hashCode());
-        result = (prime * result) + ((this.revisionId == null) ? 0 : this.revisionId.hashCode());
+        result = (prime * result) + ((childEntries == null) ? 0 : childEntries.hashCode());
+        result = (prime * result) + ((path == null) ? 0 : path.hashCode());
+        result = (prime * result) + ((properties == null) ? 0 : properties.hashCode());
+        result = (prime * result) + ((revisionId == null) ? 0 : revisionId.hashCode());
         return result;
     }
 
@@ -238,43 +193,36 @@ public class NodeImpl implements Node {
         if (obj == null) {
             return false;
         }
-        if (this.getClass() != obj.getClass()) {
+        if (getClass() != obj.getClass()) {
             return false;
         }
         NodeImpl other = (NodeImpl) obj;
-        if (this.children == null) {
-            if (other.children != null) {
-                return false;
-            }
-        } else if (!this.children.equals(other.children)) {
-            return false;
-        }
-        if (this.name == null) {
-            if (other.name != null) {
+        if (childEntries == null) {
+            if (other.childEntries != null) {
                 return false;
             }
-        } else if (!this.name.equals(other.name)) {
+        } else if (!childEntries.equals(other.childEntries)) {
             return false;
         }
-        if (this.path == null) {
+        if (path == null) {
             if (other.path != null) {
                 return false;
             }
-        } else if (!this.path.equals(other.path)) {
+        } else if (!path.equals(other.path)) {
             return false;
         }
-        if (this.properties == null) {
+        if (properties == null) {
             if (other.properties != null) {
                 return false;
             }
-        } else if (!this.properties.equals(other.properties)) {
+        } else if (!properties.equals(other.properties)) {
             return false;
         }
-        if (this.revisionId == null) {
+        if (revisionId == null) {
             if (other.revisionId != null) {
                 return false;
             }
-        } else if (!this.revisionId.equals(other.revisionId)) {
+        } else if (!revisionId.equals(other.revisionId)) {
             return false;
         }
         return true;
@@ -283,42 +231,35 @@ public class NodeImpl implements Node {
     @Override
     public String toString() {
         StringBuilder builder = new StringBuilder();
-        builder.append("NodeImpl [");
-        if (this.name != null) {
-            builder.append("name=");
-            builder.append(this.name);
-            builder.append(", ");
-        }
-        if (this.path != null) {
-            builder.append("path=");
-            builder.append(this.path);
-            builder.append(", ");
-        }
-        if (this.revisionId != null) {
-            builder.append("revisionId=");
-            builder.append(this.revisionId);
-            builder.append(", ");
-        }
-        if (this.properties != null) {
-            builder.append("properties=");
-            builder.append(this.properties);
-            builder.append(", ");
-        }
-        if (this.children != null) {
-            builder.append("children=");
-            builder.append(this.children);
+        builder.append("NodeImpl ");
+        builder.append("path=");
+        builder.append(path);
+
+        if (revisionId != null) {
+            builder.append(", revisionId=");
+            builder.append(revisionId);
+        }
+
+        if (!childEntries.isEmpty()) {
+            builder.append(", children=[");
+            Set<String> childNames = childEntries.keySet();
+            int childCount = childNames.size();
+            int i = 0;
+            for (String childName : childEntries.keySet()) {
+                if (i++ < childCount - 1) {
+                    builder.append(childName + ", ");
+                } else {
+                    builder.append(childName);
+                }
+            }
+            builder.append("]");
+        }
+
+        if (!properties.isEmpty()) {
+            builder.append(", properties=");
+            builder.append(properties);
         }
-        builder.append("]");
-        return builder.toString();
-    }
 
-    private void getDescendantsRecursive(Node node, Set<Node> descendants) {
-        Set<Node> children = node.getChildren();
-        if (children != null) {
-            for (Node child : children) {
-                descendants.add(child);
-                this.getDescendantsRecursive(child, descendants);
-            }
-        }
+        return builder.toString();
     }
-}
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/MongoNodeDelta.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/MongoNodeDelta.java?rev=1407119&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/MongoNodeDelta.java (added)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/MongoNodeDelta.java Thu Nov  8 15:17:50 2012
@@ -0,0 +1,238 @@
+/*
+ * 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.mongomk.impl.model.tree;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.jackrabbit.mk.model.Id;
+import org.apache.jackrabbit.mk.model.tree.NodeState;
+import org.apache.jackrabbit.mk.model.tree.NodeStateDiff;
+import org.apache.jackrabbit.mk.model.tree.NodeStore;
+import org.apache.jackrabbit.mk.model.tree.PropertyState;
+
+/**
+ * Note: Most of this functionality is mirrored from NodeDelta with the hopes
+ * that the two functionality can be consolidated at some point.
+ */
+public class MongoNodeDelta {
+
+    public static enum ConflictType {
+        /**
+         * same property has been added or set, but with differing values
+         */
+        PROPERTY_VALUE_CONFLICT,
+        /**
+         * child nodes with identical name have been added or modified, but
+         * with differing id's; the corresponding node subtrees are hence differing
+         * and potentially conflicting.
+         */
+        NODE_CONTENT_CONFLICT,
+        /**
+         * a modified property has been deleted
+         */
+        REMOVED_DIRTY_PROPERTY_CONFLICT,
+        /**
+         * a child node entry pointing to a modified subtree has been deleted
+         */
+        REMOVED_DIRTY_NODE_CONFLICT
+    }
+
+    private final NodeStore provider;
+
+    private final NodeState node1;
+
+    Map<String, String> addedProperties = new HashMap<String, String>();
+    Map<String, String> removedProperties = new HashMap<String, String>();
+    Map<String, String> changedProperties = new HashMap<String, String>();
+
+    Map<String, NodeState> addedChildNodes = new HashMap<String, NodeState>();
+    Map<String, Id> removedChildNodes = new HashMap<String, Id>();
+    Map<String, NodeState> changedChildNodes = new HashMap<String, NodeState>();
+
+    public MongoNodeDelta(NodeStore provider, NodeState node1, NodeState node2) {
+        this.provider = provider;
+        this.node1 = node1;
+        this.provider.compare(node1, node2, new DiffHandler());
+    }
+
+    public Map<String, String> getAddedProperties() {
+        return addedProperties;
+    }
+
+    public Map<String, String> getRemovedProperties() {
+        return removedProperties;
+    }
+
+    public Map<String, String> getChangedProperties() {
+        return changedProperties;
+    }
+
+    public Map<String, NodeState> getAddedChildNodes() {
+        return addedChildNodes;
+    }
+
+    public Map<String, Id> getRemovedChildNodes() {
+        return removedChildNodes;
+    }
+
+    public Map<String, NodeState> getChangedChildNodes() {
+        return changedChildNodes;
+    }
+
+    public boolean conflictsWith(MongoNodeDelta other) {
+        return !listConflicts(other).isEmpty();
+    }
+
+    public List<Conflict> listConflicts(MongoNodeDelta other) {
+        // assume that both delta's were built using the *same* base node revision
+        if (!node1.equals(other.node1)) {
+            throw new IllegalArgumentException("other and this NodeDelta object are expected to share common node1 instance");
+        }
+
+        List<Conflict> conflicts = new ArrayList<Conflict>();
+
+        // properties
+
+        Map<String, String> otherAddedProps = other.getAddedProperties();
+        for (Map.Entry<String, String> added : addedProperties.entrySet()) {
+            String otherValue = otherAddedProps.get(added.getKey());
+            if (otherValue != null && !added.getValue().equals(otherValue)) {
+                // same property added with conflicting values
+                conflicts.add(new Conflict(ConflictType.PROPERTY_VALUE_CONFLICT, added.getKey()));
+            }
+        }
+
+        Map<String, String> otherChangedProps = other.getChangedProperties();
+        Map<String, String> otherRemovedProps = other.getRemovedProperties();
+        for (Map.Entry<String, String> changed : changedProperties.entrySet()) {
+            String otherValue = otherChangedProps.get(changed.getKey());
+            if (otherValue != null && !changed.getValue().equals(otherValue)) {
+                // same property changed with conflicting values
+                conflicts.add(new Conflict(ConflictType.PROPERTY_VALUE_CONFLICT, changed.getKey()));
+            }
+            if (otherRemovedProps.containsKey(changed.getKey())) {
+                // changed property has been removed
+                conflicts.add(new Conflict(ConflictType.REMOVED_DIRTY_PROPERTY_CONFLICT, changed.getKey()));
+            }
+        }
+
+        for (Map.Entry<String, String> removed : removedProperties.entrySet()) {
+            if (otherChangedProps.containsKey(removed.getKey())) {
+                // removed property has been changed
+                conflicts.add(new Conflict(ConflictType.REMOVED_DIRTY_PROPERTY_CONFLICT, removed.getKey()));
+            }
+        }
+
+        // child node entries
+
+        //Map<String, Id> otherAddedChildNodes = other.getAddedChildNodes();
+        Map<String, NodeState> otherAddedChildNodes = other.getAddedChildNodes();
+        for (Map.Entry<String, NodeState> added : addedChildNodes.entrySet()) {
+            NodeState otherValue = otherAddedChildNodes.get(added.getKey());
+            if (otherValue != null && !added.getValue().equals(otherValue)) {
+                // same child node entry added with different target id's
+                conflicts.add(new Conflict(ConflictType.NODE_CONTENT_CONFLICT, added.getKey()));
+            }
+        }
+
+        //Map<String, Id> otherChangedChildNodes = other.getChangedChildNodes();
+        Map<String, NodeState> otherChangedChildNodes = other.getChangedChildNodes();
+        Map<String, Id> otherRemovedChildNodes = other.getRemovedChildNodes();
+        for (Map.Entry<String, NodeState> changed : changedChildNodes.entrySet()) {
+            NodeState otherValue = otherChangedChildNodes.get(changed.getKey());
+            if (otherValue != null && !changed.getValue().equals(otherValue)) {
+                // same child node entry changed with different target id's
+                conflicts.add(new Conflict(ConflictType.NODE_CONTENT_CONFLICT, changed.getKey()));
+            }
+            if (otherRemovedChildNodes.containsKey(changed.getKey())) {
+                // changed child node entry has been removed
+                conflicts.add(new Conflict(ConflictType.REMOVED_DIRTY_NODE_CONFLICT, changed.getKey()));
+            }
+        }
+
+        for (Map.Entry<String, Id> removed : removedChildNodes.entrySet()) {
+            if (otherChangedChildNodes.containsKey(removed.getKey())) {
+                // removed child node entry has been changed
+                conflicts.add(new Conflict(ConflictType.REMOVED_DIRTY_NODE_CONFLICT, removed.getKey()));
+            }
+        }
+
+        return conflicts;
+    }
+
+    //--------------------------------------------------------< inner classes >
+
+    private class DiffHandler implements NodeStateDiff {
+
+        @Override
+        public void propertyAdded(PropertyState after) {
+            addedProperties.put(after.getName(), after.getEncodedValue());
+        }
+
+        @Override
+        public void propertyChanged(PropertyState before, PropertyState after) {
+            changedProperties.put(after.getName(), after.getEncodedValue());
+        }
+
+        @Override
+        public void propertyDeleted(PropertyState before) {
+            removedProperties.put(before.getName(), before.getEncodedValue());
+        }
+
+        @Override
+        public void childNodeAdded(String name, NodeState after) {
+            addedChildNodes.put(name, after);
+        }
+
+        @Override
+        public void childNodeChanged(
+                String name, NodeState before, NodeState after) {
+            changedChildNodes.put(name, after /*provider.getId(after)*/);
+        }
+
+        @Override
+        public void childNodeDeleted(String name, NodeState before) {
+            removedChildNodes.put(name, null /*provider.getId(before)*/);
+        }
+    }
+
+    public static class Conflict {
+
+        final ConflictType type;
+        final String name;
+
+        /**
+         * @param type conflict type
+         * @param name name of conflicting property or child node
+         */
+        Conflict(ConflictType type, String name) {
+            this.type = type;
+            this.name = name;
+        }
+
+        public ConflictType getType() {
+            return type;
+        }
+
+        public String getName() {
+            return name;
+        }
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/MongoNodeDelta.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/MongoNodeDelta.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/MongoNodeState.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/MongoNodeState.java?rev=1407119&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/MongoNodeState.java (added)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/MongoNodeState.java Thu Nov  8 15:17:50 2012
@@ -0,0 +1,139 @@
+package org.apache.jackrabbit.mongomk.impl.model.tree;
+
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.jackrabbit.mk.model.tree.AbstractChildNode;
+import org.apache.jackrabbit.mk.model.tree.AbstractNodeState;
+import org.apache.jackrabbit.mk.model.tree.AbstractPropertyState;
+import org.apache.jackrabbit.mk.model.tree.ChildNode;
+import org.apache.jackrabbit.mk.model.tree.NodeState;
+import org.apache.jackrabbit.mk.model.tree.PropertyState;
+import org.apache.jackrabbit.mongomk.api.model.Node;
+import org.apache.jackrabbit.oak.commons.PathUtils;
+
+/**
+ * This dummy NodeStore implementation is needed in order to be able to reuse
+ * Oak's DiffBuilder in MongoMK.
+ */
+public class MongoNodeState extends AbstractNodeState {
+
+    private final Node node;
+
+    /**
+     * Create a node state with the supplied node.
+     *
+     * @param node Node.
+     */
+    public MongoNodeState(Node node) {
+        this.node = node;
+    }
+
+    /**
+     * Returns the underlying node.
+     *
+     * @return The underlying node.
+     */
+    public Node unwrap() {
+        return node;
+    }
+
+    @Override
+    public Iterable<? extends PropertyState> getProperties() {
+        return new Iterable<PropertyState>() {
+            @Override
+            public Iterator<PropertyState> iterator() {
+                final Iterator<Map.Entry<String, String>> iterator =
+                        node.getProperties().entrySet().iterator();
+                return new Iterator<PropertyState>() {
+                    @Override
+                    public boolean hasNext() {
+                        return iterator.hasNext();
+                    }
+                    @Override
+                    public PropertyState next() {
+                        Map.Entry<String, String> entry = iterator.next();
+                        return new SimplePropertyState(entry.getKey(), entry.getValue());
+                    }
+                    @Override
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+                };
+            }
+        };
+    }
+
+    @Override
+    public Iterable<? extends ChildNode> getChildNodeEntries(final long offset,
+            final int count) {
+        if (count < -1) {
+            throw new IllegalArgumentException("Illegal count: " + count);
+        }
+
+        if (offset > Integer.MAX_VALUE) {
+            return Collections.emptyList();
+        }
+
+        return new Iterable<ChildNode>() {
+            @Override
+            public Iterator<ChildNode> iterator() {
+                final Iterator<Node> iterator =
+                        node.getChildNodeEntries((int) offset, count);
+                return new Iterator<ChildNode>() {
+                    @Override
+                    public boolean hasNext() {
+                        return iterator.hasNext();
+                    }
+                    @Override
+                    public ChildNode next() {
+                        return getChildNodeEntry(iterator.next());
+                    }
+                    @Override
+                    public void remove() {
+                        throw new UnsupportedOperationException();
+                    }
+                };
+            }
+        };
+    }
+
+    private ChildNode getChildNodeEntry(final Node entry) {
+
+        return new AbstractChildNode() {
+            @Override
+            public String getName() {
+                return PathUtils.getName(entry.getPath());
+            }
+            @Override
+            public NodeState getNode() {
+                try {
+                    return new MongoNodeState(entry);
+                } catch (Exception e) {
+                    throw new RuntimeException("Unexpected error", e);
+                }
+            }
+        };
+    }
+
+    private static class SimplePropertyState extends AbstractPropertyState {
+        private final String name;
+        private final String value;
+
+        public SimplePropertyState(String name, String value) {
+            this.name = name;
+            this.value = value;
+        }
+
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
+        public String getEncodedValue() {
+            return value;
+        }
+    }
+}

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/MongoNodeState.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/MongoNodeState.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/SimpleMongoNodeStore.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/SimpleMongoNodeStore.java?rev=1407119&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/SimpleMongoNodeStore.java (added)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/SimpleMongoNodeStore.java Thu Nov  8 15:17:50 2012
@@ -0,0 +1,67 @@
+package org.apache.jackrabbit.mongomk.impl.model.tree;
+
+import org.apache.jackrabbit.mk.model.ChildNodeEntry;
+import org.apache.jackrabbit.mk.model.Id;
+import org.apache.jackrabbit.mk.model.NodeDiffHandler;
+import org.apache.jackrabbit.mk.model.tree.NodeState;
+import org.apache.jackrabbit.mk.model.tree.NodeStateDiff;
+import org.apache.jackrabbit.mk.model.tree.NodeStore;
+import org.apache.jackrabbit.mongomk.api.model.Node;
+
+/**
+ * This dummy NodeStore implementation is needed in order to be able to reuse
+ * Oak's DiffBuilder in MongoMK.
+ */
+public class SimpleMongoNodeStore implements NodeStore {
+
+    @Override
+    public NodeState getRoot() {
+        return null;
+    }
+
+    @Override
+    public void compare(final NodeState before, final NodeState after,
+            final NodeStateDiff diff) {
+
+        Node beforeNode = ((MongoNodeState)before).unwrap();
+        Node afterNode = ((MongoNodeState)after).unwrap();
+
+        beforeNode.diff(afterNode, new NodeDiffHandler() {
+            @Override
+            public void propAdded(String propName, String value) {
+                diff.propertyAdded(after.getProperty(propName));
+            }
+
+            @Override
+            public void propChanged(String propName, String oldValue,
+                    String newValue) {
+                diff.propertyChanged(before.getProperty(propName),
+                        after.getProperty(propName));
+            }
+
+            @Override
+            public void propDeleted(String propName, String value) {
+                diff.propertyDeleted(before.getProperty(propName));
+            }
+
+            @Override
+            public void childNodeAdded(ChildNodeEntry added) {
+                String name = added.getName();
+                diff.childNodeAdded(name, after.getChildNode(name));
+            }
+
+            @Override
+            public void childNodeDeleted(ChildNodeEntry deleted) {
+                String name = deleted.getName();
+                diff.childNodeDeleted(name, before.getChildNode(name));
+            }
+
+            @Override
+            public void childNodeChanged(ChildNodeEntry changed, Id newId) {
+                String name = changed.getName();
+                diff.childNodeChanged(name, before.getChildNode(name),
+                        after.getChildNode(name));
+            }
+        });
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/SimpleMongoNodeStore.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/model/tree/SimpleMongoNodeStore.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Copied: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/osgi/MongoMicroKernelService.java (from r1407101, jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/osgi/MongoMicroKernalService.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/osgi/MongoMicroKernelService.java?p2=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/osgi/MongoMicroKernelService.java&p1=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/osgi/MongoMicroKernalService.java&r1=1407101&r2=1407119&rev=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/osgi/MongoMicroKernalService.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/osgi/MongoMicroKernelService.java Thu Nov  8 15:17:50 2012
@@ -19,16 +19,18 @@
 
 package org.apache.jackrabbit.mongomk.osgi;
 
+import java.util.Map;
+import java.util.Properties;
+
 import org.apache.felix.scr.annotations.Activate;
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.ConfigurationPolicy;
 import org.apache.felix.scr.annotations.Property;
 import org.apache.jackrabbit.mk.api.MicroKernel;
-import org.apache.jackrabbit.mongomk.impl.BlobStoreMongo;
 import org.apache.jackrabbit.mongomk.impl.MongoConnection;
 import org.apache.jackrabbit.mongomk.impl.MongoMicroKernel;
-import org.apache.jackrabbit.mongomk.impl.NodeStoreMongo;
-import org.apache.jackrabbit.mongomk.util.MongoUtil;
+import org.apache.jackrabbit.mongomk.impl.MongoNodeStore;
+import org.apache.jackrabbit.mongomk.impl.blob.MongoGridFSBlobStore;
 import org.apache.sling.commons.osgi.PropertiesUtil;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.ServiceRegistration;
@@ -36,8 +38,7 @@ import org.osgi.service.component.annota
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import java.util.Map;
-import java.util.Properties;
+import com.mongodb.DB;
 
 
 @Component(metatype = true,
@@ -45,15 +46,12 @@ import java.util.Properties;
         description = "%oak.mongomk.description",
         policy = ConfigurationPolicy.REQUIRE
 )
-public class MongoMicroKernalService {
+public class MongoMicroKernelService {
 
     private static final String DEFAULT_HOST = "localhost";
-
     private static final int DEFAULT_PORT= 27017;
-
     private static final String DEFAULT_DB = "oak";
 
-
     @Property(value = DEFAULT_HOST)
     private static final String PROP_HOST = "host";
 
@@ -66,8 +64,7 @@ public class MongoMicroKernalService {
     private final Logger logger = LoggerFactory.getLogger(this.getClass());
 
     private ServiceRegistration reg;
-
-    private MongoConnection connection;
+    private MongoMicroKernel mk;
 
     @Activate
     private void activate(BundleContext context,Map<String,?> config) throws Exception {
@@ -75,14 +72,17 @@ public class MongoMicroKernalService {
         int port = PropertiesUtil.toInteger(config.get(PROP_PORT), DEFAULT_PORT);
         String db = PropertiesUtil.toString(config.get(PROP_DB), DEFAULT_DB);
 
-        logger.info("Starting MongoDB MicroKernal with host={}, port={}, db={}",
+        logger.info("Starting MongoDB MicroKernel with host={}, port={}, db={}",
                 new Object[] {host, port, db});
-        connection = new MongoConnection(host,port,db);
 
-        MongoUtil.bootstrap(connection);
-        logger.info("Connected to database {}", connection.getDB());
+        MongoConnection connection = new MongoConnection(host, port, db);
+        DB mongoDB = connection.getDB();
 
-        MongoMicroKernel mk = new MongoMicroKernel( new NodeStoreMongo(connection),new BlobStoreMongo(connection));
+        logger.info("Connected to database {}", mongoDB);
+
+        MongoNodeStore nodeStore = new MongoNodeStore(mongoDB);
+        MongoGridFSBlobStore blobStore = new MongoGridFSBlobStore(mongoDB);
+        MongoMicroKernel mk = new MongoMicroKernel(connection, nodeStore, blobStore);
 
         Properties props = new Properties();
         props.setProperty("oak.mk.type","mongo");
@@ -90,14 +90,13 @@ public class MongoMicroKernalService {
     }
 
     @Deactivate
-    private void deactivate(){
-        if(reg != null){
+    private void deactivate() {
+        if (reg != null){
             reg.unregister();
         }
 
-        if(connection != null){
-            connection.close();
+        if (mk != null) {
+            mk.dispose();
         }
     }
-
-}
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/osgi/MongoMicroKernelService.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/osgi/MongoMicroKernelService.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/util/MongoUtil.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/util/MongoUtil.java?rev=1407119&r1=1407118&r2=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/util/MongoUtil.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/util/MongoUtil.java Thu Nov  8 15:17:50 2012
@@ -16,116 +16,39 @@
  */
 package org.apache.jackrabbit.mongomk.util;
 
-import java.util.Arrays;
-
-import com.mongodb.DB;
-import org.apache.jackrabbit.mongomk.impl.MongoConnection;
-import org.apache.jackrabbit.mongomk.model.CommitMongo;
-import org.apache.jackrabbit.mongomk.model.HeadMongo;
-import org.apache.jackrabbit.mongomk.model.NodeMongo;
-
-import com.mongodb.BasicDBObject;
-import com.mongodb.DBCollection;
-import com.mongodb.DBObject;
+import org.apache.jackrabbit.mk.model.tree.NodeState;
+import org.apache.jackrabbit.mongomk.api.model.Node;
+import org.apache.jackrabbit.mongomk.impl.model.tree.MongoNodeState;
 
 /**
- * Utility classes for preparing the {@code MongoDB} environement.
- *
- * @author <a href="mailto:pmarx@adobe.com>Philipp Marx</a>
+ * MongoMK specific utility class.
  */
-@SuppressWarnings("javadoc")
 public class MongoUtil {
 
-    public static final String INITIAL_COMMIT_MESSAGE = "This is an autogenerated initial commit";
-    public static final String INITIAL_COMMIT_PATH = "";
-    public static final String INITIAL_COMMIT_DIFF = "+\"/\" : {}";
-
-    public static void clearCommitCollection(MongoConnection mongoConnection) {
-        DBCollection commitCollection = mongoConnection.getCommitCollection();
-        commitCollection.drop();
-    }
-
-    public static void clearDatabase(MongoConnection mongoConnection) {
-        clearNodeCollection(mongoConnection);
-        clearCommitCollection(mongoConnection);
-        clearHeadCollection(mongoConnection);
-    }
-
-    public static void clearHeadCollection(MongoConnection mongoConnection) {
-        DBCollection headCollection = mongoConnection.getHeadCollection();
-        headCollection.drop();
-    }
-
-    public static void clearNodeCollection(MongoConnection mongoConnection) {
-        DBCollection nodeCollection = mongoConnection.getNodeCollection();
-        nodeCollection.drop();
-    }
-
-    public static void initCommitCollection(MongoConnection mongoConnection) {
-        DBCollection commitCollection = mongoConnection.getCommitCollection();
-        DBObject index = new BasicDBObject();
-        index.put(CommitMongo.KEY_REVISION_ID, 1L);
-        DBObject options = new BasicDBObject();
-        options.put("unique", Boolean.TRUE);
-        commitCollection.ensureIndex(index, options);
-        CommitMongo commit = new CommitMongo();
-        commit.setAffectedPaths(Arrays.asList(new String[] { "/" }));
-        commit.setBaseRevId(0L);
-        commit.setDiff(INITIAL_COMMIT_DIFF);
-        commit.setMessage(INITIAL_COMMIT_MESSAGE);
-        commit.setPath(INITIAL_COMMIT_PATH);
-        commit.setRevisionId(0L);
-        commitCollection.insert(commit);
-    }
-
-    public static void initDatabase(MongoConnection mongoConnection) {
-        clearDatabase(mongoConnection);
-
-        initNodeCollection(mongoConnection);
-        initCommitCollection(mongoConnection);
-        initHeadCollection(mongoConnection);
+    public static String fromMongoRepresentation(Long revisionId) {
+        return String.valueOf(revisionId);
     }
 
-    public static void bootstrap(MongoConnection mongoConnection){
-        DB db = mongoConnection.getDB();
-        if(!db.collectionExists(MongoConnection.COLLECTION_NODES)){
-            initNodeCollection(mongoConnection);
-        }
-        if(!db.collectionExists(MongoConnection.COLLECTION_COMMITS)){
-            initCommitCollection(mongoConnection);
+    public static Long toMongoRepresentation(String revisionId) throws Exception {
+        if (revisionId == null) {
+            return null;
         }
-        if(!db.collectionExists(MongoConnection.COLLECTION_HEAD)){
-            initHeadCollection(mongoConnection);
+        try {
+            return Long.parseLong(revisionId);
+        } catch (NumberFormatException e) {
+            throw new Exception("Invalid revision id: " + revisionId);
         }
     }
 
-    public static void initHeadCollection(MongoConnection mongoConnection) {
-        DBCollection headCollection = mongoConnection.getHeadCollection();
-        HeadMongo headMongo = new HeadMongo();
-        headMongo.setHeadRevisionId(0L);
-        headMongo.setNextRevisionId(1L);
-        headCollection.insert(headMongo);
+    public static NodeState wrap(Node node) {
+        return node != null? new MongoNodeState(node) : null;
     }
 
-    public static void initNodeCollection(MongoConnection mongoConnection) {
-        DBCollection nodeCollection = mongoConnection.getNodeCollection();
-        DBObject index = new BasicDBObject();
-        index.put(NodeMongo.KEY_PATH, 1L);
-        index.put(NodeMongo.KEY_REVISION_ID, 1L);
-        DBObject options = new BasicDBObject();
-        options.put("unique", Boolean.TRUE);
-        nodeCollection.ensureIndex(index, options);
-        NodeMongo root = new NodeMongo();
-        root.setRevisionId(0L);
-        root.setPath("/");
-        nodeCollection.insert(root);
-    }
-
-    public static String fromMongoRepresentation(Long revisionId) {
-        return String.valueOf(revisionId);
+    public static String adjustPath(String path) {
+        return (path == null || path.isEmpty()) ? "/" : path;
     }
 
-    public static Long toMongoRepresentation(String revisionId) {
-        return revisionId != null? Long.parseLong(revisionId) : null;
+    public static boolean isFiltered(String path) {
+        return !"/".equals(path);
     }
-}
+}
\ No newline at end of file

Copied: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/util/NodeBuilder.java (from r1407101, jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/builder/NodeBuilder.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/util/NodeBuilder.java?p2=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/util/NodeBuilder.java&p1=jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/builder/NodeBuilder.java&r1=1407101&r2=1407119&rev=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/impl/builder/NodeBuilder.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/util/NodeBuilder.java Thu Nov  8 15:17:50 2012
@@ -14,26 +14,24 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.jackrabbit.mongomk.impl.builder;
+package org.apache.jackrabbit.mongomk.util;
 
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
 
+import org.apache.jackrabbit.mk.json.JsopBuilder;
 import org.apache.jackrabbit.mongomk.api.model.Node;
 import org.apache.jackrabbit.mongomk.impl.json.JsonUtil;
 import org.apache.jackrabbit.mongomk.impl.model.NodeImpl;
-import org.apache.jackrabbit.mongomk.util.MongoUtil;
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.json.JSONArray;
 import org.json.JSONException;
 import org.json.JSONObject;
 
 /**
- * A builder to create {@link Node}s from <a hred="http://en.wikipedia.org/wiki/JavaScript_Object_Notation">JSON</a>
- * strings.
- *
- * @author <a href="mailto:pmarx@adobe.com>Philipp Marx</a>
+ * A builder to create {@link Node}s from JSON strings. This class is for testing
+ * purposes only.
  */
 public class NodeBuilder {
 
@@ -108,19 +106,33 @@ public class NodeBuilder {
                 String childPath = PathUtils.concat(realPath, key);
 
                 Node childNode = parseNode(childPath, (JSONObject) value);
-                node.addChild(childNode);
+                node.addChildNodeEntry(childNode);
             } else {
                 if (properties == null) {
                     properties = new HashMap<String, Object>();
                 }
 
-                Object converted = JsonUtil.convertJsonValue(value.toString());
+                Object converted = JsonUtil.toJsonValue(value.toString());
                 properties.put(key, converted);
             }
         }
 
-        node.setProperties(properties);
+        if (properties != null) {
+            for (Map.Entry<String, Object> entry : properties.entrySet()) {
+                node.addProperty(entry.getKey(), convertObjectValue(entry.getValue()));
+            }
+        }
 
         return node;
     }
+
+    private String convertObjectValue(Object value) {
+        if (value == null) {
+            return null;
+        }
+        if (value instanceof String) {
+            return JsopBuilder.encode(value.toString());
+        }
+        return value.toString();
+    }
 }

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/util/NodeBuilder.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/main/java/org/apache/jackrabbit/mongomk/util/NodeBuilder.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/oak/trunk/oak-mongomk/src/main/resources/OSGI-INF/metatype/metatype.properties
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=1407119&r1=1407118&r2=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/main/resources/OSGI-INF/metatype/metatype.properties (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/main/resources/OSGI-INF/metatype/metatype.properties Thu Nov  8 15:17:50 2012
@@ -17,9 +17,9 @@
 # under the License.
 #
 
-oak.mongomk.label=Apache Jackrabbit Oak MongoDB MicroKernal Service
+oak.mongomk.label=Apache Jackrabbit Oak MongoDB MicroKernel Service
 oak.mongomk.description= Configure an instance of the MongoDB \
-  based MicroKernal implementation
+  based MicroKernel implementation
 
 host.name = MongoDB Host
 host.description = The host to connect to.

Added: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mk/blobs/MongoBlobStoreTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mk/blobs/MongoBlobStoreTest.java?rev=1407119&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mk/blobs/MongoBlobStoreTest.java (added)
+++ jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mk/blobs/MongoBlobStoreTest.java Thu Nov  8 15:17:50 2012
@@ -0,0 +1,329 @@
+/*
+ * 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.blobs;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.Properties;
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.jackrabbit.mongomk.impl.MongoConnection;
+import org.apache.jackrabbit.mongomk.impl.blob.MongoBlobStore;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import com.mongodb.DB;
+
+/**
+ * Tests the {@link MongoBlobStore} implementation. It should really extend from
+ * AbstractBlobStore but it cannot due to classpath issues, so instead AbstractBlobStore
+ * tests are copied here as well.
+ */
+public class MongoBlobStoreTest /*extends AbstractBlobStoreTest*/ {
+
+    protected AbstractBlobStore store;
+    private static DB db;
+
+    @BeforeClass
+    public static void setUpBeforeClass() throws Exception {
+        createDefaultMongoConnection();
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        dropCollections();
+        MongoBlobStore blobStore = new MongoBlobStore(db);
+        blobStore.setBlockSize(128);
+        blobStore.setBlockSizeMin(48);
+        this.store = blobStore;
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        dropCollections();
+        store = null;
+    }
+
+    @AfterClass
+    public static void tearDownAfterClass() throws Exception {
+        db.dropDatabase();
+    }
+
+    @Test
+    public void testWriteFile() throws Exception {
+        store.setBlockSize(1024 * 1024);
+        byte[] data = new byte[4 * 1024 * 1024];
+        Random r = new Random(0);
+        r.nextBytes(data);
+        String tempFileName = "target/temp/test";
+        File tempFile = new File(tempFileName);
+        tempFile.getParentFile().mkdirs();
+        OutputStream out = new FileOutputStream(tempFile, false);
+        out.write(data);
+        out.close();
+        String s = store.writeBlob(tempFileName);
+        assertEquals(data.length, store.getBlobLength(s));
+        byte[] buff = new byte[1];
+        for (int i = 0; i < data.length; i += 1024) {
+            store.readBlob(s, i, buff, 0, 1);
+            assertEquals(data[i], buff[0]);
+        }
+        try {
+            store.writeBlob(tempFileName + "_wrong");
+            fail();
+        } catch (Exception e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testCombinedIdentifier() throws Exception {
+        String id = store.writeBlob(new ByteArrayInputStream(new byte[2]));
+        assertEquals(2, store.getBlobLength(id));
+        String combinedId = id + id;
+        assertEquals(4, store.getBlobLength(combinedId));
+        doTestRead(new byte[4], 4, combinedId);
+    }
+
+    @Test
+    public void testEmptyIdentifier() throws Exception {
+        byte[] data = new byte[1];
+        assertEquals(-1, store.readBlob("", 0, data, 0, 1));
+        assertEquals(0, store.getBlobLength(""));
+    }
+
+    @Test
+    public void testCloseStream() throws Exception {
+        final AtomicBoolean closed = new AtomicBoolean();
+        InputStream in = new InputStream() {
+            public void close() {
+                closed.set(true);
+            }
+            public int read() throws IOException {
+                return -1;
+            }
+        };
+        store.writeBlob(in);
+        assertTrue(closed.get());
+    }
+
+    @Test
+    public void testExceptionWhileReading() throws Exception {
+        final AtomicBoolean closed = new AtomicBoolean();
+        InputStream in = new InputStream() {
+            public void close() {
+                closed.set(true);
+            }
+            public int read() throws IOException {
+                throw new RuntimeException("abc");
+            }
+        };
+        try {
+            store.writeBlob(in);
+        } catch (Exception e) {
+            String msg = e.getMessage();
+            assertTrue(msg, msg.indexOf("abc") >= 0);
+        }
+        assertTrue(closed.get());
+    }
+
+    @Test
+    public void testIllegalIdentifier() throws Exception {
+        byte[] data = new byte[1];
+        try {
+            store.readBlob("ff", 0, data, 0, 1);
+            fail();
+        } catch (Exception e) {
+            // expected
+        }
+        try {
+            store.getBlobLength("ff");
+            fail();
+        } catch (Exception e) {
+            // expected
+        }
+        try {
+            store.mark("ff");
+            fail();
+        } catch (Exception e) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testSmall() throws Exception {
+        doTest(10, 300);
+    }
+
+    @Test
+    public void testMedium() throws Exception {
+        doTest(100, 100);
+    }
+
+    @Test
+    public void testLarge() throws Exception {
+        doTest(1000, 10);
+    }
+
+    @Test
+    @Ignore // FIXME - GC is not implemented in MongoBlobStore yet.
+    public void testGarbageCollection() throws Exception {
+        HashMap<String, byte[]> map = new HashMap<String, byte[]>();
+        ArrayList<String> mem = new ArrayList<String>();
+        int count;
+        for (int i = 1; i <= 1000; i *= 10) {
+            byte[] data = new byte[i];
+            String id;
+            id = store.writeBlob(new ByteArrayInputStream(data));
+            // copy the id so the string is not in the weak hash map
+            map.put(new String(id), data);
+            mem.add(id);
+            data = new byte[i];
+            Arrays.fill(data, (byte) 1);
+            id = store.writeBlob(new ByteArrayInputStream(data));
+            // copy the id so the string is not in the weak hash map
+            map.put(new String(id), data);
+            mem.add(id);
+        }
+        store.startMark();
+        store.sweep();
+        for (String id : map.keySet()) {
+            byte[] test = readFully(id);
+            assertTrue(Arrays.equals(map.get(id), test));
+        }
+
+        mem.clear();
+
+        store.clearInUse();
+        store.startMark();
+        for (String id : map.keySet()) {
+            byte[] d = map.get(id);
+            if (d[0] != 0) {
+                continue;
+            }
+            store.mark(id);
+        }
+        count = store.sweep();
+
+        store.clearInUse();
+        store.clearCache();
+
+        // https://issues.apache.org/jira/browse/OAK-60
+        // endure there is at least one old entry (with age 1 ms)
+        try {
+            Thread.sleep(1);
+        } catch (InterruptedException e) {
+            // ignore
+        }
+
+        store.startMark();
+        count = store.sweep();
+        assertTrue("count: " + count, count > 0);
+        int failedCount = 0;
+        for (String id : map.keySet()) {
+            long length = store.getBlobLength(id);
+            try {
+                readFully(id);
+            } catch (Exception e) {
+                assertTrue(id + ":" + length, length > store.getBlockSizeMin());
+                failedCount++;
+            }
+        }
+        assertTrue("failedCount: " + failedCount, failedCount > 0);
+    }
+
+    private void doTest(int maxLength, int count) throws Exception {
+        String[] s = new String[count * 2];
+        Random r = new Random(0);
+        for (int i = 0; i < s.length;) {
+            byte[] data = new byte[r.nextInt(maxLength)];
+            r.nextBytes(data);
+            s[i++] = store.writeBlob(new ByteArrayInputStream(data));
+            s[i++] = store.writeBlob(new ByteArrayInputStream(data));
+        }
+        r.setSeed(0);
+        for (int i = 0; i < s.length;) {
+            int expectedLen = r.nextInt(maxLength);
+            byte[] expectedData = new byte[expectedLen];
+            r.nextBytes(expectedData);
+            assertEquals(expectedLen, store.getBlobLength(s[i++]));
+
+            String id = s[i++];
+            doTestRead(expectedData, expectedLen, id);
+        }
+    }
+
+    private void doTestRead(byte[] expected, int expectedLen, String id) throws Exception {
+        byte[] got = readFully(id);
+        assertEquals(expectedLen, got.length);
+        assertEquals(expected.length, got.length);
+        for (int i = 0; i < got.length; i++) {
+            assertEquals(expected[i], got[i]);
+        }
+    }
+
+    private byte[] readFully(String id) throws Exception {
+        int len = (int) store.getBlobLength(id);
+        byte[] data;
+        if (len < 100) {
+            data = new byte[len];
+            for (int i = 0; i < len; i++) {
+                store.readBlob(id, i, data, i, 1);
+            }
+        } else {
+            data = BlobStoreInputStream.readFully(store, id);
+        }
+        assertEquals(len, data.length);
+        return data;
+    }
+
+    private static void createDefaultMongoConnection() throws Exception {
+        InputStream is = MongoBlobStoreTest.class.getResourceAsStream("/config.cfg");
+        Properties properties = new Properties();
+        properties.load(is);
+
+        String host = properties.getProperty("host");
+        int port = Integer.parseInt(properties.getProperty("port"));
+        String database = properties.getProperty("db");
+
+        MongoConnection mongoConnection = new MongoConnection(host, port, database);
+        db = mongoConnection.getDB();
+    }
+
+    protected void dropCollections() {
+        if (db == null) {
+            return;
+        }
+        db.getCollection(MongoBlobStore.COLLECTION_BLOBS).drop();
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mk/blobs/MongoBlobStoreTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mk/blobs/MongoBlobStoreTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Added: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/BaseMongoMicroKernelTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/BaseMongoMicroKernelTest.java?rev=1407119&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/BaseMongoMicroKernelTest.java (added)
+++ jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/BaseMongoMicroKernelTest.java Thu Nov  8 15:17:50 2012
@@ -0,0 +1,244 @@
+/*
+ * 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.mongomk;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.io.InputStream;
+import java.util.Properties;
+
+import org.apache.jackrabbit.mk.api.MicroKernel;
+import org.apache.jackrabbit.mk.blobs.BlobStore;
+import org.apache.jackrabbit.mongomk.impl.MongoConnection;
+import org.apache.jackrabbit.mongomk.impl.MongoMicroKernel;
+import org.apache.jackrabbit.mongomk.impl.MongoNodeStore;
+import org.apache.jackrabbit.mongomk.impl.blob.MongoBlobStore;
+import org.apache.jackrabbit.mongomk.impl.blob.MongoGridFSBlobStore;
+import org.json.simple.JSONArray;
+import org.json.simple.JSONObject;
+import org.json.simple.parser.JSONParser;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.BeforeClass;
+
+import com.mongodb.DB;
+
+/**
+ * Base class for {@code MongoDB} tests that need the MongoMK.
+ */
+public class BaseMongoMicroKernelTest {
+
+    public static MicroKernel mk;
+    public static MongoConnection mongoConnection;
+
+    @BeforeClass
+    public static void setUpBeforeClass() throws Exception {
+        createDefaultMongoConnection();
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        DB db = mongoConnection.getDB();
+        dropCollections(db);
+
+        MongoNodeStore nodeStore = new MongoNodeStore(db);
+        MongoAssert.setNodeStore(nodeStore);
+        BlobStore blobStore = new MongoGridFSBlobStore(db);
+        mk = new MongoMicroKernel(mongoConnection, nodeStore, blobStore);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        DB db = mongoConnection.getDB();
+        dropCollections(db);
+    }
+
+    @AfterClass
+    public static void tearDownAfterClass() throws Exception {
+        mongoConnection.getDB().dropDatabase();
+    }
+
+    protected MongoNodeStore getNodeStore() {
+        MongoMicroKernel mongoMk = (MongoMicroKernel)mk;
+        return (MongoNodeStore)mongoMk.getNodeStore();
+    }
+
+    protected JSONObject getObjectArrayEntry(JSONArray array, int pos) {
+        assertTrue(pos >= 0 && pos < array.size());
+        Object entry = array.get(pos);
+        if (entry instanceof JSONObject) {
+            return (JSONObject) entry;
+        }
+        throw new AssertionError("failed to resolve JSONObject array entry at pos " + pos + ": " + entry);
+    }
+
+    protected JSONArray parseJSONArray(String json) throws AssertionError {
+        JSONParser parser = new JSONParser();
+        try {
+            Object obj = parser.parse(json);
+            assertTrue(obj instanceof JSONArray);
+            return (JSONArray) obj;
+        } catch (Exception e) {
+            throw new AssertionError("not a valid JSON array: " + e.getMessage());
+        }
+    }
+
+    protected JSONObject parseJSONObject(String json) throws AssertionError {
+        JSONParser parser = new JSONParser();
+        try {
+            Object obj = parser.parse(json);
+            assertTrue(obj instanceof JSONObject);
+            return (JSONObject) obj;
+        } catch (Exception e) {
+            throw new AssertionError("not a valid JSON object: " + e.getMessage());
+        }
+    }
+
+    protected void assertNodesExist(String revision, String...paths) {
+        doAssertNodes(true, revision, paths);
+    }
+
+    protected void assertNodesNotExist(String revision, String...paths) {
+        doAssertNodes(false, revision, paths);
+    }
+
+    protected void assertPropExists(String rev, String path, String property) {
+        String nodes = mk.getNodes(path, rev, -1 /*depth*/, 0 /*offset*/, -1 /*maxChildNodes*/, null /*filter*/);
+        JSONObject obj = parseJSONObject(nodes);
+        assertPropertyExists(obj, property);
+    }
+
+    protected void assertPropNotExists(String rev, String path, String property) {
+        String nodes = mk.getNodes(path, rev, -1 /*depth*/, 0 /*offset*/, -1 /*maxChildNodes*/, null /*filter*/);
+        if (nodes == null) {
+            return;
+        }
+        JSONObject obj = parseJSONObject(nodes);
+        assertPropertyNotExists(obj, property);
+    }
+
+    protected void assertPropValue(String rev, String path, String property, String value) {
+        String nodes = mk.getNodes(path, rev, -1 /*depth*/, 0 /*offset*/, -1 /*maxChildNodes*/, null /*filter*/);
+        JSONObject obj = parseJSONObject(nodes);
+        assertPropertyValue(obj, property, value);
+    }
+
+    protected void assertPropertyExists(JSONObject obj, String relPath, Class<?> type)
+            throws AssertionError {
+        Object val = resolveValue(obj, relPath);
+        assertNotNull("not found: " + relPath, val);
+
+        assertTrue(type.isInstance(val));
+    }
+
+    protected void assertPropertyExists(JSONObject obj, String relPath)
+            throws AssertionError {
+        Object val = resolveValue(obj, relPath);
+        assertNotNull("not found: " + relPath, val);
+    }
+
+    protected void assertPropertyNotExists(JSONObject obj, String relPath)
+            throws AssertionError {
+        Object val = resolveValue(obj, relPath);
+        assertNull(val);
+    }
+
+    protected void assertPropertyValue(JSONObject obj, String relPath, String expected)
+            throws AssertionError {
+        Object val = resolveValue(obj, relPath);
+        assertNotNull("not found: " + relPath, val);
+        assertEquals(expected, val);
+    }
+
+    protected void assertPropertyValue(JSONObject obj, String relPath, Double expected)
+            throws AssertionError {
+        Object val = resolveValue(obj, relPath);
+        assertNotNull("not found: " + relPath, val);
+
+        assertEquals(expected, val);
+    }
+
+    protected void assertPropertyValue(JSONObject obj, String relPath, Long expected)
+            throws AssertionError {
+        Object val = resolveValue(obj, relPath);
+        assertNotNull("not found: " + relPath, val);
+        assertEquals(expected, val);
+    }
+
+    protected void assertPropertyValue(JSONObject obj, String relPath, Boolean expected)
+            throws AssertionError {
+        Object val = resolveValue(obj, relPath);
+        assertNotNull("not found: " + relPath, val);
+
+        assertEquals(expected, val);
+    }
+
+    private void doAssertNodes(boolean checkExists, String revision, String...paths) {
+        for (String path : paths) {
+            boolean exists = mk.nodeExists(path, revision);
+            if (checkExists) {
+                assertTrue(path + " does not exist", exists);
+            } else {
+                assertFalse(path + " should not exist", exists);
+            }
+        }
+    }
+
+    protected JSONObject resolveObjectValue(JSONObject obj, String relPath) {
+        Object val = resolveValue(obj, relPath);
+        if (val instanceof JSONObject) {
+            return (JSONObject) val;
+        }
+        throw new AssertionError("failed to resolve JSONObject value at " + relPath + ": " + val);
+    }
+
+    private Object resolveValue(JSONObject obj, String relPath) {
+        String names[] = relPath.split("/");
+        Object val = obj;
+        for (String name : names) {
+            if (! (val instanceof JSONObject)) {
+                throw new AssertionError("not found: " + relPath);
+            }
+            val = ((JSONObject) val).get(name);
+        }
+        return val;
+    }
+
+    private static void createDefaultMongoConnection() throws Exception {
+        InputStream is = BaseMongoMicroKernelTest.class.getResourceAsStream("/config.cfg");
+        Properties properties = new Properties();
+        properties.load(is);
+
+        String host = properties.getProperty("host");
+        int port = Integer.parseInt(properties.getProperty("port"));
+        String database = properties.getProperty("db");
+
+        mongoConnection = new MongoConnection(host, port, database);
+    }
+
+    protected void dropCollections(DB db) {
+        db.getCollection(MongoBlobStore.COLLECTION_BLOBS).drop();
+        db.getCollection(MongoNodeStore.COLLECTION_COMMITS).drop();
+        db.getCollection(MongoNodeStore.COLLECTION_NODES).drop();
+        db.getCollection(MongoNodeStore.COLLECTION_SYNC).drop();
+    }
+}
\ No newline at end of file

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/BaseMongoMicroKernelTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/BaseMongoMicroKernelTest.java
------------------------------------------------------------------------------
    svn:keywords = Author Date Id Revision Rev URL

Modified: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/MongoAssert.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/MongoAssert.java?rev=1407119&r1=1407118&r2=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/MongoAssert.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/MongoAssert.java Thu Nov  8 15:17:50 2012
@@ -18,16 +18,18 @@ package org.apache.jackrabbit.mongomk;
 
 import java.util.Arrays;
 import java.util.HashSet;
+import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
 
 import org.apache.jackrabbit.mongomk.api.model.Commit;
 import org.apache.jackrabbit.mongomk.api.model.Node;
-import org.apache.jackrabbit.mongomk.impl.MongoConnection;
-import org.apache.jackrabbit.mongomk.model.CommitMongo;
-import org.apache.jackrabbit.mongomk.model.HeadMongo;
-import org.apache.jackrabbit.mongomk.model.NodeMongo;
+import org.apache.jackrabbit.mongomk.impl.MongoNodeStore;
+import org.apache.jackrabbit.mongomk.impl.model.MongoCommit;
+import org.apache.jackrabbit.mongomk.impl.model.MongoNode;
+import org.apache.jackrabbit.mongomk.impl.model.MongoSync;
+import org.apache.jackrabbit.mongomk.util.MongoUtil;
+import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.junit.Assert;
 
 import com.mongodb.DBCollection;
@@ -36,19 +38,17 @@ import com.mongodb.QueryBuilder;
 
 /**
  * Assertion utilities for {@code MongoDB} tests.
- *
- * @author <a href="mailto:pmarx@adobe.com>Philipp Marx</a>
  */
-@SuppressWarnings("javadoc")
 public class MongoAssert {
 
-    private static MongoConnection mongoConnection;
+    private static MongoNodeStore nodeStore;
 
-    public static void assertCommitContainsAffectedPaths(Long revisionId, String... expectedPaths) {
-        DBCollection commitCollection = mongoConnection.getCommitCollection();
-        DBObject query = QueryBuilder.start(CommitMongo.KEY_REVISION_ID)
-                .is(revisionId).get();
-        CommitMongo result = (CommitMongo) commitCollection.findOne(query);
+    public static void assertCommitContainsAffectedPaths(String revisionId,
+            String... expectedPaths) throws Exception {
+        DBCollection commitCollection = nodeStore.getCommitCollection();
+        DBObject query = QueryBuilder.start(MongoCommit.KEY_REVISION_ID)
+                .is(MongoUtil.toMongoRepresentation(revisionId)).get();
+        MongoCommit result = (MongoCommit) commitCollection.findOne(query);
         Assert.assertNotNull(result);
 
         List<String> actualPaths = result.getAffectedPaths();
@@ -56,32 +56,33 @@ public class MongoAssert {
     }
 
     public static void assertCommitExists(Commit commit) {
-        DBCollection commitCollection = mongoConnection.getCommitCollection();
-        DBObject query = QueryBuilder.start(CommitMongo.KEY_REVISION_ID)
-                .is(commit.getRevisionId()).and(CommitMongo.KEY_MESSAGE)
-                .is(commit.getMessage()).and(CommitMongo.KEY_DIFF).is(commit.getDiff()).and(CommitMongo.KEY_PATH)
-                .is(commit.getPath()).and(CommitMongo.KEY_FAILED).notEquals(Boolean.TRUE).get();
-        CommitMongo result = (CommitMongo) commitCollection.findOne(query);
+        DBCollection commitCollection = nodeStore.getCommitCollection();
+        DBObject query = QueryBuilder.start(MongoCommit.KEY_REVISION_ID)
+                .is(commit.getRevisionId()).and(MongoCommit.KEY_MESSAGE)
+                .is(commit.getMessage()).and(MongoCommit.KEY_DIFF).is(commit.getDiff()).and(MongoCommit.KEY_PATH)
+                .is(commit.getPath()).and(MongoCommit.KEY_FAILED).notEquals(Boolean.TRUE).get();
+        MongoCommit result = (MongoCommit) commitCollection.findOne(query);
         Assert.assertNotNull(result);
     }
 
     public static void assertHeadRevision(long revisionId) {
-        DBCollection headCollection = mongoConnection.getHeadCollection();
-        HeadMongo result = (HeadMongo) headCollection.findOne();
+        DBCollection headCollection = nodeStore.getSyncCollection();
+        MongoSync result = (MongoSync) headCollection.findOne();
         Assert.assertEquals(revisionId, result.getHeadRevisionId());
     }
 
     public static void assertNextRevision(long revisionId) {
-        DBCollection headCollection = mongoConnection.getHeadCollection();
-        HeadMongo result = (HeadMongo) headCollection.findOne();
+        DBCollection headCollection = nodeStore.getSyncCollection();
+        MongoSync result = (MongoSync) headCollection.findOne();
         Assert.assertEquals(revisionId, result.getNextRevisionId());
     }
 
-    public static void assertNodeRevisionId(String path, Long revisionId, boolean exists) {
-        DBCollection nodeCollection = mongoConnection.getNodeCollection();
-        DBObject query = QueryBuilder.start(NodeMongo.KEY_PATH).is(path).and(NodeMongo.KEY_REVISION_ID)
-                .is(revisionId).get();
-        NodeMongo nodeMongo = (NodeMongo) nodeCollection.findOne(query);
+    public static void assertNodeRevisionId(String path, String revisionId,
+            boolean exists) throws Exception {
+        DBCollection nodeCollection = nodeStore.getNodeCollection();
+        DBObject query = QueryBuilder.start(MongoNode.KEY_PATH).is(path).and(MongoNode.KEY_REVISION_ID)
+                .is(MongoUtil.toMongoRepresentation(revisionId)).get();
+        MongoNode nodeMongo = (MongoNode) nodeCollection.findOne(query);
 
         if (exists) {
             Assert.assertNotNull(nodeMongo);
@@ -91,43 +92,36 @@ public class MongoAssert {
     }
 
     public static void assertNodesExist(Node expected) {
-        DBCollection nodeCollection = mongoConnection.getNodeCollection();
-        QueryBuilder qb = QueryBuilder.start(NodeMongo.KEY_PATH).is(expected.getPath())
-                .and(NodeMongo.KEY_REVISION_ID)
+        DBCollection nodeCollection = nodeStore.getNodeCollection();
+        QueryBuilder qb = QueryBuilder.start(MongoNode.KEY_PATH).is(expected.getPath())
+                .and(MongoNode.KEY_REVISION_ID)
                 .is(expected.getRevisionId());
-        Map<String, Object> properties = expected.getProperties();
+        Map<String, String> properties = expected.getProperties();
         if (properties != null) {
-            for (Map.Entry<String, Object> entry : properties.entrySet()) {
-                qb.and(NodeMongo.KEY_PROPERTIES + "." + entry.getKey()).is(entry.getValue());
+            for (Map.Entry<String, String> entry : properties.entrySet()) {
+                qb.and(MongoNode.KEY_PROPERTIES + "." + entry.getKey()).is(entry.getValue());
             }
         }
 
         DBObject query = qb.get();
 
-        NodeMongo nodeMongo = (NodeMongo) nodeCollection.findOne(query);
+        MongoNode nodeMongo = (MongoNode) nodeCollection.findOne(query);
         Assert.assertNotNull(nodeMongo);
 
-        Set<Node> children = expected.getChildren();
-        if (children != null) {
-            List<String> childNames = nodeMongo.getChildren();
-            Assert.assertNotNull(childNames);
-            Assert.assertEquals(children.size(), childNames.size());
-            Assert.assertEquals(children.size(), new HashSet<String>(childNames).size());
-            for (Node child : children) {
-                assertNodesExist(child);
-                Assert.assertTrue(childNames.contains(child.getName()));
-            }
-        } else {
-            Assert.assertNull(nodeMongo.getChildren());
+        List<String> nodeMongoChildren = nodeMongo.getChildren();
+        int actual = nodeMongoChildren != null? nodeMongoChildren.size() : 0;
+        Assert.assertEquals(expected.getChildNodeCount(), actual);
+
+        for (Iterator<Node> it = expected.getChildNodeEntries(0, -1); it.hasNext(); ) {
+            Node childNode = it.next();
+            assertNodesExist(childNode);
+            String childName = PathUtils.getName(childNode.getPath());
+            Assert.assertTrue(nodeMongoChildren.contains(childName));
         }
     }
 
-    static void setMongoConnection(MongoConnection mongoConnection) {
+    public static void setNodeStore(MongoNodeStore nodeStore) {
         // must be set prior to using this class.
-        MongoAssert.mongoConnection = mongoConnection;
-    }
-
-    private MongoAssert() {
-        // no instantiation
+        MongoAssert.nodeStore = nodeStore;
     }
-}
+}
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/impl/InstructionAssert.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/impl/InstructionAssert.java?rev=1407119&r1=1407118&r2=1407119&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/impl/InstructionAssert.java (original)
+++ jackrabbit/oak/trunk/oak-mongomk/src/test/java/org/apache/jackrabbit/mongomk/impl/InstructionAssert.java Thu Nov  8 15:17:50 2012
@@ -18,31 +18,18 @@ package org.apache.jackrabbit.mongomk.im
 
 import static junit.framework.Assert.assertEquals;
 
-import org.apache.jackrabbit.mongomk.api.model.Instruction.AddNodeInstruction;
-import org.apache.jackrabbit.mongomk.api.model.Instruction.AddPropertyInstruction;
-import org.apache.jackrabbit.mongomk.api.model.Instruction.CopyNodeInstruction;
-import org.apache.jackrabbit.mongomk.api.model.Instruction.MoveNodeInstruction;
-import org.apache.jackrabbit.mongomk.api.model.Instruction.RemoveNodeInstruction;
-import org.apache.jackrabbit.mongomk.api.model.Instruction.SetPropertyInstruction;
+import org.apache.jackrabbit.mongomk.api.instruction.Instruction.AddNodeInstruction;
+import org.apache.jackrabbit.mongomk.api.instruction.Instruction.CopyNodeInstruction;
+import org.apache.jackrabbit.mongomk.api.instruction.Instruction.MoveNodeInstruction;
+import org.apache.jackrabbit.mongomk.api.instruction.Instruction.RemoveNodeInstruction;
+import org.apache.jackrabbit.mongomk.api.instruction.Instruction.SetPropertyInstruction;
 
-
-/**
- * @author <a href="mailto:pmarx@adobe.com>Philipp Marx</a>
- */
-@SuppressWarnings("javadoc")
 public class InstructionAssert {
 
     public static void assertAddNodeInstruction(AddNodeInstruction instruction, String path) {
         assertEquals(path, instruction.getPath());
     }
 
-    public static void assertAddPropertyInstruction(AddPropertyInstruction instruction, String path, String key,
-            Object value) {
-        assertEquals(path, instruction.getPath());
-        assertEquals(key, instruction.getKey());
-        assertEquals(value, instruction.getValue());
-    }
-
     public static void assertCopyNodeInstruction(CopyNodeInstruction instruction, String path, String sourcePath,
             String destPath) {
         assertEquals(path, instruction.getPath());
@@ -67,8 +54,4 @@ public class InstructionAssert {
         assertEquals(key, instruction.getKey());
         assertEquals(value, instruction.getValue());
     }
-
-    private InstructionAssert() {
-        // no instantiation
-    }
-}
+}
\ No newline at end of file



Mime
View raw message