mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-07-24 17:32:48 +00:00
AMP dependency checking on the tool side.
This is work in progress and the repo is not currently double checking the runtime dependencies. To declare a dependency, add the following to your module.properties: module.depends.ABC=ABCfromVersion - ABCtoVersion Wildcard * can be used in place of fromVersion or toVersion, as well as just a single version. The most common usage will be: module.depends.ABC=1.0-* i.e. this module depends on ABC version 1.0 or later being present. git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@5601 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -32,9 +32,11 @@ import java.util.Properties;
|
|||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
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.ModuleDetails;
|
||||||
import org.alfresco.service.cmr.module.ModuleInstallState;
|
import org.alfresco.service.cmr.module.ModuleInstallState;
|
||||||
import org.alfresco.util.ISO8601DateFormat;
|
import org.alfresco.util.ISO8601DateFormat;
|
||||||
|
import org.alfresco.util.Pair;
|
||||||
import org.alfresco.util.VersionNumber;
|
import org.alfresco.util.VersionNumber;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -49,6 +51,8 @@ import org.alfresco.util.VersionNumber;
|
|||||||
*/
|
*/
|
||||||
public class ModuleDetailsImpl implements ModuleDetails
|
public class ModuleDetailsImpl implements ModuleDetails
|
||||||
{
|
{
|
||||||
|
private static final long serialVersionUID = 5782747774317351424L;
|
||||||
|
|
||||||
private String id;
|
private String id;
|
||||||
private List<String> aliases;
|
private List<String> aliases;
|
||||||
private VersionNumber version;
|
private VersionNumber version;
|
||||||
@@ -56,6 +60,7 @@ public class ModuleDetailsImpl implements ModuleDetails
|
|||||||
private String description;
|
private String description;
|
||||||
private VersionNumber repoVersionMin;
|
private VersionNumber repoVersionMin;
|
||||||
private VersionNumber repoVersionMax;
|
private VersionNumber repoVersionMax;
|
||||||
|
private List<ModuleDependency> dependencies;
|
||||||
private Date installDate;
|
private Date installDate;
|
||||||
private ModuleInstallState installState;
|
private ModuleInstallState installState;
|
||||||
|
|
||||||
@@ -67,6 +72,7 @@ public class ModuleDetailsImpl implements ModuleDetails
|
|||||||
aliases = new ArrayList<String>(0);
|
aliases = new ArrayList<String>(0);
|
||||||
repoVersionMin = VersionNumber.VERSION_ZERO;
|
repoVersionMin = VersionNumber.VERSION_ZERO;
|
||||||
repoVersionMax = VersionNumber.VERSION_BIG;
|
repoVersionMax = VersionNumber.VERSION_BIG;
|
||||||
|
dependencies = new ArrayList<ModuleDependency>(0);
|
||||||
this.installState = ModuleInstallState.UNKNOWN;
|
this.installState = ModuleInstallState.UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,6 +157,8 @@ public class ModuleDetailsImpl implements ModuleDetails
|
|||||||
{
|
{
|
||||||
repoVersionMax = new VersionNumber(trimmedProperties.getProperty(PROP_REPO_VERSION_MAX));
|
repoVersionMax = new VersionNumber(trimmedProperties.getProperty(PROP_REPO_VERSION_MAX));
|
||||||
}
|
}
|
||||||
|
// DEPENDENCIES
|
||||||
|
this.dependencies = extractDependencies(trimmedProperties);
|
||||||
// INSTALL DATE
|
// INSTALL DATE
|
||||||
if (trimmedProperties.getProperty(PROP_INSTALL_DATE) != null)
|
if (trimmedProperties.getProperty(PROP_INSTALL_DATE) != null)
|
||||||
{
|
{
|
||||||
@@ -212,6 +220,34 @@ public class ModuleDetailsImpl implements ModuleDetails
|
|||||||
this.title = title;
|
this.title = title;
|
||||||
this.description = description;
|
this.description = description;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static List<ModuleDependency> extractDependencies(Properties properties)
|
||||||
|
{
|
||||||
|
int prefixLength = PROP_DEPENDS_PREFIX.length();
|
||||||
|
|
||||||
|
List<ModuleDependency> dependencies = new ArrayList<ModuleDependency>(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()
|
public Properties getProperties()
|
||||||
{
|
{
|
||||||
@@ -230,6 +266,15 @@ public class ModuleDetailsImpl implements ModuleDetails
|
|||||||
{
|
{
|
||||||
properties.setProperty(PROP_REPO_VERSION_MAX, repoVersionMax.toString());
|
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)
|
if (installDate != null)
|
||||||
{
|
{
|
||||||
String installDateStr = ISO8601DateFormat.format(installDate);
|
String installDateStr = ISO8601DateFormat.format(installDate);
|
||||||
@@ -310,6 +355,11 @@ public class ModuleDetailsImpl implements ModuleDetails
|
|||||||
this.repoVersionMax = repoVersionMax;
|
this.repoVersionMax = repoVersionMax;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public List<ModuleDependency> getDependencies()
|
||||||
|
{
|
||||||
|
return dependencies;
|
||||||
|
}
|
||||||
|
|
||||||
public Date getInstallDate()
|
public Date getInstallDate()
|
||||||
{
|
{
|
||||||
return installDate;
|
return installDate;
|
||||||
@@ -329,4 +379,164 @@ public class ModuleDetailsImpl implements ModuleDetails
|
|||||||
{
|
{
|
||||||
this.installState = installState;
|
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<Pair<VersionNumber, VersionNumber>> 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<Pair<VersionNumber, VersionNumber>> buildVersionRanges(String versionStr)
|
||||||
|
{
|
||||||
|
List<Pair<VersionNumber, VersionNumber>> versionRanges = new ArrayList<Pair<VersionNumber, VersionNumber>>(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<VersionNumber, VersionNumber> rangePair = new Pair<VersionNumber, VersionNumber>(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<VersionNumber, VersionNumber> 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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,9 +24,11 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.repo.module;
|
package org.alfresco.repo.module;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
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.ModuleDetails;
|
||||||
import org.alfresco.service.cmr.module.ModuleInstallState;
|
import org.alfresco.service.cmr.module.ModuleInstallState;
|
||||||
import org.alfresco.util.VersionNumber;
|
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_VERSION, "1.0.0");
|
||||||
defaultProperties.setProperty(ModuleDetails.PROP_REPO_VERSION_MIN, new VersionNumber("1.2").toString());
|
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_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());
|
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);
|
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<ModuleDependency> 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
|
public void testTrimming() throws Exception
|
||||||
{
|
{
|
||||||
defaultProperties.setProperty(ModuleDetails.PROP_INSTALL_STATE, " ");
|
defaultProperties.setProperty(ModuleDetails.PROP_INSTALL_STATE, " ");
|
||||||
|
@@ -30,12 +30,14 @@ import java.io.FileOutputStream;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
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.ModuleDetails;
|
||||||
import org.alfresco.service.cmr.module.ModuleInstallState;
|
import org.alfresco.service.cmr.module.ModuleInstallState;
|
||||||
import org.alfresco.util.VersionNumber;
|
import org.alfresco.util.VersionNumber;
|
||||||
@@ -127,25 +129,17 @@ public class ModuleManagementTool
|
|||||||
{
|
{
|
||||||
this.verbose = verbose;
|
this.verbose = verbose;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Installs all modules within a folder into the given WAR file.
|
||||||
*
|
*
|
||||||
* @param directory
|
* @see #installModule(String, String, boolean, boolean, boolean)
|
||||||
* @param warFileLocation
|
|
||||||
*/
|
*/
|
||||||
public void installModules(String directory, String warFileLocation)
|
public void installModules(String directory, String warFileLocation)
|
||||||
{
|
{
|
||||||
installModules(directory, warFileLocation, false, false, true);
|
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)
|
public void installModules(String directoryLocation, String warFileLocation, boolean preview, boolean forceInstall, boolean backupWAR)
|
||||||
{
|
{
|
||||||
java.io.File dir = new java.io.File(directoryLocation);
|
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)
|
private void installModules(java.io.File dir, String warFileLocation, boolean preview, boolean forceInstall, boolean backupWAR)
|
||||||
{
|
{
|
||||||
java.io.File[] children = dir.listFiles();
|
java.io.File[] children = dir.listFiles();
|
||||||
@@ -256,6 +242,25 @@ public class ModuleManagementTool
|
|||||||
String installingId = installingModuleDetails.getId();
|
String installingId = installingModuleDetails.getId();
|
||||||
VersionNumber installingVersion = installingModuleDetails.getVersion();
|
VersionNumber installingVersion = installingModuleDetails.getVersion();
|
||||||
|
|
||||||
|
// Check that the target war has the necessary dependencies for this install
|
||||||
|
List<ModuleDependency> installingModuleDependencies = installingModuleDetails.getDependencies();
|
||||||
|
List<ModuleDependency> missingDependencies = new ArrayList<ModuleDependency>(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
|
// Try to find an installed module by the ID
|
||||||
ModuleDetails installedModuleDetails = ModuleDetailsHelper.createModuleDetailsFromWarAndId(warFileLocation, installingId);
|
ModuleDetails installedModuleDetails = ModuleDetailsHelper.createModuleDetailsFromWarAndId(warFileLocation, installingId);
|
||||||
if (installedModuleDetails == null)
|
if (installedModuleDetails == null)
|
||||||
@@ -716,71 +721,69 @@ public class ModuleManagementTool
|
|||||||
*/
|
*/
|
||||||
public static void main(String[] args)
|
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 (args.length > 3)
|
||||||
if (operation.equals(OP_INSTALL) == true && args.length >= 3)
|
{
|
||||||
{
|
for (int i = 3; i < args.length; i++)
|
||||||
String aepFileLocation = args[1];
|
|
||||||
String warFileLocation = args[2];
|
|
||||||
boolean forceInstall = false;
|
|
||||||
boolean previewInstall = false;
|
|
||||||
boolean backup = true;
|
|
||||||
boolean directory = false;
|
|
||||||
|
|
||||||
if (args.length > 3)
|
|
||||||
{
|
{
|
||||||
for (int i = 3; i < args.length; i++)
|
String option = args[i];
|
||||||
|
if (OPTION_VERBOSE.equals(option) == true)
|
||||||
{
|
{
|
||||||
String option = args[i];
|
manager.setVerbose(true);
|
||||||
if (OPTION_VERBOSE.equals(option) == true)
|
}
|
||||||
{
|
else if (OPTION_FORCE.equals(option) == true)
|
||||||
manager.setVerbose(true);
|
{
|
||||||
}
|
forceInstall = true;
|
||||||
else if (OPTION_FORCE.equals(option) == true)
|
}
|
||||||
{
|
else if (OPTION_PREVIEW.equals(option) == true)
|
||||||
forceInstall = true;
|
{
|
||||||
}
|
previewInstall = true;
|
||||||
else if (OPTION_PREVIEW.equals(option) == true)
|
manager.setVerbose(true);
|
||||||
{
|
}
|
||||||
previewInstall = true;
|
else if (OPTION_NOBACKUP.equals(option) == true)
|
||||||
manager.setVerbose(true);
|
{
|
||||||
}
|
backup = false;
|
||||||
else if (OPTION_NOBACKUP.equals(option) == true)
|
}
|
||||||
{
|
else if (OPTION_DIRECTORY.equals(option) == true)
|
||||||
backup = false;
|
{
|
||||||
}
|
directory = true;
|
||||||
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
|
// Install the module
|
||||||
String warFileLocation = args[1];
|
manager.installModule(aepFileLocation, warFileLocation, previewInstall, forceInstall, backup);
|
||||||
manager.listModules(warFileLocation);
|
|
||||||
}
|
}
|
||||||
else
|
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
|
else
|
||||||
{
|
{
|
||||||
outputUsage();
|
outputUsage();
|
||||||
|
@@ -45,9 +45,10 @@ import de.schlichtherle.io.FileOutputStream;
|
|||||||
import de.schlichtherle.io.ZipDetector;
|
import de.schlichtherle.io.ZipDetector;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Module management tool unit test
|
* @see org.alfresco.repo.module.tool.ModuleManagementTool
|
||||||
*
|
*
|
||||||
* @author Roy Wetherall
|
* @author Roy Wetherall
|
||||||
|
* @author Derek Hulley
|
||||||
*/
|
*/
|
||||||
public class ModuleManagementToolTest extends TestCase
|
public class ModuleManagementToolTest extends TestCase
|
||||||
{
|
{
|
||||||
@@ -61,11 +62,9 @@ public class ModuleManagementToolTest extends TestCase
|
|||||||
manager.setVerbose(true);
|
manager.setVerbose(true);
|
||||||
|
|
||||||
String warLocation = getFileLocation(".war", "module/test.war");
|
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");
|
String ampV2Location = getFileLocation(".amp", "module/test_v2.amp");
|
||||||
|
|
||||||
System.out.println(warLocation);
|
|
||||||
|
|
||||||
// Initial install of module
|
// Initial install of module
|
||||||
this.manager.installModule(ampLocation, warLocation);
|
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()
|
public void testPreviewInstall()
|
||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
manager.setVerbose(true);
|
manager.setVerbose(true);
|
||||||
|
|
||||||
String warLocation = getFileLocation(".war", "module/test.war");
|
String warLocation = getFileLocation(".war", "module/test.war");
|
||||||
String ampLocation = getFileLocation(".amp", "module/test.amp");
|
String ampLocation = getFileLocation(".amp", "module/test_v1.amp");
|
||||||
|
|
||||||
System.out.println(warLocation);
|
|
||||||
|
|
||||||
// Initial install of module
|
// Initial install of module
|
||||||
this.manager.installModule(ampLocation, warLocation, true, false, true);
|
this.manager.installModule(ampLocation, warLocation, true, false, true);
|
||||||
@@ -183,9 +214,7 @@ public class ModuleManagementToolTest extends TestCase
|
|||||||
manager.setVerbose(true);
|
manager.setVerbose(true);
|
||||||
|
|
||||||
String warLocation = getFileLocation(".war", "module/test.war");
|
String warLocation = getFileLocation(".war", "module/test.war");
|
||||||
String ampLocation = getFileLocation(".amp", "module/test.amp");
|
String ampLocation = getFileLocation(".amp", "module/test_v1.amp");
|
||||||
|
|
||||||
System.out.println(warLocation);
|
|
||||||
|
|
||||||
// Initial install of module
|
// Initial install of module
|
||||||
this.manager.installModule(ampLocation, warLocation, false, false, false);
|
this.manager.installModule(ampLocation, warLocation, false, false, false);
|
||||||
@@ -198,15 +227,13 @@ public class ModuleManagementToolTest extends TestCase
|
|||||||
manager.setVerbose(true);
|
manager.setVerbose(true);
|
||||||
|
|
||||||
String warLocation = getFileLocation(".war", "module/test.war");
|
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");
|
String ampV2Location = getFileLocation(".amp", "module/test_v2.amp");
|
||||||
|
|
||||||
int index = ampV2Location.lastIndexOf(File.separator);
|
int index = ampV2Location.lastIndexOf(File.separator);
|
||||||
System.out.println(index);
|
System.out.println(index);
|
||||||
String directoryLocation = ampV2Location.substring(0, index);
|
String directoryLocation = ampV2Location.substring(0, index);
|
||||||
|
|
||||||
System.out.println(warLocation);
|
|
||||||
System.out.println(directoryLocation);
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
this.manager.installModules(directoryLocation, warLocation);
|
this.manager.installModules(directoryLocation, warLocation);
|
||||||
@@ -222,7 +249,7 @@ public class ModuleManagementToolTest extends TestCase
|
|||||||
throws Exception
|
throws Exception
|
||||||
{
|
{
|
||||||
String warLocation = getFileLocation(".war", "module/test.war");
|
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);
|
this.manager.listModules(warLocation);
|
||||||
|
|
||||||
@@ -230,7 +257,7 @@ public class ModuleManagementToolTest extends TestCase
|
|||||||
|
|
||||||
this.manager.listModules(warLocation);
|
this.manager.listModules(warLocation);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFileLocation(String extension, String location)
|
private String getFileLocation(String extension, String location)
|
||||||
throws IOException
|
throws IOException
|
||||||
{
|
{
|
||||||
|
@@ -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 <tt>null</tt>
|
||||||
|
* in which case <tt>false</tt> will always be returned.
|
||||||
|
* @return Returns true if the module satisfies the dependency
|
||||||
|
* requirements.
|
||||||
|
*/
|
||||||
|
public boolean isValidDependency(ModuleDetails moduleDetails);
|
||||||
|
}
|
@@ -24,6 +24,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.alfresco.service.cmr.module;
|
package org.alfresco.service.cmr.module;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
@@ -36,7 +37,7 @@ import org.alfresco.util.VersionNumber;
|
|||||||
* @author Roy Wetherall
|
* @author Roy Wetherall
|
||||||
* @since 2.0
|
* @since 2.0
|
||||||
*/
|
*/
|
||||||
public interface ModuleDetails
|
public interface ModuleDetails extends Serializable
|
||||||
{
|
{
|
||||||
static final String PROP_ID = "module.id";
|
static final String PROP_ID = "module.id";
|
||||||
static final String PROP_ALIASES = "module.aliases";
|
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_DESCRIPTION = "module.description";
|
||||||
static final String PROP_REPO_VERSION_MIN = "module.repo.version.min";
|
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_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_DATE = "module.installDate";
|
||||||
static final String PROP_INSTALL_STATE = "module.installState";
|
static final String PROP_INSTALL_STATE = "module.installState";
|
||||||
|
|
||||||
@@ -110,6 +112,11 @@ public interface ModuleDetails
|
|||||||
*/
|
*/
|
||||||
void setRepoVersionMax(VersionNumber repoVersionMax);
|
void setRepoVersionMax(VersionNumber repoVersionMax);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Returns a list of module dependencies that must be present for this module
|
||||||
|
*/
|
||||||
|
List<ModuleDependency> getDependencies();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the modules install date
|
* Get the modules install date
|
||||||
*
|
*
|
||||||
|
BIN
source/test-resources/module/dependent_on_test_v1.amp
Normal file
BIN
source/test-resources/module/dependent_on_test_v1.amp
Normal file
Binary file not shown.
BIN
source/test-resources/module/dependent_on_test_v2.amp
Normal file
BIN
source/test-resources/module/dependent_on_test_v2.amp
Normal file
Binary file not shown.
Reference in New Issue
Block a user