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 2020/03/18 22:01:40 UTC

[camel-quarkus] 01/02: Fix #897 List the JVM-only extensions in the docs

This is an automated email from the ASF dual-hosted git repository.

ppalaga pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git

commit 360b436ae96e4cdbd3ac3398a13fd49f7af9dec9
Author: Peter Palaga <pp...@redhat.com>
AuthorDate: Wed Mar 18 17:21:59 2020 +0100

    Fix #897 List the JVM-only extensions in the docs
---
 catalog/pom.xml                                    |  13 +-
 .../pages/list-of-camel-quarkus-extensions.adoc    | 403 +++++++----
 extensions/readme.adoc                             | 383 ----------
 pom.xml                                            |   4 +
 tooling/package-maven-plugin/pom.xml               | 112 +--
 .../org/apache/camel/quarkus/maven/CqCatalog.java  | 462 ++++++++++++
 .../org/apache/camel/quarkus/maven/CqUtils.java    |  97 +++
 .../apache/camel/quarkus/maven/ExtMvelHelper.java  |  81 ---
 .../camel/quarkus/maven/JSonSchemaHelper.java      | 567 ---------------
 .../quarkus/maven/PrepareCatalogQuarkusMojo.java   | 465 ++++---------
 .../quarkus/maven/UpdateDocExtensionsListMojo.java | 775 ++++-----------------
 .../camel-quarkus-package-maven-plugin.properties  |  16 -
 .../extension-list-templates/readme-components.ftl |  14 +
 .../readme-dataformats.ftl                         |  12 +
 .../extension-list-templates/readme-languages.ftl  |  12 +
 .../extension-list-templates/readme-others.ftl     |  11 +
 .../src/main/resources/other-template.mvel         |  14 -
 .../src/main/resources/readme-components.mvel      |  14 -
 .../src/main/resources/readme-dataformats.mvel     |  12 -
 .../src/main/resources/readme-languages.mvel       |  12 -
 .../src/main/resources/readme-others.mvel          |  12 -
 tooling/pom.xml                                    | 114 +--
 22 files changed, 1181 insertions(+), 2424 deletions(-)

diff --git a/catalog/pom.xml b/catalog/pom.xml
index 23f873f..ae16306 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -86,10 +86,15 @@
                         </goals>
                         <phase>process-resources</phase>
                         <configuration>
-                            <extensionDirs>
-                                <extensionDir>${camel.quarkus.project.root}/extensions-core</extensionDir>
-                                <extensionDir>${camel.quarkus.project.root}/extensions</extensionDir>
-                            </extensionDirs>
+                            <extensionDirectories>
+                                <extensionDirectory>${camel.quarkus.project.root}/extensions-core</extensionDirectory>
+                                <extensionDirectory>${camel.quarkus.project.root}/extensions</extensionDirectory>
+                                <extensionDirectory>${camel.quarkus.project.root}/extensions-jvm</extensionDirectory>
+                            </extensionDirectories>
+                            <skipArtifactIdBases>
+                                <skipArtifactIdBase>http-common</skipArtifactIdBase>
+                            </skipArtifactIdBases>
+                            <extensionListFile>${camel.quarkus.project.root}/docs/modules/ROOT/pages/list-of-camel-quarkus-extensions.adoc</extensionListFile>
                         </configuration>
                     </execution>
                 </executions>
diff --git a/docs/modules/ROOT/pages/list-of-camel-quarkus-extensions.adoc b/docs/modules/ROOT/pages/list-of-camel-quarkus-extensions.adoc
index 010e861..c0cfc38 100644
--- a/docs/modules/ROOT/pages/list-of-camel-quarkus-extensions.adoc
+++ b/docs/modules/ROOT/pages/list-of-camel-quarkus-extensions.adoc
@@ -18,248 +18,332 @@ In case you are missing some Camel feature in the list:
 == Camel Components
 
 // components: START
-Number of Camel components: 79 in 68 JAR artifacts (0 deprecated)
+Number of Camel components: 80 in 69 JAR artifacts (0 deprecated)
 
-[width="100%",cols="4,1,5",options="header"]
+[width="100%",cols="4,1,1,5",options="header"]
 |===
-| Component | Since | Description
+| Component | Target +
+Level | Since | Description
 
 | link:https://camel.apache.org/components/latest/activemq-component.html[ActiveMQ] (camel-quarkus-activemq) +
-`activemq:destinationType:destinationName` | 1.0.0-M5 | The activemq component allows messages to be sent to (or consumed from) Apache ActiveMQ. This component extends the Camel JMS component.
+`activemq:destinationType:destinationName` | Native +
+ Stable | 1.0.0-M5 | The activemq component allows messages to be sent to (or consumed from) Apache ActiveMQ. This component extends the Camel JMS component.
 
 | xref:extensions/ahc.adoc[AHC] (camel-quarkus-ahc) +
-`ahc:httpUri` | 1.0.0-M3 | To call external HTTP services using Async Http Client.
+`ahc:httpUri` | Native +
+ Stable | 1.0.0-M3 | To call external HTTP services using Async Http Client.
 
 | link:https://camel.apache.org/components/latest/ahc-ws-component.html[AHC Websocket] (camel-quarkus-ahc-ws) +
-`ahc-ws:httpUri` | 1.0.0-M3 | To exchange data with external Websocket servers using Async Http Client.
+`ahc-ws:httpUri` | Native +
+ Stable | 1.0.0-M3 | To exchange data with external Websocket servers using Async Http Client.
 
 | link:https://camel.apache.org/components/latest/aws-ec2-component.html[AWS EC2] (camel-quarkus-aws-ec2) +
-`aws-ec2:label` | 1.0.0-M3 | The aws-ec2 is used for managing Amazon EC2 instances.
+`aws-ec2:label` | Native +
+ Stable | 1.0.0-M3 | The aws-ec2 is used for managing Amazon EC2 instances.
 
 | link:https://camel.apache.org/components/latest/aws-ecs-component.html[AWS ECS] (camel-quarkus-aws-ecs) +
-`aws-ecs:label` | 1.0.0-M1 | The aws-ecs is used for managing Amazon ECS
+`aws-ecs:label` | Native +
+ Stable | 1.0.0-M1 | The aws-ecs is used for managing Amazon ECS
 
 | link:https://camel.apache.org/components/latest/aws-eks-component.html[AWS EKS] (camel-quarkus-aws-eks) +
-`aws-eks:label` | 0.2.0 | The aws-eks is used for managing Amazon EKS
+`aws-eks:label` | Native +
+ Stable | 0.2.0 | The aws-eks is used for managing Amazon EKS
 
 | link:https://camel.apache.org/components/latest/aws-iam-component.html[AWS IAM] (camel-quarkus-aws-iam) +
-`aws-iam:label` | 1.1.0 | The aws-iam is used for managing Amazon IAM
+`aws-iam:label` | Native +
+ Stable | 1.1.0 | The aws-iam is used for managing Amazon IAM
 
 | link:https://camel.apache.org/components/latest/aws-kinesis-component.html[AWS Kinesis] (camel-quarkus-aws-kinesis) +
-`aws-kinesis:streamName` | 1.0.0-M3 | The aws-kinesis component is for consuming and producing records from Amazon Kinesis Streams.
+`aws-kinesis:streamName` | Native +
+ Stable | 1.0.0-M3 | The aws-kinesis component is for consuming and producing records from Amazon Kinesis Streams.
 
 | link:https://camel.apache.org/components/latest/aws-kinesis-firehose-component.html[AWS Kinesis Firehose] (camel-quarkus-aws-kinesis) +
-`aws-kinesis-firehose:streamName` | 1.0.0-M3 | The aws-kinesis-firehose component is used for producing Amazon's Kinesis Firehose streams.
+`aws-kinesis-firehose:streamName` | Native +
+ Stable | 1.0.0-M3 | The aws-kinesis-firehose component is used for producing Amazon's Kinesis Firehose streams.
 
 | link:https://camel.apache.org/components/latest/aws-kms-component.html[AWS KMS] (camel-quarkus-aws-kms) +
-`aws-kms:label` | 1.0.0-M1 | The aws-kms is used for managing Amazon KMS
+`aws-kms:label` | Native +
+ Stable | 1.0.0-M1 | The aws-kms is used for managing Amazon KMS
 
 | link:https://camel.apache.org/components/latest/aws-lambda-component.html[AWS Lambda] (camel-quarkus-aws-lambda) +
-`aws-lambda:function` | 1.0.0-M3 | The aws-lambda is used for managing and invoking functions from Amazon Lambda.
+`aws-lambda:function` | Native +
+ Stable | 1.0.0-M3 | The aws-lambda is used for managing and invoking functions from Amazon Lambda.
 
 | link:https://camel.apache.org/components/latest/aws-s3-component.html[AWS S3 Storage Service] (camel-quarkus-aws-s3) +
-`aws-s3://bucketNameOrArn` | 0.2.0 | The aws-s3 component is used for storing and retrieving object from Amazon S3 Storage Service.
+`aws-s3://bucketNameOrArn` | Native +
+ Stable | 0.2.0 | The aws-s3 component is used for storing and retrieving object from Amazon S3 Storage Service.
 
 | link:https://camel.apache.org/components/latest/aws-sns-component.html[AWS Simple Notification System] (camel-quarkus-aws-sns) +
-`aws-sns:topicNameOrArn` | 0.2.0 | The aws-sns component is used for sending messages to an Amazon Simple Notification Topic.
+`aws-sns:topicNameOrArn` | Native +
+ Stable | 0.2.0 | The aws-sns component is used for sending messages to an Amazon Simple Notification Topic.
 
 | link:https://camel.apache.org/components/latest/aws-sqs-component.html[AWS Simple Queue Service] (camel-quarkus-aws-sqs) +
-`aws-sqs:queueNameOrArn` | 0.2.0 | The aws-sqs component is used for sending and receiving messages to Amazon's SQS service.
+`aws-sqs:queueNameOrArn` | Native +
+ Stable | 0.2.0 | The aws-sqs component is used for sending and receiving messages to Amazon's SQS service.
 
 | link:https://camel.apache.org/components/latest/aws-translate-component.html[AWS Translate] (camel-quarkus-aws-translate) +
-`aws-translate:label` | 1.0.0-M3 | The aws-translate component is used for managing Amazon Translate
+`aws-translate:label` | Native +
+ Stable | 1.0.0-M3 | The aws-translate component is used for managing Amazon Translate
 
 | link:https://camel.apache.org/components/latest/azure-blob-component.html[Azure Storage Blob Service] (camel-quarkus-azure) +
-`azure-blob:containerOrBlobUri` | 1.0.0-M4 | The azure-blob component is used for storing and retrieving blobs from Azure Storage Blob Service.
+`azure-blob:containerOrBlobUri` | Native +
+ Stable | 1.0.0-M4 | The azure-blob component is used for storing and retrieving blobs from Azure Storage Blob Service.
 
 | link:https://camel.apache.org/components/latest/azure-queue-component.html[Azure Storage Queue Service] (camel-quarkus-azure) +
-`azure-queue:containerAndQueueUri` | 1.0.0-M4 | The azure-queue component is used for storing and retrieving messages from Azure Storage Queue Service.
+`azure-queue:containerAndQueueUri` | Native +
+ Stable | 1.0.0-M4 | The azure-queue component is used for storing and retrieving messages from Azure Storage Queue Service.
 
 | link:https://camel.apache.org/components/latest/bean-component.html[Bean] (camel-quarkus-bean) +
-`bean:beanName` | 0.2.0 | The bean component is for invoking Java beans from Camel.
+`bean:beanName` | Native +
+ Stable | 0.2.0 | The bean component is for invoking Java beans from Camel.
 
 | link:https://camel.apache.org/components/latest/bean-validator-component.html[Bean Validator] (camel-quarkus-bean-validator) +
-`bean-validator:label` | 1.0.0-M1 | The Validator component performs bean validation of the message body using the Java Bean Validation API.
+`bean-validator:label` | Native +
+ Stable | 1.0.0-M1 | The Validator component performs bean validation of the message body using the Java Bean Validation API.
 
 | link:https://camel.apache.org/components/latest/box-component.html[Box] (camel-quarkus-box) +
-`box:apiName/methodName` | 1.0.0-M4 | For uploading downloading and managing files folders groups collaborations etc on box DOT com.
+`box:apiName/methodName` | Native +
+ Stable | 1.0.0-M4 | For uploading downloading and managing files folders groups collaborations etc on box DOT com.
 
 | link:https://camel.apache.org/components/latest/braintree-component.html[Braintree] (camel-quarkus-braintree) +
-`braintree:apiName/methodName` | 1.2.0 | The braintree component is used for integrating with the Braintree Payment System.
+`braintree:apiName/methodName` | Native +
+ Stable | 1.2.0 | The braintree component is used for integrating with the Braintree Payment System.
 
 | link:https://camel.apache.org/components/latest/class-component.html[Class] (camel-quarkus-bean) +
-`class:beanName` | 0.2.0 | The Class component is for invoking Java classes (Java beans) from Camel.
+`class:beanName` | Native +
+ Stable | 0.2.0 | The Class component is for invoking Java classes (Java beans) from Camel.
 
 | link:https://camel.apache.org/components/latest/consul-component.html[Consul] (camel-quarkus-consul) +
-`consul:apiEndpoint` | 1.0.0-M3 | The camel consul component allows you to work with Consul, a distributed, highly available, datacenter-aware, service discovery and configuration system.
+`consul:apiEndpoint` | Native +
+ Stable | 1.0.0-M3 | The camel consul component allows you to work with Consul, a distributed, highly available, datacenter-aware, service discovery and configuration system.
 
 | link:https://camel.apache.org/components/latest/controlbus-component.html[Control Bus] (camel-quarkus-controlbus) +
-`controlbus:command:language` | 0.4.0 | The controlbus component provides easy management of Camel applications based on the Control Bus EIP pattern.
+`controlbus:command:language` | Native +
+ Stable | 0.4.0 | The controlbus component provides easy management of Camel applications based on the Control Bus EIP pattern.
 
 | link:https://camel.apache.org/components/latest/dataformat-component.html[Data Format] (camel-quarkus-dataformat) +
-`dataformat:name:operation` | 0.4.0 | The dataformat component is used for working with Data Formats as if it was a regular Component supporting Endpoints and URIs.
+`dataformat:name:operation` | Native +
+ Stable | 0.4.0 | The dataformat component is used for working with Data Formats as if it was a regular Component supporting Endpoints and URIs.
 
 | link:https://camel.apache.org/components/latest/direct-component.html[Direct] (camel-quarkus-direct) +
-`direct:name` | 0.2.0 | The direct component provides direct, synchronous call to another endpoint from the same CamelContext.
+`direct:name` | Native +
+ Stable | 0.2.0 | The direct component provides direct, synchronous call to another endpoint from the same CamelContext.
 
 | xref:extensions/dozer.adoc[Dozer] (camel-quarkus-dozer) +
-`dozer:name` | 1.0.0-M1 | The dozer component provides the ability to map between Java beans using the Dozer mapping library.
+`dozer:name` | Native +
+ Stable | 1.0.0-M1 | The dozer component provides the ability to map between Java beans using the Dozer mapping library.
+
+| link:https://camel.apache.org/components/latest/elasticsearch-rest-component.html[Elastichsearch Rest] (camel-quarkus-elasticsearch-rest) +
+`elasticsearch-rest:clusterName` | JVM +
+ Preview | 1.0.0-M6 | The elasticsearch component is used for interfacing with ElasticSearch server using REST API.
 
 | link:https://camel.apache.org/components/latest/exec-component.html[Exec] (camel-quarkus-exec) +
-`exec:executable` | 0.4.0 | The exec component can be used to execute OS system commands.
+`exec:executable` | Native +
+ Stable | 0.4.0 | The exec component can be used to execute OS system commands.
 
 | xref:extensions/fhir.adoc[FHIR] (camel-quarkus-fhir) +
-`fhir:apiName/methodName` | 0.3.0 | The fhir component is used for working with the FHIR protocol (health care).
+`fhir:apiName/methodName` | Native +
+ Stable | 0.3.0 | The fhir component is used for working with the FHIR protocol (health care).
 
 | link:https://camel.apache.org/components/latest/file-component.html[File] (camel-quarkus-file) +
-`file:directoryName` | 0.4.0 | The file component is used for reading or writing files.
+`file:directoryName` | Native +
+ Stable | 0.4.0 | The file component is used for reading or writing files.
 
 | xref:extensions/file-watch.adoc[File Watch] (camel-quarkus-file-watch) +
-`file-watch:path` | 1.0.0-M5 | The file-watch is used to monitor file events in directory using java.nio.file.WatchService
+`file-watch:path` | Native +
+ Stable | 1.0.0-M5 | The file-watch is used to monitor file events in directory using java.nio.file.WatchService
 
 | link:https://camel.apache.org/components/latest/ftp-component.html[FTP] (camel-quarkus-ftp) +
-`ftp:host:port/directoryName` | 1.0.0-M1 | The \ftp component is used for uploading or downloading files from FTP servers.
+`ftp:host:port/directoryName` | Native +
+ Stable | 1.0.0-M1 | The ftp component is used for uploading or downloading files from FTP servers.
 
 | link:https://camel.apache.org/components/latest/ftps-component.html[FTPS] (camel-quarkus-ftp) +
-`ftps:host:port/directoryName` | 1.0.0-M1 | The \ftps (FTP secure SSL/TLS) component is used for uploading or downloading files from FTP servers.
+`ftps:host:port/directoryName` | Native +
+ Stable | 1.0.0-M1 | The ftps (FTP secure SSL/TLS) component is used for uploading or downloading files from FTP servers.
 
 | link:https://camel.apache.org/components/latest/google-drive-component.html[Google Drive] (camel-quarkus-google-drive) +
-`google-drive:apiName/methodName` | 1.0.0-M6 | The google-drive component provides access to Google Drive file storage service.
+`google-drive:apiName/methodName` | Native +
+ Stable | 1.0.0-M6 | The google-drive component provides access to Google Drive file storage service.
 
 | link:https://camel.apache.org/components/latest/google-mail-component.html[Google Mail] (camel-quarkus-google-mail) +
-`google-mail:apiName/methodName` | 1.0.0-M6 | The google-mail component provides access to Google Mail.
+`google-mail:apiName/methodName` | Native +
+ Stable | 1.0.0-M6 | The google-mail component provides access to Google Mail.
 
 | link:https://camel.apache.org/components/latest/google-mail-stream-component.html[Google Mail Stream] (camel-quarkus-google-mail) +
-`google-mail-stream:index` | 1.0.0-M6 | The google-mail component provides access to Google Mail.
+`google-mail-stream:index` | Native +
+ Stable | 1.0.0-M6 | The google-mail component provides access to Google Mail.
 
 | xref:extensions/graphql.adoc[GraphQL] (camel-quarkus-graphql) +
-`graphql:httpUri` | 1.0.0-M5 | A Camel GraphQL Component
+`graphql:httpUri` | Native +
+ Stable | 1.0.0-M5 | A Camel GraphQL Component
 
 | xref:extensions/http.adoc[HTTP] (camel-quarkus-http) +
-`http:httpUri` | 1.0.0-M3 | For calling out to external HTTP servers using Apache HTTP Client 4.x.
+`http:httpUri` | Native +
+ Stable | 1.0.0-M3 | For calling out to external HTTP servers using Apache HTTP Client 4.x.
 
 | link:https://camel.apache.org/components/latest/infinispan-component.html[Infinispan] (camel-quarkus-infinispan) +
-`infinispan:cacheName` | 0.2.0 | For reading/writing from/to Infinispan distributed key/value store and data grid.
+`infinispan:cacheName` | Native +
+ Stable | 0.2.0 | For reading/writing from/to Infinispan distributed key/value store and data grid.
 
 | xref:extensions/websocket-jsr356.adoc[Javax Websocket] (camel-quarkus-websocket-jsr356) +
-`websocket-jsr356:uri` | 1.0.0-M4 | Camel WebSocket using JSR356 (javax)
+`websocket-jsr356:uri` | Native +
+ Stable | 1.0.0-M4 | Camel WebSocket using JSR356 (javax)
 
 | link:https://camel.apache.org/components/latest/jdbc-component.html[JDBC] (camel-quarkus-jdbc) +
-`jdbc:dataSourceName` | 0.2.0 | The jdbc component enables you to access databases through JDBC, where SQL queries are sent in the message body.
+`jdbc:dataSourceName` | Native +
+ Stable | 0.2.0 | The jdbc component enables you to access databases through JDBC, where SQL queries are sent in the message body.
 
 | link:https://camel.apache.org/components/latest/jira-component.html[Jira] (camel-quarkus-jira) +
-`jira:type` | 1.0.0-M4 | The jira component interacts with the JIRA issue tracker.
+`jira:type` | Native +
+ Stable | 1.0.0-M4 | The jira component interacts with the JIRA issue tracker.
 
 | link:https://camel.apache.org/components/latest/jms-component.html[JMS] (camel-quarkus-jms) +
-`jms:destinationType:destinationName` | 1.2.0 | The jms component allows messages to be sent to (or consumed from) a JMS Queue or Topic.
+`jms:destinationType:destinationName` | Native +
+ Stable | 1.2.0 | The jms component allows messages to be sent to (or consumed from) a JMS Queue or Topic.
 
 | link:https://camel.apache.org/components/latest/kafka-component.html[Kafka] (camel-quarkus-kafka) +
-`kafka:topic` | 1.0.0-M1 | The kafka component allows messages to be sent to (or consumed from) Apache Kafka brokers.
+`kafka:topic` | Native +
+ Stable | 1.0.0-M1 | The kafka component allows messages to be sent to (or consumed from) Apache Kafka brokers.
 
 | link:https://camel.apache.org/components/latest/log-component.html[Log] (camel-quarkus-log) +
-`log:loggerName` | 0.2.0 | The log component logs message exchanges to the underlying logging mechanism.
+`log:loggerName` | Native +
+ Stable | 0.2.0 | The log component logs message exchanges to the underlying logging mechanism.
 
 | link:https://camel.apache.org/components/latest/mail-component.html[Mail] (camel-quarkus-mail) +
-`imap:host:port` | 0.2.0 | To send or receive emails using imap/pop3 or smtp protocols.
+`imap:host:port` | Native +
+ Stable | 0.2.0 | To send or receive emails using imap/pop3 or smtp protocols.
 
 | xref:extensions/microprofile-metrics.adoc[MicroProfile Metrics] (camel-quarkus-microprofile-metrics) +
-`microprofile-metrics:metricType:metricName` | 0.2.0 | Camel metrics exposed with Eclipse MicroProfile Metrics
+`microprofile-metrics:metricType:metricName` | Native +
+ Stable | 0.2.0 | Camel metrics exposed with Eclipse MicroProfile Metrics
 
 | xref:extensions/mongodb.adoc[MongoDB] (camel-quarkus-mongodb) +
-`mongodb:connectionBean` | 1.0.0-M1 | Component for working with documents stored in MongoDB database.
+`mongodb:connectionBean` | Native +
+ Stable | 1.0.0-M1 | Component for working with documents stored in MongoDB database.
 
 | link:https://camel.apache.org/components/latest/mustache-component.html[Mustache] (camel-quarkus-mustache) +
-`mustache:resourceUri` | 1.0.0-M5 | Transforms the message using a Mustache template.
+`mustache:resourceUri` | Native +
+ Stable | 1.0.0-M5 | Transforms the message using a Mustache template.
 
 | xref:extensions/netty.adoc[Netty] (camel-quarkus-netty) +
-`netty:protocol:host:port` | 0.4.0 | Socket level networking using TCP or UDP with the Netty 4.x library.
+`netty:protocol:host:port` | Native +
+ Stable | 0.4.0 | Socket level networking using TCP or UDP with the Netty 4.x library.
 
 | xref:extensions/netty-http.adoc[Netty HTTP] (camel-quarkus-netty-http) +
-`netty-http:protocol:host:port/path` | 0.2.0 | Netty HTTP server and client using the Netty 4.x library.
+`netty-http:protocol:host:port/path` | Native +
+ Stable | 0.2.0 | Netty HTTP server and client using the Netty 4.x library.
 
 | link:https://camel.apache.org/components/latest/olingo4-component.html[Olingo4] (camel-quarkus-olingo4) +
-`olingo4:apiName/methodName` | 1.0.0-M4 | Communicates with OData 4.0 services using Apache Olingo OData API.
+`olingo4:apiName/methodName` | Native +
+ Stable | 1.0.0-M4 | Communicates with OData 4.0 services using Apache Olingo OData API.
 
 | link:https://camel.apache.org/components/latest/paho-component.html[Paho] (camel-quarkus-paho) +
-`paho:topic` | 0.2.0 | Component for communicating with MQTT message brokers using Eclipse Paho MQTT Client.
+`paho:topic` | Native +
+ Stable | 0.2.0 | Component for communicating with MQTT message brokers using Eclipse Paho MQTT Client.
 
 | link:https://camel.apache.org/components/latest/pdf-component.html[PDF] (camel-quarkus-pdf) +
-`pdf:operation` | 0.3.1 | The pdf components provides the ability to create, modify or extract content from PDF documents.
+`pdf:operation` | Native +
+ Stable | 0.3.1 | The pdf components provides the ability to create, modify or extract content from PDF documents.
 
 | xref:extensions/platform-http.adoc[Platform HTTP] (camel-quarkus-platform-http) +
-`platform-http:path` | 0.3.0 | HTTP service leveraging existing runtime platform HTTP server
+`platform-http:path` | Native +
+ Stable | 0.3.0 | HTTP service leveraging existing runtime platform HTTP server
 
 | link:https://camel.apache.org/components/latest/reactive-streams-component.html[Reactive Streams] (camel-quarkus-reactive-streams) +
-`reactive-streams:stream` | 1.0.0-M3 | Reactive Camel using reactive streams
+`reactive-streams:stream` | Native +
+ Stable | 1.0.0-M3 | Reactive Camel using reactive streams
 
 | link:https://camel.apache.org/components/latest/ref-component.html[Ref] (camel-quarkus-ref) +
-`ref:name` | 1.0.0-M5 | The ref component is used for lookup of existing endpoints bound in the Registry.
+`ref:name` | Native +
+ Stable | 1.0.0-M5 | The ref component is used for lookup of existing endpoints bound in the Registry.
 
 | link:https://camel.apache.org/components/latest/rest-component.html[REST] (camel-quarkus-rest) +
-`rest:method:path:uriTemplate` | 0.2.0 | The rest component is used for either hosting REST services (consumer) or calling external REST services (producer).
+`rest:method:path:uriTemplate` | Native +
+ Stable | 0.2.0 | The rest component is used for either hosting REST services (consumer) or calling external REST services (producer).
 
 | link:https://camel.apache.org/components/latest/rest-api-component.html[REST API] (camel-quarkus-rest) +
-`rest-api:path/contextIdPattern` | 0.2.0 | The rest-api component is used for providing Swagger API of the REST services which has been defined using the rest-dsl in Camel.
+`rest-api:path/contextIdPattern` | Native +
+ Stable | 0.2.0 | The rest-api component is used for providing Swagger API of the REST services which has been defined using the rest-dsl in Camel.
 
 | link:https://camel.apache.org/components/latest/salesforce-component.html[Salesforce] (camel-quarkus-salesforce) +
-`salesforce:operationName:topicName` | 0.2.0 | The salesforce component is used for integrating Camel with the massive Salesforce API.
+`salesforce:operationName:topicName` | Native +
+ Stable | 0.2.0 | The salesforce component is used for integrating Camel with the massive Salesforce API.
 
 | link:https://camel.apache.org/components/latest/scheduler-component.html[Scheduler] (camel-quarkus-scheduler) +
-`scheduler:name` | 0.4.0 | The scheduler component is used for generating message exchanges when a scheduler fires.
+`scheduler:name` | Native +
+ Stable | 0.4.0 | The scheduler component is used for generating message exchanges when a scheduler fires.
 
 | link:https://camel.apache.org/components/latest/seda-component.html[SEDA] (camel-quarkus-seda) +
-`seda:name` | 1.0.0-M1 | The seda component provides asynchronous call to another endpoint from any CamelContext in the same JVM.
+`seda:name` | Native +
+ Stable | 1.0.0-M1 | The seda component provides asynchronous call to another endpoint from any CamelContext in the same JVM.
 
 | link:https://camel.apache.org/components/latest/servlet-component.html[Servlet] (camel-quarkus-servlet) +
-`servlet:contextPath` | 0.2.0 | To use a HTTP Servlet as entry for Camel routes when running in a servlet container.
+`servlet:contextPath` | Native +
+ Stable | 0.2.0 | To use a HTTP Servlet as entry for Camel routes when running in a servlet container.
 
 | link:https://camel.apache.org/components/latest/sftp-component.html[SFTP] (camel-quarkus-ftp) +
-`sftp:host:port/directoryName` | 1.0.0-M1 | The \sftp (FTP over SSH) component is used for uploading or downloading files from SFTP servers.
+`sftp:host:port/directoryName` | Native +
+ Stable | 1.0.0-M1 | The sftp (FTP over SSH) component is used for uploading or downloading files from SFTP servers.
 
 | link:https://camel.apache.org/components/latest/sjms-component.html[Simple JMS] (camel-quarkus-sjms) +
-`sjms:destinationType:destinationName` | 1.0.0-M1 | The sjms component (simple jms) allows messages to be sent to (or consumed from) a JMS Queue or Topic (uses JMS 1.x API).
+`sjms:destinationType:destinationName` | Native +
+ Stable | 1.0.0-M1 | The sjms component (simple jms) allows messages to be sent to (or consumed from) a JMS Queue or Topic (uses JMS 1.x API).
 
 | link:https://camel.apache.org/components/latest/sjms-batch-component.html[Simple JMS Batch] (camel-quarkus-sjms) +
-`sjms-batch:destinationName` | 1.0.0-M1 | The sjms-batch component is a specialized for highly performant, transactional batch consumption from a JMS queue.
+`sjms-batch:destinationName` | Native +
+ Stable | 1.0.0-M1 | The sjms-batch component is a specialized for highly performant, transactional batch consumption from a JMS queue.
 
 | link:https://camel.apache.org/components/latest/sjms2-component.html[Simple JMS2] (camel-quarkus-sjms2) +
-`sjms2:destinationType:destinationName` | 1.0.0-M1 | The sjms2 component (simple jms) allows messages to be sent to (or consumed from) a JMS Queue or Topic (uses JMS 2.x API).
+`sjms2:destinationType:destinationName` | Native +
+ Stable | 1.0.0-M1 | The sjms2 component (simple jms) allows messages to be sent to (or consumed from) a JMS Queue or Topic (uses JMS 2.x API).
 
 | link:https://camel.apache.org/components/latest/slack-component.html[Slack] (camel-quarkus-slack) +
-`slack:channel` | 0.3.0 | The slack component allows you to send messages to Slack.
+`slack:channel` | Native +
+ Stable | 0.3.0 | The slack component allows you to send messages to Slack.
 
 | xref:extensions/sql.adoc[SQL] (camel-quarkus-sql) +
-`sql:query` | 1.0.0-M2 | The sql component allows you to work with databases using JDBC SQL queries.
+`sql:query` | Native +
+ Stable | 1.0.0-M2 | The sql component allows you to work with databases using JDBC SQL queries.
 
 | xref:extensions/sql.adoc[SQL Stored Procedure] (camel-quarkus-sql) +
-`sql-stored:template` | 1.0.0-M2 | The sql component allows you to work with databases using JDBC Stored Procedure queries.
+`sql-stored:template` | Native +
+ Stable | 1.0.0-M2 | The sql component allows you to work with databases using JDBC Stored Procedure queries.
 
 | xref:extensions/stream.adoc[Stream] (camel-quarkus-stream) +
-`stream:kind` | 1.0.0-M4 | The stream: component provides access to the system-in, system-out and system-err streams as well as allowing streaming of file.
+`stream:kind` | Native +
+ Stable | 1.0.0-M4 | The stream: component provides access to the system-in, system-out and system-err streams as well as allowing streaming of file.
 
 | link:https://camel.apache.org/components/latest/telegram-component.html[Telegram] (camel-quarkus-telegram) +
-`telegram:type` | 1.0.0-M4 | The telegram component provides access to the Telegram Bot API.
+`telegram:type` | Native +
+ Stable | 1.0.0-M4 | The telegram component provides access to the Telegram Bot API.
 
 | link:https://camel.apache.org/components/latest/timer-component.html[Timer] (camel-quarkus-timer) +
-`timer:timerName` | 0.2.0 | The timer component is used for generating message exchanges when a timer fires.
+`timer:timerName` | Native +
+ Stable | 0.2.0 | The timer component is used for generating message exchanges when a timer fires.
 
 | link:https://camel.apache.org/components/latest/twitter-directmessage-component.html[Twitter Direct Message] (camel-quarkus-twitter) +
-`twitter-directmessage:user` | 0.2.0 | The Twitter Direct Message Component consumes/produces user's direct messages.
+`twitter-directmessage:user` | Native +
+ Stable | 0.2.0 | The Twitter Direct Message Component consumes/produces user's direct messages.
 
 | link:https://camel.apache.org/components/latest/twitter-search-component.html[Twitter Search] (camel-quarkus-twitter) +
-`twitter-search:keywords` | 0.2.0 | The Twitter Search component consumes search results.
+`twitter-search:keywords` | Native +
+ Stable | 0.2.0 | The Twitter Search component consumes search results.
 
 | link:https://camel.apache.org/components/latest/twitter-timeline-component.html[Twitter Timeline] (camel-quarkus-twitter) +
-`twitter-timeline:timelineType` | 0.2.0 | The Twitter Timeline component consumes twitter timeline or update the status of specific user.
+`twitter-timeline:timelineType` | Native +
+ Stable | 0.2.0 | The Twitter Timeline component consumes twitter timeline or update the status of specific user.
 
 | link:https://camel.apache.org/components/latest/validator-component.html[Validator] (camel-quarkus-validator) +
-`validator:resourceUri` | 0.4.0 | Validates the payload of a message using XML Schema and JAXP Validation.
+`validator:resourceUri` | Native +
+ Stable | 0.4.0 | Validates the payload of a message using XML Schema and JAXP Validation.
 
 | link:https://camel.apache.org/components/latest/vm-component.html[VM] (camel-quarkus-vm) +
-`vm:name` | 0.3.0 | The vm component provides asynchronous call to another endpoint from the same CamelContext.
+`vm:name` | Native +
+ Stable | 0.3.0 | The vm component provides asynchronous call to another endpoint from the same CamelContext.
 
 | xref:extensions/xslt.adoc[XSLT] (camel-quarkus-xslt) +
-`xslt:resourceUri` | 0.4.0 | Transforms the message using a XSLT template.
+`xslt:resourceUri` | Native +
+ Stable | 0.4.0 | Transforms the message using a XSLT template.
 
 |===
 // components: END
@@ -269,57 +353,82 @@ Number of Camel components: 79 in 68 JAR artifacts (0 deprecated)
 // dataformats: START
 Number of Camel data formats: 24 in 19 JAR artifacts (0 deprecated)
 
-[width="100%",cols="4,1,5",options="header"]
+[width="100%",cols="4,1,1,5",options="header"]
 |===
-| Data Format | Since | Description
+| Data Format | Target +
+Level | Since | Description
 
-| link:https://camel.apache.org/components/latest/base64-dataformat.html[Base64] (camel-quarkus-base64) | 1.0.0-M1 | The Base64 data format is used for base64 encoding and decoding.
+| link:https://camel.apache.org/components/latest/base64-dataformat.html[Base64] (camel-quarkus-base64) | Native +
+ Stable | 1.0.0-M1 | The Base64 data format is used for base64 encoding and decoding.
 
-| link:https://camel.apache.org/components/latest/bindy-dataformat.html[Bindy CSV] (camel-quarkus-bindy) | 1.0.0-M4 | The Bindy data format is used for working with flat payloads (such as CSV, delimited, fixed length formats, or FIX messages).
+| link:https://camel.apache.org/components/latest/bindy-dataformat.html[Bindy CSV] (camel-quarkus-bindy) | Native +
+ Stable | 1.0.0-M4 | The Bindy data format is used for working with flat payloads (such as CSV, delimited, fixed length formats, or FIX messages).
 
-| link:https://camel.apache.org/components/latest/bindy-dataformat.html[Bindy Fixed Length] (camel-quarkus-bindy) | 1.0.0-M4 | The Bindy data format is used for working with flat payloads (such as CSV, delimited, fixed length formats, or FIX messages).
+| link:https://camel.apache.org/components/latest/bindy-dataformat.html[Bindy Fixed Length] (camel-quarkus-bindy) | Native +
+ Stable | 1.0.0-M4 | The Bindy data format is used for working with flat payloads (such as CSV, delimited, fixed length formats, or FIX messages).
 
-| link:https://camel.apache.org/components/latest/bindy-dataformat.html[Bindy Key Value Pair] (camel-quarkus-bindy) | 1.0.0-M4 | The Bindy data format is used for working with flat payloads (such as CSV, delimited, fixed length formats, or FIX messages).
+| link:https://camel.apache.org/components/latest/bindy-dataformat.html[Bindy Key Value Pair] (camel-quarkus-bindy) | Native +
+ Stable | 1.0.0-M4 | The Bindy data format is used for working with flat payloads (such as CSV, delimited, fixed length formats, or FIX messages).
 
-| link:https://camel.apache.org/components/latest/csv-dataformat.html[CSV] (camel-quarkus-csv) | 0.2.0 | The CSV data format is used for handling CSV payloads.
+| link:https://camel.apache.org/components/latest/csv-dataformat.html[CSV] (camel-quarkus-csv) | Native +
+ Stable | 0.2.0 | The CSV data format is used for handling CSV payloads.
 
-| xref:extensions/fhir.adoc[FHIR JSon] (camel-quarkus-fhir) | 0.3.0 | The FHIR JSon data format is used to marshall/unmarshall to/from FHIR objects to/from JSON.
+| xref:extensions/fhir.adoc[FHIR JSon] (camel-quarkus-fhir) | Native +
+ Stable | 0.3.0 | The FHIR JSon data format is used to marshall/unmarshall to/from FHIR objects to/from JSON.
 
-| xref:extensions/fhir.adoc[FHIR XML] (camel-quarkus-fhir) | 0.3.0 | The FHIR XML data format is used to marshall/unmarshall from/to FHIR objects to/from XML.
+| xref:extensions/fhir.adoc[FHIR XML] (camel-quarkus-fhir) | Native +
+ Stable | 0.3.0 | The FHIR XML data format is used to marshall/unmarshall from/to FHIR objects to/from XML.
 
-| link:https://camel.apache.org/components/latest/gzipdeflater-dataformat.html[GZip Deflater] (camel-quarkus-zip-deflater) | 1.0.0-M4 | The GZip data format is a message compression and de-compression format (which works with the popular gzip/gunzip tools).
+| link:https://camel.apache.org/components/latest/gzipdeflater-dataformat.html[GZip Deflater] (camel-quarkus-zip-deflater) | Native +
+ Stable | 1.0.0-M4 | The GZip data format is a message compression and de-compression format (which works with the popular gzip/gunzip tools).
 
-| link:https://camel.apache.org/components/latest/ical-dataformat.html[iCal] (camel-quarkus-ical) | 1.0.0-M5 | The iCal dataformat is used for working with iCalendar messages.
+| link:https://camel.apache.org/components/latest/ical-dataformat.html[iCal] (camel-quarkus-ical) | Native +
+ Stable | 1.0.0-M5 | The iCal dataformat is used for working with iCalendar messages.
 
-| link:https://camel.apache.org/components/latest/jacksonxml-dataformat.html[JacksonXML] (camel-quarkus-jacksonxml) | 1.0.0-M5 | JacksonXML data format is used for unmarshal a XML payload to POJO or to marshal POJO back to XML payload.
+| link:https://camel.apache.org/components/latest/jacksonxml-dataformat.html[JacksonXML] (camel-quarkus-jacksonxml) | Native +
+ Stable | 1.0.0-M5 | JacksonXML data format is used for unmarshal a XML payload to POJO or to marshal POJO back to XML payload.
 
-| link:https://camel.apache.org/components/latest/jaxb-dataformat.html[JAXB] (camel-quarkus-jaxb) | 1.0.0-M5 | JAXB data format uses the JAXB2 XML marshalling standard to unmarshal an XML payload into Java objects or to marshal Java objects into an XML payload.
+| link:https://camel.apache.org/components/latest/jaxb-dataformat.html[JAXB] (camel-quarkus-jaxb) | Native +
+ Stable | 1.0.0-M5 | JAXB data format uses the JAXB2 XML marshalling standard to unmarshal an XML payload into Java objects or to marshal Java objects into an XML payload.
 
-| link:https://camel.apache.org/components/latest/json-gson-dataformat.html[JSon GSon] (camel-quarkus-gson) | 1.0.0-M4 | JSon data format is used for unmarshal a JSon payload to POJO or to marshal POJO back to JSon payload.
+| link:https://camel.apache.org/components/latest/json-gson-dataformat.html[JSon GSon] (camel-quarkus-gson) | Native +
+ Stable | 1.0.0-M4 | JSon data format is used for unmarshal a JSon payload to POJO or to marshal POJO back to JSon payload.
 
-| link:https://camel.apache.org/components/latest/json-jackson-dataformat.html[JSon Jackson] (camel-quarkus-jackson) | 0.3.0 | JSon data format is used for unmarshal a JSon payload to POJO or to marshal POJO back to JSon payload.
+| link:https://camel.apache.org/components/latest/json-jackson-dataformat.html[JSon Jackson] (camel-quarkus-jackson) | Native +
+ Stable | 0.3.0 | JSon data format is used for unmarshal a JSon payload to POJO or to marshal POJO back to JSon payload.
 
-| link:https://camel.apache.org/components/latest/json-johnzon-dataformat.html[JSon Johnzon] (camel-quarkus-johnzon) | 1.0.0-M5 | JSon data format is used for unmarshal a JSon payload to POJO or to marshal POJO back to JSon payload.
+| link:https://camel.apache.org/components/latest/json-johnzon-dataformat.html[JSon Johnzon] (camel-quarkus-johnzon) | Native +
+ Stable | 1.0.0-M5 | JSon data format is used for unmarshal a JSon payload to POJO or to marshal POJO back to JSon payload.
 
-| link:https://camel.apache.org/components/latest/json-xstream-dataformat.html[JSon XStream] (camel-quarkus-xstream) | 1.0.0-M5 | JSon data format is used for unmarshal a JSon payload to POJO or to marshal POJO back to JSon payload.
+| link:https://camel.apache.org/components/latest/json-xstream-dataformat.html[JSon XStream] (camel-quarkus-xstream) | Native +
+ Stable | 1.0.0-M5 | JSon data format is used for unmarshal a JSon payload to POJO or to marshal POJO back to JSon payload.
 
-| link:https://camel.apache.org/components/latest/lzf-dataformat.html[LZF Deflate Compression] (camel-quarkus-lzf) | 1.0.0-M4 | The LZF data format is a message compression and de-compression format (uses the LZF deflate algorithm).
+| link:https://camel.apache.org/components/latest/lzf-dataformat.html[LZF Deflate Compression] (camel-quarkus-lzf) | Native +
+ Stable | 1.0.0-M4 | The LZF data format is a message compression and de-compression format (uses the LZF deflate algorithm).
 
-| link:https://camel.apache.org/components/latest/mime-multipart-dataformat.html[MIME Multipart] (camel-quarkus-mail) | 0.2.0 | The MIME Multipart data format is used for marshalling Camel messages with attachments into MIME-Multipart message, and vise-versa.
+| link:https://camel.apache.org/components/latest/mime-multipart-dataformat.html[MIME Multipart] (camel-quarkus-mail) | Native +
+ Stable | 0.2.0 | The MIME Multipart data format is used for marshalling Camel messages with attachments into MIME-Multipart message, and vise-versa.
 
-| link:https://camel.apache.org/components/latest/soapjaxb-dataformat.html[SOAP] (camel-quarkus-soap) | 1.0.0-M5 | SOAP is a data format which uses JAXB2 and JAX-WS annotations to marshal and unmarshal SOAP payloads.
+| link:https://camel.apache.org/components/latest/soapjaxb-dataformat.html[SOAP] (camel-quarkus-soap) | Native +
+ Stable | 1.0.0-M5 | SOAP is a data format which uses JAXB2 and JAX-WS annotations to marshal and unmarshal SOAP payloads.
 
-| link:https://camel.apache.org/components/latest/tarfile-dataformat.html[Tar File] (camel-quarkus-tarfile) | 0.3.0 | The Tar File data format is a message compression and de-compression format of tar files.
+| link:https://camel.apache.org/components/latest/tarfile-dataformat.html[Tar File] (camel-quarkus-tarfile) | Native +
+ Stable | 0.3.0 | The Tar File data format is a message compression and de-compression format of tar files.
 
-| link:https://camel.apache.org/components/latest/tidyMarkup-dataformat.html[TidyMarkup] (camel-quarkus-tagsoup) | 1.0.0-M1 | TidyMarkup data format is used for parsing HTML and return it as pretty well-formed HTML.
+| link:https://camel.apache.org/components/latest/tidyMarkup-dataformat.html[TidyMarkup] (camel-quarkus-tagsoup) | Native +
+ Stable | 1.0.0-M1 | TidyMarkup data format is used for parsing HTML and return it as pretty well-formed HTML.
 
-| link:https://camel.apache.org/components/latest/xstream-dataformat.html[XStream] (camel-quarkus-xstream) | 1.0.0-M5 | XStream data format is used for unmarshal a XML payload to POJO or to marshal POJO back to XML payload.
+| link:https://camel.apache.org/components/latest/xstream-dataformat.html[XStream] (camel-quarkus-xstream) | Native +
+ Stable | 1.0.0-M5 | XStream data format is used for unmarshal a XML payload to POJO or to marshal POJO back to XML payload.
 
-| link:https://camel.apache.org/components/latest/yaml-snakeyaml-dataformat.html[YAML SnakeYAML] (camel-quarkus-snakeyaml) | 0.4.0 | YAML is a data format to marshal and unmarshal Java objects to and from YAML.
+| link:https://camel.apache.org/components/latest/yaml-snakeyaml-dataformat.html[YAML SnakeYAML] (camel-quarkus-snakeyaml) | Native +
+ Stable | 0.4.0 | YAML is a data format to marshal and unmarshal Java objects to and from YAML.
 
-| link:https://camel.apache.org/components/latest/zipdeflater-dataformat.html[Zip Deflate Compression] (camel-quarkus-zip-deflater) | 1.0.0-M4 | Zip Deflate Compression data format is a message compression and de-compression format (not zip files).
+| link:https://camel.apache.org/components/latest/zipdeflater-dataformat.html[Zip Deflate Compression] (camel-quarkus-zip-deflater) | Native +
+ Stable | 1.0.0-M4 | Zip Deflate Compression data format is a message compression and de-compression format (not zip files).
 
-| link:https://camel.apache.org/components/latest/zipfile-dataformat.html[Zip File] (camel-quarkus-zipfile) | 0.2.0 | The Zip File data format is a message compression and de-compression format of zip files.
+| link:https://camel.apache.org/components/latest/zipfile-dataformat.html[Zip File] (camel-quarkus-zipfile) | Native +
+ Stable | 0.2.0 | The Zip File data format is a message compression and de-compression format of zip files.
 |===
 // dataformats: END
 
@@ -328,31 +437,43 @@ Number of Camel data formats: 24 in 19 JAR artifacts (0 deprecated)
 // languages: START
 Number of Camel languages: 11 in 5 JAR artifacts (0 deprecated)
 
-[width="100%",cols="4,1,5",options="header"]
+[width="100%",cols="4,1,1,5",options="header"]
 |===
-| Language | Since | Description
+| Language | Target +
+Level | Since | Description
 
-| link:https://camel.apache.org/components/latest/bean-language.html[Bean method] (camel-quarkus-bean) | 0.2.0 | To use a Java bean (aka method call) in Camel expressions or predicates.
+| link:https://camel.apache.org/components/latest/bean-language.html[Bean method] (camel-quarkus-bean) | Native +
+ Stable | 0.2.0 | To use a Java bean (aka method call) in Camel expressions or predicates.
 
-| link:https://camel.apache.org/components/latest/constant-language.html[Constant] (camel-quarkus-core) | 0.2.0 | To use a constant value in Camel expressions or predicates. Important: this is a fixed constant value that is only set once during starting up the route, do not use this if you want dynamic values during routing.
+| link:https://camel.apache.org/components/latest/constant-language.html[Constant] (camel-quarkus-core) | Native +
+ Stable | 0.2.0 | To use a constant value in Camel expressions or predicates. Important: this is a fixed constant value that is only set once during starting up the route, do not use this if you want dynamic values during routing.
 
-| link:https://camel.apache.org/components/latest/exchangeProperty-language.html[ExchangeProperty] (camel-quarkus-core) | 0.2.0 | To use a Camel Exchange property in expressions or predicates.
+| link:https://camel.apache.org/components/latest/exchangeProperty-language.html[ExchangeProperty] (camel-quarkus-core) | Native +
+ Stable | 0.2.0 | To use a Camel Exchange property in expressions or predicates.
 
-| link:https://camel.apache.org/components/latest/file-language.html[File] (camel-quarkus-core) | 0.2.0 | For expressions and predicates using the file/simple language.
+| link:https://camel.apache.org/components/latest/file-language.html[File] (camel-quarkus-core) | Native +
+ Stable | 0.2.0 | For expressions and predicates using the file/simple language.
 
-| link:https://camel.apache.org/components/latest/header-language.html[Header] (camel-quarkus-core) | 0.2.0 | To use a Camel Message header in expressions or predicates.
+| link:https://camel.apache.org/components/latest/header-language.html[Header] (camel-quarkus-core) | Native +
+ Stable | 0.2.0 | To use a Camel Message header in expressions or predicates.
 
-| link:https://camel.apache.org/components/latest/jsonpath-language.html[JsonPath] (camel-quarkus-jsonpath) | 1.0.0-M3 | To use JsonPath in Camel expressions or predicates.
+| link:https://camel.apache.org/components/latest/jsonpath-language.html[JsonPath] (camel-quarkus-jsonpath) | Native +
+ Stable | 1.0.0-M3 | To use JsonPath in Camel expressions or predicates.
 
-| link:https://camel.apache.org/components/latest/ref-language.html[Ref] (camel-quarkus-core) | 0.2.0 | Reference to an existing Camel expression or predicate, which is looked up from the Camel registry.
+| link:https://camel.apache.org/components/latest/ref-language.html[Ref] (camel-quarkus-core) | Native +
+ Stable | 0.2.0 | Reference to an existing Camel expression or predicate, which is looked up from the Camel registry.
 
-| link:https://camel.apache.org/components/latest/simple-language.html[Simple] (camel-quarkus-core) | 0.2.0 | To use Camels built-in Simple language in Camel expressions or predicates.
+| link:https://camel.apache.org/components/latest/simple-language.html[Simple] (camel-quarkus-core) | Native +
+ Stable | 0.2.0 | To use Camels built-in Simple language in Camel expressions or predicates.
 
-| link:https://camel.apache.org/components/latest/tokenize-language.html[Tokenize] (camel-quarkus-core) | 0.2.0 | To use Camel message body or header with a tokenizer in Camel expressions or predicates.
+| link:https://camel.apache.org/components/latest/tokenize-language.html[Tokenize] (camel-quarkus-core) | Native +
+ Stable | 0.2.0 | To use Camel message body or header with a tokenizer in Camel expressions or predicates.
 
-| link:https://camel.apache.org/components/latest/xtokenize-language.html[XML Tokenize] (camel-quarkus-xml-jaxp) | 1.0.0-M5 | To use Camel message body or header with a XML tokenizer in Camel expressions or predicates.
+| link:https://camel.apache.org/components/latest/xtokenize-language.html[XML Tokenize] (camel-quarkus-xml-jaxp) | Native +
+ Stable | 1.0.0-M5 | To use Camel message body or header with a XML tokenizer in Camel expressions or predicates.
 
-| link:https://camel.apache.org/components/latest/xpath-language.html[XPath] (camel-quarkus-xpath) | 1.0.0-M4 | To use XPath (XML) in Camel expressions or predicates.
+| link:https://camel.apache.org/components/latest/xpath-language.html[XPath] (camel-quarkus-xpath) | Native +
+ Stable | 1.0.0-M4 | To use XPath (XML) in Camel expressions or predicates.
 |===
 // languages: END
 
@@ -361,32 +482,44 @@ Number of Camel languages: 11 in 5 JAR artifacts (0 deprecated)
 // others: START
 Number of miscellaneous extensions: 12 in 12 JAR artifacts (0 deprecated)
 
-[width="100%",cols="4,1,5",options="header"]
+[width="100%",cols="4,1,1,5",options="header"]
 |===
-| Extension | Since | Description
+| Extension | Target Level | Since | Description
 
-| (camel-quarkus-attachments) | 0.3.0 | Java Attachments support for Camel Message
+| (camel-quarkus-attachments) | Native +
+ Stable | 0.3.0 | Java Attachments support for Camel Message
 
-| (camel-quarkus-caffeine-lrucache) | 1.0.0-M5 | Provides an implementation of the LRUCacheFactory based on Caffeine
+| (camel-quarkus-caffeine-lrucache) | Native +
+ Stable | 1.0.0-M5 | Provides an implementation of the LRUCacheFactory based on Caffeine
 
-| (camel-quarkus-core-cloud) | 0.2.0 | The Camel Quarkus core cloud module
+| (camel-quarkus-core-cloud) | Native +
+ Stable | 0.2.0 | The Camel Quarkus core cloud module
 
-| (camel-quarkus-endpointdsl) | 1.0.0-M3 | camel-quarkus-endpointdsl
+| (camel-quarkus-endpointdsl) | Native +
+ Stable | 1.0.0-M3 | camel-quarkus-endpointdsl
 
-| (camel-quarkus-hystrix) | 1.0.0-M1 | Circuit Breaker EIP using Netflix Hystrix
+| (camel-quarkus-hystrix) | Native +
+ Stable | 1.0.0-M1 | Circuit Breaker EIP using Netflix Hystrix
 
-| (camel-quarkus-kotlin) | 1.0.0-M3 | camel-quarkus-kotlin
+| (camel-quarkus-kotlin) | Native +
+ Stable | 1.0.0-M3 | camel-quarkus-kotlin
 
-| xref:extensions/microprofile-health.adoc[camel-quarkus-microprofile-health]  | 0.3.0 | Bridging Eclipse MicroProfile Health with Camel health checks
+| xref:extensions/microprofile-health.adoc[camel-quarkus-microprofile-health]  | Native +
+ Stable | 0.3.0 | Bridging Eclipse MicroProfile Health with Camel health checks
 
-| xref:extensions/opentracing.adoc[camel-quarkus-opentracing]  | 0.3.0 | Distributed tracing using OpenTracing
+| xref:extensions/opentracing.adoc[camel-quarkus-opentracing]  | Native +
+ Stable | 0.3.0 | Distributed tracing using OpenTracing
 
-| xref:extensions/qute.adoc[camel-quarkus-qute]  | 1.0.0-M6 | Camel component uses Quarkus Qute as the templating engine
+| xref:extensions/qute.adoc[camel-quarkus-qute]  | Native +
+ Stable | 1.0.0-M6 | Camel component uses Quarkus Qute as the templating engine
 
-| (camel-quarkus-reactive-executor) | 0.3.0 | Reactive Executor for camel-core using Vert.x
+| (camel-quarkus-reactive-executor) | Native +
+ Stable | 0.3.0 | Reactive Executor for camel-core using Vert.x
 
-| (camel-quarkus-xml-io) | 1.0.0-M5 | An XML stack for parsing XML route definitions. A fast an light weight alternative to camel-quarkus-xml-jaxp
+| (camel-quarkus-xml-io) | Native +
+ Stable | 1.0.0-M5 | An XML stack for parsing XML route definitions. A fast an light weight alternative to camel-quarkus-xml-jaxp
 
-| (camel-quarkus-xml-jaxb) | 1.0.0-M5 | An XML stack for parsing XML route definitions. A legacy alternative to the fast an light weight camel-quarkus-xml-io
+| (camel-quarkus-xml-jaxb) | Native +
+ Stable | 1.0.0-M5 | An XML stack for parsing XML route definitions. A legacy alternative to the fast an light weight camel-quarkus-xml-io
 |===
 // others: END
diff --git a/extensions/readme.adoc b/extensions/readme.adoc
deleted file mode 100644
index bca5960..0000000
--- a/extensions/readme.adoc
+++ /dev/null
@@ -1,383 +0,0 @@
-= Extensions
-
-Apache Camel Quarkus supports the following Camel artifacts as Quarkus Extensions
-
-== Camel Components
-
-// components: START
-Number of Camel components: 79 in 68 JAR artifacts (0 deprecated)
-
-[width="100%",cols="4,1,5",options="header"]
-|===
-| Component | Since | Description
-
-| link:https://camel.apache.org/components/latest/activemq-component.html[ActiveMQ] (camel-quarkus-activemq) +
-`activemq:destinationType:destinationName` | 1.0.0-M5 | The activemq component allows messages to be sent to (or consumed from) Apache ActiveMQ. This component extends the Camel JMS component.
-
-| xref:extensions/ahc.adoc[AHC] (camel-quarkus-ahc) +
-`ahc:httpUri` | 1.0.0-M3 | To call external HTTP services using Async Http Client.
-
-| link:https://camel.apache.org/components/latest/ahc-ws-component.html[AHC Websocket] (camel-quarkus-ahc-ws) +
-`ahc-ws:httpUri` | 1.0.0-M3 | To exchange data with external Websocket servers using Async Http Client.
-
-| link:https://camel.apache.org/components/latest/aws-ec2-component.html[AWS EC2] (camel-quarkus-aws-ec2) +
-`aws-ec2:label` | 1.0.0-M3 | The aws-ec2 is used for managing Amazon EC2 instances.
-
-| link:https://camel.apache.org/components/latest/aws-ecs-component.html[AWS ECS] (camel-quarkus-aws-ecs) +
-`aws-ecs:label` | 1.0.0-M1 | The aws-ecs is used for managing Amazon ECS
-
-| link:https://camel.apache.org/components/latest/aws-eks-component.html[AWS EKS] (camel-quarkus-aws-eks) +
-`aws-eks:label` | 0.2.0 | The aws-eks is used for managing Amazon EKS
-
-| link:https://camel.apache.org/components/latest/aws-iam-component.html[AWS IAM] (camel-quarkus-aws-iam) +
-`aws-iam:label` | 1.1.0 | The aws-iam is used for managing Amazon IAM
-
-| link:https://camel.apache.org/components/latest/aws-kinesis-component.html[AWS Kinesis] (camel-quarkus-aws-kinesis) +
-`aws-kinesis:streamName` | 1.0.0-M3 | The aws-kinesis component is for consuming and producing records from Amazon Kinesis Streams.
-
-| link:https://camel.apache.org/components/latest/aws-kinesis-firehose-component.html[AWS Kinesis Firehose] (camel-quarkus-aws-kinesis) +
-`aws-kinesis-firehose:streamName` | 1.0.0-M3 | The aws-kinesis-firehose component is used for producing Amazon's Kinesis Firehose streams.
-
-| link:https://camel.apache.org/components/latest/aws-kms-component.html[AWS KMS] (camel-quarkus-aws-kms) +
-`aws-kms:label` | 1.0.0-M1 | The aws-kms is used for managing Amazon KMS
-
-| link:https://camel.apache.org/components/latest/aws-lambda-component.html[AWS Lambda] (camel-quarkus-aws-lambda) +
-`aws-lambda:function` | 1.0.0-M3 | The aws-lambda is used for managing and invoking functions from Amazon Lambda.
-
-| link:https://camel.apache.org/components/latest/aws-s3-component.html[AWS S3 Storage Service] (camel-quarkus-aws-s3) +
-`aws-s3://bucketNameOrArn` | 0.2.0 | The aws-s3 component is used for storing and retrieving object from Amazon S3 Storage Service.
-
-| link:https://camel.apache.org/components/latest/aws-sns-component.html[AWS Simple Notification System] (camel-quarkus-aws-sns) +
-`aws-sns:topicNameOrArn` | 0.2.0 | The aws-sns component is used for sending messages to an Amazon Simple Notification Topic.
-
-| link:https://camel.apache.org/components/latest/aws-sqs-component.html[AWS Simple Queue Service] (camel-quarkus-aws-sqs) +
-`aws-sqs:queueNameOrArn` | 0.2.0 | The aws-sqs component is used for sending and receiving messages to Amazon's SQS service.
-
-| link:https://camel.apache.org/components/latest/aws-translate-component.html[AWS Translate] (camel-quarkus-aws-translate) +
-`aws-translate:label` | 1.0.0-M3 | The aws-translate component is used for managing Amazon Translate
-
-| link:https://camel.apache.org/components/latest/azure-blob-component.html[Azure Storage Blob Service] (camel-quarkus-azure) +
-`azure-blob:containerOrBlobUri` | 1.0.0-M4 | The azure-blob component is used for storing and retrieving blobs from Azure Storage Blob Service.
-
-| link:https://camel.apache.org/components/latest/azure-queue-component.html[Azure Storage Queue Service] (camel-quarkus-azure) +
-`azure-queue:containerAndQueueUri` | 1.0.0-M4 | The azure-queue component is used for storing and retrieving messages from Azure Storage Queue Service.
-
-| link:https://camel.apache.org/components/latest/bean-component.html[Bean] (camel-quarkus-bean) +
-`bean:beanName` | 0.2.0 | The bean component is for invoking Java beans from Camel.
-
-| link:https://camel.apache.org/components/latest/bean-validator-component.html[Bean Validator] (camel-quarkus-bean-validator) +
-`bean-validator:label` | 1.0.0-M1 | The Validator component performs bean validation of the message body using the Java Bean Validation API.
-
-| link:https://camel.apache.org/components/latest/box-component.html[Box] (camel-quarkus-box) +
-`box:apiName/methodName` | 1.0.0-M4 | For uploading downloading and managing files folders groups collaborations etc on box DOT com.
-
-| link:https://camel.apache.org/components/latest/braintree-component.html[Braintree] (camel-quarkus-braintree) +
-`braintree:apiName/methodName` | 1.2.0 | The braintree component is used for integrating with the Braintree Payment System.
-
-| link:https://camel.apache.org/components/latest/class-component.html[Class] (camel-quarkus-bean) +
-`class:beanName` | 0.2.0 | The Class component is for invoking Java classes (Java beans) from Camel.
-
-| link:https://camel.apache.org/components/latest/consul-component.html[Consul] (camel-quarkus-consul) +
-`consul:apiEndpoint` | 1.0.0-M3 | The camel consul component allows you to work with Consul, a distributed, highly available, datacenter-aware, service discovery and configuration system.
-
-| link:https://camel.apache.org/components/latest/controlbus-component.html[Control Bus] (camel-quarkus-controlbus) +
-`controlbus:command:language` | 0.4.0 | The controlbus component provides easy management of Camel applications based on the Control Bus EIP pattern.
-
-| link:https://camel.apache.org/components/latest/dataformat-component.html[Data Format] (camel-quarkus-dataformat) +
-`dataformat:name:operation` | 0.4.0 | The dataformat component is used for working with Data Formats as if it was a regular Component supporting Endpoints and URIs.
-
-| link:https://camel.apache.org/components/latest/direct-component.html[Direct] (camel-quarkus-direct) +
-`direct:name` | 0.2.0 | The direct component provides direct, synchronous call to another endpoint from the same CamelContext.
-
-| xref:extensions/dozer.adoc[Dozer] (camel-quarkus-dozer) +
-`dozer:name` | 1.0.0-M1 | The dozer component provides the ability to map between Java beans using the Dozer mapping library.
-
-| link:https://camel.apache.org/components/latest/exec-component.html[Exec] (camel-quarkus-exec) +
-`exec:executable` | 0.4.0 | The exec component can be used to execute OS system commands.
-
-| xref:extensions/fhir.adoc[FHIR] (camel-quarkus-fhir) +
-`fhir:apiName/methodName` | 0.3.0 | The fhir component is used for working with the FHIR protocol (health care).
-
-| link:https://camel.apache.org/components/latest/file-component.html[File] (camel-quarkus-file) +
-`file:directoryName` | 0.4.0 | The file component is used for reading or writing files.
-
-| xref:extensions/file-watch.adoc[File Watch] (camel-quarkus-file-watch) +
-`file-watch:path` | 1.0.0-M5 | The file-watch is used to monitor file events in directory using java.nio.file.WatchService
-
-| link:https://camel.apache.org/components/latest/ftp-component.html[FTP] (camel-quarkus-ftp) +
-`ftp:host:port/directoryName` | 1.0.0-M1 | The \ftp component is used for uploading or downloading files from FTP servers.
-
-| link:https://camel.apache.org/components/latest/ftps-component.html[FTPS] (camel-quarkus-ftp) +
-`ftps:host:port/directoryName` | 1.0.0-M1 | The \ftps (FTP secure SSL/TLS) component is used for uploading or downloading files from FTP servers.
-
-| link:https://camel.apache.org/components/latest/google-drive-component.html[Google Drive] (camel-quarkus-google-drive) +
-`google-drive:apiName/methodName` | 1.0.0-M6 | The google-drive component provides access to Google Drive file storage service.
-
-| link:https://camel.apache.org/components/latest/google-mail-component.html[Google Mail] (camel-quarkus-google-mail) +
-`google-mail:apiName/methodName` | 1.0.0-M6 | The google-mail component provides access to Google Mail.
-
-| link:https://camel.apache.org/components/latest/google-mail-stream-component.html[Google Mail Stream] (camel-quarkus-google-mail) +
-`google-mail-stream:index` | 1.0.0-M6 | The google-mail component provides access to Google Mail.
-
-| xref:extensions/graphql.adoc[GraphQL] (camel-quarkus-graphql) +
-`graphql:httpUri` | 1.0.0-M5 | A Camel GraphQL Component
-
-| xref:extensions/http.adoc[HTTP] (camel-quarkus-http) +
-`http:httpUri` | 1.0.0-M3 | For calling out to external HTTP servers using Apache HTTP Client 4.x.
-
-| link:https://camel.apache.org/components/latest/infinispan-component.html[Infinispan] (camel-quarkus-infinispan) +
-`infinispan:cacheName` | 0.2.0 | For reading/writing from/to Infinispan distributed key/value store and data grid.
-
-| xref:extensions/websocket-jsr356.adoc[Javax Websocket] (camel-quarkus-websocket-jsr356) +
-`websocket-jsr356:uri` | 1.0.0-M4 | Camel WebSocket using JSR356 (javax)
-
-| link:https://camel.apache.org/components/latest/jdbc-component.html[JDBC] (camel-quarkus-jdbc) +
-`jdbc:dataSourceName` | 0.2.0 | The jdbc component enables you to access databases through JDBC, where SQL queries are sent in the message body.
-
-| link:https://camel.apache.org/components/latest/jira-component.html[Jira] (camel-quarkus-jira) +
-`jira:type` | 1.0.0-M4 | The jira component interacts with the JIRA issue tracker.
-
-| link:https://camel.apache.org/components/latest/jms-component.html[JMS] (camel-quarkus-jms) +
-`jms:destinationType:destinationName` | 1.2.0 | The jms component allows messages to be sent to (or consumed from) a JMS Queue or Topic.
-
-| link:https://camel.apache.org/components/latest/kafka-component.html[Kafka] (camel-quarkus-kafka) +
-`kafka:topic` | 1.0.0-M1 | The kafka component allows messages to be sent to (or consumed from) Apache Kafka brokers.
-
-| link:https://camel.apache.org/components/latest/log-component.html[Log] (camel-quarkus-log) +
-`log:loggerName` | 0.2.0 | The log component logs message exchanges to the underlying logging mechanism.
-
-| link:https://camel.apache.org/components/latest/mail-component.html[Mail] (camel-quarkus-mail) +
-`imap:host:port` | 0.2.0 | To send or receive emails using imap/pop3 or smtp protocols.
-
-| xref:extensions/microprofile-metrics.adoc[MicroProfile Metrics] (camel-quarkus-microprofile-metrics) +
-`microprofile-metrics:metricType:metricName` | 0.2.0 | Camel metrics exposed with Eclipse MicroProfile Metrics
-
-| xref:extensions/mongodb.adoc[MongoDB] (camel-quarkus-mongodb) +
-`mongodb:connectionBean` | 1.0.0-M1 | Component for working with documents stored in MongoDB database.
-
-| link:https://camel.apache.org/components/latest/mustache-component.html[Mustache] (camel-quarkus-mustache) +
-`mustache:resourceUri` | 1.0.0-M5 | Transforms the message using a Mustache template.
-
-| xref:extensions/netty.adoc[Netty] (camel-quarkus-netty) +
-`netty:protocol:host:port` | 0.4.0 | Socket level networking using TCP or UDP with the Netty 4.x library.
-
-| xref:extensions/netty-http.adoc[Netty HTTP] (camel-quarkus-netty-http) +
-`netty-http:protocol:host:port/path` | 0.2.0 | Netty HTTP server and client using the Netty 4.x library.
-
-| link:https://camel.apache.org/components/latest/olingo4-component.html[Olingo4] (camel-quarkus-olingo4) +
-`olingo4:apiName/methodName` | 1.0.0-M4 | Communicates with OData 4.0 services using Apache Olingo OData API.
-
-| link:https://camel.apache.org/components/latest/paho-component.html[Paho] (camel-quarkus-paho) +
-`paho:topic` | 0.2.0 | Component for communicating with MQTT message brokers using Eclipse Paho MQTT Client.
-
-| link:https://camel.apache.org/components/latest/pdf-component.html[PDF] (camel-quarkus-pdf) +
-`pdf:operation` | 0.3.1 | The pdf components provides the ability to create, modify or extract content from PDF documents.
-
-| xref:extensions/platform-http.adoc[Platform HTTP] (camel-quarkus-platform-http) +
-`platform-http:path` | 0.3.0 | HTTP service leveraging existing runtime platform HTTP server
-
-| link:https://camel.apache.org/components/latest/reactive-streams-component.html[Reactive Streams] (camel-quarkus-reactive-streams) +
-`reactive-streams:stream` | 1.0.0-M3 | Reactive Camel using reactive streams
-
-| link:https://camel.apache.org/components/latest/ref-component.html[Ref] (camel-quarkus-ref) +
-`ref:name` | 1.0.0-M5 | The ref component is used for lookup of existing endpoints bound in the Registry.
-
-| link:https://camel.apache.org/components/latest/rest-component.html[REST] (camel-quarkus-rest) +
-`rest:method:path:uriTemplate` | 0.2.0 | The rest component is used for either hosting REST services (consumer) or calling external REST services (producer).
-
-| link:https://camel.apache.org/components/latest/rest-api-component.html[REST API] (camel-quarkus-rest) +
-`rest-api:path/contextIdPattern` | 0.2.0 | The rest-api component is used for providing Swagger API of the REST services which has been defined using the rest-dsl in Camel.
-
-| link:https://camel.apache.org/components/latest/salesforce-component.html[Salesforce] (camel-quarkus-salesforce) +
-`salesforce:operationName:topicName` | 0.2.0 | The salesforce component is used for integrating Camel with the massive Salesforce API.
-
-| link:https://camel.apache.org/components/latest/scheduler-component.html[Scheduler] (camel-quarkus-scheduler) +
-`scheduler:name` | 0.4.0 | The scheduler component is used for generating message exchanges when a scheduler fires.
-
-| link:https://camel.apache.org/components/latest/seda-component.html[SEDA] (camel-quarkus-seda) +
-`seda:name` | 1.0.0-M1 | The seda component provides asynchronous call to another endpoint from any CamelContext in the same JVM.
-
-| link:https://camel.apache.org/components/latest/servlet-component.html[Servlet] (camel-quarkus-servlet) +
-`servlet:contextPath` | 0.2.0 | To use a HTTP Servlet as entry for Camel routes when running in a servlet container.
-
-| link:https://camel.apache.org/components/latest/sftp-component.html[SFTP] (camel-quarkus-ftp) +
-`sftp:host:port/directoryName` | 1.0.0-M1 | The \sftp (FTP over SSH) component is used for uploading or downloading files from SFTP servers.
-
-| link:https://camel.apache.org/components/latest/sjms-component.html[Simple JMS] (camel-quarkus-sjms) +
-`sjms:destinationType:destinationName` | 1.0.0-M1 | The sjms component (simple jms) allows messages to be sent to (or consumed from) a JMS Queue or Topic (uses JMS 1.x API).
-
-| link:https://camel.apache.org/components/latest/sjms-batch-component.html[Simple JMS Batch] (camel-quarkus-sjms) +
-`sjms-batch:destinationName` | 1.0.0-M1 | The sjms-batch component is a specialized for highly performant, transactional batch consumption from a JMS queue.
-
-| link:https://camel.apache.org/components/latest/sjms2-component.html[Simple JMS2] (camel-quarkus-sjms2) +
-`sjms2:destinationType:destinationName` | 1.0.0-M1 | The sjms2 component (simple jms) allows messages to be sent to (or consumed from) a JMS Queue or Topic (uses JMS 2.x API).
-
-| link:https://camel.apache.org/components/latest/slack-component.html[Slack] (camel-quarkus-slack) +
-`slack:channel` | 0.3.0 | The slack component allows you to send messages to Slack.
-
-| xref:extensions/sql.adoc[SQL] (camel-quarkus-sql) +
-`sql:query` | 1.0.0-M2 | The sql component allows you to work with databases using JDBC SQL queries.
-
-| xref:extensions/sql.adoc[SQL Stored Procedure] (camel-quarkus-sql) +
-`sql-stored:template` | 1.0.0-M2 | The sql component allows you to work with databases using JDBC Stored Procedure queries.
-
-| xref:extensions/stream.adoc[Stream] (camel-quarkus-stream) +
-`stream:kind` | 1.0.0-M4 | The stream: component provides access to the system-in, system-out and system-err streams as well as allowing streaming of file.
-
-| link:https://camel.apache.org/components/latest/telegram-component.html[Telegram] (camel-quarkus-telegram) +
-`telegram:type` | 1.0.0-M4 | The telegram component provides access to the Telegram Bot API.
-
-| link:https://camel.apache.org/components/latest/timer-component.html[Timer] (camel-quarkus-timer) +
-`timer:timerName` | 0.2.0 | The timer component is used for generating message exchanges when a timer fires.
-
-| link:https://camel.apache.org/components/latest/twitter-directmessage-component.html[Twitter Direct Message] (camel-quarkus-twitter) +
-`twitter-directmessage:user` | 0.2.0 | The Twitter Direct Message Component consumes/produces user's direct messages.
-
-| link:https://camel.apache.org/components/latest/twitter-search-component.html[Twitter Search] (camel-quarkus-twitter) +
-`twitter-search:keywords` | 0.2.0 | The Twitter Search component consumes search results.
-
-| link:https://camel.apache.org/components/latest/twitter-timeline-component.html[Twitter Timeline] (camel-quarkus-twitter) +
-`twitter-timeline:timelineType` | 0.2.0 | The Twitter Timeline component consumes twitter timeline or update the status of specific user.
-
-| link:https://camel.apache.org/components/latest/validator-component.html[Validator] (camel-quarkus-validator) +
-`validator:resourceUri` | 0.4.0 | Validates the payload of a message using XML Schema and JAXP Validation.
-
-| link:https://camel.apache.org/components/latest/vm-component.html[VM] (camel-quarkus-vm) +
-`vm:name` | 0.3.0 | The vm component provides asynchronous call to another endpoint from the same CamelContext.
-
-| xref:extensions/xslt.adoc[XSLT] (camel-quarkus-xslt) +
-`xslt:resourceUri` | 0.4.0 | Transforms the message using a XSLT template.
-
-|===
-// components: END
-
-
-== Camel Data Formats
-
-// dataformats: START
-Number of Camel data formats: 24 in 19 JAR artifacts (0 deprecated)
-
-[width="100%",cols="4,1,5",options="header"]
-|===
-| Data Format | Since | Description
-
-| link:https://camel.apache.org/components/latest/base64-dataformat.html[Base64] (camel-quarkus-base64) | 1.0.0-M1 | The Base64 data format is used for base64 encoding and decoding.
-
-| link:https://camel.apache.org/components/latest/bindy-dataformat.html[Bindy CSV] (camel-quarkus-bindy) | 1.0.0-M4 | The Bindy data format is used for working with flat payloads (such as CSV, delimited, fixed length formats, or FIX messages).
-
-| link:https://camel.apache.org/components/latest/bindy-dataformat.html[Bindy Fixed Length] (camel-quarkus-bindy) | 1.0.0-M4 | The Bindy data format is used for working with flat payloads (such as CSV, delimited, fixed length formats, or FIX messages).
-
-| link:https://camel.apache.org/components/latest/bindy-dataformat.html[Bindy Key Value Pair] (camel-quarkus-bindy) | 1.0.0-M4 | The Bindy data format is used for working with flat payloads (such as CSV, delimited, fixed length formats, or FIX messages).
-
-| link:https://camel.apache.org/components/latest/csv-dataformat.html[CSV] (camel-quarkus-csv) | 0.2.0 | The CSV data format is used for handling CSV payloads.
-
-| xref:extensions/fhir.adoc[FHIR JSon] (camel-quarkus-fhir) | 0.3.0 | The FHIR JSon data format is used to marshall/unmarshall to/from FHIR objects to/from JSON.
-
-| xref:extensions/fhir.adoc[FHIR XML] (camel-quarkus-fhir) | 0.3.0 | The FHIR XML data format is used to marshall/unmarshall from/to FHIR objects to/from XML.
-
-| link:https://camel.apache.org/components/latest/gzipdeflater-dataformat.html[GZip Deflater] (camel-quarkus-zip-deflater) | 1.0.0-M4 | The GZip data format is a message compression and de-compression format (which works with the popular gzip/gunzip tools).
-
-| link:https://camel.apache.org/components/latest/ical-dataformat.html[iCal] (camel-quarkus-ical) | 1.0.0-M5 | The iCal dataformat is used for working with iCalendar messages.
-
-| link:https://camel.apache.org/components/latest/jacksonxml-dataformat.html[JacksonXML] (camel-quarkus-jacksonxml) | 1.0.0-M5 | JacksonXML data format is used for unmarshal a XML payload to POJO or to marshal POJO back to XML payload.
-
-| link:https://camel.apache.org/components/latest/jaxb-dataformat.html[JAXB] (camel-quarkus-jaxb) | 1.0.0-M5 | JAXB data format uses the JAXB2 XML marshalling standard to unmarshal an XML payload into Java objects or to marshal Java objects into an XML payload.
-
-| link:https://camel.apache.org/components/latest/json-gson-dataformat.html[JSon GSon] (camel-quarkus-gson) | 1.0.0-M4 | JSon data format is used for unmarshal a JSon payload to POJO or to marshal POJO back to JSon payload.
-
-| link:https://camel.apache.org/components/latest/json-jackson-dataformat.html[JSon Jackson] (camel-quarkus-jackson) | 0.3.0 | JSon data format is used for unmarshal a JSon payload to POJO or to marshal POJO back to JSon payload.
-
-| link:https://camel.apache.org/components/latest/json-johnzon-dataformat.html[JSon Johnzon] (camel-quarkus-johnzon) | 1.0.0-M5 | JSon data format is used for unmarshal a JSon payload to POJO or to marshal POJO back to JSon payload.
-
-| link:https://camel.apache.org/components/latest/json-xstream-dataformat.html[JSon XStream] (camel-quarkus-xstream) | 1.0.0-M5 | JSon data format is used for unmarshal a JSon payload to POJO or to marshal POJO back to JSon payload.
-
-| link:https://camel.apache.org/components/latest/lzf-dataformat.html[LZF Deflate Compression] (camel-quarkus-lzf) | 1.0.0-M4 | The LZF data format is a message compression and de-compression format (uses the LZF deflate algorithm).
-
-| link:https://camel.apache.org/components/latest/mime-multipart-dataformat.html[MIME Multipart] (camel-quarkus-mail) | 0.2.0 | The MIME Multipart data format is used for marshalling Camel messages with attachments into MIME-Multipart message, and vise-versa.
-
-| link:https://camel.apache.org/components/latest/soapjaxb-dataformat.html[SOAP] (camel-quarkus-soap) | 1.0.0-M5 | SOAP is a data format which uses JAXB2 and JAX-WS annotations to marshal and unmarshal SOAP payloads.
-
-| link:https://camel.apache.org/components/latest/tarfile-dataformat.html[Tar File] (camel-quarkus-tarfile) | 0.3.0 | The Tar File data format is a message compression and de-compression format of tar files.
-
-| link:https://camel.apache.org/components/latest/tidyMarkup-dataformat.html[TidyMarkup] (camel-quarkus-tagsoup) | 1.0.0-M1 | TidyMarkup data format is used for parsing HTML and return it as pretty well-formed HTML.
-
-| link:https://camel.apache.org/components/latest/xstream-dataformat.html[XStream] (camel-quarkus-xstream) | 1.0.0-M5 | XStream data format is used for unmarshal a XML payload to POJO or to marshal POJO back to XML payload.
-
-| link:https://camel.apache.org/components/latest/yaml-snakeyaml-dataformat.html[YAML SnakeYAML] (camel-quarkus-snakeyaml) | 0.4.0 | YAML is a data format to marshal and unmarshal Java objects to and from YAML.
-
-| link:https://camel.apache.org/components/latest/zipdeflater-dataformat.html[Zip Deflate Compression] (camel-quarkus-zip-deflater) | 1.0.0-M4 | Zip Deflate Compression data format is a message compression and de-compression format (not zip files).
-
-| link:https://camel.apache.org/components/latest/zipfile-dataformat.html[Zip File] (camel-quarkus-zipfile) | 0.2.0 | The Zip File data format is a message compression and de-compression format of zip files.
-|===
-// dataformats: END
-
-
-== Camel Languages
-
-// languages: START
-Number of Camel languages: 11 in 5 JAR artifacts (0 deprecated)
-
-[width="100%",cols="4,1,5",options="header"]
-|===
-| Language | Since | Description
-
-| link:https://camel.apache.org/components/latest/bean-language.html[Bean method] (camel-quarkus-bean) | 0.2.0 | To use a Java bean (aka method call) in Camel expressions or predicates.
-
-| link:https://camel.apache.org/components/latest/constant-language.html[Constant] (camel-quarkus-core) | 0.2.0 | To use a constant value in Camel expressions or predicates. Important: this is a fixed constant value that is only set once during starting up the route, do not use this if you want dynamic values during routing.
-
-| link:https://camel.apache.org/components/latest/exchangeProperty-language.html[ExchangeProperty] (camel-quarkus-core) | 0.2.0 | To use a Camel Exchange property in expressions or predicates.
-
-| link:https://camel.apache.org/components/latest/file-language.html[File] (camel-quarkus-core) | 0.2.0 | For expressions and predicates using the file/simple language.
-
-| link:https://camel.apache.org/components/latest/header-language.html[Header] (camel-quarkus-core) | 0.2.0 | To use a Camel Message header in expressions or predicates.
-
-| link:https://camel.apache.org/components/latest/jsonpath-language.html[JsonPath] (camel-quarkus-jsonpath) | 1.0.0-M3 | To use JsonPath in Camel expressions or predicates.
-
-| link:https://camel.apache.org/components/latest/ref-language.html[Ref] (camel-quarkus-core) | 0.2.0 | Reference to an existing Camel expression or predicate, which is looked up from the Camel registry.
-
-| link:https://camel.apache.org/components/latest/simple-language.html[Simple] (camel-quarkus-core) | 0.2.0 | To use Camels built-in Simple language in Camel expressions or predicates.
-
-| link:https://camel.apache.org/components/latest/tokenize-language.html[Tokenize] (camel-quarkus-core) | 0.2.0 | To use Camel message body or header with a tokenizer in Camel expressions or predicates.
-
-| link:https://camel.apache.org/components/latest/xtokenize-language.html[XML Tokenize] (camel-quarkus-xml-jaxp) | 1.0.0-M5 | To use Camel message body or header with a XML tokenizer in Camel expressions or predicates.
-
-| link:https://camel.apache.org/components/latest/xpath-language.html[XPath] (camel-quarkus-xpath) | 1.0.0-M4 | To use XPath (XML) in Camel expressions or predicates.
-|===
-// languages: END
-
-
-== Miscellaneous Extensions
-
-// others: START
-Number of miscellaneous extensions: 12 in 12 JAR artifacts (0 deprecated)
-
-[width="100%",cols="4,1,5",options="header"]
-|===
-| Extension | Since | Description
-
-| (camel-quarkus-attachments) | 0.3.0 | Java Attachments support for Camel Message
-
-| (camel-quarkus-caffeine-lrucache) | 1.0.0-M5 | Provides an implementation of the LRUCacheFactory based on Caffeine
-
-| (camel-quarkus-core-cloud) | 0.2.0 | The Camel Quarkus core cloud module
-
-| (camel-quarkus-endpointdsl) | 1.0.0-M3 | camel-quarkus-endpointdsl
-
-| (camel-quarkus-hystrix) | 1.0.0-M1 | Circuit Breaker EIP using Netflix Hystrix
-
-| (camel-quarkus-kotlin) | 1.0.0-M3 | camel-quarkus-kotlin
-
-| xref:extensions/microprofile-health.adoc[camel-quarkus-microprofile-health]  | 0.3.0 | Bridging Eclipse MicroProfile Health with Camel health checks
-
-| xref:extensions/opentracing.adoc[camel-quarkus-opentracing]  | 0.3.0 | Distributed tracing using OpenTracing
-
-| xref:extensions/qute.adoc[camel-quarkus-qute]  | 1.0.0-M6 | Camel component uses Quarkus Qute as the templating engine
-
-| (camel-quarkus-reactive-executor) | 0.3.0 | Reactive Executor for camel-core using Vert.x
-
-| (camel-quarkus-xml-io) | 1.0.0-M5 | An XML stack for parsing XML route definitions. A fast an light weight alternative to camel-quarkus-xml-jaxp
-
-| (camel-quarkus-xml-jaxb) | 1.0.0-M5 | An XML stack for parsing XML route definitions. A legacy alternative to the fast an light weight camel-quarkus-xml-io
-|===
-// others: END
-
diff --git a/pom.xml b/pom.xml
index 06a708a..010682e 100644
--- a/pom.xml
+++ b/pom.xml
@@ -42,8 +42,10 @@
 
         <ahc.version>2.10.4</ahc.version>
         <camel.version>3.1.0</camel.version>
+        <freemarker.version>2.3.30</freemarker.version>
         <google-http-client.version>1.22.0</google-http-client.version>
         <guava.version>26.0-jre</guava.version>
+        <gson.version>2.8.5</gson.version>
         <hapi.version>4.1.0</hapi.version>
         <quarkus.version>1.3.0.Final</quarkus.version>
         <httpmime.version>4.1.3</httpmime.version>
@@ -88,6 +90,7 @@
         <!-- NOTE: We pin to this version due to https://github.com/apache/camel-quarkus/issues/723 -->
         <maven-surefire-plugin.version>2.22.2</maven-surefire-plugin.version>
         <cq-plugin.version>0.0.1</cq-plugin.version>
+        <rpkgtests-maven-plugin.version>0.6.0</rpkgtests-maven-plugin.version>
 
         <!-- maven-release-plugin -->
         <tagNameFormat>@{project.version}</tagNameFormat>
@@ -255,6 +258,7 @@
                         <excludes>
                             <exclude>**/*.adoc</exclude>
                             <exclude>**/*.csv</exclude>
+                            <exclude>**/*.ftl</exclude>
                             <exclude>**/*.graphql</exclude>
                             <exclude>**/*.ics</exclude>
                             <exclude>**/*.lock</exclude>
diff --git a/tooling/package-maven-plugin/pom.xml b/tooling/package-maven-plugin/pom.xml
index d8d07f2..8bd0303 100644
--- a/tooling/package-maven-plugin/pom.xml
+++ b/tooling/package-maven-plugin/pom.xml
@@ -22,8 +22,9 @@
     <modelVersion>4.0.0</modelVersion>
     <parent>
         <groupId>org.apache.camel.quarkus</groupId>
-        <artifactId>camel-quarkus-tooling</artifactId>
+        <artifactId>camel-quarkus-build-parent</artifactId>
         <version>1.1.0-SNAPSHOT</version>
+        <relativePath>../../poms/build-parent/pom.xml</relativePath>
     </parent>
 
     <artifactId>camel-quarkus-package-maven-plugin</artifactId>
@@ -32,110 +33,59 @@
     <name>Camel Quarkus :: Tooling :: Maven :: Package Maven Plugin</name>
     <description>Maven plugin to help package Camel quarkus components and plugins</description>
 
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>com.google.code.gson</groupId>
+                <artifactId>gson</artifactId>
+                <version>${gson.version}</version>
+            </dependency>
+            <dependency>
+                <groupId>org.freemarker</groupId>
+                <artifactId>freemarker</artifactId>
+                <version>${freemarker.version}</version>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
     <dependencies>
+
         <dependency>
-            <groupId>org.apache.camel</groupId>
-            <artifactId>camel-package-maven-plugin</artifactId>
-            <version>${camel.version}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.codehaus.plexus</groupId>
-                    <artifactId>plexus-component-annotations</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.asciidoctor</groupId>
-                    <artifactId>asciidoctorj</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.mvel</groupId>
-                    <artifactId>mvel2</artifactId>
-                </exclusion>
-            </exclusions>
+            <groupId>com.google.code.gson</groupId>
+            <artifactId>gson</artifactId>
         </dependency>
+
         <dependency>
             <groupId>org.apache.camel</groupId>
-            <artifactId>camel-support</artifactId>
-            <version>${camel.version}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-            </exclusions>
+            <artifactId>camel-catalog</artifactId>
         </dependency>
+
         <dependency>
-            <groupId>org.apache.camel</groupId>
-            <artifactId>camel-util</artifactId>
-            <version>${camel.version}</version>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.slf4j</groupId>
-                    <artifactId>slf4j-api</artifactId>
-                </exclusion>
-            </exclusions>
+            <groupId>org.freemarker</groupId>
+            <artifactId>freemarker</artifactId>
         </dependency>
+
         <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-core</artifactId>
+            <scope>provided</scope>
             <exclusions>
                 <exclusion>
                     <groupId>org.codehaus.plexus</groupId>
                     <artifactId>plexus-classworlds</artifactId>
                 </exclusion>
-                <exclusion>
-                    <groupId>org.codehaus.plexus</groupId>
-                    <artifactId>plexus-component-annotations</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>commons-io</groupId>
-                    <artifactId>commons-io</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>org.apache.commons</groupId>
-                    <artifactId>commons-lang3</artifactId>
-                </exclusion>
-                <exclusion>
-                    <groupId>com.google.guava</groupId>
-                    <artifactId>guava</artifactId>
-                </exclusion>
             </exclusions>
         </dependency>
         <dependency>
-            <groupId>org.apache.maven</groupId>
-            <artifactId>maven-artifact</artifactId>
-            <exclusions>
-                <exclusion>
-                    <groupId>org.apache.commons</groupId>
-                    <artifactId>commons-lang3</artifactId>
-                </exclusion>
-            </exclusions>
-        </dependency>
-        <dependency>
-            <groupId>org.apache.maven</groupId>
-            <artifactId>maven-plugin-api</artifactId>
-        </dependency>
-        <dependency>
             <groupId>org.apache.maven.plugin-tools</groupId>
             <artifactId>maven-plugin-annotations</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.codehaus.plexus</groupId>
-            <artifactId>plexus-utils</artifactId>
-        </dependency>
-        <dependency>
-            <groupId>org.sonatype.plexus</groupId>
-            <artifactId>plexus-build-api</artifactId>
+            <scope>provided</scope>
         </dependency>
 
         <dependency>
-            <groupId>org.apache.camel</groupId>
-            <artifactId>camel-util-json</artifactId>
-            <version>${camel.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>org.mvel</groupId>
-            <artifactId>mvel2</artifactId>
-            <version>${mvel.version}</version>
+            <groupId>org.junit.jupiter</groupId>
+            <artifactId>junit-jupiter-api</artifactId>
+            <scope>test</scope>
         </dependency>
 
     </dependencies>
diff --git a/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CqCatalog.java b/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CqCatalog.java
new file mode 100644
index 0000000..3fdbf73
--- /dev/null
+++ b/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CqCatalog.java
@@ -0,0 +1,462 @@
+/*
+ * 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.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
+import org.apache.camel.catalog.CamelCatalog;
+import org.apache.camel.catalog.DefaultCamelCatalog;
+import org.apache.camel.catalog.DefaultVersionManager;
+import org.apache.camel.catalog.RuntimeProvider;
+import org.apache.camel.catalog.impl.CatalogHelper;
+import org.apache.camel.tooling.model.BaseModel;
+import org.apache.camel.tooling.model.ComponentModel;
+import org.apache.camel.tooling.model.DataFormatModel;
+import org.apache.camel.tooling.model.LanguageModel;
+import org.apache.camel.tooling.model.OtherModel;
+
+public class CqCatalog {
+
+    private final DefaultCamelCatalog catalog;
+
+    public CqCatalog(Path baseDir) {
+        super();
+        final DefaultCamelCatalog c = new DefaultCamelCatalog(true);
+        c.setRuntimeProvider(new CqRuntimeProvider(c));
+        c.setVersionManager(new CqVersionManager(c, baseDir));
+        this.catalog = c;
+    }
+
+    public CqCatalog() {
+        super();
+        this.catalog = new DefaultCamelCatalog(true);
+    }
+
+    public String toCamelArtifactIdBase(String cqArtifactIdBase) {
+        if ("core".equals(cqArtifactIdBase)) {
+            return "base";
+        } else if ("reactive-executor".equals(cqArtifactIdBase)) {
+            return "reactive-executor-vertx";
+        } else {
+            return cqArtifactIdBase;
+        }
+    }
+
+    public List<WrappedModel> filterModels(String artifactIdBase) {
+        artifactIdBase = toCamelArtifactIdBase(artifactIdBase);
+        final String camelArtifactId = "camel-" + artifactIdBase;
+        return Stream.of(Kind.values())
+                .flatMap(kind -> kind.all(this))
+                .filter(wrappedModel -> wrappedModel.getArtifactId().equals(camelArtifactId))
+                .collect(Collectors.toList());
+    }
+
+    enum Kind {
+        component() {
+            @Override
+            public Optional<WrappedModel> load(CqCatalog catalog, String name) {
+                final BaseModel<?> delegate = catalog.catalog.componentModel(name);
+                return Optional.ofNullable(delegate == null ? null : new WrappedModel(catalog, this, delegate));
+            }
+
+            @Override
+            public String getArtifactId(BaseModel<?> delegate) {
+                return ((ComponentModel) delegate).getArtifactId();
+            }
+
+            @Override
+            protected Stream<WrappedModel> all(CqCatalog catalog) {
+                return catalog.catalog.findComponentNames().stream()
+                        .map(name -> new WrappedModel(catalog, this, catalog.catalog.componentModel(name)));
+            }
+
+            protected String getScheme(BaseModel<?> delegate) {
+                return ((ComponentModel) delegate).getScheme();
+            }
+
+            @Override
+            protected String getJson(CqCatalog catalog, BaseModel<?> delegate) {
+                return catalog.catalog.componentJSonSchema(getScheme(delegate));
+            }
+        },
+        language() {
+            @Override
+            public Optional<WrappedModel> load(CqCatalog catalog, String name) {
+                final BaseModel<?> delegate = catalog.catalog.languageModel(name);
+                return Optional.ofNullable(delegate == null ? null : new WrappedModel(catalog, this, delegate));
+            }
+
+            @Override
+            public String getArtifactId(BaseModel<?> delegate) {
+                return ((LanguageModel) delegate).getArtifactId();
+            }
+
+            @Override
+            protected Stream<WrappedModel> all(CqCatalog catalog) {
+                return catalog.catalog.findLanguageNames().stream()
+                        .map(name -> new WrappedModel(catalog, this, catalog.catalog.languageModel(name)));
+            }
+
+            @Override
+            protected String getJson(CqCatalog catalog, BaseModel<?> delegate) {
+                return catalog.catalog.languageJSonSchema(getScheme(delegate));
+            }
+        },
+        dataformat() {
+            @Override
+            public Optional<WrappedModel> load(CqCatalog catalog, String name) {
+                final BaseModel<?> delegate = catalog.catalog.dataFormatModel(name);
+                return Optional.ofNullable(delegate == null ? null : new WrappedModel(catalog, this, delegate));
+            }
+
+            @Override
+            public String getArtifactId(BaseModel<?> delegate) {
+                return ((DataFormatModel) delegate).getArtifactId();
+            }
+
+            @Override
+            protected Stream<WrappedModel> all(CqCatalog catalog) {
+                return catalog.catalog.findDataFormatNames().stream()
+                        .map(name -> new WrappedModel(catalog, this, catalog.catalog.dataFormatModel(name)));
+            }
+
+            @Override
+            protected String getJson(CqCatalog catalog, BaseModel<?> delegate) {
+                return catalog.catalog.dataFormatJSonSchema(getScheme(delegate));
+            }
+        },
+        other() {
+            @Override
+            public Optional<WrappedModel> load(CqCatalog catalog, String name) {
+                final BaseModel<?> delegate = catalog.catalog.otherModel(name);
+                return Optional.ofNullable(delegate == null ? null : new WrappedModel(catalog, this, delegate));
+            }
+
+            @Override
+            public String getArtifactId(BaseModel<?> delegate) {
+                return ((OtherModel) delegate).getArtifactId();
+            }
+
+            @Override
+            protected Stream<WrappedModel> all(CqCatalog catalog) {
+                return catalog.catalog.findOtherNames().stream()
+                        .map(name -> new WrappedModel(catalog, this, catalog.catalog.otherModel(name)));
+            }
+
+            @Override
+            protected String getJson(CqCatalog catalog, BaseModel<?> delegate) {
+                return catalog.catalog.otherJSonSchema(getScheme(delegate));
+            }
+        };
+
+        public abstract Optional<WrappedModel> load(CqCatalog catalog, String name);
+
+        protected String getScheme(BaseModel<?> delegate) {
+            return delegate.getName();
+        }
+
+        protected abstract Stream<WrappedModel> all(CqCatalog catalog);
+
+        protected abstract String getJson(CqCatalog catalog, BaseModel<?> delegate);
+
+        public abstract String getArtifactId(BaseModel<?> delegate);
+
+        public String getPluralName() {
+            return name() + "s";
+        }
+    }
+
+    public static class WrappedModel implements Comparable<WrappedModel> {
+        final BaseModel<?> delegate;
+        final Kind kind;
+        final CqCatalog catalog;
+        final String supportLevel;
+        final String target;
+
+        public WrappedModel(CqCatalog catalog, Kind kind, BaseModel<?> delegate) {
+            super();
+            this.catalog = catalog;
+            this.kind = kind;
+            this.delegate = delegate;
+            final JsonObject json = getJson().getAsJsonObject(kind.name());
+            String sl = null;
+            try {
+                sl = json.get("supportLevel").getAsString();
+            } catch (Exception ignored) {
+            }
+            this.supportLevel = sl;
+            String t = null;
+            try {
+                t = json.get("compilationTarget").getAsString();
+            } catch (Exception ignored) {
+            }
+            this.target = t;
+        }
+
+        public String getArtifactId() {
+            return kind.getArtifactId(delegate);
+        }
+
+        public String getArtifactIdBase() {
+            final String artifactId = getArtifactId();
+            if (artifactId.startsWith("camel-quarkus-")) {
+                return artifactId.substring("camel-quarkus-".length());
+            } else if (artifactId.startsWith("camel-")) {
+                return artifactId.substring("camel-".length());
+            }
+            throw new IllegalStateException(
+                    "Unexpected artifactId " + artifactId + "; expected one starting with camel-quarkus- or camel-");
+        }
+
+        public String getKind() {
+            return kind.name();
+        }
+
+        public boolean isFirstScheme() {
+            switch (kind) {
+            case component:
+                final String altSchemes = ((ComponentModel) delegate).getAlternativeSchemes();
+                if (altSchemes == null || altSchemes.isEmpty()) {
+                    return true;
+                } else {
+                    final String scheme = getScheme();
+                    return altSchemes.equals(scheme) || altSchemes.startsWith(scheme + ",");
+                }
+            default:
+                return true;
+            }
+        }
+
+        public String getScheme() {
+            return kind.getScheme(delegate);
+        }
+
+        public String getSyntax() {
+            switch (kind) {
+            case component:
+                return ((ComponentModel) delegate).getSyntax();
+            default:
+                throw new UnsupportedOperationException(kind.getPluralName() + " do not have syntax");
+            }
+        }
+
+        public String getFirstVersion() {
+            return delegate.getFirstVersion();
+        }
+
+        public String getTitle() {
+            return delegate.getTitle();
+        }
+
+        public String getDescription() {
+            return delegate.getDescription();
+        }
+
+        public boolean isDeprecated() {
+            return delegate.isDeprecated();
+        }
+
+        public JsonObject getJson() {
+            final JsonParser jsonParser = new JsonParser();
+            return (JsonObject) jsonParser.parse(kind.getJson(catalog, delegate));
+        }
+
+        @Override
+        public String toString() {
+            return "WrappedModel [scheme=" + getScheme() + ", kind=" + getKind() + "]";
+        }
+
+        @Override
+        public int compareTo(WrappedModel other) {
+            return this.getTitle().compareToIgnoreCase(other.getTitle());
+        }
+
+        public String getSupportLevel() {
+            return supportLevel;
+        }
+
+        public String getTarget() {
+            return target;
+        }
+
+    }
+
+    static class CqVersionManager extends DefaultVersionManager {
+        private final Path baseDir;
+
+        public CqVersionManager(CamelCatalog camelCatalog, Path baseDir) {
+            super(camelCatalog);
+            this.baseDir = baseDir;
+        }
+
+        @Override
+        public InputStream getResourceAsStream(String name) {
+            try {
+                return Files.newInputStream(baseDir.resolve(name));
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        }
+
+    }
+
+    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 CamelCatalog camelCatalog;
+
+        public CqRuntimeProvider(CamelCatalog camelCatalog) {
+            this.camelCatalog = camelCatalog;
+        }
+
+        @Override
+        public CamelCatalog getCamelCatalog() {
+            return camelCatalog;
+        }
+
+        @Override
+        public void setCamelCatalog(CamelCatalog camelCatalog) {
+            this.camelCatalog = camelCatalog;
+        }
+
+        @Override
+        public String getProviderName() {
+            return "camel-quarkus";
+        }
+
+        @Override
+        public String getProviderGroupId() {
+            return "org.apache.camel.quarkus";
+        }
+
+        @Override
+        public String getProviderArtifactId() {
+            return "camel-quarkus-catalog";
+        }
+
+        @Override
+        public String getComponentJSonSchemaDirectory() {
+            return COMPONENT_DIR;
+        }
+
+        @Override
+        public String getDataFormatJSonSchemaDirectory() {
+            return DATAFORMAT_DIR;
+        }
+
+        @Override
+        public String getLanguageJSonSchemaDirectory() {
+            return LANGUAGE_DIR;
+        }
+
+        @Override
+        public String getOtherJSonSchemaDirectory() {
+            return OTHER_DIR;
+        }
+
+        protected String getComponentsCatalog() {
+            return COMPONENTS_CATALOG;
+        }
+
+        protected String getDataFormatsCatalog() {
+            return DATA_FORMATS_CATALOG;
+        }
+
+        protected String getLanguageCatalog() {
+            return LANGUAGE_CATALOG;
+        }
+
+        protected String getOtherCatalog() {
+            return OTHER_CATALOG;
+        }
+
+        @Override
+        public List<String> findComponentNames() {
+            List<String> names = new ArrayList<>();
+            InputStream is = getCamelCatalog().getVersionManager().getResourceAsStream(getComponentsCatalog());
+            if (is != null) {
+                try {
+                    CatalogHelper.loadLines(is, names);
+                } catch (IOException e) {
+                    // ignore
+                }
+            }
+            return names;
+        }
+
+        @Override
+        public List<String> findDataFormatNames() {
+            List<String> names = new ArrayList<>();
+            InputStream is = getCamelCatalog().getVersionManager().getResourceAsStream(getDataFormatsCatalog());
+            if (is != null) {
+                try {
+                    CatalogHelper.loadLines(is, names);
+                } catch (IOException e) {
+                    // ignore
+                }
+            }
+            return names;
+        }
+
+        @Override
+        public List<String> findLanguageNames() {
+            List<String> names = new ArrayList<>();
+            InputStream is = getCamelCatalog().getVersionManager().getResourceAsStream(getLanguageCatalog());
+            if (is != null) {
+                try {
+                    CatalogHelper.loadLines(is, names);
+                } catch (IOException e) {
+                    // ignore
+                }
+            }
+            return names;
+        }
+
+        @Override
+        public List<String> findOtherNames() {
+            List<String> names = new ArrayList<>();
+            InputStream is = getCamelCatalog().getVersionManager().getResourceAsStream(getOtherCatalog());
+            if (is != null) {
+                try {
+                    CatalogHelper.loadLines(is, names);
+                } catch (IOException e) {
+                    // ignore
+                }
+            }
+            return names;
+        }
+    }
+
+}
diff --git a/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CqUtils.java b/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CqUtils.java
new file mode 100644
index 0000000..c8cb31f
--- /dev/null
+++ b/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/CqUtils.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.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.util.stream.Stream;
+
+import freemarker.cache.ClassTemplateLoader;
+import freemarker.cache.FileTemplateLoader;
+import freemarker.cache.MultiTemplateLoader;
+import freemarker.cache.TemplateLoader;
+import freemarker.template.Configuration;
+import freemarker.template.TemplateExceptionHandler;
+import org.apache.maven.model.Model;
+
+public class CqUtils {
+    public static final String CLASSPATH_PREFIX = "classpath:";
+
+    public static final String FILE_PREFIX = "file:";
+
+    static TemplateLoader createTemplateLoader(Path basePath, String defaultUriBase, String templatesUriBase) {
+        final TemplateLoader defaultLoader = new ClassTemplateLoader(CqUtils.class,
+                defaultUriBase.substring(CLASSPATH_PREFIX.length()));
+        if (defaultUriBase.equals(templatesUriBase)) {
+            return defaultLoader;
+        } else if (templatesUriBase.startsWith(CLASSPATH_PREFIX)) {
+            return new MultiTemplateLoader( //
+                    new TemplateLoader[] { //
+                            new ClassTemplateLoader(CqUtils.class,
+                                    templatesUriBase.substring(CLASSPATH_PREFIX.length())), //
+                            defaultLoader //
+                    });
+        } else if (templatesUriBase.startsWith(FILE_PREFIX)) {
+            final Path resolvedTemplatesDir = basePath.resolve(templatesUriBase.substring(FILE_PREFIX.length()));
+            try {
+                return new MultiTemplateLoader( //
+                        new TemplateLoader[] { //
+                                new FileTemplateLoader(resolvedTemplatesDir.toFile()),
+                                defaultLoader //
+                        });
+            } catch (IOException e) {
+                throw new RuntimeException(e);
+            }
+        } else {
+            throw new IllegalStateException(String.format(
+                    "Cannot handle templatesUriBase '%s'; only value starting with '%s' or '%s' are supported",
+                    templatesUriBase, CLASSPATH_PREFIX, FILE_PREFIX));
+        }
+    }
+
+    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);
+        }
+    }
+
+    public static Configuration getTemplateConfig(Path basePath, String defaultUriBase, String templatesUriBase,
+            String encoding) {
+        final Configuration templateCfg = new Configuration(Configuration.VERSION_2_3_28);
+        templateCfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
+        templateCfg.setTemplateLoader(createTemplateLoader(basePath, defaultUriBase, templatesUriBase));
+        templateCfg.setDefaultEncoding(encoding);
+        templateCfg.setInterpolationSyntax(Configuration.SQUARE_BRACKET_INTERPOLATION_SYNTAX);
+        templateCfg.setTagSyntax(Configuration.SQUARE_BRACKET_TAG_SYNTAX);
+        return templateCfg;
+    }
+
+    static String getVersion(Model basePom) {
+        return basePom.getVersion() != null ? basePom.getVersion()
+                : basePom.getParent() != null && basePom.getParent().getVersion() != null
+                        ? basePom.getParent().getVersion()
+                        : null;
+    }
+
+}
diff --git a/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/ExtMvelHelper.java b/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/ExtMvelHelper.java
deleted file mode 100644
index 0b0f86e..0000000
--- a/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/ExtMvelHelper.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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;
-
-import org.apache.camel.maven.packaging.MvelHelper;
-import org.apache.camel.tooling.util.Strings;
-import org.apache.camel.tooling.model.ComponentModel;
-import org.apache.camel.tooling.model.DataFormatModel;
-import org.apache.camel.tooling.model.LanguageModel;
-
-public class ExtMvelHelper {
-
-    private final Path extensionsDocPath;
-
-    public ExtMvelHelper(Path extensionsDocPath) {
-        this.extensionsDocPath = extensionsDocPath;
-    }
-
-    public static String escape(final String raw) {
-        return MvelHelper.escape(raw);
-    }
-
-    public String getFirstVersionShort(Object model) {
-        return org.apache.camel.tooling.model.Strings.cutLastZeroDigit((String) invokeGetter(model, "getFirstVersion"));
-    }
-
-    public String getDocLink(Object model) {
-        if (localDocExists(model)) {
-            return getLocalDocLink(model);
-        } else if (model instanceof ComponentModel) {
-            return String.format("link:https://camel.apache.org/%s/latest/%s", "components",
-                    invokeGetter(model, "getScheme") + "-component.html");
-        } else if (model instanceof DataFormatModel) {
-            return String.format("link:https://camel.apache.org/%s/latest/%s", "components",
-                    invokeGetter(model, "getName") + "-dataformat.html");
-        } else if (model instanceof LanguageModel) {
-            return String.format("link:https://camel.apache.org/%s/latest/%s", "components",
-                    invokeGetter(model, "getName") + "-language.html");
-        } else {
-            return null;
-        }
-    }
-
-    private Object invokeGetter(Object model, String method) {
-        try {
-            return model.getClass().getMethod(method)
-                    .invoke(model);
-        } catch (Exception e) {
-            throw new RuntimeException("Unable to access " + method + " from " + model, e);
-        }
-    }
-
-    private boolean localDocExists(Object model) {
-        Path path = extensionsDocPath.resolve(getExtensionDocName(model));
-        return path.toFile().exists();
-    }
-
-    private String getLocalDocLink(Object model) {
-        return "xref:extensions/" + getExtensionDocName(model);
-    }
-
-    private String getExtensionDocName(Object model) {
-        return Strings.after((String) invokeGetter(model, "getArtifactId"), "camel-quarkus-") + ".adoc";
-    }
-}
diff --git a/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/JSonSchemaHelper.java b/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/JSonSchemaHelper.java
deleted file mode 100644
index 1b560d0..0000000
--- a/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/JSonSchemaHelper.java
+++ /dev/null
@@ -1,567 +0,0 @@
-/*
- * 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.ArrayList;
-import java.util.LinkedHashMap;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import org.apache.camel.util.json.JsonArray;
-import org.apache.camel.util.json.JsonObject;
-import org.apache.camel.util.json.Jsoner;
-
-/**
- * Used for parsing Camel components json meta-data descriptors.
- */
-public final class JSonSchemaHelper {
-
-    private static final String[] LOGGING_LEVELS = new String[]{"ERROR", "WARN", "INFO", "DEBUG", "TRACE", "OFF"};
-
-    private JSonSchemaHelper() {
-    }
-
-    /**
-     * Parses the camel-main json schema to split it into a list or rows, where each row contains key value pairs with the metadata
-     *
-     * @param json the main configuration json
-     * @return a list of all the rows, where each row is a set of key value pairs with metadata
-     * @throws RuntimeException is thrown if error parsing the json data
-     */
-    @SuppressWarnings("unchecked")
-    public static List<Map<String, String>> parseMainJsonSchema(String json) {
-        List<Map<String, String>> answer = new ArrayList<>();
-        if (json == null) {
-            return answer;
-        }
-
-        // convert into a List<Map<String, String>> structure which is expected as output from this parser
-        try {
-            JsonObject output = (JsonObject) Jsoner.deserialize(json);
-            for (String key : output.keySet()) {
-                JsonArray array = (JsonArray) output.get(key);
-                if (key.equals("properties")) {
-                    // flattern each entry in the row with name as they key, and its value as the content (its a map also)
-                    for (Object obj : array) {
-                        Map entry = (Map) obj;
-                        Map<String, String> newRow = new LinkedHashMap();
-                        newRow.putAll(entry);
-                        answer.add(newRow);
-                        String name = ((Map) obj).get("name").toString();
-                        // use naming style with camel case
-                        String lookupKey = dashToCamelCase(name);
-                        newRow.put("name", lookupKey);
-                        // its the java type
-                        String type = newRow.get("type");
-                        newRow.put("javaType", type);
-                        newRow.put("type", fromMainToType(type));
-                        // add known enums
-                        if ("org.apache.camel.LoggingLevel".equals(type)) {
-                            newRow.put("enum", "ERROR,WARN,INFO,DEBUG,TRACE,OFF");
-                        } else if ("org.apache.camel.ManagementStatisticsLevel".equals(type)) {
-                            newRow.put("enum", "Extended,Default,RoutesOnly,Off");
-                        } else if ("org.apache.camel.spi.RestBindingMode".equals(type)) {
-                            newRow.put("enum", "auto,off,json,xml,json_xml");
-                        } else if ("org.apache.camel.spi.RestHostNameResolver".equals(type)) {
-                            newRow.put("enum", "allLocalIp,localIp,localHostName");
-                        }
-                    }
-                }
-            }
-        } catch (Exception e) {
-            // wrap parsing exceptions as runtime
-            throw new RuntimeException("Cannot parse json", e);
-        }
-
-        return answer;
-    }
-
-    private static String fromMainToType(String type) {
-        if ("boolean".equals(type) || "java.lang.Boolean".equals(type)) {
-            return "boolean";
-        } else if ("int".equals(type) || "java.lang.Integer".equals(type)) {
-            return "integer";
-        } else if ("long".equals(type) || "java.lang.Long".equals(type)) {
-            return "integer";
-        } else if ("float".equals(type) || "java.lang.Float".equals(type)) {
-            return "number";
-        } else if ("double".equals(type) || "java.lang.Double".equals(type)) {
-            return "number";
-        } else if ("string".equals(type) || "java.lang.String".equals(type)) {
-            return "string";
-        } else {
-            return "object";
-        }
-    }
-
-    /**
-     * Parses the json schema to split it into a list or rows, where each row contains key value pairs with the metadata
-     *
-     * @param group the group to parse from such as <tt>component</tt>, <tt>componentProperties</tt>, or <tt>properties</tt>.
-     * @param json the json
-     * @return a list of all the rows, where each row is a set of key value pairs with metadata
-     * @throws RuntimeException is thrown if error parsing the json data
-     */
-    @SuppressWarnings("unchecked")
-    public static List<Map<String, String>> parseJsonSchema(String group, String json, boolean parseProperties) {
-        List<Map<String, String>> answer = new ArrayList<>();
-        if (json == null) {
-            return answer;
-        }
-
-        // convert into a List<Map<String, String>> structure which is expected as output from this parser
-        try {
-            JsonObject output = (JsonObject) Jsoner.deserialize(json);
-            for (String key : output.keySet()) {
-                Map row = output.getMap(key);
-                if (key.equals(group)) {
-                    if (parseProperties) {
-                        // flattern each entry in the row with name as they key, and its value as the content (its a map also)
-                        for (Object obj : row.entrySet()) {
-                            Map.Entry entry = (Map.Entry) obj;
-                            Map<String, String> newRow = new LinkedHashMap();
-                            newRow.put("name", entry.getKey().toString());
-
-                            Map newData = transformMap((Map) entry.getValue());
-                            newRow.putAll(newData);
-                            answer.add(newRow);
-                        }
-                    } else {
-                        // flattern each entry in the row as a list of single Map<key, value> elements
-                        Map newData = transformMap(row);
-                        for (Object obj : newData.entrySet()) {
-                            Map.Entry entry = (Map.Entry) obj;
-                            Map<String, String> newRow = new LinkedHashMap<>();
-                            newRow.put(entry.getKey().toString(), entry.getValue().toString());
-                            answer.add(newRow);
-                        }
-                    }
-                }
-            }
-        } catch (Exception e) {
-            // wrap parsing exceptions as runtime
-            throw new RuntimeException("Cannot parse json", e);
-        }
-
-        return answer;
-    }
-
-    private static Map<String, String> transformMap(Map jsonMap) {
-        Map<String, String> answer = new LinkedHashMap<>();
-
-        for (Object rowObj : jsonMap.entrySet()) {
-            Map.Entry rowEntry = (Map.Entry) rowObj;
-            // if its a list type then its an enum, and we need to parse it as a single line separated with comma
-            // to be backwards compatible
-            Object newValue = rowEntry.getValue();
-            if (newValue instanceof List) {
-                List<?> list = (List) newValue;
-                newValue = list.stream().map(Object::toString)
-                        .collect(Collectors.joining(","));
-            }
-            // ensure value is escaped
-            String value = escapeJson(newValue.toString());
-            answer.put(rowEntry.getKey().toString(), value);
-        }
-
-        return answer;
-    }
-
-    private static String escapeJson(String value) {
-        // need to safe encode \r as \\r so its escaped
-        // need to safe encode \n as \\n so its escaped
-        // need to safe encode \t as \\t so its escaped
-        return value
-                .replace("\\r", "\\\\r")
-                .replace("\\n", "\\\\n")
-                .replace("\\t", "\\\\t");
-    }
-
-    public static boolean isComponentLenientProperties(List<Map<String, String>> rows) {
-        for (Map<String, String> row : rows) {
-            if (row.containsKey("lenientProperties")) {
-                return "true".equals(row.get("lenientProperties"));
-            }
-        }
-        return false;
-    }
-
-    public static boolean isComponentConsumerOnly(List<Map<String, String>> rows) {
-        for (Map<String, String> row : rows) {
-            if (row.containsKey("consumerOnly")) {
-                return "true".equals(row.get("consumerOnly"));
-            }
-        }
-        return false;
-    }
-
-    public static boolean isComponentProducerOnly(List<Map<String, String>> rows) {
-        for (Map<String, String> row : rows) {
-            if (row.containsKey("producerOnly")) {
-                return "true".equals(row.get("producerOnly"));
-            }
-        }
-        return false;
-    }
-
-    public static boolean isPropertyConsumerOnly(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String labels = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equalsIgnoreCase(row.get("name"));
-            }
-            if (row.containsKey("label")) {
-                labels = row.get("label");
-            }
-            if (found) {
-                return labels != null && labels.contains("consumer");
-            }
-        }
-        return false;
-    }
-
-    public static boolean isPropertyProducerOnly(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String labels = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equalsIgnoreCase(row.get("name"));
-            }
-            if (row.containsKey("label")) {
-                labels = row.get("label");
-            }
-            if (found) {
-                return labels != null && labels.contains("producer");
-            }
-        }
-        return false;
-    }
-
-    public static boolean isPropertyRequired(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            boolean required = false;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equalsIgnoreCase(row.get("name"));
-            }
-            if (row.containsKey("required")) {
-                required = "true".equals(row.get("required"));
-            }
-            if (found) {
-                return required;
-            }
-        }
-        return false;
-    }
-
-    public static boolean isPropertyDeprecated(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            boolean deprecated = false;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equalsIgnoreCase(row.get("name"));
-            }
-            if (row.containsKey("deprecated")) {
-                deprecated = "true".equals(row.get("deprecated"));
-            }
-            if (found) {
-                return deprecated;
-            }
-        }
-        return false;
-    }
-
-    public static String getPropertyKind(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String kind = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equalsIgnoreCase(row.get("name"));
-            }
-            if (row.containsKey("kind")) {
-                kind = row.get("kind");
-            }
-            if (found) {
-                return kind;
-            }
-        }
-        return null;
-    }
-
-    public static String getPropertyJavaType(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String javaType = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equalsIgnoreCase(row.get("name"));
-            }
-            if (row.containsKey("javaType")) {
-                javaType = row.get("javaType");
-            }
-            if (found) {
-                return javaType;
-            }
-        }
-        return null;
-    }
-
-    public static boolean isPropertyBoolean(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String type = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equalsIgnoreCase(row.get("name"));
-            }
-            if (row.containsKey("type")) {
-                type = row.get("type");
-            }
-            if (found) {
-                return "boolean".equals(type);
-            }
-        }
-        return false;
-    }
-
-    public static boolean isPropertyInteger(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String type = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equalsIgnoreCase(row.get("name"));
-            }
-            if (row.containsKey("type")) {
-                type = row.get("type");
-            }
-            if (found) {
-                return "integer".equals(type);
-            }
-        }
-        return false;
-    }
-
-    public static boolean isPropertyArray(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String type = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equalsIgnoreCase(row.get("name"));
-            }
-            if (row.containsKey("type")) {
-                type = row.get("type");
-            }
-            if (found) {
-                return "array".equals(type);
-            }
-        }
-        return false;
-    }
-
-    public static boolean isPropertyNumber(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String type = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equalsIgnoreCase(row.get("name"));
-            }
-            if (row.containsKey("type")) {
-                type = row.get("type");
-            }
-            if (found) {
-                return "number".equals(type);
-            }
-        }
-        return false;
-    }
-
-    public static boolean isPropertyObject(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String type = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equalsIgnoreCase(row.get("name"));
-            }
-            if (row.containsKey("type")) {
-                type = row.get("type");
-            }
-            if (found) {
-                return "object".equals(type);
-            }
-        }
-        return false;
-    }
-
-    public static String getPropertyDefaultValue(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String defaultValue = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equalsIgnoreCase(row.get("name"));
-            }
-            if (row.containsKey("defaultValue")) {
-                defaultValue = row.get("defaultValue");
-            }
-            if (found) {
-                return defaultValue;
-            }
-        }
-        return null;
-    }
-
-    public static String stripOptionalPrefixFromName(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            boolean found = false;
-            if (row.containsKey("name")) {
-                String optionalPrefix = row.get("optionalPrefix");
-                if (optionalPrefix != null && !optionalPrefix.isEmpty() && name.startsWith(optionalPrefix)) {
-                    name = name.substring(optionalPrefix.length());
-                    // try again
-                    return stripOptionalPrefixFromName(rows, name);
-                } else {
-                    found = name.equalsIgnoreCase(row.get("name"));
-                }
-            }
-            if (found) {
-                return name;
-            }
-        }
-        return name;
-    }
-
-    public static String getPropertyEnum(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String enums = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equalsIgnoreCase(row.get("name"));
-            }
-            if (row.containsKey("enum")) {
-                enums = row.get("enum");
-            }
-            if (found) {
-                return enums;
-            }
-        }
-        return null;
-    }
-
-    public static String getPropertyPrefix(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String prefix = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equalsIgnoreCase(row.get("name"));
-            }
-            if (row.containsKey("prefix")) {
-                prefix = row.get("prefix");
-            }
-            if (found) {
-                return prefix;
-            }
-        }
-        return null;
-    }
-
-    public static boolean isPropertyMultiValue(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            boolean multiValue = false;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                found = name.equalsIgnoreCase(row.get("name"));
-            }
-            if (row.containsKey("multiValue")) {
-                multiValue = "true".equals(row.get("multiValue"));
-            }
-            if (found) {
-                return multiValue;
-            }
-        }
-        return false;
-    }
-
-    public static String getPropertyNameFromNameWithPrefix(List<Map<String, String>> rows, String name) {
-        for (Map<String, String> row : rows) {
-            String propertyName = null;
-            boolean found = false;
-            if (row.containsKey("name")) {
-                propertyName = row.get("name");
-            }
-            if (row.containsKey("prefix")) {
-                String preifx = row.get("prefix");
-                found = name.startsWith(preifx);
-            }
-            if (found) {
-                return propertyName;
-            }
-        }
-        return null;
-    }
-
-    public static Map<String, String> getRow(List<Map<String, String>> rows, String key) {
-        for (Map<String, String> row : rows) {
-            if (key.equals(row.get("name"))) {
-                return row;
-            }
-        }
-        return null;
-    }
-
-    public static Set<String> getNames(List<Map<String, String>> rows) {
-        Set<String> answer = new LinkedHashSet<>();
-        for (Map<String, String> row : rows) {
-            if (row.containsKey("name")) {
-                answer.add(row.get("name"));
-            }
-        }
-        return answer;
-    }
-
-    /**
-     * Converts the string from dash format into camel case (hello-great-world -> helloGreatWorld)
-     *
-     * @param text  the string
-     * @return the string camel cased
-     */
-    private static String dashToCamelCase(String text) {
-        if (text == null) {
-            return null;
-        }
-        int length = text.length();
-        if (length == 0) {
-            return text;
-        }
-        if (text.indexOf('-') == -1) {
-            return text;
-        }
-
-        StringBuilder sb = new StringBuilder();
-
-        for (int i = 0; i < text.length(); i++) {
-            char c = text.charAt(i);
-            if (c == '-') {
-                i++;
-                sb.append(Character.toUpperCase(text.charAt(i)));
-            } else {
-                sb.append(c);
-            }
-        }
-        return sb.toString();
-    }
-}
\ No newline at end of file
diff --git a/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PrepareCatalogQuarkusMojo.java b/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PrepareCatalogQuarkusMojo.java
index ea76e65..3fe41dd 100644
--- a/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PrepareCatalogQuarkusMojo.java
+++ b/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PrepareCatalogQuarkusMojo.java
@@ -16,395 +16,189 @@
  */
 package org.apache.camel.quarkus.maven;
 
-import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
-import java.io.InputStreamReader;
 import java.io.Reader;
 import java.io.Writer;
-import java.net.URL;
 import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.EnumMap;
-import java.util.HashMap;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Optional;
 import java.util.Properties;
 import java.util.Set;
 import java.util.TreeSet;
 import java.util.stream.Collectors;
 
-import org.apache.maven.execution.MavenSession;
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+import com.google.gson.JsonObject;
+import org.apache.camel.quarkus.maven.CqCatalog.Kind;
+import org.apache.camel.quarkus.maven.CqCatalog.WrappedModel;
 import org.apache.maven.model.Dependency;
 import org.apache.maven.model.Model;
 import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
-import org.apache.maven.plugins.annotations.Component;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
-import org.apache.maven.plugins.annotations.ResolutionScope;
-import org.apache.maven.project.MavenProject;
-import org.apache.maven.project.MavenProjectHelper;
-import org.apache.maven.project.ProjectBuilder;
-import org.apache.maven.repository.RepositorySystem;
 import org.codehaus.plexus.util.xml.pull.XmlPullParserException;
-import org.mvel2.templates.TemplateRuntime;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-
-import static org.apache.camel.tooling.util.PackageHelper.loadText;
 
 /**
  * Prepares the Quarkus provider camel catalog to include component it supports
+ *
+ * @since 0.1.0
  */
-@Mojo(name = "prepare-catalog-quarkus", threadSafe = true, requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME)
+@Mojo(name = "prepare-catalog-quarkus", threadSafe = true)
 public class PrepareCatalogQuarkusMojo extends AbstractMojo {
 
-    private static final Set<String> EXCLUDE_EXTENSIONS = Collections
-            .unmodifiableSet(new HashSet<>(Arrays.asList("http-common", "support")));
-
-    /**
-     * The maven project.
-     */
-    @Parameter(property = "project", required = true, readonly = true)
-    protected MavenProject project;
-
-    @Component
-    private RepositorySystem repositorySystem;
-
-    @Component
-    private ProjectBuilder mavenProjectBuilder;
-
-    @Parameter(defaultValue = "${session}", readonly = true)
-    private MavenSession session;
-
-    @Component
-    private MavenProjectHelper projectHelper;
-
-    /**
-     * The output directory for components catalog
-     */
-    @Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/quarkus/components")
-    protected File componentsOutDir;
-
-    /**
-     * The output directory for dataformats catalog
-     */
-    @Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/quarkus/dataformats")
-    protected File dataFormatsOutDir;
-
+    public static final String CQ_CATALOG_DIR = "org/apache/camel/catalog/quarkus";
     /**
-     * The output directory for languages catalog
+     * The output directory where the catalog files should be written.
      */
-    @Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/quarkus/languages")
-    protected File languagesOutDir;
+    @Parameter(defaultValue = "${project.build.directory}/classes", property = "cq.catalogBaseDir")
+    File catalogBaseDir;
 
     /**
-     * The output directory for others catalog
+     * List of directories that contain extensions
      */
-    @Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/quarkus/others")
-    protected File othersOutDir;
+    @Parameter(property = "cq.extensionDirectories", required = true)
+    List<File> extensionDirectories;
 
     /**
-     * The directory where all quarkus extension starters are
+     * A set of artifactIdBases that are nor extensions and should be excluded from the catalog
      */
-    @Parameter(property = "camel.quarkus.extensionDirs")
-    protected List<String> extensionDirs;
+    @Parameter(property = "cq.skipArtifactIdBases")
+    Set<String> skipArtifactIdBases;
 
-    /**
-     * Execute goal.
-     *
-     * @throws MojoExecutionException execution of the main class or one of the
-     *             threads it generated failed.
-     * @throws MojoFailureException something bad happened...
-     */
     @Override
     public void execute() throws MojoExecutionException, MojoFailureException {
-        final List<CamelQuarkusExtension> extensions = findExtensionModules();
-        final CamelCatalog camelCatalog = CamelCatalog.load();
-        for (Kind kind : Kind.values()) {
-            doExecute(extensions, kind, camelCatalog);
+        final Path catalogPath = catalogBaseDir.toPath().resolve(CQ_CATALOG_DIR);
+        if (skipArtifactIdBases == null) {
+            skipArtifactIdBases = Collections.emptySet();
         }
-        appendOthers(extensions, camelCatalog);
-    }
 
-    protected void doExecute(List<CamelQuarkusExtension> extensions, Kind kind, CamelCatalog catalog)
-            throws MojoExecutionException {
-
-        final Path outsDir = kind.getPath(this);
-
-        // make sure to create out dir
-        try {
-            Files.createDirectories(outsDir);
-        } catch (IOException e) {
-            throw new MojoExecutionException("Could not create " + outsDir, e);
+        final Map<Kind, Set<String>> schemesByKind = new EnumMap<>(Kind.class);
+        for (Kind kind : Kind.values()) {
+            schemesByKind.put(kind, new TreeSet<>());
         }
 
         final Gson gson = new GsonBuilder().enableComplexMapKeySerialization().setPrettyPrinting().create();
+        final CqCatalog catalog = new CqCatalog();
+        extensionDirectories.stream()
+                .map(File::toPath)
+                .forEach(extDir -> {
+                    CqUtils.findExtensionArtifactIdBases(extDir)
+                            .filter(artifactIdBase -> !skipArtifactIdBases.contains(artifactIdBase))
+                            .forEach(artifactIdBase -> {
+                                final List<WrappedModel> models = catalog.filterModels(artifactIdBase);
+                                final CamelQuarkusExtension ext = CamelQuarkusExtension
+                                        .read(extDir.resolve(artifactIdBase).resolve("pom.xml"), catalog);
+                                final boolean nativeSupported = !extDir.getFileName().toString().endsWith("-jvm");
+                                if (models.isEmpty()) {
+                                    appendOther(ext, nativeSupported, schemesByKind, gson, catalogPath);
+                                } else {
+                                    for (WrappedModel model : models) {
+                                        final JsonObject newCatalogEntry = model.getJson();
+                                        final JsonObject kindObject = newCatalogEntry.get(model.kind.name()).getAsJsonObject();
+                                        final String firstVersion = ext.getFirstVersion()
+                                                .orElseThrow(() -> new RuntimeException(
+                                                        "firstVersion property is missing in " + ext.getRuntimePomXmlPath()));
+                                        // lets use the camel-quarkus version as first version instead of Apache Camel
+                                        // version
+                                        kindObject.addProperty("firstVersion", firstVersion);
+
+                                        // update json metadata to adapt to camel-quarkus-catalog
+                                        kindObject.addProperty("groupId", "org.apache.camel.quarkus");
+                                        kindObject.addProperty("artifactId", ext.getRuntimeArtifactId());
+                                        kindObject.addProperty("version", ext.getVersion());
+                                        kindObject.addProperty("compilationTarget", nativeSupported ? "Native" : "JVM");
+                                        kindObject.addProperty("supportLevel", nativeSupported ? "Stable" : "Preview");
+
+                                        final Path out = catalogPath.resolve(model.kind.getPluralName())
+                                                .resolve(model.getScheme() + ".json");
+                                        try {
+                                            Files.createDirectories(out.getParent());
+                                        } catch (IOException e) {
+                                            throw new RuntimeException("Could not create " + out.getParent(), e);
+                                        }
+                                        try (Writer w = Files.newBufferedWriter(out, StandardCharsets.UTF_8)) {
+                                            gson.toJson(newCatalogEntry, w);
+                                        } catch (IOException e) {
+                                            throw new RuntimeException("Could not write to " + out);
+                                        }
+
+                                        schemesByKind.get(model.kind).add(model.getScheme());
+
+                                    }
+                                }
+                            });
+                });
 
-        final Set<String> names = new TreeSet<>();
-
-        for (CamelQuarkusExtension ext : extensions) {
-            final String artifactId = ext.getCamelComponentArtifactId();
-            for (JsonObject catalogEntry : catalog.getByArtifactId(kind, artifactId)) {
-                final JsonObject newCatalogEntry = catalogEntry.deepCopy();
-                final JsonObject kindObject = newCatalogEntry.get(kind.getSingularName()).getAsJsonObject();
-                final String firstVersion = ext.getFirstVersion().orElseThrow(() -> new MojoExecutionException(
-                        "firstVersion property is missing in " + ext.getRuntimePomXmlPath()));
-                // lets use the camel-quarkus version as first version instead of Apache Camel version
-                kindObject.addProperty("firstVersion", firstVersion);
-
-                // update json metadata to adapt to camel-quarkus-catalog
-                kindObject.addProperty("groupId", "org.apache.camel.quarkus");
-                kindObject.addProperty("artifactId", ext.getRuntimeArtifactId());
-                kindObject.addProperty("version", project.getVersion());
-
-                final String name = kind.getName(newCatalogEntry);
-                names.add(name);
-                final Path out = outsDir.resolve(name + ".json");
-                try (Writer w = Files.newBufferedWriter(out, StandardCharsets.UTF_8)) {
-                    gson.toJson(newCatalogEntry, w);
-                } catch (IOException e) {
-                    throw new MojoExecutionException("Could not write to " + out);
-                }
+        for (Kind kind : Kind.values()) {
+            final Path newCatalog = catalogPath.resolve(kind.getPluralName() + ".properties");
+            try {
+                Files.createDirectories(newCatalog.getParent());
+                Files.write(newCatalog,
+                        schemesByKind.get(kind).stream().collect(Collectors.joining("\n")).getBytes(StandardCharsets.UTF_8));
+            } catch (IOException e) {
+                throw new MojoExecutionException("Could not write to " + newCatalog);
             }
         }
 
-        final Path newCatalog = outsDir.resolve("../" + kind + ".properties");
-        try {
-            Files.write(newCatalog, names.stream().collect(Collectors.joining("\n")).getBytes(StandardCharsets.UTF_8));
-        } catch (IOException e) {
-            throw new MojoExecutionException("Could not write to " + newCatalog);
-        }
     }
 
-    protected void appendOthers(List<CamelQuarkusExtension> extensions, CamelCatalog catalog)
-            throws MojoExecutionException, MojoFailureException {
-        // make sure to create out dir
-        othersOutDir.mkdirs();
-        final Path othersPropertiesPath = othersOutDir.toPath().resolve("../others.properties");
-
-        Set<String> names;
-        try {
-            names = Files.lines(othersPropertiesPath).collect(Collectors.toCollection(TreeSet::new));
-        } catch (IOException e) {
-            throw new RuntimeException("Could not read " + othersPropertiesPath, e);
-        }
-
-        for (CamelQuarkusExtension ext : extensions) {
-            // skip if the extension is already one of the following
-            if (ext.getCamelComponentArtifactId() == null || !catalog.getKind(ext.getCamelComponentArtifactId()).isPresent()) {
-                final Map<String, String> model = new HashMap<>();
-
-                String firstVersion = ext.getFirstVersion().orElseThrow(() -> new MojoExecutionException(
-                        "firstVersion property is missing in " + ext.getRuntimePomXmlPath()));
-                model.put("firstVersion", firstVersion);
-
-                final String name = ext.getRuntimeArtifactId().replace("camel-quarkus-", "");
-                names.add(name);
-                model.put("name", name);
-                final String title = ext.getName().orElseThrow(() -> new MojoExecutionException(
-                        "name is missing in " + ext.getRuntimePomXmlPath()));
-                model.put("title", title);
-                model.put("description", ext.getDescription().orElseThrow(() -> new MojoExecutionException(
-                        "description is missing in " + ext.getRuntimePomXmlPath())));
-                if (title.contains("(deprecated)")) {
-                    model.put("deprecated", "true");
-                } else {
-                    model.put("deprecated", "false");
-                }
-                model.put("label", ext.getLabel().orElse("quarkus"));
-                model.put("groupId", "org.apache.camel.quarkus");
-                model.put("artifactId", ext.getRuntimeArtifactId());
-                model.put("version", project.getVersion());
-
-                final String text = templateOther(model);
-
-                // write new json file
-                Path to = othersOutDir.toPath().resolve(name + ".json");
-                try {
-                    Files.write(to, text.getBytes(StandardCharsets.UTF_8));
-                } catch (IOException e) {
-                    throw new RuntimeException("Could not write to " + to, e);
-                }
-            }
+    void appendOther(CamelQuarkusExtension ext, boolean nativeSupported, Map<Kind, Set<String>> schemesByKind, Gson gson,
+            Path catalogPath) {
+        final JsonObject other = new JsonObject();
+        String firstVersion = ext.getFirstVersion().orElseThrow(() -> new RuntimeException(
+                "firstVersion property is missing in " + ext.getRuntimePomXmlPath()));
+        other.addProperty("firstVersion", firstVersion);
+        final Kind kind = Kind.other;
+        final String name = ext.getRuntimeArtifactId().replace("camel-quarkus-", "");
+        schemesByKind.get(kind).add(name);
+        other.addProperty("name", name);
+        final String title = ext.getName().orElseThrow(() -> new RuntimeException(
+                "name is missing in " + ext.getRuntimePomXmlPath()));
+        other.addProperty("title", title);
+        other.addProperty("description", ext.getDescription().orElseThrow(() -> new RuntimeException(
+                "description is missing in " + ext.getRuntimePomXmlPath())));
+        if (title.contains("(deprecated)")) {
+            other.addProperty("deprecated", "true");
+        } else {
+            other.addProperty("deprecated", "false");
         }
+        other.addProperty("label", ext.getLabel().orElse("quarkus"));
+        other.addProperty("groupId", "org.apache.camel.quarkus");
+        other.addProperty("artifactId", ext.getRuntimeArtifactId());
+        other.addProperty("version", ext.getVersion());
+        other.addProperty("compilationTarget", nativeSupported ? "Native" : "JVM");
+        other.addProperty("supportLevel", nativeSupported ? "Stable" : "Preview");
+
+        final JsonObject json = new JsonObject();
+        json.add("other", other);
+
+        // write new json file
+        final Path out = catalogPath.resolve(kind.getPluralName()).resolve(name + ".json");
         try {
-            Files.write(othersPropertiesPath,
-                    names.stream().collect(Collectors.joining("\n")).getBytes(StandardCharsets.UTF_8));
+            Files.createDirectories(out.getParent());
         } catch (IOException e) {
-            throw new RuntimeException("Could not write to " + othersPropertiesPath, e);
+            throw new RuntimeException("Could not create " + out.getParent(), e);
         }
-    }
-
-    private String templateOther(Map<?, ?> model) throws MojoExecutionException {
-        try {
-            String template = loadText(getClass().getClassLoader().getResourceAsStream("other-template.mvel"));
-            String out = (String) TemplateRuntime.eval(template, model);
-            return out;
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
-        }
-    }
-
-    private List<CamelQuarkusExtension> findExtensionModules() {
-        final Path basePath = project.getBasedir().toPath();
-        return extensionDirs.stream()
-                .map(relPath -> basePath.resolve(relPath))
-                .flatMap(extensionsDir -> {
-                    try {
-                        return Files.list(extensionsDir);
-                    } catch (IOException e) {
-                        throw new RuntimeException(e);
-                    }
-                })
-                .filter(Files::isDirectory)
-                .filter(path -> !EXCLUDE_EXTENSIONS.contains(path.getFileName().toString()))
-                .map(path -> path.resolve("pom.xml"))
-                .filter(Files::exists)
-                .map(CamelQuarkusExtension::read)
-                .collect(Collectors.toList());
-    }
-
-    enum Kind {
-        components() {
-            @Override
-            public String getName(JsonObject json) {
-                return json.get(getSingularName()).getAsJsonObject().get("scheme").getAsString();
-            }
-
-            @Override
-            public Path getPath(PrepareCatalogQuarkusMojo mojo) {
-                return mojo.componentsOutDir.toPath();
-            }
-
-        },
-        languages() {
-            @Override
-            public String getName(JsonObject json) {
-                return json.get(getSingularName()).getAsJsonObject().get("name").getAsString();
-            }
-
-            @Override
-            public Path getPath(PrepareCatalogQuarkusMojo mojo) {
-                return mojo.languagesOutDir.toPath();
-            }
-        },
-        dataformats() {
-            @Override
-            public String getName(JsonObject json) {
-                return json.get(getSingularName()).getAsJsonObject().get("name").getAsString();
-            }
-
-            @Override
-            public Path getPath(PrepareCatalogQuarkusMojo mojo) {
-                return mojo.dataFormatsOutDir.toPath();
-            }
-        },
-        others() {
-            @Override
-            public String getName(JsonObject json) {
-                return json.get(getSingularName()).getAsJsonObject().get("name").getAsString();
-            }
-
-            @Override
-            public Path getPath(PrepareCatalogQuarkusMojo mojo) {
-                return mojo.othersOutDir.toPath();
-            }
-        };
-
-        public abstract String getName(JsonObject json);
-
-        public abstract Path getPath(PrepareCatalogQuarkusMojo mojo);
-
-        public String getSingularName() {
-            return name().substring(0, name().length() - 1);
-        }
-    }
-
-    static class CamelCatalog {
-
-        public static CamelCatalog load() {
-
-            Map<Kind, Map<String, List<JsonObject>>> entriesByKindByArtifactId = new EnumMap<>(Kind.class);
-
-            for (Kind kind : Kind.values()) {
-                final String resourcePath = "org/apache/camel/catalog/" + kind + ".properties";
-                final URL url = PrepareCatalogQuarkusMojo.class.getClassLoader().getResource(resourcePath);
-                try (BufferedReader propsReader = new BufferedReader(
-                        new InputStreamReader(
-                                url.openStream(),
-                                StandardCharsets.UTF_8))) {
-                    /* Load the catalog entries */
-
-                    final JsonParser jsonParser = new JsonParser();
-                    final Map<String, List<JsonObject>> entries = new HashMap<>();
-                    propsReader.lines()
-                            .map(name -> {
-                                final String rPath = "org/apache/camel/catalog/" + kind + "/" + name + ".json";
-                                try (Reader r = new InputStreamReader(PrepareCatalogQuarkusMojo.class.getClassLoader()
-                                        .getResourceAsStream(rPath), StandardCharsets.UTF_8)) {
-                                    return jsonParser.parse(r).getAsJsonObject();
-                                } catch (IOException e) {
-                                    throw new RuntimeException("Could not load resource " + rPath + " from class path", e);
-                                }
-                            })
-                            .forEach(json -> {
-                                String aid = json.get(kind.getSingularName()).getAsJsonObject().get("artifactId").getAsString();
-                                List<JsonObject> jsons = entries.get(aid);
-                                if (jsons == null) {
-                                    jsons = new ArrayList<JsonObject>();
-                                    entries.put(aid, jsons);
-                                }
-                                jsons.add(json);
-                            });
-
-                    entriesByKindByArtifactId.put(kind, entries);
-
-                } catch (IOException e) {
-                    throw new RuntimeException("Could not load resource " + resourcePath + " from class path", e);
-                }
-            }
-            return new CamelCatalog(entriesByKindByArtifactId);
-
-        }
-
-        private final Map<Kind, Map<String, List<JsonObject>>> entriesByKindByArtifactId;
-
-        public CamelCatalog(Map<Kind, Map<String, List<JsonObject>>> entriesByKindByArtifactId2) {
-            super();
-            this.entriesByKindByArtifactId = entriesByKindByArtifactId2;
-        }
-
-        public List<JsonObject> getByArtifactId(Kind kind, String artifactId) {
-            final Map<String, List<JsonObject>> kindEntries = entriesByKindByArtifactId.get(kind);
-            List<JsonObject> result = kindEntries != null ? kindEntries.get(artifactId) : null;
-            return result == null ? Collections.emptyList() : result;
-        }
-
-        public Optional<Kind> getKind(String artifactId) {
-            return entriesByKindByArtifactId.entrySet().stream()
-                    .filter(en -> en.getValue().containsKey(artifactId))
-                    .map(Entry::getKey)
-                    .findFirst();
+        try (Writer w = Files.newBufferedWriter(out, StandardCharsets.UTF_8)) {
+            gson.toJson(json, w);
+        } catch (IOException e) {
+            throw new RuntimeException("Could not write to " + out);
         }
     }
 
     static class CamelQuarkusExtension {
 
-        public static CamelQuarkusExtension read(Path parentPomXmlPath) {
+        public static CamelQuarkusExtension read(Path parentPomXmlPath, CqCatalog catalog) {
             final Path runtimePomXmlPath = parentPomXmlPath.getParent().resolve("runtime/pom.xml").toAbsolutePath().normalize();
             try (Reader parentReader = Files.newBufferedReader(parentPomXmlPath, StandardCharsets.UTF_8);
                     Reader runtimeReader = Files.newBufferedReader(runtimePomXmlPath, StandardCharsets.UTF_8)) {
@@ -415,9 +209,7 @@ public class PrepareCatalogQuarkusMojo extends AbstractMojo {
 
                 final String aid = runtimePom.getArtifactId();
                 String camelComponentArtifactId = null;
-                if (aid.equals("camel-quarkus-core")) {
-                    camelComponentArtifactId = "camel-base";
-                } else if (deps != null && !deps.isEmpty()) {
+                if (deps != null && !deps.isEmpty()) {
                     Optional<Dependency> artifact = deps.stream()
                             .filter(dep ->
 
@@ -425,7 +217,7 @@ public class PrepareCatalogQuarkusMojo extends AbstractMojo {
                                     ("compile".equals(dep.getScope()) || dep.getScope() == null))
                             .findFirst();
                     if (artifact.isPresent()) {
-                        camelComponentArtifactId = artifact.get().getArtifactId();
+                        camelComponentArtifactId = catalog.toCamelArtifactIdBase(artifact.get().getArtifactId());
                     }
                 }
                 final Properties props = runtimePom.getProperties() != null ? runtimePom.getProperties() : new Properties();
@@ -435,6 +227,8 @@ public class PrepareCatalogQuarkusMojo extends AbstractMojo {
                     name = parentPom.getName().replace("Camel Quarkus :: ", "");
                 }
 
+                final String version = CqUtils.getVersion(runtimePom);
+
                 return new CamelQuarkusExtension(
                         parentPomXmlPath,
                         runtimePomXmlPath,
@@ -443,13 +237,15 @@ public class PrepareCatalogQuarkusMojo extends AbstractMojo {
                         aid,
                         name,
                         runtimePom.getDescription(),
-                        props.getProperty("label"));
+                        props.getProperty("label"),
+                        version);
             } catch (IOException | XmlPullParserException e) {
                 throw new RuntimeException("Could not read " + parentPomXmlPath, e);
             }
         }
 
         private final String label;
+        private final String version;
 
         private final String description;
 
@@ -469,7 +265,7 @@ public class PrepareCatalogQuarkusMojo extends AbstractMojo {
                 String runtimeArtifactId,
                 String name,
                 String description,
-                String label) {
+                String label, String version) {
             super();
             this.parentPomXmlPath = pomXmlPath;
             this.runtimePomXmlPath = runtimePomXmlPath;
@@ -479,6 +275,11 @@ public class PrepareCatalogQuarkusMojo extends AbstractMojo {
             this.name = name;
             this.description = description;
             this.label = label;
+            this.version = version;
+        }
+
+        public String getVersion() {
+            return version;
         }
 
         public Path getParentPomXmlPath() {
diff --git a/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/UpdateDocExtensionsListMojo.java b/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/UpdateDocExtensionsListMojo.java
index 3cb0b85..953efa9 100644
--- a/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/UpdateDocExtensionsListMojo.java
+++ b/tooling/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/UpdateDocExtensionsListMojo.java
@@ -17,39 +17,36 @@
 package org.apache.camel.quarkus.maven;
 
 import java.io.File;
-import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.nio.file.Files;
 import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.Set;
-import java.util.TreeSet;
-
-import static java.util.stream.Collectors.toSet;
-
-import org.apache.camel.util.StringHelper;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import freemarker.ext.beans.StringModel;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateException;
+import freemarker.template.TemplateMethodModelEx;
+import freemarker.template.TemplateModelException;
+import freemarker.template.utility.DeepUnwrap;
+import org.apache.camel.quarkus.maven.CqCatalog.Kind;
+import org.apache.camel.quarkus.maven.CqCatalog.WrappedModel;
 import org.apache.camel.tooling.model.ComponentModel;
 import org.apache.camel.tooling.model.DataFormatModel;
-import org.apache.camel.tooling.model.LanguageModel;
-import org.apache.camel.tooling.model.OtherModel;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
-import org.apache.maven.plugins.annotations.Component;
 import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
-import org.apache.maven.project.MavenProject;
-import org.apache.maven.project.MavenProjectHelper;
-import org.mvel2.templates.TemplateRuntime;
 
-import static org.apache.camel.tooling.util.PackageHelper.loadText;
-import static org.apache.camel.tooling.util.PackageHelper.writeText;
+import static java.util.stream.Collectors.toSet;
 
 /**
  * Updates the documentation in:
@@ -61,698 +58,170 @@ import static org.apache.camel.tooling.util.PackageHelper.writeText;
  */
 @Mojo(name = "update-doc-extensions-list", threadSafe = true)
 public class UpdateDocExtensionsListMojo extends AbstractMojo {
-
-    /**
-     * The maven project.
-     */
-    @Parameter(property = "project", required = true, readonly = true)
-    protected MavenProject project;
-
-    /**
-     * The directory for components catalog
-     */
-    @Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/quarkus/components")
-    protected File componentsDir;
-
+    static final String DEFAULT_TEMPLATES_URI_BASE = "classpath:/extension-list-templates";
     /**
-     * The directory for data formats catalog
+     * The directory relative to which the catalog data is read.
      */
-    @Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/quarkus/dataformats")
-    protected File dataFormatsDir;
+    @Parameter(defaultValue = "${project.build.directory}/classes", property = "camel-quarkus.catalogBaseDir")
+    File catalogBaseDir;
 
     /**
-     * The directory for languages catalog
+     * The path to the document containing the list of extensions.
      */
-    @Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/quarkus/languages")
-    protected File languagesDir;
+    @Parameter(defaultValue = "${project.basedir}/../../docs/modules/ROOT/pages/list-of-camel-quarkus-extensions.adoc")
+    File extensionListFile;
 
     /**
-     * The directory for others catalog
      */
-    @Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/quarkus/others")
-    protected File othersDir;
-
+    @Parameter(defaultValue = DEFAULT_TEMPLATES_URI_BASE, required = true, property = "camel-quarkus.templatesUriBase")
+    String templatesUriBase;
     /**
-     * The directory for extensions
+     * Directory where the changes should be performed. Default is the current directory of the current Java process.
      */
-    @Parameter(defaultValue = "${project.directory}/../../extensions")
-    protected File readmeExtensionsDir;
+    @Parameter(property = "camel-quarkus.basedir", defaultValue = "${project.basedir}")
+    File baseDir;
 
     /**
-     * The website doc base directory
+     * Encoding to read and write files in the current source tree
      */
-    @Parameter(defaultValue = "${project.directory}/../../docs/modules/ROOT/pages")
-    protected File websiteDocBaseDir;
-
-    /**
-     * The website doc for extensions
-     */
-    @Parameter(defaultValue = "${project.directory}/../../docs/modules/ROOT/pages/list-of-camel-quarkus-extensions.adoc")
-    protected File websiteDocFile;
-
-    /**
-     * Maven ProjectHelper.
-     */
-    @Component
-    private MavenProjectHelper projectHelper;
+    @Parameter(defaultValue = "${project.build.sourceEncoding}", required = true, property = "camel-quarkus.encoding")
+    String encoding;
 
     /**
      * Execute goal.
      *
      * @throws MojoExecutionException execution of the main class or one of the
-     *         threads it generated failed.
-     * @throws MojoFailureException something bad happened...
+     *                                threads it generated failed.
+     * @throws MojoFailureException   something bad happened...
      */
     @Override
     public void execute() throws MojoExecutionException, MojoFailureException {
-        executeComponentsReadme();
-        executeDataFormatsReadme();
-        executeLanguagesReadme();
-        executeOthersReadme();
-    }
+        final Path catalogBasePath = catalogBaseDir.toPath();
+        final Path basePath = baseDir.toPath();
+        final Path extensionListPath = extensionListFile.toPath();
 
-    protected void executeComponentsReadme() throws MojoExecutionException, MojoFailureException {
-        Set<File> componentFiles = new TreeSet<>();
-
-        if (componentsDir != null && componentsDir.isDirectory()) {
-            File[] files = componentsDir.listFiles();
-            if (files != null) {
-                componentFiles.addAll(Arrays.asList(files));
-            }
-        }
+        final Configuration cfg = CqUtils.getTemplateConfig(basePath, DEFAULT_TEMPLATES_URI_BASE, templatesUriBase, encoding);
 
+        String document;
         try {
-            List<ComponentModel> models = new ArrayList<>();
-            for (File file : componentFiles) {
-                String json = loadText(new FileInputStream(file));
-                ComponentModel model = generateComponentModel(json);
-
-                // filter out alternative schemas which reuses documentation
-                boolean add = true;
-                if (!model.getAlternativeSchemes().isEmpty()) {
-                    String first = model.getAlternativeSchemes().split(",")[0];
-                    if (!model.getScheme().equals(first)) {
-                        add = false;
-                    }
-                }
-                if (add) {
-                    models.add(model);
-
-                    // special for camel-mail where we want to refer its imap scheme to mail so its mail.adoc in the doc link
-                    if ("imap".equals(model.getScheme())) {
-                        model.setScheme("mail");
-                        model.setTitle("Mail");
-                    }
-                }
-            }
-
-            // sort the models
-            Collections.sort(models, new ComponentComparator());
-
-            // filter out unwanted components
-            List<ComponentModel> components = new ArrayList<>();
-            for (ComponentModel model : models) {
-                components.add(model);
-            }
-
-            // how many different artifacts
-            int count = components.stream()
-                    .map(ComponentModel::getArtifactId)
-                    .collect(toSet()).size();
-
-            // how many deprecated
-            long deprecated = components.stream()
-                    .filter(ComponentModel::isDeprecated)
-                    .count();
-
-            // update the big readme file in the extensions dir
-            File file = new File(readmeExtensionsDir, "readme.adoc");
-            boolean exists = file.exists();
-            String changed = templateComponents(components, count, deprecated);
-            boolean updated = updateComponents(file, changed);
-            if (updated) {
-                getLog().info("Updated readme.adoc file: " + file);
-            } else if (exists) {
-                getLog().debug("No changes to readme.adoc file: " + file);
-            } else {
-                getLog().warn("No readme.adoc file: " + file);
-            }
-
-            // update doc in the website dir
-            file = websiteDocFile;
-            exists = file.exists();
-            changed = templateComponents(components, count, deprecated);
-            updated = updateComponents(file, changed);
-            if (updated) {
-                getLog().info("Updated website doc file: " + file);
-            } else if (exists) {
-                getLog().debug("No changes to website doc file: " + file);
-            } else {
-                getLog().warn("No website doc file: " + file);
-            }
-
+            document = new String(Files.readAllBytes(extensionListPath), encoding);
         } catch (IOException e) {
-            throw new MojoFailureException("Error due " + e.getMessage(), e);
-        }
-    }
-
-    protected void executeDataFormatsReadme() throws MojoExecutionException, MojoFailureException {
-        Set<File> dataFormatFiles = new TreeSet<>();
-
-        if (dataFormatsDir != null && dataFormatsDir.isDirectory()) {
-            File[] files = dataFormatsDir.listFiles();
-            if (files != null) {
-                dataFormatFiles.addAll(Arrays.asList(files));
-            }
-        }
-
-        try {
-            List<DataFormatModel> models = new ArrayList<>();
-            for (File file : dataFormatFiles) {
-                String json = loadText(new FileInputStream(file));
-                DataFormatModel model = generateDataFormatModel(json);
-
-                // special for bindy as we have one common file
-                if (model.getName().startsWith("bindy")) {
-                    model.setName("bindy");
-                }
-
-                models.add(model);
-            }
-
-            // sort the models
-            Collections.sort(models, new DataFormatComparator());
-
-            // how many different artifacts
-            int count = models.stream()
-                    .map(DataFormatModel::getArtifactId)
+            throw new RuntimeException("Could not read " + extensionListPath, e);
+        }
+        final GetDocLink getDocLink = new GetDocLink(extensionListPath.getParent().resolve("extensions"));
+        final CqCatalog catalog = new CqCatalog(catalogBasePath);
+        for (Kind kind : Kind.values()) {
+
+            final Map<String, Object> model = new HashMap<>(3);
+            final List<WrappedModel> models = kind.all(catalog)
+                    .filter(WrappedModel::isFirstScheme)
+                    .peek(m -> {
+                        // special for camel-mail where we want to refer its imap scheme to mail so its mail.adoc in the
+                        // doc link
+                        if ("imap".equals(m.getScheme())) {
+                            final ComponentModel delegate = (ComponentModel) m.delegate;
+                            delegate.setScheme("mail");
+                            delegate.setTitle("Mail");
+                        }
+                        if (m.getScheme().startsWith("bindy")) {
+                            final DataFormatModel delegate = (DataFormatModel) m.delegate;
+                            delegate.setName("bindy");
+                        }
+                    })
+                    .sorted()
+                    .collect(Collectors.toList());
+            model.put("components", models);
+            final int artifactIdCount = models.stream()
+                    .map(WrappedModel::getArtifactId)
                     .collect(toSet()).size();
-
-            // how many deprecated
-            long deprecated = models.stream()
-                    .filter(DataFormatModel::isDeprecated)
+            model.put("numberOfArtifacts", artifactIdCount);
+            final long deprecatedCount = models.stream()
+                    .filter(m -> m.delegate.isDeprecated())
                     .count();
+            model.put("numberOfDeprecated", deprecatedCount);
+            model.put("getDocLink", getDocLink);
 
-            // filter out camel-core
-            List<DataFormatModel> dataFormats = new ArrayList<>();
-            for (DataFormatModel model : models) {
-                dataFormats.add(model);
-            }
-
-            // update the big readme file in the extensions dir
-            File file = new File(readmeExtensionsDir, "readme.adoc");
-            boolean exists = file.exists();
-            String changed = templateDataFormats(dataFormats, count, deprecated);
-            boolean updated = updateDataFormats(file, changed);
-            if (updated) {
-                getLog().info("Updated readme.adoc file: " + file);
-            } else if (exists) {
-                getLog().debug("No changes to readme.adoc file: " + file);
-            } else {
-                getLog().warn("No readme.adoc file: " + file);
-            }
-
-            // update doc in the website dir
-            file = websiteDocFile;
-            exists = file.exists();
-            changed = templateDataFormats(dataFormats, count, deprecated);
-            updated = updateDataFormats(file, changed);
-            if (updated) {
-                getLog().info("Updated website doc file: " + file);
-            } else if (exists) {
-                getLog().debug("No changes to website doc file: " + file);
-            } else {
-                getLog().warn("No website doc file: " + file);
-            }
-
-        } catch (IOException e) {
-            throw new MojoFailureException("Error due " + e.getMessage(), e);
-        }
-    }
-
-    protected void executeLanguagesReadme() throws MojoExecutionException, MojoFailureException {
-        Set<File> languageFiles = new TreeSet<>();
-
-        if (languagesDir != null && languagesDir.isDirectory()) {
-            File[] files = languagesDir.listFiles();
-            if (files != null) {
-                languageFiles.addAll(Arrays.asList(files));
-            }
+            final String extList = evalTemplate(cfg, "readme-" + kind.getPluralName() + ".ftl", model);
+            document = replace(document, extensionListPath, extList, kind);
         }
 
         try {
-            List<LanguageModel> models = new ArrayList<>();
-            for (File file : languageFiles) {
-                String json = loadText(new FileInputStream(file));
-                LanguageModel model = generateLanguageModel(json);
-                models.add(model);
-            }
-
-            // sort the models
-            Collections.sort(models, new LanguageComparator());
-
-            // filter out camel-core
-            List<LanguageModel> languages = new ArrayList<>();
-            for (LanguageModel model : models) {
-                languages.add(model);
-            }
-
-            // how many different artifacts
-            int count = languages.stream()
-                    .map(LanguageModel::getArtifactId)
-                    .collect(toSet()).size();
-
-            // how many deprecated
-            long deprecated = languages.stream()
-                    .filter(LanguageModel::isDeprecated)
-                    .count();
-
-            // update the big readme file in the extensions dir
-            File file = new File(readmeExtensionsDir, "readme.adoc");
-            boolean exists = file.exists();
-            String changed = templateLanguages(languages, count, deprecated);
-            boolean updated = updateLanguages(file, changed);
-            if (updated) {
-                getLog().info("Updated readme.adoc file: " + file);
-            } else if (exists) {
-                getLog().debug("No changes to readme.adoc file: " + file);
-            } else {
-                getLog().warn("No readme.adoc file: " + file);
-            }
-
-            // update doc in the website dir
-            file = websiteDocFile;
-            exists = file.exists();
-            changed = templateLanguages(languages, count, deprecated);
-            updated = updateLanguages(file, changed);
-            if (updated) {
-                getLog().info("Updated website doc file: " + file);
-            } else if (exists) {
-                getLog().debug("No changes to website doc file: " + file);
-            } else {
-                getLog().warn("No website doc file: " + file);
-            }
-
+            Files.write(extensionListPath, document.getBytes(encoding));
         } catch (IOException e) {
-            throw new MojoFailureException("Error due " + e.getMessage(), e);
+            throw new RuntimeException("Could not write to " + extensionListPath, e);
         }
-    }
-
-    protected void executeOthersReadme() throws MojoExecutionException, MojoFailureException {
-        Set<File> otherFiles = new TreeSet<>();
 
-        if (othersDir != null && othersDir.isDirectory()) {
-            File[] files = othersDir.listFiles();
-            if (files != null) {
-                otherFiles.addAll(Arrays.asList(files));
-            }
-        }
-
-        try {
-            List<OtherModel> others = new ArrayList<>();
-            for (File file : otherFiles) {
-                String json = loadText(new FileInputStream(file));
-                OtherModel model = generateOtherModel(json);
-                others.add(model);
-            }
-
-            // sort the models
-            Collections.sort(others, new OtherComparator());
-
-            // how many different artifacts
-            int count = others.stream()
-                    .map(OtherModel::getArtifactId)
-                    .collect(toSet()).size();
-
-            // how many deprecated
-            long deprecated = others.stream()
-                    .filter(OtherModel::isDeprecated)
-                    .count();
-
-            // update the big readme file in the extensions dir
-            File file = new File(readmeExtensionsDir, "readme.adoc");
-            boolean exists = file.exists();
-            String changed = templateOthers(others, count, deprecated);
-            boolean updated = updateOthers(file, changed);
-            if (updated) {
-                getLog().info("Updated readme.adoc file: " + file);
-            } else if (exists) {
-                getLog().debug("No changes to readme.adoc file: " + file);
-            } else {
-                getLog().warn("No readme.adoc file: " + file);
-            }
-
-            // update doc in the website dir
-            file = websiteDocFile;
-            exists = file.exists();
-            changed = templateOthers(others, count, deprecated);
-            updated = updateOthers(file, changed);
-            if (updated) {
-                getLog().info("Updated website doc file: " + file);
-            } else if (exists) {
-                getLog().debug("No changes to website doc file: " + file);
-            } else {
-                getLog().warn("No website doc file: " + file);
-            }
-
-        } catch (IOException e) {
-            throw new MojoFailureException("Error due " + e.getMessage(), e);
-        }
-    }
-
-    private String templateComponents(List<ComponentModel> models, int artifacts, long deprecated)
-            throws MojoExecutionException {
-        try {
-            String template = loadText(
-                    UpdateDocExtensionsListMojo.class.getClassLoader().getResourceAsStream("readme-components.mvel"));
-            Map<String, Object> map = new HashMap<>();
-            map.put("components", models);
-            map.put("numberOfArtifacts", artifacts);
-            map.put("numberOfDeprecated", deprecated);
-            String out = (String) TemplateRuntime.eval(template, map,
-                    Collections.singletonMap("util", new ExtMvelHelper(getExtensionsDocPath())));
-            return out;
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
-        }
     }
 
-    private String templateDataFormats(List<DataFormatModel> models, int artifacts, long deprecated)
-            throws MojoExecutionException {
-        try {
-            String template = loadText(
-                    UpdateDocExtensionsListMojo.class.getClassLoader().getResourceAsStream("readme-dataformats.mvel"));
-            Map<String, Object> map = new HashMap<>();
-            map.put("dataformats", models);
-            map.put("numberOfArtifacts", artifacts);
-            map.put("numberOfDeprecated", deprecated);
-            String out = (String) TemplateRuntime.eval(template, map,
-                    Collections.singletonMap("util", new ExtMvelHelper(getExtensionsDocPath())));
-            return out;
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
-        }
-    }
-
-    private String templateLanguages(List<LanguageModel> models, int artifacts, long deprecated) throws MojoExecutionException {
-        try {
-            String template = loadText(
-                    UpdateDocExtensionsListMojo.class.getClassLoader().getResourceAsStream("readme-languages.mvel"));
-            Map<String, Object> map = new HashMap<>();
-            map.put("languages", models);
-            map.put("numberOfArtifacts", artifacts);
-            map.put("numberOfDeprecated", deprecated);
-            String out = (String) TemplateRuntime.eval(template, map,
-                    Collections.singletonMap("util", new ExtMvelHelper(getExtensionsDocPath())));
-            return out;
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
-        }
-    }
+    static String replace(String document, Path documentPath, String list, Kind kind) {
+        final Pattern pat = Pattern.compile("(" + Pattern.quote("// " + kind.getPluralName() + ": START\n") + ")(.*)("
+                + Pattern.quote("// " + kind.getPluralName() + ": END\n") + ")", Pattern.DOTALL);
 
-    private String templateOthers(List<OtherModel> models, int artifacts, long deprecated) throws MojoExecutionException {
-        try {
-            String template = loadText(
-                    UpdateDocExtensionsListMojo.class.getClassLoader().getResourceAsStream("readme-others.mvel"));
-            Map<String, Object> map = new HashMap<>();
-            map.put("others", models);
-            map.put("numberOfArtifacts", artifacts);
-            map.put("numberOfDeprecated", deprecated);
-            String out = (String) TemplateRuntime.eval(template, map,
-                    Collections.singletonMap("util", new ExtMvelHelper(getExtensionsDocPath())));
-            return out;
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
+        final Matcher m = pat.matcher(document);
+        final StringBuffer sb = new StringBuffer(document.length());
+        if (m.find()) {
+            m.appendReplacement(sb, "$1" + Matcher.quoteReplacement(list) + "$3");
+        } else {
+            throw new IllegalStateException("Could not find " + pat.pattern() + " in " + documentPath + ":\n\n" + document);
         }
+        m.appendTail(sb);
+        return sb.toString();
     }
 
-    private boolean updateComponents(File file, String changed) throws MojoExecutionException {
-        if (!file.exists()) {
-            return false;
-        }
-
+    static String evalTemplate(Configuration cfg, String templateUri, Map<String, Object> model) {
         try {
-            String text = loadText(new FileInputStream(file));
-
-            String existing = StringHelper.between(text, "// components: START", "// components: END");
-            if (existing != null) {
-                // remove leading line breaks etc
-                existing = existing.trim();
-                changed = changed.trim();
-                if (existing.equals(changed)) {
-                    return false;
-                } else {
-                    String before = StringHelper.before(text, "// components: START");
-                    String after = StringHelper.after(text, "// components: END");
-                    text = before + "// components: START\n" + changed + "\n// components: END" + after;
-                    writeText(file, text);
-                    return true;
+            final Template template = cfg.getTemplate(templateUri);
+            try (Writer out = new StringWriter()) {
+                try {
+                    template.process(model, out);
+                } catch (TemplateException e) {
+                    throw new RuntimeException("Could not process template " + templateUri + ":\n\n" + out.toString(), e);
                 }
-            } else {
-                getLog().warn("Cannot find markers in file " + file);
-                getLog().warn("Add the following markers");
-                getLog().warn("\t// components: START");
-                getLog().warn("\t// components: END");
-                return false;
+                return out.toString();
             }
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
+        } catch (IOException e) {
+            throw new RuntimeException("Could not evaluate template " + templateUri, e);
         }
     }
 
-    private boolean updateDataFormats(File file, String changed) throws MojoExecutionException {
-        if (!file.exists()) {
-            return false;
-        }
-
-        try {
-            String text = loadText(new FileInputStream(file));
+    static class GetDocLink implements TemplateMethodModelEx {
+        private final Path extensionsDocPath;
 
-            String existing = StringHelper.between(text, "// dataformats: START", "// dataformats: END");
-            if (existing != null) {
-                // remove leading line breaks etc
-                existing = existing.trim();
-                changed = changed.trim();
-                if (existing.equals(changed)) {
-                    return false;
-                } else {
-                    String before = StringHelper.before(text, "// dataformats: START");
-                    String after = StringHelper.after(text, "// dataformats: END");
-                    text = before + "// dataformats: START\n" + changed + "\n// dataformats: END" + after;
-                    writeText(file, text);
-                    return true;
-                }
-            } else {
-                getLog().warn("Cannot find markers in file " + file);
-                getLog().warn("Add the following markers");
-                getLog().warn("\t// dataformats: START");
-                getLog().warn("\t// dataformats: END");
-                return false;
-            }
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
-        }
-    }
-
-    private boolean updateLanguages(File file, String changed) throws MojoExecutionException {
-        if (!file.exists()) {
-            return false;
+        public GetDocLink(Path extensionsDocPath) {
+            super();
+            this.extensionsDocPath = extensionsDocPath;
         }
 
-        try {
-            String text = loadText(new FileInputStream(file));
-
-            String existing = StringHelper.between(text, "// languages: START", "// languages: END");
-            if (existing != null) {
-                // remove leading line breaks etc
-                existing = existing.trim();
-                changed = changed.trim();
-                if (existing.equals(changed)) {
-                    return false;
-                } else {
-                    String before = StringHelper.before(text, "// languages: START");
-                    String after = StringHelper.after(text, "// languages: END");
-                    text = before + "// languages: START\n" + changed + "\n// languages: END" + after;
-                    writeText(file, text);
-                    return true;
-                }
-            } else {
-                getLog().warn("Cannot find markers in file " + file);
-                getLog().warn("Add the following markers");
-                getLog().warn("\t// languages: START");
-                getLog().warn("\t// languages: END");
-                return false;
-            }
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
-        }
-    }
-
-    private boolean updateOthers(File file, String changed) throws MojoExecutionException {
-        if (!file.exists()) {
-            return false;
-        }
-
-        try {
-            String text = loadText(new FileInputStream(file));
-
-            String existing = StringHelper.between(text, "// others: START", "// others: END");
-            if (existing != null) {
-                // remove leading line breaks etc
-                existing = existing.trim();
-                changed = changed.trim();
-                if (existing.equals(changed)) {
-                    return false;
-                } else {
-                    String before = StringHelper.before(text, "// others: START");
-                    String after = StringHelper.after(text, "// others: END");
-                    text = before + "// others: START\n" + changed + "\n// others: END" + after;
-                    writeText(file, text);
-                    return true;
-                }
+        @Override
+        public Object exec(List arguments) throws TemplateModelException {
+            if (arguments.size() != 1) {
+                throw new TemplateModelException("Wrong argument count in toCamelCase()");
+            }
+            WrappedModel model = (WrappedModel) DeepUnwrap.unwrap((StringModel) arguments.get(0));
+            if (localDocExists(model)) {
+                return getLocalDocLink(model);
+            } else if (model.kind == Kind.other) {
+                return null;
             } else {
-                getLog().warn("Cannot find markers in file " + file);
-                getLog().warn("Add the following markers");
-                getLog().warn("\t// others: START");
-                getLog().warn("\t// others: END");
-                return false;
+                return String.format("link:https://camel.apache.org/components/latest/%s-%s.html",
+                        model.getScheme(),
+                        model.getKind());
             }
-        } catch (Exception e) {
-            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
         }
-    }
 
-    private static class ComponentComparator implements Comparator<ComponentModel> {
-
-        @Override
-        public int compare(ComponentModel o1, ComponentModel o2) {
-            // lets sort by title
-            return o1.getTitle().compareToIgnoreCase(o2.getTitle());
+        private boolean localDocExists(WrappedModel model) {
+            final Path path = extensionsDocPath.resolve(getExtensionDocName(model));
+            return path.toFile().exists();
         }
-    }
 
-    private static class DataFormatComparator implements Comparator<DataFormatModel> {
-
-        @Override
-        public int compare(DataFormatModel o1, DataFormatModel o2) {
-            // lets sort by title
-            return o1.getTitle().compareToIgnoreCase(o2.getTitle());
+        private String getLocalDocLink(WrappedModel model) {
+            return "xref:extensions/" + getExtensionDocName(model);
         }
-    }
 
-    private static class LanguageComparator implements Comparator<LanguageModel> {
-
-        @Override
-        public int compare(LanguageModel o1, LanguageModel o2) {
-            // lets sort by title
-            return o1.getTitle().compareToIgnoreCase(o2.getTitle());
-        }
-
-    }
-
-    private static class OtherComparator implements Comparator<OtherModel> {
-
-        @Override
-        public int compare(OtherModel o1, OtherModel o2) {
-            // lets sort by title
-            return o1.getTitle().compareToIgnoreCase(o2.getTitle());
+        private String getExtensionDocName(WrappedModel model) {
+            return model.getArtifactIdBase() + ".adoc";
         }
 
     }
 
-    private ComponentModel generateComponentModel(String json) {
-        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
-
-        ComponentModel component = new ComponentModel();
-        component.setScheme(getJSonValue("scheme", rows));
-        component.setSyntax(getJSonValue("syntax", rows));
-        component.setAlternativeSyntax(getJSonValue("alternativeSyntax", rows));
-        component.setAlternativeSchemes(getJSonValue("alternativeSchemes", rows));
-        component.setTitle(getJSonValue("title", rows));
-        component.setDescription(getJSonValue("description", rows));
-        component.setFirstVersion(getJSonValue("firstVersion", rows));
-        component.setLabel(getJSonValue("label", rows));
-        component.setDeprecated(Boolean.valueOf(getJSonValue("deprecated", rows)));
-        component.setDeprecationNote(getJSonValue("deprecationNote", rows));
-        component.setConsumerOnly(Boolean.valueOf(getJSonValue("consumerOnly", rows)));
-        component.setProducerOnly(Boolean.valueOf(getJSonValue("producerOnly", rows)));
-        component.setJavaType(getJSonValue("javaType", rows));
-        component.setGroupId(getJSonValue("groupId", rows));
-        component.setArtifactId(getJSonValue("artifactId", rows));
-        component.setVersion(getJSonValue("version", rows));
-
-        return component;
-    }
-
-    private DataFormatModel generateDataFormatModel(String json) {
-        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("dataformat", json, false);
-
-        DataFormatModel dataFormat = new DataFormatModel();
-        dataFormat.setName(getJSonValue("name", rows));
-        dataFormat.setTitle(getJSonValue("title", rows));
-        dataFormat.setModelName(getJSonValue("modelName", rows));
-        dataFormat.setDescription(getJSonValue("description", rows));
-        dataFormat.setFirstVersion(getJSonValue("firstVersion", rows));
-        dataFormat.setLabel(getJSonValue("label", rows));
-        dataFormat.setDeprecated(Boolean.valueOf(getJSonValue("deprecated", rows)));
-        dataFormat.setDeprecationNote(getJSonValue("deprecationNote", rows));
-        dataFormat.setJavaType(getJSonValue("javaType", rows));
-        dataFormat.setGroupId(getJSonValue("groupId", rows));
-        dataFormat.setArtifactId(getJSonValue("artifactId", rows));
-        dataFormat.setVersion(getJSonValue("version", rows));
-
-        return dataFormat;
-    }
-
-    private LanguageModel generateLanguageModel(String json) {
-        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("language", json, false);
-
-        LanguageModel language = new LanguageModel();
-        language.setTitle(getJSonValue("title", rows));
-        language.setName(getJSonValue("name", rows));
-        language.setModelName(getJSonValue("modelName", rows));
-        language.setDescription(getJSonValue("description", rows));
-        language.setFirstVersion(getJSonValue("firstVersion", rows));
-        language.setLabel(getJSonValue("label", rows));
-        language.setDeprecated(Boolean.valueOf(getJSonValue("deprecated", rows)));
-        language.setDeprecationNote(getJSonValue("deprecationNote", rows));
-        language.setJavaType(getJSonValue("javaType", rows));
-        language.setGroupId(getJSonValue("groupId", rows));
-        language.setArtifactId(getJSonValue("artifactId", rows));
-        language.setVersion(getJSonValue("version", rows));
-
-        return language;
-    }
-
-    private OtherModel generateOtherModel(String json) {
-        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("other", json, false);
-
-        OtherModel other = new OtherModel();
-        other.setName(getJSonValue("name", rows));
-        other.setTitle(getJSonValue("title", rows));
-        other.setDescription(getJSonValue("description", rows));
-        other.setFirstVersion(getJSonValue("firstVersion", rows));
-        other.setLabel(getJSonValue("label", rows));
-        other.setDeprecated(Boolean.valueOf(getJSonValue("deprecated", rows)));
-        other.setDeprecationNote(getJSonValue("deprecationNote", rows));
-        other.setGroupId(getJSonValue("groupId", rows));
-        other.setArtifactId(getJSonValue("artifactId", rows));
-        other.setVersion(getJSonValue("version", rows));
-
-        return other;
-    }
-
-    private String getJSonValue(String key, List<Map<String, String>> rows) {
-        for (Map<String, String> row : rows) {
-            if (row.containsKey(key)) {
-                return row.get(key);
-            }
-        }
-        return "";
-    }
-
-    private Path getExtensionsDocPath() {
-        return Paths.get(websiteDocBaseDir.toString(), "extensions");
-    }
-
 }
diff --git a/tooling/package-maven-plugin/src/main/resources/camel-quarkus-package-maven-plugin.properties b/tooling/package-maven-plugin/src/main/resources/camel-quarkus-package-maven-plugin.properties
deleted file mode 100644
index fa7a54b..0000000
--- a/tooling/package-maven-plugin/src/main/resources/camel-quarkus-package-maven-plugin.properties
+++ /dev/null
@@ -1,16 +0,0 @@
-## ---------------------------------------------------------------------------
-## 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.
-## ---------------------------------------------------------------------------
diff --git a/tooling/package-maven-plugin/src/main/resources/extension-list-templates/readme-components.ftl b/tooling/package-maven-plugin/src/main/resources/extension-list-templates/readme-components.ftl
new file mode 100644
index 0000000..b0cb97e
--- /dev/null
+++ b/tooling/package-maven-plugin/src/main/resources/extension-list-templates/readme-components.ftl
@@ -0,0 +1,14 @@
+Number of Camel components: [=components?size] in [=numberOfArtifacts] JAR artifacts ([=numberOfDeprecated] deprecated)
+
+[width="100%",cols="4,1,1,5",options="header"]
+|===
+| Component | Target +
+Level | Since | Description
+[#list components as row]
+
+| [=getDocLink(row)][[=row.title]] ([=row.artifactId]) +
+`[=row.syntax]` | [=row.target] +
+ [=row.supportLevel] | [=row.firstVersion] | [#if row.deprecated]*deprecated* [/#if][=row.description]
+[/#list]
+
+|===
diff --git a/tooling/package-maven-plugin/src/main/resources/extension-list-templates/readme-dataformats.ftl b/tooling/package-maven-plugin/src/main/resources/extension-list-templates/readme-dataformats.ftl
new file mode 100644
index 0000000..bb74b82
--- /dev/null
+++ b/tooling/package-maven-plugin/src/main/resources/extension-list-templates/readme-dataformats.ftl
@@ -0,0 +1,12 @@
+Number of Camel data formats: [=components?size] in [=numberOfArtifacts] JAR artifacts ([=numberOfDeprecated] deprecated)
+
+[width="100%",cols="4,1,1,5",options="header"]
+|===
+| Data Format | Target +
+Level | Since | Description
+[#list components as row]
+
+| [=getDocLink(row)][[=row.title]] ([=row.artifactId]) | [=row.target] +
+ [=row.supportLevel] | [=row.firstVersion] | [#if row.deprecated]*deprecated* [/#if][=row.description]
+[/#list]
+|===
diff --git a/tooling/package-maven-plugin/src/main/resources/extension-list-templates/readme-languages.ftl b/tooling/package-maven-plugin/src/main/resources/extension-list-templates/readme-languages.ftl
new file mode 100644
index 0000000..3defb57
--- /dev/null
+++ b/tooling/package-maven-plugin/src/main/resources/extension-list-templates/readme-languages.ftl
@@ -0,0 +1,12 @@
+Number of Camel languages: [=components?size] in [=numberOfArtifacts] JAR artifacts ([=numberOfDeprecated] deprecated)
+
+[width="100%",cols="4,1,1,5",options="header"]
+|===
+| Language | Target +
+Level | Since | Description
+[#list components as row]
+
+| [=getDocLink(row)][[=row.title]] ([=row.artifactId]) | [=row.target] +
+ [=row.supportLevel] | [=row.firstVersion] | [#if row.deprecated]*deprecated* [/#if][=row.description]
+[/#list]
+|===
diff --git a/tooling/package-maven-plugin/src/main/resources/extension-list-templates/readme-others.ftl b/tooling/package-maven-plugin/src/main/resources/extension-list-templates/readme-others.ftl
new file mode 100644
index 0000000..90b4669
--- /dev/null
+++ b/tooling/package-maven-plugin/src/main/resources/extension-list-templates/readme-others.ftl
@@ -0,0 +1,11 @@
+Number of miscellaneous extensions: [=components?size] in [=numberOfArtifacts] JAR artifacts ([=numberOfDeprecated] deprecated)
+
+[width="100%",cols="4,1,1,5",options="header"]
+|===
+| Extension | Target Level | Since | Description
+[#list components as row]
+
+|[#if getDocLink(row)??] [=getDocLink(row)][[=row.artifactId]] [#else] ([=row.artifactId])[/#if] | [=row.target] +
+ [=row.supportLevel] | [=row.firstVersion] | [#if row.deprecated]*deprecated* [/#if][=row.description]
+[/#list]
+|===
diff --git a/tooling/package-maven-plugin/src/main/resources/other-template.mvel b/tooling/package-maven-plugin/src/main/resources/other-template.mvel
deleted file mode 100644
index 1d57f31..0000000
--- a/tooling/package-maven-plugin/src/main/resources/other-template.mvel
+++ /dev/null
@@ -1,14 +0,0 @@
-{
- "other": {
-    "name": "@{name}",
-    "kind": "other",
-    "title": "@{title}",
-    "description": "@{description}",
-    "deprecated": @{deprecated},
-    "firstVersion": "@{firstVersion}",
-    "label": "@{label}",
-    "groupId": "@{groupId}",
-    "artifactId": "@{artifactId}",
-    "version": "@{version}"
-  }
-}
\ No newline at end of file
diff --git a/tooling/package-maven-plugin/src/main/resources/readme-components.mvel b/tooling/package-maven-plugin/src/main/resources/readme-components.mvel
deleted file mode 100644
index 581b37c..0000000
--- a/tooling/package-maven-plugin/src/main/resources/readme-components.mvel
+++ /dev/null
@@ -1,14 +0,0 @@
-@if{!components.isEmpty()}
-
-Number of Camel components: @{components.size} in @{numberOfArtifacts} JAR artifacts (@{numberOfDeprecated} deprecated)
-
-[width="100%",cols="4,1,5",options="header"]
-|===
-| Component | Since | Description
-@foreach{row : components}
-| @{util.getDocLink(row)}[@{row.title}] (@{row.artifactId}) +
-`@{row.syntax}` | @{row.firstVersion} | @if{row.deprecated == "true"}*deprecated* @end{}@{util.escape(row.description)}
-@end{}
-|===
-
-@end{}
\ No newline at end of file
diff --git a/tooling/package-maven-plugin/src/main/resources/readme-dataformats.mvel b/tooling/package-maven-plugin/src/main/resources/readme-dataformats.mvel
deleted file mode 100644
index ecfe04b..0000000
--- a/tooling/package-maven-plugin/src/main/resources/readme-dataformats.mvel
+++ /dev/null
@@ -1,12 +0,0 @@
-@if{!dataformats.isEmpty()}
-
-Number of Camel data formats: @{dataformats.size} in @{numberOfArtifacts} JAR artifacts (@{numberOfDeprecated} deprecated)
-
-[width="100%",cols="4,1,5",options="header"]
-|===
-| Data Format | Since | Description
-@foreach{row : dataformats}
-| @{util.getDocLink(row)}[@{row.title}] (@{row.artifactId}) | @{row.firstVersion} | @if{row.deprecated == "true"}*deprecated* @end{}@{util.escape(row.description)}
-@end{}|===
-
-@end{}
\ No newline at end of file
diff --git a/tooling/package-maven-plugin/src/main/resources/readme-languages.mvel b/tooling/package-maven-plugin/src/main/resources/readme-languages.mvel
deleted file mode 100644
index 5339cfe..0000000
--- a/tooling/package-maven-plugin/src/main/resources/readme-languages.mvel
+++ /dev/null
@@ -1,12 +0,0 @@
-@if{!languages.isEmpty()}
-
-Number of Camel languages: @{languages.size} in @{numberOfArtifacts} JAR artifacts (@{numberOfDeprecated} deprecated)
-
-[width="100%",cols="4,1,5",options="header"]
-|===
-| Language | Since | Description
-@foreach{row : languages}
-| @{util.getDocLink(row)}[@{row.title}] (@{row.artifactId}) | @{row.firstVersion} | @if{row.deprecated == "true"}*deprecated* @end{}@{util.escape(row.description)}
-@end{}|===
-
-@end{}
\ No newline at end of file
diff --git a/tooling/package-maven-plugin/src/main/resources/readme-others.mvel b/tooling/package-maven-plugin/src/main/resources/readme-others.mvel
deleted file mode 100644
index e627bc3..0000000
--- a/tooling/package-maven-plugin/src/main/resources/readme-others.mvel
+++ /dev/null
@@ -1,12 +0,0 @@
-@if{!others.isEmpty()}
-
-Number of miscellaneous extensions: @{others.size} in @{numberOfArtifacts} JAR artifacts (@{numberOfDeprecated} deprecated)
-
-[width="100%",cols="4,1,5",options="header"]
-|===
-| Extension | Since | Description
-@foreach{row : others}
-|@if{util.getDocLink(row) != null} @{util.getDocLink(row)}[@{row.artifactId}] @else{} (@{row.artifactId})@end{} | @{row.firstVersion} | @if{row.deprecated == "true"}*deprecated* @end{}@{util.escape(row.description)}
-@end{}|===
-
-@end{}
\ No newline at end of file
diff --git a/tooling/pom.xml b/tooling/pom.xml
index db3593f..a013662 100644
--- a/tooling/pom.xml
+++ b/tooling/pom.xml
@@ -32,23 +32,6 @@
     <name>Camel Quarkus :: Tooling</name>
     <description>Camel Quarkus Tooling Parent POM</description>
 
-    <properties>
-        <build-helper-maven-plugin.version>1.7</build-helper-maven-plugin.version>
-        <maven-version>3.6.2</maven-version>
-        <maven-maven-plugin-descriptor-version>2.2.1</maven-maven-plugin-descriptor-version>
-        <maven-project-version>2.2.1</maven-project-version>
-        <maven-dependency-tree-version>3.0.1</maven-dependency-tree-version>
-        <maven-plugin-annotations-version>3.6.0</maven-plugin-annotations-version>
-        <maven-reporting-api-version>3.0</maven-reporting-api-version>
-        <maven-reporting-impl-version>3.0.0</maven-reporting-impl-version>
-        <maven-resolver-version>1.4.1</maven-resolver-version>
-        <plexus-build-api-version>0.0.7</plexus-build-api-version>
-        <plexus-container-default-version>2.0.0</plexus-container-default-version>
-        <plexus-utils-version>3.2.1</plexus-utils-version>
-        <rpkgtests-maven-plugin.version>0.6.0</rpkgtests-maven-plugin.version>
-        <mvel.version>2.4.5.Final</mvel.version>
-    </properties>
-
     <modules>
         <module>package-maven-plugin</module>
         <module>test-list</module>
@@ -57,99 +40,14 @@
     <dependencyManagement>
         <dependencies>
             <dependency>
-                <groupId>org.apache.maven</groupId>
-                <artifactId>maven-core</artifactId>
-                <version>${maven-version}</version>
-                <exclusions>
-                    <exclusion>
-                        <groupId>org.slf4j</groupId>
-                        <artifactId>slf4j-jdk14</artifactId>
-                    </exclusion>
-                    <exclusion>
-                        <groupId>org.slf4j</groupId>
-                        <artifactId>jcl-over-slf4j</artifactId>
-                    </exclusion>
-                    <exclusion>
-                        <groupId>org.slf4j</groupId>
-                        <artifactId>slf4j-nop</artifactId>
-                    </exclusion>
-                </exclusions>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.maven</groupId>
-                <artifactId>maven-artifact</artifactId>
-                <version>${maven-version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.maven</groupId>
-                <artifactId>maven-plugin-api</artifactId>
-                <version>${maven-version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.maven</groupId>
-                <artifactId>maven-compat</artifactId>
-                <version>${maven-version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.maven.plugin-tools</groupId>
-                <artifactId>maven-plugin-annotations</artifactId>
-                <version>${maven-plugin-annotations-version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.maven</groupId>
-                <artifactId>maven-plugin-descriptor</artifactId>
-                <version>${maven-maven-plugin-descriptor-version}</version>
-                <exclusions>
-                    <exclusion>
-                        <groupId>log4j</groupId>
-                        <artifactId>log4j</artifactId>
-                    </exclusion>
-                </exclusions>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.maven</groupId>
-                <artifactId>maven-project</artifactId>
-                <version>${maven-project-version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.maven.shared</groupId>
-                <artifactId>maven-dependency-tree</artifactId>
-                <version>${maven-dependency-tree-version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.maven.reporting</groupId>
-                <artifactId>maven-reporting-api</artifactId>
-                <version>${maven-reporting-api-version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.maven.reporting</groupId>
-                <artifactId>maven-reporting-impl</artifactId>
-                <version>${maven-reporting-impl-version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.maven.resolver</groupId>
-                <artifactId>maven-resolver-api</artifactId>
-                <version>${maven-resolver-version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.apache.maven.resolver</groupId>
-                <artifactId>maven-resolver-util</artifactId>
-                <version>${maven-resolver-version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.codehaus.plexus</groupId>
-                <artifactId>plexus-container-default</artifactId>
-                <version>${plexus-container-default-version}</version>
-            </dependency>
-            <dependency>
-                <groupId>org.codehaus.plexus</groupId>
-                <artifactId>plexus-utils</artifactId>
-                <version>${plexus-utils-version}</version>
+                <groupId>com.google.code.gson</groupId>
+                <artifactId>gson</artifactId>
+                <version>${gson.version}</version>
             </dependency>
             <dependency>
-                <groupId>org.sonatype.plexus</groupId>
-                <artifactId>plexus-build-api</artifactId>
-                <version>${plexus-build-api-version}</version>
+                <groupId>org.freemarker</groupId>
+                <artifactId>freemarker</artifactId>
+                <version>${freemarker.version}</version>
             </dependency>
         </dependencies>
     </dependencyManagement>