Package org.apache.jackrabbit.test.api.lock

Source Code of org.apache.jackrabbit.test.api.lock.LockTest

/*
* Copyright 2004-2005 The Apache Software Foundation or its licensors,
*                     as applicable.
*
* Licensed 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.test.api.lock;

import org.apache.jackrabbit.test.AbstractJCRTest;
import org.apache.jackrabbit.test.NotExecutableException;

import javax.jcr.Node;
import javax.jcr.Session;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.lock.LockException;
import javax.jcr.lock.Lock;

/**
* <code>LockTest</code> contains the test cases for the lock support in
* the JCR specification.
*
* @test
* @sources LockTest.java
* @executeClass org.apache.jackrabbit.test.api.lock.LockTest
* @keywords locking
*
* @tck.config testroot must allow child nodes of type <code>nodetype</code>
* @tck.config nodetype nodetype which is lockable or allows to add mix:lockable.
* The node must also allow child nodes with the same node type as itself.
* @tck.config nodename1 name of a lockable child node of type <code>nodetype</code>.
*/
public class LockTest extends AbstractJCRTest {

    /**
     * Test lock token functionality
     */
    public void testAddRemoveLockToken() throws Exception {
        // create new node
        Node n = testRootNode.addNode(nodeName1, testNodeType);
        n.addMixin(mixLockable);
        testRootNode.save();

        // lock node and get lock token
        Lock lock = n.lock(false, true);

        // assert: session must get a non-null lock token
        assertNotNull("session must get a non-null lock token",
                lock.getLockToken());

        // assert: session must hold lock token
        assertTrue("session must hold lock token",
                containsLockToken(superuser, lock.getLockToken()));

        // remove lock token
        String lockToken = lock.getLockToken();
        superuser.removeLockToken(lockToken);

        // assert: session must get a null lock token
        assertNull("session must get a null lock token",
                lock.getLockToken());

        // assert: session must still hold lock token
        assertFalse("session must not hold lock token",
                containsLockToken(superuser, lockToken));

        // assert: session unable to modify node
        try {
            n.addNode(nodeName2, testNodeType);
            fail("session unable to modify node");
        } catch (LockException e) {
            // expected
        }

        // add lock token
        superuser.addLockToken(lockToken);

        // assert: session must get a non-null lock token
        assertNotNull("session must get a non-null lock token",
                lock.getLockToken());

        // assert: session must hold lock token
        assertTrue("session must hold lock token",
                containsLockToken(superuser, lock.getLockToken()));

        // assert: session able to modify node
        n.addNode(nodeName2, testNodeType);
    }

    /**
     * Test session scope: other session may not access nodes that are
     * locked.
     */
    public void testNodeLocked() throws Exception {
        // create new node and lock it
        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
        n1.addMixin(mixLockable);
        testRootNode.save();

        // lock node
        Lock lock = n1.lock(false, true);

        // assert: isLive must return true
        assertTrue("Lock must be live", lock.isLive());

        // create new session
        Session otherSuperuser = helper.getSuperuserSession();

        try {
            // get same node
            Node n2 = (Node) otherSuperuser.getItem(n1.getPath());

            // assert: lock token must be null for other session
            assertNull("Lock token must be null for other session",
                    n2.getLock().getLockToken());

            // assert: modifying same node in other session must fail
            try {
                n2.addNode(nodeName2, testNodeType);
                fail("modifying same node in other session must fail");
            } catch (LockException e) {
                // expected
            }
        } finally {
            otherSuperuser.logout();
        }
    }

    /**
     * Test to get the lock holding node of a node
     */
    public void testGetNode() throws Exception {
        // create new node with a sub node and lock it
        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
        n1.addMixin(mixLockable);
        Node n1Sub = n1.addNode(nodeName1, testNodeType);
        n1Sub.addMixin(mixLockable);
        testRootNode.save();

        // lock node
        n1.lock(true, true);

        assertEquals("getNode() must return the lock holder",
                n1.getPath(),
                n1.getLock().getNode().getPath());

        assertEquals("getNode() must return the lock holder",
                n1.getPath(),
                n1Sub.getLock().getNode().getPath());

        n1.unlock();
    }

    /**
     * Test if getLockOwner() returns the same value as returned by
     * Session.getUserId at the time that the lock was placed
     */
    public void testGetLockOwnerProperty() throws Exception {
        // create new node and lock it
        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
        n1.addMixin(mixLockable);
        testRootNode.save();

        // lock node
        Lock lock = n1.lock(false, true);

        if (n1.getSession().getUserID() == null) {
            assertFalse("jcr:lockOwner must not exist if Session.getUserId() returns null",
                    n1.hasProperty(jcrLockOwner));
        } else {
            assertEquals("getLockOwner() must return the same value as stored " +
                    "in property " + jcrLockOwner + " of the lock holding " +
                    "node",
                    n1.getProperty(jcrLockOwner).getString(),
                    lock.getLockOwner());
        }
        n1.unlock();
    }

    /**
     * Test if getLockOwner() returns the same value as returned by
     * Session.getUserId at the time that the lock was placed
     */
    public void testGetLockOwner() throws Exception {
        // create new node and lock it
        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
        n1.addMixin(mixLockable);
        testRootNode.save();

        // lock node
        Lock lock = n1.lock(false, true);

        assertEquals("getLockOwner() must return the same value as returned " +
                "by Session.getUserId at the time that the lock was placed",
                testRootNode.getSession().getUserID(),
                lock.getLockOwner());

        n1.unlock();
    }

    /**
     * Test if a shallow lock does not lock the child nodes of the locked node.
     */
    public void testShallowLock() throws Exception {
        // create new nodes
        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
        n1.addMixin(mixLockable);
        Node n2 = n1.addNode(nodeName2, testNodeType);
        testRootNode.save();

        // lock parent node
        n1.lock(false, true);

        assertFalse("Shallow lock must not lock the child nodes of a node.",
                n2.isLocked());
    }

    /**
     * Test if it is possible to lock and unlock a checked-in node.
     */
    public void testCheckedIn()
            throws NotExecutableException, RepositoryException {

        Session session = testRootNode.getSession();

        if (session.getRepository().getDescriptor(Repository.OPTION_LOCKING_SUPPORTED) == null) {
            throw new NotExecutableException("Versioning is not supported.");
        }

        // create a node that is lockable and versionable
        Node node = testRootNode.addNode(nodeName1, testNodeType);
        node.addMixin(mixLockable);
        // try to make it versionable if it is not
        if (!node.isNodeType(mixVersionable)) {
            if (node.canAddMixin(mixVersionable)) {
                node.addMixin(mixVersionable);
            } else {
                throw new NotExecutableException("Node " + nodeName1 + " is " +
                        "not versionable and does not allow to add " +
                        "mix:versionable");
            }
        }
        testRootNode.save();

        node.checkin();

        node.lock(false, false);
        assertTrue("Locking of a checked-in node failed.",
                node.isLocked());

        node.unlock();
        assertFalse("Unlocking of a checked-in node failed.",
                node.isLocked());
    }

    /**
     * Test parent/child lock
     */
    public void testParentChildLock() throws Exception {
        // create new nodes
        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
        n1.addMixin(mixLockable);
        Node n2 = n1.addNode(nodeName2, testNodeType);
        n2.addMixin(mixLockable);
        testRootNode.save();

        // lock parent node
        n1.lock(false, true);

        // lock child node
        n2.lock(false, true);

        // unlock parent node
        n1.unlock();

        // child node must still hold lock
        assertTrue("child node must still hold lock", n2.holdsLock());
    }

    /**
     * Test parent/child lock
     */
    public void testParentChildDeepLock() throws Exception {
        // create new nodes
        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
        n1.addMixin(mixLockable);
        Node n2 = n1.addNode(nodeName2, testNodeType);
        n2.addMixin(mixLockable);
        testRootNode.save();

        // lock child node
        n2.lock(false, true);

        // assert: unable to deep lock parent node
        try {
            n1.lock(true, true);
            fail("unable to deep lock parent node");
        } catch (LockException e) {
            // expected
        }
    }

    /**
     * Test Lock.isDeep()
     */
    public void testIsDeep() throws RepositoryException {
        // create two lockable nodes
        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
        n1.addMixin(mixLockable);
        Node n2 = testRootNode.addNode(nodeName2, testNodeType);
        n2.addMixin(mixLockable);
        testRootNode.save();

        // lock node 1 "undeeply"
        Lock lock1 = n1.lock(false, true);
        assertFalse("Lock.isDeep() must be false if the lock has not been set " +
                "as not deep",
                lock1.isDeep());

        // lock node 2 "deeply"
        Lock lock2 = n2.lock(true, true);
        assertTrue("Lock.isDeep() must be true if the lock has been set " +
                "as deep",
                lock2.isDeep());
    }

    /**
     * Test Lock.isSessionScoped()
     */
    public void testIsSessionScoped() throws RepositoryException {
        // create two lockable nodes
        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
        n1.addMixin(mixLockable);
        Node n2 = testRootNode.addNode(nodeName2, testNodeType);
        n2.addMixin(mixLockable);
        testRootNode.save();

        // lock node 1 session-scoped
        Lock lock1 = n1.lock(false, true);
        assertTrue("Lock.isSessionScoped() must be true if the lock " +
                "is session-scoped",
                lock1.isSessionScoped());

        // lock node 2 open-scoped
        Lock lock2 = n2.lock(false, false);
        assertFalse("Lock.isSessionScoped() must be false if the lock " +
                "is open-scoped",
                lock2.isSessionScoped());

        n2.unlock();
    }

    /**
     * Test locks are released when session logs out
     */
    public void testLogout() throws Exception {
        // add node
        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
        n1.addMixin(mixLockable);
        testRootNode.save();

        // create new session
        Session otherSuperuser = helper.getSuperuserSession();

        Lock lock;
        try {
            // get node created above
            Node n2 = (Node) otherSuperuser.getItem(n1.getPath());

            // lock node
            lock = n2.lock(false, true);

            // assert: lock must be alive
            assertTrue("lock must be alive", lock.isLive());

            // assert: node must be locked
            assertTrue("node must be locked", n1.isLocked());
        } finally {
            // log out
            otherSuperuser.logout();
        }


        // assert: lock must not be alive
        assertFalse("lock must not be alive", lock.isLive());

        // assert: node must not be locked
        assertFalse("node must not be locked", n1.isLocked());
    }

    /**
     * Test locks may be transferred to other session
     */
    public void testLockTransfer() throws Exception {
        // add node
        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
        n1.addMixin(mixLockable);
        testRootNode.save();

        // create new session
        Session otherSuperuser = helper.getSuperuserSession();

        try {
            // get node created above
            Node n2 = (Node) otherSuperuser.getItem(n1.getPath());

            // lock node
            Lock lock = n2.lock(false, true);

            // assert: user must get non-null token
            assertNotNull("user must get non-null token", lock.getLockToken());

            // transfer to standard session
            String lockToken = lock.getLockToken();
            otherSuperuser.removeLockToken(lockToken);
            superuser.addLockToken(lockToken);

            // assert: user must get null token
            assertNull("user must get null token", lock.getLockToken());

            // assert: user must get non-null token
            assertNotNull("user must get non-null token",
                    n1.getLock().getLockToken());
        } finally {
            // log out
            otherSuperuser.logout();
        }
    }

    /**
     * Test open-scoped locks
     */
    public void testOpenScopedLocks() throws Exception {
        // add node
        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
        n1.addMixin(mixLockable);
        testRootNode.save();

        // create new session
        Session otherSuperuser = helper.getSuperuserSession();

        try {
            // get node created above
            Node n2 = (Node) otherSuperuser.getItem(n1.getPath());

            // lock node
            Lock lock = n2.lock(false, false);

            // transfer to standard session
            String lockToken = lock.getLockToken();
            otherSuperuser.removeLockToken(lockToken);
            superuser.addLockToken(lockToken);
        } finally {
            // log out
            otherSuperuser.logout();
        }

        // assert: node still locked
        assertTrue(n1.isLocked());
    }

    /**
     * Test refresh
     */
    public void testRefresh() throws Exception {
        // create new node
        Node n = testRootNode.addNode(nodeName1, testNodeType);
        n.addMixin(mixLockable);
        testRootNode.save();

        // lock node and get lock token
        Lock lock = n.lock(false, true);

        // assert: lock must be alive
        assertTrue("lock must be alive", lock.isLive());

        // assert: refresh must succeed
        lock.refresh();

        // unlock node
        n.unlock();

        // assert: lock must not be alive
        assertFalse("lock must not be alive", lock.isLive());
    }

    /**
     * Test refresh
     */
    public void testRefreshNotLive() throws Exception {
        // create new node
        Node n = testRootNode.addNode(nodeName1, testNodeType);
        n.addMixin(mixLockable);
        testRootNode.save();

        // lock node and get lock token
        Lock lock = n.lock(false, true);

        // assert: lock must be alive
        assertTrue("lock must be alive", lock.isLive());

        // unlock node
        n.unlock();

        // assert: lock must not be alive
        assertFalse("lock must not be alive", lock.isLive());

        // refresh
        try {
            lock.refresh();
            fail("Refresh on a lock that is not alive must fail");
        } catch (LockException e) {
            // success
        }
    }

    /**
     * Test getLock
     */
    public void testGetLock() throws Exception {
        // create new nodes
        Node n1 = testRootNode.addNode(nodeName1, testNodeType);
        n1.addMixin(mixLockable);
        Node n2 = n1.addNode(nodeName2, testNodeType);
        n2.addMixin(mixLockable);
        testRootNode.save();

        // deep lock parent node
        n1.lock(true, true);

        // get lock on child node
        Lock lock = n2.getLock();

        // lock holding node must be parent
        assertTrue("lock holding node must be parent", lock.getNode().equals(n1));
    }

    /**
     * Tests if a locked, checked-in node can be unlocked
     */
    public void testCheckedInUnlock() throws Exception {
        if (superuser.getRepository().getDescriptor(Repository.OPTION_VERSIONING_SUPPORTED) == null) {
            throw new NotExecutableException("Repository does not support versioning.");
        }

        // set up versionable and lockable node
        Node testNode = testRootNode.addNode(nodeName1);
        testNode.addMixin(mixVersionable);
        testNode.addMixin(mixLockable);
        testRootNode.save();

        // lock and check-in
        testNode.lock(false, true);
        testNode.save();
        testNode.checkin();

        // do the unlock
        testNode.unlock();
        assertFalse("Could not unlock a locked, checked-in node", testNode.holdsLock());
    }

    /**
     * Tests if locks are maintained when child nodes are reordered
     */
    public void testReorder() throws Exception {
        // create three lockable nodes with same name
        Node testNode = testRootNode.addNode(nodeName1);
        testNode.addMixin(mixLockable);
        testNode = testRootNode.addNode(nodeName1);
        testNode.addMixin(mixLockable);
        testNode = testRootNode.addNode(nodeName1);
        testNode.addMixin(mixLockable);
        testRootNode.save();

        // lock last node (3)
        testNode.lock(false, true);

        // assert: last node locked
        assertTrue("Third child node locked",
                testRootNode.getNode(nodeName1 + "[3]").isLocked());

        // move last node in front of first
        testRootNode.orderBefore(nodeName1 + "[3]", nodeName1 + "[1]");
        testRootNode.save();

        // assert: first node locked
        assertTrue("First child node locked",
                testRootNode.getNode(nodeName1 + "[1]").isLocked());
    }

    /**
     * Tests if locks are maintained when child nodes are reordered
     */
    public void testReorder2() throws Exception {
        // create three lockable nodes with same name
        Node testNode = testRootNode.addNode(nodeName1);
        testNode.addMixin(mixLockable);
        testNode = testRootNode.addNode(nodeName1);
        testNode.addMixin(mixLockable);
        testNode = testRootNode.addNode(nodeName1);
        testNode.addMixin(mixLockable);
        testRootNode.save();

        // lock first node (1)
        testRootNode.getNode(nodeName1 + "[1]").lock(false, true);

        // assert: first node locked
        assertTrue("First child node locked",
                testRootNode.getNode(nodeName1 + "[1]").isLocked());

        // move first node to last
        testRootNode.orderBefore(nodeName1 + "[1]", null);
        testRootNode.save();

        // assert: third node locked
        assertTrue("Third child node locked",
                testRootNode.getNode(nodeName1 + "[3]").isLocked());
    }

    /**
     * Tests if move preserves lock state (JIRA issue JCR-207). A node that has
     * been locked must still appear locked when it has been moved or renamed,
     * regardless whether the changes have already been made persistent.
     */
    public void testMoveLocked() throws Exception {
        Session session = testRootNode.getSession();

        // create two nodes, parent and child
        Node testNode1 = testRootNode.addNode(nodeName1);
        testNode1.addMixin(mixLockable);
        Node testNode2 = testNode1.addNode(nodeName2);
        testNode2.addMixin(mixLockable);
        testRootNode.save();

        // lock child node
        testNode2.lock(false, true);

        // assert: child node locked
        assertTrue("Child node locked", testNode2.isLocked());

        // move child node up
        String newPath = testRootNode.getPath() + "/" + testNode2.getName();
        session.move(testNode2.getPath(), newPath);

        // assert: child node locked, before save
        assertTrue("Child node locked before save", testNode2.isLocked());
        session.save();

        // assert: child node locked, after save
        assertTrue("Child node locked after save", testNode2.isLocked());
    }

    /**
     * Tests if unlocking the first of two locked same-name sibling nodes does
     * not unlock the second (JIRA issue JCR-284).
     */
    public void testUnlockSameNameSibling() throws RepositoryException {
        Session session = testRootNode.getSession();

        // create two same-name sibling nodes
        Node n1 = testRootNode.addNode(nodeName1);
        n1.addMixin("mix:lockable");
        Node n2 = testRootNode.addNode(nodeName1);
        n2.addMixin("mix:lockable");
        session.save();

        // lock both nodes
        n1.lock(true, true);
        n2.lock(true, true);

        // assert: both nodes are locked
        assertTrue("First node locked: ", n1.isLocked());
        assertTrue("Second node locked: ", n2.isLocked());

        // unlock first sibling
        n1.unlock();

        // assert: first node unlocked, second node still locked
        assertFalse("First node unlocked: ", n1.isLocked());
        assertTrue("Second node locked: ", n2.isLocked());
    }

    /**
     * Return a flag indicating whether the indicated session contains
     * a specific lock token
     */
    private boolean containsLockToken(Session session, String lockToken) {
        String[] lt = session.getLockTokens();
        for (int i = 0; i < lt.length; i++) {
            if (lt[i].equals(lockToken)) {
                return true;
            }
        }
        return false;
    }
}
TOP

Related Classes of org.apache.jackrabbit.test.api.lock.LockTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.