You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ja...@apache.org on 2020/09/02 11:56:19 UTC
[camel-quarkus] 04/13: Add Camel AS2 Modules as Quarkus Extension
#1471
This is an automated email from the ASF dual-hosted git repository.
jamesnetherton pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/camel-quarkus.git
commit 60f9b50695adbd28f45bdce1f3620ed12eaac92a
Author: JiriOndrusek <on...@gmail.com>
AuthorDate: Mon Jul 20 15:30:39 2020 +0200
Add Camel AS2 Modules as Quarkus Extension #1471
---
catalog/pom.xml | 2 +
docs/modules/ROOT/nav.adoc | 1 +
docs/modules/ROOT/pages/reference/components.adoc | 3 +
.../ROOT/pages/reference/extensions/as2.adoc | 37 +++++
docs/modules/ROOT/pages/reference/index.adoc | 3 +
extensions-support/bouncycastle/deployment/pom.xml | 69 +++++++++
.../deployment/BouncycastleSupportProcessor.java | 54 +++++++
extensions-support/{ => bouncycastle}/pom.xml | 34 +----
extensions-support/bouncycastle/runtime/pom.xml | 80 ++++++++++
.../main/resources/META-INF/quarkus-extension.yaml | 27 ++++
extensions-support/pom.xml | 1 +
extensions/as2/deployment/pom.xml | 67 ++++++++
.../component/as2/deployment/As2Processor.java | 87 +++++++++++
extensions/as2/pom.xml | 39 +++++
extensions/as2/runtime/pom.xml | 108 +++++++++++++
extensions/as2/runtime/src/main/doc/usage.adoc | 4 +
.../camel/quarkus/component/as2/As2Recorder.java | 34 +++++
.../main/resources/META-INF/quarkus-extension.yaml | 31 ++++
extensions/pom.xml | 1 +
integration-tests/as2/pom.xml | 145 ++++++++++++++++++
.../component/as2/it/As2CertificateHelper.java | 140 +++++++++++++++++
.../quarkus/component/as2/it/As2Resource.java | 131 ++++++++++++++++
.../component/as2/it/transport/ClientResult.java | 68 +++++++++
.../component/as2/it/transport/Request.java | 152 ++++++++++++++++++
.../component/as2/it/transport/ServerResult.java | 39 +++++
.../as2/src/main/resources/application.properties | 18 +++
.../camel/quarkus/component/as2/it/As2Helper.java | 123 +++++++++++++++
.../camel/quarkus/component/as2/it/As2IT.java | 24 +++
.../quarkus/component/as2/it/As2Receiver.java | 169 +++++++++++++++++++++
.../camel/quarkus/component/as2/it/As2Sender.java | 54 +++++++
.../camel/quarkus/component/as2/it/As2Test.java | 127 ++++++++++++++++
.../quarkus/component/as2/it/As2TestResource.java | 35 +++++
integration-tests/pom.xml | 1 +
poms/bom/pom.xml | 35 +++++
tooling/scripts/test-categories.yaml | 1 +
35 files changed, 1917 insertions(+), 27 deletions(-)
diff --git a/catalog/pom.xml b/catalog/pom.xml
index c64a753..5aa78ea 100644
--- a/catalog/pom.xml
+++ b/catalog/pom.xml
@@ -44,6 +44,7 @@
camel-quarkus-amqp
camel-quarkus-apns
camel-quarkus-arangodb
+ camel-quarkus-as2
camel-quarkus-asterisk
camel-quarkus-atmos
camel-quarkus-atom
@@ -246,6 +247,7 @@
camel-quarkus-support-ahc
camel-quarkus-support-aws
camel-quarkus-support-aws2
+ camel-quarkus-support-bouncycastle
camel-quarkus-support-common
camel-quarkus-support-commons-logging
camel-quarkus-support-consul-client
diff --git a/docs/modules/ROOT/nav.adoc b/docs/modules/ROOT/nav.adoc
index e5e414b..7dffb40 100644
--- a/docs/modules/ROOT/nav.adoc
+++ b/docs/modules/ROOT/nav.adoc
@@ -19,6 +19,7 @@
*** xref:reference/extensions/amqp.adoc[AMQP]
*** xref:reference/extensions/apns.adoc[APNS]
*** xref:reference/extensions/arangodb.adoc[ArangoDb]
+*** xref:reference/extensions/as2.adoc[AS2]
*** xref:reference/extensions/asterisk.adoc[Asterisk]
*** xref:reference/extensions/ahc.adoc[Async HTTP Client (AHC)]
*** xref:reference/extensions/ahc-ws.adoc[Async HTTP Client (AHC) Websocket]
diff --git a/docs/modules/ROOT/pages/reference/components.adoc b/docs/modules/ROOT/pages/reference/components.adoc
index 5ea5ced..09da315 100644
--- a/docs/modules/ROOT/pages/reference/components.adoc
+++ b/docs/modules/ROOT/pages/reference/components.adoc
@@ -22,6 +22,9 @@ Preview | 1.1.0 | Send notifications to Apple iOS devices.
| xref:reference/extensions/arangodb.adoc[ArangoDb] | [.camel-element-artifact]##camel-quarkus-arangodb## | [.camel-element-Native]##Native## +
Stable | 1.1.0 | Perform operations on ArangoDb when used as a Document Database, or as a Graph Database
+| xref:reference/extensions/as2.adoc[AS2] | [.camel-element-artifact]##camel-quarkus-as2## | [.camel-element-Native]##Native## +
+Stable | 1.0.0-CR4 | Transfer data securely and reliably using the AS2 protocol (RFC4130).
+
| xref:reference/extensions/asterisk.adoc[Asterisk] | [.camel-element-artifact]##camel-quarkus-asterisk## | [.camel-element-JVM]##JVM## +
Preview | 1.1.0 | Interact with Asterisk PBX Server.
diff --git a/docs/modules/ROOT/pages/reference/extensions/as2.adoc b/docs/modules/ROOT/pages/reference/extensions/as2.adoc
new file mode 100644
index 0000000..23db52b
--- /dev/null
+++ b/docs/modules/ROOT/pages/reference/extensions/as2.adoc
@@ -0,0 +1,37 @@
+// Do not edit directly!
+// This file was generated by camel-quarkus-maven-plugin:update-extension-doc-page
+
+[[as2]]
+= AS2
+:page-aliases: extensions/as2.adoc
+
+[.badges]
+[.badge-key]##Since Camel Quarkus##[.badge-version]##1.0.0-CR4## [.badge-key]##JVM##[.badge-supported]##supported## [.badge-key]##Native##[.badge-supported]##supported##
+
+Transfer data securely and reliably using the AS2 protocol (RFC4130).
+
+== What's inside
+
+* https://camel.apache.org/components/latest/as2-component.html[AS2 component], URI syntax: `as2:apiName/methodName`
+
+Please refer to the above link for usage and configuration details.
+
+== Maven coordinates
+
+[source,xml]
+----
+<dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-as2</artifactId>
+</dependency>
+----
+
+Check the xref:user-guide/index.adoc[User guide] for more information about writing Camel Quarkus applications.
+
+== Usage
+
+Depending on its configuration, this component may require SSL encryption on its connections. In such a case, you will need
+to add `quarkus.ssl.native=true` to your `application.properties`.
+See also https://quarkus.io/guides/native-and-ssl[Quarkus native SSL guide] and xref:user-guide/native-mode.adoc[Native mode]
+section of Camel Quarkus user guide.
+
diff --git a/docs/modules/ROOT/pages/reference/index.adoc b/docs/modules/ROOT/pages/reference/index.adoc
index 76e9a03..0a400c3 100644
--- a/docs/modules/ROOT/pages/reference/index.adoc
+++ b/docs/modules/ROOT/pages/reference/index.adoc
@@ -35,6 +35,9 @@ Preview | 1.1.0 | Send notifications to Apple iOS devices.
| xref:reference/extensions/arangodb.adoc[ArangoDb] | camel-quarkus-arangodb | [.camel-element-Native]##Native## +
Stable | 1.1.0 | Perform operations on ArangoDb when used as a Document Database, or as a Graph Database
+| xref:reference/extensions/as2.adoc[AS2] | camel-quarkus-as2 | [.camel-element-Native]##Native## +
+Stable | 1.0.0-CR4 | Transfer data securely and reliably using the AS2 protocol (RFC4130).
+
| xref:reference/extensions/asterisk.adoc[Asterisk] | camel-quarkus-asterisk | [.camel-element-JVM]##JVM## +
Preview | 1.1.0 | Interact with Asterisk PBX Server.
diff --git a/extensions-support/bouncycastle/deployment/pom.xml b/extensions-support/bouncycastle/deployment/pom.xml
new file mode 100644
index 0000000..477c47b
--- /dev/null
+++ b/extensions-support/bouncycastle/deployment/pom.xml
@@ -0,0 +1,69 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-support-bouncycastle-parent</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>camel-quarkus-support-bouncycastle-deployment</artifactId>
+ <name>Camel Quarkus :: Support :: Bouncy Castle :: Deployment</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-core-deployment</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-support-bouncycastle</artifactId>
+ </dependency>
+ <dependency>
+ <artifactId>bcprov-jdk15on</artifactId>
+ <groupId>org.bouncycastle</groupId>
+ </dependency>
+ <dependency>
+ <artifactId>bcpkix-jdk15on</artifactId>
+ <groupId>org.bouncycastle</groupId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <annotationProcessorPaths>
+ <path>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-extension-processor</artifactId>
+ <version>${quarkus.version}</version>
+ </path>
+ </annotationProcessorPaths>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/extensions-support/bouncycastle/deployment/src/main/java/org/apache/camel/quarkus/support/bouncycastle/deployment/BouncycastleSupportProcessor.java b/extensions-support/bouncycastle/deployment/src/main/java/org/apache/camel/quarkus/support/bouncycastle/deployment/BouncycastleSupportProcessor.java
new file mode 100644
index 0000000..47dfbac
--- /dev/null
+++ b/extensions-support/bouncycastle/deployment/src/main/java/org/apache/camel/quarkus/support/bouncycastle/deployment/BouncycastleSupportProcessor.java
@@ -0,0 +1,54 @@
+/*
+ * 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.support.bouncycastle.deployment;
+
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
+import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.deployment.builditem.IndexDependencyBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
+import org.jboss.jandex.IndexView;
+
+public class BouncycastleSupportProcessor {
+ static final String FEATURE = "camel-support-bouncycastle";
+
+ @BuildStep
+ FeatureBuildItem feature() {
+ return new FeatureBuildItem(FEATURE);
+ }
+
+ @BuildStep
+ ReflectiveClassBuildItem registerForReflection(CombinedIndexBuildItem combinedIndex) {
+ IndexView index = combinedIndex.getIndex();
+
+ String[] dtos = index.getKnownClasses().stream()
+ .map(ci -> ci.name().toString())
+ .filter(n -> n.startsWith("org.bouncycastle.jcajce.provider.digest.") ||
+ n.startsWith("org.bouncycastle.jcajce.provider.symmetric.") ||
+ n.startsWith("org.bouncycastle.jcajce.provider.asymmetric.") ||
+ n.startsWith("org.bouncycastle.jcajce.provider.keystore."))
+ .sorted()
+ .toArray(String[]::new);
+
+ return new ReflectiveClassBuildItem(false, false, dtos);
+ }
+
+ @BuildStep
+ IndexDependencyBuildItem registerBCDependencyForIndex() {
+ return new IndexDependencyBuildItem("org.bouncycastle", "bcprov-jdk15on");
+ }
+}
diff --git a/extensions-support/pom.xml b/extensions-support/bouncycastle/pom.xml
similarity index 57%
copy from extensions-support/pom.xml
copy to extensions-support/bouncycastle/pom.xml
index 12dee0c..f1bc64d 100644
--- a/extensions-support/pom.xml
+++ b/extensions-support/bouncycastle/pom.xml
@@ -18,40 +18,20 @@
-->
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-
+ <modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.camel.quarkus</groupId>
- <artifactId>camel-quarkus</artifactId>
+ <artifactId>camel-quarkus-build-parent</artifactId>
<version>1.1.0-SNAPSHOT</version>
+ <relativePath>../../poms/build-parent/pom.xml</relativePath>
</parent>
- <modelVersion>4.0.0</modelVersion>
-
- <artifactId>camel-quarkus-extensions-support</artifactId>
- <name>Camel Quarkus :: Extensions :: Support</name>
+ <artifactId>camel-quarkus-support-bouncycastle-parent</artifactId>
+ <name>Camel Quarkus :: Support :: Bouncy Castle</name>
<packaging>pom</packaging>
<modules>
- <!-- extensions a..z; do not remove this comment, it is important when sorting via mvn process-resources -Pformat -->
- <module>ahc</module>
- <module>aws</module>
- <module>aws2</module>
- <module>common</module>
- <module>commons-logging</module>
- <module>consul-client</module>
- <module>debezium</module>
- <module>google-http-client</module>
- <module>httpclient</module>
- <module>jackson-dataformat-xml</module>
- <module>jetty</module>
- <module>mail</module>
- <module>mongodb</module>
- <module>policy</module>
- <module>retrofit</module>
- <module>spring</module>
- <module>webhook</module>
- <module>xstream</module>
- <module>xml</module>
- <module>xalan</module>
+ <module>deployment</module>
+ <module>runtime</module>
</modules>
</project>
diff --git a/extensions-support/bouncycastle/runtime/pom.xml b/extensions-support/bouncycastle/runtime/pom.xml
new file mode 100644
index 0000000..07a6eac
--- /dev/null
+++ b/extensions-support/bouncycastle/runtime/pom.xml
@@ -0,0 +1,80 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-support-bouncycastle-parent</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>camel-quarkus-support-bouncycastle</artifactId>
+ <name>Camel Quarkus :: Support :: Bouncy Castle :: Runtime</name>
+
+ <properties>
+ <firstVersion>1.1.0</firstVersion>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-bom</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.javassist</groupId>
+ <artifactId>javassist</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-bootstrap-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <annotationProcessorPaths>
+ <path>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-extension-processor</artifactId>
+ <version>${quarkus.version}</version>
+ </path>
+ </annotationProcessorPaths>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/extensions-support/bouncycastle/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions-support/bouncycastle/runtime/src/main/resources/META-INF/quarkus-extension.yaml
new file mode 100644
index 0000000..50c9c1a
--- /dev/null
+++ b/extensions-support/bouncycastle/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -0,0 +1,27 @@
+#
+# 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.
+#
+
+---
+name: "Camel Quarkus Support Bouncy Castle"
+description: "Camel Quarkus Support Bouncy Castle"
+metadata:
+ unlisted: true
+ keywords:
+ - "camel"
+ guide: "https://quarkus.io/guides/camel"
+ categories:
+ - "integration"
diff --git a/extensions-support/pom.xml b/extensions-support/pom.xml
index 12dee0c..8fd3916 100644
--- a/extensions-support/pom.xml
+++ b/extensions-support/pom.xml
@@ -36,6 +36,7 @@
<module>ahc</module>
<module>aws</module>
<module>aws2</module>
+ <module>bouncycastle</module>
<module>common</module>
<module>commons-logging</module>
<module>consul-client</module>
diff --git a/extensions/as2/deployment/pom.xml b/extensions/as2/deployment/pom.xml
new file mode 100644
index 0000000..83d9cf6
--- /dev/null
+++ b/extensions/as2/deployment/pom.xml
@@ -0,0 +1,67 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-as2-parent</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>camel-quarkus-as2-deployment</artifactId>
+ <name>Camel Quarkus :: AS2 :: Deployment</name>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-core-deployment</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-as2</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-support-bouncycastle-deployment</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <annotationProcessorPaths>
+ <path>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-extension-processor</artifactId>
+ <version>${quarkus.version}</version>
+ </path>
+ </annotationProcessorPaths>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+</project>
diff --git a/extensions/as2/deployment/src/main/java/org/apache/camel/quarkus/component/as2/deployment/As2Processor.java b/extensions/as2/deployment/src/main/java/org/apache/camel/quarkus/component/as2/deployment/As2Processor.java
new file mode 100644
index 0000000..8aebdaf
--- /dev/null
+++ b/extensions/as2/deployment/src/main/java/org/apache/camel/quarkus/component/as2/deployment/As2Processor.java
@@ -0,0 +1,87 @@
+/*
+ * 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.component.as2.deployment;
+
+import io.quarkus.deployment.annotations.BuildStep;
+import io.quarkus.deployment.annotations.ExecutionTime;
+import io.quarkus.deployment.annotations.Record;
+import io.quarkus.deployment.builditem.CombinedIndexBuildItem;
+import io.quarkus.deployment.builditem.FeatureBuildItem;
+import io.quarkus.deployment.builditem.IndexDependencyBuildItem;
+import io.quarkus.deployment.builditem.LogConsoleFormatBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.NativeImageResourceBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.ReflectiveClassBuildItem;
+import io.quarkus.deployment.builditem.nativeimage.RuntimeInitializedClassBuildItem;
+import org.apache.camel.component.as2.AS2ClientManagerEndpointConfiguration;
+import org.apache.camel.component.as2.AS2ServerManagerEndpointConfiguration;
+import org.apache.camel.component.as2.api.util.AS2Utils;
+import org.apache.camel.quarkus.component.as2.As2Recorder;
+import org.jboss.jandex.IndexView;
+
+class As2Processor {
+
+ private static final String FEATURE = "camel-as2";
+
+ @BuildStep
+ FeatureBuildItem feature() {
+ return new FeatureBuildItem(FEATURE);
+ }
+
+ @BuildStep
+ RuntimeInitializedClassBuildItem runtimeInitializedClasses() {
+ return new RuntimeInitializedClassBuildItem(AS2Utils.class.getCanonicalName());
+ }
+
+ @BuildStep
+ ReflectiveClassBuildItem registerAs2ConfigurationForReflection() {
+ return new ReflectiveClassBuildItem(true, true,
+ AS2ServerManagerEndpointConfiguration.class.getCanonicalName(),
+ AS2ClientManagerEndpointConfiguration.class.getCanonicalName(),
+ java.security.AlgorithmParameterGeneratorSpi.class.getCanonicalName());
+ }
+
+ @BuildStep
+ ReflectiveClassBuildItem registerForReflection(CombinedIndexBuildItem combinedIndex) {
+ IndexView index = combinedIndex.getIndex();
+
+ String[] dtos = index.getKnownClasses().stream()
+ .map(ci -> ci.name().toString())
+ .filter(n -> n.startsWith("org.apache.velocity.runtime") || n.startsWith("org.apache.velocity.util"))
+ .sorted()
+ .toArray(String[]::new);
+
+ return new ReflectiveClassBuildItem(false, false, dtos);
+ }
+
+ @BuildStep
+ IndexDependencyBuildItem registerDependencyForIndex() {
+ return new IndexDependencyBuildItem("org.apache.velocity", "velocity-engine-core");
+ }
+
+ @BuildStep
+ NativeImageResourceBuildItem initResources() {
+ return new NativeImageResourceBuildItem("org/apache/velocity/runtime/defaults/velocity.properties",
+ "org/apache/velocity/runtime/defaults/directive.properties");
+ }
+
+ @BuildStep
+ @Record(ExecutionTime.RUNTIME_INIT)
+ public LogConsoleFormatBuildItem setUpFormatter(As2Recorder as2Recorder) {
+ return new LogConsoleFormatBuildItem(as2Recorder.createFormatter());
+ }
+
+}
diff --git a/extensions/as2/pom.xml b/extensions/as2/pom.xml
new file mode 100644
index 0000000..6440496
--- /dev/null
+++ b/extensions/as2/pom.xml
@@ -0,0 +1,39 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-build-parent</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <relativePath>../../poms/build-parent/pom.xml</relativePath>
+ </parent>
+
+ <artifactId>camel-quarkus-as2-parent</artifactId>
+ <name>Camel Quarkus :: AS2</name>
+ <packaging>pom</packaging>
+
+ <modules>
+ <module>deployment</module>
+ <module>runtime</module>
+ </modules>
+</project>
diff --git a/extensions/as2/runtime/pom.xml b/extensions/as2/runtime/pom.xml
new file mode 100644
index 0000000..6ee151f
--- /dev/null
+++ b/extensions/as2/runtime/pom.xml
@@ -0,0 +1,108 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-as2-parent</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>camel-quarkus-as2</artifactId>
+ <name>Camel Quarkus :: AS2 :: Runtime</name>
+ <description>Transfer data securely and reliably using the AS2 protocol (RFC4130).</description>
+
+ <properties>
+ <firstVersion>1.0.0-CR4</firstVersion>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-bom</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-core</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
+ <artifactId>camel-as2</artifactId>
+ <exclusions>
+ <exclusion>
+ <artifactId>log4j-slf4j-impl</artifactId>
+ <groupId>org.apache.logging.log4j</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-support-bouncycastle</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.jboss.slf4j</groupId>
+ <artifactId>slf4j-jboss-logging</artifactId>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>update-extension-doc-page</id>
+ <goals><goal>update-extension-doc-page</goal></goals>
+ <phase>process-classes</phase>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-bootstrap-maven-plugin</artifactId>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <configuration>
+ <annotationProcessorPaths>
+ <path>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-extension-processor</artifactId>
+ <version>${quarkus.version}</version>
+ </path>
+ </annotationProcessorPaths>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/extensions/as2/runtime/src/main/doc/usage.adoc b/extensions/as2/runtime/src/main/doc/usage.adoc
new file mode 100644
index 0000000..f0af355
--- /dev/null
+++ b/extensions/as2/runtime/src/main/doc/usage.adoc
@@ -0,0 +1,4 @@
+Depending on its configuration, this component may require SSL encryption on its connections. In such a case, you will need
+to add `quarkus.ssl.native=true` to your `application.properties`.
+See also https://quarkus.io/guides/native-and-ssl[Quarkus native SSL guide] and xref:user-guide/native-mode.adoc[Native mode]
+section of Camel Quarkus user guide.
diff --git a/extensions/as2/runtime/src/main/java/org/apache/camel/quarkus/component/as2/As2Recorder.java b/extensions/as2/runtime/src/main/java/org/apache/camel/quarkus/component/as2/As2Recorder.java
new file mode 100644
index 0000000..cbfe6bb
--- /dev/null
+++ b/extensions/as2/runtime/src/main/java/org/apache/camel/quarkus/component/as2/As2Recorder.java
@@ -0,0 +1,34 @@
+/*
+ * 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.component.as2;
+
+import java.util.Optional;
+import java.util.logging.Formatter;
+
+import io.quarkus.runtime.RuntimeValue;
+import io.quarkus.runtime.annotations.Recorder;
+import org.jboss.logmanager.formatters.PatternFormatter;
+
+@Recorder
+public class As2Recorder {
+
+ public RuntimeValue<Optional<Formatter>> createFormatter() {
+ final Formatter formatter = new PatternFormatter("[%30.30t] %-30.30c{1} %-5p %m%n");
+ return new RuntimeValue<>(Optional.of(formatter));
+ }
+}
diff --git a/extensions/as2/runtime/src/main/resources/META-INF/quarkus-extension.yaml b/extensions/as2/runtime/src/main/resources/META-INF/quarkus-extension.yaml
new file mode 100644
index 0000000..7ecc69c
--- /dev/null
+++ b/extensions/as2/runtime/src/main/resources/META-INF/quarkus-extension.yaml
@@ -0,0 +1,31 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License. You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+# This is a generated file. Do not edit directly!
+# To re-generate, run the following command from the top level directory:
+#
+# mvn -N cq:update-quarkus-metadata
+#
+---
+name: "Camel AS2"
+description: "Transfer data securely and reliably using the AS2 protocol (RFC4130)"
+metadata:
+ guide: "https://camel.apache.org/camel-quarkus/latest/reference/extensions/as2.html"
+ categories:
+ - "integration"
+ status:
+ - "stable"
diff --git a/extensions/pom.xml b/extensions/pom.xml
index dc708c9..15a1df3 100644
--- a/extensions/pom.xml
+++ b/extensions/pom.xml
@@ -38,6 +38,7 @@
<module>ahc-ws</module>
<module>amqp</module>
<module>arangodb</module>
+ <module>as2</module>
<module>attachments</module>
<module>avro</module>
<module>aws-ec2</module>
diff --git a/integration-tests/as2/pom.xml b/integration-tests/as2/pom.xml
new file mode 100644
index 0000000..e1d0dad
--- /dev/null
+++ b/integration-tests/as2/pom.xml
@@ -0,0 +1,145 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-integration-tests</artifactId>
+ <version>1.1.0-SNAPSHOT</version>
+ <relativePath>../pom.xml</relativePath>
+ </parent>
+
+ <artifactId>camel-quarkus-integration-test-as2</artifactId>
+ <name>Camel Quarkus :: Integration Tests :: AS2</name>
+ <description>Integration tests for Camel Quarkus AS2 extension</description>
+
+ <properties>
+ <!-- mvnd, a.k.a. Maven Daemon: https://github.com/gnodet/mvnd -->
+ <!-- The following rule tells mvnd to build the listed deployment modules before this module. -->
+ <!-- This is important because mvnd builds modules in parallel by default. The deployment modules are not -->
+ <!-- explicit dependencies of this module in the Maven sense, although they are required by the Quarkus Maven plugin. -->
+ <!-- Please update rule whenever you change the dependencies of this module by running -->
+ <!-- mvn process-resources -Pformat from the root directory -->
+ <mvnd.builder.rule>camel-quarkus-as2-deployment,camel-quarkus-mock-deployment,camel-quarkus-support-policy-deployment</mvnd.builder.rule>
+ </properties>
+
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-bom-test</artifactId>
+ <version>${project.version}</version>
+ <type>pom</type>
+ <scope>import</scope>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-as2</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-resteasy</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-resteasy-jackson</artifactId>
+ </dependency>
+
+ <!-- test dependencies -->
+ <dependency>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-junit5</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>io.rest-assured</groupId>
+ <artifactId>rest-assured</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-integration-test-support</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.awaitility</groupId>
+ <artifactId>awaitility</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-mock</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>io.quarkus</groupId>
+ <artifactId>quarkus-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>build</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+
+ <profiles>
+ <profile>
+ <id>native</id>
+ <activation>
+ <property>
+ <name>native</name>
+ </property>
+ </activation>
+ <properties>
+ <quarkus.package.type>native</quarkus.package.type>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-failsafe-plugin</artifactId>
+ <executions>
+ <execution>
+ <goals>
+ <goal>integration-test</goal>
+ <goal>verify</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+ </profile>
+ </profiles>
+
+</project>
diff --git a/integration-tests/as2/src/main/java/org/apache/camel/quarkus/component/as2/it/As2CertificateHelper.java b/integration-tests/as2/src/main/java/org/apache/camel/quarkus/component/as2/it/As2CertificateHelper.java
new file mode 100644
index 0000000..d6089e6
--- /dev/null
+++ b/integration-tests/as2/src/main/java/org/apache/camel/quarkus/component/as2/it/As2CertificateHelper.java
@@ -0,0 +1,140 @@
+/*
+ * 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.component.as2.it;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.camel.component.as2.api.AS2ClientConnection;
+import org.apache.camel.component.as2.api.AS2ClientManager;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.bc.BcX509ExtensionUtils;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+
+public class As2CertificateHelper {
+
+ private static final String TARGET_HOST = "localhost";
+ private static final String AS2_VERSION = "1.1";
+ private static final String USER_AGENT = "Camel AS2 Endpoint";
+ private static final String CLIENT_FQDN = "example.org";
+
+ private static KeyPair signingKP;
+ private static X509Certificate signingCert;
+ private static List<X509Certificate> certList;
+ // certificate serial number seed.
+ static int serialNo = 1;
+
+ private As2CertificateHelper() {
+ }
+
+ public static void setup() throws Exception {
+ Security.addProvider(new BouncyCastleProvider());
+
+ //
+ // set up our certificates
+ //
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");
+
+ kpg.initialize(1024, new SecureRandom());
+
+ String issueDN = "O=Earth 2 Software, C=E2";
+ KeyPair issueKP = kpg.generateKeyPair();
+ X509Certificate issueCert = makeCertificate(
+ issueKP, issueDN, issueKP, issueDN);
+
+ //
+ // certificate we sign against
+ //
+ String signingDN = "CN=Shekdon, E=test@gmail.com, O=Earth 2 Software, C=E2";
+ signingKP = kpg.generateKeyPair();
+ signingCert = makeCertificate(
+ signingKP, signingDN, issueKP, issueDN);
+
+ certList = new ArrayList<>();
+
+ certList.add(signingCert);
+ certList.add(issueCert);
+
+ }
+
+ /**
+ * create a basic X509 certificate from the given keys
+ */
+ public static X509Certificate makeCertificate(KeyPair subKP, String subDN, KeyPair issKP, String issDN)
+ throws GeneralSecurityException, IOException, OperatorCreationException {
+ PublicKey subPub = subKP.getPublic();
+ PrivateKey issPriv = issKP.getPrivate();
+ PublicKey issPub = issKP.getPublic();
+
+ X509v3CertificateBuilder v3CertGen = new JcaX509v3CertificateBuilder(new X500Name(issDN),
+ BigInteger.valueOf(serialNo++), new Date(System.currentTimeMillis()),
+ new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100)), new X500Name(subDN), subPub);
+
+ v3CertGen.addExtension(Extension.subjectKeyIdentifier, false, createSubjectKeyId(subPub));
+
+ v3CertGen.addExtension(Extension.authorityKeyIdentifier, false, createAuthorityKeyId(issPub));
+
+ return new JcaX509CertificateConverter().setProvider("BC").getCertificate(
+ v3CertGen.build(new JcaContentSignerBuilder("MD5withRSA").setProvider("BC").build(issPriv)));
+ }
+
+ public static AuthorityKeyIdentifier createAuthorityKeyId(PublicKey pub) throws IOException {
+ SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(pub.getEncoded());
+
+ BcX509ExtensionUtils utils = new BcX509ExtensionUtils();
+ return utils.createAuthorityKeyIdentifier(info);
+ }
+
+ public static SubjectKeyIdentifier createSubjectKeyId(PublicKey pub) throws IOException {
+ SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(pub.getEncoded());
+
+ return new BcX509ExtensionUtils().createSubjectKeyIdentifier(info);
+ }
+
+ public static AS2ClientManager createClient(int port) throws IOException {
+ AS2ClientConnection clientConnection = new AS2ClientConnection(AS2_VERSION, USER_AGENT, CLIENT_FQDN, TARGET_HOST, port);
+ return new AS2ClientManager(clientConnection);
+ }
+
+ public static List<X509Certificate> getCertList() {
+ return certList;
+ }
+
+ public static KeyPair getSigningKP() {
+ return signingKP;
+ }
+}
diff --git a/integration-tests/as2/src/main/java/org/apache/camel/quarkus/component/as2/it/As2Resource.java b/integration-tests/as2/src/main/java/org/apache/camel/quarkus/component/as2/it/As2Resource.java
new file mode 100644
index 0000000..3f4c04d
--- /dev/null
+++ b/integration-tests/as2/src/main/java/org/apache/camel/quarkus/component/as2/it/As2Resource.java
@@ -0,0 +1,131 @@
+/*
+ * 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.component.as2.it;
+
+import javax.enterprise.context.ApplicationScoped;
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.core.MediaType;
+
+import org.apache.camel.ConsumerTemplate;
+import org.apache.camel.Exchange;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.as2.api.entity.DispositionNotificationMultipartReportEntity;
+import org.apache.camel.component.as2.api.entity.MimeEntity;
+import org.apache.camel.component.as2.api.entity.MultipartSignedEntity;
+import org.apache.camel.component.as2.internal.AS2Constants;
+import org.apache.camel.quarkus.component.as2.it.transport.ClientResult;
+import org.apache.camel.quarkus.component.as2.it.transport.Request;
+import org.apache.camel.quarkus.component.as2.it.transport.ServerResult;
+import org.apache.http.protocol.HttpCoreContext;
+import org.jboss.logging.Logger;
+
+@Path("/as2")
+@ApplicationScoped
+public class As2Resource {
+
+ public static String CLIENT_PORT_PARAMETER = As2Resource.class.getSimpleName() + "-client-port";
+ public static String SERVER_PORT_PARAMETER = As2Resource.class.getSimpleName() + "-server-port";
+
+ private static final Logger LOG = Logger.getLogger(As2Resource.class);
+
+ @Inject
+ ProducerTemplate producerTemplate;
+
+ @Inject
+ ConsumerTemplate consumerTemplate;
+
+ @Path("/client")
+ @POST
+ @Consumes(MediaType.APPLICATION_JSON)
+ @Produces(MediaType.APPLICATION_JSON)
+ public ClientResult client(Request request) throws Exception {
+ LOG.infof("Sending to as2: %s", request.getHeaders());
+ As2CertificateHelper.setup();
+ final Object response = producerTemplate.requestBodyAndHeaders(getClientEndpoint(),
+ request.getEdiMessage(), request.collectHeaders());
+ ClientResult clientResult = new ClientResult();
+ if (response instanceof DispositionNotificationMultipartReportEntity) {
+ clientResult.setDispositionNotificationMultipartReportEntity(true);
+ clientResult.setPartsCount(((DispositionNotificationMultipartReportEntity) response).getPartCount());
+ if (clientResult.getPartsCount() > 1) {
+ clientResult.setSecondPartClassName(
+ ((DispositionNotificationMultipartReportEntity) response).getPart(1).getClass().getSimpleName());
+ }
+ } else if (response instanceof MultipartSignedEntity) {
+ clientResult.setMultipartSignedEntity(true);
+ MimeEntity responseSignedDataEntity = ((MultipartSignedEntity) response).getSignedDataEntity();
+ clientResult
+ .setPartsCount(((DispositionNotificationMultipartReportEntity) responseSignedDataEntity).getPartCount());
+ if (clientResult.getPartsCount() > 1) {
+ clientResult.setSecondPartClassName(
+ ((DispositionNotificationMultipartReportEntity) responseSignedDataEntity).getPart(1).getClass()
+ .getSimpleName());
+ }
+ clientResult.setSignedEntityReceived(((MultipartSignedEntity) response).getSignatureEntity() != null);
+ }
+
+ LOG.infof("Got response from as2: %s", response);
+ return clientResult;
+ }
+
+ @Path("/serverInit")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public boolean serverInit() throws Exception {
+ LOG.info("Initializing server from as2 component.");
+ //execute request, which won't return anything, because client doesn't send anything, but it starts component
+ consumerTemplate.receiveNoWait(getServerEndpoint());
+ return true;
+ }
+
+ @Path("/server")
+ @GET
+ @Produces(MediaType.APPLICATION_JSON)
+ public ServerResult server() throws Exception {
+ LOG.info("Receiving from as2.");
+ Exchange exchange = consumerTemplate.receive(getServerEndpoint());
+ if (exchange == null) {
+ return null;
+ }
+ ServerResult serverResult = new ServerResult();
+ serverResult.setResult(exchange.getIn().getBody(String.class));
+ HttpCoreContext coreContext = exchange.getProperty(AS2Constants.AS2_INTERCHANGE, HttpCoreContext.class);
+ if (coreContext != null) {
+ serverResult.setRequestClass(coreContext.getRequest().getClass().getSimpleName());
+ }
+ return serverResult;
+ }
+
+ private String getServerEndpoint() {
+ String url = String.format("as2://server/listen?serverPortNumber=%s&clientFqdn=%s&requestUriPattern=/",
+ System.getProperty(SERVER_PORT_PARAMETER), "example.com");
+
+ return url;
+ }
+
+ private String getClientEndpoint() {
+ String url = String.format("as2://client/send?inBody=ediMessage&targetPortNumber=%s&targetHostname=%s",
+ System.getProperty(CLIENT_PORT_PARAMETER), "localhost");
+
+ return url;
+ }
+}
diff --git a/integration-tests/as2/src/main/java/org/apache/camel/quarkus/component/as2/it/transport/ClientResult.java b/integration-tests/as2/src/main/java/org/apache/camel/quarkus/component/as2/it/transport/ClientResult.java
new file mode 100644
index 0000000..2c8518e
--- /dev/null
+++ b/integration-tests/as2/src/main/java/org/apache/camel/quarkus/component/as2/it/transport/ClientResult.java
@@ -0,0 +1,68 @@
+/*
+ * 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.component.as2.it.transport;
+
+public class ClientResult {
+
+ boolean dispositionNotificationMultipartReportEntity;
+ boolean multipartSignedEntity;
+ boolean signedEntityReceived;
+
+ int partsCount;
+
+ String secondPartClassName;
+
+ public boolean isDispositionNotificationMultipartReportEntity() {
+ return dispositionNotificationMultipartReportEntity;
+ }
+
+ public void setDispositionNotificationMultipartReportEntity(boolean dispositionNotificationMultipartReportEntity) {
+ this.dispositionNotificationMultipartReportEntity = dispositionNotificationMultipartReportEntity;
+ }
+
+ public int getPartsCount() {
+ return partsCount;
+ }
+
+ public void setPartsCount(int partsCount) {
+ this.partsCount = partsCount;
+ }
+
+ public String getSecondPartClassName() {
+ return secondPartClassName;
+ }
+
+ public void setSecondPartClassName(String secondPartClassName) {
+ this.secondPartClassName = secondPartClassName;
+ }
+
+ public boolean isMultipartSignedEntity() {
+ return multipartSignedEntity;
+ }
+
+ public void setMultipartSignedEntity(boolean multipartSignedEntity) {
+ this.multipartSignedEntity = multipartSignedEntity;
+ }
+
+ public boolean isSignedEntityReceived() {
+ return signedEntityReceived;
+ }
+
+ public void setSignedEntityReceived(boolean signedEntityReceived) {
+ this.signedEntityReceived = signedEntityReceived;
+ }
+}
diff --git a/integration-tests/as2/src/main/java/org/apache/camel/quarkus/component/as2/it/transport/Request.java b/integration-tests/as2/src/main/java/org/apache/camel/quarkus/component/as2/it/transport/Request.java
new file mode 100644
index 0000000..8b89a3b
--- /dev/null
+++ b/integration-tests/as2/src/main/java/org/apache/camel/quarkus/component/as2/it/transport/Request.java
@@ -0,0 +1,152 @@
+/*
+ * 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.component.as2.it.transport;
+
+import java.security.cert.Certificate;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.component.as2.api.AS2Charset;
+import org.apache.camel.component.as2.api.AS2EncryptionAlgorithm;
+import org.apache.camel.component.as2.api.AS2MediaType;
+import org.apache.camel.component.as2.api.AS2MessageStructure;
+import org.apache.camel.component.as2.api.AS2SignatureAlgorithm;
+import org.apache.camel.quarkus.component.as2.it.As2CertificateHelper;
+import org.apache.http.entity.ContentType;
+
+public class Request {
+
+ private AS2MessageStructure messageStructure;
+ private String messageStructureKey;
+ private ContentType contentType;
+ private String contentTypeKey;
+ private Map<String, Object> headers = new HashMap<>();
+ private String ediMessage;
+ private AS2EncryptionAlgorithm encryptionAlgorithm;
+ private AS2SignatureAlgorithm signingAlgorithm;
+
+ public Request() {
+ }
+
+ public Request(String ediMessage) {
+ this.ediMessage = ediMessage;
+ }
+
+ public AS2MessageStructure getMessageStructure() {
+ return messageStructure;
+ }
+
+ public void setMessageStructure(AS2MessageStructure messageStructure) {
+ this.messageStructure = messageStructure;
+ }
+
+ public Map<String, Object> getHeaders() {
+ return headers;
+ }
+
+ public void addField(String key, Object value) {
+ this.headers.put(key, value);
+ }
+
+ public void setHeaders(Map<String, Object> headers) {
+ this.headers = headers;
+ }
+
+ public String getMessageStructureKey() {
+ return messageStructureKey;
+ }
+
+ public void setMessageStructureKey(String messageStructureKey) {
+ this.messageStructureKey = messageStructureKey;
+ }
+
+ public ContentType getContentType() {
+ return contentType;
+ }
+
+ public void setContentType(ContentType contentType) {
+ this.contentType = contentType;
+ }
+
+ public String getContentTypeKey() {
+ return contentTypeKey;
+ }
+
+ public void setContentTypeKey(String contentTypeKey) {
+ this.contentTypeKey = contentTypeKey;
+ }
+
+ public String getEdiMessage() {
+ return ediMessage;
+ }
+
+ public Request withEdiMessage(String ediMessage) {
+ this.ediMessage = ediMessage;
+ return this;
+ }
+
+ public Request withHeaders(Map<String, Object> headers) {
+ this.headers = headers;
+ for (Map.Entry<String, Object> entry : headers.entrySet()) {
+ if (entry.getValue() instanceof AS2MessageStructure) {
+ setMessageStructure((AS2MessageStructure) entry.getValue());
+ setMessageStructureKey(entry.getKey());
+ }
+ }
+ return this;
+ }
+
+ public Map<String, Object> collectHeaders() {
+ Map<String, Object> retVal = new HashMap<>(headers);
+ if (getMessageStructure() != null) {
+ retVal.put(getMessageStructureKey(), getMessageStructure());
+ }
+ retVal.put("CamelAS2.ediMessageContentType",
+ org.apache.http.entity.ContentType.create(AS2MediaType.APPLICATION_EDIFACT, AS2Charset.US_ASCII));
+ if (getEncryptionAlgorithm() != null) {
+ retVal.put("CamelAS2.encryptingCertificateChain", As2CertificateHelper.getCertList());
+ retVal.put("CamelAS2.encryptingAlgorithm", getEncryptionAlgorithm());
+ }
+ if (getSigningAlgorithm() != null) {
+ // parameter type is java.security.cert.Certificate[]
+ retVal.put("CamelAS2.signingCertificateChain", As2CertificateHelper.getCertList().toArray(new Certificate[0]));
+ // parameter type is java.security.PrivateKey
+ retVal.put("CamelAS2.signingPrivateKey", As2CertificateHelper.getSigningKP().getPrivate());
+ // parameter type is org.apache.camel.component.as2.api.AS2SignatureAlgorithm
+ retVal.put("CamelAS2.signingAlgorithm", getSigningAlgorithm());
+ }
+ return retVal;
+ }
+
+ public AS2EncryptionAlgorithm getEncryptionAlgorithm() {
+ return encryptionAlgorithm;
+ }
+
+ public Request withEncryptionAlgorithm(AS2EncryptionAlgorithm encryptionAlgorithm) {
+ this.encryptionAlgorithm = encryptionAlgorithm;
+ return this;
+ }
+
+ public AS2SignatureAlgorithm getSigningAlgorithm() {
+ return signingAlgorithm;
+ }
+
+ public Request withSigningAlgorithm(AS2SignatureAlgorithm signingAlgorithm) {
+ this.signingAlgorithm = signingAlgorithm;
+ return this;
+ }
+}
diff --git a/integration-tests/as2/src/main/java/org/apache/camel/quarkus/component/as2/it/transport/ServerResult.java b/integration-tests/as2/src/main/java/org/apache/camel/quarkus/component/as2/it/transport/ServerResult.java
new file mode 100644
index 0000000..bfc79cf
--- /dev/null
+++ b/integration-tests/as2/src/main/java/org/apache/camel/quarkus/component/as2/it/transport/ServerResult.java
@@ -0,0 +1,39 @@
+/*
+ * 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.component.as2.it.transport;
+
+public class ServerResult {
+
+ String result;
+ String requestClass;
+
+ public String getResult() {
+ return result;
+ }
+
+ public void setResult(String result) {
+ this.result = result;
+ }
+
+ public String getRequestClass() {
+ return requestClass;
+ }
+
+ public void setRequestClass(String requestClass) {
+ this.requestClass = requestClass;
+ }
+}
diff --git a/integration-tests/as2/src/main/resources/application.properties b/integration-tests/as2/src/main/resources/application.properties
new file mode 100644
index 0000000..8136208
--- /dev/null
+++ b/integration-tests/as2/src/main/resources/application.properties
@@ -0,0 +1,18 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+quarkus.ssl.native=true
diff --git a/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2Helper.java b/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2Helper.java
new file mode 100644
index 0000000..d4b0123
--- /dev/null
+++ b/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2Helper.java
@@ -0,0 +1,123 @@
+/*
+ * 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.component.as2.it;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.camel.component.as2.api.AS2Charset;
+import org.apache.camel.component.as2.api.AS2EncryptionAlgorithm;
+import org.apache.camel.component.as2.api.AS2MediaType;
+import org.apache.camel.component.as2.api.AS2MessageStructure;
+import org.apache.camel.component.as2.api.AS2SignatureAlgorithm;
+import org.apache.camel.quarkus.component.as2.it.transport.Request;
+import org.apache.http.entity.ContentType;
+
+public class As2Helper {
+
+ public static final String AS2_VERSION = "1.1";
+ public static final String REQUEST_URI = "/";
+ public static final String SUBJECT = "Test Case";
+ public static final String AS2_NAME = "878051556";
+ public static final String FROM = "mrAS@example.org";
+ public static final String[] SIGNED_RECEIPT_MIC_ALGORITHMS = new String[] { "sha1", "md5" };
+ public static final String DISPOSITION_NOTIFICATION_TO = FROM;
+ public static final String EDI_MESSAGE = "UNB+UNOA:1+005435656:1+006415160:1+060515:1434+00000000000778'\n"
+ + "UNH+00000000000117+INVOIC:D:97B:UN'\n"
+ + "BGM+380+342459+9'\n"
+ + "DTM+3:20060515:102'\n"
+ + "RFF+ON:521052'\n"
+ + "NAD+BY+792820524::16++CUMMINS MID-RANGE ENGINE PLANT'\n"
+ + "NAD+SE+005435656::16++GENERAL WIDGET COMPANY'\n"
+ + "CUX+1:USD'\n"
+ + "LIN+1++157870:IN'\n"
+ + "IMD+F++:::WIDGET'\n"
+ + "QTY+47:1020:EA'\n"
+ + "ALI+US'\n"
+ + "MOA+203:1202.58'\n"
+ + "PRI+INV:1.179'\n"
+ + "LIN+2++157871:IN'\n"
+ + "IMD+F++:::DIFFERENT WIDGET'\n"
+ + "QTY+47:20:EA'\n"
+ + "ALI+JP'\n"
+ + "MOA+203:410'\n"
+ + "PRI+INV:20.5'\n"
+ + "UNS+S'\n"
+ + "MOA+39:2137.58'\n"
+ + "ALC+C+ABG'\n"
+ + "MOA+8:525'\n"
+ + "UNT+23+00000000000117'\n"
+ + "UNZ+1+00000000000778'";
+
+ private static final String EDI_MESSAGE_CONTENT_TRANSFER_ENCODING = "7bit";
+
+ private As2Helper() {
+ }
+
+ public static Request createPlainRequest() {
+ final Map<String, Object> headers = createBaseHeaders(AS2MessageStructure.PLAIN);
+
+ return new Request()
+ .withHeaders(headers)
+ .withEdiMessage(EDI_MESSAGE);
+ }
+
+ public static Request createEncryptedRequest() {
+ final Map<String, Object> headers = createBaseHeaders(AS2MessageStructure.ENCRYPTED);
+
+ return new Request()
+ .withHeaders(headers)
+ .withEdiMessage(EDI_MESSAGE)
+ .withEncryptionAlgorithm(AS2EncryptionAlgorithm.AES128_CBC);
+ }
+
+ public static Request createMultipartSignedRequest() {
+ final Map<String, Object> headers = createBaseHeaders(AS2MessageStructure.SIGNED);
+ // parameter type is String[]
+ headers.put("CamelAS2.signedReceiptMicAlgorithms", SIGNED_RECEIPT_MIC_ALGORITHMS);
+
+ return new Request()
+ .withHeaders(headers)
+ .withEdiMessage(EDI_MESSAGE)
+ .withSigningAlgorithm(AS2SignatureAlgorithm.SHA512WITHRSA);
+ }
+
+ private static Map<String, Object> createBaseHeaders(AS2MessageStructure plain) {
+ final Map<String, Object> headers = new HashMap<>();
+ // parameter type is String
+ headers.put("CamelAS2.requestUri", REQUEST_URI);
+ // parameter type is String
+ headers.put("CamelAS2.subject", SUBJECT);
+ // parameter type is String
+ headers.put("CamelAS2.from", FROM);
+ // parameter type is String
+ headers.put("CamelAS2.as2From", AS2_NAME);
+ // parameter type is String
+ headers.put("CamelAS2.as2To", AS2_NAME);
+ // parameter type is org.apache.camel.component.as2.api.AS2MessageStructure
+ headers.put("CamelAS2.as2MessageStructure", plain);
+ // parameter type is org.apache.http.entity.ContentType
+ headers.put("CamelAS2.ediMessageContentType",
+ ContentType.create(AS2MediaType.APPLICATION_EDIFACT, AS2Charset.US_ASCII));
+ // parameter type is String
+ headers.put("CamelAS2.ediMessageTransferEncoding", EDI_MESSAGE_CONTENT_TRANSFER_ENCODING);
+ // parameter type is String
+ headers.put("CamelAS2.dispositionNotificationTo", DISPOSITION_NOTIFICATION_TO);
+ return headers;
+ }
+
+}
diff --git a/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2IT.java b/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2IT.java
new file mode 100644
index 0000000..1896dda
--- /dev/null
+++ b/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2IT.java
@@ -0,0 +1,24 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.as2.it;
+
+import io.quarkus.test.junit.NativeImageTest;
+
+@NativeImageTest
+class As2IT extends As2Test {
+
+}
diff --git a/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2Receiver.java b/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2Receiver.java
new file mode 100644
index 0000000..6b288bb
--- /dev/null
+++ b/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2Receiver.java
@@ -0,0 +1,169 @@
+/*
+ * 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.component.as2.it;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.PrivateKey;
+import java.security.PublicKey;
+import java.security.SecureRandom;
+import java.security.Security;
+import java.security.cert.Certificate;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.apache.camel.component.as2.api.AS2ServerConnection;
+import org.apache.camel.component.as2.api.AS2SignatureAlgorithm;
+import org.apache.http.HttpException;
+import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
+import org.apache.http.protocol.HttpContext;
+import org.apache.http.protocol.HttpRequestHandler;
+import org.bouncycastle.asn1.x500.X500Name;
+import org.bouncycastle.asn1.x509.AuthorityKeyIdentifier;
+import org.bouncycastle.asn1.x509.Extension;
+import org.bouncycastle.asn1.x509.SubjectKeyIdentifier;
+import org.bouncycastle.asn1.x509.SubjectPublicKeyInfo;
+import org.bouncycastle.cert.X509v3CertificateBuilder;
+import org.bouncycastle.cert.bc.BcX509ExtensionUtils;
+import org.bouncycastle.cert.jcajce.JcaX509CertificateConverter;
+import org.bouncycastle.cert.jcajce.JcaX509v3CertificateBuilder;
+import org.bouncycastle.jce.provider.BouncyCastleProvider;
+import org.bouncycastle.operator.OperatorCreationException;
+import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
+
+public class As2Receiver {
+ private static final String SERVER_FQDN = "server.example.com";
+ private static final String ORIGIN_SERVER_NAME = "AS2ClientManagerIntegrationTest Server";
+ private static AS2ServerConnection serverConnection;
+ private static KeyPair serverSigningKP;
+ private static List<X509Certificate> serverCertList;
+ private static RequestHandler receiverHandler;
+ // certificate serial number seed.
+ private static int serialNo = 1;
+
+ private As2Receiver() {
+ }
+
+ public static RequestHandler startReceiver(int port) throws Exception {
+ if (receiverHandler == null) {
+ setupServerKeysAndCertificates();
+ receiverHandler = receiveTestMessages(port);
+ }
+ return receiverHandler;
+ }
+
+ private static void setupServerKeysAndCertificates() throws Exception {
+ Security.addProvider(new BouncyCastleProvider());
+
+ //
+ // set up our certificates
+ //
+ KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA", "BC");
+
+ kpg.initialize(1024, new SecureRandom());
+
+ String issueDN = "O=Earth2 Software, C=E2";
+ KeyPair issueKP = kpg.generateKeyPair();
+ X509Certificate issueCert = makeCertificate(
+ issueKP, issueDN, issueKP, issueDN);
+
+ //
+ // certificate we sign against
+ //
+ String signingDN = "CN=Sheldon, E=test@gmail.com, O=Earth2 Software, C=E2";
+ serverSigningKP = kpg.generateKeyPair();
+ X509Certificate signingCert = makeCertificate(
+ serverSigningKP, signingDN, issueKP, issueDN);
+
+ serverCertList = new ArrayList<>();
+
+ serverCertList.add(signingCert);
+ serverCertList.add(issueCert);
+ }
+
+ private static RequestHandler receiveTestMessages(int port) throws IOException {
+ serverConnection = new AS2ServerConnection(As2Helper.AS2_VERSION, ORIGIN_SERVER_NAME,
+ SERVER_FQDN, port, AS2SignatureAlgorithm.SHA256WITHRSA,
+ serverCertList.toArray(new Certificate[0]), serverSigningKP.getPrivate(), serverSigningKP.getPrivate());
+
+ RequestHandler handler = new RequestHandler();
+ serverConnection.listen("/", handler);
+
+ return handler;
+ }
+
+ /**
+ * create a basic X509 certificate from the given keys
+ */
+ public static X509Certificate makeCertificate(KeyPair subKP, String subDN, KeyPair issKP, String issDN)
+ throws GeneralSecurityException, IOException, OperatorCreationException {
+ PublicKey subPub = subKP.getPublic();
+ PrivateKey issPriv = issKP.getPrivate();
+ PublicKey issPub = issKP.getPublic();
+
+ X509v3CertificateBuilder v3CertGen = new JcaX509v3CertificateBuilder(new X500Name(issDN),
+ BigInteger.valueOf(serialNo++), new Date(System.currentTimeMillis()),
+ new Date(System.currentTimeMillis() + (1000L * 60 * 60 * 24 * 100)), new X500Name(subDN), subPub);
+
+ v3CertGen.addExtension(Extension.subjectKeyIdentifier, false, createSubjectKeyId(subPub));
+
+ v3CertGen.addExtension(Extension.authorityKeyIdentifier, false, createAuthorityKeyId(issPub));
+
+ return new JcaX509CertificateConverter().setProvider("BC").getCertificate(
+ v3CertGen.build(new JcaContentSignerBuilder("MD5withRSA").setProvider("BC").build(issPriv)));
+ }
+
+ public static AuthorityKeyIdentifier createAuthorityKeyId(PublicKey pub) throws IOException {
+ SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(pub.getEncoded());
+
+ BcX509ExtensionUtils utils = new BcX509ExtensionUtils();
+ return utils.createAuthorityKeyIdentifier(info);
+ }
+
+ public static SubjectKeyIdentifier createSubjectKeyId(PublicKey pub) throws IOException {
+ SubjectPublicKeyInfo info = SubjectPublicKeyInfo.getInstance(pub.getEncoded());
+
+ return new BcX509ExtensionUtils().createSubjectKeyIdentifier(info);
+ }
+
+ public static class RequestHandler implements HttpRequestHandler {
+
+ private HttpRequest request;
+ private HttpResponse response;
+
+ @Override
+ public void handle(HttpRequest request, HttpResponse response, HttpContext context)
+ throws HttpException, IOException {
+ this.request = request;
+ this.response = response;
+ }
+
+ public HttpRequest getRequest() {
+ return request;
+ }
+
+ public HttpResponse getResponse() {
+ return response;
+ }
+ }
+}
diff --git a/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2Sender.java b/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2Sender.java
new file mode 100644
index 0000000..e8d2d9e
--- /dev/null
+++ b/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2Sender.java
@@ -0,0 +1,54 @@
+/*
+ * 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.component.as2.it;
+
+import java.io.IOException;
+
+import org.apache.camel.component.as2.api.AS2Charset;
+import org.apache.camel.component.as2.api.AS2ClientConnection;
+import org.apache.camel.component.as2.api.AS2ClientManager;
+import org.apache.camel.component.as2.api.AS2MediaType;
+import org.apache.camel.component.as2.api.AS2MessageStructure;
+import org.apache.http.HttpException;
+import org.apache.http.entity.ContentType;
+
+public class As2Sender {
+
+ private static final String TARGET_HOST = "localhost";
+ private static final String USER_AGENT = "Camel AS2 Endpoint";
+ private static final String CLIENT_FQDN = "example.org";
+
+ private As2Sender() {
+ }
+
+ public static As2SenderClient createClient(int port) throws IOException {
+ AS2ClientConnection clientConnection = new AS2ClientConnection(As2Helper.AS2_VERSION, USER_AGENT, CLIENT_FQDN,
+ TARGET_HOST, port);
+ AS2ClientManager clientManager = new AS2ClientManager(clientConnection);
+
+ return ediMessage -> clientManager.send(ediMessage, As2Helper.REQUEST_URI, As2Helper.SUBJECT, As2Helper.FROM,
+ As2Helper.AS2_NAME,
+ As2Helper.AS2_NAME, AS2MessageStructure.PLAIN,
+ ContentType.create(AS2MediaType.APPLICATION_EDIFACT, AS2Charset.US_ASCII), null, null, null, null,
+ null, As2Helper.DISPOSITION_NOTIFICATION_TO, As2Helper.SIGNED_RECEIPT_MIC_ALGORITHMS, null, null);
+ }
+
+ public interface As2SenderClient {
+
+ void sendMessage(String ediMessage) throws HttpException;
+ }
+}
diff --git a/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2Test.java b/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2Test.java
new file mode 100644
index 0000000..d58986c
--- /dev/null
+++ b/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2Test.java
@@ -0,0 +1,127 @@
+/*
+ * 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.component.as2.it;
+
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.TimeUnit;
+
+import io.quarkus.test.common.QuarkusTestResource;
+import io.quarkus.test.junit.QuarkusTest;
+import io.restassured.RestAssured;
+import org.apache.camel.component.as2.api.entity.AS2MessageDispositionNotificationEntity;
+import org.apache.camel.quarkus.component.as2.it.transport.ClientResult;
+import org.apache.camel.quarkus.component.as2.it.transport.Request;
+import org.apache.camel.quarkus.component.as2.it.transport.ServerResult;
+import org.apache.http.message.BasicHttpEntityEnclosingRequest;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.awaitility.Awaitility.await;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+@QuarkusTestResource(As2TestResource.class)
+@QuarkusTest
+public class As2Test {
+ private static final Logger LOG = LoggerFactory.getLogger(As2Test.class);
+
+ @Test
+ public void serverPlainTest() throws Exception {
+
+ //prepare component by sending empty request with no wait
+ ExecutorService executor = Executors.newSingleThreadExecutor();
+ Future<Boolean> initResult = executor.submit(
+ () -> RestAssured.given().get("/as2/serverInit").then().statusCode(200).extract().as(Boolean.class));
+
+ //give some time for server component to be created
+ await().atMost(5L, TimeUnit.SECONDS).untilAsserted(() -> {
+ assertTrue(initResult.get());
+ });
+
+ //execute component server to wait for the result
+ Future<ServerResult> futureResult = executor.submit(
+ () -> RestAssured.given().get("/as2/server").then().statusCode(200).extract().as(ServerResult.class));
+
+ //create client for sending message to server
+ As2Sender.As2SenderClient client = As2Sender
+ .createClient(Integer.parseInt(System.getProperty(As2Resource.SERVER_PORT_PARAMETER)));
+
+ //send message to server
+ client.sendMessage(As2Helper.EDI_MESSAGE);
+
+ //wait for the result from the server
+ await().atMost(10L, TimeUnit.SECONDS).untilAsserted(() -> {
+ ServerResult result = futureResult.get();
+
+ assertEquals(As2Helper.EDI_MESSAGE.replaceAll("[\n\r]", ""), result.getResult().replaceAll("[\n\r]", ""),
+ "Unexpected content for enveloped mime part");
+
+ assertEquals(BasicHttpEntityEnclosingRequest.class.getSimpleName(), result.getRequestClass(),
+ "Request does not contain entity");
+ });
+ }
+
+ @Test
+ public void clientPlainTest() throws Exception {
+ clientTest(As2Helper.createPlainRequest());
+ }
+
+ @Test
+ public void clientEncryptionTest() throws Exception {
+ clientTest(As2Helper.createEncryptedRequest());
+ }
+
+ @Test
+ public void clientMultipartSignedTest() throws Exception {
+ ClientResult clientResult = clientTest(As2Helper.createMultipartSignedRequest());
+
+ Assertions.assertTrue(clientResult.isSignedEntityReceived(), "Signature Entity");
+ }
+
+ private ClientResult clientTest(Request request) throws Exception {
+
+ //start server (not component)
+ As2Receiver.RequestHandler requestHandler = As2Receiver
+ .startReceiver(Integer.parseInt(System.getProperty(As2Resource.CLIENT_PORT_PARAMETER)));
+
+ //send message by component (as client)
+ ClientResult clientResult = RestAssured.given() //
+ .contentType(io.restassured.http.ContentType.JSON)
+ .body(request)
+ .post("/as2/client") //
+ .then()
+ .statusCode(200)
+ .extract().body().as(ClientResult.class);
+
+ //assert result
+ assertNotNull(clientResult, "Response entity");
+ assertEquals(2, clientResult.getPartsCount(), "Unexpected number of body parts in report");
+ assertEquals(AS2MessageDispositionNotificationEntity.class.getSimpleName(), clientResult.getSecondPartClassName(),
+ "Unexpected type of As2Entity");
+
+ //assert that receiver was really used
+ assertNotNull(requestHandler.getRequest(), "Request");
+ assertNotNull(requestHandler.getResponse(), "Response");
+
+ return clientResult;
+ }
+}
diff --git a/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2TestResource.java b/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2TestResource.java
new file mode 100644
index 0000000..59a2f01
--- /dev/null
+++ b/integration-tests/as2/src/test/java/org/apache/camel/quarkus/component/as2/it/As2TestResource.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.quarkus.component.as2.it;
+
+import java.util.Map;
+import java.util.Objects;
+
+import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
+import org.apache.camel.quarkus.test.AvailablePortFinder;
+
+public class As2TestResource implements QuarkusTestResourceLifecycleManager {
+ @Override
+ public Map<String, String> start() {
+ return AvailablePortFinder.reserveNetworkPorts(Objects::toString, As2Resource.CLIENT_PORT_PARAMETER,
+ As2Resource.SERVER_PORT_PARAMETER);
+ }
+
+ @Override
+ public void stop() {
+ }
+}
diff --git a/integration-tests/pom.xml b/integration-tests/pom.xml
index 588d462..b235131 100644
--- a/integration-tests/pom.xml
+++ b/integration-tests/pom.xml
@@ -67,6 +67,7 @@
<module>activemq</module>
<module>amqp</module>
<module>arangodb</module>
+ <module>as2</module>
<module>avro</module>
<module>aws</module>
<module>aws2</module>
diff --git a/poms/bom/pom.xml b/poms/bom/pom.xml
index 2e8333b..dc7ec44 100644
--- a/poms/bom/pom.xml
+++ b/poms/bom/pom.xml
@@ -141,6 +141,11 @@
</dependency>
<dependency>
<groupId>org.apache.camel</groupId>
+ <artifactId>camel-as2</artifactId>
+ <version>${camel.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel</groupId>
<artifactId>camel-asterisk</artifactId>
<version>${camel.version}</version>
</dependency>
@@ -1695,6 +1700,16 @@
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-as2</artifactId>
+ <version>${camel-quarkus.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-as2-deployment</artifactId>
+ <version>${camel-quarkus.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-asterisk</artifactId>
<version>${camel-quarkus.version}</version>
</dependency>
@@ -3675,6 +3690,16 @@
</dependency>
<dependency>
<groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-support-bouncycastle</artifactId>
+ <version>${camel-quarkus.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
+ <artifactId>camel-quarkus-support-bouncycastle-deployment</artifactId>
+ <version>${camel-quarkus.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.camel.quarkus</groupId>
<artifactId>camel-quarkus-support-common</artifactId>
<version>${camel-quarkus.version}</version>
</dependency>
@@ -4431,6 +4456,16 @@
<version>${ahc.version}</version>
</dependency>
<dependency>
+ <artifactId>bcpkix-jdk15on</artifactId>
+ <groupId>org.bouncycastle</groupId>
+ <version>${bouncycastle.version}</version>
+ </dependency>
+ <dependency>
+ <artifactId>bcprov-jdk15on</artifactId>
+ <groupId>org.bouncycastle</groupId>
+ <version>${bouncycastle.version}</version>
+ </dependency>
+ <dependency>
<groupId>org.codehaus.groovy</groupId>
<artifactId>groovy</artifactId>
<version>${groovy.version}</version>
diff --git a/tooling/scripts/test-categories.yaml b/tooling/scripts/test-categories.yaml
index 5c800ad..b148895 100644
--- a/tooling/scripts/test-categories.yaml
+++ b/tooling/scripts/test-categories.yaml
@@ -95,6 +95,7 @@ misc:
- qute
- stream
- tika
+ - as2
networking2-dataformats:
- git
- mail