mirror of
https://github.com/Alfresco/alfresco-community-repo.git
synced 2025-09-17 14:21:39 +00:00
[MNT-24623] fix for unzipping zip files having accent chars (#3321)
This commit is contained in:
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
@@ -41,6 +41,11 @@ import java.util.List;
|
|||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.zip.ZipException;
|
import java.util.zip.ZipException;
|
||||||
|
|
||||||
|
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
||||||
|
import org.apache.commons.compress.archivers.zip.ZipFile;
|
||||||
|
import org.apache.commons.compress.utils.InputStreamStatistics;
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.model.ApplicationModel;
|
import org.alfresco.model.ApplicationModel;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
@@ -62,10 +67,6 @@ import org.alfresco.service.cmr.view.ImporterService;
|
|||||||
import org.alfresco.service.cmr.view.Location;
|
import org.alfresco.service.cmr.view.Location;
|
||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.util.TempFileProvider;
|
import org.alfresco.util.TempFileProvider;
|
||||||
import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
|
|
||||||
import org.apache.commons.compress.archivers.zip.ZipFile;
|
|
||||||
import org.apache.commons.compress.utils.InputStreamStatistics;
|
|
||||||
import org.apache.commons.lang3.StringUtils;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Importer action executor
|
* Importer action executor
|
||||||
@@ -110,7 +111,8 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
|||||||
/**
|
/**
|
||||||
* Sets the ImporterService to use
|
* Sets the ImporterService to use
|
||||||
*
|
*
|
||||||
* @param importerService The ImporterService
|
* @param importerService
|
||||||
|
* The ImporterService
|
||||||
*/
|
*/
|
||||||
public void setImporterService(ImporterService importerService)
|
public void setImporterService(ImporterService importerService)
|
||||||
{
|
{
|
||||||
@@ -120,27 +122,30 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
|||||||
/**
|
/**
|
||||||
* Sets the NodeService to use
|
* Sets the NodeService to use
|
||||||
*
|
*
|
||||||
* @param nodeService The NodeService
|
* @param nodeService
|
||||||
|
* The NodeService
|
||||||
*/
|
*/
|
||||||
public void setNodeService(NodeService nodeService)
|
public void setNodeService(NodeService nodeService)
|
||||||
{
|
{
|
||||||
this.nodeService = nodeService;
|
this.nodeService = nodeService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the ContentService to use
|
* Sets the ContentService to use
|
||||||
*
|
*
|
||||||
* @param contentService The ContentService
|
* @param contentService
|
||||||
|
* The ContentService
|
||||||
*/
|
*/
|
||||||
public void setContentService(ContentService contentService)
|
public void setContentService(ContentService contentService)
|
||||||
{
|
{
|
||||||
this.contentService = contentService;
|
this.contentService = contentService;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the FileFolderService to use
|
* Sets the FileFolderService to use
|
||||||
*
|
*
|
||||||
* @param fileFolderService The FileFolderService
|
* @param fileFolderService
|
||||||
|
* The FileFolderService
|
||||||
*/
|
*/
|
||||||
public void setFileFolderService(FileFolderService fileFolderService)
|
public void setFileFolderService(FileFolderService fileFolderService)
|
||||||
{
|
{
|
||||||
@@ -152,19 +157,21 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
|||||||
*/
|
*/
|
||||||
public boolean isHighByteZip()
|
public boolean isHighByteZip()
|
||||||
{
|
{
|
||||||
return this.highByteZip;
|
return this.highByteZip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param highByteZip the encoding switch for high-byte ZIP filenames to set
|
* @param highByteZip
|
||||||
|
* the encoding switch for high-byte ZIP filenames to set
|
||||||
*/
|
*/
|
||||||
public void setHighByteZip(boolean highByteZip)
|
public void setHighByteZip(boolean highByteZip)
|
||||||
{
|
{
|
||||||
this.highByteZip = highByteZip;
|
this.highByteZip = highByteZip;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param ratioThreshold the compression ratio threshold for Zip bomb detection
|
* @param ratioThreshold
|
||||||
|
* the compression ratio threshold for Zip bomb detection
|
||||||
*/
|
*/
|
||||||
public void setRatioThreshold(long ratioThreshold)
|
public void setRatioThreshold(long ratioThreshold)
|
||||||
{
|
{
|
||||||
@@ -172,10 +179,10 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method sets a value for the uncompressed bytes limit. If the string does not {@link Long#parseLong(String) parse} to a
|
* This method sets a value for the uncompressed bytes limit. If the string does not {@link Long#parseLong(String) parse} to a java long.
|
||||||
* java long.
|
|
||||||
*
|
*
|
||||||
* @param limit a String representing a valid Java long.
|
* @param limit
|
||||||
|
* a String representing a valid Java long.
|
||||||
*/
|
*/
|
||||||
public void setUncompressedBytesLimit(String limit)
|
public void setUncompressedBytesLimit(String limit)
|
||||||
{
|
{
|
||||||
@@ -200,110 +207,112 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
|||||||
{
|
{
|
||||||
if (this.nodeService.exists(actionedUponNodeRef) == true)
|
if (this.nodeService.exists(actionedUponNodeRef) == true)
|
||||||
{
|
{
|
||||||
// The node being passed in should be an Alfresco content package
|
// The node being passed in should be an Alfresco content package
|
||||||
ContentReader reader = this.contentService.getReader(actionedUponNodeRef, ContentModel.PROP_CONTENT);
|
ContentReader reader = this.contentService.getReader(actionedUponNodeRef, ContentModel.PROP_CONTENT);
|
||||||
if (reader != null)
|
if (reader != null)
|
||||||
{
|
{
|
||||||
NodeRef importDest = (NodeRef)ruleAction.getParameterValue(PARAM_DESTINATION_FOLDER);
|
NodeRef importDest = (NodeRef) ruleAction.getParameterValue(PARAM_DESTINATION_FOLDER);
|
||||||
if (MimetypeMap.MIMETYPE_ACP.equals(reader.getMimetype()))
|
if (MimetypeMap.MIMETYPE_ACP.equals(reader.getMimetype()))
|
||||||
{
|
{
|
||||||
// perform an import of an Alfresco ACP file (special format ZIP structure)
|
// perform an import of an Alfresco ACP file (special format ZIP structure)
|
||||||
File zipFile = null;
|
File zipFile = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// unfortunately a ZIP file can not be read directly from an input stream so we have to create
|
// unfortunately a ZIP file can not be read directly from an input stream so we have to create
|
||||||
// a temporary file first
|
// a temporary file first
|
||||||
zipFile = TempFileProvider.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX_ACP);
|
zipFile = TempFileProvider.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX_ACP);
|
||||||
reader.getContent(zipFile);
|
reader.getContent(zipFile);
|
||||||
|
|
||||||
ACPImportPackageHandler importHandler = new ACPImportPackageHandler(zipFile,
|
ACPImportPackageHandler importHandler = new ACPImportPackageHandler(zipFile,
|
||||||
(String)ruleAction.getParameterValue(PARAM_ENCODING));
|
(String) ruleAction.getParameterValue(PARAM_ENCODING));
|
||||||
|
|
||||||
this.importerService.importView(importHandler, new Location(importDest), null, null);
|
this.importerService.importView(importHandler, new Location(importDest), null, null);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
// now the import is done, delete the temporary file
|
// now the import is done, delete the temporary file
|
||||||
if (zipFile != null)
|
if (zipFile != null)
|
||||||
{
|
{
|
||||||
zipFile.delete();
|
zipFile.delete();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (MimetypeMap.MIMETYPE_ZIP.equals(reader.getMimetype()))
|
else if (MimetypeMap.MIMETYPE_ZIP.equals(reader.getMimetype()))
|
||||||
{
|
{
|
||||||
// perform an import of a standard ZIP file
|
// perform an import of a standard ZIP file
|
||||||
ZipFile zipFile = null;
|
ZipFile zipFile = null;
|
||||||
File tempFile = null;
|
File tempFile = null;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
tempFile = TempFileProvider.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX_ACP);
|
tempFile = TempFileProvider.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX_ACP);
|
||||||
reader.getContent(tempFile);
|
reader.getContent(tempFile);
|
||||||
// NOTE: This encoding allows us to workaround bug:
|
// NOTE: This encoding allows us to workaround bug:
|
||||||
// http://bugs.sun.com/bugdatabase/view_bug.do;:WuuT?bug_id=4820807
|
// http://bugs.sun.com/bugdatabase/view_bug.do;:WuuT?bug_id=4820807
|
||||||
// We also try to use the extra encoding information if present
|
// We also try to use the extra encoding information if present
|
||||||
String encoding = (String) ruleAction.getParameterValue(PARAM_ENCODING);
|
String encoding = (String) ruleAction.getParameterValue(PARAM_ENCODING);
|
||||||
if (encoding == null)
|
if (encoding == null)
|
||||||
{
|
{
|
||||||
encoding = "UTF-8";
|
encoding = "UTF-8";
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (encoding.equalsIgnoreCase("default"))
|
if (encoding.equalsIgnoreCase("default"))
|
||||||
{
|
{
|
||||||
encoding = null;
|
encoding = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
zipFile = new ZipFile(tempFile, encoding, false);
|
zipFile = new ZipFile(tempFile, encoding, false);
|
||||||
// build a temp dir name based on the ID of the noderef we are importing
|
// build a temp dir name based on the ID of the noderef we are importing
|
||||||
// also use the long life temp folder as large ZIP files can take a while
|
// also use the long life temp folder as large ZIP files can take a while
|
||||||
File alfTempDir = TempFileProvider.getLongLifeTempDir("import");
|
File alfTempDir = TempFileProvider.getLongLifeTempDir("import");
|
||||||
File tempDir = new File(alfTempDir.getPath() + File.separatorChar + actionedUponNodeRef.getId());
|
File tempDir = new File(alfTempDir.getPath() + File.separatorChar + actionedUponNodeRef.getId());
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// TODO: improve this code to directly pipe the zip stream output into the repo objects -
|
// TODO: improve this code to directly pipe the zip stream output into the repo objects -
|
||||||
// to remove the need to expand to the filesystem first?
|
// to remove the need to expand to the filesystem first?
|
||||||
extractFile(zipFile, tempDir.getPath(), new ZipBombProtection(ratioThreshold, uncompressedBytesLimit));
|
extractFile(zipFile, tempDir.getPath(), new ZipBombProtection(ratioThreshold, uncompressedBytesLimit));
|
||||||
importDirectory(tempDir.getPath(), importDest);
|
importDirectory(tempDir.getPath(), importDest);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
deleteDir(tempDir);
|
deleteDir(tempDir);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (IOException ioErr)
|
catch (IOException ioErr)
|
||||||
{
|
{
|
||||||
throw new AlfrescoRuntimeException("Failed to import ZIP file.", ioErr);
|
throw new AlfrescoRuntimeException("Failed to import ZIP file.", ioErr);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
// now the import is done, delete the temporary file
|
// now the import is done, delete the temporary file
|
||||||
if (tempFile != null)
|
if (tempFile != null)
|
||||||
{
|
{
|
||||||
tempFile.delete();
|
tempFile.delete();
|
||||||
}
|
}
|
||||||
if (zipFile != null)
|
if (zipFile != null)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
zipFile.close();
|
zipFile.close();
|
||||||
}
|
}
|
||||||
catch (IOException e)
|
catch (IOException e)
|
||||||
{
|
{
|
||||||
throw new AlfrescoRuntimeException("Failed to close zip package.", e);
|
throw new AlfrescoRuntimeException("Failed to close zip package.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Recursively import a directory structure into the specified root node
|
* Recursively import a directory structure into the specified root node
|
||||||
*
|
*
|
||||||
* @param dir The directory of files and folders to import
|
* @param dir
|
||||||
* @param root The root node to import into
|
* The directory of files and folders to import
|
||||||
|
* @param root
|
||||||
|
* The root node to import into
|
||||||
*/
|
*/
|
||||||
private void importDirectory(String dir, NodeRef root)
|
private void importDirectory(String dir, NodeRef root)
|
||||||
{
|
{
|
||||||
@@ -368,16 +377,18 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
|||||||
protected void addParameterDefinitions(List<ParameterDefinition> paramList)
|
protected void addParameterDefinitions(List<ParameterDefinition> paramList)
|
||||||
{
|
{
|
||||||
paramList.add(new ParameterDefinitionImpl(PARAM_DESTINATION_FOLDER, DataTypeDefinition.NODE_REF,
|
paramList.add(new ParameterDefinitionImpl(PARAM_DESTINATION_FOLDER, DataTypeDefinition.NODE_REF,
|
||||||
true, getParamDisplayLabel(PARAM_DESTINATION_FOLDER)));
|
true, getParamDisplayLabel(PARAM_DESTINATION_FOLDER)));
|
||||||
paramList.add(new ParameterDefinitionImpl(PARAM_ENCODING, DataTypeDefinition.TEXT,
|
paramList.add(new ParameterDefinitionImpl(PARAM_ENCODING, DataTypeDefinition.TEXT,
|
||||||
false, getParamDisplayLabel(PARAM_ENCODING)));
|
false, getParamDisplayLabel(PARAM_ENCODING)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Extract the file and folder structure of a ZIP file into the specified directory
|
* Extract the file and folder structure of a ZIP file into the specified directory
|
||||||
*
|
*
|
||||||
* @param archive The ZIP archive to extract
|
* @param archive
|
||||||
* @param extractDir The directory to extract into
|
* The ZIP archive to extract
|
||||||
|
* @param extractDir
|
||||||
|
* The directory to extract into
|
||||||
*/
|
*/
|
||||||
public static void extractFile(ZipFile archive, String extractDir)
|
public static void extractFile(ZipFile archive, String extractDir)
|
||||||
{
|
{
|
||||||
@@ -387,9 +398,12 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
|||||||
/**
|
/**
|
||||||
* Extract the file and folder structure of a ZIP file into the specified directory using a progress tracker
|
* Extract the file and folder structure of a ZIP file into the specified directory using a progress tracker
|
||||||
*
|
*
|
||||||
* @param archive The ZIP archive to extract
|
* @param archive
|
||||||
* @param extractDir The directory to extract into
|
* The ZIP archive to extract
|
||||||
* @param tracker The extraction progress tracker to check against during the extraction process
|
* @param extractDir
|
||||||
|
* The directory to extract into
|
||||||
|
* @param tracker
|
||||||
|
* The extraction progress tracker to check against during the extraction process
|
||||||
*/
|
*/
|
||||||
public static void extractFile(ZipFile archive, String extractDir, ExtractionProgressTracker tracker)
|
public static void extractFile(ZipFile archive, String extractDir, ExtractionProgressTracker tracker)
|
||||||
{
|
{
|
||||||
@@ -407,7 +421,7 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
|||||||
ZipArchiveEntry entry = e.nextElement();
|
ZipArchiveEntry entry = e.nextElement();
|
||||||
if (!entry.isDirectory())
|
if (!entry.isDirectory())
|
||||||
{
|
{
|
||||||
fileName = StringUtils.stripAccents(entry.getName()).replaceAll("\\?","_");
|
fileName = StringUtils.stripAccents(entry.getName()).replaceAll("\\?", "_");
|
||||||
fileName = fileName.replace('/', File.separatorChar);
|
fileName = fileName.replace('/', File.separatorChar);
|
||||||
|
|
||||||
if (fileName.startsWith("/") || fileName.indexOf(":" + File.separator) == 1 || fileName.contains(".." + File.separator))
|
if (fileName.startsWith("/") || fileName.indexOf(":" + File.separator) == 1 || fileName.contains(".." + File.separator))
|
||||||
@@ -421,12 +435,13 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
|||||||
if (parent != null)
|
if (parent != null)
|
||||||
{
|
{
|
||||||
File parentFile = new File(parent);
|
File parentFile = new File(parent);
|
||||||
if (!parentFile.exists()) parentFile.mkdirs();
|
if (!parentFile.exists())
|
||||||
|
parentFile.mkdirs();
|
||||||
}
|
}
|
||||||
|
|
||||||
try (InputStream zis = archive.getInputStream(entry);
|
try (InputStream zis = archive.getInputStream(entry);
|
||||||
InputStream in = new BufferedInputStream(zis, BUFFER_SIZE);
|
InputStream in = new BufferedInputStream(zis, BUFFER_SIZE);
|
||||||
OutputStream out = new BufferedOutputStream(new FileOutputStream(destFileName), BUFFER_SIZE))
|
OutputStream out = new BufferedOutputStream(new FileOutputStream(destFileName), BUFFER_SIZE))
|
||||||
{
|
{
|
||||||
final InputStreamStatistics entryStats = (InputStreamStatistics) zis;
|
final InputStreamStatistics entryStats = (InputStreamStatistics) zis;
|
||||||
int count;
|
int count;
|
||||||
@@ -441,7 +456,7 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
File newdir = new File(extractDir + entry.getName());
|
File newdir = new File(extractDir + StringUtils.stripAccents(entry.getName()).replaceAll("\\?", "_"));
|
||||||
newdir.mkdirs();
|
newdir.mkdirs();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -463,7 +478,8 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
|||||||
/**
|
/**
|
||||||
* Recursively delete a dir of files and directories
|
* Recursively delete a dir of files and directories
|
||||||
*
|
*
|
||||||
* @param dir directory to delete
|
* @param dir
|
||||||
|
* directory to delete
|
||||||
*/
|
*/
|
||||||
public static void deleteDir(File dir)
|
public static void deleteDir(File dir)
|
||||||
{
|
{
|
||||||
@@ -478,8 +494,10 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
|||||||
{
|
{
|
||||||
for (File file : files)
|
for (File file : files)
|
||||||
{
|
{
|
||||||
if (file.isFile()) file.delete();
|
if (file.isFile())
|
||||||
else deleteDir(file);
|
file.delete();
|
||||||
|
else
|
||||||
|
deleteDir(file);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -525,8 +543,7 @@ public class ImporterActionExecuter extends ActionExecuterAbstractBase
|
|||||||
{
|
{
|
||||||
void reportProgress(long compressedBytesCount, long uncompressedBytesCount);
|
void reportProgress(long compressedBytesCount, long uncompressedBytesCount);
|
||||||
|
|
||||||
ExtractionProgressTracker NONE = new ExtractionProgressTracker()
|
ExtractionProgressTracker NONE = new ExtractionProgressTracker() {
|
||||||
{
|
|
||||||
@Override
|
@Override
|
||||||
public void reportProgress(long compressedBytesCount, long uncompressedBytesCount)
|
public void reportProgress(long compressedBytesCount, long uncompressedBytesCount)
|
||||||
{
|
{
|
||||||
|
@@ -2,7 +2,7 @@
|
|||||||
* #%L
|
* #%L
|
||||||
* Alfresco Repository
|
* Alfresco Repository
|
||||||
* %%
|
* %%
|
||||||
* Copyright (C) 2005 - 2022 Alfresco Software Limited
|
* Copyright (C) 2005 - 2025 Alfresco Software Limited
|
||||||
* %%
|
* %%
|
||||||
* This file is part of the Alfresco software.
|
* This file is part of the Alfresco software.
|
||||||
* If the software was purchased under a paid Alfresco license, the terms of
|
* If the software was purchased under a paid Alfresco license, the terms of
|
||||||
@@ -34,6 +34,10 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.junit.AfterClass;
|
||||||
|
import org.junit.BeforeClass;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
import org.alfresco.error.AlfrescoRuntimeException;
|
import org.alfresco.error.AlfrescoRuntimeException;
|
||||||
import org.alfresco.model.ContentModel;
|
import org.alfresco.model.ContentModel;
|
||||||
import org.alfresco.repo.action.ActionImpl;
|
import org.alfresco.repo.action.ActionImpl;
|
||||||
@@ -44,7 +48,6 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper;
|
|||||||
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback;
|
||||||
import org.alfresco.service.ServiceRegistry;
|
import org.alfresco.service.ServiceRegistry;
|
||||||
import org.alfresco.service.cmr.action.Action;
|
import org.alfresco.service.cmr.action.Action;
|
||||||
import org.alfresco.service.cmr.repository.ContentData;
|
|
||||||
import org.alfresco.service.cmr.repository.ContentService;
|
import org.alfresco.service.cmr.repository.ContentService;
|
||||||
import org.alfresco.service.cmr.repository.ContentWriter;
|
import org.alfresco.service.cmr.repository.ContentWriter;
|
||||||
import org.alfresco.service.cmr.repository.NodeRef;
|
import org.alfresco.service.cmr.repository.NodeRef;
|
||||||
@@ -53,15 +56,13 @@ import org.alfresco.service.cmr.repository.StoreRef;
|
|||||||
import org.alfresco.service.namespace.QName;
|
import org.alfresco.service.namespace.QName;
|
||||||
import org.alfresco.util.GUID;
|
import org.alfresco.util.GUID;
|
||||||
import org.alfresco.util.test.junitrules.ApplicationContextInit;
|
import org.alfresco.util.test.junitrules.ApplicationContextInit;
|
||||||
import org.junit.AfterClass;
|
|
||||||
import org.junit.BeforeClass;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class contains tests for {@link ImporterActionExecuter}.
|
* This class contains tests for {@link ImporterActionExecuter}.
|
||||||
*
|
*
|
||||||
* @author abalmus
|
* @author abalmus
|
||||||
*/
|
*/
|
||||||
|
@SuppressWarnings("PMD.JUnitTestsShouldIncludeAssert")
|
||||||
public class ImporterActionExecuterTest
|
public class ImporterActionExecuterTest
|
||||||
{
|
{
|
||||||
// Rule to initialise the default Alfresco spring configuration
|
// Rule to initialise the default Alfresco spring configuration
|
||||||
@@ -87,8 +88,7 @@ public class ImporterActionExecuterTest
|
|||||||
AuthenticationUtil.setRunAsUserSystem();
|
AuthenticationUtil.setRunAsUserSystem();
|
||||||
|
|
||||||
// we need a store
|
// we need a store
|
||||||
storeRef = serviceRegistry.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<StoreRef>()
|
storeRef = serviceRegistry.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<StoreRef>() {
|
||||||
{
|
|
||||||
public StoreRef execute()
|
public StoreRef execute()
|
||||||
{
|
{
|
||||||
StoreRef storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.nanoTime());
|
StoreRef storeRef = nodeService.createStore(StoreRef.PROTOCOL_WORKSPACE, "Test_" + System.nanoTime());
|
||||||
@@ -102,8 +102,7 @@ public class ImporterActionExecuterTest
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
serviceRegistry.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>()
|
serviceRegistry.getRetryingTransactionHelper().doInTransaction(new RetryingTransactionCallback<Void>() {
|
||||||
{
|
|
||||||
public Void execute()
|
public Void execute()
|
||||||
{
|
{
|
||||||
if (storeRef != null)
|
if (storeRef != null)
|
||||||
@@ -125,8 +124,7 @@ public class ImporterActionExecuterTest
|
|||||||
{
|
{
|
||||||
final RetryingTransactionHelper retryingTransactionHelper = serviceRegistry.getRetryingTransactionHelper();
|
final RetryingTransactionHelper retryingTransactionHelper = serviceRegistry.getRetryingTransactionHelper();
|
||||||
|
|
||||||
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>()
|
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>() {
|
||||||
{
|
|
||||||
public Void execute()
|
public Void execute()
|
||||||
{
|
{
|
||||||
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
|
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
|
||||||
@@ -162,8 +160,7 @@ public class ImporterActionExecuterTest
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* MNT-16292: Unzipped files which have folders do not get the cm:titled
|
* MNT-16292: Unzipped files which have folders do not get the cm:titled aspect applied
|
||||||
* aspect applied
|
|
||||||
*
|
*
|
||||||
* @throws IOException
|
* @throws IOException
|
||||||
*/
|
*/
|
||||||
@@ -172,8 +169,7 @@ public class ImporterActionExecuterTest
|
|||||||
{
|
{
|
||||||
final RetryingTransactionHelper retryingTransactionHelper = serviceRegistry.getRetryingTransactionHelper();
|
final RetryingTransactionHelper retryingTransactionHelper = serviceRegistry.getRetryingTransactionHelper();
|
||||||
|
|
||||||
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>()
|
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>() {
|
||||||
{
|
|
||||||
public Void execute()
|
public Void execute()
|
||||||
{
|
{
|
||||||
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
|
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
|
||||||
@@ -199,7 +195,7 @@ public class ImporterActionExecuterTest
|
|||||||
assertTrue("folder didn't get the cm:titled aspect applied", hasAspectTitled);
|
assertTrue("folder didn't get the cm:titled aspect applied", hasAspectTitled);
|
||||||
|
|
||||||
// MNT-17017 check ContentModel.PROP_TITLE is not set on the top level folder, just like Share
|
// MNT-17017 check ContentModel.PROP_TITLE is not set on the top level folder, just like Share
|
||||||
String title = (String)nodeService.getProperty(importedFolder, ContentModel.PROP_TITLE);
|
String title = (String) nodeService.getProperty(importedFolder, ContentModel.PROP_TITLE);
|
||||||
assertNull("The title should not have cm:title set", title);
|
assertNull("The title should not have cm:title set", title);
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@@ -224,8 +220,7 @@ public class ImporterActionExecuterTest
|
|||||||
{
|
{
|
||||||
final RetryingTransactionHelper retryingTransactionHelper = serviceRegistry.getRetryingTransactionHelper();
|
final RetryingTransactionHelper retryingTransactionHelper = serviceRegistry.getRetryingTransactionHelper();
|
||||||
|
|
||||||
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>()
|
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>() {
|
||||||
{
|
|
||||||
public Void execute()
|
public Void execute()
|
||||||
{
|
{
|
||||||
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
|
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
|
||||||
@@ -270,8 +265,7 @@ public class ImporterActionExecuterTest
|
|||||||
{
|
{
|
||||||
final RetryingTransactionHelper retryingTransactionHelper = serviceRegistry.getRetryingTransactionHelper();
|
final RetryingTransactionHelper retryingTransactionHelper = serviceRegistry.getRetryingTransactionHelper();
|
||||||
|
|
||||||
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>()
|
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>() {
|
||||||
{
|
|
||||||
public Void execute()
|
public Void execute()
|
||||||
{
|
{
|
||||||
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
|
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
|
||||||
@@ -306,6 +300,46 @@ public class ImporterActionExecuterTest
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testUnzipZipFileHavingAccentCharInFolderName() throws IOException
|
||||||
|
{
|
||||||
|
final RetryingTransactionHelper retryingTransactionHelper = serviceRegistry.getRetryingTransactionHelper();
|
||||||
|
|
||||||
|
retryingTransactionHelper.doInTransaction(new RetryingTransactionCallback<Void>() {
|
||||||
|
@Override
|
||||||
|
public Void execute() throws Throwable
|
||||||
|
|
||||||
|
{
|
||||||
|
NodeRef rootNodeRef = nodeService.getRootNode(storeRef);
|
||||||
|
|
||||||
|
// create test data
|
||||||
|
NodeRef zipFileNodeRef = nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, ContentModel.ASSOC_CHILDREN, ContentModel.TYPE_CONTENT).getChildRef();
|
||||||
|
NodeRef targetFolderNodeRef = nodeService.createNode(rootNodeRef, ContentModel.ASSOC_CHILDREN, ContentModel.ASSOC_CHILDREN, ContentModel.TYPE_FOLDER).getChildRef();
|
||||||
|
|
||||||
|
putContent(zipFileNodeRef, "import-archive-test/accentCharTestZip.zip");
|
||||||
|
|
||||||
|
Action action = createAction(zipFileNodeRef, "ImporterActionExecuterTestActionDefinition", targetFolderNodeRef);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
importerActionExecuter.setUncompressedBytesLimit("100000");
|
||||||
|
importerActionExecuter.execute(action, zipFileNodeRef);
|
||||||
|
NodeRef importedFolder = nodeService.getChildByName(targetFolderNodeRef, ContentModel.ASSOC_CONTAINS, "accentCharTestZip");
|
||||||
|
assertNotNull("unzip action failed", importedFolder);
|
||||||
|
assertTrue("multiple folder structure created", nodeService.getChildAssocs(importedFolder).size() == 1);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
// clean test data
|
||||||
|
nodeService.deleteNode(targetFolderNodeRef);
|
||||||
|
nodeService.deleteNode(zipFileNodeRef);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private void putContent(NodeRef zipFileNodeRef, String resource)
|
private void putContent(NodeRef zipFileNodeRef, String resource)
|
||||||
{
|
{
|
||||||
URL url = AbstractContentTransformerTest.class.getClassLoader().getResource(resource);
|
URL url = AbstractContentTransformerTest.class.getClassLoader().getResource(resource);
|
||||||
|
Binary file not shown.
Reference in New Issue
Block a user