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

davsclaus 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 d603bdd93625 CAMEL-23703: Add native x64 camel.exe bootstrap to 
camel-launcher Windows distribution
d603bdd93625 is described below

commit d603bdd93625d0dc2a13e1efcde6f69b6dcbc3ba
Author: Adriano Machado <[email protected]>
AuthorDate: Wed Jul 15 03:00:52 2026 -0400

    CAMEL-23703: Add native x64 camel.exe bootstrap to camel-launcher Windows 
distribution
    
    Adds a native x64 bin/camel.exe to the camel-launcher Windows distribution 
alongside
    bin/camel.bat. The executable is a thin C bootstrap (~130 lines) that 
locates the adjacent
    camel.bat, forwards all arguments verbatim (preserving spaces and Unicode), 
and returns
    the child exit code. It exists so package managers requiring a genuine 
executable (e.g.
    WinGet) can expose camel directly.
    
    Native build logic lives in a new standalone module tooling/camel-exe with 
MSVC Maven
    profile, behavioral tests (Windows-only), and a release gate property. A 
dedicated CI
    workflow builds and tests camel.exe on Windows x64.
    
    Closes #24665
---
 .github/workflows/camel-launcher-windows.yml       | 133 +++++++++++++
 .../ROOT/pages/camel-4x-upgrade-guide-4_22.adoc    |   8 +
 dsl/camel-jbang/camel-launcher/README.md           |  20 ++
 dsl/camel-jbang/camel-launcher/pom.xml             | 106 ++++++++++
 .../camel-launcher/src/main/assembly/bin.xml       |   8 +
 .../jbang/launcher/CamelLauncherWindowsExeIT.java  |  77 ++++++++
 tooling/camel-exe/README.md                        |  45 +++++
 tooling/camel-exe/pom.xml                          | 214 ++++++++++++++++++++
 tooling/camel-exe/src/main/native/README.md        |  26 +++
 tooling/camel-exe/src/main/native/camel.c          | 146 ++++++++++++++
 .../camel/tooling/exe/CamelExeBootstrapTest.java   | 217 +++++++++++++++++++++
 .../java/org/apache/camel/maven/RepackageMojo.java |   8 +-
 .../org/apache/camel/maven/RepackageMojoTest.java  |  45 +++++
 tooling/pom.xml                                    |   1 +
 14 files changed, 1053 insertions(+), 1 deletion(-)

diff --git a/.github/workflows/camel-launcher-windows.yml 
b/.github/workflows/camel-launcher-windows.yml
new file mode 100644
index 000000000000..d6a9cca15176
--- /dev/null
+++ b/.github/workflows/camel-launcher-windows.yml
@@ -0,0 +1,133 @@
+#
+# 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.
+#
+
+name: Camel launcher Windows build
+
+on:
+  push:
+    branches:
+      - main
+  pull_request:
+    branches:
+      - main
+  workflow_dispatch:
+
+concurrency:
+  group: ${{ github.workflow }}-${{ github.ref }}
+  cancel-in-progress: true
+
+permissions:
+  contents: read
+
+jobs:
+  detect-changes:
+    runs-on: ubuntu-latest
+    outputs:
+      camel-exe: ${{ steps.changes.outputs.camel-exe }}
+      camel-launcher: ${{ steps.changes.outputs.camel-launcher }}
+    steps:
+      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # 
v7.0.0
+        with:
+          persist-credentials: false
+          # 50 commits covers any reasonable push batch; PRs fetch the base 
ref below.
+          fetch-depth: 50
+      - id: changes
+        run: |
+          if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
+            echo "camel-exe=true" >> "$GITHUB_OUTPUT"
+            echo "camel-launcher=true" >> "$GITHUB_OUTPUT"
+            exit 0
+          fi
+
+          if [ "${{ github.event_name }}" = "pull_request" ]; then
+            git fetch origin "${{ github.base_ref }}" --depth=1
+            CHANGED="$(git diff --name-only "origin/${{ github.base_ref 
}}"...HEAD)"
+          else
+            CHANGED="$(git diff --name-only "${{ github.event.before }}" "${{ 
github.sha }}")"
+          fi
+
+          echo "Changed files:"
+          echo "$CHANGED"
+
+          camel_exe=false
+          camel_launcher=false
+
+          if echo "$CHANGED" | grep -qE 
'^(tooling/camel-exe/|\.github/workflows/camel-launcher-windows\.yml)'; then
+            camel_exe=true
+          fi
+
+          if echo "$CHANGED" | grep -qE 
'^(dsl/camel-jbang/camel-launcher/|tooling/camel-exe/|\.github/workflows/camel-launcher-windows\.yml)';
 then
+            camel_launcher=true
+          fi
+
+          echo "camel-exe=$camel_exe" >> "$GITHUB_OUTPUT"
+          echo "camel-launcher=$camel_launcher" >> "$GITHUB_OUTPUT"
+
+  camel-exe:
+    needs: detect-changes
+    if: github.event_name == 'workflow_dispatch' || 
needs.detect-changes.outputs.camel-exe == 'true'
+    runs-on: windows-2022
+    steps:
+      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # 
v7.0.0
+        with:
+          persist-credentials: false
+      - name: Set up JDK 21
+        uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # 
v5.2.0
+        with:
+          distribution: 'temurin'
+          java-version: '21'
+          cache: 'maven'
+      - name: Build and test native camel.exe
+        shell: cmd
+        run: |
+          for /f "usebackq delims=" %%i in (`"%ProgramFiles(x86)%\Microsoft 
Visual Studio\Installer\vswhere.exe" -latest -products * -requires 
Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) 
do set "VSINSTALL=%%i"
+          call "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat"
+          mvn -B -ntp -pl buildingtools install -DskipTests
+          mvn -B -ntp -pl tooling/camel-exe verify 
-Dcamel.exe.requireWindowsExe=true
+
+  camel-launcher-windows:
+    needs: detect-changes
+    if: github.event_name == 'workflow_dispatch' || 
needs.detect-changes.outputs.camel-launcher == 'true'
+    runs-on: windows-2022
+    steps:
+      - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # 
v7.0.0
+        with:
+          persist-credentials: false
+      - name: Set up JDK 21
+        uses: actions/setup-java@be666c2fcd27ec809703dec50e508c2fdc7f6654 # 
v5.2.0
+        with:
+          distribution: 'temurin'
+          java-version: '21'
+          cache: 'maven'
+      - name: Build launcher with native camel.exe
+        shell: cmd
+        run: |
+          for /f "usebackq delims=" %%i in (`"%ProgramFiles(x86)%\Microsoft 
Visual Studio\Installer\vswhere.exe" -latest -products * -requires 
Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath`) 
do set "VSINSTALL=%%i"
+          call "%VSINSTALL%\VC\Auxiliary\Build\vcvars64.bat"
+          mvn -B -ntp -pl 
buildingtools,tooling/camel-exe,dsl/camel-jbang/camel-launcher -am install 
-DskipTests -Dcamel.launcher.requireWindowsExe=true
+      - name: Assert archive carries bin/camel.exe
+        shell: pwsh
+        run: |
+          $zip = Get-ChildItem 
dsl/camel-jbang/camel-launcher/target/camel-launcher-*-bin.zip | Select-Object 
-First 1
+          Add-Type -AssemblyName System.IO.Compression.FileSystem
+          $archive = [System.IO.Compression.ZipFile]::OpenRead($zip.FullName)
+          try {
+              $names = $archive.Entries.FullName
+              if (-not ($names -like '*/bin/camel.exe')) { throw 'camel.exe 
missing from launcher archive' }
+          } finally {
+              $archive.Dispose()
+          }
diff --git 
a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc 
b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
index 0454ac8a835a..e58517c676e4 100644
--- a/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
+++ b/docs/user-manual/modules/ROOT/pages/camel-4x-upgrade-guide-4_22.adoc
@@ -80,6 +80,14 @@ The Gentoo `java-config` auto-detection and the IBM AIX 
`$JAVA_HOME/jre/sh/java`
 removed; set `JAVA_HOME` or `JAVACMD` explicitly on those platforms.
 `JAVA_OPTS` handling is unchanged: when unset, the default `-Xmx512m` heap is 
applied.
 
+==== Native `camel.exe` in the launcher distribution
+
+The `camel-launcher` Windows distribution now ships a native x64 
`bin/camel.exe`
+alongside `bin/camel.bat`. `camel.exe` is a thin bootstrap: it forwards all
+arguments to the adjacent `camel.bat` (preserving spaces and Unicode) and 
returns
+its exit code. It exists so package managers that require a genuine executable
+users may continue to invoke `bin\camel.bat`; both behave identically.
+
 === camel-langchain4j-agent
 
 The `Agent.chat()` method return type has changed from `String` to 
`Result<String>` (from `dev.langchain4j.service.Result`).
diff --git a/dsl/camel-jbang/camel-launcher/README.md 
b/dsl/camel-jbang/camel-launcher/README.md
index 06e2f1dd63cb..845c8b894fe5 100644
--- a/dsl/camel-jbang/camel-launcher/README.md
+++ b/dsl/camel-jbang/camel-launcher/README.md
@@ -16,6 +16,22 @@ This will create:
 1. A self-executing JAR (`camel-launcher-<version>.jar`) in the `target` 
directory using Spring Boot's nested JAR structure
 2. Distribution archives (`camel-launcher-<version>-bin.zip` and 
`camel-launcher-<version>-bin.tar.gz`) in the `target` directory
 
+On Windows, the distribution archives also include `bin/camel.exe`, a native 
bootstrap built by
+[`tooling/camel-exe`](../../../tooling/camel-exe). Release builds on a Windows 
x64 host run an integration test during `verify` that asserts
+`target/camel.exe` is staged and `bin/camel.exe` is present in the assembled 
ZIP:
+
+```bash
+mvn -pl tooling/camel-exe,dsl/camel-jbang/camel-launcher -am verify 
-Dcamel.launcher.requireWindowsExe=true
+```
+
+To build and test only the native bootstrap:
+
+```bash
+mvn -pl tooling/camel-exe verify -Dcamel.exe.requireWindowsExe=true
+```
+
+See 
[`tooling/camel-exe/src/main/native/README.md`](../../../tooling/camel-exe/src/main/native/README.md)
 for MSVC requirements.
+
 ## Usage
 
 ### Using the JAR directly
@@ -47,8 +63,12 @@ java -jar camel-launcher-<version>.jar run hello.java
    
    # On Windows
    bin\camel.bat [command] [options]
+   bin\camel.exe [command] [options]
    ```
 
+   `camel.exe` and `camel.bat` behave identically on Windows; `camel.exe` 
exists for package managers
+   (such as WinGet) that require a genuine executable command.
+
 ## Benefits
 
 - No need for JBang installation
diff --git a/dsl/camel-jbang/camel-launcher/pom.xml 
b/dsl/camel-jbang/camel-launcher/pom.xml
index 3694faf67e92..6668d00051cd 100644
--- a/dsl/camel-jbang/camel-launcher/pom.xml
+++ b/dsl/camel-jbang/camel-launcher/pom.xml
@@ -325,4 +325,110 @@
             </plugin>
         </plugins>
     </build>
+
+    <profiles>
+        <!--
+            On Windows, copy the native camel.exe artifact from 
tooling/camel-exe into target/
+            so the assembly descriptor can include it in bin/camel.exe.
+        -->
+        <profile>
+            <id>include-camel-exe</id>
+            <activation>
+                <os>
+                    <family>windows</family>
+                </os>
+            </activation>
+            <dependencies>
+                <dependency>
+                    <groupId>org.apache.camel</groupId>
+                    <artifactId>camel-exe</artifactId>
+                    <version>${project.version}</version>
+                    <type>exe</type>
+                </dependency>
+            </dependencies>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-dependency-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>copy-camel-exe</id>
+                                <phase>generate-resources</phase>
+                                <goals>
+                                    <goal>copy</goal>
+                                </goals>
+                                <configuration>
+                                    <artifactItems>
+                                        <artifactItem>
+                                            <groupId>org.apache.camel</groupId>
+                                            <artifactId>camel-exe</artifactId>
+                                            
<version>${project.version}</version>
+                                            <type>exe</type>
+                                            
<outputDirectory>${project.build.directory}</outputDirectory>
+                                            
<destFileName>camel.exe</destFileName>
+                                        </artifactItem>
+                                    </artifactItems>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <!--
+            Release gate: fails the build before packaging if camel.exe was 
not copied into
+            target/. Enabled only when -Dcamel.launcher.requireWindowsExe=true 
(release job on
+            a Windows x64 host), so ordinary cross-platform dev builds are 
unaffected.
+        -->
+        <profile>
+            <id>require-windows-exe</id>
+            <activation>
+                <property>
+                    <name>camel.launcher.requireWindowsExe</name>
+                    <value>true</value>
+                </property>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-enforcer-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>require-camel-exe</id>
+                                <phase>prepare-package</phase>
+                                <goals>
+                                    <goal>enforce</goal>
+                                </goals>
+                                <configuration>
+                                    <rules>
+                                        <requireFilesExist>
+                                            <files>
+                                                
<file>${project.build.directory}/camel.exe</file>
+                                            </files>
+                                        </requireFilesExist>
+                                    </rules>
+                                    <fail>true</fail>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-failsafe-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <goals>
+                                    <goal>integration-test</goal>
+                                    <goal>verify</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
 </project>
diff --git a/dsl/camel-jbang/camel-launcher/src/main/assembly/bin.xml 
b/dsl/camel-jbang/camel-launcher/src/main/assembly/bin.xml
index 32432cac0ccb..7506708d80a9 100644
--- a/dsl/camel-jbang/camel-launcher/src/main/assembly/bin.xml
+++ b/dsl/camel-jbang/camel-launcher/src/main/assembly/bin.xml
@@ -70,5 +70,13 @@
                 <include>*.*</include>
             </includes>
         </fileSet>
+        <fileSet>
+            <directory>${project.build.directory}</directory>
+            <outputDirectory>bin</outputDirectory>
+            <includes>
+                <include>camel.exe</include>
+            </includes>
+            <fileMode>0755</fileMode>
+        </fileSet>
     </fileSets>
 </assembly>
diff --git 
a/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/CamelLauncherWindowsExeIT.java
 
b/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/CamelLauncherWindowsExeIT.java
new file mode 100644
index 000000000000..c2108f78fa20
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-launcher/src/test/java/org/apache/camel/dsl/jbang/launcher/CamelLauncherWindowsExeIT.java
@@ -0,0 +1,77 @@
+/*
+ * 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.dsl.jbang.launcher;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.stream.Stream;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledIfSystemProperty;
+import org.junit.jupiter.api.condition.EnabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Release gate for the native {@code camel.exe} packaged into the launcher 
distribution. Runs during {@code verify}
+ * when {@code -Dcamel.launcher.requireWindowsExe=true} is set on a Windows 
x64 host.
+ */
+@EnabledOnOs(OS.WINDOWS)
+@EnabledIfSystemProperty(named = "camel.launcher.requireWindowsExe", matches = 
"true")
+class CamelLauncherWindowsExeIT {
+
+    private static final Path TARGET = Paths.get("target");
+    private static final Path STAGED_EXE = TARGET.resolve("camel.exe");
+
+    @Test
+    void stagedCamelExeExists() {
+        assertTrue(Files.isRegularFile(STAGED_EXE),
+                "target/camel.exe must be present before packaging the 
launcher distribution");
+    }
+
+    @Test
+    void binArchiveIncludesCamelExe() throws IOException {
+        Path zip = findBinZip();
+        assertNotNull(zip, "camel-launcher-*-bin.zip must be produced by the 
assembly plugin");
+
+        try (ZipFile archive = new ZipFile(zip.toFile())) {
+            // maven-assembly-plugin defaults includeBaseDirectory to true, so 
entries are
+            // nested under camel-launcher-<version>/, not at the archive root.
+            ZipEntry entry = archive.stream()
+                    .filter(e -> e.getName().endsWith("/bin/camel.exe"))
+                    .findFirst()
+                    .orElse(null);
+            assertNotNull(entry, "bin/camel.exe must be included in " + 
zip.getFileName());
+            assertTrue(entry.getSize() > 0, "bin/camel.exe must not be empty");
+        }
+    }
+
+    private static Path findBinZip() throws IOException {
+        try (Stream<Path> paths = Files.list(TARGET)) {
+            return paths
+                    .filter(p -> 
p.getFileName().toString().matches("camel-launcher-.*-bin\\.zip"))
+                    .findFirst()
+                    .orElse(null);
+        }
+    }
+}
diff --git a/tooling/camel-exe/README.md b/tooling/camel-exe/README.md
new file mode 100644
index 000000000000..390463492995
--- /dev/null
+++ b/tooling/camel-exe/README.md
@@ -0,0 +1,45 @@
+# Camel :: Exe
+
+Standalone Maven module that builds the native Windows **`camel.exe`** 
bootstrap for the
+[Camel CLI launcher](../../dsl/camel-jbang/camel-launcher).
+
+## Purpose
+
+WinGet's portable installer (and similar package managers) require a genuine 
executable as
+the `camel` command. A `.bat` or `.cmd` shim is not enough — it produces a 
broken
+`camel.exe` symlink. This module compiles a minimal x64 native binary that 
satisfies that
+contract.
+
+`camel.exe` does not embed Java or run Camel itself. It locates `camel.bat` in 
the same
+directory, forwards the caller's command line (preserving spaces and Unicode), 
and returns
+its exit code. All Java discovery and CLI parsing remain in `camel.bat` and 
the launcher
+JAR.
+
+## Why a separate module?
+
+The launcher (`dsl/camel-jbang/camel-launcher`) is a fat JAR with a large 
upstream
+dependency tree (jbang core, plugins, repackager, and their transitive Camel 
deps). The
+native bootstrap is ~100 lines of C with **no Java dependencies**. Keeping it 
here allows:
+
+- **Fast Windows CI** — `mvn -pl tooling/camel-exe verify` compiles and tests 
the exe
+  without building the full jbang graph.
+- **Clear separation** — packaging bootstrap vs. runtime launcher.
+- **Reusable artifact** — `camel-launcher` copies the attached `exe` artifact 
into its
+  distribution on Windows (`bin/camel.exe` inside `camel-launcher-*-bin.zip`).
+
+## Build and test
+
+On a Windows x64 host with Microsoft C/C++ Build Tools (`cl.exe`) on PATH:
+
+```bash
+mvn -pl tooling/camel-exe verify -Dcamel.exe.requireWindowsExe=true
+```
+
+Release and integration builds that produce the launcher ZIP also build this 
module first:
+
+```bash
+mvn -pl tooling/camel-exe,dsl/camel-jbang/camel-launcher -am verify 
-Dcamel.launcher.requireWindowsExe=true
+```
+
+See [src/main/native/README.md](src/main/native/README.md) for MSVC setup, 
compiler
+flags, and the release-gate profile.
diff --git a/tooling/camel-exe/pom.xml b/tooling/camel-exe/pom.xml
new file mode 100644
index 000000000000..f05e18ea80f5
--- /dev/null
+++ b/tooling/camel-exe/pom.xml
@@ -0,0 +1,214 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    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.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.camel</groupId>
+        <artifactId>tooling</artifactId>
+        <version>4.22.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-exe</artifactId>
+    <packaging>pom</packaging>
+
+    <name>Camel :: Exe</name>
+    <description>Native Windows camel.exe bootstrap for the Camel CLI 
launcher</description>
+
+    <properties>
+        <camel-prepare-component>false</camel-prepare-component>
+        <label>tooling</label>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <!--
+        POM packaging is used because the main artifact is a native .exe, not 
a jar.
+        The test plugins below are wired manually so that 
CamelExeBootstrapTest (Java,
+        Windows-only) runs during the standard 'mvn verify' lifecycle.
+    -->
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.codehaus.mojo</groupId>
+                <artifactId>build-helper-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>add-test-source</id>
+                        <phase>generate-test-sources</phase>
+                        <goals>
+                            <goal>add-test-source</goal>
+                        </goals>
+                        <configuration>
+                            <sources>
+                                <source>src/test/java</source>
+                            </sources>
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>default-testCompile</id>
+                        <phase>test-compile</phase>
+                        <goals>
+                            <goal>testCompile</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>default-test</id>
+                        <phase>test</phase>
+                        <goals>
+                            <goal>test</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <profiles>
+        <!--
+            Compiles the native x64 camel.exe bootstrap with the Microsoft 
C/C++ Build Tools.
+            Activates automatically on Windows; requires cl.exe on PATH (run 
from a developer
+            command prompt / after vcvars64.bat). Non-Windows builds skip this 
and omit camel.exe.
+        -->
+        <profile>
+            <id>build-windows-exe</id>
+            <activation>
+                <os>
+                    <family>windows</family>
+                </os>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>exec-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>compile-camel-exe</id>
+                                <phase>generate-test-resources</phase>
+                                <goals>
+                                    <goal>exec</goal>
+                                </goals>
+                                <configuration>
+                                    <executable>cl.exe</executable>
+                                    <arguments>
+                                        <argument>/nologo</argument>
+                                        <argument>/W4</argument>
+                                        <argument>/O1</argument>
+                                        <argument>/MT</argument>
+                                        <argument>/Brepro</argument>
+                                        
<argument>/Fe:${project.build.directory}\camel.exe</argument>
+                                        
<argument>/Fo:${project.build.directory}\camel.obj</argument>
+                                        
<argument>${project.basedir}\src\main\native\camel.c</argument>
+                                        <argument>/link</argument>
+                                        <argument>/Brepro</argument>
+                                        <argument>/SUBSYSTEM:CONSOLE</argument>
+                                    </arguments>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.codehaus.mojo</groupId>
+                        <artifactId>build-helper-maven-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>attach-camel-exe</id>
+                                <phase>package</phase>
+                                <goals>
+                                    <goal>attach-artifact</goal>
+                                </goals>
+                                <configuration>
+                                    <artifacts>
+                                        <artifact>
+                                            
<file>${project.build.directory}/camel.exe</file>
+                                            <type>exe</type>
+                                        </artifact>
+                                    </artifacts>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <!--
+            Release gate: fails the build before packaging if the native 
camel.exe was not
+            produced. Enabled only when -Dcamel.exe.requireWindowsExe=true 
(release job on
+            a Windows x64 host), so ordinary cross-platform dev builds are 
unaffected.
+        -->
+        <profile>
+            <id>require-windows-exe</id>
+            <activation>
+                <property>
+                    <name>camel.exe.requireWindowsExe</name>
+                    <value>true</value>
+                </property>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-enforcer-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>require-camel-exe</id>
+                                <phase>prepare-package</phase>
+                                <goals>
+                                    <goal>enforce</goal>
+                                </goals>
+                                <configuration>
+                                    <rules>
+                                        <requireFilesExist>
+                                            <files>
+                                                
<file>${project.build.directory}/camel.exe</file>
+                                            </files>
+                                        </requireFilesExist>
+                                    </rules>
+                                    <fail>true</fail>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>
+</project>
diff --git a/tooling/camel-exe/src/main/native/README.md 
b/tooling/camel-exe/src/main/native/README.md
new file mode 100644
index 000000000000..506b2bde8c71
--- /dev/null
+++ b/tooling/camel-exe/src/main/native/README.md
@@ -0,0 +1,26 @@
+# Native build (`camel.c`)
+
+Compiler flags, MSVC setup, and release-gate details for the `camel.exe` 
bootstrap.
+See the [module README](../../../README.md) for purpose, architecture, and 
integration
+with `camel-launcher`.
+
+## MSVC setup
+
+The `build-windows-exe` Maven profile activates automatically on Windows and 
invokes
+`cl.exe`. MSVC must be on PATH — open a developer command prompt (e.g. run
+`vcvars64.bat`) or provision MSVC in CI before running Maven.
+
+## Compiler invocation
+
+    cl /nologo /W4 /O1 /MT /Brepro /Fe:target\camel.exe 
src\main\native\camel.c /link /Brepro /SUBSYSTEM:CONSOLE
+
+- `/MT` — static CRT (no runtime DLL dependency)
+- `/Brepro` — deterministic PE header timestamp on both compiler and linker, so
+  repeated builds from the same source produce byte-identical output
+
+## Release gate
+
+Release builds pass `-Dcamel.exe.requireWindowsExe=true`, which activates the
+`require-windows-exe` profile. The enforcer fails the build if 
`target/camel.exe` is
+absent. Because MSVC cannot cross-compile from macOS/Linux, the launcher 
ZIP/TAR that
+carries `camel.exe` must be assembled on a Windows x64 host.
diff --git a/tooling/camel-exe/src/main/native/camel.c 
b/tooling/camel-exe/src/main/native/camel.c
new file mode 100644
index 000000000000..8f77121d1046
--- /dev/null
+++ b/tooling/camel-exe/src/main/native/camel.c
@@ -0,0 +1,146 @@
+/**
+ * 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.
+ */
+/*
+ * camel.exe - minimal WinGet-compatible bootstrap for the Camel CLI launcher.
+ *
+ * It locates the camel.bat sitting in the same directory, forwards the 
caller's
+ * exact command-line tail (preserving Unicode and Windows quoting), inherits 
the
+ * standard streams, and returns the child process exit code. It performs NO 
Java
+ * discovery and NO Camel option parsing; that all lives in camel.bat.
+ */
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+
+/* Return the command-line tail after argv[0], preserving the caller's 
quoting. */
+static LPWSTR skip_argv0(LPWSTR cmd) {
+    LPWSTR p = cmd;
+    if (*p == L'"') {
+        p++;
+        while (*p && *p != L'"') {
+            p++;
+        }
+        if (*p == L'"') {
+            p++;
+        }
+    } else {
+        while (*p && *p != L' ' && *p != L'\t') {
+            p++;
+        }
+    }
+    while (*p == L' ' || *p == L'\t') {
+        p++;
+    }
+    return p;
+}
+
+/*
+ * Return a heap-allocated wide string holding the directory that contains this
+ * exe, or NULL on failure. The caller must free() the result. Uses a doubling
+ * loop so paths beyond MAX_PATH (260) work on Windows 10+ with long-path
+ * support enabled.
+ */
+static wchar_t *get_exe_dir(void) {
+    DWORD bufSize = MAX_PATH;
+    wchar_t *buf = (wchar_t *) malloc(bufSize * sizeof(wchar_t));
+    if (buf == NULL) {
+        return NULL;
+    }
+    for (;;) {
+        DWORD n = GetModuleFileNameW(NULL, buf, bufSize);
+        if (n == 0) {
+            free(buf);
+            return NULL;
+        }
+        if (n < bufSize) {
+            break;
+        }
+        bufSize *= 2;
+        wchar_t *tmp = (wchar_t *) realloc(buf, bufSize * sizeof(wchar_t));
+        if (tmp == NULL) {
+            free(buf);
+            return NULL;
+        }
+        buf = tmp;
+    }
+    wchar_t *slash = wcsrchr(buf, L'\\');
+    if (slash == NULL) {
+        free(buf);
+        return NULL;
+    }
+    *slash = L'\0';
+    return buf;
+}
+
+int wmain(void) {
+    wchar_t *exePath = get_exe_dir();
+    if (exePath == NULL) {
+        fwprintf(stderr, L"camel: cannot resolve launcher directory\n");
+        return 1;
+    }
+
+    LPWSTR tail = skip_argv0(GetCommandLineW());
+
+    /*
+     * cmd.exe /S /C ""<dir>\camel.bat" <tail>"
+     * With /S and a command wrapped in an outer pair of quotes, cmd strips the
+     * first and last quote and executes the remainder verbatim, so the inner
+     * quotes around the (possibly spaced/Unicode) camel.bat path survive.
+     */
+    size_t cap = wcslen(exePath) + wcslen(tail) + 64;
+    LPWSTR cmdline = (LPWSTR) malloc(cap * sizeof(wchar_t));
+    if (cmdline == NULL) {
+        fwprintf(stderr, L"camel: out of memory\n");
+        free(exePath);
+        return 1;
+    }
+    int ret = _snwprintf_s(cmdline, cap, _TRUNCATE,
+                           L"cmd.exe /S /C \"\"%s\\camel.bat\" %s\"", exePath, 
tail);
+    if (ret == -1) {
+        fwprintf(stderr, L"camel: command line was truncated\n");
+        free(cmdline);
+        free(exePath);
+        return 1;
+    }
+
+    STARTUPINFOW si;
+    PROCESS_INFORMATION pi;
+    ZeroMemory(&si, sizeof(si));
+    si.cb = sizeof(si);
+    ZeroMemory(&pi, sizeof(pi));
+
+    /* bInheritHandles=TRUE and no STARTF_USESTDHANDLES: child shares our 
console. */
+    if (!CreateProcessW(NULL, cmdline, NULL, NULL, TRUE, 0, NULL, NULL, &si, 
&pi)) {
+        fwprintf(stderr, L"camel: failed to start camel.bat (error %lu)\n", 
GetLastError());
+        free(cmdline);
+        free(exePath);
+        return 1;
+    }
+
+    WaitForSingleObject(pi.hProcess, INFINITE);
+    DWORD code = 1;
+    if (!GetExitCodeProcess(pi.hProcess, &code)) {
+        fwprintf(stderr, L"camel: failed to get exit code (error %lu)\n", 
GetLastError());
+    }
+    CloseHandle(pi.hProcess);
+    CloseHandle(pi.hThread);
+    free(cmdline);
+    free(exePath);
+    return (int) code;
+}
diff --git 
a/tooling/camel-exe/src/test/java/org/apache/camel/tooling/exe/CamelExeBootstrapTest.java
 
b/tooling/camel-exe/src/test/java/org/apache/camel/tooling/exe/CamelExeBootstrapTest.java
new file mode 100644
index 000000000000..3171012393c3
--- /dev/null
+++ 
b/tooling/camel-exe/src/test/java/org/apache/camel/tooling/exe/CamelExeBootstrapTest.java
@@ -0,0 +1,217 @@
+/*
+ * 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.tooling.exe;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+import org.junit.jupiter.api.io.TempDir;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+/**
+ * Windows-only behavioral test for the native camel.exe bootstrap. Requires 
the build-windows-exe profile to have
+ * produced target/camel.exe; the test fails loudly if it is missing so a 
broken native build does not pass silently.
+ */
+@EnabledOnOs(OS.WINDOWS)
+class CamelExeBootstrapTest {
+
+    private static final Path BUILT_EXE = Paths.get("target/camel.exe");
+    private static final String CAPTURED_ARGS_FILE = "camel-args.txt";
+    private static final String CAPTURE_ARGS_SCRIPT = "capture-arg.ps1";
+
+    /** Writes a fake camel.bat that echoes each argument on its own line and 
returns exitCode. */
+    private Path fakeBat(Path dir, int exitCode) throws Exception {
+        Path bat = dir.resolve("camel.bat");
+        String body = "@echo off\r\n"
+                      + ":loop\r\n"
+                      + "if \"%~1\"==\"\" goto done\r\n"
+                      + "echo ARG=%~1\r\n"
+                      + "shift\r\n"
+                      + "goto loop\r\n"
+                      + ":done\r\n"
+                      + "exit /b " + exitCode + "\r\n";
+        Files.writeString(bat, body, StandardCharsets.UTF_8);
+        return bat;
+    }
+
+    /**
+     * Writes a fake camel.bat that appends each forwarded argument to {@link 
#CAPTURED_ARGS_FILE} as UTF-8.
+     * <p>
+     * Non-ASCII argument checks cannot rely on parsing process stdout: 
cmd.exe {@code echo} uses the console OEM code
+     * page on Windows CI hosts, so Unicode forwarded correctly by camel.exe 
is still mangled (for example {@code ü}
+     * becomes {@code ?}) before Java reads the pipe. We therefore capture 
arguments in a UTF-8 file via a helper
+     * PowerShell script. The batch file passes all arguments at once using 
{@code %*} (the raw command-line tail)
+     * rather than iterating with {@code %~1}, because per-argument expansion 
through cmd.exe's batch variable
+     * substitution can corrupt non-ASCII characters on certain OEM code pages.
+     */
+    private void fakeBatCapturingArgsToUtf8File(Path dir, int exitCode) throws 
Exception {
+        Path captureScript = dir.resolve(CAPTURE_ARGS_SCRIPT);
+        String ps1 = "$outFile = $args[0]\r\n"
+                     + "for ($i = 1; $i -lt $args.Count; $i++) {\r\n"
+                     + "    [System.IO.File]::AppendAllText($outFile,\r\n"
+                     + "        $args[$i] + [Environment]::NewLine,\r\n"
+                     + "        [System.Text.UTF8Encoding]::new($false))\r\n"
+                     + "}\r\n"
+                     + "exit " + exitCode + "\r\n";
+        Files.writeString(captureScript, ps1, StandardCharsets.UTF_8);
+
+        Path bat = dir.resolve("camel.bat");
+        String body = "@powershell -NoProfile -ExecutionPolicy Bypass -File 
\"%~dp0" + CAPTURE_ARGS_SCRIPT + "\" "
+                      + "\"%~dp0" + CAPTURED_ARGS_FILE + "\" %*\r\n"
+                      + "@exit /b %ERRORLEVEL%\r\n";
+        Files.writeString(bat, body, StandardCharsets.UTF_8);
+    }
+
+    private List<String> readCapturedArgs(Path dir) throws Exception {
+        Path file = dir.resolve(CAPTURED_ARGS_FILE);
+        if (!Files.exists(file)) {
+            return List.of();
+        }
+        return Files.readAllLines(file, StandardCharsets.UTF_8);
+    }
+
+    private Path stagedExe(Path dir) throws Exception {
+        assertTrue(Files.exists(BUILT_EXE),
+                "target/camel.exe must be built by the build-windows-exe 
profile before this test");
+        Path exe = dir.resolve("camel.exe");
+        Files.copy(BUILT_EXE, exe);
+        return exe;
+    }
+
+    private static final class Result {
+        int exit;
+        String stdout;
+    }
+
+    private Result run(Path exe, String... args) throws Exception {
+        List<String> cmd = new ArrayList<>();
+        cmd.add(exe.toString());
+        for (String a : args) {
+            cmd.add(a);
+        }
+        ProcessBuilder pb = new ProcessBuilder(cmd);
+        pb.redirectErrorStream(true);
+        Process p = pb.start();
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        // Drain stdout on a background thread: reading it inline would block 
until the pipe closes
+        // at process exit, making the waitFor timeout below unreachable if 
camel.exe hangs.
+        Thread drain = new Thread(() -> {
+            try {
+                p.getInputStream().transferTo(out);
+            } catch (IOException e) {
+                // stream closes abruptly when the process is destroyed on 
timeout below
+            }
+        });
+        drain.start();
+        try {
+            boolean exited = p.waitFor(60, TimeUnit.SECONDS);
+            if (!exited) {
+                p.destroyForcibly();
+            }
+            assertTrue(exited, "camel.exe did not exit in time");
+            drain.join(TimeUnit.SECONDS.toMillis(5));
+            Result r = new Result();
+            r.exit = p.exitValue();
+            r.stdout = out.toString(StandardCharsets.UTF_8);
+            return r;
+        } finally {
+            if (p.isAlive()) {
+                p.destroyForcibly();
+            }
+        }
+    }
+
+    @Test
+    void forwardsArgumentsToAdjacentCamelBat(@TempDir Path dir) throws 
Exception {
+        fakeBat(dir, 0);
+        Path exe = stagedExe(dir);
+
+        Result r = run(exe, "version");
+
+        assertEquals(0, r.exit);
+        assertTrue(r.stdout.contains("ARG=version"), r.stdout);
+    }
+
+    @Test
+    void preservesArgumentWithSpaces(@TempDir Path dir) throws Exception {
+        fakeBat(dir, 0);
+        Path exe = stagedExe(dir);
+
+        Result r = run(exe, "run", "my route.yaml");
+
+        assertTrue(r.stdout.contains("ARG=run"), r.stdout);
+        assertTrue(r.stdout.contains("ARG=my route.yaml"), "spaced argument 
must survive as one token: " + r.stdout);
+    }
+
+    @Test
+    void preservesUnicodeArgument(@TempDir Path dir) throws Exception {
+        fakeBatCapturingArgsToUtf8File(dir, 0);
+        Path exe = stagedExe(dir);
+
+        Result r = run(exe, "run", "rüte-über.yaml");
+
+        assertEquals(0, r.exit);
+        List<String> captured = readCapturedArgs(dir);
+        assertTrue(captured.contains("run"), captured.toString());
+        assertTrue(captured.contains("rüte-über.yaml"), "Unicode argument must 
survive: " + captured);
+    }
+
+    @Test
+    void propagatesChildExitCode(@TempDir Path dir) throws Exception {
+        fakeBat(dir, 42);
+        Path exe = stagedExe(dir);
+
+        Result r = run(exe, "version");
+
+        assertEquals(42, r.exit, "camel.exe must return camel.bat's exit 
code");
+    }
+
+    @Test
+    void worksWhenExeDirectoryHasSpaces(@TempDir Path base) throws Exception {
+        Path dir = base.resolve("Program Files X");
+        Files.createDirectories(dir);
+        fakeBat(dir, 0);
+        Path exe = stagedExe(dir);
+
+        Result r = run(exe, "version");
+
+        assertEquals(0, r.exit, r.stdout);
+        assertTrue(r.stdout.contains("ARG=version"), r.stdout);
+    }
+
+    @Test
+    void failsGracefullyWhenCamelBatIsMissing(@TempDir Path dir) throws 
Exception {
+        Path exe = stagedExe(dir);
+
+        Result r = run(exe, "version");
+
+        assertTrue(r.exit != 0, "exit code must be non-zero when camel.bat is 
missing");
+        assertTrue(r.stdout.length() > 0, "error message must be present in 
output");
+    }
+}
diff --git 
a/tooling/maven/camel-repackager-maven-plugin/src/main/java/org/apache/camel/maven/RepackageMojo.java
 
b/tooling/maven/camel-repackager-maven-plugin/src/main/java/org/apache/camel/maven/RepackageMojo.java
index 3ffeec345ba4..3c2bab83feac 100644
--- 
a/tooling/maven/camel-repackager-maven-plugin/src/main/java/org/apache/camel/maven/RepackageMojo.java
+++ 
b/tooling/maven/camel-repackager-maven-plugin/src/main/java/org/apache/camel/maven/RepackageMojo.java
@@ -129,7 +129,13 @@ public class RepackageMojo extends AbstractMojo {
         }
     }
 
-    private boolean includeArtifact(Artifact artifact) {
+    boolean includeArtifact(Artifact artifact) {
+        // Only jar-type artifacts are valid Spring Boot loader libraries. 
Non-jar artifacts
+        // (e.g. the native camel-exe:exe bootstrap, which camel-launcher 
depends on purely to
+        // stage bin/camel.exe via the assembly descriptor) must never be 
embedded in BOOT-INF/lib.
+        if (!"jar".equals(artifact.getType())) {
+            return false;
+        }
         String scope = artifact.getScope();
         // Include compile and runtime dependencies
         return Artifact.SCOPE_COMPILE.equals(scope) ||
diff --git 
a/tooling/maven/camel-repackager-maven-plugin/src/test/java/org/apache/camel/maven/RepackageMojoTest.java
 
b/tooling/maven/camel-repackager-maven-plugin/src/test/java/org/apache/camel/maven/RepackageMojoTest.java
index 279a8aeab423..329a43d57197 100644
--- 
a/tooling/maven/camel-repackager-maven-plugin/src/test/java/org/apache/camel/maven/RepackageMojoTest.java
+++ 
b/tooling/maven/camel-repackager-maven-plugin/src/test/java/org/apache/camel/maven/RepackageMojoTest.java
@@ -18,6 +18,9 @@ package org.apache.camel.maven;
 
 import java.io.File;
 
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DefaultArtifact;
+import org.apache.maven.artifact.handler.DefaultArtifactHandler;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.io.TempDir;
 
@@ -61,4 +64,46 @@ public class RepackageMojoTest {
 
         assertTrue(true, "Placeholder test - would verify dependency 
inclusion");
     }
+
+    @Test
+    public void testCompileScopedJarIsIncluded() {
+        RepackageMojo mojo = new RepackageMojo();
+        Artifact artifact = artifact("org.apache.camel", "camel-jbang-core", 
"jar", Artifact.SCOPE_COMPILE);
+
+        assertTrue(mojo.includeArtifact(artifact),
+                "a compile-scoped jar dependency must be bundled into 
BOOT-INF/lib");
+    }
+
+    @Test
+    public void testNonJarArtifactIsExcludedEvenWhenCompileScoped() {
+        // camel-launcher depends on camel-exe:exe purely so the assembly 
descriptor can stage
+        // bin/camel.exe; it must never end up embedded as a Spring Boot 
loader library.
+        RepackageMojo mojo = new RepackageMojo();
+        Artifact artifact = artifact("org.apache.camel", "camel-exe", "exe", 
Artifact.SCOPE_COMPILE);
+
+        assertFalse(mojo.includeArtifact(artifact),
+                "a non-jar artifact (e.g. the native camel-exe:exe bootstrap) 
must not be bundled into BOOT-INF/lib");
+    }
+
+    @Test
+    public void testProvidedCamelJarIsIncluded() {
+        RepackageMojo mojo = new RepackageMojo();
+        Artifact artifact = artifact("org.apache.camel", "camel-util", "jar", 
Artifact.SCOPE_PROVIDED);
+
+        assertTrue(mojo.includeArtifact(artifact),
+                "a provided-scope org.apache.camel jar dependency must still 
be bundled");
+    }
+
+    @Test
+    public void testProvidedNonCamelJarIsExcluded() {
+        RepackageMojo mojo = new RepackageMojo();
+        Artifact artifact = artifact("org.jolokia", "jolokia-agent-jvm", 
"jar", Artifact.SCOPE_PROVIDED);
+
+        assertFalse(mojo.includeArtifact(artifact),
+                "a provided-scope non-Camel jar dependency must not be 
bundled");
+    }
+
+    private static Artifact artifact(String groupId, String artifactId, String 
type, String scope) {
+        return new DefaultArtifact(groupId, artifactId, "1.0", scope, type, 
null, new DefaultArtifactHandler(type));
+    }
 }
diff --git a/tooling/pom.xml b/tooling/pom.xml
index 16fbb6fe64e4..282288030da4 100644
--- a/tooling/pom.xml
+++ b/tooling/pom.xml
@@ -42,6 +42,7 @@
 
     <modules>
         <module>parent</module>
+        <module>camel-exe</module>
         <module>spi-annotations</module>
         <module>camel-tooling-model</module>
         <module>camel-util-json</module>

Reply via email to