This is an automated email from the ASF dual-hosted git repository. orpiske 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 b0bada2 CAMEL-16612: add support for JBang within Camel (#5770) b0bada2 is described below commit b0bada2f41029cd8496db4defc09b3a48b403ad4 Author: Otavio Rodolfo Piske <orpi...@users.noreply.github.com> AuthorDate: Fri Jul 9 10:09:15 2021 +0200 CAMEL-16612: add support for JBang within Camel (#5770) This introduces a JBang-based script that can run Kamelet bindings and search for Kamelets in the catalog. Additionally, it supports searching for kamelets, components, languages and miscellaneous components. --- camel-dependencies/pom.xml | 1 + dsl/camel-jbang/camel-jbang-core/pom.xml | 48 +++ .../apache/camel/dsl/jbang/core/api/Converter.java | 24 ++ .../apache/camel/dsl/jbang/core/api/Extractor.java | 22 ++ .../apache/camel/dsl/jbang/core/api/Printer.java | 22 ++ .../dsl/jbang/core/commands/AbstractSearch.java | 103 ++++++ .../dsl/jbang/core/common/MatchExtractor.java | 47 +++ .../jbang/core/components/ComponentConverter.java | 37 +++ .../components/ComponentDescriptionMatching.java | 35 ++ .../jbang/core/components/ComponentPrinter.java | 28 ++ .../dsl/jbang/core/kamelets/KameletConverter.java | 35 ++ .../core/kamelets/KameletDescriptionMatching.java | 35 ++ .../dsl/jbang/core/kamelets/KameletPrinter.java | 28 ++ .../jbang/core/languages/LanguageConverter.java | 37 +++ .../languages/LanguageDescriptionMatching.java | 35 ++ .../dsl/jbang/core/languages/LanguagePrinter.java | 28 ++ .../dsl/jbang/core/others/OtherConverter.java | 37 +++ .../core/others/OtherDescriptionMatching.java | 35 ++ .../camel/dsl/jbang/core/others/OtherPrinter.java | 28 ++ .../camel/dsl/jbang/core/types/Component.java | 25 ++ .../apache/camel/dsl/jbang/core/types/Kamelet.java | 24 ++ .../camel/dsl/jbang/core/types/Language.java | 22 ++ .../apache/camel/dsl/jbang/core/types/Other.java | 21 ++ dsl/camel-jbang/camel-jbang-main/README.md | 113 +++++++ .../camel-jbang-main/dist/CamelJBang.java | 363 +++++++++++++++++++++ .../camel-jbang-main/examples/earthquake.yaml | 22 ++ .../examples/jms-amqp-10-sink-binding.yaml | 31 ++ .../jms-apache-artemis-source-binding.yaml | 24 ++ .../examples/kafka-unsecured-sink.yaml | 30 ++ .../examples/kafka-unsecured-source.yaml | 24 ++ dsl/camel-jbang/camel-jbang-main/pom.xml | 141 ++++++++ .../src/main/jbang/main/CamelJBang.java | 363 +++++++++++++++++++++ dsl/camel-jbang/pom.xml | 40 +++ dsl/pom.xml | 1 + jbang-catalog.json | 9 + parent/pom.xml | 7 + 36 files changed, 1925 insertions(+) diff --git a/camel-dependencies/pom.xml b/camel-dependencies/pom.xml index faa33ae..635146d 100644 --- a/camel-dependencies/pom.xml +++ b/camel-dependencies/pom.xml @@ -452,6 +452,7 @@ <pdfbox-version>2.0.24</pdfbox-version> <pgjdbc-driver-version>42.2.14</pgjdbc-driver-version> <pgjdbc-ng-driver-version>0.8.6</pgjdbc-ng-driver-version> + <picocli-version>4.5.0</picocli-version> <powermock-version>2.0.7</powermock-version> <properties-maven-plugin-version>1.0-alpha-2</properties-maven-plugin-version> <protobuf-maven-plugin-version>0.6.1</protobuf-maven-plugin-version> diff --git a/dsl/camel-jbang/camel-jbang-core/pom.xml b/dsl/camel-jbang/camel-jbang-core/pom.xml new file mode 100644 index 0000000..4ed2fa7 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/pom.xml @@ -0,0 +1,48 @@ +<?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/xsd/maven-4.0.0.xsd"> + <parent> + <groupId>org.apache.camel</groupId> + <artifactId>camel-jbang</artifactId> + <version>3.12.0-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + <modelVersion>4.0.0</modelVersion> + + <artifactId>camel-jbang-core</artifactId> + + <dependencies> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-main</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-kamelet-main</artifactId> + </dependency> + + <dependency> + <groupId>commons-io</groupId> + <artifactId>commons-io</artifactId> + </dependency> + + </dependencies> + +</project> diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/api/Converter.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/api/Converter.java new file mode 100644 index 0000000..962d13e --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/api/Converter.java @@ -0,0 +1,24 @@ +/* + * 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.api; + +import java.util.regex.Matcher; + +public interface Converter<T> { + T convert(Matcher matcher); +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/api/Extractor.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/api/Extractor.java new file mode 100644 index 0000000..be531a9 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/api/Extractor.java @@ -0,0 +1,22 @@ +/* + * 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.api; + +public interface Extractor { + void extract(String line); +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/api/Printer.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/api/Printer.java new file mode 100644 index 0000000..e43ae90 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/api/Printer.java @@ -0,0 +1,22 @@ +/* + * 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.api; + +public interface Printer<T> { + void inject(T data); +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/AbstractSearch.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/AbstractSearch.java new file mode 100644 index 0000000..3103fbd --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/AbstractSearch.java @@ -0,0 +1,103 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.camel.dsl.jbang.core.commands; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileReader; +import java.io.IOException; +import java.util.regex.Pattern; + +import org.apache.camel.CamelContext; +import org.apache.camel.dsl.jbang.core.api.Extractor; +import org.apache.camel.github.GitHubResourceResolver; +import org.apache.camel.main.KameletMain; +import org.apache.camel.spi.Resource; +import org.apache.commons.io.IOUtils; + +public abstract class AbstractSearch { + private String resourceLocation; + private Pattern pattern; + + // Only used for the search subcommand + protected AbstractSearch() { + } + + public AbstractSearch(String resourceLocation, Pattern pattern) { + this.resourceLocation = resourceLocation; + this.pattern = pattern; + } + + protected void downloadResource(File indexFile) throws Exception { + KameletMain main = new KameletMain(); + main.start(); + CamelContext context = main.getCamelContext(); + + try (GitHubResourceResolver resolver = new GitHubResourceResolver()) { + resolver.setCamelContext(context); + + Resource resource = resolver.resolve(resourceLocation); + + if (!resource.exists()) { + throw new Exception("The resource does not exist"); + } + + try (FileOutputStream fo = new FileOutputStream(indexFile)) { + IOUtils.copy(resource.getInputStream(), fo); + } + } + } + + private void readFileByLine(File indexFile, Extractor extractor) throws IOException { + FileReader indexFileReader = new FileReader(indexFile); + try (BufferedReader br = new BufferedReader(indexFileReader)) { + + String line; + do { + line = br.readLine(); + + if (line == null) { + break; + } + + extractor.extract(line); + + } while (line != null); + } + } + + public abstract void printHeader(); + + public void search(Extractor extractor) throws Exception { + File indexFile = getIndexFile(); + + printHeader(); + + readFileByLine(indexFile, extractor); + } + + private File getIndexFile() throws Exception { + File indexFile = new File("index"); + indexFile.deleteOnExit(); + + downloadResource(indexFile); + + return indexFile; + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/MatchExtractor.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/MatchExtractor.java new file mode 100644 index 0000000..bad3886 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/MatchExtractor.java @@ -0,0 +1,47 @@ +/* + * 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.common; + +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import org.apache.camel.dsl.jbang.core.api.Converter; +import org.apache.camel.dsl.jbang.core.api.Extractor; +import org.apache.camel.dsl.jbang.core.api.Printer; + +public class MatchExtractor<T> implements Extractor { + private final Pattern pattern; + private final Converter<T> converter; + private final Printer<T> injector; + + public MatchExtractor(Pattern pattern, Converter<T> converter, Printer<T> injector) { + this.pattern = pattern; + this.converter = converter; + this.injector = injector; + } + + @Override + public void extract(String line) { + Matcher matcher = pattern.matcher(line); + + if (matcher.find()) { + T data = converter.convert(matcher); + injector.inject(data); + } + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/components/ComponentConverter.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/components/ComponentConverter.java new file mode 100644 index 0000000..c7baa88 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/components/ComponentConverter.java @@ -0,0 +1,37 @@ +/* + * 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.components; + +import java.util.regex.Matcher; + +import org.apache.camel.dsl.jbang.core.api.Converter; +import org.apache.camel.dsl.jbang.core.types.Component; + +public class ComponentConverter implements Converter<Component> { + @Override + public Component convert(Matcher matcher) { + Component component = new Component(); + + component.name = matcher.group(2).replace(".adoc", ""); + component.shortName = component.name.replace("-component", ""); + component.description = matcher.group(3); + component.link = String.format("https://camel.apache.org/components/latest/%s.html", component.name); + + return component; + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/components/ComponentDescriptionMatching.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/components/ComponentDescriptionMatching.java new file mode 100644 index 0000000..33f48e6 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/components/ComponentDescriptionMatching.java @@ -0,0 +1,35 @@ +/* + * 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.components; + +import org.apache.camel.dsl.jbang.core.types.Component; + +public class ComponentDescriptionMatching extends ComponentPrinter { + private final String searchTerm; + + public ComponentDescriptionMatching(String searchTerm) { + this.searchTerm = searchTerm; + } + + @Override + public void inject(Component component) { + if (component.description.toLowerCase().contains(searchTerm.toLowerCase())) { + super.inject(component); + } + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/components/ComponentPrinter.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/components/ComponentPrinter.java new file mode 100644 index 0000000..0ff9126 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/components/ComponentPrinter.java @@ -0,0 +1,28 @@ +/* + * 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.components; + +import org.apache.camel.dsl.jbang.core.api.Printer; +import org.apache.camel.dsl.jbang.core.types.Component; + +public class ComponentPrinter implements Printer<Component> { + @Override + public void inject(Component component) { + System.out.printf("%-35s %-45s %s%n", component.shortName, component.description, component.link); + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/kamelets/KameletConverter.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/kamelets/KameletConverter.java new file mode 100644 index 0000000..c9e3926 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/kamelets/KameletConverter.java @@ -0,0 +1,35 @@ +/* + * 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.kamelets; + +import java.util.regex.Matcher; + +import org.apache.camel.dsl.jbang.core.api.Converter; +import org.apache.camel.dsl.jbang.core.types.Kamelet; + +public class KameletConverter implements Converter<Kamelet> { + public Kamelet convert(Matcher matcher) { + Kamelet kamelet = new Kamelet(); + + kamelet.name = matcher.group(3).replace(".adoc", ""); + kamelet.description = matcher.group(5); + kamelet.link = String.format("https://camel.apache.org/camel-kamelets/latest/%s.html", kamelet.name); + + return kamelet; + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/kamelets/KameletDescriptionMatching.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/kamelets/KameletDescriptionMatching.java new file mode 100644 index 0000000..dcea85e --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/kamelets/KameletDescriptionMatching.java @@ -0,0 +1,35 @@ +/* + * 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.kamelets; + +import org.apache.camel.dsl.jbang.core.types.Kamelet; + +public class KameletDescriptionMatching extends KameletPrinter { + private final String searchTerm; + + public KameletDescriptionMatching(String searchTerm) { + this.searchTerm = searchTerm; + } + + @Override + public void inject(Kamelet kamelet) { + if (kamelet.description.toLowerCase().contains(searchTerm.toLowerCase())) { + super.inject(kamelet); + } + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/kamelets/KameletPrinter.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/kamelets/KameletPrinter.java new file mode 100644 index 0000000..b541f95 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/kamelets/KameletPrinter.java @@ -0,0 +1,28 @@ +/* + * 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.kamelets; + +import org.apache.camel.dsl.jbang.core.api.Printer; +import org.apache.camel.dsl.jbang.core.types.Kamelet; + +public class KameletPrinter implements Printer<Kamelet> { + @Override + public void inject(Kamelet kamelet) { + System.out.printf("%-35s %-45s %s%n", kamelet.name, kamelet.description, kamelet.link); + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/languages/LanguageConverter.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/languages/LanguageConverter.java new file mode 100644 index 0000000..24da419 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/languages/LanguageConverter.java @@ -0,0 +1,37 @@ +/* + * 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.languages; + +import java.util.regex.Matcher; + +import org.apache.camel.dsl.jbang.core.api.Converter; +import org.apache.camel.dsl.jbang.core.types.Language; + +public class LanguageConverter implements Converter<Language> { + @Override + public Language convert(Matcher matcher) { + Language language = new Language(); + + language.name = matcher.group(2).replace(".adoc", ""); + language.shortName = language.name.replace("-language", ""); + language.description = matcher.group(3); + language.link = String.format("https://camel.apache.org/components/latest/languages/%s.html", language.name); + + return language; + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/languages/LanguageDescriptionMatching.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/languages/LanguageDescriptionMatching.java new file mode 100644 index 0000000..4ba77dd --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/languages/LanguageDescriptionMatching.java @@ -0,0 +1,35 @@ +/* + * 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.languages; + +import org.apache.camel.dsl.jbang.core.types.Language; + +public class LanguageDescriptionMatching extends LanguagePrinter { + private final String searchTerm; + + public LanguageDescriptionMatching(String searchTerm) { + this.searchTerm = searchTerm; + } + + @Override + public void inject(Language language) { + if (language.description.toLowerCase().contains(searchTerm.toLowerCase())) { + super.inject(language); + } + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/languages/LanguagePrinter.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/languages/LanguagePrinter.java new file mode 100644 index 0000000..b2768a7 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/languages/LanguagePrinter.java @@ -0,0 +1,28 @@ +/* + * 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.languages; + +import org.apache.camel.dsl.jbang.core.api.Printer; +import org.apache.camel.dsl.jbang.core.types.Language; + +public class LanguagePrinter implements Printer<Language> { + @Override + public void inject(Language language) { + System.out.printf("%-35s %-45s %s%n", language.shortName, language.description, language.link); + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/others/OtherConverter.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/others/OtherConverter.java new file mode 100644 index 0000000..2db5b11 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/others/OtherConverter.java @@ -0,0 +1,37 @@ +/* + * 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.others; + +import java.util.regex.Matcher; + +import org.apache.camel.dsl.jbang.core.api.Converter; +import org.apache.camel.dsl.jbang.core.types.Other; + +public class OtherConverter implements Converter<Other> { + @Override + public Other convert(Matcher matcher) { + Other other = new Other(); + + other.name = matcher.group(2).replace(".adoc", ""); + other.shortName = other.name.replace("-other", ""); + other.description = matcher.group(3); + other.link = String.format("https://camel.apache.org/components/latest/others/%s.html", other.name); + + return other; + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/others/OtherDescriptionMatching.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/others/OtherDescriptionMatching.java new file mode 100644 index 0000000..b67f174 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/others/OtherDescriptionMatching.java @@ -0,0 +1,35 @@ +/* + * 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.others; + +import org.apache.camel.dsl.jbang.core.types.Other; + +public class OtherDescriptionMatching extends OtherPrinter { + private final String searchTerm; + + public OtherDescriptionMatching(String searchTerm) { + this.searchTerm = searchTerm; + } + + @Override + public void inject(Other other) { + if (other.description.toLowerCase().contains(searchTerm.toLowerCase())) { + super.inject(other); + } + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/others/OtherPrinter.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/others/OtherPrinter.java new file mode 100644 index 0000000..cd78963 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/others/OtherPrinter.java @@ -0,0 +1,28 @@ +/* + * 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.others; + +import org.apache.camel.dsl.jbang.core.api.Printer; +import org.apache.camel.dsl.jbang.core.types.Other; + +public class OtherPrinter implements Printer<Other> { + @Override + public void inject(Other other) { + System.out.printf("%-35s %-45s %s%n", other.shortName, other.description, other.link); + } +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/types/Component.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/types/Component.java new file mode 100644 index 0000000..84d2de7 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/types/Component.java @@ -0,0 +1,25 @@ +/* + * 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.types; + +public class Component { + public String name; + public String shortName; + public String description; + public String link; +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/types/Kamelet.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/types/Kamelet.java new file mode 100644 index 0000000..b0896b5 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/types/Kamelet.java @@ -0,0 +1,24 @@ +/* + * 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.types; + +public class Kamelet { + public String name; + public String description; + public String link; +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/types/Language.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/types/Language.java new file mode 100644 index 0000000..4cd64f5 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/types/Language.java @@ -0,0 +1,22 @@ +/* + * 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.types; + +public class Language extends Component { + +} diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/types/Other.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/types/Other.java new file mode 100644 index 0000000..d48f326 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/types/Other.java @@ -0,0 +1,21 @@ +/* + * 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.types; + +public class Other extends Component { +} diff --git a/dsl/camel-jbang/camel-jbang-main/README.md b/dsl/camel-jbang/camel-jbang-main/README.md new file mode 100644 index 0000000..b1e0f75 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-main/README.md @@ -0,0 +1,113 @@ +# Camel JBang + +A JBang-based Camel app for running Kamelets + +## Usage + +``` +./CamelJBang.java run path/to/route-binding.yaml +``` + +To show the help: + +``` +./CamelJBang.java --help +``` + +After launching, the scripts will run indefinitely. If you want to stop them, you can either use Ctrl + C or remove the +run locks: + +``` +rm .run*.lock +``` + +## Running the other examples + +To run the Earthquake example: + +``` +./CamelJBang.java run examples/earthquake.yaml +``` + +To run the JMS examples, you will need an instance of the Apache Artemis broker. If you don't have one available, you can build a container from the image used in Camel tests: + +``` +docker build -f ../../test-infra/camel-test-infra-artemis/src/test/resources/org/apache/camel/test/infra/artemis/services/Dockerfile --build-arg FROMIMAGE=fedora:33 -t apache-artemis:latest . +``` + +Then you can launch the container using: + + +``` +docker run --rm -p 61616:61616 -p 5672:5672 -p 8161:8161 apache-artemis:latest +``` + +And, lastly, to run the examples, first open a terminal to run the source binding: + +``` +./CamelJBang.java run examples/jms-apache-artemis-source-binding.yaml +``` + +Then, open another one to run the sink binding: + +``` +./CamelJBang.java run examples/jms-amqp-10-sink-binding.yaml +``` + +The Kafka example follow the same pattern, but you will need a Kafka broker instance. There are several container images +available for Kafka, such as the Confluent one and the Strimzi project one. + + +## Development + +### Handling Dependencies Versions + +This module aims to be both simple and practical, as such, there are a few recommendations to follow when contributing +to the code on +this particular module. + +The module leverages JBang's ability to [parameterize dependencies](https://www.jbang.dev/documentation/guide/latest/dependencies.html#system-properties-and-environment-variables) along with Antrun's +ability to process source code on the fly and perform string substitution to replace strings on files. + +During the build, the *perfectly valid* Java-based JBang script code is copied to the `dist` directory. Then the antrun +plugin replaces the references to parameterized dependencies. The parameterized dependencies are in the format `${name}`. + +In order to minimize the problems caused by CVEs in dependencies and ensure the correct alignment of dependencies within +Camel, all references to dependencies should use parameterized ones. Such as: + +``` +//DEPS org.apache.camel:camel-bom:${camel.jbang.version}@pom +``` + +After being processed by antrun, during the build, the aforementioned line would be transformed to something like (for +a Camel 3.12.0-SNAPSHOT build): + +``` +//DEPS org.apache.camel:camel-bom:3.12.0-SNAPSHOT@pom +``` + +The same applies to Camel version references, which should rely on the `${camel.jbang.version}` parameter (such +as when displaying help information). + +Despite this transformation, the code in `src/main/jbang` should be valid nonetheless and can be executed for development +and debugging purposes by correctly resolving the parameterized variables on the command line. Such as: + +``` +jbang -Dcamel.jbang.version=3.12.0-SNAPSHOT -Dcamel.jbang.log4j2.version=2.13.3 -Dcamel.jbang.picocli.version=4.5.0 CamelJBang.java +``` + +Alternatively, it is possible to just build the module and then execute the post-processed script on the `dist` directory. + +```mvn clean package && ./dist/Camel``` + +### Checkstyle + +Because the first line of the script requires a she-bang like line, it violates the default checkstyle used by the +Apache Camel project. As such, the checkstyle is skipped for this module. Nonetheless, the usual Apache Camel coding +should be observed and followed when contributing to this module. + +If needed, the checkstyle plugin can be forcely run using the following command: + +``` +mvn -Dcheckstyle.skip=false clean verify +``` diff --git a/dsl/camel-jbang/camel-jbang-main/dist/CamelJBang.java b/dsl/camel-jbang/camel-jbang-main/dist/CamelJBang.java new file mode 100755 index 0000000..e213467 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-main/dist/CamelJBang.java @@ -0,0 +1,363 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? + +/* + * 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. + */ + +//REPOS mavencentral,apache=https://repository.apache.org/snapshots +//DEPS org.apache.camel:camel-bom:3.12.0-SNAPSHOT@pom +//DEPS org.apache.camel:camel-core +//DEPS org.apache.camel:camel-core-model +//DEPS org.apache.camel:camel-api +//DEPS org.apache.camel:camel-main +//DEPS org.apache.camel:camel-kamelet-main +//DEPS org.apache.camel:camel-file-watch +//DEPS org.apache.camel:camel-resourceresolver-github +//DEPS org.apache.camel:camel-jbang-core:3.12.0-SNAPSHOT +//DEPS org.apache.logging.log4j:log4j-api:2.13.3 +//DEPS org.apache.logging.log4j:log4j-core:2.13.3 +//DEPS org.apache.logging.log4j:log4j-slf4j-impl:2.13.3 +//DEPS info.picocli:picocli:4.5.0 + +package main; + +import java.io.File; +import java.io.IOException; +import java.util.concurrent.Callable; +import java.util.regex.Pattern; + +import org.apache.camel.CamelContext; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.dsl.jbang.core.commands.AbstractSearch; +import org.apache.camel.dsl.jbang.core.common.MatchExtractor; +import org.apache.camel.dsl.jbang.core.components.ComponentConverter; +import org.apache.camel.dsl.jbang.core.components.ComponentDescriptionMatching; +import org.apache.camel.dsl.jbang.core.components.ComponentPrinter; +import org.apache.camel.dsl.jbang.core.kamelets.KameletConverter; +import org.apache.camel.dsl.jbang.core.kamelets.KameletDescriptionMatching; +import org.apache.camel.dsl.jbang.core.kamelets.KameletPrinter; +import org.apache.camel.dsl.jbang.core.languages.LanguageConverter; +import org.apache.camel.dsl.jbang.core.languages.LanguageDescriptionMatching; +import org.apache.camel.dsl.jbang.core.languages.LanguagePrinter; +import org.apache.camel.dsl.jbang.core.others.OtherConverter; +import org.apache.camel.dsl.jbang.core.others.OtherDescriptionMatching; +import org.apache.camel.dsl.jbang.core.others.OtherPrinter; +import org.apache.camel.dsl.jbang.core.types.Component; +import org.apache.camel.dsl.jbang.core.types.Kamelet; +import org.apache.camel.dsl.jbang.core.types.Language; +import org.apache.camel.dsl.jbang.core.types.Other; +import org.apache.camel.main.KameletMain; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.config.Configurator; +import org.apache.logging.log4j.core.config.DefaultConfiguration; +import picocli.CommandLine; +import picocli.CommandLine.Command; +import picocli.CommandLine.Option; +import picocli.CommandLine.Parameters; + +@Command(name = "run", description = "Run a Kamelet") +class Run implements Callable<Integer> { + private CamelContext context; + + @Parameters(description = "The path to the kamelet binding", arity = "1") + private String binding; + + @Option(names = { "--debug-level" }, defaultValue = "info", description = "Default debug level") + private String debugLevel; + + class ShutdownRoute extends RouteBuilder { + private File lockFile; + + public ShutdownRoute(File lockFile) { + this.lockFile = lockFile; + } + + public void configure() { + fromF("file-watch://%s?events=DELETE&antInclude=%s", lockFile.getParent(), lockFile.getName()) + .process(p -> context.shutdown()); + } + } + + @Override + public Integer call() throws Exception { + switch (debugLevel) { + case "trace": + Configurator.setRootLevel(Level.TRACE); + break; + case "debug": + Configurator.setRootLevel(Level.DEBUG); + break; + case "info": + Configurator.setRootLevel(Level.INFO); + break; + case "warn": + Configurator.setRootLevel(Level.WARN); + break; + case "fatal": + Configurator.setRootLevel(Level.FATAL); + break; + default: { + System.err.println("Invalid debug level " + debugLevel); + return 1; + } + } + + File bindingFile = new File(binding); + if (!bindingFile.exists()) { + System.err.println("The binding file does not exist"); + + return 1; + } + + System.setProperty("camel.main.routes-include-pattern", "file:" + binding); + System.setProperty("camel.main.name", "CamelJBang"); + + System.out.println("Starting Camel JBang!"); + KameletMain main = new KameletMain(); + + main.configure().addRoutesBuilder(new ShutdownRoute(createLockFile())); + main.start(); + context = main.getCamelContext(); + + main.run(); + return 0; + } + + public File createLockFile() throws IOException { + File lockFile = File.createTempFile(".run", ".camel.lock", new File(".")); + + System.out.printf("A new lock file was created on %s. Delete this file to stop running%n", + lockFile.getAbsolutePath()); + lockFile.deleteOnExit(); + + return lockFile; + } +} + +@Command(name = "search", description = "Search for kameletes, components and patterns (use --help)") +class Search extends AbstractSearch implements Callable<Integer> { + public Search() { + super(null, null); + } + + public void printHeader() { + } + + @Override + public Integer call() throws Exception { + CommandLine.usage(this, System.out); + + return 0; + } +} + +@Command(name = "kamelets", description = "Search for a Kamelet in the Kamelet catalog") +class SearchKamelets extends AbstractSearch implements Callable<Integer> { + /* + * Matches the following line. Separate them into groups and pick the last + * which contains the description: + * + * xref:ROOT:mariadb-sink.adoc[image:kamelets/mariadb-sink.svg[] MariaDB Sink] + */ + private static final Pattern PATTERN = Pattern.compile("(.*):(.*):(.*)\\[(.*)\\[\\] (.*)\\]"); + + @Option(names = { "--search-term" }, defaultValue = "", description = "Default debug level") + private String searchTerm; + + SearchKamelets() { + super("github:apache:camel-kamelets:docs/modules/ROOT/nav.adoc", PATTERN); + } + + @Override + public void printHeader() { + System.out.printf("%-35s %-45s %s%n", "KAMELET", "DESCRIPTION", "LINK"); + System.out.printf("%-35s %-45s %s%n", "-------", "-----------", "-----"); + } + + @Override + public Integer call() throws Exception { + MatchExtractor<Kamelet> matchExtractor; + + if (searchTerm.isEmpty()) { + matchExtractor = new MatchExtractor<>(PATTERN, new KameletConverter(), new KameletPrinter()); + + search(matchExtractor); + } else { + matchExtractor = new MatchExtractor<>( + PATTERN, new KameletConverter(), + new KameletDescriptionMatching(searchTerm)); + + search(matchExtractor); + } + + return 0; + } +} + +@Command(name = "components", description = "Search for Camel Core components") +class SearchComponents extends AbstractSearch implements Callable<Integer> { + /* + * Matches the following line. Separate them into groups and pick the last + * which contains the description: + * + * * xref:ROOT:index.adoc[Components] + */ + private static final Pattern PATTERN = Pattern.compile("(.*):(.*)\\[(.*)\\]"); + + @Option(names = { "--search-term" }, defaultValue = "", description = "Default debug level") + private String searchTerm; + + SearchComponents() { + super("github:apache:camel:docs/components/modules/ROOT/nav.adoc", PATTERN); + } + + @Override + public void printHeader() { + System.out.printf("%-35s %-45s %s%n", "COMPONENT", "DESCRIPTION", "LINK"); + System.out.printf("%-35s %-45s %s%n", "-------", "-----------", "-----"); + } + + @Override + public Integer call() throws Exception { + + MatchExtractor<Component> matchExtractor; + if (searchTerm.isEmpty()) { + matchExtractor = new MatchExtractor<>(PATTERN, new ComponentConverter(), new ComponentPrinter()); + + } else { + matchExtractor = new MatchExtractor<>( + PATTERN, new ComponentConverter(), + new ComponentDescriptionMatching(searchTerm)); + + } + search(matchExtractor); + + return 0; + } +} + +@Command(name = "languages", description = "Search for Camel expression languages") +class SearchLanguages extends AbstractSearch implements Callable<Integer> { + /* + * Matches the following line. Separate them into groups and pick the last + * which contains the description: + * + * * xref:ROOT:index.adoc[Components] + */ + private static final Pattern PATTERN = Pattern.compile("(.*):(.*)\\[(.*)\\]"); + + @Option(names = { "--search-term" }, defaultValue = "", description = "Default debug level") + private String searchTerm; + + SearchLanguages() { + super("github:apache:camel:docs/components/modules/languages/nav.adoc", PATTERN); + } + + @Override + public void printHeader() { + System.out.printf("%-35s %-45s %s%n", "LANGUAGE", "DESCRIPTION", "LINK"); + System.out.printf("%-35s %-45s %s%n", "-------", "-----------", "-----"); + } + + @Override + public Integer call() throws Exception { + + MatchExtractor<Language> matchExtractor; + if (searchTerm.isEmpty()) { + matchExtractor = new MatchExtractor<>(PATTERN, new LanguageConverter(), new LanguagePrinter()); + + } else { + matchExtractor = new MatchExtractor<>( + PATTERN, new LanguageConverter(), + new LanguageDescriptionMatching(searchTerm)); + + } + search(matchExtractor); + + return 0; + } +} + +@Command(name = "others", description = "Search for Camel miscellaneous components") +class SearchOthers extends AbstractSearch implements Callable<Integer> { + /* + * Matches the following line. Separate them into groups and pick the last + * which contains the description: + * + * * xref:ROOT:index.adoc[Components] + */ + private static final Pattern PATTERN = Pattern.compile("(.*):(.*)\\[(.*)\\]"); + + @Option(names = { "--search-term" }, defaultValue = "", description = "Default debug level") + private String searchTerm; + + SearchOthers() { + super("github:apache:camel:docs/components/modules/others/nav.adoc", PATTERN); + } + + @Override + public void printHeader() { + System.out.printf("%-35s %-45s %s%n", "COMPONENT", "DESCRIPTION", "LINK"); + System.out.printf("%-35s %-45s %s%n", "-------", "-----------", "-----"); + } + + @Override + public Integer call() throws Exception { + + MatchExtractor<Other> matchExtractor; + if (searchTerm.isEmpty()) { + matchExtractor = new MatchExtractor<>(PATTERN, new OtherConverter(), new OtherPrinter()); + + } else { + matchExtractor = new MatchExtractor<>( + PATTERN, new OtherConverter(), + new OtherDescriptionMatching(searchTerm)); + + } + search(matchExtractor); + + return 0; + } +} + +@Command(name = "CamelJBang", mixinStandardHelpOptions = true, version = "CamelJBang 3.12.0-SNAPSHOT", + description = "A JBang-based Camel app for running Kamelets") +class CamelJBang implements Callable<Integer> { + private static CommandLine commandLine; + + static { + Configurator.initialize(new DefaultConfiguration()); + } + + public static void main(String... args) { + commandLine = new CommandLine(new CamelJBang()) + .addSubcommand("run", new Run()) + .addSubcommand("search", new CommandLine(new Search()) + .addSubcommand("kamelets", new SearchKamelets()) + .addSubcommand("components", new SearchComponents()) + .addSubcommand("languages", new SearchLanguages()) + .addSubcommand("others", new SearchOthers())); + + int exitCode = commandLine.execute(args); + System.exit(exitCode); + } + + @Override + public Integer call() throws Exception { + commandLine.execute("--help"); + return 0; + } +} diff --git a/dsl/camel-jbang/camel-jbang-main/examples/earthquake.yaml b/dsl/camel-jbang/camel-jbang-main/examples/earthquake.yaml new file mode 100644 index 0000000..5e83825 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-main/examples/earthquake.yaml @@ -0,0 +1,22 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +- route: + from: "kamelet:earthquake-source" + steps: + - unmarshal: + json: {} + - log: "Earthquake with magnitude ${body[properties][mag]} at ${body[properties][place]}" diff --git a/dsl/camel-jbang/camel-jbang-main/examples/jms-amqp-10-sink-binding.yaml b/dsl/camel-jbang/camel-jbang-main/examples/jms-amqp-10-sink-binding.yaml new file mode 100644 index 0000000..f4608a8 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-main/examples/jms-amqp-10-sink-binding.yaml @@ -0,0 +1,31 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +- route: + from: + uri: "kamelet:timer-source" + parameters: + period: 12399 + # You can override it using jbang run -D=message="new message" CamelJbang.java opts... + message: "Hello Camel JBang" + steps: + - log: "${body}" + - to: + uri: "kamelet:jms-amqp-10-sink" + parameters: + remoteURI: amqp://localhost:61616 + destinationName: test-queue + diff --git a/dsl/camel-jbang/camel-jbang-main/examples/jms-apache-artemis-source-binding.yaml b/dsl/camel-jbang/camel-jbang-main/examples/jms-apache-artemis-source-binding.yaml new file mode 100644 index 0000000..08edfe6 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-main/examples/jms-apache-artemis-source-binding.yaml @@ -0,0 +1,24 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +- route: + from: + uri: "kamelet:jms-apache-artemis-source" + parameters: + destinationName: test-queue + brokerURL: tcp://localhost:61616 + steps: + - log: "${body}" \ No newline at end of file diff --git a/dsl/camel-jbang/camel-jbang-main/examples/kafka-unsecured-sink.yaml b/dsl/camel-jbang/camel-jbang-main/examples/kafka-unsecured-sink.yaml new file mode 100644 index 0000000..93d6bb5 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-main/examples/kafka-unsecured-sink.yaml @@ -0,0 +1,30 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +- route: + from: + uri: "kamelet:timer-source" + parameters: + period: 12399 + message: "Hello Kafka from Camel JBang" + steps: + - log: "${body}" + - to: + uri: "kamelet:kafka-not-secured-sink" + parameters: + brokers: localhost:9092 + topic: test-topic + diff --git a/dsl/camel-jbang/camel-jbang-main/examples/kafka-unsecured-source.yaml b/dsl/camel-jbang/camel-jbang-main/examples/kafka-unsecured-source.yaml new file mode 100644 index 0000000..16e2ca4 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-main/examples/kafka-unsecured-source.yaml @@ -0,0 +1,24 @@ +## --------------------------------------------------------------------------- +## 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. +## --------------------------------------------------------------------------- +- route: + from: + uri: "kamelet:kafka-not-secured-source" + parameters: + brokers: localhost:9092 + topic: test-topic + steps: + - log: "${body}" \ No newline at end of file diff --git a/dsl/camel-jbang/camel-jbang-main/pom.xml b/dsl/camel-jbang/camel-jbang-main/pom.xml new file mode 100644 index 0000000..f4af4ac --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-main/pom.xml @@ -0,0 +1,141 @@ +<?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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.camel</groupId> + <artifactId>camel-jbang</artifactId> + <version>3.12.0-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <artifactId>camel-jbang-main</artifactId> + <packaging>jar</packaging> + + <name>Camel :: JBang</name> + <description>Camel JBang</description> + + <properties> + <checkstyle.skip>true</checkstyle.skip> + <dist.dir>dist</dist.dir> + </properties> + + <dependencies> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-core</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-core-model</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-api</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-main</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-kamelet-main</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-file-watch</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-resourceresolver-github</artifactId> + </dependency> + <dependency> + <groupId>org.apache.camel</groupId> + <artifactId>camel-jbang-core</artifactId> + <version>${project.version}</version> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-api</artifactId> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-core</artifactId> + </dependency> + <dependency> + <groupId>org.apache.logging.log4j</groupId> + <artifactId>log4j-slf4j-impl</artifactId> + </dependency> + <dependency> + <groupId>info.picocli</groupId> + <artifactId>picocli</artifactId> + </dependency> + </dependencies> + + <build> + <resources> + <resource> + <directory>src/main/jbang/main</directory> + <targetPath>${basedir}/dist</targetPath> + <includes> + <include>**/*.java</include> + </includes> + </resource> + </resources> + <sourceDirectory>src/main/jbang</sourceDirectory> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-checkstyle-plugin</artifactId> + <configuration> + <skip>${checkstyle.skip}</skip> + </configuration> + </plugin> + + <plugin> + <artifactId>maven-antrun-plugin</artifactId> + <executions> + <execution> + <phase>prepare-package</phase> + <configuration> + <tasks> + <replace token="${camel.jbang.version}" value="${project.version}" dir="${dist.dir}"> + <include name="**/*.java"/> + </replace> + <replace token="${camel.jbang.log4j2.version}" value="${log4j2-version}" dir="${dist.dir}"> + <include name="**/*.java"/> + </replace> + <replace token="${camel.jbang.picocli.version}" value="${picocli-version}" dir="${dist.dir}"> + <include name="**/*.java"/> + </replace> + <chmod file="${dist.dir}/*.java" perm="u+x" /> + </tasks> + </configuration> + <goals> + <goal>run</goal> + </goals> + </execution> + </executions> + </plugin> + </plugins> + </build> +</project> diff --git a/dsl/camel-jbang/camel-jbang-main/src/main/jbang/main/CamelJBang.java b/dsl/camel-jbang/camel-jbang-main/src/main/jbang/main/CamelJBang.java new file mode 100755 index 0000000..a3cee46 --- /dev/null +++ b/dsl/camel-jbang/camel-jbang-main/src/main/jbang/main/CamelJBang.java @@ -0,0 +1,363 @@ +///usr/bin/env jbang "$0" "$@" ; exit $? + +/* + * 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. + */ + +//REPOS mavencentral,apache=https://repository.apache.org/snapshots +//DEPS org.apache.camel:camel-bom:${camel.jbang.version}@pom +//DEPS org.apache.camel:camel-core +//DEPS org.apache.camel:camel-core-model +//DEPS org.apache.camel:camel-api +//DEPS org.apache.camel:camel-main +//DEPS org.apache.camel:camel-kamelet-main +//DEPS org.apache.camel:camel-file-watch +//DEPS org.apache.camel:camel-resourceresolver-github +//DEPS org.apache.camel:camel-jbang-core:${camel.jbang.version} +//DEPS org.apache.logging.log4j:log4j-api:${camel.jbang.log4j2.version} +//DEPS org.apache.logging.log4j:log4j-core:${camel.jbang.log4j2.version} +//DEPS org.apache.logging.log4j:log4j-slf4j-impl:${camel.jbang.log4j2.version} +//DEPS info.picocli:picocli:${camel.jbang.picocli.version} + +package main; + +import java.io.File; +import java.io.IOException; +import java.util.concurrent.Callable; +import java.util.regex.Pattern; + +import org.apache.camel.CamelContext; +import org.apache.camel.builder.RouteBuilder; +import org.apache.camel.dsl.jbang.core.commands.AbstractSearch; +import org.apache.camel.dsl.jbang.core.common.MatchExtractor; +import org.apache.camel.dsl.jbang.core.components.ComponentConverter; +import org.apache.camel.dsl.jbang.core.components.ComponentDescriptionMatching; +import org.apache.camel.dsl.jbang.core.components.ComponentPrinter; +import org.apache.camel.dsl.jbang.core.kamelets.KameletConverter; +import org.apache.camel.dsl.jbang.core.kamelets.KameletDescriptionMatching; +import org.apache.camel.dsl.jbang.core.kamelets.KameletPrinter; +import org.apache.camel.dsl.jbang.core.languages.LanguageConverter; +import org.apache.camel.dsl.jbang.core.languages.LanguageDescriptionMatching; +import org.apache.camel.dsl.jbang.core.languages.LanguagePrinter; +import org.apache.camel.dsl.jbang.core.others.OtherConverter; +import org.apache.camel.dsl.jbang.core.others.OtherDescriptionMatching; +import org.apache.camel.dsl.jbang.core.others.OtherPrinter; +import org.apache.camel.dsl.jbang.core.types.Component; +import org.apache.camel.dsl.jbang.core.types.Kamelet; +import org.apache.camel.dsl.jbang.core.types.Language; +import org.apache.camel.dsl.jbang.core.types.Other; +import org.apache.camel.main.KameletMain; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.config.Configurator; +import org.apache.logging.log4j.core.config.DefaultConfiguration; +import picocli.CommandLine; +import picocli.CommandLine.Command; +import picocli.CommandLine.Option; +import picocli.CommandLine.Parameters; + +@Command(name = "run", description = "Run a Kamelet") +class Run implements Callable<Integer> { + private CamelContext context; + + @Parameters(description = "The path to the kamelet binding", arity = "1") + private String binding; + + @Option(names = { "--debug-level" }, defaultValue = "info", description = "Default debug level") + private String debugLevel; + + class ShutdownRoute extends RouteBuilder { + private File lockFile; + + public ShutdownRoute(File lockFile) { + this.lockFile = lockFile; + } + + public void configure() { + fromF("file-watch://%s?events=DELETE&antInclude=%s", lockFile.getParent(), lockFile.getName()) + .process(p -> context.shutdown()); + } + } + + @Override + public Integer call() throws Exception { + switch (debugLevel) { + case "trace": + Configurator.setRootLevel(Level.TRACE); + break; + case "debug": + Configurator.setRootLevel(Level.DEBUG); + break; + case "info": + Configurator.setRootLevel(Level.INFO); + break; + case "warn": + Configurator.setRootLevel(Level.WARN); + break; + case "fatal": + Configurator.setRootLevel(Level.FATAL); + break; + default: { + System.err.println("Invalid debug level " + debugLevel); + return 1; + } + } + + File bindingFile = new File(binding); + if (!bindingFile.exists()) { + System.err.println("The binding file does not exist"); + + return 1; + } + + System.setProperty("camel.main.routes-include-pattern", "file:" + binding); + System.setProperty("camel.main.name", "CamelJBang"); + + System.out.println("Starting Camel JBang!"); + KameletMain main = new KameletMain(); + + main.configure().addRoutesBuilder(new ShutdownRoute(createLockFile())); + main.start(); + context = main.getCamelContext(); + + main.run(); + return 0; + } + + public File createLockFile() throws IOException { + File lockFile = File.createTempFile(".run", ".camel.lock", new File(".")); + + System.out.printf("A new lock file was created on %s. Delete this file to stop running%n", + lockFile.getAbsolutePath()); + lockFile.deleteOnExit(); + + return lockFile; + } +} + +@Command(name = "search", description = "Search for kameletes, components and patterns (use --help)") +class Search extends AbstractSearch implements Callable<Integer> { + public Search() { + super(null, null); + } + + public void printHeader() { + } + + @Override + public Integer call() throws Exception { + CommandLine.usage(this, System.out); + + return 0; + } +} + +@Command(name = "kamelets", description = "Search for a Kamelet in the Kamelet catalog") +class SearchKamelets extends AbstractSearch implements Callable<Integer> { + /* + * Matches the following line. Separate them into groups and pick the last + * which contains the description: + * + * xref:ROOT:mariadb-sink.adoc[image:kamelets/mariadb-sink.svg[] MariaDB Sink] + */ + private static final Pattern PATTERN = Pattern.compile("(.*):(.*):(.*)\\[(.*)\\[\\] (.*)\\]"); + + @Option(names = { "--search-term" }, defaultValue = "", description = "Default debug level") + private String searchTerm; + + SearchKamelets() { + super("github:apache:camel-kamelets:docs/modules/ROOT/nav.adoc", PATTERN); + } + + @Override + public void printHeader() { + System.out.printf("%-35s %-45s %s%n", "KAMELET", "DESCRIPTION", "LINK"); + System.out.printf("%-35s %-45s %s%n", "-------", "-----------", "-----"); + } + + @Override + public Integer call() throws Exception { + MatchExtractor<Kamelet> matchExtractor; + + if (searchTerm.isEmpty()) { + matchExtractor = new MatchExtractor<>(PATTERN, new KameletConverter(), new KameletPrinter()); + + search(matchExtractor); + } else { + matchExtractor = new MatchExtractor<>( + PATTERN, new KameletConverter(), + new KameletDescriptionMatching(searchTerm)); + + search(matchExtractor); + } + + return 0; + } +} + +@Command(name = "components", description = "Search for Camel Core components") +class SearchComponents extends AbstractSearch implements Callable<Integer> { + /* + * Matches the following line. Separate them into groups and pick the last + * which contains the description: + * + * * xref:ROOT:index.adoc[Components] + */ + private static final Pattern PATTERN = Pattern.compile("(.*):(.*)\\[(.*)\\]"); + + @Option(names = { "--search-term" }, defaultValue = "", description = "Default debug level") + private String searchTerm; + + SearchComponents() { + super("github:apache:camel:docs/components/modules/ROOT/nav.adoc", PATTERN); + } + + @Override + public void printHeader() { + System.out.printf("%-35s %-45s %s%n", "COMPONENT", "DESCRIPTION", "LINK"); + System.out.printf("%-35s %-45s %s%n", "-------", "-----------", "-----"); + } + + @Override + public Integer call() throws Exception { + + MatchExtractor<Component> matchExtractor; + if (searchTerm.isEmpty()) { + matchExtractor = new MatchExtractor<>(PATTERN, new ComponentConverter(), new ComponentPrinter()); + + } else { + matchExtractor = new MatchExtractor<>( + PATTERN, new ComponentConverter(), + new ComponentDescriptionMatching(searchTerm)); + + } + search(matchExtractor); + + return 0; + } +} + +@Command(name = "languages", description = "Search for Camel expression languages") +class SearchLanguages extends AbstractSearch implements Callable<Integer> { + /* + * Matches the following line. Separate them into groups and pick the last + * which contains the description: + * + * * xref:ROOT:index.adoc[Components] + */ + private static final Pattern PATTERN = Pattern.compile("(.*):(.*)\\[(.*)\\]"); + + @Option(names = { "--search-term" }, defaultValue = "", description = "Default debug level") + private String searchTerm; + + SearchLanguages() { + super("github:apache:camel:docs/components/modules/languages/nav.adoc", PATTERN); + } + + @Override + public void printHeader() { + System.out.printf("%-35s %-45s %s%n", "LANGUAGE", "DESCRIPTION", "LINK"); + System.out.printf("%-35s %-45s %s%n", "-------", "-----------", "-----"); + } + + @Override + public Integer call() throws Exception { + + MatchExtractor<Language> matchExtractor; + if (searchTerm.isEmpty()) { + matchExtractor = new MatchExtractor<>(PATTERN, new LanguageConverter(), new LanguagePrinter()); + + } else { + matchExtractor = new MatchExtractor<>( + PATTERN, new LanguageConverter(), + new LanguageDescriptionMatching(searchTerm)); + + } + search(matchExtractor); + + return 0; + } +} + +@Command(name = "others", description = "Search for Camel miscellaneous components") +class SearchOthers extends AbstractSearch implements Callable<Integer> { + /* + * Matches the following line. Separate them into groups and pick the last + * which contains the description: + * + * * xref:ROOT:index.adoc[Components] + */ + private static final Pattern PATTERN = Pattern.compile("(.*):(.*)\\[(.*)\\]"); + + @Option(names = { "--search-term" }, defaultValue = "", description = "Default debug level") + private String searchTerm; + + SearchOthers() { + super("github:apache:camel:docs/components/modules/others/nav.adoc", PATTERN); + } + + @Override + public void printHeader() { + System.out.printf("%-35s %-45s %s%n", "COMPONENT", "DESCRIPTION", "LINK"); + System.out.printf("%-35s %-45s %s%n", "-------", "-----------", "-----"); + } + + @Override + public Integer call() throws Exception { + + MatchExtractor<Other> matchExtractor; + if (searchTerm.isEmpty()) { + matchExtractor = new MatchExtractor<>(PATTERN, new OtherConverter(), new OtherPrinter()); + + } else { + matchExtractor = new MatchExtractor<>( + PATTERN, new OtherConverter(), + new OtherDescriptionMatching(searchTerm)); + + } + search(matchExtractor); + + return 0; + } +} + +@Command(name = "CamelJBang", mixinStandardHelpOptions = true, version = "CamelJBang ${camel.jbang.version}", + description = "A JBang-based Camel app for running Kamelets") +class CamelJBang implements Callable<Integer> { + private static CommandLine commandLine; + + static { + Configurator.initialize(new DefaultConfiguration()); + } + + public static void main(String... args) { + commandLine = new CommandLine(new CamelJBang()) + .addSubcommand("run", new Run()) + .addSubcommand("search", new CommandLine(new Search()) + .addSubcommand("kamelets", new SearchKamelets()) + .addSubcommand("components", new SearchComponents()) + .addSubcommand("languages", new SearchLanguages()) + .addSubcommand("others", new SearchOthers())); + + int exitCode = commandLine.execute(args); + System.exit(exitCode); + } + + @Override + public Integer call() throws Exception { + commandLine.execute("--help"); + return 0; + } +} diff --git a/dsl/camel-jbang/pom.xml b/dsl/camel-jbang/pom.xml new file mode 100644 index 0000000..d9d5c11 --- /dev/null +++ b/dsl/camel-jbang/pom.xml @@ -0,0 +1,40 @@ +<?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/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <parent> + <groupId>org.apache.camel</groupId> + <artifactId>dsl</artifactId> + <version>3.12.0-SNAPSHOT</version> + <relativePath>../pom.xml</relativePath> + </parent> + + <artifactId>camel-jbang</artifactId> + <packaging>pom</packaging> + + <name>Camel :: DSLs :: JBang Modules</name> + <description>Camel DSLs JBang Modules</description> + + <modules> + <module>camel-jbang-core</module> + <module>camel-jbang-main</module> + </modules> +</project> diff --git a/dsl/pom.xml b/dsl/pom.xml index c7460e3..08eb648 100644 --- a/dsl/pom.xml +++ b/dsl/pom.xml @@ -44,6 +44,7 @@ <module>camel-js-dsl</module> <module>camel-kotlin-dsl</module> <module>camel-kamelet-main</module> + <module>camel-jbang</module> </modules> <properties> diff --git a/jbang-catalog.json b/jbang-catalog.json new file mode 100644 index 0000000..2674370 --- /dev/null +++ b/jbang-catalog.json @@ -0,0 +1,9 @@ +{ + "catalogs": {}, + "aliases": { + "CamelJBang": { + "script-ref": "dsl/camel-jbang/camel-jbang-main/dist/CamelJBang.java", + "description": "A JBang-based Camel app for running Kamelets" + } + } +} diff --git a/parent/pom.xml b/parent/pom.xml index a388fd0..892ca30 100644 --- a/parent/pom.xml +++ b/parent/pom.xml @@ -438,6 +438,7 @@ <pdfbox-version>2.0.24</pdfbox-version> <pgjdbc-driver-version>42.2.14</pgjdbc-driver-version> <pgjdbc-ng-driver-version>0.8.6</pgjdbc-ng-driver-version> + <picocli-version>4.5.0</picocli-version> <powermock-version>2.0.7</powermock-version> <properties-maven-plugin-version>1.0-alpha-2</properties-maven-plugin-version> <protobuf-version>3.17.3</protobuf-version> @@ -4010,6 +4011,12 @@ <version>${java-grok-version}</version> </dependency> + <dependency> + <groupId>info.picocli</groupId> + <artifactId>picocli</artifactId> + <version>${picocli-version}</version> + </dependency> + <!-- directory-watcher for camel-file-watch component --> <dependency> <groupId>io.methvin</groupId>