You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2023/12/01 11:29:32 UTC

(camel) branch main updated: Add checksum feature to camel-file/ftp (#12280)

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 ee5a75e4012 Add checksum feature to camel-file/ftp (#12280)
ee5a75e4012 is described below

commit ee5a75e40124a6ec0802624776bfddd018ddeb03
Author: Benjamin Graf <gr...@users.noreply.github.com>
AuthorDate: Fri Dec 1 12:29:26 2023 +0100

    Add checksum feature to camel-file/ftp (#12280)
---
 components/camel-file/pom.xml                      |  4 ++
 .../camel/component/file/GenericFileEndpoint.java  | 18 ++++++++
 .../camel/component/file/GenericFileProducer.java  | 29 ++++++++++++
 .../FileProducerChecksumFileAlgorithmTest.java     | 52 ++++++++++++++++++++++
 4 files changed, 103 insertions(+)

diff --git a/components/camel-file/pom.xml b/components/camel-file/pom.xml
index 0aa95240204..5f637d91669 100644
--- a/components/camel-file/pom.xml
+++ b/components/camel-file/pom.xml
@@ -43,6 +43,10 @@
             <groupId>org.apache.camel</groupId>
             <artifactId>camel-cluster</artifactId>
         </dependency>
+        <dependency>
+            <groupId>commons-codec</groupId>
+            <artifactId>commons-codec</artifactId>
+        </dependency>
 
     </dependencies>
 </project>
diff --git a/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java b/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java
index 668dddecb94..9b7d47f25fd 100644
--- a/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java
+++ b/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileEndpoint.java
@@ -162,6 +162,11 @@ public abstract class GenericFileEndpoint<T> extends ScheduledPollEndpoint imple
                                                 + "To specify new-line (slash-n or slash-r) or tab (slash-t) characters then escape with an extra slash, "
                                                 + "eg slash-slash-n.")
     protected String appendChars;
+    @UriParam(label = "producer",
+              description = "If provided, then Camel will write a checksum file when the original file has been written. The checksum file "
+                            + "will contain the checksum created with the provided algorithm for the original file. The checksum file will "
+                            + "always be written in the same folder as the original file.")
+    protected String checksumFileAlgorithm;
 
     // consumer options
 
@@ -1518,6 +1523,19 @@ public abstract class GenericFileEndpoint<T> extends ScheduledPollEndpoint imple
         this.synchronous = synchronous;
     }
 
+    public String getChecksumFileAlgorithm() {
+        return checksumFileAlgorithm;
+    }
+
+    /**
+     * If provided, then Camel will write a checksum file when the original file has been written. The checksum file
+     * will contain the checksum created with the provided algorithm for the original file. The checksum file will
+     * always be written in the same folder as the original file.
+     */
+    public void setChecksumFileAlgorithm(String checksumFileAlgorithm) {
+        this.checksumFileAlgorithm = checksumFileAlgorithm;
+    }
+
     /**
      * Configures the given message with the file which sets the body to the file object.
      */
diff --git a/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileProducer.java b/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileProducer.java
index ac1f8435b63..417f083b233 100644
--- a/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileProducer.java
+++ b/components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileProducer.java
@@ -17,6 +17,7 @@
 package org.apache.camel.component.file;
 
 import java.io.File;
+import java.io.InputStream;
 import java.util.Collections;
 import java.util.Map;
 import java.util.concurrent.locks.Lock;
@@ -27,10 +28,12 @@ import org.apache.camel.Expression;
 import org.apache.camel.support.DefaultExchange;
 import org.apache.camel.support.DefaultProducer;
 import org.apache.camel.support.LRUCacheFactory;
+import org.apache.camel.support.MessageHelper;
 import org.apache.camel.support.service.ServiceHelper;
 import org.apache.camel.util.FileUtil;
 import org.apache.camel.util.ObjectHelper;
 import org.apache.camel.util.StringHelper;
+import org.apache.commons.codec.digest.DigestUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -212,6 +215,11 @@ public class GenericFileProducer<T> extends DefaultProducer {
                 }
             }
 
+            // any checksum file to write?
+            if (endpoint.getChecksumFileAlgorithm() != null) {
+                writeChecksumFile(exchange, target);
+            }
+
             // any done file to write?
             if (endpoint.getDoneFileName() != null) {
                 String doneFileName = endpoint.createDoneFileName(target);
@@ -242,6 +250,27 @@ public class GenericFileProducer<T> extends DefaultProducer {
         postWriteCheck(exchange);
     }
 
+    public void writeChecksumFile(Exchange exchange, String target) throws Exception {
+        String algorithm = endpoint.getChecksumFileAlgorithm();
+        String checksumFileName = target + "." + algorithm;
+
+        // create exchange with checksum as body to write as the checksum file
+        MessageHelper.resetStreamCache(exchange.getIn());
+        InputStream is = exchange.getIn().getMandatoryBody(InputStream.class);
+        Exchange checksumExchange = new DefaultExchange(exchange);
+        checksumExchange.getIn().setBody(new DigestUtils(algorithm).digestAsHex(is));
+
+        LOG.trace("Writing checksum file: [{}]", checksumFileName);
+        // delete any existing done file
+        if (operations.existsFile(checksumFileName)) {
+            if (!operations.deleteFile(checksumFileName)) {
+                throw new GenericFileOperationFailedException(
+                        "Cannot delete existing checksum file: " + checksumFileName);
+            }
+        }
+        writeFile(checksumExchange, checksumFileName);
+    }
+
     /**
      * If we fail writing out a file, we will call this method. This hook is provided to disconnect from servers or
      * clean up files we created (if needed).
diff --git a/core/camel-core/src/test/java/org/apache/camel/component/file/FileProducerChecksumFileAlgorithmTest.java b/core/camel-core/src/test/java/org/apache/camel/component/file/FileProducerChecksumFileAlgorithmTest.java
new file mode 100644
index 00000000000..59772d3a1e5
--- /dev/null
+++ b/core/camel-core/src/test/java/org/apache/camel/component/file/FileProducerChecksumFileAlgorithmTest.java
@@ -0,0 +1,52 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.file;
+
+import org.apache.camel.ContextTestSupport;
+import org.apache.camel.Exchange;
+import org.apache.camel.converter.stream.InputStreamCache;
+import org.junit.jupiter.api.Test;
+
+import static org.apache.camel.TestSupport.assertFileExists;
+
+public class FileProducerChecksumFileAlgorithmTest extends ContextTestSupport {
+
+    @Test
+    public void testProducerChecksumFileMd5() throws Exception {
+        template.sendBodyAndHeader(fileUri("?checksumFileAlgorithm=md5"), "Hello World", Exchange.FILE_NAME, "hello.txt");
+
+        assertFileExists(testFile("hello.txt"));
+        assertFileExists(testFile("hello.txt.md5"), "b10a8db164e0754105b7a99be72e3fe5");
+    }
+
+    @Test
+    public void testProducerChecksumFileSha256() throws Exception {
+        template.sendBodyAndHeader(fileUri("?checksumFileAlgorithm=sha256"), "Hello World", Exchange.FILE_NAME, "hello.txt");
+
+        assertFileExists(testFile("hello.txt"));
+        assertFileExists(testFile("hello.txt.sha256"), "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e");
+    }
+
+    @Test
+    public void testProducerChecksumFileSha256WithStreamCaching() throws Exception {
+        InputStreamCache cache = new InputStreamCache("Hello World".getBytes());
+        template.sendBodyAndHeader(fileUri("?checksumFileAlgorithm=sha256"), cache, Exchange.FILE_NAME, "hello.txt");
+
+        assertFileExists(testFile("hello.txt"));
+        assertFileExists(testFile("hello.txt.sha256"), "a591a6d40bf420404a011733cfb7b190d62c65bf0bcda32b57b277d9ad9f146e");
+    }
+}