mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-08-07 17:49:17 +00:00
FIXED : ALF-12777: MMT should not install AMPs which override pre-existing files in the war file, unless -force is provided
The MMT is moving toward more of a validation phase (checks things, calculate changes) then an execution phase (makes the changes). git-svn-id: https://svn.alfresco.com/repos/alfresco-enterprise/alfresco/HEAD/root@33880 c4b6b30b-aa2e-2d43-bbcb-ca4b014f7261
This commit is contained in:
@@ -26,6 +26,7 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.Date;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.alfresco.error.AlfrescoRuntimeException;
|
||||
@@ -196,7 +197,7 @@ public class ModuleManagementTool implements LogOutput
|
||||
* @param warFileLocation the location of the WAR file into which the AMP file is to be installed.
|
||||
* @param preview indicates whether this should be a preview install. This means that the process of
|
||||
* installation will be followed and reported, but the WAR file will not be modified.
|
||||
* @param forceInstall indicates whether the installed files will be replaces reguarless of the currently installed
|
||||
* @param forceInstall indicates whether the installed files will be replaces regardless of the currently installed
|
||||
* version of the AMP. Generally used during development of the AMP.
|
||||
* @param backupWAR indicates whether we should backup the war we are modifying or not
|
||||
*/
|
||||
@@ -240,6 +241,68 @@ public class ModuleManagementTool implements LogOutput
|
||||
// Try to find an installed module by the ID
|
||||
ModuleDetails installedModuleDetails = warHelper.getModuleDetailsOrAlias(theWar, installingModuleDetails);
|
||||
|
||||
uninstallIfNecessary(warFileLocation, installedModuleDetails, preview, forceInstall, installingVersion);
|
||||
|
||||
outputMessage("Adding files relating to version '" + installingVersion + "' of module '" + installingId + "'");
|
||||
InstalledFiles installedFiles = new InstalledFiles(warFileLocation, installingId);
|
||||
|
||||
Properties directoryChanges = calculateChanges(ampFileLocation, warFileLocation, preview, forceInstall, installedFiles);
|
||||
|
||||
if (preview == false)
|
||||
{
|
||||
//Now actually do the changes
|
||||
if (directoryChanges != null && directoryChanges.size() > 0)
|
||||
{
|
||||
for (Entry<Object, Object> entry : directoryChanges.entrySet())
|
||||
{
|
||||
|
||||
File destination = new File((String) entry.getValue(), DETECTOR_AMP_AND_WAR);
|
||||
File source = new File((String) entry.getKey(), DETECTOR_AMP_AND_WAR);
|
||||
//Do the bulk copy since this is quicker than copying files one by one
|
||||
//The changes aren't actuall "committed" until the File.update() is called (below)
|
||||
destination.copyAllFrom(source);
|
||||
}
|
||||
}
|
||||
|
||||
// Save the installed file list
|
||||
installedFiles.save();
|
||||
|
||||
// Update the installed module details
|
||||
installingModuleDetails.setInstallState(ModuleInstallState.INSTALLED);
|
||||
installingModuleDetails.setInstallDate(new Date());
|
||||
ModuleDetailsHelper.saveModuleDetails(warFileLocation, installingModuleDetails);
|
||||
|
||||
// Update the zip files
|
||||
File.update();
|
||||
|
||||
// Set the modified date
|
||||
java.io.File warFile = new java.io.File(warFileLocation);
|
||||
if (warFile.exists())
|
||||
{
|
||||
warFile.setLastModified(System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ZipWarningException ignore)
|
||||
{
|
||||
// Only instances of the class ZipWarningException exist in the chain of
|
||||
// exceptions. We choose to ignore this.
|
||||
}
|
||||
catch (ZipControllerException exception)
|
||||
{
|
||||
// At least one exception occured which is not just a ZipWarningException.
|
||||
// This is a severe situation that needs to be handled.
|
||||
throw new ModuleManagementToolException("A Zip error was encountered during deployment of the AEP into the WAR", exception);
|
||||
}
|
||||
catch (IOException exception)
|
||||
{
|
||||
throw new ModuleManagementToolException("An IO error was encountered during deployment of the AEP into the WAR", exception);
|
||||
}
|
||||
}
|
||||
|
||||
private void uninstallIfNecessary(String warFileLocation, ModuleDetails installedModuleDetails, boolean preview,
|
||||
boolean forceInstall, VersionNumber installingVersion)
|
||||
{
|
||||
// Now clean up the old instance
|
||||
if (installedModuleDetails != null)
|
||||
{
|
||||
@@ -275,6 +338,14 @@ public class ModuleManagementTool implements LogOutput
|
||||
uninstallModule(installedId, warFileLocation, preview, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*/
|
||||
private Properties calculateChanges(String ampFileLocation, String warFileLocation, boolean preview,
|
||||
boolean forceInstall, InstalledFiles installedFiles) throws IOException
|
||||
{
|
||||
Properties dirChanges = new Properties();
|
||||
|
||||
// Check if a custom mapping file has been defined
|
||||
Properties fileMappingProperties = null;
|
||||
@@ -297,8 +368,6 @@ public class ModuleManagementTool implements LogOutput
|
||||
}
|
||||
|
||||
// Copy the files from the AMP file into the WAR file
|
||||
outputMessage("Adding files relating to version '" + installingVersion + "' of module '" + installingId + "'");
|
||||
InstalledFiles installedFiles = new InstalledFiles(warFileLocation, installingId);
|
||||
for (Map.Entry<Object, Object> entry : fileMappingProperties.entrySet())
|
||||
{
|
||||
// The file mappings are expected to start with "/"
|
||||
@@ -317,62 +386,21 @@ public class ModuleManagementTool implements LogOutput
|
||||
mappingTarget = mappingTarget.trim(); //trim whitespace
|
||||
|
||||
// Run throught the files one by one figuring out what we are going to do during the copy
|
||||
copyToWar(ampFileLocation, warFileLocation, mappingSource, mappingTarget, installedFiles, preview);
|
||||
calculateCopyToWar(ampFileLocation, warFileLocation, mappingSource, mappingTarget, installedFiles, preview, forceInstall);
|
||||
|
||||
if (preview == false)
|
||||
{
|
||||
// Get a reference to the source folder (if it isn't present don't do anything)
|
||||
File source = new File(ampFileLocation + "/" + mappingSource, DETECTOR_AMP_AND_WAR);
|
||||
if (source != null && source.list() != null)
|
||||
{
|
||||
// Get a reference to the destination folder
|
||||
File destination = new File(warFileLocation + "/" + mappingTarget, DETECTOR_AMP_AND_WAR);
|
||||
if (destination == null)
|
||||
{
|
||||
throw new ModuleManagementToolException("The destination folder '" + mappingTarget + "' as specified in mapping properties does not exist in the war");
|
||||
}
|
||||
// Do the bulk copy since this is quicker than copying files one by one
|
||||
destination.copyAllFrom(source);
|
||||
}
|
||||
}
|
||||
// Add to the list of directory changes so we can implement the changes later.
|
||||
String sourceDir = ampFileLocation + mappingSource;
|
||||
String destinationDir = warFileLocation + mappingTarget;
|
||||
dirChanges.put(sourceDir, destinationDir);
|
||||
}
|
||||
|
||||
if (preview == false)
|
||||
{
|
||||
// Save the installed file list
|
||||
installedFiles.save();
|
||||
}
|
||||
|
||||
// Update the installed module details
|
||||
installingModuleDetails.setInstallState(ModuleInstallState.INSTALLED);
|
||||
installingModuleDetails.setInstallDate(new Date());
|
||||
ModuleDetailsHelper.saveModuleDetails(warFileLocation, installingModuleDetails);
|
||||
|
||||
// Update the zip files
|
||||
File.update();
|
||||
|
||||
// Set the modified date
|
||||
java.io.File warFile = new java.io.File(warFileLocation);
|
||||
if (warFile.exists())
|
||||
{
|
||||
warFile.setLastModified(System.currentTimeMillis());
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (ZipWarningException ignore)
|
||||
{
|
||||
// Only instances of the class ZipWarningException exist in the chain of
|
||||
// exceptions. We choose to ignore this.
|
||||
}
|
||||
catch (ZipControllerException exception)
|
||||
{
|
||||
// At least one exception occured which is not just a ZipWarningException.
|
||||
// This is a severe situation that needs to be handled.
|
||||
throw new ModuleManagementToolException("A Zip error was encountered during deployment of the AEP into the WAR", exception);
|
||||
}
|
||||
catch (IOException exception)
|
||||
{
|
||||
throw new ModuleManagementToolException("An IO error was encountered during deployment of the AEP into the WAR", exception);
|
||||
}
|
||||
return dirChanges;
|
||||
}
|
||||
|
||||
private void backupWar(String warFileLocation, boolean backupWAR)
|
||||
@@ -511,9 +539,11 @@ public class ModuleManagementTool implements LogOutput
|
||||
* @param destinationDir the directory in the WAR to copy to. It must start with "/".
|
||||
* @param installedFiles a list of the currently installed files
|
||||
* @param preview indicates whether this is a preview install or not
|
||||
* @param forceInstall indicates whether the installed files will be replaces regardless of the currently installed
|
||||
* version of the AMP.
|
||||
* @throws IOException throws any IOExpceptions thar are raised
|
||||
*/
|
||||
private void copyToWar(String ampFileLocation, String warFileLocation, String sourceDir, String destinationDir, InstalledFiles installedFiles, boolean preview)
|
||||
private void calculateCopyToWar(String ampFileLocation, String warFileLocation, String sourceDir, String destinationDir, InstalledFiles installedFiles, boolean preview, boolean forceInstall)
|
||||
throws IOException
|
||||
{
|
||||
if (sourceDir.length() == 0 || !sourceDir.startsWith("/"))
|
||||
@@ -554,6 +584,8 @@ public class ModuleManagementTool implements LogOutput
|
||||
createFile = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (forceInstall)
|
||||
{
|
||||
// Backup file about to be updated
|
||||
backupLocation = BACKUP_DIR + "/" + generateGuid() + ".bin";
|
||||
@@ -562,6 +594,14 @@ public class ModuleManagementTool implements LogOutput
|
||||
File backupFile = new File(warFileLocation + backupLocation, DETECTOR_AMP_AND_WAR);
|
||||
backupFile.copyFrom(destinationChild);
|
||||
}
|
||||
} else {
|
||||
//Not a forced install, there is an existing file in the war, lets rollback the transaction,
|
||||
//throw an error and explain the problem.
|
||||
// File.
|
||||
// ZipController zipController = ZipController.getInstance(warFile);
|
||||
// zipController.reset();
|
||||
throw new ModuleManagementToolException("ERROR: The amp will overwrite an existing file in the war '" + destinationDir + "/" + sourceChild.getName() + "'. Execution halted. By specifying -force , you can force installation of AMP regardless of the current war state.");
|
||||
}
|
||||
}
|
||||
|
||||
if (createFile == true)
|
||||
@@ -583,8 +623,8 @@ public class ModuleManagementTool implements LogOutput
|
||||
mkdir = true;
|
||||
}
|
||||
|
||||
copyToWar(ampFileLocation, warFileLocation, sourceDir + "/" + sourceChild.getName(),
|
||||
destinationDir + "/" + sourceChild.getName(), installedFiles, preview);
|
||||
calculateCopyToWar(ampFileLocation, warFileLocation, sourceDir + "/" + sourceChild.getName(),
|
||||
destinationDir + "/" + sourceChild.getName(), installedFiles, preview, forceInstall);
|
||||
if (mkdir == true)
|
||||
{
|
||||
installedFiles.addMkdir(destinationDir + "/" + sourceChild.getName());
|
||||
|
@@ -81,18 +81,8 @@ public class ModuleManagementToolTest extends TestCase
|
||||
InstalledFiles installed0 = new InstalledFiles(warLocation, "test");
|
||||
installed0.load();
|
||||
assertNotNull(installed0);
|
||||
assertEquals(8, installed0.getAdds().size());
|
||||
assertEquals(9, installed0.getAdds().size());
|
||||
assertEquals(1, installed0.getMkdirs().size());
|
||||
assertEquals(1, installed0.getUpdates().size());
|
||||
String backup = null;
|
||||
String orig = null;
|
||||
for (Map.Entry<String, String> update : installed0.getUpdates().entrySet())
|
||||
{
|
||||
checkContentsOfFile(warLocation + update.getKey(), "VERSIONONE");
|
||||
checkContentsOfFile(warLocation + update.getValue(), "ORIGIONAL");
|
||||
backup = update.getValue();
|
||||
orig = update.getKey();
|
||||
}
|
||||
|
||||
// Try and install same version
|
||||
try
|
||||
@@ -129,7 +119,6 @@ public class ModuleManagementToolTest extends TestCase
|
||||
files3.add("/scripts/test.js");
|
||||
files3.add("/jsp/test.jsp");
|
||||
files3.add("/extra.txt");
|
||||
files3.add(backup);
|
||||
checkForFileNonExistance(warLocation, files3);
|
||||
|
||||
// Check the intstalled files
|
||||
@@ -140,9 +129,6 @@ public class ModuleManagementToolTest extends TestCase
|
||||
assertEquals(1, installed1.getMkdirs().size());
|
||||
assertEquals(0, installed1.getUpdates().size());
|
||||
|
||||
// Ensure the file has been reverted as it isnt updated in the v2.0
|
||||
checkContentsOfFile(warLocation + orig, "ORIGIONAL");
|
||||
|
||||
/**
|
||||
* Try and install an earlier version over a later version
|
||||
*/
|
||||
@@ -269,6 +255,28 @@ public class ModuleManagementToolTest extends TestCase
|
||||
}
|
||||
}
|
||||
|
||||
public void testExistingFilesInWar() throws Exception
|
||||
{
|
||||
manager.setVerbose(true);
|
||||
|
||||
String warLocation = getFileLocation(".war", "module/test.war");
|
||||
String ampLocation = getFileLocation(".amp", "module/test_v4.amp");
|
||||
|
||||
try
|
||||
{
|
||||
this.manager.installModule(ampLocation, warLocation, false, false, true);
|
||||
}
|
||||
catch(ModuleManagementToolException exception)
|
||||
{
|
||||
assertTrue(exception.getMessage().contains("will overwrite an existing file in the war"));
|
||||
}
|
||||
|
||||
this.manager.installModule(ampLocation, warLocation, false, true, true); //Now force it
|
||||
checkContentsOfFile(warLocation + "/jsp/relogin.jsp", "VERSIONONE");
|
||||
checkContentsOfFile(warLocation + "/css/main.css", "p{margin-bottom:1em;}");
|
||||
|
||||
}
|
||||
|
||||
public void testWhiteSpaceInCustomMapping()
|
||||
throws Exception
|
||||
{
|
||||
|
Binary file not shown.
BIN
source/test-resources/module/test_v4.amp
Normal file
BIN
source/test-resources/module/test_v4.amp
Normal file
Binary file not shown.
Reference in New Issue
Block a user