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 an...@apache.org on 2012/10/30 11:37:10 UTC

svn commit: r1403656 - in /jackrabbit/oak/trunk: oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ oak-jcr/ oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/

Author: angela
Date: Tue Oct 30 10:37:09 2012
New Revision: 1403656

URL: http://svn.apache.org/viewvc?rev=1403656&view=rev
Log:
OAK-250 : Enforce jcr constraints for 'protected' items 

- move definition and effective node type related code to nodetype plugin package
- remove duplicate code in NodeTypeImpl
- add missing test for protection in NodeType#canSetProperty
- add TODO/FIXME comments in NodeTypeImpl for code that seems insufficient to me

Added:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/DefinitionProvider.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeTypeProvider.java
Modified:
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeImpl.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadWriteNodeTypeManager.java
    jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/RootNodeDefinition.java
    jackrabbit/oak/trunk/oak-jcr/pom.xml
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ItemImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/PropertyImpl.java
    jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionDelegate.java

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/DefinitionProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/DefinitionProvider.java?rev=1403656&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/DefinitionProvider.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/DefinitionProvider.java Tue Oct 30 10:37:09 2012
@@ -0,0 +1,46 @@
+/*
+ * 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.oak.plugins.nodetype;
+
+import javax.annotation.Nonnull;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeDefinition;
+import javax.jcr.nodetype.NodeType;
+import javax.jcr.nodetype.PropertyDefinition;
+
+/**
+ * DefinitionProvider... TODO
+ */
+public interface DefinitionProvider {
+
+    @Nonnull
+    NodeDefinition getRootDefinition() throws RepositoryException;
+
+    @Nonnull
+    NodeDefinition getDefinition(Node parent, Node targetNode) throws RepositoryException;
+
+    @Nonnull
+    PropertyDefinition getDefinition(Node parent, Property targetProperty) throws RepositoryException;
+
+    @Nonnull
+    PropertyDefinition getDefinition(Node parent, String propertyName, boolean isMultiple, int type, boolean exactTypeMatch) throws RepositoryException;
+
+    @Nonnull
+    PropertyDefinition getDefinition(NodeType nodeType, String propertyName, boolean isMultiple, int type, boolean exactTypeMatch) throws RepositoryException;
+}
\ No newline at end of file

Added: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeTypeProvider.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeTypeProvider.java?rev=1403656&view=auto
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeTypeProvider.java (added)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/EffectiveNodeTypeProvider.java Tue Oct 30 10:37:09 2012
@@ -0,0 +1,36 @@
+/*
+ * 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.oak.plugins.nodetype;
+
+import javax.jcr.Node;
+import javax.jcr.RepositoryException;
+import javax.jcr.nodetype.NodeType;
+
+/**
+ * EffectiveNodeTypeProvider... TODO
+ */
+public interface EffectiveNodeTypeProvider {
+
+    /**
+     * Calculates and returns all effective node types of the given node.
+     *
+     * @param targetNode the node for which the types should be calculated.
+     * @return all types of the given node
+     * @throws RepositoryException if the type information can not be accessed
+     */
+    Iterable<NodeType> getEffectiveNodeTypes(Node targetNode) throws RepositoryException;
+}
\ No newline at end of file

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeImpl.java?rev=1403656&r1=1403655&r2=1403656&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeImpl.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/NodeTypeImpl.java Tue Oct 30 10:37:09 2012
@@ -35,7 +35,6 @@ import javax.jcr.nodetype.NoSuchNodeType
 import javax.jcr.nodetype.NodeDefinition;
 import javax.jcr.nodetype.NodeType;
 import javax.jcr.nodetype.NodeTypeIterator;
-import javax.jcr.nodetype.NodeTypeManager;
 import javax.jcr.nodetype.PropertyDefinition;
 
 import org.apache.jackrabbit.commons.iterator.NodeTypeIteratorAdapter;
@@ -73,17 +72,15 @@ import static org.apache.jackrabbit.oak.
  */
 class NodeTypeImpl implements NodeType {
 
-    private static final Logger log =
-            LoggerFactory.getLogger(NodeTypeImpl.class);
+    private static final Logger log = LoggerFactory.getLogger(NodeTypeImpl.class);
 
-    private final NodeTypeManager manager;
+    private final ReadOnlyNodeTypeManager manager;
 
     private final ValueFactory factory;
 
     private final NodeUtil node;
 
-    public NodeTypeImpl(
-            NodeTypeManager manager, ValueFactory factory, NodeUtil node) {
+    public NodeTypeImpl(ReadOnlyNodeTypeManager manager, ValueFactory factory, NodeUtil node) {
         this.manager = manager;
         this.factory = factory;
         this.node = node;
@@ -272,16 +269,15 @@ class NodeTypeImpl implements NodeType {
             return canRemoveProperty(propertyName);
         }
 
-        for (PropertyDefinition definition : getPropertyDefinitions()) {
-            String name = definition.getName();
-            if (propertyName.equals(name) || "*".equals(name)) {
-                if (!definition.isMultiple()) {
-                    return meetsTypeConstraints(value, definition.getRequiredType()) &&
-                           meetsValueConstraints(value, definition.getValueConstraints());
-                }
-            }
+        try {
+            PropertyDefinition def = manager.getDefinition(this, propertyName, false, value.getType(), false);
+            return !def.isProtected() &&
+                    meetsTypeConstraints(value, def.getRequiredType()) &&
+                    meetsValueConstraints(value, def.getValueConstraints());
+        } catch (RepositoryException e) {
+            log.debug(e.getMessage());
+            return false;
         }
-        return false;
     }
 
     @Override
@@ -290,16 +286,16 @@ class NodeTypeImpl implements NodeType {
             return canRemoveProperty(propertyName);
         }
 
-        for (PropertyDefinition definition : getPropertyDefinitions()) {
-            String name = definition.getName();
-            if (propertyName.equals(name) || "*".equals(name)) {
-                if (definition.isMultiple()) {
-                    return meetsTypeConstraints(values, definition.getRequiredType()) &&
-                           meetsValueConstraints(values, definition.getValueConstraints());
-                }
-            }
+        try {
+            int type = (values.length == 0) ? PropertyType.STRING : values[0].getType();
+            PropertyDefinition def = manager.getDefinition(this, propertyName, true, type, false);
+            return !def.isProtected() &&
+                    meetsTypeConstraints(values, def.getRequiredType()) &&
+                    meetsValueConstraints(values, def.getValueConstraints());
+        } catch (RepositoryException e) {
+            log.debug(e.getMessage());
+            return false;
         }
-        return false;
     }
 
     private static boolean meetsTypeConstraints(Value value, int requiredType) {
@@ -427,9 +423,13 @@ class NodeTypeImpl implements NodeType {
             log.warn("Unable to access node type " + nodeTypeName, e);
             return false;
         }
+        // FIXME: properly calculate matching definition
         for (NodeDefinition definition : getChildNodeDefinitions()) {
             String name = definition.getName();
             if (matches(childNodeName, name) || "*".equals(name)) {
+                if (definition.isProtected()) {
+                    return false;
+                }
                 for (String required : definition.getRequiredPrimaryTypeNames()) {
                     if (type.isNodeType(required)) {
                         return true;
@@ -447,6 +447,7 @@ class NodeTypeImpl implements NodeType {
 
     @Override
     public boolean canRemoveNode(String nodeName) {
+        // FIXME: properly calculate matching definition taking residual definitions into account.
         NodeDefinition[] childNodeDefinitions = getChildNodeDefinitions();
         for (NodeDefinition definition : childNodeDefinitions) {
             String name = definition.getName();
@@ -461,6 +462,7 @@ class NodeTypeImpl implements NodeType {
 
     @Override
     public boolean canRemoveProperty(String propertyName) {
+        // FIXME: should properly calculate matching definition taking residual definitions into account.
         PropertyDefinition[] propertyDefinitions = getPropertyDefinitions();
         for (PropertyDefinition definition : propertyDefinitions) {
             String name = definition.getName();

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java?rev=1403656&r1=1403655&r2=1403656&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadOnlyNodeTypeManager.java Tue Oct 30 10:37:09 2012
@@ -16,36 +16,50 @@
  */
 package org.apache.jackrabbit.oak.plugins.nodetype;
 
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
 import java.util.List;
-
+import java.util.Map;
+import java.util.Queue;
 import javax.annotation.CheckForNull;
 import javax.annotation.Nonnull;
+import javax.jcr.Node;
+import javax.jcr.Property;
+import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.UnsupportedRepositoryOperationException;
+import javax.jcr.Value;
 import javax.jcr.ValueFactory;
 import javax.jcr.nodetype.NoSuchNodeTypeException;
+import javax.jcr.nodetype.NodeDefinition;
 import javax.jcr.nodetype.NodeDefinitionTemplate;
 import javax.jcr.nodetype.NodeType;
 import javax.jcr.nodetype.NodeTypeDefinition;
 import javax.jcr.nodetype.NodeTypeIterator;
 import javax.jcr.nodetype.NodeTypeManager;
 import javax.jcr.nodetype.NodeTypeTemplate;
+import javax.jcr.nodetype.PropertyDefinition;
 import javax.jcr.nodetype.PropertyDefinitionTemplate;
 
 import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Queues;
 import org.apache.jackrabbit.commons.iterator.NodeTypeIteratorAdapter;
 import org.apache.jackrabbit.oak.api.Tree;
 import org.apache.jackrabbit.oak.namepath.NameMapper;
 import org.apache.jackrabbit.oak.namepath.NamePathMapperImpl;
 import org.apache.jackrabbit.oak.util.NodeUtil;
 
+import static javax.jcr.PropertyType.UNDEFINED;
+
 /**
  * Base implementation of a {@link NodeTypeManager} with support for reading
  * node types from the {@link Tree} returned by {@link #getTypes()}. Methods
  * related to node type modifications throw
  * {@link UnsupportedRepositoryOperationException}.
  */
-public abstract class ReadOnlyNodeTypeManager implements NodeTypeManager {
+public abstract class ReadOnlyNodeTypeManager implements NodeTypeManager, EffectiveNodeTypeProvider, DefinitionProvider {
 
     /**
      * Returns the internal name for the specified JCR name.
@@ -206,4 +220,203 @@ public abstract class ReadOnlyNodeTypeMa
     public void unregisterNodeTypes(String[] names) throws RepositoryException {
         throw new UnsupportedRepositoryOperationException();
     }
+
+    //------------------------------------------< EffectiveNodeTypeProvider >---
+
+    /**
+     * Returns all the node types of the given node, in a breadth-first
+     * traversal order of the type hierarchy.
+     *
+     * @param node node instance
+     * @return all types of the given node
+     * @throws RepositoryException if the type information can not be accessed
+     * @param node
+     * @return
+     * @throws RepositoryException
+     */
+    @Override
+    public Iterable<NodeType> getEffectiveNodeTypes(Node node) throws RepositoryException {
+        Queue<NodeType> queue = Queues.newArrayDeque();
+        queue.add(node.getPrimaryNodeType());
+        queue.addAll(Arrays.asList(node.getMixinNodeTypes()));
+
+        return getEffectiveNodeTypes(queue);
+    }
+
+
+    //-------------------------------------------------< DefinitionProvider >---
+
+    @Override
+    public NodeDefinition getRootDefinition() throws RepositoryException {
+        return new RootNodeDefinition(this);
+    }
+
+    @Override
+    public NodeDefinition getDefinition(@Nonnull Node parent, @Nonnull Node targetNode) throws RepositoryException {
+        String name = targetNode.getName();
+        List<NodeDefinition> residualDefs = new ArrayList<NodeDefinition>();
+        // TODO: This may need to be optimized
+        for (NodeType nt : getEffectiveNodeTypes(parent)) {
+            for (NodeDefinition def : nt.getDeclaredChildNodeDefinitions()) {
+                String defName = def.getName();
+                if (name.equals(defName)) {
+                    boolean match = true;
+                    for (String type : def.getRequiredPrimaryTypeNames()) {
+                        if (!targetNode.isNodeType(type)) {
+                            match = false;
+                        }
+                    }
+                    if (match) {
+                        return def;
+                    }
+                } else if ("*".equals(defName)) {
+                    residualDefs.add(def);
+                }
+            }
+        }
+
+        for (NodeDefinition def : residualDefs) {
+            String defName = def.getName();
+            if ("*".equals(defName)) {
+                boolean match = true;
+                for (String type : def.getRequiredPrimaryTypeNames()) {
+                    if (!targetNode.isNodeType(type)) {
+                        match = false;
+                    }
+                }
+                if (match) {
+                    return def;
+                }
+            }
+        }
+
+        throw new RepositoryException("No matching node definition found for " + this);
+    }
+
+    @Override
+    public PropertyDefinition getDefinition(Node parent, Property targetProperty) throws RepositoryException {
+        String name = targetProperty.getName();
+        boolean isMultiple = targetProperty.isMultiple();
+        int type = UNDEFINED;
+        if (isMultiple) {
+            Value[] values = targetProperty.getValues();
+            if (values.length > 0) {
+                type = values[0].getType();
+            }
+        } else {
+            type = targetProperty.getValue().getType();
+        }
+
+        // TODO: This may need to be optimized
+        List<PropertyDefinition> residualDefs = new ArrayList<PropertyDefinition>();
+        for (NodeType nt : getEffectiveNodeTypes(parent)) {
+            for (PropertyDefinition def : nt.getDeclaredPropertyDefinitions()) {
+                String defName = def.getName();
+                int defType = def.getRequiredType();
+                if ((name.equals(defName))
+                        && (type == defType || UNDEFINED == type || UNDEFINED == defType)
+                        && isMultiple == def.isMultiple()) {
+                    return def;
+                } else if ("*".equals(defName)) {
+                    residualDefs.add(def);
+                }
+            }
+        }
+
+        for (PropertyDefinition def : residualDefs) {
+            String defName = def.getName();
+            int defType = def.getRequiredType();
+            if (("*".equals(defName))
+                    && (type == defType || UNDEFINED == type || UNDEFINED == defType)
+                    && isMultiple == def.isMultiple()) {
+                return def;
+            }
+        }
+
+        // FIXME: Shouldn't be needed
+        for (NodeType nt : getEffectiveNodeTypes(parent)) {
+            for (PropertyDefinition def : nt.getDeclaredPropertyDefinitions()) {
+                String defName = def.getName();
+                if ((name.equals(defName) || "*".equals(defName))
+                        && type == PropertyType.STRING
+                        && isMultiple == def.isMultiple()) {
+                    return def;
+                }
+            }
+        }
+
+        throw new RepositoryException("No matching property definition found for " + this);
+    }
+
+    @Override
+    public PropertyDefinition getDefinition(Node parent, String propertyName, boolean isMultiple, int type, boolean exactTypeMatch) throws RepositoryException {
+        return getPropertyDefinition(getEffectiveNodeTypes(parent), propertyName, isMultiple, type, exactTypeMatch);
+    }
+
+    @Override
+    public PropertyDefinition getDefinition(NodeType nodeType, String propertyName, boolean isMultiple, int type, boolean exactTypeMatch) throws RepositoryException {
+        Queue<NodeType> queue = Queues.newArrayDeque();
+        queue.add(nodeType);
+        Collection<NodeType> effective = getEffectiveNodeTypes(queue);
+        return getPropertyDefinition(effective, propertyName, isMultiple, type, exactTypeMatch);
+    }
+
+    //------------------------------------------------------------< private >---
+
+    private Collection<NodeType> getEffectiveNodeTypes(Queue<NodeType> queue) {
+        Map<String, NodeType> types = Maps.<String, NodeType>newHashMap();
+        while (!queue.isEmpty()) {
+            NodeType type = queue.remove();
+            String name = type.getName();
+            if (!types.containsKey(name)) {
+                types.put(name, type);
+                queue.addAll(Arrays.asList(type.getDeclaredSupertypes()));
+            }
+        }
+
+        return types.values();
+    }
+
+    private PropertyDefinition getPropertyDefinition(Iterable<NodeType> effectiveNodeTypes,
+                                                     String propertyName, boolean isMultiple,
+                                                     int type, boolean exactTypeMatch) throws RepositoryException {
+        // TODO: This may need to be optimized
+        for (NodeType nt : effectiveNodeTypes) {
+            for (PropertyDefinition def : nt.getDeclaredPropertyDefinitions()) {
+                String defName = def.getName();
+                int defType = def.getRequiredType();
+                if (propertyName.equals(defName)
+                        && isMultiple == def.isMultiple()
+                        &&(!exactTypeMatch || (type == defType || UNDEFINED == type || UNDEFINED == defType))) {
+                    return def;
+                }
+            }
+        }
+
+        // try if there is a residual definition
+        for (NodeType nt : effectiveNodeTypes) {
+            for (PropertyDefinition def : nt.getDeclaredPropertyDefinitions()) {
+                String defName = def.getName();
+                int defType = def.getRequiredType();
+                if ("*".equals(defName)
+                        && isMultiple == def.isMultiple()
+                        && (!exactTypeMatch || (type == defType || UNDEFINED == type || UNDEFINED == defType))) {
+                    return def;
+                }
+            }
+        }
+
+        // FIXME: Shouldn't be needed
+        for (NodeType nt : effectiveNodeTypes) {
+            for (PropertyDefinition def : nt.getDeclaredPropertyDefinitions()) {
+                String defName = def.getName();
+                if ((propertyName.equals(defName) || "*".equals(defName))
+                        && type == PropertyType.STRING
+                        && isMultiple == def.isMultiple()) {
+                    return def;
+                }
+            }
+        }
+        throw new RepositoryException("No matching property definition found for " + propertyName);
+    }
 }

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadWriteNodeTypeManager.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadWriteNodeTypeManager.java?rev=1403656&r1=1403655&r2=1403656&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadWriteNodeTypeManager.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/ReadWriteNodeTypeManager.java Tue Oct 30 10:37:09 2012
@@ -100,7 +100,6 @@ import static org.apache.jackrabbit.oak.
  * {@link ReadOnlyNodeTypeManager} for the following methods:
  * <ul>
  *     <li>{@link #getValueFactory()}</li>
- *     <li>{@link #getCoreValueFactory()}</li>
  *     <li>{@link #getNameMapper()}</li>
  * </ul>
  */

Modified: jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/RootNodeDefinition.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/RootNodeDefinition.java?rev=1403656&r1=1403655&r2=1403656&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/RootNodeDefinition.java (original)
+++ jackrabbit/oak/trunk/oak-core/src/main/java/org/apache/jackrabbit/oak/plugins/nodetype/RootNodeDefinition.java Tue Oct 30 10:37:09 2012
@@ -28,7 +28,7 @@ import org.slf4j.LoggerFactory;
 /**
  * Node definition for the root node.
  */
-public final class RootNodeDefinition implements NodeDefinition {
+final class RootNodeDefinition implements NodeDefinition {
 
     /**
      * logger instance
@@ -39,10 +39,11 @@ public final class RootNodeDefinition im
 
     private final NodeTypeManager ntManager;
 
-    public RootNodeDefinition(NodeTypeManager ntManager) {
+    RootNodeDefinition(NodeTypeManager ntManager) {
         this.ntManager = ntManager;
     }
 
+    //-----------------------------------------------------< NodeDefinition >---
     @Override
     public NodeType[] getRequiredPrimaryTypes() {
         try {

Modified: jackrabbit/oak/trunk/oak-jcr/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/pom.xml?rev=1403656&r1=1403655&r2=1403656&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/pom.xml (original)
+++ jackrabbit/oak/trunk/oak-jcr/pom.xml Tue Oct 30 10:37:09 2012
@@ -65,8 +65,6 @@
       org.apache.jackrabbit.test.api.nodetype.CanSetPropertyDoubleTest#testConversionsMultiple  <!-- OAK-302 -->
       org.apache.jackrabbit.test.api.nodetype.CanSetPropertyLongTest#testConversions            <!-- OAK-302 -->
       org.apache.jackrabbit.test.api.nodetype.CanSetPropertyLongTest#testConversionsMultiple    <!-- OAK-302 -->
-      org.apache.jackrabbit.test.api.nodetype.CanSetPropertyMultipleTest#testReturnFalseBecauseIsProtected  <!-- OAK-250 -->
-      org.apache.jackrabbit.test.api.nodetype.CanSetPropertyTest#testReturnFalseBecauseIsProtected          <!-- OAK-250 -->
       org.apache.jackrabbit.test.api.SetPropertyAssumeTypeTest#testValueConstraintViolationExceptionBecauseOfInvalidTypeParameter
       org.apache.jackrabbit.test.api.SetPropertyAssumeTypeTest#testValuesConstraintViolationExceptionBecauseOfInvalidTypeParameter
       org.apache.jackrabbit.test.api.SetPropertyAssumeTypeTest#testStringConstraintViolationExceptionBecauseOfInvalidTypeParameter

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ItemImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ItemImpl.java?rev=1403656&r1=1403655&r2=1403656&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ItemImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/ItemImpl.java Tue Oct 30 10:37:09 2012
@@ -16,31 +16,21 @@
  */
 package org.apache.jackrabbit.oak.jcr;
 
-import java.util.Arrays;
-import java.util.Map;
-import java.util.Queue;
 import javax.annotation.Nonnull;
 import javax.jcr.InvalidItemStateException;
 import javax.jcr.Item;
 import javax.jcr.Node;
 import javax.jcr.Property;
-import javax.jcr.PropertyType;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
 import javax.jcr.ValueFactory;
 import javax.jcr.nodetype.ConstraintViolationException;
 import javax.jcr.nodetype.ItemDefinition;
-import javax.jcr.nodetype.NodeType;
-import javax.jcr.nodetype.PropertyDefinition;
 
-import com.google.common.collect.Maps;
-import com.google.common.collect.Queues;
 import org.apache.jackrabbit.commons.AbstractItem;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import static javax.jcr.PropertyType.UNDEFINED;
-
 /**
  * {@code ItemImpl}...
  */
@@ -158,85 +148,7 @@ abstract class ItemImpl<T extends ItemDe
         return (isNode() ? "Node[" : "Property[") + dlg + ']';
     }
 
-    //------------------------------------------------------------< internal >---
-
-    /**
-     * Returns all the node types of the given node, in a breadth-first
-     * traversal order of the type hierarchy.
-     * <p>
-     * This utility method used by the getDefinition() methods in the
-     * {@link PropertyImpl} and {@link NodeImpl} subclasses.
-     *
-     * @param node node instance
-     * @return all types of the given node
-     * @throws RepositoryException if the type information can not be accessed
-     */
-    protected static Iterable<NodeType> getAllNodeTypes(Node node)
-            throws RepositoryException {
-        Map<String, NodeType> types = Maps.newHashMap();
-
-        Queue<NodeType> queue = Queues.newArrayDeque();
-        queue.add(node.getPrimaryNodeType());
-        queue.addAll(Arrays.asList(node.getMixinNodeTypes()));
-        while (!queue.isEmpty()) {
-            NodeType type = queue.remove();
-            String name = type.getName();
-            if (!types.containsKey(name)) {
-                types.put(name, type);
-                queue.addAll(Arrays.asList(type.getDeclaredSupertypes()));
-            }
-        }
-
-        return types.values();
-    }
-
-    // FIXME: move to node type utility (oak-nodetype-plugin)
-    protected static PropertyDefinition getPropertyDefinition(Node parent,
-                                                              String propName,
-                                                              boolean isMultiple,
-                                                              int type,
-                                                              boolean exactTypeMatch) throws RepositoryException {
-        // TODO: This may need to be optimized
-        for (NodeType nt : getAllNodeTypes(parent)) {
-            for (PropertyDefinition def : nt.getDeclaredPropertyDefinitions()) {
-                String defName = def.getName();
-                int defType = def.getRequiredType();
-                if (propName.equals(defName)
-                        && isMultiple == def.isMultiple()
-                        &&(!exactTypeMatch || (type == defType || UNDEFINED == type || UNDEFINED == defType))) {
-                    return def;
-                }
-            }
-        }
-
-        // try if there is a residual definition
-        for (NodeType nt : getAllNodeTypes(parent)) {
-            for (PropertyDefinition def : nt.getDeclaredPropertyDefinitions()) {
-                String defName = def.getName();
-                int defType = def.getRequiredType();
-                if ("*".equals(defName)
-                        && isMultiple == def.isMultiple()
-                        && (!exactTypeMatch || (type == defType || UNDEFINED == type || UNDEFINED == defType))) {
-                    return def;
-                }
-            }
-        }
-
-        // FIXME: Shouldn't be needed
-        for (NodeType nt : getAllNodeTypes(parent)) {
-            for (PropertyDefinition def : nt.getDeclaredPropertyDefinitions()) {
-                String defName = def.getName();
-                if ((propName.equals(defName) || "*".equals(defName))
-                        && type == PropertyType.STRING
-                        && isMultiple == def.isMultiple()) {
-                    return def;
-                }
-            }
-        }
-        throw new RepositoryException("No matching property definition found for " + propName);
-    }
-
-
+    //-----------------------------------------------------------< internal >---
     /**
      * Performs a sanity check on this item and the associated session.
      *

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java?rev=1403656&r1=1403655&r2=1403656&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java Tue Oct 30 10:37:09 2012
@@ -18,7 +18,6 @@ package org.apache.jackrabbit.oak.jcr;
 
 import java.io.InputStream;
 import java.math.BigDecimal;
-import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Calendar;
 import java.util.Collections;
@@ -75,7 +74,6 @@ import org.apache.jackrabbit.oak.api.Tre
 import org.apache.jackrabbit.oak.commons.PathUtils;
 import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
 import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
-import org.apache.jackrabbit.oak.plugins.nodetype.RootNodeDefinition;
 import org.apache.jackrabbit.oak.util.TODO;
 import org.apache.jackrabbit.value.ValueHelper;
 import org.slf4j.Logger;
@@ -954,47 +952,10 @@ public class NodeImpl extends ItemImpl<N
     @Nonnull
     public NodeDefinition getDefinition() throws RepositoryException {
         if (getDepth() == 0) {
-            return new RootNodeDefinition(dlg.sessionDelegate.getNodeTypeManager());
-        }
-
-        String name = getName();
-        List<NodeDefinition> residualDefs = new ArrayList<NodeDefinition>();
-        // TODO: This may need to be optimized
-        for (NodeType nt : getAllNodeTypes(getParent())) {
-            for (NodeDefinition def : nt.getDeclaredChildNodeDefinitions()) {
-                String defName = def.getName();
-                if (name.equals(defName)) {
-                    boolean match = true;
-                    for (String type : def.getRequiredPrimaryTypeNames()) {
-                        if (!isNodeType(type)) {
-                            match = false;
-                        }
-                    }
-                    if (match) {
-                        return def;
-                    }
-                } else if ("*".equals(defName)) {
-                    residualDefs.add(def);
-                }
-            }
-        }
-
-        for (NodeDefinition def : residualDefs) {
-            String defName = def.getName();
-            if ("*".equals(defName)) {
-                boolean match = true;
-                for (String type : def.getRequiredPrimaryTypeNames()) {
-                    if (!isNodeType(type)) {
-                        match = false;
-                    }
-                }
-                if (match) {
-                    return def;
-                }
-            }
+            return dlg.sessionDelegate.getDefinitionProvider().getRootDefinition();
+        } else {
+            return dlg.sessionDelegate.getDefinitionProvider().getDefinition(getParent(), this);
         }
-
-        throw new RepositoryException("No matching node definition found for " + this);
     }
 
     @Override
@@ -1359,7 +1320,7 @@ public class NodeImpl extends ItemImpl<N
     }
 
     private void autoCreateItems() throws RepositoryException {
-        Iterable<NodeType> types = getAllNodeTypes(this);
+        Iterable<NodeType> types = dlg.sessionDelegate.getEffectiveNodeTypeProvider().getEffectiveNodeTypes(this);
         for (NodeType nt : types) {
             for (PropertyDefinition pd : nt.getPropertyDefinitions()) {
                 if (pd.isAutoCreated() && dlg.getProperty(pd.getName()) == null) {
@@ -1442,7 +1403,7 @@ public class NodeImpl extends ItemImpl<N
         addNode(definition.getName(), definition.getDefaultPrimaryTypeName());
     }
 
-    // TODO: hack to filter for a subset of supported mixins for now
+    // FIXME: hack to filter for a subset of supported mixins for now
     // this allows only harmless mixin types so that other code like addMixin gets test coverage
     private boolean isSupportedMixinName(String mixinName) throws RepositoryException {
         String oakName = sessionDelegate.getOakPathOrThrow(mixinName);
@@ -1500,7 +1461,7 @@ public class NodeImpl extends ItemImpl<N
                     if (hasProperty(jcrName)) {
                         definition = getProperty(jcrName).getDefinition();
                     } else {
-                        definition = getPropertyDefinition(NodeImpl.this, oakName, false, type, exactTypeMatch);
+                        definition = dlg.sessionDelegate.getDefinitionProvider().getDefinition(NodeImpl.this, oakName, false, type, exactTypeMatch);
                     }
                     checkProtected(definition);
                     if (definition.isMultiple()) {
@@ -1535,7 +1496,7 @@ public class NodeImpl extends ItemImpl<N
                     if (hasProperty(jcrName)) {
                         definition = getProperty(jcrName).getDefinition();
                     } else {
-                        definition = getPropertyDefinition(NodeImpl.this, oakName, true, type, exactTypeMatch);
+                        definition = dlg.sessionDelegate.getDefinitionProvider().getDefinition(NodeImpl.this, oakName, true, type, exactTypeMatch);
                     }
                     checkProtected(definition);
                     if (!definition.isMultiple()) {

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/PropertyImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/PropertyImpl.java?rev=1403656&r1=1403655&r2=1403656&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/PropertyImpl.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/PropertyImpl.java Tue Oct 30 10:37:09 2012
@@ -45,7 +45,6 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import static com.google.common.base.Preconditions.checkArgument;
-import static javax.jcr.PropertyType.UNDEFINED;
 
 /**
  * {@code PropertyImpl}...
@@ -550,17 +549,7 @@ public class PropertyImpl extends ItemIm
     @Override
     @Nonnull
     public PropertyDefinition getDefinition() throws RepositoryException {
-        int type = UNDEFINED;
-        if (isMultiple()) {
-            Value[] values = getValues();
-            if (values.length > 0) {
-                type = values[0].getType();
-            }
-        } else {
-            type = getValue().getType();
-        }
-
-        return getPropertyDefinition(getParent(), getName(), isMultiple(), type, true);
+        return dlg.sessionDelegate.getDefinitionProvider().getDefinition(getParent(), this);
     }
 
     /**

Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionDelegate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionDelegate.java?rev=1403656&r1=1403655&r2=1403656&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionDelegate.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/SessionDelegate.java Tue Oct 30 10:37:09 2012
@@ -47,6 +47,8 @@ import org.apache.jackrabbit.oak.commons
 import org.apache.jackrabbit.oak.namepath.NamePathMapper;
 import org.apache.jackrabbit.oak.namepath.NamePathMapperImpl;
 import org.apache.jackrabbit.oak.plugins.identifier.IdentifierManager;
+import org.apache.jackrabbit.oak.plugins.nodetype.DefinitionProvider;
+import org.apache.jackrabbit.oak.plugins.nodetype.EffectiveNodeTypeProvider;
 import org.apache.jackrabbit.oak.plugins.observation.ObservationManagerImpl;
 import org.apache.jackrabbit.oak.spi.security.SecurityProvider;
 import org.apache.jackrabbit.oak.spi.security.privilege.PrivilegeManagerImpl;
@@ -512,4 +514,14 @@ public class SessionDelegate {
         }
         return privilegeManager;
     }
+
+    @Nonnull
+    EffectiveNodeTypeProvider getEffectiveNodeTypeProvider() throws RepositoryException {
+        return (EffectiveNodeTypeProvider) workspace.getNodeTypeManager();
+    }
+
+    @Nonnull
+    DefinitionProvider getDefinitionProvider() throws RepositoryException {
+        return (DefinitionProvider) workspace.getNodeTypeManager();
+    }
 }