You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by da...@apache.org on 2019/10/09 08:57:17 UTC

[camel-quarkus] branch master updated: Generate extension list readme file via tooling like we do at Apache Camel (#243)

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

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


The following commit(s) were added to refs/heads/master by this push:
     new 1c08fef  Generate extension list readme file via tooling like we do at Apache Camel (#243)
1c08fef is described below

commit 1c08fef7cbc61e21c0a9d342e3c493ade0632a8b
Author: Claus Ibsen <cl...@gmail.com>
AuthorDate: Wed Oct 9 10:57:13 2019 +0200

    Generate extension list readme file via tooling like we do at Apache Camel (#243)
    
    * Generate extension list readme file via tooling like we do at Apache Camel
    
    * Polished
    
    * Generate extension list readme file via tooling like we do at Apache Camel
    
    * Lets use firstVersion from camel-quarkus release in quarkus catalog and readme documentation.
---
 catalog/camel-quarkus-catalog/pom.xml              |   2 +
 extensions/aws-eks/runtime/pom.xml                 |   4 +
 extensions/aws-s3/runtime/pom.xml                  |   4 +
 extensions/aws-sns/runtime/pom.xml                 |   4 +
 extensions/aws-sqs/runtime/pom.xml                 |   4 +
 extensions/bean/runtime/pom.xml                    |   4 +
 extensions/csv/runtime/pom.xml                     |   4 +
 extensions/direct/runtime/pom.xml                  |   4 +
 extensions/infinispan/runtime/pom.xml              |   4 +
 extensions/jdbc/runtime/pom.xml                    |   4 +
 extensions/log/runtime/pom.xml                     |   4 +
 extensions/mail/runtime/pom.xml                    |   1 +
 extensions/microprofile-metrics/runtime/pom.xml    |   4 +
 extensions/netty-http/runtime/pom.xml              |   4 +
 extensions/paho/runtime/pom.xml                    |   4 +
 extensions/readme.adoc                             | 142 +++++
 extensions/rest/runtime/pom.xml                    |   4 +
 extensions/salesforce/runtime/pom.xml              |   4 +
 extensions/servlet/runtime/pom.xml                 |   4 +
 extensions/timer/runtime/pom.xml                   |   4 +
 extensions/twitter/runtime/pom.xml                 |   4 +
 extensions/zipfile/runtime/pom.xml                 |   4 +
 tooling/maven/package-maven-plugin/pom.xml         |   5 +
 .../camel/quarkus/maven/JSonSchemaHelper.java      | 206 +++++++
 .../org/apache/camel/quarkus/maven/MvelHelper.java |  46 ++
 .../apache/camel/quarkus/maven/PackageHelper.java  |  29 -
 .../quarkus/maven/PrepareCatalogQuarkusMojo.java   |  51 +-
 .../quarkus/maven/PrepareExtensionsReadmeMojo.java | 676 +++++++++++++++++++++
 .../{PackageHelper.java => StringHelper.java}      |  89 +--
 .../camel/quarkus/maven/model/ComponentModel.java  | 190 ++++++
 .../camel/quarkus/maven/model/DataFormatModel.java | 155 +++++
 .../camel/quarkus/maven/model/LanguageModel.java   | 155 +++++
 .../camel/quarkus/maven/model/OtherModel.java      | 145 +++++
 .../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 +
 37 files changed, 1930 insertions(+), 88 deletions(-)

diff --git a/catalog/camel-quarkus-catalog/pom.xml b/catalog/camel-quarkus-catalog/pom.xml
index 4d2c64d..7ce0e6e 100644
--- a/catalog/camel-quarkus-catalog/pom.xml
+++ b/catalog/camel-quarkus-catalog/pom.xml
@@ -86,8 +86,10 @@
                 </dependencies>
                 <executions>
                     <execution>
+                        <!-- prepare the catalog, readme files, etc. -->
                         <goals>
                             <goal>prepare-catalog-quarkus</goal>
+                            <goal>prepare-extensions-readme</goal>
                         </goals>
                         <phase>process-resources</phase>
                     </execution>
diff --git a/extensions/aws-eks/runtime/pom.xml b/extensions/aws-eks/runtime/pom.xml
index 1dd882d..7835957 100644
--- a/extensions/aws-eks/runtime/pom.xml
+++ b/extensions/aws-eks/runtime/pom.xml
@@ -28,6 +28,10 @@
     <artifactId>camel-quarkus-aws-eks</artifactId>
     <name>Camel Quarkus :: AWS EKS :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/aws-s3/runtime/pom.xml b/extensions/aws-s3/runtime/pom.xml
index 7205d07..cab552b 100644
--- a/extensions/aws-s3/runtime/pom.xml
+++ b/extensions/aws-s3/runtime/pom.xml
@@ -28,6 +28,10 @@
     <artifactId>camel-quarkus-aws-s3</artifactId>
     <name>Camel Quarkus :: AWS S3 :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/aws-sns/runtime/pom.xml b/extensions/aws-sns/runtime/pom.xml
index 18cfa48..8ddffaa 100644
--- a/extensions/aws-sns/runtime/pom.xml
+++ b/extensions/aws-sns/runtime/pom.xml
@@ -28,6 +28,10 @@
     <artifactId>camel-quarkus-aws-sns</artifactId>
     <name>Camel Quarkus :: AWS SNS :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/aws-sqs/runtime/pom.xml b/extensions/aws-sqs/runtime/pom.xml
index 112df66..f8e1f69 100644
--- a/extensions/aws-sqs/runtime/pom.xml
+++ b/extensions/aws-sqs/runtime/pom.xml
@@ -28,6 +28,10 @@
     <artifactId>camel-quarkus-aws-sqs</artifactId>
     <name>Camel Quarkus :: AWS SQS :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/bean/runtime/pom.xml b/extensions/bean/runtime/pom.xml
index 1bc6c4a..6cbe8aa 100644
--- a/extensions/bean/runtime/pom.xml
+++ b/extensions/bean/runtime/pom.xml
@@ -29,6 +29,10 @@
     <artifactId>camel-quarkus-bean</artifactId>
     <name>Camel Quarkus :: Bean :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/csv/runtime/pom.xml b/extensions/csv/runtime/pom.xml
index e0c66ed..af39fbb 100644
--- a/extensions/csv/runtime/pom.xml
+++ b/extensions/csv/runtime/pom.xml
@@ -29,6 +29,10 @@
     <artifactId>camel-quarkus-csv</artifactId>
     <name>Camel Quarkus :: CSV :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/direct/runtime/pom.xml b/extensions/direct/runtime/pom.xml
index d01e480..1e6dc7d 100644
--- a/extensions/direct/runtime/pom.xml
+++ b/extensions/direct/runtime/pom.xml
@@ -29,6 +29,10 @@
     <artifactId>camel-quarkus-direct</artifactId>
     <name>Camel Quarkus :: Direct :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/infinispan/runtime/pom.xml b/extensions/infinispan/runtime/pom.xml
index 1d12979..977e07c 100644
--- a/extensions/infinispan/runtime/pom.xml
+++ b/extensions/infinispan/runtime/pom.xml
@@ -28,6 +28,10 @@
     <artifactId>camel-quarkus-infinispan</artifactId>
     <name>Camel Quarkus :: Infinispan :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/jdbc/runtime/pom.xml b/extensions/jdbc/runtime/pom.xml
index 6c52175..b2fbeea 100644
--- a/extensions/jdbc/runtime/pom.xml
+++ b/extensions/jdbc/runtime/pom.xml
@@ -28,6 +28,10 @@
     <artifactId>camel-quarkus-jdbc</artifactId>
     <name>Camel Quarkus :: JDBC :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/log/runtime/pom.xml b/extensions/log/runtime/pom.xml
index a343a49..b123a67 100644
--- a/extensions/log/runtime/pom.xml
+++ b/extensions/log/runtime/pom.xml
@@ -29,6 +29,10 @@
     <artifactId>camel-quarkus-log</artifactId>
     <name>Camel Quarkus :: Log :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/mail/runtime/pom.xml b/extensions/mail/runtime/pom.xml
index 7ad876e..14fbe04 100644
--- a/extensions/mail/runtime/pom.xml
+++ b/extensions/mail/runtime/pom.xml
@@ -13,6 +13,7 @@
 
     <properties>
         <jakarta-mail-version>1.6.4</jakarta-mail-version>
+        <firstVersion>0.2.0</firstVersion>
     </properties>
 
     <dependencyManagement>
diff --git a/extensions/microprofile-metrics/runtime/pom.xml b/extensions/microprofile-metrics/runtime/pom.xml
index ad9f536..b581f73 100644
--- a/extensions/microprofile-metrics/runtime/pom.xml
+++ b/extensions/microprofile-metrics/runtime/pom.xml
@@ -29,6 +29,10 @@
     <artifactId>camel-quarkus-microprofile-metrics</artifactId>
     <name>Camel Quarkus :: MicroProfile Metrics :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/netty-http/runtime/pom.xml b/extensions/netty-http/runtime/pom.xml
index 444370d..3c28faf 100644
--- a/extensions/netty-http/runtime/pom.xml
+++ b/extensions/netty-http/runtime/pom.xml
@@ -28,6 +28,10 @@
     <artifactId>camel-quarkus-netty-http</artifactId>
     <name>Camel Quarkus :: Netty HTTP :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/paho/runtime/pom.xml b/extensions/paho/runtime/pom.xml
index 231fe72..6b9b3b6 100644
--- a/extensions/paho/runtime/pom.xml
+++ b/extensions/paho/runtime/pom.xml
@@ -29,6 +29,10 @@
     <artifactId>camel-quarkus-paho</artifactId>
     <name>Camel Quarkus :: Paho :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/readme.adoc b/extensions/readme.adoc
new file mode 100644
index 0000000..6faca8b
--- /dev/null
+++ b/extensions/readme.adoc
@@ -0,0 +1,142 @@
+= Components
+
+// components: START
+Number of Components: 22 in 18 JAR artifacts (0 deprecated)
+
+[width="100%",cols="4,1,5",options="header"]
+|===
+| Component | Available From | Description
+
+| link:https://camel.apache.org/components/latest/aws-eks-component.html[AWS EKS] (camel-quarkus-aws-eks) +
+`aws-eks:label` | 0.2 | The aws-kms is used for managing Amazon EKS
+
+| link:https://camel.apache.org/components/latest/aws-s3-component.html[AWS S3 Storage Service] (camel-quarkus-aws-s3) +
+`aws-s3://bucketNameOrArn` | 0.2 | 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 | 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 | The aws-sqs component is used for sending and receiving messages to Amazon's SQS service.
+
+| link:https://camel.apache.org/components/latest/bean-component.html[Bean] (camel-quarkus-bean) +
+`bean:beanName` | 0.2 | The bean component is for invoking Java beans from Camel.
+
+| link:https://camel.apache.org/components/latest/class-component.html[Class] (camel-quarkus-bean) +
+`class:beanName` | 0.2 | The class component is for invoking Java classes (Java beans) from Camel.
+
+| link:https://camel.apache.org/components/latest/direct-component.html[Direct] (camel-quarkus-direct) +
+`direct:name` | 0.2 | The direct component provides direct, synchronous call to another endpoint from the same CamelContext.
+
+| link:https://camel.apache.org/components/latest/infinispan-component.html[Infinispan] (camel-quarkus-infinispan) +
+`infinispan:cacheName` | 0.2 | For reading/writing from/to Infinispan distributed key/value store and data grid.
+
+| link:https://camel.apache.org/components/latest/jdbc-component.html[JDBC] (camel-quarkus-jdbc) +
+`jdbc:dataSourceName` | 0.2 | 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/log-component.html[Log] (camel-quarkus-log) +
+`log:loggerName` | 0.2 | 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 | To send or receive emails using imap/pop3 or smtp protocols.
+
+| link:https://camel.apache.org/components/latest/microprofile-metrics-component.html[MicroProfile Metrics] (camel-quarkus-microprofile-metrics) +
+`microprofile-metrics:metricType:metricName` | 0.2 | Camel metrics exposed with Eclipse MicroProfile Metrics
+
+| link:https://camel.apache.org/components/latest/netty-http-component.html[Netty HTTP] (camel-quarkus-netty-http) +
+`netty-http:protocol:host:port/path` | 0.2 | Netty HTTP server and client using the Netty 4.x library.
+
+| link:https://camel.apache.org/components/latest/paho-component.html[Paho] (camel-quarkus-paho) +
+`paho:topic` | 0.2 | Component for communicating with MQTT M2M message brokers using Eclipse Paho MQTT Client.
+
+| link:https://camel.apache.org/components/latest/rest-component.html[REST] (camel-quarkus-rest) +
+`rest:method:path:uriTemplate` | 0.2 | 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 | 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 | The salesforce component is used for integrating Camel with the massive Salesforce API.
+
+| link:https://camel.apache.org/components/latest/servlet-component.html[Servlet] (camel-quarkus-servlet) +
+`servlet:contextPath` | 0.2 | To use a HTTP Servlet as entry for Camel routes when running in a servlet container.
+
+| link:https://camel.apache.org/components/latest/timer-component.html[Timer] (camel-quarkus-timer) +
+`timer:timerName` | 0.2 | 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 | 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 | 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 | The Twitter Timeline component consumes twitter timeline or update the status of specific user.
+
+|===
+// components: END
+
+
+== Data Formats
+
+// dataformats: START
+Number of Data Formats: 3 in 3 JAR artifacts (0 deprecated)
+
+[width="100%",cols="4,1,5",options="header"]
+|===
+| Data Format | Available From | Description
+
+| link:https://camel.apache.org/components/latest/csv-dataformat.html[CSV] (camel-quarkus-csv) | 0.2 | The CSV data format is used for handling CSV payloads.
+
+| link:https://camel.apache.org/components/latest/mime-multipart-dataformat.html[MIME Multipart] (camel-quarkus-mail) | 0.2 | The MIME Multipart data format can marshal a Camel message with attachments into a Camel message having a MIME-Multipart message as message body (and no attachments), and vise-versa when unmarshalling.
+
+| link:https://camel.apache.org/components/latest/zipfile-dataformat.html[Zip File] (camel-quarkus-zipfile) | 0.2 | The Zip File data format is a message compression and de-compression format of zip files.
+|===
+// dataformats: END
+
+
+== Expression Languages
+
+// languages: START
+Number of Languages: 8 in 2 JAR artifacts (0 deprecated)
+
+[width="100%",cols="4,1,5",options="header"]
+|===
+| Language | Available From | Description
+
+| link:https://camel.apache.org/components/latest/bean-language.html[Bean method] (camel-quarkus-bean) | 0.2 | 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 | 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 | 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 | 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 | To use a Camel Message header in expressions or predicates.
+
+| link:https://camel.apache.org/components/latest/ref-language.html[Ref] (camel-quarkus-core) | 0.2 | 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 | 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 | To use Camel message body or header with a tokenizer in Camel expressions or predicates.
+|===
+// languages: END
+
+
+== Miscellaneous Components
+
+// others: START
+Number of Miscellaneous Components: 3 in 3 JAR artifacts (0 deprecated)
+
+[width="100%",cols="4,1,5",options="header"]
+|===
+| Component | Available From | Description
+
+| (camel-quarkus-core-cloud) | 0.2 | The Camel Quarkus core cloud module
+
+| (camel-quarkus-platform-http) | 0.2.1 | HTTP platform component is used for integrating Camel HTTP with Quarkus HTTP layer
+
+| (camel-quarkus-reactive-executor) | 0.2.1 | To use Quarkus reactive executor with Camel
+|===
+// others: END
+
diff --git a/extensions/rest/runtime/pom.xml b/extensions/rest/runtime/pom.xml
index 61ba4f0..bc4e03d 100644
--- a/extensions/rest/runtime/pom.xml
+++ b/extensions/rest/runtime/pom.xml
@@ -29,6 +29,10 @@
     <artifactId>camel-quarkus-rest</artifactId>
     <name>Camel Quarkus :: Rest :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/salesforce/runtime/pom.xml b/extensions/salesforce/runtime/pom.xml
index b707f3f..2c2cbf9 100644
--- a/extensions/salesforce/runtime/pom.xml
+++ b/extensions/salesforce/runtime/pom.xml
@@ -28,6 +28,10 @@
     <artifactId>camel-quarkus-salesforce</artifactId>
     <name>Camel Quarkus :: Salesforce :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/servlet/runtime/pom.xml b/extensions/servlet/runtime/pom.xml
index 4932696..ccf780b 100644
--- a/extensions/servlet/runtime/pom.xml
+++ b/extensions/servlet/runtime/pom.xml
@@ -28,6 +28,10 @@
     <artifactId>camel-quarkus-servlet</artifactId>
     <name>Camel Quarkus :: Servlet :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/timer/runtime/pom.xml b/extensions/timer/runtime/pom.xml
index 5187bb7..685d252 100644
--- a/extensions/timer/runtime/pom.xml
+++ b/extensions/timer/runtime/pom.xml
@@ -29,6 +29,10 @@
     <artifactId>camel-quarkus-timer</artifactId>
     <name>Camel Quarkus :: Timer :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/twitter/runtime/pom.xml b/extensions/twitter/runtime/pom.xml
index 1b3fec6..79f78be 100644
--- a/extensions/twitter/runtime/pom.xml
+++ b/extensions/twitter/runtime/pom.xml
@@ -29,6 +29,10 @@
     <artifactId>camel-quarkus-twitter</artifactId>
     <name>Camel Quarkus :: Twitter :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/extensions/zipfile/runtime/pom.xml b/extensions/zipfile/runtime/pom.xml
index eddac77..5ba982b 100644
--- a/extensions/zipfile/runtime/pom.xml
+++ b/extensions/zipfile/runtime/pom.xml
@@ -29,6 +29,10 @@
     <artifactId>camel-quarkus-zipfile</artifactId>
     <name>Camel Quarkus :: ZipFile :: Runtime</name>
 
+    <properties>
+        <firstVersion>0.2.0</firstVersion>
+    </properties>
+
     <dependencyManagement>
         <dependencies>
             <dependency>
diff --git a/tooling/maven/package-maven-plugin/pom.xml b/tooling/maven/package-maven-plugin/pom.xml
index 4130638..d9a1878 100644
--- a/tooling/maven/package-maven-plugin/pom.xml
+++ b/tooling/maven/package-maven-plugin/pom.xml
@@ -86,6 +86,11 @@
         </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>2.4.4.Final</version>
diff --git a/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/JSonSchemaHelper.java b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/JSonSchemaHelper.java
new file mode 100644
index 0000000..22ad577
--- /dev/null
+++ b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/JSonSchemaHelper.java
@@ -0,0 +1,206 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.maven;
+
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+
+import org.apache.camel.util.json.JsonObject;
+import org.apache.camel.util.json.Jsoner;
+
+public final class JSonSchemaHelper {
+
+    private JSonSchemaHelper() {
+    }
+
+    /**
+     * 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
+     */
+    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<String, String> 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
+            .replaceAll("\\\\r", "\\\\\\r")
+            .replaceAll("\\\\n", "\\\\\\n")
+            .replaceAll("\\\\t", "\\\\\\t");
+    }
+
+    /**
+     * Gets the value with the key in a safe way, eg returning an empty string if there was no value for the key.
+     */
+    public static String getSafeValue(String key, List<Map<String, String>> rows) {
+        for (Map<String, String> row : rows) {
+            String value = row.get(key);
+            if (value != null) {
+                return value;
+            }
+        }
+        return "";
+    }
+
+    /**
+     * Gets the value with the key in a safe way, eg returning an empty string if there was no value for the key.
+     */
+    public static String getSafeValue(String key, Map<String, String> rows) {
+        String value = rows.get(key);
+        if (value != null) {
+            return value;
+        }
+        return "";
+    }
+
+    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.equals(row.get("name"));
+            }
+            if (row.containsKey("defaultValue")) {
+                defaultValue = row.get("defaultValue");
+            }
+            if (found) {
+                return defaultValue;
+            }
+        }
+        return null;
+    }
+
+    public static String getPropertyDescriptionValue(List<Map<String, String>> rows, String name) {
+        for (Map<String, String> row : rows) {
+            String description = null;
+            boolean found = false;
+            if (row.containsKey("name")) {
+                found = name.equals(row.get("name"));
+            }
+            if (row.containsKey("description")) {
+                description = row.get("description");
+            }
+            if (found) {
+                return description;
+            }
+        }
+        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.equals(row.get("name"));
+            }
+            if (row.containsKey("javaType")) {
+                javaType = row.get("javaType");
+            }
+            if (found) {
+                return javaType;
+            }
+        }
+        return null;
+    }
+
+    public static String getPropertyType(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.equals(row.get("name"));
+            }
+            if (row.containsKey("type")) {
+                type = row.get("type");
+            }
+            if (found) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+}
diff --git a/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/MvelHelper.java b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/MvelHelper.java
new file mode 100644
index 0000000..6ecb3fc
--- /dev/null
+++ b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/MvelHelper.java
@@ -0,0 +1,46 @@
+/*
+ * 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.regex.Pattern;
+
+public final class MvelHelper {
+
+    public static final MvelHelper INSTANCE = new MvelHelper();
+
+    private static final Pattern DOLLAR_ESCAPE = Pattern.compile("\\$");
+
+    private static final Pattern CURLY_BRACKET_ESCAPE = Pattern.compile("(\\{[a-zA-Z0-9]+?)\\}");
+
+    private static final Pattern URL_ESCAPE = Pattern.compile("(?<!href=\")(http(:?s)?://|(:?s)?ftp(?:s)?)");
+
+    private MvelHelper() {
+        // utility class
+    }
+
+    public static String escape(final String raw) {
+        if (raw == null) {
+            return null;
+        }
+
+        final String escapedDollars = DOLLAR_ESCAPE.matcher(raw).replaceAll("\\\\\\$");
+        final String escapedCurlyBrackets = CURLY_BRACKET_ESCAPE.matcher(escapedDollars).replaceAll("\\\\$1\\\\}");
+        final String escapedUrls = URL_ESCAPE.matcher(escapedCurlyBrackets).replaceAll("\\\\$1");
+
+        return escapedUrls;
+    }
+}
diff --git a/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PackageHelper.java b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PackageHelper.java
index 65b4355..15f4e9f 100644
--- a/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PackageHelper.java
+++ b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PackageHelper.java
@@ -58,35 +58,6 @@ public final class PackageHelper {
         }
     }
 
-    /**
-     * Converts the value to use title style instead of dash cased
-     */
-    public static String camelDashToTitle(String value) {
-        StringBuilder sb = new StringBuilder(value.length());
-        boolean dash = false;
-
-        for (char c : value.toCharArray()) {
-            if ('-' == c) {
-                dash = true;
-                continue;
-            }
-
-            if (dash) {
-                sb.append(' ');
-                sb.append(Character.toUpperCase(c));
-            } else {
-                // upper case first
-                if (sb.length() == 0) {
-                    sb.append(Character.toUpperCase(c));
-                } else {
-                    sb.append(c);
-                }
-            }
-            dash = false;
-        }
-        return sb.toString();
-    }
-
     public static void writeText(File file, String text) throws IOException {
         FileOutputStream fos = new FileOutputStream(file, false);
         try {
diff --git a/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PrepareCatalogQuarkusMojo.java b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PrepareCatalogQuarkusMojo.java
index 906d72b..b59ccdd 100644
--- a/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PrepareCatalogQuarkusMojo.java
+++ b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PrepareCatalogQuarkusMojo.java
@@ -50,9 +50,9 @@ import org.apache.maven.project.ProjectBuildingResult;
 import org.apache.maven.repository.RepositorySystem;
 import org.mvel2.templates.TemplateRuntime;
 
-import static org.apache.camel.quarkus.maven.PackageHelper.camelDashToTitle;
 import static org.apache.camel.quarkus.maven.PackageHelper.loadText;
 import static org.apache.camel.quarkus.maven.PackageHelper.writeText;
+import static org.apache.camel.quarkus.maven.StringHelper.camelDashToTitle;
 
 /**
  * Prepares the Quarkus provider camel catalog to include component it supports
@@ -60,6 +60,8 @@ import static org.apache.camel.quarkus.maven.PackageHelper.writeText;
 @Mojo(name = "prepare-catalog-quarkus", threadSafe = true, requiresDependencyCollection = ResolutionScope.COMPILE_PLUS_RUNTIME)
 public class PrepareCatalogQuarkusMojo extends AbstractMojo {
 
+    private static final String DEFAULT_FIRST_VERSION = "0.2.0";
+
     private static final String[] EXCLUDE_EXTENSIONS = {
             "http-common", "jetty-common", "support", "xml-common", "xstream-common"
     };
@@ -69,6 +71,7 @@ public class PrepareCatalogQuarkusMojo extends AbstractMojo {
     private static final Pattern GROUP_PATTERN = Pattern.compile("\"groupId\": \"(org.apache.camel)\"");
     private static final Pattern ARTIFACT_PATTERN = Pattern.compile("\"artifactId\": \"camel-(.*)\"");
     private static final Pattern VERSION_PATTERN = Pattern.compile("\"version\": \"(.*)\"");
+    private static final Pattern FIRST_VERSION_PATTERN = Pattern.compile("\"firstVersion\": \"(.*)\"");
 
     /**
      * The maven project.
@@ -196,6 +199,30 @@ public class PrepareCatalogQuarkusMojo extends AbstractMojo {
                     String text = loadText(is);
                     boolean match = text.contains("\"artifactId\": \"" + artifactId + "\"");
                     if (match) {
+                        try {
+                            String qaid;
+                            if ("camel-base".equals(artifactId)) {
+                                qaid = "camel-quarkus-core";
+                            } else {
+                                qaid = artifactId.replaceFirst("camel-", "camel-quarkus-");
+                            }
+                            MavenProject extPom = getMavenProject("org.apache.camel.quarkus", qaid, project.getVersion());
+                            String firstVersion = (String) extPom.getProperties().getOrDefault("firstVersion", DEFAULT_FIRST_VERSION);
+                            // lets use the camel-quarkus version as first version instead of Apache Camel version
+                            text = FIRST_VERSION_PATTERN.matcher(text).replaceFirst("\"firstVersion\": \"" + firstVersion + "\"");
+
+                            // update json metadata to adapt to camel-quarkus-catalog
+                            text = GROUP_PATTERN.matcher(text).replaceFirst("\"groupId\": \"org.apache.camel.quarkus\"");
+                            if ("camel-base".equals(artifactId)) {
+                                text = ARTIFACT_PATTERN.matcher(text).replaceFirst("\"artifactId\": \"camel-quarkus-core\"");
+                            } else {
+                                text = ARTIFACT_PATTERN.matcher(text).replaceFirst("\"artifactId\": \"camel-quarkus-$1\"");
+                            }
+                            text = VERSION_PATTERN.matcher(text).replaceFirst("\"version\": \"" + project.getVersion() + "\"");
+                        } catch (ProjectBuildingException e) {
+                            throw new MojoFailureException("Error loading pom.xml from extension " + name, e);
+                        }
+
                         jsonFiles.add(text);
                     }
                 }
@@ -204,32 +231,26 @@ public class PrepareCatalogQuarkusMojo extends AbstractMojo {
             }
 
             for (String text : jsonFiles) {
-                text = GROUP_PATTERN.matcher(text).replaceFirst("\"groupId\": \"org.apache.camel.quarkus\"");
-                if ("camel-base".equals(artifactId)) {
-                    text = ARTIFACT_PATTERN.matcher(text).replaceFirst("\"artifactId\": \"camel-quarkus-core\"");
-                } else {
-                    text = ARTIFACT_PATTERN.matcher(text).replaceFirst("\"artifactId\": \"camel-quarkus-$1\"");
-                }
-                text = VERSION_PATTERN.matcher(text).replaceFirst("\"version\": \"" + project.getVersion() + "\"");
-
-                Pattern pattern = null;
+                // compute the name depending on what kind it is
+                Pattern pattern;
                 if ("components".equals(kind)) {
                     pattern = SCHEME_PATTERN;
                 } else if ("languages".equals(kind)) {
                     pattern = NAME_PATTERN;
                 } else if ("dataformats".equals(kind)) {
                     pattern = NAME_PATTERN;
+                } else {
+                    throw new IllegalArgumentException("Unknown kind " + kind);
                 }
 
                 Matcher matcher = pattern.matcher(text);
                 if (matcher.find()) {
-                    String scheme = matcher.group(1);
-
+                    String name = matcher.group(1);
                     try {
-                        File to = new File(outsDir, scheme + ".json");
+                        File to = new File(outsDir, name + ".json");
                         writeText(to, text);
                     } catch (IOException e) {
-                        throw new MojoFailureException("Cannot write json file " + scheme, e);
+                        throw new MojoFailureException("Cannot write json file " + name, e);
                     }
                 }
             }
@@ -292,7 +313,7 @@ public class PrepareCatalogQuarkusMojo extends AbstractMojo {
                 } else {
                     model.put("deprecated", "false");
                 }
-                model.put("firstVersion", extPom.getProperties().getOrDefault("firstVersion", "1.0.0"));
+                model.put("firstVersion", extPom.getProperties().getOrDefault("firstVersion", "0.2.0"));
                 model.put("label", extPom.getProperties().getOrDefault("label", "quarkus"));
                 model.put("groupId", "org.apache.camel.quarkus");
                 model.put("artifactId", "camel-quarkus-" + extension);
diff --git a/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PrepareExtensionsReadmeMojo.java b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PrepareExtensionsReadmeMojo.java
new file mode 100644
index 0000000..e9ee00a
--- /dev/null
+++ b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PrepareExtensionsReadmeMojo.java
@@ -0,0 +1,676 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.maven;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+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 org.apache.camel.quarkus.maven.model.ComponentModel;
+import org.apache.camel.quarkus.maven.model.DataFormatModel;
+import org.apache.camel.quarkus.maven.model.LanguageModel;
+import org.apache.camel.quarkus.maven.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 java.util.stream.Collectors.toSet;
+import static org.apache.camel.quarkus.maven.PackageHelper.loadText;
+import static org.apache.camel.quarkus.maven.PackageHelper.writeText;
+
+/**
+ * Prepares the extensions/readme.adoc files content up to date with all the extensions that Apache Camel Quarkus ships.
+ */
+@Mojo(name = "prepare-extensions-readme", threadSafe = true)
+public class PrepareExtensionsReadmeMojo 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;
+
+    /**
+     * The directory for data formats catalog
+     */
+    @Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/quarkus/dataformats")
+    protected File dataFormatsDir;
+
+    /**
+     * The directory for languages catalog
+     */
+    @Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/quarkus/languages")
+    protected File languagesDir;
+
+    /**
+     * The directory for others catalog
+     */
+    @Parameter(defaultValue = "${project.build.directory}/classes/org/apache/camel/catalog/quarkus/others")
+    protected File othersDir;
+
+    /**
+     * The directory for components
+     */
+    @Parameter(defaultValue = "${project.directory}/../../../extensions")
+    protected File readmeComponentsDir;
+
+    /**
+     * Maven ProjectHelper.
+     */
+    @Component
+    private MavenProjectHelper projectHelper;
+
+    /**
+     * 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 {
+        // update readme file in extensions
+        executeComponentsReadme();
+        executeLanguagesReadme();
+        executeDataFormatsReadme();
+        executeOthersReadme();
+    }
+
+    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(o -> "true".equals(o.getDeprecated()))
+                    .count();
+
+            // update the big readme file in the components dir
+            File file = new File(readmeComponentsDir, "readme.adoc");
+
+            // update regular components
+            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);
+            }
+
+        } catch (IOException e) {
+            throw new MojoFailureException("Error due " + e.getMessage(), e);
+        }
+    }
+
+    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));
+            }
+        }
+
+        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(c -> "true".equals(c.getDeprecated()))
+                    .count();
+
+            // update the big readme file in the core/components dir
+            File file;
+            file = new File(readmeComponentsDir, "readme.adoc");
+
+            // update regular components
+            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);
+            }
+
+        } 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)
+                        .collect(toSet()).size();
+
+            // how many deprecated
+            long deprecated = models.stream()
+                    .filter(m -> "true".equals(m.getDeprecated()))
+                    .count();
+
+            // filter out camel-core
+            List<DataFormatModel> dataFormats = new ArrayList<>();
+            for (DataFormatModel model : models) {
+                dataFormats.add(model);
+            }
+
+            // update the big readme file in the core/components dir
+            File file;
+            file = new File(readmeComponentsDir, "readme.adoc");
+
+            // update regular data formats
+            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);
+            }
+
+        } 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));
+            }
+        }
+
+        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(l -> "true".equals(l.getDeprecated()))
+                    .count();
+
+            // update the big readme file in the core/components dir
+            File file;
+            file = new File(readmeComponentsDir, "readme.adoc");
+
+            // update regular data formats
+            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);
+            }
+
+        } 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(PrepareExtensionsReadmeMojo.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", MvelHelper.INSTANCE));
+            return out;
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
+        }
+    }
+
+    private String templateOthers(List<OtherModel> models, int artifacts, long deprecated) throws MojoExecutionException {
+        try {
+            String template = loadText(PrepareExtensionsReadmeMojo.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", MvelHelper.INSTANCE));
+            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(PrepareExtensionsReadmeMojo.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", MvelHelper.INSTANCE));
+            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(PrepareExtensionsReadmeMojo.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", MvelHelper.INSTANCE));
+            return out;
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error processing mvel template. Reason: " + e, e);
+        }
+    }
+
+    private boolean updateComponents(File file, String changed) throws MojoExecutionException {
+        if (!file.exists()) {
+            return false;
+        }
+
+        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;
+                }
+            } 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;
+            }
+        } 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;
+                }
+            } 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;
+            }
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error reading file " + file + " Reason: " + e, e);
+        }
+    }
+
+    private boolean updateDataFormats(File file, String changed) throws MojoExecutionException {
+        if (!file.exists()) {
+            return false;
+        }
+
+        try {
+            String text = loadText(new FileInputStream(file));
+
+            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;
+        }
+
+        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 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 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 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 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 ComponentModel generateComponentModel(String json) {
+        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("component", json, false);
+
+        ComponentModel component = new ComponentModel();
+        component.setScheme(JSonSchemaHelper.getSafeValue("scheme", rows));
+        component.setSyntax(JSonSchemaHelper.getSafeValue("syntax", rows));
+        component.setAlternativeSyntax(JSonSchemaHelper.getSafeValue("alternativeSyntax", rows));
+        component.setAlternativeSchemes(JSonSchemaHelper.getSafeValue("alternativeSchemes", rows));
+        component.setTitle(JSonSchemaHelper.getSafeValue("title", rows));
+        component.setDescription(JSonSchemaHelper.getSafeValue("description", rows));
+        component.setFirstVersion(JSonSchemaHelper.getSafeValue("firstVersion", rows));
+        component.setLabel(JSonSchemaHelper.getSafeValue("label", rows));
+        component.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", rows));
+        component.setDeprecationNote(JSonSchemaHelper.getSafeValue("deprecationNote", rows));
+        component.setConsumerOnly(JSonSchemaHelper.getSafeValue("consumerOnly", rows));
+        component.setProducerOnly(JSonSchemaHelper.getSafeValue("producerOnly", rows));
+        component.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows));
+        component.setGroupId(JSonSchemaHelper.getSafeValue("groupId", rows));
+        component.setArtifactId(JSonSchemaHelper.getSafeValue("artifactId", rows));
+        component.setVersion(JSonSchemaHelper.getSafeValue("version", rows));
+
+        return component;
+    }
+
+    private OtherModel generateOtherModel(String json) {
+        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("other", json, false);
+
+        OtherModel other = new OtherModel();
+        other.setName(JSonSchemaHelper.getSafeValue("name", rows));
+        other.setTitle(JSonSchemaHelper.getSafeValue("title", rows));
+        other.setDescription(JSonSchemaHelper.getSafeValue("description", rows));
+        other.setFirstVersion(JSonSchemaHelper.getSafeValue("firstVersion", rows));
+        other.setLabel(JSonSchemaHelper.getSafeValue("label", rows));
+        other.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", rows));
+        other.setDeprecationNote(JSonSchemaHelper.getSafeValue("deprecationNote", rows));
+        other.setGroupId(JSonSchemaHelper.getSafeValue("groupId", rows));
+        other.setArtifactId(JSonSchemaHelper.getSafeValue("artifactId", rows));
+        other.setVersion(JSonSchemaHelper.getSafeValue("version", rows));
+
+        return other;
+    }
+
+    private DataFormatModel generateDataFormatModel(String json) {
+        List<Map<String, String>> rows = JSonSchemaHelper.parseJsonSchema("dataformat", json, false);
+
+        DataFormatModel dataFormat = new DataFormatModel();
+        dataFormat.setName(JSonSchemaHelper.getSafeValue("name", rows));
+        dataFormat.setTitle(JSonSchemaHelper.getSafeValue("title", rows));
+        dataFormat.setModelName(JSonSchemaHelper.getSafeValue("modelName", rows));
+        dataFormat.setDescription(JSonSchemaHelper.getSafeValue("description", rows));
+        dataFormat.setFirstVersion(JSonSchemaHelper.getSafeValue("firstVersion", rows));
+        dataFormat.setLabel(JSonSchemaHelper.getSafeValue("label", rows));
+        dataFormat.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", rows));
+        dataFormat.setDeprecationNote(JSonSchemaHelper.getSafeValue("deprecationNote", rows));
+        dataFormat.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows));
+        dataFormat.setGroupId(JSonSchemaHelper.getSafeValue("groupId", rows));
+        dataFormat.setArtifactId(JSonSchemaHelper.getSafeValue("artifactId", rows));
+        dataFormat.setVersion(JSonSchemaHelper.getSafeValue("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(JSonSchemaHelper.getSafeValue("title", rows));
+        language.setName(JSonSchemaHelper.getSafeValue("name", rows));
+        language.setModelName(JSonSchemaHelper.getSafeValue("modelName", rows));
+        language.setDescription(JSonSchemaHelper.getSafeValue("description", rows));
+        language.setFirstVersion(JSonSchemaHelper.getSafeValue("firstVersion", rows));
+        language.setLabel(JSonSchemaHelper.getSafeValue("label", rows));
+        language.setDeprecated(JSonSchemaHelper.getSafeValue("deprecated", rows));
+        language.setDeprecationNote(JSonSchemaHelper.getSafeValue("deprecationNote", rows));
+        language.setJavaType(JSonSchemaHelper.getSafeValue("javaType", rows));
+        language.setGroupId(JSonSchemaHelper.getSafeValue("groupId", rows));
+        language.setArtifactId(JSonSchemaHelper.getSafeValue("artifactId", rows));
+        language.setVersion(JSonSchemaHelper.getSafeValue("version", rows));
+
+        return language;
+    }
+
+}
diff --git a/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PackageHelper.java b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/StringHelper.java
similarity index 52%
copy from tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PackageHelper.java
copy to tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/StringHelper.java
index 65b4355..bcc16a7 100644
--- a/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/PackageHelper.java
+++ b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/StringHelper.java
@@ -16,46 +16,57 @@
  */
 package org.apache.camel.quarkus.maven;
 
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.LineNumberReader;
+public final class StringHelper {
 
-public final class PackageHelper {
+    private StringHelper() {
+        // Utils Class
+    }
+
+    public static String after(String text, String after) {
+        if (!text.contains(after)) {
+            return null;
+        }
+        return text.substring(text.indexOf(after) + after.length());
+    }
+
+    public static String before(String text, String before) {
+        if (!text.contains(before)) {
+            return null;
+        }
+        return text.substring(0, text.indexOf(before));
+    }
 
-    private PackageHelper() {
+    public static String between(String text, String after, String before) {
+        text = after(text, after);
+        if (text == null) {
+            return null;
+        }
+        return before(text, before);
     }
-    
+
+    public static String cutLastZeroDigit(String version) {
+        String answer = version;
+        // cut last digit so its not 2.18.0 but 2.18
+        String[] parts = version.split("\\.");
+        if (parts.length == 3 && parts[2].equals("0")) {
+            answer = parts[0] + "." + parts[1];
+        }
+        return answer;
+    }
+
     /**
-     * Loads the entire stream into memory as a String and returns it.
-     * <p/>
-     * <b>Notice:</b> This implementation appends a <tt>\n</tt> as line
-     * terminator at the of the text.
-     * <p/>
-     * Warning, don't use for crazy big streams :)
+     * Returns the base class name, i.e. without package and generic related
+     * information.
+     * 
+     * @param className The class name which base class is to be computed.
+     * @return the base class name, i.e. without package and generic related
+     *         information.
      */
-    public static String loadText(InputStream in) throws IOException {
-        StringBuilder builder = new StringBuilder();
-        InputStreamReader isr = new InputStreamReader(in);
-        try {
-            BufferedReader reader = new LineNumberReader(isr);
-            while (true) {
-                String line = reader.readLine();
-                if (line != null) {
-                    builder.append(line);
-                    builder.append("\n");
-                } else {
-                    break;
-                }
-            }
-            return builder.toString();
-        } finally {
-            isr.close();
-            in.close();
+    public static String getClassShortName(String className) {
+        if (className != null) {
+            return className.replaceAll("<.*>", "").replaceAll(".*[.]([^.]+)", "$1");
         }
+        return className;
     }
 
     /**
@@ -86,14 +97,4 @@ public final class PackageHelper {
         }
         return sb.toString();
     }
-
-    public static void writeText(File file, String text) throws IOException {
-        FileOutputStream fos = new FileOutputStream(file, false);
-        try {
-            fos.write(text.getBytes());
-        } finally {
-            fos.close();
-        }
-    }
-
 }
diff --git a/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/model/ComponentModel.java b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/model/ComponentModel.java
new file mode 100644
index 0000000..fb9dda6
--- /dev/null
+++ b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/model/ComponentModel.java
@@ -0,0 +1,190 @@
+/*
+ * 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.model;
+
+import org.apache.camel.quarkus.maven.StringHelper;
+
+import static org.apache.camel.quarkus.maven.StringHelper.cutLastZeroDigit;
+
+public class ComponentModel {
+
+    private String kind;
+    private String scheme;
+    private String syntax;
+    private String alternativeSyntax;
+    private String alternativeSchemes;
+    private String title;
+    private String description;
+    private String firstVersion;
+    private String label;
+    private String deprecated;
+    private String deprecationNote;
+    private String consumerOnly;
+    private String producerOnly;
+    private String javaType;
+    private String groupId;
+    private String artifactId;
+    private String version;
+
+    public String getKind() {
+        return kind;
+    }
+
+    public void setKind(String kind) {
+        this.kind = kind;
+    }
+
+    public String getScheme() {
+        return scheme;
+    }
+
+    public void setScheme(String scheme) {
+        this.scheme = scheme;
+    }
+
+    public String getSyntax() {
+        return syntax;
+    }
+
+    public void setSyntax(String syntax) {
+        this.syntax = syntax;
+    }
+
+    public String getAlternativeSyntax() {
+        return alternativeSyntax;
+    }
+
+    public void setAlternativeSyntax(String alternativeSyntax) {
+        this.alternativeSyntax = alternativeSyntax;
+    }
+
+    public String getAlternativeSchemes() {
+        return alternativeSchemes;
+    }
+
+    public void setAlternativeSchemes(String alternativeSchemes) {
+        this.alternativeSchemes = alternativeSchemes;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getFirstVersion() {
+        return firstVersion;
+    }
+
+    public void setFirstVersion(String firstVersion) {
+        this.firstVersion = firstVersion;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public String getDeprecated() {
+        return deprecated;
+    }
+
+    public void setDeprecated(String deprecated) {
+        this.deprecated = deprecated;
+    }
+
+    public String getDeprecationNote() {
+        return deprecationNote;
+    }
+
+    public void setDeprecationNote(String deprecationNote) {
+        this.deprecationNote = deprecationNote;
+    }
+
+    public String getConsumerOnly() {
+        return consumerOnly;
+    }
+
+    public void setConsumerOnly(String consumerOnly) {
+        this.consumerOnly = consumerOnly;
+    }
+
+    public String getProducerOnly() {
+        return producerOnly;
+    }
+
+    public void setProducerOnly(String producerOnly) {
+        this.producerOnly = producerOnly;
+    }
+
+    public String getJavaType() {
+        return javaType;
+    }
+
+    public void setJavaType(String javaType) {
+        this.javaType = javaType;
+    }
+
+    public String getGroupId() {
+        return groupId;
+    }
+
+    public void setGroupId(String groupId) {
+        this.groupId = groupId;
+    }
+
+    public String getArtifactId() {
+        return artifactId;
+    }
+
+    public void setArtifactId(String artifactId) {
+        this.artifactId = artifactId;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public String getShortJavaType() {
+        return StringHelper.getClassShortName(javaType);
+    }
+
+    public String getDocLink() {
+        return "https://camel.apache.org/components/latest/" + scheme + "-component.html";
+    }
+
+    public String getFirstVersionShort() {
+        return cutLastZeroDigit(firstVersion);
+    }
+}
diff --git a/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/model/DataFormatModel.java b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/model/DataFormatModel.java
new file mode 100644
index 0000000..340fa5c
--- /dev/null
+++ b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/model/DataFormatModel.java
@@ -0,0 +1,155 @@
+/*
+ * 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.model;
+
+import org.apache.camel.quarkus.maven.StringHelper;
+
+import static org.apache.camel.quarkus.maven.StringHelper.cutLastZeroDigit;
+
+public class DataFormatModel {
+
+    private String kind;
+    private String name;
+    private String modelName;
+    private String title;
+    private String description;
+    private String firstVersion;
+    private String label;
+    private String deprecated;
+    private String deprecationNote;
+    private String javaType;
+    private String groupId;
+    private String artifactId;
+    private String version;
+
+    public String getKind() {
+        return kind;
+    }
+
+    public void setKind(String kind) {
+        this.kind = kind;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getModelName() {
+        return modelName;
+    }
+
+    public void setModelName(String modelName) {
+        this.modelName = modelName;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getFirstVersion() {
+        return firstVersion;
+    }
+
+    public void setFirstVersion(String firstVersion) {
+        this.firstVersion = firstVersion;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public String getDeprecated() {
+        return deprecated;
+    }
+
+    public void setDeprecated(String deprecated) {
+        this.deprecated = deprecated;
+    }
+
+    public String getDeprecationNote() {
+        return deprecationNote;
+    }
+
+    public void setDeprecationNote(String deprecationNote) {
+        this.deprecationNote = deprecationNote;
+    }
+
+    public String getJavaType() {
+        return javaType;
+    }
+
+    public void setJavaType(String javaType) {
+        this.javaType = javaType;
+    }
+
+    public String getGroupId() {
+        return groupId;
+    }
+
+    public void setGroupId(String groupId) {
+        this.groupId = groupId;
+    }
+
+    public String getArtifactId() {
+        return artifactId;
+    }
+
+    public void setArtifactId(String artifactId) {
+        this.artifactId = artifactId;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public String getShortJavaType() {
+        return StringHelper.getClassShortName(javaType);
+    }
+
+    public String getDocLink() {
+        return "https://camel.apache.org/components/latest/" + name + "-dataformat.html";
+    }
+
+    public String getFirstVersionShort() {
+        return cutLastZeroDigit(firstVersion);
+    }
+
+}
diff --git a/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/model/LanguageModel.java b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/model/LanguageModel.java
new file mode 100644
index 0000000..9d3ea32
--- /dev/null
+++ b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/model/LanguageModel.java
@@ -0,0 +1,155 @@
+/*
+ * 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.model;
+
+import org.apache.camel.quarkus.maven.StringHelper;
+
+import static org.apache.camel.quarkus.maven.StringHelper.cutLastZeroDigit;
+
+public class LanguageModel {
+
+    private String kind;
+    private String name;
+    private String modelName;
+    private String title;
+    private String description;
+    private String firstVersion;
+    private String label;
+    private String deprecated;
+    private String deprecationNote;
+    private String javaType;
+    private String groupId;
+    private String artifactId;
+    private String version;
+
+    public String getKind() {
+        return kind;
+    }
+
+    public void setKind(String kind) {
+        this.kind = kind;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getModelName() {
+        return modelName;
+    }
+
+    public void setModelName(String modelName) {
+        this.modelName = modelName;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getFirstVersion() {
+        return firstVersion;
+    }
+
+    public void setFirstVersion(String firstVersion) {
+        this.firstVersion = firstVersion;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public String getDeprecated() {
+        return deprecated;
+    }
+
+    public void setDeprecated(String deprecated) {
+        this.deprecated = deprecated;
+    }
+
+    public String getDeprecationNote() {
+        return deprecationNote;
+    }
+
+    public void setDeprecationNote(String deprecationNote) {
+        this.deprecationNote = deprecationNote;
+    }
+
+    public String getJavaType() {
+        return javaType;
+    }
+
+    public void setJavaType(String javaType) {
+        this.javaType = javaType;
+    }
+
+    public String getGroupId() {
+        return groupId;
+    }
+
+    public void setGroupId(String groupId) {
+        this.groupId = groupId;
+    }
+
+    public String getArtifactId() {
+        return artifactId;
+    }
+
+    public void setArtifactId(String artifactId) {
+        this.artifactId = artifactId;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public String getShortJavaType() {
+        return StringHelper.getClassShortName(javaType);
+    }
+
+    public String getDocLink() {
+        return "https://camel.apache.org/components/latest/" + name + "-language.html";
+    }
+
+    public String getFirstVersionShort() {
+        return cutLastZeroDigit(firstVersion);
+    }
+
+}
diff --git a/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/model/OtherModel.java b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/model/OtherModel.java
new file mode 100644
index 0000000..3ca3f55
--- /dev/null
+++ b/tooling/maven/package-maven-plugin/src/main/java/org/apache/camel/quarkus/maven/model/OtherModel.java
@@ -0,0 +1,145 @@
+/*
+ * 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.model;
+
+import org.apache.camel.quarkus.maven.StringHelper;
+
+import static org.apache.camel.quarkus.maven.StringHelper.cutLastZeroDigit;
+
+public class OtherModel {
+
+    private String kind;
+    private String name;
+    private String title;
+    private String description;
+    private String firstVersion;
+    private String label;
+    private String deprecated;
+    private String deprecationNote;
+    private String groupId;
+    private String artifactId;
+    private String version;
+    private String javaType;
+
+    public String getJavaType() {
+        return javaType;
+    }
+
+    public void setJavaType(String javaType) {
+        this.javaType = javaType;
+    }
+
+    public String getKind() {
+        return kind;
+    }
+
+    public void setKind(String kind) {
+        this.kind = kind;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getTitle() {
+        return title;
+    }
+
+    public void setTitle(String title) {
+        this.title = title;
+    }
+
+    public String getDescription() {
+        return description;
+    }
+
+    public void setDescription(String description) {
+        this.description = description;
+    }
+
+    public String getFirstVersion() {
+        return firstVersion;
+    }
+
+    public void setFirstVersion(String firstVersion) {
+        this.firstVersion = firstVersion;
+    }
+
+    public String getLabel() {
+        return label;
+    }
+
+    public void setLabel(String label) {
+        this.label = label;
+    }
+
+    public String getDeprecated() {
+        return deprecated;
+    }
+
+    public void setDeprecated(String deprecated) {
+        this.deprecated = deprecated;
+    }
+
+    public String getDeprecationNote() {
+        return deprecationNote;
+    }
+
+    public void setDeprecationNote(String deprecationNote) {
+        this.deprecationNote = deprecationNote;
+    }
+
+    public String getGroupId() {
+        return groupId;
+    }
+
+    public void setGroupId(String groupId) {
+        this.groupId = groupId;
+    }
+
+    public String getArtifactId() {
+        return artifactId;
+    }
+
+    public void setArtifactId(String artifactId) {
+        this.artifactId = artifactId;
+    }
+
+    public String getVersion() {
+        return version;
+    }
+
+    public void setVersion(String version) {
+        this.version = version;
+    }
+
+    public String getDocLink() {
+        return "https://camel.apache.org/components/latest/" + name + ".html";
+    }
+
+    public String getFirstVersionShort() {
+        return cutLastZeroDigit(firstVersion);
+    }
+
+    public String getShortJavaType() {
+        return StringHelper.getClassShortName(javaType);
+    }
+}
diff --git a/tooling/maven/package-maven-plugin/src/main/resources/readme-components.mvel b/tooling/maven/package-maven-plugin/src/main/resources/readme-components.mvel
new file mode 100644
index 0000000..fff7791
--- /dev/null
+++ b/tooling/maven/package-maven-plugin/src/main/resources/readme-components.mvel
@@ -0,0 +1,14 @@
+@if{!components.isEmpty()}
+
+Number of Components: @{components.size} in @{numberOfArtifacts} JAR artifacts (@{numberOfDeprecated} deprecated)
+
+[width="100%",cols="4,1,5",options="header"]
+|===
+| Component | Available From | Description
+@foreach{row : components}
+| link:@{row.docLink}[@{row.title}] (@{row.artifactId}) +
+`@{row.syntax}` | @{row.firstVersionShort} | @if{row.deprecated == "true"}*deprecated* @end{}@{util.escape(row.description)}
+@end{}
+|===
+
+@end{}
\ No newline at end of file
diff --git a/tooling/maven/package-maven-plugin/src/main/resources/readme-dataformats.mvel b/tooling/maven/package-maven-plugin/src/main/resources/readme-dataformats.mvel
new file mode 100644
index 0000000..5f018b4
--- /dev/null
+++ b/tooling/maven/package-maven-plugin/src/main/resources/readme-dataformats.mvel
@@ -0,0 +1,12 @@
+@if{!dataformats.isEmpty()}
+
+Number of Data Formats: @{dataformats.size} in @{numberOfArtifacts} JAR artifacts (@{numberOfDeprecated} deprecated)
+
+[width="100%",cols="4,1,5",options="header"]
+|===
+| Data Format | Available From | Description
+@foreach{row : dataformats}
+| link:@{row.docLink}[@{row.title}] (@{row.artifactId}) | @{row.firstVersionShort} | @if{row.deprecated == "true"}*deprecated* @end{}@{util.escape(row.description)}
+@end{}|===
+
+@end{}
\ No newline at end of file
diff --git a/tooling/maven/package-maven-plugin/src/main/resources/readme-languages.mvel b/tooling/maven/package-maven-plugin/src/main/resources/readme-languages.mvel
new file mode 100644
index 0000000..632f0c8
--- /dev/null
+++ b/tooling/maven/package-maven-plugin/src/main/resources/readme-languages.mvel
@@ -0,0 +1,12 @@
+@if{!languages.isEmpty()}
+
+Number of Languages: @{languages.size} in @{numberOfArtifacts} JAR artifacts (@{numberOfDeprecated} deprecated)
+
+[width="100%",cols="4,1,5",options="header"]
+|===
+| Language | Available From | Description
+@foreach{row : languages}
+| link:@{row.docLink}[@{row.title}] (@{row.artifactId}) | @{row.firstVersionShort} | @if{row.deprecated == "true"}*deprecated* @end{}@{util.escape(row.description)}
+@end{}|===
+
+@end{}
\ No newline at end of file
diff --git a/tooling/maven/package-maven-plugin/src/main/resources/readme-others.mvel b/tooling/maven/package-maven-plugin/src/main/resources/readme-others.mvel
new file mode 100644
index 0000000..841c87d
--- /dev/null
+++ b/tooling/maven/package-maven-plugin/src/main/resources/readme-others.mvel
@@ -0,0 +1,12 @@
+@if{!others.isEmpty()}
+
+Number of Miscellaneous Components: @{others.size} in @{numberOfArtifacts} JAR artifacts (@{numberOfDeprecated} deprecated)
+
+[width="100%",cols="4,1,5",options="header"]
+|===
+| Component | Available From | Description
+@foreach{row : others}
+| (@{row.artifactId}) | @{row.firstVersionShort} | @if{row.deprecated == "true"}*deprecated* @end{}@{util.escape(row.description)}
+@end{}|===
+
+@end{}
\ No newline at end of file