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 ed36a2ceed..7ca8943f27 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 @@ -17,7 +17,6 @@ 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; @@ -133,7 +132,7 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr { targetIsUnfiledRecords = (dictionaryService.isSubClass(actionedUponType, ContentModel.TYPE_CONTENT) && !recordService.isFiled(actionedUponNodeRef)) || TYPE_UNFILED_RECORD_FOLDER.equals(actionedUponType); - } + } // first look to see if the destination record folder has been specified NodeRef recordFolder = (NodeRef)action.getParameterValue(PARAM_DESTINATION_RECORD_FOLDER); @@ -144,15 +143,21 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr { public NodeRef execute() throws Throwable { + NodeRef result = null; try { - // get the reference to the record folder based on the relative path - return createOrResolvePath(action, actionedUponNodeRef, finaltargetIsUnfiledRecords); + synchronized (this) + { + // 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); } @@ -168,18 +173,22 @@ 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) - { - recordService.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) + { + recordService.link(actionedUponNodeRef, finalRecordFolder); + } + } + } catch (FileNotFoundException fileNotFound) { @@ -361,18 +370,7 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr */ private NodeRef getChild(NodeRef parent, String childName) { - NodeRef child = null; - List children = nodeService.getChildAssocs(parent); - for (ChildAssociationRef childAssoc : children) { - NodeRef childNodeRef = childAssoc.getChildRef(); - String existingChildName = (String)nodeService.getProperty(childNodeRef, ContentModel.PROP_NAME); - if(existingChildName.equals(childName)) - { - child = childNodeRef; - break; - } - } - return child; + return nodeService.getChildByName(parent, ContentModel.ASSOC_CONTAINS, childName); } /** @@ -392,22 +390,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 = recordFolderService.createRecordFolder(parent, childName); - } - else - { - if(RecordsManagementModel.TYPE_RECORD_FOLDER.equals(nodeService.getType(parent))) - { - throw new AlfrescoRuntimeException("Unable to execute " + action.getActionDefinitionName() + " action, because the destination path could not be created."); - } - child = filePlanService.createRecordCategory(parent, childName); + if(targetisUnfiledRecords) + { + // create unfiled folder + child = fileFolderService.create(parent, childName, RecordsManagementModel.TYPE_UNFILED_RECORD_FOLDER).getNodeRef(); + } + else if(lastAsFolder) + { + // create record folder + child = recordFolderService.createRecordFolder(parent, childName); + } + else + { + // ensure we are not trying to create a record categtory in a record folder + if(RecordsManagementModel.TYPE_RECORD_FOLDER.equals(nodeService.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); + } } return child; } 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 82b94f8fd0..de53d974f5 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 @@ -329,38 +329,44 @@ public class JSONConversionComponent extends org.alfresco.repo.jscript.app.JSONC * @return */ @SuppressWarnings("unchecked") - private JSONObject setRmNodeValues(NodeRef nodeRef, boolean useShortQName) - { - JSONObject rmNodeValues = new JSONObject(); - - // UI convenience type - rmNodeValues.put("uiType", getUIType(nodeRef)); - - // Get the 'kind' of the file plan component - FilePlanComponentKind kind = filePlanService.getFilePlanComponentKind(nodeRef); - rmNodeValues.put("kind", kind.toString()); - - // File plan node reference - NodeRef filePlan = filePlanService.getFilePlan(nodeRef); - rmNodeValues.put("filePlan", filePlan.toString()); - - // Unfiled container node reference - NodeRef unfiledRecordContainer = filePlanService.getUnfiledContainer(filePlan); - if (unfiledRecordContainer != null) + private JSONObject setRmNodeValues(final NodeRef nodeRef, final boolean useShortQName) + { + return AuthenticationUtil.runAsSystem(new RunAsWork() { - 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()); - } + public JSONObject doWork() + { + JSONObject rmNodeValues = new JSONObject(); - // Set the indicators array - setIndicators(rmNodeValues, nodeRef); + // UI convenience type + rmNodeValues.put("uiType", getUIType(nodeRef)); - // Set the actions array - setActions(rmNodeValues, nodeRef); - - return rmNodeValues; + // Get the 'kind' of the file plan component + FilePlanComponentKind kind = filePlanService.getFilePlanComponentKind(nodeRef); + rmNodeValues.put("kind", kind.toString()); + + // File plan node reference + NodeRef filePlan = filePlanService.getFilePlan(nodeRef); + 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()); + } + + // Set the indicators array + setIndicators(rmNodeValues, nodeRef); + + // Set the actions array + setActions(rmNodeValues, nodeRef); + + return rmNodeValues; + } + }); } @SuppressWarnings("unchecked") 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..5ee680be6a 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 @@ -46,8 +46,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 +73,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 0cc4cd45f2..724158dde3 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 @@ -973,7 +973,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); @@ -981,15 +981,24 @@ public class RecordServiceImpl extends BaseBehaviourBean if (isRecord(nodeRef)) { - ChildAssociationRef childAssocRef = nodeService.getPrimaryParent(nodeRef); - if (childAssocRef != null) - { - NodeRef parent = childAssocRef.getParentRef(); - if (parent != null && recordFolderService.isRecordFolder(parent)) - { - result = true; - } - } + result = AuthenticationUtil.runAsSystem(new RunAsWork() + { + public Boolean doWork() throws Exception + { + boolean result = false; + ChildAssociationRef childAssocRef = nodeService.getPrimaryParent(nodeRef); + if (childAssocRef != null) + { + NodeRef parent = childAssocRef.getParentRef(); + if (parent != null && recordFolderService.isRecordFolder(parent)) + { + result = true; + } + } + return result; + } + }); + } return result; 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 89193d0def..2ef8b753d8 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 61268ae7cb..a4fd365b8c 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 @@ -46,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; @@ -72,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) @@ -137,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); } } @@ -149,37 +148,37 @@ 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); - - // set the writers property (this will in turn apply the aspect if required) - nodeService.setProperty(nodeRef, PROP_WRITERS, (Serializable)addToMap(writersMap, 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) + 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)) { @@ -189,22 +188,7 @@ public class ExtendedSecurityServiceImpl extends ServiceBaseImpl NodeRef child = assoc.getChildRef(); 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); - } - } + } } /** @@ -217,37 +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); - for (String authority : authorities) { - if ((!authority.equals(PermissionService.ALL_AUTHORITIES) && !authority.equals(PermissionService.OWNER_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); } } - - // update the reference count - nodeService.setProperty(filePlan, propertyName, (Serializable)addToMap(referenceCountMap, authorities)); } } 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/legacy/action/FileToActionTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/legacy/action/FileToActionTest.java index cadc97243c..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; } 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 aac8a820f7..1cf86bb235 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