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 <[email protected]>
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);

Reply via email to