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 89049d9ebda CAMEL-18425: camel-cli - Make regular Camel applications work with Camel CLI 89049d9ebda is described below commit 89049d9ebdac689188c44ff163ab27ddd03d3a1d Author: Claus Ibsen <claus.ib...@gmail.com> AuthorDate: Thu Aug 25 19:35:56 2022 +0200 CAMEL-18425: camel-cli - Make regular Camel applications work with Camel CLI --- bom/camel-bom/pom.xml | 5 + .../org/apache/camel/catalog/others.properties | 1 + .../apache/camel/catalog/others/cli-connector.json | 15 ++ .../org/apache/camel/ExtendedCamelContext.java | 11 ++ .../org/apache/camel/spi/CliConnectorFactory.java | 69 +++++++ .../camel/impl/engine/AbstractCamelContext.java | 30 +++ .../camel/impl/engine/SimpleCamelContext.java | 12 ++ .../camel/impl/ExtendedCamelContextConfigurer.java | 6 + .../camel/impl/lw/LightweightCamelContext.java | 11 ++ .../impl/lw/LightweightRuntimeCamelContext.java | 13 ++ .../camel/main/DefaultConfigurationConfigurer.java | 5 + docs/components/modules/others/nav.adoc | 1 + .../modules/others/pages/cli-connector.adoc | 1 + dsl/camel-cli-connector/pom.xml | 129 +++++++++++++ .../org/apache/camel/cli-connector-factory | 2 + .../services/org/apache/camel/other.properties | 7 + .../src/generated/resources/cli-connector.json | 15 ++ .../src/main/docs/cli-connector.adoc | 27 +++ .../cli/connector/DefaultCliConnectorFactory.java | 71 +++++++ .../camel/cli/connector/LocalCliConnector.java | 206 +++++++++++++++++++++ dsl/camel-jbang/camel-jbang-core/pom.xml | 4 + .../apache/camel/dsl/jbang/core/commands/Run.java | 77 -------- .../core/commands/process/CamelContextStatus.java | 21 ++- .../jbang/core/commands/process/ListProcess.java | 2 + .../core/commands/process/ProcessBaseCommand.java | 43 ++++- dsl/pom.xml | 1 + parent/pom.xml | 5 + 27 files changed, 710 insertions(+), 80 deletions(-) diff --git a/bom/camel-bom/pom.xml b/bom/camel-bom/pom.xml index 8ddddd276b7..092e662202e 100644 --- a/bom/camel-bom/pom.xml +++ b/bom/camel-bom/pom.xml @@ -436,6 +436,11 @@ <artifactId>camel-chunk</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-cli-connector</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-cloud</artifactId> diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties index af396b27e3c..22bae335791 100644 --- a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others.properties @@ -4,6 +4,7 @@ caffeine-lrucache cdi cdi-jta cdi-main +cli-connector cloud cloudevents cluster diff --git a/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others/cli-connector.json b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others/cli-connector.json new file mode 100644 index 00000000000..93654b1747b --- /dev/null +++ b/catalog/camel-catalog/src/generated/resources/org/apache/camel/catalog/others/cli-connector.json @@ -0,0 +1,15 @@ +{ + "other": { + "kind": "other", + "name": "cli-connector", + "title": "CLI Connector", + "description": "Runtime adapter connecting with Camel CLI", + "deprecated": false, + "firstVersion": "3.19.0", + "label": "tooling", + "supportLevel": "Preview", + "groupId": "org.apache.camel", + "artifactId": "camel-cli-connector", + "version": "3.19.0-SNAPSHOT" + } +} diff --git a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java index c7f4ceb0d5e..bcbec2d9f94 100644 --- a/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java +++ b/core/camel-api/src/main/java/org/apache/camel/ExtendedCamelContext.java @@ -32,6 +32,7 @@ import org.apache.camel.spi.BeanProxyFactory; import org.apache.camel.spi.BootstrapCloseable; import org.apache.camel.spi.CamelBeanPostProcessor; import org.apache.camel.spi.CamelDependencyInjectionAnnotationFactory; +import org.apache.camel.spi.CliConnectorFactory; import org.apache.camel.spi.ComponentNameResolver; import org.apache.camel.spi.ComponentResolver; import org.apache.camel.spi.ConfigurerResolver; @@ -789,6 +790,16 @@ public interface ExtendedCamelContext extends CamelContext { */ void setStartupStepRecorder(StartupStepRecorder startupStepRecorder); + /** + * Gets the {@link CliConnectorFactory} (optional). + */ + CliConnectorFactory getCliConnectorFactory(); + + /** + * Sets the {@link CliConnectorFactory} to use. + */ + void setCliConnectorFactory(CliConnectorFactory cliConnectorFactory); + /** * Internal API for adding routes. Do not use this as end user. */ 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 new file mode 100644 index 00000000000..5ca9212992f --- /dev/null +++ b/core/camel-api/src/main/java/org/apache/camel/spi/CliConnectorFactory.java @@ -0,0 +1,69 @@ +/* + * 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.spi; + +import org.apache.camel.Service; + +/** + * Factory for creating connector to CLI tooling. + * <p/> + * Such as a local connector that allows Camel CLI to manage local running Camel integrations. + */ +public interface CliConnectorFactory { + + /** + * Service factory key. + */ + String FACTORY = "cli-connector-factory"; + + /** + * To enable CLI connector. + */ + void setEnabled(boolean enabled); + + /** + * Whether CLI connector is enabled. + */ + boolean isEnabled(); + + /** + * What runtime platform is in use, such as camel-jbang, camel-spring-boot, or camel-quarkus etc. + */ + void setRuntime(String runtime); + + /** + * What runtime platform is in use, such as camel-jbang, camel-spring-boot, or camel-quarkus etc. + */ + String getRuntime(); + + /** + * What runtime platform version is in use. + */ + void setRuntimeVersion(String version); + + /** + * What runtime platform version is in use. + */ + String getRuntimeVersion(); + + /** + * 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. + */ + Service createConnector(); + +} diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java index 81f97ad688b..ba50e572758 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/AbstractCamelContext.java @@ -98,6 +98,7 @@ import org.apache.camel.spi.CamelContextTracker; import org.apache.camel.spi.CamelDependencyInjectionAnnotationFactory; import org.apache.camel.spi.CamelLogger; import org.apache.camel.spi.ClassResolver; +import org.apache.camel.spi.CliConnectorFactory; import org.apache.camel.spi.ComponentNameResolver; import org.apache.camel.spi.ComponentResolver; import org.apache.camel.spi.ConfigurerResolver; @@ -313,6 +314,7 @@ public abstract class AbstractCamelContext extends BaseService private volatile RestRegistryFactory restRegistryFactory; private volatile RestRegistry restRegistry; private volatile HeadersMapFactory headersMapFactory; + private volatile CliConnectorFactory cliConnectorFactory; private volatile BeanProxyFactory beanProxyFactory; private volatile BeanProcessorFactory beanProcessorFactory; private volatile XMLRoutesDefinitionLoader xmlRoutesDefinitionLoader; @@ -1525,6 +1527,10 @@ public abstract class AbstractCamelContext extends BaseService boolean forceStart, boolean useLifecycleStrategies) throws Exception { + if (object == null) { + return; + } + // inject CamelContext CamelContextAware.trySetCamelContext(object, getCamelContextReference()); @@ -2858,6 +2864,11 @@ public abstract class AbstractCamelContext extends BaseService forceLazyInitialization(); + CliConnectorFactory ccf = getCliConnectorFactory(); + if (ccf != null && ccf.isEnabled()) { + LOG.info("Detected: {} JAR (Enabling Camel CLI Connector)", ccf); + addService(ccf.createConnector(), true); + } addService(getManagementStrategy(), false); lifecycleStrategies.sort(OrderedComparator.get()); ServiceHelper.initService(lifecycleStrategies); @@ -5293,6 +5304,8 @@ public abstract class AbstractCamelContext extends BaseService protected abstract HeadersMapFactory createHeadersMapFactory(); + protected abstract CliConnectorFactory createCliConnectorFactory(); + protected abstract BeanProxyFactory createBeanProxyFactory(); protected abstract AnnotationBasedProcessorFactory createAnnotationBasedProcessorFactory(); @@ -5365,6 +5378,23 @@ public abstract class AbstractCamelContext extends BaseService this.startupStepRecorder = startupStepRecorder; } + @Override + public CliConnectorFactory getCliConnectorFactory() { + if (cliConnectorFactory == null) { + synchronized (lock) { + if (cliConnectorFactory == null) { + setCliConnectorFactory(createCliConnectorFactory()); + } + } + } + return cliConnectorFactory; + } + + @Override + public void setCliConnectorFactory(CliConnectorFactory cliConnectorFactory) { + this.cliConnectorFactory = cliConnectorFactory; + } + @Deprecated public enum Initialization { Eager, diff --git a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java index aaa24bbd5ae..0ea1c69b103 100644 --- a/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java +++ b/core/camel-base-engine/src/main/java/org/apache/camel/impl/engine/SimpleCamelContext.java @@ -40,6 +40,7 @@ import org.apache.camel.spi.CamelBeanPostProcessor; import org.apache.camel.spi.CamelContextNameStrategy; import org.apache.camel.spi.CamelDependencyInjectionAnnotationFactory; import org.apache.camel.spi.ClassResolver; +import org.apache.camel.spi.CliConnectorFactory; import org.apache.camel.spi.ComponentNameResolver; import org.apache.camel.spi.ComponentResolver; import org.apache.camel.spi.ConfigurerResolver; @@ -409,6 +410,17 @@ public class SimpleCamelContext extends AbstractCamelContext { return result.orElseGet(DefaultHeadersMapFactory::new); } + @Override + protected CliConnectorFactory createCliConnectorFactory() { + Optional<CliConnectorFactory> result = ResolverHelper.resolveService( + getCamelContextReference(), + getBootstrapFactoryFinder(), + CliConnectorFactory.FACTORY, + CliConnectorFactory.class); + // cli-connector is optional + return result.orElse(null); + } + @Override protected BeanProxyFactory createBeanProxyFactory() { Optional<BeanProxyFactory> result = ResolverHelper.resolveService( diff --git a/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java b/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java index e6fc9fb97c8..a721c3d8460 100644 --- a/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java +++ b/core/camel-core-engine/src/generated/java/org/apache/camel/impl/ExtendedCamelContextConfigurer.java @@ -49,6 +49,8 @@ public class ExtendedCamelContextConfigurer extends org.apache.camel.support.com case "CaseInsensitiveHeaders": target.setCaseInsensitiveHeaders(property(camelContext, java.lang.Boolean.class, value)); return true; case "classresolver": case "ClassResolver": target.setClassResolver(property(camelContext, org.apache.camel.spi.ClassResolver.class, value)); return true; + case "cliconnectorfactory": + case "CliConnectorFactory": target.setCliConnectorFactory(property(camelContext, org.apache.camel.spi.CliConnectorFactory.class, value)); return true; case "componentnameresolver": case "ComponentNameResolver": target.setComponentNameResolver(property(camelContext, org.apache.camel.spi.ComponentNameResolver.class, value)); return true; case "componentresolver": @@ -252,6 +254,8 @@ public class ExtendedCamelContextConfigurer extends org.apache.camel.support.com case "CaseInsensitiveHeaders": return java.lang.Boolean.class; case "classresolver": case "ClassResolver": return org.apache.camel.spi.ClassResolver.class; + case "cliconnectorfactory": + case "CliConnectorFactory": return org.apache.camel.spi.CliConnectorFactory.class; case "componentnameresolver": case "ComponentNameResolver": return org.apache.camel.spi.ComponentNameResolver.class; case "componentresolver": @@ -456,6 +460,8 @@ public class ExtendedCamelContextConfigurer extends org.apache.camel.support.com case "CaseInsensitiveHeaders": return target.isCaseInsensitiveHeaders(); case "classresolver": case "ClassResolver": return target.getClassResolver(); + case "cliconnectorfactory": + case "CliConnectorFactory": return target.getCliConnectorFactory(); case "componentnameresolver": case "ComponentNameResolver": return target.getComponentNameResolver(); case "componentresolver": diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java index 5afb8d37a2e..9136cda08b2 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightCamelContext.java @@ -83,6 +83,7 @@ import org.apache.camel.spi.CamelBeanPostProcessor; import org.apache.camel.spi.CamelContextNameStrategy; import org.apache.camel.spi.CamelDependencyInjectionAnnotationFactory; import org.apache.camel.spi.ClassResolver; +import org.apache.camel.spi.CliConnectorFactory; import org.apache.camel.spi.ComponentNameResolver; import org.apache.camel.spi.ComponentResolver; import org.apache.camel.spi.ConfigurerResolver; @@ -1781,6 +1782,16 @@ public class LightweightCamelContext implements ExtendedCamelContext, CatalogCam getExtendedCamelContext().setStartupStepRecorder(startupStepRecorder); } + @Override + public CliConnectorFactory getCliConnectorFactory() { + return getExtendedCamelContext().getCliConnectorFactory(); + } + + @Override + public void setCliConnectorFactory(CliConnectorFactory cliConnectorFactory) { + getExtendedCamelContext().setCliConnectorFactory(cliConnectorFactory); + } + @Override public String getTestExcludeRoutes() { return getExtendedCamelContext().getTestExcludeRoutes(); diff --git a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java index cdfa5250766..9d74aad134d 100644 --- a/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java +++ b/core/camel-core-engine/src/main/java/org/apache/camel/impl/lw/LightweightRuntimeCamelContext.java @@ -78,6 +78,7 @@ import org.apache.camel.spi.CamelBeanPostProcessor; import org.apache.camel.spi.CamelContextNameStrategy; import org.apache.camel.spi.CamelDependencyInjectionAnnotationFactory; import org.apache.camel.spi.ClassResolver; +import org.apache.camel.spi.CliConnectorFactory; import org.apache.camel.spi.ComponentNameResolver; import org.apache.camel.spi.ComponentResolver; import org.apache.camel.spi.ConfigurerResolver; @@ -181,6 +182,7 @@ public class LightweightRuntimeCamelContext implements ExtendedCamelContext, Cat private final CamelBeanPostProcessor beanPostProcessor; private final CamelDependencyInjectionAnnotationFactory dependencyInjectionAnnotationFactory; private final HeadersMapFactory headersMapFactory; + private final CliConnectorFactory cliConnectorFactory; private final ExchangeFactory exchangeFactory; private final ExchangeFactoryManager exchangeFactoryManager; private final ProcessorExchangeFactory processorExchangeFactory; @@ -236,6 +238,7 @@ public class LightweightRuntimeCamelContext implements ExtendedCamelContext, Cat dependencyInjectionAnnotationFactory = context.adapt(ExtendedCamelContext.class).getDependencyInjectionAnnotationFactory(); headersMapFactory = context.adapt(ExtendedCamelContext.class).getHeadersMapFactory(); + cliConnectorFactory = context.adapt(ExtendedCamelContext.class).getCliConnectorFactory(); exchangeFactory = context.adapt(ExtendedCamelContext.class).getExchangeFactory(); exchangeFactoryManager = context.adapt(ExtendedCamelContext.class).getExchangeFactoryManager(); modelineFactory = context.adapt(ExtendedCamelContext.class).getModelineFactory(); @@ -1714,6 +1717,16 @@ public class LightweightRuntimeCamelContext implements ExtendedCamelContext, Cat throw new UnsupportedOperationException(); } + @Override + public CliConnectorFactory getCliConnectorFactory() { + return cliConnectorFactory; + } + + @Override + public void setCliConnectorFactory(CliConnectorFactory cliConnectorFactory) { + throw new UnsupportedOperationException(); + } + @Override public ExchangeFactory getExchangeFactory() { return exchangeFactory; diff --git a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java index 18d076b6d5f..a1b431f763b 100644 --- a/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java +++ b/core/camel-main/src/main/java/org/apache/camel/main/DefaultConfigurationConfigurer.java @@ -43,6 +43,7 @@ import org.apache.camel.model.ModelCamelContext; import org.apache.camel.model.ModelLifecycleStrategy; import org.apache.camel.spi.AsyncProcessorAwaitManager; import org.apache.camel.spi.ClassResolver; +import org.apache.camel.spi.CliConnectorFactory; import org.apache.camel.spi.Debugger; import org.apache.camel.spi.EndpointStrategy; import org.apache.camel.spi.EventFactory; @@ -353,6 +354,10 @@ public final class DefaultConfigurationConfigurer { if (ssr != null) { ecc.setStartupStepRecorder(ssr); } + CliConnectorFactory ccf = getSingleBeanOfType(registry, CliConnectorFactory.class); + if (ccf != null) { + ecc.setCliConnectorFactory(ccf); + } PropertiesComponent pc = getSingleBeanOfType(registry, PropertiesComponent.class); if (pc != null) { ecc.setPropertiesComponent(pc); diff --git a/docs/components/modules/others/nav.adoc b/docs/components/modules/others/nav.adoc index 3a4e32a00e4..a531911b5e3 100644 --- a/docs/components/modules/others/nav.adoc +++ b/docs/components/modules/others/nav.adoc @@ -8,6 +8,7 @@ ** xref:cdi.adoc[CDI] ** xref:cdi-jta.adoc[CDI JTA] ** xref:cdi-main.adoc[CDI Main] +** xref:cli-connector.adoc[CLI Connector] ** xref:cloudevents.adoc[Cloudevents] ** xref:csimple-joor.adoc[CSimple jOOR] ** xref:cxf-transport.adoc[CXF Transport] diff --git a/docs/components/modules/others/pages/cli-connector.adoc b/docs/components/modules/others/pages/cli-connector.adoc new file mode 120000 index 00000000000..fb1b71544cb --- /dev/null +++ b/docs/components/modules/others/pages/cli-connector.adoc @@ -0,0 +1 @@ +../../../../../dsl/camel-cli-connector/src/main/docs/cli-connector.adoc \ No newline at end of file diff --git a/dsl/camel-cli-connector/pom.xml b/dsl/camel-cli-connector/pom.xml new file mode 100644 index 00000000000..e5a568f1be9 --- /dev/null +++ b/dsl/camel-cli-connector/pom.xml @@ -0,0 +1,129 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + + 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. + +--> +<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/maven-v4_0_0.xsd"> + + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.camel</groupId> + <artifactId>dsl</artifactId> + <version>3.19.0-SNAPSHOT</version> + </parent> + + <artifactId>camel-cli-connector</artifactId> + <packaging>jar</packaging> + <name>Camel :: DSL :: CLI Connector</name> + <description>Runtime adapter connecting with Camel CLI</description> + + <properties> + <firstVersion>3.19.0</firstVersion> + <title>CLI Connector</title> + <label>tooling</label> + </properties> + + <dependencies> + + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-support</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-util-json</artifactId> + </dependency> + + <!-- insights --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-console</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-health</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-management</artifactId> + </dependency> + + <!-- test dependencies --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-test-junit5</artifactId> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-slf4j-impl</artifactId> + <scope>test</scope> + </dependency> + + </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.apache.camel</groupId> + <artifactId>camel-package-maven-plugin</artifactId> + <executions> + <execution> + <id>generate</id> + <goals> + <goal>generate</goal> + </goals> + <phase>process-classes</phase> + </execution> + <execution> + <id>generate-postcompile</id> + <goals> + <goal>generate-postcompile</goal> + </goals> + <phase>prepare-package</phase> + </execution> + </executions> + </plugin> + <plugin> + <groupId>org.codehaus.mojo</groupId> + <artifactId>build-helper-maven-plugin</artifactId> + <executions> + <execution> + <phase>initialize</phase> + <goals> + <goal>add-source</goal> + <goal>add-resource</goal> + </goals> + <configuration> + <sources> + <source>src/generated/java</source> + </sources> + <resources> + <resource> + <directory>src/generated/resources</directory> + </resource> + </resources> + </configuration> + </execution> + </executions> + </plugin> + </plugins> + </build> + +</project> \ No newline at end of file diff --git a/dsl/camel-cli-connector/src/generated/resources/META-INF/services/org/apache/camel/cli-connector-factory b/dsl/camel-cli-connector/src/generated/resources/META-INF/services/org/apache/camel/cli-connector-factory new file mode 100644 index 00000000000..c5d7357fc02 --- /dev/null +++ b/dsl/camel-cli-connector/src/generated/resources/META-INF/services/org/apache/camel/cli-connector-factory @@ -0,0 +1,2 @@ +# Generated by camel build tools - do NOT edit this file! +class=org.apache.camel.cli.connector.DefaultCliConnectorFactory diff --git a/dsl/camel-cli-connector/src/generated/resources/META-INF/services/org/apache/camel/other.properties b/dsl/camel-cli-connector/src/generated/resources/META-INF/services/org/apache/camel/other.properties new file mode 100644 index 00000000000..89f0cd06c6e --- /dev/null +++ b/dsl/camel-cli-connector/src/generated/resources/META-INF/services/org/apache/camel/other.properties @@ -0,0 +1,7 @@ +# Generated by camel build tools - do NOT edit this file! +name=cli-connector +groupId=org.apache.camel +artifactId=camel-cli-connector +version=3.19.0-SNAPSHOT +projectName=Camel :: DSL :: CLI Connector +projectDescription=Runtime adapter connecting with Camel CLI diff --git a/dsl/camel-cli-connector/src/generated/resources/cli-connector.json b/dsl/camel-cli-connector/src/generated/resources/cli-connector.json new file mode 100644 index 00000000000..93654b1747b --- /dev/null +++ b/dsl/camel-cli-connector/src/generated/resources/cli-connector.json @@ -0,0 +1,15 @@ +{ + "other": { + "kind": "other", + "name": "cli-connector", + "title": "CLI Connector", + "description": "Runtime adapter connecting with Camel CLI", + "deprecated": false, + "firstVersion": "3.19.0", + "label": "tooling", + "supportLevel": "Preview", + "groupId": "org.apache.camel", + "artifactId": "camel-cli-connector", + "version": "3.19.0-SNAPSHOT" + } +} diff --git a/dsl/camel-cli-connector/src/main/docs/cli-connector.adoc b/dsl/camel-cli-connector/src/main/docs/cli-connector.adoc new file mode 100644 index 00000000000..45876334430 --- /dev/null +++ b/dsl/camel-cli-connector/src/main/docs/cli-connector.adoc @@ -0,0 +1,27 @@ += CLI Connector Component +:doctitle: CLI Connector +:shortname: cli-connector +:artifactid: camel-cli-connector +:description: Runtime adapter connecting with Camel CLI +:since: 3.19 +:supportlevel: Preview + +*Since Camel {since}* + +The camel-cli-connector allows the Camel CLI to be able to manage running Camel integrations. + +Currently, only a local connector is provided, which means that the Camel CLI can only be +managing local running Camel integrations. + +These integrations can be using different runtimes such as Camel Main, Camel Spring Boot or Camel Quarkus etc. + + +== Auto-detection from classpath + +To use this implementation all you need to do is to add the `camel-cli-connector` dependency to the classpath, +and Camel should auto-detect this on startup and log as follows: + +[source,text] +---- +Local CLI Connector started +---- 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 new file mode 100644 index 00000000000..07f59815f6e --- /dev/null +++ b/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/DefaultCliConnectorFactory.java @@ -0,0 +1,71 @@ +/* + * 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.cli.connector; + +import org.apache.camel.Service; +import org.apache.camel.spi.CliConnectorFactory; +import org.apache.camel.spi.annotations.JdkService; + +@JdkService(CliConnectorFactory.FACTORY) +public class DefaultCliConnectorFactory implements CliConnectorFactory { + + private boolean enabled = true; + private String runtime; + private String runtimeVersion; + + @Override + public boolean isEnabled() { + return enabled; + } + + @Override + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + @Override + public String getRuntime() { + return runtime; + } + + @Override + public void setRuntime(String runtime) { + this.runtime = runtime; + } + + public String getRuntimeVersion() { + return runtimeVersion; + } + + public void setRuntimeVersion(String runtimeVersion) { + this.runtimeVersion = runtimeVersion; + } + + @Override + public Service createConnector() { + if (enabled) { + return new LocalCliConnector(); + } else { + return null; + } + } + + @Override + public String toString() { + return "camel-cli-connector"; + } +} 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 new file mode 100644 index 00000000000..affeb5dc93a --- /dev/null +++ b/dsl/camel-cli-connector/src/main/java/org/apache/camel/cli/connector/LocalCliConnector.java @@ -0,0 +1,206 @@ +/* + * 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.cli.connector; + +import java.io.File; +import java.util.Collection; +import java.util.Locale; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; + +import org.apache.camel.CamelContext; +import org.apache.camel.CamelContextAware; +import org.apache.camel.ExtendedCamelContext; +import org.apache.camel.console.DevConsole; +import org.apache.camel.health.HealthCheck; +import org.apache.camel.health.HealthCheckHelper; +import org.apache.camel.spi.CliConnectorFactory; +import org.apache.camel.support.service.ServiceSupport; +import org.apache.camel.util.FileUtil; +import org.apache.camel.util.IOHelper; +import org.apache.camel.util.concurrent.ThreadHelper; +import org.apache.camel.util.json.JsonObject; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * CLI Connector for local management of Camel integrations from the Camel CLI. + */ +public class LocalCliConnector extends ServiceSupport implements CamelContextAware { + + private static final Logger LOG = LoggerFactory.getLogger(LocalCliConnector.class); + + private CamelContext camelContext; + private int delay = 2000; + private String platform; + private String platformVersion; + private ScheduledExecutorService executor; + private File lockFile; + private File statusFile; + + @Override + public CamelContext getCamelContext() { + return camelContext; + } + + @Override + public void setCamelContext(CamelContext camelContext) { + this.camelContext = camelContext; + } + + @Override + protected void doStart() throws Exception { + // create thread from JDK so it is not managed by Camel because we want the pool to be independent when + // camel is being stopped which otherwise can lead to stopping the thread pool while the task is running + executor = Executors.newSingleThreadScheduledExecutor(r -> { + String threadName = ThreadHelper.resolveThreadName(null, "LocalCliConnector"); + return new Thread(r, threadName); + }); + + lockFile = createLockFile(getPid()); + if (lockFile != null) { + statusFile = createLockFile(lockFile.getName() + "-status.json"); + } + executor.scheduleWithFixedDelay(this::statusTask, 1000, delay, TimeUnit.MILLISECONDS); + + // what platform are we running + CliConnectorFactory ccf = camelContext.adapt(ExtendedCamelContext.class).getCliConnectorFactory(); + platform = ccf.getRuntime(); + if (platform == null) { + // use camel context name to guess platform if not specified + String sn = camelContext.getClass().getSimpleName().toLowerCase(Locale.ROOT); + if (sn.contains("boot")) { + platform = "Spring Boot"; + } else if (sn.contains("spring")) { + platform = "Spring"; + } else if (sn.contains("quarkus")) { + platform = "Quarkus"; + } else if (sn.contains("osgi")) { + platform = "Karaf"; + } else if (sn.contains("cdi")) { + platform = "CDI"; + } else if (sn.contains("kamelet") || camelContext.getName().equals("CamelJBang")) { + platform = "JBang"; + // dev.jbang.BuildConfig + // dev.jbang.util.getJBangVersion + } else { + platform = "Camel"; + } + } + platformVersion = ccf.getRuntimeVersion(); + + LOG.info("Local CLI Connector started"); + } + + protected void statusTask() { + // if the lock file is deleted then stop + if (!lockFile.exists()) { + try { + camelContext.stop(); + } finally { + if (lockFile != null) { + FileUtil.deleteFile(lockFile); + } + if (statusFile != null) { + FileUtil.deleteFile(statusFile); + } + } + return; + } + try { + JsonObject root = new JsonObject(); + + // what runtime are in use + JsonObject rc = new JsonObject(); + rc.put("platform", platform); + if (platformVersion != null) { + rc.put("version", platformVersion); + } + root.put("runtime", rc); + + // collect details via console + DevConsole dc = camelContext.adapt(ExtendedCamelContext.class) + .getDevConsoleResolver().resolveDevConsole("context"); + DevConsole dc2 = camelContext.adapt(ExtendedCamelContext.class) + .getDevConsoleResolver().resolveDevConsole("route"); + int ready = 0; + int total = 0; + if (dc != null && dc2 != null) { + JsonObject json = (JsonObject) dc.call(DevConsole.MediaType.JSON); + JsonObject json2 = (JsonObject) dc2.call(DevConsole.MediaType.JSON); + if (json != null && json2 != null) { + root.put("context", json); + root.put("routes", json2.get("routes")); + } + } + // and health-check readiness + Collection<HealthCheck.Result> res = HealthCheckHelper.invokeReadiness(camelContext); + for (var r : res) { + if (r.getState().equals(HealthCheck.State.UP)) { + ready++; + } + total++; + } + JsonObject hc = new JsonObject(); + hc.put("ready", ready); + hc.put("total", total); + root.put("healthChecks", hc); + + LOG.trace("Updating status file: {}", statusFile); + IOHelper.writeText(root.toJson(), statusFile); + } catch (Throwable e) { + // ignore + } + } + + @Override + protected void doStop() throws Exception { + // cleanup + if (executor != null) { + camelContext.getExecutorServiceManager().shutdown(executor); + executor = null; + } + } + + private static String getPid() { + try { + return "" + ProcessHandle.current().pid(); + } catch (Throwable e) { + return null; + } + } + + private static File createLockFile(String name) { + File answer = null; + if (name != null) { + File dir = new File(System.getProperty("user.home"), ".camel"); + try { + dir.mkdirs(); + answer = new File(dir, name); + if (!answer.exists()) { + answer.createNewFile(); + } + answer.deleteOnExit(); + } catch (Exception e) { + answer = null; + } + } + return answer; + } + +} diff --git a/dsl/camel-jbang/camel-jbang-core/pom.xml b/dsl/camel-jbang/camel-jbang-core/pom.xml index d08abf5d450..823ffa790e0 100644 --- a/dsl/camel-jbang/camel-jbang-core/pom.xml +++ b/dsl/camel-jbang/camel-jbang-core/pom.xml @@ -59,6 +59,10 @@ </dependency> <!-- cli --> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-cli-connector</artifactId> + </dependency> <dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java index 35dbc130deb..ce959f140db 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/Run.java @@ -30,16 +30,12 @@ import java.nio.file.Files; import java.nio.file.Paths; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Locale; import java.util.Properties; import java.util.Set; import java.util.StringJoiner; -import java.util.concurrent.Executors; -import java.util.concurrent.ScheduledExecutorService; -import java.util.concurrent.TimeUnit; import java.util.function.Supplier; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -49,12 +45,8 @@ import com.fasterxml.jackson.databind.ObjectMapper; import io.apicurio.datamodels.Library; import io.apicurio.datamodels.openapi.models.OasDocument; import org.apache.camel.CamelContext; -import org.apache.camel.ExtendedCamelContext; -import org.apache.camel.console.DevConsole; import org.apache.camel.dsl.jbang.core.common.RuntimeUtil; import org.apache.camel.generator.openapi.RestDslGenerator; -import org.apache.camel.health.HealthCheck; -import org.apache.camel.health.HealthCheckHelper; import org.apache.camel.impl.lw.LightweightCamelContext; import org.apache.camel.main.KameletMain; import org.apache.camel.main.download.DownloadListener; @@ -64,7 +56,6 @@ 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.json.JsonObject; import org.apache.logging.log4j.Level; import org.apache.logging.log4j.core.config.Configurator; import picocli.CommandLine; @@ -95,9 +86,6 @@ class Run extends CamelCommand { "^\\s*public class\\s+([a-zA-Z0-9]*)[\\s+|;].*$", Pattern.MULTILINE); private CamelContext context; - private File lockFile; - private File statusFile; - private ScheduledExecutorService executor; private boolean silentRun; private boolean pipeRun; @@ -165,10 +153,6 @@ class Run extends CamelCommand { @Option(names = { "-p", "--prop", "--property" }, description = "Additional properties (override existing)", arity = "0") String[] property; - @Option(names = { "--file-lock" }, - description = "Whether to create a temporary file lock, which upon deleting triggers this process to terminate", defaultValue = "true") - boolean fileLock = true; - @Option(names = { "--jfr" }, description = "Enables Java Flight Recorder saving recording to disk on exit") boolean jfr; @@ -245,12 +229,6 @@ class Run extends CamelCommand { } private int stop() { - if (lockFile != null) { - FileUtil.deleteFile(lockFile); - } - if (statusFile != null) { - FileUtil.deleteFile(statusFile); - } return 0; } @@ -409,10 +387,6 @@ class Run extends CamelCommand { writeSetting(main, profileProperties, "camel.jbang.jfr", jfr || jfrProfile != null ? "jfr" : null); writeSetting(main, profileProperties, "camel.jbang.jfr-profile", jfrProfile != null ? jfrProfile : null); - if (fileLock) { - initLockFile(main); - } - StringJoiner js = new StringJoiner(","); StringJoiner sjReload = new StringJoiner(","); StringJoiner sjClasspathFiles = new StringJoiner(","); @@ -571,57 +545,6 @@ class Run extends CamelCommand { return main.getExitCode(); } - private void initLockFile(KameletMain main) { - lockFile = createLockFile(getPid()); - if (lockFile != null) { - statusFile = createLockFile(lockFile.getName() + "-status.json"); - } - // to trigger shutdown on file lock deletion - executor = Executors.newSingleThreadScheduledExecutor(); - executor.scheduleWithFixedDelay(() -> { - // if the lock file is deleted then stop - if (!lockFile.exists()) { - context.stop(); - return; - } - try { - // update status file with details from the context console - JsonObject root = new JsonObject(); - DevConsole dc = main.getCamelContext().adapt(ExtendedCamelContext.class) - .getDevConsoleResolver().resolveDevConsole("context"); - DevConsole dc2 = main.getCamelContext().adapt(ExtendedCamelContext.class) - .getDevConsoleResolver().resolveDevConsole("route"); - int ready = 0; - int total = 0; - if (dc != null && dc2 != null) { - JsonObject json = (JsonObject) dc.call(DevConsole.MediaType.JSON); - JsonObject json2 = (JsonObject) dc2.call(DevConsole.MediaType.JSON); - if (json != null && json2 != null) { - root.put("context", json); - json.put("runtime", "camel-jbang"); - root.put("routes", json2.get("routes")); - } - } - // and health-check readiness - Collection<HealthCheck.Result> res = HealthCheckHelper.invokeReadiness(main.getCamelContext()); - for (var r : res) { - if (r.getState().equals(HealthCheck.State.UP)) { - ready++; - } - total++; - } - JsonObject hc = new JsonObject(); - hc.put("ready", ready); - hc.put("total", total); - root.put("healthChecks", hc); - - IOHelper.writeText(root.toJson(), statusFile); - } catch (Throwable e) { - // ignore - } - }, 2000, 2000, TimeUnit.MILLISECONDS); - } - private String evalGistSource(KameletMain main, String file) throws Exception { StringJoiner routes = new StringJoiner(","); StringJoiner kamelets = new StringJoiner(","); 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 7ed706897ef..73fba159cf0 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 @@ -81,10 +81,12 @@ public class CamelContextStatus extends ProcessBaseCommand { row.ago = TimeUtils.printSince(extractSince(ph)); JsonObject root = loadStatus(ph.pid()); if (root != null) { - JsonObject hc = (JsonObject) root.get("healthChecks"); - row.ready = hc != null ? hc.getString("ready") + "/" + hc.getString("total") : null; + JsonObject runtime = (JsonObject) root.get("runtime"); + row.platform = runtime != null ? runtime.getString("platform") : null; + row.platformVersion = runtime != null ? runtime.getString("platformVersion") : 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(); @@ -95,6 +97,8 @@ public class CamelContextStatus extends ProcessBaseCommand { row.sinceLast = last.toString(); } } + JsonObject hc = (JsonObject) root.get("healthChecks"); + row.ready = hc != null ? hc.getString("ready") + "/" + hc.getString("total") : null; } rows.add(row); } @@ -105,6 +109,8 @@ public class CamelContextStatus extends ProcessBaseCommand { new Column().header("PID").headerAlign(HorizontalAlign.CENTER).with(r -> r.pid), new Column().header("NAME").dataAlign(HorizontalAlign.LEFT).maxWidth(30, OverflowBehaviour.ELLIPSIS) .with(r -> r.name), + 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)), @@ -118,6 +124,14 @@ public class CamelContextStatus extends ProcessBaseCommand { return 0; } + private String getPlatform(Row r) { + if (r.platformVersion != null) { + return r.platform + " v" + r.platformVersion + ")"; + } else { + return r.platform; + } + } + private JsonObject loadStatus(long pid) { try { File f = getStatusFile("" + pid); @@ -135,6 +149,9 @@ public class CamelContextStatus extends ProcessBaseCommand { private static class Row { String pid; + String platform; + String platformVersion; + String camelVersion; String name; String ready; String state; 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 55233f1f528..cb1046c55c8 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 @@ -45,7 +45,9 @@ public class ListProcess extends ProcessBaseCommand { public Integer call() throws Exception { List<Row> rows = new ArrayList<>(); + final long cur = ProcessHandle.current().pid(); ProcessHandle.allProcesses() + .filter(ph -> ph.pid() != cur) .sorted((o1, o2) -> { switch (sort) { case "pid": 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 82abe67c958..8181e14150a 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 @@ -51,8 +51,10 @@ abstract class ProcessBaseCommand extends CamelCommand { } } + final long cur = ProcessHandle.current().pid(); final String pattern = name; ProcessHandle.allProcesses() + .filter(ph -> ph.pid() != cur) .forEach(ph -> { String pName = extractName(ph); // ignore file extension, so it is easier to match by name @@ -67,6 +69,45 @@ abstract class ProcessBaseCommand extends CamelCommand { static String extractName(ProcessHandle ph) { String cl = ph.info().commandLine().orElse(""); + + String name = extractCamelJBangName(cl); + if (name == null) { + name = extractCamelMavenName(cl); + } + if (name == null) { + name = extractCamelMain(cl); + } + + return name == null ? "" : name; + } + + private static String extractCamelMavenName(String cl) { + String name = StringHelper.before(cl, " camel:run"); + if (name != null) { + if (name.contains("org.codehaus.plexus.classworlds.launcher.Launcher")) { + return "mvn camel:run"; + } + } + + return null; + } + + private static String extractCamelMain(String cl) { + if (cl != null) { + if (cl.contains("camel-main")) { + int pos = cl.lastIndexOf(" "); + String after = cl.substring(pos); + after = after.trim(); + if (after.matches("[\\w|.]+")) { + return "camel-main"; + } + } + } + + return null; + } + + private static String extractCamelJBangName(String cl) { String name = StringHelper.after(cl, "main.CamelJBang run"); if (name != null) { name = name.trim(); @@ -83,7 +124,7 @@ abstract class ProcessBaseCommand extends CamelCommand { return js.toString(); } - return ""; + return null; } static long extractSince(ProcessHandle ph) { diff --git a/dsl/pom.xml b/dsl/pom.xml index 5a4ec865a65..e3a29e2680f 100644 --- a/dsl/pom.xml +++ b/dsl/pom.xml @@ -42,6 +42,7 @@ <modules> <module>camel-endpointdsl</module> <module>camel-componentdsl</module> + <module>camel-cli-connector</module> <module>camel-dsl-support</module> <module>camel-dsl-modeline</module> <module>camel-endpointdsl-support</module> diff --git a/parent/pom.xml b/parent/pom.xml index 6ff0661c1e6..c1fd3805c3b 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -1100,6 +1100,11 @@ <artifactId>camel-chunk</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-cli-connector</artifactId> + <version>${project.version}</version> + </dependency> <dependency> <groupId>org.apache.camel</groupId> <artifactId>camel-cloudevents</artifactId>