diff --git a/src/main/java/org/alfresco/repo/download/CreateDownloadArchiveAction.java b/src/main/java/org/alfresco/repo/download/CreateDownloadArchiveAction.java index 8059f4a690..48f88eeb7e 100644 --- a/src/main/java/org/alfresco/repo/download/CreateDownloadArchiveAction.java +++ b/src/main/java/org/alfresco/repo/download/CreateDownloadArchiveAction.java @@ -43,6 +43,7 @@ import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransacti import org.alfresco.service.cmr.action.Action; import org.alfresco.service.cmr.action.ParameterDefinition; import org.alfresco.service.cmr.coci.CheckOutCheckInService; +import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.download.DownloadRequest; import org.alfresco.service.cmr.download.DownloadStatus; import org.alfresco.service.cmr.download.DownloadStatus.Status; @@ -84,6 +85,7 @@ public class CreateDownloadArchiveAction extends ActionExecuterAbstractBase private NodeService nodeService; private RetryingTransactionHelper transactionHelper; private DownloadStatusUpdateService updateService; + private DictionaryService dictionaryService; private long maximumContentSize = -1l; @@ -167,6 +169,11 @@ public class CreateDownloadArchiveAction extends ActionExecuterAbstractBase this.updateService = updateService; } + public void setDictionaryService(DictionaryService dictionaryService) + { + this.dictionaryService = dictionaryService; + } + /** * Create an archive file containing content from the repository. * @@ -246,7 +253,7 @@ public class CreateDownloadArchiveAction extends ActionExecuterAbstractBase { // perform the actual export final File tempFile = TempFileProvider.createTempFile(TEMP_FILE_PREFIX, TEMP_FILE_SUFFIX); - final ZipDownloadExporter handler = new ZipDownloadExporter(tempFile, checkOutCheckInService, nodeService, transactionHelper, updateService, downloadStorage, actionedUponNodeRef, estimator.getSize(), estimator.getFileCount()); + final ZipDownloadExporter handler = new ZipDownloadExporter(tempFile, checkOutCheckInService, nodeService, transactionHelper, updateService, downloadStorage, dictionaryService, actionedUponNodeRef, estimator.getSize(), estimator.getFileCount()); try { exporterService.exportView(handler, crawlerParameters, null); diff --git a/src/main/java/org/alfresco/repo/download/ZipDownloadExporter.java b/src/main/java/org/alfresco/repo/download/ZipDownloadExporter.java index 7aef4c507e..738a6bfbe0 100644 --- a/src/main/java/org/alfresco/repo/download/ZipDownloadExporter.java +++ b/src/main/java/org/alfresco/repo/download/ZipDownloadExporter.java @@ -39,6 +39,7 @@ import org.alfresco.model.ContentModel; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; import org.alfresco.service.cmr.coci.CheckOutCheckInService; +import org.alfresco.service.cmr.dictionary.DictionaryService; import org.alfresco.service.cmr.download.DownloadStatus; import org.alfresco.service.cmr.download.DownloadStatus.Status; import org.alfresco.service.cmr.repository.ContentData; @@ -77,6 +78,7 @@ public class ZipDownloadExporter extends BaseExporter private RetryingTransactionHelper transactionHelper; private DownloadStorage downloadStorage; + private DictionaryService dictionaryService; private DownloadStatusUpdateService updateService; private Deque> path = new LinkedList>(); @@ -93,11 +95,12 @@ public class ZipDownloadExporter extends BaseExporter * @param transactionHelper RetryingTransactionHelper * @param updateService DownloadStatusUpdateService * @param downloadStorage DownloadStorage + * @param dictionaryService DictionaryService * @param downloadNodeRef NodeRef * @param total long * @param totalFileCount long */ - public ZipDownloadExporter(File zipFile, CheckOutCheckInService checkOutCheckInService, NodeService nodeService, RetryingTransactionHelper transactionHelper, DownloadStatusUpdateService updateService, DownloadStorage downloadStorage, NodeRef downloadNodeRef, long total, long totalFileCount) + public ZipDownloadExporter(File zipFile, CheckOutCheckInService checkOutCheckInService, NodeService nodeService, RetryingTransactionHelper transactionHelper, DownloadStatusUpdateService updateService, DownloadStorage downloadStorage, DictionaryService dictionaryService, NodeRef downloadNodeRef, long total, long totalFileCount) { super(checkOutCheckInService, nodeService); try @@ -106,6 +109,7 @@ public class ZipDownloadExporter extends BaseExporter this.updateService = updateService; this.transactionHelper = transactionHelper; this.downloadStorage = downloadStorage; + this.dictionaryService = dictionaryService; this.downloadNodeRef = downloadNodeRef; this.total = total; @@ -134,7 +138,7 @@ public class ZipDownloadExporter extends BaseExporter { this.currentName = (String)nodeService.getProperty(nodeRef, ContentModel.PROP_NAME); path.push(new Pair(currentName, nodeRef)); - if (ContentModel.TYPE_FOLDER.equals(nodeService.getType(nodeRef))) + if (dictionaryService.isSubClass(nodeService.getType(nodeRef), ContentModel.TYPE_FOLDER)) { String path = getPath() + PATH_SEPARATOR; ZipArchiveEntry archiveEntry = new ZipArchiveEntry(path); diff --git a/src/main/resources/alfresco/download-services-context.xml b/src/main/resources/alfresco/download-services-context.xml index e7206022d8..451db5b4a0 100644 --- a/src/main/resources/alfresco/download-services-context.xml +++ b/src/main/resources/alfresco/download-services-context.xml @@ -89,18 +89,19 @@ - - - - - - - - - - - - + + + + + + + + + + + + + diff --git a/src/test/java/org/alfresco/repo/download/DownloadServiceIntegrationTest.java b/src/test/java/org/alfresco/repo/download/DownloadServiceIntegrationTest.java index 29877bff86..3a6db742f6 100644 --- a/src/test/java/org/alfresco/repo/download/DownloadServiceIntegrationTest.java +++ b/src/test/java/org/alfresco/repo/download/DownloadServiceIntegrationTest.java @@ -34,6 +34,7 @@ import org.alfresco.repo.security.authentication.AuthenticationUtil; import org.alfresco.repo.security.permissions.AccessDeniedException; import org.alfresco.repo.transaction.RetryingTransactionHelper; import org.alfresco.repo.transaction.RetryingTransactionHelper.RetryingTransactionCallback; +import org.alfresco.service.cmr.admin.RepoAdminService; import org.alfresco.service.cmr.coci.CheckOutCheckInService; import org.alfresco.service.cmr.download.DownloadService; import org.alfresco.service.cmr.download.DownloadStatus; @@ -69,8 +70,11 @@ import org.junit.Test; import org.junit.experimental.categories.Category; import org.junit.rules.RuleChain; +import java.io.ByteArrayInputStream; import java.io.IOException; +import java.io.InputStream; import java.io.Serializable; +import java.io.UnsupportedEncodingException; import java.util.Date; import java.util.List; import java.util.Map; @@ -123,6 +127,7 @@ public class DownloadServiceIntegrationTest private static PermissionService PERMISSION_SERVICE; private static RetryingTransactionHelper TRANSACTION_HELPER; private static IntegrityChecker INTEGRITY_CHECKER; + private static RepoAdminService REPO_ADMIN_SERVICE; // Test Content private NodeRef rootFolder; @@ -136,6 +141,41 @@ public class DownloadServiceIntegrationTest private Set allEntries; private NodeRef fileToCheckout; + + // MNT-21671 Download as zip does not include custom folders. + // Define a custom model that is child of cm:folder + private static final String CUSTOM_FOLDER_MODEL_XML = + "" + + " Custom Model" + + " " + + " 1.0" + + + " " + + " " + + " " + + " " + + + " " + + " " + + " " + + + " " + + " " + + " Custom FolderX" + + " cm:folder" + + " " + + " " + + " d:text" + + " " + + " " + + " " + + " " + + " " + + " " + + + " " + + " " + + ""; @BeforeClass public static void init() { @@ -151,6 +191,7 @@ public class DownloadServiceIntegrationTest INTEGRITY_CHECKER.setEnabled(true); INTEGRITY_CHECKER.setFailOnViolation(true); INTEGRITY_CHECKER.setTraceOn(true); + REPO_ADMIN_SERVICE = APP_CONTEXT_INIT.getApplicationContext().getBean("RepoAdminService", RepoAdminService.class); } /** @@ -203,6 +244,24 @@ public class DownloadServiceIntegrationTest allEntries.add("rootFolder/level1Folder2/fileToCheckout.txt"); PERMISSION_SERVICE.setPermission(level1Folder2, TEST_USER.getUsername(), PermissionService.ALL_PERMISSIONS, true); PERMISSION_SERVICE.setPermission(fileToCheckout, TEST_USER.getUsername(), PermissionService.ALL_PERMISSIONS, true); + + // MNT-21671 Download as zip does not include custom folders. + // deploy custom model + final String modelFileName1 = "model-MNT-21671.xml"; + InputStream modelStream = null; + try + { + modelStream = new ByteArrayInputStream(CUSTOM_FOLDER_MODEL_XML.getBytes("UTF-8")); + } + catch (UnsupportedEncodingException e) + { + e.printStackTrace(); + } + REPO_ADMIN_SERVICE.deployModel(modelStream, modelFileName1); + final QName customFolderType = QName.createQName("{custom.model}folderx"); + + testNodes.createNode(rootFolder, "level1CustomFolder", customFolderType, AuthenticationUtil.getAdminUserName()); + allEntries.add("rootFolder/level1CustomFolder/"); } @Test public void createDownload() throws IOException, InterruptedException