This is an automated email from the ASF dual-hosted git repository.

fmariani 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 66cf13f220b0 Consider WrappedFile.getFIleLength() in all components 
working with Files/Streams
66cf13f220b0 is described below

commit 66cf13f220b02acf98db2984c1175b43a2c4b3d2
Author: Croway <[email protected]>
AuthorDate: Thu Jan 29 11:36:23 2026 +0100

    Consider WrappedFile.getFIleLength() in all components working with 
Files/Streams
---
 .../camel/component/aws2/s3/AWS2S3Producer.java    |  4 ++
 .../azure/storage/blob/BlobStreamAndLength.java    |  9 ++--
 .../storage/datalake/FileStreamAndLength.java      | 11 +++--
 .../google/storage/GoogleCloudStorageProducer.java | 14 +++++-
 .../component/huaweicloud/obs/OBSProducer.java     |  6 +++
 .../src/main/docs/ibm-cos-component.adoc           | 54 ++++++++++++++++++++++
 .../camel/component/ibm/cos/IBMCOSProducer.java    | 11 +++++
 .../camel/component/minio/MinioProducer.java       | 19 ++++++--
 8 files changed, 116 insertions(+), 12 deletions(-)

diff --git 
a/components/camel-aws/camel-aws2-s3/src/main/java/org/apache/camel/component/aws2/s3/AWS2S3Producer.java
 
b/components/camel-aws/camel-aws2-s3/src/main/java/org/apache/camel/component/aws2/s3/AWS2S3Producer.java
index 2603723906de..b0e14787cbac 100644
--- 
a/components/camel-aws/camel-aws2-s3/src/main/java/org/apache/camel/component/aws2/s3/AWS2S3Producer.java
+++ 
b/components/camel-aws/camel-aws2-s3/src/main/java/org/apache/camel/component/aws2/s3/AWS2S3Producer.java
@@ -174,6 +174,10 @@ public class AWS2S3Producer extends DefaultProducer {
 
         // Need to check if the message body is WrappedFile
         if (obj instanceof WrappedFile<?> wf) {
+            // Get file length from WrappedFile before unwrapping (works for 
remote files like SFTP)
+            if (contentLength <= 0) {
+                contentLength = wf.getFileLength();
+            }
             obj = wf.getFile();
         }
         if (obj instanceof File f) {
diff --git 
a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobStreamAndLength.java
 
b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobStreamAndLength.java
index 34bd2e3d6885..d2908a453a04 100644
--- 
a/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobStreamAndLength.java
+++ 
b/components/camel-azure/camel-azure-storage-blob/src/main/java/org/apache/camel/component/azure/storage/blob/BlobStreamAndLength.java
@@ -43,9 +43,12 @@ public final class BlobStreamAndLength {
         Long blobSize = 
exchange.getIn().getHeader(BlobConstants.BLOB_UPLOAD_SIZE, () -> null, 
Long.class);
         exchange.getIn().removeHeader(BlobConstants.BLOB_UPLOAD_SIZE); // 
remove to avoid issues for further uploads
 
-        if (body instanceof WrappedFile) {
-            // unwrap file
-            body = ((WrappedFile) body).getFile();
+        if (body instanceof WrappedFile wf) {
+            // Get file length from WrappedFile before unwrapping (works for 
remote files like SFTP)
+            if (blobSize == null) {
+                blobSize = wf.getFileLength();
+            }
+            body = wf.getFile();
         }
 
         if (body instanceof InputStream) {
diff --git 
a/components/camel-azure/camel-azure-storage-datalake/src/main/java/org/apache/camel/component/azure/storage/datalake/FileStreamAndLength.java
 
b/components/camel-azure/camel-azure-storage-datalake/src/main/java/org/apache/camel/component/azure/storage/datalake/FileStreamAndLength.java
index 44abf44520ce..ce6c210db692 100644
--- 
a/components/camel-azure/camel-azure-storage-datalake/src/main/java/org/apache/camel/component/azure/storage/datalake/FileStreamAndLength.java
+++ 
b/components/camel-azure/camel-azure-storage-datalake/src/main/java/org/apache/camel/component/azure/storage/datalake/FileStreamAndLength.java
@@ -38,16 +38,21 @@ public final class FileStreamAndLength {
     @SuppressWarnings("rawtypes")
     public static FileStreamAndLength 
createFileStreamAndLengthFromExchangeBody(final Exchange exchange) throws 
IOException {
         Object body = exchange.getIn().getBody();
+        long fileLength = -1;
 
-        if (body instanceof WrappedFile) {
-            body = ((WrappedFile) body).getFile();
+        if (body instanceof WrappedFile wf) {
+            // Get file length from WrappedFile before unwrapping (works for 
remote files like SFTP)
+            fileLength = wf.getFileLength();
+            body = wf.getFile();
         }
 
         if (body instanceof InputStream) {
             if (!((InputStream) body).markSupported()) {
                 throw new IllegalArgumentException("Inputstream does not 
support mark rest operations");
             }
-            return new FileStreamAndLength((InputStream) body, 
DataLakeUtils.getInputStreamLength((InputStream) body));
+            // Use cached file length if available, otherwise calculate from 
stream
+            long length = fileLength > 0 ? fileLength : 
DataLakeUtils.getInputStreamLength((InputStream) body);
+            return new FileStreamAndLength((InputStream) body, length);
         }
 
         if (body instanceof File) {
diff --git 
a/components/camel-google/camel-google-storage/src/main/java/org/apache/camel/component/google/storage/GoogleCloudStorageProducer.java
 
b/components/camel-google/camel-google-storage/src/main/java/org/apache/camel/component/google/storage/GoogleCloudStorageProducer.java
index 83e98449baf4..723b87050a53 100644
--- 
a/components/camel-google/camel-google-storage/src/main/java/org/apache/camel/component/google/storage/GoogleCloudStorageProducer.java
+++ 
b/components/camel-google/camel-google-storage/src/main/java/org/apache/camel/component/google/storage/GoogleCloudStorageProducer.java
@@ -98,17 +98,27 @@ public class GoogleCloudStorageProducer extends 
DefaultProducer {
 
         InputStream is;
         Object obj = exchange.getIn().getMandatoryBody();
+        long fileLength = -1;
 
         // Need to check if the message body is WrappedFile
-        if (obj instanceof WrappedFile) {
-            obj = ((WrappedFile<?>) obj).getFile();
+        if (obj instanceof WrappedFile<?> wf) {
+            // Get file length from WrappedFile before unwrapping (works for 
remote files like SFTP)
+            fileLength = wf.getFileLength();
+            obj = wf.getFile();
         }
         if (obj instanceof File) {
             File filePayload = (File) obj;
             is = new FileInputStream(filePayload);
+            if (fileLength <= 0) {
+                fileLength = filePayload.length();
+            }
         } else {
             is = exchange.getIn().getMandatoryBody(InputStream.class);
         }
+        // Set content length from WrappedFile if available and not already set
+        if (fileLength > 0 && !objectMetadata.containsKey("Content-Length")) {
+            objectMetadata.put("Content-Length", String.valueOf(fileLength));
+        }
         // Handle Content-Length if not already set
         is = setContentLength(objectMetadata, is);
 
diff --git 
a/components/camel-huawei/camel-huaweicloud-obs/src/main/java/org/apache/camel/component/huaweicloud/obs/OBSProducer.java
 
b/components/camel-huawei/camel-huaweicloud-obs/src/main/java/org/apache/camel/component/huaweicloud/obs/OBSProducer.java
index 0843703231b6..c4e678da8618 100644
--- 
a/components/camel-huawei/camel-huaweicloud-obs/src/main/java/org/apache/camel/component/huaweicloud/obs/OBSProducer.java
+++ 
b/components/camel-huawei/camel-huaweicloud-obs/src/main/java/org/apache/camel/component/huaweicloud/obs/OBSProducer.java
@@ -40,6 +40,7 @@ import com.obs.services.model.ObsBucket;
 import com.obs.services.model.ObsObject;
 import com.obs.services.model.PutObjectResult;
 import org.apache.camel.Exchange;
+import org.apache.camel.WrappedFile;
 import org.apache.camel.component.huaweicloud.obs.constants.OBSConstants;
 import org.apache.camel.component.huaweicloud.obs.constants.OBSOperations;
 import org.apache.camel.component.huaweicloud.obs.constants.OBSProperties;
@@ -112,6 +113,11 @@ public class OBSProducer extends DefaultProducer {
 
         Object body = exchange.getMessage().getBody();
 
+        // Handle WrappedFile (e.g., from SFTP, FTP) by extracting the 
underlying file/stream
+        if (body instanceof WrappedFile<?> wf) {
+            body = wf.getFile();
+        }
+
         // if body doesn't contain File, then user must pass object name. 
Bucket name is mandatory in all case
         if ((ObjectHelper.isEmpty(clientConfigurations.getBucketName()) ||
                 ObjectHelper.isEmpty(clientConfigurations.getObjectName())) && 
!(body instanceof File)) {
diff --git 
a/components/camel-ibm/camel-ibm-cos/src/main/docs/ibm-cos-component.adoc 
b/components/camel-ibm/camel-ibm-cos/src/main/docs/ibm-cos-component.adoc
index c9c0e64f8640..b2f24b340019 100644
--- a/components/camel-ibm/camel-ibm-cos/src/main/docs/ibm-cos-component.adoc
+++ b/components/camel-ibm/camel-ibm-cos/src/main/docs/ibm-cos-component.adoc
@@ -373,6 +373,60 @@ 
from("ibm-cos://mycamelbucket?cosClient=#cosClient&prefix=inbox/&deleteAfterRead
 
 This route will only consume objects whose keys start with "inbox/".
 
+== Running Integration Tests
+
+Integration tests require valid IBM Cloud credentials. Follow these steps to 
set up and run the tests.
+
+=== Creating Service Credentials
+
+1. Log in to the https://cloud.ibm.com[IBM Cloud Console]
+2. Navigate to your Cloud Object Storage instance (or create one if you don't 
have one)
+3. Go to **Service credentials** in the left menu
+4. Click **New credential**
+5. Give it a name (e.g., `camel-cos-test`)
+6. **Important**: Set the role to **Manager** (required for bucket creation 
operations)
+7. Click **Add**
+8. Expand the newly created credential to view the JSON
+
+=== Mapping Credentials to Test Properties
+
+From the service credential JSON, extract the following values:
+
+[cols="1,2,3"]
+|===
+|System Property |JSON Field |Example
+
+|`camel.ibm.cos.apiKey`
+|`apikey`
+|`Hh1u4wjecZ_jUhJScOt0sN...`
+
+|`camel.ibm.cos.serviceInstanceId`
+|`resource_instance_id`
+|`crn:v1:bluemix:public:cloud-object-storage:global:a/...`
+
+|`camel.ibm.cos.endpointUrl`
+|Not in credentials - choose based on region
+|`https://s3.us-south.cloud-object-storage.appdomain.cloud`
+|===
+
+NOTE: The `endpoints` field in the credentials JSON is a control API URL, not 
the actual COS endpoint. You must choose a regional endpoint from the 
https://cloud.ibm.com/docs/cloud-object-storage?topic=cloud-object-storage-endpoints[IBM
 COS Endpoints documentation].
+
+=== Running the Tests
+
+[source,bash]
+----
+mvn verify -pl components/camel-ibm/camel-ibm-cos \
+  -Dcamel.ibm.cos.apiKey=YOUR_API_KEY \
+  -Dcamel.ibm.cos.serviceInstanceId='YOUR_SERVICE_INSTANCE_ID' \
+  
-Dcamel.ibm.cos.endpointUrl=https://s3.us-south.cloud-object-storage.appdomain.cloud
+----
+
+TIP: Use single quotes around the `serviceInstanceId` value to prevent shell 
interpretation of special characters in the CRN.
+
+=== Troubleshooting
+
+* **403 Forbidden**: Ensure your service credential has the **Manager** role. 
Writer role is not sufficient for bucket creation.
+
 == Dependencies
 
 Maven users will need to add the following dependency to their `pom.xml`.
diff --git 
a/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSProducer.java
 
b/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSProducer.java
index 57d8e2460fdb..e8bed18528fa 100644
--- 
a/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSProducer.java
+++ 
b/components/camel-ibm/camel-ibm-cos/src/main/java/org/apache/camel/component/ibm/cos/IBMCOSProducer.java
@@ -35,6 +35,7 @@ import 
com.ibm.cloud.objectstorage.services.s3.model.PutObjectResult;
 import com.ibm.cloud.objectstorage.services.s3.model.S3Object;
 import org.apache.camel.Exchange;
 import org.apache.camel.Message;
+import org.apache.camel.WrappedFile;
 import org.apache.camel.support.DefaultProducer;
 import org.apache.camel.util.ObjectHelper;
 import org.slf4j.Logger;
@@ -122,12 +123,22 @@ public class IBMCOSProducer extends DefaultProducer {
             metadata.setContentType(contentType);
         }
 
+        // Check for WrappedFile to get file length (works for remote files 
like SFTP)
+        Object body = exchange.getIn().getMandatoryBody();
+        long wrappedFileLength = -1;
+        if (body instanceof WrappedFile<?> wf) {
+            wrappedFileLength = wf.getFileLength();
+        }
+
         InputStream inputStream = 
exchange.getIn().getMandatoryBody(InputStream.class);
 
         // Calculate content length if not provided to avoid SDK warnings
         Long contentLength = 
exchange.getIn().getHeader(IBMCOSConstants.CONTENT_LENGTH, Long.class);
         if (contentLength != null) {
             metadata.setContentLength(contentLength);
+        } else if (wrappedFileLength > 0) {
+            // Use file length from WrappedFile (avoids reading stream into 
memory)
+            metadata.setContentLength(wrappedFileLength);
         } else if (inputStream.markSupported()) {
             // For ByteArrayInputStream and similar streams that support 
mark/reset
             inputStream.mark(Integer.MAX_VALUE);
diff --git 
a/components/camel-minio/src/main/java/org/apache/camel/component/minio/MinioProducer.java
 
b/components/camel-minio/src/main/java/org/apache/camel/component/minio/MinioProducer.java
index a77928f9dab6..f5cfba2c68ba 100644
--- 
a/components/camel-minio/src/main/java/org/apache/camel/component/minio/MinioProducer.java
+++ 
b/components/camel-minio/src/main/java/org/apache/camel/component/minio/MinioProducer.java
@@ -142,18 +142,29 @@ public class MinioProducer extends DefaultProducer {
             // the content-length may already be known
             long contentLength = 
Long.parseLong(objectMetadata.getOrDefault(Exchange.CONTENT_LENGTH, "-1"));
 
-            Object object = exchange.getIn().getMandatoryBody();
+            // Use getBody() first to check for WrappedFile before any type 
conversion
+            Object object = exchange.getIn().getBody();
             InputStream inputStream = null;
             File filePayload = null;
             try {
                 // Need to check if the message body is WrappedFile
-                if (object instanceof WrappedFile) {
-                    object = ((WrappedFile<?>) object).getFile();
+                if (object instanceof WrappedFile<?> wf) {
+                    // Get file length from WrappedFile before unwrapping 
(works for remote files like SFTP)
+                    contentLength = wf.getFileLength();
+                    object = wf.getFile();
+                }
+                if (object == null) {
+                    throw new IllegalArgumentException("Message body is null");
                 }
                 if (object instanceof File) {
                     filePayload = (File) object;
                     inputStream = new FileInputStream(filePayload);
-                    contentLength = filePayload.length();
+                    if (contentLength <= 0) {
+                        contentLength = filePayload.length();
+                    }
+                } else if (object instanceof InputStream) {
+                    // Use the InputStream directly (e.g., from 
WrappedFile.getFile())
+                    inputStream = (InputStream) object;
                 } else {
                     inputStream = 
exchange.getMessage().getMandatoryBody(InputStream.class);
                     if (contentLength <= 0) {

Reply via email to