alfresco-community-repo/source/java/org/alfresco/repo/lock/LockBehaviourImplTest.java
Dave Ward 6f7095f450 Merged V4.0-BUG-FIX to HEAD
33935: ALF-12854: SOLR - requires more detailed tracking information
   - Part 1: info reported for the SOLR SUMMARY action
   33936: ALF-11693: Treat logging.properties the same way as log4j.properties and excluded it from the core .jar
   33945: ALF-12867: RIP jmx-dumper.jar
   33946: Fix minor issue introduced in r33920
   33947: IT-6847 "Error displays on recent 4.0 TS upgrade while navigate to a document details page"
   - errors spotted on folder details & in document library list also resolved by this fix
   33951: ALF-12867: Fixed typo
   33955: Some unit tests and examples on how to implement file wiping or shredding
    - One API change: On EagerContentStoreCleaner, the following is now protected:
         protected boolean deleteFromStore(String contentUrl, ContentStore store)
    - Examples in unit test ContentStoreCleanerTest: testForcedImmediateShredding and testShreddingCleanup
   33962: RIP hyperic plugin
   33965: ALF-12697: Asynchronously get RSS items for dashlets on page load
   33969: Fix for ALF-12307 Solr backup fills the disk
   - number to Keep can be set by property/subsystem/Share admin
   - set default backup localtion
   33970: Fix for ALF-12854 SOLR - requires more detailed tracking information
   Part 2: basic stats added to JMX and improved statistical moment calculation
   33984: Update 4.0.1 installers to use Tomcat 6.0.35
   - Remembered to set useHttpOnly on <Context>
   - Also commented out JreMemoryLeakPreventionListener
   33988: ALF-12717	CIFS: Unfriendly message occurs when a user with consumer/contributor role tries to rename space.
   33997: ALF-12697: Remove async WebScript from dashlet family
   33999: Fix for ALF-12854 SOLR - requires more detailed tracking information
   - Final part - Expose via share admin
   34005: Fix for ALF-12708
   34007: Merged V3.4-BUG-FIX (3.4.9) to 3.4-BUG-FIX (4.0.1)
      34006: Merged V3.4 (3.4.8) to V3.4-BUG-FIX (3.4.9)
         34002: ALF-12898: MMT does not calculate the current version number correctly and does not report errors
            - ModuleManagementTool was constructing the wrong current war file version number.
              The minor and revision values were the wrong way around. 3.4.8 became 3.8.4
            - Modified unit test to use the actual version number in the test war 4.1.0 rather than 4.0.1
            - Modified the ModuleManagementTool so that problems would be reported to the user even if they did not have -verbose set
   34016: Update version.revision for 4.0.1
   34022: Merged V3.4-BUG-FIX to V4.0-BUG-FIX
      33952: ALF-5680: It is possible to cut/paste a locked file   
      34003: Merged DEV to V3.4-BUG-FIX
         34001: ALF-12709: CLONE - Run action Wizard. Can't run action.
            Fixed regression connected with separator of AVM path in .NodeRef. id that has been changed from .;. to .|.
   34023: Merged V3.4-BUG-FIX to V4.0-BUG-FIX (RECORD ONLY)
      33912: ALF-9899: Merged HEAD to V3.4-BUG-FIX (PARTIAL)
         31912: Merged DEV to HEAD
            31823: TransactionalCache provides REPEATABLE READ
                   - Values found in shared cache are placed into transactional cache
                   - Previously, values could keep changing until first write (READ COMMITTED)
                     but now the first read sets the value until it is changed by the current
                     transaction   
      33981: Updated version.revision for 3.4.9
      33985: ALF-12364: Merged V4.0-BUG-FIX to V3.4-BUG-FIX
         33984: Update 3.4.9 installers to use Tomcat 6.0.35
            - Remembered to set useHttpOnly on <Context>
            - Also commented out JreMemoryLeakPreventionListener


git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@34024 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
2012-02-18 12:12:01 +00:00

394 lines
15 KiB
Java

/*
* Copyright (C) 2005-2010 Alfresco Software Limited.
*
* This file is part of Alfresco
*
* Alfresco is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Alfresco is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Alfresco. If not, see <http://www.gnu.org/licenses/>.
*/
package org.alfresco.repo.lock;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.alfresco.model.ContentModel;
import org.alfresco.repo.security.authentication.AuthenticationComponent;
import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.lock.LockType;
import org.alfresco.service.cmr.lock.NodeLockedException;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.NodeRef;
import org.alfresco.service.cmr.repository.NodeService;
import org.alfresco.service.cmr.repository.StoreRef;
import org.alfresco.service.cmr.security.MutableAuthenticationService;
import org.alfresco.service.cmr.security.PermissionService;
import org.alfresco.service.cmr.version.VersionService;
import org.alfresco.service.namespace.QName;
import org.alfresco.util.BaseSpringTest;
import org.alfresco.util.TestWithUserUtils;
/**
* LockBehaviourImpl Unit Test.
*
* @author Roy Wetherall
*/
public class LockBehaviourImplTest extends BaseSpringTest
{
/**
* The lock service
*/
private LockService lockService;
/**
* The version service
*/
private VersionService versionService;
/**
* The node service
*/
private NodeService nodeService;
/**
* The authentication service
*/
private MutableAuthenticationService authenticationService;
private PermissionService permissionService;
/**
* Node references used in the tests
*/
private NodeRef nodeRef;
private NodeRef noAspectNode;
/**
* Store reference
*/
private StoreRef storeRef;
/**
* User details
*/
private static final String PWD = "password";
private static final String GOOD_USER_NAME = "goodUser";
private static final String BAD_USER_NAME = "badUser";
NodeRef rootNodeRef;
@Override
protected void onSetUpInTransaction() throws Exception
{
this.nodeService = (NodeService)applicationContext.getBean("dbNodeService");
this.lockService = (LockService)applicationContext.getBean("lockService");
this.versionService = (VersionService)applicationContext.getBean("versionService");
this.authenticationService = (MutableAuthenticationService)applicationContext.getBean("authenticationService");
this.permissionService = (PermissionService)applicationContext.getBean("permissionService");
// Set the authentication
AuthenticationComponent authComponent = (AuthenticationComponent)this.applicationContext.getBean("authenticationComponent");
authComponent.setSystemUserAsCurrentUser();
// Create the node properties
HashMap<QName, Serializable> nodeProperties = new HashMap<QName, Serializable>();
nodeProperties.put(QName.createQName("{test}property1"), "value1");
// Create a workspace that contains the 'live' nodes
this.storeRef = this.nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.currentTimeMillis());
// Get a reference to the root node
rootNodeRef = this.nodeService.getRootNode(this.storeRef);
// Create node
this.nodeRef = this.nodeService.createNode(
rootNodeRef,
ContentModel.ASSOC_CHILDREN,
QName.createQName("{}ParentNode"),
ContentModel.TYPE_FOLDER,
nodeProperties).getChildRef();
this.nodeService.addAspect(this.nodeRef, ContentModel.ASPECT_LOCKABLE, new HashMap<QName, Serializable>());
assertNotNull(this.nodeRef);
// Create a node with no lockAspect
this.noAspectNode = this.nodeService.createNode(
rootNodeRef,
ContentModel.ASSOC_CHILDREN,
QName.createQName("{}noAspectNode"),
ContentModel.TYPE_CONTAINER,
nodeProperties).getChildRef();
assertNotNull(this.noAspectNode);
// Create the users
TestWithUserUtils.createUser(GOOD_USER_NAME, PWD, rootNodeRef, this.nodeService, this.authenticationService);
TestWithUserUtils.createUser(BAD_USER_NAME, PWD, rootNodeRef, this.nodeService, this.authenticationService);
// Stash the user node ref's for later use
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
permissionService.setPermission(rootNodeRef, GOOD_USER_NAME, PermissionService.ALL_PERMISSIONS, true);
permissionService.setPermission(rootNodeRef, BAD_USER_NAME, PermissionService.READ, true);
}
/**
* Test checkForLock (no user specified)
*/
public void testCheckForLockNoUser()
{
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
this.lockService.checkForLock(this.nodeRef);
this.lockService.checkForLock(this.noAspectNode);
// Give the node a write lock (as the good user)
this.lockService.lock(this.nodeRef, LockType.WRITE_LOCK);
this.lockService.checkForLock(this.nodeRef);
// Give the node a read only lock (as the good user)
this.lockService.unlock(this.nodeRef);
this.lockService.lock(this.nodeRef, LockType.READ_ONLY_LOCK);
try
{
this.lockService.checkForLock(this.nodeRef);
fail("The node locked exception should have been raised");
}
catch (NodeLockedException exception)
{
// Correct behaviour
}
// Give the node a write lock (as the bad user)
this.lockService.unlock(this.nodeRef);
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
this.lockService.lock(this.nodeRef, LockType.WRITE_LOCK);
try
{
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
this.lockService.checkForLock(this.nodeRef);
fail("The node locked exception should have been raised");
}
catch (NodeLockedException exception)
{
// Correct behaviour
}
// Give the node a read only lock (as the bad user)
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
this.lockService.unlock(this.nodeRef);
this.lockService.lock(this.nodeRef, LockType.READ_ONLY_LOCK);
try
{
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
this.lockService.checkForLock(this.nodeRef);
fail("The node locked exception should have been raised");
}
catch (NodeLockedException exception)
{
// Correct behaviour
}
}
public void testCheckForLockWhenExpired()
{
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
this.lockService.lock(this.nodeRef, LockType.READ_ONLY_LOCK, 1);
try
{
this.lockService.checkForLock(this.nodeRef);
fail("Should be locked.");
}
catch (NodeLockedException e)
{
// Expected
}
try {Thread.sleep(2*1000); } catch (Exception e) {};
// Should now have expired so the node should no longer appear to be locked
this.lockService.checkForLock(this.nodeRef);
}
/**
* Test version service lock checking
*/
public void testVersionServiceLockBehaviour01()
{
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
// Add the version aspect to the node
this.nodeService.addAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE, null);
try
{
this.versionService.createVersion(this.nodeRef, new HashMap<String, Serializable>());
}
catch (NodeLockedException exception)
{
fail("There is no lock so this should have worked.");
}
// Lock the node as the good user with a write lock
this.lockService.lock(this.nodeRef, LockType.WRITE_LOCK);
try
{
this.versionService.createVersion(this.nodeRef, new HashMap<String, Serializable>());
}
catch (NodeLockedException exception)
{
fail("Tried to version as the lock owner so should work.");
}
this.lockService.unlock(this.nodeRef);
// Lock the node as the good user with a read only lock
this.lockService.lock(this.nodeRef, LockType.READ_ONLY_LOCK);
try
{
this.versionService.createVersion(this.nodeRef, new HashMap<String, Serializable>());
fail("Should have failed since this node has been locked with a read only lock.");
}
catch (NodeLockedException exception)
{
}
this.lockService.unlock(this.nodeRef);
}
/**
* Test version service lock checking
*/
public void testVersionServiceLockBehaviour02()
{
// Add the version aspect to the node
this.nodeService.addAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE, null);
// Lock the node as the bad user with a write lock
this.lockService.lock(this.nodeRef, LockType.WRITE_LOCK);
try
{
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
this.versionService.createVersion(this.nodeRef, new HashMap<String, Serializable>());
fail("Should have failed since this node has been locked by another user with a write lock.");
}
catch (NodeLockedException exception)
{
}
}
/**
* Test that the node service lock behaviour is as we expect
*
*/
@SuppressWarnings("unused")
public void testNodeServiceLockBehaviour()
{
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
// Check that we can create a new node and set of it properties when no lock is present
ChildAssociationRef childAssocRef = this.nodeService.createNode(
this.nodeRef,
ContentModel.ASSOC_CONTAINS,
QName.createQName("{test}nodeServiceLockTest"),
ContentModel.TYPE_CONTAINER);
NodeRef nodeRef = childAssocRef.getChildRef();
// Lets lock the parent node and check that whether we can still create a new node
this.lockService.lock(this.nodeRef, LockType.WRITE_LOCK);
ChildAssociationRef childAssocRef2 = this.nodeService.createNode(
this.nodeRef,
ContentModel.ASSOC_CONTAINS,
QName.createQName("{test}nodeServiceLockTest"),
ContentModel.TYPE_CONTAINER);
NodeRef nodeRef2 = childAssocRef.getChildRef();
// Lets check that we can do other stuff with the node since we have it locked
this.nodeService.setProperty(this.nodeRef, QName.createQName("{test}prop1"), "value1");
Map<QName, Serializable> propMap = new HashMap<QName, Serializable>();
propMap.put(QName.createQName("{test}prop2"), "value2");
this.nodeService.setProperties(this.nodeRef, propMap);
this.nodeService.removeAspect(this.nodeRef, ContentModel.ASPECT_VERSIONABLE);
// TODO there are various other calls that could be more vigirously checked
// Lock the node as the 'bad' user
this.lockService.unlock(this.nodeRef);
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
this.lockService.lock(this.nodeRef, LockType.WRITE_LOCK);
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
// Lets check that we can't create a new child
try
{
this.nodeService.createNode(
this.nodeRef,
ContentModel.ASSOC_CONTAINS,
QName.createQName("{test}nodeServiceLockTest"),
ContentModel.TYPE_CONTAINER);
fail("The parent is locked so a new child should not have been created.");
}
catch(NodeLockedException exception)
{
}
// TODO various other tests along these lines ...
// TODO check that delete is also working
}
/**
* ALF-5680: It is possible to cut/paste a locked file
*/
public void testCannotMoveNodeWhenLocked()
{
TestWithUserUtils.authenticateUser(GOOD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
// Create the node that we'll try to move
NodeRef parentNode = this.nodeRef;
ChildAssociationRef childAssocRef = nodeService.createNode(
parentNode,
ContentModel.ASSOC_CONTAINS,
QName.createQName("{test}nodeServiceLockTest"),
ContentModel.TYPE_CONTENT);
NodeRef nodeRef = childAssocRef.getChildRef();
// Lock it - so that it can't be moved.
this.lockService.lock(nodeRef, LockType.WRITE_LOCK);
// Create the new container that we'll move the node to.
NodeRef newParentRef = nodeService.createNode(
parentNode,
ContentModel.ASSOC_CONTAINS,
QName.createQName("{test}nodeServiceLockTest"),
ContentModel.TYPE_CONTAINER).getChildRef();
// Now the bad user will try to move the node.
TestWithUserUtils.authenticateUser(BAD_USER_NAME, PWD, rootNodeRef, this.authenticationService);
try
{
nodeService.moveNode(
nodeRef,
newParentRef,
ContentModel.ASSOC_CONTAINS,
QName.createQName("{test}nodeServiceLockTest"));
fail("Shouldn't have been able to move locked node.");
}
catch (NodeLockedException e)
{
// Good, we can't move it - as expected.
}
}
}