This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch var in repository https://gitbox.apache.org/repos/asf/camel.git
commit 93f35d7d1b894a1f2bd07e0eccf78b3bb644d9a1 Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Sat Dec 30 13:59:25 2023 +0100 CAMEL-19749: Add variables as concept to Camel --- .../camel/cli/connector/LocalCliConnector.java | 7 + .../dsl/jbang/core/commands/CamelJBangMain.java | 1 + .../jbang/core/commands/process/ListVariable.java | 169 +++++++++++++++++++++ 3 files changed, 177 insertions(+) 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 bc7b89a9ddb..bf2f3cacfc8 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 @@ -943,6 +943,13 @@ public class LocalCliConnector extends ServiceSupport implements CliConnector, C root.put("consumers", json); } } + DevConsole dc15 = dcr.resolveById("variables"); + if (dc15 != null) { + JsonObject json = (JsonObject) dc15.call(DevConsole.MediaType.JSON); + if (json != null && !json.isEmpty()) { + root.put("variables", json); + } + } } // various details JsonObject services = collectServices(); 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 f66f17b4ebe..bce20df06d9 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 @@ -76,6 +76,7 @@ public class CamelJBangMain implements Callable<Integer> { .addSubcommand("processor", new CommandLine(new CamelProcessorStatus(main))) .addSubcommand("count", new CommandLine(new CamelCount(main))) .addSubcommand("health", new CommandLine(new ListHealth(main))) + .addSubcommand("variable", new CommandLine(new ListVariable(main))) .addSubcommand("consumer", new CommandLine(new ListConsumer(main))) .addSubcommand("endpoint", new CommandLine(new ListEndpoint(main))) .addSubcommand("event", new CommandLine(new ListEvent(main))) diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListVariable.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListVariable.java new file mode 100644 index 00000000000..ee6549d2844 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/process/ListVariable.java @@ -0,0 +1,169 @@ +/* + * 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.process; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; + +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.dsl.jbang.core.common.ProcessHelper; +import org.apache.camel.util.json.JsonArray; +import org.apache.camel.util.json.JsonObject; +import picocli.CommandLine; +import picocli.CommandLine.Command; + +@Command(name = "variable", description = "List variables in a running Camel integration", sortOptions = false) +public class ListVariable extends ProcessWatchCommand { + + public static class PidNameKeyCompletionCandidates implements Iterable<String> { + + public PidNameKeyCompletionCandidates() { + } + + @Override + public Iterator<String> iterator() { + return List.of("pid", "name", "key").iterator(); + } + + } + + @CommandLine.Parameters(description = "Name or pid of running Camel integration", arity = "0..1") + String name = "*"; + + @CommandLine.Option(names = { "--sort" }, completionCandidates = PidNameKeyCompletionCandidates.class, + description = "Sort by pid, name or key", defaultValue = "pid") + String sort; + + public ListVariable(CamelJBangMain main) { + super(main); + } + + @Override + public Integer doProcessWatchCall() throws Exception { + List<Row> rows = new ArrayList<>(); + + List<Long> pids = findPids(name); + + ProcessHandle.allProcesses() + .filter(ph -> pids.contains(ph.pid())) + .forEach(ph -> { + JsonObject root = loadStatus(ph.pid()); + // there must be a status file for the running Camel integration + if (root != null) { + Row row = new Row(); + JsonObject context = (JsonObject) root.get("context"); + if (context == null) { + return; + } + row.name = context.getString("name"); + if ("CamelJBang".equals(row.name)) { + row.name = ProcessHelper.extractName(root, ph); + } + row.pid = Long.toString(ph.pid()); + + // platform-http is special + JsonObject jo = (JsonObject) root.get("variables"); + for (String id : jo.keySet()) { + JsonArray arr = jo.getCollection(id); + for (int i = 0; i < arr.size(); i++) { + row = row.copy(); + jo = (JsonObject) arr.get(i); + row.id = id; + row.key = jo.getString("key"); + row.className = jo.getString("className"); + row.value = jo.get("value"); + rows.add(row); + } + } + } + }); + + // sort rows + rows.sort(this::sortRow); + + if (!rows.isEmpty()) { + printer().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(30, OverflowBehaviour.ELLIPSIS_RIGHT) + .with(r -> r.name), + new Column().header("REPOSITORY").headerAlign(HorizontalAlign.CENTER).with(r -> r.id), + new Column().header("KEY").dataAlign(HorizontalAlign.LEFT).maxWidth(50, OverflowBehaviour.ELLIPSIS_RIGHT) + .with(r -> r.key), + new Column().header("TYPE").headerAlign(HorizontalAlign.CENTER) + .maxWidth(40, OverflowBehaviour.ELLIPSIS_LEFT).with(r -> r.className), + new Column().header("VALUE").headerAlign(HorizontalAlign.RIGHT).maxWidth(80, OverflowBehaviour.NEWLINE) + .with(r -> r.value.toString())))); + } + + return 0; + } + + protected int sortRow(Row o1, Row o2) { + String s = sort; + int negate = 1; + if (s.startsWith("-")) { + s = s.substring(1); + negate = -1; + } + switch (s) { + case "pid": + return Long.compare(Long.parseLong(o1.pid), Long.parseLong(o2.pid)) * negate; + case "name": + return o1.name.compareToIgnoreCase(o2.name) * negate; + case "key": + return o1.key.compareToIgnoreCase(o2.key) * negate; + default: + return 0; + } + } + + private String getValue(Row r) { + if (r.value != null) { + // clip very large value + String s = r.value.toString(); + if (s.length() > 300) { + s = s.substring(0, 300) + "..."; + } + return s; + } + return ""; + } + + private static class Row implements Cloneable { + String pid; + String name; + String id; + String key; + String className; + Object value; + + Row copy() { + try { + return (Row) clone(); + } catch (CloneNotSupportedException e) { + return null; + } + } + } + +}