diff --git a/config/alfresco/bootstrap-context.xml b/config/alfresco/bootstrap-context.xml
index 2540a07b81..699630b290 100644
--- a/config/alfresco/bootstrap-context.xml
+++ b/config/alfresco/bootstrap-context.xml
@@ -79,6 +79,10 @@
+ * This uses the bootstrap importer to get the paths to look for. If not present, + * the required structures are created. + *
+ * This class should be replaced with a more generic ImporterPatch
+ * that can do conditional importing into given locations.
+ *
+ * JIRA: {@link http://www.alfresco.org/jira/browse/AR-342 AR-342}
+ *
+ * @author Kevin Roast
+ */
+public class EmailTemplatesContentPatch extends AbstractPatch
+{
+ private static final String MSG_CREATED = "patch.emailTemplatesContent.result";
+
+ public static final String PROPERTY_COMPANY_HOME_CHILDNAME = "spaces.company_home.childname";
+ public static final String PROPERTY_DICTIONARY_CHILDNAME = "spaces.dictionary.childname";
+ public static final String PROPERTY_EMAIL_TEMPLATES_CHILDNAME = "spaces.templates.email.childname";
+
+ private ImporterBootstrap importerBootstrap;
+ private NamespaceService namespaceService;
+ private SearchService searchService;
+ private ImporterService importerService;
+ private AuthenticationComponent authComponent;
+ private NodeService nodeService;
+ private MessageSource messageSource;
+
+ protected Properties configuration;
+ protected NodeRef emailTemplatesNodeRef;
+
+ private String templatesACP;
+
+ public void setImporterBootstrap(ImporterBootstrap importerBootstrap)
+ {
+ this.importerBootstrap = importerBootstrap;
+ }
+
+ public void setNamespaceService(NamespaceService namespaceService)
+ {
+ this.namespaceService = namespaceService;
+ }
+
+ public void setSearchService(SearchService searchService)
+ {
+ this.searchService = searchService;
+ }
+
+ public void setImporterService(ImporterService importerService)
+ {
+ this.importerService = importerService;
+ }
+
+ public void setNodeService(NodeService nodeService)
+ {
+ this.nodeService = nodeService;
+ }
+
+ public void setAuthenticationComponent(AuthenticationComponent authComponent)
+ {
+ this.authComponent = authComponent;
+ }
+
+ public void setMessageSource(MessageSource messageSource)
+ {
+ this.messageSource = messageSource;
+ }
+
+ /**
+ * @param templatesACP The templates ACP file to import.
+ */
+ public void setTemplatesACP(String templatesACP)
+ {
+ this.templatesACP = templatesACP;
+ }
+
+ /**
+ * Ensure that required properties have been set
+ */
+ protected void checkRequiredProperties() throws Exception
+ {
+ if (importerBootstrap == null)
+ {
+ throw new PatchException("'importerBootstrap' property has not been set");
+ }
+ if (namespaceService == null)
+ {
+ throw new PatchException("'namespaceService' property has not been set");
+ }
+ if (searchService == null)
+ {
+ throw new PatchException("'searchService' property has not been set");
+ }
+ if (nodeService == null)
+ {
+ throw new PatchException("'nodeService' property has not been set");
+ }
+ if (importerService == null)
+ {
+ throw new PatchException("'importerService' property has not been set");
+ }
+ if (messageSource == null)
+ {
+ throw new PatchException("'messageSource' property has not been set");
+ }
+ if (templatesACP == null || templatesACP.length() == 0)
+ {
+ throw new PatchException("'templatesACP' property has not been set");
+ }
+ }
+
+ /**
+ * Extracts pertinent references and properties that are common to execution
+ * of this and derived patches.
+ */
+ protected void setUp() throws Exception
+ {
+ // get the node store that we must work against
+ StoreRef storeRef = importerBootstrap.getStoreRef();
+ if (storeRef == null)
+ {
+ throw new PatchException("Bootstrap store has not been set");
+ }
+ NodeRef storeRootNodeRef = nodeService.getRootNode(storeRef);
+
+ this.configuration = importerBootstrap.getConfiguration();
+
+ // get the association names that form the path
+ String companyHomeChildName = configuration.getProperty(PROPERTY_COMPANY_HOME_CHILDNAME);
+ if (companyHomeChildName == null || companyHomeChildName.length() == 0)
+ {
+ throw new PatchException("Bootstrap property '" + PROPERTY_COMPANY_HOME_CHILDNAME + "' is not present");
+ }
+ String dictionaryChildName = configuration.getProperty(PROPERTY_DICTIONARY_CHILDNAME);
+ if (dictionaryChildName == null || dictionaryChildName.length() == 0)
+ {
+ throw new PatchException("Bootstrap property '" + PROPERTY_DICTIONARY_CHILDNAME + "' is not present");
+ }
+ String emailTemplatesChildName = configuration.getProperty(PROPERTY_EMAIL_TEMPLATES_CHILDNAME);
+ if (emailTemplatesChildName == null || emailTemplatesChildName.length() == 0)
+ {
+ throw new PatchException("Bootstrap property '" + PROPERTY_EMAIL_TEMPLATES_CHILDNAME + "' is not present");
+ }
+
+ // build the search string to get the email templates node
+ StringBuilder sb = new StringBuilder(128);
+ sb.append("/").append(companyHomeChildName)
+ .append("/").append(dictionaryChildName)
+ .append("/").append(emailTemplatesChildName);
+ String xpath = sb.toString();
+
+ // get the templates node
+ List