| /* |
| * 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.k.tooling.maven; |
| |
| import java.io.IOException; |
| import java.io.Writer; |
| import java.nio.charset.StandardCharsets; |
| import java.nio.file.Files; |
| import java.nio.file.Path; |
| import java.nio.file.Paths; |
| import java.util.Arrays; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| import java.util.Objects; |
| import java.util.Set; |
| import java.util.TreeMap; |
| import java.util.TreeSet; |
| |
| import com.fasterxml.jackson.annotation.JsonInclude; |
| import com.fasterxml.jackson.databind.ObjectMapper; |
| import com.fasterxml.jackson.dataformat.yaml.YAMLFactory; |
| import com.fasterxml.jackson.dataformat.yaml.YAMLGenerator; |
| import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; |
| import org.apache.camel.catalog.DefaultCamelCatalog; |
| import org.apache.camel.catalog.quarkus.QuarkusRuntimeProvider; |
| import org.apache.camel.impl.engine.AbstractCamelContext; |
| import org.apache.camel.k.catalog.model.CamelArtifact; |
| import org.apache.camel.k.catalog.model.CamelCapability; |
| import org.apache.camel.k.catalog.model.CamelLoader; |
| import org.apache.camel.k.catalog.model.CamelScheme; |
| import org.apache.camel.k.catalog.model.CatalogComponentDefinition; |
| import org.apache.camel.k.catalog.model.CatalogDataFormatDefinition; |
| import org.apache.camel.k.catalog.model.CatalogDefinition; |
| import org.apache.camel.k.catalog.model.CatalogLanguageDefinition; |
| import org.apache.camel.k.catalog.model.CatalogOtherDefinition; |
| import org.apache.camel.k.catalog.model.CatalogSupport; |
| import org.apache.camel.k.catalog.model.k8s.ObjectMeta; |
| import org.apache.camel.k.catalog.model.k8s.crd.CamelCatalog; |
| import org.apache.camel.k.catalog.model.k8s.crd.CamelCatalogSpec; |
| import org.apache.camel.k.catalog.model.k8s.crd.RuntimeSpec; |
| import org.apache.camel.k.tooling.maven.support.MavenSupport; |
| import org.apache.camel.quarkus.core.FastCamelContext; |
| import org.apache.commons.lang3.StringUtils; |
| import org.apache.maven.plugin.AbstractMojo; |
| import org.apache.maven.plugin.MojoExecutionException; |
| import org.apache.maven.plugin.MojoFailureException; |
| import org.apache.maven.plugins.annotations.LifecyclePhase; |
| import org.apache.maven.plugins.annotations.Mojo; |
| import org.apache.maven.plugins.annotations.Parameter; |
| import org.apache.maven.plugins.annotations.ResolutionScope; |
| |
| @Mojo( |
| name = "generate-catalog", |
| defaultPhase = LifecyclePhase.GENERATE_RESOURCES, |
| threadSafe = true, |
| requiresDependencyResolution = ResolutionScope.COMPILE_PLUS_RUNTIME, |
| requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME) |
| public class GenerateCatalogMojo extends AbstractMojo { |
| private static final List<String> KNOWN_HTTP_URIS = Arrays.asList( |
| "ahc", |
| "ahc-ws", |
| "atmosphere-websocket", |
| "cxf", |
| "cxfrs", |
| "grpc", |
| "jetty", |
| "knative", |
| "netty-http", |
| "platform-http", |
| "rest", |
| "restlet", |
| "servlet", |
| "spark-rest", |
| "spring-ws", |
| "undertow", |
| "webhook", |
| "websocket" |
| ); |
| |
| private static final List<String> KNOWN_PASSIVE_URIS = Arrays.asList( |
| "bean", |
| "binding", |
| "browse", |
| "class", |
| "controlbus", |
| "dataformat", |
| "dataset", |
| "direct", |
| "direct-vm", |
| "language", |
| "log", |
| "mock", |
| "ref", |
| "seda", |
| "stub", |
| "test", |
| "validator", |
| "vm" |
| ); |
| |
| @Parameter(property = "catalog.path", defaultValue = "${project.build.directory}") |
| private String outputPath; |
| |
| @Parameter(property = "catalog.file", defaultValue = "camel-catalog-${runtime.version}.yaml") |
| private String outputFile; |
| |
| @Parameter(property = "components.exclusion.list") |
| private Set<String> componentsExclusionList; |
| |
| @Parameter(property = "dataformats.exclusion.list") |
| private Set<String> dataformatsExclusionList; |
| |
| @Parameter(property = "languages.exclusion.list") |
| private Set<String> languagesExclusionList; |
| |
| @Parameter(property = "others.exclusion.list") |
| private Set<String> othersExclusionList; |
| |
| @Parameter(property = "dsls.exclusion.list") |
| private Set<String> dslsExclusionList; |
| |
| @Parameter(property = "capabilities.exclusion.list") |
| private Set<String> capabilitiesExclusionList; |
| |
| // ******************** |
| // |
| // ******************** |
| |
| @Override |
| public void execute() throws MojoExecutionException, MojoFailureException { |
| final Path output = Paths.get(this.outputPath, this.outputFile); |
| |
| try { |
| if (Files.notExists(output.getParent())) { |
| Files.createDirectories(output.getParent()); |
| } |
| if (Files.exists(output)) { |
| Files.delete(output); |
| } |
| } catch (IOException e) { |
| throw new MojoExecutionException("Exception while generating camel catalog", e); |
| } |
| |
| final org.apache.camel.catalog.CamelCatalog catalog = new DefaultCamelCatalog(); |
| catalog.setRuntimeProvider(new QuarkusRuntimeProvider()); |
| |
| final String runtimeVersion = MavenSupport.getVersion(getClass(), "/META-INF/maven/org.apache.camel.k/camel-k-maven-plugin/pom.properties"); |
| final String catalogName = String.format("camel-catalog-%s", runtimeVersion.toLowerCase(Locale.US)); |
| |
| try { |
| CamelCatalogSpec.Builder catalogSpec = new CamelCatalogSpec.Builder(); |
| |
| RuntimeSpec.Builder runtimeSpec = new RuntimeSpec.Builder() |
| .version(runtimeVersion) |
| .provider("quarkus"); |
| |
| MavenSupport.getVersion( |
| AbstractCamelContext.class, |
| "org.apache.camel", "camel-base", |
| version -> runtimeSpec.putMetadata("camel.version", version)); |
| MavenSupport.getVersion( |
| FastCamelContext.class, |
| "io.quarkus", "quarkus-core", |
| version -> runtimeSpec.putMetadata("quarkus.version", version)); |
| MavenSupport.getVersion( |
| QuarkusRuntimeProvider.class, |
| "org.apache.camel.quarkus", "camel-quarkus-catalog", |
| version -> runtimeSpec.putMetadata("camel-quarkus.version", version)); |
| |
| runtimeSpec.putMetadata("quarkus.native-builder-image", MavenSupport.getApplicationProperty(getClass(), "quarkus.native-builder-image")); |
| |
| runtimeSpec.applicationClass("io.quarkus.bootstrap.runner.QuarkusEntryPoint"); |
| runtimeSpec.addDependency("org.apache.camel.k", "camel-k-runtime"); |
| |
| if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("cron")) { |
| runtimeSpec.putCapability( |
| "cron", |
| CamelCapability.forArtifact( |
| "org.apache.camel.k", "camel-k-cron")); |
| |
| catalogSpec.putArtifact( |
| new CamelArtifact.Builder() |
| .groupId("org.apache.camel.k") |
| .artifactId("camel-k-cron") |
| .build() |
| ); |
| } |
| if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("health")) { |
| runtimeSpec.putCapability( |
| "health", |
| CamelCapability.forArtifact( |
| "org.apache.camel.quarkus", "camel-quarkus-microprofile-health")); |
| } |
| if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("platform-http")) { |
| runtimeSpec.putCapability( |
| "platform-http", |
| CamelCapability.forArtifact( |
| "org.apache.camel.quarkus", "camel-quarkus-platform-http")); |
| } |
| if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("rest")) { |
| runtimeSpec.putCapability( |
| "rest", |
| new CamelCapability.Builder() |
| .addDependency("org.apache.camel.quarkus", "camel-quarkus-rest") |
| .addDependency("org.apache.camel.quarkus", "camel-quarkus-platform-http") |
| .build()); |
| } |
| if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("circuit-breaker")) { |
| runtimeSpec.putCapability( |
| "circuit-breaker", |
| CamelCapability.forArtifact( |
| "org.apache.camel.quarkus", "camel-quarkus-microprofile-fault-tolerance")); |
| } |
| if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("tracing")) { |
| runtimeSpec.putCapability( |
| "tracing", |
| CamelCapability.forArtifact( |
| "org.apache.camel.quarkus", "camel-quarkus-opentracing")); |
| } |
| if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("telemetry")) { |
| runtimeSpec.putCapability( |
| "telemetry", |
| CamelCapability.forArtifact( |
| "org.apache.camel.quarkus", "camel-quarkus-opentelemetry")); |
| } |
| if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("master")) { |
| runtimeSpec.putCapability( |
| "master", |
| CamelCapability.forArtifact( |
| "org.apache.camel.k", "camel-k-master")); |
| |
| catalogSpec.putArtifact( |
| new CamelArtifact.Builder() |
| .groupId("org.apache.camel.k") |
| .artifactId("camel-k-master") |
| .build() |
| ); |
| } |
| if (capabilitiesExclusionList != null && !capabilitiesExclusionList.contains("resume-kafka")) { |
| runtimeSpec.putCapability( |
| "resume-kafka", |
| CamelCapability.forArtifact( |
| "org.apache.camel.k", "camel-k-resume-kafka")); |
| |
| catalogSpec.putArtifact( |
| new CamelArtifact.Builder() |
| .groupId("org.apache.camel.k") |
| .artifactId("camel-k-resume-kafka") |
| .build() |
| ); |
| } |
| |
| catalogSpec.runtime(runtimeSpec.build()); |
| |
| process(catalog, catalogSpec); |
| |
| ObjectMeta.Builder metadata = new ObjectMeta.Builder() |
| .name(catalogName) |
| .putLabels("app", "camel-k") |
| .putLabels("camel.apache.org/catalog.version", catalog.getCatalogVersion()) |
| .putLabels("camel.apache.org/catalog.loader.version", catalog.getLoadedVersion()) |
| .putLabels("camel.apache.org/runtime.version", runtimeVersion); |
| |
| CamelCatalog cr = new CamelCatalog.Builder() |
| .metadata(metadata.build()) |
| .spec(catalogSpec.build()) |
| .build(); |
| |
| // |
| // apiVersion: camel.apache.org/v1 |
| // kind: CamelCatalog |
| // metadata: |
| // name: catalog-x.y.z-main |
| // labels: |
| // app: "camel-k" |
| // camel.apache.org/catalog.version: x.y.x |
| // camel.apache.org/catalog.loader.version: x.y.z |
| // camel.apache.org/runtime.version: x.y.x |
| // camel.apache.org/runtime.provider: main |
| // spec: |
| // version: |
| // runtimeVersion: |
| // status: |
| // artifacts: |
| // |
| try (Writer writer = Files.newBufferedWriter(output, StandardCharsets.UTF_8)) { |
| |
| YAMLFactory factory = new YAMLFactory() |
| .configure(YAMLGenerator.Feature.MINIMIZE_QUOTES, true) |
| .configure(YAMLGenerator.Feature.ALWAYS_QUOTE_NUMBERS_AS_STRINGS, true) |
| .configure(YAMLGenerator.Feature.USE_NATIVE_TYPE_ID, false) |
| .configure(YAMLGenerator.Feature.WRITE_DOC_START_MARKER, false); |
| |
| // write license header |
| writer.write( |
| GenerateSupport.getResourceAsString("/catalog-license.txt") |
| ); |
| |
| getLog().info("Writing catalog file to: " + output); |
| |
| // write catalog data |
| ObjectMapper mapper = new ObjectMapper(factory); |
| mapper.registerModule(new Jdk8Module()); |
| mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL); |
| mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); |
| mapper.writeValue(writer, cr); |
| } |
| } catch (IOException e) { |
| throw new MojoExecutionException("Exception while generating catalog", e); |
| } |
| } |
| |
| // ******************** |
| // |
| // ******************** |
| |
| public void process( |
| org.apache.camel.catalog.CamelCatalog catalog, |
| CamelCatalogSpec.Builder specBuilder) { |
| |
| Map<String, CamelArtifact> artifacts = new TreeMap<>(); |
| |
| processComponents(catalog, artifacts); |
| processLanguages(catalog, artifacts); |
| processDataFormats(catalog, artifacts); |
| processOthers(catalog, artifacts); |
| processLoaders(specBuilder); |
| |
| specBuilder.putAllArtifacts(artifacts); |
| } |
| |
| private void processLoaders(CamelCatalogSpec.Builder specBuilder) { |
| if (dslsExclusionList != null) { |
| getLog().info("dsls.exclusion.list: " + dslsExclusionList); |
| } |
| |
| if (dslsExclusionList != null && !dslsExclusionList.contains("yaml")) { |
| specBuilder.putLoader( |
| "yaml", |
| CamelLoader.fromArtifact("org.apache.camel.quarkus", "camel-quarkus-yaml-dsl") |
| .addLanguage("yaml") |
| .putMetadata("native", "true") |
| .build() |
| ); |
| } |
| if (dslsExclusionList != null && !dslsExclusionList.contains("groovy")) { |
| specBuilder.putLoader( |
| "groovy", |
| CamelLoader.fromArtifact("org.apache.camel.quarkus", "camel-quarkus-groovy-dsl") |
| .addLanguage("groovy") |
| .putMetadata("native", "true") |
| .putMetadata("sources-required-at-build-time", "true") |
| .build() |
| ); |
| } |
| if (dslsExclusionList != null && !dslsExclusionList.contains("kts")) { |
| specBuilder.putLoader( |
| "kts", |
| CamelLoader.fromArtifact("org.apache.camel.quarkus", "camel-quarkus-kotlin-dsl") |
| .addLanguage("kts") |
| .putMetadata("native", "true") |
| .putMetadata("sources-required-at-build-time", "true") |
| .build() |
| ); |
| } |
| if (dslsExclusionList != null && !dslsExclusionList.contains("js")) { |
| specBuilder.putLoader( |
| "js", |
| CamelLoader.fromArtifact("org.apache.camel.quarkus", "camel-quarkus-js-dsl") |
| .addLanguage("js") |
| // Guest languages are not yet supported on Mandrel in native mode. |
| .putMetadata("native", "false") |
| .build() |
| ); |
| } |
| if (dslsExclusionList != null && !dslsExclusionList.contains("xml")) { |
| specBuilder.putLoader( |
| "xml", |
| CamelLoader.fromArtifact("org.apache.camel.quarkus", "camel-quarkus-xml-io-dsl") |
| .addLanguage("xml") |
| .putMetadata("native", "true") |
| .build() |
| ); |
| } |
| if (dslsExclusionList != null && !dslsExclusionList.contains("java")) { |
| specBuilder.putLoader( |
| "java", |
| CamelLoader.fromArtifact("org.apache.camel.quarkus", "camel-quarkus-java-joor-dsl") |
| .addLanguages("java") |
| .putMetadata("native", "true") |
| .putMetadata("sources-required-at-build-time", "true") |
| .build() |
| ); |
| } |
| if (dslsExclusionList != null && !dslsExclusionList.contains("jsh")) { |
| specBuilder.putLoader( |
| "jsh", |
| CamelLoader.fromArtifact("org.apache.camel.quarkus", "camel-quarkus-jsh-dsl") |
| .addLanguages("jsh") |
| // Native mode is not yet supported due to https://github.com/apache/camel-quarkus/issues/4458. |
| .putMetadata("native", "false") |
| .putMetadata("sources-required-at-build-time", "true") |
| .build() |
| ); |
| } |
| } |
| |
| private void processComponents(org.apache.camel.catalog.CamelCatalog catalog, Map<String, CamelArtifact> artifacts) { |
| final Set<String> elements = new TreeSet<>(catalog.findComponentNames()); |
| |
| if (componentsExclusionList != null) { |
| getLog().info("components.exclusion.list: " + componentsExclusionList); |
| elements.removeAll(componentsExclusionList); |
| } |
| |
| for (String name : elements) { |
| String json = catalog.componentJSonSchema(name); |
| CatalogComponentDefinition definition = CatalogSupport.unmarshallComponent(json); |
| |
| artifacts.compute(definition.getArtifactId(), (key, artifact) -> { |
| CamelArtifact.Builder builder = artifactBuilder(artifact, definition); |
| builder.addJavaType(definition.getJavaType()); |
| |
| definition.getSchemes().map(StringUtils::trimToNull).filter(Objects::nonNull).forEach(scheme -> { |
| builder.addScheme( |
| new CamelScheme.Builder() |
| .id(scheme) |
| .http(KNOWN_HTTP_URIS.contains(scheme)) |
| .passive(KNOWN_PASSIVE_URIS.contains(scheme)) |
| .build()); |
| }); |
| |
| return builder.build(); |
| }); |
| } |
| } |
| |
| private void processLanguages(org.apache.camel.catalog.CamelCatalog catalog, Map<String, CamelArtifact> artifacts) { |
| final Set<String> elements = new TreeSet<>(catalog.findLanguageNames()); |
| |
| if (languagesExclusionList != null) { |
| getLog().info("languages.exclusion.list: " + languagesExclusionList); |
| elements.removeAll(languagesExclusionList); |
| } |
| |
| for (String name : elements) { |
| String json = catalog.languageJSonSchema(name); |
| CatalogLanguageDefinition definition = CatalogSupport.unmarshallLanguage(json); |
| |
| artifacts.compute(definition.getArtifactId(), (key, artifact) -> { |
| CamelArtifact.Builder builder = artifactBuilder(artifact, definition); |
| builder.addLanguage(definition.getName()); |
| builder.addJavaType(definition.getJavaType()); |
| |
| return builder.build(); |
| }); |
| } |
| } |
| |
| private void processDataFormats(org.apache.camel.catalog.CamelCatalog catalog, Map<String, CamelArtifact> artifacts) { |
| final Set<String> elements = new TreeSet<>(catalog.findDataFormatNames()); |
| |
| if (dataformatsExclusionList != null) { |
| getLog().info("dataformats.exclusion.list: " + dataformatsExclusionList); |
| elements.removeAll(dataformatsExclusionList); |
| } |
| |
| for (String name : elements) { |
| String json = catalog.dataFormatJSonSchema(name); |
| CatalogDataFormatDefinition definition = CatalogSupport.unmarshallDataFormat(json); |
| |
| artifacts.compute(definition.getArtifactId(), (key, artifact) -> { |
| CamelArtifact.Builder builder = artifactBuilder(artifact, definition); |
| builder.addDataformat(definition.getName()); |
| builder.addJavaType(definition.getJavaType()); |
| |
| return builder.build(); |
| }); |
| } |
| } |
| |
| private void processOthers(org.apache.camel.catalog.CamelCatalog catalog, Map<String, CamelArtifact> artifacts) { |
| final Set<String> elements = new TreeSet<>(catalog.findOtherNames()); |
| |
| if (othersExclusionList != null) { |
| getLog().info("others.exclusion.list: " + othersExclusionList); |
| elements.removeAll(othersExclusionList); |
| } |
| |
| for (String name : elements) { |
| String json = catalog.otherJSonSchema(name); |
| CatalogOtherDefinition definition = CatalogSupport.unmarshallOther(json); |
| |
| artifacts.compute(definition.getArtifactId(), (key, artifact) -> artifactBuilder(artifact, definition).build()); |
| } |
| } |
| |
| private CamelArtifact.Builder artifactBuilder(CamelArtifact artifact, CatalogDefinition definition) { |
| CamelArtifact.Builder builder = new CamelArtifact.Builder(); |
| |
| if (artifact != null) { |
| builder.from(artifact); |
| } else { |
| Objects.requireNonNull(definition.getGroupId()); |
| Objects.requireNonNull(definition.getArtifactId()); |
| |
| builder.groupId(definition.getGroupId()); |
| builder.artifactId(definition.getArtifactId()); |
| } |
| |
| return builder; |
| } |
| } |