This is an automated email from the ASF dual-hosted git repository. davsclaus pushed a commit to branch jbrp in repository https://gitbox.apache.org/repos/asf/camel.git
commit 56d19593e5b8c6d138f8479f0131897e5ab09753 Author: Claus Ibsen <[email protected]> AuthorDate: Tue Dec 23 16:01:01 2025 +0100 camel-jbang - Add plugin for route-parser --- bom/camel-bom/pom.xml | 5 + .../camel/dsl/jbang/core/common/PluginType.java | 3 +- .../jbang/core/commands/plugin/PluginGetTest.java | 22 ++-- .../{ => camel-jbang-plugin-route-parser}/pom.xml | 47 ++++--- .../camel-jbang-plugin-route-parser | 2 + .../jbang/core/commands/parser/ParserPlugin.java | 32 +++++ .../core/commands/parser/RouteParserCommand.java | 146 +++++++++++++++++++++ dsl/camel-jbang/pom.xml | 1 + parent/pom.xml | 5 + 9 files changed, 235 insertions(+), 28 deletions(-) diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml index e399a6774f85..869f1c3f83db 100644 --- a/bom/camel-bom/pom.xml +++ b/bom/camel-bom/pom.xml @@ -1222,6 +1222,11 @@ <artifactId>camel-jbang-plugin-kubernetes</artifactId> <version>4.17.0-SNAPSHOT</version> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-jbang-plugin-route-parser</artifactId> + <version>4.17.0-SNAPSHOT</version> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-jbang-plugin-test</artifactId> diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginType.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginType.java index 98c0b081e897..5c952404d3b0 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginType.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/PluginType.java @@ -27,7 +27,8 @@ public enum PluginType { KUBERNETES("kubernetes", "kubernetes", "Run Camel applications on Kubernetes", "4.8.0", null), GENERATE("generate", "generate", "Generate code such as DTOs", "4.8.0", null), EDIT("edit", "edit", "Edit Camel files with suggestions", "4.12.0", null), - TEST("test", "test", "Manage tests for Camel applications", "4.14.0", null); + TEST("test", "test", "Manage tests for Camel applications", "4.14.0", null), + ROUTE_PARSER("route-parser", "route-parser", "Parses Java route and dumps route structure", "4.17.0", null); private final String name; private final String command; diff --git a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginGetTest.java b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginGetTest.java index 0bd83461a02a..887c0af4a879 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginGetTest.java +++ b/dsl/camel-jbang/camel-jbang-core/src/test/java/org/apache/camel/dsl/jbang/core/commands/plugin/PluginGetTest.java @@ -70,12 +70,12 @@ class PluginGetTest extends CamelCommandBaseTestSupport { command.doCall(); List<String> output = printer.getLines(); - Assertions.assertEquals(7, output.size()); + Assertions.assertEquals(8, output.size()); Assertions.assertEquals("Supported plugins:", output.get(0)); - Assertions.assertEquals("NAME COMMAND DEPENDENCY DESCRIPTION", + Assertions.assertEquals("NAME COMMAND DEPENDENCY DESCRIPTION", output.get(2)); Assertions.assertEquals( - "kubernetes kubernetes org.apache.camel:camel-jbang-plugin-kubernetes %s" + "kubernetes kubernetes org.apache.camel:camel-jbang-plugin-kubernetes %s" .formatted(PluginType.KUBERNETES.getDescription()), output.get(3)); } @@ -120,31 +120,35 @@ class PluginGetTest extends CamelCommandBaseTestSupport { command.doCall(); List<String> output = printer.getLines(); - Assertions.assertEquals(10, output.size()); + Assertions.assertEquals(11, output.size()); Assertions.assertEquals("NAME COMMAND DEPENDENCY DESCRIPTION", output.get(0)); Assertions.assertEquals( "foo-plugin foo org.apache.camel:foo-plugin:1.0.0 Plugin foo-plugin called with command foo", output.get(1)); Assertions.assertEquals("Supported plugins:", output.get(3)); - Assertions.assertEquals("NAME COMMAND DEPENDENCY DESCRIPTION", + Assertions.assertEquals("NAME COMMAND DEPENDENCY DESCRIPTION", output.get(5)); Assertions.assertEquals( - "kubernetes kubernetes org.apache.camel:camel-jbang-plugin-kubernetes %s" + "kubernetes kubernetes org.apache.camel:camel-jbang-plugin-kubernetes %s" .formatted(PluginType.KUBERNETES.getDescription()), output.get(6)); Assertions.assertEquals( - "generate generate org.apache.camel:camel-jbang-plugin-generate %s" + "generate generate org.apache.camel:camel-jbang-plugin-generate %s" .formatted(PluginType.GENERATE.getDescription()), output.get(7)); Assertions.assertEquals( - "edit edit org.apache.camel:camel-jbang-plugin-edit %s" + "edit edit org.apache.camel:camel-jbang-plugin-edit %s" .formatted(PluginType.EDIT.getDescription()), output.get(8)); Assertions.assertEquals( - "test test org.apache.camel:camel-jbang-plugin-test %s" + "test test org.apache.camel:camel-jbang-plugin-test %s" .formatted(PluginType.TEST.getDescription()), output.get(9)); + Assertions.assertEquals( + "route-parser route-parser org.apache.camel:camel-jbang-plugin-route-parser %s" + .formatted(PluginType.ROUTE_PARSER.getDescription()), + output.get(10)); } } diff --git a/dsl/camel-jbang/pom.xml b/dsl/camel-jbang/camel-jbang-plugin-route-parser/pom.xml similarity index 56% copy from dsl/camel-jbang/pom.xml copy to dsl/camel-jbang/camel-jbang-plugin-route-parser/pom.xml index d7bbf0cf4cbb..e6fed824f978 100644 --- a/dsl/camel-jbang/pom.xml +++ b/dsl/camel-jbang/camel-jbang-plugin-route-parser/pom.xml @@ -18,30 +18,41 @@ --> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.apache.camel</groupId> - <artifactId>dsl</artifactId> + <artifactId>camel-jbang-parent</artifactId> <version>4.17.0-SNAPSHOT</version> <relativePath>../pom.xml</relativePath> </parent> - <artifactId>camel-jbang-parent</artifactId> - <packaging>pom</packaging> - - <name>Camel :: JBang :: Parent</name> - <description>Camel JBang Modules (parent)</description> - - <modules> - <module>camel-jbang-console</module> - <module>camel-jbang-core</module> - <module>camel-jbang-main</module> - <module>camel-jbang-plugin-generate</module> - <module>camel-jbang-plugin-edit</module> - <module>camel-jbang-plugin-kubernetes</module> - <module>camel-jbang-plugin-test</module> - <module>camel-jbang-it</module> - <module>camel-launcher</module> - </modules> + <artifactId>camel-jbang-plugin-route-parser</artifactId> + + <name>Camel :: JBang :: Plugin :: Route Parser</name> + <description>Camel JBang Edit Route Parser</description> + + <properties> + <firstVersion>4.17.0</firstVersion> + <label>jbang</label> + <supportLevel>Preview</supportLevel> + <camel-prepare-component>false</camel-prepare-component> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-jbang-core</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-route-parser</artifactId> + </dependency> + <dependency> + <groupId>org.jboss.forge.roaster</groupId> + <artifactId>roaster-jdt</artifactId> + <version>${roaster-version}</version> + </dependency> + </dependencies> </project> diff --git a/dsl/camel-jbang/camel-jbang-plugin-route-parser/src/generated/resources/META-INF/services/org/apache/camel/camel-jbang-plugin/camel-jbang-plugin-route-parser b/dsl/camel-jbang/camel-jbang-plugin-route-parser/src/generated/resources/META-INF/services/org/apache/camel/camel-jbang-plugin/camel-jbang-plugin-route-parser new file mode 100644 index 000000000000..f89c31e6b57d --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-plugin-route-parser/src/generated/resources/META-INF/services/org/apache/camel/camel-jbang-plugin/camel-jbang-plugin-route-parser @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.dsl.jbang.core.commands.parser.ParserPlugin diff --git a/dsl/camel-jbang/camel-jbang-plugin-route-parser/src/main/java/org/apache/camel/dsl/jbang/core/commands/parser/ParserPlugin.java b/dsl/camel-jbang/camel-jbang-plugin-route-parser/src/main/java/org/apache/camel/dsl/jbang/core/commands/parser/ParserPlugin.java new file mode 100644 index 000000000000..c6608535b448 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-plugin-route-parser/src/main/java/org/apache/camel/dsl/jbang/core/commands/parser/ParserPlugin.java @@ -0,0 +1,32 @@ +/* + * 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.parser; + +import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain; +import org.apache.camel.dsl.jbang.core.common.CamelJBangPlugin; +import org.apache.camel.dsl.jbang.core.common.Plugin; +import picocli.CommandLine; + +@CamelJBangPlugin(name = "camel-jbang-plugin-route-parser", firstVersion = "4.17.0") +public class ParserPlugin implements Plugin { + + @Override + public void customize(CommandLine commandLine, CamelJBangMain main) { + commandLine.addSubcommand("route-parser", new RouteParserCommand(main)); + } + +} diff --git a/dsl/camel-jbang/camel-jbang-plugin-route-parser/src/main/java/org/apache/camel/dsl/jbang/core/commands/parser/RouteParserCommand.java b/dsl/camel-jbang/camel-jbang-plugin-route-parser/src/main/java/org/apache/camel/dsl/jbang/core/commands/parser/RouteParserCommand.java new file mode 100644 index 000000000000..0863160b15f2 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-plugin-route-parser/src/main/java/org/apache/camel/dsl/jbang/core/commands/parser/RouteParserCommand.java @@ -0,0 +1,146 @@ +/* + * 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.parser; + +import java.io.File; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.apache.camel.dsl.jbang.core.commands.CamelCommand; +import org.apache.camel.dsl.jbang.core.commands.CamelJBangMain; +import org.apache.camel.dsl.jbang.core.commands.CommandHelper; +import org.apache.camel.parser.RouteBuilderParser; +import org.apache.camel.parser.model.CamelNodeDetails; +import org.apache.camel.util.FileUtil; +import org.apache.camel.util.StopWatch; +import org.fusesource.jansi.Ansi; +import org.fusesource.jansi.AnsiConsole; +import org.jboss.forge.roaster.Roaster; +import org.jboss.forge.roaster.model.source.JavaClassSource; +import picocli.CommandLine; + [email protected](name = "route-parser", description = "Parses Java route and dumps route structure") +public class RouteParserCommand extends CamelCommand { + + @CommandLine.Parameters(description = { "The Camel RouteBuilder Java source files to parse." }, + arity = "1..9", + paramLabel = "<files>", + parameterConsumer = FilesConsumer.class) + Path[] filePaths; + List<String> files = new ArrayList<>(); + + @CommandLine.Option(names = { "--raw" }, + description = "To output raw without metadata") + boolean raw; + + @CommandLine.Option(names = { "--watch" }, + description = "Execute periodically and showing output fullscreen") + boolean watch; + + private CommandHelper.ReadConsoleTask waitUserTask; + + public RouteParserCommand(CamelJBangMain main) { + super(main); + } + + @Override + public Integer doCall() throws Exception { + int exit; + final AtomicBoolean running = new AtomicBoolean(true); + if (watch) { + Thread t = new Thread(() -> { + waitUserTask = new CommandHelper.ReadConsoleTask(() -> running.set(false)); + waitUserTask.run(); + }, "WaitForUser"); + t.start(); + do { + exit = doWatchCall(); + if (exit == 0) { + // use 2-sec delay in watch mode + try { + StopWatch watch = new StopWatch(); + while (running.get() && watch.taken() < 2000) { + Thread.sleep(100); + } + } catch (Exception e) { + running.set(false); + } + } + } while (exit == 0 && running.get()); + } else { + exit = doWatchCall(); + } + return exit; + } + + protected Integer doWatchCall() throws Exception { + for (String file : files) { + Integer code = doDumpFile(file); + if (code != 0) { + return code; + } + } + return 0; + } + + protected Integer doDumpFile(String file) throws Exception { + File f = new File(file); + if (!f.exists() || !f.isFile()) { + printer().printErr("File not found: " + file); + return -1; + } + String ext = FileUtil.onlyExt(file); + if (!"java".equals(ext)) { + printer().printErr("Only .java source file is supported"); + return -1; + } + JavaClassSource clazz = (JavaClassSource) Roaster.parse(f); + String fqn = clazz.getQualifiedName(); + fqn = fqn.replace('.', '/'); + fqn = fqn + ".java"; + List<CamelNodeDetails> list = RouteBuilderParser.parseRouteBuilderTree(clazz, fqn, true); + if (watch) { + clearScreen(); + } + for (var route : list) { + printer().println(); + if (!raw) { + printer().printf("Source: %s%n", route.getFileName()); + printer().println("--------------------------------------------------------------------------------"); + } + String tree = route.dump(0); + printer().println(tree); + printer().println(); + } + return 0; + } + + protected void clearScreen() { + AnsiConsole.out().print(Ansi.ansi().eraseScreen().cursor(1, 1)); + } + + static class FilesConsumer extends CamelCommand.ParameterConsumer<RouteParserCommand> { + protected void doConsumeParameters(Stack<String> args, RouteParserCommand cmd) { + String arg = args.pop(); + cmd.files.add(arg); + } + } + +} diff --git a/dsl/camel-jbang/pom.xml b/dsl/camel-jbang/pom.xml index d7bbf0cf4cbb..fea393926c71 100644 --- a/dsl/camel-jbang/pom.xml +++ b/dsl/camel-jbang/pom.xml @@ -40,6 +40,7 @@ <module>camel-jbang-plugin-generate</module> <module>camel-jbang-plugin-edit</module> <module>camel-jbang-plugin-kubernetes</module> + <module>camel-jbang-plugin-route-parser</module> <module>camel-jbang-plugin-test</module> <module>camel-jbang-it</module> <module>camel-launcher</module> diff --git a/parent/pom.xml b/parent/pom.xml index dfd4138ba96f..7ede630cfd8f 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -3050,6 +3050,11 @@ <artifactId>camel-jbang-plugin-kubernetes</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-jbang-plugin-route-parser</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-jbang-plugin-test</artifactId>
