You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by pp...@apache.org on 2021/09/03 07:50:13 UTC
[camel-quarkus] 01/02: Allow extending an existing Catalog
This is an automated email from the ASF dual-hosted git repository.
ppalaga pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit 68be716bd4777db6889b12dc570adff3494b6934
Author: Peter Palaga <pp...@redhat.com>
AuthorDate: Thu Sep 2 21:44:21 2021 +0200
Allow extending an existing Catalog
---
pom.xml | 3 +
tooling/maven-plugin/pom.xml | 10 +
.../quarkus/maven/AbstractDocGeneratorMojo.java | 16 +-
.../quarkus/maven/AbstractExtensionListMojo.java | 97 ++++++++++
.../quarkus/maven/CheckExtensionPagesMojo.java | 51 ++----
.../org/apache/camel/quarkus/maven/CqCatalog.java | 142 ++++++++++----
.../org/apache/camel/quarkus/maven/CqUtils.java | 45 ++++-
.../camel/quarkus/maven/ExtensionModule.java | 66 +++++++
.../org/apache/camel/quarkus/maven/PatternSet.java | 48 +++++
.../quarkus/maven/PrepareCatalogQuarkusMojo.java | 203 ++++++++-------------
10 files changed, 465 insertions(+), 216 deletions(-)
diff --git a/pom.xml b/pom.xml
index 95cef43..1c0f46f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -141,6 +141,9 @@
<wiremock.version>2.27.2</wiremock.version>
<zt-exec.version>1.11</zt-exec.version>
+ <!-- Tooling dependency versions (keep sorted alphabetically) -->
+ <maven-utils.version>0.1.0</maven-utils.version>
+
<!-- Maven plugin versions (keep sorted alphabetically) -->
<cq-plugin.version>0.40.0</cq-plugin.version>
<build-helper-maven-plugin.version>3.1.0</build-helper-maven-plugin.version>
diff --git a/tooling/maven-plugin/pom.xml b/tooling/maven-plugin/pom.xml
index a2b70f4..f650245 100644
--- a/tooling/maven-plugin/pom.xml
+++ b/tooling/maven-plugin/pom.xml
@@ -46,6 +46,11 @@
<artifactId>quarkus-extension-processor</artifactId>
<version>${quarkus.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.l2x6.maven-utils</groupId>
+ <artifactId>maven-utils</artifactId>
+ <version>${maven-utils.version}</version>
+ </dependency>
</dependencies>
</dependencyManagement>
<dependencies>
@@ -88,6 +93,11 @@
</dependency>
<dependency>
+ <groupId>org.l2x6.maven-utils</groupId>
+ <artifactId>maven-utils</artifactId>
+ </dependency>
+
+ <dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<scope>test</scope>
diff --git a/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/AbstractDocGeneratorMojo.java b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/AbstractDocGeneratorMojo.java
index 7407509..c54eb2e 100644
--- a/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/AbstractDocGeneratorMojo.java
+++ b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/AbstractDocGeneratorMojo.java
@@ -24,13 +24,12 @@ import java.util.Map;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
-import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugins.annotations.Parameter;
/**
* Base for {@link CheckExtensionPagesMojo} and {@link UpdateExtensionDocPageMojo}.
*/
-abstract class AbstractDocGeneratorMojo extends AbstractMojo {
+abstract class AbstractDocGeneratorMojo extends AbstractExtensionListMojo {
public static final String DEFAULT_TEMPLATES_URI_BASE = "classpath:/doc-templates";
/**
*/
@@ -42,19 +41,6 @@ abstract class AbstractDocGeneratorMojo extends AbstractMojo {
@Parameter(property = "camel-quarkus.basedir", defaultValue = "${project.basedir}")
File baseDir;
- /**
- * Encoding to read and write files in the current source tree
- */
- @Parameter(defaultValue = "${project.build.sourceEncoding}", required = true, property = "camel-quarkus.encoding")
- String encoding;
- /**
- * The root directory of the Camel Quarkus source tree.
- *
- * @since 1.0.0-M8
- */
- @Parameter(defaultValue = "${maven.multiModuleProjectDirectory}", required = true, property = "camel-quarkus.multiModuleProjectDirectory")
- File multiModuleProjectDirectory;
-
protected static <T extends Writer> T evalTemplate(Configuration cfg, String templateUri, Map<String, Object> model,
T out) {
try {
diff --git a/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/AbstractExtensionListMojo.java b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/AbstractExtensionListMojo.java
new file mode 100644
index 0000000..4fde01d
--- /dev/null
+++ b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/AbstractExtensionListMojo.java
@@ -0,0 +1,97 @@
+/*
+ * 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.quarkus.maven;
+
+import java.io.File;
+import java.nio.charset.Charset;
+import java.nio.file.Path;
+import java.util.List;
+import java.util.stream.Stream;
+
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugins.annotations.Parameter;
+import org.l2x6.maven.utils.MavenSourceTree;
+
+public abstract class AbstractExtensionListMojo extends AbstractMojo {
+
+ /**
+ * A set of regular expressions to match against artifactIdBases. The matching extensions will not be processed by
+ * this mojo.
+ *
+ * @since 0.1.0
+ */
+ @Parameter(property = "cq.skipArtifactIdBases")
+ protected List<String> skipArtifactIdBases;
+ private PatternSet skipArtifactIdBasePatterns;
+
+ /**
+ * The root directory of the Camel Quarkus source tree.
+ *
+ * @since 0.41.0
+ */
+ @Parameter(defaultValue = "${maven.multiModuleProjectDirectory}", readonly = true)
+ protected File multiModuleProjectDirectory;
+ private Path rootModuleDirectory;
+
+ /**
+ * Encoding to read and write files in the current source tree
+ *
+ * @since 0.18.0
+ */
+ @Parameter(defaultValue = "utf-8", required = true, property = "cq.encoding")
+ String encoding;
+ private Charset charset;
+
+ private MavenSourceTree tree;
+
+ Path getRootModuleDirectory() {
+ if (rootModuleDirectory == null) {
+ rootModuleDirectory = multiModuleProjectDirectory.toPath().toAbsolutePath().normalize();
+ }
+ return rootModuleDirectory;
+ }
+
+ Charset getCharset() {
+ if (charset == null) {
+ charset = Charset.forName(encoding);
+ }
+ return charset;
+ }
+
+ Stream<ExtensionModule> findExtensions() {
+ getSkipArtifactIdBases();
+ return CqUtils.findExtensions(
+ getRootModuleDirectory(),
+ getTree().getModulesByGa().values(),
+ artifactIdBase -> !skipArtifactIdBasePatterns.matchesAny(artifactIdBase));
+ }
+
+ PatternSet getSkipArtifactIdBases() {
+ if (skipArtifactIdBasePatterns == null) {
+ skipArtifactIdBasePatterns = skipArtifactIdBases == null ? PatternSet.empty() : new PatternSet(skipArtifactIdBases);
+ }
+ return skipArtifactIdBasePatterns;
+ }
+
+ public MavenSourceTree getTree() {
+ if (tree == null) {
+ tree = MavenSourceTree.of(getRootModuleDirectory().resolve("pom.xml"), getCharset());
+ }
+ return tree;
+ }
+
+}
diff --git a/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CheckExtensionPagesMojo.java b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CheckExtensionPagesMojo.java
index b8fe771..8cb2377 100644
--- a/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CheckExtensionPagesMojo.java
+++ b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CheckExtensionPagesMojo.java
@@ -23,10 +23,8 @@ import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
-import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
import java.util.TreeSet;
import java.util.regex.Matcher;
@@ -62,7 +60,7 @@ public class CheckExtensionPagesMojo extends AbstractDocGeneratorMojo {
/**
* The directory relative to which the catalog data is read.
*/
- @Parameter(defaultValue = "${project.build.directory}/classes", property = "camel-quarkus.catalogBaseDir")
+ @Parameter(defaultValue = "${project.build.directory}/classes", property = "cq.catalogBaseDir")
File catalogBaseDir;
/**
@@ -72,18 +70,6 @@ public class CheckExtensionPagesMojo extends AbstractDocGeneratorMojo {
File docsBaseDir;
/**
- * List of directories that contain extensions
- */
- @Parameter(property = "cq.extensionDirectories", required = true)
- List<File> extensionDirectories;
-
- /**
- * A set of artifactIdBases that are not extensions and should be excluded from the catalog
- */
- @Parameter(property = "cq.skipArtifactIdBases")
- Set<String> skipArtifactIdBases;
-
- /**
* The version of Camel we depend on
*/
@Parameter(property = "camel.version")
@@ -108,9 +94,6 @@ public class CheckExtensionPagesMojo extends AbstractDocGeneratorMojo {
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
final Path docsBasePath = docsBaseDir.toPath();
- if (skipArtifactIdBases == null) {
- skipArtifactIdBases = Collections.emptySet();
- }
camelBits(docsBasePath);
extensions(docsBasePath);
@@ -186,17 +169,13 @@ public class CheckExtensionPagesMojo extends AbstractDocGeneratorMojo {
final Set<String> artifactIdBases = new HashSet<>();
final Set<CamelQuarkusExtension> extensions = new TreeSet<>(Comparator.comparing(e -> e.getName().get()));
- extensionDirectories.stream()
- .map(File::toPath)
- .forEach(extDir -> {
- CqUtils.findExtensionArtifactIdBases(extDir)
- .filter(artifactIdBase -> !skipArtifactIdBases.contains(artifactIdBase))
- .forEach(artifactIdBase -> {
- artifactIdBases.add(artifactIdBase);
- final Path runtimePomXmlPath = extDir.resolve(artifactIdBase).resolve("runtime/pom.xml")
- .toAbsolutePath().normalize();
- extensions.add(CamelQuarkusExtension.read(runtimePomXmlPath));
- });
+ findExtensions()
+ .forEach(ext -> {
+ final String artifactIdBase = ext.getArtifactIdBase();
+ artifactIdBases.add(artifactIdBase);
+ final Path runtimePomXmlPath = ext.getExtensionDir().resolve("runtime/pom.xml")
+ .toAbsolutePath().normalize();
+ extensions.add(CamelQuarkusExtension.read(runtimePomXmlPath));
});
final String extLinks = extensions.stream()
@@ -223,12 +202,14 @@ public class CheckExtensionPagesMojo extends AbstractDocGeneratorMojo {
void replace(Path path, String replacementKey, String value) {
try {
- String document = new String(Files.readAllBytes(path), encoding);
- document = replace(document, path, replacementKey, value);
- try {
- Files.write(path, document.getBytes(encoding));
- } catch (IOException e) {
- throw new RuntimeException("Could not write to " + path, e);
+ final String oldDocument = new String(Files.readAllBytes(path), encoding);
+ final String newDocument = replace(oldDocument, path, replacementKey, value);
+ if (!oldDocument.equals(newDocument)) {
+ try {
+ Files.write(path, newDocument.getBytes(encoding));
+ } catch (IOException e) {
+ throw new RuntimeException("Could not write to " + path, e);
+ }
}
} catch (IOException e) {
throw new RuntimeException("Could not read from " + path, e);
diff --git a/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CqCatalog.java b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CqCatalog.java
index ac0663e..18dc539 100644
--- a/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CqCatalog.java
+++ b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CqCatalog.java
@@ -18,12 +18,14 @@ package org.apache.camel.quarkus.maven;
import java.io.IOException;
import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
+import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -38,17 +40,20 @@ import org.apache.camel.catalog.impl.CatalogHelper;
import org.apache.camel.tooling.model.ArtifactModel;
import org.apache.camel.tooling.model.ComponentModel;
import org.apache.camel.tooling.model.DataFormatModel;
+import org.apache.camel.tooling.model.JsonMapper;
+import org.apache.camel.tooling.model.LanguageModel;
+import org.apache.camel.tooling.model.OtherModel;
public class CqCatalog {
public enum Flavor {
- camel("org.apache.camel", "camel-catalog") {
+ camel("org.apache.camel", "camel-catalog", "org/apache/camel/catalog") {
@Override
public RuntimeProvider createRuntimeProvider(DefaultCamelCatalog c) {
return new DefaultRuntimeProvider(c);
}
},
- camelQuarkus("org.apache.camel.quarkus", "camel-quarkus-catalog") {
+ camelQuarkus("org.apache.camel.quarkus", "camel-quarkus-catalog", CQ_CATALOG_DIR) {
@Override
public RuntimeProvider createRuntimeProvider(DefaultCamelCatalog c) {
return new CqRuntimeProvider(c);
@@ -57,10 +62,12 @@ public class CqCatalog {
private final String groupId;
private final String artifactId;
+ private final String catalogDir;
- private Flavor(String groupId, String artifactId) {
+ private Flavor(String groupId, String artifactId, String catalogDir) {
this.groupId = groupId;
this.artifactId = artifactId;
+ this.catalogDir = catalogDir;
}
public abstract RuntimeProvider createRuntimeProvider(DefaultCamelCatalog c);
@@ -75,6 +82,8 @@ public class CqCatalog {
}
private final DefaultCamelCatalog catalog;
+ private final Flavor flavor;
+ public static final String CQ_CATALOG_DIR = "org/apache/camel/catalog/quarkus";
private static final ThreadLocal<CqCatalog> threadLocalCamelCatalog = ThreadLocal.withInitial(CqCatalog::new);
@@ -82,16 +91,38 @@ public class CqCatalog {
return threadLocalCamelCatalog.get();
}
+ public static CqCatalog findFirstFromClassPath() {
+ try {
+ Class.forName("org.apache.camel.catalog.quarkus.QuarkusRuntimeProvider");
+ return new CqCatalog(Flavor.camelQuarkus,
+ name -> Thread.currentThread().getContextClassLoader().getResourceAsStream(name));
+ } catch (ClassNotFoundException e) {
+ return new CqCatalog(Flavor.camel,
+ name -> Thread.currentThread().getContextClassLoader().getResourceAsStream(name));
+ }
+ }
+
public CqCatalog(Path baseDir, Flavor flavor) {
- super();
+ this(flavor, name -> {
+ try {
+ return Files.newInputStream(baseDir.resolve(name));
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ });
+ }
+
+ public CqCatalog(Flavor flavor, Function<String, InputStream> resourceLocator) {
+ this.flavor = flavor;
final DefaultCamelCatalog c = new DefaultCamelCatalog(true);
c.setRuntimeProvider(flavor.createRuntimeProvider(c));
- c.setVersionManager(new CqVersionManager(c, baseDir));
+ c.setVersionManager(new CqVersionManager(c, resourceLocator));
this.catalog = c;
}
public CqCatalog() {
super();
+ this.flavor = Flavor.camel;
this.catalog = new DefaultCamelCatalog(true);
}
@@ -107,17 +138,26 @@ public class CqCatalog {
public Stream<ArtifactModel<?>> filterModels(String cqArtifactIdBase) {
final Predicate<ArtifactModel<?>> filter;
- if ("core".equals(cqArtifactIdBase)) {
- filter = model -> ("camel-base".equals(model.getArtifactId())
- || "camel-core-languages".equals(model.getArtifactId())) && !"csimple".equals(model.getName());
- } else if ("csimple".equals(cqArtifactIdBase)) {
- filter = model -> "camel-core-languages".equals(model.getArtifactId()) && "csimple".equals(model.getName());
- } else if ("reactive-executor".equals(cqArtifactIdBase)) {
- filter = model -> "camel-reactive-executor-vertx".equals(model.getArtifactId());
- } else if ("qute".equals(cqArtifactIdBase)) {
- filter = model -> "camel-quarkus-qute-component".equals(model.getArtifactId());
- } else {
- filter = model -> ("camel-" + cqArtifactIdBase).equals(model.getArtifactId());
+ switch (flavor) {
+ case camel:
+ if ("core".equals(cqArtifactIdBase)) {
+ filter = model -> ("camel-base".equals(model.getArtifactId())
+ || "camel-core-languages".equals(model.getArtifactId())) && !"csimple".equals(model.getName());
+ } else if ("csimple".equals(cqArtifactIdBase)) {
+ filter = model -> "camel-core-languages".equals(model.getArtifactId()) && "csimple".equals(model.getName());
+ } else if ("reactive-executor".equals(cqArtifactIdBase)) {
+ filter = model -> "camel-reactive-executor-vertx".equals(model.getArtifactId());
+ } else if ("qute".equals(cqArtifactIdBase)) {
+ filter = model -> "camel-quarkus-qute-component".equals(model.getArtifactId());
+ } else {
+ filter = model -> ("camel-" + cqArtifactIdBase).equals(model.getArtifactId());
+ }
+ break;
+ case camelQuarkus:
+ filter = model -> ("camel-quarkus-" + cqArtifactIdBase).equals(model.getArtifactId());
+ break;
+ default:
+ throw new IllegalStateException("Unexpected " + Flavor.class.getName() + " " + flavor);
}
return models().filter(filter);
}
@@ -135,6 +175,43 @@ public class CqCatalog {
catalog.addComponent(name, className, jsonSchema);
}
+ public void store(Path baseDir) {
+ models().forEach(m -> serialize(baseDir.resolve(flavor.catalogDir), m));
+ }
+
+ static void serialize(final Path catalogPath, ArtifactModel<?> model) {
+ final Path out = catalogPath.resolve(model.getKind() + "s")
+ .resolve(model.getName() + ".json");
+ try {
+ Files.createDirectories(out.getParent());
+ } catch (IOException e) {
+ throw new RuntimeException("Could not create " + out.getParent(), e);
+ }
+ String rawJson;
+ switch (Kind.valueOf(model.getKind())) {
+ case component:
+ rawJson = JsonMapper.createParameterJsonSchema((ComponentModel) model);
+ break;
+ case language:
+ rawJson = JsonMapper.createParameterJsonSchema((LanguageModel) model);
+ break;
+ case dataformat:
+ rawJson = JsonMapper.createParameterJsonSchema((DataFormatModel) model);
+ break;
+ case other:
+ rawJson = JsonMapper.createJsonSchema((OtherModel) model);
+ break;
+ default:
+ throw new IllegalStateException("Cannot serialize kind " + model.getKind());
+ }
+
+ try {
+ Files.write(out, rawJson.getBytes(StandardCharsets.UTF_8));
+ } catch (IOException e) {
+ throw new RuntimeException("Could not write to " + out, e);
+ }
+ }
+
public static Stream<Kind> kinds() {
return Stream.of(Kind.values())
.filter(kind -> kind != org.apache.camel.catalog.Kind.eip);
@@ -192,7 +269,10 @@ public class CqCatalog {
public static List<ArtifactModel<?>> primaryModel(Stream<ArtifactModel<?>> input) {
final List<ArtifactModel<?>> models = input
.filter(CqCatalog::isFirstScheme)
- .filter(m -> !m.getName().startsWith("google-") || !m.getName().endsWith("-stream")) // ignore the google stream component variants
+ .filter(m -> !m.getName().startsWith("google-") || !m.getName().endsWith("-stream")) // ignore the
+ // google stream
+ // component
+ // variants
.collect(Collectors.toList());
if (models.size() > 1) {
List<ArtifactModel<?>> componentModels = models.stream()
@@ -222,34 +302,30 @@ public class CqCatalog {
}
static class CqVersionManager extends DefaultVersionManager {
- private final Path baseDir;
+ private final Function<String, InputStream> resourceLocator;
- public CqVersionManager(CamelCatalog camelCatalog, Path baseDir) {
+ public CqVersionManager(CamelCatalog camelCatalog, Function<String, InputStream> resourceLocator) {
super(camelCatalog);
- this.baseDir = baseDir;
+ this.resourceLocator = resourceLocator;
}
@Override
public InputStream getResourceAsStream(String name) {
- try {
- return Files.newInputStream(baseDir.resolve(name));
- } catch (IOException e) {
- throw new RuntimeException(e);
- }
+ return resourceLocator.apply(name);
}
}
static class CqRuntimeProvider implements RuntimeProvider {
- private static final String COMPONENT_DIR = PrepareCatalogQuarkusMojo.CQ_CATALOG_DIR + "/components";
- private static final String DATAFORMAT_DIR = PrepareCatalogQuarkusMojo.CQ_CATALOG_DIR + "/dataformats";
- private static final String LANGUAGE_DIR = PrepareCatalogQuarkusMojo.CQ_CATALOG_DIR + "/languages";
- private static final String OTHER_DIR = PrepareCatalogQuarkusMojo.CQ_CATALOG_DIR + "/others";
- private static final String COMPONENTS_CATALOG = PrepareCatalogQuarkusMojo.CQ_CATALOG_DIR + "/components.properties";
- private static final String DATA_FORMATS_CATALOG = PrepareCatalogQuarkusMojo.CQ_CATALOG_DIR + "/dataformats.properties";
- private static final String LANGUAGE_CATALOG = PrepareCatalogQuarkusMojo.CQ_CATALOG_DIR + "/languages.properties";
- private static final String OTHER_CATALOG = PrepareCatalogQuarkusMojo.CQ_CATALOG_DIR + "/others.properties";
+ private static final String COMPONENT_DIR = CQ_CATALOG_DIR + "/components";
+ private static final String DATAFORMAT_DIR = CQ_CATALOG_DIR + "/dataformats";
+ private static final String LANGUAGE_DIR = CQ_CATALOG_DIR + "/languages";
+ private static final String OTHER_DIR = CQ_CATALOG_DIR + "/others";
+ private static final String COMPONENTS_CATALOG = CQ_CATALOG_DIR + "/components.properties";
+ private static final String DATA_FORMATS_CATALOG = CQ_CATALOG_DIR + "/dataformats.properties";
+ private static final String LANGUAGE_CATALOG = CQ_CATALOG_DIR + "/languages.properties";
+ private static final String OTHER_CATALOG = CQ_CATALOG_DIR + "/others.properties";
private CamelCatalog camelCatalog;
diff --git a/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CqUtils.java b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CqUtils.java
index d744903..b22e83d 100644
--- a/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CqUtils.java
+++ b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CqUtils.java
@@ -19,13 +19,16 @@ package org.apache.camel.quarkus.maven;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.io.Reader;
import java.net.URL;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
+import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -43,7 +46,10 @@ import org.apache.camel.tooling.model.JsonMapper;
import org.apache.camel.tooling.model.LanguageModel;
import org.apache.camel.tooling.model.OtherModel;
import org.apache.maven.model.Model;
+import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.plugin.logging.Log;
+import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
+import org.l2x6.maven.utils.MavenSourceTree.Module;
public class CqUtils {
public static final String CLASSPATH_PREFIX = "classpath:";
@@ -80,16 +86,39 @@ public class CqUtils {
}
}
+ public static Stream<ExtensionModule> findExtensions(Path basePath, Collection<Module> modules,
+ Predicate<String> artifactIdBaseFilter) {
+ return modules.stream()
+ .filter(p -> p.getGav().getArtifactId().asConstant().endsWith("-deployment"))
+ .map(p -> {
+ final Path extensionDir = basePath.resolve(p.getPomPath()).getParent().getParent().toAbsolutePath()
+ .normalize();
+ final String deploymentArtifactId = p.getGav().getArtifactId().asConstant();
+ if (!deploymentArtifactId.startsWith("camel-quarkus-")) {
+ throw new IllegalStateException("Should start with 'camel-quarkus-': " + deploymentArtifactId);
+ }
+ final String artifactIdBase = deploymentArtifactId.substring("camel-quarkus-".length(),
+ deploymentArtifactId.length() - "-deployment".length());
+ return new ExtensionModule(extensionDir, artifactIdBase);
+ })
+ .filter(e -> artifactIdBaseFilter.test(e.getArtifactIdBase()))
+ .sorted();
+ }
+
public static Stream<String> findExtensionArtifactIdBases(Path extensionDir) {
- try {
- return Files.list(extensionDir)
- .filter(path -> Files.isDirectory(path)
- && Files.exists(path.resolve("pom.xml"))
- && Files.exists(path.resolve("runtime")))
- .map(dir -> dir.getFileName().toString());
- } catch (IOException e) {
- throw new RuntimeException(e);
+ final Path extListPomPath = extensionDir.resolve("pom.xml");
+ final List<String> modules;
+ try (Reader r = Files.newBufferedReader(extListPomPath, StandardCharsets.UTF_8)) {
+ final MavenXpp3Reader rxppReader = new MavenXpp3Reader();
+ final Model extListPom = rxppReader.read(r);
+ modules = extListPom.getModules();
+ } catch (IOException | XmlPullParserException e) {
+ throw new RuntimeException("Could not read " + extListPomPath);
}
+
+ return modules.stream()
+ .filter(m -> Files.isRegularFile(extensionDir.resolve(m + "/pom.xml"))
+ && Files.isDirectory(extensionDir.resolve(m + "/runtime")));
}
public static Configuration getTemplateConfig(Path basePath, String defaultUriBase, String templatesUriBase,
diff --git a/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/ExtensionModule.java b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/ExtensionModule.java
new file mode 100644
index 0000000..4e617e8
--- /dev/null
+++ b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/ExtensionModule.java
@@ -0,0 +1,66 @@
+/*
+ * 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.quarkus.maven;
+
+import java.nio.file.Path;
+
+public class ExtensionModule implements Comparable<ExtensionModule> {
+
+ private final Path extensionDir;
+ private final String artifactIdBase;
+
+ public ExtensionModule(Path extensionDir, String artifactIdBase) {
+ super();
+ this.extensionDir = extensionDir;
+ this.artifactIdBase = artifactIdBase;
+ }
+
+ /**
+ * @return the absolute canonical path of the directory whose children are the runtime and deployment directories of
+ * this {@link ExtensionModule}
+ */
+ public Path getExtensionDir() {
+ return extensionDir;
+ }
+
+ public String getArtifactIdBase() {
+ return artifactIdBase;
+ }
+
+ @Override
+ public String toString() {
+ return artifactIdBase + " (" + extensionDir + ")";
+ }
+
+ public boolean isNativeSupported() {
+ return !extensionDir.getParent().getFileName().toString().equals("extensions-jvm");
+ }
+
+ @Override
+ public int compareTo(ExtensionModule other) {
+ return this.artifactIdBase.compareTo(other.artifactIdBase);
+ }
+
+ public Path getRuntimePomPath() {
+ return extensionDir.resolve("runtime/pom.xml");
+ }
+
+ public Path getPomPath() {
+ return extensionDir.resolve("pom.xml");
+ }
+
+}
diff --git a/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PatternSet.java b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PatternSet.java
new file mode 100644
index 0000000..2c03ef3
--- /dev/null
+++ b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PatternSet.java
@@ -0,0 +1,48 @@
+/*
+ * 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.quarkus.maven;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+public class PatternSet {
+
+ private static final PatternSet EMPTY = new PatternSet(Collections.emptyList());
+
+ public static PatternSet empty() {
+ return EMPTY;
+ }
+
+ private final List<Pattern> patterns;
+
+ PatternSet(Collection<String> rawPatterns) {
+ this.patterns = rawPatterns.stream()
+ .map(Pattern::compile)
+ .collect(Collectors.toList());
+ }
+
+ public boolean matchesAny(String string) {
+ if (patterns.isEmpty()) {
+ return false;
+ }
+ return patterns.stream()
+ .anyMatch(pat -> pat.matcher(string).matches());
+ }
+}
diff --git a/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PrepareCatalogQuarkusMojo.java b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PrepareCatalogQuarkusMojo.java
index dc19c29..c0e9c45 100644
--- a/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PrepareCatalogQuarkusMojo.java
+++ b/tooling/maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PrepareCatalogQuarkusMojo.java
@@ -21,7 +21,6 @@ import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
-import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@@ -33,11 +32,9 @@ import org.apache.camel.catalog.Kind;
import org.apache.camel.tooling.model.ArtifactModel;
import org.apache.camel.tooling.model.ComponentModel;
import org.apache.camel.tooling.model.DataFormatModel;
-import org.apache.camel.tooling.model.JsonMapper;
import org.apache.camel.tooling.model.LanguageModel;
import org.apache.camel.tooling.model.OtherModel;
import org.apache.camel.tooling.model.SupportLevel;
-import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Mojo;
@@ -49,9 +46,8 @@ import org.apache.maven.plugins.annotations.Parameter;
* @since 0.1.0
*/
@Mojo(name = "prepare-catalog-quarkus", threadSafe = true)
-public class PrepareCatalogQuarkusMojo extends AbstractMojo {
+public class PrepareCatalogQuarkusMojo extends AbstractExtensionListMojo {
- public static final String CQ_CATALOG_DIR = "org/apache/camel/catalog/quarkus";
public static final String CAMEL_ARTIFACT = "camelArtifact";
/**
* The output directory where the catalog files should be written.
@@ -60,104 +56,94 @@ public class PrepareCatalogQuarkusMojo extends AbstractMojo {
File catalogBaseDir;
/**
- * List of directories that contain extensions
+ * If {@code true}, the Catalog available in the class path will be first dumped to {@link #catalogBaseDir}
+ * and then some of its options will be overwritten by this mojo; otherwise no dump happens and this mojo writes to
+ * {@link #catalogBaseDir} as usual.
+ *
+ * @since 2.3.0
*/
- @Parameter(property = "cq.extensionDirectories", required = true)
- List<File> extensionDirectories;
-
- /**
- * A set of artifactIdBases that are not extensions and should be excluded from the catalog
- */
- @Parameter(property = "cq.skipArtifactIdBases")
- Set<String> skipArtifactIdBases;
+ @Parameter(property = "cq.extendClassPathCatalog", defaultValue = "false")
+ boolean extendClassPathCatalog;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
- final Path catalogPath = catalogBaseDir.toPath().resolve(CQ_CATALOG_DIR);
- if (skipArtifactIdBases == null) {
- skipArtifactIdBases = Collections.emptySet();
- }
+ final Path catalogPath = catalogBaseDir.toPath().resolve(CqCatalog.CQ_CATALOG_DIR);
final Map<String, Set<String>> schemesByKind = new LinkedHashMap<>();
CqCatalog.kinds().forEach(kind -> schemesByKind.put(kind.name(), new TreeSet<>()));
- final CqCatalog catalog = new CqCatalog();
- extensionDirectories.stream()
- .map(File::toPath)
- .forEach(extDir -> {
+ final CqCatalog catalog = CqCatalog.findFirstFromClassPath();
+ if (extendClassPathCatalog) {
+ catalog.store(catalogBaseDir.toPath());
+ }
- /* Discover local components, such as Qute and add them to the catalog */
- CqUtils.findExtensionArtifactIdBases(extDir)
- .filter(artifactIdBase -> !skipArtifactIdBases.contains(artifactIdBase))
- .forEach(artifactIdBase -> {
- final Path schemaFile = extDir
- .resolve(artifactIdBase)
- .resolve("component/src/generated/resources/org/apache/camel/component/"
- + artifactIdBase + "/" + artifactIdBase + ".json")
- .toAbsolutePath().normalize();
- if (Files.isRegularFile(schemaFile)) {
- try {
- final String schema = new String(Files.readAllBytes(schemaFile),
- StandardCharsets.UTF_8);
- final String capBase = artifactIdBase.substring(0, 1).toUpperCase()
- + artifactIdBase.substring(1);
- getLog().debug("Adding an extra component " + artifactIdBase + " " +
- "org.apache.camel.component." + artifactIdBase + "." + capBase + "Component " +
- schema);
- catalog.addComponent(artifactIdBase,
- "org.apache.camel.component." + artifactIdBase + "." + capBase + "Component",
- schema);
- } catch (IOException e) {
- throw new RuntimeException("Could not read " + schemaFile, e);
- }
- }
- });
+ findExtensions()
+ .forEach(ext -> {
+ final String artifactIdBase = ext.getArtifactIdBase();
+ final Path schemaFile = ext
+ .getExtensionDir()
+ .resolve("component/src/generated/resources/org/apache/camel/component/"
+ + artifactIdBase + "/" + artifactIdBase + ".json")
+ .toAbsolutePath().normalize();
+ if (Files.isRegularFile(schemaFile)) {
+ try {
+ final String schema = new String(Files.readAllBytes(schemaFile),
+ StandardCharsets.UTF_8);
+ final String capBase = artifactIdBase.substring(0, 1).toUpperCase()
+ + artifactIdBase.substring(1);
+ getLog().debug("Adding an extra component " + artifactIdBase + " " +
+ "org.apache.camel.component." + artifactIdBase + "." + capBase + "Component " +
+ schema);
+ catalog.addComponent(artifactIdBase,
+ "org.apache.camel.component." + artifactIdBase + "." + capBase + "Component",
+ schema);
+ } catch (IOException e) {
+ throw new RuntimeException("Could not read " + schemaFile, e);
+ }
+ }
});
- extensionDirectories.stream()
- .map(File::toPath)
- .forEach(extDir -> {
- CqUtils.findExtensionArtifactIdBases(extDir)
- .filter(artifactIdBase -> !skipArtifactIdBases.contains(artifactIdBase))
- .forEach(artifactIdBase -> {
- final List<ArtifactModel<?>> models = catalog.filterModels(artifactIdBase)
- .collect(Collectors.toList());
- final Path runtimePomXmlPath = extDir.resolve(artifactIdBase).resolve("runtime/pom.xml")
- .toAbsolutePath().normalize();
- final CamelQuarkusExtension ext = CamelQuarkusExtension.read(runtimePomXmlPath);
- final boolean nativeSupported = ext.isNativeSupported();
- if (models.isEmpty()) {
- final ArtifactModel<?> model;
- final Kind extKind = ext.getKind();
- if (extKind == Kind.component) {
- model = new ComponentModel();
- } else if (extKind == Kind.language) {
- model = new LanguageModel();
- } else if (extKind == Kind.dataformat) {
- model = new DataFormatModel();
- } else {
- model = new OtherModel();
- }
- final String name = ext.getRuntimeArtifactId().replace("camel-quarkus-", "");
- model.setName(name);
- final String title = ext.getName().orElseThrow(() -> new RuntimeException(
- "name is missing in " + ext.getRuntimePomXmlPath()));
- model.setTitle(title);
- model.setDescription(ext.getDescription().orElseThrow(() -> new RuntimeException(
- "description is missing in " + ext.getRuntimePomXmlPath())));
- model.setDeprecated(CqUtils.isDeprecated(title, models));
- model.setLabel(ext.getLabel().orElse("quarkus"));
- update(model, ext, nativeSupported);
- serialize(catalogPath, model);
- schemesByKind.get(model.getKind()).add(model.getName());
- } else {
- for (ArtifactModel<?> model : models) {
- update(model, ext, nativeSupported);
- serialize(catalogPath, model);
- schemesByKind.get(model.getKind()).add(model.getName());
- }
- }
- });
+ findExtensions()
+ .forEach(extPath -> {
+ final String artifactIdBase = extPath.getArtifactIdBase();
+ final List<ArtifactModel<?>> models = catalog.filterModels(artifactIdBase)
+ .collect(Collectors.toList());
+ final Path runtimePomXmlPath = extPath
+ .getExtensionDir().resolve("runtime/pom.xml")
+ .toAbsolutePath().normalize();
+ final CamelQuarkusExtension ext = CamelQuarkusExtension.read(runtimePomXmlPath);
+ final boolean nativeSupported = ext.isNativeSupported();
+ if (models.isEmpty()) {
+ final ArtifactModel<?> model;
+ final Kind extKind = ext.getKind();
+ if (extKind == Kind.component) {
+ model = new ComponentModel();
+ } else if (extKind == Kind.language) {
+ model = new LanguageModel();
+ } else if (extKind == Kind.dataformat) {
+ model = new DataFormatModel();
+ } else {
+ model = new OtherModel();
+ }
+ final String name = ext.getRuntimeArtifactId().replace("camel-quarkus-", "");
+ model.setName(name);
+ final String title = ext.getName().orElseThrow(() -> new RuntimeException(
+ "name is missing in " + ext.getRuntimePomXmlPath()));
+ model.setTitle(title);
+ model.setDescription(ext.getDescription().orElseThrow(() -> new RuntimeException(
+ "description is missing in " + ext.getRuntimePomXmlPath())));
+ model.setDeprecated(CqUtils.isDeprecated(title, models));
+ model.setLabel(ext.getLabel().orElse("quarkus"));
+ update(model, ext, nativeSupported);
+ CqCatalog.serialize(catalogPath, model);
+ schemesByKind.get(model.getKind()).add(model.getName());
+ } else {
+ for (ArtifactModel<?> model : models) {
+ update(model, ext, nativeSupported);
+ CqCatalog.serialize(catalogPath, model);
+ schemesByKind.get(model.getKind()).add(model.getName());
+ }
+ }
});
CqCatalog.kinds().forEach(kind -> {
@@ -174,39 +160,6 @@ public class PrepareCatalogQuarkusMojo extends AbstractMojo {
}
- private void serialize(final Path catalogPath, ArtifactModel<?> model) {
- final Path out = catalogPath.resolve(model.getKind() + "s")
- .resolve(model.getName() + ".json");
- try {
- Files.createDirectories(out.getParent());
- } catch (IOException e) {
- throw new RuntimeException("Could not create " + out.getParent(), e);
- }
- String rawJson;
- switch (Kind.valueOf(model.getKind())) {
- case component:
- rawJson = JsonMapper.createParameterJsonSchema((ComponentModel) model);
- break;
- case language:
- rawJson = JsonMapper.createParameterJsonSchema((LanguageModel) model);
- break;
- case dataformat:
- rawJson = JsonMapper.createParameterJsonSchema((DataFormatModel) model);
- break;
- case other:
- rawJson = JsonMapper.createJsonSchema((OtherModel) model);
- break;
- default:
- throw new IllegalStateException("Cannot serialize kind " + model.getKind());
- }
-
- try {
- Files.write(out, rawJson.getBytes(StandardCharsets.UTF_8));
- } catch (IOException e) {
- throw new RuntimeException("Could not write to " + out);
- }
- }
-
private static void update(ArtifactModel<?> model, CamelQuarkusExtension ext, boolean nativeSupported) {
final String firstVersion = ext.getJvmSince()
.orElseThrow(() -> new RuntimeException(