From 80e6b7aace7aae955586e62918af46a05d205548 Mon Sep 17 00:00:00 2001 From: Ross Gale Date: Tue, 30 Apr 2019 14:39:47 +0100 Subject: [PATCH 01/24] Creating hotfix branch --- pom.xml | 2 +- rm-automation/pom.xml | 2 +- rm-automation/rm-automation-community-rest-api/pom.xml | 2 +- rm-community/pom.xml | 2 +- rm-community/rm-community-repo/pom.xml | 2 +- rm-community/rm-community-rest-api-explorer/pom.xml | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/pom.xml b/pom.xml index 3ff2e1b1f0..5abb8617da 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.alfresco alfresco-rm pom - 3.0.2-SNAPSHOT + 3.0.1.1-SNAPSHOT Alfresco Records Management http://www.alfresco.org/ diff --git a/rm-automation/pom.xml b/rm-automation/pom.xml index f3819b4891..55610d154e 100644 --- a/rm-automation/pom.xml +++ b/rm-automation/pom.xml @@ -8,7 +8,7 @@ org.alfresco alfresco-rm - 3.0.2-SNAPSHOT + 3.0.1.1-SNAPSHOT diff --git a/rm-automation/rm-automation-community-rest-api/pom.xml b/rm-automation/rm-automation-community-rest-api/pom.xml index d45d244d80..e02ff008a4 100644 --- a/rm-automation/rm-automation-community-rest-api/pom.xml +++ b/rm-automation/rm-automation-community-rest-api/pom.xml @@ -8,7 +8,7 @@ org.alfresco alfresco-rm-automation - 3.0.2-SNAPSHOT + 3.0.1.1-SNAPSHOT diff --git a/rm-community/pom.xml b/rm-community/pom.xml index 935a202542..9793907bc9 100644 --- a/rm-community/pom.xml +++ b/rm-community/pom.xml @@ -8,7 +8,7 @@ org.alfresco alfresco-rm - 3.0.2-SNAPSHOT + 3.0.1.1-SNAPSHOT diff --git a/rm-community/rm-community-repo/pom.xml b/rm-community/rm-community-repo/pom.xml index 76bbb7602f..e8ded87046 100644 --- a/rm-community/rm-community-repo/pom.xml +++ b/rm-community/rm-community-repo/pom.xml @@ -9,7 +9,7 @@ org.alfresco alfresco-rm-community - 3.0.2-SNAPSHOT + 3.0.1.1-SNAPSHOT diff --git a/rm-community/rm-community-rest-api-explorer/pom.xml b/rm-community/rm-community-rest-api-explorer/pom.xml index ff7981e582..1fa60b9927 100644 --- a/rm-community/rm-community-rest-api-explorer/pom.xml +++ b/rm-community/rm-community-rest-api-explorer/pom.xml @@ -7,7 +7,7 @@ org.alfresco alfresco-rm-community - 3.0.2-SNAPSHOT + 3.0.1.1-SNAPSHOT From 81033bbf12dd7172cd47656de530f5ca15829526 Mon Sep 17 00:00:00 2001 From: Ross Gale Date: Wed, 13 Nov 2019 15:52:29 +0000 Subject: [PATCH 02/24] Initial patch code to apply disposition fix to records --- .../patch/rm-patch-v24-context.xml | 14 +- .../query/rm-common-SqlMap.xml | 35 ++++- .../org_alfresco_module_rm/version.properties | 2 +- .../v24/RMv24DispositionInheritancePatch.java | 120 ++++++++++++++++++ .../query/NodeRefEntity.java | 77 +++++++++++ .../query/RecordsManagementQueryDAO.java | 11 ++ .../query/RecordsManagementQueryDAOImpl.java | 23 ++++ 7 files changed, 277 insertions(+), 5 deletions(-) create mode 100644 rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v24/RMv24DispositionInheritancePatch.java create mode 100644 rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/NodeRefEntity.java diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml index e3e843041e..682a3a0331 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml @@ -14,5 +14,17 @@ - + + + + + + + + + + + \ No newline at end of file diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml index e3f1c1a89d..2845b537fa 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml @@ -7,8 +7,15 @@ - - select count(*) from @@ -19,5 +26,27 @@ prop.string_value = ? - + + + + + \ No newline at end of file diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties index cf2c7c2600..8cce8ad3ce 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties @@ -1,3 +1,3 @@ # RM Schema number -version.rm.schema=2501 +version.rm.schema=2502 diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v24/RMv24DispositionInheritancePatch.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v24/RMv24DispositionInheritancePatch.java new file mode 100644 index 0000000000..dffff5a9a4 --- /dev/null +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v24/RMv24DispositionInheritancePatch.java @@ -0,0 +1,120 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2019 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * - + * 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 . + * #L% + */ + +package org.alfresco.module.org_alfresco_module_rm.patch.v24; + +import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.ASPECT_DISPOSITION_LIFECYCLE; + +import java.util.List; + +import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; +import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; +import org.alfresco.module.org_alfresco_module_rm.patch.AbstractModulePatch; +import org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * RM v2.4 patch that ensures that file plan root containers do not inherited rules, because this is no longer enforced + * in the service code anymore. + *

+ * See https://issues.alfresco.com/jira/browse/RM-3154 + * + * @author Roy Wetherall + * @since 2.4 + */ +public class RMv24DispositionInheritancePatch extends AbstractModulePatch +{ + private static Log logger = LogFactory.getLog(RMv24DispositionInheritancePatch.class); + + private DispositionService dispositionService; + + private RecordService recordService; + + private NodeService nodeService; + + private RecordsManagementQueryDAO recordsManagementQueryDAO; + + public void setDispositionService(DispositionService dispositionService) + { + this.dispositionService = dispositionService; + } + + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setRecordService(RecordService recordService) + { + this.recordService = recordService; + } + + public void setRecordsManagementQueryDAO(RecordsManagementQueryDAO recordsManagementQueryDAO) + { + this.recordsManagementQueryDAO = recordsManagementQueryDAO; + } + + /** + * @see AbstractModulePatch#applyInternal() + *

+ * Checks for records added to a disposition schedule pre MNT-19967 and applys disposition step and properties + */ + @Override + public void applyInternal() + { + logger.info("***********************recordsManagementQueryDAO.getNodeRefs()***************************"); + logger.info(recordsManagementQueryDAO.getRecordFoldersWithSchedules()); + logger.info("***********************RMv24DispositionInheritancePatch***************************"); + + + List folders = recordsManagementQueryDAO.getRecordFoldersWithSchedules(); + logger.info("folders: " + folders); + for (NodeRef folder : folders) + { + DispositionSchedule schedule = dispositionService.getDispositionSchedule(folder); + logger.info("schedule: " + schedule); + if (schedule.isRecordLevelDisposition()) + { + List records = recordService.getRecords(folder); + logger.info("records: " + records); + for (NodeRef record : records) + { + if (!nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)) + { + logger.info("updating record: " + record); + dispositionService.updateNextDispositionAction(record); + } + } + } + } + } +} + diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/NodeRefEntity.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/NodeRefEntity.java new file mode 100644 index 0000000000..e61e526763 --- /dev/null +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/NodeRefEntity.java @@ -0,0 +1,77 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2019 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * - + * 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 . + * #L% + */ +package org.alfresco.module.org_alfresco_module_rm.query; + +/** + * NodeRef Entity - used by {@link RecordsManagementQueryDAOImpl}. + * + * @author Tom Page + * @since 2.5.0.4 + */ +public class NodeRefEntity +{ + private String protocol; + private String identifier; + private String uuid; + + /** + * Default constructor. + */ + public NodeRefEntity() + { + } + + public String getProtocol() + { + return protocol; + } + + public void setProtocol(String protocol) + { + this.protocol = protocol; + } + + public String getIdentifier() + { + return identifier; + } + + public void setIdentifier(String identifier) + { + this.identifier = identifier; + } + + public String getUuid() + { + return uuid; + } + + public void setUuid(String uuid) + { + this.uuid = uuid; + } +} diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java index c0743f604d..f68ce3723a 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java @@ -27,6 +27,10 @@ package org.alfresco.module.org_alfresco_module_rm.query; +import java.util.List; + +import org.alfresco.service.cmr.repository.NodeRef; + /** * Records management query DAO * @@ -46,4 +50,11 @@ public interface RecordsManagementQueryDAO * @return int count */ int getCountRmaIdentifier(String identifierValue); + + /** + * Returns a list of nodeRef for all record folders in the system + * that have the property recordSearchHasDispositionSchedule:true + * @return List of nodeRefs + */ + public List getRecordFoldersWithSchedules(); } diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java index 68742ee271..0432e13612 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java @@ -27,11 +27,14 @@ package org.alfresco.module.org_alfresco_module_rm.query; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.repo.domain.qname.QNameDAO; +import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.QName; import org.alfresco.util.Pair; import org.mybatis.spring.SqlSessionTemplate; @@ -45,6 +48,7 @@ import org.mybatis.spring.SqlSessionTemplate; public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, RecordsManagementModel { private static final String COUNT_IDENTIFIER = "alfresco.query.rm.select_CountRMIndentifier"; + private static final String SCHEDULED_FOLDERS = "alfresco.query.rm.select_RecordFoldersWithSchedules"; /** SQL session template */ protected SqlSessionTemplate template; @@ -97,4 +101,23 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, return result; } + /** + * @see org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO#getRecordFoldersWithSchedules() + */ + @Override + public List getRecordFoldersWithSchedules() + { + List entities = template.selectList(SCHEDULED_FOLDERS); + + List results = new ArrayList<>(); + + // convert the entities to NodeRefs + for (NodeRefEntity nodeRefEntity : entities) + { + results.add(new NodeRef(nodeRefEntity.getProtocol(), nodeRefEntity.getIdentifier(), nodeRefEntity.getUuid())); + } + + return results; + } + } From 1e1209f9874518c010e91248ca075a10159f4821 Mon Sep 17 00:00:00 2001 From: Ross Gale Date: Sun, 17 Nov 2019 22:07:31 +0000 Subject: [PATCH 03/24] RM-7051 adding batch code --- .../query/rm-common-SqlMap.xml | 58 ++++++++++++----- .../disposition/DispositionService.java | 8 +++ .../disposition/DispositionServiceImpl.java | 28 ++++++++ .../v24/RMv24DispositionInheritancePatch.java | 65 +++++++++++++------ .../query/NodeRefEntity.java | 11 ++++ .../query/RecordsManagementQueryDAO.java | 15 ++++- .../query/RecordsManagementQueryDAOImpl.java | 34 +++++++++- 7 files changed, 177 insertions(+), 42 deletions(-) diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml index 2845b537fa..201b68d956 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml @@ -8,7 +8,20 @@ + + + + + + + + + + + + + @@ -29,23 +42,36 @@ + + diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java index 4da6fde0dd..2ba7dbcc0e 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java @@ -237,6 +237,14 @@ public interface DispositionService */ void updateNextDispositionAction(NodeRef nodeRef); + /** + * Updates the next disposition action + * + * @param nodeRef node reference + * @param DispositionSchedule the schedule to be applied + */ + void updateNextDispositionAction(NodeRef nodeRef, DispositionSchedule dispositionSchedule); + /** * Refreshes the disposition action details of the given node. * diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java index 32f68c1bb5..78087ffffd 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java @@ -954,6 +954,34 @@ public class DispositionServiceImpl extends ServiceBaseImpl { // Get this disposition instructions for the node DispositionSchedule di = getDispositionSchedule(nodeRef); + + updateNextDispositionAction(nodeRef, di); + + return null; + } + + }; + + AuthenticationUtil.runAsSystem(runAsWork); + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#updateNextDispositionAction(NodeRef) + */ + @Override + public void updateNextDispositionAction(final NodeRef nodeRef, final DispositionSchedule di) + { + + + RunAsWork runAsWork = new RunAsWork() + { + /** + * @see org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork#doWork() + */ + @Override + public Void doWork() + { + if (di != null) { // Get the current action node diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v24/RMv24DispositionInheritancePatch.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v24/RMv24DispositionInheritancePatch.java index dffff5a9a4..b1fe090b1b 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v24/RMv24DispositionInheritancePatch.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v24/RMv24DispositionInheritancePatch.java @@ -31,11 +31,13 @@ import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagement import java.util.List; +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.disposition.DispositionService; import org.alfresco.module.org_alfresco_module_rm.patch.AbstractModulePatch; import org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO; import org.alfresco.module.org_alfresco_module_rm.record.RecordService; +import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; import org.apache.commons.logging.Log; @@ -52,7 +54,9 @@ import org.apache.commons.logging.LogFactory; */ public class RMv24DispositionInheritancePatch extends AbstractModulePatch { - private static Log logger = LogFactory.getLog(RMv24DispositionInheritancePatch.class); + private static final Log logger = LogFactory.getLog(RMv24DispositionInheritancePatch.class); + + private static final long BATCH_SIZE = 5L; private DispositionService dispositionService; @@ -90,30 +94,51 @@ public class RMv24DispositionInheritancePatch extends AbstractModulePatch @Override public void applyInternal() { - logger.info("***********************recordsManagementQueryDAO.getNodeRefs()***************************"); - logger.info(recordsManagementQueryDAO.getRecordFoldersWithSchedules()); - logger.info("***********************RMv24DispositionInheritancePatch***************************"); + logger.info("********************Patch start********************"); + int maxNode = recordsManagementQueryDAO.getRecordFoldersWithSchedulesCount(); + logger.info("nodes to update: "+ maxNode); - - List folders = recordsManagementQueryDAO.getRecordFoldersWithSchedules(); - logger.info("folders: " + folders); - for (NodeRef folder : folders) + for (Long i = 0L; i < maxNode; i += BATCH_SIZE) { - DispositionSchedule schedule = dispositionService.getDispositionSchedule(folder); - logger.info("schedule: " + schedule); - if (schedule.isRecordLevelDisposition()) - { - List records = recordService.getRecords(folder); - logger.info("records: " + records); - for (NodeRef record : records) + final Long finali = i; + int updatedRecords = transactionService.getRetryingTransactionHelper() + .doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() { - if (!nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)) + public Integer execute() throws Throwable { - logger.info("updating record: " + record); - dispositionService.updateNextDispositionAction(record); + int recordCount = 0; + logger.info("********************Patch start********************"); + logger.info("********************Query start********************"); + logger.info(finali); + logger.info(finali + BATCH_SIZE); + logger.info(recordsManagementQueryDAO.getRecordFoldersWithSchedules(finali, finali + BATCH_SIZE)); + List folders = recordsManagementQueryDAO.getRecordFoldersWithSchedules(finali, finali + BATCH_SIZE); + logger.info("********************Query end********************"); + for (NodeRef folder : folders) + + { + + DispositionSchedule schedule = dispositionService.getDispositionSchedule(folder); + if (schedule.isRecordLevelDisposition()) + { + List records = recordService.getRecords(folder); + for (NodeRef record : records) + { + if (!nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)) + { + logger.info("updating record: " + record); + dispositionService.updateNextDispositionAction(record, schedule); + recordCount ++; + } + } + } + } + logger.info("********************Patch end********************"); + return recordCount; } - } - } + }, false, true); + + logger.info("....completed: "+ updatedRecords); } } } diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/NodeRefEntity.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/NodeRefEntity.java index e61e526763..203a186e45 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/NodeRefEntity.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/NodeRefEntity.java @@ -34,6 +34,7 @@ package org.alfresco.module.org_alfresco_module_rm.query; */ public class NodeRefEntity { + private Long num; private String protocol; private String identifier; private String uuid; @@ -45,6 +46,16 @@ public class NodeRefEntity { } + public Long getNum() + { + return num; + } + + public void setNum(Long num) + { + this.num = num; + } + public String getProtocol() { return protocol; diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java index f68ce3723a..0c6af0d6f2 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java @@ -52,9 +52,18 @@ public interface RecordsManagementQueryDAO int getCountRmaIdentifier(String identifierValue); /** - * Returns a list of nodeRef for all record folders in the system + * Returns a number of nodeRefs for record folders in the system * that have the property recordSearchHasDispositionSchedule:true - * @return List of nodeRefs + * (used for MNT-20864) + * @param start long - the first result row to return + * @param end long - the last result row to return + * @return list of node refs */ - public List getRecordFoldersWithSchedules(); + public List getRecordFoldersWithSchedules(Long start, Long end); + + /** + * Returns the count of record folders with a schedule applied (used for MNT-20864) + * @return the number of record folders with a disposition schedule + */ + public int getRecordFoldersWithSchedulesCount(); } diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java index 0432e13612..b761d0bd3b 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java @@ -49,7 +49,8 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, { private static final String COUNT_IDENTIFIER = "alfresco.query.rm.select_CountRMIndentifier"; private static final String SCHEDULED_FOLDERS = "alfresco.query.rm.select_RecordFoldersWithSchedules"; - + private static final String SCHEDULED_FOLDERS_COUNT = "alfresco.query.rm.select_RecordFoldersWithSchedulesCount"; + /** SQL session template */ protected SqlSessionTemplate template; @@ -105,9 +106,16 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, * @see org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO#getRecordFoldersWithSchedules() */ @Override - public List getRecordFoldersWithSchedules() + public List getRecordFoldersWithSchedules(Long start, Long end) { - List entities = template.selectList(SCHEDULED_FOLDERS); + Map params = new HashMap(2); + params.put("dispositionQnameId", qnameDAO.getQName(PROP_RS_HAS_DISPOITION_SCHEDULE) + .getFirst()); + params.put("folderQnameId",qnameDAO.getQName(TYPE_RECORD_FOLDER).getFirst()); + params.put("start", start); + params.put("end", end); + + List entities = template.selectList(SCHEDULED_FOLDERS, params); List results = new ArrayList<>(); @@ -120,4 +128,24 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, return results; } + public int getRecordFoldersWithSchedulesCount() + { + int result = 0; + + Map params = new HashMap(2); + params.put("dispositionQnameId", qnameDAO.getQName(PROP_RS_HAS_DISPOITION_SCHEDULE) + .getFirst()); + params.put("folderQnameId", qnameDAO.getQName(TYPE_RECORD_FOLDER) + .getFirst()); + + Integer count = template.selectOne(SCHEDULED_FOLDERS_COUNT, params); + + if (count != null) + { + result = count; + } + + return result; + } + } From efc5281183121bf6486ba414a7496498e352fb4c Mon Sep 17 00:00:00 2001 From: Ross Gale Date: Sun, 17 Nov 2019 22:20:31 +0000 Subject: [PATCH 04/24] RM-7051 adding batch code --- .../module/org_alfresco_module_rm/query/rm-common-SqlMap.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml index 201b68d956..29b744ae05 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml @@ -8,14 +8,14 @@ - + - + From 9783335a3b1af002fe99ea6733cb8afc9a9de599 Mon Sep 17 00:00:00 2001 From: Ross Gale Date: Mon, 18 Nov 2019 10:55:39 +0000 Subject: [PATCH 05/24] RM-7051 adding code to deal with held records/folders --- .../patch/rm-patch-v24-context.xml | 1 + .../v24/RMv24DispositionInheritancePatch.java | 43 ++++++++++++------- 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml index 682a3a0331..475f1d3b39 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml @@ -25,6 +25,7 @@ + \ No newline at end of file diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v24/RMv24DispositionInheritancePatch.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v24/RMv24DispositionInheritancePatch.java index b1fe090b1b..029e4c48fe 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v24/RMv24DispositionInheritancePatch.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v24/RMv24DispositionInheritancePatch.java @@ -28,15 +28,19 @@ package org.alfresco.module.org_alfresco_module_rm.patch.v24; import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.ASPECT_DISPOSITION_LIFECYCLE; +import static org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel.ASPECT_FROZEN; +import java.util.ArrayList; import java.util.List; 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.disposition.DispositionService; +import org.alfresco.module.org_alfresco_module_rm.hold.HoldService; import org.alfresco.module.org_alfresco_module_rm.patch.AbstractModulePatch; import org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO; import org.alfresco.module.org_alfresco_module_rm.record.RecordService; +import org.alfresco.repo.policy.BehaviourFilter; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; @@ -66,6 +70,8 @@ public class RMv24DispositionInheritancePatch extends AbstractModulePatch private RecordsManagementQueryDAO recordsManagementQueryDAO; + private BehaviourFilter behaviourFilter; + public void setDispositionService(DispositionService dispositionService) { this.dispositionService = dispositionService; @@ -86,6 +92,11 @@ public class RMv24DispositionInheritancePatch extends AbstractModulePatch this.recordsManagementQueryDAO = recordsManagementQueryDAO; } + public void setBehaviourFilter(BehaviourFilter behaviourFilter) + { + this.behaviourFilter = behaviourFilter; + } + /** * @see AbstractModulePatch#applyInternal() *

@@ -94,11 +105,10 @@ public class RMv24DispositionInheritancePatch extends AbstractModulePatch @Override public void applyInternal() { - logger.info("********************Patch start********************"); - int maxNode = recordsManagementQueryDAO.getRecordFoldersWithSchedulesCount(); - logger.info("nodes to update: "+ maxNode); + int totalFolders = recordsManagementQueryDAO.getRecordFoldersWithSchedulesCount(); + logger.info("Folders to update: "+ totalFolders); - for (Long i = 0L; i < maxNode; i += BATCH_SIZE) + for (Long i = 0L; i < totalFolders; i += BATCH_SIZE) { final Long finali = i; int updatedRecords = transactionService.getRetryingTransactionHelper() @@ -107,17 +117,14 @@ public class RMv24DispositionInheritancePatch extends AbstractModulePatch public Integer execute() throws Throwable { int recordCount = 0; - logger.info("********************Patch start********************"); - logger.info("********************Query start********************"); - logger.info(finali); - logger.info(finali + BATCH_SIZE); - logger.info(recordsManagementQueryDAO.getRecordFoldersWithSchedules(finali, finali + BATCH_SIZE)); List folders = recordsManagementQueryDAO.getRecordFoldersWithSchedules(finali, finali + BATCH_SIZE); - logger.info("********************Query end********************"); for (NodeRef folder : folders) - { - + if (LOGGER.isDebugEnabled()) + { + logger.info("Checking folder: " + folder); + } + behaviourFilter.disableBehaviour(folder); DispositionSchedule schedule = dispositionService.getDispositionSchedule(folder); if (schedule.isRecordLevelDisposition()) { @@ -126,19 +133,25 @@ public class RMv24DispositionInheritancePatch extends AbstractModulePatch { if (!nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)) { - logger.info("updating record: " + record); + if (LOGGER.isDebugEnabled()) + { + logger.info("updating record: " + record); + } + behaviourFilter.disableBehaviour(record); dispositionService.updateNextDispositionAction(record, schedule); recordCount ++; + behaviourFilter.enableBehaviour(record); } } } + behaviourFilter.enableBehaviour(folder); } - logger.info("********************Patch end********************"); return recordCount; } }, false, true); - logger.info("....completed: "+ updatedRecords); + logger.info("Records updated: "+ updatedRecords); + logger.info("Updating folders: "+ finali + " to: " +(finali + BATCH_SIZE) + " of "+totalFolders); } } } From 8caf6f8c8d12930b62bce89d2fb4d413ece642c1 Mon Sep 17 00:00:00 2001 From: Ross Gale Date: Mon, 18 Nov 2019 14:05:17 +0000 Subject: [PATCH 06/24] RM-7051 updating messaging to report on batch completion --- .../patch/v24/RMv24DispositionInheritancePatch.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v24/RMv24DispositionInheritancePatch.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v24/RMv24DispositionInheritancePatch.java index 029e4c48fe..b08a287f97 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v24/RMv24DispositionInheritancePatch.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/patch/v24/RMv24DispositionInheritancePatch.java @@ -124,10 +124,10 @@ public class RMv24DispositionInheritancePatch extends AbstractModulePatch { logger.info("Checking folder: " + folder); } - behaviourFilter.disableBehaviour(folder); DispositionSchedule schedule = dispositionService.getDispositionSchedule(folder); if (schedule.isRecordLevelDisposition()) { + behaviourFilter.disableBehaviour(folder); List records = recordService.getRecords(folder); for (NodeRef record : records) { @@ -143,8 +143,8 @@ public class RMv24DispositionInheritancePatch extends AbstractModulePatch behaviourFilter.enableBehaviour(record); } } + behaviourFilter.enableBehaviour(folder); } - behaviourFilter.enableBehaviour(folder); } return recordCount; } From 239f81728672162243f0c0e7b268787ffc008623 Mon Sep 17 00:00:00 2001 From: Ross Gale Date: Mon, 18 Nov 2019 23:28:08 +0000 Subject: [PATCH 07/24] RM-7051 updating patch code --- .../model/recordsModel.xml | 5 ++ .../patch/rm-patch-v24-context.xml | 2 + .../query/rm-common-SqlMap.xml | 43 ++++++++++++--- .../model/RecordsManagementModel.java | 1 + .../v24/RMv24DispositionInheritancePatch.java | 55 +++++++++++++++---- 5 files changed, 87 insertions(+), 19 deletions(-) diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml index 8b03748dc2..51300be384 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml @@ -700,6 +700,11 @@ Saved search + + disposition processed + + + Vital Record Definition diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml index 475f1d3b39..3ddc8db447 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml @@ -26,6 +26,8 @@ + + \ No newline at end of file diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml index 29b744ae05..80881da8de 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml @@ -15,6 +15,14 @@ + + + + + + + + @@ -44,21 +52,40 @@ + + - - - - - - + \ No newline at end of file diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java index 0c6af0d6f2..e49aee431c 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java @@ -61,9 +61,4 @@ public interface RecordsManagementQueryDAO */ public List getRecordFoldersWithSchedules(Long start, Long end); - /** - * Returns the count of record folders with a schedule applied (used for MNT-20864) - * @return the number of record folders with a disposition schedule - */ - public int getRecordFoldersWithSchedulesCount(); } diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java index 333fefe657..1293ddf911 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java @@ -48,7 +48,7 @@ import org.mybatis.spring.SqlSessionTemplate; public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, RecordsManagementModel { private static final String COUNT_IDENTIFIER = "alfresco.query.rm.select_CountRMIndentifier"; - private static final String SCHEDULED_FOLDERS = "alfresco.query.rm.select_RecordFoldersWithSchedulesExtended"; + private static final String SCHEDULED_FOLDERS = "alfresco.query.rm.select_RecordFoldersWithSchedules"; private static final String SCHEDULED_FOLDERS_COUNT = "alfresco.query.rm.select_RecordFoldersWithSchedulesCount"; /** SQL session template */ @@ -130,24 +130,4 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, return results; } - public int getRecordFoldersWithSchedulesCount() - { - int result = 0; - - Map params = new HashMap(2); - params.put("dispositionQnameId", qnameDAO.getQName(PROP_RS_HAS_DISPOITION_SCHEDULE) - .getFirst()); - params.put("folderQnameId", qnameDAO.getQName(TYPE_RECORD_FOLDER) - .getFirst()); - - Integer count = template.selectOne(SCHEDULED_FOLDERS_COUNT, params); - - if (count != null) - { - result = count; - } - - return result; - } - } From 7d7946ea0684c7da271ff5f6f522fa206a288dde Mon Sep 17 00:00:00 2001 From: Ross Gale Date: Wed, 20 Nov 2019 10:51:33 +0000 Subject: [PATCH 11/24] RM-7051 running the find records and update as system --- .../schedule/UpdateRecordScheduleGet.java | 90 +++++++++++-------- 1 file changed, 51 insertions(+), 39 deletions(-) diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java index effba5a757..211a978e97 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java @@ -63,6 +63,7 @@ import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.repo.domain.node.NodeDAO; import org.alfresco.repo.domain.qname.QNameDAO; import org.alfresco.repo.policy.BehaviourFilter; +import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.cmr.repository.NodeService; @@ -350,45 +351,56 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record return value; } - - private int updateRecordFolder(final NodeRef recordFolder) + + private int updateRecordFolder(final NodeRef recordFolder) { - return transactionService.getRetryingTransactionHelper() - .doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() - { - public Integer execute() throws Throwable - { - int recordCount = 0; - - behaviourFilter.disableBehaviour(recordFolder); - if (logger.isDebugEnabled()) - { - logger.info("Checking folder: " + recordFolder); - } - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordFolder); - if (schedule.isRecordLevelDisposition()) - { - List records = recordService.getRecords(recordFolder); - for (NodeRef record : records) - { - if (!nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)) - { - if (logger.isDebugEnabled()) - { - logger.info("updating record: " + record); - } - behaviourFilter.disableBehaviour(record); - dispositionService.updateNextDispositionAction(record, schedule); - recordCount ++; - behaviourFilter.enableBehaviour(record); - } - } - } - nodeService.addAspect(recordFolder, ASPECT_DISPOSITION_PROCESSED, null); - behaviourFilter.enableBehaviour(recordFolder); - - return recordCount; - } - }, false, true); + return transactionService.getRetryingTransactionHelper() + .doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + public Integer execute() throws Throwable + { + int recordCount = 0; + + behaviourFilter.disableBehaviour(recordFolder); + if (logger.isDebugEnabled()) + { + logger.info("Checking folder: " + recordFolder); + } + recordCount = AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork() + { + @Override + public Integer doWork() throws Exception + { + DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordFolder); + int innerRecordCount = 0; + if (schedule.isRecordLevelDisposition()) + { + + List records = recordService.getRecords(recordFolder); + for (NodeRef record : records) + { + if (!nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)) + { + if (logger.isDebugEnabled()) + { + logger.info("updating record: " + record); + } + behaviourFilter.disableBehaviour(record); + dispositionService.updateNextDispositionAction(record, schedule); + innerRecordCount++; + behaviourFilter.enableBehaviour(record); + + } + } + + } + return innerRecordCount; + } + }); + nodeService.addAspect(recordFolder, ASPECT_DISPOSITION_PROCESSED, null); + behaviourFilter.enableBehaviour(recordFolder); + return recordCount; + } + }, false, true); } } From 9bf4f1d9d901d24122416b74e322e8af81f3bd23 Mon Sep 17 00:00:00 2001 From: Ross Gale Date: Wed, 20 Nov 2019 13:33:35 +0000 Subject: [PATCH 12/24] RM-7051 updating messaging --- .../web/scripts/schedule/UpdateRecordScheduleGet.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java index 211a978e97..2eee54ef37 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java @@ -97,6 +97,7 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record private static final String MODEL_STATUS = "responsestatus"; private static final String MODEL_MESSAGE = "message"; private static final String MESSAGE_ALL_TEMPLATE = "Updated {0} records with updated disposition instructions."; + private static final String MESSAGE_FOLDER_TEMPLATE = "Updated records in folder {0} with updated disposition instructions."; /** services */ private NodeService nodeService; @@ -170,11 +171,12 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record NodeRef recordFolder = getRecordFolder(req); int processedRecords = 0; - + String message; if (recordFolder != null) { // Process the specified record folder - processedRecords = processedRecords + updateRecordFolder(recordFolder); + updateRecordFolder(recordFolder); + message = MessageFormat.format(MESSAGE_FOLDER_TEMPLATE, recordFolder); } else { @@ -202,10 +204,9 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record break; } } + message = MessageFormat.format(MESSAGE_ALL_TEMPLATE, processedRecords); } - String message = MessageFormat.format(MESSAGE_ALL_TEMPLATE, processedRecords); - model.put(MODEL_STATUS, SUCCESS_STATUS); model.put(MODEL_MESSAGE, message); logger.info(message); From bbadc9799e24afb07eb2c1877f42f9706f229fee Mon Sep 17 00:00:00 2001 From: Ross Gale Date: Thu, 21 Nov 2019 01:16:37 +0000 Subject: [PATCH 13/24] RM-7051 simplyfing sql and adding check for links --- .../query/rm-common-SqlMap.xml | 10 ++------- .../query/RecordsManagementQueryDAOImpl.java | 2 -- .../schedule/UpdateRecordScheduleGet.java | 21 +++++++++++-------- 3 files changed, 14 insertions(+), 19 deletions(-) diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml index be7f12f03d..2aff927c18 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml @@ -9,7 +9,6 @@ - @@ -42,15 +41,10 @@ select alfn.id , alfs.protocol, alfs.identifier, alfn.uuid from alf_node alfn, alf_store alfs - where alfn.id in ( - select node_id - from alf_node_properties - where qname_id = ? - and boolean_value = true - and node_id not in ( + where alfn.id not in ( select node_id from alf_node_aspects - where qname_id = ? )) + where qname_id = ? ) and type_qname_id = ? and alfn.store_id = alfs.id and alfn.id between ? and ? diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java index 1293ddf911..372e2aede4 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java @@ -109,8 +109,6 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, public List getRecordFoldersWithSchedules(Long start, Long end) { Map params = new HashMap(2); - params.put("dispositionQnameId", qnameDAO.getQName(PROP_RS_HAS_DISPOITION_SCHEDULE) - .getFirst()); params.put("processed", qnameDAO.getQName(ASPECT_DISPOSITION_PROCESSED) .getFirst()); params.put("folderQnameId",qnameDAO.getQName(TYPE_RECORD_FOLDER).getFirst()); diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java index 2eee54ef37..86213aff12 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java @@ -96,7 +96,7 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record private static final String SUCCESS_STATUS = "success"; private static final String MODEL_STATUS = "responsestatus"; private static final String MODEL_MESSAGE = "message"; - private static final String MESSAGE_ALL_TEMPLATE = "Updated {0} records with updated disposition instructions."; + private static final String MESSAGE_ALL_TEMPLATE = "Updated {0} records from {1} folders with updated disposition instructions."; private static final String MESSAGE_FOLDER_TEMPLATE = "Updated records in folder {0} with updated disposition instructions."; /** services */ @@ -204,7 +204,7 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record break; } } - message = MessageFormat.format(MESSAGE_ALL_TEMPLATE, processedRecords); + message = MessageFormat.format(MESSAGE_ALL_TEMPLATE, processedRecords, processedRecordFolders); } model.put(MODEL_STATUS, SUCCESS_STATUS); @@ -374,7 +374,7 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record { DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordFolder); int innerRecordCount = 0; - if (schedule.isRecordLevelDisposition()) + if (schedule != null && schedule.isRecordLevelDisposition()) { List records = recordService.getRecords(recordFolder); @@ -382,14 +382,17 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record { if (!nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)) { - if (logger.isDebugEnabled()) + if (recordFolder.equals(nodeService.getPrimaryParent(record).getParentRef())) { - logger.info("updating record: " + record); + if (logger.isDebugEnabled()) + { + logger.info("updating record: " + record); + } + behaviourFilter.disableBehaviour(record); + dispositionService.updateNextDispositionAction(record, schedule); + innerRecordCount++; + behaviourFilter.enableBehaviour(record); } - behaviourFilter.disableBehaviour(record); - dispositionService.updateNextDispositionAction(record, schedule); - innerRecordCount++; - behaviourFilter.enableBehaviour(record); } } From 42e6fbdb6a5794e701fb87e8b9dcf42936095ee9 Mon Sep 17 00:00:00 2001 From: Roy Wetherall Date: Thu, 21 Nov 2019 13:54:09 +1100 Subject: [PATCH 14/24] Prevent unwanted audit entries appearing when updating the records --- .../schedule/UpdateRecordScheduleGet.java | 84 ++++++++++--------- 1 file changed, 45 insertions(+), 39 deletions(-) diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java index 86213aff12..8e9c3c92d5 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java @@ -361,48 +361,54 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record public Integer execute() throws Throwable { int recordCount = 0; - - behaviourFilter.disableBehaviour(recordFolder); - if (logger.isDebugEnabled()) + + behaviourFilter.disableBehaviour(ASPECT_FILE_PLAN_COMPONENT); + try { - logger.info("Checking folder: " + recordFolder); + if (logger.isDebugEnabled()) + { + logger.info("Checking folder: " + recordFolder); + } + recordCount = AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork() + { + @Override + public Integer doWork() throws Exception + { + DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordFolder); + int innerRecordCount = 0; + if (schedule != null && schedule.isRecordLevelDisposition()) + { + + List records = recordService.getRecords(recordFolder); + for (NodeRef record : records) + { + if (!nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)) + { + if (recordFolder.equals(nodeService.getPrimaryParent(record).getParentRef())) + { + if (logger.isDebugEnabled()) + { + logger.info("updating record: " + record); + } + + // update record disposition information + dispositionService.updateNextDispositionAction(record, schedule); + innerRecordCount++; + } + } + } + + } + return innerRecordCount; + } + }); + + nodeService.addAspect(recordFolder, ASPECT_DISPOSITION_PROCESSED, null); } - recordCount = AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork() + finally { - @Override - public Integer doWork() throws Exception - { - DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordFolder); - int innerRecordCount = 0; - if (schedule != null && schedule.isRecordLevelDisposition()) - { - - List records = recordService.getRecords(recordFolder); - for (NodeRef record : records) - { - if (!nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)) - { - if (recordFolder.equals(nodeService.getPrimaryParent(record).getParentRef())) - { - if (logger.isDebugEnabled()) - { - logger.info("updating record: " + record); - } - behaviourFilter.disableBehaviour(record); - dispositionService.updateNextDispositionAction(record, schedule); - innerRecordCount++; - behaviourFilter.enableBehaviour(record); - } - - } - } - - } - return innerRecordCount; - } - }); - nodeService.addAspect(recordFolder, ASPECT_DISPOSITION_PROCESSED, null); - behaviourFilter.enableBehaviour(recordFolder); + behaviourFilter.enableBehaviour(ASPECT_FILE_PLAN_COMPONENT); + } return recordCount; } }, false, true); From fbf379d6f2701c55dcce7c06e6db874adef1d938 Mon Sep 17 00:00:00 2001 From: Ross Gale Date: Thu, 21 Nov 2019 11:04:35 +0000 Subject: [PATCH 15/24] RM-7051 review comments --- .../model/recordsModel.xml | 3 +- .../query/rm-common-SqlMap.xml | 3 +- .../rm-webscript-context.xml | 4 +- .../rm-updaterecordschedule.get.desc.xml | 8 +- .../disposition/DispositionService.java | 4 +- .../disposition/DispositionServiceImpl.java | 14 +- .../query/RecordsManagementQueryDAO.java | 2 +- .../query/RecordsManagementQueryDAOImpl.java | 10 +- .../schedule/UpdateRecordScheduleGet.java | 173 ++++++++++-------- 9 files changed, 119 insertions(+), 102 deletions(-) diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml index 51300be384..51dd360d23 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml @@ -701,10 +701,9 @@ - disposition processed + Disposition processed - Vital Record Definition diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml index 2aff927c18..5314ebe76a 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml @@ -39,8 +39,7 @@ parameterMap="parameter_folderPatchPaging" resultMap="result_NodeRefEntity"> select alfn.id , alfs.protocol, alfs.identifier, alfn.uuid - from alf_node alfn, - alf_store alfs + from alf_node alfn, alf_store alfs where alfn.id not in ( select node_id from alf_node_aspects diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml index 30477644fa..0215c04957 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml @@ -666,10 +666,10 @@ - + + parent="webscript"> diff --git a/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.desc.xml b/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.desc.xml index 7d1df216f7..8ff54084a0 100644 --- a/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.desc.xml +++ b/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.desc.xml @@ -1,9 +1,9 @@ - Updates Record Schedules based on Hierarchical Disposition Instructions + Updates Record Schedules based on Hierarchical Retention Instructions - URL parameter maxRecordFolders is optional, and represents the maximum number of record folders that should be processed. If not specified maxRecordFolders will be set to 10000
- URL parameter recordFolder is optional, and represents the nodeRef of a record folder who's records should be processed. If specified then maxRecordFolders will be ignored.
+ Updates records schedules by reviewing retention instructions defined within the principle hierarchy.
+ URL parameter maxRecordFolders is optional, and represents the maximum number of record folders that should be processed. If not specified maxRecordFolders will be set to the max value for an integer.
+ URL parameter recordFolder is optional, and represents the nodeRef of a record folder whose records should be processed. If specified then maxRecordFolders will be ignored.
]]>
/api/rm/rm-updateRecordSchedule?maxRecordFolders={maxRecordFolders?}&recordFolder={recordFolder?} diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java index 2ba7dbcc0e..dccc56df6b 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java @@ -240,8 +240,8 @@ public interface DispositionService /** * Updates the next disposition action * - * @param nodeRef node reference - * @param DispositionSchedule the schedule to be applied + * @param nodeRef node reference + * @param dispositionSchedule the schedule to be applied */ void updateNextDispositionAction(NodeRef nodeRef, DispositionSchedule dispositionSchedule); diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java index 78087ffffd..e044026c75 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java @@ -953,9 +953,9 @@ public class DispositionServiceImpl extends ServiceBaseImpl public Void doWork() { // Get this disposition instructions for the node - DispositionSchedule di = getDispositionSchedule(nodeRef); + DispositionSchedule dispositionSchedule = getDispositionSchedule(nodeRef); - updateNextDispositionAction(nodeRef, di); + updateNextDispositionAction(nodeRef, dispositionSchedule); return null; } @@ -969,7 +969,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl * @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#updateNextDispositionAction(NodeRef) */ @Override - public void updateNextDispositionAction(final NodeRef nodeRef, final DispositionSchedule di) + public void updateNextDispositionAction(final NodeRef nodeRef, final DispositionSchedule dispositionSchedule) { @@ -982,7 +982,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl public Void doWork() { - if (di != null) + if (dispositionSchedule != null) { // Get the current action node NodeRef currentDispositionAction = null; @@ -1001,7 +1001,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl nodeService.moveNode(currentDispositionAction, nodeRef, ASSOC_DISPOSITION_ACTION_HISTORY, ASSOC_DISPOSITION_ACTION_HISTORY); } - List dispositionActionDefinitions = di.getDispositionActionDefinitions(); + List dispositionActionDefinitions = dispositionSchedule.getDispositionActionDefinitions(); DispositionActionDefinition currentDispositionActionDefinition = null; DispositionActionDefinition nextDispositionActionDefinition = null; @@ -1017,14 +1017,14 @@ public class DispositionServiceImpl extends ServiceBaseImpl { // Get the current action String currentADId = (String) nodeService.getProperty(currentDispositionAction, PROP_DISPOSITION_ACTION_ID); - currentDispositionActionDefinition = di.getDispositionActionDefinition(currentADId); + currentDispositionActionDefinition = dispositionSchedule.getDispositionActionDefinition(currentADId); // When the record has multiple disposition schedules the current disposition action may not be found by id // In this case it will be searched by name if(currentDispositionActionDefinition == null) { String currentADName = (String) nodeService.getProperty(currentDispositionAction, PROP_DISPOSITION_ACTION); - currentDispositionActionDefinition = di.getDispositionActionDefinitionByName(currentADName); + currentDispositionActionDefinition = dispositionSchedule.getDispositionActionDefinitionByName(currentADName); } // Get the next disposition action diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java index e49aee431c..eac96d6f45 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java @@ -59,6 +59,6 @@ public interface RecordsManagementQueryDAO * @param end long - the last result row to return * @return list of node refs */ - public List getRecordFoldersWithSchedules(Long start, Long end); + List getRecordFoldersWithSchedules(Long start, Long end); } diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java index 372e2aede4..3eb65251e0 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java @@ -103,15 +103,16 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, } /** - * @see org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO#getRecordFoldersWithSchedules() + * @see org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO#getRecordFoldersWithSchedules(Long, Long) */ @Override public List getRecordFoldersWithSchedules(Long start, Long end) { - Map params = new HashMap(2); + Map params = new HashMap<>(2); params.put("processed", qnameDAO.getQName(ASPECT_DISPOSITION_PROCESSED) .getFirst()); - params.put("folderQnameId",qnameDAO.getQName(TYPE_RECORD_FOLDER).getFirst()); + params.put("folderQnameId", qnameDAO.getQName(TYPE_RECORD_FOLDER) + .getFirst()); params.put("start", start); params.put("end", end); @@ -122,7 +123,8 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, // convert the entities to NodeRefs for (NodeRefEntity nodeRefEntity : entities) { - results.add(new NodeRef(nodeRefEntity.getProtocol(), nodeRefEntity.getIdentifier(), nodeRefEntity.getUuid())); + results.add( + new NodeRef(nodeRefEntity.getProtocol(), nodeRefEntity.getIdentifier(), nodeRefEntity.getUuid())); } return results; diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java index 86213aff12..5f4f15acc5 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java @@ -42,6 +42,7 @@ * You should have received a copy of the GNU Lesser General Public License * along with Alfresco. If not, see . */ + package org.alfresco.repo.web.scripts.schedule; import java.io.IOException; @@ -86,20 +87,26 @@ import org.springframework.extensions.webscripts.WebScriptResponse; */ public class UpdateRecordScheduleGet extends AbstractWebScript implements RecordsManagementModel { - /** logger */ + /** + * logger + */ private static Log logger = LogFactory.getLog(UpdateRecordScheduleGet.class); - - /** parameters */ + + /** + * parameters + */ private static final String PARAM_MAX_RECORD_FOLDERS = "maxRecordFolders"; private static final String PARAM_RECORD_FOLDER = "recordFolder"; - - private static final String SUCCESS_STATUS = "success"; + + private static final String SUCCESS_STATUS = "success"; private static final String MODEL_STATUS = "responsestatus"; private static final String MODEL_MESSAGE = "message"; private static final String MESSAGE_ALL_TEMPLATE = "Updated {0} records from {1} folders with updated disposition instructions."; private static final String MESSAGE_FOLDER_TEMPLATE = "Updated records in folder {0} with updated disposition instructions."; - /** services */ + /** + * services + */ private NodeService nodeService; private DispositionService dispositionService; private RecordService recordService; @@ -108,54 +115,56 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record private BehaviourFilter behaviourFilter; private NodeDAO nodeDAO; private QNameDAO qnameDAO; - - /** service setters */ + + /** + * service setters + */ public void setNodeService(NodeService nodeService) { this.nodeService = nodeService; } - public void setRecordsManagementQueryDAO(RecordsManagementQueryDAO recordsManagementQueryDAO) + public void setRecordsManagementQueryDAO(RecordsManagementQueryDAO recordsManagementQueryDAO) { - this.recordsManagementQueryDAO = recordsManagementQueryDAO; - } - - public void setRecordService(RecordService recordService) - { - this.recordService = recordService; - } + this.recordsManagementQueryDAO = recordsManagementQueryDAO; + } - public void setDispositionService(DispositionService dispositionService) + public void setRecordService(RecordService recordService) { - this.dispositionService = dispositionService; - } - + this.recordService = recordService; + } + + public void setDispositionService(DispositionService dispositionService) + { + this.dispositionService = dispositionService; + } + public void setTransactionService(TransactionService transactionService) { this.transactionService = transactionService; } - - public void setBehaviourFilter(BehaviourFilter behaviourFilter) - { - this.behaviourFilter = behaviourFilter; - } - - public void setNodeDAO(NodeDAO nodeDAO) - { - this.nodeDAO = nodeDAO; - } - public void setQnameDAO(QNameDAO qnameDAO) + public void setBehaviourFilter(BehaviourFilter behaviourFilter) { - this.qnameDAO = qnameDAO; - } - + this.behaviourFilter = behaviourFilter; + } + + public void setNodeDAO(NodeDAO nodeDAO) + { + this.nodeDAO = nodeDAO; + } + + public void setQnameDAO(QNameDAO qnameDAO) + { + this.qnameDAO = qnameDAO; + } + /** * Build web script model */ protected Map buildModel(WebScriptRequest req, WebScriptResponse res) throws IOException { - Map model = new HashMap(); + Map model = new HashMap<>(); transactionService.getRetryingTransactionHelper() .doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() { @@ -165,7 +174,7 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record return null; } - },false,true); + }, false, true); int maxRecordFolders = getMaxRecordFolders(req); NodeRef recordFolder = getRecordFolder(req); @@ -174,35 +183,35 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record String message; if (recordFolder != null) { - // Process the specified record folder - updateRecordFolder(recordFolder); + // Process the specified record folder + updateRecordFolder(recordFolder); message = MessageFormat.format(MESSAGE_FOLDER_TEMPLATE, recordFolder); } else { - int processedRecordFolders = 0; - int queryBatchSize = 10000; - Long maxNodeId = nodeDAO.getMaxNodeId(); - for (Long i = 0L; i < maxNodeId; i += queryBatchSize) + int processedRecordFolders = 0; + int queryBatchSize = 10000; + Long maxNodeId = nodeDAO.getMaxNodeId(); + for (Long i = 0L; i < maxNodeId; i += queryBatchSize) { List folders = recordsManagementQueryDAO.getRecordFoldersWithSchedules(i, i + queryBatchSize); for (NodeRef folder : folders) { - processedRecords = processedRecords + updateRecordFolder(folder); - processedRecordFolders++; - - if (processedRecordFolders >= maxRecordFolders) - { - // stop processing since we have meet our limit - break; - } + processedRecords = processedRecords + updateRecordFolder(folder); + processedRecordFolders++; + + if (processedRecordFolders >= maxRecordFolders) + { + // stop processing since we have meet our limit + break; + } } - + if (processedRecordFolders >= maxRecordFolders) - { - // stop processing since we have meet our limit - break; - } + { + // stop processing since we have meet our limit + break; + } } message = MessageFormat.format(MESSAGE_ALL_TEMPLATE, processedRecords, processedRecordFolders); } @@ -227,18 +236,19 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record try { - String mimetype = getContainer().getFormatRegistry().getMimeType(req.getAgent(), format); - if (mimetype == null) - { + String mimetype = getContainer().getFormatRegistry() + .getMimeType(req.getAgent(), format); + if (mimetype == null) + { throw new WebScriptException("Web Script format '" + format + "' is not registered"); } // construct model for script / template Status status = new Status(); Cache cache = new Cache(getDescription().getRequiredCache()); - + Map model = buildModel(req, res); - + if (model == null) { return; } model.put("status", status); model.put("cache", cache); @@ -261,7 +271,8 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record String location = status.getLocation(); if (location != null && location.length() > 0) { - if (logger.isDebugEnabled()) logger.debug("Setting location to " + location); + if (logger.isDebugEnabled()) + logger.debug("Setting location to " + location); res.setHeader(WebScriptResponse.HEADER_LOCATION, location); } @@ -275,12 +286,15 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record } if (format.equals(WebScriptResponse.JSON_FORMAT) && callback != null) { - if (logger.isDebugEnabled()) logger.debug("Rendering JSON callback response: content type=" - + Format.JAVASCRIPT.mimetype() + ", status=" + statusCode + ", callback=" + callback); + if (logger.isDebugEnabled()) + logger.debug( + "Rendering JSON callback response: content type=" + Format.JAVASCRIPT.mimetype() + ", status=" + + statusCode + ", callback=" + callback); // NOTE: special case for wrapping JSON results in a javascript function callback res.setContentType(Format.JAVASCRIPT.mimetype() + ";charset=UTF-8"); - res.getWriter().write((callback + "(")); + res.getWriter() + .write((callback + "(")); } else { @@ -296,7 +310,8 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record if (format.equals(WebScriptResponse.JSON_FORMAT) && callback != null) { // NOTE: special case for wrapping JSON results in a javascript function callback - res.getWriter().write(")"); + res.getWriter() + .write(")"); } } catch (Throwable e) @@ -318,7 +333,8 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record String templatePath = getDescription().getId() + "." + format; - if (logger.isDebugEnabled()) logger.debug("Rendering template '" + templatePath + "'"); + if (logger.isDebugEnabled()) + logger.debug("Rendering template '" + templatePath + "'"); renderTemplate(templatePath, model, writer); } @@ -333,24 +349,24 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record { value = Integer.parseInt(valueStr); } - catch(NumberFormatException ex) + catch (NumberFormatException ex) { //do nothing here, the value will remain 0L in this case } } return value; - } - + } + protected NodeRef getRecordFolder(WebScriptRequest req) { - String valueStr = req.getParameter(PARAM_RECORD_FOLDER); - NodeRef value = null; - if (StringUtils.isNotBlank(valueStr)) - { - value = new NodeRef(valueStr); - } - - return value; + String valueStr = req.getParameter(PARAM_RECORD_FOLDER); + NodeRef value = null; + if (StringUtils.isNotBlank(valueStr)) + { + value = new NodeRef(valueStr); + } + + return value; } private int updateRecordFolder(final NodeRef recordFolder) @@ -382,7 +398,8 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record { if (!nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)) { - if (recordFolder.equals(nodeService.getPrimaryParent(record).getParentRef())) + if (recordFolder.equals(nodeService.getPrimaryParent(record) + .getParentRef())) { if (logger.isDebugEnabled()) { From 7fba698dd89f056333caf4b1bbd6ba1ff1a53616 Mon Sep 17 00:00:00 2001 From: alfresco-build Date: Thu, 21 Nov 2019 18:15:29 +0000 Subject: [PATCH 16/24] [maven-release-plugin] prepare release V2.5.3.3 --- pom.xml | 4 ++-- rm-automation/pom.xml | 2 +- rm-community/pom.xml | 2 +- rm-community/rm-community-repo/pom.xml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 4797d209c1..6e30593f25 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.alfresco alfresco-rm pom - 2.5.3.3-SNAPSHOT + 2.5.3.3 Alfresco Records Management @@ -24,7 +24,7 @@ scm:git:https://git.alfresco.com/records-management/records-management.git scm:git:https://git.alfresco.com/records-management/records-management.git https://git.alfresco.com/records-management/records-management - V2.5.3 + V2.5.3.3 diff --git a/rm-automation/pom.xml b/rm-automation/pom.xml index c61d666c8e..cba0601acb 100644 --- a/rm-automation/pom.xml +++ b/rm-automation/pom.xml @@ -8,7 +8,7 @@ org.alfresco alfresco-rm - 2.5.3.3-SNAPSHOT + 2.5.3.3 diff --git a/rm-community/pom.xml b/rm-community/pom.xml index 73c9631e3e..1bef20a0df 100644 --- a/rm-community/pom.xml +++ b/rm-community/pom.xml @@ -8,7 +8,7 @@ org.alfresco alfresco-rm - 2.5.3.3-SNAPSHOT + 2.5.3.3 diff --git a/rm-community/rm-community-repo/pom.xml b/rm-community/rm-community-repo/pom.xml index 7e79f8c07f..9c4d521566 100644 --- a/rm-community/rm-community-repo/pom.xml +++ b/rm-community/rm-community-repo/pom.xml @@ -9,7 +9,7 @@ org.alfresco alfresco-rm-community - 2.5.3.3-SNAPSHOT + 2.5.3.3 From 3c0a62fa815e13c52c26b2fa6769ff674f558d93 Mon Sep 17 00:00:00 2001 From: alfresco-build Date: Thu, 21 Nov 2019 18:15:33 +0000 Subject: [PATCH 17/24] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- rm-automation/pom.xml | 2 +- rm-community/pom.xml | 2 +- rm-community/rm-community-repo/pom.xml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 6e30593f25..57eee00ace 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.alfresco alfresco-rm pom - 2.5.3.3 + -SNAPSHOT Alfresco Records Management @@ -24,7 +24,7 @@ scm:git:https://git.alfresco.com/records-management/records-management.git scm:git:https://git.alfresco.com/records-management/records-management.git https://git.alfresco.com/records-management/records-management - V2.5.3.3 + V2.5.3 diff --git a/rm-automation/pom.xml b/rm-automation/pom.xml index cba0601acb..a4535a14f7 100644 --- a/rm-automation/pom.xml +++ b/rm-automation/pom.xml @@ -8,7 +8,7 @@ org.alfresco alfresco-rm - 2.5.3.3 + -SNAPSHOT diff --git a/rm-community/pom.xml b/rm-community/pom.xml index 1bef20a0df..f71ea772c9 100644 --- a/rm-community/pom.xml +++ b/rm-community/pom.xml @@ -8,7 +8,7 @@ org.alfresco alfresco-rm - 2.5.3.3 + -SNAPSHOT diff --git a/rm-community/rm-community-repo/pom.xml b/rm-community/rm-community-repo/pom.xml index 9c4d521566..311609cbc4 100644 --- a/rm-community/rm-community-repo/pom.xml +++ b/rm-community/rm-community-repo/pom.xml @@ -9,7 +9,7 @@ org.alfresco alfresco-rm-community - 2.5.3.3 + -SNAPSHOT From b6a7b93a527e95b8efc8ca22fee8a23252038c5d Mon Sep 17 00:00:00 2001 From: Ross Gale Date: Fri, 22 Nov 2019 08:55:41 +0000 Subject: [PATCH 18/24] Updating version number after release --- pom.xml | 2 +- rm-automation/pom.xml | 2 +- rm-community/pom.xml | 2 +- rm-community/rm-community-repo/pom.xml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/pom.xml b/pom.xml index 57eee00ace..37c07218a2 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.alfresco alfresco-rm pom - -SNAPSHOT + 2.5.3.4-SNAPSHOT Alfresco Records Management diff --git a/rm-automation/pom.xml b/rm-automation/pom.xml index a4535a14f7..88ba6b6d02 100644 --- a/rm-automation/pom.xml +++ b/rm-automation/pom.xml @@ -8,7 +8,7 @@ org.alfresco alfresco-rm - -SNAPSHOT + 2.5.3.4-SNAPSHOT diff --git a/rm-community/pom.xml b/rm-community/pom.xml index f71ea772c9..e820c70be9 100644 --- a/rm-community/pom.xml +++ b/rm-community/pom.xml @@ -8,7 +8,7 @@ org.alfresco alfresco-rm - -SNAPSHOT + 2.5.3.4-SNAPSHOT diff --git a/rm-community/rm-community-repo/pom.xml b/rm-community/rm-community-repo/pom.xml index 311609cbc4..21601dee66 100644 --- a/rm-community/rm-community-repo/pom.xml +++ b/rm-community/rm-community-repo/pom.xml @@ -9,7 +9,7 @@ org.alfresco alfresco-rm-community - -SNAPSHOT + 2.5.3.4-SNAPSHOT From 92c8c2db21cf7e8ba4f6676f824160c2b6853532 Mon Sep 17 00:00:00 2001 From: Ross Gale Date: Fri, 22 Nov 2019 14:25:27 +0000 Subject: [PATCH 19/24] Merge branch 'hotfix-2.5/RM-7051_Disposition' into 'release/V2.5.3.x' Resolve RM-7051 "Hotfix 2.5/ disposition" See merge request records-management/records-management!1303 Adds web script to ensure all records have correct disposition instructions --- .../model/recordsModel.xml | 4 + .../patch/rm-patch-v24-context.xml | 2 +- .../query/rm-common-SqlMap.xml | 35 +- .../rm-webscript-context.xml | 15 + .../org_alfresco_module_rm/version.properties | 2 +- .../rm-updaterecordschedule.get.desc.xml | 13 + .../rm-updaterecordschedule.get.json.ftl | 30 ++ .../disposition/DispositionService.java | 8 + .../disposition/DispositionServiceImpl.java | 38 +- .../model/RecordsManagementModel.java | 1 + .../query/NodeRefEntity.java | 88 ++++ .../query/RecordsManagementQueryDAO.java | 15 + .../query/RecordsManagementQueryDAOImpl.java | 35 +- .../schedule/UpdateRecordScheduleGet.java | 430 ++++++++++++++++++ 14 files changed, 705 insertions(+), 11 deletions(-) create mode 100644 rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.desc.xml create mode 100644 rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.json.ftl create mode 100644 rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/NodeRefEntity.java create mode 100644 rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml index 8b03748dc2..51dd360d23 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml @@ -700,6 +700,10 @@ Saved search
+ + Disposition processed + + Vital Record Definition diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml index e3e843041e..b2527baa9f 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml @@ -14,5 +14,5 @@ - + \ No newline at end of file diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml index e3f1c1a89d..5314ebe76a 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml @@ -7,8 +7,23 @@ - - select count(*) from @@ -19,5 +34,19 @@ prop.string_value = ? - + + + \ No newline at end of file diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml index d4f8b73a05..0215c04957 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml @@ -665,4 +665,19 @@ parent="rmBaseWebscript"> + + + + + + + + + + + + + \ No newline at end of file diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties index cf2c7c2600..8cce8ad3ce 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties @@ -1,3 +1,3 @@ # RM Schema number -version.rm.schema=2501 +version.rm.schema=2502 diff --git a/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.desc.xml b/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.desc.xml new file mode 100644 index 0000000000..8ff54084a0 --- /dev/null +++ b/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.desc.xml @@ -0,0 +1,13 @@ + + Updates Record Schedules based on Hierarchical Retention Instructions + + URL parameter maxRecordFolders is optional, and represents the maximum number of record folders that should be processed. If not specified maxRecordFolders will be set to the max value for an integer.
+ URL parameter recordFolder is optional, and represents the nodeRef of a record folder whose records should be processed. If specified then maxRecordFolders will be ignored.
+ ]]> +
+ /api/rm/rm-updateRecordSchedule?maxRecordFolders={maxRecordFolders?}&recordFolder={recordFolder?} + argument + admin + required +
\ No newline at end of file diff --git a/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.json.ftl b/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.json.ftl new file mode 100644 index 0000000000..2b395291a4 --- /dev/null +++ b/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.json.ftl @@ -0,0 +1,30 @@ +<#-- + #%L + Alfresco Records Management Module + %% + Copyright (C) 2005 - 2019 Alfresco Software Limited + %% + This file is part of the Alfresco software. + - + If the software was purchased under a paid Alfresco license, the terms of + the paid license agreement will prevail. Otherwise, the software is + provided under the following open source license terms: + - + 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 . + #L% +--> +{ + "responsestatus" : "${responsestatus?json_string}", + "message" : "${message?json_string}" +} diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java index 4da6fde0dd..dccc56df6b 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java @@ -237,6 +237,14 @@ public interface DispositionService */ void updateNextDispositionAction(NodeRef nodeRef); + /** + * Updates the next disposition action + * + * @param nodeRef node reference + * @param dispositionSchedule the schedule to be applied + */ + void updateNextDispositionAction(NodeRef nodeRef, DispositionSchedule dispositionSchedule); + /** * Refreshes the disposition action details of the given node. * diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java index 32f68c1bb5..e044026c75 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java @@ -953,8 +953,36 @@ public class DispositionServiceImpl extends ServiceBaseImpl public Void doWork() { // Get this disposition instructions for the node - DispositionSchedule di = getDispositionSchedule(nodeRef); - if (di != null) + DispositionSchedule dispositionSchedule = getDispositionSchedule(nodeRef); + + updateNextDispositionAction(nodeRef, dispositionSchedule); + + return null; + } + + }; + + AuthenticationUtil.runAsSystem(runAsWork); + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#updateNextDispositionAction(NodeRef) + */ + @Override + public void updateNextDispositionAction(final NodeRef nodeRef, final DispositionSchedule dispositionSchedule) + { + + + RunAsWork runAsWork = new RunAsWork() + { + /** + * @see org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork#doWork() + */ + @Override + public Void doWork() + { + + if (dispositionSchedule != null) { // Get the current action node NodeRef currentDispositionAction = null; @@ -973,7 +1001,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl nodeService.moveNode(currentDispositionAction, nodeRef, ASSOC_DISPOSITION_ACTION_HISTORY, ASSOC_DISPOSITION_ACTION_HISTORY); } - List dispositionActionDefinitions = di.getDispositionActionDefinitions(); + List dispositionActionDefinitions = dispositionSchedule.getDispositionActionDefinitions(); DispositionActionDefinition currentDispositionActionDefinition = null; DispositionActionDefinition nextDispositionActionDefinition = null; @@ -989,14 +1017,14 @@ public class DispositionServiceImpl extends ServiceBaseImpl { // Get the current action String currentADId = (String) nodeService.getProperty(currentDispositionAction, PROP_DISPOSITION_ACTION_ID); - currentDispositionActionDefinition = di.getDispositionActionDefinition(currentADId); + currentDispositionActionDefinition = dispositionSchedule.getDispositionActionDefinition(currentADId); // When the record has multiple disposition schedules the current disposition action may not be found by id // In this case it will be searched by name if(currentDispositionActionDefinition == null) { String currentADName = (String) nodeService.getProperty(currentDispositionAction, PROP_DISPOSITION_ACTION); - currentDispositionActionDefinition = di.getDispositionActionDefinitionByName(currentADName); + currentDispositionActionDefinition = dispositionSchedule.getDispositionActionDefinitionByName(currentADName); } // Get the next disposition action diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java index fc95771ddc..42c5a25fde 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java @@ -281,4 +281,5 @@ public interface RecordsManagementModel extends RecordsManagementCustomModel QName PROP_COUNT = QName.createQName(RM_URI, "count"); QName ASPECT_SAVED_SEARCH = QName.createQName(RM_URI, "savedSearch"); + QName ASPECT_DISPOSITION_PROCESSED = QName.createQName(RM_URI, "dispositionProcessed"); } diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/NodeRefEntity.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/NodeRefEntity.java new file mode 100644 index 0000000000..203a186e45 --- /dev/null +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/NodeRefEntity.java @@ -0,0 +1,88 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2019 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * - + * 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 . + * #L% + */ +package org.alfresco.module.org_alfresco_module_rm.query; + +/** + * NodeRef Entity - used by {@link RecordsManagementQueryDAOImpl}. + * + * @author Tom Page + * @since 2.5.0.4 + */ +public class NodeRefEntity +{ + private Long num; + private String protocol; + private String identifier; + private String uuid; + + /** + * Default constructor. + */ + public NodeRefEntity() + { + } + + public Long getNum() + { + return num; + } + + public void setNum(Long num) + { + this.num = num; + } + + public String getProtocol() + { + return protocol; + } + + public void setProtocol(String protocol) + { + this.protocol = protocol; + } + + public String getIdentifier() + { + return identifier; + } + + public void setIdentifier(String identifier) + { + this.identifier = identifier; + } + + public String getUuid() + { + return uuid; + } + + public void setUuid(String uuid) + { + this.uuid = uuid; + } +} diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java index c0743f604d..eac96d6f45 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java @@ -27,6 +27,10 @@ package org.alfresco.module.org_alfresco_module_rm.query; +import java.util.List; + +import org.alfresco.service.cmr.repository.NodeRef; + /** * Records management query DAO * @@ -46,4 +50,15 @@ public interface RecordsManagementQueryDAO * @return int count */ int getCountRmaIdentifier(String identifierValue); + + /** + * Returns a number of nodeRefs for record folders in the system + * that have the property recordSearchHasDispositionSchedule:true + * (used for MNT-20864) + * @param start long - the first result row to return + * @param end long - the last result row to return + * @return list of node refs + */ + List getRecordFoldersWithSchedules(Long start, Long end); + } diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java index 68742ee271..3eb65251e0 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java @@ -27,11 +27,14 @@ package org.alfresco.module.org_alfresco_module_rm.query; +import java.util.ArrayList; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; import org.alfresco.repo.domain.qname.QNameDAO; +import org.alfresco.service.cmr.repository.NodeRef; import org.alfresco.service.namespace.QName; import org.alfresco.util.Pair; import org.mybatis.spring.SqlSessionTemplate; @@ -45,7 +48,9 @@ import org.mybatis.spring.SqlSessionTemplate; public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, RecordsManagementModel { private static final String COUNT_IDENTIFIER = "alfresco.query.rm.select_CountRMIndentifier"; - + private static final String SCHEDULED_FOLDERS = "alfresco.query.rm.select_RecordFoldersWithSchedules"; + private static final String SCHEDULED_FOLDERS_COUNT = "alfresco.query.rm.select_RecordFoldersWithSchedulesCount"; + /** SQL session template */ protected SqlSessionTemplate template; @@ -97,4 +102,32 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, return result; } + /** + * @see org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO#getRecordFoldersWithSchedules(Long, Long) + */ + @Override + public List getRecordFoldersWithSchedules(Long start, Long end) + { + Map params = new HashMap<>(2); + params.put("processed", qnameDAO.getQName(ASPECT_DISPOSITION_PROCESSED) + .getFirst()); + params.put("folderQnameId", qnameDAO.getQName(TYPE_RECORD_FOLDER) + .getFirst()); + params.put("start", start); + params.put("end", end); + + List entities = template.selectList(SCHEDULED_FOLDERS, params); + + List results = new ArrayList<>(); + + // convert the entities to NodeRefs + for (NodeRefEntity nodeRefEntity : entities) + { + results.add( + new NodeRef(nodeRefEntity.getProtocol(), nodeRefEntity.getIdentifier(), nodeRefEntity.getUuid())); + } + + return results; + } + } diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java new file mode 100644 index 0000000000..ee5c16207e --- /dev/null +++ b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java @@ -0,0 +1,430 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2019 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * - + * 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 . + * #L% + */ +/* + * 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.repo.web.scripts.schedule; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; +import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; +import org.alfresco.repo.domain.node.NodeDAO; +import org.alfresco.repo.domain.qname.QNameDAO; +import org.alfresco.repo.policy.BehaviourFilter; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.transaction.TransactionService; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.webscripts.AbstractWebScript; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.Format; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +/** + * Webscript used to update records that are missing their schedule information + * + * @author Roy Wetherall + */ +public class UpdateRecordScheduleGet extends AbstractWebScript implements RecordsManagementModel +{ + /** + * logger + */ + private static Log logger = LogFactory.getLog(UpdateRecordScheduleGet.class); + + /** + * parameters + */ + private static final String PARAM_MAX_RECORD_FOLDERS = "maxRecordFolders"; + private static final String PARAM_RECORD_FOLDER = "recordFolder"; + + private static final String SUCCESS_STATUS = "success"; + private static final String MODEL_STATUS = "responsestatus"; + private static final String MODEL_MESSAGE = "message"; + private static final String MESSAGE_ALL_TEMPLATE = "Updated {0} records from {1} folders with updated disposition instructions."; + private static final String MESSAGE_FOLDER_TEMPLATE = "Updated records in folder {0} with updated disposition instructions."; + + /** + * services + */ + private NodeService nodeService; + private DispositionService dispositionService; + private RecordService recordService; + private TransactionService transactionService; + private RecordsManagementQueryDAO recordsManagementQueryDAO; + private BehaviourFilter behaviourFilter; + private NodeDAO nodeDAO; + private QNameDAO qnameDAO; + + /** + * service setters + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setRecordsManagementQueryDAO(RecordsManagementQueryDAO recordsManagementQueryDAO) + { + this.recordsManagementQueryDAO = recordsManagementQueryDAO; + } + + public void setRecordService(RecordService recordService) + { + this.recordService = recordService; + } + + public void setDispositionService(DispositionService dispositionService) + { + this.dispositionService = dispositionService; + } + + public void setTransactionService(TransactionService transactionService) + { + this.transactionService = transactionService; + } + + public void setBehaviourFilter(BehaviourFilter behaviourFilter) + { + this.behaviourFilter = behaviourFilter; + } + + public void setNodeDAO(NodeDAO nodeDAO) + { + this.nodeDAO = nodeDAO; + } + + public void setQnameDAO(QNameDAO qnameDAO) + { + this.qnameDAO = qnameDAO; + } + + /** + * Build web script model + */ + protected Map buildModel(WebScriptRequest req, WebScriptResponse res) throws IOException + { + Map model = new HashMap<>(); + transactionService.getRetryingTransactionHelper() + .doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + public String execute() throws Throwable + { + qnameDAO.getOrCreateQName(ASPECT_DISPOSITION_PROCESSED); + return null; + } + + }, false, true); + + int maxRecordFolders = getMaxRecordFolders(req); + NodeRef recordFolder = getRecordFolder(req); + + int processedRecords = 0; + String message; + if (recordFolder != null) + { + // Process the specified record folder + updateRecordFolder(recordFolder); + message = MessageFormat.format(MESSAGE_FOLDER_TEMPLATE, recordFolder); + } + else + { + int processedRecordFolders = 0; + int queryBatchSize = 10000; + Long maxNodeId = nodeDAO.getMaxNodeId(); + for (Long i = 0L; i < maxNodeId; i += queryBatchSize) + { + List folders = recordsManagementQueryDAO.getRecordFoldersWithSchedules(i, i + queryBatchSize); + for (NodeRef folder : folders) + { + processedRecords = processedRecords + updateRecordFolder(folder); + processedRecordFolders++; + + if (processedRecordFolders >= maxRecordFolders) + { + // stop processing since we have meet our limit + break; + } + } + + if (processedRecordFolders >= maxRecordFolders) + { + // stop processing since we have meet our limit + break; + } + } + message = MessageFormat.format(MESSAGE_ALL_TEMPLATE, processedRecords, processedRecordFolders); + } + + model.put(MODEL_STATUS, SUCCESS_STATUS); + model.put(MODEL_MESSAGE, message); + logger.info(message); + + return model; + } + + /* + * (non-Javadoc) + * @see org.alfresco.repo.web.scripts.content.StreamContent#execute(org.springframework.extensions.webscripts. + * WebScriptRequest, org.springframework.extensions.webscripts.WebScriptResponse) + */ + @Override + public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException + { + // retrieve requested format + String format = req.getFormat(); + + try + { + String mimetype = getContainer().getFormatRegistry() + .getMimeType(req.getAgent(), format); + if (mimetype == null) + { + throw new WebScriptException("Web Script format '" + format + "' is not registered"); + } + + // construct model for script / template + Status status = new Status(); + Cache cache = new Cache(getDescription().getRequiredCache()); + + Map model = buildModel(req, res); + + if (model == null) { return; } + model.put("status", status); + model.put("cache", cache); + + Map templateModel = createTemplateParameters(req, res, model); + + // render output + int statusCode = status.getCode(); + if (statusCode != HttpServletResponse.SC_OK && !req.forceSuccessStatus()) + { + if (logger.isDebugEnabled()) + { + logger.debug("Force success status header in response: " + req.forceSuccessStatus()); + logger.debug("Setting status " + statusCode); + } + res.setStatus(statusCode); + } + + // apply location + String location = status.getLocation(); + if (location != null && location.length() > 0) + { + if (logger.isDebugEnabled()) + logger.debug("Setting location to " + location); + res.setHeader(WebScriptResponse.HEADER_LOCATION, location); + } + + // apply cache + res.setCache(cache); + + String callback = null; + if (getContainer().allowCallbacks()) + { + callback = req.getJSONCallback(); + } + if (format.equals(WebScriptResponse.JSON_FORMAT) && callback != null) + { + if (logger.isDebugEnabled()) + logger.debug( + "Rendering JSON callback response: content type=" + Format.JAVASCRIPT.mimetype() + ", status=" + + statusCode + ", callback=" + callback); + + // NOTE: special case for wrapping JSON results in a javascript function callback + res.setContentType(Format.JAVASCRIPT.mimetype() + ";charset=UTF-8"); + res.getWriter() + .write((callback + "(")); + } + else + { + if (logger.isDebugEnabled()) + logger.debug("Rendering response: content type=" + mimetype + ", status=" + statusCode); + + res.setContentType(mimetype + ";charset=UTF-8"); + } + + // render response according to requested format + renderFormatTemplate(format, templateModel, res.getWriter()); + + if (format.equals(WebScriptResponse.JSON_FORMAT) && callback != null) + { + // NOTE: special case for wrapping JSON results in a javascript function callback + res.getWriter() + .write(")"); + } + } + catch (Throwable e) + { + if (logger.isDebugEnabled()) + { + StringWriter stack = new StringWriter(); + e.printStackTrace(new PrintWriter(stack)); + logger.debug("Caught exception; decorating with appropriate status template : " + stack.toString()); + } + + throw createStatusException(e, req, res); + } + } + + protected void renderFormatTemplate(String format, Map model, Writer writer) + { + format = (format == null) ? "" : format; + + String templatePath = getDescription().getId() + "." + format; + + if (logger.isDebugEnabled()) + logger.debug("Rendering template '" + templatePath + "'"); + + renderTemplate(templatePath, model, writer); + } + + protected int getMaxRecordFolders(WebScriptRequest req) + { + String valueStr = req.getParameter(PARAM_MAX_RECORD_FOLDERS); + int value = Integer.MAX_VALUE; + if (StringUtils.isNotBlank(valueStr)) + { + try + { + value = Integer.parseInt(valueStr); + } + catch (NumberFormatException ex) + { + //do nothing here, the value will remain 0L in this case + } + } + return value; + } + + protected NodeRef getRecordFolder(WebScriptRequest req) + { + String valueStr = req.getParameter(PARAM_RECORD_FOLDER); + NodeRef value = null; + if (StringUtils.isNotBlank(valueStr)) + { + value = new NodeRef(valueStr); + } + + return value; + } + + private int updateRecordFolder(final NodeRef recordFolder) + { + return transactionService.getRetryingTransactionHelper() + .doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + public Integer execute() throws Throwable + { + int recordCount = 0; + + behaviourFilter.disableBehaviour(ASPECT_FILE_PLAN_COMPONENT); + try + { + if (logger.isDebugEnabled()) + { + logger.info("Checking folder: " + recordFolder); + } + recordCount = AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork() + { + @Override + public Integer doWork() throws Exception + { + DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordFolder); + int innerRecordCount = 0; + if (schedule != null && schedule.isRecordLevelDisposition()) + { + + List records = recordService.getRecords(recordFolder); + for (NodeRef record : records) + { + if (!nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)) + { + if (recordFolder.equals(nodeService.getPrimaryParent(record).getParentRef())) + { + if (logger.isDebugEnabled()) + { + logger.info("updating record: " + record); + } + + // update record disposition information + dispositionService.updateNextDispositionAction(record, schedule); + innerRecordCount++; + } + } + } + } + return innerRecordCount; + } + }); + nodeService.addAspect(recordFolder, ASPECT_DISPOSITION_PROCESSED, null); + } + finally + { + behaviourFilter.enableBehaviour(ASPECT_FILE_PLAN_COMPONENT); + } + return recordCount; + } + }, false, true); + } +} From 5d3efcc4c440820941823dad8e89a76f1650b805 Mon Sep 17 00:00:00 2001 From: Ross Gale Date: Fri, 22 Nov 2019 18:15:24 +0000 Subject: [PATCH 20/24] Merge branch 'hotfix-2.5/RM-7051_Disposition' into 'release/V2.5.3.x' Resolve RM-7051 "Hotfix 2.5/ disposition" See merge request records-management/records-management!1303 Adds web script to ensure all records have correct disposition instructions --- .../model/recordsModel.xml | 4 + .../patch/rm-patch-v24-context.xml | 2 +- .../query/rm-common-SqlMap.xml | 35 +- .../rm-webscript-context.xml | 15 + .../org_alfresco_module_rm/version.properties | 2 +- .../rm-updaterecordschedule.get.desc.xml | 13 + .../rm-updaterecordschedule.get.json.ftl | 30 ++ .../disposition/DispositionService.java | 8 + .../disposition/DispositionServiceImpl.java | 38 +- .../model/RecordsManagementModel.java | 1 + .../query/NodeRefEntity.java | 88 ++++ .../query/RecordsManagementQueryDAO.java | 15 +- .../query/RecordsManagementQueryDAOImpl.java | 35 +- .../schedule/UpdateRecordScheduleGet.java | 430 ++++++++++++++++++ 14 files changed, 705 insertions(+), 11 deletions(-) create mode 100644 rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.desc.xml create mode 100644 rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.json.ftl create mode 100644 rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/NodeRefEntity.java create mode 100644 rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml index b49c740fb9..911576a784 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/model/recordsModel.xml @@ -712,6 +712,10 @@ Saved search
+ + Disposition processed + + Vital Record Definition diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml index e3e843041e..b2527baa9f 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v24-context.xml @@ -14,5 +14,5 @@ - + \ No newline at end of file diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml index d3b63f4467..d6ebbeca54 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/query/rm-common-SqlMap.xml @@ -7,8 +7,23 @@ - - select count(*) from @@ -20,6 +35,21 @@ + + + + \ No newline at end of file diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml index d4f8b73a05..0215c04957 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml @@ -665,4 +665,19 @@ parent="rmBaseWebscript"> + + + + + + + + + + + + + \ No newline at end of file diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties index cf2c7c2600..8cce8ad3ce 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties @@ -1,3 +1,3 @@ # RM Schema number -version.rm.schema=2501 +version.rm.schema=2502 diff --git a/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.desc.xml b/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.desc.xml new file mode 100644 index 0000000000..8ff54084a0 --- /dev/null +++ b/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.desc.xml @@ -0,0 +1,13 @@ + + Updates Record Schedules based on Hierarchical Retention Instructions + + URL parameter maxRecordFolders is optional, and represents the maximum number of record folders that should be processed. If not specified maxRecordFolders will be set to the max value for an integer.
+ URL parameter recordFolder is optional, and represents the nodeRef of a record folder whose records should be processed. If specified then maxRecordFolders will be ignored.
+ ]]> +
+ /api/rm/rm-updateRecordSchedule?maxRecordFolders={maxRecordFolders?}&recordFolder={recordFolder?} + argument + admin + required +
\ No newline at end of file diff --git a/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.json.ftl b/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.json.ftl new file mode 100644 index 0000000000..2b395291a4 --- /dev/null +++ b/rm-community/rm-community-repo/config/alfresco/templates/webscripts/org/alfresco/repository/schedules/rm-updaterecordschedule.get.json.ftl @@ -0,0 +1,30 @@ +<#-- + #%L + Alfresco Records Management Module + %% + Copyright (C) 2005 - 2019 Alfresco Software Limited + %% + This file is part of the Alfresco software. + - + If the software was purchased under a paid Alfresco license, the terms of + the paid license agreement will prevail. Otherwise, the software is + provided under the following open source license terms: + - + 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 . + #L% +--> +{ + "responsestatus" : "${responsestatus?json_string}", + "message" : "${message?json_string}" +} diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java index 4da6fde0dd..dccc56df6b 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionService.java @@ -237,6 +237,14 @@ public interface DispositionService */ void updateNextDispositionAction(NodeRef nodeRef); + /** + * Updates the next disposition action + * + * @param nodeRef node reference + * @param dispositionSchedule the schedule to be applied + */ + void updateNextDispositionAction(NodeRef nodeRef, DispositionSchedule dispositionSchedule); + /** * Refreshes the disposition action details of the given node. * diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java index 32f68c1bb5..e044026c75 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/disposition/DispositionServiceImpl.java @@ -953,8 +953,36 @@ public class DispositionServiceImpl extends ServiceBaseImpl public Void doWork() { // Get this disposition instructions for the node - DispositionSchedule di = getDispositionSchedule(nodeRef); - if (di != null) + DispositionSchedule dispositionSchedule = getDispositionSchedule(nodeRef); + + updateNextDispositionAction(nodeRef, dispositionSchedule); + + return null; + } + + }; + + AuthenticationUtil.runAsSystem(runAsWork); + } + + /** + * @see org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService#updateNextDispositionAction(NodeRef) + */ + @Override + public void updateNextDispositionAction(final NodeRef nodeRef, final DispositionSchedule dispositionSchedule) + { + + + RunAsWork runAsWork = new RunAsWork() + { + /** + * @see org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork#doWork() + */ + @Override + public Void doWork() + { + + if (dispositionSchedule != null) { // Get the current action node NodeRef currentDispositionAction = null; @@ -973,7 +1001,7 @@ public class DispositionServiceImpl extends ServiceBaseImpl nodeService.moveNode(currentDispositionAction, nodeRef, ASSOC_DISPOSITION_ACTION_HISTORY, ASSOC_DISPOSITION_ACTION_HISTORY); } - List dispositionActionDefinitions = di.getDispositionActionDefinitions(); + List dispositionActionDefinitions = dispositionSchedule.getDispositionActionDefinitions(); DispositionActionDefinition currentDispositionActionDefinition = null; DispositionActionDefinition nextDispositionActionDefinition = null; @@ -989,14 +1017,14 @@ public class DispositionServiceImpl extends ServiceBaseImpl { // Get the current action String currentADId = (String) nodeService.getProperty(currentDispositionAction, PROP_DISPOSITION_ACTION_ID); - currentDispositionActionDefinition = di.getDispositionActionDefinition(currentADId); + currentDispositionActionDefinition = dispositionSchedule.getDispositionActionDefinition(currentADId); // When the record has multiple disposition schedules the current disposition action may not be found by id // In this case it will be searched by name if(currentDispositionActionDefinition == null) { String currentADName = (String) nodeService.getProperty(currentDispositionAction, PROP_DISPOSITION_ACTION); - currentDispositionActionDefinition = di.getDispositionActionDefinitionByName(currentADName); + currentDispositionActionDefinition = dispositionSchedule.getDispositionActionDefinitionByName(currentADName); } // Get the next disposition action diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java index 600e48d4e5..e1ac53d9a5 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/RecordsManagementModel.java @@ -282,4 +282,5 @@ public interface RecordsManagementModel extends RecordsManagementCustomModel QName PROP_COUNT = QName.createQName(RM_URI, "count"); QName ASPECT_SAVED_SEARCH = QName.createQName(RM_URI, "savedSearch"); + QName ASPECT_DISPOSITION_PROCESSED = QName.createQName(RM_URI, "dispositionProcessed"); } diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/NodeRefEntity.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/NodeRefEntity.java new file mode 100644 index 0000000000..203a186e45 --- /dev/null +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/NodeRefEntity.java @@ -0,0 +1,88 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2019 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * - + * 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 . + * #L% + */ +package org.alfresco.module.org_alfresco_module_rm.query; + +/** + * NodeRef Entity - used by {@link RecordsManagementQueryDAOImpl}. + * + * @author Tom Page + * @since 2.5.0.4 + */ +public class NodeRefEntity +{ + private Long num; + private String protocol; + private String identifier; + private String uuid; + + /** + * Default constructor. + */ + public NodeRefEntity() + { + } + + public Long getNum() + { + return num; + } + + public void setNum(Long num) + { + this.num = num; + } + + public String getProtocol() + { + return protocol; + } + + public void setProtocol(String protocol) + { + this.protocol = protocol; + } + + public String getIdentifier() + { + return identifier; + } + + public void setIdentifier(String identifier) + { + this.identifier = identifier; + } + + public String getUuid() + { + return uuid; + } + + public void setUuid(String uuid) + { + this.uuid = uuid; + } +} diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java index ad4a3e2103..ea3a61c6dc 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAO.java @@ -27,9 +27,11 @@ package org.alfresco.module.org_alfresco_module_rm.query; -import java.util.Collection; + +import java.util.List; import org.alfresco.service.cmr.repository.NodeRef; +import java.util.Collection; import org.alfresco.service.namespace.QName; /** @@ -52,6 +54,16 @@ public interface RecordsManagementQueryDAO */ int getCountRmaIdentifier(String identifierValue); + /** + * Returns a number of nodeRefs for record folders in the system + * that have the property recordSearchHasDispositionSchedule:true + * (used for MNT-20864) + * @param start long - the first result row to return + * @param end long - the last result row to return + * @return list of node refs + */ + List getRecordFoldersWithSchedules(Long start, Long end); + /** * Returns whether a given node contains children with one of the given values for the given property * @@ -62,4 +74,5 @@ public interface RecordsManagementQueryDAO * false otherwise */ public boolean hasChildrenWithPropertyValues(NodeRef parent, QName property, Collection propertyValues); + } diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java index 99e05941a5..7c7ac5fc6c 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/query/RecordsManagementQueryDAOImpl.java @@ -27,8 +27,10 @@ package org.alfresco.module.org_alfresco_module_rm.query; +import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; @@ -50,8 +52,10 @@ import org.mybatis.spring.SqlSessionTemplate; public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, RecordsManagementModel { private static final String COUNT_IDENTIFIER = "alfresco.query.rm.select_CountRMIndentifier"; + private static final String SCHEDULED_FOLDERS = "alfresco.query.rm.select_RecordFoldersWithSchedules"; + private static final String SCHEDULED_FOLDERS_COUNT = "alfresco.query.rm.select_RecordFoldersWithSchedulesCount"; private static final String COUNT_CHILDREN_WITH_PROPERTY_VALUES = "select_CountChildrenWithPropertyValues"; - + /** SQL session template */ protected SqlSessionTemplate template; @@ -115,6 +119,34 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, return result; } + /** + * @see org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO#getRecordFoldersWithSchedules(Long, Long) + */ + @Override + public List getRecordFoldersWithSchedules(Long start, Long end) + { + Map params = new HashMap<>(2); + params.put("processed", qnameDAO.getQName(ASPECT_DISPOSITION_PROCESSED) + .getFirst()); + params.put("folderQnameId", qnameDAO.getQName(TYPE_RECORD_FOLDER) + .getFirst()); + params.put("start", start); + params.put("end", end); + + List entities = template.selectList(SCHEDULED_FOLDERS, params); + + List results = new ArrayList<>(); + + // convert the entities to NodeRefs + for (NodeRefEntity nodeRefEntity : entities) + { + results.add( + new NodeRef(nodeRefEntity.getProtocol(), nodeRefEntity.getIdentifier(), nodeRefEntity.getUuid())); + } + + return results; + } + @Override public boolean hasChildrenWithPropertyValues(NodeRef parent, QName property, Collection propertyValues) { @@ -150,4 +182,5 @@ public class RecordsManagementQueryDAOImpl implements RecordsManagementQueryDAO, Long count = template.selectOne(COUNT_CHILDREN_WITH_PROPERTY_VALUES, queryParams); return count > 0; } + } diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java new file mode 100644 index 0000000000..ee5c16207e --- /dev/null +++ b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java @@ -0,0 +1,430 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2019 Alfresco Software Limited + * %% + * This file is part of the Alfresco software. + * - + * If the software was purchased under a paid Alfresco license, the terms of + * the paid license agreement will prevail. Otherwise, the software is + * provided under the following open source license terms: + * - + * 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 . + * #L% + */ +/* + * 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.repo.web.scripts.schedule; + +import java.io.IOException; +import java.io.PrintWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.text.MessageFormat; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.servlet.http.HttpServletResponse; + +import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; +import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; +import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO; +import org.alfresco.module.org_alfresco_module_rm.record.RecordService; +import org.alfresco.repo.domain.node.NodeDAO; +import org.alfresco.repo.domain.qname.QNameDAO; +import org.alfresco.repo.policy.BehaviourFilter; +import org.alfresco.repo.security.authentication.AuthenticationUtil; +import org.alfresco.repo.transaction.RetryingTransactionHelper; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.transaction.TransactionService; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.extensions.webscripts.AbstractWebScript; +import org.springframework.extensions.webscripts.Cache; +import org.springframework.extensions.webscripts.Format; +import org.springframework.extensions.webscripts.Status; +import org.springframework.extensions.webscripts.WebScriptException; +import org.springframework.extensions.webscripts.WebScriptRequest; +import org.springframework.extensions.webscripts.WebScriptResponse; + +/** + * Webscript used to update records that are missing their schedule information + * + * @author Roy Wetherall + */ +public class UpdateRecordScheduleGet extends AbstractWebScript implements RecordsManagementModel +{ + /** + * logger + */ + private static Log logger = LogFactory.getLog(UpdateRecordScheduleGet.class); + + /** + * parameters + */ + private static final String PARAM_MAX_RECORD_FOLDERS = "maxRecordFolders"; + private static final String PARAM_RECORD_FOLDER = "recordFolder"; + + private static final String SUCCESS_STATUS = "success"; + private static final String MODEL_STATUS = "responsestatus"; + private static final String MODEL_MESSAGE = "message"; + private static final String MESSAGE_ALL_TEMPLATE = "Updated {0} records from {1} folders with updated disposition instructions."; + private static final String MESSAGE_FOLDER_TEMPLATE = "Updated records in folder {0} with updated disposition instructions."; + + /** + * services + */ + private NodeService nodeService; + private DispositionService dispositionService; + private RecordService recordService; + private TransactionService transactionService; + private RecordsManagementQueryDAO recordsManagementQueryDAO; + private BehaviourFilter behaviourFilter; + private NodeDAO nodeDAO; + private QNameDAO qnameDAO; + + /** + * service setters + */ + public void setNodeService(NodeService nodeService) + { + this.nodeService = nodeService; + } + + public void setRecordsManagementQueryDAO(RecordsManagementQueryDAO recordsManagementQueryDAO) + { + this.recordsManagementQueryDAO = recordsManagementQueryDAO; + } + + public void setRecordService(RecordService recordService) + { + this.recordService = recordService; + } + + public void setDispositionService(DispositionService dispositionService) + { + this.dispositionService = dispositionService; + } + + public void setTransactionService(TransactionService transactionService) + { + this.transactionService = transactionService; + } + + public void setBehaviourFilter(BehaviourFilter behaviourFilter) + { + this.behaviourFilter = behaviourFilter; + } + + public void setNodeDAO(NodeDAO nodeDAO) + { + this.nodeDAO = nodeDAO; + } + + public void setQnameDAO(QNameDAO qnameDAO) + { + this.qnameDAO = qnameDAO; + } + + /** + * Build web script model + */ + protected Map buildModel(WebScriptRequest req, WebScriptResponse res) throws IOException + { + Map model = new HashMap<>(); + transactionService.getRetryingTransactionHelper() + .doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + public String execute() throws Throwable + { + qnameDAO.getOrCreateQName(ASPECT_DISPOSITION_PROCESSED); + return null; + } + + }, false, true); + + int maxRecordFolders = getMaxRecordFolders(req); + NodeRef recordFolder = getRecordFolder(req); + + int processedRecords = 0; + String message; + if (recordFolder != null) + { + // Process the specified record folder + updateRecordFolder(recordFolder); + message = MessageFormat.format(MESSAGE_FOLDER_TEMPLATE, recordFolder); + } + else + { + int processedRecordFolders = 0; + int queryBatchSize = 10000; + Long maxNodeId = nodeDAO.getMaxNodeId(); + for (Long i = 0L; i < maxNodeId; i += queryBatchSize) + { + List folders = recordsManagementQueryDAO.getRecordFoldersWithSchedules(i, i + queryBatchSize); + for (NodeRef folder : folders) + { + processedRecords = processedRecords + updateRecordFolder(folder); + processedRecordFolders++; + + if (processedRecordFolders >= maxRecordFolders) + { + // stop processing since we have meet our limit + break; + } + } + + if (processedRecordFolders >= maxRecordFolders) + { + // stop processing since we have meet our limit + break; + } + } + message = MessageFormat.format(MESSAGE_ALL_TEMPLATE, processedRecords, processedRecordFolders); + } + + model.put(MODEL_STATUS, SUCCESS_STATUS); + model.put(MODEL_MESSAGE, message); + logger.info(message); + + return model; + } + + /* + * (non-Javadoc) + * @see org.alfresco.repo.web.scripts.content.StreamContent#execute(org.springframework.extensions.webscripts. + * WebScriptRequest, org.springframework.extensions.webscripts.WebScriptResponse) + */ + @Override + public void execute(WebScriptRequest req, WebScriptResponse res) throws IOException + { + // retrieve requested format + String format = req.getFormat(); + + try + { + String mimetype = getContainer().getFormatRegistry() + .getMimeType(req.getAgent(), format); + if (mimetype == null) + { + throw new WebScriptException("Web Script format '" + format + "' is not registered"); + } + + // construct model for script / template + Status status = new Status(); + Cache cache = new Cache(getDescription().getRequiredCache()); + + Map model = buildModel(req, res); + + if (model == null) { return; } + model.put("status", status); + model.put("cache", cache); + + Map templateModel = createTemplateParameters(req, res, model); + + // render output + int statusCode = status.getCode(); + if (statusCode != HttpServletResponse.SC_OK && !req.forceSuccessStatus()) + { + if (logger.isDebugEnabled()) + { + logger.debug("Force success status header in response: " + req.forceSuccessStatus()); + logger.debug("Setting status " + statusCode); + } + res.setStatus(statusCode); + } + + // apply location + String location = status.getLocation(); + if (location != null && location.length() > 0) + { + if (logger.isDebugEnabled()) + logger.debug("Setting location to " + location); + res.setHeader(WebScriptResponse.HEADER_LOCATION, location); + } + + // apply cache + res.setCache(cache); + + String callback = null; + if (getContainer().allowCallbacks()) + { + callback = req.getJSONCallback(); + } + if (format.equals(WebScriptResponse.JSON_FORMAT) && callback != null) + { + if (logger.isDebugEnabled()) + logger.debug( + "Rendering JSON callback response: content type=" + Format.JAVASCRIPT.mimetype() + ", status=" + + statusCode + ", callback=" + callback); + + // NOTE: special case for wrapping JSON results in a javascript function callback + res.setContentType(Format.JAVASCRIPT.mimetype() + ";charset=UTF-8"); + res.getWriter() + .write((callback + "(")); + } + else + { + if (logger.isDebugEnabled()) + logger.debug("Rendering response: content type=" + mimetype + ", status=" + statusCode); + + res.setContentType(mimetype + ";charset=UTF-8"); + } + + // render response according to requested format + renderFormatTemplate(format, templateModel, res.getWriter()); + + if (format.equals(WebScriptResponse.JSON_FORMAT) && callback != null) + { + // NOTE: special case for wrapping JSON results in a javascript function callback + res.getWriter() + .write(")"); + } + } + catch (Throwable e) + { + if (logger.isDebugEnabled()) + { + StringWriter stack = new StringWriter(); + e.printStackTrace(new PrintWriter(stack)); + logger.debug("Caught exception; decorating with appropriate status template : " + stack.toString()); + } + + throw createStatusException(e, req, res); + } + } + + protected void renderFormatTemplate(String format, Map model, Writer writer) + { + format = (format == null) ? "" : format; + + String templatePath = getDescription().getId() + "." + format; + + if (logger.isDebugEnabled()) + logger.debug("Rendering template '" + templatePath + "'"); + + renderTemplate(templatePath, model, writer); + } + + protected int getMaxRecordFolders(WebScriptRequest req) + { + String valueStr = req.getParameter(PARAM_MAX_RECORD_FOLDERS); + int value = Integer.MAX_VALUE; + if (StringUtils.isNotBlank(valueStr)) + { + try + { + value = Integer.parseInt(valueStr); + } + catch (NumberFormatException ex) + { + //do nothing here, the value will remain 0L in this case + } + } + return value; + } + + protected NodeRef getRecordFolder(WebScriptRequest req) + { + String valueStr = req.getParameter(PARAM_RECORD_FOLDER); + NodeRef value = null; + if (StringUtils.isNotBlank(valueStr)) + { + value = new NodeRef(valueStr); + } + + return value; + } + + private int updateRecordFolder(final NodeRef recordFolder) + { + return transactionService.getRetryingTransactionHelper() + .doInTransaction(new RetryingTransactionHelper.RetryingTransactionCallback() + { + public Integer execute() throws Throwable + { + int recordCount = 0; + + behaviourFilter.disableBehaviour(ASPECT_FILE_PLAN_COMPONENT); + try + { + if (logger.isDebugEnabled()) + { + logger.info("Checking folder: " + recordFolder); + } + recordCount = AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork() + { + @Override + public Integer doWork() throws Exception + { + DispositionSchedule schedule = dispositionService.getDispositionSchedule(recordFolder); + int innerRecordCount = 0; + if (schedule != null && schedule.isRecordLevelDisposition()) + { + + List records = recordService.getRecords(recordFolder); + for (NodeRef record : records) + { + if (!nodeService.hasAspect(record, ASPECT_DISPOSITION_LIFECYCLE)) + { + if (recordFolder.equals(nodeService.getPrimaryParent(record).getParentRef())) + { + if (logger.isDebugEnabled()) + { + logger.info("updating record: " + record); + } + + // update record disposition information + dispositionService.updateNextDispositionAction(record, schedule); + innerRecordCount++; + } + } + } + } + return innerRecordCount; + } + }); + nodeService.addAspect(recordFolder, ASPECT_DISPOSITION_PROCESSED, null); + } + finally + { + behaviourFilter.enableBehaviour(ASPECT_FILE_PLAN_COMPONENT); + } + return recordCount; + } + }, false, true); + } +} From 98f04870680618013bc42eda4e738b4f8501d134 Mon Sep 17 00:00:00 2001 From: Ross Gale Date: Mon, 25 Nov 2019 08:35:50 +0000 Subject: [PATCH 21/24] Update version.properties --- .../alfresco/module/org_alfresco_module_rm/version.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties index 8cce8ad3ce..cf2c7c2600 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/version.properties @@ -1,3 +1,3 @@ # RM Schema number -version.rm.schema=2502 +version.rm.schema=2501 From 2b7541b501e394f2a6ba9b99464fbba676dadbde Mon Sep 17 00:00:00 2001 From: Roxana Lucanu Date: Tue, 26 Nov 2019 21:57:35 +0200 Subject: [PATCH 22/24] RM-7060 Reapply search aspect when filing/moving --- .../RecordsManagementSearchBehaviour.java | 47 ++++++++++++++++++- 1 file changed, 46 insertions(+), 1 deletion(-) diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordsManagementSearchBehaviour.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordsManagementSearchBehaviour.java index 9ba27e2447..d7963c18c3 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordsManagementSearchBehaviour.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/model/behaviour/RecordsManagementSearchBehaviour.java @@ -49,9 +49,12 @@ import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.module.org_alfresco_module_rm.recordfolder.RecordFolderService; import org.alfresco.module.org_alfresco_module_rm.vital.VitalRecordDefinition; import org.alfresco.module.org_alfresco_module_rm.vital.VitalRecordService; +import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.policy.Behaviour.NotificationFrequency; import org.alfresco.repo.policy.JavaBehaviour; import org.alfresco.repo.policy.PolicyComponent; +import org.alfresco.repo.policy.annotation.Behaviour; +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.repo.transaction.TransactionalResourceHelper; @@ -73,7 +76,8 @@ import org.apache.commons.logging.LogFactory; * @author Roy Wetherall * @since 1.0 */ -public class RecordsManagementSearchBehaviour implements RecordsManagementModel +public class RecordsManagementSearchBehaviour implements RecordsManagementModel, + NodeServicePolicies.OnMoveNodePolicy { /** logger */ private static Log logger = LogFactory.getLog(RecordsManagementSearchBehaviour.class); @@ -172,6 +176,9 @@ public class RecordsManagementSearchBehaviour implements RecordsManagementModel private JavaBehaviour jbEventExecutionUpdate = new JavaBehaviour(this, "eventExecutionUpdate", NotificationFrequency.TRANSACTION_COMMIT); private JavaBehaviour jbEventExecutionDelete = new JavaBehaviour(this, "eventExecutionDelete", NotificationFrequency.TRANSACTION_COMMIT); + /** on move record or record folder behavior */ + private JavaBehaviour jbMoveNode = new JavaBehaviour(this, "onMoveNode", NotificationFrequency.TRANSACTION_COMMIT); + /** Array of behaviours related to disposition schedule artifacts */ private JavaBehaviour[] jbDispositionBehaviours = { @@ -243,6 +250,11 @@ public class RecordsManagementSearchBehaviour implements RecordsManagementModel QName.createQName(NamespaceService.ALFRESCO_URI, "onUpdateProperties"), ASPECT_VITAL_RECORD_DEFINITION, new JavaBehaviour(this, "vitalRecordDefintionUpdateProperties", NotificationFrequency.TRANSACTION_COMMIT)); + + this.policyComponent.bindClassBehaviour( + QName.createQName(NamespaceService.ALFRESCO_URI, "onMoveNode"), + ASPECT_FILE_PLAN_COMPONENT, + jbMoveNode); } /** @@ -907,4 +919,37 @@ public class RecordsManagementSearchBehaviour implements RecordsManagementModel return results; } + + /** + * Record and record folder move behavior + * + * @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(ChildAssociationRef oldChildAssocRef, ChildAssociationRef newChildAssocRef) + { + // check the parent has actually changed + if (!oldChildAssocRef.getParentRef().equals(newChildAssocRef.getParentRef())) + { + final NodeRef recordOrFolder = newChildAssocRef.getChildRef(); + final boolean isRecordOrFolder = recordService.isRecord(recordOrFolder) || recordFolderService.isRecordFolder(recordOrFolder); + AuthenticationUtil.runAsSystem(new AuthenticationUtil.RunAsWork() + { + @Override + public Void doWork() + { + if (nodeService.exists(recordOrFolder) && isRecordOrFolder) + { + applySearchAspect(recordOrFolder); + } + return null; + } + }); + } + } } From 23300d09cded8fcab64ebdd340818b7bdd53f012 Mon Sep 17 00:00:00 2001 From: Roxana Lucanu Date: Wed, 27 Nov 2019 11:28:32 +0200 Subject: [PATCH 23/24] RM-7060 Fix integration tests --- .../test/integration/record/MoveRecordTest.java | 2 +- .../test/integration/recordfolder/MoveRecordFolderTest.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/MoveRecordTest.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/MoveRecordTest.java index 727af89284..6df3aaaea1 100644 --- a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/MoveRecordTest.java +++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/record/MoveRecordTest.java @@ -120,7 +120,7 @@ public class MoveRecordTest extends BaseRMTestCase assertNull(dispositionService.getNextDispositionAction(record)); // check the search aspect properties - assertFalse(nodeService.hasAspect(record, ASPECT_RM_SEARCH)); + assertTrue(nodeService.hasAspect(record, ASPECT_RM_SEARCH)); } }); diff --git a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/recordfolder/MoveRecordFolderTest.java b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/recordfolder/MoveRecordFolderTest.java index e8b26622ea..81f5d08633 100644 --- a/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/recordfolder/MoveRecordFolderTest.java +++ b/rm-community/rm-community-repo/test/java/org/alfresco/module/org_alfresco_module_rm/test/integration/recordfolder/MoveRecordFolderTest.java @@ -218,7 +218,7 @@ public class MoveRecordFolderTest extends BaseRMTestCase assertNull(dispositionService.getNextDispositionAction(recordFolder)); // check the search aspect properties - assertFalse(nodeService.hasAspect(recordFolder, ASPECT_RM_SEARCH)); + assertTrue(nodeService.hasAspect(recordFolder, ASPECT_RM_SEARCH)); } }); } From 4de8b50e4df8eec287abe373b4f40b8052c00b37 Mon Sep 17 00:00:00 2001 From: Ross Gale Date: Wed, 4 Dec 2019 14:01:54 +0000 Subject: [PATCH 24/24] RM-7051 updating code to deal with held content after 3.2 change --- .../rm-webscript-context.xml | 2 ++ .../schedule/UpdateRecordScheduleGet.java | 21 +++++++++++++++---- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml index 0f854c64ee..afdcdee66d 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-webscript-context.xml @@ -694,6 +694,8 @@ + + \ No newline at end of file diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java index ee5c16207e..40bcbac32e 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/repo/web/scripts/schedule/UpdateRecordScheduleGet.java @@ -59,6 +59,8 @@ import javax.servlet.http.HttpServletResponse; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionSchedule; import org.alfresco.module.org_alfresco_module_rm.disposition.DispositionService; import org.alfresco.module.org_alfresco_module_rm.model.RecordsManagementModel; +import org.alfresco.module.org_alfresco_module_rm.model.behaviour.RecordsManagementSearchBehaviour; +import org.alfresco.module.org_alfresco_module_rm.model.rma.aspect.FrozenAspect; import org.alfresco.module.org_alfresco_module_rm.query.RecordsManagementQueryDAO; import org.alfresco.module.org_alfresco_module_rm.record.RecordService; import org.alfresco.repo.domain.node.NodeDAO; @@ -115,7 +117,8 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record private BehaviourFilter behaviourFilter; private NodeDAO nodeDAO; private QNameDAO qnameDAO; - + private FrozenAspect frozenAspect; + private RecordsManagementSearchBehaviour recordsManagementSearchBehaviour; /** * service setters */ @@ -159,6 +162,16 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record this.qnameDAO = qnameDAO; } + public void setFrozenAspect(FrozenAspect frozenAspect) + { + this.frozenAspect = frozenAspect; + } + + public void setRecordsManagementSearchBehaviour(RecordsManagementSearchBehaviour recordsManagementSearchBehaviour) + { + this.recordsManagementSearchBehaviour = recordsManagementSearchBehaviour; + } + /** * Build web script model */ @@ -377,8 +390,7 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record public Integer execute() throws Throwable { int recordCount = 0; - - behaviourFilter.disableBehaviour(ASPECT_FILE_PLAN_COMPONENT); + frozenAspect.disableOnPropUpdateFrozenAspect(); try { if (logger.isDebugEnabled()) @@ -409,6 +421,7 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record // update record disposition information dispositionService.updateNextDispositionAction(record, schedule); + recordsManagementSearchBehaviour.onAddDispositionLifecycleAspect(record,null); innerRecordCount++; } } @@ -421,7 +434,7 @@ public class UpdateRecordScheduleGet extends AbstractWebScript implements Record } finally { - behaviourFilter.enableBehaviour(ASPECT_FILE_PLAN_COMPONENT); + frozenAspect.enableOnPropUpdateFrozenAspect(); } return recordCount; }