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 @@ /${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.templates.content.childname} alfresco/templates/content_template_examples.xml + + /${spaces.company_home.childname}/${spaces.dictionary.childname}/${spaces.templates.email.childname} + alfresco/templates/email_templates.acp + diff --git a/config/alfresco/messages/patch-service.properties b/config/alfresco/messages/patch-service.properties index 6c01ea98dd..7f2fbac27e 100644 --- a/config/alfresco/messages/patch-service.properties +++ b/config/alfresco/messages/patch-service.properties @@ -47,3 +47,6 @@ patch.forumsIcons.result=Updated {0} icon references patch.emailTemplatesFolder.description=Ensures the existence of the 'Email Templates' folder. patch.emailTemplatesFolder.result.exists=The email templates folder already exists: {0} patch.emailTemplatesFolder.result.created=The email templates folder was successfully created: {0} + +patch.emailTemplatesContent.description=Loads the email templates into the Email Templates folder. +patch.emailTemplatesContent.result=Imported the Email Templates into the default folder. diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml index 444506f106..2554ad6986 100644 --- a/config/alfresco/patch/patch-services-context.xml +++ b/config/alfresco/patch/patch-services-context.xml @@ -307,5 +307,28 @@ + + patch.emailTemplatesContent + patch.emailTemplatesContent.description + 0 + 9 + 10 + alfresco/templates/email_templates.acp + + + + + + + + + + + + + + + + diff --git a/config/alfresco/templates/email_templates.acp b/config/alfresco/templates/email_templates.acp new file mode 100644 index 0000000000..75006346e6 Binary files /dev/null and b/config/alfresco/templates/email_templates.acp differ diff --git a/config/alfresco/version.properties b/config/alfresco/version.properties index e86b455a1f..967997f2b9 100644 --- a/config/alfresco/version.properties +++ b/config/alfresco/version.properties @@ -15,4 +15,4 @@ version.edition=Community Network # Schema number -version.schema=9 +version.schema=10 diff --git a/source/java/org/alfresco/repo/admin/patch/impl/EmailTemplatesContentPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/EmailTemplatesContentPatch.java new file mode 100644 index 0000000000..a475ed692e --- /dev/null +++ b/source/java/org/alfresco/repo/admin/patch/impl/EmailTemplatesContentPatch.java @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2005 Alfresco, Inc. + * + * Licensed under the Mozilla Public License version 1.1 + * with a permitted attribution clause. You may obtain a + * copy of the License at + * + * http://www.alfresco.org/legal/license.txt + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, + * either express or implied. See the License for the specific + * language governing permissions and limitations under the + * License. + */ +package org.alfresco.repo.admin.patch.impl; + +import java.io.IOException; +import java.io.Serializable; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.alfresco.i18n.I18NUtil; +import org.alfresco.model.ContentModel; +import org.alfresco.repo.admin.patch.AbstractPatch; +import org.alfresco.repo.importer.ACPImportPackageHandler; +import org.alfresco.repo.importer.ImporterBootstrap; +import org.alfresco.repo.security.authentication.AuthenticationComponent; +import org.alfresco.service.cmr.admin.PatchException; +import org.alfresco.service.cmr.repository.ChildAssociationRef; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.NodeService; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.search.SearchService; +import org.alfresco.service.cmr.view.ImporterService; +import org.alfresco.service.cmr.view.Location; +import org.alfresco.service.namespace.NamespaceService; +import org.alfresco.service.namespace.QName; +import org.springframework.context.MessageSource; +import org.springframework.core.io.ClassPathResource; + +/** + * Ensures that the email templates are imported into the default folder. + *

+ * 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 nodeRefs = searchService.selectNodes(storeRootNodeRef, xpath, null, namespaceService, false); + if (nodeRefs.size() == 0) + { + throw new PatchException("Unable to locate Email Templates folder: \n" + + " root: " + storeRootNodeRef + "\n" + + " xpath: " + xpath); + } + else if (nodeRefs.size() > 1) + { + throw new PatchException("Found too many Email Templates folder results: \n" + + " root: " + storeRootNodeRef + "\n" + + " xpath: " + xpath + "\n" + + " results: " + nodeRefs); + } + this.emailTemplatesNodeRef = nodeRefs.get(0); + } + + @Override + protected String applyInternal() throws Exception + { + // common properties must be set before we can continue + checkRequiredProperties(); + + setUp(); + + // import the content + try + { + authComponent.setCurrentUser(authComponent.getSystemUserName()); + + importContent(); + } + finally + { + authComponent.clearCurrentSecurityContext(); + } + + // output a message to describe the result + return I18NUtil.getMessage(MSG_CREATED); + } + + private void importContent() throws IOException + { + // import the content + ClassPathResource acpResource = new ClassPathResource(this.templatesACP); + ACPImportPackageHandler acpHandler = new ACPImportPackageHandler(acpResource.getFile(), null); + Location importLocation = new Location(this.emailTemplatesNodeRef); + importerService.importView(acpHandler, importLocation, null, null); + } +}