You are viewing a plain text version of this content. The canonical link for it is here.
Posted to oak-commits@jackrabbit.apache.org by ju...@apache.org on 2013/05/17 11:18:00 UTC

svn commit: r1483709 - in /jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak: osgi/ plugins/nodetype/ spi/commit/

Author: jukka
Date: Fri May 17 09:17:59 2013
New Revision: 1483709

URL: http://svn.apache.org/r1483709
Log:
OAK-66: JCR Node Type Management

Move the calculation of effective types from enter() to childNodeAdded/Changed() where it belongs

Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/OsgiEditorProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveType.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditor.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/CompositeEditorProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/EditorProvider.java

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/OsgiEditorProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/OsgiEditorProvider.java?rev=1483709&r1=1483708&r2=1483709&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/OsgiEditorProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/osgi/OsgiEditorProvider.java Fri May 17 09:17:59 2013
@@ -20,6 +20,7 @@ package org.apache.jackrabbit.oak.osgi;
 
 import javax.annotation.CheckForNull;
 
+import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.spi.commit.CompositeEditorProvider;
 import org.apache.jackrabbit.oak.spi.commit.Editor;
 import org.apache.jackrabbit.oak.spi.commit.EditorProvider;
@@ -43,7 +44,8 @@ public class OsgiEditorProvider
     @Override
     @CheckForNull
     public Editor getRootEditor(
-            NodeState before, NodeState after, NodeBuilder builder) {
+            NodeState before, NodeState after, NodeBuilder builder)
+            throws CommitFailedException {
         EditorProvider provider =
                 CompositeEditorProvider.compose(getServices());
         return provider.getRootEditor(before, after, builder);

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveType.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveType.java?rev=1483709&r1=1483708&r2=1483709&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveType.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveType.java Fri May 17 09:17:59 2013
@@ -18,15 +18,23 @@ package org.apache.jackrabbit.oak.plugin
 
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.collect.Iterables.addAll;
+import static com.google.common.collect.Iterables.concat;
+import static com.google.common.collect.Lists.newArrayListWithCapacity;
 import static com.google.common.collect.Sets.newHashSet;
+import static org.apache.jackrabbit.JcrConstants.JCR_DEFAULTPRIMARYTYPE;
+import static org.apache.jackrabbit.JcrConstants.JCR_ISMIXIN;
 import static org.apache.jackrabbit.JcrConstants.JCR_MANDATORY;
 import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
 import static org.apache.jackrabbit.JcrConstants.JCR_NODETYPENAME;
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
 import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
+import static org.apache.jackrabbit.oak.api.CommitFailedException.CONSTRAINT;
 import static org.apache.jackrabbit.oak.api.Type.NAMES;
 import static org.apache.jackrabbit.oak.api.Type.UNDEFINED;
 import static org.apache.jackrabbit.oak.api.Type.UNDEFINEDS;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_IS_ABSTRACT;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_NAMED_CHILD_NODE_DEFINITIONS;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_RESIDUAL_CHILD_NODE_DEFINITIONS;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.OAK_SUPERTYPES;
 
 import java.util.List;
@@ -35,12 +43,14 @@ import java.util.Set;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 
+import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.spi.state.ChildNodeEntry;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
 import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
 
 class EffectiveType {
 
@@ -50,6 +60,12 @@ class EffectiveType {
         this.types = checkNotNull(types);
     }
 
+    CommitFailedException constraintViolation(
+            int code, String path, String message) {
+        return new CommitFailedException(
+                CONSTRAINT, code, path + this + ": " + message);
+    }
+
     @Nonnull
     Set<String> findMissingMandatoryItems(NodeState node) {
         ImmutableSet.Builder<String> builder = ImmutableSet.builder();
@@ -154,24 +170,13 @@ class EffectiveType {
      * Finds a matching definition for a child node with the given name and
      * types.
      *
-     * @param nodeName child node name
+     * @param nameWithIndex child node name, possibly with an SNS index
      * @param nodeType effective types of the child node
      * @return matching child node definition, or {@code null} if not found
      */
     @CheckForNull
-    NodeState getDefinition(String nodeName, Iterable<String> nodeType) {
-        boolean sns = false;
-        int n = nodeName.length();
-        if (n > 3 && nodeName.charAt(n - 1) == ']') {
-            int i = n - 2;
-            while (i > 1 && Character.isDigit(nodeName.charAt(i))) {
-                i--;
-            }
-            if (nodeName.charAt(i) == '[') {
-                nodeName = nodeName.substring(0, i);
-                sns = true;
-            }
-        }
+    NodeState getDefinition(String nameWithIndex, Iterable<String> nodeType) {
+        String nodeName = getNameWithoutIndex(nameWithIndex);
 
         // Find matching named child node definition
         for (NodeState type : types) {
@@ -216,6 +221,37 @@ class EffectiveType {
         return null;
     }
 
+    /**
+     * Finds the default node type for a child node with the given name.
+     *
+     * @param nameWithIndex child node name, possibly with an SNS index
+     * @return default type, or {@code null} if not found
+     */
+    @CheckForNull
+    String getDefaultType(String nameWithIndex) {
+        String name = getNameWithoutIndex(nameWithIndex);
+
+        for (NodeState type : types) {
+            NodeState named = type
+                    .getChildNode(OAK_NAMED_CHILD_NODE_DEFINITIONS)
+                    .getChildNode(name);
+            NodeState residual = type
+                    .getChildNode(OAK_RESIDUAL_CHILD_NODE_DEFINITIONS);
+
+            for (ChildNodeEntry entry : concat(
+                    named.getChildNodeEntries(),
+                    residual.getChildNodeEntries())) {
+                NodeState definition = entry.getNodeState();
+                String defaultType = definition.getName(JCR_DEFAULTPRIMARYTYPE);
+                if (defaultType != null) {
+                    return defaultType;
+                }
+            }
+        }
+
+        return null;
+    }
+
     Set<String> getTypeNames() {
         Set<String> names = newHashSet();
         for (NodeState type : types) {
@@ -225,4 +261,89 @@ class EffectiveType {
         return names;
     }
 
+    /**
+     * Collects the primary and mixin types and all related supertypes
+     * of the given child node and returns them as an effective node type.
+     *
+     * @param types the {@code /jcr:system/jcr:nodeTypes} subtree
+     * @param path path of the parent node
+     * @param name name of the child node
+     * @param primary name of the primary type
+     * @param mixins names of the mixin types
+     * @throws CommitFailedException if the effective node type is invalid
+     */
+    EffectiveType computeEffectiveType(
+            NodeState types, String path,
+            String name, String primary, Iterable<String> mixins)
+            throws CommitFailedException {
+        List<NodeState> list = Lists.newArrayList();
+
+        NodeState type = types.getChildNode(primary);
+        if (!type.exists()) {
+            throw constraintViolation(
+                    11, path, "The primary type " + primary
+                    + " of child node " + name + " does not exist");
+        } else if (type.getBoolean(JCR_ISMIXIN)) {
+            throw constraintViolation(
+                    12, path, "Mixin type " + primary
+                    + " used as the primary type of child node " + name);
+        } else if (type.getBoolean(JCR_IS_ABSTRACT)) {
+            throw constraintViolation(
+                    13, path, "Abstract type " + primary
+                    + " used as the primary type of child node " + name);
+        } else {
+            list.add(type);
+        }
+
+        // mixin types
+        for (String mixin : mixins) {
+            type = types.getChildNode(mixin);
+            if (!type.exists()) {
+                throw constraintViolation(
+                        14, path, "The mixin type " + mixin
+                        + " of child node " + name + " does not exist");
+            } else if (!type.getBoolean(JCR_ISMIXIN)) {
+                throw constraintViolation(
+                        15, path, "Primary type " + mixin
+                        + " used as a mixin type of child node " + name);
+            } else if (type.getBoolean(JCR_IS_ABSTRACT)) {
+                throw constraintViolation(
+                        16, path, "Abstract type " + mixin
+                        + " used as a mixin type of child node " + name);
+            } else {
+                list.add(type);
+            }
+        }
+
+        return new EffectiveType(list);
+    }
+
+
+    //------------------------------------------------------------< Object >--
+
+    @Override
+    public String toString() {
+        List<String> names = newArrayListWithCapacity(types.size());
+        for (NodeState type : types) {
+            names.add(type.getName(JCR_NODETYPENAME));
+        }
+        return names.toString();
+    }
+
+    //-----------------------------------------------------------< private >--
+
+    private static String getNameWithoutIndex(String name) {
+        int n = name.length();
+        if (n > 3 && name.charAt(n - 1) == ']') {
+            int i = n - 2;
+            while (i > 1 && Character.isDigit(name.charAt(i))) {
+                i--;
+            }
+            if (name.charAt(i) == '[') {
+                return name.substring(0, i);
+            }
+        }
+        return name;
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditor.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditor.java?rev=1483709&r1=1483708&r2=1483709&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditor.java Fri May 17 09:17:59 2013
@@ -16,14 +16,12 @@
  */
 package org.apache.jackrabbit.oak.plugins.nodetype;
 
-import java.util.List;
 import java.util.Set;
 import javax.jcr.PropertyType;
 import javax.jcr.Value;
 
 import com.google.common.base.Joiner;
 import com.google.common.base.Predicate;
-import com.google.common.collect.Lists;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.api.PropertyState;
 import org.apache.jackrabbit.oak.api.Type;
@@ -35,21 +33,16 @@ import org.apache.jackrabbit.oak.spi.sta
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Lists.newArrayList;
-import static org.apache.jackrabbit.JcrConstants.JCR_ISMIXIN;
 import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
 import static org.apache.jackrabbit.JcrConstants.JCR_NAME;
 import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
 import static org.apache.jackrabbit.JcrConstants.JCR_REQUIREDTYPE;
 import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
 import static org.apache.jackrabbit.JcrConstants.JCR_VALUECONSTRAINTS;
-import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED;
-import static org.apache.jackrabbit.oak.api.CommitFailedException.CONSTRAINT;
 import static org.apache.jackrabbit.oak.api.Type.NAME;
-import static org.apache.jackrabbit.oak.api.Type.NAMES;
 import static org.apache.jackrabbit.oak.api.Type.STRING;
 import static org.apache.jackrabbit.oak.api.Type.STRINGS;
-import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_IS_ABSTRACT;
+import static org.apache.jackrabbit.oak.plugins.memory.EmptyNodeState.MISSING_NODE;
 import static org.apache.jackrabbit.oak.plugins.nodetype.constraint.Constraints.valueConstraint;
 
 /**
@@ -69,31 +62,31 @@ class TypeEditor extends DefaultEditor {
 
     private final NodeState types;
 
-    private final List<String> typeNames = newArrayList();
+    private EffectiveType effective;
 
-    private EffectiveType effective = null;
+    private final NodeBuilder builder;
 
-    private final NodeBuilder node;
-
-    // TODO: Calculate default type from the node definition
-    private final String defaultType = NT_UNSTRUCTURED;
-
-    TypeEditor(NodeState types, NodeBuilder node) {
+    TypeEditor(NodeState types, EffectiveType effective, NodeBuilder builder) {
         this.parent = null;
         this.nodeName = null;
         this.types = checkNotNull(types);
-        this.node = node;
+        this.effective = checkNotNull(effective);
+        this.builder = checkNotNull(builder);
     }
 
-    private TypeEditor(TypeEditor parent, String name) {
+    private TypeEditor(
+            TypeEditor parent, String name,
+            EffectiveType effective, NodeBuilder builder) {
         this.parent = checkNotNull(parent);
         this.nodeName = checkNotNull(name);
         this.types = parent.types;
-        if (parent != null && parent.node != null) {
-            this.node = parent.node.child(name);
-        } else {
-            this.node = null;
-        }
+        this.effective = checkNotNull(effective);
+        this.builder = checkNotNull(builder);
+    }
+
+    private CommitFailedException constraintViolation(
+            int code, String message) {
+        return effective.constraintViolation(code, getPath(), message);
     }
 
     private String getPath() {
@@ -106,46 +99,19 @@ class TypeEditor extends DefaultEditor {
         }
     }
 
-    /**
-     * Computes the effective type of the modified type.
-     */
-    @Override
-    public void enter(NodeState before, NodeState after)
-            throws CommitFailedException {
-        if (after.getProperty(JCR_PRIMARYTYPE) == null && node != null) {
-            node.setProperty(JCR_PRIMARYTYPE, defaultType, Type.NAME);
-        }
-        computeEffectiveType(after);
-
-        // find matching entry in the parent node's effective type
-        // TODO: this should be in childNodeAdded()
-        if (parent != null && parent.effective.getDefinition(
-                nodeName, effective.getTypeNames()) == null) {
-            Set<String> parentTypes = parent.effective.getTypeNames();
-            throw constraintViolation(
-                    1, "No matching child node definition found for child node "
-                    + nodeName + " in any of the parent types " + parentTypes);
-        }
-    }
-
     @Override
     public void leave(NodeState before, NodeState after)
             throws CommitFailedException {
         // TODO: add any auto-created items that are still missing
 
         // verify the presence of all mandatory items
-        Set<String> missing = effective.findMissingMandatoryItems(node.getNodeState());
+        Set<String> missing = effective.findMissingMandatoryItems(builder.getNodeState());
         if (!missing.isEmpty()) {
             throw constraintViolation(
                     2, "Missing mandatory items " + Joiner.on(", ").join(missing));
         }
     }
 
-    private CommitFailedException constraintViolation(int code, String message) {
-        return new CommitFailedException(
-                CONSTRAINT, code, getPath() + typeNames + ": " + message);
-    }
-
     @Override
     public void propertyAdded(PropertyState after) throws CommitFailedException {
         NodeState definition = effective.getDefinition(after);
@@ -172,14 +138,39 @@ class TypeEditor extends DefaultEditor {
     @Override
     public Editor childNodeAdded(String name, NodeState after)
             throws CommitFailedException {
-        return new TypeEditor(this, name);
+        return childNodeChanged(name, MISSING_NODE, after);
     }
 
     @Override
     public Editor childNodeChanged(
             String name, NodeState before, NodeState after)
             throws CommitFailedException {
-        return new TypeEditor(this, name);
+        NodeBuilder childBuilder = builder.getChildNode(name);
+
+        String primary = after.getName(JCR_PRIMARYTYPE);
+        if (primary == null) {
+            // no primary type defined, find and apply a default type
+            primary = effective.getDefaultType(name);
+            if (primary != null) {
+                builder.setProperty(JCR_PRIMARYTYPE, primary, NAME);
+            } else {
+                throw constraintViolation(
+                        5, "No default primary type available "
+                        + " for child node " + name);
+            }
+        }
+
+        EffectiveType childType = effective.computeEffectiveType(
+                types, getPath(), // TODO: compute path only on demand
+                name, primary, after.getNames(JCR_MIXINTYPES));
+
+        if (effective.getDefinition(name, childType.getTypeNames()) == null) {
+            throw constraintViolation(
+                    1, "No matching definition found for child node " + name
+                    + " with effective type " + childType.getTypeNames());
+        }
+
+        return new TypeEditor(this, name, childType, childBuilder);
     }
 
     //-----------------------------------------------------------< private >--
@@ -259,62 +250,4 @@ class TypeEditor extends DefaultEditor {
         return JCR_UUID.equals(property.getName()) && JCR_UUID.equals(definition.getName(JCR_NAME));
     }
 
-    /**
-     * Collects the primary and mixin types and all related supertypes
-     * of the given node and places them in the {@link #effective} list
-     * of effective node type definitions.
-     *
-     * @param node node state
-     * @throws CommitFailedException if the effective node type is invalid
-     */
-    private void computeEffectiveType(NodeState node)
-            throws CommitFailedException {
-        List<NodeState> list = Lists.newArrayList();
-
-        // primary type
-        PropertyState primary = node.getProperty(JCR_PRIMARYTYPE);
-        if (primary != null && primary.getType() == NAME) {
-            String name = primary.getValue(NAME);
-            typeNames.add(name);
-
-            NodeState type = types.getChildNode(name);
-            if (!type.exists()) {
-                throw constraintViolation(
-                        6, "Primary node type " + name + " does not exist");
-            } else if (type.getBoolean(JCR_ISMIXIN)) {
-                throw constraintViolation(
-                        7, "Can not use mixin type " + name + " as primary");
-            } else if (type.getBoolean(JCR_IS_ABSTRACT)) {
-                throw constraintViolation(
-                        8, "Can not use abstract type " + name + " as primary");
-            }
-
-            list.add(type);
-        }
-
-        // mixin types
-        PropertyState mixins = node.getProperty(JCR_MIXINTYPES);
-        if (mixins != null && mixins.getType() == NAMES) {
-            for (String name : mixins.getValue(NAMES)) {
-                typeNames.add(name);
-
-                NodeState type = types.getChildNode(name);
-                if (!type.exists()) {
-                    throw constraintViolation(
-                            9, "Mixin node type " + name + " does not exist");
-                } else if (!type.getBoolean(JCR_ISMIXIN)) {
-                    throw constraintViolation(
-                            10, "Can not use primary type " + name + " as mixin");
-                } else if (type.getBoolean(JCR_IS_ABSTRACT)) {
-                    throw constraintViolation(
-                            11, "Can not use abstract type " + name + " as mixin");
-                }
-
-                list.add(type);
-            }
-        }
-
-        effective = new EffectiveType(list);
-    }
-
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorProvider.java?rev=1483709&r1=1483708&r2=1483709&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorProvider.java Fri May 17 09:17:59 2013
@@ -16,11 +16,16 @@
  */
 package org.apache.jackrabbit.oak.plugins.nodetype;
 
+import static java.util.Arrays.asList;
+import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
 import static org.apache.jackrabbit.JcrConstants.JCR_SYSTEM;
+import static org.apache.jackrabbit.oak.api.Type.NAME;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_NODE_TYPES;
 
 import org.apache.felix.scr.annotations.Component;
 import org.apache.felix.scr.annotations.Service;
+import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.spi.commit.Editor;
 import org.apache.jackrabbit.oak.spi.commit.EditorProvider;
 import org.apache.jackrabbit.oak.spi.commit.VisibleEditor;
@@ -33,11 +38,24 @@ public class TypeEditorProvider implemen
 
     @Override
     public Editor getRootEditor(
-            NodeState before, NodeState after, NodeBuilder builder) {
+            NodeState before, NodeState after, NodeBuilder builder)
+            throws CommitFailedException {
         NodeState system = after.getChildNode(JCR_SYSTEM);
         NodeState types = system.getChildNode(JCR_NODE_TYPES);
         if (types.exists()) {
-            return new VisibleEditor(new TypeEditor(types, builder));
+
+            String primary = after.getName(JCR_PRIMARYTYPE);
+            if (primary == null) {
+                // no primary type on the root node, set the hardcoded default
+                primary = "rep:root";
+                builder.setProperty(JCR_PRIMARYTYPE, primary, NAME);
+            }
+            NodeState unstructured = types.getChildNode("oak:unstructured");
+            EffectiveType parent = new EffectiveType(asList(unstructured));
+            EffectiveType effective = parent.computeEffectiveType(
+                    types, "/", null, primary, after.getNames(JCR_MIXINTYPES));
+
+            return new VisibleEditor(new TypeEditor(types, effective, builder));
         } else {
             return null;
         }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/CompositeEditorProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/CompositeEditorProvider.java?rev=1483709&r1=1483708&r2=1483709&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/CompositeEditorProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/CompositeEditorProvider.java Fri May 17 09:17:59 2013
@@ -25,6 +25,7 @@ import java.util.List;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
 
+import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
@@ -71,7 +72,8 @@ public class CompositeEditorProvider imp
 
     @Override @CheckForNull
     public Editor getRootEditor(
-            NodeState before, NodeState after, NodeBuilder builder) {
+            NodeState before, NodeState after, NodeBuilder builder)
+            throws CommitFailedException {
         List<Editor> list = Lists.newArrayListWithCapacity(providers.size());
         for (EditorProvider provider : providers) {
             Editor editor = provider.getRootEditor(before, after, builder);

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/EditorProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/EditorProvider.java?rev=1483709&r1=1483708&r2=1483709&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/EditorProvider.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/spi/commit/EditorProvider.java Fri May 17 09:17:59 2013
@@ -16,6 +16,7 @@
  */
 package org.apache.jackrabbit.oak.spi.commit;
 
+import org.apache.jackrabbit.oak.api.CommitFailedException;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
 import org.apache.jackrabbit.oak.spi.state.NodeState;
 
@@ -44,8 +45,10 @@ public interface EditorProvider {
      * @param after   modified root state
      * @param builder node builder based on the after state
      * @return editor for processing the changes, or {@code null}
+     * @throws CommitFailedException if processing failed
      */
     @CheckForNull
-    Editor getRootEditor(NodeState before, NodeState after, NodeBuilder builder);
+    Editor getRootEditor(NodeState before, NodeState after, NodeBuilder builder)
+        throws CommitFailedException;
 
 }