diff --git a/config/alfresco/transfer-service-context.xml b/config/alfresco/transfer-service-context.xml index 996410da69..69462a9c27 100644 --- a/config/alfresco/transfer-service-context.xml +++ b/config/alfresco/transfer-service-context.xml @@ -51,6 +51,7 @@ + @@ -101,8 +102,9 @@ - - + + + diff --git a/source/java/org/alfresco/repo/transfer/DefaultManifestProcessorFactoryImpl.java b/source/java/org/alfresco/repo/transfer/DefaultManifestProcessorFactoryImpl.java index bfb7c94870..c58d2cc81a 100644 --- a/source/java/org/alfresco/repo/transfer/DefaultManifestProcessorFactoryImpl.java +++ b/source/java/org/alfresco/repo/transfer/DefaultManifestProcessorFactoryImpl.java @@ -27,17 +27,18 @@ import org.alfresco.repo.transfer.requisite.TransferRequsiteWriter; import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.repository.ContentService; import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.transfer.TransferReceiver; /** * @author brian - * */ public class DefaultManifestProcessorFactoryImpl implements ManifestProcessorFactory { private NodeService nodeService; private ContentService contentService; private DictionaryService dictionaryService; + private PermissionService permissionService; private CorrespondingNodeResolverFactory nodeResolverFactory; /* @@ -55,6 +56,7 @@ public class DefaultManifestProcessorFactoryImpl implements ManifestProcessorFac primaryProcessor.setNodeResolver(nodeResolver); primaryProcessor.setNodeService(nodeService); primaryProcessor.setDictionaryService(dictionaryService); + primaryProcessor.setPermissionService(getPermissionService()); processors.add(primaryProcessor); RepoSecondaryManifestProcessorImpl secondaryProcessor = new RepoSecondaryManifestProcessorImpl(receiver, transferId); @@ -119,4 +121,14 @@ public class DefaultManifestProcessorFactoryImpl implements ManifestProcessorFac return processor; } + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + + public PermissionService getPermissionService() + { + return permissionService; + } + } diff --git a/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java b/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java index 17fb3e31ba..e8e84c8ff7 100644 --- a/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java +++ b/source/java/org/alfresco/repo/transfer/RepoPrimaryManifestProcessorImpl.java @@ -30,6 +30,8 @@ import java.util.Set; import org.alfresco.model.ContentModel; import org.alfresco.repo.transfer.CorrespondingNodeResolver.ResolvedParentChildPair; +import org.alfresco.repo.transfer.manifest.ManifestAccessControl; +import org.alfresco.repo.transfer.manifest.ManifestPermission; import org.alfresco.repo.transfer.manifest.TransferManifestDeletedNode; import org.alfresco.repo.transfer.manifest.TransferManifestHeader; import org.alfresco.repo.transfer.manifest.TransferManifestNode; @@ -43,6 +45,9 @@ import org.alfresco.service.cmr.repository.ContentWriter; 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.AccessPermission; +import org.alfresco.service.cmr.security.AccessStatus; +import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.transfer.TransferReceiver; import org.alfresco.service.namespace.QName; import org.apache.commons.logging.Log; @@ -78,6 +83,7 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB } private NodeService nodeService; + private PermissionService permissionService; private ContentService contentService; private DictionaryService dictionaryService; private CorrespondingNodeResolver nodeResolver; @@ -319,6 +325,27 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB { nodeService.addAspect(newNode.getChildRef(), aspect, null); } + + ManifestAccessControl acl = node.getAccessControl(); + // Apply new ACL to this node + if(acl != null) + { + permissionService.setInheritParentPermissions(newNode.getChildRef(), acl.isInherited()); + + if(acl.getPermissions() != null) + { + for(ManifestPermission permission : acl.getPermissions()) + { + log.debug("setting permission on node"); + AccessStatus status = AccessStatus.valueOf(permission.getStatus()); + // The node has its own access control list + permissionService.setPermission(newNode.getChildRef(), + permission.getAuthority(), + permission.getPermission(), + status == AccessStatus.ALLOWED); + } + } + } // Is the node that we've just added the parent of any orphans that // we've found earlier? @@ -435,6 +462,70 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB { nodeService.removeAspect(nodeToUpdate, aspect); } + + // Check the ACL of this updated node + + ManifestAccessControl acl = node.getAccessControl(); + if(acl != null) + { + boolean existInherit = permissionService.getInheritParentPermissions(nodeToUpdate); + if(existInherit != acl.isInherited()) + { + log.debug("changed inherit permissions flag"); + permissionService.setInheritParentPermissions(nodeToUpdate, acl.isInherited()); + } + + Set existingPermissions = permissionService.getAllSetPermissions(nodeToUpdate); + List newPermissions = acl.getPermissions(); + + if(existingPermissions.size() > 0 || newPermissions != null) + { + // Yes we have explicit permissions on this node. + log.debug("have to check permissions"); + + Setwork = new HashSet(); + for(AccessPermission permission : existingPermissions) + { + if(permission.isSetDirectly()) + { + ManifestPermission p = new ManifestPermission(); + p.setAuthority(permission.getAuthority()); + p.setPermission(permission.getPermission()); + p.setStatus(permission.getAccessStatus().toString()); + work.add(p); + } + } + + // Do we need to check whether to add any permissions ? + if(newPermissions != null) + { + // Do we need to add any permissions ? + for(ManifestPermission permission : acl.getPermissions()) + { + if(!work.contains(permission)) + { + log.debug("setting permission on node:" + permission); + AccessStatus status = AccessStatus.valueOf(permission.getStatus()); + permissionService.setPermission(nodeToUpdate, + permission.getAuthority(), + permission.getPermission(), + status == AccessStatus.ALLOWED); + } + } + + // Remove permissions from "work" that should be there + work.removeAll(newPermissions); + + } + + // Do we need to remove any permissions + for(ManifestPermission permission : work) + { + log.debug("removing permission on node:" + permission); + permissionService.deletePermission(nodeToUpdate, permission.getAuthority(), permission.getPermission()); + } + } + } } } @@ -684,4 +775,14 @@ public class RepoPrimaryManifestProcessorImpl extends AbstractManifestProcessorB this.nodeResolver = nodeResolver; } + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + + public PermissionService getPermissionService() + { + return permissionService; + } + } diff --git a/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java b/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java index e856649b2a..b1a93801fe 100644 --- a/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java +++ b/source/java/org/alfresco/repo/transfer/TransferServiceImplTest.java @@ -48,7 +48,9 @@ import org.alfresco.service.cmr.repository.Path; import org.alfresco.service.cmr.repository.StoreRef; import org.alfresco.service.cmr.search.ResultSet; import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.security.MutableAuthenticationService; +import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.transfer.TransferCallback; import org.alfresco.service.cmr.transfer.TransferDefinition; import org.alfresco.service.cmr.transfer.TransferEvent; @@ -86,6 +88,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest private TransactionService transactionService; private TransferReceiver receiver; private TransferManifestNodeFactory transferManifestNodeFactory; + private PermissionService permissionService; String COMPANY_HOME_XPATH_QUERY = "/{http://www.alfresco.org/model/application/1.0}company_home"; String GUEST_HOME_XPATH_QUERY = "/{http://www.alfresco.org/model/application/1.0}company_home/{http://www.alfresco.org/model/application/1.0}guest_home"; @@ -116,6 +119,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest this.contentService = (ContentService) this.applicationContext.getBean("contentService"); this.authenticationService = (MutableAuthenticationService) this.applicationContext.getBean("authenticationService"); this.actionService = (ActionService)this.applicationContext.getBean("actionService"); + this.permissionService = (PermissionService)this.applicationContext.getBean("permissionService"); this.receiver = (TransferReceiver)this.applicationContext.getBean("transferReceiver"); this.transferManifestNodeFactory = (TransferManifestNodeFactory)this.applicationContext.getBean("transferManifestNodeFactory"); this.authenticationComponent = (AuthenticationComponent) this.applicationContext.getBean("authenticationComponent"); @@ -740,9 +744,7 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest Date srcModifiedDate = (Date)nodeService.getProperty(contentNodeRef, ContentModel.PROP_MODIFIED); logger.debug("srcModifiedDate : " + srcModifiedDate + " destModifiedDate : " + destModifiedDate); - - // BUGBUG - MER 14/07/2010 - can't set modified date - // assertTrue("after update, modified date is not correct", destModifiedDate.compareTo(srcModifiedDate) == 0); + assertTrue("after update, modified date is not correct", destModifiedDate.compareTo(srcModifiedDate) == 0); Date destCreatedDate = (Date)nodeService.getProperty(destNodeRef, ContentModel.PROP_CREATED); Date srcCreatedDate = (Date)nodeService.getProperty(contentNodeRef, ContentModel.PROP_CREATED); @@ -2646,6 +2648,354 @@ public class TransferServiceImplTest extends BaseAlfrescoSpringTest // } } + + /** + * Test the transfer method with regard to permissions on a node. + * + * Step 1: + * Create a node with a single permission + * Inherit:false + * Read, Admin, Allow + * Transfer + * + * Step 2: + * Update it to have several permissions + * Inherit:false + * Read, Everyone, DENY + * Read, Admin, Allow + * + * Step 3: + * Remove a permission + * Inherit:false + * Read, Admin, Allow + * + * Step 4: + * Revert to inherit all permissions + * Inherit:true + * + * This is a unit test so it does some shenanigans to send to the same instance of alfresco. + */ + public void testTransferWithPermissions() throws Exception + { + setDefaultRollback(false); + + String CONTENT_TITLE = "ContentTitle"; + String CONTENT_TITLE_UPDATED = "ContentTitleUpdated"; + Locale CONTENT_LOCALE = Locale.GERMAN; + String CONTENT_STRING = "Hello"; + + /** + * 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(receiver, 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))); + + /** + * Now go ahead and create our transfer target + */ + String targetName = "testTransferWithPermissions"; + TransferTarget transferMe; + NodeRef contentNodeRef; + NodeRef destNodeRef; + + 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 name = GUID.generate(); + ChildAssociationRef child = nodeService.createNode(guestHome, ContentModel.ASSOC_CONTAINS, QName.createQName(name), ContentModel.TYPE_CONTENT); + contentNodeRef = child.getChildRef(); + nodeService.setProperty(contentNodeRef, ContentModel.PROP_TITLE, CONTENT_TITLE); + nodeService.setProperty(contentNodeRef, ContentModel.PROP_NAME, name); + + ContentWriter writer = contentService.getWriter(contentNodeRef, ContentModel.PROP_CONTENT, true); + writer.setLocale(CONTENT_LOCALE); + writer.putContent(CONTENT_STRING); + + permissionService.setInheritParentPermissions(contentNodeRef, false); + permissionService.setPermission(contentNodeRef, "admin", PermissionService.READ, true); + + if(!transferService.targetExists(targetName)) + { + transferMe = createTransferTarget(targetName); + } + else + { + transferMe = transferService.getTransferTarget(targetName); + } + } + finally + { + endTransaction(); + } + + /** + * Step 1 + */ + logger.debug("First transfer - create new node with inheritParent permission off"); + startNewTransaction(); + try + { + /** + * Transfer our transfer target node + */ + { + TransferDefinition definition = new TransferDefinition(); + Setnodes = new HashSet(); + nodes.add(contentNodeRef); + definition.setNodes(nodes); + transferService.transfer(targetName, definition); + } + } + finally + { + endTransaction(); + } + + startNewTransaction(); + try + { + // Now validate that the target node exists with the correct permissions + destNodeRef = testNodeFactory.getMappedNodeRef(contentNodeRef); + assertFalse("unit test stuffed up - comparing with self", destNodeRef.equals(transferMe.getNodeRef())); + assertTrue("dest node ref does not exist", nodeService.exists(destNodeRef)); + assertEquals("title is wrong", (String)nodeService.getProperty(destNodeRef, ContentModel.PROP_TITLE), CONTENT_TITLE); + assertEquals("type is wrong", nodeService.getType(contentNodeRef), nodeService.getType(destNodeRef)); + + // Check ACL of destination node + boolean srcInherit = permissionService.getInheritParentPermissions(contentNodeRef); + Set srcPerm = permissionService.getAllSetPermissions(contentNodeRef); + + boolean destInherit = permissionService.getInheritParentPermissions(destNodeRef); + Set destPerm = permissionService.getAllSetPermissions(destNodeRef); + + assertFalse("inherit parent permissions (src) flag is incorrect", srcInherit); + assertFalse("inherit parent permissions (dest) flag is incorrect", destInherit); + + // Check destination has the source's permissions + for (AccessPermission p : srcPerm) + { + logger.debug("checking permission :" + p); + assertTrue("permission is missing", destPerm.contains(p)); + } + } + finally + { + endTransaction(); + } + + /** + * Step 2 + * Update it to have several permissions + * Inherit:false + * Read, Everyone, DENY + * Read, Admin, Allow + */ + startNewTransaction(); + try + { + permissionService.setPermission(contentNodeRef, "EVERYONE", PermissionService.READ, false); + permissionService.setPermission(contentNodeRef, "admin", PermissionService.FULL_CONTROL, true); + } + finally + { + endTransaction(); + } + + startNewTransaction(); + try + { + /** + * Transfer our transfer target node + */ + { + TransferDefinition definition = new TransferDefinition(); + Setnodes = new HashSet(); + nodes.add(contentNodeRef); + definition.setNodes(nodes); + transferService.transfer(targetName, definition); + } + } + finally + { + endTransaction(); + } + + + startNewTransaction(); + try + { + // Now validate that the target node exists with the correct permissions + destNodeRef = testNodeFactory.getMappedNodeRef(contentNodeRef); + + // Check ACL of destination node + boolean srcInherit = permissionService.getInheritParentPermissions(contentNodeRef); + Set srcPerm = permissionService.getAllSetPermissions(contentNodeRef); + + boolean destInherit = permissionService.getInheritParentPermissions(destNodeRef); + Set destPerm = permissionService.getAllSetPermissions(destNodeRef); + + assertFalse("inherit parent permissions (src) flag is incorrect", srcInherit); + assertFalse("inherit parent permissions (dest) flag is incorrect", destInherit); + + // Check destination has the source's permissions + for (AccessPermission p : srcPerm) + { + logger.debug("checking permission :" + p); + assertTrue("Step2, permission is missing", destPerm.contains(p)); + } + } + finally + { + endTransaction(); + } + + /** + * Step 3 Remove a permission + */ + startNewTransaction(); + try + { + permissionService.deletePermission(contentNodeRef, "admin", PermissionService.FULL_CONTROL); + } + finally + { + endTransaction(); + } + + startNewTransaction(); + try + { + /** + * Transfer our transfer target node + */ + { + TransferDefinition definition = new TransferDefinition(); + Setnodes = new HashSet(); + nodes.add(contentNodeRef); + definition.setNodes(nodes); + transferService.transfer(targetName, definition); + } + } + finally + { + endTransaction(); + } + + startNewTransaction(); + try + { + // Now validate that the target node exists with the correct permissions + destNodeRef = testNodeFactory.getMappedNodeRef(contentNodeRef); + + // Check ACL of destination node + boolean srcInherit = permissionService.getInheritParentPermissions(contentNodeRef); + Set srcPerm = permissionService.getAllSetPermissions(contentNodeRef); + + boolean destInherit = permissionService.getInheritParentPermissions(destNodeRef); + Set destPerm = permissionService.getAllSetPermissions(destNodeRef); + + assertFalse("inherit parent permissions (src) flag is incorrect", srcInherit); + assertFalse("inherit parent permissions (dest) flag is incorrect", destInherit); + + // Check destination has the source's permissions + for (AccessPermission p : srcPerm) + { + logger.debug("checking permission :" + p); + assertTrue("permission is missing", destPerm.contains(p)); + } + } + finally + { + endTransaction(); + } + + /** + * Step 4 + * Revert to inherit all permissions + */ + startNewTransaction(); + try + { + permissionService.setInheritParentPermissions(contentNodeRef, true); + } + finally + { + endTransaction(); + } + + startNewTransaction(); + try + { + /** + * Transfer our transfer target node + */ + { + TransferDefinition definition = new TransferDefinition(); + Setnodes = new HashSet(); + nodes.add(contentNodeRef); + definition.setNodes(nodes); + transferService.transfer(targetName, definition); + } + } + finally + { + endTransaction(); + } + + startNewTransaction(); + try + { + // Now validate that the target node exists with the correct permissions + destNodeRef = testNodeFactory.getMappedNodeRef(contentNodeRef); + assertFalse("unit test stuffed up - comparing with self", destNodeRef.equals(transferMe.getNodeRef())); + assertTrue("dest node ref does not exist", nodeService.exists(destNodeRef)); + assertEquals("title is wrong", (String)nodeService.getProperty(destNodeRef, ContentModel.PROP_TITLE), CONTENT_TITLE); + assertEquals("type is wrong", nodeService.getType(contentNodeRef), nodeService.getType(destNodeRef)); + + // Check ACL of destination node + boolean srcInherit = permissionService.getInheritParentPermissions(contentNodeRef); + Set srcPerm = permissionService.getAllSetPermissions(contentNodeRef); + + boolean destInherit = permissionService.getInheritParentPermissions(destNodeRef); + Set destPerm = permissionService.getAllSetPermissions(destNodeRef); + + assertTrue("inherit parent permissions (src) flag is incorrect", srcInherit); + assertTrue("inherit parent permissions (dest) flag is incorrect", destInherit); + + // Check destination has the source's permissions + for (AccessPermission p : srcPerm) + { + if(p.isSetDirectly()) + { + logger.debug("checking permission :" + p); + assertTrue("permission is missing:" + p, destPerm.contains(p)); + } + } + } + finally + { + endTransaction(); + } + } + private TransferTarget createTransferTarget(String name) { diff --git a/source/java/org/alfresco/repo/transfer/manifest/ManifestModel.java b/source/java/org/alfresco/repo/transfer/manifest/ManifestModel.java index a05fdd57d8..08f1a62217 100644 --- a/source/java/org/alfresco/repo/transfer/manifest/ManifestModel.java +++ b/source/java/org/alfresco/repo/transfer/manifest/ManifestModel.java @@ -30,6 +30,7 @@ public interface ManifestModel extends TransferModel static final String LOCALNAME_HEADER_CREATED_DATE = "createdDate"; static final String LOCALNAME_HEADER_NODE_COUNT = "nodeCount"; static final String LOCALNAME_HEADER_SYNC = "sync"; + static final String LOCALNAME_HEADER_RONLY = "readOnly"; static final String LOCALNAME_HEADER_REPOSITORY_ID = "repositoryId"; static final String LOCALNAME_ELEMENT_NODES = "nodes"; static final String LOCALNAME_ELEMENT_NODE = "node"; @@ -53,6 +54,8 @@ public interface ManifestModel extends TransferModel static final String LOCALNAME_ELEMENT_VALUE_SERIALIZED = "serializedValue"; static final String LOCALNAME_ELEMENT_MLVALUE = "mlvalue"; static final String LOCALNAME_ELEMENT_CONTENT_HEADER = "content"; + static final String LOCALNAME_ELEMENT_ACL = "acl"; + static final String LOCALNAME_ELEMENT_ACL_PERMISSION = "permission"; // Manifest file prefix static final String MANIFEST_PREFIX = "xfer"; diff --git a/source/java/org/alfresco/repo/transfer/manifest/TransferManifestHeader.java b/source/java/org/alfresco/repo/transfer/manifest/TransferManifestHeader.java index 8881712191..b02c90e131 100644 --- a/source/java/org/alfresco/repo/transfer/manifest/TransferManifestHeader.java +++ b/source/java/org/alfresco/repo/transfer/manifest/TransferManifestHeader.java @@ -32,6 +32,7 @@ public class TransferManifestHeader private int nodeCount; private String repositoryId; private boolean isSync; + private boolean isReadOnly; public void setCreatedDate(Date createDate) { @@ -87,5 +88,15 @@ public class TransferManifestHeader return isSync; } + public void setReadOnly(boolean isReadOnly) + { + this.isReadOnly = isReadOnly; + } + + public boolean isReadOnly() + { + return isReadOnly; + } + } diff --git a/source/java/org/alfresco/repo/transfer/manifest/TransferManifestNodeFactoryImpl.java b/source/java/org/alfresco/repo/transfer/manifest/TransferManifestNodeFactoryImpl.java index 99c187000f..59df1f7f7a 100644 --- a/source/java/org/alfresco/repo/transfer/manifest/TransferManifestNodeFactoryImpl.java +++ b/source/java/org/alfresco/repo/transfer/manifest/TransferManifestNodeFactoryImpl.java @@ -18,12 +18,18 @@ */ package org.alfresco.repo.transfer.manifest; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; + import org.alfresco.model.ContentModel; 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.Path; import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.security.AccessPermission; +import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.cmr.transfer.TransferException; import org.alfresco.service.namespace.RegexQNamePattern; @@ -36,6 +42,7 @@ import org.alfresco.service.namespace.RegexQNamePattern; public class TransferManifestNodeFactoryImpl implements TransferManifestNodeFactory { private NodeService nodeService; + private PermissionService permissionService; public void init() { @@ -113,6 +120,28 @@ public class TransferManifestNodeFactoryImpl implements TransferManifestNodeFact node.setTargetAssocs(nodeService.getTargetAssocs(nodeRef, RegexQNamePattern.MATCH_ALL )); node.setSourceAssocs(nodeService.getSourceAssocs(nodeRef, RegexQNamePattern.MATCH_ALL)); + boolean inherit = permissionService.getInheritParentPermissions(nodeRef); + + ManifestAccessControl acl = new ManifestAccessControl(); + acl.setInherited(inherit); + node.setAccessControl(acl); + + Set permissions = permissionService.getAllSetPermissions(nodeRef); + + List mps = new ArrayList(permissions.size()); + for(AccessPermission permission : permissions) + { + if(permission.isSetDirectly()) + { + ManifestPermission mp = new ManifestPermission(); + mp.setStatus(permission.getAccessStatus().toString()); + mp.setAuthority(permission.getAuthority()); + mp.setPermission(permission.getPermission()); + mps.add(mp); + } + } + acl.setPermissions(mps); + return node; } } @@ -127,4 +156,14 @@ public class TransferManifestNodeFactoryImpl implements TransferManifestNodeFact { return nodeService; } + + public void setPermissionService(PermissionService permissionService) + { + this.permissionService = permissionService; + } + + public PermissionService getPermissionService() + { + return permissionService; + } } diff --git a/source/java/org/alfresco/repo/transfer/manifest/TransferManifestNormalNode.java b/source/java/org/alfresco/repo/transfer/manifest/TransferManifestNormalNode.java index 840443a58b..0a8660baea 100644 --- a/source/java/org/alfresco/repo/transfer/manifest/TransferManifestNormalNode.java +++ b/source/java/org/alfresco/repo/transfer/manifest/TransferManifestNormalNode.java @@ -49,6 +49,7 @@ public class TransferManifestNormalNode implements TransferManifestNode private List sourceAssocs; private List targetAssocs; private Path parentPath; + private ManifestAccessControl accessControl; public void setNodeRef(NodeRef nodeRef) { @@ -79,29 +80,6 @@ public class TransferManifestNormalNode implements TransferManifestNode { return properties; } -// -// /** -// * Gets the property data type -// * -// * @param propertyName name of property -// * @return data type of named property -// */ -// public DataTypeDefinition getPropertyDataType(QName propertyName); -// -// /** -// * @return the aspects of this node -// */ -// public Set getNodeAspects(); -// -// /** -// * @return true => the node inherits permissions from its parent -// */ -// public boolean getInheritPermissions(); -// -// /** -// * @return the permissions applied to this node -// */ -// public List getAccessControlEntries(); public void setProperties(Map properties) { @@ -188,4 +166,14 @@ public class TransferManifestNormalNode implements TransferManifestNode return primaryParentAssoc; } + public void setAccessControl(ManifestAccessControl accessControl) + { + this.accessControl = accessControl; + } + + public ManifestAccessControl getAccessControl() + { + return accessControl; + } + } diff --git a/source/java/org/alfresco/repo/transfer/manifest/XMLTransferManifestReader.java b/source/java/org/alfresco/repo/transfer/manifest/XMLTransferManifestReader.java index 302c24ba91..45bf8e8fca 100644 --- a/source/java/org/alfresco/repo/transfer/manifest/XMLTransferManifestReader.java +++ b/source/java/org/alfresco/repo/transfer/manifest/XMLTransferManifestReader.java @@ -312,6 +312,29 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content ContentData contentHeader = new ContentData(contentURL, mimetype, size.longValue(), encoding, locale); props.put("contentHeader", contentHeader); } + else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_ACL)) + { + String isInherited = (String)atts.getValue("", "isInherited"); + ManifestAccessControl acl = new ManifestAccessControl(); + + if("TRUE".equalsIgnoreCase(isInherited)) + { + acl.setInherited(true); + } + props.put("acl", acl); + } + else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_ACL_PERMISSION)) + { + + String authority = (String)atts.getValue("", "authority"); + String permission = (String)atts.getValue("", "permission"); + String status = (String)atts.getValue("", "status"); + ManifestPermission perm = new ManifestPermission(); + perm.setAuthority(authority); + perm.setPermission(permission); + perm.setStatus(status); + props.put("permission", perm); + } } // if transfer URI } // startElement @@ -392,6 +415,11 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content TransferManifestHeader header = (TransferManifestHeader)props.get("header"); header.setSync(true); } + else if(elementName.equals(ManifestModel.LOCALNAME_HEADER_RONLY)) + { + TransferManifestHeader header = (TransferManifestHeader)props.get("header"); + header.setReadOnly(true); + } else if(elementName.equals(ManifestModel.LOCALNAME_HEADER_REPOSITORY_ID)) { TransferManifestHeader header = (TransferManifestHeader)props.get("header"); @@ -574,6 +602,20 @@ public class XMLTransferManifestReader extends DefaultHandler implements Content ContentData data = (ContentData)props.get("contentHeader"); props.put("value", data); } + else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_ACL)) + { + TransferManifestNormalNode node = (TransferManifestNormalNode)props.get("node"); + ManifestAccessControl acl = (ManifestAccessControl)props.get("acl"); + node.setAccessControl(acl); + } + else if(elementName.equals(ManifestModel.LOCALNAME_ELEMENT_ACL_PERMISSION)) + { + ManifestAccessControl acl = (ManifestAccessControl)props.get("acl"); + ManifestPermission permission = (ManifestPermission)props.get("permission"); + acl.addPermission(permission); + } + + } // if transfer URI } // end element diff --git a/source/java/org/alfresco/repo/transfer/manifest/XMLTransferManifestWriter.java b/source/java/org/alfresco/repo/transfer/manifest/XMLTransferManifestWriter.java index 883221e6ab..562a008154 100644 --- a/source/java/org/alfresco/repo/transfer/manifest/XMLTransferManifestWriter.java +++ b/source/java/org/alfresco/repo/transfer/manifest/XMLTransferManifestWriter.java @@ -168,6 +168,17 @@ public class XMLTransferManifestWriter implements TransferManifestWriter ManifestModel.LOCALNAME_HEADER_SYNC, PREFIX + ":" + ManifestModel.LOCALNAME_HEADER_SYNC); } + + if(header.isReadOnly()) + { + // Is this a read only transfer + writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI, + ManifestModel.LOCALNAME_HEADER_RONLY, PREFIX + ":" + + ManifestModel.LOCALNAME_HEADER_RONLY, EMPTY_ATTRIBUTES); + writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI, + ManifestModel.LOCALNAME_HEADER_RONLY, PREFIX + ":" + + ManifestModel.LOCALNAME_HEADER_RONLY); + } // End Header @@ -259,6 +270,8 @@ public class XMLTransferManifestWriter implements TransferManifestWriter writeTargetAssocs(node.getTargetAssocs()); writeSourceAssocs(node.getSourceAssocs()); + + writeAccessControl(node.getAccessControl()); writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI, ManifestModel.LOCALNAME_ELEMENT_NODE, PREFIX + ":" @@ -654,4 +667,49 @@ public class XMLTransferManifestWriter implements TransferManifestWriter ManifestModel.LOCALNAME_ELEMENT_ASSOC, PREFIX + ":" + ManifestModel.LOCALNAME_ELEMENT_ASSOC); } + + private void writeAccessControl(ManifestAccessControl acl) throws SAXException + { + if(acl != null) + { + AttributesImpl attributes = new AttributesImpl(); + attributes.addAttribute(TransferModel.TRANSFER_MODEL_1_0_URI, "isInherited", "isInherited", "boolean", + acl.isInherited()?"true":"false"); + + writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI, + ManifestModel.LOCALNAME_ELEMENT_ACL, PREFIX + ":" + + ManifestModel.LOCALNAME_ELEMENT_ACL, attributes); + + if(acl.getPermissions() != null) + { + for(ManifestPermission permission : acl.getPermissions()) + { + writePermission(permission); + } + } + + writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI, + ManifestModel.LOCALNAME_ELEMENT_ACL, PREFIX + ":" + + ManifestModel.LOCALNAME_ELEMENT_ACL); + } + } + + private void writePermission(ManifestPermission permission) throws SAXException + { + AttributesImpl attributes = new AttributesImpl(); + attributes.addAttribute(TransferModel.TRANSFER_MODEL_1_0_URI, "status", "status", "String", + permission.getStatus()); + attributes.addAttribute(TransferModel.TRANSFER_MODEL_1_0_URI, "authority", "authority", "String", + permission.getAuthority()); + attributes.addAttribute(TransferModel.TRANSFER_MODEL_1_0_URI, "permission", "permission", "String", + permission.getPermission()); + + writer.startElement(TransferModel.TRANSFER_MODEL_1_0_URI, + ManifestModel.LOCALNAME_ELEMENT_ACL_PERMISSION, PREFIX + ":" + + ManifestModel.LOCALNAME_ELEMENT_ACL_PERMISSION, attributes); + + writer.endElement(TransferModel.TRANSFER_MODEL_1_0_URI, + ManifestModel.LOCALNAME_ELEMENT_ACL_PERMISSION, PREFIX + ":" + + ManifestModel.LOCALNAME_ELEMENT_ACL_PERMISSION); + } } diff --git a/source/java/org/alfresco/service/cmr/transfer/TransferDefinition.java b/source/java/org/alfresco/service/cmr/transfer/TransferDefinition.java index 9c3470b1bb..58302ed57d 100644 --- a/source/java/org/alfresco/service/cmr/transfer/TransferDefinition.java +++ b/source/java/org/alfresco/service/cmr/transfer/TransferDefinition.java @@ -47,9 +47,20 @@ public class TransferDefinition implements Serializable // Which nodes to deploy private Set nodes; - - // is complete + + /** + * isSync specifies whether the list of nodes is to be sync'ed. If sync then the transfer + * machinery can determine by the absence of a node or association in the transfer that the missing + * nodes should be deleted on the destination. + * Else with a non sync transfer then the archive node ref is required to remote a node on the destination. + */ private boolean isSync = false; + + /** + * isReadOnly specifies whether the transferred nodes should be editable on the destination system. + */ + private boolean isReadOnly = false; + /** * Set which nodes to transfer @@ -96,4 +107,20 @@ public class TransferDefinition implements Serializable { return isSync; } + + /** + * isReadOnly specifies whether the transferred nodes should be editable on the destination system. + */ + public void setReadOnly(boolean isReadOnly) + { + this.isReadOnly = isReadOnly; + } + + /** + * isReadOnly specifies whether the transferred nodes should be editable on the destination system. + */ + public boolean isReadOnly() + { + return isReadOnly; + } }