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/04/26 08:56:29 UTC
svn commit: r1476074 - in /jackrabbit/oak/trunk/oak-jcr/src:
main/java/org/apache/jackrabbit/oak/jcr/NodeImpl.java
main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
test/java/org/apache/jackrabbit/oak/jcr/nodetype/MixinTest.java
Author: jukka
Date: Fri Apr 26 06:56:28 2013
New Revision: 1476074
URL: http://svn.apache.org/r1476074
Log:
OAK-702: Optimize access to node type information
Use the /jcr:system/jcr:nodeTypes tree directly in addNode()
Modified:
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/delegate/NodeDelegate.java
jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/MixinTest.java
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=1476074&r1=1476073&r2=1476074&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 Fri Apr 26 06:56:28 2013
@@ -76,7 +76,6 @@ import org.apache.jackrabbit.oak.core.Id
import org.apache.jackrabbit.oak.jcr.delegate.NodeDelegate;
import org.apache.jackrabbit.oak.jcr.delegate.PropertyDelegate;
import org.apache.jackrabbit.oak.plugins.memory.PropertyStates;
-import org.apache.jackrabbit.oak.plugins.nodetype.DefinitionProvider;
import org.apache.jackrabbit.oak.plugins.nodetype.EffectiveNodeType;
import org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants;
import org.apache.jackrabbit.oak.plugins.value.ValueFactoryImpl;
@@ -90,6 +89,7 @@ import static com.google.common.base.Pre
import static javax.jcr.Property.JCR_LOCK_IS_DEEP;
import static javax.jcr.Property.JCR_LOCK_OWNER;
import static javax.jcr.PropertyType.UNDEFINED;
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
/**
* TODO document
@@ -203,9 +203,17 @@ public class NodeImpl<T extends NodeDele
return addNode(relPath, null);
}
- @Override
- @Nonnull
- public Node addNode(final String relPath, final String primaryNodeTypeName) throws RepositoryException {
+ @Override @Nonnull
+ public Node addNode(final String relPath, String primaryNodeTypeName)
+ throws RepositoryException {
+ final String oakPath = getOakPathOrThrowNotFound(relPath);
+ final String oakTypeName;
+ if (primaryNodeTypeName != null) {
+ oakTypeName = getOakName(primaryNodeTypeName);
+ } else {
+ oakTypeName = null;
+ }
+
return perform(new ItemWriteOperation<Node>() {
@Override
protected void checkPreconditions() throws RepositoryException {
@@ -215,7 +223,6 @@ public class NodeImpl<T extends NodeDele
@Override
public Node perform() throws RepositoryException {
- String oakPath = sessionContext.getOakPathOrThrowNotFound(relPath);
String oakName = PathUtils.getName(oakPath);
String parentPath = PathUtils.getParentPath(oakPath);
@@ -238,30 +245,14 @@ public class NodeImpl<T extends NodeDele
throw new ItemExistsException(relPath);
}
- String ntName = primaryNodeTypeName;
- if (ntName == null) {
- DefinitionProvider dp = getDefinitionProvider();
- NodeDefinition def = dp.getDefinition(parent.getTree(), oakName);
- ntName = def.getDefaultPrimaryTypeName();
- if (ntName == null) {
- throw new ConstraintViolationException(
- "no matching child node definition found for " + relPath);
- }
- } else {
- // check for NODE_TYPE_MANAGEMENT permission here as we cannot
- // distinguish between user-supplied and system-generated
- // modification of that property in the PermissionValidator
- if (!hasNtMgtPermission(JcrConstants.JCR_PRIMARYTYPE, ntName)) {
- throw new AccessDeniedException("Access denied.");
- }
+ // check for NODE_TYPE_MANAGEMENT permission here as we cannot
+ // distinguish between user-supplied and system-generated
+ // modification of that property in the PermissionValidator
+ if (oakTypeName != null &&
+ !hasNtMgtPermission(JCR_PRIMARYTYPE, oakTypeName)) {
+ throw new AccessDeniedException("Access denied.");
}
-
- // TODO: figure out the right place for this check
- NodeType nt = getNodeTypeManager().getNodeType(ntName); // throws on not found
- if (nt.isAbstract() || nt.isMixin()) {
- throw new ConstraintViolationException();
- }
- // TODO: END
+ String ntName = dlg.getDefaultChildType(oakName, oakTypeName);
NodeDelegate added = parent.addChild(oakName);
if (added == null) {
Modified: jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java?rev=1476074&r1=1476073&r2=1476074&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/main/java/org/apache/jackrabbit/oak/jcr/delegate/NodeDelegate.java Fri Apr 26 06:56:28 2013
@@ -16,8 +16,23 @@
*/
package org.apache.jackrabbit.oak.jcr.delegate;
+import static com.google.common.collect.Lists.newArrayList;
+import static java.util.Collections.emptyList;
+import static org.apache.jackrabbit.JcrConstants.JCR_DEFAULTPRIMARYTYPE;
+import static org.apache.jackrabbit.JcrConstants.JCR_ISMIXIN;
+import static org.apache.jackrabbit.JcrConstants.JCR_MIXINTYPES;
+import static org.apache.jackrabbit.JcrConstants.JCR_PRIMARYTYPE;
+import static org.apache.jackrabbit.oak.api.Type.BOOLEAN;
+import static org.apache.jackrabbit.oak.api.Type.NAME;
+import static org.apache.jackrabbit.oak.api.Type.NAMES;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.JCR_IS_ABSTRACT;
+import static org.apache.jackrabbit.oak.plugins.nodetype.NodeTypeConstants.NODE_TYPES_PATH;
+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 java.util.Collections;
import java.util.Iterator;
+import java.util.List;
import javax.annotation.CheckForNull;
import javax.annotation.Nonnull;
@@ -25,10 +40,13 @@ import javax.jcr.InvalidItemStateExcepti
import javax.jcr.ItemNotFoundException;
import javax.jcr.RepositoryException;
import javax.jcr.ValueFormatException;
+import javax.jcr.nodetype.ConstraintViolationException;
+import javax.jcr.nodetype.NoSuchNodeTypeException;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterators;
+
import org.apache.jackrabbit.oak.api.PropertyState;
import org.apache.jackrabbit.oak.api.Tree;
import org.apache.jackrabbit.oak.api.TreeLocation;
@@ -242,6 +260,86 @@ public class NodeDelegate extends ItemDe
getTree().setOrderableChildren(enable);
}
+ public String getDefaultChildType(String childName, String typeName)
+ throws NoSuchNodeTypeException, ConstraintViolationException,
+ InvalidItemStateException {
+ Tree typeRoot = sessionDelegate.getRoot().getTree(NODE_TYPES_PATH);
+ if (typeName != null) {
+ Tree type = typeRoot.getChild(typeName);
+ if (type == null) {
+ throw new NoSuchNodeTypeException(
+ "Node type " + typeName + " does not exist");
+ } else if (getBoolean(type, JCR_IS_ABSTRACT)) {
+ throw new ConstraintViolationException(
+ "Node type " + typeName + " is abstract");
+ } else if (getBoolean(type, JCR_ISMIXIN)) {
+ throw new ConstraintViolationException(
+ "Node type " + typeName + " is a mixin type");
+ } else {
+ return typeName;
+ }
+ } else {
+ List<Tree> types = newArrayList();
+ Tree parent = getTree();
+
+ String primary = getName(parent, JCR_PRIMARYTYPE);
+ if (primary != null) {
+ Tree type = typeRoot.getChild(primary);
+ if (type != null) {
+ types.add(type);
+ }
+ }
+
+ for (String mixin : getNames(parent, JCR_MIXINTYPES)) {
+ Tree type = typeRoot.getChild(mixin);
+ if (type != null) {
+ types.add(type);
+ }
+ }
+
+ // first look for named node definitions
+ for (Tree type : types) {
+ Tree named = type.getChild(OAK_NAMED_CHILD_NODE_DEFINITIONS);
+ if (named != null) {
+ Tree definitions = named.getChild(childName);
+ if (definitions != null) {
+ String defaultName =
+ findDefaultPrimaryType(typeRoot, definitions);
+ if (defaultName != null) {
+ return defaultName;
+ }
+ }
+ }
+ }
+
+ // then check residual definitions
+ for (Tree type : types) {
+ Tree definitions = type.getChild(OAK_RESIDUAL_CHILD_NODE_DEFINITIONS);
+ if (definitions != null) {
+ String defaultName =
+ findDefaultPrimaryType(typeRoot, definitions);
+ if (defaultName != null) {
+ return defaultName;
+ }
+ }
+ }
+
+ // no matching child node definition found
+ throw new ConstraintViolationException(
+ "No default node type available for child node " + childName);
+ }
+ }
+
+ private String findDefaultPrimaryType(Tree typeRoot, Tree definitions) {
+ for (Tree definition : definitions.getChildren()) {
+ String defaultName = getName(definition, JCR_DEFAULTPRIMARYTYPE);
+ if (defaultName != null) {
+ return defaultName;
+ }
+ }
+ return null;
+ }
+
//------------------------------------------------------------< internal >---
@Nonnull // FIXME this should be package private. OAK-672
@@ -297,4 +395,34 @@ public class NodeDelegate extends ItemDe
}
});
}
+
+ // Generic property value accessors. TODO: add to Tree?
+
+ private static boolean getBoolean(Tree tree, String name) {
+ PropertyState property = tree.getProperty(name);
+ return property != null
+ && property.getType() == BOOLEAN
+ && property.getValue(BOOLEAN);
+ }
+
+ @CheckForNull
+ private static String getName(Tree tree, String name) {
+ PropertyState property = tree.getProperty(name);
+ if (property != null && property.getType() == NAME) {
+ return property.getValue(NAME);
+ } else {
+ return null;
+ }
+ }
+
+ @Nonnull
+ private static Iterable<String> getNames(Tree tree, String name) {
+ PropertyState property = tree.getProperty(name);
+ if (property != null && property.getType() == NAMES) {
+ return property.getValue(NAMES);
+ } else {
+ return emptyList();
+ }
+ }
+
}
Modified: jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/MixinTest.java
URL: http://svn.apache.org/viewvc/jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/MixinTest.java?rev=1476074&r1=1476073&r2=1476074&view=diff
==============================================================================
--- jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/MixinTest.java (original)
+++ jackrabbit/oak/trunk/oak-jcr/src/test/java/org/apache/jackrabbit/oak/jcr/nodetype/MixinTest.java Fri Apr 26 06:56:28 2013
@@ -16,6 +16,8 @@
*/
package org.apache.jackrabbit.oak.jcr.nodetype;
+import static org.apache.jackrabbit.JcrConstants.NT_UNSTRUCTURED;
+
import javax.jcr.Node;
import javax.jcr.nodetype.NoSuchNodeTypeException;
@@ -47,19 +49,26 @@ public class MixinTest extends AbstractJ
@Test
public void testRemoveMixinWithoutMixinProperty() throws Exception {
+ Node node = testRootNode.addNode(
+ "testRemoveMixinWithoutMixinProperty", NT_UNSTRUCTURED);
+ superuser.save();
try {
- assertFalse(testRootNode.hasProperty(JcrConstants.JCR_MIXINTYPES));
- testRootNode.removeMixin(JcrConstants.MIX_REFERENCEABLE);
+ node.removeMixin(JcrConstants.MIX_REFERENCEABLE);
fail();
} catch (NoSuchNodeTypeException e) {
// success
+ } finally {
+ node.remove();
+ superuser.save();
}
}
@Test
public void testRemoveInheritedMixin() throws Exception {
- testRootNode.addMixin(JcrConstants.MIX_VERSIONABLE);
+ Node node = testRootNode.addNode(
+ "testRemoveInheritedMixin", NT_UNSTRUCTURED);
+ node.addMixin(JcrConstants.MIX_VERSIONABLE);
superuser.save();
try {
@@ -67,6 +76,9 @@ public class MixinTest extends AbstractJ
fail();
} catch (NoSuchNodeTypeException e) {
// success
+ } finally {
+ node.remove();
+ superuser.save();
}
}