You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by st...@apache.org on 2004/09/24 16:11:13 UTC

svn commit: rev 47161 - incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/jcr/core

Author: stefan
Date: Fri Sep 24 07:11:12 2004
New Revision: 47161

Modified:
   incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/jcr/core/NodeImpl.java
Log:
fixing bug JCR-3: potentially inconsistent state of node if 
addMixin fails

Modified: incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/jcr/core/NodeImpl.java
==============================================================================
--- incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/jcr/core/NodeImpl.java	(original)
+++ incubator/jackrabbit/trunk/src/java/org/apache/jackrabbit/jcr/core/NodeImpl.java	Fri Sep 24 07:11:12 2004
@@ -1708,48 +1708,60 @@
 	    throw new ConstraintViolationException(ntce.getMessage());
 	}
 
-	// modify the state of this node
-	NodeState thisState = (NodeState) getOrCreateTransientItemState();
-	// add mixin name
-	Set mixins = new HashSet(thisState.getMixinTypeNames());
-	mixins.add(ntName);
-	thisState.setMixinTypeNames(mixins);
+	// do the actual modifications implied by the new mixin;
+	// try to revert the changes in case an excpetion occurs
+	try {
+	    // modify the state of this node
+	    NodeState thisState = (NodeState) getOrCreateTransientItemState();
+	    // add mixin name
+	    Set mixins = new HashSet(thisState.getMixinTypeNames());
+	    mixins.add(ntName);
+	    thisState.setMixinTypeNames(mixins);
 
-	// set jcr:mixinTypes property
-	setMixinTypesProperty(mixins);
+	    // set jcr:mixinTypes property
+	    setMixinTypesProperty(mixins);
 
-	// add 'auto-create' properties defined in mixin type
-	PropertyDef[] pda = mixin.getAutoCreatePropertyDefs();
-	for (int i = 0; i < pda.length; i++) {
-	    PropertyDefImpl pd = (PropertyDefImpl) pda[i];
-	    // make sure that the property is not already defined by primary type
-	    // or existing mixin's
-	    NodeTypeImpl declaringNT = (NodeTypeImpl) pd.getDeclaringNodeType();
-	    if (!entExisting.includesNodeType(declaringNT.getQName())) {
-		createChildProperty(pd.getQName(), pd.getRequiredType(), pd);
+	    // add 'auto-create' properties defined in mixin type
+	    PropertyDef[] pda = mixin.getAutoCreatePropertyDefs();
+	    for (int i = 0; i < pda.length; i++) {
+		PropertyDefImpl pd = (PropertyDefImpl) pda[i];
+		// make sure that the property is not already defined by primary type
+		// or existing mixin's
+		NodeTypeImpl declaringNT = (NodeTypeImpl) pd.getDeclaringNodeType();
+		if (!entExisting.includesNodeType(declaringNT.getQName())) {
+		    createChildProperty(pd.getQName(), pd.getRequiredType(), pd);
+		}
 	    }
-	}
 
-	// recursively add 'auto-create' child nodes defined in mixin type
-	NodeDef[] nda = mixin.getAutoCreateNodeDefs();
-	for (int i = 0; i < nda.length; i++) {
-	    NodeDefImpl nd = (NodeDefImpl) nda[i];
-	    // make sure that the child node is not already defined by primary type
-	    // or existing mixin's
-	    NodeTypeImpl declaringNT = (NodeTypeImpl) nd.getDeclaringNodeType();
-	    if (!entExisting.includesNodeType(declaringNT.getQName())) {
-		createChildNode(nd.getQName(), nd, (NodeTypeImpl) nd.getDefaultPrimaryType(), null);
+	    // recursively add 'auto-create' child nodes defined in mixin type
+	    NodeDef[] nda = mixin.getAutoCreateNodeDefs();
+	    for (int i = 0; i < nda.length; i++) {
+		NodeDefImpl nd = (NodeDefImpl) nda[i];
+		// make sure that the child node is not already defined by primary type
+		// or existing mixin's
+		NodeTypeImpl declaringNT = (NodeTypeImpl) nd.getDeclaringNodeType();
+		if (!entExisting.includesNodeType(declaringNT.getQName())) {
+		    createChildNode(nd.getQName(), nd, (NodeTypeImpl) nd.getDefaultPrimaryType(), null);
+		}
 	    }
-	}
 
-	// check for special node types
-	// todo centralize version history creation code (currently in NodeImpl.addMixin & ItemImpl.initVersionHistories
-	if (ntName.equals(NodeTypeRegistry.MIX_VERSIONABLE)) {
-	    VersionHistory hist = rep.getVersionManager().createVersionHistory(this);
-	    internalSetProperty(VersionImpl.PROPNAME_VERSION_HISTORY, InternalValue.create(new UUID(hist.getUUID())));
-	    internalSetProperty(VersionImpl.PROPNAME_BASE_VERSION, InternalValue.create(new UUID(hist.getRootVersion().getUUID())));
-	    internalSetProperty(VersionImpl.PROPNAME_IS_CHECKED_OUT, InternalValue.create(true));
-	    internalSetProperty(VersionImpl.PROPNAME_PREDECESSORS, new InternalValue[]{InternalValue.create(new UUID(hist.getRootVersion().getUUID()))});
+	    // check for special node types
+	    // todo centralize version history creation code (currently in NodeImpl.addMixin & ItemImpl.initVersionHistories
+	    if (ntName.equals(NodeTypeRegistry.MIX_VERSIONABLE)) {
+		VersionHistory hist = rep.getVersionManager().createVersionHistory(this);
+		internalSetProperty(VersionImpl.PROPNAME_VERSION_HISTORY, InternalValue.create(new UUID(hist.getUUID())));
+		internalSetProperty(VersionImpl.PROPNAME_BASE_VERSION, InternalValue.create(new UUID(hist.getRootVersion().getUUID())));
+		internalSetProperty(VersionImpl.PROPNAME_IS_CHECKED_OUT, InternalValue.create(true));
+		internalSetProperty(VersionImpl.PROPNAME_PREDECESSORS, new InternalValue[]{InternalValue.create(new UUID(hist.getRootVersion().getUUID()))});
+	    }
+	} catch (RepositoryException re) {
+	    // try to undo the modifications by removing the mixin 
+	    try {
+		removeMixin(mixinName);
+	    } catch (RepositoryException re1) {
+		// silently ignore & fall through
+	    }
+	    throw re;
 	}
     }