Skip to content

Commit

Permalink
MODE-1748 - Fixed the VersionException that was being thrown when con…
Browse files Browse the repository at this point in the history
…tent was imported and nodes were marked as checked in. The issue is identical to MODE-1450 and the fix involves propagating a "skipVersioningValidation" flag to avoid the version checks.
  • Loading branch information
Horia Chiorean authored and rhauch committed Jan 15, 2013
1 parent b9595ec commit d030d5e
Show file tree
Hide file tree
Showing 16 changed files with 505 additions and 32 deletions.
60 changes: 38 additions & 22 deletions modeshape-jcr/src/main/java/org/modeshape/jcr/AbstractJcrNode.java
Expand Up @@ -968,7 +968,7 @@ final AbstractJcrNode addNode( String relPath,
// delegate to the parent node ...
Name childName = path.getLastSegment().getName();
session.checkPermission(path, ModeShapePermissions.ADD_NODE);
return ((AbstractJcrNode)parent).addChildNode(childName, childPrimaryTypeName, desiredKey);
return ((AbstractJcrNode)parent).addChildNode(childName, childPrimaryTypeName, desiredKey, false);
} else if (parent instanceof AbstractJcrProperty) {
// Per the TCK, if relPath references a property, then we have to throw a ConstraintViolationException.
throw new ConstraintViolationException(JcrI18n.invalidPathParameter.text(relPath, "relPath"));
Expand All @@ -984,17 +984,19 @@ final AbstractJcrNode addNode( String relPath,
// Otherwise, the path has size == 1 and it specifies the child ...
session.checkPermission(path, ModeShapePermissions.ADD_NODE);
Name childName = path.getLastSegment().getName();
return addChildNode(childName, childPrimaryTypeName, desiredKey);
return addChildNode(childName, childPrimaryTypeName, desiredKey, false);
}

/**
* Adds the a new node with the given primary type (if specified) at the given relative path with the given UUID (if
* specified).
*
*
* @param childName the name for the new node; may not be null
* @param childPrimaryNodeTypeName the desired primary type for the new node; null value indicates that the default primary
* type from the appropriate definition for this node should be used
* @param desiredKey the key for the new node; may be null if the key is to be generated
* @param skipVersioningValidation true if the operation can be performed on a checked-in node.
* @return the newly created node
* @throws ItemExistsException if an item at the specified path already exists and same-name siblings are not allowed.
* @throws PathNotFoundException if the specified path implies intermediary nodes that do not exist.
Expand All @@ -1006,7 +1008,8 @@ final AbstractJcrNode addNode( String relPath,
*/
final AbstractJcrNode addChildNode( Name childName,
Name childPrimaryNodeTypeName,
NodeKey desiredKey )
NodeKey desiredKey,
boolean skipVersioningValidation )
throws ItemExistsException, PathNotFoundException, VersionException, ConstraintViolationException, LockException,
RepositoryException {
checkNodeTypeCanBeModified();
Expand All @@ -1033,7 +1036,7 @@ final AbstractJcrNode addChildNode( Name childName,

// See if this node is checked in. If so, then we can only create children if the child
// node definition has an OPV of 'ignore'. See Section 15.2.2 of the JSR-283 spec for details ...
if (!isCheckedOut() && childDefn.getOnParentVersion() != OnParentVersionAction.IGNORE) {
if (!skipVersioningValidation && !isCheckedOut() && childDefn.getOnParentVersion() != OnParentVersionAction.IGNORE) {
// The OPV is not 'ignore', so we can't create the new node ...
Path parentPath = path();
String parentPathStr = readable(parentPath);
Expand Down Expand Up @@ -1265,7 +1268,7 @@ protected void autoCreateChildren( Name primaryType,
if (!childNames.contains(childName)) {
// We've not already created a child with this name ...
JcrNodeType childPrimaryType = defn.getDefaultPrimaryType();
addChildNode(childName, childPrimaryType.getInternalName(), null);
addChildNode(childName, childPrimaryType.getInternalName(), null, false);
}
}
}
Expand Down Expand Up @@ -1333,7 +1336,7 @@ public AbstractJcrProperty setProperty( String name,
if (jcrValue.value() == null) {
throw new ValueFormatException(JcrI18n.valueMayNotContainNull.text(name));
}
return setProperty(nameFrom(name), jcrValue, false, false); // don't skip constraint checks or protected checks
return setProperty(nameFrom(name), jcrValue, false, false, false); // don't skip constraint checks or protected checks

}

Expand All @@ -1350,7 +1353,7 @@ public AbstractJcrProperty setProperty( String name,
throw new ValueFormatException(JcrI18n.valueMayNotContainNull.text(name));
}
// don't skip constraint checks or protected checks
return setProperty(nameFrom(name), jcrValue.asType(type), false, false);
return setProperty(nameFrom(name), jcrValue.asType(type), false, false, false);
}

@Override
Expand Down Expand Up @@ -1430,7 +1433,7 @@ public AbstractJcrProperty setProperty( String name,
checkSession();
if (value == null) return removeExistingProperty(nameFrom(name));
// don't skip constraint checks or protected checks
return setProperty(nameFrom(name), valueFrom(PropertyType.STRING, value), false, false);
return setProperty(nameFrom(name), valueFrom(PropertyType.STRING, value), false, false, false);
}

@Override
Expand All @@ -1442,7 +1445,7 @@ public AbstractJcrProperty setProperty( String name,
checkSession();
if (value == null) return removeExistingProperty(nameFrom(name));
// don't skip constraint checks or protected checks
return setProperty(nameFrom(name), valueFrom(type, value), false, false);
return setProperty(nameFrom(name), valueFrom(type, value), false, false, false);
}

@Override
Expand All @@ -1453,7 +1456,7 @@ public AbstractJcrProperty setProperty( String name,
checkSession();
if (value == null) return removeExistingProperty(nameFrom(name));
// don't skip constraint checks or protected checks
return setProperty(nameFrom(name), valueFrom(value), false, false);
return setProperty(nameFrom(name), valueFrom(value), false, false, false);
}

@Override
Expand All @@ -1463,7 +1466,7 @@ public AbstractJcrProperty setProperty( String name,
CheckArg.isNotNull(name, "name");
checkSession();
// don't skip constraint checks or protected checks
return setProperty(nameFrom(name), valueFrom(PropertyType.BINARY, value), false, false);
return setProperty(nameFrom(name), valueFrom(PropertyType.BINARY, value), false, false, false);
}

@Override
Expand All @@ -1473,7 +1476,7 @@ public AbstractJcrProperty setProperty( String name,
CheckArg.isNotNull(name, "name");
checkSession();
// don't skip constraint checks or protected checks
return setProperty(nameFrom(name), valueFrom(PropertyType.BOOLEAN, value), false, false);
return setProperty(nameFrom(name), valueFrom(PropertyType.BOOLEAN, value), false, false, false);
}

@Override
Expand All @@ -1483,7 +1486,7 @@ public AbstractJcrProperty setProperty( String name,
CheckArg.isNotNull(name, "name");
checkSession();
// don't skip constraint checks or protected checks
return setProperty(nameFrom(name), valueFrom(PropertyType.DOUBLE, value), false, false);
return setProperty(nameFrom(name), valueFrom(PropertyType.DOUBLE, value), false, false, false);
}

@Override
Expand All @@ -1493,7 +1496,7 @@ public AbstractJcrProperty setProperty( String name,
CheckArg.isNotNull(name, "name");
checkSession();
// don't skip constraint checks or protected checks
return setProperty(nameFrom(name), valueFrom(PropertyType.DECIMAL, value), false, false);
return setProperty(nameFrom(name), valueFrom(PropertyType.DECIMAL, value), false, false, false);
}

@Override
Expand All @@ -1503,7 +1506,7 @@ public AbstractJcrProperty setProperty( String name,
CheckArg.isNotNull(name, "name");
checkSession();
// don't skip constraint checks or protected checks
return setProperty(nameFrom(name), valueFrom(PropertyType.LONG, value), false, false);
return setProperty(nameFrom(name), valueFrom(PropertyType.LONG, value), false, false, false);
}

@Override
Expand All @@ -1514,7 +1517,7 @@ public AbstractJcrProperty setProperty( String name,
checkSession();
if (value == null) return removeExistingProperty(nameFrom(name));
// don't skip constraint checks or protected checks
return setProperty(nameFrom(name), valueFrom(value), false, false);
return setProperty(nameFrom(name), valueFrom(value), false, false, false);
}

@Override
Expand All @@ -1525,7 +1528,7 @@ public AbstractJcrProperty setProperty( String name,
checkSession();
if (value == null) return removeExistingProperty(nameFrom(name));
// don't skip constraint checks or protected checks
return setProperty(nameFrom(name), valueFrom(value), false, false);
return setProperty(nameFrom(name), valueFrom(value), false, false, false);
}

/**
Expand All @@ -1550,11 +1553,13 @@ final AbstractJcrProperty removeExistingProperty( Name name ) throws VersionExce
}

/**
*
* @param name the name of the property; may not be null
* @param value the value of the property; may not be null
* @param skipReferenceValidation indicates whether constraints on REFERENCE properties should be enforced
* @param skipProtectedValidation true if protected properties can be set by the caller of this method, or false if the method
* should validate that protected methods are not being called
* @param skipVersioningValidation true if the property can be set even if a node is checked in
* @return the new JCR property object
* @throws VersionException if the node is checked out
* @throws LockException if the node is locked
Expand All @@ -1564,7 +1569,8 @@ final AbstractJcrProperty removeExistingProperty( Name name ) throws VersionExce
final AbstractJcrProperty setProperty( Name name,
JcrValue value,
boolean skipReferenceValidation,
boolean skipProtectedValidation )
boolean skipProtectedValidation,
boolean skipVersioningValidation )
throws VersionException, LockException, ConstraintViolationException, RepositoryException {
assert value != null;
assert value.value() != null;
Expand All @@ -1589,7 +1595,17 @@ final AbstractJcrProperty setProperty( Name name,
}
if (existing.getDefinition().getRequiredType() == value.getType()) {
// The new value's type and the existing type are the same, so just delegate to the existing JCR property ...
existing.setValue(value);
try {
//set the property via the public method, so that additional checks are performed
existing.setValue(value);
} catch (VersionException e) {
if (skipVersioningValidation) {
//the node is checked in, but we should ignore that, so set the property via the protected method
((JcrSingleValueProperty) existing).setValue(value);
} else {
throw e;
}
}
return existing;
}
}
Expand Down Expand Up @@ -1637,7 +1653,7 @@ final AbstractJcrProperty setProperty( Name name,
}
}

if (!isCheckedOut()) {
if (!skipVersioningValidation && !isCheckedOut()) {
// Node is not checked out, so changing property is only allowed if OPV of property is 'ignore' ...
if (defn.getOnParentVersion() != OnParentVersionAction.IGNORE) {
// Can't change this property ...
Expand Down Expand Up @@ -2236,7 +2252,7 @@ private void autoCreateItemsFor( JcrNodeType nodeType )
} else {
assert propDefn.getDefaultValues().length == 1;
// don't skip constraint checks or protected checks
setProperty(propDefn.getInternalName(), defaultValues[0], false, false);
setProperty(propDefn.getInternalName(), defaultValues[0], false, false, false);
}
}
// otherwise, we don't care
Expand All @@ -2252,7 +2268,7 @@ private void autoCreateItemsFor( JcrNodeType nodeType )
JcrNodeType defaultPrimaryType = nodeDefn.getDefaultPrimaryType();
assert defaultPrimaryType != null;
Name primaryType = defaultPrimaryType.getInternalName();
addChildNode(nodeName, primaryType, null);
addChildNode(nodeName, primaryType, null, false);
}
}
}
Expand Down
Expand Up @@ -641,7 +641,7 @@ public void addPropertyValue( Name name,
if (JcrLexicon.UUID.equals(name)) return;

// The node was already created, so set the property using the editor ...
node.setProperty(name, (JcrValue)valueFor(value, propertyType), true, true);
node.setProperty(name, (JcrValue)valueFor(value, propertyType), true, true, true);
} else {
// The node hasn't been created yet, so just enqueue the property value into the map ...
List<Value> values = properties.get(name);
Expand Down Expand Up @@ -791,7 +791,7 @@ protected void create() throws SAXException {
}

// Otherwise, it's just a regular node...
child = parent.addChildNode(nodeName, primaryTypeName, key);
child = parent.addChildNode(nodeName, primaryTypeName, key, true);
} else {
child = existingNode;
}
Expand Down Expand Up @@ -825,7 +825,7 @@ protected void create() throws SAXException {

if (values.size() == 1 && !this.multiValuedPropertyNames.contains(propertyName)) {
// Don't check references or the protected status ...
prop = child.setProperty(propertyName, (JcrValue)values.get(0), true, true);
prop = child.setProperty(propertyName, (JcrValue)values.get(0), true, true, true);
} else {
prop = child.setProperty(propertyName,
values.toArray(new JcrValue[values.size()]),
Expand Down
Expand Up @@ -1696,7 +1696,7 @@ public void process( MutableCachedNode node,
jcrNode.setProperty(propName, defaultValues, defn.getRequiredType(), false);
} else {
// don't skip constraint checks or protected checks
jcrNode.setProperty(propName, defaultValues[0], false, false);
jcrNode.setProperty(propName, defaultValues[0], false, false, false);
}
} else {
// There is no default for this mandatory property, so this is a constraint violation ...
Expand Down
Expand Up @@ -190,7 +190,7 @@ public void copy( String srcWorkspace,
/*
* Use the JCR add child here to perform the parent validations
*/
AbstractJcrNode copy = parentNode.addChildNode(newNodeName, sourceNode.getPrimaryTypeName(), null);
AbstractJcrNode copy = parentNode.addChildNode(newNodeName, sourceNode.getPrimaryTypeName(), null, false);
Map<NodeKey, NodeKey> nodeKeyCorrespondence = copy.mutable().deepCopy(copySession.cache(),
sourceNode.node(),
sourceSession.cache());
Expand All @@ -213,7 +213,7 @@ public void copy( String srcWorkspace,
if (dstNode.isNodeType(JcrMixLexicon.REFERENCEABLE) && dstNode.hasProperty(JcrLexicon.UUID)) {
// for referenceable nodes, update the UUID to be be same as the new identifier
JcrValue identifierValue = dstNode.valueFactory().createValue(dstNode.getIdentifier());
dstNode.setProperty(JcrLexicon.UUID, identifierValue, true, true);
dstNode.setProperty(JcrLexicon.UUID, identifierValue, true, true, false);

// if there are any incoming references within the copied subgraph, they need to point to the new nodes
for (PropertyIterator incomingReferencesIterator = dstNode.getAllReferences(); incomingReferencesIterator.hasNext();) {
Expand Down Expand Up @@ -384,7 +384,7 @@ public void clone( String srcWorkspace,

// Use the JCR add child here to perform the parent validations
NodeKey cloneKey = parentNode.key().withId(sourceNode.key().getIdentifier());
parentNode.addChildNode(newNodeName, sourceNode.getPrimaryTypeName(), cloneKey);
parentNode.addChildNode(newNodeName, sourceNode.getPrimaryTypeName(), cloneKey, false);

deepClone(sourceSession, sourceNode.key(), cloneSession, cloneKey);
}
Expand Down
Expand Up @@ -1124,7 +1124,7 @@ public Collection<JcrNodeDefinition> getMandatoryChildNodeDefinitions( Name prim

/**
* Get the auto-created property definitions for the named node type. This method is used when
* {@link AbstractJcrNode#addChildNode(Name, Name, NodeKey) creating nodes}, which only needs the auto-created properties
* {@link AbstractJcrNode#addChildNode(org.modeshape.jcr.value.Name, org.modeshape.jcr.value.Name, org.modeshape.jcr.cache.NodeKey, boolean) creating nodes}, which only needs the auto-created properties
* for the primary type. It's also used when {@link AbstractJcrNode#addMixin(String) adding a mixin}.
*
* @param nodeType the node type name; may not be null
Expand All @@ -1136,7 +1136,7 @@ public Collection<JcrPropertyDefinition> getAutoCreatedPropertyDefinitions( Name

/**
* Get the auto-created child node definitions for the named node type. This method is used when
* {@link AbstractJcrNode#addChildNode(Name, Name, NodeKey) creating nodes}, which only needs the auto-created properties
* {@link AbstractJcrNode#addChildNode(org.modeshape.jcr.value.Name, org.modeshape.jcr.value.Name, org.modeshape.jcr.cache.NodeKey, boolean) creating nodes}, which only needs the auto-created properties
* for the primary type. It's also used when {@link AbstractJcrNode#addMixin(String) adding a mixin}.
*
* @param nodeType the node type name; may not be null
Expand Down
Expand Up @@ -252,7 +252,8 @@ private void setCreatedByIfNecessary( JcrSession outputSession,
// set by the system session when it saves and it will default to "modeshape-worker"
for (AbstractJcrNode node : outputNodes) {
if (node.isNodeType(JcrMixLexicon.CREATED)) {
node.setProperty(JcrLexicon.CREATED_BY, outputSession.getValueFactory().createValue(work.getUserId()), true, true);
node.setProperty(JcrLexicon.CREATED_BY, outputSession.getValueFactory().createValue(work.getUserId()), true, true,
false);
}
}
}
Expand Down

0 comments on commit d030d5e

Please sign in to comment.