This is an automated email from the ASF dual-hosted git repository.
apupier 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 7ecda889d52e CAMEL-25218: camel-jsonpath - read a remote file with a
charset instead of failing with ClassCastException
7ecda889d52e is described below
commit 7ecda889d52e3559961bf4ed342ce6d7627f3b4b
Author: smjain <[email protected]>
AuthorDate: Wed Sep 30 16:21:51 2026 +0530
CAMEL-25218: camel-jsonpath - read a remote file with a charset instead of
failing with ClassCastException
When the message body is a GenericFile with a charset, JsonPathEngine
opened it with new FileInputStream((File) genericFile.getFile()). The ftp
and ftps consumers set the endpoint charset on their RemoteFile, whose file
is an FTPFile, so every jsonpath expression on such a message failed with
a ClassCastException.
A java.io.File is still read directly; any other generic file is read
through the GenericFile type converter (the downloaded content), and both
are parsed in the file charset.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
.../org/apache/camel/jsonpath/JsonPathEngine.java | 12 ++-
.../JsonPathRemoteGenericFileCharsetTest.java | 91 ++++++++++++++++++++++
2 files changed, 100 insertions(+), 3 deletions(-)
diff --git
a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java
b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java
index 67cd783abe30..c21f096911a5 100644
---
a/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java
+++
b/components/camel-jsonpath/src/main/java/org/apache/camel/jsonpath/JsonPathEngine.java
@@ -176,9 +176,15 @@ public class JsonPathEngine {
LOG.trace("JSonPath: {} is read as generic file: {}", path, json);
GenericFile<?> genericFile = (GenericFile<?>) json;
if (genericFile.getCharset() != null) {
- // special treatment for generic file with charset
- InputStream inputStream = new FileInputStream((File)
genericFile.getFile());
- return JsonPath.using(configuration).parse(inputStream,
genericFile.getCharset()).read(path);
+ // special treatment for generic file with charset: a remote
file (such as from the ftp consumer) is
+ // not a java.io.File, and its content is the body of the
generic file
+ InputStream inputStream = genericFile.getFile() instanceof
File file
+ ? new FileInputStream(file)
+ :
exchange.getContext().getTypeConverter().tryConvertTo(InputStream.class,
exchange, genericFile);
+ if (inputStream != null) {
+ // json-path closes the stream
+ return JsonPath.using(configuration).parse(inputStream,
genericFile.getCharset()).read(path);
+ }
}
}
diff --git
a/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathRemoteGenericFileCharsetTest.java
b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathRemoteGenericFileCharsetTest.java
new file mode 100644
index 000000000000..2e4410f9ad90
--- /dev/null
+++
b/components/camel-jsonpath/src/test/java/org/apache/camel/jsonpath/JsonPathRemoteGenericFileCharsetTest.java
@@ -0,0 +1,91 @@
+/*
+ * 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.jsonpath;
+
+import java.nio.file.Files;
+import java.nio.file.Paths;
+
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.component.file.GenericFile;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.junit6.CamelTestSupport;
+import org.junit.jupiter.api.Test;
+
+/**
+ * A remote file (such as from the ftp consumer) is a {@link GenericFile}
whose file is not a {@link java.io.File}. When
+ * the consumer has a charset, the JSON must be read from the file body in
that charset.
+ */
+public class JsonPathRemoteGenericFileCharsetTest extends CamelTestSupport {
+
+ // stands in for org.apache.commons.net.ftp.FTPFile
+ private static final class RemoteEntry {
+ }
+
+ @Override
+ protected RouteBuilder createRouteBuilder() {
+ return new RouteBuilder() {
+ @Override
+ public void configure() {
+
from("direct:start").transform().jsonpath("$.store.book[0].title", String.class)
+ .to("mock:title");
+ }
+ };
+ }
+
+ @Test
+ public void testRemoteFileWithCharsetUtf8() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:title");
+ mock.expectedBodiesReceived("Joseph und seine Brüder");
+
+ template.sendBody("direct:start",
remoteFile("src/test/resources/germanbooks-utf8.json", "UTF-8"));
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Test
+ public void testRemoteFileWithCharsetIso88591() throws Exception {
+ MockEndpoint mock = getMockEndpoint("mock:title");
+ mock.expectedBodiesReceived("Joseph und seine Brüder");
+
+ template.sendBody("direct:start",
remoteFile("src/test/resources/germanbooks-iso-8859-1.json", "ISO-8859-1"));
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ @Test
+ public void testRemoteFileWithoutCharset() throws Exception {
+ // control: without a charset the body is read as a stream and the
encoding detected (UTF-8)
+ MockEndpoint mock = getMockEndpoint("mock:title");
+ mock.expectedBodiesReceived("Joseph und seine Brüder");
+
+ template.sendBody("direct:start",
remoteFile("src/test/resources/germanbooks-utf8.json", null));
+
+ MockEndpoint.assertIsSatisfied(context);
+ }
+
+ private static GenericFile<RemoteEntry> remoteFile(String path, String
charset) throws Exception {
+ GenericFile<RemoteEntry> file = new GenericFile<>();
+ file.setFile(new RemoteEntry());
+ file.setEndpointPath("inbox");
+ file.setFileName("books.json");
+ file.setFileNameOnly("books.json");
+ file.setCharset(charset);
+ // the remote consumer has downloaded the content into the body
+ file.setBody(Files.readAllBytes(Paths.get(path)));
+ return file;
+ }
+}