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 5c6edcdddb10 CAMEL-26912: camel-jbang - a drive letter on Windows is
not a scheme, and mvn is mvn.cmd (#29824)
5c6edcdddb10 is described below
commit 5c6edcdddb1096fdb6389985dc4734e6a624483d
Author: Claus Ibsen <[email protected]>
AuthorDate: Fri Nov 13 16:41:27 2026 +0100
CAMEL-26912: camel-jbang - a drive letter on Windows is not a scheme, and
mvn is mvn.cmd (#29824)
C:\\path was taken for a file with the scheme C, so the export dropped
absolute files, and a process cannot be started as mvn on Windows.
Co-Authored-By: Claude Opus 5.5 <[email protected]>
Signed-off-by: Claus Ibsen <[email protected]>
---
.../dsl/jbang/core/commands/CamelCommand.java | 6 ++-
.../camel/dsl/jbang/run/common/MavenCommand.java | 14 ++++--
.../camel/dsl/jbang/run/export/Exporter.java | 6 ++-
.../dsl/jbang/run/common/MavenCommandTest.java | 53 ++++++++++++++++++++++
.../camel/dsl/jbang/run/export/ExporterTest.java | 11 +++++
5 files changed, 85 insertions(+), 5 deletions(-)
diff --git
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelCommand.java
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelCommand.java
index ed001f6b7903..174f542d7945 100644
---
a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelCommand.java
+++
b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelCommand.java
@@ -234,9 +234,13 @@ public abstract class CamelCommand implements
Command<CommandInvocation>, Comman
return values != null ? values.toArray(new String[0]) : null;
}
+ /**
+ * The scheme of a file, such as classpath or github, or null for a file
without scheme. A single letter is the
+ * drive of a path on Windows (C:\work\route.camel.yaml), not a scheme
(CAMEL-26912).
+ */
protected static String getScheme(String name) {
int pos = name.indexOf(":");
- if (pos != -1) {
+ if (pos > 1) {
return name.substring(0, pos);
}
return null;
diff --git
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/common/MavenCommand.java
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/common/MavenCommand.java
index fa51644a869f..2fc3c0487b97 100644
---
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/common/MavenCommand.java
+++
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/common/MavenCommand.java
@@ -37,10 +37,18 @@ public final class MavenCommand {
}
/**
- * The Maven wrapper of the directory when it has one that can run, and
otherwise mvn.
+ * The Maven wrapper of the directory when it has one that can run, and
otherwise mvn (mvn.cmd on Windows, which a
+ * process cannot be started with as mvn).
*/
public static String of(Path dir) {
- Path wrapper = wrapper(dir);
- return Files.isExecutable(wrapper) ? wrapper.toString() : "mvn";
+ return of(dir, FileUtil.isWindows());
+ }
+
+ static String of(Path dir, boolean windows) {
+ Path wrapper = dir.resolve(windows ? "mvnw.cmd" : "mvnw");
+ if (Files.isExecutable(wrapper)) {
+ return wrapper.toString();
+ }
+ return windows ? "mvn.cmd" : "mvn";
}
}
diff --git
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/Exporter.java
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/Exporter.java
index a20af4603aaa..4c1c985dbd7c 100644
---
a/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/Exporter.java
+++
b/dsl/camel-jbang/camel-jbang-run/src/main/java/org/apache/camel/dsl/jbang/run/export/Exporter.java
@@ -1444,9 +1444,13 @@ abstract class Exporter {
copyApplicationPropertiesFiles(srcResourcesDir.toPath());
}
+ /**
+ * The scheme of a file, such as classpath or github, or null for a file
without scheme. A single letter is the
+ * drive of a path on Windows (C:\work\route.camel.yaml), not a scheme
(CAMEL-26912).
+ */
protected static String getScheme(String name) {
int pos = name.indexOf(":");
- if (pos != -1) {
+ if (pos > 1) {
return name.substring(0, pos);
}
return null;
diff --git
a/dsl/camel-jbang/camel-jbang-run/src/test/java/org/apache/camel/dsl/jbang/run/common/MavenCommandTest.java
b/dsl/camel-jbang/camel-jbang-run/src/test/java/org/apache/camel/dsl/jbang/run/common/MavenCommandTest.java
new file mode 100644
index 000000000000..717719b7fcc3
--- /dev/null
+++
b/dsl/camel-jbang/camel-jbang-run/src/test/java/org/apache/camel/dsl/jbang/run/common/MavenCommandTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.run.common;
+
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+import org.apache.camel.util.FileUtil;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.DisabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+import org.junit.jupiter.api.io.TempDir;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * The Maven that builds a project: its wrapper, else mvn from the path.
+ */
+class MavenCommandTest {
+
+ @TempDir
+ Path dir;
+
+ @Test
+ void mvnFromThePathWithoutWrapper() {
+ assertThat(MavenCommand.of(dir, false)).isEqualTo("mvn");
+ // a process cannot be started as mvn on Windows, where it is mvn.cmd
+ assertThat(MavenCommand.of(dir, true)).isEqualTo("mvn.cmd");
+ }
+
+ @Test
+ @DisabledOnOs(value = OS.WINDOWS, disabledReason = "a file is executable
on Windows without the permission")
+ void theWrapperOfTheProject() throws Exception {
+ Path mvnw = Files.writeString(dir.resolve("mvnw"), "#!/bin/sh");
+ assertThat(MavenCommand.of(dir, false)).isEqualTo("mvn");
+ FileUtil.setPosixFilePermissions(mvnw, "rwxr-xr-x");
+ assertThat(MavenCommand.of(dir, false)).isEqualTo(mvnw.toString());
+ }
+}
diff --git
a/dsl/camel-jbang/camel-jbang-run/src/test/java/org/apache/camel/dsl/jbang/run/export/ExporterTest.java
b/dsl/camel-jbang/camel-jbang-run/src/test/java/org/apache/camel/dsl/jbang/run/export/ExporterTest.java
index c6604242803e..03c613f04ce2 100644
---
a/dsl/camel-jbang/camel-jbang-run/src/test/java/org/apache/camel/dsl/jbang/run/export/ExporterTest.java
+++
b/dsl/camel-jbang/camel-jbang-run/src/test/java/org/apache/camel/dsl/jbang/run/export/ExporterTest.java
@@ -35,4 +35,15 @@ class ExporterTest {
.containsEntry("id", "custom1")
.containsEntry("url", "https://other.repo/releases");
}
+
+ @Test
+ public void aDriveOfWindowsIsNoScheme() {
+
assertThat(Exporter.getScheme("classpath:tls/keystore.jks")).isEqualTo("classpath");
+
assertThat(Exporter.getScheme("file:C:\\certs\\keystore.jks")).isEqualTo("file");
+
assertThat(Exporter.getScheme("github:apache:camel-kamelets-examples:jbang/hello-java")).isEqualTo("github");
+ // the export kept \certs\keystore.jks of it, which is not the file
+ assertThat(Exporter.getScheme("C:\\certs\\keystore.jks")).isNull();
+ assertThat(Exporter.getScheme("c:/certs/keystore.jks")).isNull();
+ assertThat(Exporter.getScheme("route.camel.yaml")).isNull();
+ }
}