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/14 19:17:55 UTC
[04/12] 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
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/feature/CELIX-426-cxx-api
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, ®);
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, ®));
+ 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(®istration->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(®istration->lock);
- return status;
+
+ return CELIX_SUCCESS;
}
celix_status_t serviceRegistration_ungetService(service_registration_pt registration, bundle_pt bundle, const void** service) {
celixThreadRwlock_readLock(®istration->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(®istration->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, ®istration);
+ 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);
+}
+