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 8d239dffb36a8ef3498e89f4dc812bb47ebbb91f
Author: Andrea Cosentino <anco...@gmail.com>
AuthorDate: Tue Mar 24 08:34:21 2020 +0100

    Added camel-kura to components
---
 components/camel-kura/pom.xml                      | 125 +++++++++
 .../services/org/apache/camel/other.properties     |   7 +
 .../camel-kura/src/generated/resources/kura.json   |  14 +
 components/camel-kura/src/main/docs/kura.adoc      | 298 +++++++++++++++++++++
 .../apache/camel/component/kura/KuraRouter.java    | 149 +++++++++++
 .../camel/component/kura/KuraRouterTest.java       | 144 ++++++++++
 .../src/test/resources/log4j2.properties           |  30 +++
 components/camel-kura/src/test/resources/route.xml |  25 ++
 components/pom.xml                                 |   1 +
 9 files changed, 793 insertions(+)

diff --git a/components/camel-kura/pom.xml b/components/camel-kura/pom.xml
new file mode 100644
index 0000000..8b1f4af
--- /dev/null
+++ b/components/camel-kura/pom.xml
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+    Licensed to the Apache Software Foundation (ASF) under one or more
+    contributor license agreements.  See the NOTICE file distributed with
+    this work for additional information regarding copyright ownership.
+    The ASF licenses this file to You under the Apache License, Version 2.0
+    (the "License"); you may not use this file except in compliance with
+    the License.  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+    Unless required by applicable law or agreed to in writing, software
+    distributed under the License is distributed on an "AS IS" BASIS,
+    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+    See the License for the specific language governing permissions and
+    limitations under the License.
+
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+
+    <modelVersion>4.0.0</modelVersion>
+
+    <parent>
+        <groupId>org.apache.camel.karaf</groupId>
+        <artifactId>components</artifactId>
+        <version>3.2.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>camel-kura</artifactId>
+    <packaging>jar</packaging>
+    <name>Camel :: Kura</name>
+    <description>Using Camel with Eclipse Kura (OSGi)</description>
+
+    <properties>
+        <firstVersion>2.15.0</firstVersion>
+        <label>iot,osgi</label>
+
+    </properties>
+
+    <dependencies>
+
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-support</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-core-osgi</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.framework</artifactId>
+            <version>${felix-framework-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.configadmin</artifactId>
+            <version>${felix-configadmin-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr</artifactId>
+            <version>${felix-scr-version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+            <version>${felix-scr-annotations-version}</version>
+        </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>
+
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-test</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-xml-jaxb</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-mock</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.camel</groupId>
+            <artifactId>camel-direct</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.mockito</groupId>
+            <artifactId>mockito-core</artifactId>
+            <scope>test</scope>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+
+</project>
diff --git 
a/components/camel-kura/src/generated/resources/META-INF/services/org/apache/camel/other.properties
 
b/components/camel-kura/src/generated/resources/META-INF/services/org/apache/camel/other.properties
new file mode 100644
index 0000000..343cb4c
--- /dev/null
+++ 
b/components/camel-kura/src/generated/resources/META-INF/services/org/apache/camel/other.properties
@@ -0,0 +1,7 @@
+# Generated by camel build tools - do NOT edit this file!
+name=kura
+groupId=org.apache.camel
+artifactId=camel-kura
+version=3.2.0-SNAPSHOT
+projectName=Camel :: Kura
+projectDescription=Using Camel with Eclipse Kura (OSGi)
diff --git a/components/camel-kura/src/generated/resources/kura.json 
b/components/camel-kura/src/generated/resources/kura.json
new file mode 100644
index 0000000..1d8e69d
--- /dev/null
+++ b/components/camel-kura/src/generated/resources/kura.json
@@ -0,0 +1,14 @@
+{
+  "other": {
+    "kind": "other",
+    "name": "kura",
+    "title": "Kura",
+    "description": "Using Camel with Eclipse Kura (OSGi)",
+    "deprecated": false,
+    "firstVersion": "2.15.0",
+    "label": "iot,osgi",
+    "groupId": "org.apache.camel",
+    "artifactId": "camel-kura",
+    "version": "3.2.0-SNAPSHOT"
+  }
+}
diff --git a/components/camel-kura/src/main/docs/kura.adoc 
b/components/camel-kura/src/main/docs/kura.adoc
new file mode 100644
index 0000000..43945d5
--- /dev/null
+++ b/components/camel-kura/src/main/docs/kura.adoc
@@ -0,0 +1,298 @@
+[[Kura-EclipseKuracomponent]]
+= Eclipse Kura component
+
+*Since Camel 2.15*
+
+This documentation page covers the integration options of Camel with the
+https://eclipse.org/kura/[Eclipse Kura] M2M gateway. The common reason
+to deploy Camel routes into the Eclipse Kura is to provide enterprise
+integration patterns and Camel components to the messaging M2M gateway.
+For example you might want to install Kura on Raspberry PI, then read
+temperature from the sensor attached to that Raspberry PI using Kura
+services and finally forward the current temperature value to your data
+center service using Camel EIP and components.
+
+[[Kura-KuraRouteractivator]]
+== KuraRouter activator
+
+Bundles deployed to the Eclipse Kura are usually
+http://eclipse.github.io/kura/doc/hello-example.html#create-java-class[developed
+as bundle activators]. So the easiest way to deploy Apache Camel routes
+into the Kura is to create an OSGi bundle containing the class extending
+`org.apache.camel.kura.KuraRouter` class:
+
+[source,java]
+-------------------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+
+  @Override
+  public void configure() throws Exception {
+    from("timer:trigger").
+      to("netty-http:http://app.mydatacenter.com/api";);
+  }
+
+}
+-------------------------------------------------------
+
+Keep in mind that `KuraRouter` implements
+the `org.osgi.framework.BundleActivator` interface, so you need to
+register its `start` and `stop` lifecycle methods
+while 
http://eclipse.github.io/kura/doc/hello-example.html#create-component-class[creating
+Kura bundle component class].
+
+Kura router starts its own OSGi-aware `CamelContext`. It means that for
+every class extending `KuraRouter`, there will be a dedicated
+`CamelContext` instance. Ideally we recommend to deploy one `KuraRouter`
+per OSGi bundle.
+
+[[Kura-DeployingKuraRouter]]
+=== Deploying KuraRouter
+
+Bundle containing your Kura router class should import the following
+packages in the OSGi manifest:
+
+[source,xml]
+--------------------------------------------------------------------------------------------------------------------
+Import-Package: org.osgi.framework;version="1.3.0",
+  org.slf4j;version="1.6.4",
+  
org.apache.camel,org.apache.camel.impl,org.apache.camel.core.osgi,org.apache.camel.builder,org.apache.camel.model,
+  org.apache.camel.component.kura
+--------------------------------------------------------------------------------------------------------------------
+
+Keep in mind that you don't have to import every Camel component bundle
+you plan to use in your routes, as Camel components are resolved as the
+services on the runtime level.
+
+Before you deploy your router bundle, be sure that you have deployed
+(and started) the following Camel core bundles (using Kura GoGo
+shell)...
+
+[source,xml]
+-----------------------------------------------------------------------------------------------------------
+install 
file:///home/user/.m2/repository/org/apache/camel/camel-core/2.15.0/camel-core-2.15.0.jar
+start <camel-core-bundle-id>
+install 
file:///home/user/.m2/repository/org/apache/camel/camel-core-osgi/2.15.0/camel-core-osgi-2.15.0.jar
+start <camel-core-osgi-bundle-id>
+install 
file:///home/user/.m2/repository/org/apache/camel/camel-kura/2.15.0/camel-kura-2.15.0.jar
 
+start <camel-kura-bundle-id>
+-----------------------------------------------------------------------------------------------------------
+
+...and all the components you plan to use in your routes:
+
+[source,xml]
+-----------------------------------------------------------------------------------------------------
+install 
file:///home/user/.m2/repository/org/apache/camel/camel-stream/2.15.0/camel-stream-2.15.0.jar
+start <camel-stream-bundle-id>
+-----------------------------------------------------------------------------------------------------
+
+Then finally deploy your router bundle:
+
+[source,xml]
+----------------------------------------------------------------------------------
+install 
file:///home/user/.m2/repository/com/example/myrouter/1.0/myrouter-1.0.jar
+start <your-bundle-id>
+----------------------------------------------------------------------------------
+
+[[Kura-KuraRouterutilities]]
+=== KuraRouter utilities 
+
+ Kura router base class provides many useful utilities. This section
+explores each of them.
+
+[[Kura-SLF4Jlogger]]
+==== SLF4J logger
+
+Kura uses SLF4J facade for logging purposes. Protected member `log`
+returns SLF4J logger instance associated with the given Kura router.
+
+[source,java]
+----------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+
+    @Override
+    public void configure() throws Exception {
+        log.info("Configuring Camel routes!");
+        ...
+    }
+
+}
+----------------------------------------------
+
+[[Kura-BundleContext]]
+==== BundleContext
+
+Protected member `bundleContext` returns bundle context associated with
+the given Kura router.
+
+[source,java]
+---------------------------------------------------------------------------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+
+    @Override
+    public void configure() throws Exception {
+        ServiceReference<MyService> serviceRef = 
bundleContext.getServiceReference(LogService.class.getName());
+        MyService myService = bundleContext.getService(serviceRef);
+        ...
+    }
+
+}
+---------------------------------------------------------------------------------------------------------------
+
+[[Kura-CamelContext]]
+==== CamelContext
+
+Protected member `camelContext` is the `CamelContext` associated with
+the given Kura router.
+
+[source,java]
+----------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+
+    @Override
+    public void configure() throws Exception {
+        camelContext.getStatus();
+        ...
+    }
+
+}
+----------------------------------------------
+
+[[Kura-ProducerTemplate]]
+==== ProducerTemplate
+
+Protected member `producerTemplate` is the `ProducerTemplate` instance
+associated with the given Camel context.
+
+[source,java]
+-----------------------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+
+    @Override
+    public void configure() throws Exception {
+        producerTemplate.sendBody("jms:temperature", 22.0);
+        ...
+    }
+
+}
+-----------------------------------------------------------
+
+[[Kura-ConsumerTemplate]]
+==== ConsumerTemplate
+
+Protected member `consumerTemplate` is the `ConsumerTemplate` instance
+associated with the given Camel context.
+
+[source,java]
+--------------------------------------------------------------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+
+    @Override
+    public void configure() throws Exception {
+        double currentTemperature = 
producerTemplate.receiveBody("jms:temperature", Double.class);
+        ...
+    }
+
+}
+--------------------------------------------------------------------------------------------------
+
+[[Kura-OSGiserviceresolver]]
+==== OSGi service resolver
+
+OSGi service resolver (`service(Class<T> serviceType)`) can be used to
+easily retrieve service by type from the OSGi bundle context.
+
+[source,java]
+-------------------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+
+    @Override
+    public void configure() throws Exception {
+        MyService myService = service(MyService.class);
+        ...
+    }
+
+}
+-------------------------------------------------------
+
+If service is not found, a `null` value is returned. If you want your
+application to fail if the service is not available, use
+`requiredService(Class)` method instead. The `requiredService` throws
+`IllegalStateException` if a service cannot be found.
+
+[source,java]
+---------------------------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+
+    @Override
+    public void configure() throws Exception {
+        MyService myService = requiredService(MyService.class);
+        ...
+    }
+
+}
+---------------------------------------------------------------
+
+[[Kura-KuraRouteractivatorcallbacks]]
+=== KuraRouter activator callbacks
+
+Kura router comes with the lifecycle callbacks that can be used to
+customize the way the Camel router works. For example to configure the
+`CamelContext` instance associated with the router just before the
+former is started, override `beforeStart` method of the `KuraRouter`
+class:
+
+[source,java]
+--------------------------------------------------------------------------
+public class MyKuraRouter extends KuraRouter {
+ 
+  ...
+
+  protected void beforeStart(CamelContext camelContext) {
+    OsgiDefaultCamelContext osgiContext = (OsgiCamelContext) camelContext;
+    osgiContext.setName("NameOfTheRouter");
+  }
+
+}
+--------------------------------------------------------------------------
+
+[[Kura-LoadingXMLroutesfromConfigurationAdmin]]
+=== Loading XML routes from ConfigurationAdmin
+
+Sometimes it is desired to read the XML definition of the routes from
+the server configuration. This a common scenario for IoT gateways where
+over-the-air redeployment cost may be significant. To address this
+requirement each `KuraRouter` looks for the
+`kura.camel.BUNDLE-SYMBOLIC-NAME.route` property from the `kura.camel`
+PID using the OSGi ConfigurationAdmin. This approach allows you to
+define Camel XML routes file per deployed `KuraRouter`. In order to
+update a route, just edit an appropriate configuration property and
+restart a bundle associated with it. The content of
+the `kura.camel.BUNDLE-SYMBOLIC-NAME.route` property is expected to be
+Camel XML route file, for example:
+
+[source,java]
+------------------------------------------------------
+<routes xmlns="http://camel.apache.org/schema/spring";>
+    <route id="loaded">
+        <from uri="direct:bar"/>
+        <to uri="mock:bar"/>
+    </route>
+</routes>
+------------------------------------------------------
+
+ 
+
+[[Kura-DeployingKurarouterasadeclarativeOSGiservice]]
+=== Deploying Kura router as a declarative OSGi service
+
+If you would like to deploy your Kura router as a declarative OSGi
+service, you can use `activate` and `deactivate` methods provided by
+`KuraRouter`.
+
+[source,java]
+----------------------------------------------------------------------------------------------------------------------------------------------
+<scr:component name="org.eclipse.kura.example.camel.MyKuraRouter" 
activate="activate" deactivate="deactivate" enabled="true" immediate="true">
+  <implementation class="org.eclipse.kura.example.camel.MyKuraRouter"/>
+</scr:component>
+----------------------------------------------------------------------------------------------------------------------------------------------
+
diff --git 
a/components/camel-kura/src/main/java/org/apache/camel/component/kura/KuraRouter.java
 
b/components/camel-kura/src/main/java/org/apache/camel/component/kura/KuraRouter.java
new file mode 100644
index 0000000..6f48073
--- /dev/null
+++ 
b/components/camel-kura/src/main/java/org/apache/camel/component/kura/KuraRouter.java
@@ -0,0 +1,149 @@
+/*
+ * 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.component.kura;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Map;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ConsumerTemplate;
+import org.apache.camel.ExtendedCamelContext;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.builder.RouteBuilder;
+import org.apache.camel.core.osgi.OsgiDefaultCamelContext;
+import org.apache.camel.model.Model;
+import org.apache.camel.model.RoutesDefinition;
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public abstract class KuraRouter extends RouteBuilder implements 
BundleActivator {
+
+    // Member collaborators
+
+    protected final Logger log = LoggerFactory.getLogger(getClass());
+
+    protected BundleContext bundleContext;
+
+    protected CamelContext camelContext;
+
+    protected ProducerTemplate producerTemplate;
+
+    protected ConsumerTemplate consumerTemplate;
+
+    // Lifecycle
+
+    @Override
+    public void start(BundleContext bundleContext) throws Exception {
+        try {
+            this.bundleContext = bundleContext;
+            log.debug("Initializing bundle {}.", 
bundleContext.getBundle().getBundleId());
+            camelContext = createCamelContext();
+
+            camelContext.addRoutes(this);
+            ConfigurationAdmin configurationAdmin = 
requiredService(ConfigurationAdmin.class);
+            Configuration camelKuraConfig = 
configurationAdmin.getConfiguration(camelXmlRoutesPid());
+            if (camelKuraConfig != null && camelKuraConfig.getProperties() != 
null) {
+                Object routePropertyValue = 
camelKuraConfig.getProperties().get(camelXmlRoutesProperty());
+                if (routePropertyValue != null) {
+                    InputStream routesXml = new 
ByteArrayInputStream(routePropertyValue.toString().getBytes());
+                    ExtendedCamelContext ecc = 
camelContext.adapt(ExtendedCamelContext.class);
+                    RoutesDefinition routes = (RoutesDefinition) 
ecc.getXMLRoutesDefinitionLoader().loadRoutesDefinition(ecc, routesXml);
+                    
camelContext.getExtension(Model.class).addRouteDefinitions(routes.getRoutes());
+                }
+            }
+
+            beforeStart(camelContext);
+            log.debug("About to start Camel Kura router: {}", 
getClass().getName());
+            camelContext.start();
+            producerTemplate = camelContext.createProducerTemplate();
+            consumerTemplate = camelContext.createConsumerTemplate();
+            log.debug("Bundle {} started.", 
bundleContext.getBundle().getBundleId());
+        } catch (Throwable e) {
+            String errorMessage = "Problem when starting Kura module " + 
getClass().getName() + ":";
+            log.warn(errorMessage, e);
+
+            // Print error to the Kura console.
+            System.err.println(errorMessage);
+            e.printStackTrace();
+
+            throw e;
+        }
+    }
+
+    @Override
+    public void stop(BundleContext bundleContext) throws Exception {
+        log.debug("Stopping bundle {}.", 
bundleContext.getBundle().getBundleId());
+        camelContext.stop();
+        log.debug("Bundle {} stopped.", 
bundleContext.getBundle().getBundleId());
+    }
+
+    protected void activate(ComponentContext componentContext, Map<String, 
Object> properties) throws Exception {
+        start(componentContext.getBundleContext());
+    }
+
+    protected void deactivate(ComponentContext componentContext) throws 
Exception {
+        stop(componentContext.getBundleContext());
+    }
+
+    // Callbacks
+
+    @Override
+    public void configure() throws Exception {
+        log.debug("No programmatic routes configuration found.");
+    }
+
+    protected CamelContext createCamelContext() {
+        return new OsgiDefaultCamelContext(bundleContext);
+    }
+
+    protected void beforeStart(CamelContext camelContext) {
+        log.debug("Empty KuraRouter CamelContext before start configuration - 
skipping.");
+    }
+
+    // API Helpers
+
+    protected <T> T service(Class<T> serviceType) {
+        ServiceReference reference = 
bundleContext.getServiceReference(serviceType.getName());
+        return reference == null ? null : (T) 
bundleContext.getService(reference);
+    }
+
+    protected <T> T requiredService(Class<T> serviceType) {
+        ServiceReference reference = 
bundleContext.getServiceReference(serviceType.getName());
+        if (reference == null) {
+            throw new IllegalStateException("Cannot find service: " + 
serviceType.getName());
+        }
+        return (T) bundleContext.getService(reference);
+    }
+
+    // Private helpers
+
+    protected String camelXmlRoutesPid() {
+        return "kura.camel";
+    }
+
+    protected String camelXmlRoutesProperty() {
+        return "kura.camel." + bundleContext.getBundle().getSymbolicName() + 
".route";
+    }
+
+}
diff --git 
a/components/camel-kura/src/test/java/org/apache/camel/component/kura/KuraRouterTest.java
 
b/components/camel-kura/src/test/java/org/apache/camel/component/kura/KuraRouterTest.java
new file mode 100644
index 0000000..7cb653b
--- /dev/null
+++ 
b/components/camel-kura/src/test/java/org/apache/camel/component/kura/KuraRouterTest.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.component.kura;
+
+import java.nio.charset.StandardCharsets;
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.apache.camel.CamelContext;
+import org.apache.camel.ServiceStatus;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.apache.camel.impl.DefaultCamelContext;
+import org.apache.camel.model.Model;
+import org.apache.commons.io.IOUtils;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.cm.Configuration;
+import org.osgi.service.cm.ConfigurationAdmin;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.BDDMockito.given;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
+import static org.mockito.Mockito.mock;
+
+public class KuraRouterTest extends Assert {
+
+    TestKuraRouter router = new TestKuraRouter();
+
+    BundleContext bundleContext = mock(BundleContext.class, 
RETURNS_DEEP_STUBS);
+
+    ConfigurationAdmin configurationAdmin = mock(ConfigurationAdmin.class);
+
+    Configuration configuration = mock(Configuration.class);
+
+    @Before
+    public void before() throws Exception {
+        
given(bundleContext.getBundle().getVersion().toString()).willReturn("version");
+        
given(bundleContext.getBundle().getSymbolicName()).willReturn("symbolic_name");
+        
given(bundleContext.getService(any(ServiceReference.class))).willReturn(configurationAdmin);
+
+        router.start(bundleContext);
+    }
+
+    @After
+    public void after() throws Exception {
+        router.stop(bundleContext);
+    }
+
+    @Test
+    public void shouldCloseCamelContext() throws Exception {
+        // When
+        router.stop(bundleContext);
+
+        // Then
+        Assert.assertEquals(ServiceStatus.Stopped, 
router.camelContext.getStatus());
+    }
+
+    @Test
+    public void shouldStartCamelContext() throws Exception {
+        // Given
+        String message = "foo";
+        MockEndpoint mockEndpoint = 
router.camelContext.getEndpoint("mock:test", MockEndpoint.class);
+        mockEndpoint.expectedBodiesReceived(message);
+
+        // When
+        router.producerTemplate.sendBody("direct:start", message);
+
+        // Then
+        mockEndpoint.assertIsSatisfied();
+    }
+
+    @Test
+    public void shouldCreateConsumerTemplate() throws Exception {
+        assertNotNull(router.consumerTemplate);
+    }
+
+    @Test
+    public void shouldReturnNoService() {
+        
given(bundleContext.getServiceReference(any(String.class))).willReturn(null);
+        assertNull(router.service(ConfigurationAdmin.class));
+    }
+
+    @Test
+    public void shouldReturnService() {
+        assertNotNull(router.service(ConfigurationAdmin.class));
+    }
+
+    @Test(expected = IllegalStateException.class)
+    public void shouldValidateLackOfService() {
+        
given(bundleContext.getServiceReference(any(String.class))).willReturn(null);
+        router.requiredService(ConfigurationAdmin.class);
+    }
+
+    @Test
+    public void shouldLoadXmlRoutes() throws Exception {
+        // Given
+        
given(configurationAdmin.getConfiguration(anyString())).willReturn(configuration);
+        Dictionary<String, Object> properties = new Hashtable<>();
+        String routeDefinition = 
IOUtils.toString(getClass().getResource("/route.xml"), StandardCharsets.UTF_8);
+        properties.put("kura.camel.symbolic_name.route", routeDefinition);
+        given(configuration.getProperties()).willReturn(properties);
+
+        // When
+        router.start(router.bundleContext);
+
+        // Then
+        
assertNotNull(router.camelContext.getExtension(Model.class).getRouteDefinition("loaded"));
+    }
+
+    static class TestKuraRouter extends KuraRouter {
+
+        @Override
+        public void configure() throws Exception {
+            from("direct:start").to("mock:test");
+        }
+
+        @Override
+        protected CamelContext createCamelContext() {
+            return new DefaultCamelContext();
+        }
+
+    }
+
+}
+
diff --git a/components/camel-kura/src/test/resources/log4j2.properties 
b/components/camel-kura/src/test/resources/log4j2.properties
new file mode 100644
index 0000000..d3198e9
--- /dev/null
+++ b/components/camel-kura/src/test/resources/log4j2.properties
@@ -0,0 +1,30 @@
+## ---------------------------------------------------------------------------
+## 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.console.type = Console
+appender.console.name = console
+appender.console.layout.type = PatternLayout
+appender.console.layout.pattern = %d %-5p %c{1} - %m %n
+appender.file.type = File
+appender.file.name = file
+appender.file.fileName = target/camel-kura.log
+appender.file.layout.type = PatternLayout
+appender.file.layout.pattern = %d %-5p %c{1} - %m %n
+logger.kura.name = org.apache.camel.component.kura
+logger.kura.level = DEBUG
+rootLogger.level = INFO
+rootLogger.appenderRef.file.ref = file
diff --git a/components/camel-kura/src/test/resources/route.xml 
b/components/camel-kura/src/test/resources/route.xml
new file mode 100644
index 0000000..3999ef3
--- /dev/null
+++ b/components/camel-kura/src/test/resources/route.xml
@@ -0,0 +1,25 @@
+<?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.
+
+-->
+<routes xmlns="http://camel.apache.org/schema/spring";>
+    <route id="loaded">
+        <from uri="direct:bar"/>
+        <to uri="mock:bar"/>
+    </route>
+</routes>
diff --git a/components/pom.xml b/components/pom.xml
index 1914ce9..19a1315 100644
--- a/components/pom.xml
+++ b/components/pom.xml
@@ -31,6 +31,7 @@
     <packaging>pom</packaging>
 
     <modules>
+        <module>camel-kura</module> 
         <module>camel-paxlogging</module>
     </modules>
 

Reply via email to