Federico Mariani created CAMEL-24106:
----------------------------------------
Summary: camel-xslt: 'source' option silently ignored when the
message body is an InputStream - transforms the wrong document
Key: CAMEL-24106
URL: https://issues.apache.org/jira/browse/CAMEL-24106
Project: Camel
Issue Type: Bug
Components: camel-xslt
Affects Versions: 4.21.0
Reporter: Federico Mariani
Attachments: XsltSourceOptionInputStreamBodyTest.java
h3. Problem
{{XmlSourceHandlerFactoryImpl.getSource(Exchange, Expression)}} checks
{{isInputStreamNeeded(exchange)}} against the *message body* first, and when it
returns true it reads the body directly and never evaluates the configured
{{source}} expression:
{code:java}
public Source getSource(Exchange exchange, Expression source) throws Exception {
if (isInputStreamNeeded(exchange)) {
InputStream is = exchange.getIn().getBody(InputStream.class); // <--
'source' ignored
return getSource(exchange, is);
} else {
Object body = source != null ? source.evaluate(exchange, Object.class)
: exchange.getMessage().getBody();
...
{code}
{{isInputStreamNeeded()}} returns true when the body is an {{InputStream}}, a
{{StreamCache}}, or any type without a direct {{Source}} converter - which is
exactly the common case with {{file}}, {{http}}, {{ftp}}, {{netty}} consumers
or stream caching. In all those setups {{xslt:...?source=header:x}} /
{{source=variable:x}} / {{source=property:x}} silently transforms the *body*
instead of the configured source. No error, wrong output.
h3. Failure scenario
{code:java}
from("direct:start")
.to("xslt:xslt/transform.xsl?source=header:xmlSource")
.to("mock:result");
template.send("direct:start", e -> {
e.getIn().setHeader("xmlSource",
"<mail><subject>FromHeader</subject>...</mail>");
e.getIn().setBody(new
ByteArrayInputStream("<mail><subject>FromBody</subject>...</mail>".getBytes()));
});
// output contains <subject>FromBody</subject> - the header source was never
looked at
{code}
h3. History
Introduced together with the option itself in CAMEL-21859 (4.12.0). The tests
added there only exercise header/variable/property sources with a *null*
message body, which takes the {{else}} branch - hence unnoticed. Affects
{{xslt}}, {{xslt-saxon}} (handler is inherited by
{{SaxonXmlSourceHandlerFactoryImpl}}), and {{camel-xj}} in the XML->JSON
direction (its JSON-input handler evaluates the expression correctly and is
fine).
h3. Fix direction
Evaluate the {{source}} expression first and only fall back to the
InputStream-conversion shortcut when no expression is configured (or base
{{isInputStreamNeeded}} on the evaluated source value instead of the body).
h3. Reproducer
Attached {{XsltSourceOptionInputStreamBodyTest.java}} - two tests, one against
{{xslt:}} and one against {{xslt-saxon:}}; both fail with output {{FromBody}}
instead of {{FromHeader}}.
----
_This issue was researched and filed by Claude Code on behalf of [~fmariani]
(GitHub: Croway), as part of a code review of camel-xslt and camel-xslt-saxon.
The attached JUnit reproducer fails deterministically on current main
(4.22.0-SNAPSHOT); place it in
{{components/camel-xslt-saxon/src/test/java/org/apache/camel/component/xslt/saxon/}}._
--
This message was sent by Atlassian Jira
(v8.20.10#820010)