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 b8e356ce61fd CAMEL-24727: camel-jbang-export - an exporter holds the 
export request instead of extending it, and the exporters are internal (#28738)
b8e356ce61fd is described below

commit b8e356ce61fdd8c371d51b3c49eb744d500b7b2a
Author: Claus Ibsen <[email protected]>
AuthorDate: Fri Oct 30 19:46:21 2026 +0100

    CAMEL-24727: camel-jbang-export - an exporter holds the export request 
instead of extending it, and the exporters are internal (#28738)
    
    Signed-off-by: Claus Ibsen <[email protected]>
    Co-Authored-By: Claude Opus 5.5 <[email protected]>
---
 .../dsl/jbang/core/commands/ExportBaseCommand.java |  13 +-
 .../apache/camel/dsl/jbang/core/commands/Run.java  |  13 +-
 .../camel/dsl/jbang/export/CamelMainExporter.java  |  86 +++---
 .../apache/camel/dsl/jbang/export/Exporter.java    | 307 ++++++---------------
 .../camel/dsl/jbang/export/ProjectExporter.java    |   2 +-
 .../camel/dsl/jbang/export/QuarkusExporter.java    |  94 +++----
 .../camel/dsl/jbang/export/SpringBootExporter.java | 115 ++++----
 .../dsl/jbang/export/common/ExportHelper.java      | 148 ++++++++++
 .../core/commands/kubernetes/KubernetesExport.java |   7 +-
 9 files changed, 397 insertions(+), 388 deletions(-)

diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
index 58fa300b7443..6d07a81d6347 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportBaseCommand.java
@@ -35,8 +35,8 @@ import 
org.apache.camel.dsl.jbang.core.common.RuntimeCompletionCandidates;
 import org.apache.camel.dsl.jbang.core.common.RuntimeTypeConverter;
 import org.apache.camel.dsl.jbang.export.ExportContext;
 import org.apache.camel.dsl.jbang.export.ExportRequest;
-import org.apache.camel.dsl.jbang.export.Exporter;
 import org.apache.camel.dsl.jbang.export.ProjectExporter;
+import org.apache.camel.dsl.jbang.export.common.ExportHelper;
 import org.apache.camel.dsl.jbang.export.common.HawtioVersion;
 import org.apache.camel.dsl.jbang.export.common.MavenResolver;
 import org.apache.camel.dsl.jbang.export.common.Printer;
@@ -373,7 +373,7 @@ public abstract class ExportBaseCommand extends 
CamelCommand {
      * --clean-dir.
      */
     static boolean isCurrentDirOrParent(String dir) {
-        return Exporter.isCurrentDirOrParent(dir);
+        return ExportHelper.isCurrentDirOrParent(dir);
     }
 
     /**
@@ -384,12 +384,7 @@ public abstract class ExportBaseCommand extends 
CamelCommand {
         ExportRequest request = toRequest();
         request.exportBaseDir = exportBaseDir;
         applySystemProperties(request);
-        Exporter exporter = new 
ProjectExporter(exportContext()).createExporter(request);
-        if (exporter == null) {
-            printer().printErr("Unknown runtime: " + runtime);
-            return 1;
-        }
-        return exporter.export();
+        return new ProjectExporter(exportContext()).export(exportBaseDir, 
request);
     }
 
     /**
@@ -415,7 +410,7 @@ public abstract class ExportBaseCommand extends 
CamelCommand {
     }
 
     public Comparator<MavenGav> mavenGavComparator() {
-        return Exporter.mavenGavComparator();
+        return ExportHelper.mavenGavComparator();
     }
 
     /**
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
index f479e65ce187..b124b4292f94 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java
@@ -63,10 +63,8 @@ import 
org.apache.camel.dsl.jbang.core.common.ProfileCompletionCandidates;
 import org.apache.camel.dsl.jbang.core.common.RunRuntimeCompletionCandidates;
 import org.apache.camel.dsl.jbang.core.common.RunRuntimeTypeConverter;
 import org.apache.camel.dsl.jbang.core.common.TerminalWidthHelper;
-import org.apache.camel.dsl.jbang.export.CamelMainExporter;
 import org.apache.camel.dsl.jbang.export.ExportRequest;
-import org.apache.camel.dsl.jbang.export.QuarkusExporter;
-import org.apache.camel.dsl.jbang.export.SpringBootExporter;
+import org.apache.camel.dsl.jbang.export.ProjectExporter;
 import org.apache.camel.dsl.jbang.export.common.ExportHelper;
 import org.apache.camel.dsl.jbang.export.common.Printer;
 import org.apache.camel.dsl.jbang.export.common.RuntimeType;
@@ -1026,7 +1024,8 @@ public class Run extends CamelCommand {
 
         // run export
         ExportBaseCommand.applySystemProperties(eq);
-        int exit = new QuarkusExporter(eq, CliExportContext.create(getMain(), 
getMain().getOut(), eq.yes)).export();
+        int exit = new ProjectExporter(CliExportContext.create(getMain(), 
getMain().getOut(), eq.yes))
+                .export(eq.exportBaseDir, eq);
         if (exit != 0) {
             return exit;
         }
@@ -1188,7 +1187,8 @@ public class Run extends CamelCommand {
 
         // run export
         ExportBaseCommand.applySystemProperties(eq);
-        int exit = new CamelMainExporter(eq, 
CliExportContext.create(getMain(), getMain().getOut(), eq.yes)).export();
+        int exit = new ProjectExporter(CliExportContext.create(getMain(), 
getMain().getOut(), eq.yes))
+                .export(eq.exportBaseDir, eq);
         if (exit != 0) {
             return exit;
         }
@@ -1824,7 +1824,8 @@ public class Run extends CamelCommand {
 
         // run export
         ExportBaseCommand.applySystemProperties(eq);
-        int exit = new SpringBootExporter(eq, 
CliExportContext.create(getMain(), getMain().getOut(), eq.yes)).export();
+        int exit = new ProjectExporter(CliExportContext.create(getMain(), 
getMain().getOut(), eq.yes))
+                .export(eq.exportBaseDir, eq);
         if (exit != 0) {
             return exit;
         }
diff --git 
a/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/CamelMainExporter.java
 
b/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/CamelMainExporter.java
index e2c964c235c8..345d50293c6e 100644
--- 
a/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/CamelMainExporter.java
+++ 
b/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/CamelMainExporter.java
@@ -46,39 +46,39 @@ import static 
org.apache.camel.dsl.jbang.export.common.ExportHelper.exportPackag
 /**
  * Exports to a Camel Main Maven project.
  */
-public class CamelMainExporter extends Exporter {
+class CamelMainExporter extends Exporter {
 
-    public CamelMainExporter(ExportRequest request, ExportContext context) {
+    CamelMainExporter(ExportRequest request, ExportContext context) {
         super(request, context);
-        if (pomTemplateName == null) {
-            pomTemplateName = "main-pom.ftl";
+        if (this.request.pomTemplateName == null) {
+            this.request.pomTemplateName = "main-pom.ftl";
         }
     }
 
     @Override
     public Integer export() throws Exception {
         try {
-            MavenGav.parseStrictGav(gav);
+            MavenGav.parseStrictGav(request.gav);
         } catch (IllegalArgumentException e) {
             printer().printErr("--gav must be in syntax: 
groupId:artifactId:version");
             return 1;
         }
-        if (parentPom != null) {
+        if (request.parentPom != null) {
             try {
-                MavenGav.parseStrictGav(parentPom);
+                MavenGav.parseStrictGav(request.parentPom);
             } catch (IllegalArgumentException e) {
                 printer().printErr("--parent-pom must be in syntax: 
groupId:artifactId:version");
                 return 1;
             }
         }
-        String[] ids = gav.split(":");
+        String[] ids = request.gav.split(":");
 
         // the settings file has information what to export
         Path settings = runSettingsFile();
-        if (mavenResolver.fresh() || !files.isEmpty() || 
!Files.exists(settings)) {
+        if (request.mavenResolver.fresh() || !request.files.isEmpty() || 
!Files.exists(settings)) {
             // allow to automatic build
             printer().println("Generating fresh run data");
-            int silent = runSilently(ignoreLoadingError, lazyBean, verbose);
+            int silent = runSilently(request.ignoreLoadingError, 
request.lazyBean, request.verbose);
             if (silent != 0) {
                 return silent;
             }
@@ -86,10 +86,10 @@ public class CamelMainExporter extends Exporter {
             printer().println("Reusing existing run data");
         }
 
-        printer().println("Exporting as Camel Main project to: " + exportDir);
+        printer().println("Exporting as Camel Main project to: " + 
request.exportDir);
 
-        exportBaseDir = exportBaseDir != null ? exportBaseDir : Path.of(".");
-        Path profile = exportBaseDir.resolve("application.properties");
+        request.exportBaseDir = request.exportBaseDir != null ? 
request.exportBaseDir : Path.of(".");
+        Path profile = request.exportBaseDir.resolve("application.properties");
 
         // use a temporary work dir
         Path buildDir = buildDir();
@@ -101,7 +101,7 @@ public class CamelMainExporter extends Exporter {
 
         // compute source folders
         Path srcJavaDirRoot = buildDir.resolve("src/main/java");
-        String srcPackageName = exportPackageName(ids[0], ids[1], packageName);
+        String srcPackageName = exportPackageName(ids[0], ids[1], 
request.packageName);
         Path srcJavaDir;
         if (srcPackageName == null) {
             srcJavaDir = srcJavaDirRoot;
@@ -124,7 +124,7 @@ public class CamelMainExporter extends Exporter {
         Map<String, String> devProfile = new LinkedHashMap<>();
         copySettingsAndProfile(settings, profile,
                 srcResourcesDir, prop -> {
-                    if (groovyPrecompiled && 
!prop.containsKey("camel.main.groovyPreloadCompiled")) {
+                    if (request.groovyPrecompiled && 
!prop.containsKey("camel.main.groovyPreloadCompiled")) {
                         prop.put("camel.main.groovyPreloadCompiled", "true");
                     }
                     if (!prop.containsKey("camel.main.basePackageScan")
@@ -147,7 +147,7 @@ public class CamelMainExporter extends Exporter {
                             prop.put("camel.server.port", port);
                         }
                         if 
(!prop.containsKey("camel.server.health-check-enabled")) {
-                            if (VersionHelper.isGE(camelVersion, "4.14.0")) {
+                            if (VersionHelper.isGE(request.camelVersion, 
"4.14.0")) {
                                 prop.put("camel.management.enabled", "true");
                                 
prop.put("camel.management.health-check-enabled", "true");
                             } else {
@@ -156,7 +156,7 @@ public class CamelMainExporter extends Exporter {
                             }
                         }
                     }
-                    port = httpManagementPort(settings);
+                    port = ExportHelper.httpManagementPort(settings);
                     if (port != -1) {
                         prop.put("camel.management.enabled", "true");
                         prop.put("camel.management.port", port);
@@ -176,11 +176,11 @@ public class CamelMainExporter extends Exporter {
                 });
         writeDevProfileProperties(srcResourcesDir, devProfile);
         // create main class
-        createMainClassSource(srcJavaDir, srcPackageName, mainClassname);
+        createMainClassSource(srcJavaDir, srcPackageName, 
request.mainClassname);
         // copy local lib JARs
         copyLocalLibDependencies(deps);
         // copy local lib JARs
-        if (groovyPrecompiled) {
+        if (request.groovyPrecompiled) {
             copyGroovyPrecompiled(srcResourcesDir);
         }
         // copy agent JARs and remove as dependency
@@ -188,62 +188,62 @@ public class CamelMainExporter extends Exporter {
         deps.removeIf(d -> d.startsWith("agent:"));
         createMavenPom(settings, profile,
                 buildDir.resolve("pom.xml"), deps, srcPackageName);
-        if (mavenWrapper) {
+        if (request.mavenWrapper) {
             copyMavenWrapper();
         }
-        if (camelWrapper) {
+        if (request.camelWrapper) {
             copyCamelWrapper();
         }
-        if (docker) {
+        if (request.docker) {
             copyDockerFiles(buildDir.toString());
         }
         String appJar = Paths.get("target", ids[1] + "-" + ids[2] + 
".jar").toString();
         copyReadme(buildDir.toString(), appJar);
-        if (cleanExportDir || !isCurrentDirOrParent(exportDir)) {
+        if (request.cleanExportDir || 
!ExportHelper.isCurrentDirOrParent(request.exportDir)) {
             // cleaning current dir can be a bit dangerous so only clean if 
explicit enabled
             // otherwise always clean export-dir to avoid stale data
-            if (cleanExportDir) {
-                String absPath = 
Path.of(exportDir).toAbsolutePath().toString();
-                if (!yes && !exportContext.confirm("Are you sure you want to 
delete " + absPath + "?")) {
+            if (request.cleanExportDir) {
+                String absPath = 
Path.of(request.exportDir).toAbsolutePath().toString();
+                if (!request.yes && !exportContext.confirm("Are you sure you 
want to delete " + absPath + "?")) {
                     return 1;
                 }
             }
-            ExportHelper.cleanExportDir(exportDir);
+            ExportHelper.cleanExportDir(request.exportDir);
         }
         // copy to export dir and remove work dir
-        PathUtils.copyDirectory(buildDir, Path.of(exportDir));
-        createDeferredSymlinks(buildDir, Path.of(exportDir));
+        PathUtils.copyDirectory(buildDir, Path.of(request.exportDir));
+        createDeferredSymlinks(buildDir, Path.of(request.exportDir));
         PathUtils.deleteDirectory(buildDir);
 
         return 0;
     }
 
     private void createMavenPom(Path settings, Path profile, Path pom, 
Set<String> deps, String packageName) throws Exception {
-        String[] ids = gav.split(":");
+        String[] ids = request.gav.split(":");
 
         CamelCatalog catalog = new DefaultCamelCatalog();
-        if (ObjectHelper.isEmpty(camelVersion)) {
-            camelVersion = catalog.getLoadedVersion();
+        if (ObjectHelper.isEmpty(request.camelVersion)) {
+            request.camelVersion = catalog.getLoadedVersion();
         }
-        if (ObjectHelper.isEmpty(camelVersion)) {
-            camelVersion = VersionHelper.extractCamelVersion();
+        if (ObjectHelper.isEmpty(request.camelVersion)) {
+            request.camelVersion = VersionHelper.extractCamelVersion();
         }
 
         Properties prop = new CamelCaseOrderedProperties();
         RuntimeUtil.loadProperties(prop, settings);
-        String repos = getMavenRepositories(settings, prop, camelVersion);
+        String repos = getMavenRepositories(settings, prop, 
request.camelVersion);
 
         // build the template data model
         Map<String, Object> model = new HashMap<>();
         model.put("GroupId", ids[0]);
         model.put("ArtifactId", ids[1]);
         model.put("Version", ids[2]);
-        model.put("JavaVersion", javaVersion);
-        model.put("CamelVersion", camelVersion);
+        model.put("JavaVersion", request.javaVersion);
+        model.put("CamelVersion", request.camelVersion);
         if (packageName != null) {
-            model.put("MainClassname", packageName + "." + mainClassname);
+            model.put("MainClassname", packageName + "." + 
request.mainClassname);
         } else {
-            model.put("MainClassname", mainClassname);
+            model.put("MainClassname", request.mainClassname);
         }
         model.put("ProjectBuildOutputTimestamp", 
this.getBuildMavenProjectDate());
         model.put("BuildProperties", formatBuildProperties());
@@ -255,7 +255,7 @@ public class CamelMainExporter extends Exporter {
         // kubernetes/docker properties
         enrichKubernetesModel(model, settings, profile);
 
-        String context = TemplateHelper.processTemplate(pomTemplateName, 
model);
+        String context = 
TemplateHelper.processTemplate(request.pomTemplateName, model);
         Files.writeString(pom, context);
     }
 
@@ -282,7 +282,7 @@ public class CamelMainExporter extends Exporter {
                 }
             }
             if (fromImage == null) {
-                fromImage = "mirror.gcr.io/library/eclipse-temurin:" + 
javaVersion + "-jre";
+                fromImage = "mirror.gcr.io/library/eclipse-temurin:" + 
request.javaVersion + "-jre";
                 kubernetesProperties.add(Map.of("key", "jib.from.image", 
"value", fromImage));
             }
         }
@@ -302,7 +302,7 @@ public class CamelMainExporter extends Exporter {
             model.put("Port", String.valueOf(port));
         }
         if (jkube) {
-            model.put("JkubeMavenPluginVersion", 
jkubeMavenPluginVersion(settings, prop));
+            model.put("JkubeMavenPluginVersion", 
ExportHelper.jkubeMavenPluginVersion(settings, prop));
         }
     }
 
@@ -390,7 +390,7 @@ public class CamelMainExporter extends Exporter {
     protected void copyGroovyPrecompiled(Path srcResourcesDir) throws 
Exception {
         // are there any pre-compiled groovy code
         // the silent run compiles the groovy code into the work directory
-        File gc = workDir.resolve("compile/groovy").toFile();
+        File gc = request.workDir.resolve("compile/groovy").toFile();
         if (gc.exists() && gc.isDirectory()) {
             File[] files = gc.listFiles();
             if (files != null) {
diff --git 
a/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/Exporter.java
 
b/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/Exporter.java
index e3facfaa0965..966bc515422a 100644
--- 
a/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/Exporter.java
+++ 
b/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/Exporter.java
@@ -30,10 +30,8 @@ import java.time.temporal.ChronoUnit;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
-import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
@@ -72,10 +70,10 @@ import org.apache.camel.util.StringHelper;
 import static org.apache.camel.dsl.jbang.export.common.CamelJBangConstants.*;
 
 /**
- * Exports Camel files to a Maven project of a runtime. The exporter is 
configured from a copy of the
- * {@link ExportRequest}, and uses the {@link ExportContext} of its caller.
+ * Exports Camel files to a Maven project of a runtime. The exporter holds a 
copy of the {@link ExportRequest}, and uses
+ * the {@link ExportContext} of its caller.
  */
-public abstract class Exporter extends ExportRequest {
+abstract class Exporter {
 
     protected static final String[] SETTINGS_PROP_SOURCE_KEYS = new String[] {
             "camel.main.routesIncludePattern",
@@ -99,10 +97,11 @@ public abstract class Exporter extends ExportRequest {
     // Map to store deferred symbolic links: target path in the build dir → 
original source path
     private Map<Path, Path> deferredSymlinks = new HashMap<>();
 
+    protected final ExportRequest request;
     protected final ExportContext exportContext;
 
     protected Exporter(ExportRequest request, ExportContext context) {
-        super(request);
+        this.request = new ExportRequest(request);
         this.exportContext = context;
     }
 
@@ -110,14 +109,14 @@ public abstract class Exporter extends ExportRequest {
      * The directory in the work directory where the project is built, before 
it is copied to the export directory.
      */
     protected Path buildDir() {
-        return workDir.resolve("work");
+        return request.workDir.resolve("work");
     }
 
     /**
      * The run settings in the work directory, which the dependency resolver 
writes.
      */
     protected Path runSettingsFile() {
-        return workDir.resolve(ExportHelper.RUN_SETTINGS_FILE);
+        return request.workDir.resolve(ExportHelper.RUN_SETTINGS_FILE);
     }
 
     /**
@@ -162,7 +161,7 @@ public abstract class Exporter extends ExportRequest {
         }
 
         // sort artifacts
-        gavs.sort(mavenGavComparator());
+        gavs.sort(ExportHelper.mavenGavComparator());
 
         List<Map<String, Object>> result = new ArrayList<>();
         for (MavenGav gav : gavs) {
@@ -178,78 +177,12 @@ public abstract class Exporter extends ExportRequest {
         return result;
     }
 
-    public static Comparator<MavenGav> mavenGavComparator() {
-        return new Comparator<MavenGav>() {
-            @Override
-            public int compare(MavenGav o1, MavenGav o2) {
-                int r1 = rankGroupId(o1);
-                int r2 = rankGroupId(o2);
-
-                if (r1 > r2) {
-                    return -1;
-                } else if (r2 > r1) {
-                    return 1;
-                } else {
-                    return o1.toString().compareTo(o2.toString());
-                }
-            }
-
-            int rankGroupId(MavenGav o1) {
-                String g1 = o1.getGroupId();
-                if (g1 == null) {
-                    return 0;
-                }
-
-                switch (g1) {
-                    case "org.springframework.boot" -> {
-                        return 30;
-                    }
-                    case "io.quarkus" -> {
-                        return 30;
-                    }
-                    case "org.apache.camel.quarkus" -> {
-                        String a1 = o1.getArtifactId();
-                        // main/core/engine first
-                        if ("camel-quarkus-core".equals(a1)) {
-                            return 21;
-                        }
-                        return 20;
-                    }
-                    case "org.apache.camel.springboot" -> {
-                        String a1 = o1.getArtifactId();
-                        // main/core/engine first
-                        if ("camel-spring-boot-starter".equals(a1)) {
-                            return 21;
-                        } else if 
("camel-spring-boot-engine-starter".equals(a1)) {
-                            return 22;
-                        }
-                        return 20;
-                    }
-                    case "org.apache.camel" -> {
-                        String a1 = o1.getArtifactId();
-                        // main/core/engine first
-                        if ("camel-main".equals(a1)) {
-                            return 11;
-                        }
-                        return 10;
-                    }
-                    case "org.apache.camel.kamelets" -> {
-                        return 5;
-                    }
-                    default -> {
-                        return 0;
-                    }
-                }
-            }
-        };
-    }
-
     /**
      * Formats build properties as XML property lines for inclusion in POM 
templates.
      */
     protected void enrichParentPom(Map<String, Object> model) {
-        if (parentPom != null) {
-            MavenGav gav = MavenGav.parseStrictGav(parentPom);
+        if (request.parentPom != null) {
+            MavenGav gav = MavenGav.parseStrictGav(request.parentPom);
             model.put("ParentGroupId", gav.getGroupId());
             model.put("ParentArtifactId", gav.getArtifactId());
             model.put("ParentVersion", gav.getVersion());
@@ -259,7 +192,7 @@ public abstract class Exporter extends ExportRequest {
     protected String formatBuildProperties() {
         Properties properties = mapBuildProperties();
 
-        if (!skipPlugins) {
+        if (!request.skipPlugins) {
             Set<PluginExporter> exporters = pluginExporters();
 
             for (PluginExporter exporter : exporters) {
@@ -279,30 +212,20 @@ public abstract class Exporter extends ExportRequest {
      */
     public abstract Integer export() throws Exception;
 
-    /**
-     * Whether the directory is the current directory, or one that contains 
it, such as <tt>./</tt>, <tt>$PWD</tt> or
-     * <tt>..</tt>: cleaning it before the export deletes the files of the 
project, so it is only cleaned with
-     * --clean-dir.
-     */
-    public static boolean isCurrentDirOrParent(String dir) {
-        Path path = Path.of(dir).toAbsolutePath().normalize();
-        return Path.of("").toAbsolutePath().normalize().startsWith(path);
-    }
-
     protected Integer runSilently(boolean ignoreLoadingError, boolean 
lazyBean, boolean verbose) throws Exception {
-        if (kameletsVersion == null) {
-            kameletsVersion = VersionHelper.extractKameletsVersion();
-        }
-        ExportRequest request = new ExportRequest(this);
-        request.ignoreLoadingError = ignoreLoadingError;
-        request.lazyBean = lazyBean;
-        request.verbose = verbose;
-        return exportContext.getDependencyResolver().resolve(request, 
exportContext);
+        if (request.kameletsVersion == null) {
+            request.kameletsVersion = VersionHelper.extractKameletsVersion();
+        }
+        ExportRequest silent = new ExportRequest(request);
+        silent.ignoreLoadingError = ignoreLoadingError;
+        silent.lazyBean = lazyBean;
+        silent.verbose = verbose;
+        return exportContext.getDependencyResolver().resolve(silent, 
exportContext);
     }
 
     protected void addDependencies(String... deps) {
         var depsArray = Optional.ofNullable(deps).orElse(new String[0]);
-        dependencies.addAll(Arrays.asList(depsArray));
+        request.dependencies.addAll(Arrays.asList(depsArray));
     }
 
     /**
@@ -333,19 +256,20 @@ public abstract class Exporter extends ExportRequest {
             return o1.compareTo(o2);
         });
 
-        if (kameletsVersion == null) {
-            kameletsVersion = VersionHelper.extractKameletsVersion();
+        if (request.kameletsVersion == null) {
+            request.kameletsVersion = VersionHelper.extractKameletsVersion();
         }
 
         // custom dependencies
-        for (String d : dependencies) {
+        for (String d : request.dependencies) {
             answer.add(normalizeDependency(d));
         }
 
         List<String> lines = RuntimeUtil.loadPropertiesLines(settings);
 
         // check if we use custom and/or official ASF kamelets
-        List<String> officialKamelets = 
KameletCatalogHelper.findKameletNames(kameletsVersion, mavenResolver.repos());
+        List<String> officialKamelets
+                = 
KameletCatalogHelper.findKameletNames(request.kameletsVersion, 
request.mavenResolver.repos());
         boolean kamelets = false;
         boolean asfKamelets = false;
         for (String line : lines) {
@@ -381,9 +305,9 @@ public abstract class Exporter extends ExportRequest {
                     answer.add("camel:yaml-dsl");
                     if (asfKamelets) {
                         // include JARs for official ASF kamelets
-                        answer.add("org.apache.camel.kamelets:camel-kamelets:" 
+ kameletsVersion);
-                        if (VersionHelper.compare(camelVersion, "4.10.0") < 0) 
{
-                            
answer.add("org.apache.camel.kamelets:camel-kamelets-utils:" + kameletsVersion);
+                        answer.add("org.apache.camel.kamelets:camel-kamelets:" 
+ request.kameletsVersion);
+                        if (VersionHelper.compare(request.camelVersion, 
"4.10.0") < 0) {
+                            
answer.add("org.apache.camel.kamelets:camel-kamelets-utils:" + 
request.kameletsVersion);
                         }
                     }
                 }
@@ -398,19 +322,19 @@ public abstract class Exporter extends ExportRequest {
                             answer.add("camel:yaml-dsl");
                             if (asfKamelets) {
                                 // include JARs for official ASF kamelets
-                                
answer.add("org.apache.camel.kamelets:camel-kamelets:" + kameletsVersion);
-                                if (VersionHelper.compare(camelVersion, 
"4.10.0") < 0) {
-                                    
answer.add("org.apache.camel.kamelets:camel-kamelets-utils:" + kameletsVersion);
+                                
answer.add("org.apache.camel.kamelets:camel-kamelets:" + 
request.kameletsVersion);
+                                if 
(VersionHelper.compare(request.camelVersion, "4.10.0") < 0) {
+                                    
answer.add("org.apache.camel.kamelets:camel-kamelets-utils:" + 
request.kameletsVersion);
                                 }
                             }
                         }
                     }
                 }
-            } else if (line.startsWith(DEPENDENCIES_MAIN + "=") && runtime == 
RuntimeType.main) {
+            } else if (line.startsWith(DEPENDENCIES_MAIN + "=") && 
request.runtime == RuntimeType.main) {
                 addRuntimeSpecificDependencies(StringHelper.after(line, 
DEPENDENCIES_MAIN + "="), answer);
-            } else if (line.startsWith(DEPENDENCIES_SPRING_BOOT + "=") && 
runtime == RuntimeType.springBoot) {
+            } else if (line.startsWith(DEPENDENCIES_SPRING_BOOT + "=") && 
request.runtime == RuntimeType.springBoot) {
                 addRuntimeSpecificDependencies(StringHelper.after(line, 
DEPENDENCIES_SPRING_BOOT + "="), answer);
-            } else if (line.startsWith(DEPENDENCIES_QUARKUS + "=") && runtime 
== RuntimeType.quarkus) {
+            } else if (line.startsWith(DEPENDENCIES_QUARKUS + "=") && 
request.runtime == RuntimeType.quarkus) {
                 addRuntimeSpecificDependencies(StringHelper.after(line, 
DEPENDENCIES_QUARKUS + "="), answer);
             } else if (line.startsWith(CLASSPATH_FILES + "=")) {
                 String deps = StringHelper.after(line, CLASSPATH_FILES + "=");
@@ -440,9 +364,10 @@ public abstract class Exporter extends ExportRequest {
                                     answer.add("camel:kamelet");
                                     if (asfKamelets) {
                                         // include JARs for official ASF 
kamelets
-                                        
answer.add("mvn:org.apache.camel.kamelets:camel-kamelets:" + kameletsVersion);
-                                        if 
(VersionHelper.compare(camelVersion, "4.10.0") < 0) {
-                                            
answer.add("mvn:org.apache.camel.kamelets:camel-kamelets-utils:" + 
kameletsVersion);
+                                        
answer.add("mvn:org.apache.camel.kamelets:camel-kamelets:" + 
request.kameletsVersion);
+                                        if 
(VersionHelper.compare(request.camelVersion, "4.10.0") < 0) {
+                                            
answer.add("mvn:org.apache.camel.kamelets:camel-kamelets-utils:"
+                                                       + 
request.kameletsVersion);
                                         }
                                     }
                                 }
@@ -456,9 +381,9 @@ public abstract class Exporter extends ExportRequest {
                 answer.add("camel:yaml-dsl");
                 if (asfKamelets) {
                     // include JARs for official ASF kamelets
-                    answer.add("mvn:org.apache.camel.kamelets:camel-kamelets:" 
+ kameletsVersion);
-                    if (VersionHelper.compare(camelVersion, "4.10.0") < 0) {
-                        
answer.add("mvn:org.apache.camel.kamelets:camel-kamelets-utils:" + 
kameletsVersion);
+                    answer.add("mvn:org.apache.camel.kamelets:camel-kamelets:" 
+ request.kameletsVersion);
+                    if (VersionHelper.compare(request.camelVersion, "4.10.0") 
< 0) {
+                        
answer.add("mvn:org.apache.camel.kamelets:camel-kamelets-utils:" + 
request.kameletsVersion);
                     }
                 }
             } else if (line.startsWith("modeline=")) {
@@ -501,11 +426,11 @@ public abstract class Exporter extends ExportRequest {
             }
         }
 
-        if (!skipPlugins) {
+        if (!request.skipPlugins) {
             Set<PluginExporter> exporters = pluginExporters();
 
             for (PluginExporter exporter : exporters) {
-                answer.addAll(exporter.getDependencies(runtime));
+                answer.addAll(exporter.getDependencies(request.runtime));
             }
         }
 
@@ -519,13 +444,13 @@ public abstract class Exporter extends ExportRequest {
         if (profile != null && Files.exists(profile)) {
             RuntimeUtil.loadProperties(exportProperties, profile);
         }
-        GenAiDependencyHelper.addAiObservabilityIfNeeded(answer, 
exportProperties, observe);
+        GenAiDependencyHelper.addAiObservabilityIfNeeded(answer, 
exportProperties, request.observe);
 
         // remove duplicate versions (keep first) but an explicit --dep 
version always wins over
         // an auto-detected dependency for the same groupId:artifactId (e.g. a 
JDBC driver whose
         // version is inferred from the camel-dependencies BOM)
         Set<String> preferred = new HashSet<>();
-        for (String d : dependencies) {
+        for (String d : request.dependencies) {
             String line = normalizeDependency(d);
             MavenGav gav = MavenGav.parseGav(line);
             if (gav.getVersion() != null && !gav.getVersion().isBlank()) {
@@ -737,7 +662,7 @@ public abstract class Exporter extends ExportRequest {
                     if (!java) {
                         if (kamelet) {
                             ExportHelper.safeCopy(source, out, true);
-                            if (symbolicLink) {
+                            if (request.symbolicLink) {
                                 deferredSymlinks.put(out, source);
                             }
                         } else if (jkube) {
@@ -747,13 +672,13 @@ public abstract class Exporter extends ExportRequest {
                             out = 
srcCamelResourcesDir.getParent().getParent().resolve("jkube/" + f);
                             Files.createDirectories(out.getParent());
                             ExportHelper.safeCopy(source, out, true);
-                            if (symbolicLink) {
+                            if (request.symbolicLink) {
                                 deferredSymlinks.put(out, source);
                             }
                         } else {
                             Files.createDirectories(out.getParent());
                             ExportHelper.safeCopy(getClass().getClassLoader(), 
scheme, source, out, true);
-                            if (symbolicLink) {
+                            if (request.symbolicLink) {
                                 deferredSymlinks.put(out, source);
                             }
                         }
@@ -773,7 +698,7 @@ public abstract class Exporter extends ExportRequest {
                                 throw new IOException("Cannot determine 
package name from source: " + source);
                             }
                         } else {
-                            if (javaLiveReload) {
+                            if (request.javaLiveReload) {
                                 out = 
srcJavaDirRoot.resolve(source.getFileName());
                             } else {
                                 if (packageName != null && 
!"false".equalsIgnoreCase(packageName)) {
@@ -782,9 +707,9 @@ public abstract class Exporter extends ExportRequest {
                                 }
                             }
                         }
-                        if (javaLiveReload) {
+                        if (request.javaLiveReload) {
                             ExportHelper.safeCopy(source, out, true);
-                            if (symbolicLink) {
+                            if (request.symbolicLink) {
                                 deferredSymlinks.put(out, source);
                             }
                         } else {
@@ -803,7 +728,7 @@ public abstract class Exporter extends ExportRequest {
 
         copyResourceDirs(srcResourcesDir);
 
-        if (!skipPlugins) {
+        if (!request.skipPlugins) {
             Set<PluginExporter> exporters = pluginExporters();
 
             for (PluginExporter exporter : exporters) {
@@ -814,10 +739,10 @@ public abstract class Exporter extends ExportRequest {
     }
 
     private void copyResourceDirs(Path srcResourcesDir) throws Exception {
-        if (resourceDirs == null || resourceDirs.isEmpty()) {
+        if (request.resourceDirs == null || request.resourceDirs.isEmpty()) {
             return;
         }
-        for (String dir : resourceDirs) {
+        for (String dir : request.resourceDirs) {
             Path dirPath = ExportHelper.validateResourceDir(dir);
             // use the last component as the target directory name
             // so ../shared/schemas -> src/main/resources/schemas/
@@ -832,11 +757,11 @@ public abstract class Exporter extends ExportRequest {
     }
 
     private boolean isUnderResourceDir(String file) {
-        if (resourceDirs == null || resourceDirs.isEmpty()) {
+        if (request.resourceDirs == null || request.resourceDirs.isEmpty()) {
             return false;
         }
         Path filePath = Paths.get(file).normalize();
-        for (String dir : resourceDirs) {
+        for (String dir : request.resourceDirs) {
             Path dirPath = Paths.get(dir).normalize();
             if (filePath.startsWith(dirPath)) {
                 return true;
@@ -878,8 +803,8 @@ public abstract class Exporter extends ExportRequest {
         }
 
         // include camel profile if set (so exported runtimes like Spring Boot 
and Quarkus know the profile)
-        if (this.profile != null && 
!profileProps.containsKey("camel.main.profile")) {
-            profileProps.put("camel.main.profile", this.profile);
+        if (request.profile != null && 
!profileProps.containsKey("camel.main.profile")) {
+            profileProps.put("camel.main.profile", request.profile);
         }
 
         StringBuilder content = new StringBuilder();
@@ -914,7 +839,7 @@ public abstract class Exporter extends ExportRequest {
 
         // User properties
         Properties userProps = new CamelCaseOrderedProperties();
-        userProps.putAll(propertiesMap(this.applicationProperties));
+        userProps.putAll(propertiesMap(request.applicationProperties));
         for (Map.Entry<Object, Object> entryUserProp : userProps.entrySet()) {
             String uK = entryUserProp.getKey().toString();
             String uV = entryUserProp.getValue().toString();
@@ -936,49 +861,17 @@ public abstract class Exporter extends ExportRequest {
     }
 
     protected Map<String, String> propertiesMap(String[]... propertySources) {
-        return propertiesMap(printer(), propertySources);
-    }
-
-    /**
-     * The key=value properties of the given sources, where a later source 
overrides an earlier one.
-     */
-    public static Map<String, String> propertiesMap(Printer printer, 
String[]... propertySources) {
-        Map<String, String> result = new LinkedHashMap<>();
-        if (propertySources != null) {
-            for (String[] props : 
Arrays.stream(propertySources).filter(Objects::nonNull).toList()) {
-                for (String s : props) {
-                    String[] kv = s.split("=", 2);
-                    if (kv.length < 2) {
-                        printer.printWarn("property '" + s + "' has a bad 
format (should be 'key=value'), skipping.");
-                    } else {
-                        result.put(kv[0], kv[1]);
-                    }
-                }
-            }
-        }
-        return result;
+        return ExportHelper.propertiesMap(printer(), propertySources);
     }
 
     // Returns true if it has either an openapi spec or it uses contract-first 
DSL
     protected boolean hasOpenapi(Set<String> dependencies) {
-        return openapi != null || dependencies.stream().anyMatch(s -> 
s.contains("mvn:org.apache.camel:camel-rest-openapi"));
+        return request.openapi != null
+                || dependencies.stream().anyMatch(s -> 
s.contains("mvn:org.apache.camel:camel-rest-openapi"));
     }
 
     protected Properties mapBuildProperties() {
-        return mapBuildProperties(buildProperties);
-    }
-
-    /**
-     * The given Maven build properties (prop=value) as properties.
-     */
-    public static Properties mapBuildProperties(List<String> buildProperties) {
-        var answer = new Properties();
-        buildProperties.stream()
-                .filter(item -> !item.isEmpty())
-                .map(item -> item.split("=", 2))
-                .filter(toks -> toks.length == 2)
-                .forEach(toks -> answer.setProperty(toks[0], toks[1]));
-        return answer;
+        return ExportHelper.mapBuildProperties(request.buildProperties);
     }
 
     protected void copyMavenWrapper() throws Exception {
@@ -1016,11 +909,11 @@ public abstract class Exporter extends ExportRequest {
         // write camel-wrapper.properties with the export's camel version
         String distributionUrl = "https://repo1.maven.org/maven2";
                                  + "/org/apache/camel/camel-launcher/"
-                                 + camelVersion
+                                 + request.camelVersion
                                  + "/camel-launcher-"
-                                 + camelVersion
+                                 + request.camelVersion
                                  + ".jar";
-        String content = "camel.version=" + camelVersion + "\n"
+        String content = "camel.version=" + request.camelVersion + "\n"
                          + "distributionUrl=" + distributionUrl + "\n";
         Files.writeString(camelDir.resolve("camel-wrapper.properties"), 
content);
 
@@ -1073,13 +966,13 @@ public abstract class Exporter extends ExportRequest {
             }
         }
 
-        if (mavenResolver.repos() != null) {
-            Collections.addAll(answer, 
this.mavenResolver.repos().split("\\s*,\\s*"));
+        if (request.mavenResolver.repos() != null) {
+            Collections.addAll(answer, 
request.mavenResolver.repos().split("\\s*,\\s*"));
         }
 
         // include the extra default repositories the downloads use (the 
camel.extra.repos system property unless the
         // request sets them)
-        String extraRepos = mavenResolver.downloader().getExtraRepos();
+        String extraRepos = request.mavenResolver.downloader().getExtraRepos();
         if (extraRepos != null && !extraRepos.isBlank()) {
             for (String r : extraRepos.split("\\s*,\\s*")) {
                 if (!r.isBlank()) {
@@ -1135,7 +1028,7 @@ public abstract class Exporter extends ExportRequest {
      * only has the console when running with the dev profile.
      */
     protected boolean isConsoleInApplicationProperties() {
-        return consoleForRun || "dev".equals(profile);
+        return request.consoleForRun || "dev".equals(request.profile);
     }
 
     /**
@@ -1195,18 +1088,6 @@ public abstract class Exporter extends ExportRequest {
         Files.writeString(file, content);
     }
 
-    public static int httpManagementPort(Path settings) {
-        try {
-            List<String> lines = RuntimeUtil.loadPropertiesLines(settings);
-            String port = lines.stream().filter(l -> 
l.startsWith("camel.management.port="))
-                    .map(s -> StringHelper.after(s, 
"=")).findFirst().orElse("-1");
-            return Integer.parseInt(port);
-        } catch (Exception e) {
-            // ignore
-        }
-        return -1;
-    }
-
     public static String jibMavenPluginVersion(Path settings, Properties prop) 
{
         String answer = null;
         if (prop != null) {
@@ -1224,24 +1105,6 @@ public abstract class Exporter extends ExportRequest {
         return answer != null ? answer : "3.5.2";
     }
 
-    public static String jkubeMavenPluginVersion(Path settings, Properties 
props) {
-        String answer = null;
-        if (props != null) {
-            answer = props.getProperty(JKUBE_MAVEN_PLUGIN_VERSION);
-        }
-        if (answer == null) {
-            try {
-                List<String> lines = RuntimeUtil.loadPropertiesLines(settings);
-                answer = lines.stream()
-                        .filter(l -> l.startsWith(JKUBE_MAVEN_PLUGIN_VERSION + 
"=") || l.startsWith("jkube.version="))
-                        .map(s -> StringHelper.after(s, 
"=")).findFirst().orElse(null);
-            } catch (Exception e) {
-                // ignore
-            }
-        }
-        return answer != null ? answer : "1.20.0";
-    }
-
     // This method is kept for backward compatibility with derived classes
     @Deprecated
     protected void safeCopy(File source, File target, boolean override) throws 
Exception {
@@ -1257,7 +1120,7 @@ public abstract class Exporter extends ExportRequest {
      * @throws Exception if symbolic link creation fails
      */
     protected void createDeferredSymlinks(Path buildDir, Path exportDir) 
throws Exception {
-        if (!symbolicLink || deferredSymlinks.isEmpty()) {
+        if (!request.symbolicLink || deferredSymlinks.isEmpty()) {
             return;
         }
 
@@ -1347,7 +1210,7 @@ public abstract class Exporter extends ExportRequest {
     }
 
     private MavenGav parseLocalJar(String dep) {
-        Path path = exportBaseDir.resolve(dep + ".jar");
+        Path path = request.exportBaseDir.resolve(dep + ".jar");
         if (!Files.isRegularFile(path) || !Files.exists(path)) {
             return null;
         }
@@ -1402,7 +1265,7 @@ public abstract class Exporter extends ExportRequest {
 
     private void copyAgentLibDependencies(MavenGav gav) {
         try {
-            List<MavenArtifact> artifacts = 
mavenResolver.downloader().resolveArtifacts(
+            List<MavenArtifact> artifacts = 
request.mavenResolver.downloader().resolveArtifacts(
                     List.of(gav.toString()), Set.of(), true, 
gav.getVersion().contains("SNAPSHOT"));
             for (MavenArtifact artifact : artifacts) {
                 Path target = 
buildDir().resolve("agent").resolve(artifact.getFile().getName());
@@ -1419,7 +1282,7 @@ public abstract class Exporter extends ExportRequest {
     }
 
     protected void copyApplicationPropertiesFiles(Path srcResourcesDir) throws 
Exception {
-        try (Stream<Path> files = Files.list(exportBaseDir)) {
+        try (Stream<Path> files = Files.list(request.exportBaseDir)) {
             files.filter(p -> Files.isRegularFile(p))
                     .filter(p -> {
                         String fileName = p.getFileName().toString();
@@ -1432,12 +1295,12 @@ public abstract class Exporter extends ExportRequest {
                             // skip generic as its handled specially
                             return false;
                         }
-                        if (profile == null) {
+                        if (request.profile == null) {
                             // accept all kind of configuration files
                             return name.startsWith("application");
                         } else {
                             // only accept the configuration file that matches 
the profile
-                            return name.equals("application-" + profile);
+                            return name.equals("application-" + 
request.profile);
                         }
                     })
                     .forEach(p -> {
@@ -1470,7 +1333,7 @@ public abstract class Exporter extends ExportRequest {
      * The exporters of the active plugins.
      */
     protected Set<PluginExporter> pluginExporters() {
-        return new 
LinkedHashSet<>(exportContext.getPluginExporters(mavenResolver.repos()));
+        return new 
LinkedHashSet<>(exportContext.getPluginExporters(request.mavenResolver.repos()));
     }
 
     protected Printer outPrinter() {
@@ -1478,7 +1341,7 @@ public abstract class Exporter extends ExportRequest {
     }
 
     protected Printer printer() {
-        if (quiet) {
+        if (request.quiet) {
             if (quietPrinter == null) {
                 quietPrinter = new 
Printer.QuietPrinter(exportContext.getPrinter());
             }
@@ -1488,11 +1351,11 @@ public abstract class Exporter extends ExportRequest {
     }
 
     protected String getProjectName() {
-        return ProjectExporter.projectName(name, gav, files);
+        return ProjectExporter.projectName(request.name, request.gav, 
request.files);
     }
 
     protected String getVersion() {
-        return ProjectExporter.projectVersion(gav);
+        return ProjectExporter.projectVersion(request.gav);
     }
 
     // Maven reproducible builds: 
https://maven.apache.org/guides/mini/guide-reproducible-builds.html
@@ -1504,7 +1367,7 @@ public abstract class Exporter extends ExportRequest {
     protected void copyDockerFiles(String buildDir) throws Exception {
         Path docker = Path.of(buildDir).resolve("src/main/docker");
         Files.createDirectories(docker);
-        String[] ids = gav.split(":");
+        String[] ids = request.gav.split(":");
 
         Map<String, Object> model = new HashMap<>();
         model.put("ArtifactId", ids[1]);
@@ -1517,13 +1380,13 @@ public abstract class Exporter extends ExportRequest {
 
     // Process the Dockerfile template for the Java version, e.g. 
Dockerfile25.ftl for Java 25.
     protected String processDockerfileTemplate(String templateName, 
Map<String, Object> model) throws IOException {
-        String ftlName = templateName + javaVersion + ".ftl";
+        String ftlName = templateName + request.javaVersion + ".ftl";
         try {
             return TemplateHelper.processTemplate(ftlName, model);
         } catch (TemplateNotFoundException e) {
             // fallback to JDK 21 template (other errors, e.g. a malformed 
template, are not hidden by the fallback)
             String fallback = templateName + "21.ftl";
-            printer().printf("No Dockerfile template for Java %s, falling back 
to Java 21 template%n", javaVersion);
+            printer().printf("No Dockerfile template for Java %s, falling back 
to Java 21 template%n", request.javaVersion);
             return TemplateHelper.processTemplate(fallback, model);
         }
     }
@@ -1534,7 +1397,7 @@ public abstract class Exporter extends ExportRequest {
 
     // Copy the readme.md into the same Maven project root directory.
     protected void copyReadme(String buildDir, String appJar) throws Exception 
{
-        String[] ids = gav.split(":");
+        String[] ids = request.gav.split(":");
         Map<String, Object> model = new HashMap<>();
         model.put("ArtifactId", ids[1]);
         model.put("Version", ids[2]);
@@ -1548,7 +1411,7 @@ public abstract class Exporter extends ExportRequest {
 
     // Copy the AGENTS.md into the same Maven project root directory to assist 
AI coding assistants.
     protected void copyAgents(String buildDir) throws Exception {
-        String[] ids = gav.split(":");
+        String[] ids = request.gav.split(":");
         Map<String, Object> model = new HashMap<>();
         model.put("ArtifactId", ids[1]);
 
diff --git 
a/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/ProjectExporter.java
 
b/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/ProjectExporter.java
index 19eba96174b0..aad433b178a6 100644
--- 
a/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/ProjectExporter.java
+++ 
b/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/ProjectExporter.java
@@ -190,7 +190,7 @@ public class ProjectExporter {
     /**
      * The exporter of the runtime of the request, or null for a runtime that 
cannot be exported to.
      */
-    public Exporter createExporter(ExportRequest request) {
+    Exporter createExporter(ExportRequest request) {
         return switch (request.runtime) {
             case springBoot -> new SpringBootExporter(request, context);
             case quarkus -> new QuarkusExporter(request, context);
diff --git 
a/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/QuarkusExporter.java
 
b/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/QuarkusExporter.java
index a295d8d51452..65f6b9ea7840 100644
--- 
a/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/QuarkusExporter.java
+++ 
b/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/QuarkusExporter.java
@@ -66,44 +66,44 @@ import static 
org.apache.camel.dsl.jbang.export.common.ExportHelper.exportPackag
 /**
  * Exports to a Camel Quarkus Maven project.
  */
-public class QuarkusExporter extends Exporter {
+class QuarkusExporter extends Exporter {
 
     private QuarkusPlatformBom quarkusCamelBom;
 
-    public QuarkusExporter(ExportRequest request, ExportContext context) {
+    QuarkusExporter(ExportRequest request, ExportContext context) {
         super(request, context);
-        if (pomTemplateName == null) {
-            pomTemplateName = "quarkus-pom.ftl";
+        if (this.request.pomTemplateName == null) {
+            this.request.pomTemplateName = "quarkus-pom.ftl";
         }
     }
 
     @Override
     public Integer export() throws Exception {
         try {
-            MavenGav.parseStrictGav(gav);
+            MavenGav.parseStrictGav(request.gav);
         } catch (IllegalArgumentException e) {
             printer().printErr("--gav must be in syntax: 
groupId:artifactId:version");
             return 1;
         }
-        if (parentPom != null) {
+        if (request.parentPom != null) {
             try {
-                MavenGav.parseStrictGav(parentPom);
+                MavenGav.parseStrictGav(request.parentPom);
             } catch (IllegalArgumentException e) {
                 printer().printErr("--parent-pom must be in syntax: 
groupId:artifactId:version");
                 return 1;
             }
         }
-        String[] ids = gav.split(":");
+        String[] ids = request.gav.split(":");
 
-        exportBaseDir = exportBaseDir != null ? exportBaseDir : Path.of(".");
-        Path profile = exportBaseDir.resolve("application.properties");
+        request.exportBaseDir = request.exportBaseDir != null ? 
request.exportBaseDir : Path.of(".");
+        Path profile = request.exportBaseDir.resolve("application.properties");
 
         // the settings file has information what to export
         Path settings = runSettingsFile();
-        if (mavenResolver.fresh() || !files.isEmpty() || 
!Files.exists(settings)) {
+        if (request.mavenResolver.fresh() || !request.files.isEmpty() || 
!Files.exists(settings)) {
             // allow to automatic build
             printer().println("Generating fresh run data");
-            int silent = runSilently(ignoreLoadingError, lazyBean, verbose);
+            int silent = runSilently(request.ignoreLoadingError, 
request.lazyBean, request.verbose);
             if (silent != 0) {
                 return silent;
             }
@@ -111,7 +111,7 @@ public class QuarkusExporter extends Exporter {
             printer().println("Reusing existing run data");
         }
 
-        printer().println("Exporting as Quarkus project to: " + exportDir);
+        printer().println("Exporting as Quarkus project to: " + 
request.exportDir);
 
         // use a temporary work dir
         Path buildDir = buildDir();
@@ -119,7 +119,7 @@ public class QuarkusExporter extends Exporter {
         Files.createDirectories(buildDir);
 
         Path srcJavaDirRoot = buildDir.resolve("src/main/java");
-        String srcPackageName = exportPackageName(ids[0], ids[1], packageName);
+        String srcPackageName = exportPackageName(ids[0], ids[1], 
request.packageName);
         Path srcJavaDir;
         if (srcPackageName == null) {
             srcJavaDir = srcJavaDirRoot;
@@ -152,12 +152,12 @@ public class QuarkusExporter extends Exporter {
                 }
             }
             if (!prop.containsKey("quarkus.management.port")) {
-                port = httpManagementPort(settings);
-                if (port != -1) {
-                    prop.put("quarkus.management.port", port);
+                request.port = ExportHelper.httpManagementPort(settings);
+                if (request.port != -1) {
+                    prop.put("quarkus.management.port", request.port);
                 }
             }
-            if (hawtio) {
+            if (request.hawtio) {
                 prop.setProperty("quarkus.hawtio.authenticationEnabled", 
"false");
             }
             // developer console (--console) is the camel-quarkus-console 
extension (/q/camel/dev-console), which
@@ -170,11 +170,11 @@ public class QuarkusExporter extends Exporter {
         });
         writeDevProfileProperties(srcResourcesDir, devProfile);
         // copy docker files
-        if (docker) {
+        if (request.docker) {
             copyDockerFiles(buildDir.toString());
         }
         String appJar;
-        if ("fast-jar".equals(quarkusPackageType)) {
+        if ("fast-jar".equals(request.quarkusPackageType)) {
             appJar = "target" + File.separator + "quarkus-app" + 
File.separator + "quarkus-run.jar";
         } else {
             appJar = "target" + File.separator + ids[1] + "-" + ids[2] + 
".jar";
@@ -185,27 +185,27 @@ public class QuarkusExporter extends Exporter {
         // copy local lib JARs
         copyLocalLibDependencies(deps);
         createMavenPom(settings, buildDir.resolve("pom.xml"), deps);
-        if (mavenWrapper) {
+        if (request.mavenWrapper) {
             copyMavenWrapper();
         }
-        if (camelWrapper) {
+        if (request.camelWrapper) {
             copyCamelWrapper();
         }
 
-        if (cleanExportDir || !isCurrentDirOrParent(exportDir)) {
+        if (request.cleanExportDir || 
!ExportHelper.isCurrentDirOrParent(request.exportDir)) {
             // cleaning current dir can be a bit dangerous so only clean if 
explicit enabled
             // otherwise always clean export-dir to avoid stale data
-            if (cleanExportDir) {
-                String absPath = 
Path.of(exportDir).toAbsolutePath().toString();
-                if (!yes && !exportContext.confirm("Are you sure you want to 
delete " + absPath + "?")) {
+            if (request.cleanExportDir) {
+                String absPath = 
Path.of(request.exportDir).toAbsolutePath().toString();
+                if (!request.yes && !exportContext.confirm("Are you sure you 
want to delete " + absPath + "?")) {
                     return 1;
                 }
             }
-            ExportHelper.cleanExportDir(exportDir);
+            ExportHelper.cleanExportDir(request.exportDir);
         }
         // copy to export dir and remove work dir
-        PathUtils.copyDirectory(buildDir, Path.of(exportDir));
-        createDeferredSymlinks(buildDir, Path.of(exportDir));
+        PathUtils.copyDirectory(buildDir, Path.of(request.exportDir));
+        createDeferredSymlinks(buildDir, Path.of(request.exportDir));
         PathUtils.deleteDirectory(buildDir);
 
         return 0;
@@ -280,11 +280,11 @@ public class QuarkusExporter extends Exporter {
     private QuarkusPlatformBom getQuarkusCamelBom() {
         if (quarkusCamelBom == null) {
             // resolve Quarkus platform version from registry (when download 
is true)
-            quarkusCamelBom = quarkusPlatform.resolve(
-                    camelVersion,
-                    mavenResolver.downloader()::resolveArtifact,
-                    mavenResolver.download(),
-                    mavenResolver.fresh());
+            quarkusCamelBom = request.quarkusPlatform.resolve(
+                    request.camelVersion,
+                    request.mavenResolver.downloader()::resolveArtifact,
+                    request.mavenResolver.download(),
+                    request.mavenResolver.fresh());
         }
         return quarkusCamelBom;
     }
@@ -382,7 +382,7 @@ public class QuarkusExporter extends Exporter {
     @Override
     protected void copyDockerFiles(String buildDir) throws Exception {
         Path dockerSrc = Path.of(buildDir).resolve("src/main/docker");
-        if ("uber-jar".equals(quarkusPackageType)) {
+        if ("uber-jar".equals(request.quarkusPackageType)) {
             super.copyDockerFiles(buildDir);
         } else {
             Files.createDirectories(dockerSrc);
@@ -409,7 +409,7 @@ public class QuarkusExporter extends Exporter {
 
     @Override
     protected void copyReadme(String buildDir, String appJar) throws Exception 
{
-        String[] ids = gav.split(":");
+        String[] ids = request.gav.split(":");
         Map<String, Object> model = new HashMap<>();
         model.put("ArtifactId", ids[1]);
         model.put("Version", ids[2]);
@@ -422,7 +422,7 @@ public class QuarkusExporter extends Exporter {
     }
 
     private void createMavenPom(Path settings, Path pom, Set<String> deps) 
throws Exception {
-        String[] ids = gav.split(":");
+        String[] ids = request.gav.split(":");
 
         Properties prop = new CamelCaseOrderedProperties();
         RuntimeUtil.loadProperties(prop, settings);
@@ -432,8 +432,8 @@ public class QuarkusExporter extends Exporter {
         MavenGav quarkusCamelBom = plfBom.quarkusCamelBom();
         String repos = getMavenRepositories(settings, prop, 
quarkusCamelBom.getVersion());
 
-        if (camelVersion == null) {
-            camelVersion = plfBom.camelVersion();
+        if (request.camelVersion == null) {
+            request.camelVersion = plfBom.camelVersion();
         }
 
         // Build template data model
@@ -447,8 +447,8 @@ public class QuarkusExporter extends Exporter {
         model.put("QuarkusArtifactId", quarkusCamelBom.getArtifactId());
         model.put("QuarkusVersion", quarkusCamelBom.getVersion());
         model.put("UseQuarkusJunit", 
VersionHelper.isGE(quarkusCamelBom.getVersion(), "3.31.0"));
-        model.put("QuarkusPackageType", quarkusPackageType);
-        model.put("JavaVersion", javaVersion);
+        model.put("QuarkusPackageType", request.quarkusPackageType);
+        model.put("JavaVersion", request.javaVersion);
         model.put("ProjectBuildOutputTimestamp", 
this.getBuildMavenProjectDate());
         model.put("BuildProperties", formatBuildProperties());
         model.put("Repositories", buildRepositoryList(repos));
@@ -456,14 +456,14 @@ public class QuarkusExporter extends Exporter {
         model.put("JibMavenPluginVersion", jibMavenPluginVersion(settings, 
prop));
         enrichParentPom(model);
 
-        String context = TemplateHelper.processTemplate(pomTemplateName, 
model);
+        String context = 
TemplateHelper.processTemplate(request.pomTemplateName, model);
         Files.writeString(pom, context);
     }
 
     private List<Map<String, Object>> buildQuarkusDependencyList(Set<String> 
deps, MavenGav quarkusCamelBom) {
         List<MavenGav> gavs = new ArrayList<>();
 
-        Path file = 
mavenResolver.downloader().resolveArtifact(quarkusCamelBom).getFile().toPath();
+        Path file = 
request.mavenResolver.downloader().resolveArtifact(quarkusCamelBom).getFile().toPath();
         DocumentBuilderFactory dbf = XmlHelper.createDocumentBuilderFactory();
 
         try (InputStream in = Files.newInputStream(file)) {
@@ -487,7 +487,7 @@ public class QuarkusExporter extends Exporter {
                         gav.setVersion(null);
                     } else {
                         // Use plain camel with hard-coded version
-                        gav.setVersion(camelVersion);
+                        gav.setVersion(request.camelVersion);
                     }
                 }
                 gavs.add(gav);
@@ -504,7 +504,7 @@ public class QuarkusExporter extends Exporter {
         replaceQuarkusDependencies(gavs);
 
         // sort artifacts
-        gavs.sort(mavenGavComparator());
+        gavs.sort(ExportHelper.mavenGavComparator());
 
         List<Map<String, Object>> result = new ArrayList<>();
         for (MavenGav gav : gavs) {
@@ -553,9 +553,9 @@ public class QuarkusExporter extends Exporter {
         answer.removeIf(s -> s.contains("camel-core"));
         answer.removeIf(s -> s.contains("camel-microprofile-health"));
 
-        if (hawtio) {
+        if (request.hawtio) {
             answer.add("mvn:org.apache.camel:camel-management");
-            answer.add("mvn:io.hawt:hawtio-quarkus:" + hawtioVersion);
+            answer.add("mvn:io.hawt:hawtio-quarkus:" + request.hawtioVersion);
         }
         if (settingsFlag(settings, CONSOLE)) {
             // developer console (--console) as the camel-quarkus-console 
extension
diff --git 
a/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/SpringBootExporter.java
 
b/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/SpringBootExporter.java
index 1a354cf9209a..c1d523a8ec7b 100644
--- 
a/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/SpringBootExporter.java
+++ 
b/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/SpringBootExporter.java
@@ -54,42 +54,42 @@ import static 
org.apache.camel.dsl.jbang.export.common.ExportHelper.exportPackag
 /**
  * Exports to a Camel Spring Boot Maven project.
  */
-public class SpringBootExporter extends Exporter {
+class SpringBootExporter extends Exporter {
 
-    public SpringBootExporter(ExportRequest request, ExportContext context) {
+    SpringBootExporter(ExportRequest request, ExportContext context) {
         super(request, context);
-        if (pomTemplateName == null) {
-            pomTemplateName = "spring-boot-pom.ftl";
+        if (this.request.pomTemplateName == null) {
+            this.request.pomTemplateName = "spring-boot-pom.ftl";
         }
     }
 
     @Override
     public Integer export() throws Exception {
         try {
-            MavenGav.parseStrictGav(gav);
+            MavenGav.parseStrictGav(request.gav);
         } catch (IllegalArgumentException e) {
             printer().printErr("--gav must be in syntax: 
groupId:artifactId:version");
             return 1;
         }
-        if (parentPom != null) {
+        if (request.parentPom != null) {
             try {
-                MavenGav.parseStrictGav(parentPom);
+                MavenGav.parseStrictGav(request.parentPom);
             } catch (IllegalArgumentException e) {
                 printer().printErr("--parent-pom must be in syntax: 
groupId:artifactId:version");
                 return 1;
             }
         }
-        String[] ids = gav.split(":");
+        String[] ids = request.gav.split(":");
 
-        exportBaseDir = exportBaseDir != null ? exportBaseDir : Path.of(".");
-        Path profile = exportBaseDir.resolve("application.properties");
+        request.exportBaseDir = request.exportBaseDir != null ? 
request.exportBaseDir : Path.of(".");
+        Path profile = request.exportBaseDir.resolve("application.properties");
 
         // the settings file has information what to export
         Path settings = runSettingsFile();
-        if (mavenResolver.fresh() || !files.isEmpty() || 
!Files.exists(settings)) {
+        if (request.mavenResolver.fresh() || !request.files.isEmpty() || 
!Files.exists(settings)) {
             // allow to automatic build
             printer().println("Generating fresh run data");
-            int silent = runSilently(ignoreLoadingError, lazyBean, verbose);
+            int silent = runSilently(request.ignoreLoadingError, 
request.lazyBean, request.verbose);
             if (silent != 0) {
                 return silent;
             }
@@ -97,7 +97,7 @@ public class SpringBootExporter extends Exporter {
             printer().println("Reusing existing run data");
         }
 
-        printer().println("Exporting as Spring Boot project to: " + exportDir);
+        printer().println("Exporting as Spring Boot project to: " + 
request.exportDir);
 
         // use a temporary work dir
         Path buildDir = buildDir();
@@ -105,7 +105,7 @@ public class SpringBootExporter extends Exporter {
         Files.createDirectories(buildDir);
 
         Path srcJavaDirRoot = buildDir.resolve("src/main/java");
-        String srcPackageName = exportPackageName(ids[0], ids[1], packageName);
+        String srcPackageName = exportPackageName(ids[0], ids[1], 
request.packageName);
         Path srcJavaDir;
         if (srcPackageName == null) {
             srcJavaDir = srcJavaDirRoot;
@@ -126,7 +126,7 @@ public class SpringBootExporter extends Exporter {
                 srcKameletsResourcesDir, srcPackageName);
 
         // create main class
-        createMainClassSource(srcJavaDir, srcPackageName, mainClassname);
+        createMainClassSource(srcJavaDir, srcPackageName, 
request.mainClassname);
         // gather dependencies
         final Set<String> deps = resolveDependencies(settings, profile);
         // copy local lib JARs
@@ -153,12 +153,12 @@ public class SpringBootExporter extends Exporter {
                 }
             }
             if (!prop.containsKey("management.server.port")) {
-                port = httpManagementPort(settings);
-                if (port != -1) {
-                    prop.put("management.server.port", port);
+                request.port = ExportHelper.httpManagementPort(settings);
+                if (request.port != -1) {
+                    prop.put("management.server.port", request.port);
                 }
             }
-            if (hawtio) {
+            if (request.hawtio) {
                 // spring boot needs these options configured to support hawtio
                 prop.setProperty("management.endpoints.web.exposure.include",
                         
exposeActuatorEndpoints(prop.getProperty("management.endpoints.web.exposure.include"),
@@ -173,7 +173,7 @@ public class SpringBootExporter extends Exporter {
                 // value. With --observe the starter exposes health and 
prometheus as its default, which an explicit
                 // list would replace, so keep them too (the console is then 
at /observe/camel)
                 String exposed = 
prop.getProperty("management.endpoints.web.exposure.include");
-                if (exposed == null && observe) {
+                if (exposed == null && request.observe) {
                     exposed = "health,prometheus";
                 }
                 exposed = exposeActuatorEndpoints(exposed, "camel");
@@ -187,58 +187,60 @@ public class SpringBootExporter extends Exporter {
         });
         writeDevProfileProperties(srcResourcesDir, devProfile);
         createMavenPom(settings, profile, buildDir.resolve("pom.xml"), deps);
-        if (mavenWrapper) {
+        if (request.mavenWrapper) {
             copyMavenWrapper();
         }
-        if (camelWrapper) {
+        if (request.camelWrapper) {
             copyCamelWrapper();
         }
-        if (docker) {
+        if (request.docker) {
             copyDockerFiles(buildDir.toString());
         }
         String appJar = "target" + File.separator + ids[1] + "-" + ids[2] + 
".jar";
         copyReadme(buildDir.toString(), appJar);
-        if (cleanExportDir || !isCurrentDirOrParent(exportDir)) {
+        if (request.cleanExportDir || 
!ExportHelper.isCurrentDirOrParent(request.exportDir)) {
             // cleaning current dir can be a bit dangerous so only clean if 
explicit enabled
             // otherwise always clean export-dir to avoid stale data
-            if (cleanExportDir) {
-                String absPath = 
Paths.get(exportDir).toAbsolutePath().toString();
-                if (!yes && !exportContext.confirm("Are you sure you want to 
delete " + absPath + "?")) {
+            if (request.cleanExportDir) {
+                String absPath = 
Paths.get(request.exportDir).toAbsolutePath().toString();
+                if (!request.yes && !exportContext.confirm("Are you sure you 
want to delete " + absPath + "?")) {
                     return 1;
                 }
             }
-            ExportHelper.cleanExportDir(exportDir);
+            ExportHelper.cleanExportDir(request.exportDir);
         }
         // copy to export dir and remove work dir
-        PathUtils.copyDirectory(buildDir, Paths.get(exportDir));
-        createDeferredSymlinks(buildDir, Paths.get(exportDir));
+        PathUtils.copyDirectory(buildDir, Paths.get(request.exportDir));
+        createDeferredSymlinks(buildDir, Paths.get(request.exportDir));
         PathUtils.deleteDirectory(buildDir);
 
         return 0;
     }
 
     private void createMavenPom(Path settings, Path profile, Path pom, 
Set<String> deps) throws Exception {
-        String[] ids = gav.split(":");
+        String[] ids = request.gav.split(":");
 
         Properties prop = new CamelCaseOrderedProperties();
         RuntimeUtil.loadProperties(prop, settings);
-        String sbVersion = camelSpringBootVersion != null
-                ? camelSpringBootVersion : (camelVersion == null ? 
RuntimeType.main.version() : camelVersion);
+        String sbVersion = request.camelSpringBootVersion != null
+                ? request.camelSpringBootVersion
+                : (request.camelVersion == null ? RuntimeType.main.version() : 
request.camelVersion);
         String repos = getMavenRepositories(settings, prop, sbVersion);
 
-        CamelCatalog catalog = CatalogLoader.loadSpringBootCatalog(repos, 
sbVersion, sbVersion, null, mavenResolver.download());
-        if (ObjectHelper.isEmpty(camelVersion)) {
-            camelVersion = catalog.getLoadedVersion();
+        CamelCatalog catalog
+                = CatalogLoader.loadSpringBootCatalog(repos, sbVersion, 
sbVersion, null, request.mavenResolver.download());
+        if (ObjectHelper.isEmpty(request.camelVersion)) {
+            request.camelVersion = catalog.getLoadedVersion();
         }
-        if (ObjectHelper.isEmpty(camelVersion)) {
-            camelVersion = VersionHelper.extractCamelVersion();
+        if (ObjectHelper.isEmpty(request.camelVersion)) {
+            request.camelVersion = VersionHelper.extractCamelVersion();
         }
 
         // Check if catalog provides a custom template (backward compatibility)
         // Also check old .tmpl name for catalogs that haven't been updated
-        InputStream catalogTemplate = catalog.loadResource("camel-jbang", 
pomTemplateName);
+        InputStream catalogTemplate = catalog.loadResource("camel-jbang", 
request.pomTemplateName);
         if (catalogTemplate == null) {
-            catalogTemplate = catalog.loadResource("camel-jbang", 
pomTemplateName.replace(".ftl", ".tmpl"));
+            catalogTemplate = catalog.loadResource("camel-jbang", 
request.pomTemplateName.replace(".ftl", ".tmpl"));
         }
         if (catalogTemplate != null) {
             // Catalog provides a custom template - use legacy regex-based 
processing
@@ -256,10 +258,10 @@ public class SpringBootExporter extends Exporter {
         model.put("GroupId", ids[0]);
         model.put("ArtifactId", ids[1]);
         model.put("Version", ids[2]);
-        model.put("SpringBootVersion", springBootVersion);
-        model.put("JavaVersion", javaVersion);
+        model.put("SpringBootVersion", request.springBootVersion);
+        model.put("JavaVersion", request.javaVersion);
         model.put("CamelSpringBootVersion",
-                Objects.requireNonNullElseGet(camelSpringBootVersion, () -> 
camelVersion));
+                Objects.requireNonNullElseGet(request.camelSpringBootVersion, 
() -> request.camelVersion));
         model.put("ProjectBuildOutputTimestamp", 
this.getBuildMavenProjectDate());
         model.put("BuildProperties", formatBuildProperties());
         model.put("Repositories", buildRepositoryList(repos));
@@ -267,7 +269,7 @@ public class SpringBootExporter extends Exporter {
         model.put("JibMavenPluginVersion", jibMavenPluginVersion(settings, 
prop));
         enrichParentPom(model);
 
-        String context = TemplateHelper.processTemplate(pomTemplateName, 
model);
+        String context = 
TemplateHelper.processTemplate(request.pomTemplateName, model);
         IOHelper.writeText(context, Files.newOutputStream(pom));
     }
 
@@ -286,7 +288,7 @@ public class SpringBootExporter extends Exporter {
                     gav.setArtifactId(am.getArtifactId());
                     gav.setVersion(null);
                 } else {
-                    gav.setVersion(camelVersion);
+                    gav.setVersion(request.camelVersion);
                 }
             }
             if ("org.springframework.boot".equals(gid)) {
@@ -295,7 +297,7 @@ public class SpringBootExporter extends Exporter {
             gavs.add(gav);
         }
 
-        gavs.sort(mavenGavComparator());
+        gavs.sort(ExportHelper.mavenGavComparator());
 
         List<Map<String, Object>> result = new ArrayList<>();
         for (MavenGav gav : gavs) {
@@ -319,11 +321,11 @@ public class SpringBootExporter extends Exporter {
         context = context.replaceAll("\\{\\{ \\.GroupId }}", ids[0]);
         context = context.replaceAll("\\{\\{ \\.ArtifactId }}", ids[1]);
         context = context.replaceAll("\\{\\{ \\.Version }}", ids[2]);
-        context = context.replaceAll("\\{\\{ \\.SpringBootVersion }}", 
springBootVersion);
-        context = context.replaceAll("\\{\\{ \\.JavaVersion }}", javaVersion);
-        context = context.replaceAll("\\{\\{ \\.CamelVersion }}", 
camelVersion);
+        context = context.replaceAll("\\{\\{ \\.SpringBootVersion }}", 
request.springBootVersion);
+        context = context.replaceAll("\\{\\{ \\.JavaVersion }}", 
request.javaVersion);
+        context = context.replaceAll("\\{\\{ \\.CamelVersion }}", 
request.camelVersion);
         context = context.replaceAll("\\{\\{ \\.CamelSpringBootVersion }}",
-                Objects.requireNonNullElseGet(camelSpringBootVersion, () -> 
camelVersion));
+                Objects.requireNonNullElseGet(request.camelSpringBootVersion, 
() -> request.camelVersion));
         context = context.replaceFirst("\\{\\{ \\.ProjectBuildOutputTimestamp 
}}", this.getBuildMavenProjectDate());
         context = replaceBuildProperties(context);
 
@@ -346,7 +348,7 @@ public class SpringBootExporter extends Exporter {
                     gav.setArtifactId(am.getArtifactId());
                     gav.setVersion(null);
                 } else {
-                    gav.setVersion(camelVersion);
+                    gav.setVersion(request.camelVersion);
                 }
             }
             if ("org.springframework.boot".equals(gid)) {
@@ -354,7 +356,7 @@ public class SpringBootExporter extends Exporter {
             }
             gavs.add(gav);
         }
-        gavs.sort(mavenGavComparator());
+        gavs.sort(ExportHelper.mavenGavComparator());
 
         StringBuilder sb = new StringBuilder();
         for (MavenGav gav : gavs) {
@@ -443,10 +445,10 @@ public class SpringBootExporter extends Exporter {
             // include http server if using openapi
             answer.add("mvn:org.apache.camel:camel-platform-http");
         }
-        if (hawtio) {
+        if (request.hawtio) {
             answer.add("mvn:org.apache.camel:camel-management");
-            String hawtioArtifact = springBootVersion.startsWith("4.") ? 
"hawtio-springboot4" : "hawtio-springboot";
-            answer.add("mvn:io.hawt:" + hawtioArtifact + ":" + hawtioVersion);
+            String hawtioArtifact = request.springBootVersion.startsWith("4.") 
? "hawtio-springboot4" : "hawtio-springboot";
+            answer.add("mvn:io.hawt:" + hawtioArtifact + ":" + 
request.hawtioVersion);
         }
         if (settingsFlag(settings, CamelJBangConstants.CONSOLE)) {
             // developer console (--console) as actuator endpoint 
(camel-console-starter)
@@ -503,7 +505,8 @@ public class SpringBootExporter extends Exporter {
             // skip "camel.server." or "camel.management." as this is for 
camel-main only
             return null;
         }
-        boolean camel44orOlder = camelSpringBootVersion != null && 
VersionHelper.isGE("4.4.0", camelSpringBootVersion);
+        boolean camel44orOlder
+                = request.camelSpringBootVersion != null && 
VersionHelper.isGE("4.4.0", request.camelSpringBootVersion);
         if (camel44orOlder) {
             // camel.main.x should be renamed to camel.springboot.x (for camel 
4.4.x or older)
             if (key.startsWith("camel.main.")) {
diff --git 
a/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/common/ExportHelper.java
 
b/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/common/ExportHelper.java
index dd94eef2f959..6a9e57b6d1d8 100644
--- 
a/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/common/ExportHelper.java
+++ 
b/dsl/camel-jbang/camel-jbang-export/src/main/java/org/apache/camel/dsl/jbang/export/common/ExportHelper.java
@@ -23,11 +23,21 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.nio.file.StandardCopyOption;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Properties;
 import java.util.stream.Stream;
 
+import org.apache.camel.tooling.maven.MavenGav;
 import org.apache.camel.util.FileUtil;
 import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.StringHelper;
+
+import static 
org.apache.camel.dsl.jbang.export.common.CamelJBangConstants.JKUBE_MAVEN_PLUGIN_VERSION;
 
 /**
  * Helper class provides export utilities for instance when copying files from 
temporary work folder to export directory
@@ -204,4 +214,142 @@ public final class ExportHelper {
         return sb.toString();
     }
 
+    public static Comparator<MavenGav> mavenGavComparator() {
+        return new Comparator<MavenGav>() {
+            @Override
+            public int compare(MavenGav o1, MavenGav o2) {
+                int r1 = rankGroupId(o1);
+                int r2 = rankGroupId(o2);
+
+                if (r1 > r2) {
+                    return -1;
+                } else if (r2 > r1) {
+                    return 1;
+                } else {
+                    return o1.toString().compareTo(o2.toString());
+                }
+            }
+
+            int rankGroupId(MavenGav o1) {
+                String g1 = o1.getGroupId();
+                if (g1 == null) {
+                    return 0;
+                }
+
+                switch (g1) {
+                    case "org.springframework.boot" -> {
+                        return 30;
+                    }
+                    case "io.quarkus" -> {
+                        return 30;
+                    }
+                    case "org.apache.camel.quarkus" -> {
+                        String a1 = o1.getArtifactId();
+                        // main/core/engine first
+                        if ("camel-quarkus-core".equals(a1)) {
+                            return 21;
+                        }
+                        return 20;
+                    }
+                    case "org.apache.camel.springboot" -> {
+                        String a1 = o1.getArtifactId();
+                        // main/core/engine first
+                        if ("camel-spring-boot-starter".equals(a1)) {
+                            return 21;
+                        } else if 
("camel-spring-boot-engine-starter".equals(a1)) {
+                            return 22;
+                        }
+                        return 20;
+                    }
+                    case "org.apache.camel" -> {
+                        String a1 = o1.getArtifactId();
+                        // main/core/engine first
+                        if ("camel-main".equals(a1)) {
+                            return 11;
+                        }
+                        return 10;
+                    }
+                    case "org.apache.camel.kamelets" -> {
+                        return 5;
+                    }
+                    default -> {
+                        return 0;
+                    }
+                }
+            }
+        };
+    }
+
+    /**
+     * Whether the directory is the current directory, or one that contains 
it, such as <tt>./</tt>, <tt>$PWD</tt> or
+     * <tt>..</tt>: cleaning it before the export deletes the files of the 
project, so it is only cleaned with
+     * --clean-dir.
+     */
+    public static boolean isCurrentDirOrParent(String dir) {
+        Path path = Path.of(dir).toAbsolutePath().normalize();
+        return Path.of("").toAbsolutePath().normalize().startsWith(path);
+    }
+
+    /**
+     * The key=value properties of the given sources, where a later source 
overrides an earlier one.
+     */
+    public static Map<String, String> propertiesMap(Printer printer, 
String[]... propertySources) {
+        Map<String, String> result = new LinkedHashMap<>();
+        if (propertySources != null) {
+            for (String[] props : 
Arrays.stream(propertySources).filter(Objects::nonNull).toList()) {
+                for (String s : props) {
+                    String[] kv = s.split("=", 2);
+                    if (kv.length < 2) {
+                        printer.printWarn("property '" + s + "' has a bad 
format (should be 'key=value'), skipping.");
+                    } else {
+                        result.put(kv[0], kv[1]);
+                    }
+                }
+            }
+        }
+        return result;
+    }
+
+    /**
+     * The given Maven build properties (prop=value) as properties.
+     */
+    public static Properties mapBuildProperties(List<String> buildProperties) {
+        var answer = new Properties();
+        buildProperties.stream()
+                .filter(item -> !item.isEmpty())
+                .map(item -> item.split("=", 2))
+                .filter(toks -> toks.length == 2)
+                .forEach(toks -> answer.setProperty(toks[0], toks[1]));
+        return answer;
+    }
+
+    public static int httpManagementPort(Path settings) {
+        try {
+            List<String> lines = RuntimeUtil.loadPropertiesLines(settings);
+            String port = lines.stream().filter(l -> 
l.startsWith("camel.management.port="))
+                    .map(s -> StringHelper.after(s, 
"=")).findFirst().orElse("-1");
+            return Integer.parseInt(port);
+        } catch (Exception e) {
+            // ignore
+        }
+        return -1;
+    }
+
+    public static String jkubeMavenPluginVersion(Path settings, Properties 
props) {
+        String answer = null;
+        if (props != null) {
+            answer = props.getProperty(JKUBE_MAVEN_PLUGIN_VERSION);
+        }
+        if (answer == null) {
+            try {
+                List<String> lines = RuntimeUtil.loadPropertiesLines(settings);
+                answer = lines.stream()
+                        .filter(l -> l.startsWith(JKUBE_MAVEN_PLUGIN_VERSION + 
"=") || l.startsWith("jkube.version="))
+                        .map(s -> StringHelper.after(s, 
"=")).findFirst().orElse(null);
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+        return answer != null ? answer : "1.20.0";
+    }
 }
diff --git 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java
 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java
index b21cbec14f8c..117396050074 100644
--- 
a/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java
+++ 
b/dsl/camel-jbang/camel-jbang-plugin-kubernetes/src/main/java/org/apache/camel/dsl/jbang/core/commands/kubernetes/KubernetesExport.java
@@ -45,7 +45,6 @@ import 
org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.model.Containe
 import org.apache.camel.dsl.jbang.core.commands.kubernetes.traits.model.Traits;
 import org.apache.camel.dsl.jbang.core.common.CommandLineHelper;
 import org.apache.camel.dsl.jbang.export.ExportRequest;
-import org.apache.camel.dsl.jbang.export.Exporter;
 import org.apache.camel.dsl.jbang.export.common.CatalogLoader;
 import org.apache.camel.dsl.jbang.export.common.ExportHelper;
 import org.apache.camel.dsl.jbang.export.common.MavenResolverMixinSpec;
@@ -316,7 +315,7 @@ public class KubernetesExport extends Export {
         Traits traitsSpec = getTraitSpec(applicationProfileProperties, 
applicationProperties);
 
         // Map properties to env variables (where needed)
-        var propsMap = Exporter.propertiesMap(printer(), 
applicationProfileProperties, applicationProperties);
+        var propsMap = ExportHelper.propertiesMap(printer(), 
applicationProfileProperties, applicationProperties);
         if (propsMap.containsKey("ssl.truststore.certificates")) {
             addEnvVar("SSL_TRUSTSTORE_CERTIFICATES", 
propsMap.get("ssl.truststore.certificates"));
         }
@@ -383,8 +382,8 @@ public class KubernetesExport extends Export {
         }
 
         Path settingsPath = 
CommandLineHelper.getWorkDir().resolve(Run.RUN_SETTINGS_FILE);
-        var jkubeVersion = Exporter.jkubeMavenPluginVersion(settingsPath, 
Exporter.mapBuildProperties(buildProperties));
-        var managementPort = Exporter.httpManagementPort(settingsPath);
+        var jkubeVersion = ExportHelper.jkubeMavenPluginVersion(settingsPath, 
ExportHelper.mapBuildProperties(buildProperties));
+        var managementPort = ExportHelper.httpManagementPort(settingsPath);
         buildProperties.add("jkube.version=%s".formatted(jkubeVersion));
 
         boolean cronJobEnabled = traitsSpec.getCronjob() != null

Reply via email to