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 2021/07/30 14:34:44 UTC
[celix] 01/01: Adds support for the service.bundleid and
service.scope framework props
This is an automated email from the ASF dual-hosted git repository.
pnoltes pushed a commit to branch feature/update_standard_service_properties
in repository https://gitbox.apache.org/repos/asf/celix.git
commit 4612552589644f612b674cdf67ec414a89c8f80f
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Fri Jul 30 16:34:36 2021 +0200
Adds support for the service.bundleid and service.scope framework props
---
.../gtest/src/CxxBundleContextTestSuite.cc | 45 +++++++++++
libs/framework/include/celix/Constants.h | 41 ++++++++--
libs/framework/include/celix_constants.h | 90 +++++++++++++++++-----
libs/framework/src/service_registry.c | 6 ++
4 files changed, 157 insertions(+), 25 deletions(-)
diff --git a/libs/framework/gtest/src/CxxBundleContextTestSuite.cc b/libs/framework/gtest/src/CxxBundleContextTestSuite.cc
index 8f059fd..52654c4 100644
--- a/libs/framework/gtest/src/CxxBundleContextTestSuite.cc
+++ b/libs/framework/gtest/src/CxxBundleContextTestSuite.cc
@@ -20,6 +20,7 @@
#include <gtest/gtest.h>
#include <atomic>
+#include <search.h>
#include "celix/BundleContext.h"
@@ -609,4 +610,48 @@ TEST_F(CxxBundleContextTestSuite, WaitForAllEvents) {
ctx->waitIfAbleForAllEvents();
svcId = ctx->findService<TestInterface>();
EXPECT_EQ(svcId, -1L);
+}
+
+
+TEST_F(CxxBundleContextTestSuite, CheckStandardServiceProperties) {
+ /*
+ * OSGi 7 specifies the following service properties which must be set by the framework:
+ * - objectClass (CELIX_FRAMEWORK_SERVICE_NAME)
+ * - service.id (CELIX_FRAMEWORK_SERVICE_ID)
+ * - service.bundleid (CELIX_FRAMEWORK_SERVICE_BUNDLE_ID)
+ * - service.scope (CELIX_FRAMEWORK_SERVICE_SCOPE)
+ */
+
+ auto svcReg = ctx->registerService<TestInterface>(std::make_shared<TestImplementation>()).build();
+ bool called = ctx->useService<TestInterface>()
+ .addUseCallback([](TestInterface& /*svc*/, const celix::Properties& props) {
+ EXPECT_FALSE(props.get(celix::SERVICE_NAME).empty());
+ EXPECT_GE(props.getAsLong(celix::SERVICE_BUNDLE_ID, -1), 0);
+ EXPECT_EQ(props.get(celix::SERVICE_SCOPE), std::string{celix::SERVICE_SCOPE_SINGLETON});
+ })
+ .build();
+ EXPECT_TRUE(called);
+
+ //note using c api, because C++ api does not yet support registering svc factories
+ celix_service_factory_t factory{nullptr, nullptr, nullptr};
+ factory.getService = [](void */*handle*/, const celix_bundle_t */*requestingBundle*/, const celix_properties_t */*svcProperties*/) -> void* {
+ //dummy svc
+ return (void*)0x42;
+ };
+ factory.ungetService = [](void */*handle*/, const celix_bundle_t */*requestingBundle*/, const celix_properties_t */*svcProperties*/) {
+ //nop
+ };
+ auto svcId = celix_bundleContext_registerServiceFactory(ctx->getCBundleContext(), &factory, "TestInterfaceFactory", nullptr);
+ EXPECT_GE(svcId, 0);
+
+ called = ctx->useService<TestInterface>("TestInterfaceFactory")
+ .addUseCallback([](TestInterface& /*svc*/, const celix::Properties& props) {
+ EXPECT_FALSE(props.get(celix::SERVICE_NAME).empty());
+ EXPECT_GE(props.getAsLong(celix::SERVICE_BUNDLE_ID, -1), 0);
+ EXPECT_EQ(props.get(celix::SERVICE_SCOPE), std::string{celix::SERVICE_SCOPE_BUNDLE});
+ })
+ .build();
+ EXPECT_TRUE(called);
+
+ celix_bundleContext_unregisterService(ctx->getCBundleContext(), svcId);
}
\ No newline at end of file
diff --git a/libs/framework/include/celix/Constants.h b/libs/framework/include/celix/Constants.h
index 084602d..8f84ccb 100644
--- a/libs/framework/include/celix/Constants.h
+++ b/libs/framework/include/celix/Constants.h
@@ -34,7 +34,7 @@ namespace celix {
*
* This property is set by the Celix framework when a service is registered.
*/
- constexpr const char * const SERVICE_NAME = OSGI_FRAMEWORK_OBJECTCLASS;
+ constexpr const char * const SERVICE_NAME = CELIX_FRAMEWORK_SERVICE_NAME;
/**
* @brief Service property (named "service.id") identifying a service's registration number (of type long).
@@ -43,7 +43,36 @@ namespace celix {
* The Celix framework assigns a unique value that is larger than all previously assigned values since the
* Celix framework was started.
*/
- constexpr const char * const SERVICE_ID = OSGI_FRAMEWORK_SERVICE_ID;
+ constexpr const char * const SERVICE_ID = CELIX_FRAMEWORK_SERVICE_ID;
+
+ /**
+ * @brief Service property (named service.bundleid) identifying the bundle id of the bundle registering the service.
+ *
+ * This property is set by the Celix framework when a service is registered. The value of this property must be of type Long.
+ */
+ constexpr const char * const SERVICE_BUNDLE_ID = CELIX_FRAMEWORK_SERVICE_BUNDLE_ID;
+
+ /**
+ * @brief Service property (named service.scope) identifying a service's scope.
+ *
+ * This property is set by the Framework when a service is registered.
+ * If the registered object implements service factory, then the value of this service property will be
+ * CELIX_FRAMEWORK_SERVICE_SCOPE_BUNDLE.
+ * Otherwise, the value of this service property will be CELIX_FRAMEWORK_SERVICE_SCOPE_SINGLETON.
+ *
+ * @warning Note that the scope "prototype" is not supported in Celix.
+ */
+ constexpr const char * const SERVICE_SCOPE = CELIX_FRAMEWORK_SERVICE_SCOPE;
+
+ /**
+ * @brief Service scope is singleton. All bundles using the service receive the same service object.
+ */
+ constexpr const char * const SERVICE_SCOPE_SINGLETON = CELIX_FRAMEWORK_SERVICE_SCOPE_SINGLETON;
+
+ /**
+ * @brief Service scope is bundle. Each bundle using the service receives a customized service object.
+ */
+ constexpr const char * const SERVICE_SCOPE_BUNDLE = CELIX_FRAMEWORK_SERVICE_SCOPE_BUNDLE;
/**
* @brief Service property (named "service.ranking") identifying a service's ranking number (of type long).
@@ -59,7 +88,7 @@ namespace celix {
* The default ranking is 0. A service with a ranking of LONG_MAX is very likely to be returned as the default
* service, whereas a service with a ranking of LONG_MIN is very unlikely to be returned.
*/
- constexpr const char * const SERVICE_RANKING = OSGI_FRAMEWORK_SERVICE_RANKING;
+ constexpr const char * const SERVICE_RANKING = CELIX_FRAMEWORK_SERVICE_RANKING;
/**
* @brief Service property (named "service.version") specifying the optional version of a service.
@@ -82,7 +111,7 @@ namespace celix {
*
* If not specified ".cache" is used.
*/
- constexpr const char * const FRAMEWORK_STORAGE = OSGI_FRAMEWORK_FRAMEWORK_STORAGE;
+ constexpr const char * const FRAMEWORK_STORAGE = CELIX_FRAMEWORK_FRAMEWORK_STORAGE;
/**
* @brief Celix framework environment property (named "org.osgi.framework.uuid") specifying the UUID for the
@@ -93,7 +122,7 @@ namespace celix {
*
* @note The Celix framework expects framework UUIDs to be unique per process.
*/
- constexpr const char * const FRAMEWORK_UUID = OSGI_FRAMEWORK_FRAMEWORK_UUID;
+ constexpr const char * const FRAMEWORK_UUID = CELIX_FRAMEWORK_FRAMEWORK_UUID;
/**
* @brief Celix framework environment property (named "CELIX_FRAMEWORK_STATIC_EVENT_QUEUE_SIZE") which configures
@@ -181,5 +210,5 @@ namespace celix {
*
* If not specified ".cache" is used.
*/
- constexpr const char * const FRAMEWORK_CACHE_DIR = OSGI_FRAMEWORK_FRAMEWORK_STORAGE;
+ constexpr const char * const FRAMEWORK_CACHE_DIR = CELIX_FRAMEWORK_FRAMEWORK_STORAGE;
}
\ No newline at end of file
diff --git a/libs/framework/include/celix_constants.h b/libs/framework/include/celix_constants.h
index c956493..b013317 100644
--- a/libs/framework/include/celix_constants.h
+++ b/libs/framework/include/celix_constants.h
@@ -27,12 +27,17 @@ extern "C" {
#endif
/**
+ * Collection of celix constants. Note that the CELIX_ macros are preferred over the OSGI_ variants.
+ */
+
+/**
* @brief Service property (named "objectClass") identifying the service name under which a service was registered
* in the Celix framework.
*
* This property is set by the Celix framework when a service is registered.
*/
-#define OSGI_FRAMEWORK_OBJECTCLASS "objectClass"
+#define CELIX_FRAMEWORK_SERVICE_NAME "objectClass"
+#define OSGI_FRAMEWORK_OBJECTCLASS CELIX_FRAMEWORK_SERVICE_NAME
/**
* @brief Service property (named "service.id") identifying a service's registration number (of type long).
@@ -41,9 +46,40 @@ extern "C" {
* The Celix framework assigns a unique value that is larger than all previously assigned values since the
* Celix framework was started.
*/
-#define OSGI_FRAMEWORK_SERVICE_ID "service.id"
+#define CELIX_FRAMEWORK_SERVICE_ID "service.id"
+#define OSGI_FRAMEWORK_SERVICE_ID CELIX_FRAMEWORK_SERVICE_ID
+
+/**
+ * @brief Service property (named service.bundleid) identifying the bundle id of the bundle registering the service.
+ *
+ * This property is set by the Celix framework when a service is registered. The value of this property must be of type Long.
+ */
+#define CELIX_FRAMEWORK_SERVICE_BUNDLE_ID "service.bundleid"
+
+/**
+ * @brief Service property (named service.scope) identifying a service's scope.
+ *
+ * This property is set by the Framework when a service is registered.
+ * If the registered object implements service factory, then the value of this service property will be
+ * CELIX_FRAMEWORK_SERVICE_SCOPE_BUNDLE.
+ * Otherwise, the value of this service property will be CELIX_FRAMEWORK_SERVICE_SCOPE_SINGLETON.
+ *
+ * @warning Note that the scope "prototype" is not supported in Celix.
+ */
+#define CELIX_FRAMEWORK_SERVICE_SCOPE "service.scope"
+
+/**
+ * @brief Service scope is singleton. All bundles using the service receive the same service object.
+ */
+#define CELIX_FRAMEWORK_SERVICE_SCOPE_SINGLETON "singleton"
+
+/**
+ * @brief Service scope is bundle. Each bundle using the service receives a customized service object.
+ */
+#define CELIX_FRAMEWORK_SERVICE_SCOPE_BUNDLE "bundle"
-#define OSGI_FRAMEWORK_SERVICE_PID "service.pid"
+#define CELIX_FRAMEWORK_SERVICE_PID "service.pid"
+#define OSGI_FRAMEWORK_SERVICE_PID CELIX_FRAMEWORK_SERVICE_PID
/**
* @brief The bundle id (value 0) used to identify the Celix framework.
@@ -64,7 +100,8 @@ extern "C" {
* The default ranking is 0. A service with a ranking of LONG_MAX is very likely to be returned as the default
* service, whereas a service with a ranking of LONG_MIN is very unlikely to be returned.
*/
-#define OSGI_FRAMEWORK_SERVICE_RANKING "service.ranking"
+#define CELIX_FRAMEWORK_SERVICE_RANKING "service.ranking"
+#define OSGI_FRAMEWORK_SERVICE_RANKING CELIX_FRAMEWORK_SERVICE_RANKING
/**
* @brief Service property (named "service.version") specifying the optional version of a service.
@@ -89,23 +126,33 @@ extern "C" {
#define CELIX_FRAMEWORK_SERVICE_CXX_LANGUAGE "C++"
#define CELIX_FRAMEWORK_SERVICE_SHARED_LANGUAGE "shared" //e.g. marker services
-#define OSGI_FRAMEWORK_BUNDLE_ACTIVATOR "Bundle-Activator"
+#define CELIX_FRAMEWORK_BUNDLE_ACTIVATOR "Bundle-Activator"
+#define OSGI_FRAMEWORK_BUNDLE_ACTIVATOR CELIX_FRAMEWORK_BUNDLE_ACTIVATOR
-#define OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_CREATE "celix_bundleActivator_create"
-#define OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_START "celix_bundleActivator_start"
-#define OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_STOP "celix_bundleActivator_stop"
-#define OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_DESTROY "celix_bundleActivator_destroy"
+#define CELIX_FRAMEWORK_BUNDLE_ACTIVATOR_CREATE "celix_bundleActivator_create"
+#define CELIX_FRAMEWORK_BUNDLE_ACTIVATOR_START "celix_bundleActivator_start"
+#define CELIX_FRAMEWORK_BUNDLE_ACTIVATOR_STOP "celix_bundleActivator_stop"
+#define CELIX_FRAMEWORK_BUNDLE_ACTIVATOR_DESTROY "celix_bundleActivator_destroy"
+#define OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_CREATE CELIX_FRAMEWORK_BUNDLE_ACTIVATOR_CREATE
+#define OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_START CELIX_FRAMEWORK_BUNDLE_ACTIVATOR_START
+#define OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_STOP CELIX_FRAMEWORK_BUNDLE_ACTIVATOR_STOP
+#define OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_DESTROY CELIX_FRAMEWORK_BUNDLE_ACTIVATOR_DESTROY
#define OSGI_FRAMEWORK_DEPRECATED_BUNDLE_ACTIVATOR_CREATE "bundleActivator_create"
#define OSGI_FRAMEWORK_DEPRECATED_BUNDLE_ACTIVATOR_START "bundleActivator_start"
#define OSGI_FRAMEWORK_DEPRECATED_BUNDLE_ACTIVATOR_STOP "bundleActivator_stop"
#define OSGI_FRAMEWORK_DEPRECATED_BUNDLE_ACTIVATOR_DESTROY "bundleActivator_destroy"
-#define OSGI_FRAMEWORK_BUNDLE_SYMBOLICNAME "Bundle-SymbolicName"
-#define OSGI_FRAMEWORK_BUNDLE_VERSION "Bundle-Version"
-#define OSGI_FRAMEWORK_PRIVATE_LIBRARY "Private-Library"
-#define OSGI_FRAMEWORK_EXPORT_LIBRARY "Export-Library"
-#define OSGI_FRAMEWORK_IMPORT_LIBRARY "Import-Library"
+#define CELIX_FRAMEWORK_BUNDLE_SYMBOLICNAME "Bundle-SymbolicName"
+#define CELIX_FRAMEWORK_BUNDLE_VERSION "Bundle-Version"
+#define CELIX_FRAMEWORK_PRIVATE_LIBRARY "Private-Library"
+#define CELIX_FRAMEWORK_EXPORT_LIBRARY "Export-Library"
+#define CELIX_FRAMEWORK_IMPORT_LIBRARY "Import-Library"
+#define OSGI_FRAMEWORK_BUNDLE_SYMBOLICNAME CELIX_FRAMEWORK_BUNDLE_SYMBOLICNAME
+#define OSGI_FRAMEWORK_BUNDLE_VERSION CELIX_FRAMEWORK_BUNDLE_VERSION
+#define OSGI_FRAMEWORK_PRIVATE_LIBRARY CELIX_FRAMEWORK_PRIVATE_LIBRARY
+#define OSGI_FRAMEWORK_EXPORT_LIBRARY CELIX_FRAMEWORK_EXPORT_LIBRARY
+#define OSGI_FRAMEWORK_IMPORT_LIBRARY CELIX_FRAMEWORK_IMPORT_LIBRARY
/**
* @brief Celix framework environment property (named "org.osgi.framework.storage") specifying the cache
@@ -113,11 +160,15 @@ extern "C" {
*
* If not specified ".cache" is used.
*/
-#define OSGI_FRAMEWORK_FRAMEWORK_STORAGE "org.osgi.framework.storage"
+#define CELIX_FRAMEWORK_FRAMEWORK_STORAGE "org.osgi.framework.storage"
+#define OSGI_FRAMEWORK_FRAMEWORK_STORAGE CELIX_FRAMEWORK_FRAMEWORK_STORAGE
-#define OSGI_FRAMEWORK_STORAGE_USE_TMP_DIR "org.osgi.framework.storage.use.tmp.dir"
-#define OSGI_FRAMEWORK_FRAMEWORK_STORAGE_CLEAN_NAME "org.osgi.framework.storage.clean"
-#define OSGI_FRAMEWORK_FRAMEWORK_STORAGE_CLEAN_DEFAULT true
+#define CELIX_FRAMEWORK_STORAGE_USE_TMP_DIR "org.osgi.framework.storage.use.tmp.dir"
+#define CELIX_FRAMEWORK_FRAMEWORK_STORAGE_CLEAN_NAME "org.osgi.framework.storage.clean"
+#define CELIX_FRAMEWORK_FRAMEWORK_STORAGE_CLEAN_DEFAULT true
+#define OSGI_FRAMEWORK_STORAGE_USE_TMP_DIR CELIX_FRAMEWORK_STORAGE_USE_TMP_DIR
+#define OSGI_FRAMEWORK_FRAMEWORK_STORAGE_CLEAN_NAME CELIX_FRAMEWORK_FRAMEWORK_STORAGE_CLEAN_NAME
+#define OSGI_FRAMEWORK_FRAMEWORK_STORAGE_CLEAN_DEFAULT CELIX_FRAMEWORK_FRAMEWORK_STORAGE_CLEAN_DEFAULT
/**
* @brief Celix framework environment property (named "org.osgi.framework.uuid") specifying the UUID for the
@@ -128,7 +179,8 @@ extern "C" {
*
* @note The Celix framework expects framework UUIDs to be unique per process.
*/
-#define OSGI_FRAMEWORK_FRAMEWORK_UUID "org.osgi.framework.uuid"
+#define CELIX_FRAMEWORK_FRAMEWORK_UUID "org.osgi.framework.uuid"
+#define OSGI_FRAMEWORK_FRAMEWORK_UUID CELIX_FRAMEWORK_FRAMEWORK_UUID
/**
* @brief Celix framework environment property (named "CELIX_BUNDLES_PATH") which specified a `;` separated
diff --git a/libs/framework/src/service_registry.c b/libs/framework/src/service_registry.c
index f73e48d..876965c 100644
--- a/libs/framework/src/service_registry.c
+++ b/libs/framework/src/service_registry.c
@@ -191,13 +191,19 @@ static celix_status_t serviceRegistry_registerServiceInternal(service_registry_p
array_list_pt regs;
long svcId = reservedId > 0 ? reservedId : celix_serviceRegistry_nextSvcId(registry);
+ celix_properties_setLong(dictionary, CELIX_FRAMEWORK_SERVICE_BUNDLE_ID, celix_bundle_getId(bundle));
+
+
if (svcType == CELIX_DEPRECATED_FACTORY_SERVICE) {
+ celix_properties_set(dictionary, CELIX_FRAMEWORK_SERVICE_SCOPE, CELIX_FRAMEWORK_SERVICE_SCOPE_BUNDLE);
*registration = serviceRegistration_createServiceFactory(registry->callback, bundle, serviceName,
svcId, serviceObject,
dictionary);
} else if (svcType == CELIX_FACTORY_SERVICE) {
+ celix_properties_set(dictionary, CELIX_FRAMEWORK_SERVICE_SCOPE, CELIX_FRAMEWORK_SERVICE_SCOPE_BUNDLE);
*registration = celix_serviceRegistration_createServiceFactory(registry->callback, bundle, serviceName, svcId, (celix_service_factory_t*)serviceObject, dictionary);
} else { //plain
+ celix_properties_set(dictionary, CELIX_FRAMEWORK_SERVICE_SCOPE, CELIX_FRAMEWORK_SERVICE_SCOPE_SINGLETON);
*registration = serviceRegistration_create(registry->callback, bundle, serviceName, svcId, serviceObject, dictionary);
}
//printf("Registering service %li with name %s\n", svcId, serviceName);