You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@camel.apache.org by ac...@apache.org on 2020/03/25 10:22:21 UTC

[camel-karaf] branch master updated (0b7cb5b -> e2518a4)

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

acosentino pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/camel-karaf.git.


    from 0b7cb5b  Added integration test again for camel-osgi-activator and fix
     new d10545d  Added camel-itest-osgi module
     new ed7f3f1  Camel-itest-osgi: set up the profile for testing
     new c447139  Added camel-test-karaf
     new 67b0879  Camel-test-karaf: Use the correct GroupID
     new e2518a4  Camel-test-karaf: Fixed the groupId and skip test for camel-itest-osgi

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 components/camel-test-karaf/pom.xml                | 216 ++++++++++
 .../services/org/apache/camel/other.properties     |   7 +
 .../src/generated/resources/test-karaf.json        |  14 +
 .../camel-test-karaf/src/main/docs/test-karaf.adoc |  10 +
 .../camel/test/karaf/AbstractFeatureTest.java      | 479 +++++++++++++++++++++
 .../camel/test/karaf/CamelKarafTestSupport.java    | 390 +++++++++++++++++
 components/pom.xml                                 |   1 +
 .../karaf/features/src/main/resources/features.xml |   4 +-
 pom.xml                                            |   5 +
 tests/camel-itest-osgi/README.adoc                 |  24 ++
 .../camel-itest-osgi/kill-karaf.sh                 |  14 +-
 tests/camel-itest-osgi/pom.xml                     | 103 +++++
 tests/camel-itest-osgi/run-tests.sh                |  73 ++++
 .../src/main/resources/META-INF/LICENSE.txt        |   0
 .../src/main/resources/META-INF/NOTICE.txt         |   0
 .../java/org/apache/camel/itest/CamelCoreTest.java |  58 +++
 .../org/apache/camel/itest/CamelGroovyTest.java    |  58 +++
 .../org/apache/camel/itest/CamelHystrixTest.java   |  60 +++
 .../itest/CamelJacksonFallbackConverterTest.java   |  66 +++
 .../org/apache/camel/itest/CamelPgEventTest.java   |  58 +++
 .../camel/itest/CamelQuartzJmxUpdateTest.java      | 172 ++++++++
 .../apache/camel/itest/CamelSaxonEnabledTest.java  |  61 +++
 .../org/apache/camel/itest/CamelSaxonTest.java     |  61 +++
 .../apache/camel/itest/CamelTypeConverterTest.java |  82 ++++
 .../itest/DuplicateNamespacePrefixIssueTest.java   |  78 ++++
 .../test/java/org/apache/camel/itest/Pojo.java}    |  62 +--
 .../camel/itest/cxf/BeanInjectRouteBuilder.java    |  17 +-
 .../camel/itest/cxf/CamelCxfBeanInjectTest.java    | 102 +++++
 .../org/apache/camel/itest/cxf/SimpleBean.java     |   8 +-
 .../org/apache/camel/itest/cxf/SimpleService.java  |   8 +-
 .../camel/itest/typeconverter/MyConverter.java     |  23 +-
 .../src/test/resources/log4j2.properties           |   7 +-
 .../org/apache/camel/itest/CamelCoreTest.xml       |   6 +-
 .../org/apache/camel/itest/CamelGroovyTest.xml     |   6 +-
 .../org/apache/camel/itest/CamelHystrixTest.xml    |  11 +-
 .../itest/CamelJacksonFallbackConverterTest.xml    |   3 +-
 .../org/apache/camel/itest/CamelPgEventTest.xml    |  16 +-
 .../camel/itest/CamelQuartzJmxUpdateTest.xml       |  11 +-
 .../apache/camel/itest/CamelSaxonEnabledTest.xml   |  19 +-
 .../org/apache/camel/itest/CamelSaxonTest.xml      |  22 +-
 .../org/apache/camel/itest/CamelSpringTest.xml     |  18 +-
 .../apache/camel/itest/CamelTypeConverterTest.xml  |   3 +-
 .../camel/itest/cxf/CamelCxfBeanInjectTest.xml}    |  71 +--
 tests/pom.xml                                      |  23 +-
 44 files changed, 2377 insertions(+), 153 deletions(-)
 create mode 100644 components/camel-test-karaf/pom.xml
 create mode 100644 components/camel-test-karaf/src/generated/resources/META-INF/services/org/apache/camel/other.properties
 create mode 100644 components/camel-test-karaf/src/generated/resources/test-karaf.json
 create mode 100644 components/camel-test-karaf/src/main/docs/test-karaf.adoc
 create mode 100644 components/camel-test-karaf/src/main/java/org/apache/camel/test/karaf/AbstractFeatureTest.java
 create mode 100644 components/camel-test-karaf/src/main/java/org/apache/camel/test/karaf/CamelKarafTestSupport.java
 create mode 100644 tests/camel-itest-osgi/README.adoc
 copy components/camel-test-blueprint/src/test/resources/META-INF/services/org/apache/camel/TypeConverter => tests/camel-itest-osgi/kill-karaf.sh (69%)
 mode change 100644 => 100755
 create mode 100644 tests/camel-itest-osgi/pom.xml
 create mode 100755 tests/camel-itest-osgi/run-tests.sh
 copy {tooling/camel-karaf-docs-maven-plugin => tests/camel-itest-osgi}/src/main/resources/META-INF/LICENSE.txt (100%)
 copy {tooling/camel-karaf-docs-maven-plugin => tests/camel-itest-osgi}/src/main/resources/META-INF/NOTICE.txt (100%)
 create mode 100644 tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelCoreTest.java
 create mode 100644 tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelGroovyTest.java
 create mode 100644 tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelHystrixTest.java
 create mode 100644 tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelJacksonFallbackConverterTest.java
 create mode 100644 tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelPgEventTest.java
 create mode 100644 tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelQuartzJmxUpdateTest.java
 create mode 100644 tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelSaxonEnabledTest.java
 create mode 100644 tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelSaxonTest.java
 create mode 100644 tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelTypeConverterTest.java
 create mode 100644 tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/DuplicateNamespacePrefixIssueTest.java
 copy tests/{camel-blueprint-cxf-test/src/test/java/org/apache/camel/component/cxf/jaxrs/testbean/Customer.java => camel-itest-osgi/src/test/java/org/apache/camel/itest/Pojo.java} (59%)
 copy components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/BlueprintPropertyInjectRoute.java => tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/cxf/BeanInjectRouteBuilder.java (65%)
 create mode 100644 tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/cxf/CamelCxfBeanInjectTest.java
 copy core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/test/MyService.java => tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/cxf/SimpleBean.java (85%)
 copy components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/IEcho.java => tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/cxf/SimpleService.java (89%)
 copy components/camel-test-blueprint/src/test/java/org/apache/camel/test/blueprint/converter/FooConverterRegression.java => tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/typeconverter/MyConverter.java (70%)
 copy {core/camel-core-osgi => tests/camel-itest-osgi}/src/test/resources/log4j2.properties (81%)
 copy components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/BlueprintAddServiceTest.xml => tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelCoreTest.xml (88%)
 copy components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/BlueprintAddServiceTest.xml => tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelGroovyTest.xml (89%)
 copy components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/BlueprintAddServiceTest.xml => tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelHystrixTest.xml (77%)
 copy components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/packagescan3.xml => tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelJacksonFallbackConverterTest.xml (90%)
 copy components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/proxy.xml => tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelPgEventTest.xml (73%)
 copy components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/SimpleWeaveAddMockLastTest.xml => tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelQuartzJmxUpdateTest.xml (85%)
 copy components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/BlueprintMultipleServiceTest.xml => tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelSaxonEnabledTest.xml (72%)
 copy components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/BlueprintStreamCachingStrategyTest.xml => tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelSaxonTest.xml (69%)
 copy components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/SimpleWeaveAddMockLastTest.xml => tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelSpringTest.xml (66%)
 copy components/camel-test-blueprint/src/test/resources/org/apache/camel/test/blueprint/packagescan3.xml => tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelTypeConverterTest.xml (90%)
 copy tests/{camel-blueprint-cxf-test/src/test/resources/org/apache/camel/test/cxf/blueprint/CxfConsumerSoap12Beans.xml => camel-itest-osgi/src/test/resources/org/apache/camel/itest/cxf/CamelCxfBeanInjectTest.xml} (50%)


[camel-karaf] 05/05: Camel-test-karaf: Fixed the groupId and skip test for camel-itest-osgi

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit e2518a49f40e1fc17cf6681bf8cfe025d230f6d9
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Wed Mar 25 11:11:15 2020 +0100

    Camel-test-karaf: Fixed the groupId and skip test for camel-itest-osgi
---
 .../main/java/org/apache/camel/test/karaf/AbstractFeatureTest.java   | 2 +-
 pom.xml                                                              | 5 +++++
 tests/camel-itest-osgi/pom.xml                                       | 3 ++-
 3 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/components/camel-test-karaf/src/main/java/org/apache/camel/test/karaf/AbstractFeatureTest.java b/components/camel-test-karaf/src/main/java/org/apache/camel/test/karaf/AbstractFeatureTest.java
index 4297bdb..ed8cc9f 100644
--- a/components/camel-test-karaf/src/main/java/org/apache/camel/test/karaf/AbstractFeatureTest.java
+++ b/components/camel-test-karaf/src/main/java/org/apache/camel/test/karaf/AbstractFeatureTest.java
@@ -365,7 +365,7 @@ public abstract class AbstractFeatureTest {
             features(getCamelKarafFeatureUrl(), camelFeatures),
 
             // install camel-test-karaf as bundle (not feature as the feature causes a bundle refresh that invalidates the @Inject bundleContext)
-            mavenBundle().groupId("org.apache.camel").artifactId("camel-test-karaf").versionAsInProject(),
+            mavenBundle().groupId("org.apache.camel.karaf").artifactId("camel-test-karaf").versionAsInProject(),
             when(JavaVersionUtil.getMajorVersion() >= 9)
                     .useOptions(
                     systemProperty("pax.exam.osgi.`unresolved.fail").value("true"),
diff --git a/pom.xml b/pom.xml
index 1137571..21428a2 100644
--- a/pom.xml
+++ b/pom.xml
@@ -861,6 +861,11 @@
                 <version>${project.version}</version>
             </dependency>
             <dependency>
+                <groupId>org.apache.camel.karaf</groupId>
+                <artifactId>camel-test-karaf</artifactId>
+                <version>${project.version}</version>
+            </dependency>
+            <dependency>
                 <groupId>org.apache.camel</groupId>
                 <artifactId>camel-parent</artifactId>
                 <version>${camel-version}</version>
diff --git a/tests/camel-itest-osgi/pom.xml b/tests/camel-itest-osgi/pom.xml
index f631bf6..e85ef07 100644
--- a/tests/camel-itest-osgi/pom.xml
+++ b/tests/camel-itest-osgi/pom.xml
@@ -37,7 +37,7 @@
 
     <dependencies>
         <dependency>
-            <groupId>org.apache.camel</groupId>
+            <groupId>org.apache.camel.karaf</groupId>
             <artifactId>camel-test-karaf</artifactId>
             <scope>test</scope>
         </dependency>
@@ -93,6 +93,7 @@
                         <karafVersion>${karaf4-version}</karafVersion>
                         <camelKarafFeatureVersion>${project.version}</camelKarafFeatureVersion>
                     </systemPropertyVariables>
+                    <skipTests>true</skipTests>
                 </configuration>
             </plugin>
         </plugins>


[camel-karaf] 03/05: Added camel-test-karaf

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit c4471396fb5c85449945313568f96ed865a84bbd
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Wed Mar 25 10:20:10 2020 +0100

    Added camel-test-karaf
---
 components/camel-test-karaf/pom.xml                | 216 ++++++++++
 .../services/org/apache/camel/other.properties     |   7 +
 .../src/generated/resources/test-karaf.json        |  14 +
 .../camel-test-karaf/src/main/docs/test-karaf.adoc |  10 +
 .../camel/test/karaf/AbstractFeatureTest.java      | 479 +++++++++++++++++++++
 .../camel/test/karaf/CamelKarafTestSupport.java    | 390 +++++++++++++++++
 components/pom.xml                                 |   1 +
 7 files changed, 1117 insertions(+)

diff --git a/components/camel-test-karaf/pom.xml b/components/camel-test-karaf/pom.xml
new file mode 100644
index 0000000..fae9c3a
--- /dev/null
+++ b/components/camel-test-karaf/pom.xml
@@ -0,0 +1,216 @@
+<?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.karaf</groupId>
+        <artifactId>components</artifactId>
+        <version>3.2.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-test-karaf</artifactId>
+    <packaging>jar</packaging>
+
+    <name>Camel Karaf :: Test :: Karaf</name>
+    <description>Camel integration testing with Apache Karaf</description>
+
+    <properties>
+        <firstVersion>2.18.0</firstVersion>
+        <label>testing,java,osgi</label>
+
+        <karf-test-version>${karaf4-version}</karf-test-version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-junit4</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-container-karaf</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.ops4j.pax.exam</groupId>
+            <artifactId>pax-exam-link-mvn</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>javax.inject</groupId>
+            <artifactId>javax.inject</artifactId>
+            <version>1</version>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf.features</groupId>
+            <artifactId>org.apache.karaf.features.core</artifactId>
+            <version>${karaf4-version}</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>apache-karaf</artifactId>
+            <version>${karf-test-version}</version>
+            <type>tar.gz</type>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.configadmin</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.gogo.runtime</artifactId>
+            <version>1.1.2</version>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.core</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.cmpn</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-support</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test</artifactId>
+        </dependency>
+
+        <!-- test -->
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <pluginManagement>
+            <plugins>
+                <!-- Eclipse m2e Lifecycle Management -->
+                <plugin>
+                    <groupId>org.eclipse.m2e</groupId>
+                    <artifactId>lifecycle-mapping</artifactId>
+                    <version>${lifecycle-mapping-version}</version>
+                    <configuration>
+                        <lifecycleMappingMetadata>
+                            <pluginExecutions>
+                                <pluginExecution>
+                                    <pluginExecutionFilter>
+                                        <groupId>org.apache.servicemix.tooling</groupId>
+                                        <artifactId>depends-maven-plugin</artifactId>
+                                        <versionRange>${depends-maven-plugin-version}</versionRange>
+                                        <goals>
+                                            <goal>generate-depends-file</goal>
+                                        </goals>
+                                    </pluginExecutionFilter>
+                                    <action>
+                                        <ignore />
+                                    </action>
+                                </pluginExecution>
+                            </pluginExecutions>
+                        </lifecycleMappingMetadata>
+                    </configuration>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+        <plugins>
+            <!-- generate dependencies versions -->
+            <plugin>
+                <groupId>org.apache.servicemix.tooling</groupId>
+                <artifactId>depends-maven-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>generate-depends-file</id>
+                        <goals>
+                            <goal>generate-depends-file</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <!-- do not re-run these tests -->
+                    <rerunFailingTestsCount>0</rerunFailingTestsCount>
+                    <systemPropertyVariables>
+                        <karafVersion>${karaf4-version}</karafVersion>
+                    </systemPropertyVariables>
+                </configuration>
+            </plugin>
+
+            <plugin>
+                <groupId>org.apache.camel</groupId>
+                <artifactId>camel-bundle-plugin</artifactId>
+                <configuration>
+                    <instructions>
+                        <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+                        <!-- Export-Package>org.apache.camel.test.karaf</Export-Package -->
+                        <DynamicImport-Package>*</DynamicImport-Package>
+                        <Import-Package />
+                        <_removeheaders>Import-Package, Private-Package, Include-Resource, Karaf-Info,
+                            Require-Capability
+                        </_removeheaders>
+                    </instructions>
+                </configuration>
+            </plugin>
+
+        </plugins>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>ci-build-profile</id>
+            <activation>
+                <property>
+                    <name>maven.repo.local</name>
+                </property>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-surefire-plugin</artifactId>
+                        <configuration>
+                            <forkedProcessTimeoutInSeconds>300</forkedProcessTimeoutInSeconds>
+                            <!--
+                                when the local repo location has been specified, we need to pass
+                                on this information to PAX mvn url
+                            -->
+                            <argLine>-Dorg.ops4j.pax.url.mvn.localRepository=${maven.repo.local}</argLine>
+                            <systemPropertyVariables>
+                                <karafVersion>${karaf4-version}</karafVersion>
+                            </systemPropertyVariables>
+                        </configuration>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+    </profiles>
+</project>
diff --git a/components/camel-test-karaf/src/generated/resources/META-INF/services/org/apache/camel/other.properties b/components/camel-test-karaf/src/generated/resources/META-INF/services/org/apache/camel/other.properties
new file mode 100644
index 0000000..f3258d5
--- /dev/null
+++ b/components/camel-test-karaf/src/generated/resources/META-INF/services/org/apache/camel/other.properties
@@ -0,0 +1,7 @@
+# Generated by camel build tools - do NOT edit this file!
+name=test-karaf
+groupId=org.apache.camel.karaf
+artifactId=camel-test-karaf
+version=3.2.0-SNAPSHOT
+projectName=Camel Karaf :: Test :: Karaf
+projectDescription=Camel integration testing with Apache Karaf
diff --git a/components/camel-test-karaf/src/generated/resources/test-karaf.json b/components/camel-test-karaf/src/generated/resources/test-karaf.json
new file mode 100644
index 0000000..8fee4cc
--- /dev/null
+++ b/components/camel-test-karaf/src/generated/resources/test-karaf.json
@@ -0,0 +1,14 @@
+{
+  "other": {
+    "kind": "other",
+    "name": "test-karaf",
+    "title": "Test Karaf",
+    "description": "Camel integration testing with Apache Karaf",
+    "deprecated": false,
+    "firstVersion": "2.18.0",
+    "label": "testing,java,osgi",
+    "groupId": "org.apache.camel.karaf",
+    "artifactId": "camel-test-karaf",
+    "version": "3.2.0-SNAPSHOT"
+  }
+}
diff --git a/components/camel-test-karaf/src/main/docs/test-karaf.adoc b/components/camel-test-karaf/src/main/docs/test-karaf.adoc
new file mode 100644
index 0000000..5668522
--- /dev/null
+++ b/components/camel-test-karaf/src/main/docs/test-karaf.adoc
@@ -0,0 +1,10 @@
+= Test Karaf
+
+*Available since Camel 2.18*
+
+Camel testing using Apache Karaf with Pax-Exam.
+
+This component allows to perform integration testing by running Karaf containers using Pax-Exam.
+
+The component is in development and needs some more polish to be ready.
+In addition there is also need for documentation.
diff --git a/components/camel-test-karaf/src/main/java/org/apache/camel/test/karaf/AbstractFeatureTest.java b/components/camel-test-karaf/src/main/java/org/apache/camel/test/karaf/AbstractFeatureTest.java
new file mode 100644
index 0000000..4297bdb
--- /dev/null
+++ b/components/camel-test-karaf/src/main/java/org/apache/camel/test/karaf/AbstractFeatureTest.java
@@ -0,0 +1,479 @@
+/*
+ * 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.test.karaf;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.reflect.Field;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.EnumSet;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Locale;
+import java.util.Properties;
+import java.util.function.Consumer;
+
+import javax.inject.Inject;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Component;
+import org.apache.camel.spi.DataFormat;
+import org.apache.camel.spi.Language;
+import org.apache.karaf.features.FeaturesService;
+import org.junit.After;
+import org.junit.Before;
+import org.ops4j.pax.exam.CoreOptions;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.ProbeBuilder;
+import org.ops4j.pax.exam.TestProbeBuilder;
+import org.ops4j.pax.exam.karaf.container.internal.JavaVersionUtil;
+import org.ops4j.pax.exam.karaf.options.KarafDistributionOption;
+import org.ops4j.pax.exam.karaf.options.LogLevelOption;
+import org.ops4j.pax.exam.options.UrlReference;
+import org.ops4j.pax.exam.options.extra.VMOption;
+import org.ops4j.pax.tinybundles.core.TinyBundle;
+import org.ops4j.pax.tinybundles.core.TinyBundles;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleException;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.blueprint.container.BlueprintContainer;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.Assert.assertNotNull;
+import static org.ops4j.pax.exam.CoreOptions.maven;
+import static org.ops4j.pax.exam.CoreOptions.mavenBundle;
+import static org.ops4j.pax.exam.CoreOptions.systemProperty;
+import static org.ops4j.pax.exam.CoreOptions.vmOption;
+import static org.ops4j.pax.exam.CoreOptions.when;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.configureConsole;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.editConfigurationFilePut;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.features;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.keepRuntimeFolder;
+import static org.ops4j.pax.exam.karaf.options.KarafDistributionOption.logLevel;
+
+public abstract class AbstractFeatureTest {
+
+    public static final Long SERVICE_TIMEOUT = 30000L;
+    protected static final Logger LOG = LoggerFactory.getLogger(AbstractFeatureTest.class);
+
+    @Inject
+    protected BundleContext bundleContext;
+
+    @Inject
+    protected BlueprintContainer blueprintContainer;
+
+    @Inject
+    protected FeaturesService featuresService;
+
+    @ProbeBuilder
+    public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) {
+        // makes sure the generated Test-Bundle contains this import!
+        probe.setHeader(Constants.DYNAMICIMPORT_PACKAGE, "*");
+        return probe;
+    }
+
+    @Before
+    public void setUp() throws Exception {
+        LOG.info("setUp() using BundleContext: {}", bundleContext);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        LOG.info("tearDown()");
+    }
+
+    protected Bundle installBlueprintAsBundle(String name, URL url, boolean start) throws BundleException {
+        return installBlueprintAsBundle(name, url, start, bundle -> { });
+    }
+
+    protected Bundle installBlueprintAsBundle(String name, URL url, boolean start, Consumer<Object> consumer) throws BundleException {
+        // TODO Type Consumer<TinyBundle> cannot be used for this method signature to avoid bundle dependency to pax tinybundles
+        TinyBundle bundle = TinyBundles.bundle();
+        bundle.add("OSGI-INF/blueprint/blueprint-" + name.toLowerCase(Locale.ENGLISH) + ".xml", url);
+        bundle.set("Manifest-Version", "2")
+                .set("Bundle-ManifestVersion", "2")
+                .set("Bundle-SymbolicName", name)
+                .set("Bundle-Version", "1.0.0")
+                .set(Constants.DYNAMICIMPORT_PACKAGE, "*");
+        consumer.accept(bundle);
+        Bundle answer = bundleContext.installBundle(name, bundle.build());
+
+        if (start) {
+            answer.start();
+        }
+        return answer;
+    }
+
+    protected Bundle installSpringAsBundle(String name, URL url, boolean start) throws BundleException {
+        return installSpringAsBundle(name, url, start, bundle -> { });
+    }
+
+    protected Bundle installSpringAsBundle(String name, URL url, boolean start, Consumer<Object> consumer) throws BundleException {
+        // TODO Type Consumer<TinyBundle> cannot be used for this method signature to avoid bundle dependency to pax tinybundles
+        TinyBundle bundle = TinyBundles.bundle();
+        bundle.add("META-INF/spring/spring-" + name.toLowerCase(Locale.ENGLISH) + ".xml", url);
+        bundle.set("Manifest-Version", "2")
+                .set("Bundle-ManifestVersion", "2")
+                .set("Bundle-SymbolicName", name)
+                .set("Bundle-Version", "1.0.0");
+        consumer.accept(bundle);
+        Bundle answer = bundleContext.installBundle(name, bundle.build());
+
+        if (start) {
+            answer.start();
+        }
+        return answer;
+    }
+
+    protected void installCamelFeature(String mainFeature) throws Exception {
+        if (!mainFeature.startsWith("camel-")) {
+            mainFeature = "camel-" + mainFeature;
+        }
+        LOG.info("Install main feature: {}", mainFeature);
+        // do not refresh bundles causing out bundle context to be invalid
+        // TODO: see if we can find a way maybe to install camel.xml as bundle/feature instead of part of unit test (see src/test/resources/OSGI-INF/blueprint)
+        featuresService.installFeature(mainFeature, EnumSet.of(FeaturesService.Option.NoAutoRefreshBundles));
+    }
+
+    protected void overridePropertiesWithConfigAdmin(String pid, Properties props) throws IOException {
+        ConfigurationAdmin configAdmin = getOsgiService(bundleContext, ConfigurationAdmin.class);
+        // passing null as second argument ties the configuration to correct bundle.
+        Configuration config = configAdmin.getConfiguration(pid, null);
+        if (config == null) {
+            throw new IllegalArgumentException("Cannot find configuration with pid " + pid + " in OSGi ConfigurationAdmin service.");
+        }
+
+        // let's merge configurations
+        Dictionary<String, Object> currentProperties = config.getProperties();
+        Dictionary newProps = new Properties();
+        if (currentProperties == null) {
+            currentProperties = newProps;
+        }
+        for (Enumeration<String> ek = currentProperties.keys(); ek.hasMoreElements();) {
+            String k = ek.nextElement();
+            newProps.put(k, currentProperties.get(k));
+        }
+        for (String p : props.stringPropertyNames()) {
+            newProps.put(p, props.getProperty(p));
+        }
+
+        LOG.info("Updating ConfigAdmin {} by overriding properties {}", config, newProps);
+        config.update(newProps);
+    }
+
+    protected void testComponent(String component) throws Exception {
+        testComponent("camel-" + component, component);
+    }
+
+    protected void testComponent(String mainFeature, String component) throws Exception {
+        LOG.info("Looking up CamelContext(myCamel) in OSGi Service Registry");
+
+        installCamelFeature(mainFeature);
+
+        CamelContext camelContext = getOsgiService(bundleContext, CamelContext.class, "(camel.context.name=myCamel)", SERVICE_TIMEOUT);
+        assertNotNull("Cannot find CamelContext with name myCamel", camelContext);
+
+        LOG.info("Getting Camel component: {}", component);
+        // do not auto start the component as it may not have been configured properly and fail in its start method
+        Component comp = camelContext.getComponent(component, true, false);
+        assertNotNull("Cannot get component with name: " + component, comp);
+
+        LOG.info("Found Camel component: {} instance: {} with className: {}", component, comp, comp.getClass());
+    }
+
+    protected void testDataFormat(String dataFormat) throws Exception {
+        testDataFormat("camel-" + dataFormat, dataFormat);
+    }
+
+    protected void testDataFormat(String mainFeature, String dataFormat) throws Exception {
+        LOG.info("Looking up CamelContext(myCamel) in OSGi Service Registry");
+
+        installCamelFeature(mainFeature);
+
+        CamelContext camelContext = getOsgiService(bundleContext, CamelContext.class, "(camel.context.name=myCamel)", SERVICE_TIMEOUT);
+        assertNotNull("Cannot find CamelContext with name myCamel", camelContext);
+
+        LOG.info("Getting Camel dataformat: {}", dataFormat);
+        DataFormat df = camelContext.resolveDataFormat(dataFormat);
+        assertNotNull("Cannot get dataformat with name: " + dataFormat, df);
+
+        LOG.info("Found Camel dataformat: {} instance: {} with className: {}", dataFormat, df, df.getClass());
+    }
+
+    protected void testLanguage(String language) throws Exception {
+        testLanguage("camel-" + language, language);
+    }
+
+    protected void testLanguage(String mainFeature, String language) throws Exception {
+        LOG.info("Looking up CamelContext(myCamel) in OSGi Service Registry");
+
+        installCamelFeature(mainFeature);
+
+        CamelContext camelContext = getOsgiService(bundleContext, CamelContext.class, "(camel.context.name=myCamel)", 20000);
+        assertNotNull("Cannot find CamelContext with name myCamel", camelContext);
+
+        LOG.info("Getting Camel language: {}", language);
+        Language lan = camelContext.resolveLanguage(language);
+        assertNotNull("Cannot get language with name: " + language, lan);
+
+        LOG.info("Found Camel language: {} instance: {} with className: {}", language, lan, lan.getClass());
+    }
+
+    public static String extractName(Class<?> clazz) {
+        String name = clazz.getName();
+        int id0 = name.indexOf("Camel") + "Camel".length();
+        int id1 = name.indexOf("Test");
+        StringBuilder sb = new StringBuilder();
+        for (int i = id0; i < id1; i++) {
+            char c = name.charAt(i);
+            if (Character.isUpperCase(c) && sb.length() > 0) {
+                sb.append("-");
+            }
+            sb.append(Character.toLowerCase(c));
+        }
+        return sb.toString();
+    }
+
+    public static UrlReference getCamelKarafFeatureUrl() {
+        return mavenBundle().
+                groupId("org.apache.camel.karaf").
+                artifactId("apache-camel").
+                version(getCamelKarafFeatureVersion()).
+                type("xml/features");
+    }
+
+    private static String getCamelKarafFeatureVersion() {
+        String camelKarafFeatureVersion = System.getProperty("camelKarafFeatureVersion");
+        if (camelKarafFeatureVersion == null) {
+            throw new RuntimeException("Please specify the maven artifact version to use for org.apache.camel.karaf/apache-camel through the camelKarafFeatureVersion System property");
+        }
+        return camelKarafFeatureVersion;
+    }
+
+    private static void switchPlatformEncodingToUTF8() {
+        try {
+            System.setProperty("file.encoding", "UTF-8");
+            Field charset = Charset.class.getDeclaredField("defaultCharset");
+            charset.setAccessible(true);
+            charset.set(null, null);
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    private static String getKarafVersion() {
+        InputStream ins = AbstractFeatureTest.class.getResourceAsStream("/META-INF/maven/dependencies.properties");
+        Properties p = new Properties();
+        try {
+            p.load(ins);
+        } catch (Throwable t) {
+            // ignore
+        }
+        String karafVersion = p.getProperty("org.apache.karaf/apache-karaf/version");
+        if (karafVersion == null) {
+            karafVersion = System.getProperty("karafVersion");
+        }
+        if (karafVersion == null) {
+            // setup the default version of it
+            karafVersion = "4.1.0";
+        }
+        return karafVersion;
+    }
+
+    public static Option[] configure(String... extra) {
+
+        List<String> camel = new ArrayList<>();
+        camel.add("camel");
+        if (extra != null && extra.length > 0) {
+            for (String e : extra) {
+                camel.add(e);
+            }
+        }
+        final String[] camelFeatures = camel.toArray(new String[camel.size()]);
+
+        switchPlatformEncodingToUTF8();
+        String karafVersion = getKarafVersion();
+        LOG.info("*** Apache Karaf version is " + karafVersion + " ***");
+
+        Option[] options = new Option[]{
+            // for remote debugging
+//            new VMOption("-Xdebug"),
+//            new VMOption("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5008"),
+
+            KarafDistributionOption.karafDistributionConfiguration()
+                    .frameworkUrl(maven().groupId("org.apache.karaf").artifactId("apache-karaf").type("tar.gz").versionAsInProject())
+                    .karafVersion(karafVersion)
+                    .name("Apache Karaf")
+                    .useDeployFolder(false).unpackDirectory(new File("target/paxexam/unpack/")),
+            logLevel(LogLevelOption.LogLevel.INFO),
+
+            // keep the folder so we can look inside when something fails
+            keepRuntimeFolder(),
+
+            // Disable the SSH port
+            configureConsole().ignoreRemoteShell(),
+
+            // need to modify the jre.properties to export some com.sun packages that some features rely on
+//            KarafDistributionOption.replaceConfigurationFile("etc/jre.properties", new File("src/test/resources/jre.properties")),
+
+            vmOption("-Dfile.encoding=UTF-8"),
+
+            // Disable the Karaf shutdown port
+            editConfigurationFilePut("etc/custom.properties", "karaf.shutdown.port", "-1"),
+
+            // log config
+            editConfigurationFilePut("etc/custom.properties", "karaf.log", "${karaf.data}/log"),
+
+            // Assign unique ports for Karaf
+//            editConfigurationFilePut("etc/org.ops4j.pax.web.cfg", "org.osgi.service.http.port", Integer.toString(AvailablePortFinder.getNextAvailable())),
+//            editConfigurationFilePut("etc/org.apache.karaf.management.cfg", "rmiRegistryPort", Integer.toString(AvailablePortFinder.getNextAvailable())),
+//            editConfigurationFilePut("etc/org.apache.karaf.management.cfg", "rmiServerPort", Integer.toString(AvailablePortFinder.getNextAvailable())),
+
+            // install junit
+            CoreOptions.junitBundles(),
+
+            // install camel
+            features(getCamelKarafFeatureUrl(), camelFeatures),
+
+            // install camel-test-karaf as bundle (not feature as the feature causes a bundle refresh that invalidates the @Inject bundleContext)
+            mavenBundle().groupId("org.apache.camel").artifactId("camel-test-karaf").versionAsInProject(),
+            when(JavaVersionUtil.getMajorVersion() >= 9)
+                    .useOptions(
+                    systemProperty("pax.exam.osgi.`unresolved.fail").value("true"),
+                    systemProperty("java.awt.headless").value("true"),
+                    new VMOption("--add-reads=java.xml=java.logging"),
+                    new VMOption("--add-exports=java.base/org.apache.karaf.specs.locator=java.xml,ALL-UNNAMED"),
+                    new VMOption("--patch-module"),
+                    new VMOption("java.base=lib/endorsed/org.apache.karaf.specs.locator-"
+                            + System.getProperty("karafVersion", "4.2.4") + ".jar"),
+                    new VMOption("--patch-module"),
+                    new VMOption("java.xml=lib/endorsed/org.apache.karaf.specs.java.xml-"
+                            + System.getProperty("karafVersion", "4.2.4") + ".jar"),
+                    new VMOption("--add-opens"),
+                    new VMOption("java.base/java.security=ALL-UNNAMED"),
+                    new VMOption("--add-opens"),
+                    new VMOption("java.base/java.net=ALL-UNNAMED"),
+                    new VMOption("--add-opens"),
+                    new VMOption("java.base/java.lang=ALL-UNNAMED"),
+                    new VMOption("--add-opens"),
+                    new VMOption("java.base/java.util=ALL-UNNAMED"),
+                    new VMOption("--add-opens"),
+                    new VMOption("java.naming/javax.naming.spi=ALL-UNNAMED"),
+                    new VMOption("--add-opens"),
+                    new VMOption("java.rmi/sun.rmi.transport.tcp=ALL-UNNAMED"),
+                    new VMOption("--add-exports=java.base/sun.net.www.protocol.http=ALL-UNNAMED"),
+                    new VMOption("--add-exports=java.base/sun.net.www.protocol.https=ALL-UNNAMED"),
+                    new VMOption("--add-exports=java.base/sun.net.www.protocol.jar=ALL-UNNAMED"),
+                    new VMOption("--add-exports=jdk.naming.rmi/com.sun.jndi.url.rmi=ALL-UNNAMED"),
+                    new VMOption("-classpath"),
+                    new VMOption("lib/jdk9plus/*" + File.pathSeparator + "lib/boot/*")
+            )
+        };
+
+        return options;
+    }
+
+    protected <T> T getOsgiService(BundleContext bundleContext, Class<T> type) {
+        return getOsgiService(bundleContext, type, null, SERVICE_TIMEOUT);
+    }
+
+    protected <T> T getOsgiService(BundleContext bundleContext, Class<T> type, long timeout) {
+        return getOsgiService(bundleContext, type, null, timeout);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T getOsgiService(BundleContext bundleContext, Class<T> type, String filter, long timeout) {
+        ServiceTracker tracker;
+        try {
+            String flt;
+            if (filter != null) {
+                if (filter.startsWith("(")) {
+                    flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")" + filter + ")";
+                } else {
+                    flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")(" + filter + "))";
+                }
+            } else {
+                flt = "(" + Constants.OBJECTCLASS + "=" + type.getName() + ")";
+            }
+            Filter osgiFilter = FrameworkUtil.createFilter(flt);
+            tracker = new ServiceTracker(bundleContext, osgiFilter, null);
+            tracker.open(true);
+            // Note that the tracker is not closed to keep the reference
+            // This is buggy, as the service reference may change i think
+            Object svc = tracker.waitForService(timeout);
+
+            if (svc == null) {
+                Dictionary<?, ?> dic = bundleContext.getBundle().getHeaders();
+                LOG.warn("Test bundle headers: " + explode(dic));
+
+                for (ServiceReference ref : asCollection(bundleContext.getAllServiceReferences(null, null))) {
+                    LOG.warn("ServiceReference: " + ref + ", bundle: " + ref.getBundle() + ", symbolicName: " + ref.getBundle().getSymbolicName());
+                }
+
+                for (ServiceReference ref : asCollection(bundleContext.getAllServiceReferences(null, flt))) {
+                    LOG.warn("Filtered ServiceReference: " + ref + ", bundle: " + ref.getBundle() + ", symbolicName: " + ref.getBundle().getSymbolicName());
+                }
+
+                throw new RuntimeException("Gave up waiting for service " + flt);
+            }
+            return type.cast(svc);
+        } catch (InvalidSyntaxException e) {
+            throw new IllegalArgumentException("Invalid filter", e);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /**
+     * Explode the dictionary into a <code>,</code> delimited list of <code>key=value</code> pairs.
+     */
+    private static String explode(Dictionary<?, ?> dictionary) {
+        Enumeration<?> keys = dictionary.keys();
+        StringBuilder result = new StringBuilder();
+        while (keys.hasMoreElements()) {
+            Object key = keys.nextElement();
+            result.append(String.format("%s=%s", key, dictionary.get(key)));
+            if (keys.hasMoreElements()) {
+                result.append(", ");
+            }
+        }
+        return result.toString();
+    }
+
+    /**
+     * Provides an iterable collection of references, even if the original array is <code>null</code>.
+     */
+    private static Collection<ServiceReference> asCollection(ServiceReference[] references) {
+        return references == null ? new ArrayList<>(0) : Arrays.asList(references);
+    }
+
+}
diff --git a/components/camel-test-karaf/src/main/java/org/apache/camel/test/karaf/CamelKarafTestSupport.java b/components/camel-test-karaf/src/main/java/org/apache/camel/test/karaf/CamelKarafTestSupport.java
new file mode 100644
index 0000000..992af1e
--- /dev/null
+++ b/components/camel-test-karaf/src/main/java/org/apache/camel/test/karaf/CamelKarafTestSupport.java
@@ -0,0 +1,390 @@
+/*
+ * 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.test.karaf;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.PrintStream;
+import java.net.URL;
+import java.security.Principal;
+import java.security.PrivilegedExceptionAction;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Hashtable;
+import java.util.Set;
+import java.util.concurrent.Callable;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.FutureTask;
+import java.util.concurrent.TimeUnit;
+
+import javax.inject.Inject;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXServiceURL;
+import javax.security.auth.Subject;
+
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.test.junit4.CamelTestSupport;
+import org.apache.felix.service.command.CommandProcessor;
+import org.apache.felix.service.command.CommandSession;
+import org.apache.karaf.features.Feature;
+import org.apache.karaf.features.FeaturesService;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.ProbeBuilder;
+import org.ops4j.pax.exam.TestProbeBuilder;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Filter;
+import org.osgi.framework.FrameworkUtil;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+
+public class CamelKarafTestSupport extends CamelTestSupport {
+
+    static final Long COMMAND_TIMEOUT = 30000L;
+    static final Long SERVICE_TIMEOUT = 30000L;
+
+    protected ExecutorService executor = Executors.newCachedThreadPool();
+
+    @Inject
+    protected BundleContext bundleContext;
+
+    @Inject
+    protected FeaturesService featuresService;
+
+    @ProbeBuilder
+    public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) {
+        probe.setHeader(Constants.DYNAMICIMPORT_PACKAGE, "*,org.apache.felix.service.*;status=provisional");
+        return probe;
+    }
+
+    public File getConfigFile(String path) {
+        URL res = this.getClass().getResource(path);
+        if (res == null) {
+            throw new RuntimeException("Config resource " + path + " not found");
+        }
+        return new File(res.getFile());
+    }
+
+    public static Option[] configure(String... extra) {
+        return AbstractFeatureTest.configure(extra);
+    }
+
+    /**
+     * Executes a shell command and returns output as a String.
+     * Commands have a default timeout of 10 seconds.
+     *
+     * @param command The command to execute
+     * @param principals The principals (e.g. RolePrincipal objects) to run the command under
+     */
+    protected String executeCommand(final String command, Principal... principals) {
+        return executeCommand(command, COMMAND_TIMEOUT, false, principals);
+    }
+
+    /**
+     * Executes a shell command and returns output as a String.
+     * Commands have a default timeout of 10 seconds.
+     *
+     * @param command    The command to execute.
+     * @param timeout    The amount of time in millis to wait for the command to execute.
+     * @param silent     Specifies if the command should be displayed in the screen.
+     * @param principals The principals (e.g. RolePrincipal objects) to run the command under
+     */
+    protected String executeCommand(final String command, final Long timeout, final Boolean silent, final Principal... principals) {
+
+        waitForCommandService(command);
+        String response;
+        final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
+        final PrintStream printStream = new PrintStream(byteArrayOutputStream);
+        final Callable<String> commandCallable = new Callable<String>() {
+            @Override
+            public String call() throws Exception {
+                try {
+                    if (!silent) {
+                        System.err.println(command);
+                    }
+                    final CommandProcessor commandProcessor = getOsgiService(CommandProcessor.class);
+                    final CommandSession commandSession = commandProcessor.createSession(System.in, printStream, System.err);
+                    commandSession.execute(command);
+                } catch (Exception e) {
+                    throw new RuntimeException(e.getMessage(), e);
+                }
+                printStream.flush();
+                return byteArrayOutputStream.toString();
+            }
+        };
+
+        FutureTask<String> commandFuture;
+        if (principals.length == 0) {
+            commandFuture = new FutureTask<>(commandCallable);
+        } else {
+            // If principals are defined, run the command callable via Subject.doAs()
+            commandFuture = new FutureTask<>(new Callable<String>() {
+                @Override
+                public String call() throws Exception {
+                    Subject subject = new Subject();
+                    subject.getPrincipals().addAll(Arrays.asList(principals));
+                    return Subject.doAs(subject, new PrivilegedExceptionAction<String>() {
+                        @Override
+                        public String run() throws Exception {
+                            return commandCallable.call();
+                        }
+                    });
+                }
+            });
+        }
+
+
+        try {
+            executor.submit(commandFuture);
+            response = commandFuture.get(timeout, TimeUnit.MILLISECONDS);
+        } catch (Exception e) {
+            e.printStackTrace(System.err);
+            response = "SHELL COMMAND TIMED OUT: ";
+        }
+
+        return response;
+    }
+
+    private void waitForCommandService(String command) {
+        // the commands are represented by services. Due to the asynchronous nature of services they may not be
+        // immediately available. This code waits the services to be available, in their secured form. It
+        // means that the code waits for the command service to appear with the roles defined.
+    
+        if (command == null || command.length() == 0) {
+            return;
+        }
+       
+        int spaceIdx = command.indexOf(' ');
+        if (spaceIdx > 0) {
+            command = command.substring(0, spaceIdx);
+        }
+        int colonIndx = command.indexOf(':');
+        
+        try {
+            if (colonIndx > 0) {
+                String scope = command.substring(0, colonIndx);
+                String function = command.substring(colonIndx + 1);
+                waitForService("(&(osgi.command.scope=" + scope + ")(osgi.command.function=" + function + "))", SERVICE_TIMEOUT);
+            } else {
+                waitForService("(osgi.command.function=" + command + ")", SERVICE_TIMEOUT);
+            }
+        } catch (Exception e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    private void waitForService(String filter, long timeout) throws InvalidSyntaxException,
+        InterruptedException {
+        
+        ServiceTracker st = new ServiceTracker(bundleContext,
+                                               bundleContext.createFilter(filter),
+                                               null);
+        try {
+            st.open();
+            st.waitForService(timeout);
+        } finally {
+            st.close();
+        }
+    }
+
+    protected <T> T getOsgiService(Class<T> type, long timeout) {
+        return getOsgiService(type, null, timeout);
+    }
+
+    protected <T> T getOsgiService(Class<T> type) {
+        return getOsgiService(type, null, SERVICE_TIMEOUT);
+    }
+
+    @SuppressWarnings("unchecked")
+    protected <T> T getOsgiService(Class<T> type, String filter, long timeout) {
+        ServiceTracker tracker = null;
+        try {
+            String flt;
+            if (filter != null) {
+                if (filter.startsWith("(")) {
+                    flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")" + filter + ")";
+                } else {
+                    flt = "(&(" + Constants.OBJECTCLASS + "=" + type.getName() + ")(" + filter + "))";
+                }
+            } else {
+                flt = "(" + Constants.OBJECTCLASS + "=" + type.getName() + ")";
+            }
+            Filter osgiFilter = FrameworkUtil.createFilter(flt);
+            tracker = new ServiceTracker(bundleContext, osgiFilter, null);
+            tracker.open(true);
+            // Note that the tracker is not closed to keep the reference
+            // This is buggy, as the service reference may change i think
+            Object svc = type.cast(tracker.waitForService(timeout));
+            if (svc == null) {
+                Dictionary dic = bundleContext.getBundle().getHeaders();
+                System.err.println("Test bundle headers: " + explode(dic));
+
+                for (ServiceReference ref : asCollection(bundleContext.getAllServiceReferences(null, null))) {
+                    System.err.println("ServiceReference: " + ref);
+                }
+
+                for (ServiceReference ref : asCollection(bundleContext.getAllServiceReferences(null, flt))) {
+                    System.err.println("Filtered ServiceReference: " + ref);
+                }
+
+                throw new RuntimeException("Gave up waiting for service " + flt);
+            }
+            return type.cast(svc);
+        } catch (InvalidSyntaxException e) {
+            throw new IllegalArgumentException("Invalid filter", e);
+        } catch (InterruptedException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
+    /*
+    * Explode the dictionary into a ,-delimited list of key=value pairs
+    */
+    private static String explode(Dictionary dictionary) {
+        Enumeration keys = dictionary.keys();
+        StringBuilder sb = new StringBuilder();
+        while (keys.hasMoreElements()) {
+            Object key = keys.nextElement();
+            sb.append(String.format("%s=%s", key, dictionary.get(key)));
+            if (keys.hasMoreElements()) {
+                sb.append(", ");
+            }
+        }
+        return sb.toString();
+    }
+
+    /**
+     * Provides an iterable collection of references, even if the original array is null
+     */
+    private static Collection<ServiceReference> asCollection(ServiceReference[] references) {
+        return references != null ? Arrays.asList(references) : Collections.<ServiceReference>emptyList();
+    }
+
+    public JMXConnector getJMXConnector() throws Exception {
+        return getJMXConnector("karaf", "karaf");
+    }
+
+    public JMXConnector getJMXConnector(String userName, String passWord) throws Exception {
+        JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:1099/karaf-root");
+        Hashtable<String, Object> env = new Hashtable<>();
+        String[] credentials = new String[]{userName, passWord};
+        env.put("jmx.remote.credentials", credentials);
+        JMXConnector connector = JMXConnectorFactory.connect(url, env);
+        return connector;
+    }
+
+    public void assertFeatureInstalled(String featureName) {
+        try {
+            Feature[] features = featuresService.listInstalledFeatures();
+            for (Feature feature : features) {
+                if (featureName.equals(feature.getName())) {
+                    return;
+                }
+            }
+            fail("Feature " + featureName + " should be installed but is not");
+        } catch (Exception e) {
+            throw RuntimeCamelException.wrapRuntimeCamelException(e);
+        }
+    }
+
+    public void assertFeatureInstalled(String featureName, String featureVersion) {
+        try {
+            Feature[] features = featuresService.listInstalledFeatures();
+            for (Feature feature : features) {
+                if (featureName.equals(feature.getName()) && featureVersion.equals(feature.getVersion())) {
+                    return;
+                }
+            }
+            fail("Feature " + featureName + "/" + featureVersion + " should be installed but is not");
+        } catch (Exception e) {
+            throw RuntimeCamelException.wrapRuntimeCamelException(e);
+        }
+    }
+    
+    protected void installAndAssertFeature(String feature) throws Exception {
+        featuresService.installFeature(feature);
+        assertFeatureInstalled(feature);
+    }
+
+    protected void installAndAssertFeature(String feature, String version) throws Exception {
+        featuresService.installFeature(feature, version);
+        assertFeatureInstalled(feature, version);
+    }
+
+    protected void installAssertAndUninstallFeature(String feature) throws Exception {
+        Set<Feature> featuresBefore = new HashSet<>(Arrays.asList(featuresService.listInstalledFeatures()));
+        try {
+            featuresService.installFeature(feature);
+            assertFeatureInstalled(feature);
+        } finally {
+            uninstallNewFeatures(featuresBefore);
+        }
+    }
+
+    protected void installAssertAndUninstallFeature(String feature, String version) throws Exception {
+        Set<Feature> featuresBefore = new HashSet<>(Arrays.asList(featuresService.listInstalledFeatures()));
+        try {
+            featuresService.installFeature(feature, version);
+            assertFeatureInstalled(feature, version);
+        } finally {
+            uninstallNewFeatures(featuresBefore);
+        }
+    }
+
+    protected void installAssertAndUninstallFeatures(String... feature) throws Exception {
+        Set<Feature> featuresBefore = new HashSet<>(Arrays.asList(featuresService.listInstalledFeatures()));
+        try {
+            for (String curFeature : feature) {
+                featuresService.installFeature(curFeature);
+                assertFeatureInstalled(curFeature);
+            }
+        } finally {
+            uninstallNewFeatures(featuresBefore);
+        }
+    }
+
+    /**
+     * The feature service does not uninstall feature dependencies when uninstalling a single feature.
+     * So we need to make sure we uninstall all features that were newly installed.
+     */
+    protected void uninstallNewFeatures(Set<Feature> featuresBefore) {
+        try {
+            Feature[] features = featuresService.listInstalledFeatures();
+            for (Feature curFeature : features) {
+                if (!featuresBefore.contains(curFeature)) {
+                    try {
+                        System.out.println("Uninstalling " + curFeature.getName());
+                        featuresService.uninstallFeature(curFeature.getName(), curFeature.getVersion());
+                    } catch (Exception e) {
+                        // ignore
+                    }
+                }
+            }
+        } catch (Exception e) {
+            throw RuntimeCamelException.wrapRuntimeCamelException(e);
+        }
+    }
+
+}
diff --git a/components/pom.xml b/components/pom.xml
index a02240d..c68fc35 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -40,6 +40,7 @@
         <module>camel-kura</module>
         <module>camel-osgi-activator</module>
         <module>camel-paxlogging</module>
+        <module>camel-test-karaf</module>
     </modules>
 
     <properties>


[camel-karaf] 02/05: Camel-itest-osgi: set up the profile for testing

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit ed7f3f160be677b040cebaf19b790600b83b03e3
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Wed Mar 25 10:18:17 2020 +0100

    Camel-itest-osgi: set up the profile for testing
---
 tests/camel-itest-osgi/pom.xml |  2 +-
 tests/pom.xml                  | 22 +++-------------------
 2 files changed, 4 insertions(+), 20 deletions(-)

diff --git a/tests/camel-itest-osgi/pom.xml b/tests/camel-itest-osgi/pom.xml
index fd26b15..f631bf6 100644
--- a/tests/camel-itest-osgi/pom.xml
+++ b/tests/camel-itest-osgi/pom.xml
@@ -67,7 +67,7 @@
             </exclusions>
         </dependency>
         <dependency>
-            <groupId>org.apache.camel</groupId>
+            <groupId>org.apache.camel.karaf</groupId>
             <artifactId>camel-blueprint</artifactId>
             <scope>test</scope>
         </dependency>
diff --git a/tests/pom.xml b/tests/pom.xml
index 573193b..0b6b5aa 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -65,31 +65,15 @@
     </build>
 
     <profiles>
-        <!-- includes these modules when doing the release -->
-        <profile>
-            <id>release</id>
-            <modules>
-                <module>camel-itest-osgi</module>
-                <module>camel-itest-performance</module>
-                <module>camel-performance</module>
-            </modules>
-        </profile>
-
         <!-- osgi tests -->
         <profile>
             <id>osgi.test</id>
+            <activation>
+                <activeByDefault>false</activeByDefault>
+            </activation>
             <modules>
                 <module>camel-itest-osgi</module>
             </modules>
         </profile>
-
-        <!-- performance tests -->
-        <profile>
-            <id>performance.test</id>
-            <modules>
-                <module>camel-itest-performance</module>
-                <module>camel-performance</module>
-            </modules>
-        </profile>
     </profiles>
 </project>


[camel-karaf] 04/05: Camel-test-karaf: Use the correct GroupID

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 67b087951080709c13fab38046b1e7c788ee877c
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Wed Mar 25 10:30:12 2020 +0100

    Camel-test-karaf: Use the correct GroupID
---
 platforms/karaf/features/src/main/resources/features.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/platforms/karaf/features/src/main/resources/features.xml b/platforms/karaf/features/src/main/resources/features.xml
index 2616f11..1cf821c 100644
--- a/platforms/karaf/features/src/main/resources/features.xml
+++ b/platforms/karaf/features/src/main/resources/features.xml
@@ -55,7 +55,7 @@
     <bundle>mvn:org.apache.camel/camel-management/${project.version}</bundle>
     <bundle>mvn:org.apache.camel/camel-core-engine/${project.version}</bundle>
     <bundle>mvn:org.apache.camel/camel-core-languages/${project.version}</bundle>
-    <bundle>mvn:org.apache.camel/camel-core-osgi/${project.version}</bundle>
+    <bundle>mvn:org.apache.camel.karaf/camel-core-osgi/${project.version}</bundle>
     <bundle>mvn:org.apache.camel/camel-core-catalog/${project.version}</bundle>
     <bundle>mvn:org.apache.camel/camel-cloud/${project.version}</bundle>
     <bundle>mvn:org.apache.camel/camel-cluster/${project.version}</bundle>
@@ -2533,7 +2533,7 @@
     <bundle>mvn:org.ops4j.base/ops4j-base-monitors/${ops4j-base-version}</bundle>
     <bundle>mvn:org.ops4j.base/ops4j-base-store/${ops4j-base-version}</bundle>
     <bundle>mvn:org.ops4j.pax.tinybundles/tinybundles/${tinybundles-version}</bundle>
-    <bundle>mvn:org.apache.camel/camel-test-karaf/${project.version}</bundle>
+    <bundle>mvn:org.apache.camel.karaf/camel-test-karaf/${project.version}</bundle>
   </feature>
   <feature name='camel-test-spring' version='${project.version}' start-level='50'>
     <feature version='${project.version}'>camel-spring</feature>


[camel-karaf] 01/05: Added camel-itest-osgi module

Posted by ac...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit d10545d0cfa2ff4c62fe264087cd9a777c083011
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Wed Mar 25 09:45:07 2020 +0100

    Added camel-itest-osgi module
---
 tests/camel-itest-osgi/README.adoc                 |  24 +++
 tests/camel-itest-osgi/kill-karaf.sh               |  28 +++
 tests/camel-itest-osgi/pom.xml                     | 102 +++++++++++
 tests/camel-itest-osgi/run-tests.sh                |  73 ++++++++
 .../src/main/resources/META-INF/LICENSE.txt        | 203 +++++++++++++++++++++
 .../src/main/resources/META-INF/NOTICE.txt         |  11 ++
 .../java/org/apache/camel/itest/CamelCoreTest.java |  58 ++++++
 .../org/apache/camel/itest/CamelGroovyTest.java    |  58 ++++++
 .../org/apache/camel/itest/CamelHystrixTest.java   |  60 ++++++
 .../itest/CamelJacksonFallbackConverterTest.java   |  66 +++++++
 .../org/apache/camel/itest/CamelPgEventTest.java   |  58 ++++++
 .../camel/itest/CamelQuartzJmxUpdateTest.java      | 172 +++++++++++++++++
 .../apache/camel/itest/CamelSaxonEnabledTest.java  |  61 +++++++
 .../org/apache/camel/itest/CamelSaxonTest.java     |  61 +++++++
 .../apache/camel/itest/CamelTypeConverterTest.java |  82 +++++++++
 .../itest/DuplicateNamespacePrefixIssueTest.java   |  78 ++++++++
 .../src/test/java/org/apache/camel/itest/Pojo.java |  77 ++++++++
 .../camel/itest/cxf/BeanInjectRouteBuilder.java    |  35 ++++
 .../camel/itest/cxf/CamelCxfBeanInjectTest.java    | 102 +++++++++++
 .../org/apache/camel/itest/cxf/SimpleBean.java     |  25 +++
 .../org/apache/camel/itest/cxf/SimpleService.java  |  21 +++
 .../camel/itest/typeconverter/MyConverter.java     |  39 ++++
 .../src/test/resources/log4j2.properties           |  23 +++
 .../org/apache/camel/itest/CamelCoreTest.xml       |  37 ++++
 .../org/apache/camel/itest/CamelGroovyTest.xml     |  37 ++++
 .../org/apache/camel/itest/CamelHystrixTest.xml    |  42 +++++
 .../itest/CamelJacksonFallbackConverterTest.xml    |  28 +++
 .../org/apache/camel/itest/CamelPgEventTest.xml    |  42 +++++
 .../camel/itest/CamelQuartzJmxUpdateTest.xml       |  35 ++++
 .../apache/camel/itest/CamelSaxonEnabledTest.xml   |  46 +++++
 .../org/apache/camel/itest/CamelSaxonTest.xml      |  46 +++++
 .../org/apache/camel/itest/CamelSpringTest.xml     |  38 ++++
 .../apache/camel/itest/CamelTypeConverterTest.xml  |  28 +++
 .../camel/itest/cxf/CamelCxfBeanInjectTest.xml     |  82 +++++++++
 tests/pom.xml                                      |   1 +
 35 files changed, 1979 insertions(+)

diff --git a/tests/camel-itest-osgi/README.adoc b/tests/camel-itest-osgi/README.adoc
new file mode 100644
index 0000000..60ca9bb
--- /dev/null
+++ b/tests/camel-itest-osgi/README.adoc
@@ -0,0 +1,24 @@
+= Camel OSGi Integration Tests
+
+== Overview
+
+This module is where you should add cross component tests running on Karaf container.
+
+All tests are disabled by default to not run in the main CI job. Instead there is a separate CI job that only run the tests for each commit. The results are available here:
+https://builds.apache.org/blue/organizations/jenkins/Camel.trunk.itest.osgi/activity/
+
+== How to run the tests
+
+Do not use `mvn test`. Run the following script instead.
+----
+$ ./run-tests.sh
+----
+
+****
+The reason for not using `mvn test` is that each test starts up a Karaf instance using Pax Exam, but sometimes the instance doesn't shut down well after the test and the phantom instance causes silent failures of the successive tests. The `run-tests.sh` script makes sure to kill the Karaf instance after each test finished.
+****
+
+You can also pass in the test name to start testing from the test and onwards, e.g.:
+----
+$ ./run-tests.sh CamelHystrixTest
+----
\ No newline at end of file
diff --git a/tests/camel-itest-osgi/kill-karaf.sh b/tests/camel-itest-osgi/kill-karaf.sh
new file mode 100755
index 0000000..ec03c41
--- /dev/null
+++ b/tests/camel-itest-osgi/kill-karaf.sh
@@ -0,0 +1,28 @@
+#!/bin/sh
+#
+# 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.
+#
+
+XARGS_OPTIONS="-t -n1"
+if [ `uname` = "Linux" ]; then
+  XARGS_OPTIONS="$XARGS_OPTIONS --no-run-if-empty"
+fi
+
+echo "Listing all karaf processes"
+jps -l | grep karaf
+
+echo "Killing all karaf processes"
+jps -l | grep karaf | cut -d ' ' -f 1 | xargs $XARGS_OPTIONS kill
diff --git a/tests/camel-itest-osgi/pom.xml b/tests/camel-itest-osgi/pom.xml
new file mode 100644
index 0000000..fd26b15
--- /dev/null
+++ b/tests/camel-itest-osgi/pom.xml
@@ -0,0 +1,102 @@
+<?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/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.camel.karaf</groupId>
+        <artifactId>tests</artifactId>
+        <version>3.2.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-itest-osgi</artifactId>
+    <name>Camel Karaf :: Integration Tests :: OSGi</name>
+    <description>Performs OSGi compliance integration tests</description>
+
+    <properties>
+        <karaf-test-version>${karaf4-version}</karaf-test-version>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test-karaf</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.karaf</groupId>
+            <artifactId>apache-karaf</artifactId>
+            <version>${karaf-test-version}</version>
+            <type>tar.gz</type>
+            <scope>test</scope>
+            <exclusions>
+                <exclusion>
+                    <groupId>org.apache.karaf.shell</groupId>
+                    <artifactId>org.apache.karaf.shell.dev</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.eclipse</groupId>
+                    <artifactId>osgi</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.karaf</groupId>
+                    <artifactId>org.apache.karaf.client</artifactId>
+                </exclusion>
+                <exclusion>
+                    <groupId>org.apache.felix</groupId>
+                    <artifactId>org.apache.felix.framework</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-blueprint</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-jackson</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-cxf</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+    <build>
+        <plugins>
+            <plugin>
+                <artifactId>maven-surefire-plugin</artifactId>
+                <configuration>
+                    <rerunFailingTestsCount>0</rerunFailingTestsCount>
+                    <systemPropertyVariables>
+                        <karafVersion>${karaf4-version}</karafVersion>
+                        <camelKarafFeatureVersion>${project.version}</camelKarafFeatureVersion>
+                    </systemPropertyVariables>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+
+
+</project>
diff --git a/tests/camel-itest-osgi/run-tests.sh b/tests/camel-itest-osgi/run-tests.sh
new file mode 100755
index 0000000..f9d9184
--- /dev/null
+++ b/tests/camel-itest-osgi/run-tests.sh
@@ -0,0 +1,73 @@
+#!/bin/sh
+#
+# 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 script runs the camel-itest-osgi in a more reliable way
+## than Maven surefire will do as it can hang after a while
+## The script also kills each karaf container after a test to ensure there is no Java JVMs
+## danging around.
+
+echo "Running tests and kill karaf after each test"
+
+## directory where the karaf unit tests are
+testdir='src/test/java/org/apache/camel/itest'
+
+## you can pass in the test name to start from eg run-tests.sh CamelHystrixTest
+## to start testing from this test and onwards.
+if [ "$#" -eq  "0" ]
+then
+  found=1
+else
+  found=0
+fi  
+
+## ensure the files are sorted
+for filename in $(ls -f $testdir/*Test* | sort);
+do
+  testname=$(basename ${filename%.*})
+
+  if [ $found -eq 0 ]
+  then
+    if [ $testname == "$1" ]
+    then
+     found=1
+    fi 
+  fi
+
+  if [ $found -eq 1 ] && [ $testname != "AbstractFeatureTest" ]
+  then
+    echo "*******************************************************************"
+    echo "Running test $testname"
+    echo "*******************************************************************"
+    if mvn test -Dtest=$testname ; then
+      echo "\n"
+      echo "*******************************************************************"
+      echo "Test success: $testname"
+      echo "*******************************************************************"
+      echo "\n"
+    else
+      echo "\n"
+      echo "*******************************************************************"
+      echo "Test failure: $testname"
+      echo "*******************************************************************"
+      echo "\n"
+      exit 1;
+    fi  
+    echo "Killing Karaf to ensure no dangling karaf running"
+    ./kill-karaf.sh
+  fi  
+done
diff --git a/tests/camel-itest-osgi/src/main/resources/META-INF/LICENSE.txt b/tests/camel-itest-osgi/src/main/resources/META-INF/LICENSE.txt
new file mode 100644
index 0000000..6b0b127
--- /dev/null
+++ b/tests/camel-itest-osgi/src/main/resources/META-INF/LICENSE.txt
@@ -0,0 +1,203 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
diff --git a/tests/camel-itest-osgi/src/main/resources/META-INF/NOTICE.txt b/tests/camel-itest-osgi/src/main/resources/META-INF/NOTICE.txt
new file mode 100644
index 0000000..2e215bf
--- /dev/null
+++ b/tests/camel-itest-osgi/src/main/resources/META-INF/NOTICE.txt
@@ -0,0 +1,11 @@
+   =========================================================================
+   ==  NOTICE file corresponding to the section 4 d of                    ==
+   ==  the Apache License, Version 2.0,                                   ==
+   ==  in this case for the Apache Camel distribution.                    ==
+   =========================================================================
+
+   This product includes software developed by
+   The Apache Software Foundation (http://www.apache.org/).
+
+   Please read the different LICENSE files present in the licenses directory of
+   this distribution.
diff --git a/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelCoreTest.java b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelCoreTest.java
new file mode 100644
index 0000000..1a9e930
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelCoreTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.itest;
+
+import java.net.URL;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.karaf.AbstractFeatureTest;
+import org.apache.camel.test.karaf.CamelKarafTestSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+
+@RunWith(PaxExam.class)
+public class CamelCoreTest extends AbstractFeatureTest {
+
+    @Test
+    public void testCamelCore() throws Exception {
+        // install the camel blueprint xml file we use in this test
+        URL url = ObjectHelper.loadResourceAsURL("org/apache/camel/itest/CamelCoreTest.xml", CamelCoreTest.class.getClassLoader());
+        installBlueprintAsBundle("CamelCoreTest", url, true);
+
+        // lookup Camel from OSGi
+        CamelContext camel = getOsgiService(bundleContext, CamelContext.class);
+
+        // test camel
+        MockEndpoint mock = camel.getEndpoint("mock:result", MockEndpoint.class);
+        mock.expectedBodiesReceived("Hello World");
+
+        camel.createProducerTemplate().sendBody("direct:start", "World");
+
+        mock.assertIsSatisfied();
+    }
+
+    @Configuration
+    public Option[] configure() {
+        return CamelKarafTestSupport.configure("camel-test-karaf");
+    }
+
+}
diff --git a/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelGroovyTest.java b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelGroovyTest.java
new file mode 100644
index 0000000..37a6e23
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelGroovyTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.itest;
+
+import java.net.URL;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.karaf.AbstractFeatureTest;
+import org.apache.camel.test.karaf.CamelKarafTestSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+
+@RunWith(PaxExam.class)
+public class CamelGroovyTest extends AbstractFeatureTest {
+
+    @Test
+    public void testCamelGroovy() throws Exception {
+        // install the camel blueprint xml file we use in this test
+        URL url = ObjectHelper.loadResourceAsURL("org/apache/camel/itest/CamelGroovyTest.xml", CamelGroovyTest.class.getClassLoader());
+        installBlueprintAsBundle("CamelGroovyTest", url, true);
+
+        // lookup Camel from OSGi
+        CamelContext camel = getOsgiService(bundleContext, CamelContext.class);
+
+        // test camel
+        MockEndpoint mock = camel.getEndpoint("mock:result", MockEndpoint.class);
+        mock.expectedBodiesReceived(6);
+
+        camel.createProducerTemplate().sendBody("direct:start", 3);
+
+        mock.assertIsSatisfied();
+    }
+
+    @Configuration
+    public Option[] configure() {
+        return CamelKarafTestSupport.configure("camel-test-karaf", "camel-groovy");
+    }
+
+}
diff --git a/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelHystrixTest.java b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelHystrixTest.java
new file mode 100644
index 0000000..c63606c
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelHystrixTest.java
@@ -0,0 +1,60 @@
+/*
+ * 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.itest;
+
+import java.net.URL;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.karaf.AbstractFeatureTest;
+import org.apache.camel.test.karaf.CamelKarafTestSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+
+@RunWith(PaxExam.class)
+@Ignore("Weird osgi linkage error")
+public class CamelHystrixTest extends AbstractFeatureTest {
+
+    @Test
+    public void testCamelHystrix() throws Exception {
+        // install the camel blueprint xml file we use in this test
+        URL url = ObjectHelper.loadResourceAsURL("org/apache/camel/itest/CamelHystrixTest.xml", CamelHystrixTest.class.getClassLoader());
+        installBlueprintAsBundle("CamelHystrixTest", url, true);
+
+        // lookup Camel from OSGi
+        CamelContext camel = getOsgiService(bundleContext, CamelContext.class);
+
+        // test camel
+        MockEndpoint mock = camel.getEndpoint("mock:result", MockEndpoint.class);
+        mock.expectedBodiesReceived("Fallback message");
+
+        camel.createProducerTemplate().sendBody("direct:start", "Hello World");
+
+        mock.assertIsSatisfied();
+    }
+
+    @Configuration
+    public Option[] configure() {
+        return CamelKarafTestSupport.configure("camel-test-karaf", "camel-hystrix");
+    }
+
+}
diff --git a/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelJacksonFallbackConverterTest.java b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelJacksonFallbackConverterTest.java
new file mode 100644
index 0000000..d83df0f
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelJacksonFallbackConverterTest.java
@@ -0,0 +1,66 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.itest;
+
+import java.net.URL;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.jackson.JacksonConstants;
+import org.apache.camel.support.DefaultExchange;
+import org.apache.camel.test.karaf.AbstractFeatureTest;
+import org.apache.camel.test.karaf.CamelKarafTestSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+
+@RunWith(PaxExam.class)
+public class CamelJacksonFallbackConverterTest extends AbstractFeatureTest {
+
+    @Test
+    public void test() throws Exception {
+        // install the camel blueprint xml file we use in this test
+        URL url = ObjectHelper.loadResourceAsURL("org/apache/camel/itest/CamelJacksonFallbackConverterTest.xml", CamelJacksonFallbackConverterTest.class.getClassLoader());
+        installBlueprintAsBundle("CamelJacksonFallbackConverterTest", url, true);
+
+        // lookup Camel from OSGi
+        CamelContext camel = getOsgiService(bundleContext, CamelContext.class);
+
+        // enable Jackson json type converter
+        camel.getGlobalOptions().put(JacksonConstants.ENABLE_TYPE_CONVERTER, "true");
+        // allow Jackson json to convert to pojo types also (by default jackson only converts to String and other simple types)
+        camel.getGlobalOptions().put(JacksonConstants.TYPE_CONVERTER_TO_POJO, "true");
+
+        final Pojo pojo = new Pojo(1337, "Constantine");
+
+        final DefaultExchange exchange = new DefaultExchange(camel);
+        final String string = camel.getTypeConverter().mandatoryConvertTo(String.class, exchange, pojo);
+        LOG.info("POJO -> String: {}", string);
+        final Pojo copy = camel.getTypeConverter().mandatoryConvertTo(Pojo.class, exchange, string);
+        LOG.info("String -> POJO: {}", copy);
+        Assert.assertEquals(pojo, copy);
+    }
+
+    @Configuration
+    public Option[] configure() {
+        return CamelKarafTestSupport.configure("camel-test-karaf", "camel-jackson");
+    }
+
+}
\ No newline at end of file
diff --git a/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelPgEventTest.java b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelPgEventTest.java
new file mode 100644
index 0000000..bdca497
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelPgEventTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.itest;
+
+import java.net.URL;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.karaf.AbstractFeatureTest;
+import org.apache.camel.test.karaf.CamelKarafTestSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+
+@RunWith(PaxExam.class)
+@Ignore("Needs a running PostgreSQL instance")
+public class CamelPgEventTest extends AbstractFeatureTest {
+
+    @Test
+    public void testCamelPgEvent() throws Exception {
+        // install the camel blueprint xml file we use in this test
+        URL url = ObjectHelper.loadResourceAsURL("org/apache/camel/itest/CamelPgEventTest.xml", CamelPgEventTest.class.getClassLoader());
+        installBlueprintAsBundle("CamelPgEventTest", url, true);
+        installCamelFeature("camel-pgevent");
+
+        // lookup Camel from OSGi
+        CamelContext camel = getOsgiService(bundleContext, CamelContext.class);
+
+        // test camel
+        MockEndpoint mock = camel.getEndpoint("mock:result", MockEndpoint.class);
+        mock.expectedBodiesReceived("Hello World");
+
+        mock.assertIsSatisfied(5000);
+    }
+
+    @Configuration
+    public Option[] configure() {
+        return CamelKarafTestSupport.configure("camel-test-karaf");
+    }
+}
diff --git a/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelQuartzJmxUpdateTest.java b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelQuartzJmxUpdateTest.java
new file mode 100644
index 0000000..83175d1
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelQuartzJmxUpdateTest.java
@@ -0,0 +1,172 @@
+/*
+ * 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.itest;
+
+import java.lang.management.ManagementFactory;
+import java.net.URL;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.management.MBeanServer;
+import javax.management.ObjectName;
+import javax.management.openmbean.CompositeData;
+import javax.management.openmbean.TabularData;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.karaf.AbstractFeatureTest;
+import org.apache.camel.util.ObjectHelper;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+
+/**
+ * CAMEL-11471: Unable to update the cron details from Quartz scheduler MBean
+ */
+@RunWith(PaxExam.class)
+public class CamelQuartzJmxUpdateTest extends AbstractFeatureTest {
+
+    private static final Logger LOGGER = LoggerFactory.getLogger(CamelQuartzJmxUpdateTest.class);
+
+    @Test
+    public void testUpdateCronDetails() throws Exception {
+        // install camel-quartz here as 'wrap:' is not available at boot time
+        installCamelFeature("camel-quartz");
+
+        // install the camel blueprint xml file we use in this test
+        URL url = ObjectHelper.loadResourceAsURL("org/apache/camel/itest/CamelQuartzJmxUpdateTest.xml",
+            CamelQuartzJmxUpdateTest.class.getClassLoader());
+        installBlueprintAsBundle("CamelQuartzJmxUpdateTest", url, true);
+
+        // lookup Camel from OSGi
+        CamelContext camel = getOsgiService(bundleContext, CamelContext.class);
+
+        // test camel
+        MockEndpoint mock = camel.getEndpoint("mock:result", MockEndpoint.class);
+        mock.expectedBodiesReceived("Hello World");
+        mock.assertIsSatisfied(5000);
+
+        doUpdateCronDetails();
+    }
+
+    private void doUpdateCronDetails() throws Exception {
+        String trigger = "myTimer";
+        String group = "myGroup";
+        String cronExpression = "0 * * * * ?";
+
+        MBeanServer mBeanServer = ManagementFactory.getPlatformMBeanServer();
+        Set<ObjectName> objectNames = mBeanServer.queryNames(
+            new ObjectName("quartz:type=QuartzScheduler,name=*,instance=NON_CLUSTERED"), null);
+        assertFalse("There should be a quartz scheduler MBean", objectNames.isEmpty());
+
+        ObjectName oName = objectNames.stream().findFirst().get();
+        LOGGER.info("Scheduler MBean: {}", oName);
+
+        CompositeData triggerData = (CompositeData) mBeanServer.invoke(oName, "getTrigger",
+            new Object[]{trigger, group},
+            new String[]{"java.lang.String", "java.lang.String"});
+        String jobName = (String) triggerData.get("jobName");
+        String jobGroup = (String) triggerData.get("jobGroup");
+        CompositeData jobData = (CompositeData) mBeanServer.invoke(oName, "getJobDetail",
+            new Object[]{jobName, jobGroup},
+            new String[]{"java.lang.String", "java.lang.String"});
+
+        String original = getCronExpression(jobData);
+        assertNotEquals("make sure original cron is different", cronExpression, original);
+
+        Map<String, Object> jobInfo = createJobInfo(jobName, jobGroup, cronExpression, jobData);
+        Map<String, Object> triggerInfo = createTriggerInfo(trigger, group, cronExpression, jobName, jobGroup);
+
+        // update trigger
+        mBeanServer.invoke(oName, "scheduleBasicJob",
+            new Object[]{jobInfo, triggerInfo},
+            new String[]{"java.util.Map", "java.util.Map"});
+
+        // assert job details updated
+        CompositeData jobData2 = (CompositeData) mBeanServer.invoke(oName, "getJobDetail",
+            new Object[]{jobName, jobGroup},
+            new String[]{"java.lang.String", "java.lang.String"});
+        String updated = getCronExpression(jobData2);
+        assertEquals("cron should be updated", cronExpression, updated);
+    }
+
+    private String getCronExpression(CompositeData jobData) {
+        TabularData jobDataMap = (TabularData) jobData.get("jobDataMap");
+        CompositeData cron = jobDataMap.get(new String[]{"CamelQuartzTriggerCronExpression"});
+        Iterator it = cron.values().iterator();
+        it.next();
+        return (String) it.next();
+    }
+
+    private Map<String, Object> createJobInfo(String jobName, String jobGroup, String cronExpression,
+                                              CompositeData jobData) {
+        Map<String, Object> jobInfo = new HashMap<>();
+        jobInfo.put("name", jobName);
+        jobInfo.put("group", jobGroup);
+        if (jobData.get("description") != null) {
+            jobInfo.put("description", jobData.get("description"));
+        }
+        jobInfo.put("jobClass", jobData.get("jobClass"));
+        jobInfo.put("durability", jobData.get("durability"));
+        jobInfo.put("shouldRecover", jobData.get("shouldRecover"));
+
+        Map<String, Object> jobDataMap = new HashMap<>();
+        TabularData tJobDataMap = (TabularData) jobData.get("jobDataMap");
+        for (Object cKey : tJobDataMap.keySet()) {
+            Object key = ((List) cKey).get(0);
+            CompositeData cd = tJobDataMap.get(new Object[]{key});
+            if (cd != null) {
+                Iterator it = cd.values().iterator();
+                String tKey = (String) it.next();
+                Object tValue = it.next();
+                jobDataMap.put(tKey, tValue);
+            }
+        }
+        jobDataMap.put("CamelQuartzTriggerType", "cron");
+        jobDataMap.put("CamelQuartzTriggerCronExpression", cronExpression);
+        jobInfo.put("jobDataMap", jobDataMap);
+        return jobInfo;
+    }
+
+    private Map<String, Object> createTriggerInfo(String trigger, String group, String cronExpression,
+                                                  String jobName, String jobGroup) {
+        Map<String, Object> triggerInfo = new HashMap<>();
+        triggerInfo.put("cronExpression", cronExpression);
+        triggerInfo.put("name", trigger);
+        triggerInfo.put("group", group);
+        triggerInfo.put("jobName", jobName);
+        triggerInfo.put("jobGroup", jobGroup);
+        triggerInfo.put("misfireInstruction", 1);
+        return triggerInfo;
+    }
+
+    @Configuration
+    public Option[] configure() {
+        return configure("camel-test-karaf");
+    }
+
+}
diff --git a/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelSaxonEnabledTest.java b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelSaxonEnabledTest.java
new file mode 100644
index 0000000..e0e1b24
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelSaxonEnabledTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.itest;
+
+import java.net.URL;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.karaf.AbstractFeatureTest;
+import org.apache.camel.test.karaf.CamelKarafTestSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+
+@Ignore
+@RunWith(PaxExam.class)
+public class CamelSaxonEnabledTest extends AbstractFeatureTest {
+
+    @Test
+    public void testCamelSaxonEnabled() throws Exception {
+        // install the camel blueprint xml file we use in this test
+        URL url = ObjectHelper.loadResourceAsURL("org/apache/camel/itest/CamelSaxonEnabledTest.xml", CamelSaxonEnabledTest.class.getClassLoader());
+        installBlueprintAsBundle("CamelSaxonTest", url, true);
+
+        // lookup Camel from OSGi
+        CamelContext camel = getOsgiService(bundleContext, CamelContext.class);
+
+        // test camel
+        MockEndpoint mock = camel.getEndpoint("mock:camel", MockEndpoint.class);
+        mock.expectedBodiesReceived("<name>King</name>");
+        mock.expectedHeaderReceived("type", "Camel");
+
+        camel.createProducerTemplate().sendBodyAndHeader("direct:in", "<name>King</name>", "type", "Camel");
+
+        mock.assertIsSatisfied();
+    }
+
+    @Configuration
+    public Option[] configure() {
+        return CamelKarafTestSupport.configure("camel-test-karaf", "camel-saxon");
+    }
+
+}
diff --git a/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelSaxonTest.java b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelSaxonTest.java
new file mode 100644
index 0000000..22098cd
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelSaxonTest.java
@@ -0,0 +1,61 @@
+/*
+ * 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.itest;
+
+import java.net.URL;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.test.karaf.AbstractFeatureTest;
+import org.apache.camel.test.karaf.CamelKarafTestSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+
+@Ignore
+@RunWith(PaxExam.class)
+public class CamelSaxonTest extends AbstractFeatureTest {
+
+    @Test
+    public void testCamelSaxon() throws Exception {
+        // install the camel blueprint xml file we use in this test
+        URL url = ObjectHelper.loadResourceAsURL("org/apache/camel/itest/CamelSaxonTest.xml", CamelSaxonTest.class.getClassLoader());
+        installBlueprintAsBundle("CamelSaxonTest", url, true);
+
+        // lookup Camel from OSGi
+        CamelContext camel = getOsgiService(bundleContext, CamelContext.class);
+
+        // test camel
+        MockEndpoint mock = camel.getEndpoint("mock:camel", MockEndpoint.class);
+        mock.expectedBodiesReceived("<name>King</name>");
+        mock.expectedHeaderReceived("type", "Camel");
+
+        camel.createProducerTemplate().sendBodyAndHeader("direct:in", "<name>King</name>", "type", "Camel");
+
+        mock.assertIsSatisfied();
+    }
+
+    @Configuration
+    public Option[] configure() {
+        return CamelKarafTestSupport.configure("camel-test-karaf", "camel-saxon");
+    }
+
+}
diff --git a/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelTypeConverterTest.java b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelTypeConverterTest.java
new file mode 100644
index 0000000..5b4cdcf
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/CamelTypeConverterTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.itest;
+
+import java.io.ByteArrayInputStream;
+import java.net.URL;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.itest.typeconverter.MyConverter;
+import org.apache.camel.support.DefaultExchange;
+import org.apache.camel.test.karaf.AbstractFeatureTest;
+import org.apache.camel.test.karaf.CamelKarafTestSupport;
+import org.apache.camel.util.ObjectHelper;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.ProbeBuilder;
+import org.ops4j.pax.exam.TestProbeBuilder;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.tinybundles.core.InnerClassStrategy;
+import org.ops4j.pax.tinybundles.core.TinyBundle;
+import org.osgi.framework.Constants;
+
+@RunWith(PaxExam.class)
+public class CamelTypeConverterTest extends AbstractFeatureTest {
+
+    @Test
+    public void testTypeConverterInSameBundleAsCamelRoute() throws Exception {
+        // install the camel blueprint xml file and the Camel converter we use in this test
+        URL blueprintUrl = ObjectHelper.loadResourceAsURL("org/apache/camel/itest/CamelTypeConverterTest.xml", CamelTypeConverterTest.class.getClassLoader());
+        installBlueprintAsBundle("CamelTypeConverterTest", blueprintUrl, true, bundle -> {
+            // install converter
+            ((TinyBundle) bundle)
+                .add("META-INF/services/org/apache/camel/TypeConverter", new ByteArrayInputStream("org.apache.camel.itest.typeconverter.MyConverter".getBytes()))
+                .add(MyConverter.class, InnerClassStrategy.NONE)
+                .set(Constants.DYNAMICIMPORT_PACKAGE, "*");
+        });
+
+        // lookup Camel from OSGi
+        CamelContext camel = getOsgiService(bundleContext, CamelContext.class);
+
+        final Pojo pojo = new Pojo();
+        String pojoName = "Constantine";
+        pojo.setName(pojoName);
+
+        final DefaultExchange exchange = new DefaultExchange(camel);
+        final String string = camel.getTypeConverter().mandatoryConvertTo(String.class, exchange, pojo);
+        LOG.info("POJO -> String: {}", string);
+        final Pojo copy = camel.getTypeConverter().mandatoryConvertTo(Pojo.class, exchange, string);
+        LOG.info("String -> POJO: {}", copy);
+        Assert.assertEquals(pojoName, copy.getName());
+    }
+
+    @Configuration
+    public Option[] configure() {
+        return CamelKarafTestSupport.configure("camel-test-karaf");
+    }
+
+    @ProbeBuilder
+    public TestProbeBuilder probeConfiguration(TestProbeBuilder probe) {
+        // Export Pojo class for TypeConverter bundle
+        probe.setHeader(Constants.EXPORT_PACKAGE, "org.apache.camel.itest");
+        return probe;
+    }
+
+}
diff --git a/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/DuplicateNamespacePrefixIssueTest.java b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/DuplicateNamespacePrefixIssueTest.java
new file mode 100644
index 0000000..8b1de84
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/DuplicateNamespacePrefixIssueTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.itest;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.blueprint.BlueprintCamelContext;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.model.Model;
+import org.apache.camel.model.RoutesDefinition;
+import org.apache.camel.test.karaf.AbstractFeatureTest;
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+
+/**
+ * CAMEL-10817: dumpModelAsXml can return invalid XML namespace xmlns:xmlns
+ */
+@RunWith(PaxExam.class)
+public class DuplicateNamespacePrefixIssueTest extends AbstractFeatureTest {
+
+    @Test
+    public void testRoutesNamespacePrefixesNotDuplicated() throws Exception {
+        CamelContext context = new BlueprintCamelContext(bundleContext, blueprintContainer);
+        context.addRoutes(new RouteBuilder() {
+            @Override
+            public void configure() throws Exception {
+                from("direct:foo").id("foo")
+                    .choice()
+                        .when(xpath("foo:foo/foo:foo = 'foo'"))
+                            .log("Matched foo")
+                        .when(xpath("foo:foo/foo:bar = 'bar'"))
+                            .log("Matched bar")
+                        .when(xpath("foo:foo/foo:cheese = 'cheese'"))
+                            .log("Matched cheese");
+            }
+        });
+
+        // Dump the model XML
+        ExtendedCamelContext ecc = context.adapt(ExtendedCamelContext.class);
+        String originalModelXML = ecc.getModelToXMLDumper().dumpModelAsXml(context, context.getExtension(Model.class).getRouteDefinition("foo"));
+
+        // Reload routes from dumped XML
+        InputStream stream = new ByteArrayInputStream(originalModelXML.getBytes("UTF-8"));
+        RoutesDefinition routesDefinition = (RoutesDefinition) ecc.getXMLRoutesDefinitionLoader().loadRoutesDefinition(context, stream);
+
+        // Verify namespaces are as we expect
+        String modifiedModelXML = ecc.getModelToXMLDumper().dumpModelAsXml(context, routesDefinition);
+        String modifiedRoutesElementXML = modifiedModelXML.split("\n")[1];
+        String expectedRoutesElementXML = "<routes xmlns=\"http://camel.apache.org/schema/spring\">";
+        Assert.assertEquals(expectedRoutesElementXML, modifiedRoutesElementXML);
+    }
+
+    @Configuration
+    public Option[] configure() {
+        return AbstractFeatureTest.configure();
+    }
+}
diff --git a/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/Pojo.java b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/Pojo.java
new file mode 100644
index 0000000..576d789
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/Pojo.java
@@ -0,0 +1,77 @@
+/*
+ * 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.itest;
+
+public class Pojo {
+    private int id;
+    private String name;
+
+    public Pojo(int id, String name) {
+        this.id = id;
+        this.name = name;
+    }
+
+    public Pojo() {
+    }
+    
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) {
+            return true;
+        }
+        if (!(o instanceof Pojo)) {
+            return false;
+        }
+
+
+        Pojo pojo = (Pojo) o;
+
+        if (id != pojo.getId()) {
+            return false;
+        }
+        return name != null ? name.equals(pojo.getName()) : pojo.getName() == null;
+
+    }
+
+    @Override
+    public int hashCode() {
+        int result = id;
+        result = 31 * result + (name != null ? name.hashCode() : 0);
+        return result;
+    }
+
+    @Override
+    public String toString() {
+        return "Pojo{" + "id=" + id + ", name='" + name + '\'' + '}';
+    }
+}
diff --git a/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/cxf/BeanInjectRouteBuilder.java b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/cxf/BeanInjectRouteBuilder.java
new file mode 100644
index 0000000..d91736a
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/cxf/BeanInjectRouteBuilder.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.itest.cxf;
+
+import org.apache.camel.BeanInject;
+import org.apache.camel.builder.RouteBuilder;
+
+public class BeanInjectRouteBuilder extends RouteBuilder {
+
+    @BeanInject
+    private SimpleBean simpleBean;
+
+    @Override
+    public void configure() throws Exception {
+        from("cxf:bean:routerEndpoint")
+            .bean(simpleBean) // does nothing
+            .transform(simple("scheme: ${headers.CamelCxfMessage.get(HTTP.REQUEST).scheme}"
+                + ", x-forwarded-proto: ${headers.CamelCxfMessage.get(HTTP.REQUEST).getHeader(X-Forwarded-Proto)}"));
+    }
+
+}
diff --git a/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/cxf/CamelCxfBeanInjectTest.java b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/cxf/CamelCxfBeanInjectTest.java
new file mode 100644
index 0000000..373d0d0
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/cxf/CamelCxfBeanInjectTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.itest.cxf;
+
+import java.net.URL;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+import org.apache.camel.test.AvailablePortFinder;
+import org.apache.camel.test.karaf.AbstractFeatureTest;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.cxf.BusFactory;
+import org.apache.cxf.frontend.ClientProxy;
+import org.apache.cxf.frontend.ClientProxyFactoryBean;
+import org.apache.cxf.message.Message;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.ops4j.pax.exam.Configuration;
+import org.ops4j.pax.exam.Option;
+import org.ops4j.pax.exam.junit.PaxExam;
+import org.ops4j.pax.tinybundles.core.InnerClassStrategy;
+import org.ops4j.pax.tinybundles.core.TinyBundle;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+
+@RunWith(PaxExam.class)
+@Ignore("Flaky on CI server")
+public class CamelCxfBeanInjectTest extends AbstractFeatureTest {
+
+    private static final int PORT = AvailablePortFinder.getNextAvailable();
+    private static final String ENDPOINT_ADDRESS = String.format(
+        "http://localhost:%s/CamelCxfBeanInjectTest/router", PORT);
+
+    @Before
+    public void installBlueprintXML() throws Exception {
+        // install the camel blueprint xml file we use in this test
+        URL url = ObjectHelper.loadResourceAsURL("org/apache/camel/itest/cxf/CamelCxfBeanInjectTest.xml", CamelCxfBeanInjectTest.class.getClassLoader());
+        Bundle bundle = installBlueprintAsBundle("CamelCxfBeanInjectTest", url, false, b -> {
+            ((TinyBundle) b)
+                .add(BeanInjectRouteBuilder.class, InnerClassStrategy.NONE)
+                .add(SimpleService.class, InnerClassStrategy.NONE)
+                .add(SimpleBean.class, InnerClassStrategy.NONE)
+                .set(Constants.DYNAMICIMPORT_PACKAGE, "*");
+        });
+
+        Properties props = new Properties();
+        props.put("router.address", ENDPOINT_ADDRESS);
+        props.put("router.port", Integer.toString(PORT));
+        overridePropertiesWithConfigAdmin("my-placeholders", props);
+
+        bundle.start();
+    }
+
+    @Configuration
+    public Option[] configure() {
+        return configure("camel-test-karaf", "camel-cxf");
+    }
+
+    @Test
+    public void testReverseProxy() {
+        SimpleService client = createClient();
+        setHttpHeaders(client, "X-Forwarded-Proto", "https");
+
+        String result = client.op("test");
+        Assert.assertEquals("Scheme should be set to 'https'",
+            "scheme: https, x-forwarded-proto: https", result);
+    }
+
+    private void setHttpHeaders(SimpleService client, String header, String value) {
+        Map<String, List<String>> headers = new HashMap<>();
+        headers.put(header, Arrays.asList(value));
+        ClientProxy.getClient(client).getRequestContext().put(Message.PROTOCOL_HEADERS, headers);
+    }
+
+    private SimpleService createClient() {
+        ClientProxyFactoryBean factory = new ClientProxyFactoryBean();
+        factory.setAddress(ENDPOINT_ADDRESS);
+        factory.setServiceClass(SimpleService.class);
+        factory.setBus(BusFactory.getDefaultBus());
+        return (SimpleService) factory.create();
+    }
+}
diff --git a/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/cxf/SimpleBean.java b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/cxf/SimpleBean.java
new file mode 100644
index 0000000..0f83515
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/cxf/SimpleBean.java
@@ -0,0 +1,25 @@
+/*
+ * 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.itest.cxf;
+
+public class SimpleBean {
+
+    public String op(String message) {
+        return "<<< " + message + " >>>";
+    }
+
+}
diff --git a/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/cxf/SimpleService.java b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/cxf/SimpleService.java
new file mode 100644
index 0000000..5902f66
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/cxf/SimpleService.java
@@ -0,0 +1,21 @@
+/*
+ * 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.itest.cxf;
+
+public interface SimpleService {
+    String op(String input);
+}
diff --git a/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/typeconverter/MyConverter.java b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/typeconverter/MyConverter.java
new file mode 100644
index 0000000..6b76d16
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/java/org/apache/camel/itest/typeconverter/MyConverter.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.itest.typeconverter;
+
+import org.apache.camel.Converter;
+import org.apache.camel.itest.Pojo;
+
+@Converter
+public class MyConverter {
+
+    public MyConverter() { }
+    
+    @Converter
+    public static Pojo toPojo(String name) {
+        Pojo pojo = new Pojo();
+        pojo.setName(name);
+        return pojo;
+    }
+    
+    @Converter
+    public String toString(Pojo pojo) {
+        return pojo.getName();
+    }
+
+}
diff --git a/tests/camel-itest-osgi/src/test/resources/log4j2.properties b/tests/camel-itest-osgi/src/test/resources/log4j2.properties
new file mode 100644
index 0000000..d406a9f
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/resources/log4j2.properties
@@ -0,0 +1,23 @@
+## ---------------------------------------------------------------------------
+## 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.
+## ---------------------------------------------------------------------------
+
+appender.out.type = Console
+appender.out.name = out
+appender.out.layout.type = PatternLayout
+appender.out.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+rootLogger.level = INFO
+rootLogger.appenderRef.out.ref = out
diff --git a/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelCoreTest.xml b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelCoreTest.xml
new file mode 100644
index 0000000..3f320ee
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelCoreTest.xml
@@ -0,0 +1,37 @@
+<?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.
+
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xsi:schemaLocation="
+             http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
+
+  <camelContext id="myCamel" xmlns="http://camel.apache.org/schema/blueprint">
+
+    <route>
+      <from uri="direct:start"/>
+      <transform>
+        <simple>Hello ${body}</simple>
+      </transform>
+      <to uri="mock:result"/>
+    </route>
+
+  </camelContext>
+
+</blueprint>
diff --git a/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelGroovyTest.xml b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelGroovyTest.xml
new file mode 100644
index 0000000..81039b8
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelGroovyTest.xml
@@ -0,0 +1,37 @@
+<?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.
+
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xsi:schemaLocation="
+             http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
+
+  <camelContext id="myCamel" xmlns="http://camel.apache.org/schema/blueprint">
+
+    <route>
+      <from uri="direct:start"/>
+      <transform>
+        <groovy>2 * body</groovy>
+      </transform>
+      <to uri="mock:result"/>
+    </route>
+
+  </camelContext>
+
+</blueprint>
diff --git a/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelHystrixTest.xml b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelHystrixTest.xml
new file mode 100644
index 0000000..e31b472
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelHystrixTest.xml
@@ -0,0 +1,42 @@
+<?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.
+
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xsi:schemaLocation="
+             http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
+
+  <camelContext id="myCamel" xmlns="http://camel.apache.org/schema/blueprint">
+
+    <route>
+      <from uri="direct:start"/>
+      <circuitBreaker>
+        <throwException exceptionType="java.lang.IllegalArgumentException" message="Forced"/>
+        <onFallback>
+          <transform>
+            <constant>Fallback message</constant>
+          </transform>
+        </onFallback>
+      </circuitBreaker>
+      <to uri="mock:result"/>
+    </route>
+
+  </camelContext>
+
+</blueprint>
diff --git a/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelJacksonFallbackConverterTest.xml b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelJacksonFallbackConverterTest.xml
new file mode 100644
index 0000000..f47bb35
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelJacksonFallbackConverterTest.xml
@@ -0,0 +1,28 @@
+<?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.
+
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xsi:schemaLocation="
+             http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
+
+  <camelContext id="myCamel" xmlns="http://camel.apache.org/schema/blueprint">
+  </camelContext>
+
+</blueprint>
diff --git a/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelPgEventTest.xml b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelPgEventTest.xml
new file mode 100644
index 0000000..6f61acd
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelPgEventTest.xml
@@ -0,0 +1,42 @@
+<?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.
+
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xsi:schemaLocation="
+             http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
+
+  <camelContext id="myCamel" xmlns="http://camel.apache.org/schema/blueprint">
+
+    <route>
+      <from uri="timer://test?repeatCount=1&amp;period=1"/>
+      <setBody>
+        <constant>Hello World</constant>
+      </setBody>
+      <to uri="pgevent://localhost:5432/postgres/testchannel?user=postgres&amp;pass=mysecretpassword"/>
+    </route>
+
+    <route>
+      <from uri="pgevent://localhost:5432/postgres/testchannel?user=postgres&amp;pass=mysecretpassword"/>
+      <to uri="mock:result"/>
+    </route>
+
+  </camelContext>
+
+</blueprint>
diff --git a/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelQuartzJmxUpdateTest.xml b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelQuartzJmxUpdateTest.xml
new file mode 100644
index 0000000..6eb956e
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelQuartzJmxUpdateTest.xml
@@ -0,0 +1,35 @@
+<?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.
+
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xsi:schemaLocation="
+             http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
+
+  <camelContext id="myCamel" xmlns="http://camel.apache.org/schema/blueprint">
+    <route>
+      <from uri="quartz://myGroup/myTimer?cron=0/1 * * * * ?" />
+      <transform>
+        <constant>Hello World</constant>
+      </transform>
+      <to uri="mock:result" />
+    </route>
+  </camelContext>
+
+</blueprint>
diff --git a/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelSaxonEnabledTest.xml b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelSaxonEnabledTest.xml
new file mode 100644
index 0000000..dff03e5
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelSaxonEnabledTest.xml
@@ -0,0 +1,46 @@
+<?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.
+
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xsi:schemaLocation="
+             http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
+
+  <camelContext id="myCamel" xmlns="http://camel.apache.org/schema/blueprint">
+
+    <route>
+      <from uri="direct:in"/>
+      <choice>
+        <when>
+          <xpath saxon="true">$type = 'Camel'</xpath>
+          <to uri="mock:camel"/>
+        </when>
+        <when>
+          <xpath saxon="true">//name = 'Kong'</xpath>
+          <to uri="mock:donkey"/>
+        </when>
+        <otherwise>
+          <to uri="mock:other"/>
+        </otherwise>
+      </choice>
+    </route>
+
+  </camelContext>
+
+</blueprint>
diff --git a/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelSaxonTest.xml b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelSaxonTest.xml
new file mode 100644
index 0000000..159aa66
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelSaxonTest.xml
@@ -0,0 +1,46 @@
+<?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.
+
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xsi:schemaLocation="
+             http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
+
+  <camelContext id="myCamel" xmlns="http://camel.apache.org/schema/blueprint">
+
+    <route>
+      <from uri="direct:in"/>
+      <choice>
+        <when>
+          <xpath objectModel="http://saxon.sf.net/jaxp/xpath/om">$type = 'Camel'</xpath>
+          <to uri="mock:camel"/>
+        </when>
+        <when>
+          <xpath objectModel="http://saxon.sf.net/jaxp/xpath/om">//name = 'Kong'</xpath>
+          <to uri="mock:donkey"/>
+        </when>
+        <otherwise>
+          <to uri="mock:other"/>
+        </otherwise>
+      </choice>
+    </route>
+
+  </camelContext>
+
+</blueprint>
diff --git a/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelSpringTest.xml b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelSpringTest.xml
new file mode 100644
index 0000000..96b1d4b
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelSpringTest.xml
@@ -0,0 +1,38 @@
+<?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.
+
+-->
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+		http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd
+		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd ">
+
+  <camelContext id="myCamel" xmlns="http://camel.apache.org/schema/spring">
+
+    <route>
+      <from uri="direct:start"/>
+      <transform>
+        <simple>Bye ${body}</simple>
+      </transform>
+      <to uri="mock:result"/>
+    </route>
+
+  </camelContext>
+
+</beans>
diff --git a/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelTypeConverterTest.xml b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelTypeConverterTest.xml
new file mode 100644
index 0000000..f47bb35
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/CamelTypeConverterTest.xml
@@ -0,0 +1,28 @@
+<?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.
+
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xsi:schemaLocation="
+             http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
+
+  <camelContext id="myCamel" xmlns="http://camel.apache.org/schema/blueprint">
+  </camelContext>
+
+</blueprint>
diff --git a/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/cxf/CamelCxfBeanInjectTest.xml b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/cxf/CamelCxfBeanInjectTest.xml
new file mode 100644
index 0000000..cddbd14
--- /dev/null
+++ b/tests/camel-itest-osgi/src/test/resources/org/apache/camel/itest/cxf/CamelCxfBeanInjectTest.xml
@@ -0,0 +1,82 @@
+<?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.
+
+-->
+<blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0"
+           xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+           xmlns:cxf="http://camel.apache.org/schema/blueprint/cxf"
+           xmlns:httpj="http://cxf.apache.org/transports/http-jetty/configuration"
+           xmlns:cm="http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0"
+           xsi:schemaLocation="
+             http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd
+             http://camel.apache.org/schema/blueprint/cxf http://camel.apache.org/schema/blueprint/cxf/camel-cxf.xsd
+             http://cxf.apache.org/transports/http-jetty/configuration http://cxf.apache.org/schemas/configuration/http-jetty.xsd
+             http://aries.apache.org/blueprint/xmlns/blueprint-cm/v1.1.0 http://aries.apache.org/schemas/blueprint-cm/blueprint-cm-1.1.0.xsd
+             http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd">
+
+  <!-- blueprint property placeholders -->
+  <cm:property-placeholder persistent-id="my-placeholders" update-strategy="reload">
+    <cm:default-properties>
+      <cm:property name="router.address" value="http://localhost:9000/routerEndpoint" />
+      <cm:property name="router.port" value="9000" />
+    </cm:default-properties>
+  </cm:property-placeholder>
+
+  <!-- configuration for reverse proxy -->
+  <httpj:engine-factory bus="cxf">
+    <httpj:engine port="${router.port}">
+      <httpj:connector>
+        <bean id="connector" class="org.eclipse.jetty.server.ServerConnector">
+          <argument ref="server" />
+          <argument>
+            <array>
+              <ref component-id="httpConnectionFactory" />
+            </array>
+          </argument>
+          <property name="port" value="${router.port}" />
+        </bean>
+      </httpj:connector>
+    </httpj:engine>
+  </httpj:engine-factory>
+
+  <bean id="server" class="org.eclipse.jetty.server.Server" />
+
+  <bean id="httpConfiguration" class="org.eclipse.jetty.server.HttpConfiguration">
+    <property name="customizers">
+      <list>
+        <bean class="org.eclipse.jetty.server.ForwardedRequestCustomizer" />
+      </list>
+    </property>
+  </bean>
+
+  <bean id="httpConnectionFactory" class="org.eclipse.jetty.server.HttpConnectionFactory">
+    <argument ref="httpConfiguration" />
+  </bean>
+
+  <cxf:cxfEndpoint id="routerEndpoint" address="{{router.address}}"
+                   serviceClass="org.apache.camel.itest.cxf.SimpleService" />
+
+  <bean id="routeBuilder" class="org.apache.camel.itest.cxf.BeanInjectRouteBuilder" />
+
+  <bean id="simpleBean" class="org.apache.camel.itest.cxf.SimpleBean" />
+
+  <camelContext id="myCamel" xmlns="http://camel.apache.org/schema/blueprint">
+    <routeBuilder ref="routeBuilder" />
+  </camelContext>
+
+</blueprint>
diff --git a/tests/pom.xml b/tests/pom.xml
index 873e96a..573193b 100644
--- a/tests/pom.xml
+++ b/tests/pom.xml
@@ -40,6 +40,7 @@
     <modules>
         <module>camel-blueprint-cxf-test</module>
         <module>camel-blueprint-test</module>
+        <module>camel-itest-osgi</module>
     </modules>
 
     <build>