celix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pnol...@apache.org
Subject celix git commit: CELIX-441: Started initial implementation for the service tracker api from the bundle context.
Date Tue, 17 Apr 2018 20:07:34 GMT
Repository: celix
Updated Branches:
  refs/heads/develop 2eeadb4cc -> 0657853e7


CELIX-441: Started initial implementation for the service tracker api from the bundle context.

- Implements the bundleContext_useServiceWithId for the service "tracking" functionality
- ALso implements alternatives for registering services (bundleContext_registerCService and bundleContext_registerServiceWithLang).
  These register service functions return a svcId instead of a service_registration and be unregistered with the bundleContext_unregisterService call.
- Adds several _t alternatives for the _pt typedefs.
- removes celix_test_runner.
- Implements a serviceFactory_newFramework like in the OSGi API.
- Adds serviceRegisration_getServiceId.
- Updates the service tracker with a getAndLockService and ungetAndUnlockService class which locks te removal of services,
  this is in turned used in the bundleContext_useServiceWithId function.


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

Branch: refs/heads/develop
Commit: 0657853e7c4f4283a8e5c3149dacd85f134652b0
Parents: 2eeadb4
Author: Pepijn Noltes <pepijnnoltes@gmail.com>
Authored: Tue Apr 17 22:00:34 2018 +0200
Committer: Pepijn Noltes <pepijnnoltes@gmail.com>
Committed: Tue Apr 17 22:07:28 2018 +0200

----------------------------------------------------------------------
 cmake/cmake_celix/DeployPackaging.cmake     |   5 +-
 framework/CMakeLists.txt                    |   1 +
 framework/include/bundle.h                  |   1 +
 framework/include/bundle_context.h          |  55 ++++++++++++
 framework/include/celix_framework_factory.h |  41 +++++++++
 framework/include/framework.h               |  22 +++--
 framework/include/service_registration.h    |  21 +++--
 framework/include/service_tracker.h         |  46 +++++++---
 framework/src/bundle_context.c              | 100 ++++++++++++++++++++--
 framework/src/bundle_context_private.h      |   3 +
 framework/src/celix_framework_factory.c     |  40 +++++++++
 framework/src/celix_launcher.c              | 101 +++++++++++-----------
 framework/src/framework.c                   |  16 +++-
 framework/src/framework_private.h           |   3 -
 framework/src/service_registration.c        |  12 ++-
 framework/src/service_tracker.c             | 104 ++++++++++++++++++-----
 framework/src/service_tracker_private.h     |   7 +-
 framework/tst/CMakeLists.txt                |   1 +
 framework/tst/framework_bundle_context.cpp  | 101 ++++++++++++++++++++++
 framework/tst/single_framework_test.cpp     |  42 ++++++++-
 launcher/CMakeLists.txt                     |  18 ----
 launcher/src/celix_test_runner.cpp          |  73 ----------------
 22 files changed, 600 insertions(+), 213 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/cmake/cmake_celix/DeployPackaging.cmake
----------------------------------------------------------------------
diff --git a/cmake/cmake_celix/DeployPackaging.cmake b/cmake/cmake_celix/DeployPackaging.cmake
index a16ff25..64b543d 100644
--- a/cmake/cmake_celix/DeployPackaging.cmake
+++ b/cmake/cmake_celix/DeployPackaging.cmake
@@ -81,6 +81,9 @@ function(add_celix_container)
         get_filename_component(SRC_FILENAME ${CONTAINER_LAUNCHER_SRC} NAME)
         set(LAUNCHER_SRC "${PROJECT_BINARY_DIR}/celix/gen/${CONTAINER_TARGET}-${SRC_FILENAME}")
         set(LAUNCHER_ORG "${CONTAINER_LAUNCHER_SRC}")
+        add_custom_command(OUTPUT ${LAUNCHER_SRC}
+                COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LAUNCHER_ORG} ${LAUNCHER_SRC}
+        )
     else () #generate custom launcher
         if (CONTAINER_CXX)
             set(LAUNCHER_SRC "${PROJECT_BINARY_DIR}/celix/gen/${CONTAINER_TARGET}-main.cc")
@@ -106,7 +109,7 @@ $<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_EMBEDDED_PROPERTIES>,\\n\
     if (LAUNCHER_SRC) #compilation needed
         add_executable(${CONTAINER_TARGET} ${LAUNCHER_SRC})
         set_target_properties(${CONTAINER_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CONTAINER_LOC})
-	set_target_properties(${CONTAINER_TARGET} PROPERTIES OUTPUT_NAME ${CONTAINER_NAME})
+	    set_target_properties(${CONTAINER_TARGET} PROPERTIES OUTPUT_NAME ${CONTAINER_NAME})
         target_link_libraries(${CONTAINER_TARGET} PRIVATE Celix::framework)
         set(LAUNCHER "$<TARGET_FILE:${CONTAINER_TARGET}>")
     else ()

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/framework/CMakeLists.txt b/framework/CMakeLists.txt
index 94c78c7..f6967b2 100644
--- a/framework/CMakeLists.txt
+++ b/framework/CMakeLists.txt
@@ -32,6 +32,7 @@ set(SOURCES
         src/service_registry.c src/service_tracker.c src/service_tracker_customizer.c
         src/unzip.c src/wire.c
         src/celix_log.c src/celix_launcher.c
+        src/celix_framework_factory.c
         ${IO}
 )
 add_library(framework SHARED ${SOURCES})

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/include/bundle.h
----------------------------------------------------------------------
diff --git a/framework/include/bundle.h b/framework/include/bundle.h
index 3d93bbd..7f715cc 100644
--- a/framework/include/bundle.h
+++ b/framework/include/bundle.h
@@ -28,6 +28,7 @@
 #define BUNDLE_H_
 
 typedef struct bundle * bundle_pt;
+typedef struct bundle bundle_t;
 
 #include "celix_errno.h"
 #include "bundle_state.h"

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/include/bundle_context.h
----------------------------------------------------------------------
diff --git a/framework/include/bundle_context.h b/framework/include/bundle_context.h
index b8d3f45..0ca82f4 100644
--- a/framework/include/bundle_context.h
+++ b/framework/include/bundle_context.h
@@ -71,6 +71,61 @@ bundleContext_registerServiceFactory(bundle_context_pt context, const char *serv
                                      properties_pt properties, service_registration_pt *service_registration);
 
 /**
+ * Register a C lang service to the framework.
+ *
+ * @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
+ * @return The serviceId or < 0 if registration was unsuccessful.
+ */
+long bundleContext_registerCService(bundle_context_t *ctx, const char *serviceName, const void *svc, properties_t *properties);
+
+/**
+* Register a service for the specified language to the framework.
+*
+* @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
+* @return The serviceId or < 0 if registration was unsuccessful.
+*/
+long bundleContext_registerServiceForLang(bundle_context_t *ctx, const char *serviceName, const void *svc, properties_t *properties, const char* lang);
+
+/**
+ * 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.
+ * TODO explain that this should nu be used in combination with the service_registration_t type.
+ *
+ * @param ctx The bundle context
+ * @param serviceId The service id
+ */
+void bundleContext_unregisterService(bundle_context_t *ctx, long serviceId);
+
+
+/**
+ * Get and lock the service with the provided service id
+ * Invokes the provided callback with the found service.
+ * The svc, props and owner in the callback are only valid during the callback.
+ * If no service is found the callback will not be invoked
+ *
+ * This function will block till the callback is finished. As result it is possible to provide callback data from the
+ * stack.
+ *
+ * @param ctx The bundle context
+ * @param serviceId the service id.
+ * @param callbackHandle The data pointer, which will be used in the callbacks
+ * @param use The callback, which will be called when service is retrieved.
+ * @param bool returns true if a service was found.
+ */
+bool bundleContext_useServiceWithId(
+        bundle_context_t *ctx,
+        long serviceId,
+        void *callbackHandle,
+        void (*use)(void *handle, void* svc, const properties_t *props, const bundle_t *owner)
+);
+
+/**
  * Get a service reference for the bundle context. When the service reference is no longer needed use bundleContext_ungetServiceReference.
  * ServiceReference are coupled to a bundle context. Do not share service reference between bundles. Exchange the service.id instead.
  * 

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/include/celix_framework_factory.h
----------------------------------------------------------------------
diff --git a/framework/include/celix_framework_factory.h b/framework/include/celix_framework_factory.h
new file mode 100644
index 0000000..70d2678
--- /dev/null
+++ b/framework/include/celix_framework_factory.h
@@ -0,0 +1,41 @@
+/**
+ *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_FRAMEWORK_FACTORY_H_
+#define CELIX_FRAMEWORK_FACTORY_H_
+
+#include "framework.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Creates a new framework. The framework will be in the started state.
+ * @param config The framework configuration. Can be NULL.
+ * @return a started framework or NULL
+ */
+framework_t* frameworkFactory_newFramework(properties_t *config);
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* CELIX_FRAMEWORK_FACTORY_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/include/framework.h
----------------------------------------------------------------------
diff --git a/framework/include/framework.h b/framework/include/framework.h
index ec2306f..5143f47 100644
--- a/framework/include/framework.h
+++ b/framework/include/framework.h
@@ -27,28 +27,36 @@
 #ifndef FRAMEWORK_H_
 #define FRAMEWORK_H_
 
-typedef struct activator * activator_pt;
-typedef struct framework * framework_pt;
+typedef struct activator *activator_pt;
+typedef struct activator activator_t;
+
+typedef struct framework *framework_pt;
+typedef struct framework framework_t;
 
 #include "celix_errno.h"
 #include "framework_exports.h"
 #include "bundle.h"
 #include "properties.h"
+#include "bundle_context.h"
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 // #TODO: Move to FrameworkFactory according the OSGi Spec
-FRAMEWORK_EXPORT celix_status_t framework_create(framework_pt *framework, properties_pt config);
+FRAMEWORK_EXPORT celix_status_t framework_create(framework_t **framework, properties_t *config);
+
+FRAMEWORK_EXPORT celix_status_t framework_start(framework_t *framework);
+
+FRAMEWORK_EXPORT celix_status_t framework_stop(framework_t *framework);
 
-FRAMEWORK_EXPORT celix_status_t framework_destroy(framework_pt framework);
+FRAMEWORK_EXPORT celix_status_t framework_destroy(framework_t *framework);
 
-FRAMEWORK_EXPORT celix_status_t fw_init(framework_pt framework);
+FRAMEWORK_EXPORT celix_status_t framework_waitForStop(framework_t *framework);
 
-FRAMEWORK_EXPORT celix_status_t framework_waitForStop(framework_pt framework);
+FRAMEWORK_EXPORT celix_status_t framework_getFrameworkBundle(framework_t *framework, bundle_t **bundle);
 
-FRAMEWORK_EXPORT celix_status_t framework_getFrameworkBundle(framework_pt framework, bundle_pt *bundle);
+bundle_context_t* framework_getContext(framework_t *framework);
 
 #ifdef __cplusplus
 }

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/include/service_registration.h
----------------------------------------------------------------------
diff --git a/framework/include/service_registration.h b/framework/include/service_registration.h
index 9265a00..8cb5f29 100644
--- a/framework/include/service_registration.h
+++ b/framework/include/service_registration.h
@@ -16,13 +16,7 @@
  *specific language governing permissions and limitations
  *under the License.
  */
-/*
- * service_registration.h
- *
- *  \date       Aug 6, 2010
- *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright	Apache License, Version 2.0
- */
+
 
 #ifndef SERVICE_REGISTRATION_H_
 #define SERVICE_REGISTRATION_H_
@@ -30,6 +24,8 @@
 #include "celixbool.h"
 
 typedef struct serviceRegistration * service_registration_pt;
+typedef struct serviceRegistration service_registration_t;
+
 
 #include "service_registry.h"
 #include "array_list.h"
@@ -40,16 +36,19 @@ typedef struct serviceRegistration * service_registration_pt;
 extern "C" {
 #endif
 
-FRAMEWORK_EXPORT celix_status_t serviceRegistration_unregister(service_registration_pt registration);
+FRAMEWORK_EXPORT celix_status_t serviceRegistration_unregister(service_registration_t *registration);
 
 FRAMEWORK_EXPORT celix_status_t
-serviceRegistration_getProperties(service_registration_pt registration, properties_pt *properties);
+serviceRegistration_getProperties(service_registration_t *registration, properties_pt *properties);
 
 FRAMEWORK_EXPORT celix_status_t
-serviceRegistration_setProperties(service_registration_pt registration, properties_pt properties);
+serviceRegistration_setProperties(service_registration_t *registration, properties_pt properties);
 
 FRAMEWORK_EXPORT celix_status_t
-serviceRegistration_getServiceName(service_registration_pt registration, const char **serviceName);
+serviceRegistration_getServiceName(service_registration_t *registration, const char **serviceName);
+
+FRAMEWORK_EXPORT long
+serviceRegistration_getServiceId(service_registration_t *registration);
 
 #ifdef __cplusplus
 }

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/include/service_tracker.h
----------------------------------------------------------------------
diff --git a/framework/include/service_tracker.h b/framework/include/service_tracker.h
index aa19d50..5d81a3e 100644
--- a/framework/include/service_tracker.h
+++ b/framework/include/service_tracker.h
@@ -29,42 +29,62 @@
 
 #include "service_listener.h"
 #include "array_list.h"
-#include "bundle_context.h"
 #include "service_tracker_customizer.h"
 #include "framework_exports.h"
+#include "bundle_context.h"
+
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
 typedef struct serviceTracker *service_tracker_pt;
+typedef struct serviceTracker service_tracker_t;
 
 FRAMEWORK_EXPORT celix_status_t
-serviceTracker_create(bundle_context_pt context, const char *service, service_tracker_customizer_pt customizer,
-                      service_tracker_pt *tracker);
+serviceTracker_create(bundle_context_t *ctx, const char *service, service_tracker_customizer_pt customizer,
+                      service_tracker_t **tracker);
 
 FRAMEWORK_EXPORT celix_status_t
-serviceTracker_createWithFilter(bundle_context_pt context, const char *filter, service_tracker_customizer_pt customizer,
-                                service_tracker_pt *tracker);
+serviceTracker_createWithFilter(bundle_context_t *ctx, const char *filter, service_tracker_customizer_pt customizer,
+                                service_tracker_t **tracker);
 
-FRAMEWORK_EXPORT celix_status_t serviceTracker_open(service_tracker_pt tracker);
+FRAMEWORK_EXPORT celix_status_t serviceTracker_open(service_tracker_t *tracker);
 
-FRAMEWORK_EXPORT celix_status_t serviceTracker_close(service_tracker_pt tracker);
+FRAMEWORK_EXPORT celix_status_t serviceTracker_close(service_tracker_t *tracker);
 
-FRAMEWORK_EXPORT celix_status_t serviceTracker_destroy(service_tracker_pt tracker);
+FRAMEWORK_EXPORT celix_status_t serviceTracker_destroy(service_tracker_t *tracker);
 
-FRAMEWORK_EXPORT service_reference_pt serviceTracker_getServiceReference(service_tracker_pt tracker);
+FRAMEWORK_EXPORT service_reference_pt serviceTracker_getServiceReference(service_tracker_t *tracker);
 
-FRAMEWORK_EXPORT array_list_pt serviceTracker_getServiceReferences(service_tracker_pt tracker);
+FRAMEWORK_EXPORT array_list_pt serviceTracker_getServiceReferences(service_tracker_t *tracker);
 
-FRAMEWORK_EXPORT void *serviceTracker_getService(service_tracker_pt tracker);
+FRAMEWORK_EXPORT void *serviceTracker_getService(service_tracker_t *tracker);
 
-FRAMEWORK_EXPORT array_list_pt serviceTracker_getServices(service_tracker_pt tracker);
+FRAMEWORK_EXPORT array_list_pt serviceTracker_getServices(service_tracker_t *tracker);
 
-FRAMEWORK_EXPORT void *serviceTracker_getServiceByReference(service_tracker_pt tracker, service_reference_pt reference);
+FRAMEWORK_EXPORT void *serviceTracker_getServiceByReference(service_tracker_t *tracker, service_reference_pt reference);
 
 FRAMEWORK_EXPORT void serviceTracker_serviceChanged(service_listener_pt listener, service_event_pt event);
 
+/**
+ * Locks and get the highest ranking service. This call needs to be followed with the unlockAndUngetService call
+ *
+ * @param tracker The service tracker
+ * @param svcPropsOut The ptr to ptr of the properties output, can be NULL.
+ * @param ownerOut The ptr to ptr of the bundle servic owner output, can be NULL.
+ * @return the svc if found or NULL.
+ */
+FRAMEWORK_EXPORT void* serviceTracker_lockAndGetService(service_tracker_t *tracker, properties_t **svcPropsOut, bundle_t **ownerOut);
+
+/**
+ * Unlocks and unget the requested service.
+ * @param tracker The service tracker
+ * @param svc The svc for which a lock is held
+ */
+FRAMEWORK_EXPORT void serviceTracker_unlockAndUngetService(service_tracker_t *tracker, void *svc);
+
+
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/src/bundle_context.c
----------------------------------------------------------------------
diff --git a/framework/src/bundle_context.c b/framework/src/bundle_context.c
index 928a7a4..5cbe67a 100644
--- a/framework/src/bundle_context.c
+++ b/framework/src/bundle_context.c
@@ -16,21 +16,18 @@
  *specific language governing permissions and limitations
  *under the License.
  */
-/*
- * bundle_context.c
- *
- *  \date       Mar 26, 2010
- *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright	Apache License, Version 2.0
- */
+
+
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
 
+#include "constants.h"
 #include "bundle_context_private.h"
 #include "framework_private.h"
 #include "bundle.h"
 #include "celix_log.h"
+#include "service_tracker.h"
 
 celix_status_t bundleContext_create(framework_pt framework, framework_logger_pt logger, bundle_pt bundle, bundle_context_pt *bundle_context) {
 	celix_status_t status = CELIX_SUCCESS;
@@ -46,6 +43,9 @@ celix_status_t bundleContext_create(framework_pt framework, framework_logger_pt
             context->framework = framework;
             context->bundle = bundle;
 
+            arrayList_create(&context->svcRegistrations);
+            celixThreadMutex_create(&context->mutex, NULL);
+
             *bundle_context = context;
         }
 	}
@@ -382,3 +382,89 @@ celix_status_t bundleContext_getPropertyWithDefault(bundle_context_pt context, c
 
     return status;
 }
+
+
+long bundleContext_registerCService(bundle_context_t *ctx, const char *serviceName, const void *svc, properties_t *properties) {
+    return bundleContext_registerServiceForLang(ctx, serviceName, svc, properties, CELIX_FRAMEWORK_SERVICE_C_LANGUAGE);
+}
+
+
+long bundleContext_registerServiceForLang(bundle_context_t *ctx, const char *serviceName, const void *svc, properties_t *properties, const char* lang) {
+    long svcId = -1;
+    if (properties == NULL) {
+        properties = properties_create();
+    }
+    service_registration_t *reg = NULL;
+    if (serviceName != NULL && lang != NULL) {
+        properties_set(properties, CELIX_FRAMEWORK_SERVICE_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");
+        }
+    }
+    if (svcId < 0) {
+        properties_destroy(properties);
+    } else {
+        celixThreadMutex_lock(&ctx->mutex);
+        arrayList_add(ctx->svcRegistrations, reg);
+        celixThreadMutex_unlock(&ctx->mutex);
+    }
+    return svcId;
+}
+
+void bundleContext_unregisterService(bundle_context_t *ctx, long serviceId) {
+    service_registration_t *found = NULL;
+    if (ctx != NULL && serviceId >= 0) {
+        celixThreadMutex_lock(&ctx->mutex);
+        unsigned int size = arrayList_size(ctx->svcRegistrations);
+        for (unsigned int i = 0; i < size; ++i) {
+            service_registration_t *reg = arrayList_get(ctx->svcRegistrations, i);
+            if (reg != NULL) {
+                long svcId = serviceRegistration_getServiceId(reg);
+                if (svcId == serviceId) {
+                    found = reg;
+                    arrayList_remove(ctx->svcRegistrations, i);
+                    break;
+                }
+            }
+        }
+        celixThreadMutex_unlock(&ctx->mutex);
+
+        if (found != NULL) {
+            serviceRegistration_unregister(found);
+        } else {
+            framework_logIfError(logger, CELIX_ILLEGAL_ARGUMENT, NULL, "Provided service id is not used to registered using bundleContext_registerCService/registerServiceForLang");
+        }
+    }
+}
+
+bool bundleContext_useServiceWithId(
+        bundle_context_t *ctx,
+        long serviceId,
+        void *callbackHandle,
+        void (*use)(void *handle, void *svc, const properties_t *props, const bundle_t *owner)) {
+    bool called = false;
+    char filter[64];
+    snprintf(filter, 64, "(%s=%li)", OSGI_FRAMEWORK_SERVICE_ID, serviceId);
+    service_tracker_t *trk = NULL;
+    serviceTracker_createWithFilter(ctx, filter, NULL, &trk);
+    serviceTracker_open(trk);
+    if (trk != NULL) {
+        bundle_t *bnd = NULL;
+        properties_t *props = NULL;
+        void *svc = serviceTracker_lockAndGetService(trk, &props, &bnd);
+        if (svc != NULL) {
+            use(callbackHandle, svc, props, bnd);
+            called = true;
+            serviceTracker_unlockAndUngetService(trk, svc);
+        }
+        serviceTracker_close(trk);
+        serviceTracker_destroy(trk);
+    }
+    return called;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/src/bundle_context_private.h
----------------------------------------------------------------------
diff --git a/framework/src/bundle_context_private.h b/framework/src/bundle_context_private.h
index 3810cd0..f4d5425 100644
--- a/framework/src/bundle_context_private.h
+++ b/framework/src/bundle_context_private.h
@@ -37,6 +37,9 @@ struct bundleContext {
 #endif
 	struct framework * framework;
 	struct bundle * bundle;
+
+	celix_thread_mutex_t mutex; //protect svcRegistrations.
+	array_list_t *svcRegistrations;
 };
 
 

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/src/celix_framework_factory.c
----------------------------------------------------------------------
diff --git a/framework/src/celix_framework_factory.c b/framework/src/celix_framework_factory.c
new file mode 100644
index 0000000..d5faf78
--- /dev/null
+++ b/framework/src/celix_framework_factory.c
@@ -0,0 +1,40 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "celix_framework_factory.h"
+
+framework_t* frameworkFactory_newFramework(properties_t *config) {
+    framework_t* fw = NULL;
+
+    if (config == NULL) {
+        config = properties_create();
+    }
+
+    if (config != NULL) {
+        framework_create(&fw, config);
+    }
+    if (fw != NULL) {
+        celix_status_t rc = framework_start(fw);
+        if (rc != CELIX_SUCCESS) {
+            framework_destroy(fw);
+            fw = NULL;
+        }
+    }
+    return fw;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/src/celix_launcher.c
----------------------------------------------------------------------
diff --git a/framework/src/celix_launcher.c b/framework/src/celix_launcher.c
index 8a14e9b..a8d9aea 100644
--- a/framework/src/celix_launcher.c
+++ b/framework/src/celix_launcher.c
@@ -224,63 +224,60 @@ int celixLauncher_launchWithProperties(properties_pt config, framework_pt *frame
 		autoStart = strndup(autoStartProp, 1024*10);
 	}
 
+    bundle_context_t *context = NULL;
 	status = framework_create(framework, config);
-	bundle_pt fwBundle = NULL;
 	if (status == CELIX_SUCCESS) {
-		status = fw_init(*framework);
-		if (status == CELIX_SUCCESS) {
-			// Start the system bundle
-			status = framework_getFrameworkBundle(*framework, &fwBundle);
-
-			if(status == CELIX_SUCCESS){
-				bundle_start(fwBundle);
-
-				char delims[] = " ";
-				char *result = NULL;
-				char *save_ptr = NULL;
-				linked_list_pt bundles;
-				array_list_pt installed = NULL;
-				bundle_context_pt context = NULL;
-				linked_list_iterator_pt iter = NULL;
-				unsigned int i;
-
-				linkedList_create(&bundles);
-				if (autoStart != NULL) {
-					result = strtok_r(autoStart, delims, &save_ptr);
-					while (result != NULL) {
-						char *location = strdup(result);
-						linkedList_addElement(bundles, location);
-						result = strtok_r(NULL, delims, &save_ptr);
-					}
-				}
-				// First install all bundles
-				// Afterwards start them
-				arrayList_create(&installed);
-				bundle_getContext(fwBundle, &context);
-				iter = linkedListIterator_create(bundles, 0);
-				while (linkedListIterator_hasNext(iter)) {
-					bundle_pt current = NULL;
-					char *location = (char *) linkedListIterator_next(iter);
-					if (bundleContext_installBundle(context, location, &current) == CELIX_SUCCESS) {
-						// Only add bundle if it is installed correctly
-						arrayList_add(installed, current);
-					} else {
-						printf("Could not install bundle from %s\n", location);
-					}
-					linkedListIterator_remove(iter);
-					free(location);
-				}
-				linkedListIterator_destroy(iter);
-				linkedList_destroy(bundles);
+		status = framework_start(*framework);
 
-				for (i = 0; i < arrayList_size(installed); i++) {
-					bundle_pt installedBundle = (bundle_pt) arrayList_get(installed, i);
-					bundle_startWithOptions(installedBundle, 0);
-				}
-
-				arrayList_destroy(installed);
+	}
+    if (status == CELIX_SUCCESS) {
+        context = framework_getContext(*framework);
+    }
+
+	if (context != NULL && status == CELIX_SUCCESS) {
+		char delims[] = " ";
+		char *result = NULL;
+		char *save_ptr = NULL;
+		linked_list_pt bundles;
+		array_list_pt installed = NULL;
+		bundle_context_pt context = NULL;
+		linked_list_iterator_pt iter = NULL;
+		unsigned int i;
+
+		linkedList_create(&bundles);
+		if (autoStart != NULL) {
+			result = strtok_r(autoStart, delims, &save_ptr);
+			while (result != NULL) {
+				char *location = strdup(result);
+				linkedList_addElement(bundles, location);
+				result = strtok_r(NULL, delims, &save_ptr);
 			}
 		}
+		// First install all bundles
+		// Afterwards start them
+		arrayList_create(&installed);
+		iter = linkedListIterator_create(bundles, 0);
+		while (linkedListIterator_hasNext(iter)) {
+			bundle_pt current = NULL;
+			char *location = (char *) linkedListIterator_next(iter);
+			if (bundleContext_installBundle(context, location, &current) == CELIX_SUCCESS) {
+				// Only add bundle if it is installed correctly
+				arrayList_add(installed, current);
+			} else {
+				printf("Could not install bundle from %s\n", location);
+			}
+			linkedListIterator_remove(iter);
+			free(location);
+		}
+		linkedListIterator_destroy(iter);
+		linkedList_destroy(bundles);
+
+		for (i = 0; i < arrayList_size(installed); i++) {
+			bundle_pt installedBundle = (bundle_pt) arrayList_get(installed, i);
+			bundle_startWithOptions(installedBundle, 0);
+		}
+
+		arrayList_destroy(installed);
 	}
 
 	if (status != CELIX_SUCCESS) {

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/src/framework.c
----------------------------------------------------------------------
diff --git a/framework/src/framework.c b/framework/src/framework.c
index 7d49254..b745a8c 100644
--- a/framework/src/framework.c
+++ b/framework/src/framework.c
@@ -45,6 +45,7 @@
 #include "service_reference_private.h"
 #include "listener_hook_service.h"
 #include "service_registration_private.h"
+#include "bundle_private.h"
 
 typedef celix_status_t (*create_function_pt)(bundle_context_pt context, void **userData);
 typedef celix_status_t (*start_function_pt)(void * handle, bundle_context_pt context);
@@ -258,7 +259,6 @@ celix_status_t framework_create(framework_pt *framework, properties_pt config) {
 
 celix_status_t framework_destroy(framework_pt framework) {
     celix_status_t status = CELIX_SUCCESS;
-
     celixThreadMutex_lock(&framework->installedBundleMapLock);
 
     if (framework->installedBundleMap != NULL) {
@@ -525,8 +525,8 @@ celix_status_t framework_start(framework_pt framework) {
 	return status;
 }
 
-void framework_stop(framework_pt framework) {
-	fw_stopBundle(framework, framework->bundle, true);
+celix_status_t framework_stop(framework_pt framework) {
+	return fw_stopBundle(framework, framework->bundle, true);
 }
 
 celix_status_t fw_getProperty(framework_pt framework, const char* name, const char* defaultValue, const char** value) {
@@ -2094,7 +2094,7 @@ celix_status_t framework_waitForStop(framework_pt framework) {
 		return CELIX_FRAMEWORK_EXCEPTION;
 	}
 
-	celixThread_join(framework->shutdownThread, NULL);
+    celixThread_join(framework->shutdownThread, NULL);
 
 	fw_log(framework->logger, OSGI_FRAMEWORK_LOG_INFO, "FRAMEWORK: Successful shutdown");
 	return CELIX_SUCCESS;
@@ -2189,6 +2189,14 @@ celix_status_t framework_getFrameworkBundle(framework_pt framework, bundle_pt *b
 	return status;
 }
 
+bundle_context_t* framework_getContext(framework_t *framework) {
+    bundle_context_t *result = NULL;
+    if (framework != NULL && framework->bundle != NULL) {
+        result = framework->bundle->context;
+    }
+    return result;
+}
+
 celix_status_t fw_fireBundleEvent(framework_pt framework, bundle_event_type_e eventType, bundle_pt bundle) {
 	celix_status_t status = CELIX_SUCCESS;
 

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/src/framework_private.h
----------------------------------------------------------------------
diff --git a/framework/src/framework_private.h b/framework/src/framework_private.h
index 124a4b6..910ba4c 100644
--- a/framework/src/framework_private.h
+++ b/framework/src/framework_private.h
@@ -90,9 +90,6 @@ struct framework {
     framework_logger_pt logger;
 };
 
-celix_status_t framework_start(framework_pt framework);
-void framework_stop(framework_pt framework);
-
 FRAMEWORK_EXPORT celix_status_t fw_getProperty(framework_pt framework, const char* name, const char* defaultValue, const char** value);
 
 FRAMEWORK_EXPORT celix_status_t fw_installBundle(framework_pt framework, bundle_pt * bundle, const char * location, const char *inputFile);

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/src/service_registration.c
----------------------------------------------------------------------
diff --git a/framework/src/service_registration.c b/framework/src/service_registration.c
index 262a104..fe25214 100644
--- a/framework/src/service_registration.c
+++ b/framework/src/service_registration.c
@@ -276,7 +276,7 @@ celix_status_t serviceRegistration_getBundle(service_registration_pt registratio
 celix_status_t serviceRegistration_getServiceName(service_registration_pt registration, const char **serviceName) {
 	celix_status_t status = CELIX_SUCCESS;
 
-    if (registration != NULL && *serviceName == NULL) {
+    if (registration != NULL && serviceName != NULL) {
         celixThreadRwlock_readLock(&registration->lock);
         *serviceName = registration->className;
         celixThreadRwlock_unlock(&registration->lock);
@@ -289,3 +289,13 @@ celix_status_t serviceRegistration_getServiceName(service_registration_pt regist
 
 	return status;
 }
+
+long serviceRegistration_getServiceId(service_registration_t *registration) {
+    long svcId = -1;
+    if (registration != NULL) {
+        celixThreadRwlock_readLock(&registration->lock);
+        svcId = registration->serviceId;
+        celixThreadRwlock_unlock(&registration->lock);
+    }
+    return svcId;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/src/service_tracker.c
----------------------------------------------------------------------
diff --git a/framework/src/service_tracker.c b/framework/src/service_tracker.c
index 2631058..bc94599 100644
--- a/framework/src/service_tracker.c
+++ b/framework/src/service_tracker.c
@@ -177,13 +177,14 @@ celix_status_t serviceTracker_close(service_tracker_pt tracker) {
 }
 
 service_reference_pt serviceTracker_getServiceReference(service_tracker_pt tracker) {
-	tracked_pt tracked;
+    //TODO deprecated warning -> not locked
+	tracked_t *tracked;
     service_reference_pt result = NULL;
 	unsigned int i;
 
     celixThreadRwlock_readLock(&tracker->lock);
 	for (i = 0; i < arrayList_size(tracker->trackedServices); i++) {
-		tracked = (tracked_pt) arrayList_get(tracker->trackedServices, i);
+		tracked = (tracked_t*) arrayList_get(tracker->trackedServices, i);
 		result = tracked->reference;
         break;
 	}
@@ -193,14 +194,15 @@ service_reference_pt serviceTracker_getServiceReference(service_tracker_pt track
 }
 
 array_list_pt serviceTracker_getServiceReferences(service_tracker_pt tracker) {
-	tracked_pt tracked;
+    //TODO deprecated warning -> not locked
+    tracked_t *tracked;
 	unsigned int i;
 	array_list_pt references = NULL;
 	arrayList_create(&references);
 
     celixThreadRwlock_readLock(&tracker->lock);
 	for (i = 0; i < arrayList_size(tracker->trackedServices); i++) {
-		tracked = (tracked_pt) arrayList_get(tracker->trackedServices, i);
+		tracked = (tracked_t*) arrayList_get(tracker->trackedServices, i);
 		arrayList_add(references, tracked->reference);
 	}
     celixThreadRwlock_unlock(&tracker->lock);
@@ -209,13 +211,14 @@ array_list_pt serviceTracker_getServiceReferences(service_tracker_pt tracker) {
 }
 
 void *serviceTracker_getService(service_tracker_pt tracker) {
-	tracked_pt tracked;
+    //TODO deprecated warning -> not locked
+    tracked_t* tracked;
     void *service = NULL;
 	unsigned int i;
 
     celixThreadRwlock_readLock(&tracker->lock);
     for (i = 0; i < arrayList_size(tracker->trackedServices); i++) {
-		tracked = (tracked_pt) arrayList_get(tracker->trackedServices, i);
+		tracked = (tracked_t*) arrayList_get(tracker->trackedServices, i);
 		service = tracked->service;
         break;
 	}
@@ -224,15 +227,62 @@ void *serviceTracker_getService(service_tracker_pt tracker) {
     return service;
 }
 
+void* serviceTracker_lockAndGetService(service_tracker_t *tracker, properties_t **svcPropsOut, bundle_t **ownerOut) {
+    void *result = NULL;
+    tracked_t *tracked = NULL;
+    tracked_t *highest = NULL;
+    long highestRank = 0;
+    unsigned int i;
+
+    celixThreadRwlock_readLock(&tracker->lock);
+    for (i = 0; i < arrayList_size(tracker->trackedServices); i++) {
+        tracked = (tracked_t*) arrayList_get(tracker->trackedServices, i);
+        const char *val = properties_getWithDefault(tracked->properties, OSGI_FRAMEWORK_SERVICE_RANKING, "0");
+        long rank = strtol(val, NULL, 10);
+        if (highest == NULL || rank > highestRank) {
+            highest = tracked;
+            result = tracked->service;
+            highestRank = rank;
+        }
+    }
+    if (highest != NULL) {
+        celixThreadMutex_lock(&highest->getLock);
+    }
+    celixThreadRwlock_unlock(&tracker->lock);
+
+    if (highest != NULL && svcPropsOut != NULL) {
+        *svcPropsOut = highest->properties;
+    }
+    if (highest != NULL && ownerOut != NULL) {
+        *ownerOut = tracked->serviceOwner;
+    }
+    return result;
+}
+
+void serviceTracker_unlockAndUngetService(service_tracker_t *tracker, void *svc) {
+    if (svc != NULL) {
+        celixThreadRwlock_readLock(&tracker->lock);
+        unsigned int i;
+        for (i = 0; i < arrayList_size(tracker->trackedServices); i++) {
+            tracked_t *tracked = (tracked_t *) arrayList_get(tracker->trackedServices, i);
+            if (tracked->service == svc) {
+                celixThreadMutex_unlock(&tracked->getLock);
+            }
+        }
+        celixThreadRwlock_unlock(&tracker->lock);
+    }
+}
+
 array_list_pt serviceTracker_getServices(service_tracker_pt tracker) {
-	tracked_pt tracked;
+    //TODO deprecated warning -> not locked, also make locked variant
+    tracked_t *tracked;
 	unsigned int i;
 	array_list_pt references = NULL;
 	arrayList_create(&references);
 
     celixThreadRwlock_readLock(&tracker->lock);
     for (i = 0; i < arrayList_size(tracker->trackedServices); i++) {
-		tracked = (tracked_pt) arrayList_get(tracker->trackedServices, i);
+		tracked = (tracked_t*) arrayList_get(tracker->trackedServices, i);
 		arrayList_add(references, tracked->service);
 	}
     celixThreadRwlock_unlock(&tracker->lock);
@@ -241,14 +291,15 @@ array_list_pt serviceTracker_getServices(service_tracker_pt tracker) {
 }
 
 void *serviceTracker_getServiceByReference(service_tracker_pt tracker, service_reference_pt reference) {
-	tracked_pt tracked;
+    //TODO deprecated warning -> not locked
+    tracked_t *tracked;
     void *service = NULL;
 	unsigned int i;
 
     celixThreadRwlock_readLock(&tracker->lock);
 	for (i = 0; i < arrayList_size(tracker->trackedServices); i++) {
 		bool equals = false;
-		tracked = (tracked_pt) arrayList_get(tracker->trackedServices, i);
+		tracked = (tracked_t*) arrayList_get(tracker->trackedServices, i);
 		serviceReference_equals(reference, tracked->reference, &equals);
 		if (equals) {
 			service = tracked->service;
@@ -281,7 +332,7 @@ void serviceTracker_serviceChanged(service_listener_pt listener, service_event_p
 static celix_status_t serviceTracker_track(service_tracker_pt tracker, service_reference_pt reference, service_event_pt event) {
 	celix_status_t status = CELIX_SUCCESS;
 
-    tracked_pt tracked = NULL;
+    tracked_t *tracked = NULL;
     bool found = false;
     unsigned int i;
     
@@ -290,7 +341,7 @@ static celix_status_t serviceTracker_track(service_tracker_pt tracker, service_r
     celixThreadRwlock_readLock(&tracker->lock);
     for (i = 0; i < arrayList_size(tracker->trackedServices); i++) {
         bool equals = false;
-        tracked = (tracked_pt) arrayList_get(tracker->trackedServices, i);
+        tracked = (tracked_t*) arrayList_get(tracker->trackedServices, i);
         status = serviceReference_equals(reference, tracked->reference, &equals);
         if (status != CELIX_SUCCESS) {
             break;
@@ -307,10 +358,22 @@ static celix_status_t serviceTracker_track(service_tracker_pt tracker, service_r
         status = serviceTracker_invokeAddingService(tracker, reference, &service);
         if (status == CELIX_SUCCESS) {
             if (service != NULL) {
-                tracked = (tracked_pt) calloc(1, sizeof (*tracked));
+                tracked = (tracked_t*) calloc(1, sizeof (*tracked));
                 assert(reference != NULL);
                 tracked->reference = reference;
                 tracked->service = service;
+                service_registration_t *reg = NULL;
+                properties_t *props = NULL;
+                bundle_t *bnd = NULL;
+                serviceReference_getBundle(reference, &bnd);
+                serviceReference_getServiceRegistration(reference, &reg);
+                if (reg != NULL) {
+                    serviceRegistration_getProperties(reg, &props);
+                }
+                tracked->properties = props;
+
+                tracked->serviceOwner = bnd;
+                celixThreadMutex_create(&tracked->getLock, NULL);
 
                 celixThreadRwlock_writeLock(&tracker->lock);
                 arrayList_add(tracker->trackedServices, tracked);
@@ -392,27 +455,28 @@ static celix_status_t serviceTracker_invokeAddingService(service_tracker_pt trac
 
 static celix_status_t serviceTracker_untrack(service_tracker_pt tracker, service_reference_pt reference, service_event_pt event) {
     celix_status_t status = CELIX_SUCCESS;
-    tracked_pt tracked = NULL;
+    tracked_t *found = NULL;
     unsigned int i;
-    bool found = false;
 
     celixThreadRwlock_writeLock(&tracker->lock);
     for (i = 0; i < arrayList_size(tracker->trackedServices); i++) {
         bool equals;
-        tracked = (tracked_pt) arrayList_get(tracker->trackedServices, i);
+        tracked_t *tracked = (tracked_t*) arrayList_get(tracker->trackedServices, i);
         serviceReference_equals(reference, tracked->reference, &equals);
         if (equals) {
-            found = true;
+            found = tracked;
             arrayList_remove(tracker->trackedServices, i);
             break;
         }
     }
     celixThreadRwlock_unlock(&tracker->lock);
 
-    if (found && tracked != NULL) {
-        serviceTracker_invokeRemovingService(tracker, tracked->reference, tracked->service);
+    if (found != NULL) {
+        celixThreadMutex_lock(&found->getLock);
+        serviceTracker_invokeRemovingService(tracker, found->reference, found->service);
         bundleContext_ungetServiceReference(tracker->context, reference);
-        free(tracked);
+        celixThreadMutex_destroy(&found->getLock);
+        free(found);
     }
    
     framework_logIfError(logger, status, NULL, "Cannot untrack reference");

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/src/service_tracker_private.h
----------------------------------------------------------------------
diff --git a/framework/src/service_tracker_private.h b/framework/src/service_tracker_private.h
index 1d80ba1..28086a3 100644
--- a/framework/src/service_tracker_private.h
+++ b/framework/src/service_tracker_private.h
@@ -31,7 +31,7 @@
 #include "service_tracker.h"
 
 struct serviceTracker {
-	bundle_context_pt context;
+	bundle_context_t *context;
 	char * filter;
 
 	service_tracker_pt tracker;
@@ -43,10 +43,13 @@ struct serviceTracker {
 };
 
 struct tracked {
+	celix_thread_mutex_t getLock; //TODO improve to count to that multiple services can be used in parallel from a single tracker
 	service_reference_pt reference;
 	void * service;
+	properties_t *properties;
+	bundle_t* serviceOwner;
 };
 
-typedef struct tracked * tracked_pt;
+typedef struct tracked tracked_t;
 
 #endif /* SERVICE_TRACKER_PRIVATE_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/tst/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/framework/tst/CMakeLists.txt b/framework/tst/CMakeLists.txt
index 169e828..361ec4d 100644
--- a/framework/tst/CMakeLists.txt
+++ b/framework/tst/CMakeLists.txt
@@ -20,6 +20,7 @@ add_executable(test_framework
     run_tests.cpp
     single_framework_test.cpp
     multiple_frameworks_test.cpp
+    framework_bundle_context.cpp
 )
 target_link_libraries(test_framework Celix::framework ${CURL_LIBRARIES} ${CPPUTEST_LIBRARY})
 

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/tst/framework_bundle_context.cpp
----------------------------------------------------------------------
diff --git a/framework/tst/framework_bundle_context.cpp b/framework/tst/framework_bundle_context.cpp
new file mode 100644
index 0000000..7d5bc99
--- /dev/null
+++ b/framework/tst/framework_bundle_context.cpp
@@ -0,0 +1,101 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+#include <CppUTest/TestHarness.h>
+#include <CppUTest/CommandLineTestRunner.h>
+
+#include "celix_framework_factory.h"
+
+
+TEST_GROUP(CelixFrameworkContextTests) {
+    framework_t* fw = NULL;
+    bundle_context_t *ctx = NULL;
+
+    void setup() {
+        fw = frameworkFactory_newFramework(NULL);
+        ctx = framework_getContext(fw);
+    }
+
+    void teardown() {
+        framework_destroy(fw);
+    }
+};
+
+TEST(CelixFrameworkContextTests, registerService) {
+    struct calc {
+        int (*calc)(int);
+    };
+
+    const char *calcName = "calc";
+    calc svc{};
+    svc.calc = [](int n) -> int {
+        return n * 42;
+    };
+
+    long svcId = bundleContext_registerCService(ctx, calcName, &svc, NULL);
+    CHECK(svcId >= 0);
+    bundleContext_unregisterService(ctx, svcId);
+};
+
+TEST(CelixFrameworkContextTests, incorrectUnregisterCalls) {
+    bundleContext_unregisterService(ctx, 1);
+    bundleContext_unregisterService(ctx, 2);
+    bundleContext_unregisterService(ctx, -1);
+    bundleContext_unregisterService(ctx, -2);
+};
+
+TEST(CelixFrameworkContextTests, registerAndUseService) {
+    struct calc {
+        int (*calc)(int);
+    };
+
+    const char *calcName = "calc";
+    struct calc svc{};
+    svc.calc = [](int n) -> int {
+        return n * 42;
+    };
+
+    long svcId = bundleContext_registerCService(ctx, calcName, &svc, NULL);
+    CHECK(svcId >= 0);
+
+    int result = 0;
+    bool called = bundleContext_useServiceWithId(ctx, svcId, &result, [](void *handle, void *svc, const properties_t *props, const bundle_t *bnd) {
+        CHECK(svc != NULL);
+        CHECK(props != NULL);
+        CHECK(bnd != NULL);
+        int *result =  static_cast<int*>(handle);
+        struct calc *calc = static_cast<struct calc*>(svc);
+        int tmp = calc->calc(2);
+        *result = tmp;
+    });
+    CHECK(called);
+    CHECK_EQUAL(84, result);
+
+    result = 0;
+    long nonExistingSvcId = 101;
+    called = bundleContext_useServiceWithId(ctx, nonExistingSvcId, &result, [](void *handle, void *svc, const properties_t *, const bundle_t *) {
+        int *result =  static_cast<int*>(handle);
+        struct calc *calc = static_cast<struct calc*>(svc);
+        int tmp = calc->calc(2);
+        *result = tmp;
+    });
+    CHECK(!called);
+    CHECK_EQUAL(0, result); //e.g. not called
+
+    bundleContext_unregisterService(ctx, svcId);
+};
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/framework/tst/single_framework_test.cpp
----------------------------------------------------------------------
diff --git a/framework/tst/single_framework_test.cpp b/framework/tst/single_framework_test.cpp
index e3a0fa6..11ebcb9 100644
--- a/framework/tst/single_framework_test.cpp
+++ b/framework/tst/single_framework_test.cpp
@@ -28,7 +28,7 @@ extern "C" {
 #include <ctype.h>
 
 #include "celix_launcher.h"
-#include "framework.h"
+#include "celix_framework_factory.h"
 
 
     static framework_pt framework = NULL;
@@ -81,3 +81,43 @@ TEST_GROUP(CelixFramework) {
 TEST(CelixFramework, testFramework) {
     testFramework();
 }
+
+TEST_GROUP(FrameworkFactory) {
+};
+
+
+TEST(FrameworkFactory, testFactoryCreate) {
+    framework_t* fw = frameworkFactory_newFramework(NULL);
+    CHECK(fw != NULL);
+    framework_destroy(fw);
+}
+
+TEST(FrameworkFactory, testFactoryCreateAndToManyStartAndStops) {
+    framework_t* fw = frameworkFactory_newFramework(NULL);
+    CHECK(fw != NULL);
+
+    framework_start(fw); //should already be done by frameworkFactory_newFramework();
+    framework_start(fw);
+    framework_start(fw);
+    framework_start(fw);
+
+    framework_stop(fw); //will also be implicitly done by framework_destroy
+    framework_stop(fw);
+    framework_stop(fw);
+    framework_stop(fw);
+
+    framework_destroy(fw);
+}
+
+TEST(FrameworkFactory, restartFramework) {
+    framework_t* fw = frameworkFactory_newFramework(NULL);
+    CHECK(fw != NULL);
+
+    framework_stop(fw);
+    framework_start(fw);
+    framework_stop(fw);
+    framework_start(fw);
+
+    framework_destroy(fw);
+}
+

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/launcher/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/launcher/CMakeLists.txt b/launcher/CMakeLists.txt
index 67385e5..9933ff9 100644
--- a/launcher/CMakeLists.txt
+++ b/launcher/CMakeLists.txt
@@ -36,22 +36,4 @@ if (LAUNCHER)
     install(TARGETS launcher EXPORT celix RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT framework)
     #Setup target aliases to match external usage
     add_executable(Celix::launcher ALIAS launcher)
-
-    find_package(CppUTest QUIET)
-    if (CPPUTEST_FOUND)
-        #Test running which start celix and run CppUTest RUN_ALL_TESTS.
-        #Using this test running it is possible to create bundles containing CppUTests.
-	    include_directories(celix_test_runner)
-	    include_directories(SYSTEM ${CPPUTEST_INCLUDE_DIRS})
-        add_executable(celix_test_runner
-                src/celix_test_runner.cpp
-        )
-        set_target_properties(celix_test_runner PROPERTIES "INSTALL_RPATH" "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}")
-        target_link_libraries(celix_test_runner PRIVATE
-            Celix::framework
-            ${CPPUTEST_LIBRARIES}
-            ${CPPUTEST_EXT_LIBRARIES}
-        )
-        install(TARGETS celix_test_runner RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT framework)
-    endif ()
 endif (LAUNCHER) 

http://git-wip-us.apache.org/repos/asf/celix/blob/0657853e/launcher/src/celix_test_runner.cpp
----------------------------------------------------------------------
diff --git a/launcher/src/celix_test_runner.cpp b/launcher/src/celix_test_runner.cpp
deleted file mode 100644
index 1855e9f..0000000
--- a/launcher/src/celix_test_runner.cpp
+++ /dev/null
@@ -1,73 +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 <signal.h>
-
-#include "celix_launcher.h"
-
-#include <CppUTest/CommandLineTestRunner.h>
-
-static void shutdown_framework(int signal);
-static void ignore(int signal);
-
-#define DEFAULT_CONFIG_FILE "config.properties"
-
-static framework_pt framework = NULL;
-
-int main(int argc, char *argv[]) {
-    // Perform some minimal command-line option parsing...
-    const char *cfg = DEFAULT_CONFIG_FILE;
-
-    // Set signal handler
-    (void) signal(SIGINT, shutdown_framework);
-    (void) signal(SIGUSR1, ignore);
-    (void) signal(SIGUSR2, ignore);
-
-    int rc = celixLauncher_launch(cfg, &framework);
-    if (rc != 0) {
-        printf("Error starting Celix\n");
-    }
-
-    if (rc == 0 && framework != NULL) {
-        rc = RUN_ALL_TESTS(argc, argv);
-
-        celixLauncher_stop(framework);
-        celixLauncher_waitForShutdown(framework);
-        celixLauncher_destroy(framework);
-    }
-
-    if (rc != 0) {
-        printf("*** FAILURE ***\n");
-    } else {
-        printf("*** SUCCESS ***\n");
-    }
-
-    return rc;
-}
-
-static void shutdown_framework(int __attribute__((unused)) signal) {
-    if (framework != NULL) {
-        celixLauncher_stop(framework); //NOTE main thread will destroy
-    }
-}
-
-static void ignore(int __attribute__((unused)) signal) {
-    //ignoring for signal SIGUSR1, SIGUSR2. Can be used to interrupt sleep, etc
-}


Mime
View raw message