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 <[email protected]> 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)) { /*
