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 66f66d9f701e025b99d8ac8297f2a65c68d14cac Author: Croway <[email protected]> AuthorDate: Mon Jan 19 11:39:33 2026 +0100 CAMEL-22876: camel-launcher - handle jbang dependency in camel-jbang-core --- .../camel/dsl/jbang/core/commands/Debug.java | 2 +- .../apache/camel/dsl/jbang/core/commands/Run.java | 12 +- .../camel/dsl/jbang/core/commands/RunHelper.java | 10 +- .../dsl/jbang/core/commands/infra/InfraRun.java | 4 +- .../dsl/jbang/core/common/LauncherHelper.java | 132 +++++++++++++++++++++ .../camel/dsl/jbang/launcher/CamelLauncher.java | 40 +++++++ 6 files changed, 189 insertions(+), 11 deletions(-) diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Debug.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Debug.java index 87b5d71c2fee..22e40f95070d 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Debug.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Debug.java @@ -584,7 +584,7 @@ public class Debug extends Run { cmds.add("--prop=camel.debug.loggingLevel=DEBUG"); cmds.add("--prop=camel.debug.singleStepIncludeStartEnd=true"); - RunHelper.addCamelJBangCommand(cmds); + RunHelper.addCamelCLICommand(cmds); ProcessBuilder pb = new ProcessBuilder(); pb.command(cmds); 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 c128e3ee4802..8e67e5be802e 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 @@ -43,6 +43,7 @@ import java.util.stream.Stream; import org.apache.camel.catalog.CamelCatalog; import org.apache.camel.catalog.DefaultCamelCatalog; import org.apache.camel.dsl.jbang.core.common.CommandLineHelper; +import org.apache.camel.dsl.jbang.core.common.LauncherHelper; import org.apache.camel.dsl.jbang.core.common.LoggingLevelCompletionCandidates; import org.apache.camel.dsl.jbang.core.common.Printer; import org.apache.camel.dsl.jbang.core.common.PropertyResolver; @@ -995,6 +996,15 @@ public class Run extends CamelCommand { writeSettings(DEPENDENCIES, joined); } + // 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."); + printer().printErr("To use a different Camel version, either:"); + printer().printErr(" 1. Use a different camel-launcher JAR version"); + printer().printErr(" 2. Install Camel CLI via JBang: jbang app install camel@apache/camel"); + return 1; + } + // if we have a specific camel version then make sure we really need to switch if (camelVersion != null) { CamelCatalog catalog = new DefaultCamelCatalog(); @@ -1529,7 +1539,7 @@ public class Run extends CamelCommand { cmds.remove("--background-wait=true"); cmds.remove("--background-wait"); - RunHelper.addCamelJBangCommand(cmds); + RunHelper.addCamelCLICommand(cmds); ProcessBuilder pb = new ProcessBuilder(); pb.command(cmds); diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/RunHelper.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/RunHelper.java index 4cdf6dcd3c85..b7aa8830316d 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/RunHelper.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/RunHelper.java @@ -30,6 +30,7 @@ import java.util.stream.Stream; import org.apache.camel.catalog.CamelCatalog; import org.apache.camel.catalog.DefaultCamelCatalog; +import org.apache.camel.dsl.jbang.core.common.LauncherHelper; import org.apache.camel.main.download.MavenDependencyDownloader; import org.apache.camel.tooling.maven.MavenArtifact; import org.apache.camel.util.FileUtil; @@ -305,12 +306,7 @@ public final class RunHelper { * Adds camel to the start of the list of commands to make it possible to run camel-jbang using a spawned process * (to run in background). */ - public static void addCamelJBangCommand(List<String> cmds) { - if (FileUtil.isWindows()) { - String jbangDir = System.getenv().getOrDefault("JBANG_DIR", System.getProperty("user.home") + "\\.jbang"); - cmds.add(0, jbangDir + "\\bin\\camel.cmd"); - } else { - cmds.add(0, "camel"); - } + public static void addCamelCLICommand(List<String> cmds) { + cmds.addAll(0, LauncherHelper.getCamelCommand()); } } diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraRun.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraRun.java index 41fab4f40af5..b61559d71456 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraRun.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/infra/InfraRun.java @@ -39,7 +39,7 @@ import org.apache.camel.main.download.MavenDependencyDownloader; import org.apache.camel.tooling.maven.MavenArtifact; import picocli.CommandLine; -import static org.apache.camel.dsl.jbang.core.commands.RunHelper.addCamelJBangCommand; +import static org.apache.camel.dsl.jbang.core.commands.RunHelper.addCamelCLICommand; @CommandLine.Command(name = "run", description = "Run an external service", sortOptions = false, showDefaultValues = true) public class InfraRun extends InfraBaseCommand { @@ -122,7 +122,7 @@ public class InfraRun extends InfraBaseCommand { cmds.remove("--background=true"); cmds.remove("--background"); - addCamelJBangCommand(cmds); + addCamelCLICommand(cmds); ProcessBuilder pb = new ProcessBuilder(); pb.command(cmds); diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/LauncherHelper.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/LauncherHelper.java new file mode 100644 index 000000000000..8c7f5fc4bd44 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/LauncherHelper.java @@ -0,0 +1,132 @@ +/* + * 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.io.File; +import java.net.URL; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; + +import org.apache.camel.util.FileUtil; + +/** + * Helper class for detecting and working with the camel-launcher runtime. + */ +public final class LauncherHelper { + + public static final String CAMEL_LAUNCHER_PROPERTY = "camel.launcher"; + public static final String CAMEL_LAUNCHER_JAR_PROPERTY = "camel.launcher.jar"; + + private LauncherHelper() { + } + + /** + * Detects if running from camel-launcher (fat JAR) vs JBang. + */ + public static boolean isRunningFromLauncher() { + // Check system property (set by CamelLauncher) + if ("true".equalsIgnoreCase(System.getProperty(CAMEL_LAUNCHER_PROPERTY))) { + return true; + } + + // Check JAR path as fallback + String jarPath = getLauncherJarPath(); + return jarPath != null && jarPath.contains("camel-launcher"); + } + + /** + * Gets the path to the launcher JAR file. + */ + public static String getLauncherJarPath() { + // 1. Check system property first + String jarPath = System.getProperty(CAMEL_LAUNCHER_JAR_PROPERTY); + if (jarPath != null && !jarPath.isEmpty()) { + return jarPath; + } + + // 2. Try to detect from code source location + try { + URL location = LauncherHelper.class.getProtectionDomain() + .getCodeSource().getLocation(); + if (location != null) { + String urlStr = location.toString(); + // Handle nested JAR (Spring Boot loader) + if (urlStr.startsWith("jar:file:")) { + int idx = urlStr.indexOf("!/"); + if (idx > 0) { + String path = urlStr.substring(9, idx); + // Decode URL-encoded characters (spaces, special chars) + return URLDecoder.decode(path, StandardCharsets.UTF_8); + } + } + // Handle direct file URL + if (urlStr.startsWith("file:")) { + String path = urlStr.substring(5); + return URLDecoder.decode(path, StandardCharsets.UTF_8); + } + } + } catch (Exception e) { + System.err.println("WARN: Failed to detect launcher JAR path: " + e.getMessage()); + } + return null; + } + + /** + * Gets the command to spawn a new camel process. + */ + public static List<String> getCamelCommand() { + List<String> cmds = new ArrayList<>(); + + if (isRunningFromLauncher()) { + String jarPath = getLauncherJarPath(); + if (jarPath != null) { + cmds.add(getJavaCommand()); + cmds.add("-jar"); + cmds.add(jarPath); + return cmds; + } + } + + // Fall back to JBang-style command + if (FileUtil.isWindows()) { + String jbangDir = System.getenv().getOrDefault("JBANG_DIR", + System.getProperty("user.home") + "\\.jbang"); + cmds.add(jbangDir + "\\bin\\camel.cmd"); + } else { + cmds.add("camel"); + } + return cmds; + } + + private static String getJavaCommand() { + String javaHome = System.getProperty("java.home"); + if (javaHome != null) { + StringBuilder javaBin = new StringBuilder(javaHome); + javaBin.append(File.separator).append("bin").append(File.separator).append("java"); + if (FileUtil.isWindows()) { + javaBin.append(".exe"); + } + File javaBinFile = new File(javaBin.toString()); + if (javaBinFile.exists()) { + return javaBin.toString(); + } + } + return "java"; + } +} diff --git a/dsl/camel-jbang/camel-launcher/src/main/java/org/apache/camel/dsl/jbang/launcher/CamelLauncher.java b/dsl/camel-jbang/camel-launcher/src/main/java/org/apache/camel/dsl/jbang/launcher/CamelLauncher.java index 3dc4c9b92b15..b86976b1a464 100644 --- a/dsl/camel-jbang/camel-launcher/src/main/java/org/apache/camel/dsl/jbang/launcher/CamelLauncher.java +++ b/dsl/camel-jbang/camel-launcher/src/main/java/org/apache/camel/dsl/jbang/launcher/CamelLauncher.java @@ -16,6 +16,10 @@ */ package org.apache.camel.dsl.jbang.launcher; +import java.net.URL; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; + import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain; /** @@ -32,6 +36,42 @@ public class CamelLauncher { * @param args command line arguments to pass to Camel JBang */ public static void main(String... args) { + // Set system property to indicate we're running from the launcher + System.setProperty("camel.launcher", "true"); + + // Try to determine and set the JAR path + String jarPath = detectJarPath(); + if (jarPath != null) { + System.setProperty("camel.launcher.jar", jarPath); + } + CamelJBangMain.run(args); } + + private static String detectJarPath() { + try { + URL location = CamelLauncher.class.getProtectionDomain() + .getCodeSource().getLocation(); + if (location != null) { + String urlStr = location.toString(); + // Handle nested JAR (Spring Boot loader) + if (urlStr.startsWith("jar:file:")) { + int idx = urlStr.indexOf("!/"); + if (idx > 0) { + String path = urlStr.substring(9, idx); + // Decode URL-encoded characters (spaces, special chars) + return URLDecoder.decode(path, StandardCharsets.UTF_8); + } + } + // Handle direct file URL + if (urlStr.startsWith("file:")) { + String path = urlStr.substring(5); + return URLDecoder.decode(path, StandardCharsets.UTF_8); + } + } + } catch (Exception e) { + System.err.println("WARN: Failed to detect launcher JAR path: " + e.getMessage()); + } + return null; + } }
