diff --git a/pom.xml b/pom.xml index a559433f19..918749d210 100644 --- a/pom.xml +++ b/pom.xml @@ -4,7 +4,7 @@ org.alfresco alfresco-governance-services pom - 3.5.0-SNAPSHOT + 3.5.1-SNAPSHOT Alfresco Governance Services http://www.alfresco.org/ diff --git a/rm-automation/pom.xml b/rm-automation/pom.xml index 5eee570158..20e84fc407 100644 --- a/rm-automation/pom.xml +++ b/rm-automation/pom.xml @@ -8,7 +8,7 @@ org.alfresco alfresco-governance-services - 3.5.0-SNAPSHOT + 3.5.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 b559c7682d..2606b83732 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-governance-services-automation - 3.5.0-SNAPSHOT + 3.5.1-SNAPSHOT diff --git a/rm-community/pom.xml b/rm-community/pom.xml index 3e065f78e6..e116557e08 100644 --- a/rm-community/pom.xml +++ b/rm-community/pom.xml @@ -8,7 +8,7 @@ org.alfresco alfresco-governance-services - 3.5.0-SNAPSHOT + 3.5.1-SNAPSHOT diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v35-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v35-context.xml index cc54b588ad..6159adab5f 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v35-context.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/patch/rm-patch-v35-context.xml @@ -5,16 +5,17 @@ http://www.springframework.org/schema/beans/spring-beans.xsd"> - - - - + + + + - \ No newline at end of file + diff --git a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml index 29b5a0e785..3d46d6a87a 100644 --- a/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml +++ b/rm-community/rm-community-repo/config/alfresco/module/org_alfresco_module_rm/rm-service-context.xml @@ -806,6 +806,7 @@ + rma:recordCategory diff --git a/rm-community/rm-community-repo/pom.xml b/rm-community/rm-community-repo/pom.xml index f942056ed3..814394242f 100644 --- a/rm-community/rm-community-repo/pom.xml +++ b/rm-community/rm-community-repo/pom.xml @@ -9,7 +9,7 @@ org.alfresco alfresco-governance-services-community - 3.5.0-SNAPSHOT + 3.5.1-SNAPSHOT diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/admin/RecordsManagementAdminServiceImpl.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/admin/RecordsManagementAdminServiceImpl.java index 9cd8e0c096..6fce532585 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/admin/RecordsManagementAdminServiceImpl.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/admin/RecordsManagementAdminServiceImpl.java @@ -53,6 +53,8 @@ import org.alfresco.repo.dictionary.M2Aspect; import org.alfresco.repo.dictionary.M2Constraint; import org.alfresco.repo.dictionary.M2Model; import org.alfresco.repo.dictionary.M2Property; +import org.alfresco.repo.lock.JobLockService; +import org.alfresco.repo.lock.LockAcquisitionException; import org.alfresco.repo.node.NodeServicePolicies; import org.alfresco.repo.policy.Behaviour.NotificationFrequency; import org.alfresco.repo.policy.annotation.Behaviour; @@ -71,10 +73,14 @@ import org.alfresco.service.cmr.dictionary.TypeDefinition; import org.alfresco.service.cmr.repository.AssociationRef; import org.alfresco.service.cmr.repository.ChildAssociationRef; import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.namespace.NamespaceService; import org.alfresco.service.namespace.QName; import org.alfresco.service.namespace.RegexQNamePattern; import org.alfresco.service.transaction.TransactionService; import org.alfresco.util.GUID; +import org.alfresco.util.LockCallback; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.context.ApplicationListener; import org.springframework.context.event.ContextRefreshedEvent; import org.springframework.core.Ordered; @@ -96,6 +102,9 @@ public class RecordsManagementAdminServiceImpl extends RecordsManagementAdminBas ApplicationListener, Ordered { + + private static final Logger LOGGER = LoggerFactory.getLogger(RecordsManagementAdminServiceImpl.class); + /** I18N messages*/ private static final String MSG_SERVICE_NOT_INIT = "rm.admin.service-not-init"; private static final String MSG_PROP_EXIST = "rm.admin.prop-exist"; @@ -108,17 +117,23 @@ public class RecordsManagementAdminServiceImpl extends RecordsManagementAdminBas /** Constants */ private static final String CUSTOM_CONSTRAINT_TYPE = org.alfresco.module.org_alfresco_module_rm.caveat.RMListOfValuesConstraint.class.getName(); - private static final String CAPATIBILITY_CUSTOM_CONTRAINT_TYPE = org.alfresco.module.org_alfresco_module_dod5015.caveat.RMListOfValuesConstraint.class.getName(); + private static final String CAPABILITY_CUSTOM_CONSTRAINT_TYPE = org.alfresco.module.org_alfresco_module_dod5015.caveat.RMListOfValuesConstraint.class.getName(); private static final String PARAM_ALLOWED_VALUES = "allowedValues"; private static final String PARAM_CASE_SENSITIVE = "caseSensitive"; private static final String PARAM_MATCH_LOGIC = "matchLogic"; + private static final QName LOCK_QNAME = QName.createQName(NamespaceService.SYSTEM_MODEL_1_0_URI, "RecordsManagementAdminServiceImpl"); + private static final long DEFAULT_TIME = 30000L; + /** Relationship service */ private RelationshipService relationshipService; /** Transaction service */ private TransactionService transactionService; + /** Job Lock service */ + private JobLockService jobLockService; + /** List of types that can be customisable */ private List pendingCustomisableTypes; private Map customisableTypes; @@ -152,7 +167,15 @@ public class RecordsManagementAdminServiceImpl extends RecordsManagementAdminBas return this.relationshipService; } - /** + /** + * @param jobLockService The Job Lock service + */ + public void setJobLockService(JobLockService jobLockService) + { + this.jobLockService = jobLockService; + } + + /** * Indicate that this application content listener must be executed with the lowest * precedence. (ie last) * @@ -172,30 +195,63 @@ public class RecordsManagementAdminServiceImpl extends RecordsManagementAdminBas @Override public void onApplicationEvent(ContextRefreshedEvent event) { - if(!isCustomMapInit && getDictionaryService().getAllModels().contains(RM_CUSTOM_MODEL)) - { - // run as System on bootstrap - AuthenticationUtil.runAs(new RunAsWork() - { - public Object doWork() - { - RetryingTransactionCallback callback = new RetryingTransactionCallback() - { - public Void execute() - { - // initialise custom properties - initCustomMap(); - return null; - } - }; - transactionService.getRetryingTransactionHelper().doInTransaction(callback); + final LockCallback lockCallback = new LockCallback(); - return null; + // try and get the lock + String lockToken = getLock(); + if (lockToken != null) + { + try + { + jobLockService.refreshLock(lockToken, LOCK_QNAME, DEFAULT_TIME, lockCallback); + + if (!isCustomMapInit && getDictionaryService().getAllModels().contains(RM_CUSTOM_MODEL)) + { + // run as System on bootstrap + AuthenticationUtil.runAsSystem((RunAsWork) () -> { + transactionService.getRetryingTransactionHelper() + .doInTransaction((RetryingTransactionCallback) () -> { + // initialise custom properties + initCustomMap(); + return null; + }); + return null; + }); + } } - }, AuthenticationUtil.getSystemUserName()); - } + finally + { + try + { + lockCallback.setIsRunning(false); + jobLockService.releaseLock(lockToken, LOCK_QNAME); + } + catch (LockAcquisitionException e) + { + LOGGER.debug("Lock release failed: {}: {}", LOCK_QNAME, lockToken, e); + } + } + } } - + + /** + * Attempts to get the lock. If the lock couldn't be taken, then null is returned. + * + * @return Returns the lock token or null + */ + private String getLock() + { + try + { + return jobLockService.getLock(LOCK_QNAME, DEFAULT_TIME); + } + catch (LockAcquisitionException e) + { + return null; + } + } + + /** * Helper method to indicate whether the custom map is initialised or not. * @@ -1198,7 +1254,7 @@ public class RecordsManagementAdminServiceImpl extends RecordsManagementAdminBas String type = customConstraint.getType(); if (type == null || (!type.equals(CUSTOM_CONSTRAINT_TYPE) && - !type.equals(CAPATIBILITY_CUSTOM_CONTRAINT_TYPE))) + !type.equals(CAPABILITY_CUSTOM_CONSTRAINT_TYPE))) { throw new AlfrescoRuntimeException(I18NUtil.getMessage(MSG_UNEXPECTED_TYPE_CONSTRAINT, type, constraintNameAsPrefixString, CUSTOM_CONSTRAINT_TYPE)); } diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/UpdateActionType.java b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/UpdateActionType.java index 71c1382504..08637b970b 100644 --- a/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/UpdateActionType.java +++ b/rm-community/rm-community-repo/source/java/org/alfresco/module/org_alfresco_module_rm/util/UpdateActionType.java @@ -38,5 +38,20 @@ import org.alfresco.api.AlfrescoPublicApi; public enum UpdateActionType { ADD, - REMOVE + REMOVE; + + public static UpdateActionType valueOfIgnoreCase(String name) + { + UpdateActionType actionType; + try + { + actionType = UpdateActionType.valueOf(name.toUpperCase()); + } + catch (Exception e) + { + throw new IllegalArgumentException("Could not find enum with name '" + name + "'. Not one of the values accepted for Enum class: [ADD, REMOVE]"); + } + + return actionType; + } } diff --git a/rm-community/rm-community-repo/source/java/org/alfresco/util/LockCallback.java b/rm-community/rm-community-repo/source/java/org/alfresco/util/LockCallback.java new file mode 100644 index 0000000000..ae87470fa3 --- /dev/null +++ b/rm-community/rm-community-repo/source/java/org/alfresco/util/LockCallback.java @@ -0,0 +1,54 @@ +/* + * #%L + * Alfresco Records Management Module + * %% + * Copyright (C) 2005 - 2021 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.util; + +import java.util.concurrent.atomic.AtomicBoolean; + +import org.alfresco.repo.lock.JobLockService.JobLockRefreshCallback; + +public class LockCallback implements JobLockRefreshCallback +{ + private final AtomicBoolean running = new AtomicBoolean(true); + + @Override + public boolean isActive() + { + return running.get(); + } + + @Override + public void lockReleased() + { + running.set(false); + } + + public void setIsRunning(boolean isRunning) + { + this.running.set(isRunning); + } +} diff --git a/rm-community/rm-community-rest-api-explorer/pom.xml b/rm-community/rm-community-rest-api-explorer/pom.xml index 7c19b1535b..a892c5aa15 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-governance-services-community - 3.5.0-SNAPSHOT + 3.5.1-SNAPSHOT