From 1e109021ebb7f5c27d8181038f836a469e474075 Mon Sep 17 00:00:00 2001 From: Tom Page Date: Mon, 12 Oct 2015 14:52:21 +0000 Subject: [PATCH] RM-2604 Bootstrap the CaveatDAO and create the Spring context file. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/modules/recordsmanagement/DEV/caveatmarkdatatype@114175 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../alfresco-global.properties | 10 +- .../org_alfresco_module_rm/caveat-context.xml | 33 ++++ .../org_alfresco_module_rm/module-context.xml | 9 +- .../caveat/CaveatConstants.java | 36 ++++ .../caveat/dao/CaveatDAOCache.java | 60 +++++++ .../caveat/dao/CaveatDAOFromJSON.java | 2 +- .../dao/CaveatDAOFromJSONBootstrap.java | 162 ++++++++++++++++++ .../caveat/scheme/CaveatGroup.java | 5 +- .../caveat/scheme/CaveatMark.java | 6 +- 9 files changed, 315 insertions(+), 8 deletions(-) create mode 100644 rm-server/config/alfresco/module/org_alfresco_module_rm/caveat-context.xml create mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/CaveatConstants.java create mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/dao/CaveatDAOCache.java create mode 100644 rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/dao/CaveatDAOFromJSONBootstrap.java diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/alfresco-global.properties b/rm-server/config/alfresco/module/org_alfresco_module_rm/alfresco-global.properties index 7aa485093b..0d160cc4ce 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/alfresco-global.properties +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/alfresco-global.properties @@ -68,6 +68,12 @@ rm.classification.reasonsFile=/alfresco/module/org_alfresco_module_rm/classifica # The location of the exemption categories configuration file (relative to the classpath). rm.classification.exemptionCategoriesFile=/alfresco/module/org_alfresco_module_rm/classification/rm-exemption-categories.json +# +# Caveats +# +# The location of the caveats configuration file (relative to the classpath). +rm.caveat.configFile=/alfresco/module/org_alfresco_module_rm/caveat/rm-caveats.json + # # Content cleansing # @@ -81,8 +87,8 @@ rm.completerecord.mandatorypropertiescheck.enabled=true # # Indicates whether the existing file plan is converted to a standard file plan during # upgrade to V2.2, otherwise it will be converted to a DoD compliant file plan. -# -# Note that when converted to a standard file plan that DoD related record meta-data remains +# +# Note that when converted to a standard file plan that DoD related record meta-data remains # on the individual records and will not be visible in the UI, but can be assessed via # deprecated model properties in the rma namespace. # diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/caveat-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/caveat-context.xml new file mode 100644 index 0000000000..5543a7604d --- /dev/null +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/caveat-context.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml b/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml index e38c0e6e54..4b1c3b8bdd 100644 --- a/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml +++ b/rm-server/config/alfresco/module/org_alfresco_module_rm/module-context.xml @@ -1,6 +1,6 @@ - + - + @@ -273,6 +273,9 @@ + + + diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/CaveatConstants.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/CaveatConstants.java new file mode 100644 index 0000000000..7aaf968670 --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/CaveatConstants.java @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2005-2015 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.module.org_alfresco_module_rm.caveat; + +import java.io.Serializable; + +/** + * Constants for use by the caveats feature. + * + * @author Tom Page + * @since 2.4.a + */ +public class CaveatConstants +{ + /** This utility class should not be instantiated. */ + private CaveatConstants() {} + + /** Key for accessing the persisted caveat groups and marks in the attribute service. */ + public static final Serializable[] CAVEAT_ATTRIBUTE_KEY = new String[] { "org.alfresco", "module.org_alfresco_module_rm", "caveat.groups" }; +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/dao/CaveatDAOCache.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/dao/CaveatDAOCache.java new file mode 100644 index 0000000000..70f03fe56e --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/dao/CaveatDAOCache.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2005-2015 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.module.org_alfresco_module_rm.caveat.dao; + +import java.util.Map; + +import org.alfresco.module.org_alfresco_module_rm.caveat.scheme.CaveatGroup; + +/** + * A cache that ensures the underlying caveat DAO is only executed once per query. + * + * @author Tom Page + * @since 2.4.a + */ +public class CaveatDAOCache implements CaveatDAOInterface +{ + /** The wrapped caveat DAO. */ + private CaveatDAOInterface caveatDAO; + /** A cache of the system caveat groups. */ + private Map caveatGroups; + + /** + * {@inheritDoc} The first call to this method will be cached and returned for every successive call. + */ + @Override + public Map getCaveatGroups() + { + if (caveatGroups == null) + { + caveatGroups = caveatDAO.getCaveatGroups(); + } + return caveatGroups; + } + + /** + * Set the caveat DAO to be wrapped. + * + * @param caveatDAO The caveat DAO to be wrapped. + */ + public void setCaveatDAO(CaveatDAOInterface caveatDAO) + { + this.caveatDAO = caveatDAO; + } +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/dao/CaveatDAOFromJSON.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/dao/CaveatDAOFromJSON.java index dc46586097..3df68d951d 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/dao/CaveatDAOFromJSON.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/dao/CaveatDAOFromJSON.java @@ -66,7 +66,7 @@ public class CaveatDAOFromJSON implements CaveatDAOInterface private static final Logger LOGGER = LoggerFactory.getLogger(CaveatDAOFromJSON.class); /** The location of the configuration file relative to the classpath. */ - String configLocation; + private String configLocation; /** Set the location of the configuration file relative to the classpath. */ public void setConfigLocation(String configLocation) diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/dao/CaveatDAOFromJSONBootstrap.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/dao/CaveatDAOFromJSONBootstrap.java new file mode 100644 index 0000000000..a8b2132dfb --- /dev/null +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/dao/CaveatDAOFromJSONBootstrap.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2005-2015 Alfresco Software Limited. + * + * This file is part of Alfresco + * + * Alfresco is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Alfresco is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Alfresco. If not, see . + */ +package org.alfresco.module.org_alfresco_module_rm.caveat.dao; + +import static org.alfresco.module.org_alfresco_module_rm.caveat.CaveatConstants.CAVEAT_ATTRIBUTE_KEY; + +import java.io.Serializable; +import java.util.Map; + +import org.alfresco.module.org_alfresco_module_rm.caveat.CaveatException.MalformedConfiguration; +import org.alfresco.module.org_alfresco_module_rm.caveat.scheme.CaveatGroup; +import org.alfresco.module.org_alfresco_module_rm.classification.model.ClassifiedContentModel; +import org.alfresco.module.org_alfresco_module_rm.util.AuthenticationUtil; +import org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork; +import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.service.cmr.attributes.AttributeService; +import org.alfresco.service.transaction.TransactionService; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.context.ApplicationEvent; +import org.springframework.extensions.surf.util.AbstractLifecycleBean; + +/** + * This class is responsible for ensuring all caveat data is loaded from the JSON configuration on start-up. + * + * @author Tom Page + * @since 2.4.a + */ +public class CaveatDAOFromJSONBootstrap extends AbstractLifecycleBean implements ClassifiedContentModel +{ + /** Logging utility for the class. */ + private static final Logger LOGGER = LoggerFactory.getLogger(CaveatDAOFromJSONBootstrap.class); + + private final AuthenticationUtil authenticationUtil; + private final TransactionService transactionService; + private AttributeService attributeService; + private CaveatDAOInterface caveatDAO; + + private boolean isInitialised = false; + + public CaveatDAOFromJSONBootstrap(AuthenticationUtil authUtil, + TransactionService txService, + AttributeService attributeService, + CaveatDAOInterface caveatDAO) + { + this.authenticationUtil = authUtil; + this.transactionService = txService; + this.attributeService = attributeService; + this.caveatDAO = caveatDAO; + } + + /** Set the object from which configuration options will be read. */ + public void setClassificationServiceDAO(CaveatDAOInterface caveatDAO) { this.caveatDAO = caveatDAO; } + public void setAttributeService(AttributeService attributeService) { this.attributeService = attributeService; } + + public boolean isInitialised() + { + return isInitialised; + } + + @Override public void onBootstrap(ApplicationEvent event) + { + authenticationUtil.runAsSystem(new org.alfresco.repo.security.authentication.AuthenticationUtil.RunAsWork() + { + public Void doWork() + { + RetryingTransactionCallback callback = new RetryingTransactionCallback() + { + public Void execute() + { + initialiseConfiguredCaveatGroups(CAVEAT_ATTRIBUTE_KEY); + isInitialised = true; + return null; + } + }; + transactionService.getRetryingTransactionHelper().doInTransaction(callback); + return null; + } + }); + } + + /** + * Gets the caveat configuration persisted in the system. + * + * @return the persisted caveat groups if they have been persisted, else {@code null}. + */ + private Map getPersistedValues(final Serializable[] key) + { + return authenticationUtil.runAsSystem(new RunAsWork>() + { + @Override + @SuppressWarnings("unchecked") + public Map doWork() throws Exception + { + return (Map) attributeService.getAttribute(key); + } + }); + } + + /** Return true if the map is null or empty. */ + private boolean isEmpty(Map caveatGroups) + { + return (caveatGroups == null || caveatGroups.isEmpty()); + } + + /** Helper method for debug-logging sensitive caveat group information. */ + private String loggableStatusOf(Map caveatGroups) + { + if (caveatGroups == null) { return "null"; } + else if (caveatGroups.isEmpty()) { return "empty"; } + else { return "non-empty"; } + } + + /** + * Get the configured caveat groups and marks from the JSON file. + * + * @param key The attribute service key for the caveat scheme. + */ + protected void initialiseConfiguredCaveatGroups(Serializable[] key) + { + final Map persistedValues = getPersistedValues(key); + final Map classpathValues = caveatDAO.getCaveatGroups(); + + // Note! We cannot log the entities or even the size of these lists for security reasons. + LOGGER.debug("Persisted CaveatGroup: {}", loggableStatusOf(persistedValues)); + LOGGER.debug("Classpath CaveatGroup: {}", loggableStatusOf(classpathValues)); + + if (isEmpty(classpathValues)) + { + throw new MalformedConfiguration("CaveatGroup configuration is missing."); + } + if (!classpathValues.equals(persistedValues)) + { + if (!isEmpty(persistedValues)) + { + LOGGER.warn("CaveatGroup configuration changed. This may result in unpredictable results if the caveat scheme is already in use."); + } + attributeService.setAttribute((Serializable) classpathValues, key); + } + } + + @Override protected void onShutdown(ApplicationEvent event) + { + // Intentionally empty. + } +} diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/scheme/CaveatGroup.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/scheme/CaveatGroup.java index d7d7ba980d..a11a6454fe 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/scheme/CaveatGroup.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/scheme/CaveatGroup.java @@ -19,6 +19,7 @@ package org.alfresco.module.org_alfresco_module_rm.caveat.scheme; +import java.io.Serializable; import java.util.List; import com.google.common.collect.ImmutableList; @@ -31,8 +32,10 @@ import org.alfresco.module.org_alfresco_module_rm.util.CoreServicesExtras; * @author Tom Page * @since 2.4.a */ -public class CaveatGroup +public class CaveatGroup implements Serializable { + /** Generated serial version id. */ + private static final long serialVersionUID = -8909291192015016370L; /** The unique id of the caveat group. */ private String id; /** The key to retrieve the I18n'ed display label for the caveat group. */ diff --git a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/scheme/CaveatMark.java b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/scheme/CaveatMark.java index 8ea1896bc9..5b0a6a2b04 100644 --- a/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/scheme/CaveatMark.java +++ b/rm-server/source/java/org/alfresco/module/org_alfresco_module_rm/caveat/scheme/CaveatMark.java @@ -19,6 +19,8 @@ package org.alfresco.module.org_alfresco_module_rm.caveat.scheme; +import java.io.Serializable; + import org.alfresco.module.org_alfresco_module_rm.util.CoreServicesExtras; /** @@ -28,8 +30,10 @@ import org.alfresco.module.org_alfresco_module_rm.util.CoreServicesExtras; * @author Tom Page * @since 2.4.a */ -public class CaveatMark +public class CaveatMark implements Serializable { + /** Generated serial version id. */ + private static final long serialVersionUID = 2805846540946220526L; /** The id of the group that this mark belongs to. */ private String groupId; /** The id for this mark. */