Return-Path: Delivered-To: apmail-jackrabbit-commits-archive@www.apache.org Received: (qmail 59489 invoked from network); 21 Nov 2008 13:27:40 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 21 Nov 2008 13:27:40 -0000 Received: (qmail 44752 invoked by uid 500); 21 Nov 2008 13:27:49 -0000 Delivered-To: apmail-jackrabbit-commits-archive@jackrabbit.apache.org Received: (qmail 44720 invoked by uid 500); 21 Nov 2008 13:27:49 -0000 Mailing-List: contact commits-help@jackrabbit.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@jackrabbit.apache.org Delivered-To: mailing list commits@jackrabbit.apache.org Received: (qmail 44711 invoked by uid 99); 21 Nov 2008 13:27:49 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 21 Nov 2008 05:27:49 -0800 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 21 Nov 2008 13:26:34 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id 0726B238889E; Fri, 21 Nov 2008 05:27:20 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r719577 - in /jackrabbit/trunk/jackrabbit-jcr2spi/src: main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java test/java/org/apache/jackrabbit/jcr2spi/lock/AbstractLockTest.java Date: Fri, 21 Nov 2008 13:27:19 -0000 To: commits@jackrabbit.apache.org From: angela@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20081121132720.0726B238889E@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: angela Date: Fri Nov 21 05:27:19 2008 New Revision: 719577 URL: http://svn.apache.org/viewvc?rev=719577&view=rev Log: JCR-1868: Inconsistent state when removing mix:lockable from a locked Node Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/lock/AbstractLockTest.java Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java?rev=719577&r1=719576&r2=719577&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java (original) +++ jackrabbit/trunk/jackrabbit-jcr2spi/src/main/java/org/apache/jackrabbit/jcr2spi/NodeImpl.java Fri Nov 21 05:27:19 2008 @@ -653,11 +653,7 @@ // removed, if any references are left to this node. NodeTypeImpl mixin = session.getNodeTypeManager().getNodeType(ntName); if (mixin.isNodeType(NameConstants.MIX_REFERENCEABLE)) { - // build effective node type of remaining mixin's & primary type - Name[] allRemaining = (Name[]) mixinValue.toArray(new Name[mixinValue.size() + 1]); - allRemaining[mixinValue.size()] = primaryTypeName; - EffectiveNodeType entRemaining = session.getEffectiveNodeTypeProvider().getEffectiveNodeType(allRemaining); - + EffectiveNodeType entRemaining = getRemainingENT(mixinValue); if (!entRemaining.includesNodeType(NameConstants.MIX_REFERENCEABLE)) { PropertyIterator iter = getReferences(); if (iter.hasNext()) { @@ -666,6 +662,17 @@ } } + /* + * mix:lockable: the mixin cannot be removed if the node is currently + * locked even if the editing session is the lock holder. + */ + if (mixin.isNodeType((NameConstants.MIX_LOCKABLE))) { + EffectiveNodeType entRemaining = getRemainingENT(mixinValue); + if (!entRemaining.includesNodeType(NameConstants.MIX_LOCKABLE) && isLocked()) { + throw new ConstraintViolationException(mixinName + " can not be removed: the node is locked."); + } + } + // delegate to operation Name[] mixins = (Name[]) mixinValue.toArray(new Name[mixinValue.size()]); Operation op = SetMixin.create(getNodeState(), mixins); @@ -709,6 +716,21 @@ } /** + * Build the effective node type of remaining mixin's & primary type + * + * @param remainingMixins + * @return effective node type + * @throws ConstraintViolationException + * @throws NoSuchNodeTypeException + */ + private EffectiveNodeType getRemainingENT(List remainingMixins) + throws ConstraintViolationException, NoSuchNodeTypeException { + Name[] allRemaining = (Name[]) remainingMixins.toArray(new Name[remainingMixins.size() + 1]); + allRemaining[remainingMixins.size()] = primaryTypeName; + return session.getEffectiveNodeTypeProvider().getEffectiveNodeType(allRemaining); + } + + /** * @see Node#canAddMixin(String) */ public boolean canAddMixin(String mixinName) throws RepositoryException { Modified: jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/lock/AbstractLockTest.java URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/lock/AbstractLockTest.java?rev=719577&r1=719576&r2=719577&view=diff ============================================================================== --- jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/lock/AbstractLockTest.java (original) +++ jackrabbit/trunk/jackrabbit-jcr2spi/src/test/java/org/apache/jackrabbit/jcr2spi/lock/AbstractLockTest.java Fri Nov 21 05:27:19 2008 @@ -25,8 +25,11 @@ import javax.jcr.RepositoryException; import javax.jcr.Node; import javax.jcr.Repository; +import javax.jcr.nodetype.ConstraintViolationException; import javax.jcr.lock.Lock; import javax.jcr.lock.LockException; +import java.util.List; +import java.util.Arrays; /** * AbstractLockTest... @@ -342,4 +345,39 @@ n.remove(); otherSession.save(); } + + public void testRemoveMixLockableFromLockedNode() throws RepositoryException { + try { + lockedNode.removeMixin(mixLockable); + lockedNode.save(); + + // the mixin got removed -> the lock should implicitely be released + // as well in order not to have inconsistencies + String msg = "Lock should have been released."; + assertFalse(msg, lock.isLive()); + assertFalse(msg, lockedNode.isLocked()); + List tokens = Arrays.asList(superuser.getLockTokens()); + assertFalse(msg, tokens.contains(lock.getLockToken())); + + assertFalse(msg, lockedNode.hasProperty(jcrLockOwner)); + assertFalse(msg, lockedNode.hasProperty(jcrlockIsDeep)); + + } catch (ConstraintViolationException e) { + // cannot remove the mixin -> ok + // consequently the node must still be locked, the lock still live... + String msg = "Lock must still be live."; + assertTrue(msg, lock.isLive()); + assertTrue(msg, lockedNode.isLocked()); + List tokens = Arrays.asList(superuser.getLockTokens()); + assertTrue(tokens.contains(lock.getLockToken())); + assertTrue(msg, lockedNode.hasProperty(jcrLockOwner)); + assertTrue(msg, lockedNode.hasProperty(jcrlockIsDeep)); + } finally { + // ev. re-add the mixin in order to be able to unlock the node + if (lockedNode.isLocked() && !lockedNode.isNodeType(mixLockable)) { + lockedNode.addMixin(mixLockable); + lockedNode.save(); + } + } + } } \ No newline at end of file