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