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 2024/01/21 18:35:48 UTC
(celix) 07/08: Add automatic conversion of ranking/version props for ctx
This is an automated email from the ASF dual-hosted git repository.
pnoltes pushed a commit to branch feature/674-improve-properties
in repository https://gitbox.apache.org/repos/asf/celix.git
commit a555df9711884dd1aac7a557c96bea42fda4e8d6
Author: Pepijn Noltes <pn...@apache.org>
AuthorDate: Sun Jan 21 19:19:53 2024 +0100
Add automatic conversion of ranking/version props for ctx
---
.../src/CelixBundleContextServicesTestSuite.cc | 56 ++++++++++++++++++++++
libs/framework/src/bundle_context.c | 53 ++++++++++++++++++++
2 files changed, 109 insertions(+)
diff --git a/libs/framework/gtest/src/CelixBundleContextServicesTestSuite.cc b/libs/framework/gtest/src/CelixBundleContextServicesTestSuite.cc
index d17b3892..f9955f6f 100644
--- a/libs/framework/gtest/src/CelixBundleContextServicesTestSuite.cc
+++ b/libs/framework/gtest/src/CelixBundleContextServicesTestSuite.cc
@@ -1741,3 +1741,59 @@ TEST_F(CelixBundleContextServicesTestSuite, SetServicesWithTrackerWhenMultipleRe
celix_bundleContext_unregisterService(ctx, svcId2);
celix_bundleContext_unregisterService(ctx, svcId3);
}
+
+TEST_F(CelixBundleContextServicesTestSuite, RegisterServiceWithInvalidRankingAndVersionPropertyTypeTest) {
+ //Given service properties with invalid type for ranking and version
+ celix_properties_t* props = celix_properties_create();
+ celix_properties_set(props, CELIX_FRAMEWORK_SERVICE_RANKING, "10"); //string, not long type
+ celix_properties_set(props, CELIX_FRAMEWORK_SERVICE_VERSION, "1.0.0"); //string, not celix_version_t* type
+
+ //When registering service
+ long svcId = celix_bundleContext_registerService(ctx, (void*)0x42, "TestService", props);
+
+ //Then the registration is successful
+ EXPECT_GE(svcId, 0);
+
+ //And the service properties types are corrected
+ celix_service_use_options_t opts;
+ opts.filter.serviceName = "TestService";
+ opts.useWithProperties = [](void* /*handle*/, void* /*svc*/, const celix_properties_t* props) {
+ auto propertyType = celix_properties_getType(props, CELIX_FRAMEWORK_SERVICE_RANKING);
+ EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_LONG, propertyType);
+
+ propertyType = celix_properties_getType(props, CELIX_FRAMEWORK_SERVICE_VERSION);
+ EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_VERSION, propertyType);
+ };
+ auto count = celix_bundleContext_useServicesWithOptions(ctx, &opts);
+ EXPECT_EQ(1, count);
+
+ celix_bundleContext_unregisterService(ctx, svcId);
+}
+
+TEST_F(CelixBundleContextServicesTestSuite, RegisterServiceWithInvalidRankingAndVersionValueTest) {
+ //Given service properties with invalid type for ranking and version
+ celix_properties_t* props = celix_properties_create();
+ celix_properties_set(props, CELIX_FRAMEWORK_SERVICE_RANKING, "foo"); //string, not convertable to long
+ celix_properties_set(props, CELIX_FRAMEWORK_SERVICE_VERSION, "bar"); //string, not convertable to version
+
+ //When registering service
+ long svcId = celix_bundleContext_registerService(ctx, (void*)0x42, "TestService", props);
+
+ //Then the registration is successful
+ EXPECT_GE(svcId, 0);
+
+ //And the service properties typer are kept as-is.
+ celix_service_use_options_t opts;
+ opts.filter.serviceName = "TestService";
+ opts.useWithProperties = [](void* /*handle*/, void* /*svc*/, const celix_properties_t* props) {
+ auto propertyType = celix_properties_getType(props, CELIX_FRAMEWORK_SERVICE_RANKING);
+ EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_STRING, propertyType);
+
+ propertyType = celix_properties_getType(props, CELIX_FRAMEWORK_SERVICE_VERSION);
+ EXPECT_EQ(CELIX_PROPERTIES_VALUE_TYPE_STRING, propertyType);
+ };
+ auto count = celix_bundleContext_useServicesWithOptions(ctx, &opts);
+ EXPECT_EQ(1, count);
+
+ celix_bundleContext_unregisterService(ctx, svcId);
+}
diff --git a/libs/framework/src/bundle_context.c b/libs/framework/src/bundle_context.c
index c64e2ca4..86ae2a2a 100644
--- a/libs/framework/src/bundle_context.c
+++ b/libs/framework/src/bundle_context.c
@@ -379,6 +379,52 @@ long celix_bundleContext_registerServiceFactory(celix_bundle_context_t *ctx, cel
return celix_bundleContext_registerServiceWithOptions(ctx, &opts);
}
+/**
+ * Corrects the service properties value types for the service ranking and service version to ensure
+ * that these properties are of the correct type.
+ * Print a warning log message if the service ranking or service version was not of the correct type.
+ */
+static celix_status_t celix_bundleContext_correctServicePropertiesValueTypes(celix_bundle_context_t* ctx,
+ celix_properties_t* props) {
+ celix_status_t status = CELIX_SUCCESS;
+ const celix_properties_entry_t* entry = celix_properties_getEntry(props, CELIX_FRAMEWORK_SERVICE_RANKING);
+ if (entry && entry->valueType == CELIX_PROPERTIES_VALUE_TYPE_STRING) {
+ fw_log(
+ ctx->framework->logger, CELIX_LOG_LEVEL_WARNING, "Service ranking is of type string, converting to long");
+ bool converted;
+ long ranking = celix_utils_convertStringToLong(entry->value, 0, &converted);
+ if (!converted) {
+ fw_log(ctx->framework->logger,
+ CELIX_LOG_LEVEL_WARNING,
+ "Cannot convert service ranking %s to long. Keeping %s value as string",
+ entry->value,
+ CELIX_FRAMEWORK_SERVICE_RANKING);
+ } else {
+ status = celix_properties_setLong(props, CELIX_FRAMEWORK_SERVICE_RANKING, ranking);
+ }
+ }
+
+ entry = celix_properties_getEntry(props, CELIX_FRAMEWORK_SERVICE_VERSION);
+ if (status == CELIX_SUCCESS && entry && entry->valueType == CELIX_PROPERTIES_VALUE_TYPE_STRING) {
+ fw_log(ctx->framework->logger,
+ CELIX_LOG_LEVEL_WARNING,
+ "Service version is of type string, converting to version");
+ celix_autoptr(celix_version_t) version = NULL;
+ status = celix_version_parse(entry->value, &version);
+ if (status == CELIX_ILLEGAL_ARGUMENT) {
+ fw_log(ctx->framework->logger,
+ CELIX_LOG_LEVEL_WARNING,
+ "Cannot parse service version %s. Keeping %s value as string",
+ entry->value,
+ CELIX_FRAMEWORK_SERVICE_VERSION);
+ status = CELIX_SUCCESS; //after warning, ignore parse error.
+ } else if (status == CELIX_SUCCESS) {
+ status = celix_properties_assignVersion(props, CELIX_FRAMEWORK_SERVICE_VERSION, celix_steal_ptr(version));
+ }
+ }
+ return status;
+}
+
static long celix_bundleContext_registerServiceWithOptionsInternal(bundle_context_t *ctx, const celix_service_registration_options_t *opts, bool async) {
bool valid = opts->serviceName != NULL && strncmp("", opts->serviceName, 1) != 0;
if (!valid) {
@@ -414,6 +460,13 @@ static long celix_bundleContext_registerServiceWithOptionsInternal(bundle_contex
}
}
+ celix_status_t correctionStatus = celix_bundleContext_correctServicePropertiesValueTypes(ctx, props);
+ if (correctionStatus != CELIX_SUCCESS) {
+ celix_framework_logTssErrors(ctx->framework->logger, CELIX_LOG_LEVEL_ERROR);
+ fw_log(ctx->framework->logger, CELIX_LOG_LEVEL_ERROR, "Cannot correct service properties value types");
+ return -1;
+ }
+
long svcId;
if (!async && celix_framework_isCurrentThreadTheEventLoop(ctx->framework)) {
/*