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 2018/05/11 12:59:11 UTC

[1/3] celix git commit: CELIX-446: Adds an initial implementation of a service factory which does not use the service_registration pointer and adds some documentation for the service example

Repository: celix
Updated Branches:
  refs/heads/develop a4a1f5000 -> 48aada3ab


CELIX-446: Adds an initial implementation of a service factory which does not use the service_registration pointer and adds some documentation for the service example


Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/626687fe
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/626687fe
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/626687fe

Branch: refs/heads/develop
Commit: 626687fea7a0095e384a1a692af6a3984b06ca94
Parents: a4a1f50
Author: Pepijn Noltes <pe...@gmail.com>
Authored: Thu May 10 21:36:53 2018 +0200
Committer: Pepijn Noltes <pe...@gmail.com>
Committed: Thu May 10 21:36:53 2018 +0200

----------------------------------------------------------------------
 .../services_example_c/CMakeLists.txt           |  30 ++-
 .../celix-examples/services_example_c/README.md |  58 ++++++
 .../services_example_c/api/example_calc.h       |   1 +
 .../services_example_c/src/consumer_example.c   | 184 ------------------
 .../src/dynamic_consumer_example.c              | 189 +++++++++++++++++++
 .../src/dynamic_provider_example.c              | 134 +++++++++++++
 .../services_example_c/src/provider_example.c   | 134 -------------
 .../src/simple_consumer_example.c               |  85 +++++++++
 .../src/simple_provider_example.c               |  73 +++++++
 framework/include/bundle_context.h              |  61 +++++-
 framework/include/celix_service_factory.h       |  43 +++++
 framework/include/celix_types.h                 |   2 +
 framework/include/service_factory.h             |  22 +--
 framework/include/service_registry.h            |  14 +-
 framework/private/mock/bundle_context_mock.c    |  21 +++
 framework/private/mock/framework_mock.c         |  10 +-
 .../private/mock/service_registration_mock.c    |  17 ++
 framework/private/mock/service_registry_mock.c  |  18 ++
 .../private/test/service_registration_test.cpp  |   9 +-
 framework/src/bundle_context.c                  |  39 +++-
 framework/src/framework.c                       |  18 ++
 framework/src/framework_private.h               |   3 +-
 framework/src/service_registration.c            |  61 +++---
 framework/src/service_registration_private.h    |  22 ++-
 framework/src/service_registry.c                |  25 ++-
 framework/src/service_registry_private.h        |   2 +-
 framework/tst/bundle_context_services_test.cpp  |  46 +++++
 27 files changed, 922 insertions(+), 399 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/examples/celix-examples/services_example_c/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/examples/celix-examples/services_example_c/CMakeLists.txt b/examples/celix-examples/services_example_c/CMakeLists.txt
index f56ddd8..43b88b2 100644
--- a/examples/celix-examples/services_example_c/CMakeLists.txt
+++ b/examples/celix-examples/services_example_c/CMakeLists.txt
@@ -21,24 +21,48 @@ target_include_directories(services_example_c_api INTERFACE api)
 
 add_celix_bundle(provider_example
         VERSION 1.0.0
-        SOURCES src/provider_example.c
+        SOURCES src/simple_provider_example.c
 )
 target_link_libraries(provider_example PRIVATE services_example_c_api)
 
 add_celix_bundle(consumer_example
         VERSION 1.0.0
-        SOURCES src/consumer_example.c
+        SOURCES src/simple_consumer_example.c
         )
 target_link_libraries(consumer_example PRIVATE services_example_c_api)
 
+
+
+add_celix_bundle(dynamic_provider_example
+        VERSION 1.0.0
+        SOURCES src/dynamic_provider_example.c
+)
+target_link_libraries(dynamic_provider_example PRIVATE services_example_c_api)
+
+add_celix_bundle(dynamic_consumer_example
+        VERSION 1.0.0
+        SOURCES src/dynamic_consumer_example.c
+)
+target_link_libraries(dynamic_consumer_example PRIVATE services_example_c_api)
+
 if ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU")
-  target_compile_definitions(consumer_example PRIVATE USE_NESTED_FUNCTION_EXAMPLE)
+  target_compile_definitions(dynamic_consumer_example PRIVATE USE_NESTED_FUNCTION_EXAMPLE)
 endif()
 
 add_celix_container(services_example_c
+    GROUP services_example
     BUNDLES
         Celix::shell
         Celix::shell_tui
         provider_example
         consumer_example
 )
+
+add_celix_container(dynamic_services_example_c
+    GROUP services_example
+    BUNDLES
+      Celix::shell
+      Celix::shell_tui
+      dynamic_provider_example
+      dynamic_consumer_example
+)

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/examples/celix-examples/services_example_c/README.md
----------------------------------------------------------------------
diff --git a/examples/celix-examples/services_example_c/README.md b/examples/celix-examples/services_example_c/README.md
new file mode 100644
index 0000000..a4f50ba
--- /dev/null
+++ b/examples/celix-examples/services_example_c/README.md
@@ -0,0 +1,58 @@
+<!--
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+   
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+
+# Intro
+
+This example show how services can be provided and consumer by bundles.
+
+The example uses the `celix_bundleContext_registerService` to provide
+services and uses a combination of `celix_bundleContext_useService`,
+ `celix_bundleContext_useServices` and `celix_bundleContext_trackServices`
+ to consume services.
+
+ TODO intro bundle context
+
+ See the `bundle_context.h` for documentation about these - and other -functions
+
+# Simple Service Provider & Consumer Example
+
+The simple provider/consumer example can be executed by launching the
+`services_example_c` executable target
+(build in `${CMAKE_BUILD_DIR}/deploy/services_example/services_example_c`)
+
+In this example the provide bundle only register one calc service. And
+the consumer bundle tries to use this during startup and registerd
+a service tracker for the calc service.
+
+Try stopping/starting the provider / consumer bundles (respectively bundle id 3 & 4)
+to see how this work runtime. E.g. use `stop 3`, `stop 4`, `start 3`, `start 4` in different combinations.
+
+
+# Dynamic Service Provider & Consumer Example
+
+The dynamic provider/consumer example can be executed by launching the
+`dynamic_services_example_c` executable target
+(build in `${CMAKE_BUILD_DIR}/deploy/services_example/dynamic_services_example_c`)
+
+The dynamic service provide / consumer example show how the framework copes
+with the dynamic behaviour of services.
+
+This this example the provided dynammically register more and less calc services in a thread.
+The consumer bundle uses these services in a every 5 seconds and print some info.
+
+Hopefully this example will give an idea how services can be safely used and tracked in a dynamic environment.
+

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/examples/celix-examples/services_example_c/api/example_calc.h
----------------------------------------------------------------------
diff --git a/examples/celix-examples/services_example_c/api/example_calc.h b/examples/celix-examples/services_example_c/api/example_calc.h
index 89481fa..8afe6c3 100644
--- a/examples/celix-examples/services_example_c/api/example_calc.h
+++ b/examples/celix-examples/services_example_c/api/example_calc.h
@@ -21,6 +21,7 @@
 #define CELIX_EXAMPLE_CALC_H
 
 #define EXAMPLE_CALC_NAME "example_calc"
+#define EXAMPLE_CALC_VERSION "1.0.0"
 
 struct example_calc {
     void *handle;

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/examples/celix-examples/services_example_c/src/consumer_example.c
----------------------------------------------------------------------
diff --git a/examples/celix-examples/services_example_c/src/consumer_example.c b/examples/celix-examples/services_example_c/src/consumer_example.c
deleted file mode 100644
index 899cb57..0000000
--- a/examples/celix-examples/services_example_c/src/consumer_example.c
+++ /dev/null
@@ -1,184 +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 <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <constants.h>
-
-#include "example_calc.h"
-#include "bundle_activator.h"
-
-typedef struct activator_data {
-    celix_bundle_context_t *ctx;
-    pthread_t thread;
-
-    pthread_mutex_t mutex; //protects running
-    bool running;
-    int trackCount;
-} activator_data_t;
-
-static bool isRunning(activator_data_t *data) {
-    bool result = false;
-    pthread_mutex_lock(&data->mutex);
-    result = data->running;
-    pthread_mutex_unlock(&data->mutex);
-    return result;
-}
-
-static void setRunning(activator_data_t *data, bool val) {
-    pthread_mutex_lock(&data->mutex);
-    data->running = val;
-    pthread_mutex_unlock(&data->mutex);
-}
-
-struct info {
-    int result;
-    int count;
-};
-
-static void useCalc(void *handle, void *svc) {
-    struct info *i = handle;
-    example_calc_t *calc = svc;
-    i->result += calc->calc(calc->handle, 1);
-    i->count += 1;
-}
-
-static void gccExample(activator_data_t *data) {
-#ifdef USE_NESTED_FUNCTION_EXAMPLE
-
-    int result = 0;
-    long rank = 0;
-    long svcId = 0;
-
-    void use(void *handle, void *svc, const celix_properties_t *props) {
-        example_calc_t *calc = svc;
-        rank = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_RANKING, -1L);
-        svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L);
-        result = calc->calc(calc->handle, 1);
-    }
-
-    celix_service_use_options_t opts;
-    memset(&opts, 0, sizeof(opts));
-
-    opts.serviceName = EXAMPLE_CALC_NAME;
-    opts.callbackHandle = NULL; //can be null for trampolines
-    opts.useWithProperties = use;
-    bool called = celix_bundleContext_useServiceWithOptions(data->ctx, &opts);
-
-    printf("Called func %s. Result is %i, rank is %li and svc id is %li\n", called ? "called" : "not called", result, rank, svcId);
-
-#endif
-}
-
-static void addSvc(activator_data_t *data, void *svc __attribute__((unused))) {
-    pthread_mutex_lock(&data->mutex);
-    data->trackCount += 1;
-    pthread_mutex_unlock(&data->mutex);
-}
-
-static void removeSvc(activator_data_t *data, void *svc __attribute__((unused))) {
-    pthread_mutex_lock(&data->mutex);
-    data->trackCount -= 1;
-    pthread_mutex_unlock(&data->mutex);
-}
-
-static void useHighest(activator_data_t *data __attribute__((unused)), example_calc_t *svc, const celix_properties_t *props) {
-    int result = svc->calc(svc->handle, 2);
-    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L);
-    long rank = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_RANKING, -1L);
-    printf("Called highest ranking service. Result is %i, svc id is %li, svc ranking is %li\n", result, svcId, rank);
-}
-
-
-void * run(void *handle) {
-    activator_data_t *data = handle;
-
-    printf("starting consumer thread\n");
-    long trkId = celix_bundleContext_trackServices(data->ctx, EXAMPLE_CALC_NAME, data, (void*)addSvc, (void*)removeSvc);
-
-    while (isRunning(data)) {
-        struct info info;
-        info.result = 0;
-        info.count = 0;
-        celix_bundleContext_useServices(data->ctx, EXAMPLE_CALC_NAME, &info, useCalc);
-        printf("Called calc services %i times, total result is %i\n", info.count, info.result);
-
-        gccExample(data); //gcc trampolines example (nested functions)
-
-        celix_service_use_options_t opts;
-        memset(&opts, 0, sizeof(opts));
-
-        opts.serviceName = EXAMPLE_CALC_NAME;
-        opts.callbackHandle = data;
-        opts.useWithProperties = (void*)useHighest;
-        celix_bundleContext_useServiceWithOptions(data->ctx, &opts);
-
-        pthread_mutex_lock(&data->mutex);
-        int count = data->trackCount;
-        pthread_mutex_unlock(&data->mutex);
-        printf("Current tracking count is %i\n", count);
-
-        sleep(5);
-    }
-
-    celix_bundleContext_stopTracker(data->ctx, trkId);
-    printf("exiting consumer thread\n");
-
-    pthread_exit(NULL);
-    return NULL;
-}
-
-celix_status_t bundleActivator_create(celix_bundle_context_t *ctx, void **out) {
-	celix_status_t status = CELIX_SUCCESS;
-    activator_data_t *data = calloc(1, sizeof(*data));
-    if (data != NULL) {
-       data->ctx = ctx;
-       data->trackCount = 0;
-       data->running = true;
-       pthread_mutex_init(&data->mutex, NULL);
-       *out = data;
-	} else {
-		status = CELIX_ENOMEM;
-	}
-	return status;
-}
-
-celix_status_t bundleActivator_start(void * handle, celix_bundle_context_t *ctx) {
-    activator_data_t *data = handle;
-    pthread_create(&data->thread, NULL, run, data);
-	return CELIX_SUCCESS;
-}
-
-celix_status_t bundleActivator_stop(void * handle, celix_bundle_context_t *ctx) {
-    activator_data_t *data = handle;
-    setRunning(data, false);
-    pthread_join(data->thread, NULL);
-    return CELIX_SUCCESS;
-}
-
-celix_status_t bundleActivator_destroy(void * handle, celix_bundle_context_t *ctx) {
-    activator_data_t *data = handle;
-    if (data != NULL) {
-        pthread_mutex_destroy(&data->mutex);
-        free(data);
-    }
-	return CELIX_SUCCESS;
-}

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/examples/celix-examples/services_example_c/src/dynamic_consumer_example.c
----------------------------------------------------------------------
diff --git a/examples/celix-examples/services_example_c/src/dynamic_consumer_example.c b/examples/celix-examples/services_example_c/src/dynamic_consumer_example.c
new file mode 100644
index 0000000..5a676d6
--- /dev/null
+++ b/examples/celix-examples/services_example_c/src/dynamic_consumer_example.c
@@ -0,0 +1,189 @@
+/**
+ *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 <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <constants.h>
+
+#include "example_calc.h"
+#include "bundle_activator.h"
+
+typedef struct activator_data {
+    celix_bundle_context_t *ctx;
+    pthread_t thread;
+
+    pthread_mutex_t mutex; //protects running
+    bool running;
+    int trackCount;
+} activator_data_t;
+
+static bool isRunning(activator_data_t *data) {
+    bool result = false;
+    pthread_mutex_lock(&data->mutex);
+    result = data->running;
+    pthread_mutex_unlock(&data->mutex);
+    return result;
+}
+
+static void setRunning(activator_data_t *data, bool val) {
+    pthread_mutex_lock(&data->mutex);
+    data->running = val;
+    pthread_mutex_unlock(&data->mutex);
+}
+
+struct info {
+    int result;
+    int count;
+};
+
+static void useCalc(void *handle, void *svc) {
+    struct info *i = handle;
+    example_calc_t *calc = svc;
+    i->result += calc->calc(calc->handle, 1);
+    i->count += 1;
+}
+
+static void gccExample(activator_data_t *data) {
+#ifdef USE_NESTED_FUNCTION_EXAMPLE
+
+    int result = 0;
+    long rank = 0;
+    long svcId = 0;
+
+    void use(void *handle, void *svc, const celix_properties_t *props) {
+        example_calc_t *calc = svc;
+        rank = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_RANKING, -1L);
+        svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L);
+        result = calc->calc(calc->handle, 1);
+    }
+
+    celix_service_use_options_t opts;
+    memset(&opts, 0, sizeof(opts));
+
+    opts.serviceName = EXAMPLE_CALC_NAME;
+    opts.callbackHandle = NULL; //can be null for trampolines
+    opts.useWithProperties = use;
+    bool called = celix_bundleContext_useServiceWithOptions(data->ctx, &opts);
+
+    printf("Called func %s. Result is %i, rank is %li and svc id is %li\n", called ? "called" : "not called", result, rank, svcId);
+
+#endif
+}
+
+static void addSvc(activator_data_t *data, void *svc __attribute__((unused))) {
+    pthread_mutex_lock(&data->mutex);
+    data->trackCount += 1;
+    pthread_mutex_unlock(&data->mutex);
+}
+
+static void removeSvc(activator_data_t *data, void *svc __attribute__((unused))) {
+    pthread_mutex_lock(&data->mutex);
+    data->trackCount -= 1;
+    pthread_mutex_unlock(&data->mutex);
+}
+
+static void useHighest(activator_data_t *data __attribute__((unused)), example_calc_t *svc, const celix_properties_t *props) {
+    int result = svc->calc(svc->handle, 2);
+    long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L);
+    long rank = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_RANKING, -1L);
+    printf("Called highest ranking service. Result is %i, svc id is %li, svc ranking is %li\n", result, svcId, rank);
+}
+
+
+void * run(void *handle) {
+    activator_data_t *data = handle;
+
+    printf("starting consumer thread\n");
+    celix_service_tracking_options_t opts;
+    opts.serviceName = EXAMPLE_CALC_NAME;
+    opts.callbackHandle = data;
+    opts.addWithProperties = (void*)addSvc;
+    opts.removeWithProperties = (void*)removeSvc;
+    long trkId = celix_bundleContext_trackServicesWithOptions(data->ctx, &opts);
+
+    while (isRunning(data)) {
+        struct info info;
+        info.result = 0;
+        info.count = 0;
+        celix_bundleContext_useServices(data->ctx, EXAMPLE_CALC_NAME, &info, useCalc);
+        printf("Called calc services %i times, total result is %i\n", info.count, info.result);
+
+        gccExample(data); //gcc trampolines example (nested functions)
+
+        celix_service_use_options_t opts;
+        memset(&opts, 0, sizeof(opts));
+
+        opts.serviceName = EXAMPLE_CALC_NAME;
+        opts.callbackHandle = data;
+        opts.useWithProperties = (void*)useHighest;
+        celix_bundleContext_useServiceWithOptions(data->ctx, &opts);
+
+        pthread_mutex_lock(&data->mutex);
+        int count = data->trackCount;
+        pthread_mutex_unlock(&data->mutex);
+        printf("Current tracking count is %i\n", count);
+
+        sleep(5);
+    }
+
+    celix_bundleContext_stopTracker(data->ctx, trkId);
+    printf("exiting consumer thread\n");
+
+    pthread_exit(NULL);
+    return NULL;
+}
+
+celix_status_t bundleActivator_create(celix_bundle_context_t *ctx, void **out) {
+	celix_status_t status = CELIX_SUCCESS;
+    activator_data_t *data = calloc(1, sizeof(*data));
+    if (data != NULL) {
+       data->ctx = ctx;
+       data->trackCount = 0;
+       data->running = true;
+       pthread_mutex_init(&data->mutex, NULL);
+       *out = data;
+	} else {
+		status = CELIX_ENOMEM;
+	}
+	return status;
+}
+
+celix_status_t bundleActivator_start(void * handle, celix_bundle_context_t *ctx) {
+    activator_data_t *data = handle;
+    pthread_create(&data->thread, NULL, run, data);
+	return CELIX_SUCCESS;
+}
+
+celix_status_t bundleActivator_stop(void * handle, celix_bundle_context_t *ctx) {
+    activator_data_t *data = handle;
+    setRunning(data, false);
+    pthread_join(data->thread, NULL);
+    return CELIX_SUCCESS;
+}
+
+celix_status_t bundleActivator_destroy(void * handle, celix_bundle_context_t *ctx) {
+    activator_data_t *data = handle;
+    if (data != NULL) {
+        pthread_mutex_destroy(&data->mutex);
+        free(data);
+    }
+	return CELIX_SUCCESS;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/examples/celix-examples/services_example_c/src/dynamic_provider_example.c
----------------------------------------------------------------------
diff --git a/examples/celix-examples/services_example_c/src/dynamic_provider_example.c b/examples/celix-examples/services_example_c/src/dynamic_provider_example.c
new file mode 100644
index 0000000..f322303
--- /dev/null
+++ b/examples/celix-examples/services_example_c/src/dynamic_provider_example.c
@@ -0,0 +1,134 @@
+/**
+ *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 <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "example_calc.h"
+#include "bundle_activator.h"
+#include "constants.h"
+
+typedef struct activator_data {
+    long svcIds[100];
+    example_calc_t svc;
+    celix_bundle_context_t *ctx;
+    pthread_t thread;
+
+    pthread_mutex_t mutex; //protects running
+    bool running;
+} activator_data_t;
+
+
+static int calc(void *handle __attribute__((unused)), int input) {
+    return 42 * input;
+}
+
+static bool isRunning(activator_data_t *data) {
+    bool result = false;
+    pthread_mutex_lock(&data->mutex);
+    result = data->running;
+    pthread_mutex_unlock(&data->mutex);
+    return result;
+}
+
+static void setRunning(activator_data_t *data, bool val) {
+    pthread_mutex_lock(&data->mutex);
+    data->running = val;
+    pthread_mutex_unlock(&data->mutex);
+}
+
+void * run(void *handle) {
+    activator_data_t *data = handle;
+
+    printf("starting service register thread\n");
+
+    int i = 0;
+    bool up = true;
+    while (isRunning(data)) {
+        if (up) {
+            properties_t *props = properties_create();
+            celix_properties_setLong(props, OSGI_FRAMEWORK_SERVICE_RANKING, rand());
+            data->svcIds[i++] = celix_bundleContext_registerService(data->ctx, EXAMPLE_CALC_NAME, &data->svc, NULL, props);
+        } else { //down
+            celix_bundleContext_unregisterService(data->ctx, data->svcIds[i--]);
+        }
+        if (i == 99) {
+            up = false;
+        } else if (i == 0) {
+            up = true;
+        }
+        usleep(100000);
+    }
+
+    for (int i = 0; i < 100; ++i) {
+        long id = data->svcIds[i];
+        if (id >=0 ) {
+            celix_bundleContext_unregisterService(data->ctx, id);
+        }
+    }
+
+    printf("exiting service register thread\n");
+
+    pthread_exit(NULL);
+    return NULL;
+}
+
+celix_status_t bundleActivator_create(celix_bundle_context_t *ctx, void **out) {
+	celix_status_t status = CELIX_SUCCESS;
+    activator_data_t *data = calloc(1, sizeof(*data));
+    if (data != NULL) {
+       data->svc.handle = data;
+       data->svc.calc = calc;
+       data->ctx = ctx;
+       data->running = true;
+       pthread_mutex_init(&data->mutex, NULL);
+
+       for (int i = 0; i < 100; ++i) {
+           data->svcIds[i] = -1L;
+       }
+
+       *out = data;
+	} else {
+		status = CELIX_ENOMEM;
+	}
+	return status;
+}
+
+celix_status_t bundleActivator_start(void * handle, celix_bundle_context_t *ctx) {
+    activator_data_t *data = handle;
+    pthread_create(&data->thread, NULL, run ,data);
+	return CELIX_SUCCESS;
+}
+
+celix_status_t bundleActivator_stop(void * handle, celix_bundle_context_t *ctx) {
+    activator_data_t *data = handle;
+    setRunning(data, false);
+    pthread_join(data->thread, NULL);
+    return CELIX_SUCCESS;
+}
+
+celix_status_t bundleActivator_destroy(void * handle, celix_bundle_context_t *ctx) {
+    activator_data_t *data = handle;
+    if (data != NULL) {
+        pthread_mutex_destroy(&data->mutex);
+        free(data);
+    }
+	return CELIX_SUCCESS;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/examples/celix-examples/services_example_c/src/provider_example.c
----------------------------------------------------------------------
diff --git a/examples/celix-examples/services_example_c/src/provider_example.c b/examples/celix-examples/services_example_c/src/provider_example.c
deleted file mode 100644
index f322303..0000000
--- a/examples/celix-examples/services_example_c/src/provider_example.c
+++ /dev/null
@@ -1,134 +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 <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "example_calc.h"
-#include "bundle_activator.h"
-#include "constants.h"
-
-typedef struct activator_data {
-    long svcIds[100];
-    example_calc_t svc;
-    celix_bundle_context_t *ctx;
-    pthread_t thread;
-
-    pthread_mutex_t mutex; //protects running
-    bool running;
-} activator_data_t;
-
-
-static int calc(void *handle __attribute__((unused)), int input) {
-    return 42 * input;
-}
-
-static bool isRunning(activator_data_t *data) {
-    bool result = false;
-    pthread_mutex_lock(&data->mutex);
-    result = data->running;
-    pthread_mutex_unlock(&data->mutex);
-    return result;
-}
-
-static void setRunning(activator_data_t *data, bool val) {
-    pthread_mutex_lock(&data->mutex);
-    data->running = val;
-    pthread_mutex_unlock(&data->mutex);
-}
-
-void * run(void *handle) {
-    activator_data_t *data = handle;
-
-    printf("starting service register thread\n");
-
-    int i = 0;
-    bool up = true;
-    while (isRunning(data)) {
-        if (up) {
-            properties_t *props = properties_create();
-            celix_properties_setLong(props, OSGI_FRAMEWORK_SERVICE_RANKING, rand());
-            data->svcIds[i++] = celix_bundleContext_registerService(data->ctx, EXAMPLE_CALC_NAME, &data->svc, NULL, props);
-        } else { //down
-            celix_bundleContext_unregisterService(data->ctx, data->svcIds[i--]);
-        }
-        if (i == 99) {
-            up = false;
-        } else if (i == 0) {
-            up = true;
-        }
-        usleep(100000);
-    }
-
-    for (int i = 0; i < 100; ++i) {
-        long id = data->svcIds[i];
-        if (id >=0 ) {
-            celix_bundleContext_unregisterService(data->ctx, id);
-        }
-    }
-
-    printf("exiting service register thread\n");
-
-    pthread_exit(NULL);
-    return NULL;
-}
-
-celix_status_t bundleActivator_create(celix_bundle_context_t *ctx, void **out) {
-	celix_status_t status = CELIX_SUCCESS;
-    activator_data_t *data = calloc(1, sizeof(*data));
-    if (data != NULL) {
-       data->svc.handle = data;
-       data->svc.calc = calc;
-       data->ctx = ctx;
-       data->running = true;
-       pthread_mutex_init(&data->mutex, NULL);
-
-       for (int i = 0; i < 100; ++i) {
-           data->svcIds[i] = -1L;
-       }
-
-       *out = data;
-	} else {
-		status = CELIX_ENOMEM;
-	}
-	return status;
-}
-
-celix_status_t bundleActivator_start(void * handle, celix_bundle_context_t *ctx) {
-    activator_data_t *data = handle;
-    pthread_create(&data->thread, NULL, run ,data);
-	return CELIX_SUCCESS;
-}
-
-celix_status_t bundleActivator_stop(void * handle, celix_bundle_context_t *ctx) {
-    activator_data_t *data = handle;
-    setRunning(data, false);
-    pthread_join(data->thread, NULL);
-    return CELIX_SUCCESS;
-}
-
-celix_status_t bundleActivator_destroy(void * handle, celix_bundle_context_t *ctx) {
-    activator_data_t *data = handle;
-    if (data != NULL) {
-        pthread_mutex_destroy(&data->mutex);
-        free(data);
-    }
-	return CELIX_SUCCESS;
-}

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/examples/celix-examples/services_example_c/src/simple_consumer_example.c
----------------------------------------------------------------------
diff --git a/examples/celix-examples/services_example_c/src/simple_consumer_example.c b/examples/celix-examples/services_example_c/src/simple_consumer_example.c
new file mode 100644
index 0000000..edf88c6
--- /dev/null
+++ b/examples/celix-examples/services_example_c/src/simple_consumer_example.c
@@ -0,0 +1,85 @@
+/**
+ *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 <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <constants.h>
+
+#include "example_calc.h"
+#include "bundle_activator.h"
+
+typedef struct activator_data {
+    celix_bundle_context_t *ctx;
+    long trkId;
+} activator_data_t;
+
+
+static void addSvc(activator_data_t *data __attribute__((unused)), example_calc_t *calc) {
+    int result = calc->calc(calc->handle, 2);
+    printf("Added calc service, result is %i\n", result);
+}
+
+static void removeSvc(activator_data_t *data __attribute__((unused)), example_calc_t *calc) {
+    int result = calc->calc(calc->handle, 3);
+    printf("Removing calc service, result is %i\n", result);
+}
+
+static void useCalc(activator_data_t *data __attribute__((unused)), example_calc_t *calc) {
+    int result = calc->calc(calc->handle, 2);
+    printf("Called highest ranking service. Result is %i\n", result);
+}
+
+celix_status_t bundleActivator_create(celix_bundle_context_t *ctx, void **out) {
+	celix_status_t status = CELIX_SUCCESS;
+    activator_data_t *data = calloc(1, sizeof(*data));
+    if (data != NULL) {
+       data->ctx = ctx;
+       data->trkId = -1L;
+       *out = data;
+	} else {
+		status = CELIX_ENOMEM;
+	}
+	return status;
+}
+
+celix_status_t bundleActivator_start(void * handle, celix_bundle_context_t *ctx) {
+    activator_data_t *data = handle;
+
+    printf("Starting service tracker\n");
+    data->trkId = celix_bundleContext_trackServices(data->ctx, EXAMPLE_CALC_NAME, data, (void*)addSvc, (void*)removeSvc);
+
+    printf("Trying to use calc service\n");
+    celix_bundleContext_useService(data->ctx, EXAMPLE_CALC_NAME, data, (void*)useCalc);
+
+	return CELIX_SUCCESS;
+}
+
+celix_status_t bundleActivator_stop(void * handle, celix_bundle_context_t *ctx) {
+    activator_data_t *data = handle;
+    celix_bundleContext_stopTracker(data->ctx, data->trkId);
+    return CELIX_SUCCESS;
+}
+
+celix_status_t bundleActivator_destroy(void * handle, celix_bundle_context_t *ctx) {
+    activator_data_t *data = handle;
+    free(data);
+	return CELIX_SUCCESS;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/examples/celix-examples/services_example_c/src/simple_provider_example.c
----------------------------------------------------------------------
diff --git a/examples/celix-examples/services_example_c/src/simple_provider_example.c b/examples/celix-examples/services_example_c/src/simple_provider_example.c
new file mode 100644
index 0000000..765a49e
--- /dev/null
+++ b/examples/celix-examples/services_example_c/src/simple_provider_example.c
@@ -0,0 +1,73 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "example_calc.h"
+#include "bundle_activator.h"
+#include "constants.h"
+
+typedef struct activator_data {
+    celix_bundle_context_t *ctx;
+    example_calc_t svc;
+    int seed;
+    long svcId;
+} activator_data_t;
+
+
+static int calc(activator_data_t *data, int input) {
+    return data->seed * input;
+}
+
+celix_status_t bundleActivator_create(celix_bundle_context_t *ctx, void **out) {
+	celix_status_t status = CELIX_SUCCESS;
+    activator_data_t *data = calloc(1, sizeof(*data));
+    if (data != NULL) {
+       data->svc.handle = data;
+       data->svc.calc = (void*)calc;
+       data->ctx = ctx;
+       data->seed = 42;
+       data->svcId = -1L;
+       *out = data;
+	} else {
+		status = CELIX_ENOMEM;
+	}
+	return status;
+}
+
+celix_status_t bundleActivator_start(void * handle, celix_bundle_context_t *ctx) {
+    activator_data_t *data = handle;
+    data->svcId = celix_bundleContext_registerService(data->ctx, EXAMPLE_CALC_NAME, &data->svc, EXAMPLE_CALC_VERSION, NULL);
+    printf("Registered calc service with service id %li\n", data->svcId);
+	return CELIX_SUCCESS;
+}
+
+celix_status_t bundleActivator_stop(void * handle, celix_bundle_context_t *ctx) {
+    activator_data_t *data = handle;
+    celix_bundleContext_unregisterService(data->ctx, data->svcId);
+    printf("Unregistered calc service with service id %li\n", data->svcId);
+    return CELIX_SUCCESS;
+}
+
+celix_status_t bundleActivator_destroy(void * handle, celix_bundle_context_t *ctx) {
+    activator_data_t *data = handle;
+    free(data);
+	return CELIX_SUCCESS;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/include/bundle_context.h
----------------------------------------------------------------------
diff --git a/framework/include/bundle_context.h b/framework/include/bundle_context.h
index ec974fa..44cca39 100644
--- a/framework/include/bundle_context.h
+++ b/framework/include/bundle_context.h
@@ -29,6 +29,7 @@
 #include "celix_types.h"
 
 #include "service_factory.h"
+#include "celix_service_factory.h"
 #include "service_listener.h"
 #include "bundle_listener.h"
 #include "framework_listener.h"
@@ -201,7 +202,8 @@ dm_dependency_manager_t* celix_bundleContext_getDependencyManager(celix_bundle_c
  * @param ctx The bundle context
  * @param serviceName the service name, cannot be NULL
  * @param svc the service object. Normally a pointer to a service struct (e.g. a struct with function pointers)
- * @param properties The meta properties assiated with the service. The service registration will take ownership of the properties (e.g. no destroy needed)
+ * @param serviceVersion The optional service version.
+ * @param properties The meta properties associated with the service. The service registration will take ownership of the properties (e.g. no destroy needed)
  * @return The serviceId, which should be >= 0. If < 0 then the registration was unsuccessful.
  */
 long celix_bundleContext_registerService(celix_bundle_context_t *ctx, const char *serviceName, void *svc, const char *serviceVersion, celix_properties_t *properties);
@@ -211,17 +213,56 @@ long celix_bundleContext_registerService(celix_bundle_context_t *ctx, const char
 *
 * @param ctx The bundle context
 * @param serviceName the service name, cannot be NULL
-* @param svc the service object. Normally a pointer to a service struct (e.g. a struct with function pointers)
-* @param properties The meta properties assiated with the service. The service registration will take ownership of the properties
+* @param svc Pointer to the service. Normally a pointer to a service struct (e.g. a struct with function pointers)
+* @param serviceVersion The optional service version.
+* @param lang The service language. Will be set to CELIX_FRAMEWORK_SERVICE_LANGUAGE_C if NULL is provided.
+* @param properties The meta properties associated with the service. The service registration will take ownership of the properties
 * @return The serviceId, which should >= 0. If < 0 then the registration was unsuccessful.
 */
 long celix_bundleContext_registerServiceForLang(celix_bundle_context_t *ctx, const char *serviceName, void *svc, const char *serviceVersion, const char* lang, celix_properties_t *properties);
 
-//TODO register service factory
+/**
+ * Register a service factory in the framework (for the C language).
+ * THe service factory will be called for every bundle requesting/de-requesting a service. This gives the provider the
+ * option to create bundle specific service instances.
+ *
+ * When a service is requested for a bundle the getService of the factory service will be called. This function must
+ * return a valid pointer to a service conform the registered service name or NULL.
+ * When a service in no longer needed for a bundle (e.g. ending the useService(s) calls when a service tacker is stopped)
+ * the ungetService function of the service factory will be called.
+ *
+ * @param ctx The bundle context
+ * @param serviceName The required service name of the services this factory will produce.
+ * @param factory The pointer to the factory service.
+ * @param serviceVersion The optional service version.
+ * @param properties The optional service factory properties. For a service consumer this will be seen as the service properties.
+ * @return The service id of the service factory or < 0 if the registration was unsuccessful.
+ */
+long celix_bundleContext_registerServiceFactory(celix_bundle_context_t *ctx, const char *serviceName, celix_service_factory_t *factory, const char *serviceVersion, celix_properties_t *properties);
+
+/**
+ * Register a service factory in the framework.
+ * THe service factory will be called for every bundle requesting/de-requesting a service. This gives the provider the
+ * option to create bundle specific service instances.
+ *
+ * When a service is requested for a bundle the getService of the factory service will be called. This function must
+ * return a valid pointer to a service conform the registered service name or NULL.
+ * When a service in no longer needed for a bundle (e.g. ending the useService(s) calls when a service tacker is stopped)
+ * the ungetService function of the service factory will be called.
+ *
+ * @param ctx The bundle context
+ * @param serviceName The required service name of the services this factory will produce.
+ * @param factory The pointer to the factory service.
+ * @param serviceVersion The optional service version.
+ * @param lang The d service language. Will be set to CELIX_FRAMEWORK_SERVICE_LANGUAGE_C if NULL is provided.
+ * @param properties The optional service factory properties. For a service consumer this will be seen as the service properties.
+ * @return The service id of the service factory or < 0 if the registration was unsuccessful.
+ */
+long celix_bundleContext_registerServiceFactorForLang(celix_bundle_context_t *ctx, const char *serviceName, celix_service_factory_t *factory, const char *serviceVersion, const char *lang, celix_properties_t *properties);
 
 /**
- * Unregister the service with service id. The service will only be unregistered if the bundle of the bundle context
- * is the owner of the service.
+ * Unregister the service or service factory with service id.
+ * The service will only be unregistered if the bundle of the bundle context is the owner of the service.
  *
  * Will log an error if service id is unknown. Will silently ignore services ids < 0.
  *
@@ -557,10 +598,12 @@ void celix_bundleContext_useBundle(
         void (*use)(void *handle, const celix_bundle_t *bundle)
 );
 
-//TODO add useBundleWithState (bit wise or?)
+//TODO add useBundleWithOptions (e.g. which state)
+
+
+//TODO findBundles
 
 
-//TODO except framework & own bundle
 /**
  * Use the currently active (started) bundles.
  * The provided callback will be called for all the currently started bundles.
@@ -577,7 +620,7 @@ void celix_bundleContext_useBundles(
 );
 
 
-//TODO trackerServiceTracker
+//TODO trackServiceTracker
 
 /**
  * Stop the tracker with the provided track id.

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/include/celix_service_factory.h
----------------------------------------------------------------------
diff --git a/framework/include/celix_service_factory.h b/framework/include/celix_service_factory.h
new file mode 100644
index 0000000..4373db6
--- /dev/null
+++ b/framework/include/celix_service_factory.h
@@ -0,0 +1,43 @@
+/**
+ *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 CELIX_SERVICE_FACTORY_H_
+#define CELIX_SERVICE_FACTORY_H_
+
+#include "properties.h"
+#include "bundle.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct celix_service_factory celix_service_factory_t;
+
+struct celix_service_factory {
+    void *handle;
+
+    void* (*getService)(void *handle, const celix_bundle_t *requestingBundle, const celix_properties_t *svcProperties);
+
+    void (*ungetService)(void *handle, const celix_bundle_t *requestingBundle, const celix_properties_t *svcProperties);
+};
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CELIX_SERVICE_FACTORY_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/include/celix_types.h
----------------------------------------------------------------------
diff --git a/framework/include/celix_types.h b/framework/include/celix_types.h
index 7846c1c..6e02c63 100644
--- a/framework/include/celix_types.h
+++ b/framework/include/celix_types.h
@@ -48,4 +48,6 @@ typedef struct dm_component_struct dm_component_t;
 typedef struct dm_service_dependency *dm_service_dependency_pt;
 typedef struct dm_service_dependency dm_service_dependency_t;
 
+typedef struct service_factory *service_factory_pt; //deprecated
+
 #endif //CELIX_CELIX_TYPES_H

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/include/service_factory.h
----------------------------------------------------------------------
diff --git a/framework/include/service_factory.h b/framework/include/service_factory.h
index 84e383a..80230d1 100644
--- a/framework/include/service_factory.h
+++ b/framework/include/service_factory.h
@@ -16,26 +16,10 @@
  *specific language governing permissions and limitations
  *under the License.
  */
-/*
- * service_factory.h
- *
- *  \date       Jun 26, 2011
- *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright	Apache License, Version 2.0
- */
-
 #ifndef SERVICE_FACTORY_H_
 #define SERVICE_FACTORY_H_
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-typedef struct service_factory service_factory_t;
-typedef service_factory_t *service_factory_pt;
-#ifdef __cplusplus
-}
-#endif
 
+#include "celix_types.h"
 #include "celix_errno.h"
 #include "service_registration.h"
 #include "bundle.h"
@@ -47,10 +31,10 @@ extern "C" {
 struct service_factory {
     void *handle;
 
-    celix_status_t (*getService)(void *handle, bundle_pt bundle, service_registration_pt registration, void **service);
+    celix_status_t (*getService)(void *handle, celix_bundle_t *bnd, service_registration_pt registration, void **service);
 
     celix_status_t
-    (*ungetService)(void *handle, bundle_pt bundle, service_registration_pt registration, void **service);
+    (*ungetService)(void *handle, celix_bundle_t *bnd, service_registration_pt registration, void **service);
 };
 
 #ifdef __cplusplus

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/include/service_registry.h
----------------------------------------------------------------------
diff --git a/framework/include/service_registry.h b/framework/include/service_registry.h
index 9a2ec48..9ca4a59 100644
--- a/framework/include/service_registry.h
+++ b/framework/include/service_registry.h
@@ -27,7 +27,8 @@
 #ifndef SERVICE_REGISTRY_H_
 #define SERVICE_REGISTRY_H_
 
-typedef struct serviceRegistry * service_registry_pt;
+typedef struct celix_serviceRegistry * service_registry_pt;
+typedef struct celix_serviceRegistry celix_service_registry_t;
 
 #include "properties.h"
 #include "filter.h"
@@ -35,6 +36,8 @@ typedef struct serviceRegistry * service_registry_pt;
 #include "service_event.h"
 #include "array_list.h"
 #include "service_registration.h"
+#include "celix_service_factory.h"
+
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -96,6 +99,15 @@ celix_status_t
 serviceRegistry_servicePropertiesModified(service_registry_pt registry, service_registration_pt registration,
                                           properties_pt oldprops);
 
+celix_status_t
+celix_serviceRegistry_registerServiceFactory(
+        celix_service_registry_t *reg,
+        const celix_bundle_t *bnd,
+        const char *serviceName,
+        celix_service_factory_t *factory,
+        celix_properties_t* props,
+        service_registration_t **registration);
+
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/private/mock/bundle_context_mock.c
----------------------------------------------------------------------
diff --git a/framework/private/mock/bundle_context_mock.c b/framework/private/mock/bundle_context_mock.c
index 8225580..749e3ca 100644
--- a/framework/private/mock/bundle_context_mock.c
+++ b/framework/private/mock/bundle_context_mock.c
@@ -326,3 +326,24 @@ void celix_bundleContext_useServicesWithOptions(
 			->withPointerParameters("ctx", ctx)
 			->withConstPointerParameters("opts", opts);
 }
+
+long celix_bundleContext_registerServiceFactory(celix_bundle_context_t *ctx, const char *serviceName, celix_service_factory_t *factory, const char *serviceVersion, celix_properties_t *props) {
+	mock_c()->actualCall("celix_bundleContext_registerServiceFactory")
+			->withPointerParameters("ctx", ctx)
+			->withStringParameters("serviceName", serviceName)
+			->withPointerParameters("factory", factory)
+			->withStringParameters("serviceVersion", serviceVersion)
+			->withPointerParameters("props", props);
+	return mock_c()->returnValue().value.longIntValue;
+}
+
+long celix_bundleContext_registerServiceFactorForLang(celix_bundle_context_t *ctx, const char *serviceName, celix_service_factory_t *factory, const char *serviceVersion, const char *lang, celix_properties_t *props) {
+	mock_c()->actualCall("celix_bundleContext_registerServiceFactorForLang")
+			->withPointerParameters("ctx", ctx)
+			->withStringParameters("serviceName", serviceName)
+			->withPointerParameters("factory", factory)
+			->withStringParameters("serviceVersion", serviceVersion)
+			->withStringParameters("lang", lang)
+			->withPointerParameters("props", props);
+	return mock_c()->returnValue().value.longIntValue;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/private/mock/framework_mock.c
----------------------------------------------------------------------
diff --git a/framework/private/mock/framework_mock.c b/framework/private/mock/framework_mock.c
index d718ade..7bbd752 100644
--- a/framework/private/mock/framework_mock.c
+++ b/framework/private/mock/framework_mock.c
@@ -335,4 +335,12 @@ void celix_framework_useBundle(framework_t *fw, long bundleId, void *callbackHan
 			->withPointerParameters("use", use);
 }
 
-
+service_registration_t* celix_framework_registerServiceFactory(framework_t *fw , const celix_bundle_t *bnd, const char* serviceName, celix_service_factory_t *factory, celix_properties_t *properties) {
+	mock_c()->actualCall("celix_framework_registerServiceFactory")
+			->withPointerParameters("fw", fw)
+			->withConstPointerParameters("bnd", bnd)
+			->withStringParameters("serviceName", serviceName)
+			->withPointerParameters("factory", factory)
+			->withPointerParameters("properties", properties);
+	return mock_c()->returnValue().value.pointerValue;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/private/mock/service_registration_mock.c
----------------------------------------------------------------------
diff --git a/framework/private/mock/service_registration_mock.c b/framework/private/mock/service_registration_mock.c
index 4bbf0c8..69be7eb 100644
--- a/framework/private/mock/service_registration_mock.c
+++ b/framework/private/mock/service_registration_mock.c
@@ -145,3 +145,20 @@ long serviceRegistration_getServiceId(service_registration_t *registration) {
 	return mock_c()->returnValue().value.longIntValue;
 }
 
+service_registration_t* celix_serviceRegistration_createServiceFactory(
+		registry_callback_t callback,
+		const celix_bundle_t *bnd,
+		const char *serviceName,
+		long svcId,
+		celix_service_factory_t* factory,
+		celix_properties_t *props) {
+	mock_c()->actualCall("celix_serviceRegistration_createServiceFactory")
+			->withParameterOfType("registry_callback_t", "callback", &callback)
+			->withConstPointerParameters("bnd", bnd)
+			->withStringParameters("serviceName", serviceName)
+			->withUnsignedLongIntParameters("svcId", svcId)
+			->withPointerParameters("factory", (void*) factory)
+			->withPointerParameters("props", props);
+	return mock_c()->returnValue().value.pointerValue;
+}
+

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/private/mock/service_registry_mock.c
----------------------------------------------------------------------
diff --git a/framework/private/mock/service_registry_mock.c b/framework/private/mock/service_registry_mock.c
index 60b8032..9942818 100644
--- a/framework/private/mock/service_registry_mock.c
+++ b/framework/private/mock/service_registry_mock.c
@@ -164,3 +164,21 @@ celix_status_t serviceRegistry_clearServiceRegistrations(service_registry_pt reg
 			->withPointerParameters("bundle", bundle);
 	return mock_c()->returnValue().value.intValue;
 }
+
+celix_status_t
+celix_serviceRegistry_registerServiceFactory(
+		celix_service_registry_t *reg,
+		const celix_bundle_t *bnd,
+		const char *serviceName,
+		celix_service_factory_t *factory,
+		celix_properties_t* props,
+		service_registration_t **registration) {
+	mock_c()->actualCall("celix_serviceRegistry_registerServiceFactory")
+			->withPointerParameters("reg", reg)
+			->withConstPointerParameters("bnd", bnd)
+			->withStringParameters("serviceName", serviceName)
+			->withPointerParameters("factory", factory)
+			->withPointerParameters("props", props)
+			->withOutputParameter("registration", registration);
+	return mock_c()->returnValue().value.intValue;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/private/test/service_registration_test.cpp
----------------------------------------------------------------------
diff --git a/framework/private/test/service_registration_test.cpp b/framework/private/test/service_registration_test.cpp
index da4420d..68986bf 100644
--- a/framework/private/test/service_registration_test.cpp
+++ b/framework/private/test/service_registration_test.cpp
@@ -111,8 +111,9 @@ TEST(service_registration, create) {
 	UNSIGNED_LONGS_EQUAL(serviceId, registration->serviceId);
 
 	LONGS_EQUAL(0, registration->isUnregistering);
-	LONGS_EQUAL(0, registration->isServiceFactory);
-	POINTERS_EQUAL(NULL, registration->serviceFactory);
+	LONGS_EQUAL(CELIX_PLAIN_SERVICE, registration->svcType);
+	POINTERS_EQUAL(NULL, registration->deprecatedFactory);
+	POINTERS_EQUAL(NULL, registration->factory);
 	POINTERS_EQUAL(NULL, registration->services);
 	LONGS_EQUAL(0, registration->nrOfServices);
 
@@ -143,8 +144,8 @@ TEST(service_registration, createServiceFactory) {
 	POINTERS_EQUAL(service, registration->svcObj);
 	UNSIGNED_LONGS_EQUAL(serviceId, registration->serviceId);
 	LONGS_EQUAL(0, registration->isUnregistering);
-	LONGS_EQUAL(1, registration->isServiceFactory);
-	POINTERS_EQUAL(service, registration->serviceFactory);
+	LONGS_EQUAL(CELIX_DEPRECATED_FACTORY_SERVICE, registration->svcType);
+	POINTERS_EQUAL(service, registration->deprecatedFactory);
 	POINTERS_EQUAL(NULL, registration->services);
 	LONGS_EQUAL(0, registration->nrOfServices);
 

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/src/bundle_context.c
----------------------------------------------------------------------
diff --git a/framework/src/bundle_context.c b/framework/src/bundle_context.c
index 5a9bbd1..7d5dea9 100644
--- a/framework/src/bundle_context.c
+++ b/framework/src/bundle_context.c
@@ -426,30 +426,25 @@ celix_status_t bundleContext_getPropertyWithDefault(bundle_context_pt context, c
 
 
 long celix_bundleContext_registerService(bundle_context_t *ctx, const char *serviceName, void *svc, const char *serviceVersion, properties_t *properties) {
-    return celix_bundleContext_registerServiceForLang(ctx, serviceName, svc, serviceVersion, CELIX_FRAMEWORK_SERVICE_C_LANGUAGE, properties);
+    return celix_bundleContext_registerServiceForLang(ctx, serviceName, svc, serviceVersion, NULL, properties);
 }
 
 
 long celix_bundleContext_registerServiceForLang(bundle_context_t *ctx, const char *serviceName, void *svc, const char *serviceVersion, const char* lang, properties_t *properties) {
     long svcId = -1;
+    service_registration_t *reg = NULL;
     if (properties == NULL) {
         properties = properties_create();
     }
-    service_registration_t *reg = NULL;
     if (serviceVersion != NULL) {
         properties_set(properties, CELIX_FRAMEWORK_SERVICE_VERSION, serviceVersion);
     }
-    if (serviceName != NULL && lang != NULL) {
-        properties_set(properties, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang);
+    if (serviceName != NULL) {
+        properties_set(properties, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang == NULL ? CELIX_FRAMEWORK_SERVICE_C_LANGUAGE : lang);
         bundleContext_registerService(ctx, serviceName, svc, properties, &reg);
         svcId = serviceRegistration_getServiceId(reg); //save to call with NULL
     } else {
-        if (serviceName == NULL) {
-            framework_logIfError(logger, CELIX_ILLEGAL_ARGUMENT, NULL, "Required serviceName argument is NULL");
-        }
-        if (lang == NULL) {
-            framework_logIfError(logger, CELIX_ILLEGAL_ARGUMENT, NULL, "Required lang argument is NULL");
-        }
+        framework_logIfError(logger, CELIX_ILLEGAL_ARGUMENT, NULL, "Required serviceName argument is NULL");
     }
     if (svcId < 0) {
         properties_destroy(properties);
@@ -812,4 +807,28 @@ long celix_bundleContext_trackServicesWithOptions(bundle_context_t *ctx, const c
         celixThreadMutex_unlock(&ctx->mutex);
     }
     return trackerId;
+}
+
+long celix_bundleContext_registerServiceFactory(celix_bundle_context_t *ctx, const char *serviceName, celix_service_factory_t *factory, const char *serviceVersion, celix_properties_t *props) {
+    return celix_bundleContext_registerServiceFactorForLang(ctx, serviceName, factory, serviceVersion, NULL, props);
+}
+
+long celix_bundleContext_registerServiceFactorForLang(celix_bundle_context_t *ctx, const char *serviceName, celix_service_factory_t *factory, const char *serviceVersion, const char *lang, celix_properties_t *props) {
+    if (props == NULL) {
+        props = celix_properties_create();
+    }
+    if (serviceVersion != NULL) {
+        celix_properties_set(props, CELIX_FRAMEWORK_SERVICE_VERSION, serviceVersion);
+    }
+    celix_properties_set(props, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang == NULL ? CELIX_FRAMEWORK_SERVICE_C_LANGUAGE : lang);
+    service_registration_t *reg = celix_framework_registerServiceFactory(ctx->framework, ctx->bundle, serviceName, factory, props);
+    long facId = serviceRegistration_getServiceId(reg); //save to call with NULL
+    if (facId < 0) {
+        properties_destroy(props);
+    } else {
+        celixThreadMutex_lock(&ctx->mutex);
+        arrayList_add(ctx->svcRegistrations, reg);
+        celixThreadMutex_unlock(&ctx->mutex);
+    }
+    return facId;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/src/framework.c
----------------------------------------------------------------------
diff --git a/framework/src/framework.c b/framework/src/framework.c
index b6cb825..952392c 100644
--- a/framework/src/framework.c
+++ b/framework/src/framework.c
@@ -2781,4 +2781,22 @@ void celix_framework_useBundle(framework_t *fw, long bundleId, void *callbackHan
         }
         //TODO unlock
     }
+}
+
+service_registration_t* celix_framework_registerServiceFactory(framework_t *fw , const celix_bundle_t *bnd, const char* serviceName, celix_service_factory_t *factory, celix_properties_t *properties) {
+    const char *error = NULL;
+    celix_status_t status = CELIX_SUCCESS;
+    service_registration_t *reg = NULL;
+    if (serviceName != NULL && factory != NULL) {
+        status = framework_acquireBundleLock(fw, (celix_bundle_t*)bnd, OSGI_FRAMEWORK_BUNDLE_STARTING|OSGI_FRAMEWORK_BUNDLE_ACTIVE);
+        status = CELIX_DO_IF(status, celix_serviceRegistry_registerServiceFactory(fw->registry, bnd, serviceName, factory, properties, &reg));
+        if (!framework_releaseBundleLock(fw, (celix_bundle_t*)bnd)) {
+            status = CELIX_ILLEGAL_STATE;
+            error = "Could not release bundle lock";
+        }
+    }
+
+    framework_logIfError(fw->logger, status, error, "Cannot register service factory: %s", serviceName);
+
+    return reg;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/src/framework_private.h
----------------------------------------------------------------------
diff --git a/framework/src/framework_private.h b/framework/src/framework_private.h
index 66c1125..ab0a940 100644
--- a/framework/src/framework_private.h
+++ b/framework/src/framework_private.h
@@ -65,7 +65,7 @@ struct framework {
     celix_thread_mutex_t bundleListenerLock;
 
     long nextBundleId;
-    struct serviceRegistry * registry;
+    celix_service_registry_t *registry;
     bundle_cache_pt cache;
 
     celix_thread_cond_t shutdownGate;
@@ -158,5 +158,6 @@ FRAMEWORK_EXPORT bundle_pt framework_getBundleById(framework_pt framework, long
 
 void celix_framework_useBundles(framework_t *fw, void *callbackHandle, void(*use)(void *handle, const bundle_t *bnd));
 void celix_framework_useBundle(framework_t *fw, long bundleId, void *callbackHandle, void(*use)(void *handle, const bundle_t *bnd));
+service_registration_t* celix_framework_registerServiceFactory(framework_t *fw , const celix_bundle_t *bnd, const char* serviceName, celix_service_factory_t *factory, celix_properties_t *properties);
 
 #endif /* FRAMEWORK_PRIVATE_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/src/service_registration.c
----------------------------------------------------------------------
diff --git a/framework/src/service_registration.c b/framework/src/service_registration.c
index fe25214..b3f45b2 100644
--- a/framework/src/service_registration.c
+++ b/framework/src/service_registration.c
@@ -33,7 +33,7 @@
 
 static celix_status_t serviceRegistration_initializeProperties(service_registration_pt registration, properties_pt properties);
 static celix_status_t serviceRegistration_createInternal(registry_callback_t callback, bundle_pt bundle, const char* serviceName, unsigned long serviceId,
-        const void * serviceObject, properties_pt dictionary, bool isFactory, service_registration_pt *registration);
+        const void * serviceObject, properties_pt dictionary, enum celix_service_type svcType, service_registration_pt *registration);
 static celix_status_t serviceRegistration_destroy(service_registration_pt registration);
 
 service_registration_pt serviceRegistration_create(registry_callback_t callback, bundle_pt bundle, const char* serviceName, unsigned long serviceId, const void * serviceObject, properties_pt dictionary) {
@@ -49,25 +49,25 @@ service_registration_pt serviceRegistration_createServiceFactory(registry_callba
 }
 
 static celix_status_t serviceRegistration_createInternal(registry_callback_t callback, bundle_pt bundle, const char* serviceName, unsigned long serviceId,
-        const void * serviceObject, properties_pt dictionary, bool isFactory, service_registration_pt *out) {
-    celix_status_t status = CELIX_SUCCESS;
+                                                         const void * serviceObject, properties_pt dictionary, enum celix_service_type svcType, service_registration_pt *out) {
 
+    celix_status_t status = CELIX_SUCCESS;
 	service_registration_pt  reg = calloc(1, sizeof(*reg));
     if (reg) {
         reg->callback = callback;
         reg->services = NULL;
         reg->nrOfServices = 0;
-		reg->isServiceFactory = isFactory;
+		reg->svcType = svcType;
 		reg->className = strndup(serviceName, 1024*10);
 		reg->bundle = bundle;
 		reg->refCount = 1;
-
 		reg->serviceId = serviceId;
-	reg->svcObj = serviceObject;
-		if (isFactory) {
-			reg->serviceFactory = (service_factory_pt) reg->svcObj;
-		} else {
-			reg->serviceFactory = NULL;
+	    reg->svcObj = serviceObject;
+
+		if (svcType == CELIX_DEPRECATED_FACTORY_SERVICE) {
+			reg->deprecatedFactory = (service_factory_pt) reg->svcObj;
+		} else if (svcType == CELIX_FACTORY_SERVICE) {
+			reg->factory = (celix_service_factory_t*) reg->svcObj;
 		}
 
 		reg->isUnregistering = false;
@@ -190,29 +190,29 @@ celix_status_t serviceRegistration_unregister(service_registration_pt registrati
 }
 
 celix_status_t serviceRegistration_getService(service_registration_pt registration, bundle_pt bundle, const void** service) {
-	int status = CELIX_SUCCESS;
     celixThreadRwlock_readLock(&registration->lock);
-    if (registration->isServiceFactory) {
-        service_factory_pt factory = (void*) registration->serviceFactory;
-        /*NOTE the service argument of the service_factory should be const void**.
-          To ensure backwards compatability a cast is made instead.
-        */
-        status = factory->getService(factory->handle, bundle, registration, (void**) service);
-    } else {
+    if (registration->svcType == CELIX_DEPRECATED_FACTORY_SERVICE) {
+        service_factory_pt factory = registration->deprecatedFactory;
+        factory->getService(factory->handle, bundle, registration, (void **) service);
+    } else if (registration->svcType == CELIX_FACTORY_SERVICE) {
+        celix_service_factory_t *fac = registration->factory;
+        *service = fac->getService(fac->handle, bundle, registration->properties);
+    } else { //plain service
         (*service) = registration->svcObj;
     }
     celixThreadRwlock_unlock(&registration->lock);
-    return status;
+
+    return CELIX_SUCCESS;
 }
 
 celix_status_t serviceRegistration_ungetService(service_registration_pt registration, bundle_pt bundle, const void** service) {
     celixThreadRwlock_readLock(&registration->lock);
-    if (registration->isServiceFactory) {
-        service_factory_pt factory = (void*) registration->serviceFactory;
-        /*NOTE the service argument of the service_factory should be const void**.
-          To ensure backwards compatibility a cast is made instead.
-        */
+    if (registration->svcType == CELIX_DEPRECATED_FACTORY_SERVICE) {
+        service_factory_pt factory = registration->deprecatedFactory;
         factory->ungetService(factory->handle, bundle, registration, (void**) service);
+    } else if (registration->svcType == CELIX_FACTORY_SERVICE) {
+        celix_service_factory_t *fac = registration->factory;
+        fac->ungetService(fac->handle, bundle, registration->properties);
     }
     celixThreadRwlock_unlock(&registration->lock);
     return CELIX_SUCCESS;
@@ -299,3 +299,16 @@ long serviceRegistration_getServiceId(service_registration_t *registration) {
     }
     return svcId;
 }
+
+
+service_registration_t* celix_serviceRegistration_createServiceFactory(
+        registry_callback_t callback,
+        const celix_bundle_t *bnd,
+        const char *serviceName,
+        long svcId,
+        celix_service_factory_t* factory,
+        celix_properties_t *props) {
+    service_registration_pt registration = NULL;
+    serviceRegistration_createInternal(callback, (celix_bundle_t*)bnd, serviceName, svcId, factory, props, CELIX_FACTORY_SERVICE, &registration);
+    return registration;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/src/service_registration_private.h
----------------------------------------------------------------------
diff --git a/framework/src/service_registration_private.h b/framework/src/service_registration_private.h
index ca0cb67..598e4c9 100644
--- a/framework/src/service_registration_private.h
+++ b/framework/src/service_registration_private.h
@@ -31,19 +31,26 @@
 #include "registry_callback_private.h"
 #include "service_registration.h"
 
+enum celix_service_type {
+	CELIX_PLAIN_SERVICE,
+	CELIX_FACTORY_SERVICE,
+	CELIX_DEPRECATED_FACTORY_SERVICE
+};
+
 struct serviceRegistration {
     registry_callback_t callback;
 
 	char * className;
 	bundle_pt bundle;
 	properties_pt properties;
-	const void * svcObj;
 	unsigned long serviceId;
 
 	bool isUnregistering;
 
-	bool isServiceFactory;
-	const void *serviceFactory;
+	enum celix_service_type svcType;
+	const void * svcObj;
+	service_factory_pt deprecatedFactory;
+	celix_service_factory_t *factory;
 
 	struct service *services;
 	int nrOfServices;
@@ -68,4 +75,13 @@ celix_status_t serviceRegistration_ungetService(service_registration_pt registra
 celix_status_t serviceRegistration_getBundle(service_registration_pt registration, bundle_pt *bundle);
 celix_status_t serviceRegistration_getServiceName(service_registration_pt registration, const char **serviceName);
 
+
+service_registration_t* celix_serviceRegistration_createServiceFactory(
+		registry_callback_t callback,
+		const celix_bundle_t *bnd,
+		const char *serviceName,
+		long svcId,
+		celix_service_factory_t* factory,
+		celix_properties_t *props);
+
 #endif /* SERVICE_REGISTRATION_PRIVATE_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/src/service_registry.c
----------------------------------------------------------------------
diff --git a/framework/src/service_registry.c b/framework/src/service_registry.c
index 65c1914..1493525 100644
--- a/framework/src/service_registry.c
+++ b/framework/src/service_registry.c
@@ -41,7 +41,7 @@
 #define CHECK_DELETED_REFERENCES false
 #endif
 
-static celix_status_t serviceRegistry_registerServiceInternal(service_registry_pt registry, bundle_pt bundle, const char* serviceName, const void * serviceObject, properties_pt dictionary, bool isFactory, service_registration_pt *registration);
+static celix_status_t serviceRegistry_registerServiceInternal(service_registry_pt registry, bundle_pt bundle, const char* serviceName, const void * serviceObject, properties_pt dictionary, enum celix_service_type svcType, service_registration_pt *registration);
 static celix_status_t serviceRegistry_addHooks(service_registry_pt registry, const char* serviceName, const void *serviceObject, service_registration_pt registration);
 static celix_status_t serviceRegistry_removeHook(service_registry_pt registry, service_registration_pt registration);
 static void serviceRegistry_logWarningServiceReferenceUsageCount(service_registry_pt registry, bundle_pt bundle, service_reference_pt ref, size_t usageCount, size_t refCount);
@@ -154,12 +154,16 @@ celix_status_t serviceRegistry_registerServiceFactory(service_registry_pt regist
     return serviceRegistry_registerServiceInternal(registry, bundle, serviceName, (const void *) factory, dictionary, true, registration);
 }
 
-static celix_status_t serviceRegistry_registerServiceInternal(service_registry_pt registry, bundle_pt bundle, const char* serviceName, const void* serviceObject, properties_pt dictionary, bool isFactory, service_registration_pt *registration) {
+static celix_status_t serviceRegistry_registerServiceInternal(service_registry_pt registry, bundle_pt bundle, const char* serviceName, const void * serviceObject, properties_pt dictionary, enum celix_service_type svcType, service_registration_pt *registration) {
 	array_list_pt regs;
 
-	if (isFactory) {
-	    *registration = serviceRegistration_createServiceFactory(registry->callback, bundle, serviceName, ++registry->currentServiceId, serviceObject, dictionary);
-	} else {
+	if (svcType == CELIX_DEPRECATED_FACTORY_SERVICE) {
+        *registration = serviceRegistration_createServiceFactory(registry->callback, bundle, serviceName,
+                                                                 ++registry->currentServiceId, serviceObject,
+                                                                 dictionary);
+    } else if (svcType == CELIX_FACTORY_SERVICE) {
+        *registration = celix_serviceRegistration_createServiceFactory(registry->callback, bundle, serviceName, ++registry->currentServiceId, (celix_service_factory_t*)serviceObject, dictionary);
+	} else { //plain
 	    *registration = serviceRegistration_create(registry->callback, bundle, serviceName, ++registry->currentServiceId, serviceObject, dictionary);
 	}
 
@@ -800,3 +804,14 @@ static celix_status_t serviceRegistry_getUsingBundles(service_registry_pt regist
 
     return status;
 }
+
+celix_status_t
+celix_serviceRegistry_registerServiceFactory(
+        celix_service_registry_t *reg,
+        const celix_bundle_t *bnd,
+        const char *serviceName,
+        celix_service_factory_t *factory,
+        celix_properties_t* props,
+        service_registration_t **registration) {
+    return serviceRegistry_registerServiceInternal(reg, (celix_bundle_t*)bnd, serviceName, (const void *) factory, props, CELIX_FACTORY_SERVICE, registration);
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/src/service_registry_private.h
----------------------------------------------------------------------
diff --git a/framework/src/service_registry_private.h b/framework/src/service_registry_private.h
index d68fe11..1bd0066 100644
--- a/framework/src/service_registry_private.h
+++ b/framework/src/service_registry_private.h
@@ -31,7 +31,7 @@
 #include "registry_callback_private.h"
 #include "service_registry.h"
 
-struct serviceRegistry {
+struct celix_serviceRegistry {
 	framework_pt framework;
 	registry_callback_t callback;
 

http://git-wip-us.apache.org/repos/asf/celix/blob/626687fe/framework/tst/bundle_context_services_test.cpp
----------------------------------------------------------------------
diff --git a/framework/tst/bundle_context_services_test.cpp b/framework/tst/bundle_context_services_test.cpp
index 790cbd2..2597ece 100644
--- a/framework/tst/bundle_context_services_test.cpp
+++ b/framework/tst/bundle_context_services_test.cpp
@@ -26,11 +26,13 @@
 #include <CppUTest/CommandLineTestRunner.h>
 #include <zconf.h>
 #include <string.h>
+#include <map>
 
 #include "constants.h"
 #include "bundle.h"
 #include "properties.h"
 #include "celix_framework_factory.h"
+#include "celix_service_factory.h"
 
 
 TEST_GROUP(CelixBundleContextServicesTests) {
@@ -582,3 +584,47 @@ TEST(CelixBundleContextServicesTests, servicesTrackerSetTest) {
 }
 
 //TODO test tracker with options for properties & service owners
+
+
+TEST(CelixBundleContextServicesTests, serviceFactoryTest) {
+    struct calc {
+        int (*calc)(int);
+    };
+    auto name = "CALC";
+    auto version = "1.0.0";
+
+
+    int count = 0;
+    celix_service_factory_t fac;
+    memset(&fac, 0, sizeof(fac));
+    fac.handle = (void*)&count;
+    fac.getService = [](void *handle, const celix_bundle_t *, const celix_properties_t *) -> void* {
+        auto *c = (int *)handle;
+        *c += 1;
+        static struct calc svc{}; //normally a service per bundle
+        svc.calc = [](int arg) { return arg * 42; };
+        return &svc;
+    };
+    fac.ungetService = [](void *handle, const celix_bundle_t *, const celix_properties_t *) {
+        auto *c = (int *)handle;
+        *c += 1;
+    };
+
+    long facId = celix_bundleContext_registerServiceFactory(ctx, name, &fac, version, NULL);
+    CHECK_TRUE(facId >= 0);
+
+
+    int result = -1;
+    bool called = celix_bundleContext_useService(ctx, name, &result, [](void *handle, void* svc) {
+        auto *r = (int *)(handle);
+        auto *calc = (struct calc*)svc;
+        *r = calc->calc(2);
+    });
+    CHECK_TRUE(called);
+    CHECK_EQUAL(84, result);
+    CHECK_EQUAL(2, count); //expecting getService & unGetService to be called during the useService call.
+
+
+    celix_bundleContext_unregisterService(ctx, facId);
+}
+


[2/3] celix git commit: CELIX-446: Fixes a bug in the service_registry/registration

Posted by pn...@apache.org.
CELIX-446: Fixes a bug in the service_registry/registration


Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/ae096821
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/ae096821
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/ae096821

Branch: refs/heads/develop
Commit: ae09682152db94204a12a2abd138e95e83af49ee
Parents: 626687f
Author: Pepijn Noltes <pe...@gmail.com>
Authored: Fri May 11 11:47:09 2018 +0200
Committer: Pepijn Noltes <pe...@gmail.com>
Committed: Fri May 11 11:47:09 2018 +0200

----------------------------------------------------------------------
 framework/src/service_registration.c | 4 ++--
 framework/src/service_registry.c     | 4 ++--
 2 files changed, 4 insertions(+), 4 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/ae096821/framework/src/service_registration.c
----------------------------------------------------------------------
diff --git a/framework/src/service_registration.c b/framework/src/service_registration.c
index b3f45b2..91fa62c 100644
--- a/framework/src/service_registration.c
+++ b/framework/src/service_registration.c
@@ -38,13 +38,13 @@ static celix_status_t serviceRegistration_destroy(service_registration_pt regist
 
 service_registration_pt serviceRegistration_create(registry_callback_t callback, bundle_pt bundle, const char* serviceName, unsigned long serviceId, const void * serviceObject, properties_pt dictionary) {
     service_registration_pt registration = NULL;
-	serviceRegistration_createInternal(callback, bundle, serviceName, serviceId, serviceObject, dictionary, false, &registration);
+	serviceRegistration_createInternal(callback, bundle, serviceName, serviceId, serviceObject, dictionary, CELIX_PLAIN_SERVICE, &registration);
 	return registration;
 }
 
 service_registration_pt serviceRegistration_createServiceFactory(registry_callback_t callback, bundle_pt bundle, const char* serviceName, unsigned long serviceId, const void * serviceObject, properties_pt dictionary) {
     service_registration_pt registration = NULL;
-    serviceRegistration_createInternal(callback, bundle, serviceName, serviceId, serviceObject, dictionary, true, &registration);
+    serviceRegistration_createInternal(callback, bundle, serviceName, serviceId, serviceObject, dictionary, CELIX_DEPRECATED_FACTORY_SERVICE, &registration);
     return registration;
 }
 

http://git-wip-us.apache.org/repos/asf/celix/blob/ae096821/framework/src/service_registry.c
----------------------------------------------------------------------
diff --git a/framework/src/service_registry.c b/framework/src/service_registry.c
index 1493525..026c252 100644
--- a/framework/src/service_registry.c
+++ b/framework/src/service_registry.c
@@ -147,11 +147,11 @@ celix_status_t serviceRegistry_getRegisteredServices(service_registry_pt registr
 }
 
 celix_status_t serviceRegistry_registerService(service_registry_pt registry, bundle_pt bundle, const char* serviceName, const void* serviceObject, properties_pt dictionary, service_registration_pt *registration) {
-    return serviceRegistry_registerServiceInternal(registry, bundle, serviceName, serviceObject, dictionary, false, registration);
+    return serviceRegistry_registerServiceInternal(registry, bundle, serviceName, serviceObject, dictionary, CELIX_PLAIN_SERVICE, registration);
 }
 
 celix_status_t serviceRegistry_registerServiceFactory(service_registry_pt registry, bundle_pt bundle, const char* serviceName, service_factory_pt factory, properties_pt dictionary, service_registration_pt *registration) {
-    return serviceRegistry_registerServiceInternal(registry, bundle, serviceName, (const void *) factory, dictionary, true, registration);
+    return serviceRegistry_registerServiceInternal(registry, bundle, serviceName, (const void *) factory, dictionary, CELIX_DEPRECATED_FACTORY_SERVICE, registration);
 }
 
 static celix_status_t serviceRegistry_registerServiceInternal(service_registry_pt registry, bundle_pt bundle, const char* serviceName, const void * serviceObject, properties_pt dictionary, enum celix_service_type svcType, service_registration_pt *registration) {


[3/3] celix git commit: CELIX-446: Adds celix_bundleContext_findService(s) implementation. Also adds support setting/getting different primitive types for the celix array list.

Posted by pn...@apache.org.
CELIX-446: Adds celix_bundleContext_findService(s) implementation. Also adds support setting/getting different primitive types for the celix array list.


Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/48aada3a
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/48aada3a
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/48aada3a

Branch: refs/heads/develop
Commit: 48aada3abace985b22adbe082f9e754028d6362c
Parents: ae09682
Author: Pepijn Noltes <pe...@gmail.com>
Authored: Fri May 11 14:58:13 2018 +0200
Committer: Pepijn Noltes <pe...@gmail.com>
Committed: Fri May 11 14:58:13 2018 +0200

----------------------------------------------------------------------
 .../src/dynamic_consumer_example.c              |   9 +-
 .../src/dynamic_provider_example.c              |   7 +-
 framework/include/bundle_context.h              |  93 +++++++++---
 framework/private/mock/bundle_context_mock.c    |  30 ++++
 framework/src/bundle_context.c                  |  94 ++++++++----
 framework/src/service_tracker.c                 |  32 ++--
 framework/tst/bundle_context_services_test.cpp  |  35 ++++-
 utils/include/array_list.h                      |  43 +++++-
 utils/src/array_list.c                          | 152 +++++++++++++------
 utils/src/array_list_private.h                  |   2 +-
 10 files changed, 370 insertions(+), 127 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/examples/celix-examples/services_example_c/src/dynamic_consumer_example.c
----------------------------------------------------------------------
diff --git a/examples/celix-examples/services_example_c/src/dynamic_consumer_example.c b/examples/celix-examples/services_example_c/src/dynamic_consumer_example.c
index 5a676d6..7a7f177 100644
--- a/examples/celix-examples/services_example_c/src/dynamic_consumer_example.c
+++ b/examples/celix-examples/services_example_c/src/dynamic_consumer_example.c
@@ -112,8 +112,8 @@ void * run(void *handle) {
     activator_data_t *data = handle;
 
     printf("starting consumer thread\n");
-    celix_service_tracking_options_t opts;
-    opts.serviceName = EXAMPLE_CALC_NAME;
+    celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
+    opts.filter.serviceName = EXAMPLE_CALC_NAME;
     opts.callbackHandle = data;
     opts.addWithProperties = (void*)addSvc;
     opts.removeWithProperties = (void*)removeSvc;
@@ -128,10 +128,9 @@ void * run(void *handle) {
 
         gccExample(data); //gcc trampolines example (nested functions)
 
-        celix_service_use_options_t opts;
-        memset(&opts, 0, sizeof(opts));
+        celix_service_use_options_t opts = CELIX_EMPTY_SERVICE_USE_OPTIONS;
 
-        opts.serviceName = EXAMPLE_CALC_NAME;
+        opts.filter.serviceName = EXAMPLE_CALC_NAME;
         opts.callbackHandle = data;
         opts.useWithProperties = (void*)useHighest;
         celix_bundleContext_useServiceWithOptions(data->ctx, &opts);

http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/examples/celix-examples/services_example_c/src/dynamic_provider_example.c
----------------------------------------------------------------------
diff --git a/examples/celix-examples/services_example_c/src/dynamic_provider_example.c b/examples/celix-examples/services_example_c/src/dynamic_provider_example.c
index f322303..4127c4b 100644
--- a/examples/celix-examples/services_example_c/src/dynamic_provider_example.c
+++ b/examples/celix-examples/services_example_c/src/dynamic_provider_example.c
@@ -67,7 +67,8 @@ void * run(void *handle) {
             celix_properties_setLong(props, OSGI_FRAMEWORK_SERVICE_RANKING, rand());
             data->svcIds[i++] = celix_bundleContext_registerService(data->ctx, EXAMPLE_CALC_NAME, &data->svc, NULL, props);
         } else { //down
-            celix_bundleContext_unregisterService(data->ctx, data->svcIds[i--]);
+            celix_bundleContext_unregisterService(data->ctx, data->svcIds[i]);
+            data->svcIds[--i] = -1L;
         }
         if (i == 99) {
             up = false;
@@ -79,9 +80,7 @@ void * run(void *handle) {
 
     for (int i = 0; i < 100; ++i) {
         long id = data->svcIds[i];
-        if (id >=0 ) {
-            celix_bundleContext_unregisterService(data->ctx, id);
-        }
+        celix_bundleContext_unregisterService(data->ctx, id);
     }
 
     printf("exiting service register thread\n");

http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/framework/include/bundle_context.h
----------------------------------------------------------------------
diff --git a/framework/include/bundle_context.h b/framework/include/bundle_context.h
index 44cca39..5daaff9 100644
--- a/framework/include/bundle_context.h
+++ b/framework/include/bundle_context.h
@@ -272,13 +272,51 @@ long celix_bundleContext_registerServiceFactorForLang(celix_bundle_context_t *ct
 void celix_bundleContext_unregisterService(celix_bundle_context_t *ctx, long serviceId);
 
 
-//TODO 
-//typedef struct celix_service_find_filter_options {
-// servicname, versionrange, filter, lang
-//} celix_service_find_filter_options_t;
-//celix_array_list_t* celix_bundleContext_findServices(celix_bundle_context_t *ctx, const char *serviceName);
-//celix_array_list_t* celix_bundleContext_findServices(celix_bundle_context_t *ctx, const char *serviceName);
-//alts WithOptions
+typedef struct celix_service_filter_options {
+    const char* serviceName; //REQUIRED
+    const char* versionRange;
+    const char* filter;
+    const char* lang; //NULL -> 'CELIX_LANG_C'
+} celix_service_filter_options_t;
+
+#define CELIX_EMPTY_SERVICE_FILTER_OPTIONS {.serviceName = NULL, .versionRange = NULL, .filter = NULL, .lang = NULL}
+
+
+/**
+ * Finds the highest ranking service and returns the service id.
+ *
+ * @param ctx The bundle context
+ * @param serviceName The required service name
+ * @return If found a valid service id (>= 0) if not found -1.
+ */
+long celix_bundleContext_findService(celix_bundle_context_t *ctx, const char *serviceName);
+
+/**
+ * Finds the highest ranking service and returns the service id.
+ *
+ * @param ctx The bundle context
+ * @param opts The pointer to the filter options.
+ * @return If found a valid service id (>= 0) if not found -1.
+ */
+long celix_bundleContext_findServiceWithOptions(celix_bundle_context_t *ctx, const celix_service_filter_options_t *opts);
+
+/**
+ * Finds the services with the provided service name and returns a list of the found service ids.
+ *
+ * @param ctx The bundle context
+ * @param serviceName The required service name
+ * @return A array list with as value a long int.
+ */
+celix_array_list_t* celix_bundleContext_findServices(celix_bundle_context_t *ctx, const char *serviceName);
+
+/**
+ * Finds the services conform the provider filter options and returns a list of the found service ids.
+ *
+ * @param ctx The bundle context
+ * @param opts The pointer to the filter options.
+ * @return A array list with as value a long int.
+ */
+celix_array_list_t* celix_bundleContext_findServicesWithOptions(celix_bundle_context_t *ctx, const celix_service_filter_options_t *opts);
 
 
 /**
@@ -323,11 +361,7 @@ long celix_bundleContext_trackServices(
 );
 
 typedef struct celix_service_tracker_options {
-    //service filter options
-    const char* serviceName;
-    const char* versionRange;
-    const char* filter;
-    const char* lang; //NULL -> 'CELIX_LANG_C'
+    celix_service_filter_options_t filter;
 
     //callback options
     void* callbackHandle;
@@ -335,19 +369,31 @@ typedef struct celix_service_tracker_options {
     void (*set)(void *handle, void *svc); //highest ranking
     void (*add)(void *handle, void *svc);
     void (*remove)(void *handle, void *svc);
-    void (*modified)(void *handle, void *svc);
 
     void (*setWithProperties)(void *handle, void *svc, const celix_properties_t *props); //highest ranking
     void (*addWithProperties)(void *handle, void *svc, const celix_properties_t *props);
     void (*removeWithProperties)(void *handle, void *svc, const celix_properties_t *props);
-    void (*modifiedWithProperties)(void *handle, void *svc, const celix_properties_t *props);
 
     void (*setWithOwner)(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *svcOwner); //highest ranking
     void (*addWithOwner)(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *svcOwner);
     void (*removeWithOwner)(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *svcOwner);
-    void (*modifiedWithOwner)(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *svcOwner);
 } celix_service_tracking_options_t;
 
+#define CELIX_EMPTY_SERVICE_TRACKING_OPTIONS { .filter.serviceName = NULL, \
+    .filter.versionRange = NULL, \
+    .filter.filter = NULL, \
+    .filter.lang = NULL, \
+    .callbackHandle = NULL, \
+    .set = NULL, \
+    .add = NULL, \
+    .remove = NULL, \
+    .setWithProperties = NULL, \
+    .addWithProperties = NULL, \
+    .removeWithProperties = NULL, \
+    .setWithOwner = NULL, \
+    .addWithOwner = NULL, \
+    .removeWithOwner = NULL}
+
 /**
  * Tracks services using the provided tracker options.
  * The tracker options are only using during this call and can safely be freed/reused after this call returns.
@@ -431,13 +477,7 @@ void celix_bundleContext_useServices(
 
 
 typedef struct celix_service_use_options {
-    /**
-     * service filter options. Note the serviceName is required.
-     */
-    const char *serviceName; //REQUIRED
-    const char *versionRange; //default will be empty
-    const char *filter; //default will be empty
-    const char *lang; //default will be LANG_C
+    celix_service_filter_options_t filter;
 
     /**
      * Callback info
@@ -449,6 +489,15 @@ typedef struct celix_service_use_options {
      void (*useWithOwner)(void *handle, void *svc, const celix_properties_t *props, const celix_bundle_t *svcOwner);
 } celix_service_use_options_t;
 
+#define CELIX_EMPTY_SERVICE_USE_OPTIONS {.filter.serviceName = NULL, \
+    .filter.versionRange = NULL, \
+    .filter.filter = NULL, \
+    .filter.lang = NULL, \
+    .callbackHandle = NULL, \
+    .use = NULL, \
+    .useWithProperties = NULL, \
+    .useWithOwner = NULL}
+
 /**
  * Get and lock the current highest ranking service conform the service filter info from the provided options.
  *

http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/framework/private/mock/bundle_context_mock.c
----------------------------------------------------------------------
diff --git a/framework/private/mock/bundle_context_mock.c b/framework/private/mock/bundle_context_mock.c
index 749e3ca..b763b5a 100644
--- a/framework/private/mock/bundle_context_mock.c
+++ b/framework/private/mock/bundle_context_mock.c
@@ -346,4 +346,34 @@ long celix_bundleContext_registerServiceFactorForLang(celix_bundle_context_t *ct
 			->withStringParameters("lang", lang)
 			->withPointerParameters("props", props);
 	return mock_c()->returnValue().value.longIntValue;
+}
+
+long celix_bundleContext_findService(celix_bundle_context_t *ctx, const char *serviceName) {
+	mock_c()->actualCall("celix_bundleContext_findService")
+			->withPointerParameters("ctx", ctx)
+			->withStringParameters("serviceName", serviceName);
+	return mock_c()->returnValue().value.longIntValue;
+}
+
+
+long celix_bundleContext_findServiceWithOptions(celix_bundle_context_t *ctx, const celix_service_filter_options_t *opts) {
+	mock_c()->actualCall("celix_bundleContext_findServiceWithOptions")
+			->withPointerParameters("ctx", ctx)
+			->withConstPointerParameters("opts", opts);
+	return mock_c()->returnValue().value.longIntValue;
+}
+
+
+celix_array_list_t* celix_bundleContext_findServices(celix_bundle_context_t *ctx, const char *serviceName) {
+	mock_c()->actualCall("celix_bundleContext_findServices")
+			->withPointerParameters("ctx", ctx)
+			->withStringParameters("serviceName", serviceName);
+	return mock_c()->returnValue().value.pointerValue;
+}
+
+celix_array_list_t* celix_bundleContext_findServicesWithOptions(celix_bundle_context_t *ctx, const celix_service_filter_options_t *opts) {
+	mock_c()->actualCall("celix_bundleContext_findServicesWithOptions")
+			->withPointerParameters("ctx", ctx)
+			->withConstPointerParameters("opts", opts);
+	return mock_c()->returnValue().value.pointerValue;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/framework/src/bundle_context.c
----------------------------------------------------------------------
diff --git a/framework/src/bundle_context.c b/framework/src/bundle_context.c
index 7d5dea9..ffb1704 100644
--- a/framework/src/bundle_context.c
+++ b/framework/src/bundle_context.c
@@ -672,14 +672,13 @@ bool celix_bundleContext_useServiceWithId(
         const char *serviceName,
         void *callbackHandle,
         void (*use)(void *handle, void *svc)) {
-    celix_service_use_options_t opts;
-    memset(&opts, 0, sizeof(opts));
+    celix_service_use_options_t opts = CELIX_EMPTY_SERVICE_USE_OPTIONS;
 
     char filter[64];
     snprintf(filter, 64, "(%s=%li)", OSGI_FRAMEWORK_SERVICE_ID, serviceId);
 
-    opts.serviceName = serviceName;
-    opts.filter = filter;
+    opts.filter.serviceName = serviceName;
+    opts.filter.filter = filter;
     opts.callbackHandle = callbackHandle;
     opts.use = use;
     return celix_bundleContext_useServiceWithOptions(ctx, &opts);
@@ -690,9 +689,8 @@ bool celix_bundleContext_useService(
         const char* serviceName,
         void *callbackHandle,
         void (*use)(void *handle, void *svc)) {
-    celix_service_use_options_t opts;
-    memset(&opts, 0, sizeof(opts));
-    opts.serviceName = serviceName;
+    celix_service_use_options_t opts = CELIX_EMPTY_SERVICE_USE_OPTIONS;
+    opts.filter.serviceName = serviceName;
     opts.callbackHandle = callbackHandle;
     opts.use = use;
     return celix_bundleContext_useServiceWithOptions(ctx, &opts);
@@ -704,9 +702,8 @@ void celix_bundleContext_useServices(
         const char* serviceName,
         void *callbackHandle,
         void (*use)(void *handle, void *svc)) {
-    celix_service_use_options_t opts;
-    memset(&opts, 0, sizeof(opts));
-    opts.serviceName = serviceName;
+    celix_service_use_options_t opts = CELIX_EMPTY_SERVICE_USE_OPTIONS;
+    opts.filter.serviceName = serviceName;
     opts.callbackHandle = callbackHandle;
     opts.use = use;
     celix_bundleContext_useServicesWithOptions(ctx, &opts);
@@ -721,10 +718,10 @@ bool celix_bundleContext_useServiceWithOptions(
     memset(&trkOpts, 0, sizeof(trkOpts));
 
     if (opts != NULL) {
-        trkOpts.serviceName = opts->serviceName;
+        trkOpts.filter.serviceName = opts->filter.serviceName;
         trkOpts.filter = opts->filter;
-        trkOpts.versionRange = opts->versionRange;
-        trkOpts.lang = opts->lang;
+        trkOpts.filter.versionRange = opts->filter.versionRange;
+        trkOpts.filter.lang = opts->filter.lang;
 
         service_tracker_t *trk = celix_serviceTracker_createWithOptions(ctx, &trkOpts);
         if (trk != NULL) {
@@ -737,7 +734,7 @@ bool celix_bundleContext_useServiceWithOptions(
             if (opts->useWithOwner != NULL) {
 
             }
-            called = celix_serviceTracker_useHighestRankingService(trk, opts->serviceName, opts->callbackHandle, opts->use, opts->useWithProperties, opts->useWithOwner);
+            called = celix_serviceTracker_useHighestRankingService(trk, opts->filter.serviceName, opts->callbackHandle, opts->use, opts->useWithProperties, opts->useWithOwner);
             celix_serviceTracker_destroy(trk);
         }
     }
@@ -749,18 +746,17 @@ bool celix_bundleContext_useServiceWithOptions(
 void celix_bundleContext_useServicesWithOptions(
         celix_bundle_context_t *ctx,
         const celix_service_use_options_t *opts) {
-    celix_service_tracking_options_t trkOpts;
-    memset(&trkOpts, 0, sizeof(trkOpts));
+    celix_service_tracking_options_t trkOpts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
 
     if (opts != NULL) {
-        trkOpts.serviceName = opts->serviceName;
-        trkOpts.filter = opts->filter;
-        trkOpts.versionRange = opts->versionRange;
-        trkOpts.lang = opts->lang;
+        trkOpts.filter.serviceName = opts->filter.serviceName;
+        trkOpts.filter.filter = opts->filter.filter;
+        trkOpts.filter.versionRange = opts->filter.versionRange;
+        trkOpts.filter.lang = opts->filter.lang;
 
         service_tracker_t *trk = celix_serviceTracker_createWithOptions(ctx, &trkOpts);
         if (trk != NULL) {
-            celix_serviceTracker_useServices(trk, opts->serviceName, opts->callbackHandle, opts->use, opts->useWithProperties, opts->useWithOwner);
+            celix_serviceTracker_useServices(trk, opts->filter.serviceName, opts->callbackHandle, opts->use, opts->useWithProperties, opts->useWithOwner);
             celix_serviceTracker_destroy(trk);
         }
     }
@@ -772,9 +768,8 @@ long celix_bundleContext_trackService(
         const char* serviceName,
         void* callbackHandle,
         void (*set)(void* handle, void* svc)) {
-    celix_service_tracking_options_t opts;
-    memset(&opts, 0, sizeof(opts));
-    opts.serviceName = serviceName;
+    celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
+    opts.filter.serviceName = serviceName;
     opts.callbackHandle = callbackHandle;
     opts.set = set;
     return celix_bundleContext_trackServicesWithOptions(ctx, &opts);
@@ -787,9 +782,8 @@ long celix_bundleContext_trackServices(
         void* callbackHandle,
         void (*add)(void* handle, void* svc),
         void (*remove)(void* handle, void* svc)) {
-    celix_service_tracking_options_t opts;
-    memset(&opts, 0, sizeof(opts));
-    opts.serviceName = serviceName;
+    celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
+    opts.filter.serviceName = serviceName;
     opts.callbackHandle = callbackHandle;
     opts.add = add;
     opts.remove = remove;
@@ -831,4 +825,50 @@ long celix_bundleContext_registerServiceFactorForLang(celix_bundle_context_t *ct
         celixThreadMutex_unlock(&ctx->mutex);
     }
     return facId;
+}
+
+long celix_bundleContext_findService(celix_bundle_context_t *ctx, const char *serviceName) {
+    celix_service_filter_options_t opts = CELIX_EMPTY_SERVICE_FILTER_OPTIONS;
+    opts.serviceName = serviceName;
+    return celix_bundleContext_findServiceWithOptions(ctx, &opts);
+}
+
+static void bundleContext_retrieveSvcId(void *handle, void *svc __attribute__((unused)), const celix_properties_t *props) {
+    long *svcId = handle;
+    *svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L);
+}
+
+long celix_bundleContext_findServiceWithOptions(celix_bundle_context_t *ctx, const celix_service_filter_options_t *opts) {
+    long svcId = -1L;
+    celix_service_use_options_t useOpts = CELIX_EMPTY_SERVICE_USE_OPTIONS;
+    memcpy(&useOpts.filter, opts, sizeof(useOpts.filter));
+    useOpts.callbackHandle = &svcId;
+    useOpts.useWithProperties = bundleContext_retrieveSvcId;
+    celix_bundleContext_useServiceWithOptions(ctx, &useOpts);
+    return svcId;
+}
+
+
+celix_array_list_t* celix_bundleContext_findServices(celix_bundle_context_t *ctx, const char *serviceName) {
+    celix_service_filter_options_t opts = CELIX_EMPTY_SERVICE_FILTER_OPTIONS;
+    opts.serviceName = serviceName;
+    return celix_bundleContext_findServicesWithOptions(ctx, &opts);
+}
+
+static void bundleContext_retrieveSvcIds(void *handle, void *svc __attribute__((unused)), const celix_properties_t *props) {
+    celix_array_list_t *list = handle;
+    if (list != NULL) {
+        long svcId = celix_properties_getAsLong(props, OSGI_FRAMEWORK_SERVICE_ID, -1L);
+        celix_arrayList_addLong(list, svcId);
+    }
+}
+
+celix_array_list_t* celix_bundleContext_findServicesWithOptions(celix_bundle_context_t *ctx, const celix_service_filter_options_t *opts) {
+    celix_array_list_t* list = celix_arrayList_create();
+    celix_service_use_options_t useOpts = CELIX_EMPTY_SERVICE_USE_OPTIONS;
+    memcpy(&useOpts.filter, opts, sizeof(useOpts.filter));
+    useOpts.callbackHandle = list;
+    useOpts.useWithProperties = bundleContext_retrieveSvcIds;
+    celix_bundleContext_useServicesWithOptions(ctx, &useOpts);
+    return list;
 }
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/framework/src/service_tracker.c
----------------------------------------------------------------------
diff --git a/framework/src/service_tracker.c b/framework/src/service_tracker.c
index c92efa3..56ad199 100644
--- a/framework/src/service_tracker.c
+++ b/framework/src/service_tracker.c
@@ -560,11 +560,10 @@ celix_service_tracker_t* celix_serviceTracker_create(
         const char *serviceName,
         const char *versionRange,
         const char *filter) {
-    celix_service_tracking_options_t opts;
-    memset(&opts, 0, sizeof(opts));
-    opts.serviceName = serviceName;
-    opts.filter = filter;
-    opts.versionRange = versionRange;
+    celix_service_tracking_options_t opts = CELIX_EMPTY_SERVICE_TRACKING_OPTIONS;
+    opts.filter.serviceName = serviceName;
+    opts.filter.filter = filter;
+    opts.filter.versionRange = versionRange;
     return celix_serviceTracker_createWithOptions(ctx, &opts);
 }
 
@@ -573,7 +572,7 @@ celix_service_tracker_t* celix_serviceTracker_createWithOptions(
         const celix_service_tracking_options_t *opts
 ) {
     celix_service_tracker_t *tracker = NULL;
-    if (ctx != NULL && opts != NULL && opts->serviceName != NULL) {
+    if (ctx != NULL && opts != NULL && opts->filter.serviceName != NULL) {
         tracker = calloc(1, sizeof(*tracker));
         if (tracker != NULL) {
             tracker->context = ctx;
@@ -586,44 +585,41 @@ celix_service_tracker_t* celix_serviceTracker_createWithOptions(
             tracker->set = opts->set;
             tracker->add = opts->add;
             tracker->remove = opts->remove;
-            tracker->modified = opts->modified;
             tracker->setWithProperties = opts->setWithProperties;
             tracker->addWithProperties = opts->addWithProperties;
             tracker->removeWithProperties = opts->removeWithProperties;
-            tracker->modifiedWithProperties = opts->modifiedWithProperties;
             tracker->setWithOwner = opts->setWithOwner;
             tracker->addWithOwner = opts->addWithOwner;
             tracker->removeWithOwner = opts->removeWithOwner;
-            tracker->modifiedWithOwner = opts->modifiedWithOwner;
 
             //highest service state
             celixThreadMutex_create(&tracker->mutex, NULL);
             tracker->currentHighestServiceId = -1;
 
             //setting lang
-            const char *lang = opts->lang;
+            const char *lang = opts->filter.lang;
             if (lang == NULL || strncmp("", lang, 1) == 0) {
                 lang = CELIX_FRAMEWORK_SERVICE_C_LANGUAGE;
             }
 
             //setting filter
-            if (opts->filter != NULL && opts->versionRange != NULL) {
+            if (opts->filter.filter != NULL && opts->filter.versionRange != NULL) {
                 //TODO version range
-                asprintf(&tracker->filter, "&((%s=%s)(%s=%s)%s)", OSGI_FRAMEWORK_OBJECTCLASS, opts->serviceName, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang, opts->filter);
-            } else if (opts->versionRange != NULL) {
+                asprintf(&tracker->filter, "&((%s=%s)(%s=%s)%s)", OSGI_FRAMEWORK_OBJECTCLASS, opts->filter.serviceName, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang, opts->filter.filter);
+            } else if (opts->filter.versionRange != NULL) {
                 //TODO version range
-                asprintf(&tracker->filter, "&((%s=%s)(%s=%s))", OSGI_FRAMEWORK_OBJECTCLASS, opts->serviceName, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang);
-            } else if (opts->filter != NULL) {
-                asprintf(&tracker->filter, "(&(%s=%s)(%s=%s)%s)", OSGI_FRAMEWORK_OBJECTCLASS, opts->serviceName, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang, opts->filter);
+                asprintf(&tracker->filter, "&((%s=%s)(%s=%s))", OSGI_FRAMEWORK_OBJECTCLASS, opts->filter.serviceName, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang);
+            } else if (opts->filter.filter != NULL) {
+                asprintf(&tracker->filter, "(&(%s=%s)(%s=%s)%s)", OSGI_FRAMEWORK_OBJECTCLASS, opts->filter.serviceName, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang, opts->filter.filter);
             } else {
-                asprintf(&tracker->filter, "(&(%s=%s)(%s=%s))", OSGI_FRAMEWORK_OBJECTCLASS, opts->serviceName, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang);
+                asprintf(&tracker->filter, "(&(%s=%s)(%s=%s))", OSGI_FRAMEWORK_OBJECTCLASS, opts->filter.serviceName, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang);
             }
 
             //TODO open on other thread?
             serviceTracker_open(tracker);
         }
     } else {
-        if (opts != NULL && opts->serviceName == NULL) {
+        if (opts != NULL && opts->filter.serviceName == NULL) {
             framework_log(logger, OSGI_FRAMEWORK_LOG_ERROR, __FUNCTION__, __BASE_FILE__, __LINE__,
                           "Error incorrect arguments. Missing service name.");
         } else {

http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/framework/tst/bundle_context_services_test.cpp
----------------------------------------------------------------------
diff --git a/framework/tst/bundle_context_services_test.cpp b/framework/tst/bundle_context_services_test.cpp
index 2597ece..6fa1204 100644
--- a/framework/tst/bundle_context_services_test.cpp
+++ b/framework/tst/bundle_context_services_test.cpp
@@ -297,7 +297,7 @@ TEST(CelixBundleContextServicesTests, servicesTrackerInvalidArgsTest) {
     memset(&opts, 0, sizeof(opts));
     trackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts);
     CHECK(trackerId < 0); //required opts->serviceName missing
-    opts.serviceName = "calc";
+    opts.filter.serviceName = "calc";
     trackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts);
     CHECK(trackerId >= 0); //valid
     celix_bundleContext_stopTracker(ctx, trackerId);
@@ -361,7 +361,7 @@ TEST(CelixBundleContextServicesTests, servicesTrackerTestWithProperties) {
 
     celix_service_tracking_options_t opts;
     memset(&opts, 0, sizeof(opts));
-    opts.serviceName = "calc";
+    opts.filter.serviceName = "calc";
     opts.callbackHandle = &count;
     opts.addWithProperties = add;
     opts.removeWithProperties = remove;
@@ -401,7 +401,7 @@ TEST(CelixBundleContextServicesTests, servicesTrackerTestWithOwner) {
 
     celix_service_tracking_options_t opts;
     memset(&opts, 0, sizeof(opts));
-    opts.serviceName = "calc";
+    opts.filter.serviceName = "calc";
     opts.callbackHandle = &count;
     opts.addWithOwner = add;
     opts.removeWithOwner = remove;
@@ -557,7 +557,7 @@ TEST(CelixBundleContextServicesTests, servicesTrackerSetTest) {
     celix_service_tracking_options_t opts;
     memset(&opts, 0, sizeof(opts));
     opts.callbackHandle = (void*)&count;
-    opts.serviceName = "NA";
+    opts.filter.serviceName = "NA";
     opts.set = set;
     long trackerId = celix_bundleContext_trackServicesWithOptions(ctx, &opts);
     CHECK(trackerId > 0);
@@ -628,3 +628,30 @@ TEST(CelixBundleContextServicesTests, serviceFactoryTest) {
     celix_bundleContext_unregisterService(ctx, facId);
 }
 
+TEST(CelixBundleContextServicesTests, findServicesTest) {
+    long svcId1 = celix_bundleContext_registerService(ctx, "example", (void*)0x100, NULL, NULL);
+    long svcId2 = celix_bundleContext_registerService(ctx, "example", (void*)0x100, NULL, NULL);
+
+    long foundId = celix_bundleContext_findService(ctx, "non existing service name");
+    CHECK_EQUAL(-1L, foundId);
+
+    foundId = celix_bundleContext_findService(ctx, "example");
+    CHECK_EQUAL(foundId, svcId1); //oldest should have highest ranking
+
+    array_list_t *list = celix_bundleContext_findServices(ctx, "non existintg service name");
+    CHECK_EQUAL(0, celix_arrayList_size(list));
+    arrayList_destroy(list);
+
+    list = celix_bundleContext_findServices(ctx, "example");
+    CHECK_EQUAL(2, celix_arrayList_size(list));
+    arrayList_destroy(list);
+
+    celix_bundleContext_unregisterService(ctx, svcId1);
+
+    celix_service_filter_options_t opts = CELIX_EMPTY_SERVICE_FILTER_OPTIONS;
+    opts.serviceName = "example";
+    foundId = celix_bundleContext_findServiceWithOptions(ctx, &opts);
+    CHECK_EQUAL(foundId, svcId2); //only one left
+
+    celix_bundleContext_unregisterService(ctx, svcId2);
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/utils/include/array_list.h
----------------------------------------------------------------------
diff --git a/utils/include/array_list.h b/utils/include/array_list.h
index 46a0697..fa8602b 100644
--- a/utils/include/array_list.h
+++ b/utils/include/array_list.h
@@ -30,11 +30,24 @@
 #include "celixbool.h"
 #include "exports.h"
 #include "celix_errno.h"
+#include "stdbool.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
+typedef union celix_array_list_entry {
+    void *voidPtrVal;
+    int intVal;
+    long int longVal;
+    unsigned int uintVal;
+    unsigned long ulongVal;
+    double doubleVal;
+    float floatVal;
+    bool boolVal;
+    size_t sizeVal;
+} celix_array_list_entry_t;
+
 typedef struct celix_arrayList celix_array_list_t;
 
 typedef struct celix_arrayList *array_list_pt;
@@ -45,7 +58,7 @@ typedef struct arrayListIterator array_list_iterator_t;
 
 typedef celix_status_t (*array_list_element_equals_pt)(const void *, const void *, bool *equals);
 
-typedef bool (*celix_arrayList_equals_fp)(const void *, const void *);
+typedef bool (*celix_arrayList_equals_fp)(celix_array_list_entry_t, celix_array_list_entry_t);
 
 UTILS_EXPORT celix_status_t arrayList_create(array_list_pt *list);
 
@@ -107,6 +120,7 @@ UTILS_EXPORT void arrayListIterator_remove(array_list_iterator_pt iterator);
  **********************************************************************************************************************
  **********************************************************************************************************************/
 
+
 celix_array_list_t* celix_arrayList_create();
 
 celix_array_list_t* celix_arrayList_createWithEquals(celix_arrayList_equals_fp equals);
@@ -117,8 +131,31 @@ size_t celix_arrayList_size(const celix_array_list_t *list);
 
 void* celix_arrayList_get(const celix_array_list_t *list, int index);
 
-//TODO rest
-
+//more of the same for the different entry types
+int celix_arrayList_getInt(const celix_array_list_t *list, int index);
+long int celix_arrayList_getLong(const celix_array_list_t *list, int index);
+unsigned int celix_arrayList_getUInt(const celix_array_list_t *list, int index);
+unsigned long int celix_arrayList_getULong(const celix_array_list_t *list, int index);
+float celix_arrayList_getFloat(const celix_array_list_t *list, int index);
+double celix_arrayList_getDouble(const celix_array_list_t *list, int index);
+bool celix_arrayList_getBool(const celix_array_list_t *list, int index);
+size_t celix_arrayList_getSize(const celix_array_list_t *list, int index);
+
+void celix_arrayList_add(celix_array_list_t *list, void* val);
+
+//more of the same for the different entry types
+void celix_arrayList_addInt(celix_array_list_t *list, int val);
+void celix_arrayList_addLong(celix_array_list_t *list, long val);
+void celix_arrayList_addUInt(celix_array_list_t *list, unsigned int val);
+void celix_arrayList_addULong(celix_array_list_t *list, unsigned long val);
+void celix_arrayList_addFloat(celix_array_list_t *list, float val);
+void celix_arrayList_addDouble(celix_array_list_t *list, double val);
+void celix_arrayList_addBool(celix_array_list_t *list, bool val);
+void celix_arrayList_addSize(celix_array_list_t *list, size_t val);
+
+int celix_arrayList_indexOf(celix_array_list_t *list, celix_array_list_entry_t entry);
+void celix_arrayList_remove(celix_array_list_t *list, int index);
+void celix_arrayList_removeEntry(celix_array_list_t *list, celix_array_list_entry_t entry);
 
 #ifdef __cplusplus
 }

http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/utils/src/array_list.c
----------------------------------------------------------------------
diff --git a/utils/src/array_list.c b/utils/src/array_list.c
index 751712e..ca12798 100644
--- a/utils/src/array_list.c
+++ b/utils/src/array_list.c
@@ -31,8 +31,8 @@
 #include "array_list_private.h"
 
 static celix_status_t arrayList_elementEquals(const void *a, const void *b, bool *equals);
-static bool celix_arrayList_defaultEquals(const void *a, const void *b);
-static bool celix_arrayList_equalsForElement(celix_array_list_t *list, void *a, void *b);
+static bool celix_arrayList_defaultEquals(const celix_array_list_entry_t a, const celix_array_list_entry_t b);
+static bool celix_arrayList_equalsForElement(celix_array_list_t *list, celix_array_list_entry_t a, celix_array_list_entry_t b);
 
 
 celix_status_t arrayList_create(array_list_pt *list) {
@@ -57,15 +57,15 @@ static celix_status_t arrayList_elementEquals(const void *a, const void *b, bool
 	return CELIX_SUCCESS;
 }
 
-static bool celix_arrayList_defaultEquals(const void *a, const void *b) {
-	return a == b;
+static bool celix_arrayList_defaultEquals(celix_array_list_entry_t a, celix_array_list_entry_t b) {
+	return a.longVal == b.longVal; //just compare as long int
 }
 
-static bool celix_arrayList_equalsForElement(celix_array_list_t *list, void *a, void *b) {
+static bool celix_arrayList_equalsForElement(celix_array_list_t *list, celix_array_list_entry_t a, celix_array_list_entry_t b) {
 	bool equals = false;
 	if (list != NULL) {
 		if (list->equalsDeprecated != NULL) {
-			list->equalsDeprecated(a, b, &equals);
+			list->equalsDeprecated(a.voidPtrVal, b.voidPtrVal, &equals);
 		} else if (list->equals != NULL) {
 			equals = list->equals(a, b);
 		}
@@ -74,34 +74,32 @@ static bool celix_arrayList_equalsForElement(celix_array_list_t *list, void *a,
 }
 
 void arrayList_trimToSize(array_list_pt list) {
-	unsigned int oldCapacity;
 	list->modCount++;
-	oldCapacity = list->capacity;
+	size_t oldCapacity = list->capacity;
 	if (list->size < oldCapacity) {
-		void ** newList = (void **) realloc(list->elementData, sizeof(void *) * list->size);
+		celix_array_list_entry_t * newList = realloc(list->elementData, sizeof(void *) * list->size);
 		list->capacity = list->size;
 		list->elementData = newList;
 	}
 }
 
 void arrayList_ensureCapacity(array_list_pt list, int capacity) {
-	void ** newList;
-	unsigned int oldCapacity;
+	celix_array_list_entry_t *newList;
 	list->modCount++;
-	oldCapacity = list->capacity;
+	size_t oldCapacity = list->capacity;
 	if (capacity > oldCapacity) {
-		unsigned int newCapacity = (oldCapacity * 3) / 2 + 1;
+		size_t newCapacity = (oldCapacity * 3) / 2 + 1;
 		if (newCapacity < capacity) {
 			newCapacity = capacity;
 		}
-		newList = (void **) realloc(list->elementData, sizeof(void *) * newCapacity);
+		newList = realloc(list->elementData, sizeof(void *) * newCapacity);
 		list->capacity = newCapacity;
 		list->elementData = newList;
 	}
 }
 
 unsigned int arrayList_size(array_list_pt list) {
-	return list->size;
+	return (int)list->size;
 }
 
 bool arrayList_isEmpty(array_list_pt list) {
@@ -117,14 +115,15 @@ int arrayList_indexOf(array_list_pt list, void * element) {
 	if (element == NULL) {
 		unsigned int i = 0;
 		for (i = 0; i < list->size; i++) {
-			if (list->elementData[i] == NULL) {
+			if (list->elementData[i].voidPtrVal == NULL) {
 				return i;
 			}
 		}
 	} else {
 		unsigned int i = 0;
 		for (i = 0; i < list->size; i++) {
-			bool equals = celix_arrayList_equalsForElement(list, element, list->elementData[i]);
+			celix_array_list_entry_t entry = { .voidPtrVal = element };
+			bool equals = celix_arrayList_equalsForElement(list, entry, list->elementData[i]);
 			if (equals) {
 				return i;
 			}
@@ -136,17 +135,21 @@ int arrayList_indexOf(array_list_pt list, void * element) {
 int arrayList_lastIndexOf(array_list_pt list, void * element) {
 	if (element == NULL) {
 		int i = 0;
-		for (i = list->size - 1; i >= 0; i--) {
-			if (list->elementData[i] == NULL) {
-				return i;
+		int size = (int)list->size;
+		for (i = size - 1; i >= 0; i--) {
+			if (list->elementData[i].voidPtrVal == NULL) {
+				return (int)i;
 			}
 		}
 	} else {
 		int i = 0;
-		for (i = list->size - 1; i >= 0; i--) {
-			bool equals = celix_arrayList_equalsForElement(list, element, list->elementData[i]);
+		int size = (int)list->size;
+		for (i = size - 1; i >= 0; i--) {
+			celix_array_list_entry_t entry = { .voidPtrVal = element };
+
+			bool equals = celix_arrayList_equalsForElement(list, entry, list->elementData[i]);
 			if (equals) {
-				return i;
+				return (int)i;
 			}
 		}
 	}
@@ -158,7 +161,7 @@ void * arrayList_get(array_list_pt list, unsigned int index) {
 		return NULL;
 	}
 
-	return list->elementData[index];
+	return list->elementData[index].voidPtrVal;
 }
 
 void * arrayList_set(array_list_pt list, unsigned int index, void * element) {
@@ -167,61 +170,63 @@ void * arrayList_set(array_list_pt list, unsigned int index, void * element) {
 		return NULL;
 	}
 
-	oldElement = list->elementData[index];
-	list->elementData[index] = element;
+	oldElement = list->elementData[index].voidPtrVal;
+	memset(&list->elementData[index], 0, sizeof(celix_array_list_entry_t));
+	list->elementData[index].voidPtrVal = element;
 	return oldElement;
 }
 
 bool arrayList_add(array_list_pt list, void * element) {
-	arrayList_ensureCapacity(list, list->size + 1);
-	list->elementData[list->size++] = element;
+	arrayList_ensureCapacity(list, (int)list->size + 1);
+	memset(&list->elementData[list->size], 0, sizeof(celix_array_list_entry_t));
+	list->elementData[list->size++].voidPtrVal = element;
 	return true;
 }
 
 int arrayList_addIndex(array_list_pt list, unsigned int index, void * element) {
-	unsigned int numMoved;
+	size_t numMoved;
 	if (index > list->size) {
 		return -1;
 	}
-	arrayList_ensureCapacity(list, list->size+1);
+	arrayList_ensureCapacity(list, (int)list->size+1);
 	numMoved = list->size - index;
 	memmove(list->elementData+(index+1), list->elementData+index, sizeof(void *) * numMoved);
 
-	list->elementData[index] = element;
+	list->elementData[index].voidPtrVal = element;
 	list->size++;
 	return 0;
 }
 
 void * arrayList_remove(array_list_pt list, unsigned int index) {
 	void * oldElement;
-	unsigned int numMoved;
+	size_t numMoved;
 	if (index >= list->size) {
 		return NULL;
 	}
 
 	list->modCount++;
-	oldElement = list->elementData[index];
+	oldElement = list->elementData[index].voidPtrVal;
 	numMoved = list->size - index - 1;
 	memmove(list->elementData+index, list->elementData+index+1, sizeof(void *) * numMoved);
-	list->elementData[--list->size] = NULL;
+	memset(&list->elementData[--list->size], 0, sizeof(celix_array_list_entry_t));
 
 	return oldElement;
 }
 
 void arrayList_fastRemove(array_list_pt list, unsigned int index) {
-	unsigned int numMoved;
+	size_t numMoved;
 	list->modCount++;
 
 	numMoved = list->size - index - 1;
 	memmove(list->elementData+index, list->elementData+index+1, sizeof(void *) * numMoved);
-	list->elementData[--list->size] = NULL;
+	memset(&list->elementData[--list->size], 0, sizeof(celix_array_list_entry_t));
 }
 
 bool arrayList_removeElement(array_list_pt list, void * element) {
 	if (element == NULL) {
 		unsigned int i = 0;
 		for (i = 0; i < list->size; i++) {
-			if (list->elementData[i] == NULL) {
+			if (list->elementData[i].voidPtrVal == NULL) {
 				arrayList_fastRemove(list, i);
 				return true;
 			}
@@ -229,7 +234,9 @@ bool arrayList_removeElement(array_list_pt list, void * element) {
 	} else {
 		unsigned int i = 0;
 		for (i = 0; i < list->size; i++) {
-			bool equals = celix_arrayList_equalsForElement(list, element, list->elementData[i]);
+			celix_array_list_entry_t entry;
+			entry.voidPtrVal = element;
+			bool equals = celix_arrayList_equalsForElement(list, entry, list->elementData[i]);
 			if (equals) {
 				arrayList_fastRemove(list, i);
 				return true;
@@ -245,7 +252,7 @@ void arrayList_clear(array_list_pt list) {
 
 	for (i = 0; i < list->size; i++) {
 		// free(list->elementData[i]);
-		list->elementData[i] = NULL;
+		memset(&list->elementData[i], 0, sizeof(celix_array_list_entry_t));
 	}
 	list->size = 0;
 }
@@ -375,15 +382,74 @@ size_t celix_arrayList_size(const celix_array_list_t *list) {
 	return list->size;
 }
 
-void* celix_arrayList_get(const celix_array_list_t *list, int index) {
-	void *el = NULL;
+static celix_array_list_entry_t arrayList_getEntry(const celix_array_list_t *list, int index) {
+	celix_array_list_entry_t entry;
+	memset(&entry, 0, sizeof(entry));
 	if (index < list->size) {
-		el = list->elementData[index];
+		entry = list->elementData[index];
 	}
-	return el;
+	return entry;
+}
+
+void* celix_arrayList_get(const celix_array_list_t *list, int index) {
+	return arrayList_getEntry(list, index).voidPtrVal;
+}
+
+int celix_arrayList_getInt(const celix_array_list_t *list, int index) { return arrayList_getEntry(list, index).intVal; }
+long int celix_arrayList_getLong(const celix_array_list_t *list, int index) { return arrayList_getEntry(list, index).longVal; }
+unsigned int celix_arrayList_getUInt(const celix_array_list_t *list, int index) { return arrayList_getEntry(list, index).uintVal; }
+unsigned long int celix_arrayList_getULong(const celix_array_list_t *list, int index) { return arrayList_getEntry(list, index).ulongVal; }
+float celix_arrayList_getFloat(const celix_array_list_t *list, int index) { return arrayList_getEntry(list, index).floatVal; }
+double celix_arrayList_getDouble(const celix_array_list_t *list, int index) { return arrayList_getEntry(list, index).doubleVal; }
+bool celix_arrayList_getBool(const celix_array_list_t *list, int index) { return arrayList_getEntry(list, index).boolVal; }
+size_t celix_arrayList_getSize(const celix_array_list_t *list, int index) { return arrayList_getEntry(list, index).sizeVal; }
+
+static void arrayList_addEntry(celix_array_list_t *list, celix_array_list_entry_t entry) {
+	arrayList_ensureCapacity(list, (int)list->size + 1);
+	memset(&list->elementData[list->size], 0, sizeof(entry));
+	list->elementData[list->size++] = entry;
+}
+
+void celix_arrayList_add(celix_array_list_t *list, void * element) {
+	celix_array_list_entry_t entry = { .voidPtrVal = element };
+	arrayList_addEntry(list, entry);
 }
 
+void celix_arrayList_addInt(celix_array_list_t *list, int val) { celix_array_list_entry_t entry = { .intVal = val }; arrayList_addEntry(list, entry);}
+void celix_arrayList_addLong(celix_array_list_t *list, long val)  { celix_array_list_entry_t entry = { .longVal = val }; arrayList_addEntry(list, entry);}
+void celix_arrayList_addUInt(celix_array_list_t *list, unsigned int val)  { celix_array_list_entry_t entry = { .uintVal = val }; arrayList_addEntry(list, entry);}
+void celix_arrayList_addULong(celix_array_list_t *list, unsigned long val)  { celix_array_list_entry_t entry = { .ulongVal = val }; arrayList_addEntry(list, entry);}
+void celix_arrayList_addFloat(celix_array_list_t *list, float val)  { celix_array_list_entry_t entry = { .floatVal = val }; arrayList_addEntry(list, entry);}
+void celix_arrayList_addDouble(celix_array_list_t *list, double val)  { celix_array_list_entry_t entry = { .doubleVal = val }; arrayList_addEntry(list, entry);}
+void celix_arrayList_addBool(celix_array_list_t *list, bool val)  { celix_array_list_entry_t entry = { .boolVal = val }; arrayList_addEntry(list, entry);}
+void celix_arrayList_addSize(celix_array_list_t *list, size_t val)  { celix_array_list_entry_t entry = { .sizeVal = val }; arrayList_addEntry(list, entry);}
+
+int celix_arrayList_indexOf(celix_array_list_t *list, celix_array_list_entry_t entry) {
+	size_t size = celix_arrayList_size(list);
+	int i;
+	int index = -1;
+	for (i = 0 ; i < size ; ++i) {
+		bool eq = celix_arrayList_equalsForElement(list, entry, list->elementData[i]);
+		if (eq) {
+			index = i;
+			break;
+		}
+	}
+	return index;
+}
+void celix_arrayList_remove(celix_array_list_t *list, int index) {
+	if (index >= 0 && index < list->size) {
+		list->modCount++;
+		size_t numMoved = list->size - index - 1;
+		memmove(list->elementData+index, list->elementData+index+1, sizeof(void *) * numMoved);
+		memset(&list->elementData[--list->size], 0, sizeof(celix_array_list_entry_t));
+	}
+}
 
+void celix_arrayList_removeEntry(celix_array_list_t *list, celix_array_list_entry_t entry) {
+	int index = celix_arrayList_indexOf(list, entry);
+	celix_arrayList_remove(list, index);
+}
 
 
 

http://git-wip-us.apache.org/repos/asf/celix/blob/48aada3a/utils/src/array_list_private.h
----------------------------------------------------------------------
diff --git a/utils/src/array_list_private.h b/utils/src/array_list_private.h
index e5394cd..5f83605 100644
--- a/utils/src/array_list_private.h
+++ b/utils/src/array_list_private.h
@@ -30,7 +30,7 @@
 #include "array_list.h"
 
 struct celix_arrayList {
-	void ** elementData;
+	celix_array_list_entry_t* elementData;
 	size_t size;
 	size_t capacity;