From 31efa6d4f3c17b5a9728e38bc34109cca9900475 Mon Sep 17 00:00:00 2001 From: Derek Hulley Date: Thu, 26 Apr 2007 08:42:19 +0000 Subject: [PATCH] Support for renaming of modules - When a module ID changes, the old ID gets put in a list against property 'module.aliases'. - The tool and the repo startup detect the existing installation against the alias and perform a rename. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5559 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261 --- .../repo/module/ModuleComponentHelper.java | 72 +++++++-- .../repo/module/ModuleDetailsImpl.java | 138 +++++++++++++++--- .../repo/module/ModuleDetailsImplTest.java | 108 ++++++++++++++ .../repo/module/ModuleServiceImpl.java | 2 - .../repo/module/tool/InstalledFiles.java | 12 +- .../repo/module/tool/ModuleDetailsHelper.java | 28 +++- .../module/tool/ModuleManagementTool.java | 35 ++++- .../tool/default-file-mapping.properties | 2 +- .../service/cmr/module/ModuleDetails.java | 9 ++ .../cmr/module/ModuleInstallState.java | 2 +- 10 files changed, 362 insertions(+), 46 deletions(-) create mode 100644 source/java/org/alfresco/repo/module/ModuleDetailsImplTest.java diff --git a/source/java/org/alfresco/repo/module/ModuleComponentHelper.java b/source/java/org/alfresco/repo/module/ModuleComponentHelper.java index d7c9aa3ede..5208db88e2 100644 --- a/source/java/org/alfresco/repo/module/ModuleComponentHelper.java +++ b/source/java/org/alfresco/repo/module/ModuleComponentHelper.java @@ -66,7 +66,6 @@ public class ModuleComponentHelper private static final String REGISTRY_PROPERTY_CURRENT_VERSION = "currentVersion"; private static final String REGISTRY_PATH_COMPONENTS = "components"; private static final String REGISTRY_PROPERTY_EXECUTION_DATE = "executionDate"; - private static final String REGISTRY_PROPERTY_DUMMY = "dummy"; private static final String MSG_FOUND_MODULES = "module.msg.found_modules"; private static final String MSG_STARTING = "module.msg.starting"; @@ -248,7 +247,7 @@ public class ModuleComponentHelper // Get the IDs of all modules from the registry RegistryKey moduleKeyAllIds = new RegistryKey( ModuleComponentHelper.URI_MODULES_1_0, - REGISTRY_PATH_MODULES, REGISTRY_PROPERTY_DUMMY); + REGISTRY_PATH_MODULES, null); Collection moduleIds = registryService.getChildElements(moduleKeyAllIds); // Check that each module is present in the distribution @@ -268,13 +267,65 @@ public class ModuleComponentHelper RegistryKey moduleKeyCurrentVersion = new RegistryKey( ModuleComponentHelper.URI_MODULES_1_0, REGISTRY_PATH_MODULES, moduleId, REGISTRY_PROPERTY_CURRENT_VERSION); - VersionNumber versionCurrent = (VersionNumber) registryService.getValue(moduleKeyCurrentVersion); + VersionNumber versionCurrent = (VersionNumber) registryService.getProperty(moduleKeyCurrentVersion); // The module is missing, so warn loggerService.warn(I18NUtil.getMessage(MSG_MISSING, moduleId, versionCurrent)); } } } + /** + * Copies, where necessary, the module registry details from the alias details + * and removes the alias details. + */ + private void renameModule(ModuleDetails module) + { + String moduleId = module.getId(); + List moduleAliases = module.getAliases(); + + // Get the IDs of all modules from the registry + RegistryKey moduleKeyAllIds = new RegistryKey( + ModuleComponentHelper.URI_MODULES_1_0, + REGISTRY_PATH_MODULES, null); + Collection registeredModuleIds = registryService.getChildElements(moduleKeyAllIds); + + // Firstly, is the module installed? + if (registeredModuleIds.contains(moduleId)) + { + // It is there, so we do nothing + return; + } + // Check if any of the registered modules are on the alias list + for (String moduleAlias : moduleAliases) + { + // Is this alias registered? + if (!registeredModuleIds.contains(moduleAlias)) + { + // No alias registered + continue; + } + // We found an alias and have to rename it to the new module ID + RegistryKey moduleKeyNew = new RegistryKey( + ModuleComponentHelper.URI_MODULES_1_0, + REGISTRY_PATH_MODULES, moduleId, null); + RegistryKey moduleKeyOld = new RegistryKey( + ModuleComponentHelper.URI_MODULES_1_0, + REGISTRY_PATH_MODULES, moduleAlias, null); + // Copy it all + registryService.copy(moduleKeyOld, moduleKeyNew); + // Remove the source + registryService.delete(moduleKeyOld); + // Done + if (logger.isDebugEnabled()) + { + logger.debug("Moved old module alias to new module ID: \n" + + " Alias: " + moduleAlias + "\n" + + " Module: " + moduleId); + } + break; + } + } + /** * Does the actual work without fussing about transactions and authentication. */ @@ -283,7 +334,10 @@ public class ModuleComponentHelper String moduleId = module.getId(); VersionNumber moduleVersion = module.getVersion(); - // First check that the module version is fundamentall compatible with the repository + // Check if the module needs a rename first + renameModule(module); + + // First check that the module version is fundamentally compatible with the repository VersionNumber repoVersionNumber = descriptorService.getServerDescriptor().getVersionNumber(); VersionNumber minRepoVersionNumber = module.getRepoVersionMin(); VersionNumber maxRepoVersionNumber = module.getRepoVersionMax(); @@ -303,13 +357,13 @@ public class ModuleComponentHelper RegistryKey moduleKeyCurrentVersion = new RegistryKey( ModuleComponentHelper.URI_MODULES_1_0, REGISTRY_PATH_MODULES, moduleId, REGISTRY_PROPERTY_CURRENT_VERSION); - VersionNumber versionCurrent = (VersionNumber) registryService.getValue(moduleKeyCurrentVersion); + VersionNumber versionCurrent = (VersionNumber) registryService.getProperty(moduleKeyCurrentVersion); String msg = null; if (versionCurrent == null) // There is no current version { msg = I18NUtil.getMessage(MSG_INSTALLING, moduleId, moduleVersion); // Record the install version - registryService.addValue(moduleKeyInstalledVersion, moduleVersion); + registryService.addProperty(moduleKeyInstalledVersion, moduleVersion); } else // It is an upgrade or is the same { @@ -328,7 +382,7 @@ public class ModuleComponentHelper } loggerService.info(msg); // Record the current version - registryService.addValue(moduleKeyCurrentVersion, moduleVersion); + registryService.addProperty(moduleKeyCurrentVersion, moduleVersion); Map componentsByName = getComponents(moduleId); for (ModuleComponent component : componentsByName.values()) @@ -387,7 +441,7 @@ public class ModuleComponentHelper REGISTRY_PATH_MODULES, moduleId, REGISTRY_PATH_COMPONENTS, name, REGISTRY_PROPERTY_EXECUTION_DATE); // Check if the component has been executed - Date executionDate = (Date) registryService.getValue(executionDateKey); + Date executionDate = (Date) registryService.getProperty(executionDateKey); if (executionDate != null && component.isExecuteOnceOnly()) { // It has been executed and is scheduled for a single execution - leave it @@ -410,7 +464,7 @@ public class ModuleComponentHelper component.execute(); // Keep track of it in the registry and in this run executedComponents.add(component); - registryService.addValue(executionDateKey, new Date()); + registryService.addProperty(executionDateKey, new Date()); // Done if (logger.isDebugEnabled()) { diff --git a/source/java/org/alfresco/repo/module/ModuleDetailsImpl.java b/source/java/org/alfresco/repo/module/ModuleDetailsImpl.java index 037ae0a0a3..a8f603269a 100644 --- a/source/java/org/alfresco/repo/module/ModuleDetailsImpl.java +++ b/source/java/org/alfresco/repo/module/ModuleDetailsImpl.java @@ -27,7 +27,9 @@ package org.alfresco.repo.module; import java.util.ArrayList; import java.util.Date; import java.util.List; +import java.util.Map; import java.util.Properties; +import java.util.StringTokenizer; import org.alfresco.error.AlfrescoRuntimeException; import org.alfresco.service.cmr.module.ModuleDetails; @@ -48,6 +50,7 @@ import org.alfresco.util.VersionNumber; public class ModuleDetailsImpl implements ModuleDetails { private String id; + private List aliases; private VersionNumber version; private String title; private String description; @@ -56,53 +59,102 @@ public class ModuleDetailsImpl implements ModuleDetails private Date installDate; private ModuleInstallState installState; - /** + /** + * Private constructor to set default values. + */ + private ModuleDetailsImpl() + { + aliases = new ArrayList(0); + repoVersionMin = new VersionNumber("0.0.0"); + repoVersionMax = new VersionNumber("999.999.999"); + this.installState = ModuleInstallState.UNKNOWN; + } + + /** + * Creates the instance from a set of properties. All the property values are trimmed + * and empty string values are removed from the set. In other words, zero length or + * whitespace strings are not supported. + * * @param properties the set of properties */ public ModuleDetailsImpl(Properties properties) { + // Set defaults + this(); + // Copy the properties so they don't get modified + Properties trimmedProperties = new Properties(); + // Trim all the property values + for (Map.Entry entry : properties.entrySet()) + { + String key = (String) entry.getKey(); + String value = (String) entry.getValue(); + if (value == null) + { + // Don't copy nulls over + continue; + } + String trimmedValue = value.trim(); + if (trimmedValue.length() == 0) + { + // Don't copy empty strings over + continue; + } + // It is a real value + trimmedProperties.setProperty(key, trimmedValue); + } + // Check that the required properties are present List missingProperties = new ArrayList(1); // ID - id = properties.getProperty(PROP_ID); - if (id == null) { missingProperties.add(PROP_ID); } + id = trimmedProperties.getProperty(PROP_ID); + if (id == null) + { + missingProperties.add(PROP_ID); + } + // ALIASES + String aliasesStr = trimmedProperties.getProperty(PROP_ALIASES); + if (aliasesStr != null) + { + StringTokenizer st = new StringTokenizer(aliasesStr, ","); + while (st.hasMoreTokens()) + { + String alias = st.nextToken().trim(); + if (alias.length() == 0) + { + continue; + } + aliases.add(alias); + } + } // VERSION - if (properties.getProperty(PROP_VERSION) == null) + if (trimmedProperties.getProperty(PROP_VERSION) == null) { missingProperties.add(PROP_VERSION); } else { - version = new VersionNumber(properties.getProperty(PROP_VERSION)); + version = new VersionNumber(trimmedProperties.getProperty(PROP_VERSION)); } // TITLE - title = properties.getProperty(PROP_TITLE); + title = trimmedProperties.getProperty(PROP_TITLE); if (title == null) { missingProperties.add(PROP_TITLE); } // DESCRIPTION - description = properties.getProperty(PROP_DESCRIPTION); + description = trimmedProperties.getProperty(PROP_DESCRIPTION); if (description == null) { missingProperties.add(PROP_DESCRIPTION); } // REPO MIN - if (properties.getProperty(PROP_REPO_VERSION_MIN) == null) + if (trimmedProperties.getProperty(PROP_REPO_VERSION_MIN) != null) { - repoVersionMin = new VersionNumber("0.0.0"); - } - else - { - repoVersionMin = new VersionNumber(properties.getProperty(PROP_REPO_VERSION_MIN)); + repoVersionMin = new VersionNumber(trimmedProperties.getProperty(PROP_REPO_VERSION_MIN)); } // REPO MAX - if (properties.getProperty(PROP_REPO_VERSION_MAX) == null) + if (trimmedProperties.getProperty(PROP_REPO_VERSION_MAX) != null) { - repoVersionMax = new VersionNumber("999.999.999"); - } - else - { - repoVersionMax = new VersionNumber(properties.getProperty(PROP_REPO_VERSION_MAX)); + repoVersionMax = new VersionNumber(trimmedProperties.getProperty(PROP_REPO_VERSION_MAX)); } // INSTALL DATE - if (properties.getProperty(PROP_INSTALL_DATE) != null) + if (trimmedProperties.getProperty(PROP_INSTALL_DATE) != null) { - String installDateStr = properties.getProperty(PROP_INSTALL_DATE); + String installDateStr = trimmedProperties.getProperty(PROP_INSTALL_DATE); try { installDate = ISO8601DateFormat.parse(installDateStr); @@ -112,6 +164,19 @@ public class ModuleDetailsImpl implements ModuleDetails throw new AlfrescoRuntimeException("Unable to parse install date: " + installDateStr, e); } } + // INSTALL STATE + if (trimmedProperties.getProperty(PROP_INSTALL_STATE) != null) + { + String installStateStr = trimmedProperties.getProperty(PROP_INSTALL_STATE); + try + { + installState = ModuleInstallState.valueOf(installStateStr); + } + catch (Throwable e) + { + throw new AlfrescoRuntimeException("Unable to parse install state: " + installStateStr, e); + } + } // Check if (missingProperties.size() > 0) { @@ -124,9 +189,11 @@ public class ModuleDetailsImpl implements ModuleDetails " Min repo version: " + repoVersionMin + "\n" + " Max repo version: " + repoVersionMax); } - - // Set other defaults - installState = ModuleInstallState.INSTALLED; + if (id.matches(INVALID_ID_REGEX)) + { + throw new AlfrescoRuntimeException( + "The module ID '" + id + "' is invalid. It may consist of valid characters, numbers, '.', '_' and '-'"); + } } /** @@ -137,6 +204,9 @@ public class ModuleDetailsImpl implements ModuleDetails */ public ModuleDetailsImpl(String id, VersionNumber versionNumber, String title, String description) { + // Set defaults + this(); + this.id = id; this.version = versionNumber; this.title = title; @@ -170,6 +240,21 @@ public class ModuleDetailsImpl implements ModuleDetails String installStateStr = installState.toString(); properties.setProperty(PROP_INSTALL_STATE, installStateStr); } + if (aliases.size() > 0) + { + StringBuilder sb = new StringBuilder(); + boolean first = true; + for (String oldId : aliases) + { + if (!first) + { + sb.append(", "); + } + sb.append(oldId); + first = false; + } + properties.setProperty(PROP_ALIASES, sb.toString()); + } // Done return properties; } @@ -185,6 +270,11 @@ public class ModuleDetailsImpl implements ModuleDetails return id; } + public List getAliases() + { + return aliases; + } + public VersionNumber getVersion() { return version; diff --git a/source/java/org/alfresco/repo/module/ModuleDetailsImplTest.java b/source/java/org/alfresco/repo/module/ModuleDetailsImplTest.java new file mode 100644 index 0000000000..fb9208514e --- /dev/null +++ b/source/java/org/alfresco/repo/module/ModuleDetailsImplTest.java @@ -0,0 +1,108 @@ +/* + * Copyright (C) 2005-2007 Alfresco Software Limited. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program 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 General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + * As a special exception to the terms and conditions of version 2.0 of + * the GPL, you may redistribute this Program in connection with Free/Libre + * and Open Source Software ("FLOSS") applications as described in Alfresco's + * FLOSS exception. You should have recieved a copy of the text describing + * the FLOSS exception, and it is also available here: + * http://www.alfresco.com/legal/licensing" + */ +package org.alfresco.repo.module; + +import java.util.Properties; + +import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.service.cmr.module.ModuleDetails; +import org.alfresco.service.cmr.module.ModuleInstallState; +import org.alfresco.util.VersionNumber; + +import junit.framework.TestCase; + +/** + * @see org.alfresco.repo.module.ModuleDetailsImpl + * + * @author Derek Hulley + */ +public class ModuleDetailsImplTest extends TestCase +{ + private Properties defaultProperties; + + @Override + protected void setUp() throws Exception + { + defaultProperties = new Properties(); + defaultProperties.setProperty(ModuleDetails.PROP_ID, "org.alfresco.module.Test"); + defaultProperties.setProperty(ModuleDetails.PROP_ALIASES, "test, Test"); + defaultProperties.setProperty(ModuleDetails.PROP_TITLE, "Test"); + defaultProperties.setProperty(ModuleDetails.PROP_DESCRIPTION, "Test description"); + defaultProperties.setProperty(ModuleDetails.PROP_VERSION, "1.0.0"); + defaultProperties.setProperty(ModuleDetails.PROP_REPO_VERSION_MIN, new VersionNumber("1.2").toString()); + defaultProperties.setProperty(ModuleDetails.PROP_REPO_VERSION_MAX, new VersionNumber("1.4.3").toString()); + defaultProperties.setProperty(ModuleDetails.PROP_INSTALL_STATE, ModuleInstallState.INSTALLED.toString()); + } + + @SuppressWarnings("unused") + public void testDefaults() + { + ModuleDetails details = new ModuleDetailsImpl(defaultProperties); + } + + public void testWriteAndReadProperties() + { + ModuleDetails details = new ModuleDetailsImpl(defaultProperties); + // convert back to properties + Properties processedProperties = details.getProperties(); + assertEquals("The number of properties changed", defaultProperties.size(), processedProperties.size()); + assertEquals("The properties are different", defaultProperties, processedProperties); + } + + public void testTrimming() throws Exception + { + defaultProperties.setProperty(ModuleDetails.PROP_INSTALL_STATE, " "); + ModuleDetails details = new ModuleDetailsImpl(defaultProperties); + assertEquals("Expected the install state to be UNKNOWN", ModuleInstallState.UNKNOWN, details.getInstallState()); + } + + public void testInvalidIds() throws Exception + { + String[] invalidIds = new String[] {"", " ", "$", "module$Test", "module.Test$", "org alfresco module Test"}; + for (String invalidId : invalidIds) + { + try + { + defaultProperties.setProperty(ModuleDetails.PROP_ID, invalidId); + new ModuleDetailsImpl(defaultProperties); + fail("Invalid ID not detected: " + invalidId); + } + catch (AlfrescoRuntimeException e) + { + // Expected + } + } + } + + public void testValidIds() throws Exception + { + String[] validIds = new String[] {"abc123", " abc123 ", "a-b-c", "a.b.c", "a_b_c", "A.1.2.3"}; + for (String validId : validIds) + { + defaultProperties.setProperty(ModuleDetails.PROP_ID, validId); + new ModuleDetailsImpl(defaultProperties); + } + } +} diff --git a/source/java/org/alfresco/repo/module/ModuleServiceImpl.java b/source/java/org/alfresco/repo/module/ModuleServiceImpl.java index e14229e402..06372cfff3 100644 --- a/source/java/org/alfresco/repo/module/ModuleServiceImpl.java +++ b/source/java/org/alfresco/repo/module/ModuleServiceImpl.java @@ -74,7 +74,6 @@ public class ModuleServiceImpl implements ModuleService private static Log logger = LogFactory.getLog(ModuleServiceImpl.class); private ServiceRegistry serviceRegistry; - private DescriptorService descriptorService; private AuthenticationComponent authenticationComponent; private ModuleComponentHelper moduleComponentHelper; /** A cache of module details by module ID */ @@ -95,7 +94,6 @@ public class ModuleServiceImpl implements ModuleService public void setDescriptorService(DescriptorService descriptorService) { - this.descriptorService = descriptorService; this.moduleComponentHelper.setDescriptorService(descriptorService); } diff --git a/source/java/org/alfresco/repo/module/tool/InstalledFiles.java b/source/java/org/alfresco/repo/module/tool/InstalledFiles.java index adac50e598..a75f2e0d5a 100644 --- a/source/java/org/alfresco/repo/module/tool/InstalledFiles.java +++ b/source/java/org/alfresco/repo/module/tool/InstalledFiles.java @@ -148,9 +148,17 @@ public class InstalledFiles * * @return the file location */ - private String getFileLocation() + public String getFileLocation() { - return this.warLocation + ModuleManagementTool.MODULE_DIR + "/" + this.moduleId + "/modifications.install"; + return this.warLocation + getFilePathInWar(); + } + + /** + * @return Returns the path of the install file within the WAR + */ + public String getFilePathInWar() + { + return ModuleManagementTool.MODULE_DIR + "/" + this.moduleId + "/modifications.install"; } /** diff --git a/source/java/org/alfresco/repo/module/tool/ModuleDetailsHelper.java b/source/java/org/alfresco/repo/module/tool/ModuleDetailsHelper.java index 69229afdfb..93b7d37a3f 100644 --- a/source/java/org/alfresco/repo/module/tool/ModuleDetailsHelper.java +++ b/source/java/org/alfresco/repo/module/tool/ModuleDetailsHelper.java @@ -75,7 +75,7 @@ public class ModuleDetailsHelper try { File file = new File(location, ModuleManagementTool.DETECTOR_AMP_AND_WAR); - if (file.exists() == true) + if (file.exists()) { InputStream is = new FileInputStream(file); result = createModuleDetailsFromPropertiesStream(is); @@ -102,6 +102,19 @@ public class ModuleDetailsHelper return ModuleDetailsHelper.createModuleDetailsFromPropertyLocation(modulePropertiesFileLocation); } + /** + * @param warLocation the location of the WAR file + * @param moduleId the module ID within the WAR + * @return Returns a file handle to the module properties file within the given WAR. + * The file may or may not exist. + */ + public static File getModuleDetailsFileFromWarAndId(String warLocation, String moduleId) + { + String location = ModuleDetailsHelper.getModulePropertiesFileLocation(warLocation, moduleId); + File file = new File(location, ModuleManagementTool.DETECTOR_AMP_AND_WAR); + return file; + } + /** * Gets the file location * @@ -109,9 +122,18 @@ public class ModuleDetailsHelper * @param moduleId the module id * @return the file location */ - private static String getModulePropertiesFileLocation(String warLocation, String moduleId) + public static String getModulePropertiesFileLocation(String warLocation, String moduleId) { - return warLocation + ModuleManagementTool.MODULE_DIR + "/" + moduleId + "/" + "module.properties"; + return warLocation + getModulePropertiesFilePathInWar(moduleId); + } + + /** + * @param moduleId the module ID + * @return Returns the path of the module file within a WAR + */ + public static String getModulePropertiesFilePathInWar(String moduleId) + { + return ModuleManagementTool.MODULE_DIR + "/" + moduleId + "/" + "module.properties"; } /** diff --git a/source/java/org/alfresco/repo/module/tool/ModuleManagementTool.java b/source/java/org/alfresco/repo/module/tool/ModuleManagementTool.java index 603ae87d77..b587550fef 100644 --- a/source/java/org/alfresco/repo/module/tool/ModuleManagementTool.java +++ b/source/java/org/alfresco/repo/module/tool/ModuleManagementTool.java @@ -31,6 +31,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.Date; +import java.util.List; import java.util.Map; import java.util.Properties; @@ -229,7 +230,7 @@ public class ModuleManagementTool backUpDir.mkdir(); } - // Make a backup of the war we are oging to modify + // Make a backup of the war we are going to modify if (backupWAR == true) { java.io.File warFile = new java.io.File(warFileLocation); @@ -255,8 +256,28 @@ public class ModuleManagementTool String installingId = installingModuleDetails.getId(); VersionNumber installingVersion = installingModuleDetails.getVersion(); - // Get the detail of the installed module - ModuleDetails installedModuleDetails = ModuleDetailsHelper.createModuleDetailsFromWarAndId(warFileLocation, installingModuleDetails.getId()); + // Try to find an installed module by the ID + ModuleDetails installedModuleDetails = ModuleDetailsHelper.createModuleDetailsFromWarAndId(warFileLocation, installingId); + if (installedModuleDetails == null) + { + // It might be there as one of the aliases + List installingAliases = installingModuleDetails.getAliases(); + for (String installingAlias : installingAliases) + { + ModuleDetails installedAliasModuleDetails = ModuleDetailsHelper.createModuleDetailsFromWarAndId(warFileLocation, installingAlias); + if (installedAliasModuleDetails == null) + { + // There is nothing by that alias + continue; + } + // We found an alias and will treat it as the same module + installedModuleDetails = installedAliasModuleDetails; + outputMessage("Module '" + installingAlias + "' is installed and is an alias of '" + installingId + "'"); + break; + } + } + + // Now clean up the old instance if (installedModuleDetails != null) { String installedId = installedModuleDetails.getId(); @@ -453,6 +474,12 @@ public class ModuleManagementTool outputMessage("Recovering file '" + update.getKey() + "' from backup '" + update.getValue() + "'", true); } + // Now remove the installed files list + String installedFilesPathInWar = installedFiles.getFilePathInWar(); + removeFile(warFileLocation, installedFilesPathInWar, preview); + // Remove the module properties + String modulePropertiesFileLocationInWar = ModuleDetailsHelper.getModulePropertiesFilePathInWar(moduleId); + removeFile(warFileLocation, modulePropertiesFileLocationInWar, preview); } /** @@ -478,7 +505,7 @@ public class ModuleManagementTool outputMessage("The file '" + filePath + "' was expected for removal but was not present in the war", true); } } - + /** * Copies a file from the AMP location to the correct location in the WAR, interating on directories where appropraite. * diff --git a/source/java/org/alfresco/repo/module/tool/default-file-mapping.properties b/source/java/org/alfresco/repo/module/tool/default-file-mapping.properties index ab22f4cace..0ef111b60e 100644 --- a/source/java/org/alfresco/repo/module/tool/default-file-mapping.properties +++ b/source/java/org/alfresco/repo/module/tool/default-file-mapping.properties @@ -1,4 +1,4 @@ -# The default AEP => WAR file mappings +# The default AMP => WAR file mappings /config=/WEB-INF/classes /lib=/WEB-INF/lib /licenses=/WEB-INF/licenses diff --git a/source/java/org/alfresco/service/cmr/module/ModuleDetails.java b/source/java/org/alfresco/service/cmr/module/ModuleDetails.java index 86b5f64c12..00074d726b 100644 --- a/source/java/org/alfresco/service/cmr/module/ModuleDetails.java +++ b/source/java/org/alfresco/service/cmr/module/ModuleDetails.java @@ -25,6 +25,7 @@ package org.alfresco.service.cmr.module; import java.util.Date; +import java.util.List; import java.util.Properties; import org.alfresco.util.VersionNumber; @@ -38,6 +39,7 @@ import org.alfresco.util.VersionNumber; public interface ModuleDetails { static final String PROP_ID = "module.id"; + static final String PROP_ALIASES = "module.aliases"; static final String PROP_VERSION = "module.version"; static final String PROP_TITLE = "module.title"; static final String PROP_DESCRIPTION = "module.description"; @@ -46,6 +48,8 @@ public interface ModuleDetails static final String PROP_INSTALL_DATE = "module.installDate"; static final String PROP_INSTALL_STATE = "module.installState"; + static final String INVALID_ID_REGEX = ".*[^\\w.-].*"; + /** * Get all defined properties. * @@ -60,6 +64,11 @@ public interface ModuleDetails */ String getId(); + /** + * @return Returns a list of IDs by which this module may once have been known + */ + List getAliases(); + /** * Get the version number of the module * diff --git a/source/java/org/alfresco/service/cmr/module/ModuleInstallState.java b/source/java/org/alfresco/service/cmr/module/ModuleInstallState.java index 0913d16170..0eca126a64 100644 --- a/source/java/org/alfresco/service/cmr/module/ModuleInstallState.java +++ b/source/java/org/alfresco/service/cmr/module/ModuleInstallState.java @@ -32,7 +32,7 @@ package org.alfresco.service.cmr.module; public enum ModuleInstallState { /** The state of the module is unknown */ - UKNOWN, + UNKNOWN, /** The module is installed */ INSTALLED, /** The module is disabled */