This is an automated email from the ASF dual-hosted git repository.
Croway pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-spring-boot.git
The following commit(s) were added to refs/heads/main by this push:
new 451e9d3b5c4 CAMEL-24504: camel-spring-boot - extend the String
conversion guard beyond InputStream (#1912)
451e9d3b5c4 is described below
commit 451e9d3b5c4cc051d4af94e91d11c22bd0a348a3
Author: Andrea Cosentino <[email protected]>
AuthorDate: Fri Aug 28 13:55:23 2026 +0200
CAMEL-24504: camel-spring-boot - extend the String conversion guard beyond
InputStream (#1912)
* CAMEL-24504: camel-spring-boot - extend the String conversion guard
beyond InputStream
CAMEL-23378 stopped SpringTypeConverter from converting a String into an
InputStream, because Spring's ObjectToObjectConverter finds the
FileInputStream(String) constructor and opens the value as a file path
rather
than treating it as data content.
The same reasoning applies to any target whose single-String constructor
takes a
path. FileReader and ZipFile throw a ConversionFailedException on a String
body,
so Camel's own converters never get a chance, and FileWriter goes further:
the
conversion succeeds and creates the named file on disk.
Reader, Writer and ZipFile are added to the guard. java.io.File is
deliberately
left out, since String to File is a documented Spring conversion where the
String
really is a path.
Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Signed-off-by: Andrea Cosentino <[email protected]>
* CAMEL-24504: fix import order in SpringTypeConverterTest
Co-Authored-By: Claude Sonnet 5 <[email protected]>
* CAMEL-24504: preserve StringReader conversion
---------
Signed-off-by: Andrea Cosentino <[email protected]>
Co-authored-by: Claude Opus 5 (1M context) <[email protected]>
Co-authored-by: Claus Ibsen <[email protected]>
Co-authored-by: Croway <[email protected]>
---
.../camel/spring/boot/SpringTypeConverter.java | 21 +++++++++---
.../camel/spring/boot/SpringTypeConverterTest.java | 39 ++++++++++++++++++++++
2 files changed, 56 insertions(+), 4 deletions(-)
diff --git
a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringTypeConverter.java
b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringTypeConverter.java
index 7578cf2db61..fef6ff7186a 100644
---
a/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringTypeConverter.java
+++
b/core/camel-spring-boot/src/main/java/org/apache/camel/spring/boot/SpringTypeConverter.java
@@ -16,11 +16,14 @@
*/
package org.apache.camel.spring.boot;
+import java.io.FileReader;
import java.io.InputStream;
+import java.io.Writer;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
+import java.util.zip.ZipFile;
import org.apache.camel.Exchange;
import org.apache.camel.TypeConversionException;
import org.apache.camel.support.TypeConverterSupport;
@@ -53,10 +56,13 @@ public class SpringTypeConverter extends
TypeConverterSupport {
return null;
}
- // do not attempt to convert String -> InputStream (or subclasses like
FileInputStream).
- // Spring's ObjectToObjectConverter finds FileInputStream(String)
constructor and treats
- // the String value as a file path instead of data content.
- if (value instanceof String &&
InputStream.class.isAssignableFrom(type)) {
+ // do not attempt to convert a String into a type whose single-String
constructor interprets it as a
+ // file path rather than as data content - Spring's
ObjectToObjectConverter would find
+ // FileInputStream(String), FileReader(String), FileWriter(String) or
ZipFile(String) and open, or in
+ // the Writer case create, the named file. Camel's own converters
handle these from a String body.
+ // java.io.File is deliberately not listed: String -> File is a
documented Spring conversion where the
+ // String genuinely is a path (CAMEL-23378).
+ if (value instanceof String && isFileBackedTarget(type)) {
return null;
}
@@ -86,6 +92,13 @@ public class SpringTypeConverter extends
TypeConverterSupport {
return null;
}
+ private boolean isFileBackedTarget(Class<?> type) {
+ return InputStream.class.isAssignableFrom(type)
+ || FileReader.class.isAssignableFrom(type)
+ || Writer.class.isAssignableFrom(type)
+ || ZipFile.class.isAssignableFrom(type);
+ }
+
private boolean isArrayOrCollection(Object value) {
return value instanceof Collection || value.getClass().isArray();
}
diff --git
a/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/SpringTypeConverterTest.java
b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/SpringTypeConverterTest.java
index 5fd9e3d70f7..27c842656d9 100644
---
a/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/SpringTypeConverterTest.java
+++
b/core/camel-spring-boot/src/test/java/org/apache/camel/spring/boot/SpringTypeConverterTest.java
@@ -16,11 +16,18 @@
*/
package org.apache.camel.spring.boot;
+import java.io.File;
import java.io.FileInputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
import java.io.InputStream;
+import java.io.StringReader;
+import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import java.util.zip.ZipFile;
import org.apache.camel.test.spring.junit6.CamelSpringBootTest;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@@ -85,6 +92,38 @@ public class SpringTypeConverterTest {
Assertions.assertNull(converter.convertTo(InputStream.class, null,
"some file content"));
}
+ @Test
+ public void testStringToFileReaderConversionIsBlocked() {
+ // FileReader(String) would open the content as a path, exactly as
FileInputStream(String) did
+ Assertions.assertNull(converter.convertTo(FileReader.class, null,
"some file content"));
+ }
+
+ @Test
+ public void testStringToStringReaderConversionIsStillAllowed() {
+ Assertions.assertNotNull(converter.convertTo(StringReader.class, null,
"some file content"));
+ }
+
+ @Test
+ public void testStringToFileWriterConversionIsBlocked() throws Exception {
+ // FileWriter(String) would go further and create the named file
+ Path target =
Files.createTempDirectory("spring-type-converter").resolve("must-not-be-created.txt");
+ Assertions.assertNull(converter.convertTo(FileWriter.class, null,
target.toString()));
+ Assertions.assertFalse(Files.exists(target), "converting a String must
not create a file on disk");
+ }
+
+ @Test
+ public void testStringToZipFileConversionIsBlocked() {
+ Assertions.assertNull(converter.convertTo(ZipFile.class, null, "some
file content"));
+ }
+
+ @Test
+ public void testStringToFileConversionIsStillAllowed() {
+ // String -> File is a documented Spring conversion where the String
really is a path, so the guard
+ // must not swallow it
+ Assertions.assertEquals(new File("/tmp/example.txt"),
+ converter.convertTo(File.class, null, "/tmp/example.txt"));
+ }
+
public static class Person {
private String name;
private int age;