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 5a35561a63..27e309d1f6 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 @@ -260,6 +260,7 @@ + ${rm.ghosting.enabled} @@ -761,7 +762,6 @@ - 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 4a4ebbaab2..3e3ecd1b3e 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,12 +17,10 @@ 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.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; /** @@ -35,9 +33,6 @@ 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"; @@ -94,14 +89,6 @@ 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) */ @@ -138,25 +125,7 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr NodeRef recordFolder = (NodeRef)action.getParameterValue(PARAM_DESTINATION_RECORD_FOLDER); if (recordFolder == null) { - 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); + recordFolder = createOrResolvePath(action, actionedUponNodeRef, targetIsUnfiledRecords); } // now we have the reference to the target folder we can do some final checks to see if the action is valid @@ -170,30 +139,26 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr { try { - synchronized (this) + if (getMode() == CopyMoveLinkFileToActionMode.MOVE) { - 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); - } + 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) { throw new AlfrescoRuntimeException("Unable to execute file to action, because the " + (mode == CopyMoveLinkFileToActionMode.MOVE ? "move" : "copy") + " operation failed.", fileNotFound); } - + return null; } - }); } } @@ -283,23 +248,29 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr * @param targetisUnfiledRecords true is the target is in unfiled records * @return */ - private NodeRef createOrResolvePath(Action action, NodeRef actionedUponNodeRef, boolean targetisUnfiledRecords) + private NodeRef createOrResolvePath(final Action action, final NodeRef actionedUponNodeRef, final boolean targetisUnfiledRecords) { // get the starting context - NodeRef context = getContext(action, actionedUponNodeRef, targetisUnfiledRecords); + final NodeRef context = getContext(action, actionedUponNodeRef, targetisUnfiledRecords); NodeRef path = context; // get the path we wish to resolve String pathParameter = (String)action.getParameterValue(PARAM_PATH); - String[] pathElementsArray = StringUtils.tokenizeToStringArray(pathParameter, "/", false, true); + final String[] pathElementsArray = StringUtils.tokenizeToStringArray(pathParameter, "/", false, true); if((pathElementsArray != null) && (pathElementsArray.length > 0)) { // get the create parameter Boolean createValue = (Boolean)action.getParameterValue(PARAM_CREATE_RECORD_PATH); - boolean create = createValue == null ? false : createValue.booleanValue(); + final boolean create = createValue == null ? false : createValue.booleanValue(); // create or resolve the specified path - path = createOrResolvePath(action, context, actionedUponNodeRef, Arrays.asList(pathElementsArray), targetisUnfiledRecords, create, false); + path = getTransactionService().getRetryingTransactionHelper().doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + public NodeRef execute() throws Throwable + { + return createOrResolvePath(action, context, actionedUponNodeRef, Arrays.asList(pathElementsArray), targetisUnfiledRecords, create, false); + } + }, false, true); } return path; } @@ -388,7 +359,7 @@ public abstract class CopyMoveLinkFileToBaseAction extends RMActionExecuterAbstr NodeRef child = getChild(parent, childName); if (child == null) { - if(targetisUnfiledRecords) + if (targetisUnfiledRecords) { // create unfiled folder child = fileFolderService.create(parent, childName, RecordsManagementModel.TYPE_UNFILED_RECORD_FOLDER).getNodeRef(); diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/DestroyAction.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/DestroyAction.java index 9c91f3586b..ea027ede58 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/DestroyAction.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/action/impl/DestroyAction.java @@ -29,6 +29,7 @@ import org.alfresco.module.org_alfresco_module_rm.action.RMDispositionActionExec import org.alfresco.module.org_alfresco_module_rm.capability.CapabilityService; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionActionDefinition; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; +import org.alfresco.module.org_alfresco_module_rm.record.InplaceRecordService; import org.alfresco.module.org_alfresco_module_rm.version.RecordableVersionService; import org.alfresco.repo.content.cleanup.EagerContentStoreCleaner; import org.alfresco.service.cmr.action.Action; @@ -56,10 +57,13 @@ public class DestroyAction extends RMDispositionActionExecuterAbstractBase /** Capability service */ private CapabilityService capabilityService; - + /** Recordable version service */ private RecordableVersionService recordableVersionService; + /** Inplace record service */ + private InplaceRecordService inplaceRecordService; + /** Indicates if ghosting is enabled or not */ private boolean ghostingEnabled = true; @@ -78,7 +82,7 @@ public class DestroyAction extends RMDispositionActionExecuterAbstractBase { this.capabilityService = capabilityService; } - + /** * @param recordableVersionService recordable version service */ @@ -87,6 +91,14 @@ public class DestroyAction extends RMDispositionActionExecuterAbstractBase this.recordableVersionService = recordableVersionService; } + /** + * @param inplaceRecordService inplace record service + */ + public void setInplaceRecordService(InplaceRecordService inplaceRecordService) + { + this.inplaceRecordService = inplaceRecordService; + } + /** * @param ghostingEnabled true if ghosting is enabled, false otherwise */ @@ -169,7 +181,10 @@ public class DestroyAction extends RMDispositionActionExecuterAbstractBase { recordableVersionService.destroyRecordedVersion(version); } - + + // Hide from inplace users to give the impression of destruction + inplaceRecordService.hideRecord(record); + // Add the ghosted aspect getNodeService().addAspect(record, ASPECT_GHOSTED, null); } 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 74ad459f61..5e5dd27b0a 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 @@ -50,7 +50,8 @@ import org.junit.runners.Suite.SuiteClasses; RM1914Test.class, //RM2190Test.class, RM2192Test.class, - RM3314Test.class + RM3314Test.class, + RM4101Test.class }) public class IssueTestSuite { diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM4101Test.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM4101Test.java new file mode 100644 index 0000000000..3c302264a3 --- /dev/null +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/issue/RM4101Test.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2005-2016 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.UUID; + +import org.alfresco.module.org_alfresco_module_rm.action.impl.LinkToAction; +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; + +/** + * Tests issue #4101: Link to, Copy to and File to rules fail when not run in background + * + * @author Tuna Aksoy + * @since 2.3.0.8 + */ +public class RM4101Test extends BaseRMTestCase +{ + private RuleService ruleService; + + @Override + protected void initServices() + { + super.initServices(); + + ruleService = (RuleService) applicationContext.getBean("RuleService"); + } + + @Override + protected boolean isRecordTest() + { + return true; + } + + public void testRunRuleNotInBackground() throws Exception + { + final String categoryName = "category1" + UUID.randomUUID().toString(); + final NodeRef category1 = doTestInTransaction(new Test() + { + @Override + public NodeRef run() + { + return filePlanService.createRecordCategory(filePlan, categoryName); + } + }); + + final NodeRef folder1 = doTestInTransaction(new Test() + { + @Override + public NodeRef run() + { + return recordFolderService.createRecordFolder(category1, "folder1WithRule" + UUID.randomUUID().toString()); + } + }); + + final String folder2Name = "folder2FolderToLinkTo" + UUID.randomUUID().toString(); + final NodeRef folder2 = doTestInTransaction(new Test() + { + @Override + public NodeRef run() + { + return recordFolderService.createRecordFolder(category1, folder2Name); + } + }); + + doTestInTransaction(new Test() + { + @Override + public Void run() + { + Action linkToAction = actionService.createAction(LinkToAction.NAME); + linkToAction.setParameterValue(LinkToAction.PARAM_PATH, "/" + categoryName + "/" + folder2Name); + + Rule rule = new Rule(); + rule.setRuleType(RuleType.INBOUND); + rule.setTitle("LinkTo"); + rule.setAction(linkToAction); + rule.setExecuteAsynchronously(false); + ruleService.saveRule(folder1, rule); + + return null; + } + }); + + doTestInTransaction(new Test() + { + @Override + public Void run() + { + utils.createRecord(folder1, "record1" + UUID.randomUUID().toString()); + return null; + } + + @Override + public void test(Void result) throws Exception + { + assertEquals(1, nodeService.getChildAssocs(folder2).size()); + } + }); + } +} diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/InplaceRecordPermissionTest.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/InplaceRecordPermissionTest.java index b16c1472c3..ef086d2bc8 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/InplaceRecordPermissionTest.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/InplaceRecordPermissionTest.java @@ -500,8 +500,7 @@ public class InplaceRecordPermissionTest extends BaseRMTestCase * And it's metadata is maintained * Then the inplace users will no longer see the record */ - // FIXME: See RM-4095 - public void ztestDestroyedRecordInplacePermissions() + public void testDestroyedRecordInplacePermissions() { test() .given() diff --git a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/RecordTestSuite.java b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/RecordTestSuite.java index acf5c1ddad..e20f77bae7 100644 --- a/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/RecordTestSuite.java +++ b/rm-server/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/RecordTestSuite.java @@ -38,7 +38,9 @@ import org.junit.runners.Suite.SuiteClasses; HideInplaceRecordTest.class, MoveInplaceRecordTest.class, ViewRecordTest.class, - LinkRecordTest.class + LinkRecordTest.class, + CreateInplaceRecordTest.class, + InplaceRecordPermissionTest.class }) public class RecordTestSuite {