diff --git a/source/java/org/alfresco/repo/module/ModuleDetailsImpl.java b/source/java/org/alfresco/repo/module/ModuleDetailsImpl.java index 2e5f6a688f..afc45a6c70 100644 --- a/source/java/org/alfresco/repo/module/ModuleDetailsImpl.java +++ b/source/java/org/alfresco/repo/module/ModuleDetailsImpl.java @@ -32,9 +32,11 @@ import java.util.Properties; import java.util.StringTokenizer; import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.service.cmr.module.ModuleDependency; import org.alfresco.service.cmr.module.ModuleDetails; import org.alfresco.service.cmr.module.ModuleInstallState; import org.alfresco.util.ISO8601DateFormat; +import org.alfresco.util.Pair; import org.alfresco.util.VersionNumber; /** @@ -49,6 +51,8 @@ import org.alfresco.util.VersionNumber; */ public class ModuleDetailsImpl implements ModuleDetails { + private static final long serialVersionUID = 5782747774317351424L; + private String id; private List aliases; private VersionNumber version; @@ -56,6 +60,7 @@ public class ModuleDetailsImpl implements ModuleDetails private String description; private VersionNumber repoVersionMin; private VersionNumber repoVersionMax; + private List dependencies; private Date installDate; private ModuleInstallState installState; @@ -67,6 +72,7 @@ public class ModuleDetailsImpl implements ModuleDetails aliases = new ArrayList(0); repoVersionMin = VersionNumber.VERSION_ZERO; repoVersionMax = VersionNumber.VERSION_BIG; + dependencies = new ArrayList(0); this.installState = ModuleInstallState.UNKNOWN; } @@ -151,6 +157,8 @@ public class ModuleDetailsImpl implements ModuleDetails { repoVersionMax = new VersionNumber(trimmedProperties.getProperty(PROP_REPO_VERSION_MAX)); } + // DEPENDENCIES + this.dependencies = extractDependencies(trimmedProperties); // INSTALL DATE if (trimmedProperties.getProperty(PROP_INSTALL_DATE) != null) { @@ -212,6 +220,34 @@ public class ModuleDetailsImpl implements ModuleDetails this.title = title; this.description = description; } + + private static List extractDependencies(Properties properties) + { + int prefixLength = PROP_DEPENDS_PREFIX.length(); + + List dependencies = new ArrayList(2); + for (Map.Entry entry : properties.entrySet()) + { + String key = (String) entry.getKey(); + String value = (String) entry.getValue(); + if (!key.startsWith(PROP_DEPENDS_PREFIX)) + { + continue; + } + if (key.length() == prefixLength) + { + // Just ignore it + continue; + } + String dependencyId = key.substring(prefixLength); + // Build the dependency + ModuleDependency dependency = new ModuleDependencyImpl(dependencyId, value); + // Add it + dependencies.add(dependency); + } + // Done + return dependencies; + } public Properties getProperties() { @@ -230,6 +266,15 @@ public class ModuleDetailsImpl implements ModuleDetails { properties.setProperty(PROP_REPO_VERSION_MAX, repoVersionMax.toString()); } + if (dependencies.size() > 0) + { + for (ModuleDependency dependency : dependencies) + { + String key = PROP_DEPENDS_PREFIX + dependency.getDependencyId(); + String value = dependency.getVersionString(); + properties.setProperty(key, value); + } + } if (installDate != null) { String installDateStr = ISO8601DateFormat.format(installDate); @@ -310,6 +355,11 @@ public class ModuleDetailsImpl implements ModuleDetails this.repoVersionMax = repoVersionMax; } + public List getDependencies() + { + return dependencies; + } + public Date getInstallDate() { return installDate; @@ -329,4 +379,164 @@ public class ModuleDetailsImpl implements ModuleDetails { this.installState = installState; } + + /** + * @author Derek Hulley + */ + public static final class ModuleDependencyImpl implements ModuleDependency + { + private static final long serialVersionUID = -6850832632316987487L; + + private String dependencyId; + private String versionStr; + private List> versionRanges; + + private ModuleDependencyImpl(String dependencyId, String versionStr) + { + this.dependencyId = dependencyId; + this.versionStr = versionStr; + try + { + versionRanges = buildVersionRanges(versionStr); + } + catch (Throwable e) + { + throw new AlfrescoRuntimeException("Unable to interpret the module version ranges: " + versionStr, e); + } + } + + @Override + public String toString() + { + StringBuilder sb = new StringBuilder(); + sb.append(dependencyId).append(":").append(versionStr); + return sb.toString(); + } + + private static List> buildVersionRanges(String versionStr) + { + List> versionRanges = new ArrayList>(1); + StringTokenizer rangesTokenizer = new StringTokenizer(versionStr, ","); + while (rangesTokenizer.hasMoreTokens()) + { + String range = rangesTokenizer.nextToken().trim(); + // Handle the * special case + if (range.equals("*")) + { + range = "*-*"; + } + if (range.startsWith("-")) + { + range = "*" + range; + } + if (range.endsWith("-")) + { + range = range + "*"; + } + // The range must have at least one version in it + StringTokenizer rangeTokenizer = new StringTokenizer(range, "-", false); + VersionNumber versionLower = null; + VersionNumber versionUpper = null; + while (rangeTokenizer.hasMoreTokens()) + { + String version = rangeTokenizer.nextToken(); + version = version.trim(); + if (versionLower == null) + { + if (version.equals("*")) + { + // Unbounded lower version + versionLower = VersionNumber.VERSION_ZERO; + } + else + { + // Explicit lower bound + versionLower = new VersionNumber(version); + } + } + else if (versionUpper == null) + { + if (version.equals("*")) + { + // Unbounded upper version + versionUpper = VersionNumber.VERSION_BIG; + } + else + { + // Explicit upper bound + versionUpper = new VersionNumber(version); + } + } + } + // Check + if (versionUpper == null && versionLower == null) + { + throw new AlfrescoRuntimeException( + "Valid dependency version ranges are: \n" + + " LOW - HIGH \n" + + " * - HIGH \n" + + " LOW - * \n" + + " * "); + } + else if (versionUpper == null && versionLower != null) + { + versionUpper = versionLower; + } + else if (versionLower == null && versionUpper != null) + { + versionLower = versionUpper; + } + // Create the range pair + Pair rangePair = new Pair(versionLower, versionUpper); + versionRanges.add(rangePair); + } + return versionRanges; + } + + public String getDependencyId() + { + return dependencyId; + } + + public String getVersionString() + { + return versionStr; + } + + public boolean isValidDependency(ModuleDetails moduleDetails) + { + // Nothing to compare to + if (moduleDetails == null) + { + return false; + } + // Check the ID + if (!moduleDetails.getId().equals(dependencyId)) + { + return false; + } + // Check the version number + VersionNumber checkVersion = moduleDetails.getVersion(); + boolean matched = false; + for (Pair versionRange : versionRanges) + { + VersionNumber versionLower = versionRange.getFirst(); + VersionNumber versionUpper = versionRange.getSecond(); + if (checkVersion.compareTo(versionLower) < 0) + { + // The version is too low + continue; + } + if (checkVersion.compareTo(versionUpper) > 0) + { + // The version is too high + continue; + } + // It is a match + matched = true; + break; + } + return matched; + } + } } diff --git a/source/java/org/alfresco/repo/module/ModuleDetailsImplTest.java b/source/java/org/alfresco/repo/module/ModuleDetailsImplTest.java index fb9208514e..4717010b56 100644 --- a/source/java/org/alfresco/repo/module/ModuleDetailsImplTest.java +++ b/source/java/org/alfresco/repo/module/ModuleDetailsImplTest.java @@ -24,9 +24,11 @@ */ package org.alfresco.repo.module; +import java.util.List; import java.util.Properties; import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.service.cmr.module.ModuleDependency; import org.alfresco.service.cmr.module.ModuleDetails; import org.alfresco.service.cmr.module.ModuleInstallState; import org.alfresco.util.VersionNumber; @@ -53,6 +55,14 @@ public class ModuleDetailsImplTest extends TestCase 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_DEPENDS_PREFIX + "a", "1.2.3"); + defaultProperties.setProperty(ModuleDetails.PROP_DEPENDS_PREFIX + "b", "*"); + defaultProperties.setProperty(ModuleDetails.PROP_DEPENDS_PREFIX + "c", "- 1.2"); + defaultProperties.setProperty(ModuleDetails.PROP_DEPENDS_PREFIX + "d", "1.2 -"); + defaultProperties.setProperty(ModuleDetails.PROP_DEPENDS_PREFIX + "e", "* - 1.2"); + defaultProperties.setProperty(ModuleDetails.PROP_DEPENDS_PREFIX + "f", "1.2 - *"); + defaultProperties.setProperty(ModuleDetails.PROP_DEPENDS_PREFIX + "g", "0.5, 0.6"); + defaultProperties.setProperty(ModuleDetails.PROP_DEPENDS_PREFIX + "h", "0.5 - 0.6, 0.9 - *"); defaultProperties.setProperty(ModuleDetails.PROP_INSTALL_STATE, ModuleInstallState.INSTALLED.toString()); } @@ -71,6 +81,29 @@ public class ModuleDetailsImplTest extends TestCase assertEquals("The properties are different", defaultProperties, processedProperties); } + public void testDependencyChecks() + { + ModuleDetails details = new ModuleDetailsImpl(defaultProperties); + + Properties tempProperties = new Properties(); + tempProperties.setProperty(ModuleDetails.PROP_ID, "a"); + tempProperties.setProperty(ModuleDetails.PROP_TITLE, "A"); + tempProperties.setProperty(ModuleDetails.PROP_DESCRIPTION, "A description"); + tempProperties.setProperty(ModuleDetails.PROP_VERSION, "1.0.0"); + ModuleDetails tempDetails = new ModuleDetailsImpl(tempProperties); + + List dependencies = details.getDependencies(); + assertEquals("Incorrect number of dependencies", 8, dependencies.size()); + for (ModuleDependency dependency : dependencies) + { + if (dependency.getDependencyId().equals(tempDetails.getId())) + { + // It should not match + assertFalse("No match expected", dependency.isValidDependency(tempDetails)); + } + } + } + public void testTrimming() throws Exception { defaultProperties.setProperty(ModuleDetails.PROP_INSTALL_STATE, " "); diff --git a/source/java/org/alfresco/repo/module/tool/ModuleManagementTool.java b/source/java/org/alfresco/repo/module/tool/ModuleManagementTool.java index b587550fef..d6be3a0ca7 100644 --- a/source/java/org/alfresco/repo/module/tool/ModuleManagementTool.java +++ b/source/java/org/alfresco/repo/module/tool/ModuleManagementTool.java @@ -30,12 +30,14 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; +import java.util.ArrayList; import java.util.Date; import java.util.List; import java.util.Map; import java.util.Properties; import org.alfresco.error.AlfrescoRuntimeException; +import org.alfresco.service.cmr.module.ModuleDependency; import org.alfresco.service.cmr.module.ModuleDetails; import org.alfresco.service.cmr.module.ModuleInstallState; import org.alfresco.util.VersionNumber; @@ -127,25 +129,17 @@ public class ModuleManagementTool { this.verbose = verbose; } - + /** + * Installs all modules within a folder into the given WAR file. * - * @param directory - * @param warFileLocation + * @see #installModule(String, String, boolean, boolean, boolean) */ public void installModules(String directory, String warFileLocation) { installModules(directory, warFileLocation, false, false, true); } - /** - * - * @param directoryLocation - * @param warFileLocation - * @param preview - * @param forceInstall - * @param backupWAR - */ public void installModules(String directoryLocation, String warFileLocation, boolean preview, boolean forceInstall, boolean backupWAR) { java.io.File dir = new java.io.File(directoryLocation); @@ -159,14 +153,6 @@ public class ModuleManagementTool } } - /** - * - * @param dir - * @param warFileLocation - * @param preview - * @param forceInstall - * @param backupWAR - */ private void installModules(java.io.File dir, String warFileLocation, boolean preview, boolean forceInstall, boolean backupWAR) { java.io.File[] children = dir.listFiles(); @@ -256,6 +242,25 @@ public class ModuleManagementTool String installingId = installingModuleDetails.getId(); VersionNumber installingVersion = installingModuleDetails.getVersion(); + // Check that the target war has the necessary dependencies for this install + List installingModuleDependencies = installingModuleDetails.getDependencies(); + List missingDependencies = new ArrayList(0); + for (ModuleDependency dependency : installingModuleDependencies) + { + String dependencyId = dependency.getDependencyId(); + ModuleDetails dependencyModuleDetails = ModuleDetailsHelper.createModuleDetailsFromWarAndId(warFileLocation, dependencyId); + // Check the dependency. The API specifies that a null returns false, so no null check is required + if (!dependency.isValidDependency(dependencyModuleDetails)) + { + missingDependencies.add(dependency); + continue; + } + } + if (missingDependencies.size() > 0) + { + throw new ModuleManagementToolException("The following modules must first be installed: " + missingDependencies); + } + // Try to find an installed module by the ID ModuleDetails installedModuleDetails = ModuleDetailsHelper.createModuleDetailsFromWarAndId(warFileLocation, installingId); if (installedModuleDetails == null) @@ -716,71 +721,69 @@ public class ModuleManagementTool */ public static void main(String[] args) { - if (args.length >= 1) + if (args.length <= 1) { - ModuleManagementTool manager = new ModuleManagementTool(); + outputUsage(); + return; + } + ModuleManagementTool manager = new ModuleManagementTool(); + + String operation = args[0]; + if (operation.equals(OP_INSTALL) == true && args.length >= 3) + { + String aepFileLocation = args[1]; + String warFileLocation = args[2]; + boolean forceInstall = false; + boolean previewInstall = false; + boolean backup = true; + boolean directory = false; - String operation = args[0]; - if (operation.equals(OP_INSTALL) == true && args.length >= 3) - { - String aepFileLocation = args[1]; - String warFileLocation = args[2]; - boolean forceInstall = false; - boolean previewInstall = false; - boolean backup = true; - boolean directory = false; - - if (args.length > 3) + if (args.length > 3) + { + for (int i = 3; i < args.length; i++) { - for (int i = 3; i < args.length; i++) + String option = args[i]; + if (OPTION_VERBOSE.equals(option) == true) { - String option = args[i]; - if (OPTION_VERBOSE.equals(option) == true) - { - manager.setVerbose(true); - } - else if (OPTION_FORCE.equals(option) == true) - { - forceInstall = true; - } - else if (OPTION_PREVIEW.equals(option) == true) - { - previewInstall = true; - manager.setVerbose(true); - } - else if (OPTION_NOBACKUP.equals(option) == true) - { - backup = false; - } - else if (OPTION_DIRECTORY.equals(option) == true) - { - directory = true; - } + manager.setVerbose(true); + } + else if (OPTION_FORCE.equals(option) == true) + { + forceInstall = true; + } + else if (OPTION_PREVIEW.equals(option) == true) + { + previewInstall = true; + manager.setVerbose(true); + } + else if (OPTION_NOBACKUP.equals(option) == true) + { + backup = false; + } + else if (OPTION_DIRECTORY.equals(option) == true) + { + directory = true; } } - - if (directory == false) - { - // Install the module - manager.installModule(aepFileLocation, warFileLocation, previewInstall, forceInstall, backup); - } - else - { - // Install the modules from the directory - manager.installModules(aepFileLocation, warFileLocation, previewInstall, forceInstall, backup); - } } - else if (OP_LIST.equals(operation) == true && args.length == 2) + + if (directory == false) { - // List the installed modules - String warFileLocation = args[1]; - manager.listModules(warFileLocation); + // Install the module + manager.installModule(aepFileLocation, warFileLocation, previewInstall, forceInstall, backup); } else { - outputUsage(); + // Install the modules from the directory + manager.installModules(aepFileLocation, warFileLocation, previewInstall, forceInstall, backup); } } + else if (OP_LIST.equals(operation) == true && args.length == 2) + { + // List the installed modules + String warFileLocation = args[1]; + manager.listModules(warFileLocation); + } else { outputUsage(); diff --git a/source/java/org/alfresco/repo/module/tool/ModuleManagementToolTest.java b/source/java/org/alfresco/repo/module/tool/ModuleManagementToolTest.java index b28ae22538..885363bcda 100644 --- a/source/java/org/alfresco/repo/module/tool/ModuleManagementToolTest.java +++ b/source/java/org/alfresco/repo/module/tool/ModuleManagementToolTest.java @@ -45,9 +45,10 @@ import de.schlichtherle.io.FileOutputStream; import de.schlichtherle.io.ZipDetector; /** - * Module management tool unit test + * @see org.alfresco.repo.module.tool.ModuleManagementTool * * @author Roy Wetherall + * @author Derek Hulley */ public class ModuleManagementToolTest extends TestCase { @@ -61,11 +62,9 @@ public class ModuleManagementToolTest extends TestCase manager.setVerbose(true); String warLocation = getFileLocation(".war", "module/test.war"); - String ampLocation = getFileLocation(".amp", "module/test.amp"); + String ampLocation = getFileLocation(".amp", "module/test_v1.amp"); String ampV2Location = getFileLocation(".amp", "module/test_v2.amp"); - System.out.println(warLocation); - // Initial install of module this.manager.installModule(ampLocation, warLocation); @@ -161,15 +160,47 @@ public class ModuleManagementToolTest extends TestCase } } + public void testDependencySuccess() throws Exception + { + manager.setVerbose(true); + + String warLocation = getFileLocation(".war", "module/test.war"); + String testAmpV1Location = getFileLocation(".amp", "module/test_v1.amp"); + String testAmpV2Location = getFileLocation(".amp", "module/test_v2.amp"); + String testAmpDepV1Location = getFileLocation(".amp", "module/dependent_on_test_v1.amp"); + String testAmpDepV2Location = getFileLocation(".amp", "module/dependent_on_test_v2.amp"); + + // Install V1 + this.manager.installModule(testAmpV1Location, warLocation, false, false, false); + + // Install the module dependent on test_v1 + this.manager.installModule(testAmpDepV1Location, warLocation, false, false, false); + + try + { + // Attempt to upgrade the dependent module + this.manager.installModule(testAmpDepV2Location, warLocation, false, false, false); + fail("Failed to detect inadequate dependency on the test amp"); + } + catch (ModuleManagementToolException e) + { + System.out.println("Expected: " + e.getMessage()); + } + + // Install the test_v2 + this.manager.installModule(testAmpV2Location, warLocation, false, false, false); + + // The dependent module should now go in + this.manager.installModule(testAmpDepV2Location, warLocation, false, false, false); + } + public void testPreviewInstall() throws Exception { manager.setVerbose(true); String warLocation = getFileLocation(".war", "module/test.war"); - String ampLocation = getFileLocation(".amp", "module/test.amp"); - - System.out.println(warLocation); + String ampLocation = getFileLocation(".amp", "module/test_v1.amp"); // Initial install of module this.manager.installModule(ampLocation, warLocation, true, false, true); @@ -183,9 +214,7 @@ public class ModuleManagementToolTest extends TestCase manager.setVerbose(true); String warLocation = getFileLocation(".war", "module/test.war"); - String ampLocation = getFileLocation(".amp", "module/test.amp"); - - System.out.println(warLocation); + String ampLocation = getFileLocation(".amp", "module/test_v1.amp"); // Initial install of module this.manager.installModule(ampLocation, warLocation, false, false, false); @@ -198,15 +227,13 @@ public class ModuleManagementToolTest extends TestCase manager.setVerbose(true); String warLocation = getFileLocation(".war", "module/test.war"); - String ampLocation = getFileLocation(".amp", "module/test.amp"); + String ampLocation = getFileLocation(".amp", "module/test_v1.amp"); String ampV2Location = getFileLocation(".amp", "module/test_v2.amp"); int index = ampV2Location.lastIndexOf(File.separator); System.out.println(index); String directoryLocation = ampV2Location.substring(0, index); - System.out.println(warLocation); - System.out.println(directoryLocation); try { this.manager.installModules(directoryLocation, warLocation); @@ -222,7 +249,7 @@ public class ModuleManagementToolTest extends TestCase throws Exception { String warLocation = getFileLocation(".war", "module/test.war"); - String ampLocation = getFileLocation(".amp", "module/test.amp"); + String ampLocation = getFileLocation(".amp", "module/test_v1.amp"); this.manager.listModules(warLocation); @@ -230,7 +257,7 @@ public class ModuleManagementToolTest extends TestCase this.manager.listModules(warLocation); } - + private String getFileLocation(String extension, String location) throws IOException { diff --git a/source/java/org/alfresco/service/cmr/module/ModuleDependency.java b/source/java/org/alfresco/service/cmr/module/ModuleDependency.java new file mode 100644 index 0000000000..f24e119c66 --- /dev/null +++ b/source/java/org/alfresco/service/cmr/module/ModuleDependency.java @@ -0,0 +1,63 @@ +/* + * 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.service.cmr.module; + +import java.io.Serializable; + +/** + * An ensapsulated module dependency. Since module dependencies may be range based and even + * unbounded, it is not possible to describe a dependency using a list of module version numbers. + * This class answers the + * + * @author Derek Hulley + */ +public interface ModuleDependency extends Serializable +{ + /** + * Get the ID of the module that this dependency describes. The dependency + * may be upon specific versions or a range of versions. Nevertheless, the + * module given by the returned ID will be required in one version or another. + * + * @return Returns the ID of the module that this depends on + */ + public String getDependencyId(); + + /** + * @return Returns a string representation of the versions supported + */ + public String getVersionString(); + + /** + * Check if a module satisfies the dependency requirements. + * + * @param moduleDetails the module details of the dependency. This must be + * the details of the module with the correct + * {@link #getDependencyId() ID}. This may be null + * in which case false will always be returned. + * @return Returns true if the module satisfies the dependency + * requirements. + */ + public boolean isValidDependency(ModuleDetails moduleDetails); +} diff --git a/source/java/org/alfresco/service/cmr/module/ModuleDetails.java b/source/java/org/alfresco/service/cmr/module/ModuleDetails.java index 00074d726b..a4c0ed5139 100644 --- a/source/java/org/alfresco/service/cmr/module/ModuleDetails.java +++ b/source/java/org/alfresco/service/cmr/module/ModuleDetails.java @@ -24,6 +24,7 @@ */ package org.alfresco.service.cmr.module; +import java.io.Serializable; import java.util.Date; import java.util.List; import java.util.Properties; @@ -36,7 +37,7 @@ import org.alfresco.util.VersionNumber; * @author Roy Wetherall * @since 2.0 */ -public interface ModuleDetails +public interface ModuleDetails extends Serializable { static final String PROP_ID = "module.id"; static final String PROP_ALIASES = "module.aliases"; @@ -45,6 +46,7 @@ public interface ModuleDetails static final String PROP_DESCRIPTION = "module.description"; static final String PROP_REPO_VERSION_MIN = "module.repo.version.min"; static final String PROP_REPO_VERSION_MAX = "module.repo.version.max"; + static final String PROP_DEPENDS_PREFIX = "module.depends."; static final String PROP_INSTALL_DATE = "module.installDate"; static final String PROP_INSTALL_STATE = "module.installState"; @@ -110,6 +112,11 @@ public interface ModuleDetails */ void setRepoVersionMax(VersionNumber repoVersionMax); + /** + * @return Returns a list of module dependencies that must be present for this module + */ + List getDependencies(); + /** * Get the modules install date * diff --git a/source/test-resources/module/dependent_on_test_v1.amp b/source/test-resources/module/dependent_on_test_v1.amp new file mode 100644 index 0000000000..c0e8d10426 Binary files /dev/null and b/source/test-resources/module/dependent_on_test_v1.amp differ diff --git a/source/test-resources/module/dependent_on_test_v2.amp b/source/test-resources/module/dependent_on_test_v2.amp new file mode 100644 index 0000000000..f83113e646 Binary files /dev/null and b/source/test-resources/module/dependent_on_test_v2.amp differ diff --git a/source/test-resources/module/test.amp b/source/test-resources/module/test_v1.amp similarity index 100% rename from source/test-resources/module/test.amp rename to source/test-resources/module/test_v1.amp