diff --git a/source/java/org/alfresco/repo/lock/LockServiceImpl.java b/source/java/org/alfresco/repo/lock/LockServiceImpl.java
index fa9e34dfee..e6d2f78b97 100644
--- a/source/java/org/alfresco/repo/lock/LockServiceImpl.java
+++ b/source/java/org/alfresco/repo/lock/LockServiceImpl.java
@@ -413,7 +413,7 @@ public class LockServiceImpl implements LockService,
}
/**
- * Gets the lock statuc for a node and a user name
+ * Gets the lock status for a node and a user name
*
* @param nodeRef the node reference
* @param userName the user name
@@ -516,7 +516,7 @@ public class LockServiceImpl implements LockService,
if (LockType.WRITE_LOCK.equals(lockType) == true &&
LockStatus.LOCKED.equals(currentLockStatus) == true)
{
- // Error since we are trying to preform an operation on a locked node
+ // Lock is of type Write Lock and the node is locked by another owner.
throw new NodeLockedException(nodeRef);
}
else if (LockType.READ_ONLY_LOCK.equals(lockType) == true &&
@@ -526,6 +526,14 @@ public class LockServiceImpl implements LockService,
// modifications are prevented
throw new NodeLockedException(nodeRef);
}
+ else if (LockType.NODE_LOCK.equals(lockType) == true &&
+ (LockStatus.LOCKED.equals(currentLockStatus) == true || LockStatus.LOCK_OWNER.equals(currentLockStatus) == true))
+ {
+ // Error since there is a read only lock on this object and all
+ // modifications are prevented
+ throw new NodeLockedException(nodeRef);
+ }
+
}
catch (AspectMissingException exception)
{
@@ -547,7 +555,20 @@ public class LockServiceImpl implements LockService,
QName assocQName,
boolean isNewNode)
{
- checkForLock(parentNodeRef);
+ LockType lockType = getLockType(parentNodeRef);
+ if(lockType != null)
+ {
+
+ switch (lockType)
+ {
+ case WRITE_LOCK:
+ case READ_ONLY_LOCK:
+ checkForLock(parentNodeRef);
+ break;
+ case NODE_LOCK:
+ // don't check for lock
+ }
+ }
}
/**
@@ -612,7 +633,7 @@ public class LockServiceImpl implements LockService,
/**
* OnCreateVersion behaviour for the lock aspect
*
- * Ensures that the property valies of the lock aspect are not 'frozen' in
+ * Ensures that the property values of the lock aspect are not 'frozen' in
* the version store.
*/
public void onCreateVersion(
diff --git a/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java b/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java
index 08fd1db906..d3410d9272 100644
--- a/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java
+++ b/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java
@@ -39,7 +39,6 @@ import org.alfresco.repo.transfer.manifest.TransferManifestNode;
import org.alfresco.repo.transfer.manifest.TransferManifestNormalNode;
import org.alfresco.service.cmr.dictionary.AspectDefinition;
import org.alfresco.service.cmr.dictionary.DictionaryService;
-import org.alfresco.service.cmr.lock.LockService;
import org.alfresco.service.cmr.lock.LockType;
import org.alfresco.service.cmr.repository.ChildAssociationRef;
import org.alfresco.service.cmr.repository.ContentData;
@@ -90,8 +89,7 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
private ContentService contentService;
private DictionaryService dictionaryService;
private CorrespondingNodeResolver nodeResolver;
- private LockService lockService;
-
+
// State within this class
/**
* The header of the manifest
@@ -300,7 +298,7 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
{
log.debug("new node needs to be locked");
props.put(ContentModel.PROP_LOCK_OWNER, AuthenticationUtil.getAdminUserName());
- props.put(ContentModel.PROP_LOCK_TYPE, LockType.READ_ONLY_LOCK.toString());
+ props.put(ContentModel.PROP_LOCK_TYPE, LockType.NODE_LOCK.toString());
props.put(ContentModel.PROP_EXPIRY_DATE, null);
}
@@ -431,7 +429,7 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB
if(header.isReadOnly())
{
props.put(ContentModel.PROP_LOCK_OWNER, AuthenticationUtil.getAdminUserName());
- props.put(ContentModel.PROP_LOCK_TYPE, LockType.READ_ONLY_LOCK.toString());
+ props.put(ContentModel.PROP_LOCK_TYPE, LockType.NODE_LOCK.toString());
props.put(ContentModel.PROP_EXPIRY_DATE, null);
log.debug("updated node needs to be locked");
}
diff --git a/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java b/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java
index 30a865b64b..ce69dffc07 100644
--- a/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java
+++ b/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java
@@ -4003,14 +4003,6 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
{
lockService.unlock(nodeB);
lockService.unlock(nodeC);
- AuthenticationUtil.runAs(new RunAsWork()
- {
- public Void doWork()
- {
-
- return null;
- }
- }, USER_ONE);
}
finally
{
@@ -4042,6 +4034,9 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
assertTrue("dest node C does not exist", nodeService.exists(testNodeFactory.getMappedNodeRef(nodeC)));
assertTrue("dest node D does not exist", nodeService.exists(testNodeFactory.getMappedNodeRef(nodeD)));
+ assertFalse("test fail: dest node B is still locked", nodeService.hasAspect(nodeB, ContentModel.ASPECT_LOCKABLE));
+ assertFalse("test fail: dest node C is still locked", nodeService.hasAspect(nodeC, ContentModel.ASPECT_LOCKABLE));
+
assertFalse("dest node A not locked", nodeService.hasAspect(testNodeFactory.getMappedNodeRef(nodeA), ContentModel.ASPECT_LOCKABLE));
assertFalse("dest node B not locked", nodeService.hasAspect(testNodeFactory.getMappedNodeRef(nodeB), ContentModel.ASPECT_LOCKABLE));
assertFalse("dest node C not locked", nodeService.hasAspect(testNodeFactory.getMappedNodeRef(nodeC), ContentModel.ASPECT_LOCKABLE));
@@ -4089,4 +4084,137 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest
this.personService.createPerson(ppOne);
}
}
+
+ public void testReadOnlyTemorary() throws Exception
+ {
+ setDefaultRollback(false);
+
+ String CONTENT_TITLE = "ContentTitle";
+ String CONTENT_TITLE_UPDATED = "ContentTitleUpdated";
+ String CONTENT_NAME = "Temporary";
+ Locale CONTENT_LOCALE = Locale.GERMAN;
+ String CONTENT_STRING = "The quick brown fox";
+ Setnodes = new HashSet();
+ String USER_ONE = "TransferServiceImplTest";
+ String PASSWORD = "Password";
+
+ String targetName = "testReadOnlyFlag";
+
+ NodeRef nodeA;
+ NodeRef nodeB;
+ NodeRef nodeC;
+ NodeRef nodeD;
+
+ ChildAssociationRef child;
+
+ /**
+ * For unit test
+ * - replace the HTTP transport with the in-process transport
+ * - replace the node factory with one that will map node refs, paths etc.
+ */
+ TransferTransmitter transmitter = new UnitTestInProcessTransmitterImpl(this.receiver, this.contentService, transactionService);
+ transferServiceImpl.setTransmitter(transmitter);
+ UnitTestTransferManifestNodeFactory testNodeFactory = new UnitTestTransferManifestNodeFactory(this.transferManifestNodeFactory);
+ transferServiceImpl.setTransferManifestNodeFactory(testNodeFactory);
+ List> pathMap = testNodeFactory.getPathMap();
+ // Map company_home/guest_home to company_home so tranferred nodes and moved "up" one level.
+ pathMap.add(new Pair(PathHelper.stringToPath(GUEST_HOME_XPATH_QUERY), PathHelper.stringToPath(COMPANY_HOME_XPATH_QUERY)));
+
+ TransferTarget transferMe;
+
+ startNewTransaction();
+ try
+ {
+ /**
+ * Get guest home
+ */
+ String guestHomeQuery = "/app:company_home/app:guest_home";
+ ResultSet guestHomeResult = searchService.query(StoreRef.STORE_REF_WORKSPACE_SPACESSTORE, SearchService.LANGUAGE_XPATH, guestHomeQuery);
+ assertEquals("", 1, guestHomeResult.length());
+ NodeRef guestHome = guestHomeResult.getNodeRef(0);
+
+ /**
+ * Create a test node that we will read and write
+ */
+ String guid = GUID.generate();
+
+ child = nodeService.createNode(guestHome, ContentModel.ASSOC_CONTAINS, QName.createQName(guid), ContentModel.TYPE_FOLDER);
+ nodeA = child.getChildRef();
+ nodeService.setProperty(nodeA , ContentModel.PROP_TITLE, guid);
+ nodeService.setProperty(nodeA , ContentModel.PROP_NAME, guid);
+ nodes.add(nodeA);
+
+ child = nodeService.createNode(nodeA, ContentModel.ASSOC_CONTAINS, QName.createQName("testNodeB"), ContentModel.TYPE_CONTENT);
+ nodeB = child.getChildRef();
+ nodeService.setProperty(nodeB , ContentModel.PROP_TITLE, CONTENT_TITLE + "B");
+ nodeService.setProperty(nodeB , ContentModel.PROP_NAME, "DemoNodeB");
+
+ {
+ ContentWriter writer = contentService.getWriter(nodeB , ContentModel.PROP_CONTENT, true);
+ writer.setLocale(CONTENT_LOCALE);
+ writer.putContent(CONTENT_STRING);
+ nodes.add(nodeB);
+ }
+
+ child = nodeService.createNode(nodeA, ContentModel.ASSOC_CONTAINS, QName.createQName(NamespaceService.CONTENT_MODEL_1_0_URI,"testNodeC"), ContentModel.TYPE_FOLDER);
+ nodeC = child.getChildRef();
+ nodeService.setProperty(nodeC , ContentModel.PROP_TITLE, "TestNodeC");
+ nodeService.setProperty(nodeC , ContentModel.PROP_NAME, "TestNodeC");
+ nodes.add(nodeC);
+
+ child = nodeService.createNode(nodeC, ContentModel.ASSOC_CONTAINS, QName.createQName("testNodeD"), ContentModel.TYPE_CONTENT);
+ nodeD = child.getChildRef();
+ nodeService.setProperty(nodeD , ContentModel.PROP_TITLE, CONTENT_TITLE + "D");
+ nodeService.setProperty(nodeD , ContentModel.PROP_NAME, "DemoNodeD");
+ {
+ ContentWriter writer = contentService.getWriter(nodeD , ContentModel.PROP_CONTENT, true);
+ writer.setLocale(CONTENT_LOCALE);
+ writer.putContent(CONTENT_STRING);
+ nodes.add(nodeD);
+ }
+
+ // Create users
+ createUser(USER_ONE, PASSWORD);
+
+ /**
+ * Now go ahead and create our first transfer target
+ */
+ if(!transferService.targetExists(targetName))
+ {
+ transferMe = createTransferTarget(targetName);
+ }
+ else
+ {
+ transferMe = transferService.getTransferTarget(targetName);
+ }
+ }
+ finally
+ {
+ endTransaction();
+ }
+
+ /**
+ * Step 1.
+ * transfer Nodes ABCD with read only flag set - content should all be locked on destination
+ */
+ logger.debug("transfer read only - step 1");
+ startNewTransaction();
+ try
+ {
+ /**
+ * Transfer our transfer target nodes
+ */
+ {
+ TransferDefinition definition = new TransferDefinition();
+ definition.setNodes(nodes);
+ definition.setReadOnly(true);
+ transferService.transfer(targetName, definition);
+ }
+ }
+ finally
+ {
+ endTransaction();
+ }
+ }
+
}
diff --git a/source/java/org/alfresco/service/cmr/lock/LockStatus.java b/source/java/org/alfresco/service/cmr/lock/LockStatus.java
index 34c299d56f..d28bd698dd 100644
--- a/source/java/org/alfresco/service/cmr/lock/LockStatus.java
+++ b/source/java/org/alfresco/service/cmr/lock/LockStatus.java
@@ -19,7 +19,14 @@
package org.alfresco.service.cmr.lock;
/**
- * Enum used to indicate lock status.
+ * Used to indicate lock status.
+ *
+ *
+ * - NO_LOCK - Indicates that there is no lock present
+ * - LOCKED - Indicates that the node is locked by somebody else
+ * - LOCK_OWNER - Indicates that the node is locked and the current user has lock ownership rights
+ * - LOCK_EXPIRED - Indicates that the lock has expired and the node can be considered to be unlocked
+ *
*
* @author Roy Wetherall
*/
diff --git a/source/java/org/alfresco/service/cmr/lock/LockType.java b/source/java/org/alfresco/service/cmr/lock/LockType.java
index c74ba9aa70..2a2766209c 100644
--- a/source/java/org/alfresco/service/cmr/lock/LockType.java
+++ b/source/java/org/alfresco/service/cmr/lock/LockType.java
@@ -19,8 +19,15 @@
package org.alfresco.service.cmr.lock;
/**
- * Enum used to indicate lock type
- *
- * @author Roy Wetherall
+ * The type of lock to be used by the lock service
+ *
+ * The lock owner or the administrator can release the lock.
+ *
+ * - NODE_LOCK - no-one can update or delete the locked node.
+ * - READ_ONLY_LOCK - no-one can update or delete the locked node. No one can add children to the locked node
+ * - WRITE_LOCK - the owner can update or delete the locked node. The owner can add children to the locked node
+ *
*/
-public enum LockType {READ_ONLY_LOCK, WRITE_LOCK}
\ No newline at end of file
+public enum LockType {READ_ONLY_LOCK,
+ WRITE_LOCK,
+ NODE_LOCK }
\ No newline at end of file