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 2014/01/14 23:10:28 UTC

svn commit: r1558226 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/ oak-core/src/main/resources/org/apache/jackrabbit/oak/plugins/n...

Author: jukka
Date: Tue Jan 14 22:10:27 2014
New Revision: 1558226

URL: http://svn.apache.org/r1558226
Log:
OAK-411: Validator for node type management

Merge RegistrationEditor functionality into TypeEditor to ensure that type validation is always done against properly updated type definitions.
Implement consistency checks for node type removals and modifications.
Fix some affected node type definitions and test expectations.

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeRegistration.java
      - copied, changed from r1558162, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/RegistrationEditor.java
Removed:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/RegistrationEditor.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/RegistrationEditorProvider.java
Modified:
    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/plugins/nodetype/write/InitialContent.java
    jackrabbit/oak/trunk/oak-core/src/main/resources/org/apache/jackrabbit/oak/plugins/nodetype/write/builtin_nodetypes.cnd
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlValidatorTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/JcrUUIDTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/ShadowInvisibleContentTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/ClusterPermissionsTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeValidatorTest.java
    jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserInitializerTest.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
    jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/NodeTypeTest.java
    jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java

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=1558226&r1=1558225&r2=1558226&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 Tue Jan 14 22:10:27 2014
@@ -41,6 +41,7 @@ import static org.apache.jackrabbit.JcrC
 import static org.apache.jackrabbit.JcrConstants.JCR_UUID;
 import static org.apache.jackrabbit.JcrConstants.JCR_VALUECONSTRAINTS;
 import static org.apache.jackrabbit.JcrConstants.MIX_REFERENCEABLE;
+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.STRING;
 import static org.apache.jackrabbit.oak.api.Type.STRINGS;
@@ -106,7 +107,12 @@ class TypeEditor extends DefaultEditor {
 
     private CommitFailedException constraintViolation(
             int code, String message) {
-        return effective.constraintViolation(code, getPath(), message);
+        if (effective != null) {
+            return effective.constraintViolation(code, getPath(), message);
+        } else {
+            return new CommitFailedException(
+                    CONSTRAINT, 0, getPath() + ": " + message);
+        }
     }
 
     private String getPath() {
@@ -165,14 +171,14 @@ class TypeEditor extends DefaultEditor {
         // verify the presence of all mandatory items
         for (String property : editor.effective.getMandatoryProperties()) {
             if (!after.hasProperty(property)) {
-                throw constraintViolation(
+                throw editor.constraintViolation(
                         21, "Mandatory property " + property
                         + " not found in a new node");
             }
         }
         for (String child : editor.effective.getMandatoryChildNodes()) {
             if (!after.hasChildNode(child)) {
-                throw constraintViolation(
+                throw editor.constraintViolation(
                         25, "Mandatory child node " + child
                         + " not found in a new node");
             }

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=1558226&r1=1558225&r2=1558226&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 Tue Jan 14 22:10:27 2014
@@ -20,12 +20,17 @@ import static org.apache.jackrabbit.JcrC
 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.memory.EmptyNodeState.MISSING_NODE;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_NODE_TYPES;
 
+import java.util.Collections;
+import java.util.Set;
+
 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.EditorDiff;
 import org.apache.jackrabbit.oak.spi.commit.EditorProvider;
 import org.apache.jackrabbit.oak.spi.commit.VisibleEditor;
 import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
@@ -39,22 +44,41 @@ public class TypeEditorProvider implemen
     public Editor getRootEditor(
             NodeState before, NodeState after, NodeBuilder builder)
             throws CommitFailedException {
-        NodeState system = after.getChildNode(JCR_SYSTEM);
-        NodeState types = system.getChildNode(JCR_NODE_TYPES);
-        if (types.exists()) {
-
-            String primary = after.getName(JCR_PRIMARYTYPE);
-            Iterable<String> mixins = after.getNames(JCR_MIXINTYPES);
-
-            if (primary == null) {
-                // no primary type on the root node, set the hardcoded default
-                primary = "rep:root";
-                builder.setProperty(JCR_PRIMARYTYPE, primary, NAME);
-            }
+        NodeState beforeTypes =
+                before.getChildNode(JCR_SYSTEM).getChildNode(JCR_NODE_TYPES);
+        NodeState afterTypes =
+                after.getChildNode(JCR_SYSTEM).getChildNode(JCR_NODE_TYPES);
+
+        Set<String> modifiedTypes = Collections.emptySet();
+        TypeRegistration registration = new TypeRegistration();
+        afterTypes.compareAgainstBaseState(beforeTypes, registration);
+        if (registration.isModified()) {
+            afterTypes = registration.apply(builder);
+            modifiedTypes = registration.getModifiedTypes(beforeTypes);
+        }
+
+        String primary = after.getName(JCR_PRIMARYTYPE);
+        Iterable<String> mixins = after.getNames(JCR_MIXINTYPES);
 
-            return new VisibleEditor(
-                    new TypeEditor(types, primary, mixins, builder));
+        if (primary == null && afterTypes.hasChildNode("rep:root")) {
+            // no primary type on the root node, set the hardcoded default
+            primary = "rep:root";
+            builder.setProperty(JCR_PRIMARYTYPE, primary, NAME);
+        }
+
+        Editor editor = new VisibleEditor(
+                new TypeEditor(afterTypes, primary, mixins, builder));
+        if (modifiedTypes.isEmpty()) {
+            return editor;
         } else {
+            // Some node types were modified, so scan the entire repository
+            // to make sure that the modified type definitions still apply.
+            // TODO: Only check the content that uses the modified node types.
+            CommitFailedException exception =
+                    EditorDiff.process(editor, MISSING_NODE, after);
+            if (exception != null) {
+                throw exception;
+            }
             return null;
         }
     }

Copied: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeRegistration.java (from r1558162, jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/RegistrationEditor.java)
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeRegistration.java?p2=jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeRegistration.java&p1=jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/RegistrationEditor.java&r1=1558162&r2=1558226&rev=1558226&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/RegistrationEditor.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeRegistration.java Tue Jan 14 22:10:27 2014
@@ -16,24 +16,12 @@
  */
 package org.apache.jackrabbit.oak.plugins.nodetype;
 
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Set;
-
-import com.google.common.collect.Iterables;
-import org.apache.jackrabbit.oak.api.CommitFailedException;
-import org.apache.jackrabbit.oak.api.PropertyState;
-import org.apache.jackrabbit.oak.spi.commit.DefaultEditor;
-import org.apache.jackrabbit.oak.spi.commit.Validator;
-import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
-import org.apache.jackrabbit.oak.spi.state.NodeState;
-
-import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.addAll;
 import static com.google.common.collect.Iterables.contains;
 import static com.google.common.collect.Lists.newArrayList;
 import static com.google.common.collect.Sets.newHashSet;
 import static com.google.common.collect.Sets.newLinkedHashSet;
+import static com.google.common.collect.Sets.union;
 import static java.util.Collections.emptyList;
 import static org.apache.jackrabbit.JcrConstants.JCR_CHILDNODEDEFINITION;
 import static org.apache.jackrabbit.JcrConstants.JCR_ISMIXIN;
@@ -76,33 +64,129 @@ import static org.apache.jackrabbit.oak.
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.REP_SUPERTYPES;
 import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.REP_UUID;
 
+import java.util.Collections;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+import org.apache.jackrabbit.oak.api.CommitFailedException;
+import org.apache.jackrabbit.oak.api.PropertyState;
+import org.apache.jackrabbit.oak.spi.state.DefaultNodeStateDiff;
+import org.apache.jackrabbit.oak.spi.state.NodeBuilder;
+import org.apache.jackrabbit.oak.spi.state.NodeState;
+
+import com.google.common.collect.Iterables;
+
 /**
- * Editor that validates the consistency of the in-content node type registry
- * under {@code /jcr:system/jcr:nodeTypes} and maintains the access-optimized
- * versions of node type information as defined in {@code rep:NodeType}.
+ * This class is used by the {@link TypeEditorProvider} to check for,
+ * validate, and post-process changes to the in-content node type registry
+ * under {@code /jcr:system/jcr:nodeTypes}. The post-processing is used to
+ * maintain the access-optimized versions of node type information as
+ * defined in {@code rep:NodeType}.
  *
  * <ul>
- *     <li>validate new definitions</li>
- *     <li>detect collisions,</li>
- *     <li>prevent circular inheritance,</li>
- *     <li>reject modifications to definitions that render existing content invalid,</li>
- *     <li>prevent un-registration of built-in node types.</li>
+ *   <li>validate new definitions,</li>
+ *   <li>detect collisions,</li>
+ *   <li>prevent circular inheritance,</li>
+ *   <li>reject modifications to definitions that render existing content invalid,</li>
+ *   <li>etc.</li>
  * </ul>
  */
-class RegistrationEditor extends DefaultEditor {
+class TypeRegistration extends DefaultNodeStateDiff {
 
-    private final NodeBuilder builder;
+    private final Set<String> addedTypes = newHashSet();
 
     private final Set<String> changedTypes = newHashSet();
 
     private final Set<String> removedTypes = newHashSet();
 
-    private boolean modified = false;
+    /**
+     * Checks whether any node type modifications were detected during
+     * the diff of the type registry.
+     *
+     * @return {@code true} if there were node type modifications,
+     *         {@code false} if not
+     */
+    boolean isModified() {
+        return !addedTypes.isEmpty()
+                || !changedTypes.isEmpty()
+                || !removedTypes.isEmpty();
+    }
+
+    /**
+     * Returns the names of all node types that may have been modified
+     * in backwards-incompatible ways (including being removed entirely),
+     * and thus need to be re-evaluated across the entire content tree.
+     * The names of potentially affected subtypes are also included.
+     *
+     * @param beforeTypes the type registry before the changes
+     * @return names of modified or removed node types
+     */
+    Set<String> getModifiedTypes(NodeState beforeTypes) {
+        Set<String> types = newHashSet();
+        for (String name : union(changedTypes, removedTypes)) {
+            types.add(name);
+            NodeState type = beforeTypes.getChildNode(name);
+            addAll(types, type.getNames(REP_PRIMARY_SUBTYPES));
+            addAll(types, type.getNames(REP_MIXIN_SUBTYPES));
+        }
+        return types;
+    }
+
+    NodeState apply(NodeBuilder builder) throws CommitFailedException {
+        NodeBuilder types = builder.child(JCR_SYSTEM).child(JCR_NODE_TYPES);
+
+        for (String name : types.getChildNodeNames()) {
+            validateAndCompileType(types, name);
+        }
+
+        for (String name : types.getChildNodeNames()) {
+            mergeSupertypes(types, types.child(name));
+        }
+
+        for (String name : types.getChildNodeNames()) {
+            NodeBuilder type = types.child(name);
+            String listName = REP_PRIMARY_SUBTYPES;
+            if (type.getBoolean(JCR_ISMIXIN)) {
+                listName = REP_MIXIN_SUBTYPES;
+            }
+            for (String supername : getNames(type, REP_SUPERTYPES)) {
+                addNameToList(types.child(supername), listName, name);
+            }
+        }
+
+        return types.getNodeState();
+    }
+
+    //-----------------------------------------------------< NodeStateDiff >--
+
+    @Override
+    public boolean childNodeAdded(String name, NodeState after) {
+        addedTypes.add(name);
+        return true;
+    }
+
+    @Override
+    public boolean childNodeChanged(
+            String name, NodeState before, NodeState after) {
+        // the NodeState.equals() method is potentially expensive
+        // and should generally not be used, but here we can expect
+        // the node structures to be small so even a full scan will
+        // be reasonably efficient
+        if (!before.equals(after)) {
+            changedTypes.add(name);
+        }
+        return true;
+    }
 
-    RegistrationEditor(NodeBuilder builder) {
-        this.builder = checkNotNull(builder);
+    @Override
+    public boolean childNodeDeleted(String name, NodeState before) {
+        removedTypes.add(name);
+        return true;
     }
 
+    //-----------------------------------------------------------< private >--
+
     /**
      * Validates the inheritance hierarchy of the identified node type and
      * merges supertype information to the pre-compiled type information
@@ -388,56 +472,4 @@ class RegistrationEditor extends Default
         }
     }
 
-    //------------------------------------------------------------< Editor >--
-
-    @Override
-    public void leave(NodeState before, NodeState after)
-            throws CommitFailedException {
-        if (modified) {
-            NodeBuilder types = builder.child(JCR_SYSTEM).child(JCR_NODE_TYPES);
-            for (String name : types.getChildNodeNames()) {
-                validateAndCompileType(types, name);
-            }
-            for (String name : types.getChildNodeNames()) {
-                mergeSupertypes(types, types.child(name));
-            }
-            for (String name : types.getChildNodeNames()) {
-                NodeBuilder type = types.child(name);
-                String listName = REP_PRIMARY_SUBTYPES;
-                if (type.getBoolean(JCR_ISMIXIN)) {
-                    listName = REP_MIXIN_SUBTYPES;
-                }
-                for (String supername : getNames(type, REP_SUPERTYPES)) {
-                    addNameToList(types.child(supername), listName, name);
-                }
-            }
-
-            if (!changedTypes.isEmpty() || !removedTypes.isEmpty()) {
-                // TODO: Find and re-validate any nodes in the repository that
-                // refer to any of the changed (or removed) node types.
-            }
-        }
-    }
-
-    @Override
-    public Validator childNodeAdded(String name, NodeState after) {
-        modified = true;
-        return null;
-    }
-
-    @Override
-    public Validator childNodeChanged(
-            String name, NodeState before, NodeState after) {
-        modified = true;
-        changedTypes.add(name);
-        return null;
-    }
-
-    @Override
-    public Validator childNodeDeleted(String name, NodeState before) {
-        modified = true;
-        removedTypes.add(name);
-        return null;
-    }
-
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/InitialContent.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/InitialContent.java?rev=1558226&r1=1558225&r2=1558226&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/InitialContent.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/write/InitialContent.java Tue Jan 14 22:10:27 2014
@@ -20,8 +20,6 @@ import static org.apache.jackrabbit.oak.
 
 import com.google.common.collect.ImmutableList;
 
-import org.apache.felix.scr.annotations.Component;
-import org.apache.felix.scr.annotations.Service;
 import org.apache.jackrabbit.oak.api.Type;
 import org.apache.jackrabbit.oak.core.SystemRoot;
 import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
@@ -31,7 +29,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.name.NamespaceEditorProvider;
 import org.apache.jackrabbit.oak.plugins.name.Namespaces;
 import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
-import org.apache.jackrabbit.oak.plugins.nodetype.RegistrationEditorProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypeEditorProvider;
 import org.apache.jackrabbit.oak.plugins.version.VersionConstants;
 import org.apache.jackrabbit.oak.spi.commit.CompositeEditorProvider;
 import org.apache.jackrabbit.oak.spi.commit.EditorHook;
@@ -88,9 +86,10 @@ public class InitialContent implements R
 
         NodeState base = builder.getNodeState();
         NodeStore store = new MemoryNodeStore(base);
-        BuiltInNodeTypes.register(new SystemRoot(store, new EditorHook(
-                new CompositeEditorProvider(new NamespaceEditorProvider(),
-                        new RegistrationEditorProvider()))));
+        BuiltInNodeTypes.register(new SystemRoot(
+                store, new EditorHook(new CompositeEditorProvider(
+                        new NamespaceEditorProvider(),
+                        new TypeEditorProvider()))));
         NodeState target = store.getRoot();
         target.compareAgainstBaseState(base, new ApplyDiff(builder));
     }

Modified: jackrabbit/oak/trunk/oak-core/src/main/resources/org/apache/jackrabbit/oak/plugins/nodetype/write/builtin_nodetypes.cnd
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/resources/org/apache/jackrabbit/oak/plugins/nodetype/write/builtin_nodetypes.cnd?rev=1558226&r1=1558225&r2=1558226&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/resources/org/apache/jackrabbit/oak/plugins/nodetype/write/builtin_nodetypes.cnd (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/resources/org/apache/jackrabbit/oak/plugins/nodetype/write/builtin_nodetypes.cnd Tue Jan 14 22:10:27 2014
@@ -450,10 +450,10 @@
   - rep:hasProtectedResidualProperties (BOOLEAN) protected autocreated
   - rep:hasProtectedResidualChildNodes (BOOLEAN) protected autocreated
   - rep:namedSingleValuedProperties (NAME) protected multiple autocreated
-  + rep:namedPropertyDefinitions (rep:NamedPropertyDefinitions) = rep:NamedPropertyDefinitions protected mandatory
-  + rep:residualPropertyDefinitions (rep:PropertyDefinitions) = rep:PropertyDefinitions protected mandatory
-  + rep:namedChildNodeDefinitions (rep:NamedChildNodeDefinitions) = rep:NamedChildNodeDefinitions protected mandatory
-  + rep:residualChildNodeDefinitions (rep:ChildNodeDefinitions) = rep:ChildNodeDefinitions protected mandatory
+  + rep:namedPropertyDefinitions (rep:NamedPropertyDefinitions) = rep:NamedPropertyDefinitions protected
+  + rep:residualPropertyDefinitions (rep:PropertyDefinitions) = rep:PropertyDefinitions protected
+  + rep:namedChildNodeDefinitions (rep:NamedChildNodeDefinitions) = rep:NamedChildNodeDefinitions protected
+  + rep:residualChildNodeDefinitions (rep:ChildNodeDefinitions) = rep:ChildNodeDefinitions protected
 
 [rep:NamedPropertyDefinitions]
   + * (rep:PropertyDefinitions) = rep:PropertyDefinitions protected
@@ -533,7 +533,7 @@
 [oak:QueryIndexDefinition] > oak:Unstructured
   - type (STRING) mandatory
   - async (STRING)
-  - reindex (BOOLEAN) mandatory IGNORE
+  - reindex (BOOLEAN) IGNORE
 
 //------------------------------------------------------------------------------
 // L I F E C Y C L E   M A N A G E M E N T
@@ -679,7 +679,7 @@
 [rep:PermissionStore]
   - rep:accessControlledPath (STRING) protected IGNORE
   - rep:numPermissions (LONG) protected IGNORE
-  - rep:timestamp (LONG) protected IGNORE
+  - rep:modCount (LONG) protected IGNORE
   + * (rep:PermissionStore) = rep:PermissionStore protected IGNORE
   + * (rep:Permissions) = rep:Permissions protected IGNORE
 

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java?rev=1558226&r1=1558225&r2=1558226&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/AbstractSecurityTest.java Tue Jan 14 22:10:27 2014
@@ -46,7 +46,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexProvider;
 import org.apache.jackrabbit.oak.plugins.index.reference.ReferenceEditorProvider;
 import org.apache.jackrabbit.oak.plugins.index.reference.ReferenceIndexProvider;
-import org.apache.jackrabbit.oak.plugins.nodetype.RegistrationEditorProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypeEditorProvider;
 import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
 import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
 import org.apache.jackrabbit.oak.security.SecurityProviderImpl;
@@ -84,7 +84,7 @@ public abstract class AbstractSecurityTe
                 .with(new ReferenceIndexProvider())
                 .with(new PropertyIndexEditorProvider())
                 .with(new PropertyIndexProvider())
-                .with(new RegistrationEditorProvider())
+                .with(new TypeEditorProvider())
                 .with(getSecurityProvider());
         withEditors(oak);
         contentRepository = oak.createContentRepository();

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorTest.java?rev=1558226&r1=1558225&r2=1558226&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/plugins/nodetype/TypeEditorTest.java Tue Jan 14 22:10:27 2014
@@ -106,4 +106,5 @@ public class TypeEditorTest {
         TypeEditor editor = new TypeEditor(effective);
         editor.childNodeDeleted("mandatory", EMPTY_NODE);
     }
+
 }

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlValidatorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlValidatorTest.java?rev=1558226&r1=1558225&r2=1558226&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlValidatorTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/accesscontrol/AccessControlValidatorTest.java Tue Jan 14 22:10:27 2014
@@ -150,7 +150,7 @@ public class AccessControlValidatorTest 
                 fail("Adding an ACL below access control content should fail");
             } catch (CommitFailedException e) {
                 // success
-                assertTrue(e.isAccessControlViolation());
+                assertTrue(e.isConstraintViolation());
             } finally {
                 policy.getTree().remove();
             }
@@ -170,7 +170,7 @@ public class AccessControlValidatorTest 
                 fail("Adding an ACL below access control content should fail");
             } catch (CommitFailedException e) {
                 // success
-                assertTrue(e.isAccessControlViolation());
+                assertTrue(e.isConstraintViolation());
             } finally {
                 policy.getTree().remove();
             }
@@ -190,7 +190,7 @@ public class AccessControlValidatorTest 
                 fail("Adding an ACE below an ACE or restriction should fail");
             } catch (CommitFailedException e) {
                 // success
-                assertTrue(e.isAccessControlViolation());
+                assertTrue(e.isConstraintViolation());
             } finally {
                 entry.getTree().remove();
             }
@@ -210,7 +210,7 @@ public class AccessControlValidatorTest 
                 fail("Adding an ACE below an ACE or restriction should fail");
             } catch (CommitFailedException e) {
                 // success
-                assertTrue(e.isAccessControlViolation());
+                assertTrue(e.isConstraintViolation());
             } finally {
                 entry.getTree().remove();
             }

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/JcrUUIDTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/JcrUUIDTest.java?rev=1558226&r1=1558225&r2=1558226&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/JcrUUIDTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/JcrUUIDTest.java Tue Jan 14 22:10:27 2014
@@ -24,7 +24,6 @@ import org.apache.jackrabbit.oak.api.Com
 import org.apache.jackrabbit.oak.api.Root;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
-import org.apache.jackrabbit.oak.plugins.nodetype.RegistrationEditorProvider;
 import org.apache.jackrabbit.oak.plugins.nodetype.TypeEditorProvider;
 import org.apache.jackrabbit.oak.plugins.nodetype.write.ReadWriteNodeTypeManager;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeConstants;
@@ -76,7 +75,7 @@ public class JcrUUIDTest extends Abstrac
 
     @Override
     protected Oak withEditors(Oak oak) {
-        return oak.with(new TypeEditorProvider()).with(new RegistrationEditorProvider());
+        return oak.with(new TypeEditorProvider());
     }
 
     /**

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/ShadowInvisibleContentTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/ShadowInvisibleContentTest.java?rev=1558226&r1=1558225&r2=1558226&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/ShadowInvisibleContentTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/evaluation/ShadowInvisibleContentTest.java Tue Jan 14 22:10:27 2014
@@ -56,7 +56,7 @@ public class ShadowInvisibleContentTest 
             testRoot.commit();
             fail();
         } catch (CommitFailedException e) {
-            assertTrue(e.isAccessViolation());
+            assertTrue(e.isConstraintViolation());
         }
     }
 

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/ClusterPermissionsTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/ClusterPermissionsTest.java?rev=1558226&r1=1558225&r2=1558226&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/ClusterPermissionsTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/authorization/permission/ClusterPermissionsTest.java Tue Jan 14 22:10:27 2014
@@ -42,7 +42,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.index.reference.ReferenceIndexProvider;
 import org.apache.jackrabbit.oak.plugins.mongomk.MemoryDocumentStore;
 import org.apache.jackrabbit.oak.plugins.mongomk.MongoMK;
-import org.apache.jackrabbit.oak.plugins.nodetype.RegistrationEditorProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypeEditorProvider;
 import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
 import org.apache.jackrabbit.oak.security.SecurityProviderImpl;
 import org.apache.jackrabbit.oak.spi.security.ConfigurationParameters;
@@ -95,7 +95,7 @@ public class ClusterPermissionsTest {
                 .with(new ReferenceIndexProvider())
                 .with(new PropertyIndexEditorProvider())
                 .with(new PropertyIndexProvider())
-                .with(new RegistrationEditorProvider())
+                .with(new TypeEditorProvider())
                 .with(securityProvider1 = new SecurityProviderImpl(getSecurityConfigParameters()));
         contentRepository1 = oak.createContentRepository();
         adminSession1 = login1(getAdminCredentials());
@@ -109,7 +109,7 @@ public class ClusterPermissionsTest {
                 .with(new ReferenceIndexProvider())
                 .with(new PropertyIndexEditorProvider())
                 .with(new PropertyIndexProvider())
-                .with(new RegistrationEditorProvider())
+                .with(new TypeEditorProvider())
                 .with(securityProvider2 = new SecurityProviderImpl(getSecurityConfigParameters()));
 
         contentRepository2 = oak.createContentRepository();

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeValidatorTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeValidatorTest.java?rev=1558226&r1=1558225&r2=1558226&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeValidatorTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/privilege/PrivilegeValidatorTest.java Tue Jan 14 22:10:27 2014
@@ -19,6 +19,7 @@ package org.apache.jackrabbit.oak.securi
 import java.util.Collections;
 
 import com.google.common.collect.ImmutableList;
+
 import org.apache.jackrabbit.JcrConstants;
 import org.apache.jackrabbit.oak.AbstractSecurityTest;
 import org.apache.jackrabbit.oak.api.CommitFailedException;
@@ -32,6 +33,7 @@ import org.junit.Before;
 import org.junit.Test;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static junit.framework.Assert.assertTrue;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.fail;
 
@@ -65,7 +67,7 @@ public class PrivilegeValidatorTest exte
             fail("Missing privilege bits property must be detected.");
         } catch (CommitFailedException e) {
             // success
-            assertEquals("OakConstraint0048: PrivilegeBits are missing.", e.getMessage());
+            assertTrue(e.isConstraintViolation());
         } finally {
             root.refresh();
         }

Modified: jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserInitializerTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserInitializerTest.java?rev=1558226&r1=1558225&r2=1558226&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserInitializerTest.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/test/java/org/apache/jackrabbit/oak/security/user/UserInitializerTest.java Tue Jan 14 22:10:27 2014
@@ -41,7 +41,7 @@ import org.apache.jackrabbit.oak.namepat
 import org.apache.jackrabbit.oak.plugins.index.IndexConstants;
 import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexEditorProvider;
 import org.apache.jackrabbit.oak.plugins.index.property.PropertyIndexProvider;
-import org.apache.jackrabbit.oak.plugins.nodetype.RegistrationEditorProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypeEditorProvider;
 import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
 import org.apache.jackrabbit.oak.security.SecurityProviderImpl;
 import org.apache.jackrabbit.oak.spi.security.authentication.SystemSubject;
@@ -153,7 +153,7 @@ public class UserInitializerTest extends
         final ContentRepository repo = new Oak().with(new InitialContent())
                 .with(new PropertyIndexEditorProvider())
                 .with(new PropertyIndexProvider())
-                .with(new RegistrationEditorProvider())
+                .with(new TypeEditorProvider())
                 .with(sp)
                 .createContentRepository();
 
@@ -204,7 +204,7 @@ public class UserInitializerTest extends
         final ContentRepository repo = new Oak().with(new InitialContent())
                 .with(new PropertyIndexEditorProvider())
                 .with(new PropertyIndexProvider())
-                .with(new RegistrationEditorProvider())
+                .with(new TypeEditorProvider())
                 .with(sp)
                 .createContentRepository();
 

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java?rev=1558226&r1=1558225&r2=1558226&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/Jcr.java Tue Jan 14 22:10:27 2014
@@ -37,7 +37,6 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.index.reference.ReferenceIndexProvider;
 import org.apache.jackrabbit.oak.plugins.name.NameValidatorProvider;
 import org.apache.jackrabbit.oak.plugins.name.NamespaceEditorProvider;
-import org.apache.jackrabbit.oak.plugins.nodetype.RegistrationEditorProvider;
 import org.apache.jackrabbit.oak.plugins.nodetype.TypeEditorProvider;
 import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
 import org.apache.jackrabbit.oak.plugins.version.VersionEditorProvider;
@@ -71,7 +70,6 @@ public class Jcr {
         with(new NameValidatorProvider());
         with(new NamespaceEditorProvider());
         with(new TypeEditorProvider());
-        with(new RegistrationEditorProvider());
         with(new ConflictValidatorProvider());
         with(new ReferenceEditorProvider());
         with(new ReferenceIndexProvider());

Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/NodeTypeTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/NodeTypeTest.java?rev=1558226&r1=1558225&r2=1558226&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/NodeTypeTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/NodeTypeTest.java Tue Jan 14 22:10:27 2014
@@ -18,10 +18,13 @@
  */
 package org.apache.jackrabbit.oak.jcr.nodetype;
 
+import static junit.framework.Assert.fail;
+
 import javax.jcr.Node;
 import javax.jcr.Session;
 import javax.jcr.ValueFactory;
 import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NodeTypeManager;
 
 import org.apache.jackrabbit.oak.jcr.AbstractRepositoryTest;
 import org.apache.jackrabbit.oak.jcr.NodeStoreFixture;
@@ -61,4 +64,35 @@ public class NodeTypeTest extends Abstra
 
         session.save();
     }
+
+    @Test
+    public void removeNodeType() throws Exception {
+        Session session = getAdminSession();
+        Node root = session.getRootNode();
+        ValueFactory vf = session.getValueFactory();
+        NodeTypeManager manager = session.getWorkspace().getNodeTypeManager();
+
+        Node n = root.addNode("q1", "nt:query");
+        n.setProperty("jcr:statement", vf.createValue("statement"));
+        n.setProperty("jcr:language", vf.createValue("language"));
+        session.save();
+
+        try {
+            manager.unregisterNodeType("nt:query");
+            fail();
+        } catch (ConstraintViolationException expected) {
+            // this type is referenced in content, so it can't be removed
+        }
+
+        n.remove();
+        session.save();
+
+        try {
+            manager.unregisterNodeType("nt:query");
+            // no longer referenced in content, so removal should succeed
+        } catch (ConstraintViolationException unexpected) {
+            fail();
+        }
+    }
+
 }

Modified: jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java?rev=1558226&r1=1558225&r2=1558226&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java (original)
+++ jackrabbit/oak/trunk/oak-upgrade/src/main/java/org/apache/jackrabbit/oak/upgrade/RepositoryUpgrade.java Tue Jan 14 22:10:27 2014
@@ -46,7 +46,7 @@ import org.apache.jackrabbit.oak.plugins
 import org.apache.jackrabbit.oak.plugins.index.reference.ReferenceEditorProvider;
 import org.apache.jackrabbit.oak.plugins.name.NamespaceConstants;
 import org.apache.jackrabbit.oak.plugins.name.Namespaces;
-import org.apache.jackrabbit.oak.plugins.nodetype.RegistrationEditorProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.TypeEditorProvider;
 import org.apache.jackrabbit.oak.plugins.nodetype.write.InitialContent;
 import org.apache.jackrabbit.oak.spi.commit.CommitHook;
 import org.apache.jackrabbit.oak.spi.commit.CompositeEditorProvider;
@@ -294,7 +294,7 @@ public class RepositoryUpgrade {
             CommitHook hook = new CompositeHook(
                     new EditorHook(new GroupEditorProvider()),
                     new EditorHook(new CompositeEditorProvider(
-                            new RegistrationEditorProvider(),
+                            new TypeEditorProvider(),
                             new IndexUpdateProvider(new CompositeIndexEditorProvider(
                                     new ReferenceEditorProvider(),
                                     new PropertyIndexEditorProvider())))));