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/23 08:30:03 UTC

[camel-karaf] 01/05: Camel-Karaf: First commit

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 271a283d594f15f51a5ae32a6ae470b8b770265c
Author: Andrea Cosentino <an...@gmail.com>
AuthorDate: Mon Mar 23 08:47:44 2020 +0100

    Camel-Karaf: First commit
---
 .gitignore                                         |  27 +
 core/camel-core-osgi/pom.xml                       | 107 +++
 .../apache/camel/core/osgi/OsgiBeanRepository.java | 183 ++++
 .../camel/core/osgi/OsgiCamelContextHelper.java    |  53 ++
 .../core/osgi/OsgiCamelContextNameStrategy.java    |  63 ++
 .../camel/core/osgi/OsgiCamelContextPublisher.java | 153 ++++
 .../apache/camel/core/osgi/OsgiClassResolver.java  | 186 +++++
 .../camel/core/osgi/OsgiComponentResolver.java     |  69 ++
 .../camel/core/osgi/OsgiDataFormatResolver.java    |  91 ++
 .../camel/core/osgi/OsgiDefaultCamelContext.java   |  60 ++
 .../camel/core/osgi/OsgiEventAdminNotifier.java    | 144 ++++
 .../apache/camel/core/osgi/OsgiFactoryFinder.java  | 126 +++
 .../camel/core/osgi/OsgiFactoryFinderResolver.java |  37 +
 .../camel/core/osgi/OsgiLanguageResolver.java      |  98 +++
 .../core/osgi/OsgiManagementNameStrategy.java      |  73 ++
 .../apache/camel/core/osgi/OsgiNamingHelper.java   |  91 ++
 .../core/osgi/OsgiPackageScanClassResolver.java    | 115 +++
 .../apache/camel/core/osgi/OsgiTypeConverter.java  | 336 ++++++++
 .../org/apache/camel/core/osgi/impl/Activator.java | 728 ++++++++++++++++
 .../org/apache/camel/core/osgi/impl/package.html   |  27 +
 .../camel/core/osgi/utils/BundleContextUtils.java  |  67 ++
 .../osgi/utils/BundleDelegatingClassLoader.java    |  99 +++
 .../apache/camel/core/osgi/CamelMockBundle.java    | 132 +++
 .../camel/core/osgi/CamelMockBundleContext.java    | 139 ++++
 .../camel/core/osgi/CamelMockLanguageResolver.java |  33 +
 .../camel/core/osgi/CamelOsgiTestSupport.java      |  53 ++
 .../camel/core/osgi/OsgiClassResolverTest.java     |  40 +
 .../camel/core/osgi/OsgiComponentResolverTest.java | 122 +++
 .../core/osgi/OsgiDataFormatResolverTest.java      |  88 ++
 .../camel/core/osgi/OsgiFactoryFinderTest.java     |  42 +
 .../camel/core/osgi/OsgiLanguageResolverTest.java  |  94 +++
 .../osgi/OsgiPackageScanClassResolverTest.java     |  79 ++
 .../camel/core/osgi/ServiceRegistryTest.java       |  58 ++
 .../camel/core/osgi/other/MyOtherRouteBuilder.java |  28 +
 .../core/osgi/other/MyOtherTypeConverter.java      |  77 ++
 .../core/osgi/test/MockTypeConverterRegistry.java  | 141 ++++
 .../camel/core/osgi/test/MyRouteBuilder.java       |  28 +
 .../org/apache/camel/core/osgi/test/MyService.java |  25 +
 .../camel/core/osgi/test/MyTypeConverter.java      |  77 ++
 .../src/test/resources/META-INF/LICENSE.txt        | 203 +++++
 .../src/test/resources/META-INF/NOTICE.txt         |  11 +
 .../services/org/apache/camel/component/file_test  |  19 +
 .../services/org/apache/camel/component/timer_test |  18 +
 .../services/org/apache/camel/language/bean_test   |  18 +
 .../services/org/apache/camel/language/file_test   |  18 +
 .../org/apache/camel/language/resolver/default     |  18 +
 .../resources/META-INF/spring/camel-context.xml    |  66 ++
 .../src/test/resources/log4j2.properties           |  28 +
 core/pom.xml                                       |  37 +
 pom.xml                                            | 921 +++++++++++++++++++++
 50 files changed, 5546 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..5d69a55
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,27 @@
+target
+*.iml
+*.ipr
+*.iws
+.idea
+.DS_Store
+.classpath
+.ekstazi
+.project
+.settings
+.checkstyle
+*.log
+test-salesforce-login.properties
+dependency-reduced-pom.xml
+id_file
+components/camel-solr/data
+*.epoch
+.factorypath
+.pmd
+.sts4-cache
+log-camel-lsp.out
+.vscode
+*.code-workspace
+components/camel-cxf/activemq-data
+*.swp
+.flattened-pom.xml
+.java-version
diff --git a/core/camel-core-osgi/pom.xml b/core/camel-core-osgi/pom.xml
new file mode 100644
index 0000000..205ef0e
--- /dev/null
+++ b/core/camel-core-osgi/pom.xml
@@ -0,0 +1,107 @@
+<?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>core-modules</artifactId>
+        <version>3.2.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-core-osgi</artifactId>
+    <packaging>jar</packaging>
+
+    <name>Camel Karaf :: Core OSGi</name>
+    <description>Camel Karaf Core OSGi support</description>
+
+    <properties>
+        <camel.osgi.import>
+            org.osgi.service.event;resolution:=optional,
+            *
+        </camel.osgi.import>
+        <camel.osgi.provide.capability>
+            osgi.extender; osgi.extender="org.apache.camel"; uses:="org.apache.camel.core.osgi.impl";
+            version:Version="$(version;==;${camel.osgi.version.clean})"
+        </camel.osgi.provide.capability>
+        <camel.osgi.activator>
+            org.apache.camel.core.osgi.impl.Activator
+        </camel.osgi.activator>
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-core-engine</artifactId>
+        </dependency>
+
+        <!-- osgi -->
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.cmpn</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- for testing -->
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-core-languages</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-file</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.osgi</groupId>
+            <artifactId>spring-osgi-mock</artifactId>
+            <version>1.2.1</version>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-api</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.logging.log4j</groupId>
+            <artifactId>log4j-slf4j-impl</artifactId>
+            <scope>test</scope>
+        </dependency>
+
+    </dependencies>
+</project>
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiBeanRepository.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiBeanRepository.java
new file mode 100644
index 0000000..dcec057
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiBeanRepository.java
@@ -0,0 +1,183 @@
+/*
+ * 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.core.osgi;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.Service;
+import org.apache.camel.spi.BeanRepository;
+import org.apache.camel.support.LifecycleStrategySupport;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceEvent;
+import org.osgi.framework.ServiceListener;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * The OSGi {@link BeanRepository} support to lookup beans from the OSGi service registry from its bundle context.
+ */
+public class OsgiBeanRepository extends LifecycleStrategySupport implements BeanRepository, Service, ServiceListener {
+    private static final Logger LOG = LoggerFactory.getLogger(OsgiBeanRepository.class);
+    private final BundleContext bundleContext;
+    private final Map<ServiceReference<?>, AtomicLong> serviceReferenceUsageMap = new ConcurrentHashMap<>();
+    
+    public OsgiBeanRepository(BundleContext bc) {
+        bundleContext = bc;
+        bundleContext.addServiceListener(this);
+    }
+
+    /**
+     * Support to lookup the Object with filter with the (name=NAME) and class type
+     */
+    @Override
+    public <T> T lookupByNameAndType(String name, Class<T> type) {
+        Object service = null;
+        ServiceReference<?> sr;
+        try {
+            ServiceReference<?>[] refs = bundleContext.getServiceReferences(type.getName(), "(name=" + name + ")");            
+            if (refs != null && refs.length > 0) {
+                // just return the first one
+                sr = refs[0];
+                incrementServiceUsage(sr);
+                service = bundleContext.getService(sr);
+            }
+        } catch (Exception ex) {
+            throw RuntimeCamelException.wrapRuntimeCamelException(ex);
+        }
+        service = unwrap(service);
+        return type.cast(service);
+    }
+
+    /**
+     * It's only support to look up the ServiceReference with Class name or service PID
+     */
+    @Override
+    public Object lookupByName(String name) {
+        Object service = null;
+        ServiceReference<?> sr = bundleContext.getServiceReference(name);
+        if (sr == null) {
+            // trying to lookup service by PID if not found by name
+            String filterExpression = "(" + Constants.SERVICE_PID + "=" + name + ")";
+            try {
+                ServiceReference<?>[] refs = bundleContext.getServiceReferences((String)null, filterExpression);
+                if (refs != null && refs.length > 0) {
+                    // just return the first one
+                    sr = refs[0];
+                }
+            } catch (InvalidSyntaxException ex) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Invalid OSGi service reference filter, skipped lookup by service.pid. Filter expression: {}", filterExpression, ex);
+                }
+            }
+        }
+        if (sr != null) {
+            incrementServiceUsage(sr);
+            service = bundleContext.getService(sr);
+        }
+        service = unwrap(service);
+        return service;
+    }
+
+    @Override
+    public <T> Map<String, T> findByTypeWithName(Class<T> type) {
+        Map<String, T> result = new HashMap<>();
+        int count = 0;
+        try {
+            ServiceReference<?>[] refs = bundleContext.getAllServiceReferences(type.getName(), null);
+            if (refs != null) {
+                for (ServiceReference<?> sr : refs) {
+                    if (sr != null) {
+                        Object service = bundleContext.getService(sr);
+                        incrementServiceUsage(sr);
+                        if (service != null) {
+                            String name = (String)sr.getProperty("name");
+                            service = unwrap(service);
+                            if (name != null) {
+                                result.put(name, type.cast(service));
+                            } else {
+                                // generate a unique name for it
+                                result.put(type.getSimpleName() + count, type.cast(service));
+                                count++;
+                            }
+                        }
+                    }
+                }
+            }
+        } catch (Exception ex) {
+            throw RuntimeCamelException.wrapRuntimeCamelException(ex);
+        }
+        return result;
+    }
+
+    @Override
+    public <T> Set<T> findByType(Class<T> type) {
+        Map<String, T> map = findByTypeWithName(type);
+        return new HashSet<>(map.values());
+    }
+
+    @Override
+    public void start() {
+        // noop
+    }
+
+    @Override
+    public void stop() {
+        // Unget the OSGi service as OSGi uses reference counting
+        // and we should do this as one of the last actions when stopping Camel
+        this.serviceReferenceUsageMap.forEach(this::drainServiceUsage);
+        this.serviceReferenceUsageMap.clear();
+    }
+
+    private void drainServiceUsage(ServiceReference<?> serviceReference, AtomicLong serviceUsageCount) {
+        if (serviceUsageCount != null && serviceReference != null) {
+            while (serviceUsageCount.decrementAndGet() >= 0) {
+                this.bundleContext.ungetService(serviceReference);
+            }
+        }
+    }
+
+    private void incrementServiceUsage(ServiceReference<?> sr) {
+        AtomicLong serviceUsageCount = this.serviceReferenceUsageMap.get(sr);
+        if (serviceUsageCount != null) {
+            serviceUsageCount.incrementAndGet();
+        } else {
+            this.serviceReferenceUsageMap.merge(sr, new AtomicLong(1),
+                (existingServiceUsageCount, newServiceUsageCount) -> {
+                    existingServiceUsageCount.getAndAdd(newServiceUsageCount.get());
+                    return existingServiceUsageCount;
+                });
+        }
+    }
+
+    @Override
+    public void serviceChanged(ServiceEvent event) {
+        if (event.getType() == ServiceEvent.UNREGISTERING) {
+            ServiceReference<?> serviceReference = event.getServiceReference();
+            AtomicLong serviceUsageCount = this.serviceReferenceUsageMap.remove(serviceReference);
+            drainServiceUsage(serviceReference, serviceUsageCount);
+        }
+    }
+}
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextHelper.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextHelper.java
new file mode 100644
index 0000000..aeda372
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextHelper.java
@@ -0,0 +1,53 @@
+/*
+ * 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.core.osgi;
+
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.util.ObjectHelper;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public final class OsgiCamelContextHelper {
+    private static final Logger LOG = LoggerFactory.getLogger(OsgiCamelContextHelper.class);
+
+    private OsgiCamelContextHelper() {
+        // helper class
+    }
+    
+    public static void osgiUpdate(DefaultCamelContext camelContext, BundleContext bundleContext) {
+        ObjectHelper.notNull(bundleContext, "BundleContext");
+
+        LOG.debug("Using OsgiCamelContextNameStrategy");
+        camelContext.setNameStrategy(new OsgiCamelContextNameStrategy(bundleContext));
+        LOG.debug("Using OsgiManagementNameStrategy");
+        camelContext.setManagementNameStrategy(new OsgiManagementNameStrategy(camelContext, bundleContext));
+        LOG.debug("Using OsgiClassResolver");
+        camelContext.setClassResolver(new OsgiClassResolver(camelContext, bundleContext));
+        LOG.debug("Using OsgiFactoryFinderResolver");
+        camelContext.setFactoryFinderResolver(new OsgiFactoryFinderResolver(bundleContext));
+        LOG.debug("Using OsgiPackageScanClassResolver");
+        camelContext.setPackageScanClassResolver(new OsgiPackageScanClassResolver(bundleContext));
+        LOG.debug("Using OsgiComponentResolver");
+        camelContext.setComponentResolver(new OsgiComponentResolver(bundleContext));
+        LOG.debug("Using OsgiLanguageResolver");
+        camelContext.setLanguageResolver(new OsgiLanguageResolver(bundleContext));
+        LOG.debug("Using OsgiDataFormatResolver");
+        camelContext.setDataFormatResolver(new OsgiDataFormatResolver(bundleContext));
+    }
+    
+}
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextNameStrategy.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextNameStrategy.java
new file mode 100644
index 0000000..965d11c
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextNameStrategy.java
@@ -0,0 +1,63 @@
+/*
+ * 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.core.osgi;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.camel.spi.CamelContextNameStrategy;
+import org.osgi.framework.BundleContext;
+
+import static org.apache.camel.core.osgi.OsgiCamelContextPublisher.CONTEXT_NAME_PROPERTY;
+
+/**
+ * In OSGi we want to use a {@link CamelContextNameStrategy} that finds a free name in the
+ * OSGi Service Registry to be used for auto assigned names.
+ * <p/>
+ * If there is a name clash in the OSGi registry, then a new candidate name is used by appending
+ * a unique counter.
+ */
+public class OsgiCamelContextNameStrategy implements CamelContextNameStrategy {
+
+    private static final AtomicInteger CONTEXT_COUNTER = new AtomicInteger(0);
+    private final BundleContext context;
+    private final String prefix = "camel";
+    private volatile String name;
+
+    public OsgiCamelContextNameStrategy(BundleContext context) {
+        this.context = context;
+    }
+
+    @Override
+    public String getName() {
+        if (name == null) {
+            name = getNextName();
+        }
+        return name;
+    }
+
+    @Override
+    public synchronized String getNextName() {
+        // false = do no check fist, but add the counter asap, so we have camel-1
+        return OsgiNamingHelper.findFreeCamelContextName(context, prefix, CONTEXT_NAME_PROPERTY, CONTEXT_COUNTER, false);
+    }
+
+    @Override
+    public boolean isFixedName() {
+        return false;
+    }
+
+}
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextPublisher.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextPublisher.java
new file mode 100644
index 0000000..ab0976d
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiCamelContextPublisher.java
@@ -0,0 +1,153 @@
+/*
+ * 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.core.osgi;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.spi.CamelEvent;
+import org.apache.camel.spi.CamelEvent.CamelContextEvent;
+import org.apache.camel.spi.CamelEvent.Type;
+import org.apache.camel.support.EventNotifierSupport;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.Version;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This {@link org.apache.camel.spi.EventNotifier} is in charge of registering
+ * {@link CamelContext} in the OSGi registry
+ */
+public class OsgiCamelContextPublisher extends EventNotifierSupport {
+
+    public static final String CONTEXT_SYMBOLIC_NAME_PROPERTY = "camel.context.symbolicname";
+    public static final String CONTEXT_VERSION_PROPERTY = "camel.context.version";
+    public static final String CONTEXT_NAME_PROPERTY = "camel.context.name";
+    public static final String CONTEXT_MANAGEMENT_NAME_PROPERTY = "camel.context.managementname";
+
+    private static final Logger LOG = LoggerFactory.getLogger(OsgiCamelContextPublisher.class);
+
+    private final BundleContext bundleContext;
+    private final Map<CamelContext, ServiceRegistration<?>> registrations 
+        = new ConcurrentHashMap<>();
+
+    public OsgiCamelContextPublisher(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    @Override
+    public void notify(CamelEvent event) throws Exception {
+        if (event.getType() == Type.CamelContextStarted) {
+            CamelContext context = ((CamelContextEvent) event).getContext();
+            registerCamelContext(context);
+        } else if (event.getType() == Type.CamelContextStopping) {
+            CamelContext context = ((CamelContextEvent) event).getContext();
+            ServiceRegistration<?> reg = registrations.remove(context);
+            if (reg != null) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Unregistering CamelContext [{}] from OSGi registry", context.getName());
+                }
+                try {
+                    reg.unregister();
+                } catch (Exception e) {
+                    LOG.warn("Error unregistering CamelContext [" + context.getName() + "] from OSGi registry. This exception will be ignored.", e);
+                }
+            }
+        }
+    }
+
+    @Override
+    public boolean isEnabled(CamelEvent event) {
+        return event.getType() == Type.CamelContextStarted || event.getType() == Type.CamelContextStopping;
+    }
+
+    @Override
+    protected void doShutdown() throws Exception {
+        // clear and unregister any left-over registration (which should not happen)
+        if (!registrations.isEmpty()) {
+            LOG.warn("On shutdown there are {} registrations which was supposed to have been unregistered already. Will unregister these now.", registrations.size());
+            for (ServiceRegistration<?> reg : registrations.values()) {
+                try {
+                    reg.unregister();
+                } catch (Exception e) {
+                    LOG.warn("Error unregistering from OSGi registry. This exception will be ignored.", e);
+                }
+            }
+        }
+        registrations.clear();
+    }
+
+    public ServiceRegistration<?> registerCamelContext(CamelContext camelContext) throws InvalidSyntaxException {
+        // avoid registering the same service again
+        // we must include unique camel management name so the symbolic name becomes unique,
+        // in case the bundle has more than one CamelContext
+        String name = camelContext.getName();
+        String managementName = camelContext.getManagementName();
+        String symbolicName = bundleContext.getBundle().getSymbolicName();
+
+        if (!lookupCamelContext(bundleContext, symbolicName, name)) {
+            Version bundleVersion = getBundleVersion(bundleContext.getBundle());
+
+            Dictionary<String, Object > props = new Hashtable<>();
+            props.put(CONTEXT_SYMBOLIC_NAME_PROPERTY, symbolicName);
+            props.put(CONTEXT_VERSION_PROPERTY, bundleVersion);
+            props.put(CONTEXT_NAME_PROPERTY, name);
+            if (managementName != null) {
+                props.put(CONTEXT_MANAGEMENT_NAME_PROPERTY, managementName);
+            }
+
+            LOG.debug("Registering CamelContext [{}] in OSGi registry", name);
+
+            ServiceRegistration<?> reg = bundleContext.registerService(CamelContext.class.getName(), camelContext, props);
+            if (reg != null) {
+                registrations.put(camelContext, reg);
+            }
+            return reg;
+        } else {
+            return null;
+        }
+    }
+
+    public static Version getBundleVersion(Bundle bundle) {
+        Dictionary<?, ?> headers = bundle.getHeaders();
+        String version = (String) headers.get(Constants.BUNDLE_VERSION);
+        return (version != null) ? Version.parseVersion(version) : Version.emptyVersion;
+    }
+
+    /**
+     * Lookup in the OSGi Service Registry whether a {@link org.apache.camel.CamelContext} is already registered with the given symbolic name.
+     *
+     * @return <tt>true</tt> if exists, <tt>false</tt> otherwise
+     */
+    public static boolean lookupCamelContext(BundleContext bundleContext, String symbolicName, String contextName) throws InvalidSyntaxException {
+        Version bundleVersion = getBundleVersion(bundleContext.getBundle());
+        ServiceReference<?>[] refs = bundleContext.getServiceReferences(CamelContext.class.getName(),
+                "(&(" + CONTEXT_SYMBOLIC_NAME_PROPERTY + "=" + symbolicName + ")"
+                + "(" + CONTEXT_NAME_PROPERTY + "=" + contextName + ")"
+                + "(" + CONTEXT_VERSION_PROPERTY + "=" + bundleVersion + "))");
+        return refs != null && refs.length > 0;
+    }
+
+}
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiClassResolver.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiClassResolver.java
new file mode 100644
index 0000000..0d9e059
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiClassResolver.java
@@ -0,0 +1,186 @@
+/*
+ * 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.core.osgi;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.Vector;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.apache.camel.util.CastUtils;
+import org.apache.camel.util.FileUtil;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.StringHelper;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/* Using the bundle of CamelContext to load the class */
+public class OsgiClassResolver extends DefaultClassResolver {
+    private static final Logger LOG = LoggerFactory.getLogger(OsgiClassResolver.class);
+
+    private final CamelContext camelContext;
+    private final BundleContext bundleContext;
+
+    public OsgiClassResolver(CamelContext camelContext, BundleContext context) {
+        super(camelContext);
+        this.camelContext = camelContext;
+        this.bundleContext = context;
+    }
+
+    @Override
+    public Class<?> resolveClass(String name) {
+        LOG.trace("Resolve class {}", name);
+        name = StringHelper.normalizeClassName(name);
+        if (ObjectHelper.isEmpty(name)) {
+            return null;
+        }
+        // we need to avoid the NPE issue of loading the class
+        Class<?> clazz = ObjectHelper.loadSimpleType(name);
+        if (clazz == null) {
+            clazz = doLoadClass(name, bundleContext.getBundle());
+            if (LOG.isTraceEnabled()) {
+                LOG.trace("Loading class {} using BundleContext {} -> {}", name, bundleContext.getBundle(), clazz);
+            }
+        }
+        if (clazz == null && camelContext != null) {
+            // fallback and load class using the application context classloader
+            clazz = super.loadClass(name, camelContext.getApplicationContextClassLoader());
+            if (LOG.isTraceEnabled()) {
+                LOG.trace("Loading class {} using CamelContext {} -> {}", name, camelContext, clazz);
+            }
+        }
+        return clazz;
+    }
+
+    @Override
+    public <T> Class<T> resolveClass(String name, Class<T> type) {
+        return CastUtils.cast(resolveClass(name));
+    }
+
+    @Override
+    public InputStream loadResourceAsStream(String uri) {
+        StringHelper.notEmpty(uri, "uri");
+
+        String resolvedName = resolveUriPath(uri);
+        URL url = loadResourceAsURL(resolvedName);
+        InputStream answer = null;
+        if (url != null) {
+            try {
+                answer = url.openStream();
+            } catch (IOException ex) {
+                throw new RuntimeException("Cannot load resource: " + uri, ex);
+            }
+        }
+
+        // fallback to default as OSGi may have issues loading resources
+        if (answer == null) {
+            answer = super.loadResourceAsStream(uri);
+        }
+        return answer;
+    }
+
+    @Override
+    public URL loadResourceAsURL(String uri) {
+        StringHelper.notEmpty(uri, "uri");
+        String resolvedName = resolveUriPath(uri);
+        URL answer = bundleContext.getBundle().getResource(resolvedName);
+
+        // fallback to default as OSGi may have issues loading resources
+        if (answer == null) {
+            answer = super.loadResourceAsURL(uri);
+        }
+        return answer;
+    }
+
+    @Override
+    public Enumeration<URL> loadResourcesAsURL(String uri) {
+        StringHelper.notEmpty(uri, "uri");
+        try {
+            String resolvedName = resolveUriPath(uri);
+            return bundleContext.getBundle().getResources(resolvedName);
+        } catch (IOException e) {
+            throw new RuntimeException("Cannot load resource: " + uri, e);
+        }
+    }
+
+    @Override
+    public Enumeration<URL> loadAllResourcesAsURL(String uri) {
+        StringHelper.notEmpty(uri, "uri");
+        Vector<URL> answer = new Vector<>();
+
+        try {
+            String resolvedName = resolveUriPath(uri);
+
+            Enumeration<URL> e = bundleContext.getBundle().getResources(resolvedName);
+            while (e != null && e.hasMoreElements()) {
+                answer.add(e.nextElement());
+            }
+
+            String path = FileUtil.onlyPath(uri);
+            String name = FileUtil.stripPath(uri);
+            if (path != null && name != null) {
+                for (Bundle bundle : bundleContext.getBundles()) {
+                    LOG.trace("Finding all entries in path: {} with pattern: {}", path, name);
+                    e = bundle.findEntries(path, name, false);
+                    while (e != null && e.hasMoreElements()) {
+                        answer.add(e.nextElement());
+                    }
+                }
+            }
+        } catch (IOException e) {
+            throw new RuntimeException("Cannot load resource: " + uri, e);
+        }
+
+        return answer.elements();
+    }
+
+    protected Class<?> doLoadClass(String name, Bundle loader) {
+        StringHelper.notEmpty(name, "name");
+        Class<?> answer = null;
+        // Try to use the camel context's bundle's classloader to load the class
+        if (loader != null) {
+            try {
+                answer = loader.loadClass(name);
+            } catch (ClassNotFoundException e) {
+                if (LOG.isTraceEnabled()) {
+                    LOG.trace("Cannot load class: " + name + " using classloader: " + loader + ". This exception will be ignored.", e);
+                }
+            }
+        }
+        return answer;
+    }
+
+    /**
+     * Helper operation used to remove relative path notation from
+     * resources.  Most critical for resources on the Classpath
+     * as resource loaders will not resolve the relative paths correctly.
+     *
+     * @param name the name of the resource to load
+     * @return the modified or unmodified string if there were no changes
+     */
+    private static String resolveUriPath(String name) {
+        // compact the path and use / as separator as that's used for loading resources on the classpath
+        return FileUtil.compactPath(name, '/');
+    }
+
+    
+}
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiComponentResolver.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiComponentResolver.java
new file mode 100644
index 0000000..f87ad7a
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiComponentResolver.java
@@ -0,0 +1,69 @@
+/*
+ * 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.core.osgi;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Component;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.ComponentResolver;
+import org.apache.camel.support.ResolverHelper;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OsgiComponentResolver implements ComponentResolver {
+    private static final Logger LOG = LoggerFactory.getLogger(OsgiComponentResolver.class);
+
+    private final BundleContext bundleContext;
+
+    public OsgiComponentResolver(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    @Override
+    public Component resolveComponent(String name, CamelContext context) throws Exception {
+        Component componentReg = ResolverHelper.lookupComponentInRegistryWithFallback(context, name);
+        if (componentReg != null) {
+            return componentReg;
+        }
+
+        // Check in OSGi bundles
+        return getComponent(name, context);
+    }
+
+    protected Component getComponent(String name, CamelContext context) throws Exception {
+        LOG.trace("Finding Component: {}", name);
+        try {
+            ServiceReference<?>[] refs = bundleContext.getServiceReferences(ComponentResolver.class.getName(), "(component=" + name + ")");
+            if (refs != null) {
+                for (ServiceReference<?> ref : refs) {
+                    Object service = bundleContext.getService(ref);
+                    if (ComponentResolver.class.isAssignableFrom(service.getClass())) {
+                        ComponentResolver resolver = (ComponentResolver) service;
+                        return resolver.resolveComponent(name, context);
+                    }
+                }
+            }
+            return null;
+        } catch (InvalidSyntaxException e) {
+            throw RuntimeCamelException.wrapRuntimeCamelException(e);
+        }
+    }
+
+}
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiDataFormatResolver.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiDataFormatResolver.java
new file mode 100644
index 0000000..417fba0
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiDataFormatResolver.java
@@ -0,0 +1,91 @@
+/*
+ * 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.core.osgi;
+
+import java.util.Collection;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.DataFormat;
+import org.apache.camel.spi.DataFormatFactory;
+import org.apache.camel.spi.DataFormatResolver;
+import org.apache.camel.support.ResolverHelper;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OsgiDataFormatResolver implements DataFormatResolver {
+    private static final Logger LOG = LoggerFactory.getLogger(OsgiDataFormatResolver.class);
+
+    private final BundleContext bundleContext;
+
+    public OsgiDataFormatResolver(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    @Override
+    public DataFormat resolveDataFormat(String name, CamelContext context) {
+        // lookup in registry first
+        DataFormat dataFormat = ResolverHelper.lookupDataFormatInRegistryWithFallback(context, name);
+        if (dataFormat == null) {
+            dataFormat = getDataFormat(name, context, false);
+        }
+
+        if (dataFormat == null) {
+            dataFormat = createDataFormat(name, context);
+        }
+
+        return dataFormat;
+    }
+
+    @Override
+    public DataFormat createDataFormat(String name, CamelContext context) {
+        DataFormat dataFormat = null;
+
+        // lookup in registry first
+        DataFormatFactory dataFormatFactory = ResolverHelper.lookupDataFormatFactoryInRegistryWithFallback(context, name);
+        if (dataFormatFactory != null) {
+            dataFormat = dataFormatFactory.newInstance();
+        }
+
+        if (dataFormat == null) {
+            dataFormat = getDataFormat(name, context, true);
+        }
+
+        return dataFormat;
+    }
+
+    private DataFormat getDataFormat(String name, CamelContext context, boolean create) {
+        LOG.trace("Finding DataFormat: {}", name);
+        try {
+            Collection<ServiceReference<DataFormatResolver>> refs = bundleContext.getServiceReferences(DataFormatResolver.class, "(dataformat=" + name + ")");
+            if (refs != null) {
+                for (ServiceReference<DataFormatResolver> ref : refs) {
+                    return create
+                        ? bundleContext.getService(ref).createDataFormat(name, context)
+                        : bundleContext.getService(ref).resolveDataFormat(name, context);
+                }
+            }
+            return null;
+        } catch (InvalidSyntaxException e) {
+            throw RuntimeCamelException.wrapRuntimeCamelException(e);
+        }
+    }
+
+}
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiDefaultCamelContext.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiDefaultCamelContext.java
new file mode 100644
index 0000000..9f85f73
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiDefaultCamelContext.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.core.osgi;
+
+import org.apache.camel.TypeConverter;
+import org.apache.camel.core.osgi.utils.BundleContextUtils;
+import org.apache.camel.core.osgi.utils.BundleDelegatingClassLoader;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.spi.FactoryFinder;
+import org.apache.camel.support.DefaultRegistry;
+import org.osgi.framework.BundleContext;
+
+public class OsgiDefaultCamelContext extends DefaultCamelContext {
+
+    private final BundleContext bundleContext;
+
+    public OsgiDefaultCamelContext(BundleContext bundleContext) {
+        super(false);
+        this.bundleContext = bundleContext;
+
+        // inject common osgi
+        OsgiCamelContextHelper.osgiUpdate(this, bundleContext);
+
+        // and these are blueprint specific
+        OsgiBeanRepository repo1 = new OsgiBeanRepository(bundleContext);
+        setRegistry(new DefaultRegistry(repo1));
+        // Need to clean up the OSGi service when camel context is closed.
+        addLifecycleStrategy(repo1);
+        // setup the application context classloader with the bundle classloader
+        setApplicationContextClassLoader(new BundleDelegatingClassLoader(bundleContext.getBundle()));
+
+        init();
+    }
+
+    @Override
+    protected TypeConverter createTypeConverter() {
+        // CAMEL-3614: make sure we use a bundle context which imports org.apache.camel.impl.converter package
+        BundleContext ctx = BundleContextUtils.getBundleContext(getClass());
+        if (ctx == null) {
+            ctx = bundleContext;
+        }
+        FactoryFinder finder = new OsgiFactoryFinderResolver(bundleContext).resolveDefaultFactoryFinder(getClassResolver());
+        return new OsgiTypeConverter(ctx, this, getInjector(), finder);
+    }
+
+}
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiEventAdminNotifier.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiEventAdminNotifier.java
new file mode 100644
index 0000000..2f12900
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiEventAdminNotifier.java
@@ -0,0 +1,144 @@
+/*
+ * 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.core.osgi;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.camel.spi.CamelEvent;
+import org.apache.camel.support.EventNotifierSupport;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.Constants;
+import org.osgi.framework.Version;
+import org.osgi.service.event.Event;
+import org.osgi.service.event.EventAdmin;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * This {@link org.apache.camel.spi.EventNotifier} is in charge of propagating events
+ * to OSGi {@link EventAdmin} if present.
+ */
+public class OsgiEventAdminNotifier extends EventNotifierSupport {
+
+    public static final String TYPE = "type";
+    public static final String EVENT = "event";
+    public static final String TIMESTAMP = "timestamp";
+    public static final String BUNDLE = "bundle";
+    public static final String BUNDLE_ID = "bundle.id";
+    public static final String BUNDLE_SYMBOLICNAME = "bundle.symbolicName";
+    public static final String BUNDLE_VERSION = "bundle.version";
+    public static final String CAUSE = "cause";
+
+    public static final String TOPIC_CAMEL_EVENTS = "org/apache/camel/";
+    public static final String TOPIC_CAMEL_CONTEXT_EVENTS = TOPIC_CAMEL_EVENTS + "context/";
+    public static final String TOPIC_CAMEL_EXCHANGE_EVENTS = TOPIC_CAMEL_EVENTS + "exchange/";
+    public static final String TOPIC_CAMEL_SERVICE_EVENTS = TOPIC_CAMEL_EVENTS + "service/";
+    public static final String TOPIC_CAMEL_ROUTE_EVENTS = TOPIC_CAMEL_EVENTS + "route/";
+
+    private final BundleContext bundleContext;
+    private final ServiceTracker<EventAdmin, EventAdmin> tracker;
+
+    public OsgiEventAdminNotifier(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+        this.tracker = new ServiceTracker<>(bundleContext, EventAdmin.class.getName(), null);
+        setIgnoreExchangeEvents(true);
+    }
+
+    @Override
+    public void notify(CamelEvent event) throws Exception {
+        EventAdmin eventAdmin = tracker.getService();
+        if (eventAdmin == null) {
+            return;
+        }
+
+        Dictionary<String, Object> props = new Hashtable<>();
+        props.put(TYPE, getType(event));
+        props.put(EVENT, event);
+        props.put(TIMESTAMP, System.currentTimeMillis());
+        props.put(BUNDLE, bundleContext.getBundle());
+        props.put(BUNDLE_SYMBOLICNAME, bundleContext.getBundle().getSymbolicName());
+        props.put(BUNDLE_ID, bundleContext.getBundle().getBundleId());
+        props.put(BUNDLE_VERSION, getBundleVersion(bundleContext.getBundle()));
+        try {
+            props.put(CAUSE, event.getClass().getMethod("getCause").invoke(event));
+        } catch (Throwable t) {
+            // ignore
+        }
+        eventAdmin.postEvent(new Event(getTopic(event), props));
+    }
+
+    @Override
+    public boolean isEnabled(CamelEvent event) {
+        return true;
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        tracker.open();
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        tracker.close();
+    }
+
+    public static String toUpper(String text) {
+        StringBuilder sb = new StringBuilder();
+        for (int i = 0; i < text.length(); i++) {
+            char c = text.charAt(i);
+            if (Character.isUpperCase(c) && sb.length() > 0) {
+                sb.append('_');
+            }
+            sb.append(Character.toUpperCase(c));
+        }
+        return sb.toString();
+    }
+
+    public static String getType(CamelEvent event) {
+        return event.getType().name();
+    }
+
+    public static String getTopic(CamelEvent event) {
+        String topic;
+        String type = getType(event);
+        if (type.startsWith("CamelContext")) {
+            topic = TOPIC_CAMEL_CONTEXT_EVENTS;
+            type = type.substring("CamelContext".length());
+        } else if (type.startsWith("Exchange")) {
+            topic = TOPIC_CAMEL_EXCHANGE_EVENTS;
+            type = type.substring("Exchange".length());
+        } else if (type.startsWith("Route")) {
+            topic = TOPIC_CAMEL_ROUTE_EVENTS;
+            type = type.substring("Route".length());
+        } else if (type.startsWith("Service")) {
+            topic = TOPIC_CAMEL_SERVICE_EVENTS;
+            type = type.substring("Service".length());
+        } else {
+            topic = TOPIC_CAMEL_EVENTS + "unknown/";
+        }
+        topic += toUpper(type);
+        return topic;
+    }
+
+    public static Version getBundleVersion(Bundle bundle) {
+        Dictionary<?, ?> headers = bundle.getHeaders();
+        String version = (String)headers.get(Constants.BUNDLE_VERSION);
+        return (version != null) ? Version.parseVersion(version) : Version.emptyVersion;
+    }
+
+}
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiFactoryFinder.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiFactoryFinder.java
new file mode 100644
index 0000000..ca6adb7
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiFactoryFinder.java
@@ -0,0 +1,126 @@
+/*
+ * 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.core.osgi;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Optional;
+import java.util.Properties;
+
+import org.apache.camel.impl.engine.DefaultFactoryFinder;
+import org.apache.camel.spi.ClassResolver;
+import org.apache.camel.util.IOHelper;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+public class OsgiFactoryFinder extends DefaultFactoryFinder {
+    private BundleContext bundleContext;
+
+    public OsgiFactoryFinder(BundleContext bundleContext, ClassResolver classResolver, String resourcePath) {
+        super(classResolver, resourcePath);
+        this.bundleContext = bundleContext;
+    }
+
+    private static class BundleEntry {
+        URL url;
+        Bundle bundle;
+    }
+
+    @Override
+    public Optional<Class<?>> findClass(String key, String propertyPrefix, Class<?> checkClass) {
+        final String prefix = propertyPrefix != null ? propertyPrefix : "";
+        final String classKey = propertyPrefix + key;
+
+        Class<?> answer = addToClassMap(classKey, () -> {
+            BundleEntry entry = getResource(key, checkClass);
+            if (entry != null) {
+                URL url = entry.url;
+                InputStream in = url.openStream();
+                // lets load the file
+                BufferedInputStream reader = null;
+                try {
+                    reader = IOHelper.buffered(in);
+                    Properties properties = new Properties();
+                    properties.load(reader);
+                    String className = properties.getProperty(prefix + "class");
+                    if (className == null) {
+                        throw new IOException("Expected property is missing: " + prefix + "class");
+                    }
+                    return entry.bundle.loadClass(className);
+                } finally {
+                    IOHelper.close(reader, key, null);
+                    IOHelper.close(in, key, null);
+                }
+            } else {
+                return null;
+            }
+        });
+
+        return Optional.ofNullable(answer);
+    }
+
+    @Override
+    public Optional<Class<?>> findClass(String key, String propertyPrefix) {
+        return findClass(key, propertyPrefix, null);
+    }
+
+    // As the META-INF of the Factory could not be export,
+    // we need to go through the bundles to look for it
+    // NOTE, the first found factory will be return
+    public BundleEntry getResource(String name) {
+        return getResource(name, null);
+    }
+
+    // The clazz can make sure we get right version of class that we need
+    public BundleEntry getResource(String name, Class<?> clazz) {
+        BundleEntry entry = null;
+        Bundle[] bundles;
+        
+        bundles = bundleContext.getBundles();
+        
+        URL url;
+        for (Bundle bundle : bundles) {
+            url = bundle.getEntry(getResourcePath() + name);
+            if (url != null && checkCompatibility(bundle, clazz)) {
+                entry = new BundleEntry();
+                entry.url = url;
+                entry.bundle = bundle;
+                break;
+            }
+        }
+
+        return entry;
+    }
+
+    private boolean checkCompatibility(Bundle bundle, Class<?> clazz) {
+        if (clazz == null) {
+            return true;
+        }
+        // Check bundle compatibility
+        try {
+            if (bundle.loadClass(clazz.getName()) != clazz) {
+                return false;
+            }
+        } catch (Throwable t) {
+            return false;
+        }
+        return true;
+    }
+
+}
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiFactoryFinderResolver.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiFactoryFinderResolver.java
new file mode 100644
index 0000000..631c190
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiFactoryFinderResolver.java
@@ -0,0 +1,37 @@
+/*
+ * 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.core.osgi;
+
+import org.apache.camel.spi.ClassResolver;
+import org.apache.camel.spi.FactoryFinder;
+import org.apache.camel.spi.FactoryFinderResolver;
+import org.osgi.framework.BundleContext;
+
+public class OsgiFactoryFinderResolver implements FactoryFinderResolver {
+
+    private final BundleContext bundleContext;
+
+    public OsgiFactoryFinderResolver(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    @Override
+    public FactoryFinder resolveFactoryFinder(ClassResolver classResolver, String resourcePath) {
+        return new OsgiFactoryFinder(bundleContext, classResolver, resourcePath);
+    }
+
+}
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiLanguageResolver.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiLanguageResolver.java
new file mode 100644
index 0000000..c2197dc
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiLanguageResolver.java
@@ -0,0 +1,98 @@
+/*
+ * 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.core.osgi;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.NoSuchLanguageException;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.spi.Language;
+import org.apache.camel.spi.LanguageResolver;
+import org.apache.camel.support.ResolverHelper;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OsgiLanguageResolver implements LanguageResolver {
+    private static final Logger LOG = LoggerFactory.getLogger(OsgiLanguageResolver.class);
+
+    private final BundleContext bundleContext;
+
+    public OsgiLanguageResolver(BundleContext bundleContext) {
+        this.bundleContext = bundleContext;
+    }
+
+    @Override
+    public Language resolveLanguage(String name, CamelContext context) {
+        // lookup in registry first
+        Language lang = ResolverHelper.lookupLanguageInRegistryWithFallback(context, name);
+        if (lang != null) {
+            return lang;
+        }
+
+        lang = getLanguage(name, context);
+        if (lang != null) {
+            return lang;
+        }
+        LanguageResolver resolver = getLanguageResolver("default", context);
+        if (resolver != null) {
+            return resolver.resolveLanguage(name, context);
+        }
+        throw new NoSuchLanguageException(name);
+    }
+
+    protected Language getLanguage(String name, CamelContext context) {
+        LOG.trace("Finding Language: {}", name);
+        try {
+            ServiceReference<?>[] refs = bundleContext.getServiceReferences(LanguageResolver.class.getName(), "(language=" + name + ")");
+            if (refs != null) {
+                for (ServiceReference<?> ref : refs) {
+                    Object service = bundleContext.getService(ref);
+                    if (LanguageResolver.class.isAssignableFrom(service.getClass())) {
+                        LanguageResolver resolver = (LanguageResolver) service;
+                        return resolver.resolveLanguage(name, context);
+                    }
+                }
+            }
+
+            return null;
+        } catch (InvalidSyntaxException e) {
+            throw RuntimeCamelException.wrapRuntimeCamelException(e);
+        }
+    }
+
+    protected LanguageResolver getLanguageResolver(String name, CamelContext context) {
+        LOG.trace("Finding LanguageResolver: {}", name);
+        try {
+            ServiceReference<?>[] refs = bundleContext.getServiceReferences(LanguageResolver.class.getName(), "(resolver=" + name + ")");
+            if (refs != null) {
+                for (ServiceReference<?> ref : refs) {
+                    Object service = bundleContext.getService(ref);
+                    if (LanguageResolver.class.isAssignableFrom(service.getClass())) {
+                        LanguageResolver resolver = (LanguageResolver) service;
+                        return resolver;
+                    }
+                }
+            }
+            return null;
+        } catch (InvalidSyntaxException e) {
+            throw RuntimeCamelException.wrapRuntimeCamelException(e);
+        }
+    }
+
+}
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiManagementNameStrategy.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiManagementNameStrategy.java
new file mode 100644
index 0000000..ed16568
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiManagementNameStrategy.java
@@ -0,0 +1,73 @@
+/*
+ * 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.core.osgi;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.impl.engine.DefaultManagementNameStrategy;
+import org.apache.camel.util.StringHelper;
+import org.osgi.framework.BundleContext;
+
+/**
+ * OSGi enhanced {@link org.apache.camel.spi.ManagementNameStrategy}.
+ * <p/>
+ * This {@link org.apache.camel.spi.ManagementNameStrategy} supports the default
+ * tokens (see {@link DefaultManagementNameStrategy}) and the following additional OSGi specific tokens
+ * <ul>
+ *     <li>#bundleId# - The bundle id</li>
+ *     <li>#version# - The bundle version</li>
+ *     <li>#symbolicName# - The bundle symbolic name</li>
+ * </ul>
+ * <p/>
+ * This implementation will by default use a name pattern as <tt>#symbolicName#</tt> and in case
+ * of a clash (such as multiple versions of the same symbolicName),
+ * then the pattern will fallback to append an unique counter <tt>#symbolicName#-#counter#</tt>.
+ *
+ * @see DefaultManagementNameStrategy
+ */
+public class OsgiManagementNameStrategy extends DefaultManagementNameStrategy {
+
+    private static final AtomicInteger CONTEXT_COUNTER = new AtomicInteger(0);
+    private final BundleContext bundleContext;
+
+    public OsgiManagementNameStrategy(CamelContext camelContext, BundleContext bundleContext) {
+        super(camelContext, "#symbolicName#-#name#", "#symbolicName#-#name#-#counter#");
+        this.bundleContext = bundleContext;
+    }
+
+    @Override
+    protected String customResolveManagementName(String pattern, String answer) {
+        String bundleId = "" + bundleContext.getBundle().getBundleId();
+        String symbolicName = bundleContext.getBundle().getSymbolicName();
+        if (symbolicName == null) {
+            symbolicName = "";
+        }
+        String version = bundleContext.getBundle().getVersion().toString();
+
+        answer = StringHelper.replaceAll(answer, "#bundleId#", bundleId);
+        answer = StringHelper.replaceAll(answer, "#symbolicName#", symbolicName);
+        answer = StringHelper.replaceAll(answer, "#version#", version);
+
+        // we got a candidate then find a free name
+        // true = check fist if the candidate as-is is free, if not then use the counter
+        answer = OsgiNamingHelper.findFreeCamelContextName(bundleContext, answer, OsgiCamelContextPublisher.CONTEXT_MANAGEMENT_NAME_PROPERTY, CONTEXT_COUNTER, true);
+
+        return answer;
+    }
+    
+}
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiNamingHelper.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiNamingHelper.java
new file mode 100644
index 0000000..5391887
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiNamingHelper.java
@@ -0,0 +1,91 @@
+/*
+ * 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.core.osgi;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import org.apache.camel.CamelContext;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A helper to find free names in the OSGi service registry.
+ */
+public final class OsgiNamingHelper {
+
+    private static final Logger LOG = LoggerFactory.getLogger(OsgiNamingHelper.class);
+
+    private OsgiNamingHelper() {
+    }
+
+    /**
+     * Checks the OSGi service registry for a free name (uses the counter if there is a clash to find next free name)
+     *
+     * @param context the bundle context
+     * @param prefix  the prefix for the name
+     * @param key     the key to use in the OSGi filter; either {@link OsgiCamelContextPublisher#CONTEXT_NAME_PROPERTY}
+     *                or {@link OsgiCamelContextPublisher#CONTEXT_MANAGEMENT_NAME_PROPERTY}.
+     * @param counter the counter
+     * @param checkFirst <tt>true</tt> to check the prefix name as-is before using the counter, <tt>false</tt> the counter is used immediately
+     * @return the free name, is never <tt>null</tt>
+     */
+    public static String findFreeCamelContextName(BundleContext context, String prefix, String key, AtomicInteger counter, boolean checkFirst) {
+        String candidate = null;
+        boolean clash = false;
+
+        do {
+            try {
+                clash = false;
+
+                if (candidate == null && checkFirst) {
+                    // try candidate as-is
+                    candidate = prefix;
+                } else {
+                    // generate new candidate
+                    candidate = prefix + "-" + getNextCounter(counter);
+                }
+                LOG.trace("Checking OSGi Service Registry for existence of existing CamelContext with name: {}", candidate);
+
+                ServiceReference<?>[] refs = context.getServiceReferences(CamelContext.class.getName(), "(" + key + "=" + candidate + ")");
+                if (refs != null && refs.length > 0) {
+                    for (ServiceReference<?> ref : refs) {
+                        Object id = ref.getProperty(key);
+                        if (id != null && candidate.equals(id)) {
+                            clash = true;
+                            break;
+                        }
+                    }
+                }
+            } catch (InvalidSyntaxException e) {
+                LOG.debug("Error finding free Camel name in OSGi Service Registry due " + e.getMessage() + ". This exception is ignored.", e);
+                break;
+            }
+        } while (clash);
+
+        LOG.debug("Generated free name for bundle id: {}, clash: {} -> {}", context.getBundle().getBundleId(), clash, candidate);
+        return candidate;
+    }
+
+    public static int getNextCounter(AtomicInteger counter) {
+        // we want to start counting from 1, so increment first
+        return counter.incrementAndGet();
+    }
+
+}
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiPackageScanClassResolver.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiPackageScanClassResolver.java
new file mode 100644
index 0000000..a973b54
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiPackageScanClassResolver.java
@@ -0,0 +1,115 @@
+/*
+ * 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.core.osgi;
+
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.Enumeration;
+import java.util.LinkedHashSet;
+import java.util.Set;
+
+import org.apache.camel.core.osgi.utils.BundleDelegatingClassLoader;
+import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
+import org.apache.camel.spi.PackageScanFilter;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+public class OsgiPackageScanClassResolver extends DefaultPackageScanClassResolver {
+
+    private final Bundle bundle;
+
+    public OsgiPackageScanClassResolver(BundleContext context) {
+        this(context.getBundle());
+    }
+
+    public OsgiPackageScanClassResolver(Bundle bundle) {
+        this.bundle = bundle;
+        // add the BundleDelegatingClassLoader to the class loaders
+        addClassLoader(new BundleDelegatingClassLoader(bundle));
+    }
+
+    @Override
+    public void find(PackageScanFilter test, String packageName, Set<Class<?>> classes) {
+        packageName = packageName.replace('.', '/');
+        // remember the number of classes found so far
+        int classesSize = classes.size();
+        // look in osgi bundles
+        loadImplementationsInBundle(test, packageName, classes);
+        // if we did not find any new, then fallback to use regular non bundle class loading
+        if (classes.size() == classesSize) {
+            // Using the non-OSGi classloaders as a fallback
+            // this is necessary when use JBI packaging for servicemix-camel SU
+            // so that we get chance to use SU classloader to scan packages in the SU
+            log.trace("Cannot find any classes in bundles, not trying regular classloaders scanning: {}", packageName);
+            for (ClassLoader classLoader : super.getClassLoaders()) {
+                if (!isOsgiClassloader(classLoader)) {
+                    find(test, packageName, classLoader, classes);
+                }
+            }  
+        }
+    }
+    
+    private static boolean isOsgiClassloader(ClassLoader loader) {
+        try {
+            Method mth = loader.getClass().getMethod("getBundle", new Class[] {});
+            if (mth != null) {
+                return true;
+            }
+        } catch (NoSuchMethodException e) {
+            // ignore its not an osgi loader
+        }
+        return false;
+    }
+    
+    private void loadImplementationsInBundle(PackageScanFilter test, String packageName, Set<Class<?>> classes) {       
+        Set<String> urls = getImplementationsInBundle(test, packageName);
+        if (urls != null) {
+            for (String url : urls) {
+                // substring to avoid leading slashes
+                addIfMatching(test, url, classes);
+            }
+        }
+    }
+
+    private Set<String> getImplementationsInBundle(PackageScanFilter test, String packageName) {
+        Bundle[] bundles;
+        if (bundle.getBundleContext() != null) {
+            bundles = bundle.getBundleContext().getBundles();
+        } else {
+            bundles = new Bundle[]{bundle};
+        }
+        Set<String> urls = new LinkedHashSet<>();
+        for (Bundle bd : bundles) {
+            log.trace("Searching in bundle: {}", bd);
+            try {
+                Enumeration<URL> paths = bd.findEntries("/" + packageName, "*.class", true);
+                while (paths != null && paths.hasMoreElements()) {
+                    URL path = paths.nextElement();
+                    String pathString = path.getPath();
+                    String urlString = pathString.substring(pathString.indexOf(packageName));
+                    urls.add(urlString);
+                    log.trace("Added url: {}", urlString);
+                }
+            } catch (Throwable t) {
+                log.warn("Cannot search in bundle: " + bundle + " for classes matching criteria: " + test + " due: "
+                        + t.getMessage() + ". This exception will be ignored.", t);
+            }
+        }
+        return urls;
+    }
+
+}
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiTypeConverter.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiTypeConverter.java
new file mode 100644
index 0000000..6354cf7
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/OsgiTypeConverter.java
@@ -0,0 +1,336 @@
+/*
+ * 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.core.osgi;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.Spliterator;
+import java.util.Spliterators;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+import java.util.stream.StreamSupport;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.LoggingLevel;
+import org.apache.camel.NoTypeConversionAvailableException;
+import org.apache.camel.RuntimeCamelException;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.TypeConverterExists;
+import org.apache.camel.TypeConverters;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.impl.converter.DefaultTypeConverter;
+import org.apache.camel.impl.engine.DefaultPackageScanClassResolver;
+import org.apache.camel.spi.FactoryFinder;
+import org.apache.camel.spi.Injector;
+import org.apache.camel.spi.PackageScanClassResolver;
+import org.apache.camel.spi.TypeConverterLoader;
+import org.apache.camel.spi.TypeConverterRegistry;
+import org.apache.camel.support.SimpleTypeConverter;
+import org.apache.camel.support.service.ServiceHelper;
+import org.apache.camel.support.service.ServiceSupport;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.util.tracker.ServiceTracker;
+import org.osgi.util.tracker.ServiceTrackerCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class OsgiTypeConverter extends ServiceSupport implements TypeConverter, TypeConverterRegistry,
+    ServiceTrackerCustomizer<TypeConverterLoader, Object> {
+    private static final Logger LOG = LoggerFactory.getLogger(OsgiTypeConverter.class);
+
+    private final BundleContext bundleContext;
+    private CamelContext camelContext;
+    private final Injector injector;
+    private final FactoryFinder factoryFinder;
+    private final ServiceTracker<TypeConverterLoader, Object> tracker;
+    private volatile DefaultTypeConverter delegate;
+
+    public OsgiTypeConverter(BundleContext bundleContext, CamelContext camelContext, Injector injector, FactoryFinder factoryFinder) {
+        this.bundleContext = bundleContext;
+        this.camelContext = camelContext;
+        this.injector = injector;
+        this.factoryFinder = factoryFinder;
+        this.tracker = new ServiceTracker<>(bundleContext, TypeConverterLoader.class.getName(), this);
+    }
+
+    @Override
+    public Object addingService(ServiceReference<TypeConverterLoader> serviceReference) {
+        LOG.trace("AddingService: {}, Bundle: {}", serviceReference, serviceReference.getBundle());        
+        TypeConverterLoader loader = bundleContext.getService(serviceReference);
+        try {
+            LOG.debug("loading type converter from bundle: {}", serviceReference.getBundle().getSymbolicName());
+            if (delegate != null) {
+                ServiceHelper.startService(this.delegate);
+                loader.load(delegate);
+            }
+        } catch (Throwable t) {
+            throw new RuntimeCamelException("Error loading type converters from service: " + serviceReference + " due: " + t.getMessage(), t);
+        }
+       
+        return loader;
+    }
+
+    @Override
+    public void modifiedService(ServiceReference<TypeConverterLoader> serviceReference, Object o) {
+    }
+
+    @Override
+    public void removedService(ServiceReference<TypeConverterLoader> serviceReference, Object o) {
+        LOG.trace("RemovedService: {}, Bundle: {}", serviceReference, serviceReference.getBundle());  
+        try {
+            ServiceHelper.stopService(this.delegate);
+        } catch (Exception e) {
+            // ignore
+            LOG.debug("Error stopping service due: " + e.getMessage() + ". This exception will be ignored.", e);
+        }
+        // It can force camel to reload the type converter again
+        this.delegate = null;
+    }
+
+    @Override
+    protected void doStart() throws Exception {
+        this.tracker.open();
+    }
+
+    @Override
+    protected void doStop() throws Exception {
+        this.tracker.close();
+        ServiceHelper.stopService(this.delegate);
+        this.delegate = null;
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return camelContext;
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        this.camelContext = camelContext;
+    }
+
+    @Override
+    public boolean allowNull() {
+        return getDelegate().allowNull();
+    }
+
+    @Override
+    public <T> T convertTo(Class<T> type, Object value) {
+        return getDelegate().convertTo(type, value);
+    }
+
+    @Override
+    public <T> T convertTo(Class<T> type, Exchange exchange, Object value) {
+        return getDelegate().convertTo(type, exchange, value);
+    }
+
+    @Override
+    public <T> T mandatoryConvertTo(Class<T> type, Object value) throws NoTypeConversionAvailableException {
+        return getDelegate().mandatoryConvertTo(type, value);
+    }
+
+    @Override
+    public <T> T mandatoryConvertTo(Class<T> type, Exchange exchange, Object value) throws NoTypeConversionAvailableException {
+        return getDelegate().mandatoryConvertTo(type, exchange, value);
+    }
+
+    @Override
+    public <T> T tryConvertTo(Class<T> type, Exchange exchange, Object value) {
+        return getDelegate().tryConvertTo(type, exchange, value);
+    }
+
+    @Override
+    public <T> T tryConvertTo(Class<T> type, Object value) {
+        return getDelegate().tryConvertTo(type, value);
+    }
+
+    @Override
+    public void addTypeConverter(Class<?> toType, Class<?> fromType, TypeConverter typeConverter) {
+        getDelegate().addTypeConverter(toType, fromType, typeConverter);
+    }
+
+    @Override
+    public void addTypeConverters(TypeConverters typeConverters) {
+        getDelegate().addTypeConverters(typeConverters);
+    }
+
+    @Override
+    public boolean removeTypeConverter(Class<?> toType, Class<?> fromType) {
+        return getDelegate().removeTypeConverter(toType, fromType);
+    }
+
+    @Override
+    public void addFallbackTypeConverter(TypeConverter typeConverter, boolean canPromote) {
+        getDelegate().addFallbackTypeConverter(typeConverter, canPromote);
+    }
+
+    @Override
+    public TypeConverter lookup(Class<?> toType, Class<?> fromType) {
+        return getDelegate().lookup(toType, fromType);
+    }
+
+    @Override
+    public List<Class<?>[]> listAllTypeConvertersFromTo() {
+        return getDelegate().listAllTypeConvertersFromTo();
+    }
+
+    @Override
+    public void setInjector(Injector injector) {
+        getDelegate().setInjector(injector);
+    }
+
+    @Override
+    public Injector getInjector() {
+        return getDelegate().getInjector();
+    }
+
+    @Override
+    public Statistics getStatistics() {
+        return getDelegate().getStatistics();
+    }
+
+    @Override
+    public int size() {
+        return getDelegate().size();
+    }
+
+    @Override
+    public LoggingLevel getTypeConverterExistsLoggingLevel() {
+        return getDelegate().getTypeConverterExistsLoggingLevel();
+    }
+
+    @Override
+    public void setTypeConverterExistsLoggingLevel(LoggingLevel loggingLevel) {
+        getDelegate().setTypeConverterExistsLoggingLevel(loggingLevel);
+    }
+
+    @Override
+    public TypeConverterExists getTypeConverterExists() {
+        return getDelegate().getTypeConverterExists();
+    }
+
+    @Override
+    public void setTypeConverterExists(TypeConverterExists typeConverterExists) {
+        getDelegate().setTypeConverterExists(typeConverterExists);
+    }
+
+    public synchronized DefaultTypeConverter getDelegate() {
+        if (delegate == null) {
+            delegate = createRegistry();
+        }
+        return delegate;
+    }
+
+    protected DefaultTypeConverter createRegistry() {
+        // base the osgi type converter on the default type converter
+        DefaultTypeConverter answer = new OsgiDefaultTypeConverter(new DefaultPackageScanClassResolver() {
+            @Override
+            public Set<ClassLoader> getClassLoaders() {
+                // we only need classloaders for loading core TypeConverterLoaders
+                return new HashSet<>(Arrays.asList(
+                        DefaultTypeConverter.class.getClassLoader(),
+                        DefaultCamelContext.class.getClassLoader()));
+            }
+        }, injector, factoryFinder, false);
+
+        // inject CamelContext
+        answer.setCamelContext(camelContext);
+
+
+        try {
+            // init before loading core converters
+            answer.init();
+            // only load the core type converters, as OSGi activator will keep track on bundles
+            // being installed/uninstalled and load type converters as part of that process
+            answer.loadCoreAndFastTypeConverters();
+        } catch (Exception e) {
+            throw new RuntimeCamelException("Error loading CoreTypeConverter due: " + e.getMessage(), e);
+        }
+
+        // Load the type converters the tracker has been tracking
+        // Here we need to use the ServiceReference to check the ranking
+        ServiceReference<TypeConverterLoader>[] serviceReferences = this.tracker.getServiceReferences();
+        if (serviceReferences != null) {
+            ArrayList<ServiceReference<TypeConverterLoader>> servicesList = 
+                new ArrayList<>(Arrays.asList(serviceReferences));
+            // Just make sure we install the high ranking fallback converter at last
+            Collections.sort(servicesList);
+            for (ServiceReference<TypeConverterLoader> sr : servicesList) {
+                try {
+                    LOG.debug("loading type converter from bundle: {}", sr.getBundle().getSymbolicName());
+                    ((TypeConverterLoader)this.tracker.getService(sr)).load(answer);
+                } catch (Throwable t) {
+                    throw new RuntimeCamelException("Error loading type converters from service: " + sr + " due: " + t.getMessage(), t);
+                }
+            }
+        }
+
+        LOG.trace("Created TypeConverter: {}", answer);
+        return answer;
+    }
+
+    public static <T> Stream<T> enumerationAsStream(Enumeration<T> e) {
+        return StreamSupport.stream(
+                Spliterators.spliteratorUnknownSize(
+                        new Iterator<T>() {
+                            public T next() {
+                                return e.nextElement();
+                            }
+                            public boolean hasNext() {
+                                return e.hasMoreElements();
+                            }
+                            public void forEachRemaining(Consumer<? super T> action) {
+                                while (e.hasMoreElements()) {
+                                    action.accept(e.nextElement());
+                                }
+                            }
+                        },
+                        Spliterator.ORDERED), false);
+    }
+
+    private class OsgiDefaultTypeConverter extends DefaultTypeConverter {
+
+        public OsgiDefaultTypeConverter(PackageScanClassResolver resolver, Injector injector, FactoryFinder factoryFinder, boolean loadTypeConverters) {
+            super(resolver, injector, factoryFinder, loadTypeConverters);
+        }
+
+        @Override
+        public void addTypeConverter(Class<?> toType, Class<?> fromType, TypeConverter typeConverter) {
+            // favour keeping the converter that was loaded via TypeConverterLoader META-INF file
+            // as OSGi loads these first and then gets triggered again later when there is both a META-INF/TypeConverter and META-INF/TypeConverterLoaded file
+            // for the same set of type converters and we get duplicates (so this is a way of filtering out duplicates)
+            TypeConverter converter = typeMappings.get(toType, fromType);
+            if (converter != null && converter != typeConverter) {
+                // the converter is already there which we want to keep (optimized via SimpleTypeConverter)
+                if (converter instanceof SimpleTypeConverter) {
+                    // okay keep this one
+                    return;
+                }
+            }
+            super.addTypeConverter(toType, fromType, typeConverter);
+        }
+    }
+
+}
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/impl/Activator.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/impl/Activator.java
new file mode 100644
index 0000000..6443411
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/impl/Activator.java
@@ -0,0 +1,728 @@
+/*
+ * 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.core.osgi.impl;
+
+import java.io.BufferedInputStream;
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Dictionary;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.concurrent.ConcurrentHashMap;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Component;
+import org.apache.camel.Converter;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.TypeConverterLoaderException;
+import org.apache.camel.impl.converter.AnnotationTypeConverterLoader;
+import org.apache.camel.impl.scan.AnnotatedWithPackageScanFilter;
+import org.apache.camel.model.DataFormatDefinition;
+import org.apache.camel.spi.ComponentResolver;
+import org.apache.camel.spi.ConfigurerResolver;
+import org.apache.camel.spi.DataFormat;
+import org.apache.camel.spi.DataFormatResolver;
+import org.apache.camel.spi.GeneratedPropertyConfigurer;
+import org.apache.camel.spi.Injector;
+import org.apache.camel.spi.Language;
+import org.apache.camel.spi.LanguageResolver;
+import org.apache.camel.spi.PackageScanFilter;
+import org.apache.camel.spi.TypeConverterLoader;
+import org.apache.camel.spi.TypeConverterRegistry;
+import org.apache.camel.util.IOHelper;
+import org.apache.camel.util.ObjectHelper;
+import org.apache.camel.util.StringHelper;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.BundleEvent;
+import org.osgi.framework.Constants;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.framework.wiring.BundleCapability;
+import org.osgi.framework.wiring.BundleWire;
+import org.osgi.framework.wiring.BundleWiring;
+import org.osgi.util.tracker.BundleTracker;
+import org.osgi.util.tracker.BundleTrackerCustomizer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import static org.osgi.framework.wiring.BundleRevision.PACKAGE_NAMESPACE;
+
+public class Activator implements BundleActivator, BundleTrackerCustomizer<Object> {
+
+    public static final String META_INF_CONFIGURER = "META-INF/services/org/apache/camel/configurer/";
+    public static final String META_INF_COMPONENT = "META-INF/services/org/apache/camel/component/";
+    public static final String META_INF_LANGUAGE = "META-INF/services/org/apache/camel/language/";
+    public static final String META_INF_LANGUAGE_RESOLVER = "META-INF/services/org/apache/camel/language/resolver/";
+    public static final String META_INF_DATAFORMAT = "META-INF/services/org/apache/camel/dataformat/";
+    public static final String META_INF_TYPE_CONVERTER = "META-INF/services/org/apache/camel/TypeConverter";
+    public static final String META_INF_TYPE_CONVERTER_LOADER = "META-INF/services/org/apache/camel/TypeConverterLoader";
+    public static final String META_INF_FALLBACK_TYPE_CONVERTER = "META-INF/services/org/apache/camel/FallbackTypeConverter";
+    public static final String EXTENDER_NAMESPACE = "osgi.extender";
+    public static final String CAMEL_EXTENDER = "org.apache.camel";
+
+    private static final Logger LOG = LoggerFactory.getLogger(Activator.class);
+
+    private BundleTracker<?> tracker;
+    private final Map<Long, List<BaseService>> resolvers = new ConcurrentHashMap<>();
+    private long bundleId;
+    
+    // Map from package name to the capability we export for this package
+    private final Map<String, BundleCapability> packageCapabilities = new HashMap<>();
+
+    @Override
+    public void start(BundleContext context) throws Exception {
+        LOG.info("Camel activator starting");
+        cachePackageCapabilities(context);
+        bundleId = context.getBundle().getBundleId();
+        BundleContext systemBundleContext = context.getBundle(0).getBundleContext();
+        tracker = new BundleTracker<>(systemBundleContext, Bundle.ACTIVE, this);
+        tracker.open();
+        LOG.info("Camel activator started");
+    }
+
+    @Override
+    public void stop(BundleContext context) throws Exception {
+        LOG.info("Camel activator stopping");
+        tracker.close();
+        packageCapabilities.clear();
+        LOG.info("Camel activator stopped");
+    }
+    
+    /**
+     * Caches the package capabilities that are needed for a set of interface classes
+     */
+    private void cachePackageCapabilities(BundleContext context) {
+        BundleWiring ourWiring = context.getBundle().adapt(BundleWiring.class);
+        List<BundleCapability> ourExports = ourWiring.getCapabilities(PACKAGE_NAMESPACE);
+        for (BundleCapability ourExport : ourExports) {
+            String ourPkgName = (String) ourExport.getAttributes().get(PACKAGE_NAMESPACE);
+            packageCapabilities.put(ourPkgName, ourExport);
+        }
+        for (BundleWire w : ourWiring.getRequiredWires(PACKAGE_NAMESPACE)) {
+            BundleCapability cap = w.getCapability();
+            String ourPkgName = (String) cap.getAttributes().get(PACKAGE_NAMESPACE);
+            packageCapabilities.put(ourPkgName, cap);
+        }
+    }
+
+    @Override
+    public Object addingBundle(Bundle bundle, BundleEvent event) {
+        LOG.debug("Bundle started: {}", bundle.getSymbolicName());
+        if (extenderCapabilityWired(bundle)) {
+            List<BaseService> r = new ArrayList<>();
+            registerConfigurers(bundle, r);
+            registerComponents(bundle, r);
+            registerLanguages(bundle, r);
+            registerDataFormats(bundle, r);
+            registerTypeConverterLoader(bundle, r);
+            for (BaseService service : r) {
+                service.register();
+            }
+            resolvers.put(bundle.getBundleId(), r);
+        }
+
+        return bundle;
+    }
+
+    private boolean extenderCapabilityWired(Bundle bundle) {
+        BundleWiring wiring = bundle.adapt(BundleWiring.class);
+        if (wiring == null) {
+            return true;
+        }
+        List<BundleWire> requiredWires = wiring.getRequiredWires(EXTENDER_NAMESPACE);
+        for (BundleWire requiredWire : requiredWires) {
+            if (CAMEL_EXTENDER.equals(requiredWire.getCapability().getAttributes().get(EXTENDER_NAMESPACE))) {
+                if (this.bundleId == requiredWire.getProviderWiring().getBundle().getBundleId()) {
+                    LOG.debug("Camel extender requirement of bundle {} correctly wired to this implementation", bundle.getBundleId());
+                    return true;
+                } else {
+                    LOG.info("Not processing bundle {} as it requires a camel extender but is not wired to the this implementation", bundle.getBundleId());
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    @Override
+    public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) {
+    }
+
+    @Override
+    public void removedBundle(Bundle bundle, BundleEvent event, Object object) {
+        LOG.debug("Bundle stopped: {}", bundle.getSymbolicName());
+        List<BaseService> r = resolvers.remove(bundle.getBundleId());
+        if (r != null) {
+            for (BaseService service : r) {
+                service.unregister();
+            }
+        }
+    }
+
+    protected void registerConfigurers(Bundle bundle, List<BaseService> resolvers) {
+        if (canSee(bundle, GeneratedPropertyConfigurer.class)) {
+            Map<String, String> configurers = new HashMap<>();
+            for (Enumeration<?> e = bundle.getEntryPaths(META_INF_CONFIGURER); e != null && e.hasMoreElements();) {
+                String path = (String) e.nextElement();
+                LOG.debug("Found configureer: {} in bundle {}", path, bundle.getSymbolicName());
+                String name = path.substring(path.lastIndexOf("/") + 1);
+                configurers.put(name, path);
+            }
+            if (!configurers.isEmpty()) {
+                resolvers.add(new BundleConfigurerResolver(bundle, configurers));
+            }
+        }
+    }
+
+    protected void registerComponents(Bundle bundle, List<BaseService> resolvers) {
+        if (canSee(bundle, Component.class)) {
+            Map<String, String> components = new HashMap<>();
+            for (Enumeration<?> e = bundle.getEntryPaths(META_INF_COMPONENT); e != null && e.hasMoreElements();) {
+                String path = (String) e.nextElement();
+                LOG.debug("Found entry: {} in bundle {}", path, bundle.getSymbolicName());
+                String name = path.substring(path.lastIndexOf("/") + 1);
+                components.put(name, path);
+            }
+            if (!components.isEmpty()) {
+                resolvers.add(new BundleComponentResolver(bundle, components));
+            }
+        }
+    }
+
+    protected void registerLanguages(Bundle bundle, List<BaseService> resolvers) {
+        if (canSee(bundle, Language.class)) {
+            Map<String, String> languages = new HashMap<>();
+            for (Enumeration<?> e = bundle.getEntryPaths(META_INF_LANGUAGE); e != null && e.hasMoreElements();) {
+                String path = (String) e.nextElement();
+                LOG.debug("Found entry: {} in bundle {}", path, bundle.getSymbolicName());
+                String name = path.substring(path.lastIndexOf("/") + 1);
+                languages.put(name, path);
+            }
+            if (!languages.isEmpty()) {
+                resolvers.add(new BundleLanguageResolver(bundle, languages));
+            }
+            for (Enumeration<?> e = bundle.getEntryPaths(META_INF_LANGUAGE_RESOLVER); e != null && e.hasMoreElements();) {
+                String path = (String) e.nextElement();
+                LOG.debug("Found entry: {} in bundle {}", path, bundle.getSymbolicName());
+                String name = path.substring(path.lastIndexOf("/") + 1);
+                resolvers.add(new BundleMetaLanguageResolver(bundle, name, path));
+            }
+        }
+    }
+
+    protected void registerDataFormats(Bundle bundle, List<BaseService> resolvers) {
+        if (canSee(bundle, DataFormat.class)) {
+            Map<String, String> dataformats = new HashMap<>();
+            for (Enumeration<?> e = bundle.getEntryPaths(META_INF_DATAFORMAT); e != null && e.hasMoreElements();) {
+                String path = (String) e.nextElement();
+                LOG.debug("Found entry: {} in bundle {}", path, bundle.getSymbolicName());
+                String name = path.substring(path.lastIndexOf("/") + 1);
+                dataformats.put(name, path);
+            }
+            if (!dataformats.isEmpty()) {
+                resolvers.add(new BundleDataFormatResolver(bundle, dataformats));
+            }
+        }
+    }
+
+    protected void registerTypeConverterLoader(Bundle bundle, List<BaseService> resolvers) {
+        if (canSee(bundle, TypeConverter.class)) {
+            URL url1 = bundle.getEntry(META_INF_TYPE_CONVERTER);
+            URL url2 = bundle.getEntry(META_INF_TYPE_CONVERTER_LOADER);
+            URL url3 = bundle.getEntry(META_INF_FALLBACK_TYPE_CONVERTER);
+            if (url2 != null) {
+                LOG.debug("Found TypeConverterLoader in bundle {}", bundle.getSymbolicName());
+                Set<String> packages = getConverterPackages(bundle.getEntry(META_INF_TYPE_CONVERTER_LOADER));
+
+                if (LOG.isTraceEnabled()) {
+                    LOG.trace("Found {} {} packages: {}", packages.size(), META_INF_TYPE_CONVERTER_LOADER, packages);
+                }
+                for (String pkg : packages) {
+
+                    if (StringHelper.isClassName(pkg)) {
+                        // its a FQN class name so load it directly
+                        LOG.trace("Loading {} class", pkg);
+                        try {
+                            Class<?> clazz = bundle.loadClass(pkg);
+                            BundleTypeConverterLoader bundleTypeConverterLoader =
+                                new BundleTypeConverterLoader(bundle, url3 != null);
+                            bundleTypeConverterLoader.setTypeConverterLoader((TypeConverterLoader)clazz.getDeclaredConstructor().newInstance());
+                            resolvers.add(bundleTypeConverterLoader);
+                            BundleTypeConverterLoader fallBackBundleTypeConverterLoader =
+                                new BundleTypeConverterLoader(bundle, url3 != null);
+                            // the class could be found and loaded so continue to next
+                            resolvers.add(fallBackBundleTypeConverterLoader);
+                            continue;
+                        } catch (Throwable t) {
+                            // Ignore
+                            LOG.trace("Failed to load " + pkg + " class due " + t.getMessage() + ". This exception will be ignored.", t);
+                        }
+                    }
+                }
+                    
+            } else if (url1 != null || url3 != null) {
+                LOG.debug("Found TypeConverter in bundle {}", bundle.getSymbolicName());
+                resolvers.add(new BundleTypeConverterLoader(bundle, url3 != null));
+            }
+        }
+    }
+    
+    /**
+     * Check if bundle can see the given class
+     */
+    protected boolean canSee(Bundle bundle, Class<?> clazz) {
+        if (bundle.getBundleId() == bundleId) {
+            // Need extra handling of camel core as it does not import the api
+            return true;
+        }
+        BundleCapability packageCap = packageCapabilities.get(clazz.getPackage().getName());
+        if (packageCap != null) {
+            BundleWiring wiring = bundle.adapt(BundleWiring.class);
+            List<BundleWire> imports = wiring.getRequiredWires(PACKAGE_NAMESPACE);
+            for (BundleWire importWire : imports) {
+                if (packageCap.equals(importWire.getCapability())) {
+                    return true;
+                }
+            }
+        }
+
+        // it may be running outside real OSGi container such as when unit testing with camel-test-blueprint
+        // then we need to use a different canSee algorithm that works outside real OSGi
+        if (bundle.getBundleId() >= 0) {
+            Bundle root = bundle.getBundleContext().getBundle(0);
+            if (root != null && "org.apache.felix.connect".equals(root.getSymbolicName())) {
+                return checkCompat(bundle, clazz);
+            }
+        }
+
+        return false;
+    }
+
+    /**
+     * Check if bundle can see the given class used by camel-test-blueprint
+     */
+    protected static boolean checkCompat(Bundle bundle, Class<?> clazz) {
+        // Check bundle compatibility
+        try {
+            if (bundle.loadClass(clazz.getName()) != clazz) {
+                return false;
+            }
+        } catch (Throwable t) {
+            return false;
+        }
+        return true;
+    }
+
+    protected static class BundleComponentResolver extends BaseResolver<Component> implements ComponentResolver {
+
+        private final Map<String, String> components;
+
+        public BundleComponentResolver(Bundle bundle, Map<String, String> components) {
+            super(bundle, Component.class);
+            this.components = components;
+        }
+
+        @Override
+        public Component resolveComponent(String name, CamelContext context) throws Exception {
+            return createInstance(name, components.get(name), context);
+        }
+
+        @Override
+        public void register() {
+            doRegister(ComponentResolver.class, "component", components.keySet());
+        }
+    }
+
+    protected static class BundleConfigurerResolver extends BaseResolver<GeneratedPropertyConfigurer> implements ConfigurerResolver {
+
+        private final Map<String, String> configurers;
+
+        public BundleConfigurerResolver(Bundle bundle, Map<String, String> configurers) {
+            super(bundle, GeneratedPropertyConfigurer.class);
+            this.configurers = configurers;
+        }
+
+        @Override
+        public GeneratedPropertyConfigurer resolvePropertyConfigurer(String name, CamelContext context) {
+            return createInstance(name, configurers.get(name), context);
+        }
+
+        @Override
+        public void register() {
+            doRegister(ConfigurerResolver.class, "configurer", configurers.keySet());
+        }
+    }
+
+    protected static class BundleLanguageResolver extends BaseResolver<Language> implements LanguageResolver {
+
+        private final Map<String, String> languages;
+
+        public BundleLanguageResolver(Bundle bundle, Map<String, String> languages) {
+            super(bundle, Language.class);
+            this.languages = languages;
+        }
+
+        @Override
+        public Language resolveLanguage(String name, CamelContext context) {
+            return createInstance(name, languages.get(name), context);
+        }
+
+        @Override
+        public void register() {
+            doRegister(LanguageResolver.class, "language", languages.keySet());
+        }
+    }
+
+    protected static class BundleMetaLanguageResolver extends BaseResolver<LanguageResolver> implements LanguageResolver {
+
+        private final String name;
+        private final String path;
+
+        public BundleMetaLanguageResolver(Bundle bundle, String name, String path) {
+            super(bundle, LanguageResolver.class);
+            this.name = name;
+            this.path = path;
+        }
+
+        @Override
+        public Language resolveLanguage(String name, CamelContext context) {
+            LanguageResolver resolver = createInstance(this.name, path, context);
+            return resolver.resolveLanguage(name, context);
+        }
+
+        @Override
+        public void register() {
+            doRegister(LanguageResolver.class, "resolver", name);
+        }
+    }
+
+    protected static class BundleDataFormatResolver extends BaseResolver<DataFormat> implements DataFormatResolver {
+
+        private final Map<String, String> dataformats;
+
+        public BundleDataFormatResolver(Bundle bundle, Map<String, String> dataformats) {
+            super(bundle, DataFormat.class);
+            this.dataformats = dataformats;
+        }
+
+        @Override
+        public DataFormat resolveDataFormat(String name, CamelContext context) {
+            DataFormat dataFormat = createInstance(name, dataformats.get(name), context);
+            if (dataFormat == null) {
+                dataFormat = createDataFormat(name, context);
+            }
+
+            return dataFormat;
+        }
+
+        @Override
+        public DataFormat createDataFormat(String name, CamelContext context) {
+            return createInstance(name, dataformats.get(name), context);
+        }
+
+        public DataFormatDefinition resolveDataFormatDefinition(String name, CamelContext context) {
+            return null;
+        }
+
+        @Override
+        public void register() {
+            doRegister(DataFormatResolver.class, "dataformat", dataformats.keySet());
+        }
+    }
+
+    protected static class BundleTypeConverterLoader extends BaseResolver<TypeConverter> implements TypeConverterLoader {
+
+        private TypeConverterLoader loader = new Loader();
+        private final Bundle bundle;
+        private final boolean hasFallbackTypeConverter;
+
+        public BundleTypeConverterLoader(Bundle bundle, boolean hasFallbackTypeConverter) {
+            super(bundle, TypeConverter.class);
+            ObjectHelper.notNull(bundle, "bundle");
+            this.bundle = bundle;
+            this.hasFallbackTypeConverter = hasFallbackTypeConverter;
+        }
+        
+        public void setTypeConverterLoader(TypeConverterLoader typeConverterloader) {
+            this.loader = typeConverterloader;
+        }
+
+        @Override
+        public synchronized void load(TypeConverterRegistry registry) throws TypeConverterLoaderException {
+            // must be synchronized to ensure we don't load type converters concurrently
+            // which cause Camel apps to fails in OSGi thereafter
+            try {
+                loader.load(registry);
+            } catch (Exception e) {
+                throw new TypeConverterLoaderException("Cannot load type converters using OSGi bundle: " + bundle.getBundleId(), e);
+            }
+        }
+
+        @Override
+        public void register() {
+            if (hasFallbackTypeConverter) {
+                // The FallbackTypeConverter should have a higher ranking
+                doRegister(TypeConverterLoader.class, Constants.SERVICE_RANKING, 100);
+            } else {
+                // The default service ranking is Integer(0);
+                doRegister(TypeConverterLoader.class);
+            }
+        }
+
+        class Loader extends AnnotationTypeConverterLoader {
+
+            Loader() {
+                super(null);
+            }
+
+            @Override
+            public void load(TypeConverterRegistry registry) throws TypeConverterLoaderException {
+                PackageScanFilter test = new AnnotatedWithPackageScanFilter(Converter.class, true);
+                Set<Class<?>> classes = new LinkedHashSet<>();
+                Set<String> packages = getConverterPackages(bundle.getEntry(META_INF_TYPE_CONVERTER));
+
+                if (LOG.isTraceEnabled()) {
+                    LOG.trace("Found {} {} packages: {}", packages.size(), META_INF_TYPE_CONVERTER, packages);
+                }
+                // if we only have camel-core on the classpath then we have already pre-loaded all its type converters
+                // but we exposed the "org.apache.camel.core" package in camel-core. This ensures there is at least one
+                // packageName to scan, which triggers the scanning process. That allows us to ensure that we look for
+                // META-INF/services in all the JARs.
+                if (packages.size() == 1 && "org.apache.camel.core".equals(packages.iterator().next())) {
+                    LOG.debug("No additional package names found in classpath for annotated type converters.");
+                    // no additional package names found to load type converters so break out
+                    return;
+                }
+
+                // now filter out org.apache.camel.core as its not needed anymore (it was just a dummy)
+                packages.remove("org.apache.camel.core");
+
+                for (String pkg : packages) {
+
+                    if (StringHelper.isClassName(pkg)) {
+                        // its a FQN class name so load it directly
+                        LOG.trace("Loading {} class", pkg);
+                        try {
+                            Class<?> clazz = bundle.loadClass(pkg);
+                            classes.add(clazz);
+                            // the class could be found and loaded so continue to next
+                            continue;
+                        } catch (Throwable t) {
+                            // Ignore
+                            LOG.trace("Failed to load " + pkg + " class due " + t.getMessage() + ". This exception will be ignored.", t);
+                        }
+                    }
+
+                    // its not a FQN but a package name so scan for classes in the bundle
+                    Enumeration<URL> e = bundle.findEntries("/" + pkg.replace('.', '/'), "*.class", true);
+                    while (e != null && e.hasMoreElements()) {
+                        String path = e.nextElement().getPath();
+                        String externalName = path.substring(path.charAt(0) == '/' ? 1 : 0, path.indexOf('.')).replace('/', '.');
+                        LOG.trace("Loading {} class", externalName);
+                        try {
+                            Class<?> clazz = bundle.loadClass(externalName);
+                            if (test.matches(clazz)) {
+                                classes.add(clazz);
+                            }
+                        } catch (Throwable t) {
+                            // Ignore
+                            LOG.trace("Failed to load " + externalName + " class due " + t.getMessage() + ". This exception will be ignored.", t);
+                        }
+                    }
+                }
+
+                // load the classes into type converter registry
+                LOG.debug("Found {} @Converter classes to load", classes.size());
+                for (Class<?> type : classes) {
+                    if (LOG.isTraceEnabled()) {
+                        LOG.trace("Loading converter class: {}", ObjectHelper.name(type));
+                    }
+                    loadConverterMethods(registry, type);
+                }
+
+                // register fallback converters
+                URL fallbackUrl = bundle.getEntry(META_INF_FALLBACK_TYPE_CONVERTER);
+                if (fallbackUrl != null) {
+                    LOG.debug("Found {} to load the FallbackTypeConverter", META_INF_FALLBACK_TYPE_CONVERTER);
+                    TypeConverter tc = createInstance("FallbackTypeConverter", fallbackUrl, registry.getInjector());
+                    registry.addFallbackTypeConverter(tc, false);
+                }
+
+                // now clear the maps so we do not hold references
+                visitedClasses.clear();
+                visitedURIs.clear();
+            }
+        }
+
+    }
+
+    protected abstract static class BaseResolver<T> extends BaseService {
+
+        private final Class<T> type;
+
+        public BaseResolver(Bundle bundle, Class<T> type) {
+            super(bundle);
+            this.type = type;
+        }
+
+        protected T createInstance(String name, String path, CamelContext context) {
+            if (path == null) {
+                return null;
+            }
+            URL url = bundle.getEntry(path);
+            LOG.trace("The entry {}'s url is {}", name, url);
+            //Setup the TCCL with Camel context application class loader
+            ClassLoader oldClassLoader = Thread.currentThread().getContextClassLoader();
+            try {
+                ClassLoader newClassLoader = context.getApplicationContextClassLoader();
+                if (newClassLoader != null) {
+                    Thread.currentThread().setContextClassLoader(newClassLoader);
+                }
+                T answer = createInstance(name, url, context.getInjector());
+                if (answer != null) {
+                    initBundleContext(answer);
+                }
+                return answer;
+            } finally {
+                Thread.currentThread().setContextClassLoader(oldClassLoader);
+            }
+        }
+
+        private void initBundleContext(T answer) {
+            try {
+                Method method = answer.getClass().getMethod("setBundleContext", BundleContext.class);
+                if (method != null) {
+                    method.invoke(answer, bundle.getBundleContext());
+                }
+            } catch (Exception e) {
+                // ignore
+            }
+        }
+
+        @SuppressWarnings("unchecked")
+        protected T createInstance(String name, URL url, Injector injector) {
+            try {
+                Properties properties = loadProperties(url);
+                String classname = (String) properties.get("class");
+                Class type = bundle.loadClass(classname);
+                if (!this.type.isAssignableFrom(type)) {
+                    throw new IllegalArgumentException("Type is not a " + this.type.getName() + " implementation. Found: " + type.getName());
+                }
+                return (T) injector.newInstance(type, false);
+            } catch (ClassNotFoundException e) {
+                throw new IllegalArgumentException("Invalid URI, no " + this.type.getName() + " registered for scheme : " + name, e);
+            }
+        }
+
+    }
+
+    protected abstract static class BaseService {
+
+        protected final Bundle bundle;
+        private ServiceRegistration<?> reg;
+
+        protected BaseService(Bundle bundle) {
+            this.bundle = bundle;
+        }
+
+        public abstract void register();
+
+        protected void doRegister(Class<?> type, String key, Collection<String> value) {
+            doRegister(type, key, value.toArray(new String[value.size()]));
+        }
+
+        protected void doRegister(Class<?> type, String key, Object value) {
+            Dictionary<String, Object> props = new Hashtable<>();
+            props.put(key, value);
+            doRegister(type, props);
+        }
+
+        protected void doRegister(Class<?> type) {
+            doRegister(type, null);
+        }
+
+        protected void doRegister(Class<?> type, Dictionary<String, ?> props) {
+            reg = bundle.getBundleContext().registerService(type.getName(), this, props);
+        }
+
+        public void unregister() {
+            reg.unregister();
+        }
+    }
+
+    protected static Properties loadProperties(URL url) {
+        Properties properties = new Properties();
+        BufferedInputStream reader = null;
+        try {
+            reader = IOHelper.buffered(url.openStream());
+            properties.load(reader);
+        } catch (IOException e) {
+            throw new RuntimeException(e);
+        } finally {
+            IOHelper.close(reader, "properties", LOG);
+        }
+        return properties;
+    }
+    
+    protected static Set<String> getConverterPackages(URL resource) {
+        Set<String> packages = new LinkedHashSet<>();
+        if (resource != null) {
+            BufferedReader reader = null;
+            try {
+                reader = IOHelper.buffered(new InputStreamReader(resource.openStream()));
+                while (true) {
+                    String line = reader.readLine();
+                    if (line == null) {
+                        break;
+                    }
+                    line = line.trim();
+                    if (line.startsWith("#") || line.length() == 0) {
+                        continue;
+                    }
+                    StringTokenizer iter = new StringTokenizer(line, ",");
+                    while (iter.hasMoreTokens()) {
+                        String name = iter.nextToken().trim();
+                        if (name.length() > 0) {
+                            packages.add(name);
+                        }
+                    }
+                }
+            } catch (Exception ignore) {
+                // Do nothing here
+            } finally {
+                IOHelper.close(reader, null, LOG);
+            }
+        }
+        return packages;
+    }
+
+}
+
+
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/impl/package.html b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/impl/package.html
new file mode 100644
index 0000000..aef59c0
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/impl/package.html
@@ -0,0 +1,27 @@
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<html>
+<head>
+</head>
+<body>
+
+Camel OSGi Activator.
+
+</body>
+</html>
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/utils/BundleContextUtils.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/utils/BundleContextUtils.java
new file mode 100644
index 0000000..781c98a
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/utils/BundleContextUtils.java
@@ -0,0 +1,67 @@
+/*
+ * 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.core.osgi.utils;
+
+import java.lang.reflect.Method;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+
+/**
+ * Helper class
+ */
+public final class BundleContextUtils {
+
+    private BundleContextUtils() {
+    }
+
+    /**
+     * Retrieve the BundleContext that the given class has been loaded from.
+     *
+     * @param clazz the class to find the bundle context from
+     * @return the bundle context or <code>null</code> if it can't be found
+     */
+    public static BundleContext getBundleContext(Class<?> clazz) {
+
+        // Ideally we should use FrameworkUtil.getBundle(clazz).getBundleContext()
+        // but that does not exist in OSGi 4.1, so until we upgrade, we keep that one
+
+        try {
+            ClassLoader cl = clazz.getClassLoader();
+            Class<?> clClazz = cl.getClass();
+            Method mth = null;
+            while (clClazz != null) {
+                try {
+                    mth = clClazz.getDeclaredMethod("getBundle");
+                    break;
+                } catch (NoSuchMethodException e) {
+                    // Ignore
+                }
+                clClazz = clClazz.getSuperclass();
+            }
+            if (mth != null) {
+                mth.setAccessible(true);
+                return ((Bundle) mth.invoke(cl)).getBundleContext();
+            }
+        } catch (Throwable t) {
+            // Ignore
+        }
+
+        return null;
+    }
+
+}
diff --git a/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/utils/BundleDelegatingClassLoader.java b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/utils/BundleDelegatingClassLoader.java
new file mode 100644
index 0000000..f0da831
--- /dev/null
+++ b/core/camel-core-osgi/src/main/java/org/apache/camel/core/osgi/utils/BundleDelegatingClassLoader.java
@@ -0,0 +1,99 @@
+/*
+ * 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.core.osgi.utils;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Enumeration;
+
+import org.osgi.framework.Bundle;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A ClassLoader delegating to a given OSGi bundle.
+ *
+ */
+public class BundleDelegatingClassLoader extends ClassLoader {
+    private static final Logger LOG = LoggerFactory.getLogger(BundleDelegatingClassLoader.class);
+    private final Bundle bundle;
+    private final ClassLoader classLoader;
+
+    public BundleDelegatingClassLoader(Bundle bundle) {
+        this(bundle, null);
+    }
+
+    public BundleDelegatingClassLoader(Bundle bundle, ClassLoader classLoader) {
+        this.bundle = bundle;
+        this.classLoader = classLoader;
+    }
+
+    @Override
+    protected Class<?> findClass(String name) throws ClassNotFoundException {
+        LOG.trace("FindClass: {}", name);
+        return bundle.loadClass(name);
+    }
+
+    @Override
+    protected URL findResource(String name) {
+        LOG.trace("FindResource: {}", name);
+        URL resource = bundle.getResource(name);
+        if (classLoader != null && resource == null) {
+            resource = classLoader.getResource(name);
+        }
+        return resource;
+    }
+
+    @Override
+    @SuppressWarnings({"unchecked", "rawtypes"})
+    protected Enumeration findResources(String name) throws IOException {
+        LOG.trace("FindResource: {}", name);
+        return bundle.getResources(name);
+    }
+
+    @Override
+    protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+        LOG.trace("LoadClass: {}, resolve: {}", name, resolve);
+        Class<?> clazz;
+        try {
+            clazz = findClass(name);
+        } catch (ClassNotFoundException cnfe) {
+            if (classLoader != null) {
+                try {
+                    clazz = classLoader.loadClass(name);
+                } catch (ClassNotFoundException e) {
+                    throw new ClassNotFoundException(name + " from bundle " + bundle.getBundleId() + " (" + bundle.getSymbolicName() + ")", cnfe);
+                }
+            } else {
+                throw new ClassNotFoundException(name + " from bundle " + bundle.getBundleId() + " (" + bundle.getSymbolicName() + ")", cnfe);
+            }
+        }
+        if (resolve) {
+            resolveClass(clazz);
+        }
+        return clazz;
+    }
+
+    public Bundle getBundle() {
+        return bundle;
+    }
+
+    @Override
+    public String toString() {
+        return String.format("BundleDelegatingClassLoader(%s)", bundle);
+    }
+}
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/CamelMockBundle.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/CamelMockBundle.java
new file mode 100644
index 0000000..f0cf522
--- /dev/null
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/CamelMockBundle.java
@@ -0,0 +1,132 @@
+/*
+ * 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.core.osgi;
+
+import java.net.URL;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.camel.util.CastUtils;
+import org.osgi.framework.Version;
+import org.springframework.osgi.mock.MockBundle;
+
+/**
+ *  The mock bundle will make up a normal camel-components bundle
+ */
+public class CamelMockBundle extends MockBundle {
+    
+    public static final String META_INF_COMPONENT = "META-INF/services/org/apache/camel/component/";
+    public static final String META_INF_LANGUAGE = "META-INF/services/org/apache/camel/language/";
+    public static final String META_INF_LANGUAGE_RESOLVER = "META-INF/services/org/apache/camel/language/resolver/";
+    public static final String META_INF_DATAFORMAT = "META-INF/services/org/apache/camel/dataformat/";
+
+    private static class ListEnumeration<E> implements Enumeration<E> {
+        private final List<E> list;                    
+        private int index;
+        
+        ListEnumeration(List<E> list) {
+            this.list = list;
+        }
+
+        @Override
+        public boolean hasMoreElements() {
+            return list != null && index < list.size();
+        }
+
+        @Override
+        public E nextElement() {
+            E result = null;
+            if (list != null) { 
+                result =  list.get(index);
+                index++;
+            } 
+            return result;         
+        }
+        
+    }
+    
+    public CamelMockBundle() {
+        setClassLoader(getClass().getClassLoader());
+    }
+
+    private Enumeration<String> getListEnumeration(String prefix, String entrys[]) {
+        List<String> list = new ArrayList<>();
+        for (String entry : entrys) {            
+            list.add(prefix + entry);
+        }
+        return new ListEnumeration<>(list);
+    }
+
+    @Override
+    public Enumeration<String> getEntryPaths(String path) {
+        Enumeration<String> result = null;
+        if (META_INF_COMPONENT.equals(path)) {
+            String[] entries = new String[] {"timer_test", "file_test"};
+            result = getListEnumeration(META_INF_COMPONENT, entries);
+        }
+        if (META_INF_LANGUAGE.equals(path)) {
+            String[] entries = new String[] {"bean_test", "file_test"};
+            result = getListEnumeration(META_INF_LANGUAGE, entries);
+        }
+        if (META_INF_LANGUAGE_RESOLVER.equals(path)) {
+            String[] entries = new String[] {"default"};
+            result = getListEnumeration(META_INF_LANGUAGE_RESOLVER, entries);
+        }
+
+        return result;
+    }
+    
+    @Override
+    public Enumeration<URL> findEntries(String path, String filePattern, boolean recurse) {
+        if (path.equals("/org/apache/camel/core/osgi/test") && filePattern.equals("*.class")) {
+            List<URL> urls = new ArrayList<>();
+            URL url = getClass().getClassLoader().getResource("org/apache/camel/core/osgi/test/MyTypeConverter.class");
+            urls.add(url);
+            url = getClass().getClassLoader().getResource("org/apache/camel/core/osgi/test/MyRouteBuilder.class");
+            urls.add(url);
+            return new ListEnumeration<>(urls);
+        } else {
+            return CastUtils.cast(super.findEntries(path, filePattern, recurse));
+        }
+    }
+
+    @Override
+    public Map<X509Certificate, List<X509Certificate>> getSignerCertificates(int signersType) {
+        return null;
+    }
+
+    @Override
+    public Version getVersion() {
+        return Version.parseVersion("1.0.0");
+    }
+
+    @Override
+    public Class<?> loadClass(String name) throws ClassNotFoundException {
+        if (isLoadableClass(name)) {
+            return super.loadClass(name);
+        } else {
+            throw new ClassNotFoundException(name);
+        }
+    }
+
+    protected boolean isLoadableClass(String name) {
+        return !name.startsWith("org.apache.camel.core.osgi.other");
+    }
+}
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/CamelMockBundleContext.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/CamelMockBundleContext.java
new file mode 100644
index 0000000..a1c61fa
--- /dev/null
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/CamelMockBundleContext.java
@@ -0,0 +1,139 @@
+/*
+ * 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.core.osgi;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Component;
+import org.apache.camel.component.file.FileComponent;
+import org.apache.camel.core.osgi.test.MyService;
+import org.apache.camel.language.simple.SimpleLanguage;
+import org.apache.camel.spi.ComponentResolver;
+import org.apache.camel.spi.Language;
+import org.apache.camel.spi.LanguageResolver;
+import org.osgi.framework.Bundle;
+import org.osgi.framework.Constants;
+import org.osgi.framework.InvalidSyntaxException;
+import org.osgi.framework.ServiceReference;
+import org.springframework.osgi.mock.MockBundleContext;
+import org.springframework.osgi.mock.MockServiceReference;
+
+public class CamelMockBundleContext extends MockBundleContext {
+    
+    public static final String SERVICE_PID_PREFIX = "test.";
+
+    public CamelMockBundleContext(Bundle bundle) {
+        super(bundle);
+    }
+
+    @Override
+    public Object getService(@SuppressWarnings("rawtypes") ServiceReference reference) {
+        String[] classNames = (String[]) reference.getProperty(Constants.OBJECTCLASS);        
+        String classNames0 = classNames != null ? classNames[0] : null;
+        String pid = (String)reference.getProperty(Constants.SERVICE_PID);
+        if (classNames0 != null && classNames0.equals("org.apache.camel.core.osgi.test.MyService")) {
+            return new MyService();
+        } else if (pid != null && pid.equals(SERVICE_PID_PREFIX + "org.apache.camel.core.osgi.test.MyService")) {
+            return new MyService();
+        } else if (classNames0 != null && classNames0.equals(ComponentResolver.class.getName())) {
+            return new ComponentResolver() {
+                public Component resolveComponent(String name, CamelContext context) throws Exception {
+                    if (name.equals("file_test")) {
+                        return new FileComponent();
+                    }
+                    return null;
+                }
+            };
+        } else if (classNames0 != null && classNames0.equals(LanguageResolver.class.getName())) {
+            return new LanguageResolver() {
+                public Language resolveLanguage(String name, CamelContext context) {
+                    if (name.equals("simple")) {
+                        return new SimpleLanguage();
+                    }
+                    return null;
+                }
+            };
+        } else {
+            return null;
+        }    
+    }
+
+    @Override
+    public ServiceReference getServiceReference(String clazz) {
+        // lookup Java class if clazz contains dot (.) symbol
+        if (clazz.contains(".")) {
+            try {
+                Class.forName(clazz);
+                return super.getServiceReference(clazz);
+            } catch (ClassNotFoundException ex) {
+                return null; // class not found so no service reference is returned
+            }
+        } else {
+            return super.getServiceReference(clazz);
+        }
+    }
+    
+    private static void addServicePID(ServiceReference[] srs, String filter) {
+        for (ServiceReference sr : srs) {
+            if (sr instanceof MockServiceReference) {
+                Dictionary properties = new Hashtable();
+                String pid = filter.replace("(" + Constants.SERVICE_PID + "=", "").replace(")", "");
+                properties.put(Constants.SERVICE_PID, pid);
+                for (String key : sr.getPropertyKeys()) {
+                    if (properties.get(key) == null) {
+                        properties.put(key, sr.getProperty(key));
+                    }
+                }
+                ((MockServiceReference)sr).setProperties(properties);
+            }
+        }
+    }
+    
+    @Override
+    @SuppressWarnings("rawtypes")
+    public ServiceReference[] getServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
+        // just simulate when the bundle context doesn't have right service reference
+        if (filter != null && filter.indexOf("name=test") > 0) {
+            return null;
+        } else {
+            ServiceReference[] srs = super.getServiceReferences(clazz, filter);
+            
+            // set service.pid property by filter
+            if (filter != null && filter.indexOf(Constants.SERVICE_PID + "=") > 0) {
+                addServicePID(srs, filter);
+            }
+            return srs;
+        }
+    }
+   
+    @Override
+    @SuppressWarnings({"rawtypes", "unchecked"})
+    public ServiceReference[] getAllServiceReferences(String clazz, String filter) throws InvalidSyntaxException {
+        // just simulate when the bundle context doesn't have right service reference
+        if (filter != null && filter.indexOf("name=test") > 0) {
+            return null;
+        }
+        MockServiceReference reference = new MockServiceReference(getBundle(), new String[] {clazz});
+        // setup the name property with the class name
+        Dictionary properties = new Hashtable();
+        properties.put("name", clazz);
+        reference.setProperties(properties);
+        return new ServiceReference[] {reference};
+    }
+}
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/CamelMockLanguageResolver.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/CamelMockLanguageResolver.java
new file mode 100644
index 0000000..6b5e04b
--- /dev/null
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/CamelMockLanguageResolver.java
@@ -0,0 +1,33 @@
+/*
+ * 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.core.osgi;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.impl.engine.DefaultLanguageResolver;
+import org.apache.camel.spi.Language;
+import org.apache.camel.spi.LanguageResolver;
+
+public class CamelMockLanguageResolver implements LanguageResolver {
+    // Delegate to the DefaultLanguageResolver
+    private LanguageResolver delegate = new DefaultLanguageResolver();
+
+    @Override
+    public Language resolveLanguage(String name, CamelContext context) {
+        return delegate.resolveLanguage(name, context);
+    }
+
+}
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/CamelOsgiTestSupport.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/CamelOsgiTestSupport.java
new file mode 100644
index 0000000..3fba2c5
--- /dev/null
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/CamelOsgiTestSupport.java
@@ -0,0 +1,53 @@
+/*
+ * 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.core.osgi;
+
+import org.apache.camel.spi.ClassResolver;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.osgi.framework.BundleContext;
+import org.springframework.osgi.mock.MockBundle;
+import org.springframework.osgi.mock.MockBundleContext;
+
+public class CamelOsgiTestSupport extends Assert {
+    private MockBundle bundle = new CamelMockBundle();
+    private MockBundleContext bundleContext = new CamelMockBundleContext(bundle);
+    private OsgiPackageScanClassResolver packageScanClassResolver = new OsgiPackageScanClassResolver(bundleContext);
+    private ClassResolver classResolver = new OsgiClassResolver(null, bundleContext);
+
+    @Before
+    public void setUp() throws Exception {        
+        bundleContext.setBundle(bundle);
+    }
+    
+    @After    
+    public void tearDown() throws Exception {
+    }
+    
+    public BundleContext getBundleContext() {
+        return bundleContext;
+    }
+
+    public OsgiPackageScanClassResolver getPackageScanClassResolver() {
+        return packageScanClassResolver;
+    }
+    
+    public ClassResolver getClassResolver() {
+        return classResolver;
+    }
+}
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiClassResolverTest.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiClassResolverTest.java
new file mode 100644
index 0000000..928ae79
--- /dev/null
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiClassResolverTest.java
@@ -0,0 +1,40 @@
+/*
+ * 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.core.osgi;
+
+import java.io.InputStream;
+
+import org.apache.camel.spi.ClassResolver;
+import org.junit.Test;
+
+public class OsgiClassResolverTest extends CamelOsgiTestSupport {
+    
+    @Test
+    public void testResolveClass() {
+        ClassResolver classResolver = getClassResolver();
+        Class<?> routeBuilder = classResolver.resolveClass("org.apache.camel.core.osgi.test.MyRouteBuilder");
+        assertNotNull("The class of routeBuilder should not be null.", routeBuilder);
+    }
+    
+    @Test
+    public void testResolverResource() {
+        ClassResolver classResolver = getClassResolver();
+        InputStream is = classResolver.loadResourceAsStream("META-INF/services/org/apache/camel/TypeConverterLoader");
+        assertNotNull("The InputStream should not be null.", is);
+    }
+
+}
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiComponentResolverTest.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiComponentResolverTest.java
new file mode 100644
index 0000000..1a12a13
--- /dev/null
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiComponentResolverTest.java
@@ -0,0 +1,122 @@
+/*
+ * 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.core.osgi;
+
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Component;
+import org.apache.camel.Endpoint;
+import org.apache.camel.component.file.FileComponent;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.spi.Registry;
+import org.apache.camel.support.DefaultRegistry;
+import org.apache.camel.support.service.ServiceSupport;
+import org.junit.Test;
+
+public class OsgiComponentResolverTest extends CamelOsgiTestSupport {
+
+    @Test
+    public void testOsgiResolverFindComponentTest() throws Exception {
+        CamelContext camelContext = new DefaultCamelContext();
+        OsgiComponentResolver resolver = new OsgiComponentResolver(getBundleContext());
+        Component component = resolver.resolveComponent("file_test", camelContext);
+        assertNotNull("We should find file_test component", component);
+        assertTrue("We should get the file component here", component instanceof FileComponent);
+    }
+
+    @Test
+    public void testOsgiResolverFindComponentFallbackTest() throws Exception {
+        Registry registry = new DefaultRegistry();
+        registry.bind("allstar-component", new SampleComponent(true));
+
+        CamelContext camelContext = new DefaultCamelContext(registry);
+
+        OsgiComponentResolver resolver = new OsgiComponentResolver(getBundleContext());
+        Component component = resolver.resolveComponent("allstar", camelContext);
+        assertNotNull("We should find the super component", component);
+        assertTrue("We should get the super component here", component instanceof SampleComponent);
+    }
+
+    @Test
+    public void testOsgiResolverFindLanguageDoubleFallbackTest() throws Exception {
+        Registry registry = new DefaultRegistry();
+        registry.bind("allstar", new SampleComponent(false));
+        registry.bind("allstar-component", new SampleComponent(true));
+
+        CamelContext camelContext = new DefaultCamelContext(registry);
+
+        OsgiComponentResolver resolver = new OsgiComponentResolver(getBundleContext());
+        Component component = resolver.resolveComponent("allstar", camelContext);
+        assertNotNull("We should find the super component", component);
+        assertTrue("We should get the super component here", component instanceof SampleComponent);
+        assertFalse("We should NOT find the fallback component", ((SampleComponent) component).isFallback());
+    }
+
+    private static class SampleComponent extends ServiceSupport implements Component {
+
+        private boolean fallback;
+
+        SampleComponent(boolean fallback) {
+            this.fallback = fallback;
+        }
+
+        @Override
+        public void setCamelContext(CamelContext camelContext) {
+            throw new UnsupportedOperationException("Should not be called");
+        }
+
+        @Override
+        public CamelContext getCamelContext() {
+            throw new UnsupportedOperationException("Should not be called");
+        }
+
+        @Override
+        public Endpoint createEndpoint(String uri) throws Exception {
+            throw new UnsupportedOperationException("Should not be called");
+        }
+
+        @Override
+        public Endpoint createEndpoint(String uri, Map<String, Object> parameters) throws Exception {
+            throw new UnsupportedOperationException("Should not be called");
+        }
+
+        @Override
+        public boolean useRawUri() {
+            throw new UnsupportedOperationException("Should not be called");
+        }
+
+        public boolean isFallback() {
+            return fallback;
+        }
+
+        public void setFallback(boolean fallback) {
+            this.fallback = fallback;
+        }
+
+        @Override
+        protected void doStart() throws Exception {
+            // noop
+        }
+
+        @Override
+        protected void doStop() throws Exception {
+            // noop
+        }
+    }
+
+}
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiDataFormatResolverTest.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiDataFormatResolverTest.java
new file mode 100644
index 0000000..dab6602
--- /dev/null
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiDataFormatResolverTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.core.osgi;
+
+import java.io.InputStream;
+import java.io.OutputStream;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Exchange;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.spi.DataFormat;
+import org.apache.camel.spi.Registry;
+import org.apache.camel.support.DefaultDataFormat;
+import org.apache.camel.support.DefaultRegistry;
+import org.junit.Test;
+
+public class OsgiDataFormatResolverTest extends CamelOsgiTestSupport {
+
+    @Test
+    public void testOsgiResolverFindDataFormatFallbackTest() throws Exception {
+        Registry registry = new DefaultRegistry();
+        registry.bind("allstar-dataformat", new SampleDataFormat(true));
+
+        CamelContext camelContext = new DefaultCamelContext(registry);
+
+        OsgiDataFormatResolver resolver = new OsgiDataFormatResolver(getBundleContext());
+        DataFormat dataformat = resolver.resolveDataFormat("allstar", camelContext);
+        assertNotNull("We should find the super dataformat", dataformat);
+        assertTrue("We should get the super dataformat here", dataformat instanceof SampleDataFormat);
+    }
+
+    @Test
+    public void testOsgiResolverFindLanguageDoubleFallbackTest() throws Exception {
+        Registry registry = new DefaultRegistry();
+        registry.bind("allstar", new SampleDataFormat(false));
+        registry.bind("allstar-dataformat", new SampleDataFormat(true));
+
+        CamelContext camelContext = new DefaultCamelContext(registry);
+
+        OsgiDataFormatResolver resolver = new OsgiDataFormatResolver(getBundleContext());
+        DataFormat dataformat = resolver.resolveDataFormat("allstar", camelContext);
+        assertNotNull("We should find the super dataformat", dataformat);
+        assertTrue("We should get the super dataformat here", dataformat instanceof SampleDataFormat);
+        assertFalse("We should NOT find the fallback dataformat", ((SampleDataFormat) dataformat).isFallback());
+    }
+
+    private static class SampleDataFormat extends DefaultDataFormat {
+
+        private boolean fallback;
+
+        SampleDataFormat(boolean fallback) {
+            this.fallback = fallback;
+        }
+
+        @Override
+        public void marshal(Exchange exchange, Object graph, OutputStream stream) throws Exception {
+            throw new UnsupportedOperationException("Should not be called");
+        }
+
+        @Override
+        public Object unmarshal(Exchange exchange, InputStream stream) throws Exception {
+            throw new UnsupportedOperationException("Should not be called");
+        }
+
+        public boolean isFallback() {
+            return fallback;
+        }
+
+        public void setFallback(boolean fallback) {
+            this.fallback = fallback;
+        }
+    }
+
+}
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiFactoryFinderTest.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiFactoryFinderTest.java
new file mode 100644
index 0000000..383a717
--- /dev/null
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiFactoryFinderTest.java
@@ -0,0 +1,42 @@
+/*
+ * 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.core.osgi;
+
+import java.io.IOException;
+
+import org.apache.camel.impl.engine.DefaultClassResolver;
+import org.junit.Test;
+
+public class OsgiFactoryFinderTest extends CamelOsgiTestSupport {
+
+    @Test
+    public void testFindClass() throws Exception {
+        OsgiFactoryFinder finder = new OsgiFactoryFinder(getBundleContext(), new DefaultClassResolver(), "META-INF/services/org/apache/camel/component/");
+        Class<?> clazz = finder.findClass("file_test", "strategy.factory.").orElse(null);
+        assertNotNull("We should get the file strategy factory here", clazz);
+        
+        assertFalse(finder.findClass("nofile", "strategy.factory.").isPresent());
+
+        try {
+            finder.findClass("file_test", "nostrategy.factory.");
+            fail("We should get exception here");
+        } catch (Exception ex) {
+            assertTrue("Should get IOException", ex.getCause() instanceof IOException);
+        }
+    }
+
+}
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiLanguageResolverTest.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiLanguageResolverTest.java
new file mode 100644
index 0000000..6e160f2
--- /dev/null
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiLanguageResolverTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.core.osgi;
+
+import java.io.IOException;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.Expression;
+import org.apache.camel.Predicate;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.spi.Language;
+import org.apache.camel.spi.Registry;
+import org.apache.camel.support.DefaultRegistry;
+import org.junit.Test;
+
+public class OsgiLanguageResolverTest extends CamelOsgiTestSupport {
+
+    @Test
+    public void testOsgiResolverFindLanguageTest() throws IOException {
+        CamelContext camelContext = new DefaultCamelContext();
+        OsgiLanguageResolver resolver = new OsgiLanguageResolver(getBundleContext());
+        Language language = resolver.resolveLanguage("simple", camelContext);
+        assertNotNull("We should find simple language", language);
+    }
+
+    @Test
+    public void testOsgiResolverFindLanguageFallbackTest() throws IOException {
+        Registry registry = new DefaultRegistry();
+        registry.bind("fuffy-language", new SampleLanguage(true));
+
+        CamelContext camelContext = new DefaultCamelContext(registry);
+
+        OsgiLanguageResolver resolver = new OsgiLanguageResolver(getBundleContext());
+        Language language = resolver.resolveLanguage("fuffy", camelContext);
+        assertNotNull("We should find fuffy language", language);
+        assertTrue("We should find the fallback language", ((SampleLanguage) language).isFallback());
+    }
+
+    @Test
+    public void testOsgiResolverFindLanguageDoubleFallbackTest() throws IOException {
+        Registry registry = new DefaultRegistry();
+        registry.bind("fuffy", new SampleLanguage(false));
+        registry.bind("fuffy-language", new SampleLanguage(true));
+
+        CamelContext camelContext = new DefaultCamelContext(registry);
+
+        OsgiLanguageResolver resolver = new OsgiLanguageResolver(getBundleContext());
+        Language language = resolver.resolveLanguage("fuffy", camelContext);
+        assertNotNull("We should find fuffy language", language);
+        assertFalse("We should NOT find the fallback language", ((SampleLanguage) language).isFallback());
+    }
+
+    private static class SampleLanguage implements Language {
+
+        private boolean fallback;
+
+        SampleLanguage(boolean fallback) {
+            this.fallback = fallback;
+        }
+
+        @Override
+        public Predicate createPredicate(String expression) {
+            throw new UnsupportedOperationException("Should not be called");
+        }
+
+        @Override
+        public Expression createExpression(String expression) {
+            throw new UnsupportedOperationException("Should not be called");
+        }
+
+        public boolean isFallback() {
+            return fallback;
+        }
+
+        public void setFallback(boolean fallback) {
+            this.fallback = fallback;
+        }
+    }
+
+}
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiPackageScanClassResolverTest.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiPackageScanClassResolverTest.java
new file mode 100644
index 0000000..eed874c
--- /dev/null
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/OsgiPackageScanClassResolverTest.java
@@ -0,0 +1,79 @@
+/*
+ * 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.core.osgi;
+
+import java.io.IOException;
+import java.util.Set;
+
+import org.apache.camel.Converter;
+import org.apache.camel.RoutesBuilder;
+import org.apache.camel.core.osgi.other.MyOtherRouteBuilder;
+import org.apache.camel.core.osgi.other.MyOtherTypeConverter;
+import org.apache.camel.core.osgi.test.MyRouteBuilder;
+import org.apache.camel.core.osgi.test.MyTypeConverter;
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+
+public class OsgiPackageScanClassResolverTest extends CamelOsgiTestSupport {
+
+    @Test
+    public void testOsgiResolverFindAnnotatedTest() throws IOException {
+        BundleContext context = getBundleContext();
+        assertNotNull("The BundleContext should not be null", context);
+        OsgiPackageScanClassResolver resolver = new OsgiPackageScanClassResolver(context);
+             
+        String[] packageNames = {"org.apache.camel.core.osgi.test"};
+        Set<Class<?>> classes = resolver.findAnnotated(Converter.class, packageNames);
+        assertEquals("There should find a class", classes.size(), 1);
+        assertTrue("Find a wrong class", classes.contains(MyTypeConverter.class));
+    }
+ 
+    @Test
+    public void testOsgiResolverFindImplementationTest() {
+        BundleContext context = getBundleContext();
+        assertNotNull("The BundleContext should not be null", context);
+        OsgiPackageScanClassResolver resolver = new OsgiPackageScanClassResolver(context);
+        String[] packageNames = {"org.apache.camel.core.osgi.test"};
+        Set<Class<?>> classes = resolver.findImplementations(RoutesBuilder.class, packageNames);
+        assertEquals("There should find a class", classes.size(), 1);
+        assertTrue("Find a wrong class", classes.contains(MyRouteBuilder.class));
+    }
+    
+    @Test
+    public void testOsgiResolverFindAnnotatedWithFallbackClassLoaderTest() throws IOException {
+        BundleContext context = getBundleContext();
+        assertNotNull("The BundleContext should not be null", context);
+        OsgiPackageScanClassResolver resolver = new OsgiPackageScanClassResolver(context);
+             
+        String[] packageNames = {"org.apache.camel.core.osgi.other"};
+        Set<Class<?>> classes = resolver.findAnnotated(Converter.class, packageNames);
+        assertEquals("There should find a class", classes.size(), 1);
+        assertTrue("Find a wrong class", classes.contains(MyOtherTypeConverter.class));
+    }
+    
+    @Test
+    public void testOsgiResolverFindImplementationWithFallbackClassLoaderTest() {
+        BundleContext context = getBundleContext();
+        assertNotNull("The BundleContext should not be null", context);
+        OsgiPackageScanClassResolver resolver = new OsgiPackageScanClassResolver(context);
+        String[] packageNames = {"org.apache.camel.core.osgi.other"};
+        Set<Class<?>> classes = resolver.findImplementations(RoutesBuilder.class, packageNames);
+        assertEquals("There should find a class", classes.size(), 1);
+        assertTrue("Find a wrong class", classes.contains(MyOtherRouteBuilder.class));
+    }
+
+}
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/ServiceRegistryTest.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/ServiceRegistryTest.java
new file mode 100644
index 0000000..e56fb40
--- /dev/null
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/ServiceRegistryTest.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.core.osgi;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.core.osgi.test.MyService;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.junit.Test;
+
+public class ServiceRegistryTest extends CamelOsgiTestSupport {
+
+    @Test
+    public void camelContextFactoryServiceRegistryTest() throws Exception {
+        DefaultCamelContext context = new OsgiDefaultCamelContext(getBundleContext());
+        context.start();
+
+        MyService myService = context.getRegistry().lookupByNameAndType(MyService.class.getName(), MyService.class);
+        assertNotNull("MyService should not be null", myService);
+        
+        myService = context.getRegistry().lookupByNameAndType("test", MyService.class);
+        assertNull("We should not get the MyService Object here", myService);
+
+        Object service = context.getRegistry().lookupByName(MyService.class.getName());
+        assertNotNull("MyService should not be null", service);
+        assertTrue("It should be the instance of MyService ", service instanceof MyService);
+        
+        Object serviceByPid = context.getRegistry().lookupByName(CamelMockBundleContext.SERVICE_PID_PREFIX + MyService.class.getName());
+        assertNotNull("MyService should not be null", serviceByPid);
+        assertTrue("It should be the instance of MyService ", serviceByPid instanceof MyService);
+        
+        Map<String, MyService> collection = context.getRegistry().findByTypeWithName(MyService.class);
+        assertNotNull("MyService should not be null", collection);
+        assertNotNull("There should have one MyService.", collection.get(MyService.class.getName()));
+
+        Set<MyService> collection2 = context.getRegistry().findByType(MyService.class);
+        assertNotNull("MyService should not be null", collection2);
+        assertEquals(1, collection2.size());
+
+        context.stop();
+    }
+
+}
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/other/MyOtherRouteBuilder.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/other/MyOtherRouteBuilder.java
new file mode 100644
index 0000000..1779087
--- /dev/null
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/other/MyOtherRouteBuilder.java
@@ -0,0 +1,28 @@
+/*
+ * 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.core.osgi.other;
+
+import org.apache.camel.builder.RouteBuilder;
+
+public class MyOtherRouteBuilder extends RouteBuilder {
+
+    @Override
+    public void configure() throws Exception {
+        // Do nothing here
+    }
+
+}
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/other/MyOtherTypeConverter.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/other/MyOtherTypeConverter.java
new file mode 100644
index 0000000..445a653
--- /dev/null
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/other/MyOtherTypeConverter.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.core.osgi.other;
+
+import org.apache.camel.Converter;
+import org.apache.camel.Exchange;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.component.file.GenericFile;
+import org.apache.camel.spi.TypeConverterRegistry;
+
+@Converter
+public final class MyOtherTypeConverter {
+
+    /**
+     * Utility classes should not have a public constructor.
+     */
+    private MyOtherTypeConverter() {
+    }
+    
+    /**
+     * Converts the given value to a boolean, handling strings or Boolean
+     * objects; otherwise returning false if the value could not be converted to
+     * a boolean
+     */
+    @Converter
+    public static boolean toBool(Object value) {
+        Boolean answer = null;    
+        if (value instanceof String) {
+            answer = Boolean.valueOf((String)value);
+        } 
+        if (value instanceof Boolean) {
+            answer = (Boolean) value;
+        }
+        if (answer != null) {
+            return answer.booleanValue();
+        }
+        return false;
+    }
+    
+    @Converter(fallback = true)
+    public static Object convertTo(Class<?> type, Exchange exchange, Object value, TypeConverterRegistry registry) {
+        // use a fallback type converter so we can convert the embedded body if the value is GenericFile
+        if (GenericFile.class.isAssignableFrom(value.getClass())) {
+            GenericFile<?> file = (GenericFile<?>) value;
+            Class<?> from = file.getBody().getClass();
+
+            // maybe from is already the type we want
+            if (from.isAssignableFrom(type)) {
+                return file.getBody();
+            }
+            // no then try to lookup a type converter
+            TypeConverter tc = registry.lookup(type, from);
+            if (tc != null) {
+                Object body = file.getBody();
+                return tc.convertTo(type, exchange, body);
+            }
+        }
+        
+        return null;
+    }
+    
+
+}
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/test/MockTypeConverterRegistry.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/test/MockTypeConverterRegistry.java
new file mode 100644
index 0000000..26c7c7f
--- /dev/null
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/test/MockTypeConverterRegistry.java
@@ -0,0 +1,141 @@
+/*
+ * 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.core.osgi.test;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.LoggingLevel;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.TypeConverterExists;
+import org.apache.camel.TypeConverters;
+import org.apache.camel.spi.Injector;
+import org.apache.camel.spi.TypeConverterRegistry;
+
+public class MockTypeConverterRegistry implements TypeConverterRegistry {
+    private List<TypeConverter> typeConverters = new ArrayList<>();
+    private List<TypeConverter> fallbackTypeConverters = new ArrayList<>();
+    
+    public List<TypeConverter> getTypeConverters() {
+        return typeConverters;
+    }
+    
+    public List<TypeConverter> getFallbackTypeConverters() {
+        return fallbackTypeConverters;
+    }
+    
+    @Override
+    public void addTypeConverter(Class<?> toType, Class<?> fromType, TypeConverter typeConverter) {
+        typeConverters.add(typeConverter);
+    }
+
+    @Override
+    public void addTypeConverters(TypeConverters typeConverters) {
+        // noop
+    }
+
+    @Override
+    public boolean removeTypeConverter(Class<?> toType, Class<?> fromType) {
+        // noop
+        return true;
+    }
+
+    @Override
+    public void addFallbackTypeConverter(TypeConverter typeConverter, boolean canPromote) {
+        fallbackTypeConverters.add(typeConverter);
+    }
+
+    @Override
+    public TypeConverter lookup(Class<?> toType, Class<?> fromType) {
+        return null;
+    }
+
+    @Override
+    public List<Class<?>[]> listAllTypeConvertersFromTo() {
+        return null;
+    }
+
+    @Override
+    public void setInjector(Injector injector) {
+       // do nothing
+    }
+
+    @Override
+    public Injector getInjector() {
+        return null;
+    }
+
+    @Override
+    public Statistics getStatistics() {
+        return null;
+    }
+
+    @Override
+    public int size() {
+        return typeConverters.size();
+    }
+
+    @Override
+    public LoggingLevel getTypeConverterExistsLoggingLevel() {
+        return LoggingLevel.WARN;
+    }
+
+    @Override
+    public void setTypeConverterExistsLoggingLevel(LoggingLevel loggingLevel) {
+        // noop
+    }
+
+    @Override
+    public TypeConverterExists getTypeConverterExists() {
+        return TypeConverterExists.Override;
+    }
+
+    @Override
+    public void setTypeConverterExists(TypeConverterExists typeConverterExists) {
+        // noop
+    }
+
+    public boolean isAnnotationScanning() {
+        return false;
+    }
+
+    public void setAnnotationScanning(boolean annotationScanning) {
+        // noop
+    }
+
+    @Override
+    public void setCamelContext(CamelContext camelContext) {
+        // noop
+    }
+
+    @Override
+    public CamelContext getCamelContext() {
+        return null;
+    }
+
+    @Override
+    public void start() {
+        // noop
+    }
+
+    @Override
+    public void stop() {
+        // noop
+    }
+}
+
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/test/MyRouteBuilder.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/test/MyRouteBuilder.java
new file mode 100644
index 0000000..90e8624
--- /dev/null
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/test/MyRouteBuilder.java
@@ -0,0 +1,28 @@
+/*
+ * 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.core.osgi.test;
+
+import org.apache.camel.builder.RouteBuilder;
+
+public class MyRouteBuilder extends RouteBuilder {
+
+    @Override
+    public void configure() throws Exception {
+        // Do nothing here
+    }
+
+}
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/test/MyService.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/test/MyService.java
new file mode 100644
index 0000000..637949f
--- /dev/null
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/test/MyService.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.core.osgi.test;
+
+public class MyService {
+
+    public String sayHi() {
+        return "Hello";
+    }
+
+}
diff --git a/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/test/MyTypeConverter.java b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/test/MyTypeConverter.java
new file mode 100644
index 0000000..9c71f15
--- /dev/null
+++ b/core/camel-core-osgi/src/test/java/org/apache/camel/core/osgi/test/MyTypeConverter.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.core.osgi.test;
+
+import org.apache.camel.Converter;
+import org.apache.camel.Exchange;
+import org.apache.camel.TypeConverter;
+import org.apache.camel.component.file.GenericFile;
+import org.apache.camel.spi.TypeConverterRegistry;
+
+@Converter
+public final class MyTypeConverter {
+
+    /**
+     * Utility classes should not have a public constructor.
+     */
+    private MyTypeConverter() {
+    }
+    
+    /**
+     * Converts the given value to a boolean, handling strings or Boolean
+     * objects; otherwise returning false if the value could not be converted to
+     * a boolean
+     */
+    @Converter
+    public static boolean toBool(Object value) {
+        Boolean answer = null;    
+        if (value instanceof String) {
+            answer = Boolean.valueOf((String)value);
+        } 
+        if (value instanceof Boolean) {
+            answer = (Boolean) value;
+        }
+        if (answer != null) {
+            return answer.booleanValue();
+        }
+        return false;
+    }
+    
+    @Converter(fallback = true)
+    public static Object convertTo(Class<?> type, Exchange exchange, Object value, TypeConverterRegistry registry) {
+        // use a fallback type converter so we can convert the embedded body if the value is GenericFile
+        if (GenericFile.class.isAssignableFrom(value.getClass())) {
+            GenericFile<?> file = (GenericFile<?>) value;
+            Class<?> from = file.getBody().getClass();
+
+            // maybe from is already the type we want
+            if (from.isAssignableFrom(type)) {
+                return file.getBody();
+            }
+            // no then try to lookup a type converter
+            TypeConverter tc = registry.lookup(type, from);
+            if (tc != null) {
+                Object body = file.getBody();
+                return tc.convertTo(type, exchange, body);
+            }
+        }
+        
+        return null;
+    }
+    
+
+}
diff --git a/core/camel-core-osgi/src/test/resources/META-INF/LICENSE.txt b/core/camel-core-osgi/src/test/resources/META-INF/LICENSE.txt
new file mode 100644
index 0000000..6b0b127
--- /dev/null
+++ b/core/camel-core-osgi/src/test/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/core/camel-core-osgi/src/test/resources/META-INF/NOTICE.txt b/core/camel-core-osgi/src/test/resources/META-INF/NOTICE.txt
new file mode 100644
index 0000000..2e215bf
--- /dev/null
+++ b/core/camel-core-osgi/src/test/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/core/camel-core-osgi/src/test/resources/META-INF/services/org/apache/camel/component/file_test b/core/camel-core-osgi/src/test/resources/META-INF/services/org/apache/camel/component/file_test
new file mode 100644
index 0000000..2172240
--- /dev/null
+++ b/core/camel-core-osgi/src/test/resources/META-INF/services/org/apache/camel/component/file_test
@@ -0,0 +1,19 @@
+#
+# 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.
+#
+
+class=org.apache.camel.component.file.FileComponent
+strategy.factory.class=org.apache.camel.component.file.strategy.FileProcessStrategyFactory
\ No newline at end of file
diff --git a/core/camel-core-osgi/src/test/resources/META-INF/services/org/apache/camel/component/timer_test b/core/camel-core-osgi/src/test/resources/META-INF/services/org/apache/camel/component/timer_test
new file mode 100644
index 0000000..87adb9a
--- /dev/null
+++ b/core/camel-core-osgi/src/test/resources/META-INF/services/org/apache/camel/component/timer_test
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+class=org.apache.camel.component.timer.TimerComponent
diff --git a/core/camel-core-osgi/src/test/resources/META-INF/services/org/apache/camel/language/bean_test b/core/camel-core-osgi/src/test/resources/META-INF/services/org/apache/camel/language/bean_test
new file mode 100644
index 0000000..028e2cb
--- /dev/null
+++ b/core/camel-core-osgi/src/test/resources/META-INF/services/org/apache/camel/language/bean_test
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+class=org.apache.camel.language.bean.BeanLanguage
diff --git a/core/camel-core-osgi/src/test/resources/META-INF/services/org/apache/camel/language/file_test b/core/camel-core-osgi/src/test/resources/META-INF/services/org/apache/camel/language/file_test
new file mode 100644
index 0000000..c907df9
--- /dev/null
+++ b/core/camel-core-osgi/src/test/resources/META-INF/services/org/apache/camel/language/file_test
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+class=org.apache.camel.language.simple.FileLanguage
\ No newline at end of file
diff --git a/core/camel-core-osgi/src/test/resources/META-INF/services/org/apache/camel/language/resolver/default b/core/camel-core-osgi/src/test/resources/META-INF/services/org/apache/camel/language/resolver/default
new file mode 100644
index 0000000..b6a8d70
--- /dev/null
+++ b/core/camel-core-osgi/src/test/resources/META-INF/services/org/apache/camel/language/resolver/default
@@ -0,0 +1,18 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+class=org.apache.camel.core.osgi.CamelMockLanguageResolver
\ No newline at end of file
diff --git a/core/camel-core-osgi/src/test/resources/META-INF/spring/camel-context.xml b/core/camel-core-osgi/src/test/resources/META-INF/spring/camel-context.xml
new file mode 100644
index 0000000..440ef69
--- /dev/null
+++ b/core/camel-core-osgi/src/test/resources/META-INF/spring/camel-context.xml
@@ -0,0 +1,66 @@
+<?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.
+
+-->
+<!--
+
+  The default Application Context used by the org.apache.camel.spring.Main if there
+  is no /META-INF/sprint.xml
+
+ -->
+
+<beans xmlns="http://www.springframework.org/schema/beans"
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://camel.apache.org/schema/spring http://camel.apache.org/schema/spring/camel-spring.xsd">
+
+  <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring">
+    <route>
+      <from uri="direct:a.start"/>
+      <choice>
+        <when>
+          <xpath>$foo = 'bar'</xpath>
+          <to uri="mock:x"/>
+        </when>
+        <when>
+          <xpath>$foo = 'cheese'</xpath>
+          <to uri="mock:y"/>
+        </when>
+        <otherwise>
+          <to uri="mock:z"/>
+        </otherwise>
+      </choice>
+    </route>
+    <route>
+      <from uri="direct:b.start"/>
+      <filter>
+        <xpath>/person[@name='James']</xpath>
+        <to uri="mock:b.end"/>
+      </filter>
+    </route>
+    <route>
+      <from uri="direct:c.start"/>
+      <resequence>
+        <simple>body</simple>
+        <to uri="mock:c.end"/>
+      </resequence>
+    </route>
+  </camelContext>
+
+</beans>
diff --git a/core/camel-core-osgi/src/test/resources/log4j2.properties b/core/camel-core-osgi/src/test/resources/log4j2.properties
new file mode 100644
index 0000000..2b6df8b
--- /dev/null
+++ b/core/camel-core-osgi/src/test/resources/log4j2.properties
@@ -0,0 +1,28 @@
+## ---------------------------------------------------------------------------
+## 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.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-core-osgi-test.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d [%-15.15t] %-5p %-30.30c{1} - %m%n
+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.file.ref = file
diff --git a/core/pom.xml b/core/pom.xml
new file mode 100644
index 0000000..fb91603
--- /dev/null
+++ b/core/pom.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.
+-->
+<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>karaf</artifactId>
+        <version>3.2.0-SNAPSHOT</version>
+        <relativePath>..</relativePath>
+    </parent>
+
+    <groupId>org.apache.camel.karaf</groupId>
+    <artifactId>core-modules</artifactId>
+    <name>Camel Karaf :: Core Modules</name>
+    <description>Camel Karaf Core Modules</description>
+    <packaging>pom</packaging>
+
+    <modules>
+        <module>camel-core-osgi</module>
+    </modules>
+
+</project>
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..61931ab
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,921 @@
+<?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</groupId>
+        <artifactId>apache</artifactId>
+        <version>21</version>
+    </parent>
+
+    <groupId>org.apache.camel.karaf</groupId>
+    <artifactId>karaf</artifactId>
+    <version>3.2.0-SNAPSHOT</version>
+    <packaging>pom</packaging>
+
+    <name>Camel Karaf</name>
+    <description>Camel Karaf Root POM</description>
+    <url>https://camel.apache.org</url>
+    <inceptionYear>2007</inceptionYear>
+
+    <developers>
+        <developer>
+            <name>The Apache Camel Team</name>
+            <email>dev@camel.apache.org</email>
+            <url>https://camel.apache.org</url>
+            <organization>Apache Software Foundation</organization>
+            <organizationUrl>http://apache.org/</organizationUrl>
+        </developer>
+    </developers>
+
+    <mailingLists>
+        <mailingList>
+            <name>Development List</name>
+            <subscribe>dev-subscribe@camel.apache.org</subscribe>
+            <unsubscribe>dev-unsubscribe@camel.apache.org</unsubscribe>
+            <post>dev@camel.apache.org</post>
+        </mailingList>
+        <mailingList>
+            <name>User List</name>
+            <subscribe>users-subscribe@camel.apache.org</subscribe>
+            <unsubscribe>users-unsubscribe@camel.apache.org</unsubscribe>
+            <post>users@camel.apache.org</post>
+        </mailingList>
+        <mailingList>
+            <name>Commits List</name>
+            <subscribe>commits-subscribe@camel.apache.org</subscribe>
+            <unsubscribe>commits-unsubscribe@camel.apache.org</unsubscribe>
+            <post>commits@camel.apache.org</post>
+        </mailingList>
+    </mailingLists>
+
+    <prerequisites>
+        <maven>3.5.0</maven>
+    </prerequisites>
+
+    <modules>
+        <!--<module>tooling</module>-->
+        <module>core</module>
+        <!--<module>components-starter</module>
+        <module>catalog</module>
+        <module>tests</module>
+        <module>examples</module>
+        <module>docs</module>-->
+    </modules>
+
+    <scm>
+        <connection>scm:git:http://gitbox.apache.org/repos/asf/camel-karaf.git</connection>
+        <developerConnection>scm:git:https://gitbox.apache.org/repos/asf/camel-karaf.git</developerConnection>
+        <url>https://gitbox.apache.org/repos/asf?p=camel-karaf.git;a=summary</url>
+        <tag>HEAD</tag>
+    </scm>
+    <issueManagement>
+        <system>jira</system>
+        <url>https://issues.apache.org/jira/browse/CAMEL</url>
+    </issueManagement>
+    <distributionManagement>
+        <site>
+            <id>apache.website</id>
+            <url>${site-repo-url}</url>
+        </site>
+    </distributionManagement>
+
+    <properties>
+
+        <!-- unify the encoding for all the modules -->
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+
+        <site-repo-url>scpexe://people.apache.org/www/camel.apache.org/maven/</site-repo-url>
+        <jdk.version>1.8</jdk.version>
+        <compiler.fork>false</compiler.fork>
+
+        <!-- Spring-Boot target version -->
+        <spring-boot-version>2.2.5.RELEASE</spring-boot-version>
+
+        <!-- Camel target version -->
+        <camel-version>3.2.0-SNAPSHOT</camel-version>
+
+        <!-- versions -->
+        <aether-version>1.0.2.v20150114</aether-version>
+        <arquillian-container-se-managed-version>1.0.2.Final</arquillian-container-se-managed-version>
+        <arquillian-version>1.5.0.Final</arquillian-version>
+        <asciidoctorj-version>2.1.0</asciidoctorj-version>
+        <atomix-version>1.0.8</atomix-version>
+        <avro-version>1.8.1</avro-version>
+        <cassandra-driver-guava-version>19.0</cassandra-driver-guava-version>
+        <cdi-api-2.0-version>2.0</cdi-api-2.0-version>
+        <curator-version>4.3.0</curator-version>
+        <deltaspike-version>1.9.0</deltaspike-version>
+        <egit-github-core-version>2.1.5</egit-github-core-version>
+        <exec-maven-plugin-version>1.6.0</exec-maven-plugin-version>
+        <freemarker-version>2.3.29</freemarker-version>
+        <geronimo-ws-metadata-spec-version>1.1.3</geronimo-ws-metadata-spec-version>
+        <glassfish-jaxb-runtime-version>${jakarta-jaxb-version}</glassfish-jaxb-runtime-version>
+        <google-guava-version>19.0</google-guava-version>
+        <groovy-version>3.0.2</groovy-version>
+        <grpc-guava-version>28.1-jre</grpc-guava-version>
+        <grpc-version>1.27.0</grpc-version>
+        <gson-version>2.8.5</gson-version>
+        <hadoop2-version>2.7.4</hadoop2-version>
+        <hibernate-validator-version>6.1.2.Final</hibernate-validator-version>
+        <hibernate-version>5.4.12.Final</hibernate-version>
+        <infinispan-spring-boot-version>2.2.3.Final</infinispan-spring-boot-version>
+        <jackson-version>1.9.12</jackson-version>
+        <jakarta-jaxb-version>2.3.2</jakarta-jaxb-version>
+        <jandex-version>2.1.1.Final</jandex-version>
+        <javax-annotation-api-version>1.3.2</javax-annotation-api-version>
+        <jaxb-version>2.3.0</jaxb-version>
+        <jetty9-version>9.4.20.v20190813</jetty9-version>
+        <jolokia-version>1.6.2</jolokia-version>
+        <junit-jupiter-version>5.6.0</junit-jupiter-version>
+        <kafka-avro-serializer-version>5.2.2</kafka-avro-serializer-version>
+        <log4j2-version>2.13.1</log4j2-version>
+        <lucene3-version>3.6.0</lucene3-version>
+        <maven-checkstyle-plugin-version>3.1.0</maven-checkstyle-plugin-version>
+        <maven-checkstyle-version>8.26</maven-checkstyle-version>
+        <maven-compiler-plugin-version>3.8.1</maven-compiler-plugin-version>
+        <maven-javadoc-plugin-version>3.0.1</maven-javadoc-plugin-version>
+        <maven-resources-plugin-version>3.1.0</maven-resources-plugin-version>
+        <maven-surefire-plugin-version>3.0.0-M4</maven-surefire-plugin-version>
+        <mvel-version>2.4.5.Final</mvel-version>
+        <mycila-license-version>3.0</mycila-license-version>
+        <openjpa-version>3.1.1</openjpa-version>
+        <opentracing-version>0.33.0</opentracing-version>
+        <os-maven-plugin-version>1.6.0</os-maven-plugin-version>
+        <protobuf-maven-plugin-version>0.6.1</protobuf-maven-plugin-version>
+        <protobuf-version>3.11.1</protobuf-version>
+        <reactor-version>3.2.15.RELEASE</reactor-version>
+        <roaster-version>2.20.1.Final</roaster-version>
+        <rxjava-version>1.3.8</rxjava-version>
+        <shrinkwrap-resolver-version>3.1.3</shrinkwrap-resolver-version>
+        <shrinkwrap-version>1.2.6</shrinkwrap-version>
+        <spring-cloud-commons-version>2.2.2.RELEASE</spring-cloud-commons-version>
+        <spring-cloud-consul-version>2.2.2.RELEASE</spring-cloud-consul-version>
+        <spring-cloud-netflix-version>2.2.2.RELEASE</spring-cloud-netflix-version>
+        <spring-cloud-zookeeper-version>2.2.1.RELEASE</spring-cloud-zookeeper-version>
+        <surefire.version>${maven-surefire-plugin-version}</surefire.version>
+        <testcontainers-version>1.13.0</testcontainers-version>
+        <tomcat-version>9.0.31</tomcat-version>
+        <undertow-version>2.0.30.Final</undertow-version>
+        <weld3-version>3.0.5.RELEASE</weld3-version>
+    </properties>
+
+
+    <!-- Comment out the snapshot repositories as we don't need them now -->
+    <repositories>
+        <repository>
+            <id>apache.snapshots</id>
+            <url>https://repository.apache.org/snapshots/</url>
+            <name>Apache Snapshot Repo</name>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+        </repository>
+    </repositories>
+    <pluginRepositories>
+        <pluginRepository>
+            <id>apache.snapshots</id>
+            <url>https://repository.apache.org/snapshots/</url>
+            <snapshots>
+                <enabled>true</enabled>
+            </snapshots>
+            <releases>
+                <enabled>false</enabled>
+            </releases>
+        </pluginRepository>
+    </pluginRepositories>
+
+    <dependencyManagement>
+        <dependencies>
+            <dependency>
+                <groupId>org.apache.camel</groupId>
+                <artifactId>camel-parent</artifactId>
+                <version>${camel-version}</version>
+                <type>pom</type>
+                <scope>import</scope>
+            </dependency>
+        </dependencies>
+    </dependencyManagement>
+
+    <build>
+        <defaultGoal>install</defaultGoal>
+
+        <plugins>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <version>${maven-compiler-plugin-version}</version>
+                <configuration>
+                    <source>${jdk.version}</source>
+                    <target>${jdk.version}</target>
+                    <maxmem>512M</maxmem>
+                    <fork>${compiler.fork}</fork>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-javadoc-plugin</artifactId>
+                <configuration>
+                    <attach>true</attach>
+                    <source>${jdk.version}</source>
+                    <quiet>true</quiet>
+                    <bottom>Apache Camel</bottom>
+                    <detectOfflineLinks>false</detectOfflineLinks>
+                    <javadocVersion>1.8.0</javadocVersion>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-resources-plugin</artifactId>
+                <configuration>
+                    <encoding>UTF-8</encoding>
+                </configuration>
+            </plugin>
+        </plugins>
+
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-javadoc-plugin</artifactId>
+                    <version>${maven-javadoc-plugin-version}</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-eclipse-plugin</artifactId>
+                    <version>2.10</version>
+                    <dependencies>
+                        <dependency>
+                            <groupId>org.apache.camel</groupId>
+                            <artifactId>camel-buildtools</artifactId>
+                            <version>${camel-version}</version>
+                        </dependency>
+                    </dependencies>
+                    <configuration>
+                        <downloadSources>true</downloadSources>
+                        <downloadJavadocs>false</downloadJavadocs>
+                    </configuration>
+                </plugin>
+
+                <plugin>
+                    <groupId>org.apache.rat</groupId>
+                    <artifactId>apache-rat-plugin</artifactId>
+                    <configuration>
+                        <excludeSubProjects>false</excludeSubProjects>
+                        <excludes>
+                            <exclude>**/*.mvel</exclude>
+                            <exclude>**/catalog/*.properties</exclude>
+                            <exclude>**/*.json</exclude>
+                            <exclude>**/README</exclude>
+                            <exclude>**/README.txt</exclude>
+                            <exclude>**/README.md</exclude>
+                            <exclude>**/ReadMe.md</exclude>
+                            <exclude>**/resources/**/*.xsd</exclude>
+                            <exclude>**/webapp/js/**/*</exclude>
+                            <exclude>**/test/resources/**/*</exclude>
+                            <exclude>**/test/data*/**/*</exclude>
+                            <exclude>.gitignore</exclude>
+                            <exclude>.git/**/*</exclude>
+                            <exclude>**/*.adoc</exclude>
+                            <exclude>**/*.adoc.template</exclude>
+                            <exclude>**/*.md</exclude>
+                            <exclude>**/*.sh</exclude>
+                            <exclude>**/*.bat</exclude>
+                            <exclude>**/java9-maven-settings</exclude>
+                            <exclude>**/*.pfx</exclude>
+                            <!-- tooling json-simple parser -->
+                            <exclude>**/src/main/java/org/json/simple/**</exclude>
+                            <!-- tooling/camel-manual/src/styles/print.css use a different license -->
+                            <exclude>**/src/styles/print.css</exclude>
+                            <!-- tooling for component docs -->
+                            <exclude>**/component-header.mvel</exclude>
+                            <exclude>**/component-options.mvel</exclude>
+                            <exclude>**/endpoint-options.mvel</exclude>
+                            <exclude>**/dataformat-options.mvel</exclude>
+                            <exclude>**/eip-options.mvel</exclude>
+                            <exclude>**/language-options.mvel</exclude>
+                            <exclude>**/website-components-list.mvel</exclude>
+                            <exclude>**/website-languages-list.mvel</exclude>
+                            <exclude>**/website-others-list.mvel</exclude>
+                            <exclude>**/website-dataformats-list.mvel</exclude>
+                            <exclude>**/readme-examples.mvel</exclude>
+                            <exclude>**/spring-boot-auto-configure-options.mvel</exclude>
+                            <exclude>**/camel-NOTICE.txt</exclude>
+                            <exclude>**/spring-boot-starter-NOTICE.txt</exclude>
+                            <!-- cxf does not handle comments here -->
+                            <exclude>**/src/main/resources/META-INF/cxf/cxf.extension</exclude>
+                            <exclude>**/src/main/resources/META-INF/cxf/bus-extensions.txt</exclude>
+                            <!-- ignore the api signatures files -->
+                            <exclude>**/src/signatures/*.txt</exclude>
+                            <!-- camel-salesforce BSD license from salesforce developers -->
+                            <exclude>**/CometDReplayExtension.java</exclude>
+                            <exclude>**/LICENSE-SALESFORCE.txt</exclude>
+                            <!-- camel-as2 -->
+                            <exclude>**/mdnDescription.vm</exclude>
+                            <!-- camel-jbpm -->
+                            <exclude>**/src/main/resources/*.wid</exclude>
+                            <!-- camel website and user-manual -->
+                            <exclude>**/node/**</exclude>
+                            <exclude>**/node_modules/**</exclude>
+                            <exclude>**/user-manual/**</exclude>
+                            <exclude>**/yarn.lock</exclude>
+                            <!-- examples -->
+                            <exclude>**/fabric8/*.yaml</exclude>
+                            <exclude>**/src/main/data/*.patient</exclude>
+                            <exclude>**/src/main/data/*.csv</exclude>
+                            <exclude>**/src/main/resources/avro/*.avsc</exclude>
+                            <!-- generated files -->
+                            <exclude>**/target/**/*</exclude>
+                            <exclude>**/eclipse-classes/**/*</exclude>
+                            <exclude>**/.*</exclude>
+                            <exclude>**/.settings/**/*</exclude>
+                            <exclude>**/*.iml</exclude>
+                            <exclude>**/.idea/**/*</exclude>
+                            <exclude>**/avro/**/*.avpr</exclude>
+                            <exclude>**/OSGI-INF/bundle.info</exclude>
+                            <exclude>**/test_rsa*</exclude>
+                            <exclude>**/data*/**/*.xml</exclude>
+                            <exlucde>**/*.log</exlucde>
+                            <exclude>**/id_file</exclude>
+                            <exclude>**/dependency-reduced-pom.xml</exclude>
+                            <exclude>**/Dropbox_API_Terms_and_Conditions.txt</exclude>
+                            <exclude>**/MerchandiseRestResource.apxc</exclude>
+                            <exclude>**/file-sig-api.txt</exclude>
+                            <exclude>**/Tasks__c.java</exclude>
+                            <exclude>**/*.proto</exclude>
+                            <exclude>
+                                **/src/main/resources/META-INF/services/org.kie.server.services.api.KieServerExtension
+                            </exclude>
+                            <!-- Maven Wrapper -->
+                            <exclude>.mvn/**/*</exclude>
+                        </excludes>
+                    </configuration>
+                </plugin>
+
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-release-plugin</artifactId>
+                    <!-- see https://issues.apache.org/jira/browse/MRELEASE-812 -->
+                    <version>2.4.2</version>
+                    <dependencies>
+                        <dependency>
+                            <groupId>org.apache.maven.scm</groupId>
+                            <artifactId>maven-scm-provider-gitexe</artifactId>
+                            <version>1.9</version>
+                        </dependency>
+                    </dependencies>
+                    <configuration>
+                        <localCheckout>true</localCheckout>
+                        <pushChanges>true</pushChanges>
+                        <tagNameFormat>@{project.artifactId}-@{project.version}</tagNameFormat>
+                        <useReleaseProfile>false</useReleaseProfile>
+                        <preparationGoals>clean install</preparationGoals>
+                        <goals>deploy</goals>
+                        <!-- The profile we want to use when doing the release -->
+                        <arguments>-Prelease,apache-release,sourcecheck</arguments>
+                        <autoVersionSubmodules>true</autoVersionSubmodules>
+                    </configuration>
+                </plugin>
+
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-remote-resources-plugin</artifactId>
+                    <executions>
+                        <execution>
+                            <id>process-resource-bundles</id>
+                            <phase>disabled</phase>
+                        </execution>
+                    </executions>
+                </plugin>
+
+                <plugin>
+                    <groupId>org.codehaus.mojo</groupId>
+                    <artifactId>flatten-maven-plugin</artifactId>
+                    <version>1.1.0</version>
+                    <executions>
+                        <execution>
+                            <id>default-cli</id>
+                            <phase>process-resources</phase>
+                            <goals>
+                                <goal>flatten</goal>
+                            </goals>
+                            <configuration>
+                                <updatePomFile>true</updatePomFile>
+                                <pomElements>
+                                    <build>keep</build>
+                                    <dependencyManagement>keep</dependencyManagement>
+                                    <description>keep</description>
+                                    <name>keep</name>
+                                    <parent>expand</parent>
+                                    <pluginManagement>keep</pluginManagement>
+                                    <profiles>remove</profiles>
+                                    <properties>keep</properties>
+                                </pomElements>
+                            </configuration>
+                        </execution>
+                    </executions>
+                </plugin>
+
+                <plugin>
+                    <artifactId>maven-invoker-plugin</artifactId>
+                    <configuration>
+                        <skipInstallation>${invoker.skip}</skipInstallation>
+                        <skipInvocation>${invoker.skip}</skipInvocation>
+                        <mavenOpts>-Xmx64m -XshowSettings</mavenOpts>
+                        <showVersion>true</showVersion>
+                    </configuration>
+                </plugin>
+
+                <plugin>
+                    <groupId>org.codehaus.mojo</groupId>
+                    <artifactId>exec-maven-plugin</artifactId>
+                    <version>${exec-maven-plugin-version}</version>
+                </plugin>
+
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-surefire-plugin</artifactId>
+                    <version>${maven-surefire-plugin-version}</version>
+                    <configuration>
+                        <!--forkMode>pertest</forkMode -->
+                        <forkedProcessTimeoutInSeconds>300</forkedProcessTimeoutInSeconds>
+                        <childDelegation>false</childDelegation>
+                        <useFile>true</useFile>
+                        <failIfNoTests>false</failIfNoTests>
+                        <runOrder>alphabetical</runOrder>
+                        <!-- lets re-run the failed test one more time, just to be sure -->
+                        <rerunFailingTestsCount>2</rerunFailingTestsCount>
+                        <systemPropertyVariables>
+                            <javax.xml.accessExternalSchema>file,http,https</javax.xml.accessExternalSchema>
+                            <javax.xml.accessExternalDTD>file,http</javax.xml.accessExternalDTD>
+                            <derby.stream.error.file>target/derby.log</derby.stream.error.file>
+                            <java.awt.headless>${java.awt.headless}</java.awt.headless>
+                            <java.util.logging.config.file>${basedir}/target/test-classes/logging.properties
+                            </java.util.logging.config.file>
+                            <org.apache.activemq.default.directory.prefix>target/
+                            </org.apache.activemq.default.directory.prefix>
+                        </systemPropertyVariables>
+                        <includes>
+                            <include>**/*Test.java</include>
+                        </includes>
+                        <excludes>
+                            <exclude>**/*IntegrationTest.java</exclude>
+                            <exclude>**/*XXXTest.*</exclude>
+                        </excludes>
+                    </configuration>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+    </build>
+
+    <profiles>
+        <profile>
+            <id>dev</id>
+            <properties>
+                <camel-version>3.2.0-SNAPSHOT</camel-version>
+            </properties>
+        </profile>
+
+        <profile>
+            <id>fastinstall</id>
+            <activation>
+                <property>
+                    <name>fastinstall</name>
+                </property>
+            </activation>
+            <properties>
+                <maven.test.skip.exec>true</maven.test.skip.exec>
+                <assembly.skipAssembly>true</assembly.skipAssembly>
+                <fastinstall>true</fastinstall>
+                <noassembly>true</noassembly>
+            </properties>
+        </profile>
+
+        <profile>
+            <id>setup.eclipse</id>
+            <!-- set up the eclipse workspace and generate the .classpath and .project
+              files for modules -->
+            <properties>
+                <eclipse.workspace.dir>${basedir}/../workspace</eclipse.workspace.dir>
+                <maven.test.skip.exec>true</maven.test.skip.exec>
+            </properties>
+            <build>
+                <defaultGoal>package</defaultGoal>
+                <pluginManagement>
+                    <plugins>
+                        <plugin>
+                            <groupId>org.apache.maven.plugins</groupId>
+                            <artifactId>maven-compiler-plugin</artifactId>
+                            <version>${maven-compiler-plugin-version}</version>
+                            <configuration>
+                                <source>${jdk.version}</source>
+                                <target>${jdk.version}</target>
+                                <maxmem>512M</maxmem>
+                                <fork>${compiler.fork}</fork>
+                            </configuration>
+                        </plugin>
+                    </plugins>
+                </pluginManagement>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-eclipse-plugin</artifactId>
+                        <inherited>false</inherited>
+                        <executions>
+                            <execution>
+                                <id>setup.eclipse.workspace</id>
+                                <phase>process-test-sources</phase>
+                                <goals>
+                                    <goal>configure-workspace</goal>
+                                </goals>
+                                <configuration>
+                                    <workspace>${eclipse.workspace.dir}</workspace>
+                                    <workspaceCodeStylesURL>file:etc/eclipse/CamelCodeFormatter.xml
+                                    </workspaceCodeStylesURL>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-antrun-plugin</artifactId>
+                        <inherited>false</inherited>
+                        <executions>
+                            <execution>
+                                <id>setup.workspace</id>
+                                <phase>validate</phase>
+                                <configuration>
+                                    <target>
+                                        <path id="ecp.ws.path" location="${eclipse.workspace.dir}" />
+                                        <property name="full.eclipse.workspace" refid="ecp.ws.path" />
+                                        <path path="${basedir}/etc" id="etc.path" />
+
+                                        <path id="buildtools.classpath">
+                                            <fileset dir="${basedir}/buildingtools/target" includes="*.jar" />
+                                            <pathelement location="${basedir}/buildingtools/target/classes" />
+                                            <pathelement location="${basedir}/buildingtools/src/main/resources" />
+                                        </path>
+
+                                        <whichresource resource="/camel-eclipse-pmd" property="pmd.url" classpathref="buildtools.classpath" />
+                                        <whichresource resource="/camel-pmd-ruleset.xml" property="pmdruleset.url" classpathref="buildtools.classpath" />
+                                        <whichresource resource="/camel-eclipse-checkstyle" property="eclipse.checkstyle.url" classpathref="buildtools.classpath" />
+                                        <whichresource resource="/camel-checkstyle.xml" property="checkstyle.url" classpathref="buildtools.classpath" />
+
+                                        <mkdir dir="${full.eclipse.workspace}/.metadata/.plugins/org.eclipse.core.runtime/.settings" />
+                                        <mkdir dir="${full.eclipse.workspace}/.metadata/.plugins/net.sf.eclipsecs.core" />
+                                        <mkdir dir="${full.eclipse.workspace}/.metadata/.plugins/net.sourceforge.pmd.eclipse" />
+
+                                        <get src="${checkstyle.url}" dest="${full.eclipse.workspace}/camel-checkstyle.xml" />
+
+                                        <!-- Add checkstyle config -->
+                                        <copy file="${basedir}/etc/eclipse/template.checkstyle-config.xml" tofile="${full.eclipse.workspace}/.metadata/.plugins/net.sf.eclipsecs.core/checkstyle-config.xml" overwrite="no">
+                                            <filterset>
+                                                <filter token="CHECKSTYLE_CONFIG_FILE" value="${full.eclipse.workspace}/camel-checkstyle.xml" />
+                                                <filter token="APACHE_HEADER_FILE" value="${full.eclipse.workspace}/apache-header.txt" />
+                                            </filterset>
+                                        </copy>
+
+                                        <xslt style="${basedir}/etc/eclipse/addcheckstyle.xsl" in="${full.eclipse.workspace}/.metadata/.plugins/net.sf.eclipsecs.core/checkstyle-config.xml" out="${full.eclipse.workspace}/.metadata/.plugins/net.sf.eclipsecs.core/checkstyle-config.xml.new">
+                                            <param name="checkstyleconfig" expression="${full.eclipse.workspace}/camel-checkstyle.xml" />
+                                        </xslt>
+                                        <copy file="${full.eclipse.workspace}/.metadata/.plugins/net.sf.eclipsecs.core/checkstyle-config.xml.new" tofile="${full.eclipse.workspace}/.metadata/.plugins/net.sf.eclipsecs.core/checkstyle-config.xml" overwrite="yes" />
+
+                                        <!-- Add code format rules -->
+                                        <concat destfile="${full.eclipse.workspace}/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.core.prefs" append="true" fixlastline="true">
+                                            <filelist dir="${basedir}/etc/eclipse" files="org.eclipse.jdt.core.prefs" />
+                                        </concat>
+                                        <loadfile property="eclipse.code.format" srcFile="${basedir}/etc/eclipse/CamelCodeFormatter.xml" />
+                                        <loadfile property="eclipse.code.templates" srcFile="${basedir}/etc/eclipse/codetemplates.xml" />
+                                        <loadfile property="eclipse.camel.java.code.templates" srcFile="${basedir}/etc/eclipse/camel_java_templates.xml" />
+                                        <loadfile property="eclipse.camel.xml.code.templates" srcFile="${basedir}/etc/eclipse/camel_xml_templates.xml" />
+                                        <propertyfile file="${full.eclipse.workspace}/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.jdt.ui.prefs">
+                                            <entry key="formatter_profile" value="Camel Java Conventions" />
+                                            <entry key="org.eclipse.jdt.ui.formatterprofiles" value="${eclipse.code.format}" />
+                                            <entry key="org.eclipse.jdt.ui.text.custom_code_templates" value="${eclipse.code.templates}" />
+
+                                            <!-- Add Camel templates for Java DSL -->
+                                            <entry key="org.eclipse.jdt.ui.text.custom_templates" value="${eclipse.camel.java.code.templates}" />
+
+                                            <!-- Add import order -->
+                                            <entry key="org.eclipse.jdt.ui.importorder" value="java;javax;org.w3c;org.xml;w3c;" />
+                                            <!-- Sort order -->
+                                            <entry key="org.eclipse.jdt.ui.visibility.order" value="B,R,D,V," />
+                                            <entry key="outlinesortoption" value="T,SF,F,SI,I,C,SM,M," />
+                                            <entry key="org.eclipse.jdt.ui.enable.visibility.order" value="true" />
+                                        </propertyfile>
+                                        <propertyfile file="${full.eclipse.workspace}/.metadata/.plugins/org.eclipse.core.runtime/.settings/org.eclipse.wst.xml.ui.prefs">
+                                            <entry key="eclipse.preferences.version" value="1" />
+                                            <!-- Add Camel templates for Spring DSL -->
+                                            <entry key="org.eclipse.wst.sse.ui.custom_templates" value="${eclipse.camel.xml.code.templates}" />
+                                        </propertyfile>
+                                    </target>
+                                </configuration>
+                                <goals>
+                                    <goal>run</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <!-- When not on the Mac, we need to add tools.jar to the antrun plugin
+              for schemagen to work -->
+            <id>not-mac</id>
+            <activation>
+                <os>
+                    <family>!mac</family>
+                </os>
+            </activation>
+            <build>
+                <pluginManagement>
+                    <plugins>
+                        <plugin>
+                            <groupId>org.apache.maven.plugins</groupId>
+                            <artifactId>maven-antrun-plugin</artifactId>
+                            <dependencies>
+                                <dependency>
+                                    <groupId>com.sun.xml.bind</groupId>
+                                    <artifactId>jaxb-core</artifactId>
+                                    <version>${jaxb-version}</version>
+                                </dependency>
+                                <dependency>
+                                    <groupId>com.sun.xml.bind</groupId>
+                                    <artifactId>jaxb-impl</artifactId>
+                                    <version>${jaxb-version}</version>
+                                </dependency>
+                                <dependency>
+                                    <groupId>com.sun.xml.bind</groupId>
+                                    <artifactId>jaxb-jxc</artifactId>
+                                    <version>${jaxb-version}</version>
+                                </dependency>
+                                <dependency>
+                                    <groupId>xerces</groupId>
+                                    <artifactId>xercesImpl</artifactId>
+                                    <version>2.11.0</version>
+                                </dependency>
+                                <dependency>
+                                    <groupId>ant-contrib</groupId>
+                                    <artifactId>ant-contrib</artifactId>
+                                    <version>1.0b3</version>
+                                    <exclusions>
+                                        <exclusion>
+                                            <groupId>ant</groupId>
+                                            <artifactId>ant</artifactId>
+                                        </exclusion>
+                                    </exclusions>
+                                </dependency>
+                                <dependency>
+                                    <groupId>org.apache.ant</groupId>
+                                    <artifactId>ant-trax</artifactId>
+                                    <version>1.8.0</version>
+                                </dependency>
+                                <dependency>
+                                    <groupId>org.apache.ant</groupId>
+                                    <artifactId>ant-nodeps</artifactId>
+                                    <version>1.8.1</version>
+                                </dependency>
+                            </dependencies>
+                        </plugin>
+                    </plugins>
+                </pluginManagement>
+            </build>
+        </profile>
+
+        <profile>
+            <id>jdk8-build</id>
+            <activation>
+                <jdk>(,1.9)</jdk>
+            </activation>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-antrun-plugin</artifactId>
+                        <dependencies>
+                            <dependency>
+                                <groupId>com.sun</groupId>
+                                <artifactId>tools</artifactId>
+                                <version>1.5.0</version>
+                                <scope>system</scope>
+                                <systemPath>${java.home}/../lib/tools.jar</systemPath>
+                            </dependency>
+                        </dependencies>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>deploy</id>
+            <build>
+                <defaultGoal>deploy</defaultGoal>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-source-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>attach-sources</id>
+                                <goals>
+                                    <goal>jar</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-javadoc-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>attach-javadocs</id>
+                                <goals>
+                                    <goal>jar</goal>
+                                </goals>
+                                <configuration>
+                                    <additionalOptions>${javadoc.opts}</additionalOptions>
+                                </configuration>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+        <profile>
+            <id>source-jar</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-source-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>attach-sources</id>
+                                <goals>
+                                    <goal>jar</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>release</id>
+            <activation>
+                <property>
+                    <name>release</name>
+                </property>
+            </activation>
+            <build>
+                <plugins>
+                    <!-- We want to deploy the artifact to a staging location for perusal -->
+                    <plugin>
+                        <inherited>true</inherited>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-deploy-plugin</artifactId>
+                        <configuration>
+                            <updateReleaseInfo>true</updateReleaseInfo>
+                        </configuration>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-source-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>attach-sources</id>
+                                <goals>
+                                    <goal>jar</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-javadoc-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>attach-javadocs</id>
+                                <goals>
+                                    <goal>jar</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                        <configuration>
+                            <additionalOptions>${javadoc.opts}</additionalOptions>
+                        </configuration>
+                    </plugin>
+                    <!-- We want to sign the artifact, the POM, and all attached artifacts -->
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-gpg-plugin</artifactId>
+                        <configuration>
+                            <passphrase>${gpg.passphrase}</passphrase>
+                            <useAgent>${gpg.useagent}</useAgent>
+                        </configuration>
+                        <executions>
+                            <execution>
+                                <goals>
+                                    <goal>sign</goal>
+                                </goals>
+                            </execution>
+                        </executions>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+        <profile>
+            <id>doclint-java8-disable</id>
+            <activation>
+                <jdk>[1.8,)</jdk>
+            </activation>
+            <properties>
+                <javadoc.opts>-Xdoclint:none</javadoc.opts>
+            </properties>
+        </profile>
+
+        <profile>
+            <id>cleanrepo</id>
+            <build>
+                <defaultGoal>build-helper:remove-project-artifact</defaultGoal>
+            </build>
+        </profile>
+
+        <profile>
+            <id>license</id>
+            <build>
+                <defaultGoal>license:format</defaultGoal>
+                <plugins>
+                    <plugin>
+                        <groupId>com.mycila</groupId>
+                        <artifactId>license-maven-plugin</artifactId>
+                        <version>${mycila-license-version}</version>
+                        <configuration>
+                            <header>header.txt</header>
+                            <excludes>
+                                <exclude>KEYS</exclude>
+                                <exclude>**/NOTICE</exclude>
+                                <exclude>**/LICENSE</exclude>
+                                <exclude>**/NOTICE.txt</exclude>
+                                <exclude>**/LICENSE.txt</exclude>
+                                <exclude>doap.rdf</exclude>
+                                <exclude>**/README</exclude>
+                                <exclude>**/*.adoc</exclude>
+                                <exclude>**/node_modules/**</exclude>
+                                <exclude>**/cacerts</exclude>
+                                <exclude>**/*.p12</exclude>
+                                <exclude>**/*.txt</exclude>
+                                <exclude>.mvn/**</exclude>
+                                <exclude>mvnw*</exclude>
+                                <exclude>**/META-INF/persistence*.xsd</exclude>
+                            </excludes>
+                            <mapping>
+                                <java>SLASHSTAR_STYLE</java>
+                                <properties>CAMEL_PROPERTIES_STYLE</properties>
+                                <spring.factories>CAMEL_PROPERTIES_STYLE</spring.factories>
+                                <spring.provides>CAMEL_PROPERTIES_STYLE</spring.provides>
+                            </mapping>
+                            <headerDefinitions>
+                                <headerDefinition>license-properties-headerdefinition.xml</headerDefinition>
+                            </headerDefinitions>
+                        </configuration>
+                        <dependencies>
+                            <dependency>
+                                <groupId>org.apache.camel</groupId>
+                                <artifactId>camel-buildtools</artifactId>
+                                <version>${camel-version}</version>
+                            </dependency>
+                        </dependencies>
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+
+    </profiles>
+</project>