This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/camel.git
The following commit(s) were added to refs/heads/main by this push: new c488231b60f CAMEL-20852: New option to allow adding empty files to a zip (#14426) c488231b60f is described below commit c488231b60fc37a17c3ec8016f4113cc790521e8 Author: Alexander Friedrichs <un...@users.noreply.github.com> AuthorDate: Mon Jun 10 07:22:52 2024 +0200 CAMEL-20852: New option to allow adding empty files to a zip (#14426) --- .../zipfile/ZipAggregationStrategyConfigurer.java | 6 ++++ .../apache/camel/bean/ZipAggregationStrategy.json | 2 +- .../aggregate/zipfile/ZipAggregationStrategy.java | 35 ++++++++++++++++--- .../ZipAggregationStrategyEmptyFileTest.java | 39 +++++++++++++++++++--- 4 files changed, 73 insertions(+), 9 deletions(-) diff --git a/components/camel-zipfile/src/generated/java/org/apache/camel/processor/aggregate/zipfile/ZipAggregationStrategyConfigurer.java b/components/camel-zipfile/src/generated/java/org/apache/camel/processor/aggregate/zipfile/ZipAggregationStrategyConfigurer.java index 7609bc81e1a..5f20c83f9b7 100644 --- a/components/camel-zipfile/src/generated/java/org/apache/camel/processor/aggregate/zipfile/ZipAggregationStrategyConfigurer.java +++ b/components/camel-zipfile/src/generated/java/org/apache/camel/processor/aggregate/zipfile/ZipAggregationStrategyConfigurer.java @@ -23,6 +23,8 @@ public class ZipAggregationStrategyConfigurer extends org.apache.camel.support.c public boolean configure(CamelContext camelContext, Object obj, String name, Object value, boolean ignoreCase) { org.apache.camel.processor.aggregate.zipfile.ZipAggregationStrategy target = (org.apache.camel.processor.aggregate.zipfile.ZipAggregationStrategy) obj; switch (ignoreCase ? name.toLowerCase() : name) { + case "allowemptyfiles": + case "allowEmptyFiles": target.setAllowEmptyFiles(property(camelContext, boolean.class, value)); return true; case "fileprefix": case "filePrefix": target.setFilePrefix(property(camelContext, java.lang.String.class, value)); return true; case "filesuffix": @@ -42,6 +44,8 @@ public class ZipAggregationStrategyConfigurer extends org.apache.camel.support.c @Override public Class<?> getOptionType(String name, boolean ignoreCase) { switch (ignoreCase ? name.toLowerCase() : name) { + case "allowemptyfiles": + case "allowEmptyFiles": return boolean.class; case "fileprefix": case "filePrefix": return java.lang.String.class; case "filesuffix": @@ -62,6 +66,8 @@ public class ZipAggregationStrategyConfigurer extends org.apache.camel.support.c public Object getOptionValue(Object obj, String name, boolean ignoreCase) { org.apache.camel.processor.aggregate.zipfile.ZipAggregationStrategy target = (org.apache.camel.processor.aggregate.zipfile.ZipAggregationStrategy) obj; switch (ignoreCase ? name.toLowerCase() : name) { + case "allowemptyfiles": + case "allowEmptyFiles": return target.isAllowEmptyFiles(); case "fileprefix": case "filePrefix": return target.getFilePrefix(); case "filesuffix": diff --git a/components/camel-zipfile/src/generated/resources/META-INF/services/org/apache/camel/bean/ZipAggregationStrategy.json b/components/camel-zipfile/src/generated/resources/META-INF/services/org/apache/camel/bean/ZipAggregationStrategy.json index 7f70dc05ba4..479b164f676 100644 --- a/components/camel-zipfile/src/generated/resources/META-INF/services/org/apache/camel/bean/ZipAggregationStrategy.json +++ b/components/camel-zipfile/src/generated/resources/META-INF/services/org/apache/camel/bean/ZipAggregationStrategy.json @@ -10,7 +10,7 @@ "groupId": "org.apache.camel", "artifactId": "camel-zipfile", "version": "4.7.0-SNAPSHOT", - "properties": { "filePrefix": { "index": 0, "kind": "property", "displayName": "File Prefix", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the prefix that will be used when creating the ZIP filename." }, "fileSuffix": { "index": 1, "kind": "property", "displayName": "File Suffix", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": [...] + "properties": { "filePrefix": { "index": 0, "kind": "property", "displayName": "File Prefix", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": false, "secret": false, "description": "Sets the prefix that will be used when creating the ZIP filename." }, "fileSuffix": { "index": 1, "kind": "property", "displayName": "File Suffix", "required": false, "type": "string", "javaType": "java.lang.String", "deprecated": false, "autowired": [...] } } diff --git a/components/camel-zipfile/src/main/java/org/apache/camel/processor/aggregate/zipfile/ZipAggregationStrategy.java b/components/camel-zipfile/src/main/java/org/apache/camel/processor/aggregate/zipfile/ZipAggregationStrategy.java index b7f05a312d3..156061709e9 100644 --- a/components/camel-zipfile/src/main/java/org/apache/camel/processor/aggregate/zipfile/ZipAggregationStrategy.java +++ b/components/camel-zipfile/src/main/java/org/apache/camel/processor/aggregate/zipfile/ZipAggregationStrategy.java @@ -64,6 +64,9 @@ public class ZipAggregationStrategy implements AggregationStrategy { private String filePrefix; @Metadata(description = "Sets the suffix that will be used when creating the ZIP filename.", defaultValue = "zip") private String fileSuffix = ".zip"; + @Metadata(label = "advanced", + description = "Whether to add empty files to the ZIP.", defaultValue = "false") + private boolean allowEmptyFiles; @Metadata(label = "advanced", description = "If the incoming message is from a file, then the folder structure of said file can be preserved") private boolean preserveFolderStructure; @@ -106,9 +109,25 @@ public class ZipAggregationStrategy implements AggregationStrategy { * of memory. */ public ZipAggregationStrategy(boolean preserveFolderStructure, boolean useFilenameHeader, boolean useTempFile) { + this(preserveFolderStructure, useFilenameHeader, useTempFile, false); + } + + /** + * @param preserveFolderStructure if true, the folder structure is preserved when the source is a type of + * {@link GenericFileMessage}. If used with a file, use recursive=true. + * @param useFilenameHeader if true, the filename header will be used to name aggregated byte arrays within + * the ZIP file. + * @param useTempFile if true, the ZipFileSystem will use temporary files for zip manipulations instead + * of memory. + * @param allowEmptyFiles if true, the Aggregation will also add empty files to the zip. + * + */ + public ZipAggregationStrategy(boolean preserveFolderStructure, boolean useFilenameHeader, boolean useTempFile, + boolean allowEmptyFiles) { this.preserveFolderStructure = preserveFolderStructure; this.useFilenameHeader = useFilenameHeader; this.useTempFile = useTempFile; + this.allowEmptyFiles = allowEmptyFiles; } /** @@ -147,6 +166,14 @@ public class ZipAggregationStrategy implements AggregationStrategy { this.fileSuffix = fileSuffix; } + public boolean isAllowEmptyFiles() { + return allowEmptyFiles; + } + + public void setAllowEmptyFiles(boolean allowEmptyFiles) { + this.allowEmptyFiles = allowEmptyFiles; + } + public File getParentDir() { return parentDir; } @@ -222,8 +249,8 @@ public class ZipAggregationStrategy implements AggregationStrategy { if (body instanceof File) { try { File appendFile = (File) body; - // do not try to append empty files - if (appendFile.length() > 0) { + // try to append empty data only when explicit set + if (this.allowEmptyFiles || appendFile.length() > 0) { String entryName = preserveFolderStructure ? newExchange.getIn().getHeader(Exchange.FILE_NAME, String.class) : newExchange.getIn().getMessageId(); @@ -236,8 +263,8 @@ public class ZipAggregationStrategy implements AggregationStrategy { // Handle all other messages try { byte[] buffer = newExchange.getIn().getMandatoryBody(byte[].class); - // do not try to append empty data - if (buffer.length > 0) { + // try to append empty data only when explicit set + if (this.allowEmptyFiles || buffer.length > 0) { String entryName = useFilenameHeader ? newExchange.getIn().getHeader(Exchange.FILE_NAME, String.class) : newExchange.getIn().getMessageId(); diff --git a/components/camel-zipfile/src/test/java/org/apache/camel/processor/aggregate/zipfile/ZipAggregationStrategyEmptyFileTest.java b/components/camel-zipfile/src/test/java/org/apache/camel/processor/aggregate/zipfile/ZipAggregationStrategyEmptyFileTest.java index b3c5c0e7212..74fb0fb6bf4 100644 --- a/components/camel-zipfile/src/test/java/org/apache/camel/processor/aggregate/zipfile/ZipAggregationStrategyEmptyFileTest.java +++ b/components/camel-zipfile/src/test/java/org/apache/camel/processor/aggregate/zipfile/ZipAggregationStrategyEmptyFileTest.java @@ -18,6 +18,7 @@ package org.apache.camel.processor.aggregate.zipfile; import java.io.File; import java.io.FileInputStream; +import java.io.IOException; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -35,19 +36,21 @@ import static org.junit.jupiter.api.Assertions.assertTrue; public class ZipAggregationStrategyEmptyFileTest extends CamelTestSupport { - private static final int EXPECTED_NO_FILES = 3; + private static final int EXPECTED_NO_EMPTY_FILES = 3; + private static final int EXPECTED_WITH_EMPTY_FILE = 4; private static final String TEST_DIR = "target/out_ZipAggregationStrategyEmptyFileTest"; @Override @BeforeEach public void setUp() throws Exception { deleteDirectory("target/foo"); + deleteDirectory("target/bar"); deleteDirectory(TEST_DIR); super.setUp(); } @Test - public void testEmptyFile() throws Exception { + public void testNoEmptyFile() throws Exception { MockEndpoint mock = getMockEndpoint("mock:aggregateToZipEntry"); mock.expectedMessageCount(1); @@ -57,6 +60,23 @@ public class ZipAggregationStrategyEmptyFileTest extends CamelTestSupport { template.sendBody("file:target/foo", "Bye"); template.sendBody("file:target/foo", "Howdy"); + checkResult(ZipAggregationStrategyEmptyFileTest.EXPECTED_NO_EMPTY_FILES); + } + + @Test + public void testAddEmptyFile() throws Exception { + MockEndpoint mock = getMockEndpoint("mock:aggregateToZipEntry"); + mock.expectedMessageCount(1); + + template.sendBody("file:target/bar", "Hello"); + template.sendBody("file:target/bar", ""); + template.sendBody("file:target/bar", "Bye"); + template.sendBody("file:target/bar", "Howdy"); + + checkResult(ZipAggregationStrategyEmptyFileTest.EXPECTED_WITH_EMPTY_FILE); + } + + private void checkResult(int expectedCount) throws InterruptedException, IOException { MockEndpoint.assertIsSatisfied(context); File[] files = new File(TEST_DIR).listFiles(); @@ -71,8 +91,8 @@ public class ZipAggregationStrategyEmptyFileTest extends CamelTestSupport { for (ZipEntry ze = zin.getNextEntry(); ze != null; ze = zin.getNextEntry()) { fileCount++; } - assertEquals(ZipAggregationStrategyEmptyFileTest.EXPECTED_NO_FILES, fileCount, - "Zip file should contains " + ZipAggregationStrategyEmptyFileTest.EXPECTED_NO_FILES + " files"); + assertEquals(expectedCount, fileCount, + "Zip file should contains " + expectedCount + " files"); } finally { IOHelper.close(zin); } @@ -91,6 +111,17 @@ public class ZipAggregationStrategyEmptyFileTest extends CamelTestSupport { .to("file:" + TEST_DIR) .to("mock:aggregateToZipEntry") .log("Done processing zip file: ${header.CamelFileName}"); + + ZipAggregationStrategy allowEmptyFilesZipAggregationStrategy = new ZipAggregationStrategy(); + allowEmptyFilesZipAggregationStrategy.setAllowEmptyFiles(true); + from("file:target/bar") + .aggregate(allowEmptyFilesZipAggregationStrategy) + .constant(true) + .completionSize(4) + .eagerCheckCompletion() + .to("file:" + TEST_DIR) + .to("mock:aggregateToZipEntry") + .log("Done processing zip file: ${header.CamelFileName}"); } };