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. + * + *

* * @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. + *

*/ -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