This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch copy-shroud in repository https://gitbox.apache.org/repos/asf/camel.git
commit d1044c98603769a40a4306b542af249af0c442d0 Author: Guillaume Nodet <[email protected]> AuthorDate: Tue Mar 24 07:57:25 2026 +0100 CAMEL-23236: Add camel doctor diagnostic command New `camel doctor` command that checks the environment and reports: - Java version (21+ required) - JBang version - Camel version - Maven Central reachability - Docker daemon status - Common port conflicts (8080, 8443, 9090) - Disk space in temp directory Co-Authored-By: Claude Opus 4.6 <[email protected]> --- .../dsl/jbang/core/commands/CamelJBangMain.java | 1 + .../camel/dsl/jbang/core/commands/Doctor.java | 136 +++++++++++++++++++++ 2 files changed, 137 insertions(+) diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java index bd03af9ee39c..3a3f89a0bd3b 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/CamelJBangMain.java @@ -131,6 +131,7 @@ public class CamelJBangMain implements Callable<Integer> { .addSubcommand("runtime", new CommandLine(new DependencyRuntime(this))) .addSubcommand("update", new CommandLine(new DependencyUpdate(this)))) .addSubcommand("dirty", new CommandLine(new Dirty(this))) + .addSubcommand("doctor", new CommandLine(new Doctor(this))) .addSubcommand("eval", new CommandLine(new EvalCommand(this)) .addSubcommand("expression", new CommandLine(new EvalExpressionCommand(this)))) .addSubcommand("export", new CommandLine(new Export(this))) diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Doctor.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Doctor.java new file mode 100644 index 000000000000..7527f1fc5d53 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Doctor.java @@ -0,0 +1,136 @@ +/* + * 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.commands; + +import java.io.File; +import java.net.HttpURLConnection; +import java.net.URI; + +import org.apache.camel.catalog.CamelCatalog; +import org.apache.camel.catalog.DefaultCamelCatalog; +import org.apache.camel.dsl.jbang.core.common.VersionHelper; +import picocli.CommandLine.Command; + +@Command(name = "doctor", description = "Checks the environment and reports potential issues", + sortOptions = false, showDefaultValues = true) +public class Doctor extends CamelCommand { + + public Doctor(CamelJBangMain main) { + super(main); + } + + @Override + public Integer doCall() throws Exception { + printer().println("Camel JBang Doctor"); + printer().println("=================="); + printer().println(); + + checkJava(); + checkJBang(); + checkCamelVersion(); + checkMavenCentral(); + checkDocker(); + checkCommonPorts(); + checkDiskSpace(); + + return 0; + } + + private void checkJava() { + String version = System.getProperty("java.version"); + String vendor = System.getProperty("java.vendor", ""); + int major = Runtime.version().feature(); + String status = major >= 21 ? "OK" : "WARN (21+ required)"; + printer().printf(" Java: %s (%s) [%s]%n", version, vendor, status); + } + + private void checkJBang() { + String version = VersionHelper.getJBangVersion(); + if (version != null) { + printer().printf(" JBang: %s (OK)%n", version); + } else { + printer().printf(" JBang: not detected%n"); + } + } + + private void checkCamelVersion() { + CamelCatalog catalog = new DefaultCamelCatalog(); + String version = catalog.getCatalogVersion(); + printer().printf(" Camel: %s%n", version); + } + + private void checkMavenCentral() { + try { + HttpURLConnection conn = (HttpURLConnection) URI.create("https://repo1.maven.org/maven2/") + .toURL().openConnection(); + conn.setConnectTimeout(5000); + conn.setReadTimeout(5000); + conn.setRequestMethod("HEAD"); + int code = conn.getResponseCode(); + conn.disconnect(); + printer().printf(" Maven: %s%n", code == 200 ? "reachable (OK)" : "returned " + code); + } catch (Exception e) { + printer().printf(" Maven: unreachable (%s)%n", e.getMessage()); + } + } + + private void checkDocker() { + try { + Process p = new ProcessBuilder("docker", "info") + .redirectErrorStream(true) + .start(); + int exit = p.waitFor(); + printer().printf(" Docker: %s%n", exit == 0 ? "running (OK)" : "not running"); + } catch (Exception e) { + printer().printf(" Docker: not found%n"); + } + } + + private void checkCommonPorts() { + StringBuilder conflicts = new StringBuilder(); + for (int port : new int[] { 8080, 8443, 9090 }) { + if (isPortInUse(port)) { + if (!conflicts.isEmpty()) { + conflicts.append(", "); + } + conflicts.append(port); + } + } + if (!conflicts.isEmpty()) { + printer().printf(" Ports: in use: %s%n", conflicts); + } else { + printer().printf(" Ports: 8080, 8443, 9090 free (OK)%n"); + } + } + + private static boolean isPortInUse(int port) { + try (java.net.ServerSocket ss = new java.net.ServerSocket(port)) { + ss.setReuseAddress(true); + return false; + } catch (Exception e) { + return true; + } + } + + private void checkDiskSpace() { + File tmpDir = new File(System.getProperty("java.io.tmpdir")); + long free = tmpDir.getFreeSpace(); + long mb = free / (1024 * 1024); + String status = mb > 500 ? "OK" : "LOW"; + printer().printf(" Disk space: %d MB free in temp (%s)%n", mb, status); + } +}
