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
commit 462c4e8ff30a1fca46c1ba6d3e5b75d7c2d70c61 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Fri Aug 26 12:30:07 2022 +0200 CAMEL-18425: camel-cli - Make regular Camel applications work with Camel CLI --- .../org/apache/camel/spi/CliConnectorFactory.java | 10 ++ .../cli/connector/DefaultCliConnectorFactory.java | 11 ++ .../camel/cli/connector/LocalCliConnector.java | 12 +- .../core/commands/process/CamelContextStatus.java | 101 +++++++--------- .../core/commands/process/CamelRouteStatus.java | 134 +++++++++------------ .../jbang/core/commands/process/ListProcess.java | 62 ++++++---- .../core/commands/process/ProcessBaseCommand.java | 84 +++++++++++-- 7 files changed, 240 insertions(+), 174 deletions(-) diff --git a/core/camel-api/src/main/java/org/apache/camel/spi/CliConnectorFactory.java b/core/camel-api/src/main/java/org/apache/camel/spi/CliConnectorFactory.java index 6d34675eace..ef323b6025d 100644 --- a/core/camel-api/src/main/java/org/apache/camel/spi/CliConnectorFactory.java +++ b/core/camel-api/src/main/java/org/apache/camel/spi/CliConnectorFactory.java @@ -60,6 +60,16 @@ public interface CliConnectorFactory { */ String getRuntimeVersion(); + /** + * The main class used by the runtime to start. + */ + void setRuntimeStartClass(String className); + + /** + * The main class used by the runtime to start. + */ + String getRuntimeStartClass(); + /** * Creates the connector which will be added as a {@link Service} to {@link org.apache.camel.CamelContext} as the * lifecycle to start and stop the connector. diff --git a/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/DefaultCliConnectorFactory.java b/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/DefaultCliConnectorFactory.java index 07f59815f6e..2f70726cbf0 100644 --- a/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/DefaultCliConnectorFactory.java +++ b/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/DefaultCliConnectorFactory.java @@ -26,6 +26,7 @@ public class DefaultCliConnectorFactory implements CliConnectorFactory { private boolean enabled = true; private String runtime; private String runtimeVersion; + private String runtimeStartClass; @Override public boolean isEnabled() { @@ -55,6 +56,16 @@ public class DefaultCliConnectorFactory implements CliConnectorFactory { this.runtimeVersion = runtimeVersion; } + @Override + public String getRuntimeStartClass() { + return runtimeStartClass; + } + + @Override + public void setRuntimeStartClass(String runtimeStartClass) { + this.runtimeStartClass = runtimeStartClass; + } + @Override public Service createConnector() { if (enabled) { diff --git a/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java b/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java index 60500113d95..34fbb5a62ff 100644 --- a/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java +++ b/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java @@ -49,6 +49,7 @@ public class LocalCliConnector extends ServiceSupport implements CamelContextAwa private int delay = 2000; private String platform; private String platformVersion; + private String mainClass; private ScheduledExecutorService executor; private File lockFile; private File statusFile; @@ -76,10 +77,11 @@ public class LocalCliConnector extends ServiceSupport implements CamelContextAwa if (lockFile != null) { statusFile = createLockFile(lockFile.getName() + "-status.json"); } - executor.scheduleWithFixedDelay(this::statusTask, 1000, delay, TimeUnit.MILLISECONDS); + executor.scheduleWithFixedDelay(this::statusTask, 0, delay, TimeUnit.MILLISECONDS); // what platform are we running CliConnectorFactory ccf = camelContext.adapt(ExtendedCamelContext.class).getCliConnectorFactory(); + mainClass = ccf.getRuntimeStartClass(); platform = ccf.getRuntime(); if (platform == null) { // use camel context name to guess platform if not specified @@ -125,10 +127,18 @@ public class LocalCliConnector extends ServiceSupport implements CamelContextAwa // what runtime are in use JsonObject rc = new JsonObject(); + String dir = new File(".").getAbsolutePath(); + dir = FileUtil.onlyPath(dir); + rc.put("pid", ProcessHandle.current().pid()); + rc.put("directory", dir); + ProcessHandle.current().info().user().ifPresent(u -> rc.put("user", u)); rc.put("platform", platform); if (platformVersion != null) { rc.put("version", platformVersion); } + if (mainClass != null) { + rc.put("mainClass", mainClass); + } root.put("runtime", rc); // collect details via console diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextStatus.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextStatus.java index 64edfda5faf..9e43658d841 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextStatus.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelContextStatus.java @@ -16,8 +16,6 @@ */ package org.apache.camel.dsl.jbang.core.commands.process; -import java.io.File; -import java.io.FileInputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -29,12 +27,8 @@ import com.github.freva.asciitable.Column; import com.github.freva.asciitable.HorizontalAlign; import com.github.freva.asciitable.OverflowBehaviour; import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain; -import org.apache.camel.util.IOHelper; -import org.apache.camel.util.ObjectHelper; -import org.apache.camel.util.StringHelper; import org.apache.camel.util.TimeUtils; import org.apache.camel.util.json.JsonObject; -import org.apache.camel.util.json.Jsoner; import picocli.CommandLine; import picocli.CommandLine.Command; @@ -60,50 +54,40 @@ public class CamelContextStatus extends ProcessBaseCommand { List<Long> pids = findPids(name); ProcessHandle.allProcesses() .filter(ph -> pids.contains(ph.pid())) - .sorted((o1, o2) -> { - switch (sort) { - case "pid": - return Long.compare(o1.pid(), o2.pid()); - case "name": - return extractName(o1).compareTo(extractName(o2)); - case "age": - // we want newest in top - return Long.compare(extractSince(o1), extractSince(o2)) * -1; - default: - return 0; - } - }) .forEach(ph -> { - Row row = new Row(); - row.name = extractName(ph); - if (ObjectHelper.isNotEmpty(row.name)) { + JsonObject root = loadStatus(ph.pid()); + // there must be a status file for the running Camel integration + if (root != null) { + Row row = new Row(); + row.name = extractName(root, ph); row.pid = "" + ph.pid(); - row.ago = TimeUtils.printSince(extractSince(ph)); - JsonObject root = loadStatus(ph.pid()); - if (root != null) { - JsonObject runtime = (JsonObject) root.get("runtime"); - row.platform = runtime != null ? runtime.getString("platform") : null; - row.platformVersion = runtime != null ? runtime.getString("version") : null; - JsonObject context = (JsonObject) root.get("context"); - row.state = context.getString("state").toLowerCase(Locale.ROOT); - row.camelVersion = context.getString("version"); - Map<String, ?> stats = context.getMap("statistics"); - if (stats != null) { - row.total = stats.get("exchangesTotal").toString(); - row.inflight = stats.get("exchangesInflight").toString(); - row.failed = stats.get("exchangesFailed").toString(); - Object last = stats.get("sinceLastExchange"); - if (last != null) { - row.sinceLast = last.toString(); - } + row.uptime = extractSince(ph); + row.ago = TimeUtils.printSince(row.uptime); + JsonObject runtime = (JsonObject) root.get("runtime"); + row.platform = runtime != null ? runtime.getString("platform") : null; + row.platformVersion = runtime != null ? runtime.getString("version") : null; + JsonObject context = (JsonObject) root.get("context"); + row.state = context.getString("state").toLowerCase(Locale.ROOT); + row.camelVersion = context.getString("version"); + Map<String, ?> stats = context.getMap("statistics"); + if (stats != null) { + row.total = stats.get("exchangesTotal").toString(); + row.inflight = stats.get("exchangesInflight").toString(); + row.failed = stats.get("exchangesFailed").toString(); + Object last = stats.get("sinceLastExchange"); + if (last != null) { + row.sinceLast = last.toString(); } - JsonObject hc = (JsonObject) root.get("healthChecks"); - row.ready = hc != null ? hc.getString("ready") + "/" + hc.getString("total") : null; } + JsonObject hc = (JsonObject) root.get("healthChecks"); + row.ready = hc != null ? hc.getString("ready") + "/" + hc.getString("total") : null; rows.add(row); } }); + // sort rows + rows.sort(this::sortRow); + if (!rows.isEmpty()) { System.out.println(AsciiTable.getTable(AsciiTable.NO_BORDERS, rows, Arrays.asList( new Column().header("PID").headerAlign(HorizontalAlign.CENTER).with(r -> r.pid), @@ -112,8 +96,8 @@ public class CamelContextStatus extends ProcessBaseCommand { new Column().header("CAMEL").dataAlign(HorizontalAlign.LEFT).with(r -> r.camelVersion), new Column().header("PLATFORM").dataAlign(HorizontalAlign.LEFT).with(this::getPlatform), new Column().header("READY").dataAlign(HorizontalAlign.CENTER).with(r -> r.ready), - new Column().header("STATE").headerAlign(HorizontalAlign.CENTER) - .with(r -> StringHelper.capitalize(r.state)), + new Column().header("STATUS").headerAlign(HorizontalAlign.CENTER) + .with(r -> extractState(r.state)), new Column().header("AGE").headerAlign(HorizontalAlign.CENTER).with(r -> r.ago), new Column().header("TOTAL").with(r -> r.total), new Column().header("FAILED").with(r -> r.failed), @@ -124,6 +108,19 @@ public class CamelContextStatus extends ProcessBaseCommand { return 0; } + protected int sortRow(Row o1, Row o2) { + switch (sort) { + case "pid": + return Long.compare(Long.parseLong(o1.pid), Long.parseLong(o2.pid)); + case "name": + return o1.name.compareToIgnoreCase(o2.name); + case "age": + return Long.compare(o1.uptime, o2.uptime); + default: + return 0; + } + } + private String getPlatform(Row r) { if (r.platformVersion != null) { return r.platform + " v" + r.platformVersion; @@ -132,21 +129,6 @@ public class CamelContextStatus extends ProcessBaseCommand { } } - private JsonObject loadStatus(long pid) { - try { - File f = getStatusFile("" + pid); - if (f != null) { - FileInputStream fis = new FileInputStream(f); - String text = IOHelper.loadText(fis); - IOHelper.close(fis); - return (JsonObject) Jsoner.deserialize(text); - } - } catch (Throwable e) { - // ignore - } - return null; - } - private static class Row { String pid; String platform; @@ -156,6 +138,7 @@ public class CamelContextStatus extends ProcessBaseCommand { String ready; String state; String ago; + long uptime; String total; String failed; String inflight; diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteStatus.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteStatus.java index 62267d0efca..9bcdf49c06d 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteStatus.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/CamelRouteStatus.java @@ -16,8 +16,6 @@ */ package org.apache.camel.dsl.jbang.core.commands.process; -import java.io.File; -import java.io.FileInputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -30,12 +28,10 @@ import com.github.freva.asciitable.HorizontalAlign; import com.github.freva.asciitable.OverflowBehaviour; import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain; import org.apache.camel.util.FileUtil; -import org.apache.camel.util.IOHelper; -import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.StringHelper; +import org.apache.camel.util.TimeUtils; import org.apache.camel.util.json.JsonArray; import org.apache.camel.util.json.JsonObject; -import org.apache.camel.util.json.Jsoner; import picocli.CommandLine; import picocli.CommandLine.Command; @@ -68,63 +64,49 @@ public class CamelRouteStatus extends ProcessBaseCommand { List<Long> pids = findPids(name); ProcessHandle.allProcesses() .filter(ph -> pids.contains(ph.pid())) - .sorted((o1, o2) -> { - switch (sort) { - case "pid": - return Long.compare(o1.pid(), o2.pid()); - case "name": - return extractName(o1).compareTo(extractName(o2)); - case "age": - // we want newest in top - return Long.compare(extractSince(o1), extractSince(o2)) * -1; - default: - return 0; - } - }) .forEach(ph -> { - String name = extractName(ph); - if (ObjectHelper.isNotEmpty(name)) { - JsonObject status = loadStatus(ph.pid()); - if (status != null) { - JsonArray array = (JsonArray) status.get("routes"); - for (int i = 0; i < array.size(); i++) { - JsonObject o = (JsonObject) array.get(i); - Row row = new Row(); - row.pid = "" + ph.pid(); - row.name = name; - row.routeId = o.getString("routeId"); - row.from = o.getString("from"); - row.source = o.getString("source"); - row.state = o.getString("state").toLowerCase(Locale.ROOT); - row.uptime = o.getString("uptime"); - Map<String, ?> stats = o.getMap("statistics"); - if (stats != null) { - row.total = stats.get("exchangesTotal").toString(); - row.inflight = stats.get("exchangesInflight").toString(); - row.failed = stats.get("exchangesFailed").toString(); - row.mean = stats.get("meanProcessingTime").toString(); - if ("-1".equals(row.mean)) { - row.mean = null; - } - row.max = stats.get("maxProcessingTime").toString(); - row.min = stats.get("minProcessingTime").toString(); - Object last = stats.get("sinceLastExchange"); - if (last != null) { - row.sinceLast = last.toString(); - } - } - - boolean add = true; - if (mean > 0 && row.mean != null && Long.parseLong(row.mean) < mean) { - add = false; - } - if (limit > 0 && rows.size() >= limit) { - add = false; + JsonObject root = loadStatus(ph.pid()); + if (root != null) { + String name = extractName(root, ph); + JsonArray array = (JsonArray) root.get("routes"); + for (int i = 0; i < array.size(); i++) { + JsonObject o = (JsonObject) array.get(i); + Row row = new Row(); + row.name = name; + row.pid = "" + ph.pid(); + row.routeId = o.getString("routeId"); + row.from = o.getString("from"); + row.source = o.getString("source"); + row.state = o.getString("state").toLowerCase(Locale.ROOT); + row.age = o.getString("uptime"); + row.uptime = row.age != null ? TimeUtils.toMilliSeconds(row.age) : 0; + Map<String, ?> stats = o.getMap("statistics"); + if (stats != null) { + row.total = stats.get("exchangesTotal").toString(); + row.inflight = stats.get("exchangesInflight").toString(); + row.failed = stats.get("exchangesFailed").toString(); + row.mean = stats.get("meanProcessingTime").toString(); + if ("-1".equals(row.mean)) { + row.mean = null; } - if (add) { - rows.add(row); + row.max = stats.get("maxProcessingTime").toString(); + row.min = stats.get("minProcessingTime").toString(); + Object last = stats.get("sinceLastExchange"); + if (last != null) { + row.sinceLast = last.toString(); } } + + boolean add = true; + if (mean > 0 && row.mean != null && Long.parseLong(row.mean) < mean) { + add = false; + } + if (limit > 0 && rows.size() >= limit) { + add = false; + } + if (add) { + rows.add(row); + } } } }); @@ -143,9 +125,9 @@ public class CamelRouteStatus extends ProcessBaseCommand { .with(r -> r.routeId), new Column().header("FROM").dataAlign(HorizontalAlign.LEFT).maxWidth(40, OverflowBehaviour.ELLIPSIS) .with(r -> r.from), - new Column().header("STATE").headerAlign(HorizontalAlign.CENTER) - .with(r -> StringHelper.capitalize(r.state)), - new Column().header("AGE").headerAlign(HorizontalAlign.CENTER).with(r -> r.uptime), + new Column().header("STATUS").headerAlign(HorizontalAlign.CENTER) + .with(r -> extractState(r.state)), + new Column().header("AGE").headerAlign(HorizontalAlign.CENTER).with(r -> r.age), new Column().header("TOTAL").with(r -> r.total), new Column().header("FAILED").with(r -> r.failed), new Column().header("INFLIGHT").with(r -> r.inflight), @@ -158,21 +140,6 @@ public class CamelRouteStatus extends ProcessBaseCommand { return 0; } - private JsonObject loadStatus(long pid) { - try { - File f = getStatusFile("" + pid); - if (f != null) { - FileInputStream fis = new FileInputStream(f); - String text = IOHelper.loadText(fis); - IOHelper.close(fis); - return (JsonObject) Jsoner.deserialize(text); - } - } catch (Throwable e) { - // ignore - } - return null; - } - protected String sourceLocLine(String location) { while (StringHelper.countChar(location, ':') > 1) { location = location.substring(location.indexOf(':') + 1); @@ -190,18 +157,27 @@ public class CamelRouteStatus extends ProcessBaseCommand { } protected int sortRow(Row o1, Row o2) { - // no sort by default - return 0; + switch (sort) { + case "pid": + return Long.compare(Long.parseLong(o1.pid), Long.parseLong(o2.pid)); + case "name": + return o1.name.compareToIgnoreCase(o2.name); + case "age": + return Long.compare(o1.uptime, o2.uptime); + default: + return 0; + } } static class Row { String pid; String name; + long uptime; String routeId; String from; String source; - String uptime; String state; + String age; String total; String failed; String inflight; diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListProcess.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListProcess.java index cb1046c55c8..0c00c56ddaf 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListProcess.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListProcess.java @@ -19,14 +19,15 @@ package org.apache.camel.dsl.jbang.core.commands.process; import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.Locale; import com.github.freva.asciitable.AsciiTable; import com.github.freva.asciitable.Column; import com.github.freva.asciitable.HorizontalAlign; import com.github.freva.asciitable.OverflowBehaviour; import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain; -import org.apache.camel.util.ObjectHelper; import org.apache.camel.util.TimeUtils; +import org.apache.camel.util.json.JsonObject; import picocli.CommandLine; import picocli.CommandLine.Command; @@ -45,47 +46,62 @@ public class ListProcess extends ProcessBaseCommand { public Integer call() throws Exception { List<Row> rows = new ArrayList<>(); - final long cur = ProcessHandle.current().pid(); + List<Long> pids = findPids("*"); ProcessHandle.allProcesses() - .filter(ph -> ph.pid() != cur) - .sorted((o1, o2) -> { - switch (sort) { - case "pid": - return Long.compare(o1.pid(), o2.pid()); - case "name": - return extractName(o1).compareTo(extractName(o2)); - case "age": - // we want newest in top - return Long.compare(extractSince(o1), extractSince(o2)) * -1; - default: - return 0; - } - }) + .filter(ph -> pids.contains(ph.pid())) .forEach(ph -> { - Row row = new Row(); - row.name = extractName(ph); - if (ObjectHelper.isNotEmpty(row.name)) { + JsonObject root = loadStatus(ph.pid()); + if (root != null) { + Row row = new Row(); + row.name = extractName(root, ph); row.pid = "" + ph.pid(); - row.age = TimeUtils.printSince(extractSince(ph)); + row.uptime = extractSince(ph); + row.ago = TimeUtils.printSince(row.uptime); + JsonObject context = (JsonObject) root.get("context"); + row.state = context.getString("state").toLowerCase(Locale.ROOT); + JsonObject hc = (JsonObject) root.get("healthChecks"); + row.ready = hc != null ? hc.getString("ready") + "/" + hc.getString("total") : null; rows.add(row); } }); + // sort rows + rows.sort(this::sortRow); + if (!rows.isEmpty()) { System.out.println(AsciiTable.getTable(AsciiTable.NO_BORDERS, rows, Arrays.asList( new Column().header("PID").headerAlign(HorizontalAlign.CENTER).with(r -> r.pid), - new Column().header("NAME").dataAlign(HorizontalAlign.LEFT).maxWidth(40, OverflowBehaviour.ELLIPSIS) + new Column().header("NAME").dataAlign(HorizontalAlign.LEFT).maxWidth(30, OverflowBehaviour.ELLIPSIS) .with(r -> r.name), - new Column().header("AGE").headerAlign(HorizontalAlign.CENTER).with(r -> r.age)))); + new Column().header("READY").dataAlign(HorizontalAlign.CENTER).with(r -> r.ready), + new Column().header("STATUS").headerAlign(HorizontalAlign.CENTER) + .with(r -> extractState(r.state)), + new Column().header("AGE").headerAlign(HorizontalAlign.CENTER).with(r -> r.ago)))); } return 0; } + protected int sortRow(Row o1, Row o2) { + switch (sort) { + case "pid": + return Long.compare(Long.parseLong(o1.pid), Long.parseLong(o2.pid)); + case "name": + return o1.name.compareToIgnoreCase(o2.name); + case "age": + return Long.compare(o1.uptime, o2.uptime); + default: + return 0; + } + } + private static class Row { String pid; String name; - String age; + String ready; + String state; + String ago; + long uptime; } } diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ProcessBaseCommand.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ProcessBaseCommand.java index 14075f5f92e..222774f586b 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ProcessBaseCommand.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ProcessBaseCommand.java @@ -16,6 +16,8 @@ */ package org.apache.camel.dsl.jbang.core.commands.process; +import java.io.File; +import java.io.FileInputStream; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -27,7 +29,10 @@ import org.apache.camel.dsl.jbang.core.commands.CamelCommand; import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain; import org.apache.camel.support.PatternHelper; import org.apache.camel.util.FileUtil; +import org.apache.camel.util.IOHelper; import org.apache.camel.util.StringHelper; +import org.apache.camel.util.json.JsonObject; +import org.apache.camel.util.json.Jsoner; abstract class ProcessBaseCommand extends CamelCommand { @@ -38,7 +43,7 @@ abstract class ProcessBaseCommand extends CamelCommand { super(main); } - static List<Long> findPids(String name) { + List<Long> findPids(String name) { List<Long> pids = new ArrayList<>(); // we need to know the pids of the running camel integrations @@ -56,21 +61,50 @@ abstract class ProcessBaseCommand extends CamelCommand { ProcessHandle.allProcesses() .filter(ph -> ph.pid() != cur) .forEach(ph -> { - String pName = extractName(ph); - // ignore file extension, so it is easier to match by name - pName = FileUtil.onlyName(pName); - if (!pName.isEmpty() && PatternHelper.matchPattern(pName, pattern)) { - pids.add(ph.pid()); + JsonObject root = loadStatus(ph.pid()); + // there must be a status file for the running Camel integration + if (root != null) { + String pName = extractName(root, ph); + // ignore file extension, so it is easier to match by name + pName = FileUtil.onlyName(pName); + if (pName != null && !pName.isEmpty() && PatternHelper.matchPattern(pName, pattern)) { + pids.add(ph.pid()); + } } }); return pids; } - static String extractName(ProcessHandle ph) { + static String extractMainClass(JsonObject root) { + JsonObject runtime = (JsonObject) root.get("runtime"); + return runtime != null ? runtime.getString("mainClass") : null; + } + + static String extractName(JsonObject root, ProcessHandle ph) { + String name = doExtractName(root, ph); + return FileUtil.stripPath(name); + } + + static String doExtractName(JsonObject root, ProcessHandle ph) { + // favour main class if known + if (root != null) { + String mc = extractMainClass(root); + if (mc != null) { + return mc; + } + } String cl = ph.info().commandLine().orElse(""); - // TODO: parent/child when mvn spring-boot:run etc + // this may be a maven plugin run that spawns a child process where Camel actually runs (link to child) + String mvn = extractMavenPluginName(cl); + if (mvn != null) { + // is camel running in any of the children? + boolean camel = ph.children().anyMatch(ch -> !extractName(root, ch).isEmpty()); + if (camel) { + return ""; // skip parent as we want only the child process with camel + } + } // try first camel-jbang String name = extractCamelJBangName(cl); @@ -78,8 +112,8 @@ abstract class ProcessBaseCommand extends CamelCommand { return name; } - // this may be a maven plugin run, so check that first - String mvn = extractMavenPluginName(cl); + // this may be a maven plugin run that spawns a child process where Camel actually runs (link to parent) + mvn = extractMavenPluginName(cl); if (mvn == null && ph.parent().isPresent()) { // try parent as it may spawn a sub process String clp = ph.parent().get().info().commandLine().orElse(""); @@ -100,8 +134,12 @@ abstract class ProcessBaseCommand extends CamelCommand { private static String extractCamelName(String cl, String mvn) { if (cl != null) { - if (cl.contains("camel-spring-boot") && mvn != null) { - return mvn; + if (cl.contains("camel-spring-boot")) { + if (mvn != null) { + return mvn; + } else { + return "camel-spring-boot"; + } } else if (cl.contains("camel-quarkus") && mvn != null) { return mvn; } else if ((cl.contains("camel-main") || cl.contains("camel-core")) && mvn != null) { @@ -149,4 +187,26 @@ abstract class ProcessBaseCommand extends CamelCommand { return since; } + static String extractState(String status) { + if ("started".equalsIgnoreCase(status)) { + status = "Running"; // favour using running instead of started + } + return StringHelper.capitalize(status); + } + + JsonObject loadStatus(long pid) { + try { + File f = getStatusFile("" + pid); + if (f != null) { + FileInputStream fis = new FileInputStream(f); + String text = IOHelper.loadText(fis); + IOHelper.close(fis); + return (JsonObject) Jsoner.deserialize(text); + } + } catch (Throwable e) { + // ignore + } + return null; + } + }