diff --git a/config/alfresco/messages/patch-service.properties b/config/alfresco/messages/patch-service.properties index bf73490d1b..1370e1cccb 100644 --- a/config/alfresco/messages/patch-service.properties +++ b/config/alfresco/messages/patch-service.properties @@ -82,3 +82,6 @@ patch.systemWorkflowFolder.result.created=Created system workflow container {0}. patch.rssTemplatesFolder.description=Ensures the existence of the 'RSS Templates' folder. patch.rssTemplatesFolder.result.exists=The RSS Templates folder already exists: {0} patch.rssTemplatesFolder.result.created=The RSS Templates folder was successfully created: {0} + +patch.uifacetsAspectRemovalPatch.description=Removes the incorrectly applied uifacets aspect from presentation template files. +patch.uifacetsAspectRemovalPatch.updated=Successfully removed the uifacets aspect from {0} presentation template files. diff --git a/config/alfresco/patch/patch-services-context.xml b/config/alfresco/patch/patch-services-context.xml index 20cd126753..17c6e55e8a 100644 --- a/config/alfresco/patch/patch-services-context.xml +++ b/config/alfresco/patch/patch-services-context.xml @@ -410,4 +410,19 @@ + + patch.uifacetsTemplates + patch.uifacetsAspectRemovalPatch.description + 0 + 17 + 18 + + + + + + + + + diff --git a/config/alfresco/version.properties b/config/alfresco/version.properties index bf3631ebc5..5c1e85dead 100644 --- a/config/alfresco/version.properties +++ b/config/alfresco/version.properties @@ -19,4 +19,4 @@ version.build=@build-number@ # Schema number -version.schema=17 +version.schema=18 diff --git a/source/java/org/alfresco/repo/admin/patch/impl/UIFacetsAspectRemovalPatch.java b/source/java/org/alfresco/repo/admin/patch/impl/UIFacetsAspectRemovalPatch.java new file mode 100644 index 0000000000..6aba06c231 --- /dev/null +++ b/source/java/org/alfresco/repo/admin/patch/impl/UIFacetsAspectRemovalPatch.java @@ -0,0 +1,148 @@ +/* + * 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.util.List; +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.service.cmr.admin.PatchException; +import org.alfresco.service.cmr.repository.NodeRef; +import org.alfresco.service.cmr.repository.StoreRef; +import org.alfresco.service.cmr.view.ImporterService; +import org.alfresco.service.cmr.view.Location; +import org.springframework.context.MessageSource; +import org.springframework.core.io.ClassPathResource; + +/** + * Removes the uifacets aspect incorrectly applied to the default set of Presentation + * Templates loaded during bootstrap. For new installs the bootstrap XML file has been modified + * to no longer apply the aspect. + *

+ * This uses the bootstrap importer to get the paths to look for. + * + * @author Kevin Roast + */ +public class UIFacetsAspectRemovalPatch extends AbstractPatch +{ + private static final String MSG_UPDATED = "patch.uifacetsAspectRemovalPatch.updated"; + + 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_TEMPLATES_CHILDNAME = "spaces.templates.content.childname"; + + private ImporterBootstrap importerBootstrap; + private MessageSource messageSource; + + protected Properties configuration; + protected NodeRef templatesNodeRef; + + public void setImporterBootstrap(ImporterBootstrap importerBootstrap) + { + this.importerBootstrap = importerBootstrap; + } + + public void setMessageSource(MessageSource messageSource) + { + this.messageSource = messageSource; + } + + /** + * Ensure that required properties have been set + */ + protected void checkRequiredProperties() throws Exception + { + checkPropertyNotNull(importerBootstrap, "importerBootstrap"); + checkPropertyNotNull(messageSource, "messageSource"); + } + + /** + * Extracts pertinent references and properties that are common to execution + * of this and derived patches. + * + * @return the number of updated template files + */ + protected int removeAspectFromTemplates() 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 templatesChildName = configuration.getProperty(PROPERTY_TEMPLATES_CHILDNAME); + if (templatesChildName == null || templatesChildName.length() == 0) + { + throw new PatchException("Bootstrap property '" + PROPERTY_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(templatesChildName) + .append("//*[subtypeOf('cm:content')]"); + String xpath = sb.toString(); + + // get the template content nodes + int updated = 0; + List nodeRefs = searchService.selectNodes(storeRootNodeRef, xpath, null, namespaceService, false); + for (NodeRef ref : nodeRefs) + { + // if the content has the uifacets aspect, then remove it and meaningless icon reference + if (nodeService.hasAspect(ref, ContentModel.ASPECT_UIFACETS)) + { + nodeService.removeAspect(ref, ContentModel.ASPECT_UIFACETS); + nodeService.setProperty(ref, ContentModel.PROP_ICON, null); + updated++; + } + } + return updated; + } + + @Override + protected String applyInternal() throws Exception + { + // common properties must be set before we can continue + checkRequiredProperties(); + + int updated = removeAspectFromTemplates(); + + // output a message to describe the result + return I18NUtil.getMessage(MSG_UPDATED, updated); + } +}