You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2017/11/20 20:33:26 UTC

[29/46] celix git commit: CELIX-417: Initial refactoring for CMake usage

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/json_rpc_tests.cpp
----------------------------------------------------------------------
diff --git a/dfi/test/json_rpc_tests.cpp b/dfi/test/json_rpc_tests.cpp
new file mode 100644
index 0000000..bff582e
--- /dev/null
+++ b/dfi/test/json_rpc_tests.cpp
@@ -0,0 +1,433 @@
+/**
+ *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.
+ */
+#include <CppUTest/TestHarness.h>
+#include <float.h>
+#include <assert.h>
+#include "CppUTest/CommandLineTestRunner.h"                                                                                                                                                                        
+
+extern "C" {
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <ffi.h>
+
+#include "dyn_common.h"
+#include "dyn_type.h"
+#include "json_serializer.h"
+#include "json_rpc.h"
+
+static void stdLog(void*, int level, const char *file, int line, const char *msg, ...) {
+    va_list ap;
+    const char *levels[5] = {"NIL", "ERROR", "WARNING", "INFO", "DEBUG"};
+    fprintf(stderr, "%s: FILE:%s, LINE:%i, MSG:",levels[level], file, line);
+    va_start(ap, msg);
+    vfprintf(stderr, msg, ap);
+    fprintf(stderr, "\n");
+    va_end(ap);
+}
+
+
+    void prepareTest(void) {
+        dyn_function_type *dynFunc = NULL;
+        int rc = dynFunction_parseWithStr("add(#am=handle;PDD#am=pre;*D)N", NULL, &dynFunc);
+        CHECK_EQUAL(0, rc);
+
+        char *result = NULL;
+
+        void *handle = NULL;
+        double arg1 = 1.0;
+        double arg2 = 2.0;
+
+        void *args[4];
+        args[0] = &handle;
+        args[1] = &arg1;
+        args[2] = &arg2;
+
+        rc = jsonRpc_prepareInvokeRequest(dynFunc, "add", args, &result);
+        CHECK_EQUAL(0, rc);
+
+        //printf("result is %s\n", result);
+
+        STRCMP_CONTAINS("\"add\"", result);
+        STRCMP_CONTAINS("1.0", result);
+        STRCMP_CONTAINS("2.0", result);
+
+        free(result);
+        dynFunction_destroy(dynFunc);
+    }
+
+    void handleTestPre(void) {
+        dyn_function_type *dynFunc = NULL;
+        int rc = dynFunction_parseWithStr("add(#am=handle;PDD#am=pre;*D)N", NULL, &dynFunc);
+        CHECK_EQUAL(0, rc);
+
+        const char *reply = "{\"r\":2.2}";
+        double result = -1.0;
+        double *out = &result;
+        void *args[4];
+        args[3] = &out;
+        rc = jsonRpc_handleReply(dynFunc, reply, args);
+        CHECK_EQUAL(0, rc);
+        //CHECK_EQUAL(2.2, result);
+
+        dynFunction_destroy(dynFunc);
+    }
+
+    int add(void*, double a, double b, double *result) {
+        *result = a + b;
+        return 0;
+    }
+
+    int getName_example4(void*, char** result) {
+        *result = strdup("allocatedInFunction");
+        return 0;
+    }
+
+    struct tst_seq {
+        uint32_t cap;
+        uint32_t len;
+        double *buf;
+    };
+
+
+    //StatsResult={DDD[D average min max input}
+    struct tst_StatsResult {
+        double average;
+        double min;
+        double max;
+        struct tst_seq input;
+    };
+
+
+    int stats(void*, struct tst_seq input, struct tst_StatsResult **out) {
+        assert(out != NULL);
+        assert(*out == NULL);
+        double total = 0.0;
+        unsigned int count = 0;
+        double max = DBL_MIN;
+        double min = DBL_MAX;
+
+        unsigned int i;
+        for (i = 0; i<input.len; i += 1) {
+            total += input.buf[i];
+            count += 1;
+            if (input.buf[i] > max) {
+                max = input.buf[i];
+            }
+            if (input.buf[i] < min) {
+                min = input.buf[i];
+            }
+        }
+
+        struct tst_StatsResult *result = (struct tst_StatsResult *) calloc(1, sizeof(*result));
+        if(count>0){
+		result->average = total / count;
+        }
+        result->min = min;
+        result->max = max;
+        double *buf = (double *)calloc(input.len, sizeof(double));
+        memcpy(buf, input.buf, input.len * sizeof(double));
+        result->input.len = input.len;
+        result->input.cap = input.len;
+        result->input.buf = buf;
+
+        *out = result;
+        return 0;
+    }
+
+    struct item {
+        double a;
+        double b;
+    };
+
+    struct item_seq {
+        uint32_t  cap;
+        uint32_t  len;
+        struct item **buf;
+    };
+
+    struct tst_serv {
+        void *handle;
+        int (*add)(void *, double, double, double *);
+        int (*sub)(void *, double, double, double *);
+        int (*sqrt)(void *, double, double *);
+        int (*stats)(void *, struct tst_seq, struct tst_StatsResult **);
+    };
+
+    struct tst_serv_example4 {
+        void *handle;
+        int (*getName_example4)(void *, char** name);
+    };
+
+    void callTestPreAllocated(void) {
+        dyn_interface_type *intf = NULL;
+        FILE *desc = fopen("descriptors/example1.descriptor", "r");
+        CHECK(desc != NULL);
+        int rc = dynInterface_parse(desc, &intf);
+        CHECK_EQUAL(0, rc);
+        fclose(desc);
+
+        char *result = NULL;
+
+        struct tst_serv serv;
+        serv.handle = NULL;
+        serv.add = add;
+
+
+        rc = jsonRpc_call(intf, &serv, "{\"m\":\"add(DD)D\", \"a\": [1.0,2.0]}", &result);
+        CHECK_EQUAL(0, rc);
+        STRCMP_CONTAINS("3.0", result);
+
+        free(result);
+        dynInterface_destroy(intf);
+    }
+
+    void callTestOutput(void) {
+        dyn_interface_type *intf = NULL;
+        FILE *desc = fopen("descriptors/example1.descriptor", "r");
+        CHECK(desc != NULL);
+        int rc = dynInterface_parse(desc, &intf);
+        CHECK_EQUAL(0, rc);
+        fclose(desc);
+
+        char *result = NULL;
+
+        struct tst_serv serv;
+        serv.handle = NULL;
+        serv.stats = stats;
+
+        rc = jsonRpc_call(intf, &serv, "{\"m\":\"stats([D)LStatsResult;\", \"a\": [[1.0,2.0]]}", &result);
+        CHECK_EQUAL(0, rc);
+        STRCMP_CONTAINS("1.5", result); //avg
+
+        free(result);
+        dynInterface_destroy(intf);
+    }
+
+    void handleTestOut(void) {
+        dyn_interface_type *intf = NULL;
+        FILE *desc = fopen("descriptors/example1.descriptor", "r");
+        CHECK(desc != NULL);
+        int rc = dynInterface_parse(desc, &intf);
+        CHECK_EQUAL(0, rc);
+        fclose(desc);
+
+        struct methods_head *head;
+        dynInterface_methods(intf, &head);
+        dyn_function_type *func = NULL;
+        struct method_entry *entry = NULL;
+        TAILQ_FOREACH(entry, head, entries) {
+            if (strcmp(entry->name, "stats") == 0) {
+                func = entry->dynFunc;
+                break;
+            }
+        }
+        CHECK(func != NULL);
+
+        const char *reply = "{\"r\":{\"input\":[1.0,2.0],\"max\":2.0,\"average\":1.5,\"min\":1.0}}";
+
+        void *args[3];
+        args[0] = NULL;
+        args[1] = NULL;
+        args[2] = NULL;
+
+        struct tst_StatsResult *result = NULL;
+        void *out = &result;
+        args[2] = &out;
+
+        rc = jsonRpc_handleReply(func, reply, args);
+        CHECK_EQUAL(0, rc);
+        CHECK_EQUAL(1.5, result->average);
+
+        free(result->input.buf);
+        free(result);
+        dynInterface_destroy(intf);
+    }
+
+    static void handleTestOutputSequence(void) {
+        dyn_interface_type *intf = NULL;
+        FILE *desc = fopen("descriptors/example2.descriptor", "r");
+        CHECK(desc != NULL);
+        int rc = dynInterface_parse(desc, &intf);
+        CHECK_EQUAL(0, rc);
+        fclose(desc);
+
+        struct methods_head *head;
+        dynInterface_methods(intf, &head);
+        dyn_function_type *func = NULL;
+        struct method_entry *entry = NULL;
+        TAILQ_FOREACH(entry, head, entries) {
+            if (strcmp(entry->name, "example1") == 0) {
+                func = entry->dynFunc;
+                break;
+            }
+        }
+        CHECK(func != NULL);
+
+        //dyn_type *arg = dynFunction_argumentTypeForIndex(func, 1);
+        //dynType_print(arg, stdout);
+
+        const char *reply = "{\"r\":[{\"a\":1.0,\"b\":1.5},{\"a\":2.0,\"b\":2.5}]}";
+
+        void *args[2];
+        args[0] = NULL;
+        args[1] = NULL;
+
+        struct item_seq *result = NULL;
+        void *out = &result;
+        args[1] = &out;
+
+        rc = jsonRpc_handleReply(func, reply, args);
+        CHECK_EQUAL(0, rc);
+        CHECK_EQUAL(2, result->len);
+        CHECK_EQUAL(1.0, result->buf[0]->a);
+        CHECK_EQUAL(1.5, result->buf[0]->b);
+        CHECK_EQUAL(2.0, result->buf[1]->a);
+        CHECK_EQUAL(2.5, result->buf[1]->b);
+
+
+        unsigned int i;
+        for (i = 0; i < result->len; i +=1 ) {
+            free(result->buf[i]);
+        }
+        free(result->buf);
+        free(result);
+        dynInterface_destroy(intf);
+    }
+
+
+
+
+    void callTestOutChar(void) {
+        dyn_interface_type *intf = NULL;
+        FILE *desc = fopen("descriptors/example4.descriptor", "r");
+        CHECK(desc != NULL);
+        int rc = dynInterface_parse(desc, &intf);
+        CHECK_EQUAL(0, rc);
+        fclose(desc);
+
+        char *result = NULL;
+
+        struct tst_serv_example4 serv;
+        serv.handle = NULL;
+        serv.getName_example4 = getName_example4;
+
+        rc = jsonRpc_call(intf, &serv, "{\"m\":\"getName(V)t\", \"a\": []}", &result);
+        CHECK_EQUAL(0, rc);
+
+        STRCMP_CONTAINS("allocatedInFunction", result);
+
+        free(result);
+        dynInterface_destroy(intf);
+    }
+
+
+    void handleTestOutChar(void) {
+        dyn_interface_type *intf = NULL;
+        FILE *desc = fopen("descriptors/example4.descriptor", "r");
+        CHECK(desc != NULL);
+        int rc = dynInterface_parse(desc, &intf);
+        CHECK_EQUAL(0, rc);
+        fclose(desc);
+
+        struct methods_head *head;
+        dynInterface_methods(intf, &head);
+        dyn_function_type *func = NULL;
+        struct method_entry *entry = NULL;
+        TAILQ_FOREACH(entry, head, entries) {
+            if (strcmp(entry->name, "getName") == 0) {
+                func = entry->dynFunc;
+                break;
+            }
+        }
+
+        CHECK(func != NULL);
+
+        const char *reply = "{\"r\": \"this is a test string\" }";
+        char *result = NULL;
+        void *out = &result;
+
+        void *args[2];
+        args[0] = NULL;
+        args[1] = &out;
+
+        if(func!=NULL){ // Check needed just to satisfy Coverity
+		rc = jsonRpc_handleReply(func, reply, args);
+        }
+
+        STRCMP_EQUAL("this is a test string", result);
+
+        free(result);
+        dynInterface_destroy(intf);
+    }
+
+
+}
+
+TEST_GROUP(JsonRpcTests) {
+    void setup() {
+        int lvl = 1;
+        dynCommon_logSetup(stdLog, NULL, lvl);
+        dynType_logSetup(stdLog, NULL,lvl);
+        dynFunction_logSetup(stdLog, NULL,lvl);
+        dynInterface_logSetup(stdLog, NULL,lvl);
+        jsonSerializer_logSetup(stdLog, NULL, lvl);
+        jsonRpc_logSetup(stdLog, NULL, lvl);
+
+    }
+};
+
+
+TEST(JsonRpcTests, prepareTest) {
+    prepareTest();
+}
+
+TEST(JsonRpcTests, handleTestPre) {
+    handleTestPre();
+}
+
+TEST(JsonRpcTests, handleTestOut) {
+    handleTestOut();
+}
+
+TEST(JsonRpcTests, callPre) {
+    callTestPreAllocated();
+}
+
+TEST(JsonRpcTests, callOut) {
+    callTestOutput();
+}
+
+TEST(JsonRpcTests, handleOutSeq) {
+    handleTestOutputSequence();
+}
+
+
+
+TEST(JsonRpcTests, callTestOutChar) {
+    callTestOutChar();
+}
+
+TEST(JsonRpcTests, handleOutChar) {
+    handleTestOutChar();
+}
+

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/json_serializer_tests.cpp
----------------------------------------------------------------------
diff --git a/dfi/test/json_serializer_tests.cpp b/dfi/test/json_serializer_tests.cpp
new file mode 100644
index 0000000..a52e4cc
--- /dev/null
+++ b/dfi/test/json_serializer_tests.cpp
@@ -0,0 +1,558 @@
+/**
+ *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.
+ */
+#include <CppUTest/TestHarness.h>
+#include "CppUTest/CommandLineTestRunner.h"                                                                                                                                                                        
+
+extern "C" {
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include <ffi.h>
+
+#include "dyn_common.h"
+#include "dyn_type.h"
+#include "json_serializer.h"
+
+static void stdLog(void*, int level, const char *file, int line, const char *msg, ...) {
+	va_list ap;
+	const char *levels[5] = {"NIL", "ERROR", "WARNING", "INFO", "DEBUG"};
+	fprintf(stderr, "%s: FILE:%s, LINE:%i, MSG:",levels[level], file, line);
+	va_start(ap, msg);
+	vfprintf(stderr, msg, ap);
+	fprintf(stderr, "\n");
+	va_end(ap);
+}
+
+/*********** example 1 ************************/
+/** struct type ******************************/
+const char *example1_descriptor = "{DJISF a b c d e}";
+
+const char *example1_input = "{ \
+    \"a\" : 1.0, \
+    \"b\" : 22, \
+    \"c\" : 32, \
+    \"d\" : 42, \
+    \"e\" : 4.4 \
+}";
+
+struct example1 {
+	double a;   //0
+	int64_t b;  //1
+	int32_t c;  //2
+	int16_t d;  //3
+	float e;    //4
+};
+
+static void check_example1(void *data) {
+	struct example1 *ex = (struct example1 *)data;
+	CHECK_EQUAL(1.0, ex->a);
+	LONGS_EQUAL(22, ex->b);
+	LONGS_EQUAL(32, ex->c);
+	LONGS_EQUAL(42, ex->d);
+	CHECK_EQUAL(4.4f, ex->e);
+}
+
+/*********** example 2 ************************/
+const char *example2_descriptor = "{BJJDFD byte long1 long2 double1 float1 double2}";
+
+const char *example2_input = "{ \
+    \"byte\" : 42, \
+    \"long1\" : 232, \
+    \"long2\" : 242, \
+    \"double1\" : 4.2, \
+    \"float1\" : 3.2, \
+    \"double2\" : 4.4 \
+}";
+
+struct example2 {
+	char byte;      //0
+	int64_t long1;     //1
+	int64_t long2;     //2
+	double double1; //3
+	float float1;   //4
+	double double2; //5
+};
+
+static void check_example2(void *data) {
+	struct example2 *ex = (struct example2 *)data;
+	CHECK_EQUAL(42, ex->byte);
+	LONGS_EQUAL(232, ex->long1);
+	LONGS_EQUAL(242, ex->long2);
+	CHECK_EQUAL(4.2, ex->double1);
+	CHECK_EQUAL(3.2f, ex->float1);
+	CHECK_EQUAL(4.4, ex->double2);
+}
+
+
+/*********** example 3 ************************/
+/** sequence with a simple type **************/
+const char *example3_descriptor = "{[I numbers}";
+
+const char *example3_input = "{ \
+    \"numbers\" : [22,32,42] \
+}";
+
+struct example3 {
+	struct {
+		uint32_t cap;
+		uint32_t len;
+		int32_t *buf;
+	} numbers;
+};
+
+static void check_example3(void *data) {
+	struct example3 *ex = (struct example3 *)data;
+	CHECK_EQUAL(3, ex->numbers.len);
+	CHECK_EQUAL(22, ex->numbers.buf[0]);
+	CHECK_EQUAL(32, ex->numbers.buf[1]);
+	CHECK_EQUAL(42, ex->numbers.buf[2]);
+}
+
+/*********** example 4 ************************/
+/** structs within a struct (by reference)*******/
+const char *example4_descriptor = "{{IDD index val1 val2}{IDD index val1 val2} left right}";
+
+static const char *example4_input =  "{ \
+    \"left\" : {\"index\":1, \"val1\":1.0, \"val2\":2.0 }, \
+    \"right\" : {\"index\":2, \"val1\":5.0, \"val2\":4.0 } \
+}";
+
+struct ex4_leaf {
+	int32_t index;
+	double val1;
+	double val2;
+};
+
+struct example4 {
+	struct ex4_leaf left;
+	struct ex4_leaf right;
+};
+
+static void check_example4(void *data) {
+	struct example4 *ex = (struct example4 *)data;
+	CHECK_EQUAL(1, ex->left.index);
+	CHECK_EQUAL(1.0, ex->left.val1);
+	CHECK_EQUAL(2.0, ex->left.val2);
+	CHECK_EQUAL(2, ex->right.index);
+	CHECK_EQUAL(5.0, ex->right.val1);
+	CHECK_EQUAL(4.0, ex->right.val2);
+}
+
+
+/*********** example 5 ************************/
+/** structs within a struct (by reference)*******/
+const char *example5_descriptor = "Tleaf={ts name age};Tnode={Lnode;Lnode;Lleaf; left right value};{Lnode; head}";
+
+static const char *example5_input =  "{ \
+    \"head\" : {\
+        \"left\" : {\
+            \"value\" : {\
+                \"name\" : \"John\",\
+                \"age\" : 44 \
+            }\
+        },\
+        \"right\" : {\
+            \"value\" : {\
+                \"name\" : \"Peter\", \
+                \"age\" : 55 \
+            }\
+        }\
+    }\
+}";
+
+struct leaf {
+	const char *name;
+	uint16_t age;
+};
+
+struct node {
+	struct node *left;
+	struct node *right;
+	struct leaf *value;
+};
+
+struct example5 {
+	struct node *head;
+};
+
+static void check_example5(void *data) {
+	struct example5 *ex = (struct example5 *)data;
+	CHECK_TRUE(ex->head != NULL);
+
+	CHECK(ex->head->left != NULL);
+	CHECK(ex->head->left->value != NULL);
+	STRCMP_EQUAL("John", ex->head->left->value->name);
+	CHECK_EQUAL(44, ex->head->left->value->age);
+	CHECK(ex->head->left->left == NULL);
+	CHECK(ex->head->left->right == NULL);
+
+	CHECK(ex->head->right != NULL);
+	CHECK(ex->head->right->value != NULL);
+	STRCMP_EQUAL("Peter", ex->head->right->value->name);
+	CHECK_EQUAL(55, ex->head->right->value->age);
+	CHECK(ex->head->right->left == NULL);
+	CHECK(ex->head->right->right == NULL);
+}
+
+static const char *example6_descriptor = "Tsample={DD v1 v2};[lsample;";
+
+static const char *example6_input = "[{\"v1\":0.1,\"v2\":0.2},{\"v1\":1.1,\"v2\":1.2},{\"v1\":2.1,\"v2\":2.2}]";
+
+struct ex6_sample {
+	double v1;
+	double v2;
+};
+
+struct ex6_sequence {
+	uint32_t cap;
+	uint32_t len;
+	struct ex6_sample *buf;
+};
+
+static void check_example6(struct ex6_sequence seq) {
+	CHECK_EQUAL(3, seq.cap);
+	CHECK_EQUAL(3, seq.len);
+	CHECK_EQUAL(0.1, seq.buf[0].v1);
+	CHECK_EQUAL(0.2, seq.buf[0].v2);
+	CHECK_EQUAL(1.1, seq.buf[1].v1);
+	CHECK_EQUAL(1.2, seq.buf[1].v2);
+	CHECK_EQUAL(2.1, seq.buf[2].v1);
+	CHECK_EQUAL(2.2, seq.buf[2].v2);
+}
+
+
+/*********** example 7 ************************/
+const char *example7_descriptor = "{t a}";
+
+const char *example7_input = "{ \
+    \"a\" : \"apache celix\" \
+}";
+
+struct example7 {
+	char* a;   //0
+};
+
+static void check_example7(void *data) {
+	struct example7 *ex = (struct example7 *)data;
+	STRCMP_EQUAL("apache celix", ex->a);
+}
+
+
+/*********** example 8 ************************/
+
+const char *example8_descriptor = "{ZbijNP a b c d e f}";
+
+const char *example8_input = "{ \
+    \"a\" : true, \
+    \"b\" : 4, \
+    \"c\" : 8, \
+    \"d\" : 16, \
+    \"e\" : 32 \
+}";
+
+struct example8 {
+	bool a;
+	unsigned char b;
+	uint32_t c;
+	uint64_t d;
+	int e;
+	void* f;
+};
+
+static void check_example8(void *data) {
+	struct example8 *ex = (struct example8 *)data;
+	CHECK_EQUAL(true,ex->a);
+	CHECK_EQUAL(4,ex->b);
+	CHECK_EQUAL(8,ex->c);
+	//error on mac CHECK_EQUAL(16,ex->d);
+    CHECK(16 == ex->d)
+	CHECK_EQUAL(32,ex->e);
+}
+
+
+static void parseTests(void) {
+	dyn_type *type;
+	void *inst;
+	int rc;
+
+	type = NULL;
+	inst = NULL;
+	rc = dynType_parseWithStr(example1_descriptor, NULL, NULL, &type);
+	CHECK_EQUAL(0, rc);
+	rc = jsonSerializer_deserialize(type, example1_input, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example1(inst);
+	dynType_free(type, inst);
+	dynType_destroy(type);
+
+	type = NULL;
+	inst = NULL;
+	rc = dynType_parseWithStr(example2_descriptor, NULL, NULL, &type);
+	CHECK_EQUAL(0, rc);
+	rc = jsonSerializer_deserialize(type, example2_input, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example2(inst);
+	dynType_free(type, inst);
+	dynType_destroy(type);
+
+	type = NULL;
+	inst = NULL;
+	rc = dynType_parseWithStr(example3_descriptor, NULL, NULL, &type);
+	CHECK_EQUAL(0, rc);
+	rc = jsonSerializer_deserialize(type, example3_input, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example3(inst);
+	dynType_free(type, inst);
+	dynType_destroy(type);
+
+	type = NULL;
+	inst = NULL;
+	rc = dynType_parseWithStr(example4_descriptor, NULL, NULL, &type);
+	CHECK_EQUAL(0, rc);
+	rc = jsonSerializer_deserialize(type, example4_input, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example4(inst);
+	dynType_free(type, inst);
+	dynType_destroy(type);
+
+	type = NULL;
+	inst = NULL;
+	rc = dynType_parseWithStr(example5_descriptor, NULL, NULL, &type);
+	CHECK_EQUAL(0, rc);
+	rc = jsonSerializer_deserialize(type, example5_input, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example5(inst);
+	dynType_free(type, inst);
+	dynType_destroy(type);
+
+	type = NULL;
+	struct ex6_sequence *seq;
+	rc = dynType_parseWithStr(example6_descriptor, NULL, NULL, &type);
+	CHECK_EQUAL(0, rc);
+	rc = jsonSerializer_deserialize(type, example6_input, (void **)&seq);
+	CHECK_EQUAL(0, rc);
+	check_example6((*seq));
+	dynType_free(type, seq);
+	dynType_destroy(type);
+
+
+	type = NULL;
+	inst = NULL;
+	rc = dynType_parseWithStr(example7_descriptor, NULL, NULL, &type);
+	CHECK_EQUAL(0, rc);
+	rc = jsonSerializer_deserialize(type, example7_input, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example7(inst);
+	dynType_free(type, inst);
+	dynType_destroy(type);
+
+	type = NULL;
+	inst = NULL;
+	rc = dynType_parseWithStr(example8_descriptor, NULL, NULL, &type);
+	CHECK_EQUAL(0, rc);
+	rc = jsonSerializer_deserialize(type, example8_input, &inst);
+	CHECK_EQUAL(0, rc);
+	check_example8(inst);
+	dynType_free(type, inst);
+	dynType_destroy(type);
+}
+
+const char *write_example1_descriptor = "{BSIJsijFDNZb a b c d e f g h i j k l}";
+
+struct write_example1 {
+	char a;
+	int16_t b;
+	int32_t c;
+	int64_t d;
+	uint16_t e;
+	uint32_t f;
+	uint64_t g;
+	float h;
+	double i;
+	int j;
+	bool k;
+	unsigned char l;
+};
+
+void writeTest1(void) {
+	struct write_example1 ex1;
+	ex1.a=1;
+	ex1.b=2;
+	ex1.c=3;
+	ex1.d=4;
+	ex1.e=5;
+	ex1.f=6;
+	ex1.g=7;
+	ex1.h=8.8f;
+	ex1.i=9.9;
+	ex1.j=10;
+	ex1.k=true;
+	ex1.l=12;
+
+	dyn_type *type = NULL;
+	char *result = NULL;
+	int rc = dynType_parseWithStr(write_example1_descriptor, "ex1", NULL, &type);
+	CHECK_EQUAL(0, rc);
+	rc = jsonSerializer_serialize(type, &ex1, &result);
+	CHECK_EQUAL(0, rc);
+	STRCMP_CONTAINS("\"a\":1", result);
+	STRCMP_CONTAINS("\"b\":2", result);
+	STRCMP_CONTAINS("\"c\":3", result);
+	STRCMP_CONTAINS("\"d\":4", result);
+	STRCMP_CONTAINS("\"e\":5", result);
+	STRCMP_CONTAINS("\"f\":6", result);
+	STRCMP_CONTAINS("\"g\":7", result);
+	STRCMP_CONTAINS("\"h\":8.8", result);
+	STRCMP_CONTAINS("\"i\":9.9", result);
+	STRCMP_CONTAINS("\"j\":10", result);
+	STRCMP_CONTAINS("\"k\":true", result);
+	STRCMP_CONTAINS("\"l\":12", result);
+	//printf("example 1 result: '%s'\n", result);
+	dynType_destroy(type);
+	free(result);
+}
+
+const char *write_example2_descriptor = "{*{JJ a b}{SS c d} sub1 sub2}";
+
+struct write_example2_sub {
+	int64_t a;
+	int64_t b;
+};
+
+struct write_example2 {
+	struct write_example2_sub *sub1;
+	struct {
+		int16_t c;
+		int16_t d;
+	} sub2;
+};
+
+void writeTest2(void) {
+	struct write_example2_sub sub1;
+	sub1.a = 1;
+	sub1.b = 2;
+
+	struct write_example2 ex;
+	ex.sub1=&sub1;
+	ex.sub2.c = 3;
+	ex.sub2.d = 4;
+
+	dyn_type *type = NULL;
+	char *result = NULL;
+	int rc = dynType_parseWithStr(write_example2_descriptor, "ex2", NULL, &type);
+	CHECK_EQUAL(0, rc);
+	rc = jsonSerializer_serialize(type, &ex, &result);
+	CHECK_EQUAL(0, rc);
+	STRCMP_CONTAINS("\"a\":1", result);
+	STRCMP_CONTAINS("\"b\":2", result);
+	STRCMP_CONTAINS("\"c\":3", result);
+	STRCMP_CONTAINS("\"d\":4", result);
+	//printf("example 2 result: '%s'\n", result);
+	dynType_destroy(type);
+	free(result);
+}
+
+const char *write_example3_descriptor = "Tperson={ti name age};[Lperson;";
+
+struct write_example3_person {
+	const char *name;
+	uint32_t age;
+};
+
+struct write_example3 {
+	uint32_t cap;
+	uint32_t len;
+	struct write_example3_person **buf;
+};
+
+void writeTest3(void) {
+	struct write_example3_person p1;
+	p1.name = "John";
+	p1.age = 33;
+
+	struct write_example3_person p2;
+	p2.name = "Peter";
+	p2.age = 44;
+
+	struct write_example3_person p3;
+	p3.name = "Carol";
+	p3.age = 55;
+
+	struct write_example3_person p4;
+	p4.name = "Elton";
+	p4.age = 66;
+
+	struct write_example3 seq;
+	seq.buf = (struct write_example3_person **) calloc(4, sizeof(void *));
+	seq.len = seq.cap = 4;
+	seq.buf[0] = &p1;
+	seq.buf[1] = &p2;
+	seq.buf[2] = &p3;
+	seq.buf[3] = &p4;
+
+	dyn_type *type = NULL;
+	char *result = NULL;
+	int rc = dynType_parseWithStr(write_example3_descriptor, "ex3", NULL, &type);
+	CHECK_EQUAL(0, rc);
+	rc = jsonSerializer_serialize(type, &seq, &result);
+	CHECK_EQUAL(0, rc);
+	STRCMP_CONTAINS("\"age\":33", result);
+	STRCMP_CONTAINS("\"age\":44", result);
+	STRCMP_CONTAINS("\"age\":55", result);
+	STRCMP_CONTAINS("\"age\":66", result);
+	//printf("example 3 result: '%s'\n", result);
+	free(seq.buf);
+	dynType_destroy(type);
+	free(result);
+}
+
+
+
+}
+
+TEST_GROUP(JsonSerializerTests) {
+	void setup() {
+		int lvl = 1;
+		dynCommon_logSetup(stdLog, NULL, lvl);
+		dynType_logSetup(stdLog, NULL,lvl);
+		jsonSerializer_logSetup(stdLog, NULL, lvl);
+	}
+};
+
+TEST(JsonSerializerTests, ParseTests) {
+	//TODO split up
+	parseTests();
+}
+
+TEST(JsonSerializerTests, WriteTest1) {
+	writeTest1();
+}
+
+TEST(JsonSerializerTests, WriteTest2) {
+	writeTest2();
+}
+
+TEST(JsonSerializerTests, WriteTest3) {
+	writeTest3();
+}
+
+

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/run_tests.cpp
----------------------------------------------------------------------
diff --git a/dfi/test/run_tests.cpp b/dfi/test/run_tests.cpp
new file mode 100644
index 0000000..786f4bf
--- /dev/null
+++ b/dfi/test/run_tests.cpp
@@ -0,0 +1,24 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+#include <CppUTest/TestHarness.h>
+#include "CppUTest/CommandLineTestRunner.h"                                                                                                                                                                        
+
+int main(int argc, char** argv) {
+        return RUN_ALL_TESTS(argc, argv);
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/schemas/complex.avdl
----------------------------------------------------------------------
diff --git a/dfi/test/schemas/complex.avdl b/dfi/test/schemas/complex.avdl
new file mode 100644
index 0000000..eff1fd8
--- /dev/null
+++ b/dfi/test/schemas/complex.avdl
@@ -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.
+ */
+
+protocol Complex {
+
+  record StatResult {
+    double sum;
+    double min;
+    double max;
+    array<double> input;
+  }
+
+  StatResult stats(array<double> input);
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/schemas/complex.avpr
----------------------------------------------------------------------
diff --git a/dfi/test/schemas/complex.avpr b/dfi/test/schemas/complex.avpr
new file mode 100644
index 0000000..ca39b56
--- /dev/null
+++ b/dfi/test/schemas/complex.avpr
@@ -0,0 +1,55 @@
+/**
+ *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.
+ */
+
+{
+  "protocol" : "Complex",
+  "namespace" : null,
+  "types" : [ {
+    "type" : "record",
+    "name" : "StatResult",
+    "fields" : [ {
+      "name" : "sum",
+      "type" : "double"
+    }, {
+      "name" : "min",
+      "type" : "double"
+    }, {
+      "name" : "max",
+      "type" : "double"
+    }, {
+      "name" : "input",
+      "type" : {
+        "type" : "array",
+        "items" : "double"
+      }
+    } ]
+  } ],
+  "messages" : {
+    "stats" : {
+      "request" : [ {
+        "name" : "input",
+        "type" : {
+          "type" : "array",
+          "items" : "double"
+        }
+      } ],
+      "response" : "StatResult"
+    }
+  }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/schemas/invalid1.avpr
----------------------------------------------------------------------
diff --git a/dfi/test/schemas/invalid1.avpr b/dfi/test/schemas/invalid1.avpr
new file mode 100644
index 0000000..bbf77ee
--- /dev/null
+++ b/dfi/test/schemas/invalid1.avpr
@@ -0,0 +1,47 @@
+/**
+ *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.
+ */
+{
+  "protocol" : "Complex",
+  "namespace" : null,
+  "types" : [ {
+    "type" : "record",
+    "name" : "StatResult",
+    "fields" : [ {
+      "name" : "sum",
+      "type" : "double"
+    }, {
+      "name" : "min",
+      "type" : "double"
+    }, {
+      "name" : "max",
+      "type" : "double"
+    }, {
+      "name" : "input",
+      "type" : {
+        "type" : "array",
+        "items" : "double"
+      }
+    } ]
+  } ],
+  "messages" : {
+    "stats" : {
+      "response" : "StatResult"
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/schemas/invalid2.avpr
----------------------------------------------------------------------
diff --git a/dfi/test/schemas/invalid2.avpr b/dfi/test/schemas/invalid2.avpr
new file mode 100644
index 0000000..9eb9209
--- /dev/null
+++ b/dfi/test/schemas/invalid2.avpr
@@ -0,0 +1,49 @@
+/**
+ *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.
+ */
+ {
+  "protocol" : "Simple",
+  "types" : [ ],
+  "messages" : {
+    "sum" : {
+      "request" : [ {
+        "name" : "a"
+      }, {
+        "name" : "b",
+        "type" : "double"
+      } ],
+      "response" : "double"
+    },
+    "sub" : {
+      "request" : [ {
+        "name" : "a",
+        "type" : "double"
+      }, {
+        "name" : "b",
+        "type" : "double"
+      } ],
+      "response" : "double"
+    },
+    "sqrt" : {
+      "request" : [ {
+        "name" : "a"
+      } ],
+      "response" : "double"
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/schemas/simple.avdl
----------------------------------------------------------------------
diff --git a/dfi/test/schemas/simple.avdl b/dfi/test/schemas/simple.avdl
new file mode 100644
index 0000000..a03e352
--- /dev/null
+++ b/dfi/test/schemas/simple.avdl
@@ -0,0 +1,24 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+ @namespace("org.apache.avro.test")
+protocol Simple {
+  double sum(double a, double b);
+  double sub(double a, double b);
+  double sqrt(double a);
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/schemas/simple.avpr
----------------------------------------------------------------------
diff --git a/dfi/test/schemas/simple.avpr b/dfi/test/schemas/simple.avpr
new file mode 100644
index 0000000..4910346
--- /dev/null
+++ b/dfi/test/schemas/simple.avpr
@@ -0,0 +1,51 @@
+/**
+ *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.
+ */
+ {
+  "protocol" : "Simple",
+  "types" : [ ],
+  "messages" : {
+    "sum" : {
+      "request" : [ {
+        "name" : "a",
+        "type" : "double"
+      }, {
+        "name" : "b",
+        "type" : "double"
+      } ],
+      "response" : "double"
+    },
+    "sub" : {
+      "request" : [ {
+        "name" : "a",
+        "type" : "double"
+      }, {
+        "name" : "b",
+        "type" : "double"
+      } ],
+      "response" : "double"
+    },
+    "sqrt" : {
+      "request" : [ {
+        "name" : "a",
+        "type" : "double"
+      } ],
+      "response" : "double"
+    }
+  }
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/dfi/test/schemas/simple_min.avpr
----------------------------------------------------------------------
diff --git a/dfi/test/schemas/simple_min.avpr b/dfi/test/schemas/simple_min.avpr
new file mode 100644
index 0000000..f5c6673
--- /dev/null
+++ b/dfi/test/schemas/simple_min.avpr
@@ -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.
+ */
+ {"protocol":"Simple","types":[],"messages":{"sum":{"request":[{"name":"a","type":"double"},{"name":"b","type":"double"}],"response":"double"},"sub":{"request":[{"name":"a","type":"double"},{"name":"b","type":"double"}],"response":"double"},"sqrt":{"request":[{"name":"a","type":"double"}],"response":"double"}}}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/doap/doap_Celix.rdf
----------------------------------------------------------------------
diff --git a/doap/doap_Celix.rdf b/doap/doap_Celix.rdf
index 8571a14..41da6c3 100755
--- a/doap/doap_Celix.rdf
+++ b/doap/doap_Celix.rdf
@@ -37,7 +37,7 @@
     <name>Apache Celix</name>
     <homepage rdf:resource="http://celix.apache.org" />
     <asfext:pmc rdf:resource="http://celix.apache.org" />
-    <shortdesc>OSGi framework implementation in C.</shortdesc>
+    <shortdesc>OSGi framework implementation in C and C++.</shortdesc>
      <description>
      Celix is an implementation of the OSGi specification adapted to C. 
      It will follow the API as close as possible, but since the OSGi specification is written primarily for Java, there will be differences (Java is OO, C is procedural). 

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/etcdlib/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/etcdlib/CMakeLists.txt b/etcdlib/CMakeLists.txt
index fd72d79..060eeb0 100644
--- a/etcdlib/CMakeLists.txt
+++ b/etcdlib/CMakeLists.txt
@@ -41,28 +41,34 @@ endif ()
 find_package(CURL REQUIRED)
 find_package(Jansson REQUIRED)
 
-include_directories(
-        ${CURL_INCLUDE_DIRS}
-        ${JANSSON_INCLUDE_DIRS}
-        private/include
-        public/include
-)
-
 add_library(etcdlib SHARED
-    private/src/etcd.c
+    src/etcd.c
+)
+target_include_directories(etcdlib PUBLIC api)
+target_include_directories(etcdlib PRIVATE
+    src
+    ${CURL_INCLUDE_DIRS}
+    ${JANSSON_INCLUDE_DIRS}
 )
 
 set_target_properties(etcdlib PROPERTIES "SOVERSION" 1)
 target_link_libraries(etcdlib ${CURL_LIBRARIES} ${JANSSON_LIBRARIES})
 
 add_library(etcdlib_static STATIC
-    private/src/etcd.c
+    src/etcd.c
+)
+target_include_directories(etcdlib_static PUBLIC api)
+target_include_directories(etcdlib_static PRIVATE
+    src
+    ${CURL_INCLUDE_DIRS}
+    ${JANSSON_INCLUDE_DIRS}
 )
-
 set_target_properties(etcdlib_static PROPERTIES "SOVERSION" 1)
 target_link_libraries(etcdlib_static ${CURL_LIBRARIES} ${JANSSON_LIBRARY})
 
 
 install(TARGETS etcdlib etcdlib_static DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${ETCDLIB_CMP})
-FILE(GLOB files "public/include/*.h")
-INSTALL(FILES ${files} DESTINATION include/etcdlib COMPONENT framework)
+
+#Setup target aliases to match external usage
+add_library(Celix::etcdlib ALIAS etcdlib)
+add_library(Celix::etcdlib_static ALIAS etcdlib_static)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/etcdlib/api/etcd.h
----------------------------------------------------------------------
diff --git a/etcdlib/api/etcd.h b/etcdlib/api/etcd.h
new file mode 100644
index 0000000..7980700
--- /dev/null
+++ b/etcdlib/api/etcd.h
@@ -0,0 +1,110 @@
+/**
+ *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.
+ */
+
+#ifndef ETCDLIB_H_
+#define ETCDLIB_H_
+
+#include <stdbool.h>
+
+/*
+ * If set etcdlib will _not_ initialize curl
+ * using curl_global_init. Note that 
+ * curl_global_init can be called multiple
+ * times, but is _not_ thread-safe.
+ */
+#define ETCDLIB_NO_CURL_INITIALIZATION (1)
+
+#define ETCDLIB_ACTION_CREATE   "create"
+#define ETCDLIB_ACTION_GET      "get"
+#define ETCDLIB_ACTION_SET      "set"
+#define ETCDLIB_ACTION_UPDATE   "update"
+#define ETCDLIB_ACTION_DELETE   "delete"
+#define ETCDLIB_ACTION_EXPIRE   "expire"
+
+typedef void (*etcd_key_value_callback) (const char *key, const char *value, void* arg);
+
+/**
+ * @desc Initialize the ETCD-LIB  with the server/port where Etcd can be reached.
+ * @param const char* server. String containing the IP-number of the server.
+ * @param int port. Port number of the server.
+ * @param int flags. bitwise flags to control etcdlib initialization. 
+ * @return 0 on success, non zero otherwise.
+ */
+int etcd_init(const char* server, int port, int flags);
+
+/**
+ * @desc Retrieve a single value from Etcd.
+ * @param const char* key. The Etcd-key (Note: a leading '/' should be avoided)
+ * @param char** value. The allocated memory contains the Etcd-value. The caller is responsible for freeing this memory.
+ * @param int* modifiedIndex. If not NULL the Etcd-index of the last modified value.
+ * @return 0 on success, non zero otherwise
+ */
+int etcd_get(const char* key, char** value, int* modifiedIndex);
+
+/**
+ * @desc Retrieve the contents of a directory. For every found key/value pair the given callback function is called.
+ * @param const char* directory. The Etcd-directory which has to be searched for keys
+ * @param etcd_key_value_callback callback. Callback function which is called for every found key
+ * @param void *arg. Argument is passed to the callback function
+ * @param int* modifiedIndex. If not NULL the Etcd-index of the last modified value.
+ * @return 0 on success, non zero otherwise
+ */
+int etcd_get_directory(const char* directory, etcd_key_value_callback callback, void *arg, long long* modifiedIndex);
+
+/**
+ * @desc Setting an Etcd-key/value
+ * @param const char* key. The Etcd-key (Note: a leading '/' should be avoided)
+ * @param const char* value. The Etcd-value 
+ * @param int ttl. If non-zero this is used as the TTL value
+ * @param bool prevExist. If true the value is only set when the key already exists, if false it is always set
+ * @return 0 on success, non zero otherwise
+ */
+int etcd_set(const char* key, const char* value, int ttl, bool prevExist);
+
+/**
+ * @desc Setting an Etcd-key/value and checks if there is a different previuos value
+ * @param const char* key. The Etcd-key (Note: a leading '/' should be avoided)
+ * @param const char* value. The Etcd-value 
+ * @param int ttl. If non-zero this is used as the TTL value
+ * @param bool always_write. If true the value is written, if false only when the given value is equal to the value in etcd.
+ * @return 0 on success, non zero otherwise
+ */
+int etcd_set_with_check(const char* key, const char* value, int ttl, bool always_write);
+
+/**
+ * @desc Deleting an Etcd-key
+ * @param const char* key. The Etcd-key (Note: a leading '/' should be avoided)
+ * @return 0 on success, non zero otherwise
+ */
+int etcd_del(const char* key);
+
+/**
+ * @desc Watching an etcd directory for changes
+ * @param const char* key. The Etcd-key (Note: a leading '/' should be avoided)
+ * @param long long index. The Etcd-index which the watch has to be started on.
+ * @param char** action. If not NULL, memory is allocated and contains the action-string. The caller is responsible of freeing the memory.
+ * @param char** prevValue. If not NULL, memory is allocated and contains the previous value. The caller is responsible of freeing the memory.
+ * @param char** value. If not NULL, memory is allocated and contains the new value. The caller is responsible of freeing the memory.
+ * @param char** rkey. If not NULL, memory is allocated and contains the updated key. The caller is responsible of freeing the memory.
+ * @param long long* modifiedIndex. If not NULL, the index of the modification is written.
+ * @return 0 on success, non zero otherwise
+ */
+int etcd_watch(const char* key, long long index, char** action, char** prevValue, char** value, char** rkey, long long* modifiedIndex);
+
+#endif /*ETCDLIB_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/etcdlib/private/src/etcd.c
----------------------------------------------------------------------
diff --git a/etcdlib/private/src/etcd.c b/etcdlib/private/src/etcd.c
deleted file mode 100644
index ff9f827..0000000
--- a/etcdlib/private/src/etcd.c
+++ /dev/null
@@ -1,487 +0,0 @@
-/**
- *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.
- */
-
-#include <stdio.h>
-#include <stdbool.h>
-#include <string.h>
-#include <curl/curl.h>
-#include <jansson.h>
-
-#include "etcd.h"
-
-#define ETCD_JSON_NODE                  "node"
-#define ETCD_JSON_PREVNODE              "prevNode"
-#define ETCD_JSON_NODES                 "nodes"
-#define ETCD_JSON_ACTION                "action"
-#define ETCD_JSON_KEY                   "key"
-#define ETCD_JSON_VALUE                 "value"
-#define ETCD_JSON_DIR                   "dir"
-#define ETCD_JSON_MODIFIEDINDEX         "modifiedIndex"
-
-#define MAX_OVERHEAD_LENGTH           64
-#define DEFAULT_CURL_TIMEOUT          10
-#define DEFAULT_CURL_CONECTTIMEOUT    10
-
-typedef enum {
-	GET, PUT, DELETE
-} request_t;
-
-static const char* etcd_server;
-static int etcd_port = 0;
-
-struct MemoryStruct {
-	char *memory;
-	size_t size;
-};
-
-
-/**
- * Static function declarations
- */
-static int performRequest(char* url, request_t request, void* callback, void* reqData, void* repData);
-static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp);
-/**
- * External function definition
- */
-
-
-/**
- * etcd_init
- */
-int etcd_init(const char* server, int port, int flags) {
-	int status = 0;
-	etcd_server = server;
-	etcd_port = port;
-
-	if ((flags & ETCDLIB_NO_CURL_INITIALIZATION) == 0) {
-		//NO_CURL_INITIALIZATION flag not set
-		status = curl_global_init(CURL_GLOBAL_ALL);
-	}
-
-	return status;
-}
-
-
-/**
- * etcd_get
- */
-int etcd_get(const char* key, char** value, int* modifiedIndex) {
-	json_t* js_root = NULL;
-	json_t* js_node = NULL;
-	json_t* js_value = NULL;
-	json_t* js_modifiedIndex = NULL;
-	json_error_t error;
-	int res = -1;
-	struct MemoryStruct reply;
-
-	reply.memory = malloc(1); /* will be grown as needed by the realloc above */
-	reply.size = 0; /* no data at this point */
-
-	int retVal = -1;
-	char *url;
-	asprintf(&url, "http://%s:%d/v2/keys/%s", etcd_server, etcd_port, key);
-	res = performRequest(url, GET, WriteMemoryCallback, NULL, (void*) &reply);
-	free(url);
-
-	if (res == CURLE_OK) {
-		js_root = json_loads(reply.memory, 0, &error);
-
-		if (js_root != NULL) {
-			js_node = json_object_get(js_root, ETCD_JSON_NODE);
-		}
-		if (js_node != NULL) {
-			js_value = json_object_get(js_node, ETCD_JSON_VALUE);
-			js_modifiedIndex = json_object_get(js_node,
-					ETCD_JSON_MODIFIEDINDEX);
-
-			if (js_modifiedIndex != NULL && js_value != NULL) {
-				if (modifiedIndex) {
-					*modifiedIndex = json_integer_value(js_modifiedIndex);
-				}
-				*value = strdup(json_string_value(js_value));
-				retVal = 0;
-			}
-		}
-		if (js_root != NULL) {
-			json_decref(js_root);
-		}
-	}
-
-	if (reply.memory) {
-		free(reply.memory);
-	}
-	if(retVal != 0) {
-		*value = NULL;
-	}
-	return retVal;
-}
-
-
-static int etcd_get_recursive_values(json_t* js_root, etcd_key_value_callback callback, void *arg, json_int_t *mod_index) {
-	json_t *js_nodes;
-	if ((js_nodes = json_object_get(js_root, ETCD_JSON_NODES)) != NULL) {
-		// subarray
-		if (json_is_array(js_nodes)) {
-			int len = json_array_size(js_nodes);
-			for (int i = 0; i < len; i++) {
-				json_t *js_object = json_array_get(js_nodes, i);
-				json_t *js_mod_index = json_object_get(js_object, ETCD_JSON_MODIFIEDINDEX);
-
-				if(js_mod_index != NULL) {
-					json_int_t index = json_integer_value(js_mod_index);
-					if(*mod_index < index) {
-						*mod_index = index;
-					}
-				} else {
-					printf("[ETCDLIB] Error: No INDEX found for key!\n");
-				}
-
-				if (json_object_get(js_object, ETCD_JSON_NODES)) {
-					// node contains nodes
-					etcd_get_recursive_values(js_object, callback, arg, mod_index);
-				} else {
-					json_t* js_key = json_object_get(js_object, ETCD_JSON_KEY);
-					json_t* js_value = json_object_get(js_object, ETCD_JSON_VALUE);
-
-					if (js_key && js_value) {
-						if (!json_object_get(js_object, ETCD_JSON_DIR)) {
-							callback(json_string_value(js_key), json_string_value(js_value), arg);
-						}
-					} //else empty etcd directory, not an error.
-
-				}
-			}
-		} else {
-			fprintf(stderr, "[ETCDLIB] Error: misformatted JSON: nodes element is not an array !!\n");
-		}
-	} else {
-		fprintf(stderr, "[ETCDLIB] Error: nodes element not found!!\n");
-	}
-
-	return (*mod_index > 0 ? 0 : 1);
-}
-
-/**
- * etcd_get_directory
- */
-int etcd_get_directory(const char* directory, etcd_key_value_callback callback, void* arg, long long* modifiedIndex) {
-	json_t* js_root = NULL;
-	json_t* js_rootnode = NULL;
-
-	json_error_t error;
-	int res;
-	struct MemoryStruct reply;
-
-	reply.memory = malloc(1); /* will be grown as needed by the realloc above */
-	reply.size = 0; /* no data at this point */
-
-	int retVal = 0;
-	char *url;
-
-	asprintf(&url, "http://%s:%d/v2/keys/%s?recursive=true", etcd_server, etcd_port, directory);
-
-	res = performRequest(url, GET, WriteMemoryCallback, NULL, (void*) &reply);
-	free(url);
-
-	if (res == CURLE_OK) {
-		js_root = json_loads(reply.memory, 0, &error);
-		if (js_root != NULL) {
-			js_rootnode = json_object_get(js_root, ETCD_JSON_NODE);
-		} else {
-			retVal = -1;
-			fprintf(stderr, "[ETCDLIB] Error: %s in js_root not found", ETCD_JSON_NODE);
-		}
-		if (js_rootnode != NULL) {
-			*modifiedIndex = 0;
-			retVal = etcd_get_recursive_values(js_rootnode, callback, arg, (json_int_t*)modifiedIndex);
-		}
-		if (js_root != NULL) {
-			json_decref(js_root);
-		}
-	}
-
-	if (reply.memory) {
-		free(reply.memory);
-	}
-
-	return retVal;
-}
-
-/**
- * etcd_set
- */
-int etcd_set(const char* key, const char* value, int ttl, bool prevExist) {
-	json_error_t error;
-	json_t* js_root = NULL;
-	json_t* js_node = NULL;
-	json_t* js_value = NULL;
-	int retVal = -1;
-	char *url;
-	size_t req_len = strlen(value) + MAX_OVERHEAD_LENGTH;
-	char request[req_len];
-	char* requestPtr = request;
-	int res;
-	struct MemoryStruct reply;
-
-	/* Skip leading '/', etcd cannot handle this. */
-	while(*key == '/') {
-		key++;
-	}
-
-	reply.memory = calloc(1, 1); /* will be grown as needed by the realloc above */
-	reply.size = 0; /* no data at this point */
-
-	asprintf(&url, "http://%s:%d/v2/keys/%s", etcd_server, etcd_port, key);
-
-	requestPtr += snprintf(requestPtr, req_len, "value=%s", value);
-	if (ttl > 0) {
-		requestPtr += snprintf(requestPtr, req_len-(requestPtr-request), ";ttl=%d", ttl);
-	}
-
-	if (prevExist) {
-		requestPtr += snprintf(requestPtr, req_len-(requestPtr-request), ";prevExist=true");
-	}
-
-	res = performRequest(url, PUT, WriteMemoryCallback, request, (void*) &reply);
-
-	if(url) {
-		free(url);
-	}
-
-	if (res == CURLE_OK) {
-		js_root = json_loads(reply.memory, 0, &error);
-
-		if (js_root != NULL) {
-			js_node = json_object_get(js_root, ETCD_JSON_NODE);
-		}
-		if (js_node != NULL) {
-			js_value = json_object_get(js_node, ETCD_JSON_VALUE);
-		}
-		if (js_value != NULL && json_is_string(js_value)) {
-			if(strcmp(json_string_value(js_value), value) == 0) {
-				retVal = 0;
-			}
-		}
-		if (js_root != NULL) {
-			json_decref(js_root);
-		}
-	}
-
-	if (reply.memory) {
-		free(reply.memory);
-	}
-
-	return retVal;
-}
-
-
-/**
- * etcd_set_with_check
- */
-int etcd_set_with_check(const char* key, const char* value, int ttl, bool always_write) {
-	char *etcd_value;
-	int result = 0;
-	if (etcd_get(key, &etcd_value, NULL) == 0) {
-		if(etcd_value!=NULL){
-			if (strcmp(etcd_value, value) != 0) {
-				fprintf(stderr, "[ETCDLIB] WARNING: value already exists and is different\n");
-				fprintf(stderr, "   key       = %s\n", key);
-				fprintf(stderr, "   old value = %s\n", etcd_value);
-				fprintf(stderr, "   new value = %s\n", value);
-				result = -1;
-			}
-			free(etcd_value);
-		}
-	}
-	if(always_write || !result) {
-		result = etcd_set(key, value, ttl, false);
-	}
-	return result;
-}
-
-
-/**
- * etcd_watch
- */
-int etcd_watch(const char* key, long long index, char** action, char** prevValue, char** value, char** rkey, long long* modifiedIndex) {
-	json_error_t error;
-	json_t* js_root = NULL;
-	json_t* js_node = NULL;
-	json_t* js_prevNode = NULL;
-	json_t* js_action = NULL;
-	json_t* js_value = NULL;
-	json_t* js_rkey = NULL;
-	json_t* js_prevValue = NULL;
-	json_t* js_modIndex = NULL;
-	int retVal = -1;
-	char *url = NULL;
-	int res;
-	struct MemoryStruct reply;
-
-	reply.memory = malloc(1); /* will be grown as needed by the realloc above */
-	reply.size = 0; /* no data at this point */
-
-	if (index != 0)
-		asprintf(&url, "http://%s:%d/v2/keys/%s?wait=true&recursive=true&waitIndex=%lld", etcd_server, etcd_port, key, index);
-	else
-		asprintf(&url, "http://%s:%d/v2/keys/%s?wait=true&recursive=true", etcd_server, etcd_port, key);
-	res = performRequest(url, GET, WriteMemoryCallback, NULL, (void*) &reply);
-	if(url)
-		free(url);
-	if (res == CURLE_OK) {
-		js_root = json_loads(reply.memory, 0, &error);
-
-		if (js_root != NULL) {
-			js_action = json_object_get(js_root, ETCD_JSON_ACTION);
-			js_node = json_object_get(js_root, ETCD_JSON_NODE);
-			js_prevNode = json_object_get(js_root, ETCD_JSON_PREVNODE);
-			retVal = 0;
-		}
-		if (js_prevNode != NULL) {
-			js_prevValue = json_object_get(js_prevNode, ETCD_JSON_VALUE);
-		}
-		if (js_node != NULL) {
-			js_rkey = json_object_get(js_node, ETCD_JSON_KEY);
-			js_value = json_object_get(js_node, ETCD_JSON_VALUE);
-			js_modIndex = json_object_get(js_node, ETCD_JSON_MODIFIEDINDEX);
-		}
-		if (js_prevNode != NULL) {
-			js_prevValue = json_object_get(js_prevNode, ETCD_JSON_VALUE);
-		}
-		if ((prevValue != NULL) && (js_prevValue != NULL) && (json_is_string(js_prevValue))) {
-
-			*prevValue = strdup(json_string_value(js_prevValue));
-		}
-		if(modifiedIndex != NULL) {
-			if ((js_modIndex != NULL) && (json_is_integer(js_modIndex))) {
-				*modifiedIndex = json_integer_value(js_modIndex);
-			} else {
-				*modifiedIndex = index;
-			}
-		}
-		if ((rkey != NULL) && (js_rkey != NULL) && (json_is_string(js_rkey))) {
-			*rkey = strdup(json_string_value(js_rkey));
-
-		}
-		if ((action != NULL)  && (js_action != NULL)  && (json_is_string(js_action))) {
-			*action = strdup(json_string_value(js_action));
-		}
-		if ((value != NULL) && (js_value != NULL) && (json_is_string(js_value))) {
-			*value = strdup(json_string_value(js_value));
-		}
-		if (js_root != NULL) {
-			json_decref(js_root);
-		}
-
-	}
-
-	if (reply.memory) {
-		free(reply.memory);
-	}
-
-	return retVal;
-}
-
-/**
- * etcd_del
- */
-int etcd_del(const char* key) {
-	json_error_t error;
-	json_t* js_root = NULL;
-	json_t* js_node = NULL;
-	int retVal = -1;
-	char *url;
-	int res;
-	struct MemoryStruct reply;
-
-	reply.memory = malloc(1); /* will be grown as needed by the realloc above */
-	reply.size = 0; /* no data at this point */
-
-	asprintf(&url, "http://%s:%d/v2/keys/%s?recursive=true", etcd_server, etcd_port, key);
-	res = performRequest(url, DELETE, WriteMemoryCallback, NULL, (void*) &reply);
-	free(url);
-
-	if (res == CURLE_OK) {
-		js_root = json_loads(reply.memory, 0, &error);
-		if (js_root != NULL) {
-			js_node = json_object_get(js_root, ETCD_JSON_NODE);
-		}
-
-		if (js_node != NULL) {
-			retVal = 0;
-		}
-
-		if (js_root != NULL) {
-			json_decref(js_root);
-		}
-	}
-
-	if (reply.memory) {
-		free(reply.memory);
-	}
-
-	return retVal;
-}
-
-
-static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) {
-	size_t realsize = size * nmemb;
-	struct MemoryStruct *mem = (struct MemoryStruct *) userp;
-
-	mem->memory = realloc(mem->memory, mem->size + realsize + 1);
-	if (mem->memory == NULL) {
-		/* out of memory! */
-		fprintf(stderr, "[ETCDLIB] Error: not enough memory (realloc returned NULL)\n");
-		return 0;
-	}
-
-	memcpy(&(mem->memory[mem->size]), contents, realsize);
-	mem->size += realsize;
-	mem->memory[mem->size] = 0;
-
-	return realsize;
-}
-
-static int performRequest(char* url, request_t request, void* callback, void* reqData, void* repData) {
-	CURL *curl = NULL;
-	CURLcode res = 0;
-	curl = curl_easy_init();
-	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
-	curl_easy_setopt(curl, CURLOPT_TIMEOUT, DEFAULT_CURL_TIMEOUT);
-	curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, DEFAULT_CURL_CONECTTIMEOUT);
-	curl_easy_setopt(curl, CURLOPT_URL, url);
-	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
-	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);
-	curl_easy_setopt(curl, CURLOPT_WRITEDATA, repData);
-
-	if (request == PUT) {
-		curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
-		curl_easy_setopt(curl, CURLOPT_POST, 1L);
-		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, reqData);
-	} else if (request == DELETE) {
-		curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
-	} else if (request == GET) {
-		curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
-	}
-
-	res = curl_easy_perform(curl);
-	curl_easy_cleanup(curl);
-
-	return res;
-}

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/etcdlib/public/include/etcd.h
----------------------------------------------------------------------
diff --git a/etcdlib/public/include/etcd.h b/etcdlib/public/include/etcd.h
deleted file mode 100644
index 7980700..0000000
--- a/etcdlib/public/include/etcd.h
+++ /dev/null
@@ -1,110 +0,0 @@
-/**
- *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.
- */
-
-#ifndef ETCDLIB_H_
-#define ETCDLIB_H_
-
-#include <stdbool.h>
-
-/*
- * If set etcdlib will _not_ initialize curl
- * using curl_global_init. Note that 
- * curl_global_init can be called multiple
- * times, but is _not_ thread-safe.
- */
-#define ETCDLIB_NO_CURL_INITIALIZATION (1)
-
-#define ETCDLIB_ACTION_CREATE   "create"
-#define ETCDLIB_ACTION_GET      "get"
-#define ETCDLIB_ACTION_SET      "set"
-#define ETCDLIB_ACTION_UPDATE   "update"
-#define ETCDLIB_ACTION_DELETE   "delete"
-#define ETCDLIB_ACTION_EXPIRE   "expire"
-
-typedef void (*etcd_key_value_callback) (const char *key, const char *value, void* arg);
-
-/**
- * @desc Initialize the ETCD-LIB  with the server/port where Etcd can be reached.
- * @param const char* server. String containing the IP-number of the server.
- * @param int port. Port number of the server.
- * @param int flags. bitwise flags to control etcdlib initialization. 
- * @return 0 on success, non zero otherwise.
- */
-int etcd_init(const char* server, int port, int flags);
-
-/**
- * @desc Retrieve a single value from Etcd.
- * @param const char* key. The Etcd-key (Note: a leading '/' should be avoided)
- * @param char** value. The allocated memory contains the Etcd-value. The caller is responsible for freeing this memory.
- * @param int* modifiedIndex. If not NULL the Etcd-index of the last modified value.
- * @return 0 on success, non zero otherwise
- */
-int etcd_get(const char* key, char** value, int* modifiedIndex);
-
-/**
- * @desc Retrieve the contents of a directory. For every found key/value pair the given callback function is called.
- * @param const char* directory. The Etcd-directory which has to be searched for keys
- * @param etcd_key_value_callback callback. Callback function which is called for every found key
- * @param void *arg. Argument is passed to the callback function
- * @param int* modifiedIndex. If not NULL the Etcd-index of the last modified value.
- * @return 0 on success, non zero otherwise
- */
-int etcd_get_directory(const char* directory, etcd_key_value_callback callback, void *arg, long long* modifiedIndex);
-
-/**
- * @desc Setting an Etcd-key/value
- * @param const char* key. The Etcd-key (Note: a leading '/' should be avoided)
- * @param const char* value. The Etcd-value 
- * @param int ttl. If non-zero this is used as the TTL value
- * @param bool prevExist. If true the value is only set when the key already exists, if false it is always set
- * @return 0 on success, non zero otherwise
- */
-int etcd_set(const char* key, const char* value, int ttl, bool prevExist);
-
-/**
- * @desc Setting an Etcd-key/value and checks if there is a different previuos value
- * @param const char* key. The Etcd-key (Note: a leading '/' should be avoided)
- * @param const char* value. The Etcd-value 
- * @param int ttl. If non-zero this is used as the TTL value
- * @param bool always_write. If true the value is written, if false only when the given value is equal to the value in etcd.
- * @return 0 on success, non zero otherwise
- */
-int etcd_set_with_check(const char* key, const char* value, int ttl, bool always_write);
-
-/**
- * @desc Deleting an Etcd-key
- * @param const char* key. The Etcd-key (Note: a leading '/' should be avoided)
- * @return 0 on success, non zero otherwise
- */
-int etcd_del(const char* key);
-
-/**
- * @desc Watching an etcd directory for changes
- * @param const char* key. The Etcd-key (Note: a leading '/' should be avoided)
- * @param long long index. The Etcd-index which the watch has to be started on.
- * @param char** action. If not NULL, memory is allocated and contains the action-string. The caller is responsible of freeing the memory.
- * @param char** prevValue. If not NULL, memory is allocated and contains the previous value. The caller is responsible of freeing the memory.
- * @param char** value. If not NULL, memory is allocated and contains the new value. The caller is responsible of freeing the memory.
- * @param char** rkey. If not NULL, memory is allocated and contains the updated key. The caller is responsible of freeing the memory.
- * @param long long* modifiedIndex. If not NULL, the index of the modification is written.
- * @return 0 on success, non zero otherwise
- */
-int etcd_watch(const char* key, long long index, char** action, char** prevValue, char** value, char** rkey, long long* modifiedIndex);
-
-#endif /*ETCDLIB_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/etcdlib/src/etcd.c
----------------------------------------------------------------------
diff --git a/etcdlib/src/etcd.c b/etcdlib/src/etcd.c
new file mode 100644
index 0000000..ff9f827
--- /dev/null
+++ b/etcdlib/src/etcd.c
@@ -0,0 +1,487 @@
+/**
+ *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.
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <string.h>
+#include <curl/curl.h>
+#include <jansson.h>
+
+#include "etcd.h"
+
+#define ETCD_JSON_NODE                  "node"
+#define ETCD_JSON_PREVNODE              "prevNode"
+#define ETCD_JSON_NODES                 "nodes"
+#define ETCD_JSON_ACTION                "action"
+#define ETCD_JSON_KEY                   "key"
+#define ETCD_JSON_VALUE                 "value"
+#define ETCD_JSON_DIR                   "dir"
+#define ETCD_JSON_MODIFIEDINDEX         "modifiedIndex"
+
+#define MAX_OVERHEAD_LENGTH           64
+#define DEFAULT_CURL_TIMEOUT          10
+#define DEFAULT_CURL_CONECTTIMEOUT    10
+
+typedef enum {
+	GET, PUT, DELETE
+} request_t;
+
+static const char* etcd_server;
+static int etcd_port = 0;
+
+struct MemoryStruct {
+	char *memory;
+	size_t size;
+};
+
+
+/**
+ * Static function declarations
+ */
+static int performRequest(char* url, request_t request, void* callback, void* reqData, void* repData);
+static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp);
+/**
+ * External function definition
+ */
+
+
+/**
+ * etcd_init
+ */
+int etcd_init(const char* server, int port, int flags) {
+	int status = 0;
+	etcd_server = server;
+	etcd_port = port;
+
+	if ((flags & ETCDLIB_NO_CURL_INITIALIZATION) == 0) {
+		//NO_CURL_INITIALIZATION flag not set
+		status = curl_global_init(CURL_GLOBAL_ALL);
+	}
+
+	return status;
+}
+
+
+/**
+ * etcd_get
+ */
+int etcd_get(const char* key, char** value, int* modifiedIndex) {
+	json_t* js_root = NULL;
+	json_t* js_node = NULL;
+	json_t* js_value = NULL;
+	json_t* js_modifiedIndex = NULL;
+	json_error_t error;
+	int res = -1;
+	struct MemoryStruct reply;
+
+	reply.memory = malloc(1); /* will be grown as needed by the realloc above */
+	reply.size = 0; /* no data at this point */
+
+	int retVal = -1;
+	char *url;
+	asprintf(&url, "http://%s:%d/v2/keys/%s", etcd_server, etcd_port, key);
+	res = performRequest(url, GET, WriteMemoryCallback, NULL, (void*) &reply);
+	free(url);
+
+	if (res == CURLE_OK) {
+		js_root = json_loads(reply.memory, 0, &error);
+
+		if (js_root != NULL) {
+			js_node = json_object_get(js_root, ETCD_JSON_NODE);
+		}
+		if (js_node != NULL) {
+			js_value = json_object_get(js_node, ETCD_JSON_VALUE);
+			js_modifiedIndex = json_object_get(js_node,
+					ETCD_JSON_MODIFIEDINDEX);
+
+			if (js_modifiedIndex != NULL && js_value != NULL) {
+				if (modifiedIndex) {
+					*modifiedIndex = json_integer_value(js_modifiedIndex);
+				}
+				*value = strdup(json_string_value(js_value));
+				retVal = 0;
+			}
+		}
+		if (js_root != NULL) {
+			json_decref(js_root);
+		}
+	}
+
+	if (reply.memory) {
+		free(reply.memory);
+	}
+	if(retVal != 0) {
+		*value = NULL;
+	}
+	return retVal;
+}
+
+
+static int etcd_get_recursive_values(json_t* js_root, etcd_key_value_callback callback, void *arg, json_int_t *mod_index) {
+	json_t *js_nodes;
+	if ((js_nodes = json_object_get(js_root, ETCD_JSON_NODES)) != NULL) {
+		// subarray
+		if (json_is_array(js_nodes)) {
+			int len = json_array_size(js_nodes);
+			for (int i = 0; i < len; i++) {
+				json_t *js_object = json_array_get(js_nodes, i);
+				json_t *js_mod_index = json_object_get(js_object, ETCD_JSON_MODIFIEDINDEX);
+
+				if(js_mod_index != NULL) {
+					json_int_t index = json_integer_value(js_mod_index);
+					if(*mod_index < index) {
+						*mod_index = index;
+					}
+				} else {
+					printf("[ETCDLIB] Error: No INDEX found for key!\n");
+				}
+
+				if (json_object_get(js_object, ETCD_JSON_NODES)) {
+					// node contains nodes
+					etcd_get_recursive_values(js_object, callback, arg, mod_index);
+				} else {
+					json_t* js_key = json_object_get(js_object, ETCD_JSON_KEY);
+					json_t* js_value = json_object_get(js_object, ETCD_JSON_VALUE);
+
+					if (js_key && js_value) {
+						if (!json_object_get(js_object, ETCD_JSON_DIR)) {
+							callback(json_string_value(js_key), json_string_value(js_value), arg);
+						}
+					} //else empty etcd directory, not an error.
+
+				}
+			}
+		} else {
+			fprintf(stderr, "[ETCDLIB] Error: misformatted JSON: nodes element is not an array !!\n");
+		}
+	} else {
+		fprintf(stderr, "[ETCDLIB] Error: nodes element not found!!\n");
+	}
+
+	return (*mod_index > 0 ? 0 : 1);
+}
+
+/**
+ * etcd_get_directory
+ */
+int etcd_get_directory(const char* directory, etcd_key_value_callback callback, void* arg, long long* modifiedIndex) {
+	json_t* js_root = NULL;
+	json_t* js_rootnode = NULL;
+
+	json_error_t error;
+	int res;
+	struct MemoryStruct reply;
+
+	reply.memory = malloc(1); /* will be grown as needed by the realloc above */
+	reply.size = 0; /* no data at this point */
+
+	int retVal = 0;
+	char *url;
+
+	asprintf(&url, "http://%s:%d/v2/keys/%s?recursive=true", etcd_server, etcd_port, directory);
+
+	res = performRequest(url, GET, WriteMemoryCallback, NULL, (void*) &reply);
+	free(url);
+
+	if (res == CURLE_OK) {
+		js_root = json_loads(reply.memory, 0, &error);
+		if (js_root != NULL) {
+			js_rootnode = json_object_get(js_root, ETCD_JSON_NODE);
+		} else {
+			retVal = -1;
+			fprintf(stderr, "[ETCDLIB] Error: %s in js_root not found", ETCD_JSON_NODE);
+		}
+		if (js_rootnode != NULL) {
+			*modifiedIndex = 0;
+			retVal = etcd_get_recursive_values(js_rootnode, callback, arg, (json_int_t*)modifiedIndex);
+		}
+		if (js_root != NULL) {
+			json_decref(js_root);
+		}
+	}
+
+	if (reply.memory) {
+		free(reply.memory);
+	}
+
+	return retVal;
+}
+
+/**
+ * etcd_set
+ */
+int etcd_set(const char* key, const char* value, int ttl, bool prevExist) {
+	json_error_t error;
+	json_t* js_root = NULL;
+	json_t* js_node = NULL;
+	json_t* js_value = NULL;
+	int retVal = -1;
+	char *url;
+	size_t req_len = strlen(value) + MAX_OVERHEAD_LENGTH;
+	char request[req_len];
+	char* requestPtr = request;
+	int res;
+	struct MemoryStruct reply;
+
+	/* Skip leading '/', etcd cannot handle this. */
+	while(*key == '/') {
+		key++;
+	}
+
+	reply.memory = calloc(1, 1); /* will be grown as needed by the realloc above */
+	reply.size = 0; /* no data at this point */
+
+	asprintf(&url, "http://%s:%d/v2/keys/%s", etcd_server, etcd_port, key);
+
+	requestPtr += snprintf(requestPtr, req_len, "value=%s", value);
+	if (ttl > 0) {
+		requestPtr += snprintf(requestPtr, req_len-(requestPtr-request), ";ttl=%d", ttl);
+	}
+
+	if (prevExist) {
+		requestPtr += snprintf(requestPtr, req_len-(requestPtr-request), ";prevExist=true");
+	}
+
+	res = performRequest(url, PUT, WriteMemoryCallback, request, (void*) &reply);
+
+	if(url) {
+		free(url);
+	}
+
+	if (res == CURLE_OK) {
+		js_root = json_loads(reply.memory, 0, &error);
+
+		if (js_root != NULL) {
+			js_node = json_object_get(js_root, ETCD_JSON_NODE);
+		}
+		if (js_node != NULL) {
+			js_value = json_object_get(js_node, ETCD_JSON_VALUE);
+		}
+		if (js_value != NULL && json_is_string(js_value)) {
+			if(strcmp(json_string_value(js_value), value) == 0) {
+				retVal = 0;
+			}
+		}
+		if (js_root != NULL) {
+			json_decref(js_root);
+		}
+	}
+
+	if (reply.memory) {
+		free(reply.memory);
+	}
+
+	return retVal;
+}
+
+
+/**
+ * etcd_set_with_check
+ */
+int etcd_set_with_check(const char* key, const char* value, int ttl, bool always_write) {
+	char *etcd_value;
+	int result = 0;
+	if (etcd_get(key, &etcd_value, NULL) == 0) {
+		if(etcd_value!=NULL){
+			if (strcmp(etcd_value, value) != 0) {
+				fprintf(stderr, "[ETCDLIB] WARNING: value already exists and is different\n");
+				fprintf(stderr, "   key       = %s\n", key);
+				fprintf(stderr, "   old value = %s\n", etcd_value);
+				fprintf(stderr, "   new value = %s\n", value);
+				result = -1;
+			}
+			free(etcd_value);
+		}
+	}
+	if(always_write || !result) {
+		result = etcd_set(key, value, ttl, false);
+	}
+	return result;
+}
+
+
+/**
+ * etcd_watch
+ */
+int etcd_watch(const char* key, long long index, char** action, char** prevValue, char** value, char** rkey, long long* modifiedIndex) {
+	json_error_t error;
+	json_t* js_root = NULL;
+	json_t* js_node = NULL;
+	json_t* js_prevNode = NULL;
+	json_t* js_action = NULL;
+	json_t* js_value = NULL;
+	json_t* js_rkey = NULL;
+	json_t* js_prevValue = NULL;
+	json_t* js_modIndex = NULL;
+	int retVal = -1;
+	char *url = NULL;
+	int res;
+	struct MemoryStruct reply;
+
+	reply.memory = malloc(1); /* will be grown as needed by the realloc above */
+	reply.size = 0; /* no data at this point */
+
+	if (index != 0)
+		asprintf(&url, "http://%s:%d/v2/keys/%s?wait=true&recursive=true&waitIndex=%lld", etcd_server, etcd_port, key, index);
+	else
+		asprintf(&url, "http://%s:%d/v2/keys/%s?wait=true&recursive=true", etcd_server, etcd_port, key);
+	res = performRequest(url, GET, WriteMemoryCallback, NULL, (void*) &reply);
+	if(url)
+		free(url);
+	if (res == CURLE_OK) {
+		js_root = json_loads(reply.memory, 0, &error);
+
+		if (js_root != NULL) {
+			js_action = json_object_get(js_root, ETCD_JSON_ACTION);
+			js_node = json_object_get(js_root, ETCD_JSON_NODE);
+			js_prevNode = json_object_get(js_root, ETCD_JSON_PREVNODE);
+			retVal = 0;
+		}
+		if (js_prevNode != NULL) {
+			js_prevValue = json_object_get(js_prevNode, ETCD_JSON_VALUE);
+		}
+		if (js_node != NULL) {
+			js_rkey = json_object_get(js_node, ETCD_JSON_KEY);
+			js_value = json_object_get(js_node, ETCD_JSON_VALUE);
+			js_modIndex = json_object_get(js_node, ETCD_JSON_MODIFIEDINDEX);
+		}
+		if (js_prevNode != NULL) {
+			js_prevValue = json_object_get(js_prevNode, ETCD_JSON_VALUE);
+		}
+		if ((prevValue != NULL) && (js_prevValue != NULL) && (json_is_string(js_prevValue))) {
+
+			*prevValue = strdup(json_string_value(js_prevValue));
+		}
+		if(modifiedIndex != NULL) {
+			if ((js_modIndex != NULL) && (json_is_integer(js_modIndex))) {
+				*modifiedIndex = json_integer_value(js_modIndex);
+			} else {
+				*modifiedIndex = index;
+			}
+		}
+		if ((rkey != NULL) && (js_rkey != NULL) && (json_is_string(js_rkey))) {
+			*rkey = strdup(json_string_value(js_rkey));
+
+		}
+		if ((action != NULL)  && (js_action != NULL)  && (json_is_string(js_action))) {
+			*action = strdup(json_string_value(js_action));
+		}
+		if ((value != NULL) && (js_value != NULL) && (json_is_string(js_value))) {
+			*value = strdup(json_string_value(js_value));
+		}
+		if (js_root != NULL) {
+			json_decref(js_root);
+		}
+
+	}
+
+	if (reply.memory) {
+		free(reply.memory);
+	}
+
+	return retVal;
+}
+
+/**
+ * etcd_del
+ */
+int etcd_del(const char* key) {
+	json_error_t error;
+	json_t* js_root = NULL;
+	json_t* js_node = NULL;
+	int retVal = -1;
+	char *url;
+	int res;
+	struct MemoryStruct reply;
+
+	reply.memory = malloc(1); /* will be grown as needed by the realloc above */
+	reply.size = 0; /* no data at this point */
+
+	asprintf(&url, "http://%s:%d/v2/keys/%s?recursive=true", etcd_server, etcd_port, key);
+	res = performRequest(url, DELETE, WriteMemoryCallback, NULL, (void*) &reply);
+	free(url);
+
+	if (res == CURLE_OK) {
+		js_root = json_loads(reply.memory, 0, &error);
+		if (js_root != NULL) {
+			js_node = json_object_get(js_root, ETCD_JSON_NODE);
+		}
+
+		if (js_node != NULL) {
+			retVal = 0;
+		}
+
+		if (js_root != NULL) {
+			json_decref(js_root);
+		}
+	}
+
+	if (reply.memory) {
+		free(reply.memory);
+	}
+
+	return retVal;
+}
+
+
+static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, void *userp) {
+	size_t realsize = size * nmemb;
+	struct MemoryStruct *mem = (struct MemoryStruct *) userp;
+
+	mem->memory = realloc(mem->memory, mem->size + realsize + 1);
+	if (mem->memory == NULL) {
+		/* out of memory! */
+		fprintf(stderr, "[ETCDLIB] Error: not enough memory (realloc returned NULL)\n");
+		return 0;
+	}
+
+	memcpy(&(mem->memory[mem->size]), contents, realsize);
+	mem->size += realsize;
+	mem->memory[mem->size] = 0;
+
+	return realsize;
+}
+
+static int performRequest(char* url, request_t request, void* callback, void* reqData, void* repData) {
+	CURL *curl = NULL;
+	CURLcode res = 0;
+	curl = curl_easy_init();
+	curl_easy_setopt(curl, CURLOPT_NOSIGNAL, 1);
+	curl_easy_setopt(curl, CURLOPT_TIMEOUT, DEFAULT_CURL_TIMEOUT);
+	curl_easy_setopt(curl, CURLOPT_CONNECTTIMEOUT, DEFAULT_CURL_CONECTTIMEOUT);
+	curl_easy_setopt(curl, CURLOPT_URL, url);
+	curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
+	curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, callback);
+	curl_easy_setopt(curl, CURLOPT_WRITEDATA, repData);
+
+	if (request == PUT) {
+		curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "PUT");
+		curl_easy_setopt(curl, CURLOPT_POST, 1L);
+		curl_easy_setopt(curl, CURLOPT_POSTFIELDS, reqData);
+	} else if (request == DELETE) {
+		curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "DELETE");
+	} else if (request == GET) {
+		curl_easy_setopt(curl, CURLOPT_CUSTOMREQUEST, "GET");
+	}
+
+	res = curl_easy_perform(curl);
+	curl_easy_cleanup(curl);
+
+	return res;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/event_admin/event_admin/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/event_admin/event_admin/CMakeLists.txt b/event_admin/event_admin/CMakeLists.txt
index 4fe7ccd..4a0f687 100644
--- a/event_admin/event_admin/CMakeLists.txt
+++ b/event_admin/event_admin/CMakeLists.txt
@@ -36,4 +36,4 @@ add_bundle(event_admin
 
 install_bundle(event_admin)
 
-target_link_libraries(event_admin celix_framework celix_utils)
+target_link_libraries(event_admin Celix::framework)

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/event_admin/event_handler/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/event_admin/event_handler/CMakeLists.txt b/event_admin/event_handler/CMakeLists.txt
index c786a78..2843122 100644
--- a/event_admin/event_handler/CMakeLists.txt
+++ b/event_admin/event_handler/CMakeLists.txt
@@ -32,4 +32,4 @@ add_bundle(event_handler
 
 install_bundle(event_handler)
 
-target_link_libraries(event_handler celix_framework celix_utils)
+target_link_libraries(event_handler Celix::framework)

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/event_admin/event_publisher/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/event_admin/event_publisher/CMakeLists.txt b/event_admin/event_publisher/CMakeLists.txt
index 1999a9c..dc9e516 100644
--- a/event_admin/event_publisher/CMakeLists.txt
+++ b/event_admin/event_publisher/CMakeLists.txt
@@ -31,4 +31,4 @@ add_bundle(event_publisher
 
 install_bundle(event_publisher)
 
-target_link_libraries(event_publisher celix_framework celix_utils)
+target_link_libraries(event_publisher Celix::framework)

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/examples/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 164500d..93a648b 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -28,7 +28,6 @@ if (EXAMPLES)
     if (NOT ANDROID)
     	add_subdirectory(mongoose)
     endif()
-    add_subdirectory(whiteboard)
     add_subdirectory(embedding)
     add_subdirectory(service_hook_example)
     add_subdirectory(log_service_example)

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/examples/dm_example/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/dm_example/CMakeLists.txt b/examples/dm_example/CMakeLists.txt
index 8e07825..9a9e69b 100644
--- a/examples/dm_example/CMakeLists.txt
+++ b/examples/dm_example/CMakeLists.txt
@@ -30,8 +30,8 @@ if (BUILD_DEPENDENCY_MANAGER)
     add_deploy("dm_example"
         COPY 
         BUNDLES
-            shell
-            shell_tui
+            Celix::shell
+            Celix::shell_tui
             dm_shell
             phase1
             phase2a
@@ -53,8 +53,8 @@ if (BUILD_DEPENDENCY_MANAGER)
             FROM dmbase
             GROUP examples
             BUNDLES
-                shell
-                shell_tui
+                ${CELIX_SHELL_BUNDLE}
+                ${CELIX_SHELL_TUI_BUNDLE}
                 dm_shell
                 phase1
                 phase2a

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/examples/dm_example/phase1/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/dm_example/phase1/CMakeLists.txt b/examples/dm_example/phase1/CMakeLists.txt
index 99abe65..6299688 100644
--- a/examples/dm_example/phase1/CMakeLists.txt
+++ b/examples/dm_example/phase1/CMakeLists.txt
@@ -28,16 +28,13 @@ add_bundle(phase1
         private/src/phase1_cmp.c
 )
 
-#Not possbile yet.
-#bundle_private_libs(phase1 dependency_manager)
-
 IF(APPLE)
-    target_link_libraries(phase1 celix_framework -Wl,-all_load dependency_manager_static)
+    target_link_libraries(phase1 PRIVATE -Wl,-all_load dependency_manager_static)
 else()
     if(ENABLE_ADDRESS_SANITIZER)
         #With asan there can be undefined symbols
-        target_link_libraries(phase1 -Wl,--whole-archive dependency_manager_static -Wl,--no-whole-archive celix_framework)
+        target_link_libraries(phase1 PRIVATE -Wl,--whole-archive dependency_manager_static -Wl,--no-whole-archive)
     else()
-        target_link_libraries(phase1 -Wl,--no-undefined -Wl,--whole-archive dependency_manager_static -Wl,--no-whole-archive celix_framework)
+        target_link_libraries(phase1 PRIVATE -Wl,--no-undefined -Wl,--whole-archive dependency_manager_static -Wl,--no-whole-archive)
     endif()
 endif()

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/examples/dm_example/phase2a/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/dm_example/phase2a/CMakeLists.txt b/examples/dm_example/phase2a/CMakeLists.txt
index 31c27a6..d8f9165 100644
--- a/examples/dm_example/phase2a/CMakeLists.txt
+++ b/examples/dm_example/phase2a/CMakeLists.txt
@@ -29,12 +29,12 @@ add_bundle(phase2a
 )
 
 IF(APPLE)
-    target_link_libraries(phase2a celix_framework -Wl,-all_load dependency_manager_static)
+    target_link_libraries(phase2a PRIVATE  -Wl,-all_load dependency_manager_static)
 else()
     if(ENABLE_ADDRESS_SANITIZER)
         #With asan there can be undefined symbols
-        target_link_libraries(phase2a -Wl,--whole-archive dependency_manager_static -Wl,--no-whole-archive celix_framework)
+        target_link_libraries(phase2a PRIVATE -Wl,--whole-archive dependency_manager_static -Wl,--no-whole-archive)
     else()
-        target_link_libraries(phase2a -Wl,--no-undefined -Wl,--whole-archive dependency_manager_static -Wl,--no-whole-archive celix_framework)
+        target_link_libraries(phase2a PRIVATE  -Wl,--no-undefined -Wl,--whole-archive dependency_manager_static -Wl,--no-whole-archive)
     endif()
 ENDIF()

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/examples/dm_example/phase2b/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/dm_example/phase2b/CMakeLists.txt b/examples/dm_example/phase2b/CMakeLists.txt
index 1d107ec..a65b422 100644
--- a/examples/dm_example/phase2b/CMakeLists.txt
+++ b/examples/dm_example/phase2b/CMakeLists.txt
@@ -31,12 +31,12 @@ add_bundle(phase2b
 #bundle_private_libs(phase2b dependency_manager)
 
 IF(APPLE)
-    target_link_libraries(phase2b celix_framework -Wl,-all_load dependency_manager_static)
+    target_link_libraries(phase2b PRIVATE -Wl,-all_load dependency_manager_static)
 else()
     if(ENABLE_ADDRESS_SANITIZER)
         #With asan there can be undefined symbols
-        target_link_libraries(phase2b -Wl,--whole-archive dependency_manager_static -Wl,--no-whole-archive celix_framework)
+        target_link_libraries(phase2b PRIVATE -Wl,--whole-archive dependency_manager_static -Wl,--no-whole-archive)
     else()
-        target_link_libraries(phase2b -Wl,--no-undefined -Wl,--whole-archive dependency_manager_static -Wl,--no-whole-archive celix_framework)
+        target_link_libraries(phase2b PRIVATE -Wl,--no-undefined -Wl,--whole-archive dependency_manager_static -Wl,--no-whole-archive)
     endif()
 ENDIF()

http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/examples/dm_example/phase3/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/dm_example/phase3/CMakeLists.txt b/examples/dm_example/phase3/CMakeLists.txt
index aea9f9e..9547e04 100644
--- a/examples/dm_example/phase3/CMakeLists.txt
+++ b/examples/dm_example/phase3/CMakeLists.txt
@@ -31,12 +31,12 @@ add_bundle(phase3
 #bundle_private_libs(phase3 dependency_manager)
 
 IF(APPLE)
-    target_link_libraries(phase3 celix_framework -Wl,-all_load dependency_manager_static)
+    target_link_libraries(phase3 PRIVATE -Wl,-all_load dependency_manager_static)
 else()
     if(ENABLE_ADDRESS_SANITIZER)
         #With asan there can be undefined symbols
-        target_link_libraries(phase3 -Wl,--whole-archive dependency_manager_static -Wl,--no-whole-archive celix_framework)
+        target_link_libraries(phase3 PRIVATE -Wl,--whole-archive dependency_manager_static -Wl,--no-whole-archive)
     else()
-        target_link_libraries(phase3 -Wl,--no-undefined -Wl,--whole-archive dependency_manager_static -Wl,--no-whole-archive celix_framework)
+        target_link_libraries(phase3 PRIVATE -Wl,--no-undefined -Wl,--whole-archive dependency_manager_static -Wl,--no-whole-archive)
     endif()
 ENDIF()