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

fmariani pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel.git

commit 15c6bef81e00a6f13ae5c0317be5d8f1e042281f
Author: Croway <[email protected]>
AuthorDate: Tue Apr 7 12:21:23 2026 +0200

    CAMEL-23276: Add PluginRunCustomizer to JBang Plugin SPI
---
 .../apache/camel/dsl/jbang/core/commands/Run.java  | 10 ++-
 .../apache/camel/dsl/jbang/core/common/Plugin.java | 10 +++
 .../{Plugin.java => PluginRunCustomizer.java}      | 35 +++++------
 .../jbang/core/common/PluginRunCustomizerTest.java | 73 ++++++++++++++++++++++
 4 files changed, 107 insertions(+), 21 deletions(-)

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 864199a38804..5794c634601a 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
@@ -967,8 +967,11 @@ public class Run extends CamelCommand {
         addRuntimeSpecificDependenciesFromProperties(profileProperties);
 
         // Add plugin dependencies
+        Map<String, Plugin> activePlugins = Collections.emptyMap();
         if (!skipPlugins) {
-            Set<PluginExporter> exporters = 
PluginHelper.getActivePlugins(getMain(), repositories).values()
+            activePlugins = PluginHelper.getActivePlugins(getMain(), 
repositories);
+
+            Set<PluginExporter> exporters = activePlugins.values()
                     .stream()
                     .map(Plugin::getExporter)
                     .filter(Optional::isPresent)
@@ -991,6 +994,11 @@ public class Run extends CamelCommand {
             writeSettings(DEPENDENCIES, joined);
         }
 
+        // Let plugins customize the run before KameletMain starts
+        for (Plugin plugin : activePlugins.values()) {
+            plugin.getRunCustomizer().ifPresent(customizer -> 
customizer.beforeRun(main, files));
+        }
+
         // Block --camel-version when running from camel-launcher
         if (camelVersion != null && LauncherHelper.isRunningFromLauncher()) {
             printer().printErr("The --camel-version option is not supported 
when running from camel-launcher.");
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/Plugin.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/Plugin.java
index 12db1df2eee9..8571418b5f2d 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/Plugin.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/Plugin.java
@@ -42,4 +42,14 @@ public interface Plugin {
     default Optional<PluginExporter> getExporter() {
         return Optional.empty();
     }
+
+    /**
+     * The plugin may provide an optional run customizer that is called after 
the Run command has resolved file
+     * arguments and configured dependencies, but before KameletMain.run() 
builds the CamelContext.
+     *
+     * @return the plugin specific run customizer implementation, otherwise 
empty
+     */
+    default Optional<PluginRunCustomizer> getRunCustomizer() {
+        return Optional.empty();
+    }
 }
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/Plugin.java
 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginRunCustomizer.java
similarity index 50%
copy from 
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/Plugin.java
copy to 
dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginRunCustomizer.java
index 12db1df2eee9..b0c64f653324 100644
--- 
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/Plugin.java
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginRunCustomizer.java
@@ -16,30 +16,25 @@
  */
 package org.apache.camel.dsl.jbang.core.common;
 
-import java.util.Optional;
+import java.util.List;
 
-import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
-import picocli.CommandLine;
+import org.apache.camel.main.KameletMain;
 
-@FunctionalInterface
-public interface Plugin {
-
-    /**
-     * Customize given command line adding sub-commands in particular.
-     *
-     * @param commandLine the command line to adjust.
-     * @param main        the current JBang main.
-     */
-    void customize(CommandLine commandLine, CamelJBangMain main);
+/**
+ * Plugin hook that runs after the Run command has resolved file arguments and 
configured dependencies, but before
+ * {@link KameletMain#run()} builds the CamelContext.
+ *
+ * This allows plugins to customize the environment (system properties, config 
directories, initial properties) based on
+ * the file arguments passed to the run command.
+ */
+public interface PluginRunCustomizer {
 
     /**
-     * The plugin may provide an optional project exporter implementation that 
is able to participate in an export
-     * performed by Camel JBang. Project exporter implementations may add 
properties and dependencies to the generated
-     * export.
+     * Called after the Run command has resolved file arguments and configured 
dependencies, but before
+     * KameletMain.run() builds the CamelContext.
      *
-     * @return the plugin specific exporter implementation, otherwise empty
+     * @param main  the KameletMain instance (for adding initial properties)
+     * @param files the resolved file arguments passed to the run command
      */
-    default Optional<PluginExporter> getExporter() {
-        return Optional.empty();
-    }
+    void beforeRun(KameletMain main, List<String> files);
 }
diff --git 
a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/PluginRunCustomizerTest.java
 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/PluginRunCustomizerTest.java
new file mode 100644
index 000000000000..9fc851b7db94
--- /dev/null
+++ 
b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/common/PluginRunCustomizerTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.core.common;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+
+import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain;
+import org.apache.camel.main.KameletMain;
+import org.junit.jupiter.api.Test;
+import picocli.CommandLine;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+public class PluginRunCustomizerTest {
+
+    @Test
+    public void testPluginDefaultReturnsEmpty() {
+        Plugin plugin = (commandLine, main) -> {
+            // no-op
+        };
+
+        assertTrue(plugin.getRunCustomizer().isEmpty());
+    }
+
+    @Test
+    public void testPluginWithRunCustomizer() {
+        List<String> capturedFiles = new ArrayList<>();
+        boolean[] called = { false };
+
+        PluginRunCustomizer customizer = (main, files) -> {
+            called[0] = true;
+            capturedFiles.addAll(files);
+        };
+
+        Plugin plugin = new Plugin() {
+            @Override
+            public void customize(CommandLine commandLine, CamelJBangMain 
main) {
+                // no-op
+            }
+
+            @Override
+            public Optional<PluginRunCustomizer> getRunCustomizer() {
+                return Optional.of(customizer);
+            }
+        };
+
+        Optional<PluginRunCustomizer> result = plugin.getRunCustomizer();
+        assertTrue(result.isPresent());
+
+        // Simulate invoking the customizer
+        List<String> testFiles = List.of("route.yaml", "beans.xml");
+        result.get().beforeRun(new KameletMain("test"), testFiles);
+
+        assertTrue(called[0]);
+        assertEquals(testFiles, capturedFiles);
+    }
+}

Reply via email to