Skip to content

camel-file: do not assume skip() advanced the whole offset - #29702

Open
Dhairya-007 wants to merge 2 commits into
apache:mainfrom
Dhairya-007:fix/file-resume-partial-skip
Open

Dhairya-007 wants to merge 2 commits into
apache:mainfrom
Dhairya-007:fix/file-resume-partial-skip

Conversation

@Dhairya-007

Copy link
Copy Markdown
Contributor

Problem

The file resume support positions the body at a recorded offset with a single unchecked call, in three places:

// GenericFileConverter.genericFileToInputStream
InputStream inputStream = IOHelper.toInputStream(f, charset);
inputStream.skip(file.getLastOffsetValue());

// GenericFileConverter.genericFileToReader
reader.skip(file.getLastOffsetValue());

// IOHelper.toString(BufferedReader, long offset)
reader.skip(offset);

InputStream.skip(long) and Reader.skip(long) are both specified to skip up to the requested amount and to return how far they actually got — the javadoc of the former says it "may, for a variety of reasons, end up skipping over some smaller number of bytes, possibly 0". The returned count is the only thing that says where the stream now is, and all three calls discard it, so the body can silently start somewhere other than the offset that was asked for.

How reachable is it?

Honestly: for a fresh local file the skip normally completes, because BufferedInputStream.skip delegates to the position-based skip of the channel stream, and Reader.skip loops internally. I could not make a plain local file skip short mid-stream.

The case that is reachable is an offset past the end of the file, which is exactly what a stale recorded offset looks like after the file was truncated or replaced. Today the stream runs to EOF and the exchange carries an empty or short body as if that were the file's content; nothing says the offset could not be honoured. For a resume feature, silently delivering the wrong bytes is worse than failing.

Beyond that, the code is relying on an implementation detail of the stream it happens to get. IOHelper.toInputStream returns a BufferedInputStream for the no-charset path and a ReaderInputStream for the charset path, and GenericFileConverter does not control which stream a caller ends up with.

Fix

  • GenericFileConverter.genericFileToInputStream uses InputStream.skipNBytes(long) (JDK 12+), which loops and throws EOFException if the stream ends first.
  • IOHelper gains skipFully(Reader, long), the same loop for readers, since Reader has no skipNBytes. It is used by GenericFileConverter.genericFileToReader and by IOHelper.toString(BufferedReader, long).

Behaviour change

An offset past the end of the file now fails with EOFException instead of yielding an empty body. That is the point of the change, but it is a visible difference for anyone whose resume offsets can go stale. If you would rather have an upgrade-guide entry for it, say so and I will add one.

Tests

IOHelperTest gets two cases driving a FilterReader that skips one character per call — which Reader.skip is free to do, and which a single unchecked call has to cope with:

  • testSkipFullyWithAReaderThatSkipsInSmallSteps — four one-character skips add up to the requested four, and the rest of the content is intact. A bare reader.skip(4) on that reader advances one character, so the old code would return 123456789.
  • testSkipFullyPastTheEnd — EOFException rather than a silent short read.

@github-actions

Copy link
Copy Markdown
Contributor

🌟 Thank you for your contribution to the Apache Camel project! 🌟
🤖 CI automation will test this PR automatically.

🐫 Apache Camel Committers, please review the following items:

  • First-time contributors require MANUAL approval for the GitHub Actions to run
  • You can use the command /component-test (camel-)component-name1 (camel-)component-name2.. to request a test from the test bot although they are normally detected and executed by CI.
  • You can label PRs using skip-tests and test-dependents to fine-tune the checks executed by this PR.
  • Build and test logs are available in the summary page. Only Apache Camel committers have access to the summary.

⚠️ Be careful when sharing logs. Review their contents before sharing them publicly.

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TL;DR: the skip loop is correct and cannot spin, but the new EOF path leaks the opened file, and the behaviour change needs an upgrade-guide entry.

The skipFully loop treats a 0 return as EOF, which matches the Reader.skip contract (it blocks until characters are available or EOF). skipNBytes probes with read(), and on the no-charset path Files.newInputStream clamps skip at the file size, so the EOF case really is detected now. The FilterReader-based tests show the short-skip case nicely.

  1. Close on failure. In GenericFileConverter.genericFileToInputStream (lines 126-129) the stream is opened and then skipNBytes can throw EOFException; the stream is never returned and never closed. The same goes for the reader in genericFileToReader (lines 201-207). In IOHelper.toString(BufferedReader, long), skipFully runs before the try whose finally closes the reader. Before this change these paths practically never threw; with a stale offset they now do on every attempt, leaking a file handle each time (and on Windows blocking the move or delete). Something like:

    InputStream inputStream = IOHelper.toInputStream(f, charset);
    try {
        inputStream.skipNBytes(file.getLastOffsetValue());
    } catch (IOException e) {
        IOHelper.close(inputStream);
        throw e;
    }
    return inputStream;

    plus the same for the reader, and moving skipFully(reader, offset) inside the existing try in IOHelper.toString.

  2. Upgrade guide: yes, please add the entry you offered in camel-4x-upgrade-guide-4_24.adoc: a stale offset now fails the exchange instead of giving an empty body. As far as I can tell, a failed exchange leaves the file in place and the next poll reloads the same stale offset from the resume cache, so the failure repeats on every poll; users with truncated or rotated files will want to know that, and how to reset the offset.

  3. Optional: a camel-file resume test with an offset larger than the file would pin the converter behaviour, and that the file is released afterwards.

Claude Code on behalf of davsclaus. This review was generated by an AI agent and may contain inaccuracies; please verify all suggestions before applying.

@github-actions

Copy link
Copy Markdown
Contributor

🧪 CI tested the following changed modules:

  • components/camel-file
  • core/camel-util

ℹ️ Dependent modules were not tested because the total number of affected modules exceeded the threshold (50). Use the test-dependents label to force testing all dependents.


🔬 Scalpel shadow comparison — Scalpel: 593 of 723 tested, 27 compile-only — current: 593 all tested

Maveniverse Scalpel detected 593 affected modules (current approach: 593).

Skip-tests mode would test 593 modules (2 direct + 591 downstream), skip tests for 27 (generated code, meta-modules)

Modules Scalpel would test (593)
  • archetypes ← downstream of org.apache.camel:camel-test-junit6
  • camel-a2a ← downstream of org.apache.camel:camel-test-junit6
  • camel-activemq ← downstream of org.apache.camel:camel-core-model
  • camel-activemq6 ← downstream of org.apache.camel:camel-core-model
  • camel-ai-observability ← downstream of org.apache.camel:camel-test-junit6
  • camel-ai-observability-api ← downstream of org.apache.camel:camel-test-junit6
  • camel-ai-parent ← downstream of org.apache.camel:camel-core-model
  • camel-ai-prompt ← downstream of org.apache.camel:camel-test-junit6
  • camel-ai-resource ← downstream of org.apache.camel:camel-test-junit6
  • camel-ai-tool ← downstream of org.apache.camel:camel-test-junit6
  • camel-alibaba-common ← downstream of org.apache.camel:camel-support
  • camel-alibaba-eventbridge ← downstream of org.apache.camel:camel-test-junit6
  • camel-alibaba-fc ← downstream of org.apache.camel:camel-test-junit6
  • camel-alibaba-kms ← downstream of org.apache.camel:camel-test-junit6
  • camel-alibaba-mns ← downstream of org.apache.camel:camel-test-junit6
  • camel-alibaba-oss ← downstream of org.apache.camel:camel-test-junit6
  • camel-alibaba-ots ← downstream of org.apache.camel:camel-test-junit6
  • camel-alibaba-parent ← downstream of org.apache.camel:camel-core-model
  • camel-alibaba-sls ← downstream of org.apache.camel:camel-test-junit6
  • camel-alibaba-sms ← downstream of org.apache.camel:camel-test-junit6
  • camel-amqp ← downstream of org.apache.camel:camel-test-junit6
  • camel-api ← downstream of org.apache.camel:camel-util
  • camel-api-component-maven-plugin ← downstream of org.apache.camel:camel-core
  • camel-apicurio-registry ← downstream of org.apache.camel:camel-test-junit6
  • camel-arangodb ← downstream of org.apache.camel:camel-test-junit6
  • camel-archetype-api-component ← downstream of org.apache.camel:camel-test-junit6
  • camel-archetype-component ← downstream of org.apache.camel:camel-test-junit6
  • camel-archetype-dataformat ← downstream of org.apache.camel:camel-test-junit6
  • camel-archetype-java ← downstream of org.apache.camel:camel-test-junit6
  • camel-archetype-main ← downstream of org.apache.camel:camel-test-junit6
  • camel-as2 ← downstream of org.apache.camel:camel-test-junit6
  • camel-as2-api ← downstream of org.apache.camel:camel-util
  • camel-as2-parent ← downstream of org.apache.camel:camel-core-model
  • camel-asn1 ← downstream of org.apache.camel:camel-test-junit6
  • camel-asterisk ← downstream of org.apache.camel:camel-test-junit6
  • camel-atmosphere-websocket ← downstream of org.apache.camel:camel-test-junit6
  • camel-atom ← downstream of org.apache.camel:camel-test-junit6
  • camel-attachments ← downstream of org.apache.camel:camel-test-junit6
  • camel-avro ← downstream of org.apache.camel:camel-test-junit6
  • camel-avro-rpc ← downstream of org.apache.camel:camel-test-junit6
  • camel-avro-rpc-jetty ← downstream of org.apache.camel:camel-api
  • camel-avro-rpc-parent ← downstream of org.apache.camel:camel-core-model
  • camel-avro-rpc-spi ← downstream of org.apache.camel:camel-core-model
  • camel-aws-bedrock ← downstream of org.apache.camel:camel-support
  • camel-aws-cloudtrail ← downstream of org.apache.camel:camel-support
  • camel-aws-common ← downstream of org.apache.camel:camel-support
  • camel-aws-config ← downstream of org.apache.camel:camel-test-junit6
  • camel-aws-parameter-store ← downstream of org.apache.camel:camel-support
  • camel-aws-parent ← downstream of org.apache.camel:camel-core-model
  • camel-aws-secrets-manager ← downstream of org.apache.camel:camel-support
  • camel-aws-security-hub ← downstream of org.apache.camel:camel-support
  • camel-aws2-athena ← downstream of org.apache.camel:camel-support
  • camel-aws2-comprehend ← downstream of org.apache.camel:camel-support
  • camel-aws2-cw ← downstream of org.apache.camel:camel-support
  • camel-aws2-ddb ← downstream of org.apache.camel:camel-support
  • camel-aws2-ec2 ← downstream of org.apache.camel:camel-support
  • camel-aws2-ecs ← downstream of org.apache.camel:camel-support
  • camel-aws2-eks ← downstream of org.apache.camel:camel-support
  • camel-aws2-eventbridge ← downstream of org.apache.camel:camel-support
  • camel-aws2-iam ← downstream of org.apache.camel:camel-support
  • camel-aws2-kinesis ← downstream of org.apache.camel:camel-support
  • camel-aws2-kms ← downstream of org.apache.camel:camel-support
  • camel-aws2-lambda ← downstream of org.apache.camel:camel-support
  • camel-aws2-mq ← downstream of org.apache.camel:camel-support
  • camel-aws2-msk ← downstream of org.apache.camel:camel-support
  • camel-aws2-polly ← downstream of org.apache.camel:camel-support
  • camel-aws2-redshift ← downstream of org.apache.camel:camel-support
  • camel-aws2-rekognition ← downstream of org.apache.camel:camel-support
  • camel-aws2-s3 ← downstream of org.apache.camel:camel-support
  • camel-aws2-s3-vectors ← downstream of org.apache.camel:camel-support
  • camel-aws2-ses ← downstream of org.apache.camel:camel-support
  • camel-aws2-sns ← downstream of org.apache.camel:camel-support
  • camel-aws2-sqs ← downstream of org.apache.camel:camel-support
  • camel-aws2-step-functions ← downstream of org.apache.camel:camel-support
  • camel-aws2-sts ← downstream of org.apache.camel:camel-support
  • camel-aws2-textract ← downstream of org.apache.camel:camel-support
  • camel-aws2-timestream ← downstream of org.apache.camel:camel-support
  • camel-aws2-transcribe ← downstream of org.apache.camel:camel-test-junit6
  • camel-aws2-translate ← downstream of org.apache.camel:camel-support
  • camel-azure-common ← downstream of org.apache.camel:camel-core-model
  • camel-azure-cosmosdb ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-eventgrid ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-eventhubs ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-files ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-functions ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-iothub ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-key-vault ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-parent ← downstream of org.apache.camel:camel-core-model
  • camel-azure-schema-registry ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-servicebus ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-storage-blob ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-storage-datalake ← downstream of org.apache.camel:camel-test-junit6
  • camel-azure-storage-queue ← downstream of org.apache.camel:camel-test-junit6
  • camel-barcode ← downstream of org.apache.camel:camel-support
  • camel-base ← downstream of org.apache.camel:camel-util
  • camel-base-engine ← downstream of org.apache.camel:camel-util
  • camel-base64 ← downstream of org.apache.camel:camel-test-junit6
  • camel-bean ← downstream of org.apache.camel:camel-support
  • camel-bean-validator ← downstream of org.apache.camel:camel-test-junit6
  • camel-beanio ← downstream of org.apache.camel:camel-support
  • camel-bindy ← downstream of org.apache.camel:camel-support
  • camel-bonita ← downstream of org.apache.camel:camel-test-junit6
  • camel-box ← downstream of org.apache.camel:camel-test-junit6
  • camel-box-api ← downstream of org.apache.camel:camel-api
  • camel-box-parent ← downstream of org.apache.camel:camel-core-model
  • camel-braintree ← downstream of org.apache.camel:camel-test-junit6
  • camel-browse ← downstream of org.apache.camel:camel-support
  • camel-caffeine ← downstream of org.apache.camel:camel-test-junit6
  • camel-camunda ← downstream of org.apache.camel:camel-test-junit6
  • camel-cassandraql ← downstream of org.apache.camel:camel-test-junit6
  • camel-catalog-common ← downstream of org.apache.camel:camel-support
  • camel-cbor ← downstream of org.apache.camel:camel-support
  • camel-chaos ← downstream of org.apache.camel:camel-file
  • camel-chatscript ← downstream of org.apache.camel:camel-test-junit6
  • camel-chunk ← downstream of org.apache.camel:camel-test-junit6
  • camel-cli-connector ← downstream of org.apache.camel:camel-test-junit6
  • camel-cli-debug ← downstream of org.apache.camel:camel-cli-connector
  • camel-clickhouse ← downstream of org.apache.camel:camel-test-junit6
  • camel-clickup ← downstream of org.apache.camel:camel-test-junit6
  • camel-cloudevents ← downstream of org.apache.camel:camel-test-junit6
  • camel-cluster ← downstream of org.apache.camel:camel-util
  • camel-cm-sms ← downstream of org.apache.camel:camel-support
  • camel-coap ← downstream of org.apache.camel:camel-test-junit6
  • camel-cometd ← downstream of org.apache.camel:camel-test-junit6
  • camel-console ← downstream of org.apache.camel:camel-core
  • camel-consul ← downstream of org.apache.camel:camel-file
  • camel-controlbus ← downstream of org.apache.camel:camel-support
  • camel-core ← downstream of org.apache.camel:camel-file
  • camel-core-all ← downstream of org.apache.camel:camel-util
  • camel-core-catalog ← downstream of org.apache.camel:camel-util
  • camel-core-engine ← downstream of org.apache.camel:camel-util
  • camel-core-languages ← downstream of org.apache.camel:camel-util
  • camel-core-model ← downstream of org.apache.camel:camel-util
  • camel-core-processor ← downstream of org.apache.camel:camel-util
  • camel-core-reifier ← downstream of org.apache.camel:camel-util
  • camel-core-xml ← downstream of org.apache.camel:camel-core-engine
  • camel-couchbase ← downstream of org.apache.camel:camel-test-junit6
  • camel-couchdb ← downstream of org.apache.camel:camel-test-junit6
  • camel-cron ← downstream of org.apache.camel:camel-test-junit6
  • camel-crypto ← downstream of org.apache.camel:camel-support
  • camel-crypto-pgp ← downstream of org.apache.camel:camel-support
  • camel-csv ← downstream of org.apache.camel:camel-support
  • camel-cxf-common ← downstream of org.apache.camel:camel-test-junit6
  • camel-cxf-parent ← downstream of org.apache.camel:camel-core-model
  • camel-cxf-rest ← downstream of org.apache.camel:camel-test-junit6
  • camel-cxf-soap ← downstream of org.apache.camel:camel-test-junit6
  • camel-cxf-spring-common ← downstream of org.apache.camel:camel-support
  • camel-cxf-spring-rest ← downstream of org.apache.camel:camel-http
  • camel-cxf-spring-soap ← downstream of org.apache.camel:camel-http
  • camel-cxf-spring-transport ← downstream of org.apache.camel:camel-test-junit6
  • camel-cxf-transport ← downstream of org.apache.camel:camel-test-junit6
  • camel-cyberark-vault ← downstream of org.apache.camel:camel-test-junit6
  • camel-dapr ← downstream of org.apache.camel:camel-test-junit6
  • camel-dataformat ← downstream of org.apache.camel:camel-support
  • camel-dataset ← downstream of org.apache.camel:camel-core-model
  • camel-datasonnet ← downstream of org.apache.camel:camel-core
  • camel-dataweave ← downstream of org.apache.camel:camel-core-model
  • camel-debezium-common ← downstream of org.apache.camel:camel-test-junit6
  • camel-debezium-common-parent ← downstream of org.apache.camel:camel-support
  • camel-debezium-db2 ← downstream of org.apache.camel:camel-test-junit6
  • camel-debezium-maven-plugin ← downstream of org.apache.camel:camel-test-junit6
  • camel-debezium-mongodb ← downstream of org.apache.camel:camel-test-junit6
  • camel-debezium-mysql ← downstream of org.apache.camel:camel-test-junit6
  • camel-debezium-oracle ← downstream of org.apache.camel:camel-test-junit6
  • camel-debezium-parent ← downstream of org.apache.camel:camel-core-model
  • camel-debezium-postgres ← downstream of org.apache.camel:camel-test-junit6
  • camel-debezium-sqlserver ← downstream of org.apache.camel:camel-test-junit6
  • camel-debug ← downstream of org.apache.camel:camel-support
  • camel-dependencies ← downstream of org.apache.camel:sync-properties-maven-plugin
  • camel-dfdl ← downstream of org.apache.camel:camel-test-junit6
  • camel-dhis2 ← downstream of org.apache.camel:camel-test-junit6
  • camel-dhis2-api ← downstream of org.apache.camel:camel-test-junit6
  • camel-dhis2-parent ← downstream of org.apache.camel:camel-test-junit6
  • camel-diagram ← downstream of org.apache.camel:camel-util
  • camel-direct ← downstream of org.apache.camel:camel-support
  • camel-disruptor ← downstream of org.apache.camel:camel-test-junit6
  • camel-djl ← downstream of org.apache.camel:camel-test-junit6
  • camel-dns ← downstream of org.apache.camel:camel-support
  • camel-docker ← downstream of org.apache.camel:camel-test-junit6
  • camel-docling ← downstream of org.apache.camel:camel-test-junit6
  • camel-drill ← downstream of org.apache.camel:camel-test-junit6
  • camel-dropbox ← downstream of org.apache.camel:camel-test-junit6
  • camel-dsl-modeline ← downstream of org.apache.camel:camel-test-junit6
  • camel-dsl-support ← downstream of org.apache.camel:camel-support
  • camel-duckdb ← downstream of org.apache.camel:camel-test-junit6
  • camel-dynamic-router ← downstream of org.apache.camel:camel-support
  • camel-ehcache ← downstream of org.apache.camel:camel-test-junit6
  • camel-eip-documentation-enricher-maven-plugin ← downstream of org.apache.camel:camel-util
  • camel-elasticsearch ← downstream of org.apache.camel:camel-test-junit6
  • camel-elasticsearch-rest-client ← downstream of org.apache.camel:camel-test-junit6
  • camel-event ← downstream of org.apache.camel:camel-test-junit6
  • camel-exec ← downstream of org.apache.camel:camel-support
  • camel-fastjson ← downstream of org.apache.camel:camel-support
  • camel-fhir ← downstream of org.apache.camel:camel-test-junit6
  • camel-fhir-api ← downstream of org.apache.camel:camel-support
  • camel-fhir-parent ← downstream of org.apache.camel:camel-core-model
  • camel-file ← components/camel-file/src/main/java/org/apache/camel/component/file/GenericFileConverter.java
  • camel-file-watch ← downstream of org.apache.camel:camel-support
  • camel-flatpack ← downstream of org.apache.camel:camel-file
  • camel-flink ← downstream of org.apache.camel:camel-test-junit6
  • camel-flowable ← downstream of org.apache.camel:camel-test-junit6
  • camel-fop ← downstream of org.apache.camel:camel-test-junit6
  • camel-fory ← downstream of org.apache.camel:camel-support
  • camel-freemarker ← downstream of org.apache.camel:camel-support
  • camel-ftp ← downstream of org.apache.camel:camel-test-junit6
  • camel-ftp-common ← downstream of org.apache.camel:camel-file
  • camel-geocoder ← downstream of org.apache.camel:camel-test-junit6
  • camel-git ← downstream of org.apache.camel:camel-test-junit6
  • camel-github2 ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-bigquery ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-calendar ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-common ← downstream of org.apache.camel:camel-core
  • camel-google-drive ← downstream of org.apache.camel:camel-file
  • camel-google-firestore ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-functions ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-mail ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-parent ← downstream of org.apache.camel:camel-core-model
  • camel-google-pubsub ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-secret-manager ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-sheets ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-speech-to-text ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-storage ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-text-to-speech ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-vertexai ← downstream of org.apache.camel:camel-test-junit6
  • camel-google-vision ← downstream of org.apache.camel:camel-test-junit6
  • camel-graphql ← downstream of org.apache.camel:camel-test-junit6
  • camel-grok ← downstream of org.apache.camel:camel-support
  • camel-groovy ← downstream of org.apache.camel:camel-core
  • camel-grpc ← downstream of org.apache.camel:camel-test-junit6
  • camel-gson ← downstream of org.apache.camel:camel-support
  • camel-hashicorp-vault ← downstream of org.apache.camel:camel-test-junit6
  • camel-hazelcast ← downstream of org.apache.camel:camel-support
  • camel-health ← downstream of org.apache.camel:camel-util
  • camel-hibernate ← downstream of org.apache.camel:camel-test-junit6
  • camel-hivemq ← downstream of org.apache.camel:camel-test-junit6
  • camel-hl7 ← downstream of org.apache.camel:camel-core
  • camel-http ← downstream of org.apache.camel:camel-file
  • camel-http-base ← downstream of org.apache.camel:camel-test-junit6
  • camel-http-common ← downstream of org.apache.camel:camel-test-junit6
  • camel-huawei-parent ← downstream of org.apache.camel:camel-core-model
  • camel-huaweicloud-common ← downstream of org.apache.camel:camel-support
  • camel-huaweicloud-dms ← downstream of org.apache.camel:camel-test-junit6
  • camel-huaweicloud-frs ← downstream of org.apache.camel:camel-support
  • camel-huaweicloud-functiongraph ← downstream of org.apache.camel:camel-test-junit6
  • camel-huaweicloud-iam ← downstream of org.apache.camel:camel-test-junit6
  • camel-huaweicloud-imagerecognition ← downstream of org.apache.camel:camel-support
  • camel-huaweicloud-obs ← downstream of org.apache.camel:camel-test-junit6
  • camel-huaweicloud-smn ← downstream of org.apache.camel:camel-support
  • camel-huggingface ← downstream of org.apache.camel:camel-test-junit6
  • camel-ibm-cos ← downstream of org.apache.camel:camel-test-junit6
  • camel-ibm-parent ← downstream of org.apache.camel:camel-core-model
  • camel-ibm-secrets-manager ← downstream of org.apache.camel:camel-test-junit6
  • camel-ibm-watson-discovery ← downstream of org.apache.camel:camel-test-junit6
  • camel-ibm-watson-language ← downstream of org.apache.camel:camel-test-junit6
  • camel-ibm-watson-speech-to-text ← downstream of org.apache.camel:camel-test-junit6
  • camel-ibm-watson-text-to-speech ← downstream of org.apache.camel:camel-test-junit6
  • camel-ibm-watsonx-ai ← downstream of org.apache.camel:camel-test-junit6
  • camel-ibm-watsonx-data ← downstream of org.apache.camel:camel-test-junit6
  • camel-ical ← downstream of org.apache.camel:camel-test-junit6
  • camel-iggy ← downstream of org.apache.camel:camel-test-junit6
  • camel-ignite ← downstream of org.apache.camel:camel-test-junit6
  • camel-infinispan ← downstream of org.apache.camel:camel-test-junit6
  • camel-infinispan-common ← downstream of org.apache.camel:camel-test-junit6
  • camel-infinispan-embedded ← downstream of org.apache.camel:camel-test-junit6
  • camel-infinispan-parent ← downstream of org.apache.camel:camel-core-model
  • camel-influxdb ← downstream of org.apache.camel:camel-test-junit6
  • camel-influxdb2 ← downstream of org.apache.camel:camel-test-junit6
  • camel-iso8583 ← downstream of org.apache.camel:camel-support
  • camel-jackson ← downstream of org.apache.camel:camel-core-model
  • camel-jackson-avro ← downstream of org.apache.camel:camel-test-junit6
  • camel-jackson-protobuf ← downstream of org.apache.camel:camel-test-junit6
  • camel-jackson3 ← downstream of org.apache.camel:camel-core-model
  • camel-jackson3-avro ← downstream of org.apache.camel:camel-test-junit6
  • camel-jackson3-protobuf ← downstream of org.apache.camel:camel-test-junit6
  • camel-jackson3xml ← downstream of org.apache.camel:camel-support
  • camel-jacksonxml ← downstream of org.apache.camel:camel-support
  • camel-jactl ← downstream of org.apache.camel:camel-core
  • camel-jandex ← downstream of org.apache.camel:camel-test-junit6
  • camel-jasypt ← downstream of org.apache.camel:camel-base
  • camel-java-io ← downstream of org.apache.camel:camel-xml-io
  • camel-java-joor-dsl ← downstream of org.apache.camel:camel-test-junit6
  • camel-javascript ← downstream of org.apache.camel:camel-core
  • camel-jaxb ← downstream of org.apache.camel:camel-test-junit6
  • camel-jbang-console ← downstream of org.apache.camel:camel-support
  • camel-jbang-mcp ← downstream of org.apache.camel:camel-chaos
  • camel-jbang-plugin-mcp ← downstream of org.apache.camel:camel-jbang-core
  • camel-jbang-plugin-tui ← downstream of org.apache.camel:camel-test-junit6
  • camel-jbang-plugin-validate ← downstream of org.apache.camel:camel-test-junit6
  • camel-jbang-run ← downstream of org.apache.camel:camel-test-junit6
  • camel-jcache ← downstream of org.apache.camel:camel-test-junit6
  • camel-jcr ← downstream of org.apache.camel:camel-test-junit6
  • camel-jdbc ← downstream of org.apache.camel:camel-support
  • camel-jetty ← downstream of org.apache.camel:camel-http
  • camel-jetty-common ← downstream of org.apache.camel:camel-core-model
  • camel-jfr ← downstream of org.apache.camel:camel-test-junit6
  • camel-jgroups ← downstream of org.apache.camel:camel-test-junit6
  • camel-jgroups-raft ← downstream of org.apache.camel:camel-test-junit6
  • camel-jira ← downstream of org.apache.camel:camel-file
  • camel-jms ← downstream of org.apache.camel:camel-support
  • camel-jmx ← downstream of org.apache.camel:camel-test-junit6
  • camel-jolt ← downstream of org.apache.camel:camel-test-junit6
  • camel-jooq ← downstream of org.apache.camel:camel-test-junit6
  • camel-joor ← downstream of org.apache.camel:camel-core
  • camel-jpa ← downstream of org.apache.camel:camel-test-junit6
  • camel-jq ← downstream of org.apache.camel:camel-core
  • camel-jsch ← downstream of org.apache.camel:camel-test-junit6
  • camel-jslt ← downstream of org.apache.camel:camel-test-junit6
  • camel-json-validator ← downstream of org.apache.camel:camel-test-junit6
  • camel-jsonapi ← downstream of org.apache.camel:camel-test-junit6
  • camel-jsonata ← downstream of org.apache.camel:camel-test-junit6
  • camel-jsonb ← downstream of org.apache.camel:camel-support
  • camel-jsonpath ← downstream of org.apache.camel:camel-file
  • camel-jsoup ← downstream of org.apache.camel:camel-test-junit6
  • camel-jt400 ← downstream of org.apache.camel:camel-test-junit6
  • camel-jta ← downstream of org.apache.camel:camel-core
  • camel-jte ← downstream of org.apache.camel:camel-test-junit6
  • camel-kafka ← downstream of org.apache.camel:camel-test-junit6
  • camel-kafka-common ← downstream of org.apache.camel:camel-test-junit6
  • camel-kafka-share ← downstream of org.apache.camel:camel-test-junit6
  • camel-kamelet ← downstream of org.apache.camel:camel-test-junit6
  • camel-kamelet-main-support ← downstream of org.apache.camel:camel-main
  • camel-keycloak ← downstream of org.apache.camel:camel-test-junit6
  • camel-knative ← downstream of org.apache.camel:camel-test-junit6
  • camel-knative-api ← downstream of org.apache.camel:camel-test-junit6
  • camel-knative-http ← downstream of org.apache.camel:camel-test-junit6
  • camel-knative-parent ← downstream of org.apache.camel:camel-core-model
  • camel-kserve ← downstream of org.apache.camel:camel-test-junit6
  • camel-kubernetes ← downstream of org.apache.camel:camel-http
  • camel-kudu ← downstream of org.apache.camel:camel-test-junit6
  • camel-langchain4j-agent ← downstream of org.apache.camel:camel-test-junit6
  • camel-langchain4j-agent-api ← downstream of org.apache.camel:camel-api
  • camel-langchain4j-chat ← downstream of org.apache.camel:camel-test-junit6
  • camel-langchain4j-core ← downstream of org.apache.camel:camel-test-junit6
  • camel-langchain4j-embeddings ← downstream of org.apache.camel:camel-test-junit6
  • camel-langchain4j-embeddingstore ← downstream of org.apache.camel:camel-test-junit6
  • camel-langchain4j-embeddingstore-api ← downstream of org.apache.camel:camel-api
  • camel-langchain4j-ingest ← downstream of org.apache.camel:camel-test-junit6
  • camel-langchain4j-tokenizer ← downstream of org.apache.camel:camel-test-junit6
  • camel-langchain4j-web-search ← downstream of org.apache.camel:camel-test-junit6
  • camel-language ← downstream of org.apache.camel:camel-support
  • camel-launcher-container ← downstream of org.apache.camel:camel-launcher
  • camel-ldap ← downstream of org.apache.camel:camel-test-junit6
  • camel-ldif ← downstream of org.apache.camel:camel-test-junit6
  • camel-log ← downstream of org.apache.camel:camel-support
  • camel-lra ← downstream of org.apache.camel:camel-test-junit6
  • camel-lucene ← downstream of org.apache.camel:camel-test-junit6
  • camel-lumberjack ← downstream of org.apache.camel:camel-test-junit6
  • camel-lzf ← downstream of org.apache.camel:camel-test-junit6
  • camel-mail ← downstream of org.apache.camel:camel-support
  • camel-mail-microsoft-oauth ← downstream of org.apache.camel:camel-core-model
  • camel-main ← downstream of org.apache.camel:camel-util
  • camel-management ← downstream of org.apache.camel:camel-core
  • camel-management-api ← downstream of org.apache.camel:camel-util
  • camel-mapstruct ← downstream of org.apache.camel:camel-test-junit6
  • camel-master ← downstream of org.apache.camel:camel-test-junit6
  • camel-maven-plugin ← downstream of org.apache.camel:camel-core
  • camel-mcp-server ← downstream of org.apache.camel:camel-test-junit6
  • camel-mcp-server-api ← downstream of org.apache.camel:camel-test-junit6
  • camel-mdc ← downstream of org.apache.camel:camel-support
  • camel-metrics ← downstream of org.apache.camel:camel-test-junit6
  • camel-micrometer ← downstream of org.apache.camel:camel-test-junit6
  • camel-micrometer-observability ← downstream of org.apache.camel:camel-core-model
  • camel-micrometer-prometheus ← downstream of org.apache.camel:camel-core-model
  • camel-microprofile-config ← downstream of org.apache.camel:camel-test-junit6
  • camel-microprofile-fault-tolerance ← downstream of org.apache.camel:camel-support
  • camel-microprofile-health ← downstream of org.apache.camel:camel-test-junit6
  • camel-microprofile-parent ← downstream of org.apache.camel:camel-core-model
  • camel-milo ← downstream of org.apache.camel:camel-test-junit6
  • camel-milvus ← downstream of org.apache.camel:camel-test-junit6
  • camel-mina ← downstream of org.apache.camel:camel-support
  • camel-mina-sftp ← downstream of org.apache.camel:camel-test-junit6
  • camel-minio ← downstream of org.apache.camel:camel-support
  • camel-mllp ← downstream of org.apache.camel:camel-test-junit6
  • camel-mock ← downstream of org.apache.camel:camel-support
  • camel-mongodb ← downstream of org.apache.camel:camel-test-junit6
  • camel-mongodb-gridfs ← downstream of org.apache.camel:camel-test-junit6
  • camel-mtconnect ← downstream of org.apache.camel:camel-test-junit6
  • camel-mustache ← downstream of org.apache.camel:camel-test-junit6
  • camel-mvel ← downstream of org.apache.camel:camel-core
  • camel-mybatis ← downstream of org.apache.camel:camel-test-junit6
  • camel-nats ← downstream of org.apache.camel:camel-test-junit6
  • camel-neo4j ← downstream of org.apache.camel:camel-test-junit6
  • camel-netty ← downstream of org.apache.camel:camel-support
  • camel-netty-http ← downstream of org.apache.camel:camel-http
  • camel-oaipmh ← downstream of org.apache.camel:camel-support
  • camel-oauth ← downstream of org.apache.camel:camel-test-junit6
  • camel-observability-services ← downstream of org.apache.camel:camel-core-model
  • camel-observation ← downstream of org.apache.camel:camel-support
  • camel-ocsf ← downstream of org.apache.camel:camel-test-junit6
  • camel-odata ← downstream of org.apache.camel:camel-test-junit6
  • camel-ognl ← downstream of org.apache.camel:camel-core
  • camel-olingo2 ← downstream of org.apache.camel:camel-test-junit6
  • camel-olingo2-api ← downstream of org.apache.camel:camel-test-junit6
  • camel-olingo2-parent ← downstream of org.apache.camel:camel-core-model
  • camel-olingo4 ← downstream of org.apache.camel:camel-test-junit6
  • camel-olingo4-api ← downstream of org.apache.camel:camel-test-junit6
  • camel-olingo4-parent ← downstream of org.apache.camel:camel-core-model
  • camel-once ← downstream of org.apache.camel:camel-test-junit6
  • camel-opa ← downstream of org.apache.camel:camel-test-junit6
  • camel-openai ← downstream of org.apache.camel:camel-file
  • camel-openapi-java ← downstream of org.apache.camel:camel-core-model
  • camel-openapi-rest-dsl-generator ← downstream of org.apache.camel:camel-util
  • camel-openapi-validator ← downstream of org.apache.camel:camel-test-junit6
  • camel-openfeature ← downstream of org.apache.camel:camel-test-junit6
  • camel-openfga ← downstream of org.apache.camel:camel-test-junit6
  • camel-opensearch ← downstream of org.apache.camel:camel-test-junit6
  • camel-openstack ← downstream of org.apache.camel:camel-test-junit6
  • camel-opentelemetry ← downstream of org.apache.camel:camel-support
  • camel-opentelemetry-metrics ← downstream of org.apache.camel:camel-support
  • camel-opentelemetry2 ← downstream of org.apache.camel:camel-core-model
  • camel-optaplanner ← downstream of org.apache.camel:camel-support
  • camel-paho ← downstream of org.apache.camel:camel-test-junit6
  • camel-paho-mqtt5 ← downstream of org.apache.camel:camel-test-junit6
  • camel-parquet-avro ← downstream of org.apache.camel:camel-test-junit6
  • camel-pdf ← downstream of org.apache.camel:camel-test-junit6
  • camel-pg-replication-slot ← downstream of org.apache.camel:camel-test-junit6
  • camel-pgevent ← downstream of org.apache.camel:camel-test-junit6
  • camel-pgvector ← downstream of org.apache.camel:camel-test-junit6
  • camel-pinecone ← downstream of org.apache.camel:camel-test-junit6
  • camel-platform-http ← downstream of org.apache.camel:camel-test-junit6
  • camel-platform-http-jolokia ← downstream of org.apache.camel:camel-core
  • camel-platform-http-main ← downstream of org.apache.camel:camel-test-junit6
  • camel-platform-http-vertx ← downstream of org.apache.camel:camel-file
  • camel-plc4x ← downstream of org.apache.camel:camel-test-junit6
  • camel-pqc ← downstream of org.apache.camel:camel-test-junit6
  • camel-printer ← downstream of org.apache.camel:camel-test-junit6
  • camel-protobuf ← downstream of org.apache.camel:camel-support
  • camel-pubnub ← downstream of org.apache.camel:camel-test-junit6
  • camel-pulsar ← downstream of org.apache.camel:camel-test-junit6
  • camel-python ← downstream of org.apache.camel:camel-core
  • camel-python3 ← downstream of org.apache.camel:camel-core
  • camel-qdrant ← downstream of org.apache.camel:camel-test-junit6
  • camel-quartz ← downstream of org.apache.camel:camel-support
  • camel-quickfix ← downstream of org.apache.camel:camel-support
  • camel-quickjs ← downstream of org.apache.camel:camel-core
  • camel-reactive-streams ← downstream of org.apache.camel:camel-test-junit6
  • camel-reactor ← downstream of org.apache.camel:camel-test-junit6
  • camel-redis ← downstream of org.apache.camel:camel-test-junit6
  • camel-ref ← downstream of org.apache.camel:camel-support
  • camel-resilience4j ← downstream of org.apache.camel:camel-support
  • camel-resilience4j-micrometer ← downstream of org.apache.camel:camel-core-model
  • camel-resourceresolver-github ← downstream of org.apache.camel:camel-test-junit6
  • camel-rest ← downstream of org.apache.camel:camel-support
  • camel-rest-openapi ← downstream of org.apache.camel:camel-test-junit6
  • camel-rest-postman ← downstream of org.apache.camel:camel-test-junit6
  • camel-restdsl-openapi-plugin ← downstream of org.apache.camel:camel-core
  • camel-robotframework ← downstream of org.apache.camel:camel-test-junit6
  • camel-rocketmq ← downstream of org.apache.camel:camel-test-junit6
  • camel-rss ← downstream of org.apache.camel:camel-test-junit6
  • camel-rxjava ← downstream of org.apache.camel:camel-test-junit6
  • camel-saga ← downstream of org.apache.camel:camel-support
  • camel-salesforce ← downstream of org.apache.camel:camel-test-junit6
  • camel-salesforce-codegen ← downstream of org.apache.camel:camel-core-model
  • camel-salesforce-maven-plugin ← downstream of org.apache.camel:camel-test-junit6
  • camel-salesforce-parent ← downstream of org.apache.camel:camel-core-model
  • camel-sanitizer ← downstream of org.apache.camel:camel-support
  • camel-sap-netweaver ← downstream of org.apache.camel:camel-test-junit6
  • camel-saxon ← downstream of org.apache.camel:camel-core
  • camel-scheduler ← downstream of org.apache.camel:camel-support
  • camel-schematron ← downstream of org.apache.camel:camel-test-junit6
  • camel-seda ← downstream of org.apache.camel:camel-support
  • camel-semantic ← downstream of org.apache.camel:camel-test-junit6
  • camel-semantic-openai ← downstream of org.apache.camel:camel-test-junit6
  • camel-semantic-typesafe-ai ← downstream of org.apache.camel:camel-test-junit6
  • camel-semantic-wolf-defender ← downstream of org.apache.camel:camel-test-junit6
  • camel-servicenow ← downstream of org.apache.camel:camel-test-junit6
  • camel-servicenow-maven-plugin ← downstream of org.apache.camel:camel-test-junit6
  • camel-servicenow-parent ← downstream of org.apache.camel:camel-core-model
  • camel-servlet ← downstream of org.apache.camel:camel-test-junit6
  • camel-shell ← downstream of org.apache.camel:camel-test-junit5
  • camel-shiro ← downstream of org.apache.camel:camel-test-junit6
  • camel-sjms ← downstream of org.apache.camel:camel-test-junit6
  • camel-sjms2 ← downstream of org.apache.camel:camel-test-junit6
  • camel-slack ← downstream of org.apache.camel:camel-test-junit6
  • camel-smb ← downstream of org.apache.camel:camel-file
  • camel-smooks ← downstream of org.apache.camel:camel-test-junit6
  • camel-smpp ← downstream of org.apache.camel:camel-support
  • camel-snakeyaml ← downstream of org.apache.camel:camel-support
  • camel-snmp ← downstream of org.apache.camel:camel-test-junit6
  • camel-soap ← downstream of org.apache.camel:camel-test-junit6
  • camel-solr ← downstream of org.apache.camel:camel-test-junit6
  • camel-spiffe ← downstream of org.apache.camel:camel-test-junit6
  • camel-splunk-hec ← downstream of org.apache.camel:camel-test-junit6
  • camel-spring ← downstream of org.apache.camel:camel-management-api
  • camel-spring-ai-chat ← downstream of org.apache.camel:camel-test-junit6
  • camel-spring-ai-embeddings ← downstream of org.apache.camel:camel-test-junit6
  • camel-spring-ai-image ← downstream of org.apache.camel:camel-test-junit6
  • camel-spring-ai-parent ← downstream of org.apache.camel:camel-core-model
  • camel-spring-ai-vector-store ← downstream of org.apache.camel:camel-test-junit6
  • camel-spring-batch ← downstream of org.apache.camel:camel-test-junit6
  • camel-spring-cloud-config ← downstream of org.apache.camel:camel-test-junit6
  • camel-spring-jdbc ← downstream of org.apache.camel:camel-core-model
  • camel-spring-ldap ← downstream of org.apache.camel:camel-support
  • camel-spring-main ← downstream of org.apache.camel:camel-core-model
  • camel-spring-parent ← downstream of org.apache.camel:camel-core-model
  • camel-spring-rabbitmq ← downstream of org.apache.camel:camel-http
  • camel-spring-redis ← downstream of org.apache.camel:camel-test-junit6
  • camel-spring-security ← downstream of org.apache.camel:camel-core-model
  • camel-spring-ws ← downstream of org.apache.camel:camel-support
  • camel-spring-xml ← downstream of org.apache.camel:camel-core
  • camel-sql ← downstream of org.apache.camel:camel-support
  • camel-ssh ← downstream of org.apache.camel:camel-test-junit6
  • camel-state-store ← downstream of org.apache.camel:camel-test-junit5
  • camel-state-store-parent ← downstream of org.apache.camel:camel-core-model
  • camel-stax ← downstream of org.apache.camel:camel-core
  • camel-stitch ← downstream of org.apache.camel:camel-test-junit6
  • camel-stream ← downstream of org.apache.camel:camel-test-junit6
  • camel-streamcaching-test ← downstream of org.apache.camel:camel-core
  • camel-stringtemplate ← downstream of org.apache.camel:camel-test-junit6
  • camel-stripe ← downstream of org.apache.camel:camel-test-junit6
  • camel-stub ← downstream of org.apache.camel:camel-core-model
  • camel-support ← downstream of org.apache.camel:camel-util
  • camel-swift ← downstream of org.apache.camel:camel-test-junit6
  • camel-syslog ← downstream of org.apache.camel:camel-support
  • camel-tahu ← downstream of org.apache.camel:camel-test-junit6
  • camel-tarfile ← downstream of org.apache.camel:camel-file
  • camel-telegram ← downstream of org.apache.camel:camel-test-junit6
  • camel-telemetry ← downstream of org.apache.camel:camel-support
  • camel-telemetry-dev ← downstream of org.apache.camel:camel-core-model
  • camel-tensorflow-serving ← downstream of org.apache.camel:camel-test-junit6
  • camel-test-citrus ← downstream of org.apache.camel:camel-test-junit6
  • camel-test-dst ← downstream of org.apache.camel:camel-support
  • camel-test-infra-all ← downstream of org.apache.camel:camel-test-infra-jetty
  • camel-test-infra-artemis ← downstream of org.apache.camel:camel-test-junit6
  • camel-test-infra-cli ← downstream of org.apache.camel:camel-util
  • camel-test-infra-core ← downstream of org.apache.camel:camel-core
  • camel-test-infra-jetty ← downstream of org.apache.camel:camel-util
  • camel-test-infra-qdrant ← downstream of org.apache.camel:camel-util
  • camel-test-infra-smb ← downstream of org.apache.camel:camel-test-junit6
  • camel-test-junit5 ← downstream of org.apache.camel:camel-file
  • camel-test-junit6 ← downstream of org.apache.camel:camel-file
  • camel-test-main-junit5 ← downstream of org.apache.camel:camel-test-junit5
  • camel-test-main-junit6 ← downstream of org.apache.camel:camel-test-junit6
  • camel-test-parent ← downstream of org.apache.camel:camel-core-model
  • camel-test-spring-junit5 ← downstream of org.apache.camel:camel-test-junit5
  • camel-test-spring-junit6 ← downstream of org.apache.camel:camel-test-junit6
  • camel-thrift ← downstream of org.apache.camel:camel-support
  • camel-thymeleaf ← downstream of org.apache.camel:camel-support
  • camel-tika ← downstream of org.apache.camel:camel-support
  • camel-timer ← downstream of org.apache.camel:camel-support
  • camel-tooling-maven ← downstream of org.apache.camel:camel-support
  • camel-toon ← downstream of org.apache.camel:camel-test-junit5
  • camel-tracing ← downstream of org.apache.camel:camel-support
  • camel-twilio ← downstream of org.apache.camel:camel-test-junit6
  • camel-twitter ← downstream of org.apache.camel:camel-test-junit6
  • camel-typesafe-ai ← downstream of org.apache.camel:camel-test-junit6
  • camel-ubl ← downstream of org.apache.camel:camel-test-junit5
  • camel-undertow ← downstream of org.apache.camel:camel-test-junit6
  • camel-undertow-spring-security ← downstream of org.apache.camel:camel-test-junit6
  • camel-univocity-parsers ← downstream of org.apache.camel:camel-support
  • camel-util ← core/camel-util/src/main/java/org/apache/camel/util/IOHelper.java, core/camel-util/src/test/java/org/apache/camel/util/IOHelperTest.java
  • camel-validator ← downstream of org.apache.camel:camel-support
  • camel-velocity ← downstream of org.apache.camel:camel-support
  • camel-vertx ← downstream of org.apache.camel:camel-test-junit6
  • camel-vertx-common ← downstream of org.apache.camel:camel-test-junit6
  • camel-vertx-http ← downstream of org.apache.camel:camel-test-junit6
  • camel-vertx-mqtt ← downstream of org.apache.camel:camel-test-junit6
  • camel-vertx-parent ← downstream of org.apache.camel:camel-core-model
  • camel-vertx-websocket ← downstream of org.apache.camel:camel-test-junit6
  • camel-wal ← downstream of org.apache.camel:camel-support
  • camel-wasm ← downstream of org.apache.camel:camel-test-junit6
  • camel-weather ← downstream of org.apache.camel:camel-test-junit6
  • camel-weaviate ← downstream of org.apache.camel:camel-test-junit6
  • camel-web3j ← downstream of org.apache.camel:camel-test-junit6
  • camel-webhook ← downstream of org.apache.camel:camel-test-junit6
  • camel-whatsapp ← downstream of org.apache.camel:camel-test-junit6
  • camel-wordpress ← downstream of org.apache.camel:camel-test-junit6
  • camel-workday ← downstream of org.apache.camel:camel-test-junit6
  • camel-xchange ← downstream of org.apache.camel:camel-test-junit6
  • camel-xj ← downstream of org.apache.camel:camel-test-junit6
  • camel-xml-io ← downstream of org.apache.camel:camel-util
  • camel-xml-io-dsl ← downstream of org.apache.camel:camel-core
  • camel-xml-jaxb ← downstream of org.apache.camel:camel-util
  • camel-xml-jaxb-dsl ← downstream of org.apache.camel:camel-core
  • camel-xml-jaxb-dsl-test-definition ← downstream of org.apache.camel:camel-core
  • camel-xml-jaxb-dsl-test-spring ← downstream of org.apache.camel:camel-core
  • camel-xml-jaxp ← downstream of org.apache.camel:camel-util
  • camel-xmlsecurity ← downstream of org.apache.camel:camel-test-junit6
  • camel-xmpp ← downstream of org.apache.camel:camel-test-junit6
  • camel-xpath ← downstream of org.apache.camel:camel-support
  • camel-xslt ← downstream of org.apache.camel:camel-support
  • camel-xslt-saxon ← downstream of org.apache.camel:camel-core-model
  • camel-yaml-dsl-common ← downstream of org.apache.camel:camel-core-engine
  • camel-yaml-dsl-validator ← downstream of org.apache.camel:camel-yaml-dsl
  • camel-yaml-dsl-validator-maven-plugin ← downstream of org.apache.camel:camel-yaml-dsl-validator
  • camel-yaml-io ← downstream of org.apache.camel:camel-util
  • camel-zendesk ← downstream of org.apache.camel:camel-test-junit6
  • camel-zip-deflater ← downstream of org.apache.camel:camel-test-junit6
  • camel-zipfile ← downstream of org.apache.camel:camel-file
  • camel-zookeeper ← downstream of org.apache.camel:camel-file
  • camel-zookeeper-master ← downstream of org.apache.camel:camel-test-junit6
  • components ← downstream of org.apache.camel:camel-core-model
  • sync-properties-maven-plugin ← downstream of org.apache.camel:camel-util
Modules with tests skipped (27)
  • apache-camel
  • camel-allcomponents
  • camel-catalog
  • camel-catalog-console
  • camel-catalog-maven
  • camel-catalog-suggest
  • camel-componentdsl
  • camel-endpointdsl
  • camel-endpointdsl-support
  • camel-itest
  • camel-jbang-core
  • camel-jbang-it
  • camel-jbang-main
  • camel-jbang-plugin-edit
  • camel-jbang-plugin-generate
  • camel-jbang-plugin-kubernetes
  • camel-jbang-plugin-test
  • camel-kamelet-main
  • camel-launcher
  • camel-report-maven-plugin
  • camel-route-parser
  • camel-yaml-dsl
  • camel-yaml-dsl-deserializers
  • camel-yaml-dsl-maven-plugin
  • coverage
  • docs
  • dummy-component

ℹ️ Shadow mode — Scalpel observes but does not affect test execution. Learn more

Build reactor — dependencies compiled but only changed modules were tested (2 modules, 16.6s total)

Total reactor time: 16.6s

Module Duration Status
Camel :: Util 9.9s SUCCESS
Camel :: File 6.7s SUCCESS

Top 20 slowest modules:

  • Camel :: Util (9.9s)
  • Camel :: File (6.7s)

⚙️ View full build and test results

@oscerd oscerd left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Confirmed the bug and that the sweep is complete.

InputStream.skip(long) and Reader.skip(long) both skip up to the requested amount and return how far they actually got, so a single unchecked skip(offset) on the file-resume path can leave the body starting partway into the data the recorded offset was meant to skip over. That is a real correctness issue for resume, and more likely the larger the offset or the more buffered the stream.

The fixes match the API each call has:

  • inputStream.skip(...) becomes inputStream.skipNBytes(...), which the JDK already defines as skip-exactly-or-throw, and which falls back to read() internally. That fallback is exactly why a plain skip was not enough for an InputStream.
  • The two reader calls go through the new IOHelper.skipFully, since Reader has no skipNBytes. The loop is right: Reader.skip blocks until a character is available or the stream ends, so reading a <= 0 return as end-of-stream and throwing EOFException matches the contract, and the running remaining lets the message report how far it actually got.

I grepped camel-file and IOHelper for other unchecked skip( on the offset path, and these three (GenericFileConverter twice, IOHelper.toString) are all of them, so nothing in this family is left on the old pattern.

The tests cover the part that matters: a reader that only skips one character per call still lands exactly, and skipping past the end throws. A FilterReader that returns super.skip(1) is a faithful stand-in for a short-skipping reader.

Claude Code on behalf of oscerd

The file resume support positions the body at the recorded offset with a
single unchecked call:

    inputStream.skip(file.getLastOffsetValue());   // GenericFileConverter
    reader.skip(file.getLastOffsetValue());
    reader.skip(offset);                           // IOHelper.toString

InputStream.skip and Reader.skip are both specified to skip up to the
requested amount and to return how far they actually got, so the return
value is the only thing that says where the stream now is. Discarding it
means the body silently starts somewhere other than the offset asked for.

The case reachable today is an offset past the end of the file, which
happens when the recorded offset is stale because the file was truncated or
replaced: the stream ran to EOF and the exchange carried an empty or short
body as if that were the file's content, instead of reporting that the
offset could not be honoured.

The stream now uses InputStream.skipNBytes, which loops and throws
EOFException if the stream ends first, and readers go through the new
IOHelper.skipFully, which does the same for Reader.skip.
Review follow-up on apache#29702.

The new EOFException path leaked the open file: in
GenericFileConverter.genericFileToInputStream and genericFileToReader the
stream is opened and then skipped, and when the skip throws, the stream is
neither returned nor closed - so a stale offset leaked a handle on every
poll, which on Windows also blocks the move or delete that follows. Both now
close it and rethrow. In IOHelper.toString the skip moves inside the try
whose finally already closes the reader.

Adds the upgrade-guide entry: a stale offset fails the exchange instead of
giving an empty body, and the failure repeats until the recorded offset is
reset.

GenericFileConverterResumeOffsetTest covers both converters skipping to the
offset, and an offset past the end of the file failing and releasing the file.
@Dhairya-007
Dhairya-007 force-pushed the fix/file-resume-partial-skip branch from b61fef8 to 9fdf9ae Compare November 12, 2026 13:43
@Dhairya-007

Copy link
Copy Markdown
Contributor Author

All three points are in, thanks — the leak is the important one and I had not thought it through: before this change those paths practically never threw, so opening-then-skipping was harmless; with a stale offset it throws on every poll.

1. Close on failure. All three places:

InputStream inputStream = IOHelper.toInputStream(f, charset);
try {
    inputStream.skipNBytes(file.getLastOffsetValue());
} catch (IOException e) {
    // the stream is not returned, so nothing else can close it
    IOHelper.close(inputStream);
    throw e;
}
return inputStream;

the same for the reader in genericFileToReader, and in IOHelper.toString(BufferedReader, long) the skipFully call moved inside the existing try whose finally already closes the reader.

2. Upgrade guide — added, and it says what you pointed out about the repeat: the failing exchange leaves the file in place, so the next poll reads the same offset from the resume store and fails again, and the recorded offset has to be reset for the file to be consumed from the start.

3. The test you suggested — added as GenericFileConverterResumeOffsetTest, four cases: both converters skipping to a valid offset, and an offset past the end failing with EOFException for each. Each failure case then deletes the file and asserts it is gone, which is the Windows-relevant check that the handle was actually released — the assertion that would have failed before this commit on that platform.

Also rebased on main, since the branch was 58 commits behind and the upgrade-guide entry would otherwise have landed in a conflicting spot (same situation as #29709).

@gnodet-bot gnodet-bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All three issues flagged by @davsclaus are now addressed: skipNBytes / skipFully with proper close-on-failure in both converter paths, an upgrade-guide entry, and unit tests covering the stale-offset failure and file release. LGTM.

A few notes on the implementation:

IOHelper.skipFully — the loop is correct. Reader.skip blocks until characters are available or EOF, so a return value of ≤ 0 means genuine EOF, not a transient empty read. The EOFException message reports how far the reader got (offset - remaining), which aids debugging.

GenericFileConverter — both genericFileToInputStream and genericFileToReader now close and rethrow on a stale offset. The InputStream path correctly uses skipNBytes (JDK built-in, loops and throws EOFException). The Reader path correctly delegates to skipFully. Both methods close on IOException and rethrow — no handle leak on Windows on the failing-poll cycle.

IOHelper.toString(BufferedReader, long) — skipFully is now inside the existing try/finally, so the reader is closed on a stale offset here too.

Tests — GenericFileConverterResumeOffsetTest covers both converters for the happy path and the stale-offset failure path, and asserts the file can be deleted after the failure (the Windows-critical check). IOHelperTest adds a OneAtATimeSkipReader fixture that proves the loop handles short skips.

This review was generated by an AI agent, Hermès on behalf of @gnodet.

@davsclaus davsclaus left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, this addresses everything from my last review: genericFileToInputStream and genericFileToReader close the stream/reader when the skip fails (GenericFileConverter.java:126-135, 213-219), IOHelper.toString(BufferedReader, long) skips inside the try that closes the reader (IOHelper.java:169-182), and there is a converter-level test plus an upgrade-guide entry. I checked the blast radius of the IOHelper change: every caller of toString(Reader|BufferedReader, ...) in the repo goes through the one-argument form with offset 0, where skipFully is a no-op, so only the camel-file resume path changes behaviour.

A few small wording points in the upgrade-guide entry:

  • "the exchange carried an empty or short body": for an offset past the end the old code produced an empty body; a short skip() would leave the body starting earlier (longer, not shorter). Maybe "an empty body as if that were the file's content".
  • "the failing exchange leaves the file in place": true by default, but with moveFailed the file is moved. "By default (without moveFailed)" avoids surprising those users.
  • Optional: the offset counts characters when the body is read as String/Reader and bytes when read as InputStream/byte[]. Not new, but a byte offset over multi-byte content now fails instead of silently giving an empty body, so one sentence on the unit could save someone a debugging session.

Optional in the test: the Files.delete(...) check after the failure only catches a leaked handle on Windows (Linux and macOS allow deleting an open file). A short comment saying so keeps the next reader from relying on it.

Heads-up: #29709 also appends to the end of the 4.24 upgrade guide, so whichever merges second needs a quick rebase.

Claude Code on behalf of davsclaus. This review was generated by an AI agent and may contain inaccuracies; please verify all suggestions before applying.

@github-actions github-actions Bot added the docs label Nov 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants