diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml index 0ee64536e6..8aeaa34a0a 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/rm-action-context.xml @@ -759,6 +759,7 @@ + diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/CreateRecordAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/CreateRecordAction.java index f8174a1059..e7d091eea5 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/CreateRecordAction.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/dm/CreateRecordAction.java @@ -211,8 +211,11 @@ public class CreateRecordAction extends AuditableActionExecuterAbstractBase hideRecord = hideRecordValue.booleanValue(); } - // create record from existing document - recordService.createRecord(filePlan, actionedUponNodeRef, !hideRecord); + synchronized (this) + { + // create record from existing document + recordService.createRecord(filePlan, actionedUponNodeRef, !hideRecord); + } } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveLinkFileToBaseAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveLinkFileToBaseAction.java index b879c733a0..9b8a11a0a9 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveLinkFileToBaseAction.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/CopyMoveLinkFileToBaseAction.java @@ -11,16 +11,18 @@ import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.repo.action.ParameterDefinitionImpl; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ParameterDefinition; import org.alfresco.service.cmr.dictionary.DataTypeDefinition; import org.alfresco.service.cmr.model.FileFolderService; import org.alfresco.service.cmr.model.FileNotFoundException; -import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.QName; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.dao.ConcurrencyFailureException; import org.springframework.util.StringUtils; /** @@ -33,6 +35,9 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr { private static Log logger = LogFactory.getLog(CopyMoveLinkFileToBaseAction.class); + /** Retrying transaction helper */ + private RetryingTransactionHelper retryingTransactionHelper; + /** action parameters */ public static final String PARAM_DESTINATION_RECORD_FOLDER = "destinationRecordFolder"; public static final String PARAM_PATH = "path"; @@ -89,6 +94,14 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr this.filePlanService = filePlanService; } + /** + * @param retryingTransactionHelper retrying transaction helper + */ + public void setRetryingTransactionHelper(RetryingTransactionHelper retryingTransactionHelper) + { + this.retryingTransactionHelper = retryingTransactionHelper; + } + /** * @see org.alfresco.module.org_alfresco_module_rm.action.RMActionExecuterAbstractBase#addParameterDefinitions(java.util.List) */ @@ -103,7 +116,7 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr * @see org.alfresco.repo.action.executer.ActionExecuterAbstractBase#executeImpl(org.alfresco.service.cmr.action.Action, org.alfresco.service.cmr.repository.NodeRef) */ @Override - protected void executeImpl(final Action action, final NodeRef actionedUponNodeRef) + protected synchronized void executeImpl(final Action action, final NodeRef actionedUponNodeRef) { String actionName = action.getActionDefinitionName(); if (isOkToProceedWithAction(actionedUponNodeRef, actionName)) @@ -125,8 +138,25 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr NodeRef recordFolder = (NodeRef)action.getParameterValue(PARAM_DESTINATION_RECORD_FOLDER); if (recordFolder == null) { - // get the reference to the record folder based on the relative path - recordFolder = createOrResolvePath(action, actionedUponNodeRef, targetIsUnfiledRecords); + final boolean finaltargetIsUnfiledRecords = targetIsUnfiledRecords; + recordFolder = retryingTransactionHelper.doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + public NodeRef execute() throws Throwable + { + NodeRef result = null; + try + { + // get the reference to the record folder based on the relative path + result = createOrResolvePath(action, actionedUponNodeRef, finaltargetIsUnfiledRecords); + } + catch (DuplicateChildNodeNameException ex) + { + throw new ConcurrencyFailureException("Cannot create or resolve path.", ex); + } + + return result; + } + }, false, true); } // now we have the reference to the target folder we can do some final checks to see if the action is valid @@ -140,18 +170,21 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr { try { - if(getMode() == CopyMoveLinkFileToActionMode.MOVE) - { - fileFolderService.move(actionedUponNodeRef, finalRecordFolder, null); - } - else if(getMode() == CopyMoveLinkFileToActionMode.COPY) - { - fileFolderService.copy(actionedUponNodeRef, finalRecordFolder, null); - } - else if(getMode() == CopyMoveLinkFileToActionMode.LINK) - { - getRecordService().link(actionedUponNodeRef, finalRecordFolder); - } + synchronized (this) + { + if(getMode() == CopyMoveLinkFileToActionMode.MOVE) + { + fileFolderService.move(actionedUponNodeRef, finalRecordFolder, null); + } + else if(getMode() == CopyMoveLinkFileToActionMode.COPY) + { + fileFolderService.copy(actionedUponNodeRef, finalRecordFolder, null); + } + else if(getMode() == CopyMoveLinkFileToActionMode.LINK) + { + getRecordService().link(actionedUponNodeRef, finalRecordFolder); + } + } } catch (FileNotFoundException fileNotFound) { @@ -333,19 +366,7 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr */ private NodeRef getChild(NodeRef parent, String childName) { - NodeRef child = null; - List children = getNodeService().getChildAssocs(parent); - for (ChildAssociationRef childAssoc : children) - { - NodeRef childNodeRef = childAssoc.getChildRef(); - String existingChildName = (String)getNodeService().getProperty(childNodeRef, ContentModel.PROP_NAME); - if(existingChildName.equals(childName)) - { - child = childNodeRef; - break; - } - } - return child; + return getNodeService().getChildByName(parent, ContentModel.ASSOC_CONTAINS, childName); } /** @@ -365,22 +386,31 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr @Override public NodeRef doWork() { - NodeRef child = null; - if(targetisUnfiledRecords) + // double check that the child hasn't been created by another thread + NodeRef child = getChild(parent, childName); + if (child == null) { - child = fileFolderService.create(parent, childName, RecordsManagementModel.TYPE_UNFILED_RECORD_FOLDER).getNodeRef(); - } - else if(lastAsFolder) - { - child = getRecordFolderService().createRecordFolder(parent, childName); - } - else - { - if(RecordsManagementModel.TYPE_RECORD_FOLDER.equals(getNodeService().getType(parent))) + if(targetisUnfiledRecords) { - throw new AlfrescoRuntimeException("Unable to execute " + action.getActionDefinitionName() + " action, because the destination path could not be created."); + // create unfiled folder + child = fileFolderService.create(parent, childName, RecordsManagementModel.TYPE_UNFILED_RECORD_FOLDER).getNodeRef(); + } + else if(lastAsFolder) + { + // create record folder + child = getRecordFolderService().createRecordFolder(parent, childName); + } + else + { + // ensure we are not trying to create a record categtory in a record folder + if(RecordsManagementModel.TYPE_RECORD_FOLDER.equals(getNodeService().getType(parent))) + { + throw new AlfrescoRuntimeException("Unable to execute " + action.getActionDefinitionName() + " action, because the destination path has a record category within a record folder."); + } + + // create record category + child = filePlanService.createRecordCategory(parent, childName); } - child = filePlanService.createRecordCategory(parent, childName); } return child; } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJob.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJob.java index 4f20ee4986..77bfa96e95 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJob.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/job/RecordsManagementJob.java @@ -25,6 +25,8 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; import org.quartz.Job; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; @@ -39,6 +41,8 @@ import org.quartz.JobExecutionException; */ public class RecordsManagementJob implements Job { + private static Log logger = LogFactory.getLog(RecordsManagementJob.class); + private static final long DEFAULT_TIME = 30000L; private JobLockService jobLockService; @@ -108,7 +112,18 @@ public class RecordsManagementJob implements Job } finally { - jobLockService.releaseLock(lockToken, getLockQName()); + try + { + jobLockService.releaseLock(lockToken, getLockQName()); + } + catch (LockAcquisitionException e) + { + // Ignore + if (logger.isDebugEnabled()) + { + logger.debug("Lock release failed: " + getLockQName() + ": " + lockToken + "(" + e.getMessage() + ")"); + } + } } } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java index 862335a0c0..299af55ad3 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/jscript/app/JSONConversionComponent.java @@ -18,6 +18,10 @@ */ package org.alfresco.module.org_alfresco_module_rm.jscript.app; +import static org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel.READ_RECORDS; +import static org.alfresco.repo.security.authentication.AuthenticationUtil.runAsSystem; +import static org.alfresco.service.cmr.security.AccessStatus.ALLOWED; + import java.util.ArrayList; import java.util.HashMap; import java.util.List; @@ -347,10 +351,10 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JS rootJSONObject.put("originatingLocationPath", originatingLocationPath.toString()); } } - + /** * Helper method to get the display path. - * + * * @param nodeRef node reference * @return String display path */ @@ -375,7 +379,7 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JS @SuppressWarnings("unchecked") private JSONObject setRmNodeValues(final NodeRef nodeRef, final boolean useShortQName) { - JSONObject rmNodeValues = new JSONObject(); + JSONObject rmNodeValues = new JSONObject(); // UI convenience type rmNodeValues.put("uiType", getUIType(nodeRef)); @@ -390,6 +394,23 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JS { rmNodeValues.put("primaryParentNodeRef", assoc.getParentRef().toString()); } + + // File plan node reference + NodeRef filePlan = getFilePlan(nodeRef); + if (permissionService.hasPermission(filePlan, READ_RECORDS).equals(ALLOWED)) + { + rmNodeValues.put("filePlan", filePlan.toString()); + + // Unfiled container node reference + NodeRef unfiledRecordContainer = filePlanService.getUnfiledContainer(filePlan); + if (unfiledRecordContainer != null) + { + rmNodeValues.put("unfiledRecordContainer", unfiledRecordContainer.toString()); + rmNodeValues.put("properties", propertiesToJSON(unfiledRecordContainer, nodeService.getProperties(unfiledRecordContainer), useShortQName)); + QName type = fileFolderService.getFileInfo(unfiledRecordContainer).getType(); + rmNodeValues.put("type", useShortQName ? type.toPrefixString(namespaceService) : type.toString()); + } + } Map values = AuthenticationUtil.runAsSystem(new RunAsWork>() { @@ -426,6 +447,23 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JS return rmNodeValues; } + /** + * Helper method to get the file plan as a system user for the given node + * + * @param nodeRef The node reference + * @return The file plan where the node is in + */ + private NodeRef getFilePlan(final NodeRef nodeRef) + { + return runAsSystem(new RunAsWork() + { + public NodeRef doWork() + { + return filePlanService.getFilePlan(nodeRef); + } + }); + } + @SuppressWarnings("unchecked") private void setIndicators(JSONObject rmNodeValues, NodeRef nodeRef) { diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/ExtendedSecurityAspect.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/ExtendedSecurityAspect.java index 3ed8750cd2..a35d5cdd82 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/ExtendedSecurityAspect.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/model/rma/aspect/ExtendedSecurityAspect.java @@ -18,22 +18,14 @@ */ package org.alfresco.module.org_alfresco_module_rm.model.rma.aspect; -import java.util.Set; - import org.alfresco.module.org_alfresco_module_rm.model.BaseBehaviourBean; import org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService; import org.alfresco.repo.copy.CopyBehaviourCallback; import org.alfresco.repo.copy.CopyDetails; import org.alfresco.repo.copy.DoNothingCopyBehaviourCallback; -import org.alfresco.repo.node.NodeServicePolicies; -import org.alfresco.repo.policy.Behaviour.NotificationFrequency; import org.alfresco.repo.policy.annotation.Behaviour; import org.alfresco.repo.policy.annotation.BehaviourBean; import org.alfresco.repo.policy.annotation.BehaviourKind; -import org.alfresco.repo.security.authentication.AuthenticationUtil; -import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; -import org.alfresco.service.cmr.repository.ChildAssociationRef; -import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.QName; /** @@ -46,8 +38,7 @@ import org.alfresco.service.namespace.QName; ( defaultType = "rma:extendedSecurity" ) -public class ExtendedSecurityAspect extends BaseBehaviourBean - implements NodeServicePolicies.OnMoveNodePolicy +public class ExtendedSecurityAspect extends BaseBehaviourBean { /** extended security service */ protected ExtendedSecurityService extendedSecurityService; @@ -74,40 +65,4 @@ public class ExtendedSecurityAspect extends BaseBehaviourBean { return new DoNothingCopyBehaviourCallback(); } - - /** - * Update extended security when moving a node. - * - * @see org.alfresco.repo.node.NodeServicePolicies.OnMoveNodePolicy#onMoveNode(org.alfresco.service.cmr.repository.ChildAssociationRef, org.alfresco.service.cmr.repository.ChildAssociationRef) - */ - @Override - @Behaviour - ( - kind = BehaviourKind.CLASS, - notificationFrequency = NotificationFrequency.TRANSACTION_COMMIT - ) - public void onMoveNode(final ChildAssociationRef origAssoc, final ChildAssociationRef newAssoc) - { - AuthenticationUtil.runAsSystem(new RunAsWork() - { - @Override - public Void doWork() - { - NodeRef record = newAssoc.getChildRef(); - NodeRef newParent = newAssoc.getParentRef(); - NodeRef oldParent = origAssoc.getParentRef(); - - Set readers = extendedSecurityService.getExtendedReaders(record); - Set writers = extendedSecurityService.getExtendedWriters(record); - - extendedSecurityService.addExtendedSecurity(newParent, readers, writers); - extendedSecurityService.removeExtendedSecurity(oldParent, readers, writers); - - return null; - } - }); - } - - - } diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java index a5d2bd8615..e79acc7b42 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/record/RecordServiceImpl.java @@ -1247,7 +1247,7 @@ public class RecordServiceImpl extends BaseBehaviourBean * @see org.alfresco.module.org_alfresco_module_rm.disposableitem.RecordService#isFiled(org.alfresco.service.cmr.repository.NodeRef) */ @Override - public boolean isFiled(NodeRef nodeRef) + public boolean isFiled(final NodeRef nodeRef) { ParameterCheck.mandatory("nodeRef", nodeRef); @@ -1255,7 +1255,13 @@ public class RecordServiceImpl extends BaseBehaviourBean if (isRecord(nodeRef)) { - result = (null != nodeService.getProperty(nodeRef, PROP_DATE_FILED)); + result = AuthenticationUtil.runAsSystem(new RunAsWork() + { + public Boolean doWork() throws Exception + { + return (null != nodeService.getProperty(nodeRef, PROP_DATE_FILED)); + } + }); } return result; diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/recordfolder/RecordFolderServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/recordfolder/RecordFolderServiceImpl.java index eb59072ab3..e432769e1b 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/recordfolder/RecordFolderServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/recordfolder/RecordFolderServiceImpl.java @@ -32,6 +32,8 @@ import org.alfresco.module.org_alfresco_module_rm.fileplan.FilePlanService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.NamespaceService; @@ -146,7 +148,7 @@ public class RecordFolderServiceImpl extends ServiceBaseImpl * @see org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService#isRecordFolderClosed(NodeRef) */ @Override - public boolean isRecordFolderClosed(NodeRef nodeRef) + public boolean isRecordFolderClosed(final NodeRef nodeRef) { ParameterCheck.mandatory("nodeRef", nodeRef); @@ -156,7 +158,13 @@ public class RecordFolderServiceImpl extends ServiceBaseImpl throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_RECORD_FOLDER_EXPECTED)); } - return ((Boolean) nodeService.getProperty(nodeRef, PROP_IS_CLOSED)).booleanValue(); + return AuthenticationUtil.runAsSystem(new RunAsWork() + { + public Boolean doWork() throws Exception + { + return ((Boolean) nodeService.getProperty(nodeRef, PROP_IS_CLOSED)); + } + }); } @Override diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java index b9c65bcf43..4468fc183e 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/role/FilePlanRoleServiceImpl.java @@ -40,6 +40,7 @@ import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamic import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority; import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.authority.RMAuthority; +import org.alfresco.service.cmr.repository.DuplicateChildNodeNameException; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.alfresco.service.cmr.repository.StoreRef; @@ -835,7 +836,14 @@ public class FilePlanRoleServiceImpl implements FilePlanRoleService, if (!getAllAssignedToRole(filePlan, role).contains(authorityName)) { String roleAuthority = authorityService.getName(AuthorityType.GROUP, getFullRoleName(role, filePlan)); - authorityService.addAuthority(roleAuthority, authorityName); + try + { + authorityService.addAuthority(roleAuthority, authorityName); + } + catch (DuplicateChildNodeNameException exception) + { + // ignore, because the work has already been performed + } } return null; diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImpl.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImpl.java index 099904fa9b..eeee3850e4 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImpl.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/security/ExtendedSecurityServiceImpl.java @@ -20,7 +20,6 @@ package org.alfresco.module.org_alfresco_module_rm.security; import java.io.Serializable; import java.util.HashMap; -import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; @@ -32,7 +31,6 @@ import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; import org.alfresco.module.org_alfresco_module_rm.util.ServiceBaseImpl; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.security.AuthorityType; import org.alfresco.service.cmr.security.PermissionService; import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.RegexQNamePattern; @@ -48,10 +46,6 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl implements ExtendedSecurityService, RecordsManagementModel { - /** Ad hoc properties used for reference counting */ - private static final QName PROP_EXTENDED_READER_ROLE = QName.createQName(RM_URI, "extendedReaderRole"); - private static final QName PROP_EXTENDED_WRITER_ROLE = QName.createQName(RM_URI, "extendedWriterRole"); - /** File plan service */ private FilePlanService filePlanService; @@ -74,7 +68,7 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl this.filePlanRoleService = filePlanRoleService; } - /** + /** * @see org.alfresco.module.org_alfresco_module_rm.security.ExtendedSecurityService#hasExtendedSecurity(org.alfresco.service.cmr.repository.NodeRef) */ public boolean hasExtendedSecurity(NodeRef nodeRef) @@ -139,6 +133,9 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl if (nodeRef != null) { addExtendedSecurityImpl(nodeRef, readers, writers, applyToParents); + + // add to the extended security roles + addExtendedSecurityRoles(nodeRef, readers, writers); } } @@ -151,36 +148,36 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl * @param applyToParents */ @SuppressWarnings("unchecked") - private void addExtendedSecurityImpl(NodeRef nodeRef, Set readers, Set writers, boolean applyToParents) + private void addExtendedSecurityImpl(final NodeRef nodeRef, Set readers, Set writers, boolean applyToParents) { ParameterCheck.mandatory("nodeRef", nodeRef); ParameterCheck.mandatory("applyToParents", applyToParents); - // add the aspect if missing - if (!nodeService.hasAspect(nodeRef, ASPECT_EXTENDED_SECURITY)) - { - nodeService.addAspect(nodeRef, ASPECT_EXTENDED_SECURITY, null); - } + // get the properties + final Map properties = nodeService.getProperties(nodeRef); // update the readers map if (readers != null && readers.size() != 0) { // get reader map - Map readersMap = (Map)nodeService.getProperty(nodeRef, PROP_READERS); + Map readersMap = (Map)properties.get(PROP_READERS); // set the readers property (this will in turn apply the aspect if required) - nodeService.setProperty(nodeRef, PROP_READERS, (Serializable)addToMap(readersMap, readers)); + properties.put(PROP_READERS, (Serializable)addToMap(readersMap, readers)); } // update the writers map - if (writers != null && writers.size() != 0) - { - // get writer map - Map writersMap = (Map)nodeService.getProperty(nodeRef, PROP_WRITERS); + if (writers != null && writers.size() != 0) + { + // get writer map + Map writersMap = (Map)properties.get(PROP_WRITERS); - // set the writers property (this will in turn apply the aspect if required) - nodeService.setProperty(nodeRef, PROP_WRITERS, (Serializable)addToMap(writersMap, writers)); - } + // set the writers property (this will in turn apply the aspect if required) + properties.put(PROP_WRITERS, (Serializable)addToMap(writersMap, writers)); + } + + // set properties + nodeService.setProperties(nodeRef, properties); // apply the readers to any renditions of the content if (isRecord(nodeRef)) @@ -192,21 +189,6 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl addExtendedSecurityImpl(child, readers, writers, false); } } - - // add to the extended security roles - addExtendedSecurityRoles(nodeRef, readers, writers); - - if (applyToParents) - { - // apply the extended readers up the file plan primary hierarchy - NodeRef parent = nodeService.getPrimaryParent(nodeRef).getParentRef(); - if (parent != null && - filePlanService.isFilePlanComponent(parent)) - { - addExtendedSecurityImpl(parent, readers, null, applyToParents); - addExtendedSecurityImpl(parent, writers, null, applyToParents); - } - } } /** @@ -219,43 +201,29 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl { NodeRef filePlan = filePlanService.getFilePlan(nodeRef); - addExtendedSecurityRolesImpl(filePlan, readers, PROP_EXTENDED_READER_ROLE, FilePlanRoleService.ROLE_EXTENDED_READERS); - addExtendedSecurityRolesImpl(filePlan, writers, PROP_EXTENDED_WRITER_ROLE, FilePlanRoleService.ROLE_EXTENDED_WRITERS); + addExtendedSecurityRolesImpl(filePlan, readers, FilePlanRoleService.ROLE_EXTENDED_READERS); + addExtendedSecurityRolesImpl(filePlan, writers, FilePlanRoleService.ROLE_EXTENDED_WRITERS); } /** + * Add extended security roles implementation * - * @param filePlan - * @param authorities - * @param propertyName - * @param roleName + * @param filePlan file plan + * @param authorities authorities + * @param roleName role name */ - @SuppressWarnings("unchecked") - private void addExtendedSecurityRolesImpl(NodeRef filePlan, Set authorities, QName propertyName, String roleName) + private void addExtendedSecurityRolesImpl(NodeRef filePlan, Set authorities, String roleName) { if (authorities != null) { - // get the reference count - Map referenceCountMap = (Map)nodeService.getProperty(filePlan, propertyName); - - // set of assigned authorities - Set assignedAuthorities = new HashSet(authorities.size()); - for (String authority : authorities) { - if ((!authority.equals(PermissionService.ALL_AUTHORITIES) && - !authority.equals(PermissionService.OWNER_AUTHORITY)) && - !AuthorityType.ROLE.equals(AuthorityType.getAuthorityType(authority)) && - (referenceCountMap == null || !referenceCountMap.containsKey(authority))) + if ((!authority.equals(PermissionService.ALL_AUTHORITIES) && !authority.equals(PermissionService.OWNER_AUTHORITY))) { // add the authority to the role filePlanRoleService.assignRoleToAuthority(filePlan, roleName, authority); - assignedAuthorities.add(authority); } } - - // update the reference count - nodeService.setProperty(filePlan, propertyName, (Serializable)addToMap(referenceCountMap, assignedAuthorities)); } } diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/IssueTestSuite.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/IssueTestSuite.java index e3fd8e72d5..510bcb3c9e 100755 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/IssueTestSuite.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/IssueTestSuite.java @@ -46,7 +46,9 @@ import org.junit.runners.Suite.SuiteClasses; RM1814Test.class, RM978Test.class, RM1887Test.class, - RM1914Test.class + RM1914Test.class, + //RM2190Test.class, + RM2192Test.class }) public class IssueTestSuite { diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2072Test.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2072Test.java new file mode 100644 index 0000000000..37cf0048aa --- /dev/null +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2072Test.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2005-2014 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 . + */ +package org.alfresco.module.org_alfresco_module_rm.test.integration.issue; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.alfresco.model.ContentModel; +import org.alfresco.module.org_alfresco_module_rm.action.dm.CreateRecordAction; +import org.alfresco.module.org_alfresco_module_rm.action.impl.FileToAction; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.rule.Rule; +import org.alfresco.service.cmr.rule.RuleService; +import org.alfresco.service.cmr.rule.RuleType; + + +/** + * System test for RM-2072: Concurrency exceptions and deadlocks on Records Management "File to" rule + * + * @author Roy Wetherall + * @since 2.2.1.1 + */ +public class RM2072Test extends BaseRMTestCase +{ + private static final int NUMBER_OF_BATCHES = 1; + private static final int NUMBER_IN_BATCH = 500; + + private RuleService ruleService; + private NodeRef ruleFolder; + + @Override + protected void initServices() + { + super.initServices(); + + ruleService = (RuleService)applicationContext.getBean("RuleService"); + } + + @Override + protected boolean isCollaborationSiteTest() + { + return true; + } + + @Override + protected boolean isRecordTest() + { + return true; + } + + /** + * Given that I have auto declare configured + * And that I have auto file configured to a path where only the record folder needs to be created + * When I add lots of documents in the same transaction + * Then the rules should fire + * And the documents should be filed in the new record folder + */ + public void testAutoDeclareAutoFileCreateRecordFolderOnly() throws Exception + { + doTestInTransaction(new Test() + { + @Override + public Void run() + { + // create the folder + ruleFolder = fileFolderService.create(documentLibrary, "mytestfolder", ContentModel.TYPE_FOLDER).getNodeRef(); + + // create record category + NodeRef nodeRefA = filePlanService.createRecordCategory(filePlan, "A"); + NodeRef nodeRefB = filePlanService.createRecordCategory(nodeRefA, "B"); + filePlanService.createRecordCategory(nodeRefB, "C"); + + Action action = actionService.createAction(CreateRecordAction.NAME); + action.setParameterValue(CreateRecordAction.PARAM_FILE_PLAN, filePlan); + + Rule rule = new Rule(); + rule.setRuleType(RuleType.INBOUND); + rule.setTitle("my rule"); + rule.setAction(action); + rule.setExecuteAsynchronously(true); + ruleService.saveRule(ruleFolder, rule); + + Action fileAction = actionService.createAction(FileToAction.NAME); + fileAction.setParameterValue(FileToAction.PARAM_PATH, "/A/B/C/{date.year.long}/{date.month.long}/{date.day.month}"); + fileAction.setParameterValue(FileToAction.PARAM_CREATE_RECORD_PATH, true); + + Rule fileRule = new Rule(); + fileRule.setRuleType(RuleType.INBOUND); + fileRule.setTitle("my rule"); + fileRule.setAction(fileAction); + fileRule.setExecuteAsynchronously(true); + ruleService.saveRule(filePlanService.getUnfiledContainer(filePlan), fileRule); + + return null; + } + + @Override + public void test(Void result) throws Exception + { + assertFalse(ruleService.getRules(ruleFolder).isEmpty()); + } + }); + + List records = new ArrayList(NUMBER_OF_BATCHES*NUMBER_IN_BATCH); + + for (int i = 0; i < NUMBER_OF_BATCHES; i++) + { + final int finali = i; + records.addAll(doTestInTransaction(new Test>() + { + @Override + public List run() throws Exception + { + List records = new ArrayList(NUMBER_IN_BATCH); + for (int j = 0; j < NUMBER_IN_BATCH; j++) + { + int count = (finali+1)*(j+1); + String name = "content" + count + ".txt"; + System.out.println(name + " - creating"); + + NodeRef record = fileFolderService.create(ruleFolder, name, ContentModel.TYPE_CONTENT).getNodeRef(); + records.add(record); + } + return records; + } + })); + } + + try + { + while(!records.isEmpty()) + { + Thread.sleep(1000); + + final Iterator temp = records.iterator(); + doTestInTransaction(new Test() + { + @Override + public Void run() throws Exception + { + while (temp.hasNext()) + { + NodeRef record = temp.next(); + if (nodeService.hasAspect(record, ASPECT_RECORD) && recordService.isFiled(record)) + { + String name = (String) nodeService.getProperty(record, ContentModel.PROP_NAME); + System.out.println(name + " - complete"); + temp.remove(); + } + } + + return null; + } + }); + } + } + catch (Exception exception) + { + exception.printStackTrace(); + throw exception; + } + } +} diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2190Test.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2190Test.java new file mode 100644 index 0000000000..3a298c7bd3 --- /dev/null +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2190Test.java @@ -0,0 +1,201 @@ +package org.alfresco.module.org_alfresco_module_rm.test.integration.issue; + +import static java.util.Arrays.asList; +import static org.alfresco.service.cmr.rule.RuleType.INBOUND; +import static org.alfresco.util.GUID.generate; +import static org.springframework.util.StringUtils.tokenizeToStringArray; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.alfresco.module.org_alfresco_module_rm.action.dm.CreateRecordAction; +import org.alfresco.module.org_alfresco_module_rm.action.impl.FileToAction; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.model.FileInfo; +import org.alfresco.service.cmr.model.FileNotFoundException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.rule.Rule; +import org.alfresco.service.cmr.rule.RuleService; + +/** + * System test for RM-2190: Concurrency exception when upload document to several folders with rules configured to file records + * + * @author Tuna Aksoy + * @since 2.2.1.1 + */ +public class RM2190Test extends BaseRMTestCase +{ + private static final int NUMBER_OF_BATCHES = 1; + private static final int NUMBER_IN_BATCH = 10; + + private static final String PATH = "/111/222/333"; + + private RuleService ruleService; + + private NodeRef rootFolder; + private NodeRef folder1; + private NodeRef folder2; + + @Override + protected void initServices() + { + super.initServices(); + + ruleService = (RuleService) applicationContext.getBean("RuleService"); + } + + @Override + protected boolean isCollaborationSiteTest() + { + return true; + } + + @Override + protected boolean isRecordTest() + { + return true; + } + + public void testUploadDocumentsSimultaneouslyWithRules() + { + doTestInTransaction(new Test() + { + @Override + public Void run() + { + rootFolder = fileFolderService.create(documentLibrary, generate(), TYPE_FOLDER).getNodeRef(); + + Action createAction = actionService.createAction(CreateRecordAction.NAME); + createAction.setParameterValue(CreateRecordAction.PARAM_FILE_PLAN, filePlan); + + Rule declareRule = new Rule(); + declareRule.setRuleType(INBOUND); + declareRule.setTitle(generate()); + declareRule.setAction(createAction); + declareRule.setExecuteAsynchronously(true); + declareRule.applyToChildren(true); + ruleService.saveRule(rootFolder, declareRule); + + folder1 = fileFolderService.create(rootFolder, generate(), TYPE_FOLDER).getNodeRef(); + folder2 = fileFolderService.create(rootFolder, generate(), TYPE_FOLDER).getNodeRef(); + + Action fileAction = actionService.createAction(FileToAction.NAME); + fileAction.setParameterValue(FileToAction.PARAM_PATH, PATH); + fileAction.setParameterValue(FileToAction.PARAM_CREATE_RECORD_PATH, true); + + Rule fileRule = new Rule(); + fileRule.setRuleType(INBOUND); + fileRule.setTitle(generate()); + fileRule.setAction(fileAction); + fileRule.setExecuteAsynchronously(true); + ruleService.saveRule(unfiledContainer, fileRule); + + return null; + } + + @Override + public void test(Void result) throws Exception + { + assertFalse(ruleService.getRules(rootFolder).isEmpty()); + assertFalse(ruleService.getRules(unfiledContainer).isEmpty()); + } + }); + + doTestInTransaction(new Test() + { + @Override + public Void run() throws FileNotFoundException, InterruptedException + { + Thread thread1 = new Thread() + { + public void run() { + List files = addFilesToFolder(folder1); + waitForFilesToBeDeclared(files); + } + }; + + Thread thread2 = new Thread() + { + public void run() { + List files = addFilesToFolder(folder2); + waitForFilesToBeDeclared(files); + } + }; + + thread1.start(); + thread2.start(); + + thread1.join(300000); + thread2.join(300000); + + return null; + } + + @Override + public void test(Void result) throws Exception + { + FileInfo category = fileFolderService.resolveNamePath(filePlan, asList(tokenizeToStringArray(PATH, "/", false, true))); + assertEquals(NUMBER_IN_BATCH * 2, nodeService.getChildAssocs(category.getNodeRef()).size()); + } + }); + } + + private List addFilesToFolder(final NodeRef folder) + { + List records = new ArrayList(NUMBER_OF_BATCHES * NUMBER_IN_BATCH); + + for (int i = 0; i < NUMBER_OF_BATCHES; i++) + { + final int finali = i; + records.addAll(doTestInTransaction(new Test>() + { + @Override + public List run() throws Exception + { + List files = new ArrayList(NUMBER_IN_BATCH); + for (int j = 0; j < NUMBER_IN_BATCH; j++) + { + int count = (finali+1)*(j+1); + String name = folder.getId() + " - content" + count + ".txt"; + System.out.println(name + " - creating"); + + NodeRef file = fileFolderService.create(folder, name, TYPE_CONTENT).getNodeRef(); + files.add(file); + } + return files; + } + })); + } + + return records; + } + + private void waitForFilesToBeDeclared(List files) + { + while (!files.isEmpty()) + { + final Iterator temp = files.iterator(); + doTestInTransaction(new Test() + { + @Override + public Void run() throws Exception + { + while (temp.hasNext()) + { + NodeRef record = temp.next(); + if (nodeService.hasAspect(record, ASPECT_RECORD) && recordService.isFiled(record)) + { + String name = (String) nodeService.getProperty(record, PROP_NAME); + System.out.println(name + " - complete"); + temp.remove(); + } + } + + return null; + } + }); + } + } +} diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2192Test.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2192Test.java new file mode 100644 index 0000000000..b1f26f764b --- /dev/null +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM2192Test.java @@ -0,0 +1,155 @@ +package org.alfresco.module.org_alfresco_module_rm.test.integration.issue; + +import static org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService.ROLE_RECORDS_MANAGER; +import static org.alfresco.repo.site.SiteModel.SITE_MANAGER; +import static org.alfresco.repo.site.SiteServiceImpl.getSiteContainer; +import static org.alfresco.service.cmr.rule.RuleType.INBOUND; +import static org.alfresco.service.cmr.security.AccessStatus.ALLOWED; +import static org.alfresco.service.cmr.site.SiteService.DOCUMENT_LIBRARY; +import static org.alfresco.service.cmr.site.SiteVisibility.PUBLIC; +import static org.alfresco.util.GUID.generate; + +import org.alfresco.module.org_alfresco_module_rm.action.dm.CreateRecordAction; +import org.alfresco.module.org_alfresco_module_rm.action.impl.FileToAction; +import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; +import org.alfresco.repo.jscript.app.JSONConversionComponent; +import org.alfresco.service.cmr.action.Action; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.rule.Rule; +import org.alfresco.service.cmr.rule.RuleService; + +/** + * Integration test for RM-2192 + * + * @author Tuna Aksoy + * @since 2.2.1.1 + */ +public class RM2192Test extends BaseRMTestCase +{ + private static final String PATH = "/111/222/333"; + + private RuleService ruleService; + private JSONConversionComponent converter; + + private NodeRef folder; + private String user; + private NodeRef documentLibrary2; + + @Override + protected void initServices() + { + super.initServices(); + + ruleService = (RuleService) applicationContext.getBean("RuleService"); + converter = (JSONConversionComponent) applicationContext.getBean("jsonConversionComponent"); + } + + @Override + protected boolean isCollaborationSiteTest() + { + return true; + } + + @Override + protected boolean isRecordTest() + { + return true; + } + + @Override + protected boolean isUserTest() + { + return true; + } + + @Override + protected void setupCollaborationSiteTestDataImpl() + { + super.setupCollaborationSiteTestDataImpl(); + + String collabSiteId2 = generate(); + siteService.createSite("site-dashboard", collabSiteId2, generate(), generate(), PUBLIC); + documentLibrary2 = getSiteContainer( + collabSiteId2, + DOCUMENT_LIBRARY, + true, + siteService, + transactionService, + taggingService); + + assertNotNull("Collaboration site document library component was not successfully created.", documentLibrary2); + + user = generate(); + createPerson(user); + + siteService.setMembership(collabSiteId2, user, SITE_MANAGER); + + filePlanRoleService.assignRoleToAuthority(filePlan, ROLE_RECORDS_MANAGER, user); + } + + public void testAccessToRecordAfterDeclaring() + { + doTestInTransaction(new Test() + { + @Override + public Void run() + { + folder = fileFolderService.create(documentLibrary2, generate(), TYPE_FOLDER).getNodeRef(); + + Action createAction = actionService.createAction(CreateRecordAction.NAME); + createAction.setParameterValue(CreateRecordAction.PARAM_FILE_PLAN, filePlan); + + Rule declareRule = new Rule(); + declareRule.setRuleType(INBOUND); + declareRule.setTitle(generate()); + declareRule.setAction(createAction); + declareRule.setExecuteAsynchronously(true); + declareRule.applyToChildren(true); + ruleService.saveRule(folder, declareRule); + + Action fileAction = actionService.createAction(FileToAction.NAME); + fileAction.setParameterValue(FileToAction.PARAM_PATH, PATH); + fileAction.setParameterValue(FileToAction.PARAM_CREATE_RECORD_PATH, true); + + Rule fileRule = new Rule(); + fileRule.setRuleType(INBOUND); + fileRule.setTitle(generate()); + fileRule.setAction(fileAction); + fileRule.setExecuteAsynchronously(true); + ruleService.saveRule(unfiledContainer, fileRule); + + return null; + } + + @Override + public void test(Void result) throws Exception + { + assertFalse(ruleService.getRules(folder).isEmpty()); + assertFalse(ruleService.getRules(unfiledContainer).isEmpty()); + } + }); + + doTestInTransaction(new Test() + { + NodeRef document; + + @Override + public Void run() + { + document = fileFolderService.create(folder, generate(), TYPE_CONTENT).getNodeRef(); + + return null; + } + + @Override + public void test(Void result) throws InterruptedException + { + Thread.sleep(10000); + + assertEquals(permissionService.hasPermission(document, READ_RECORDS), ALLOWED); + assertTrue(recordService.isFiled(document)); + assertNotNull(converter.toJSON(document, true)); + } + }, user); + } +} diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/FileToActionTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/FileToActionTest.java index f1d3c9d8a9..a00ef18e61 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/FileToActionTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/FileToActionTest.java @@ -29,6 +29,7 @@ import org.alfresco.module.org_alfresco_module_rm.action.impl.FileToAction; import org.alfresco.module.org_alfresco_module_rm.capability.Capability; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.test.util.BaseRMTestCase; +import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.service.cmr.model.FileInfo; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.security.AccessStatus; @@ -113,9 +114,17 @@ public class FileToActionTest extends BaseRMTestCase assertTrue(recordService.isRecord(dmDocument)); assertFalse(recordService.isFiled(dmDocument)); - // is the unfiled container the primary parent of the filed record - NodeRef parent = nodeService.getPrimaryParent(dmDocument).getParentRef(); - assertEquals(filePlanService.getUnfiledContainer(filePlan), parent); + AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork() + { + public Void doWork() throws Exception + { + // is the unfiled container the primary parent of the filed record + NodeRef parent = nodeService.getPrimaryParent(dmDocument).getParentRef(); + assertEquals(filePlanService.getUnfiledContainer(filePlan), parent); + + // TODO Auto-generated method stub + return null; + }}); return null; } @@ -203,12 +212,17 @@ public class FileToActionTest extends BaseRMTestCase private void createRecord(final String path, final String name, final String resolvedPath) { + final String[] pathValues = StringUtils.tokenizeToStringArray(resolvedPath, "/"); + + // set parameters + Map params = new HashMap(1); + params.put(FileToAction.PARAM_PATH, path); + params.put(FileToAction.PARAM_CREATE_RECORD_PATH, true); + doTestInTransaction(new Test() { public Void run() throws Exception { - String[] pathValues = StringUtils.tokenizeToStringArray(resolvedPath, "/"); - // show the folder doesn't exist to begin with FileInfo createdRecordFolder = fileFolderService.resolveNamePath(filePlan, new ArrayList(Arrays.asList(pathValues)), false); assertNull(createdRecordFolder); @@ -218,11 +232,19 @@ public class FileToActionTest extends BaseRMTestCase params.put(FileToAction.PARAM_PATH, path); params.put(FileToAction.PARAM_CREATE_RECORD_PATH, true); - // execute file-to action - rmActionService.executeRecordsManagementAction(dmDocument, FileToAction.NAME, params); + return null; + } + }, ADMIN_USER); + // execute file-to action + rmActionService.executeRecordsManagementAction(dmDocument, FileToAction.NAME, params); + + doTestInTransaction(new Test() + { + public Void run() throws Exception + { // show the folder has now been created - createdRecordFolder = fileFolderService.resolveNamePath(filePlan, new ArrayList(Arrays.asList(pathValues)), false); + FileInfo createdRecordFolder = fileFolderService.resolveNamePath(filePlan, new ArrayList(Arrays.asList(pathValues)), false); assertNotNull(createdRecordFolder); assertEquals(name, createdRecordFolder.getName()); NodeRef createdRecordFolderNodeRef = createdRecordFolder.getNodeRef(); diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/ExtendedSecurityServiceImplTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/ExtendedSecurityServiceImplTest.java index 324b0ce759..faeadd3554 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/ExtendedSecurityServiceImplTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/ExtendedSecurityServiceImplTest.java @@ -105,9 +105,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase testMap.put(monkey, Integer.valueOf(1)); testMap.put(elephant, Integer.valueOf(1)); - checkExtendedReaders(filePlan, testMap); - checkExtendedReaders(rmContainer, testMap); - checkExtendedReaders(rmFolder, testMap); checkExtendedReaders(record, testMap); Set extendedReadersToo = new HashSet(2); @@ -125,9 +122,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase testMapThree.put(elephant, Integer.valueOf(1)); testMapThree.put(snake, Integer.valueOf(1)); - checkExtendedReaders(filePlan, testMapThree); - checkExtendedReaders(rmContainer, testMapThree); - checkExtendedReaders(rmFolder, testMapThree); checkExtendedReaders(recordToo, testMapToo); // test remove (with no parent inheritance) @@ -142,9 +136,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase testMapFour.put(monkey, Integer.valueOf(1)); testMapFour.put(snake, Integer.valueOf(1)); - checkExtendedReaders(filePlan, testMapThree); - checkExtendedReaders(rmContainer, testMapThree); - checkExtendedReaders(rmFolder, testMapFour); checkExtendedReaders(recordToo, testMapToo); // test remove (apply to parents) @@ -158,9 +149,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase testMapFour.remove(snake); testMapToo.remove(snake); - checkExtendedReaders(filePlan, testMapThree); - checkExtendedReaders(rmContainer, testMapThree); - checkExtendedReaders(rmFolder, testMapFour); checkExtendedReaders(recordToo, testMapToo); return null; @@ -197,9 +185,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase extendedSecurityService.addExtendedSecurity(record, extendedReaders, null); - checkExtendedReaders(filePlan, testMap); - checkExtendedReaders(rmContainer, testMap); - checkExtendedReaders(rmFolder, testMap); checkExtendedReaders(record, testMap); assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordCategory)); assertFalse(extendedSecurityService.hasExtendedSecurity(moveRecordFolder)); @@ -212,11 +197,6 @@ public class ExtendedSecurityServiceImplTest extends BaseRMTestCase @Override public void test(Void result) throws Exception { - checkExtendedReaders(filePlan, testMap); - assertFalse(extendedSecurityService.hasExtendedSecurity(rmContainer)); - // assertEquals(0, extendedSecurityService.getExtendedReaders(rmFolder).size()); - checkExtendedReaders(moveRecordCategory, testMap); - checkExtendedReaders(moveRecordFolder, testMap); checkExtendedReaders(record, testMap); } }); diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordServiceImplTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordServiceImplTest.java index 14f5ffa379..600a54854d 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordServiceImplTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/service/RecordServiceImplTest.java @@ -28,7 +28,6 @@ import org.alfresco.module.org_alfresco_module_rm.capability.Capability; import org.alfresco.module.org_alfresco_module_rm.capability.RMPermissionModel; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.module.org_alfresco_module_rm.record.RecordService; -import org.alfresco.module.org_alfresco_module_rm.role.FilePlanRoleService; import org.alfresco.module.org_alfresco_module_rm.role.Role; import org.alfresco.module.org_alfresco_module_rm.security.ExtendedReaderDynamicAuthority; import org.alfresco.module.org_alfresco_module_rm.security.ExtendedWriterDynamicAuthority; @@ -38,7 +37,6 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.service.cmr.repository.ContentWriter; import org.alfresco.service.cmr.repository.NodeRef; -import org.alfresco.service.cmr.security.AccessPermission; import org.alfresco.service.cmr.security.AccessStatus; import org.alfresco.service.namespace.QName; import org.alfresco.util.GUID; @@ -304,15 +302,12 @@ public class RecordServiceImplTest extends BaseRMTestCase public void test(Void result) { - checkPermissions(READ_RECORDS, AccessStatus.ALLOWED, // file - // plan - AccessStatus.ALLOWED, // unfiled container + checkPermissions(READ_RECORDS, AccessStatus.DENIED, // file plan + AccessStatus.DENIED, // unfiled container AccessStatus.DENIED, // record category AccessStatus.DENIED, // record folder AccessStatus.ALLOWED); // doc/record - permissionReport(); - assertEquals(AccessStatus.ALLOWED, permissionService.hasPermission(filePlan, RMPermissionModel.VIEW_RECORDS)); @@ -362,9 +357,8 @@ public class RecordServiceImplTest extends BaseRMTestCase @Override public Void run() { - checkPermissions(READ_RECORDS, AccessStatus.ALLOWED, // file - // plan - AccessStatus.ALLOWED, // unfiled container + checkPermissions(READ_RECORDS, AccessStatus.DENIED, // file plan + AccessStatus.DENIED, // unfiled container AccessStatus.DENIED, // record category AccessStatus.DENIED, // record folder AccessStatus.ALLOWED); // doc/record @@ -394,38 +388,6 @@ public class RecordServiceImplTest extends BaseRMTestCase }, dmConsumer); } - private void permissionReport() - { - Set writers = extendedSecurityService.getExtendedWriters(dmDocument); - for (String writer : writers) - { - System.out.println("writer: " + writer); - } - - System.out.println("Users assigned to extended writers role:"); - Set assignedUsers = filePlanRoleService.getUsersAssignedToRole(filePlan, FilePlanRoleService.ROLE_EXTENDED_WRITERS); - for (String assignedUser : assignedUsers) - { - System.out.println(" ... " + assignedUser); - } - - Set perms = permissionService.getAllSetPermissions(filePlan); - for (AccessPermission perm : perms) - { - if (perm.getPermission().contains(RMPermissionModel.EDIT_NON_RECORD_METADATA)) - { - System.out.println(" ... " + perm.getAuthority() + " - " + perm.getPermission() + " - " + perm.getAccessStatus().toString()); - } - } - for (AccessPermission perm : perms) - { - if (perm.getPermission().contains(RMPermissionModel.VIEW_RECORDS)) - { - System.out.println(" ... " + perm.getAuthority() + " - " + perm.getPermission() + " - " + perm.getAccessStatus().toString()); - } - } - } - public void testCreateRecordNoLink() throws Exception { // show that users without WRITE can not create a record from a document