This is an automated email from the ASF dual-hosted git repository.

pnoltes pushed a commit to branch 
feature/685-update-container-config-properties-usage
in repository https://gitbox.apache.org/repos/asf/celix.git

commit 2c28348ee8a5d4c166a6b2635f620269c3af3a60
Author: Pepijn Noltes <[email protected]>
AuthorDate: Fri May 24 12:54:25 2024 +0200

    gh-685: Remove of old properties load and store
    
    Also introduces some additional error test to check
    the handling of properties load/save with an error
    return.
---
 .../gtest/src/rsa_client_server_tests.cc           |  42 ++--
 .../gtest/src/rsa_tests.cc                         |  25 +-
 cmake/cmake_celix/ContainerPackaging.cmake         |   9 +-
 .../BundleArchiveWithErrorInjectionTestSuite.cc    |  27 ++-
 .../src/CelixBundleCacheErrorInjectionTestSuite.cc |  42 +++-
 .../framework/gtest/src/CelixFrameworkTestSuite.cc |   3 +-
 libs/framework/src/bundle_archive.c                |  14 +-
 libs/framework/src/celix_bundle_cache.c            |   9 +-
 libs/framework/src/celix_launcher.c                | 176 +++++++-------
 .../error_injector/celix_properties/CMakeLists.txt |   2 +
 .../celix_properties/include/celix_properties_ei.h |   2 +
 .../celix_properties/src/celix_properties_ei.cc    |  22 ++
 libs/utils/gtest/src/CxxPropertiesTestSuite.cc     |  22 --
 libs/utils/gtest/src/FileUtilsTestSuite.cc         |  13 +-
 .../gtest/src/PropertiesErrorInjectionTestSuite.cc | 127 ----------
 libs/utils/gtest/src/PropertiesTestSuite.cc        |  68 ------
 libs/utils/include/celix/Properties.h              |  40 ----
 libs/utils/include/celix_properties.h              |  51 ----
 libs/utils/src/properties.c                        | 264 ---------------------
 19 files changed, 250 insertions(+), 708 deletions(-)

diff --git 
a/bundles/remote_services/remote_service_admin_dfi/gtest/src/rsa_client_server_tests.cc
 
b/bundles/remote_services/remote_service_admin_dfi/gtest/src/rsa_client_server_tests.cc
index 7e903e1e9..a5d241cf1 100644
--- 
a/bundles/remote_services/remote_service_admin_dfi/gtest/src/rsa_client_server_tests.cc
+++ 
b/bundles/remote_services/remote_service_admin_dfi/gtest/src/rsa_client_server_tests.cc
@@ -44,16 +44,16 @@ typedef struct rsa_dfi_exception_test_service {
     int (*func1)(void *handle);
 }rsa_dfi_exception_test_service_t;
 
-    static celix_framework_t *serverFramework = NULL;
-    static celix_bundle_context_t *serverContext = NULL;
+    static celix_framework_t *serverFramework = nullptr;
+    static celix_bundle_context_t *serverContext = nullptr;
 
-    static celix_framework_t *clientFramework = NULL;
-    static celix_bundle_context_t *clientContext = NULL;
+    static celix_framework_t *clientFramework = nullptr;
+    static celix_bundle_context_t *clientContext = nullptr;
 
-    static rsa_dfi_exception_test_service_t *exceptionTestService = NULL;
+    static rsa_dfi_exception_test_service_t *exceptionTestService = nullptr;
     static long exceptionTestSvcId = -1L;
-    static remote_interceptor_t *serverSvcInterceptor=NULL;
-    static remote_interceptor_t *clientSvcInterceptor=NULL;
+    static remote_interceptor_t *serverSvcInterceptor=nullptr;
+    static remote_interceptor_t *clientSvcInterceptor=nullptr;
     static long serverSvcInterceptorSvcId = -1L;
     static long clientSvcInterceptorSvcId = -1L;
     static bool clientInterceptorPreProxyCallRetval=true;
@@ -61,21 +61,23 @@ typedef struct rsa_dfi_exception_test_service {
 
     static void setupFm(bool useCurlShare) {
         //server
-        celix_properties_t *serverProps = 
celix_properties_load("server.properties");
-        ASSERT_TRUE(serverProps != NULL);
+        celix_properties_t *serverProps = nullptr;
+        ASSERT_EQ(CELIX_SUCCESS, celix_properties_load2("server.properties", 
0, &serverProps));
+        ASSERT_TRUE(serverProps != nullptr);
         serverFramework = celix_frameworkFactory_createFramework(serverProps);
-        ASSERT_TRUE(serverFramework != NULL);
+        ASSERT_TRUE(serverFramework != nullptr);
         serverContext = celix_framework_getFrameworkContext(serverFramework);
-        ASSERT_TRUE(serverContext != NULL);
+        ASSERT_TRUE(serverContext != nullptr);
 
         //client
-        celix_properties_t *clientProperties = 
celix_properties_load("client.properties");
+        celix_properties_t *clientProperties = nullptr;
+        ASSERT_EQ(CELIX_SUCCESS, celix_properties_load2("client.properties", 
0, &clientProperties));
         celix_properties_setBool(clientProperties, 
"RSA_DFI_USE_CURL_SHARE_HANDLE", useCurlShare);
-        ASSERT_TRUE(clientProperties != NULL);
+        ASSERT_TRUE(clientProperties != nullptr);
         clientFramework = 
celix_frameworkFactory_createFramework(clientProperties);
-        ASSERT_TRUE(clientFramework != NULL);
+        ASSERT_TRUE(clientFramework != nullptr);
         clientContext = celix_framework_getFrameworkContext(clientFramework);
-        ASSERT_TRUE(clientContext != NULL);
+        ASSERT_TRUE(clientContext != nullptr);
     }
 
     static void teardownFm(void) {
@@ -92,7 +94,7 @@ typedef struct rsa_dfi_exception_test_service {
         celix_properties_set(properties, 
CELIX_RSA_SERVICE_EXPORTED_INTERFACES, RSA_DIF_EXCEPTION_TEST_SERVICE);
         celix_properties_set(properties, CELIX_RSA_SERVICE_EXPORTED_CONFIGS, 
"org.amdatu.remote.admin.http");
         exceptionTestService = (rsa_dfi_exception_test_service_t 
*)calloc(1,sizeof(*exceptionTestService));
-        exceptionTestService->handle = NULL;
+        exceptionTestService->handle = nullptr;
         exceptionTestService->func1 = rsaDfi_excepTestFunc1;
         exceptionTestSvcId = 
celix_bundleContext_registerService(serverContext, exceptionTestService, 
RSA_DIF_EXCEPTION_TEST_SERVICE, properties);
     }
@@ -137,7 +139,7 @@ typedef struct rsa_dfi_exception_test_service {
     static void registerInterceptorService(void) {
         svcInterceptorPreExportCallRetval = true;
         serverSvcInterceptor = (remote_interceptor_t 
*)calloc(1,sizeof(*serverSvcInterceptor));
-        serverSvcInterceptor->handle = NULL;
+        serverSvcInterceptor->handle = nullptr;
         serverSvcInterceptor->preProxyCall = 
serverServiceInterceptor_preProxyCall;
         serverSvcInterceptor->postProxyCall = 
serverServiceInterceptor_postProxyCall;
         serverSvcInterceptor->preExportCall = 
serverServiceInterceptor_preExportCall;
@@ -153,7 +155,7 @@ typedef struct rsa_dfi_exception_test_service {
 
         clientInterceptorPreProxyCallRetval = true;
         clientSvcInterceptor = (remote_interceptor_t 
*)calloc(1,sizeof(*clientSvcInterceptor));
-        clientSvcInterceptor->handle = NULL;
+        clientSvcInterceptor->handle = nullptr;
         clientSvcInterceptor->preProxyCall = 
clientServiceInterceptor_preProxyCall;
         clientSvcInterceptor->postProxyCall = 
clientServiceInterceptor_postProxyCall;
         clientSvcInterceptor->preExportCall = 
clientServiceInterceptor_preExportCall;
@@ -472,8 +474,8 @@ public:
 
         char calcIdStr[32] = {0};
         snprintf(calcIdStr, 32, "%li", calcId);
-        celix_array_list_t *svcRegistrations = NULL;
-        auto status = serverRsaSvc->exportService(serverRsaSvc->admin, 
calcIdStr, NULL, &svcRegistrations);
+        celix_array_list_t *svcRegistrations = nullptr;
+        auto status = serverRsaSvc->exportService(serverRsaSvc->admin, 
calcIdStr, nullptr, &svcRegistrations);
         ASSERT_EQ(CELIX_SUCCESS, status);
         ASSERT_EQ(1, celix_arrayList_size(svcRegistrations));
         export_registration_t *exportedReg = 
static_cast<export_registration_t*>(celix_arrayList_get(svcRegistrations, 0));
diff --git 
a/bundles/remote_services/remote_service_admin_dfi/gtest/src/rsa_tests.cc 
b/bundles/remote_services/remote_service_admin_dfi/gtest/src/rsa_tests.cc
index 3195b4630..8d8fef378 100644
--- a/bundles/remote_services/remote_service_admin_dfi/gtest/src/rsa_tests.cc
+++ b/bundles/remote_services/remote_service_admin_dfi/gtest/src/rsa_tests.cc
@@ -33,18 +33,19 @@ extern "C" {
 
 #define TST_CONFIGURATION_TYPE "org.amdatu.remote.admin.http"
 
-    static celix_framework_t *framework = NULL;
-    static celix_bundle_context_t *context = NULL;
+    static celix_framework_t *framework = nullptr;
+    static celix_bundle_context_t *context = nullptr;
 
     long calcSvcId = -1L;
 
     static void setupFm(void) {
-        celix_properties_t *fwProperties = 
celix_properties_load("config.properties");
-        ASSERT_TRUE(fwProperties != NULL);
+        celix_properties_t *fwProperties = nullptr;
+        EXPECT_EQ(CELIX_SUCCESS, celix_properties_load2("config.properties", 
0, &fwProperties));
+        ASSERT_TRUE(fwProperties != nullptr);
         framework = celix_frameworkFactory_createFramework(fwProperties);
-        ASSERT_TRUE(framework != NULL);
+        ASSERT_TRUE(framework != nullptr);
         context = celix_framework_getFrameworkContext(framework);
-        ASSERT_TRUE(context != NULL);
+        ASSERT_TRUE(context != nullptr);
 
 
         calcSvcId = celix_bundleContext_findService(context, 
CALCULATOR_SERVICE);
@@ -87,8 +88,8 @@ extern "C" {
         char strSvcId[64];
         snprintf(strSvcId, 64, "%li", calcSvcId);
 
-        celix_array_list_t *svcRegistration = NULL;
-        int rc = rsa->exportService(rsa->admin, strSvcId, NULL, 
&svcRegistration);
+        celix_array_list_t *svcRegistration = nullptr;
+        int rc = rsa->exportService(rsa->admin, strSvcId, nullptr, 
&svcRegistration);
         ASSERT_EQ(CELIX_SUCCESS, rc);
 
         ASSERT_EQ(1, celix_arrayList_size(svcRegistration));
@@ -155,7 +156,7 @@ extern "C" {
     }
 
     static void testBundles(void) {
-        celix_array_list_t* bundles = NULL;
+        celix_array_list_t* bundles = nullptr;
 
         int rc = bundleContext_getBundles(context, &bundles);
         ASSERT_EQ(0, rc);
@@ -165,9 +166,9 @@ extern "C" {
         int size = arrayList_size(bundles);
         int i;
         for (i = 0; i < size; i += 1) {
-            celix_bundle_t *bundle = NULL;
-            module_pt module = NULL;
-            char *name = NULL;
+            celix_bundle_t *bundle = nullptr;
+            module_pt module = nullptr;
+            char *name = nullptr;
 
             bundle = (celix_bundle_t *) arrayList_get(bundles, i);
             bundle_getCurrentModule(bundle, &module);
diff --git a/cmake/cmake_celix/ContainerPackaging.cmake 
b/cmake/cmake_celix/ContainerPackaging.cmake
index 78e799eb9..382a2bd16 100644
--- a/cmake/cmake_celix/ContainerPackaging.cmake
+++ b/cmake/cmake_celix/ContainerPackaging.cmake
@@ -221,6 +221,8 @@ function(add_celix_container)
         file(GENERATE
                 OUTPUT "${STAGE1_LAUNCHER_SRC}"
                 CONTENT "#include <celix_launcher.h>
+#include <celix_err.h>
+
 int main(int argc, char *argv[]) {
     const char * config = \"\\
 CELIX_CONTAINER_NAME=$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_NAME>\\n\\
@@ -236,7 +238,12 @@ 
$<$<BOOL:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_BUNDLES_INSTALL>>:CELIX
 
$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_EMBEDDED_PROPERTIES>,\\n\\
 >\";
 
-    celix_properties_t *embeddedProps = 
celix_properties_loadFromString(config);
+    celix_properties_t *embeddedProps;
+    celix_status_t status = celix_properties_loadFromString2(config, 0, 
&embeddedProps);
+    if (status != CELIX_SUCCESS) {
+        celix_err_printErrors(stderr, \"Error creating embedded properties.\", 
NULL);
+        return -1;
+    }
     return celixLauncher_launchAndWaitForShutdown(argc, argv, embeddedProps);
 }
 "
diff --git 
a/libs/framework/gtest/src/BundleArchiveWithErrorInjectionTestSuite.cc 
b/libs/framework/gtest/src/BundleArchiveWithErrorInjectionTestSuite.cc
index 03100ddff..b7d1e5568 100644
--- a/libs/framework/gtest/src/BundleArchiveWithErrorInjectionTestSuite.cc
+++ b/libs/framework/gtest/src/BundleArchiveWithErrorInjectionTestSuite.cc
@@ -57,6 +57,7 @@ class BundleArchiveWithErrorInjectionTestSuite : public 
::testing::Test {
 
     void teardownErrorInjectors() {
         celix_ei_expect_celix_properties_create(nullptr, 0, nullptr);
+        celix_ei_expect_celix_properties_save(nullptr, 0, CELIX_SUCCESS);
         celix_ei_expect_asprintf(nullptr, 0, 0);
         celix_ei_expect_calloc(nullptr, 0, nullptr);
         celix_ei_expect_malloc(nullptr, 0, nullptr);
@@ -257,4 +258,28 @@ TEST_F(CelixBundleArchiveErrorInjectionTestSuite, 
ArchiveCreateErrorTest) {
     teardownErrorInjectors();
 
     EXPECT_EQ(CELIX_SUCCESS, celix_bundleCache_destroy(cache));
-}
\ No newline at end of file
+}
+
+TEST_F(CelixBundleArchiveErrorInjectionTestSuite, 
StoreBundleStatePropertiesErrorTest) {
+    // Given a framework
+    auto fw = celix::createFramework({
+        {CELIX_FRAMEWORK_CLEAN_CACHE_DIR_ON_CREATE, "true"},
+    });
+    auto ctx = fw->getFrameworkBundleContext();
+
+    // When an error is prepped for celix_properties_save
+    
celix_ei_expect_celix_properties_save((void*)celix_bundleCache_findBundleIdForLocation,
 1, CELIX_FILE_IO_EXCEPTION);
+
+    // When the bundle install, a bundle id is returned (async bundle install)
+    long bndId = ctx->installBundle(SIMPLE_TEST_BUNDLE1_LOCATION);
+    EXPECT_GE(bndId, 0);
+
+    // Then the bundle is not successfully installed
+
+    celix_bundleContext_useBundle(
+        ctx->getCBundleContext(), bndId, nullptr, [](void* /*handle*/, const 
celix_bundle_t* bnd) {
+            auto status = celix_bundle_getState(bnd);
+            // TODO fixme, bundle is installed and active, this is not correct
+            EXPECT_EQ(CELIX_BUNDLE_EVENT_INSTALLED, status);
+        });
+}
diff --git 
a/libs/framework/gtest/src/CelixBundleCacheErrorInjectionTestSuite.cc 
b/libs/framework/gtest/src/CelixBundleCacheErrorInjectionTestSuite.cc
index 2082013e4..732119441 100644
--- a/libs/framework/gtest/src/CelixBundleCacheErrorInjectionTestSuite.cc
+++ b/libs/framework/gtest/src/CelixBundleCacheErrorInjectionTestSuite.cc
@@ -21,6 +21,7 @@
 
 #include <string>
 
+#include "celix/FrameworkFactory.h"
 #include "celix_bundle_cache.h"
 #include "celix_constants.h"
 #include "celix_file_utils.h"
@@ -28,6 +29,7 @@
 #include "celix_log.h"
 #include "celix_properties.h"
 #include "celix_utils_ei.h"
+#include "celix_properties_ei.h"
 
 #include "asprintf_ei.h"
 #include "bundle_archive_private.h"
@@ -54,6 +56,7 @@ class CelixBundleCacheErrorInjectionTestSuite : public 
::testing::Test {
         celix_ei_expect_celix_stringHashMap_create(nullptr, 0, nullptr);
         celix_ei_expect_malloc(nullptr, 0, nullptr);
         celix_ei_expect_calloc(nullptr, 0, nullptr);
+        celix_ei_expect_celix_properties_load2(nullptr, 0, CELIX_SUCCESS);
         celix_frameworkLogger_destroy(fw.logger);
         celix_properties_destroy(fw.configurationMap);
     }
@@ -163,4 +166,41 @@ TEST_F(CelixBundleCacheErrorInjectionTestSuite, 
CreateBundleArchivesCacheErrorTe
     
celix_ei_expect_celix_utils_writeOrCreateString((void*)celix_bundleCache_createArchive,
 0, nullptr);
     EXPECT_EQ(CELIX_ENOMEM, celix_bundleCache_createBundleArchivesCache(&fw, 
true));
     EXPECT_EQ(CELIX_SUCCESS, celix_bundleCache_destroy(cache));
-}
\ No newline at end of file
+}
+
+TEST_F(CelixBundleCacheErrorInjectionTestSuite, 
LoadBundleStatePropertiesErrorTest) {
+    // Given a celix framework
+    auto fw = celix::createFramework(
+        {{"CELIX_LOGGING_DEFAULT_ACTIVE_LOG_LEVEL", "trace"}, 
{CELIX_FRAMEWORK_CLEAN_CACHE_DIR_ON_CREATE, "true"}});
+    auto ctx = fw->getFrameworkBundleContext();
+
+    // And an installed bundle (with a bundle cache)
+    long bndId = ctx->installBundle(SIMPLE_TEST_BUNDLE1_LOCATION);
+    EXPECT_GT(bndId, -1);
+
+    // When framework is stopped
+    ctx.reset();
+    fw.reset();
+
+    // And a new framework is created
+    fw = celix::createFramework(
+        {{"CELIX_LOGGING_DEFAULT_ACTIVE_LOG_LEVEL", "trace"}, 
{CELIX_FRAMEWORK_CLEAN_CACHE_DIR_ON_CREATE, "false"}});
+    ctx = fw->getFrameworkBundleContext();
+
+    // When the bundle is uninstalled
+    celix_bundleContext_uninstallBundle(ctx->getCBundleContext(), bndId);
+
+    // And a celix_properties_load error is injected
+    celix_ei_expect_celix_properties_load2(
+        (void*)celix_bundleCache_findBundleIdForLocation, 1, 
CELIX_FILE_IO_EXCEPTION);
+
+    // Then installing the bundle will fail
+    bndId = ctx->installBundle(SIMPLE_TEST_BUNDLE1_LOCATION);
+    EXPECT_GT(bndId, -1); //async install, so bundle id is returned
+    celix_bundleContext_useBundle(
+        ctx->getCBundleContext(), bndId, nullptr, [](void* /*handle*/, const 
celix_bundle_t* bnd) {
+            auto status = celix_bundle_getState(bnd);
+            // TODO fixme, bundle is installed and active, this is not correct
+            EXPECT_EQ(CELIX_BUNDLE_EVENT_INSTALLED, status);
+        });
+}
diff --git a/libs/framework/gtest/src/CelixFrameworkTestSuite.cc 
b/libs/framework/gtest/src/CelixFrameworkTestSuite.cc
index 3eae055c6..5af8f391f 100644
--- a/libs/framework/gtest/src/CelixFrameworkTestSuite.cc
+++ b/libs/framework/gtest/src/CelixFrameworkTestSuite.cc
@@ -324,7 +324,8 @@ TEST_F(FrameworkFactoryTestSuite, 
LaunchFrameworkWithConfigTest) {
      * the specified bundles will be installed and - if needed - started.
      */
 
-    auto* config = 
celix_properties_load(INSTALL_AND_START_BUNDLES_CONFIG_PROPERTIES_FILE);
+    celix_properties_t* config = nullptr;
+    ASSERT_EQ(CELIX_SUCCESS, 
celix_properties_load2(INSTALL_AND_START_BUNDLES_CONFIG_PROPERTIES_FILE, 0, 
&config));
     ASSERT_TRUE(config != nullptr);
 
     framework_t* fw = celix_frameworkFactory_createFramework(config);
diff --git a/libs/framework/src/bundle_archive.c 
b/libs/framework/src/bundle_archive.c
index 688567345..b3cdd5e83 100644
--- a/libs/framework/src/bundle_archive.c
+++ b/libs/framework/src/bundle_archive.c
@@ -62,9 +62,9 @@ struct bundleArchive {
 
 static celix_status_t 
celix_bundleArchive_storeBundleStateProperties(bundle_archive_pt archive) {
     bool needUpdate = false;
-    celix_properties_t* bundleStateProperties = NULL;
-    bundleStateProperties = 
celix_properties_load(archive->savedBundleStatePropertiesPath);
-    if (bundleStateProperties == NULL) {
+    celix_properties_t* bundleStateProperties;
+    celix_status_t status = 
celix_properties_load2(archive->savedBundleStatePropertiesPath, 0, 
&bundleStateProperties);
+    if (status != CELIX_SUCCESS) {
         celix_framework_logTssErrors(archive->fw->logger, 
CELIX_LOG_LEVEL_ERROR);
         bundleStateProperties = celix_properties_create();
     }
@@ -91,8 +91,12 @@ static celix_status_t 
celix_bundleArchive_storeBundleStateProperties(bundle_arch
 
     //save bundle cache state properties
     if (needUpdate) {
-        celix_properties_store(bundleStateProperties, 
archive->savedBundleStatePropertiesPath,
-                               "Bundle State Properties");
+        status = celix_properties_save(
+            bundleStateProperties, archive->savedBundleStatePropertiesPath, 
CELIX_PROPERTIES_ENCODE_PRETTY);
+        if (status != CELIX_SUCCESS) {
+            celix_framework_logTssErrors(archive->fw->logger, 
CELIX_LOG_LEVEL_ERROR);
+            return status;
+        }
     }
     celix_properties_destroy(bundleStateProperties);
     return CELIX_SUCCESS;
diff --git a/libs/framework/src/celix_bundle_cache.c 
b/libs/framework/src/celix_bundle_cache.c
index d1917e2d2..770d83b33 100644
--- a/libs/framework/src/celix_bundle_cache.c
+++ b/libs/framework/src/celix_bundle_cache.c
@@ -235,7 +235,14 @@ static void 
celix_bundleCache_updateIdForLocationLookupMap(celix_bundle_cache_t*
                                                                       
"%s/%s/%s", cache->cacheDir, dent->d_name,
                                                                       
CELIX_BUNDLE_ARCHIVE_STATE_PROPERTIES_FILE_NAME);
         if (celix_utils_fileExists(bundleStateProperties)) {
-            celix_properties_t* props = 
celix_properties_load(bundleStateProperties);
+            celix_properties_t* props;
+            celix_status_t status = 
celix_properties_load2(bundleStateProperties, 0, &props); //validate the file 
(and ignore the result
+            if (status != CELIX_SUCCESS) {
+                    fw_logCode(cache->fw->logger, CELIX_LOG_LEVEL_ERROR, 
status,
+                               "Cannot load bundle state properties from %s", 
bundleStateProperties);
+                    celix_framework_logTssErrors(cache->fw->logger, 
CELIX_LOG_LEVEL_ERROR);
+                    continue;
+            }
             const char* visitLoc = celix_properties_get(props, 
CELIX_BUNDLE_ARCHIVE_LOCATION_PROPERTY_NAME, NULL);
             long bndId = celix_properties_getAsLong(props, 
CELIX_BUNDLE_ARCHIVE_BUNDLE_ID_PROPERTY_NAME, -1);
             if (visitLoc != NULL && bndId >= 0) {
diff --git a/libs/framework/src/celix_launcher.c 
b/libs/framework/src/celix_launcher.c
index 8cf32a6f3..e3a72e29c 100644
--- a/libs/framework/src/celix_launcher.c
+++ b/libs/framework/src/celix_launcher.c
@@ -17,32 +17,33 @@
  * under the License.
  */
 
-
 #include "celix_launcher.h"
 
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
 #include <libgen.h>
 #include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
 
 #ifndef CELIX_NO_CURLINIT
 #include <curl/curl.h>
 #endif
 
-#include "framework.h"
-#include "celix_framework_factory.h"
 #include "celix_constants.h"
+#include "celix_framework_factory.h"
 #include "celix_framework_utils.h"
+#include "celix_err.h"
 
 static void celixLauncher_shutdownFramework(int signal);
 static void celixLauncher_ignore(int signal);
-static int celixLauncher_launchWithConfigAndProps(const char *configFile, 
celix_framework_t* *framework, celix_properties_t* packedConfig);
-static void celixLauncher_combineProperties(celix_properties_t *original, 
const celix_properties_t *append);
+static int celixLauncher_launchWithConfigAndProps(const char* configFile,
+                                                  celix_framework_t** 
framework,
+                                                  celix_properties_t* 
packedConfig);
+static void celixLauncher_combineProperties(celix_properties_t* original, 
const celix_properties_t* append);
 static celix_properties_t* celixLauncher_createConfig(const char* configFile, 
celix_properties_t* embeddedProperties);
 
 static void celixLauncher_printUsage(char* progName);
-static void celixLauncher_printProperties(celix_properties_t *embeddedProps, 
const char* configFile);
+static void celixLauncher_printProperties(celix_properties_t* embeddedProps, 
const char* configFile);
 static int celixLauncher_createBundleCache(celix_properties_t* 
embeddedProperties, const char* configFile);
 
 #define DEFAULT_CONFIG_FILE "config.properties"
@@ -50,11 +51,9 @@ static int 
celixLauncher_createBundleCache(celix_properties_t* embeddedPropertie
 #define CELIX_LAUNCHER_OK_EXIT_CODE 0
 #define CELIX_LAUNCHER_ERROR_EXIT_CODE 1
 
-static framework_t *g_fw = NULL;
-
+static framework_t* g_fw = NULL;
 
-
-int celixLauncher_launchAndWaitForShutdown(int argc, char *argv[], 
celix_properties_t* packedConfig) {
+int celixLauncher_launchAndWaitForShutdown(int argc, char* argv[], 
celix_properties_t* packedConfig) {
     celix_framework_t* framework = NULL;
     int rc = celixLauncher_launchWithArgv(argc, argv, packedConfig, 
&framework);
     if (rc == 0 && framework != NULL) {
@@ -131,43 +130,45 @@ int celixLauncher_launchWithArgv(int argc,
 }
 
 static void celixLauncher_shutdownFramework(int signal) {
-       if (g_fw != NULL) {
-               celixLauncher_stop(g_fw); //NOTE main thread will destroy
-       }
+    if (g_fw != NULL) {
+        celixLauncher_stop(g_fw); // NOTE main thread will destroy
+    }
 }
 
 static void celixLauncher_ignore(int signal) {
-       //ignoring for signal SIGUSR1, SIGUSR2. Can be used on threads
+    // ignoring for signal SIGUSR1, SIGUSR2. Can be used on threads
 }
 
-int celixLauncher_launch(const char *configFile, celix_framework_t* 
*framework) {
-       return celixLauncher_launchWithConfigAndProps(configFile, framework, 
NULL);
+int celixLauncher_launch(const char* configFile, celix_framework_t** 
framework) {
+    return celixLauncher_launchWithConfigAndProps(configFile, framework, NULL);
 }
 
-static int celixLauncher_launchWithConfigAndProps(const char *configFile, 
celix_framework_t** framework, celix_properties_t* packedConfig) {
+static int celixLauncher_launchWithConfigAndProps(const char* configFile,
+                                                  celix_framework_t** 
framework,
+                                                  celix_properties_t* 
packedConfig) {
     celix_properties_t* config = celixLauncher_createConfig(configFile, 
packedConfig);
+    if (!config) {
+        return CELIX_LAUNCHER_ERROR_EXIT_CODE;
+    }
     return celixLauncher_launchWithProperties(config, framework);
 }
 
-
 int celixLauncher_launchWithProperties(celix_properties_t* config, 
celix_framework_t** framework) {
 #ifndef CELIX_NO_CURLINIT
-       // Before doing anything else, let's setup Curl
-       curl_global_init(CURL_GLOBAL_ALL);
+    // Before doing anything else, let's setup Curl
+    curl_global_init(CURL_GLOBAL_ALL);
 #endif
-       *framework = celix_frameworkFactory_createFramework(config);
-       return *framework != NULL ? CELIX_LAUNCHER_OK_EXIT_CODE : 
CELIX_LAUNCHER_ERROR_EXIT_CODE;
+    *framework = celix_frameworkFactory_createFramework(config);
+    return *framework != NULL ? CELIX_LAUNCHER_OK_EXIT_CODE : 
CELIX_LAUNCHER_ERROR_EXIT_CODE;
 }
 
-void celixLauncher_waitForShutdown(celix_framework_t* framework) {
-    celix_framework_waitForStop(framework);
-}
+void celixLauncher_waitForShutdown(celix_framework_t* framework) { 
celix_framework_waitForStop(framework); }
 
 void celixLauncher_destroy(celix_framework_t* framework) {
     celix_frameworkFactory_destroyFramework(framework);
 #ifndef CELIX_NO_CURLINIT
-       // Cleanup Curl
-       curl_global_cleanup();
+    // Cleanup Curl
+    curl_global_cleanup();
 #endif
 }
 
@@ -175,7 +176,6 @@ void celixLauncher_stop(celix_framework_t* framework) {
     celix_framework_stopBundle(framework, CELIX_FRAMEWORK_BUNDLE_ID);
 }
 
-
 static void celixLauncher_printUsage(char* progName) {
     printf("Usage:\n  %s [-h|-p] [path/to/runtime/config.properties]\n", 
basename(progName));
     printf("Options:\n");
@@ -186,67 +186,69 @@ static void celixLauncher_printUsage(char* progName) {
     printf("\n");
 }
 
-static void celixLauncher_printProperties(celix_properties_t *embeddedProps, 
const char *configFile) {
-       celix_properties_t *keys = celix_properties_create(); //only to store 
the keys
+static void celixLauncher_printProperties(celix_properties_t* embeddedProps, 
const char* configFile) {
+    celix_properties_t* keys = celix_properties_create(); // only to store the 
keys
 
-       printf("Embedded properties:\n");
-       if (embeddedProps == NULL || celix_properties_size(embeddedProps) == 0) 
{
-               printf("|- Empty!\n");
-       } else {
+    printf("Embedded properties:\n");
+    if (embeddedProps == NULL || celix_properties_size(embeddedProps) == 0) {
+        printf("|- Empty!\n");
+    } else {
         CELIX_PROPERTIES_ITERATE(embeddedProps, visit) {
-                       printf("|- %s=%s\n", visit.key, visit.entry.value);
+            printf("|- %s=%s\n", visit.key, visit.entry.value);
             celix_properties_set(keys, visit.key, NULL);
         }
-       }
-       printf("\n");
-
-       celix_properties_t *runtimeProps = NULL;
-       if (configFile != NULL) {
-        runtimeProps = celix_properties_load(configFile);
-       }
-       printf("Runtime properties (input %s):\n", configFile);
-       if (runtimeProps == NULL || celix_properties_size(runtimeProps) == 0) {
-               printf("|- Empty!\n");
-       } else {
+    }
+    printf("\n");
+
+    celix_properties_t* runtimeProps = NULL;
+    if (configFile != NULL) {
+        celix_status_t status = celix_properties_load2(configFile, 0, 
&runtimeProps);
+        if (status != CELIX_SUCCESS) {
+            celix_err_printErrors(stderr, "Error loading config file.", NULL);
+        }
+    }
+    printf("Runtime properties (input %s):\n", configFile);
+    if (runtimeProps == NULL || celix_properties_size(runtimeProps) == 0) {
+        printf("|- Empty!\n");
+    } else {
         CELIX_PROPERTIES_ITERATE(runtimeProps, visit) {
-                       printf("|- %s=%s\n", visit.key, visit.entry.value);
+            printf("|- %s=%s\n", visit.key, visit.entry.value);
             celix_properties_set(keys, visit.key, NULL);
         }
-       }
+    }
     printf("\n");
 
-       //combined result
-       printf("Resolved (env, runtime and embedded) properties:\n");
-       if (celix_properties_size(keys) == 0) {
-               printf("|- Empty!\n");
-       } else {
+    // combined result
+    printf("Resolved (env, runtime and embedded) properties:\n");
+    if (celix_properties_size(keys) == 0) {
+        printf("|- Empty!\n");
+    } else {
         CELIX_PROPERTIES_ITERATE(keys, visit) {
-                       const char *valEm = celix_properties_get(embeddedProps, 
visit.key, NULL);
-            const char *valRt = celix_properties_get(runtimeProps, visit.key, 
NULL);
-            const char *envVal = getenv(visit.key);
-            const char *val = envVal != NULL ? envVal : valRt != NULL ? valRt 
: valEm;
-            const char *source = envVal != NULL ? "environment" : valRt != 
NULL ? "runtime" : "embedded";
-                       printf("|- %s=%s (source %s)\n", visit.key, val, 
source);
-               }
-       }
+            const char* valEm = celix_properties_get(embeddedProps, visit.key, 
NULL);
+            const char* valRt = celix_properties_get(runtimeProps, visit.key, 
NULL);
+            const char* envVal = getenv(visit.key);
+            const char* val = envVal != NULL ? envVal : valRt != NULL ? valRt 
: valEm;
+            const char* source = envVal != NULL ? "environment" : valRt != 
NULL ? "runtime" : "embedded";
+            printf("|- %s=%s (source %s)\n", visit.key, val, source);
+        }
+    }
     printf("\n");
 
-       if (runtimeProps != NULL) {
-               celix_properties_destroy(runtimeProps);
-       }
-       celix_properties_destroy(keys);
+    if (runtimeProps != NULL) {
+        celix_properties_destroy(runtimeProps);
+    }
+    celix_properties_destroy(keys);
 }
 
 static int celixLauncher_createBundleCache(celix_properties_t* 
embeddedProperties, const char* configFile) {
-    celix_framework_t* fw = NULL;
     celix_properties_t* config = celixLauncher_createConfig(configFile, 
embeddedProperties);
-    celix_status_t status = framework_create(&fw, config);
-    if (status != CELIX_SUCCESS) {
+    celix_framework_t* fw = celix_frameworkFactory_createFramework(config);
+    if (!fw) {
         fprintf(stderr, "Failed to create framework for bundle cache 
creation\n");
         return CELIX_LAUNCHER_ERROR_EXIT_CODE;
     }
-    status = celix_framework_utils_createBundleArchivesCache(fw);
-    (void)framework_destroy(fw);
+    celix_status_t status = 
celix_framework_utils_createBundleArchivesCache(fw);
+    celix_frameworkFactory_destroyFramework(fw);
     if (status != CELIX_SUCCESS) {
         fprintf(stderr, "Failed to create bundle cache\n");
         return CELIX_LAUNCHER_ERROR_EXIT_CODE;
@@ -254,28 +256,24 @@ static int 
celixLauncher_createBundleCache(celix_properties_t* embeddedPropertie
     return CELIX_LAUNCHER_OK_EXIT_CODE;
 }
 
-static void celixLauncher_combineProperties(celix_properties_t *original, 
const celix_properties_t *append) {
-       if (original != NULL && append != NULL) {
-        CELIX_PROPERTIES_ITERATE(append, visit) {
-                       celix_properties_setEntry(original, visit.key, 
&visit.entry);
-               }
-       }
+static void celixLauncher_combineProperties(celix_properties_t* original, 
const celix_properties_t* append) {
+    if (original != NULL && append != NULL) {
+        CELIX_PROPERTIES_ITERATE(append, visit) { 
celix_properties_setEntry(original, visit.key, &visit.entry); }
+    }
 }
 
 static celix_properties_t* celixLauncher_createConfig(const char* configFile, 
celix_properties_t* embeddedProperties) {
-    if (embeddedProperties == NULL) {
+    if (!embeddedProperties) {
         embeddedProperties = celix_properties_create();
     }
 
-    FILE *config = fopen(configFile, "r");
-    if (config != NULL) {
-        celix_properties_t *configProps = 
celix_properties_loadWithStream(config);
-        fclose(config);
-        if (configProps != NULL) {
-            celixLauncher_combineProperties(embeddedProperties, configProps);
-            celix_properties_destroy(configProps);
-        }
+    celix_autoptr(celix_properties_t) configProperties = NULL;
+    celix_status_t status = celix_properties_load2(configFile, 0, 
&configProperties);
+    if (status != CELIX_SUCCESS) {
+        fprintf(stderr, "Error loading config file %s\n", configFile);
+        celix_properties_destroy(embeddedProperties);
+        return NULL;
     }
-
+    celixLauncher_combineProperties(embeddedProperties, configProperties);
     return embeddedProperties;
 }
diff --git a/libs/utils/error_injector/celix_properties/CMakeLists.txt 
b/libs/utils/error_injector/celix_properties/CMakeLists.txt
index 7f65cd902..717cb50a5 100644
--- a/libs/utils/error_injector/celix_properties/CMakeLists.txt
+++ b/libs/utils/error_injector/celix_properties/CMakeLists.txt
@@ -26,5 +26,7 @@ target_link_options(properties_ei INTERFACE
         LINKER:--wrap,celix_properties_set
         LINKER:--wrap,celix_properties_setLong
         LINKER:--wrap,celix_properties_setVersion
+        LINKER:--wrap,celix_properties_save
+        LINKER:--wrap,celix_properties_load2
         )
 add_library(Celix::properties_ei ALIAS properties_ei)
diff --git 
a/libs/utils/error_injector/celix_properties/include/celix_properties_ei.h 
b/libs/utils/error_injector/celix_properties/include/celix_properties_ei.h
index ad5f7184d..c4076ec46 100644
--- a/libs/utils/error_injector/celix_properties/include/celix_properties_ei.h
+++ b/libs/utils/error_injector/celix_properties/include/celix_properties_ei.h
@@ -31,6 +31,8 @@ CELIX_EI_DECLARE(celix_properties_copy, celix_properties_t*);
 CELIX_EI_DECLARE(celix_properties_set, celix_status_t);
 CELIX_EI_DECLARE(celix_properties_setLong, celix_status_t);
 CELIX_EI_DECLARE(celix_properties_setVersion, celix_status_t);
+CELIX_EI_DECLARE(celix_properties_save, celix_status_t);
+CELIX_EI_DECLARE(celix_properties_load2, celix_status_t);
 
 #ifdef __cplusplus
 }
diff --git 
a/libs/utils/error_injector/celix_properties/src/celix_properties_ei.cc 
b/libs/utils/error_injector/celix_properties/src/celix_properties_ei.cc
index 1c9ace21c..1f2eeba60 100644
--- a/libs/utils/error_injector/celix_properties/src/celix_properties_ei.cc
+++ b/libs/utils/error_injector/celix_properties/src/celix_properties_ei.cc
@@ -55,4 +55,26 @@ celix_status_t 
__wrap_celix_properties_setVersion(celix_properties_t *properties
     return __real_celix_properties_setVersion(properties, key, version);
 }
 
+celix_status_t
+__real_celix_properties_save(const celix_properties_t* properties, const char* 
filename, int encodeFlags);
+CELIX_EI_DEFINE(celix_properties_save, celix_status_t)
+celix_status_t
+__wrap_celix_properties_save(const celix_properties_t* properties, const char* 
filename, int encodeFlags) {
+    CELIX_EI_IMPL(celix_properties_save);
+    return __real_celix_properties_save(properties, filename, encodeFlags);
+}
+
+celix_status_t
+__real_celix_properties_load2(const char* filename,
+                                    int decodeFlags,
+                                    celix_properties_t** out);
+CELIX_EI_DEFINE(celix_properties_load2, celix_status_t)
+celix_status_t
+__wrap_celix_properties_load2(const char* filename,
+                              int decodeFlags,
+                              celix_properties_t** out) {
+    CELIX_EI_IMPL(celix_properties_load2);
+    return __real_celix_properties_load2(filename, decodeFlags, out);
+}
+
 }
\ No newline at end of file
diff --git a/libs/utils/gtest/src/CxxPropertiesTestSuite.cc 
b/libs/utils/gtest/src/CxxPropertiesTestSuite.cc
index 1e65bb4f7..c95986743 100644
--- a/libs/utils/gtest/src/CxxPropertiesTestSuite.cc
+++ b/libs/utils/gtest/src/CxxPropertiesTestSuite.cc
@@ -325,25 +325,3 @@ TEST_F(CxxPropertiesTestSuite, ArrayListTest) {
     EXPECT_EQ(versions.size(), 1);
     EXPECT_EQ(versions[0], checkVersion);
 }
-
-TEST_F(CxxPropertiesTestSuite, StoreAndLoadTest) {
-    std::string path{"cxx_store_and_load_test.properties"};
-
-    celix::Properties props{};
-    props.set("key1", "1");
-    props.set("key2", "2");
-
-    EXPECT_NO_THROW(props.store(path));
-
-    celix::Properties loadedProps{};
-    EXPECT_NO_THROW(loadedProps = celix::Properties::load(path));
-    EXPECT_TRUE(loadedProps == props);
-
-    try {
-        loadedProps = celix::Properties::load("non-existence");
-        (void)loadedProps;
-        FAIL() << "Expected exception not thrown";
-    } catch (const celix::IOException& e) {
-        EXPECT_TRUE(strstr(e.what(), "Cannot load celix::Properties"));
-    }
-}
diff --git a/libs/utils/gtest/src/FileUtilsTestSuite.cc 
b/libs/utils/gtest/src/FileUtilsTestSuite.cc
index 6ff80d79c..775bcb108 100644
--- a/libs/utils/gtest/src/FileUtilsTestSuite.cc
+++ b/libs/utils/gtest/src/FileUtilsTestSuite.cc
@@ -178,13 +178,14 @@ TEST_F(FileUtilsTestSuite, ExtractZipFileTest) {
     EXPECT_EQ(status, CELIX_SUCCESS);
 
     EXPECT_TRUE(celix_utils_fileExists(file1));
-    auto* props = celix_properties_load(file1);
-    EXPECT_NE(props, nullptr);
+    celix_properties_t* props = nullptr;
+    EXPECT_EQ(CELIX_SUCCESS, celix_properties_load2(file1, 0, &props));
     EXPECT_EQ(celix_properties_getAsLong(props, "level", 0), 1);
     celix_properties_destroy(props);
 
     EXPECT_TRUE(celix_utils_fileExists(file2));
-    props = celix_properties_load(file2);
+    props = nullptr;
+    EXPECT_EQ(CELIX_SUCCESS, celix_properties_load2(file2, 0, &props));
     EXPECT_NE(props, nullptr);
     EXPECT_EQ(celix_properties_getAsLong(props, "level", 0), 2);
     celix_properties_destroy(props);
@@ -262,13 +263,15 @@ TEST_F(FileUtilsTestSuite, ExtractZipDataTest) {
     EXPECT_EQ(status, CELIX_SUCCESS);
 
     EXPECT_TRUE(celix_utils_fileExists(file1));
-    auto* props = celix_properties_load(file1);
+    celix_properties_t* props = nullptr;
+    EXPECT_EQ(CELIX_SUCCESS, celix_properties_load2(file1, 0, &props));
     EXPECT_NE(props, nullptr);
     EXPECT_EQ(celix_properties_getAsLong(props, "level", 0), 1);
     celix_properties_destroy(props);
 
     EXPECT_TRUE(celix_utils_fileExists(file2));
-    props = celix_properties_load(file2);
+    props = nullptr;
+    EXPECT_EQ(CELIX_SUCCESS, celix_properties_load2(file2, 0, &props));
     EXPECT_NE(props, nullptr);
     EXPECT_EQ(celix_properties_getAsLong(props, "level", 0), 2);
     celix_properties_destroy(props);
diff --git a/libs/utils/gtest/src/PropertiesErrorInjectionTestSuite.cc 
b/libs/utils/gtest/src/PropertiesErrorInjectionTestSuite.cc
index e7916ea38..2ff3ff66c 100644
--- a/libs/utils/gtest/src/PropertiesErrorInjectionTestSuite.cc
+++ b/libs/utils/gtest/src/PropertiesErrorInjectionTestSuite.cc
@@ -50,14 +50,8 @@ class PropertiesErrorInjectionTestSuite : public 
::testing::Test {
         celix_ei_expect_celix_stringHashMap_createWithOptions(nullptr, 0, 
nullptr);
         celix_ei_expect_celix_arrayList_copy(nullptr, 0, nullptr);
         celix_ei_expect_celix_utils_strdup(nullptr, 0, nullptr);
-        celix_ei_expect_fopen(nullptr, 0, nullptr);
-        celix_ei_expect_fputc(nullptr, 0, 0);
-        celix_ei_expect_fseek(nullptr, 0, 0);
-        celix_ei_expect_ftell(nullptr, 0, 0);
-        celix_ei_expect_celix_utils_strdup(nullptr, 0, nullptr);
         celix_ei_expect_celix_stringHashMap_put(nullptr, 0, 0);
         celix_ei_expect_celix_version_copy(nullptr, 0, nullptr);
-        celix_ei_expect_celix_arrayList_createWithOptions(nullptr, 0, nullptr);
         celix_ei_expect_celix_arrayList_copy(nullptr, 0, nullptr);
     }
 
@@ -176,116 +170,6 @@ TEST_F(PropertiesErrorInjectionTestSuite, SetFailureTest) 
{
     ASSERT_THROW(cxxProps.set("key", "value"), std::bad_alloc);
 }
 
-TEST_F(PropertiesErrorInjectionTestSuite, StoreFailureTest) {
-    // C API
-    // Given a celix properties object
-    celix_autoptr(celix_properties_t) props = celix_properties_create();
-    celix_properties_set(props, "key", "value");
-
-    // When a fopen error injection is set for celix_properties_store (during 
fopen)
-    celix_ei_expect_fopen((void*)celix_properties_store, 0, nullptr);
-    // Then the celix_properties_store call fails
-    auto status = celix_properties_store(props, "file", nullptr);
-    ASSERT_EQ(status, CELIX_FILE_IO_EXCEPTION);
-    // And a celix err msg is set
-    ASSERT_EQ(1, celix_err_getErrorCount());
-    celix_err_resetErrors();
-
-    // When a fputc error injection is set for celix_properties_store (during 
fputc)
-    celix_ei_expect_fputc((void*)celix_properties_store, 0, EOF);
-    // Then the celix_properties_store call fails
-    status = celix_properties_store(props, "file", nullptr);
-    ASSERT_EQ(status, CELIX_FILE_IO_EXCEPTION);
-    // And a celix err msg is set
-    ASSERT_EQ(1, celix_err_getErrorCount());
-    celix_err_resetErrors();
-
-    // C++ API
-    // Given a C++ celix properties object.
-    auto cxxProps = celix::Properties{};
-    cxxProps.set("key", "value");
-
-    // When a fopen error injection is set for celix_properties_store (during 
fopen)
-    celix_ei_expect_fopen((void*)celix_properties_store, 0, nullptr);
-    // Then the Properties:store throws a celix::IOException exception
-    EXPECT_THROW(cxxProps.store("file"), celix::IOException);
-    // And a celix err msg is set
-    ASSERT_EQ(1, celix_err_getErrorCount());
-    celix_err_resetErrors();
-}
-
-TEST_F(PropertiesErrorInjectionTestSuite, LoadFailureTest) {
-    // C API
-    // Given a fmemstream buffer with a properties file
-    const char* content = "key=value\n";
-    auto* memStream = fmemopen((void*)content, strlen(content), "r");
-
-    // When a fopen error injection is set for celix_properties_load (during 
fopen)
-    celix_ei_expect_fopen((void*)celix_properties_load, 0, nullptr);
-    // Then the celix_properties_load call fails
-    auto props = celix_properties_load("file");
-    ASSERT_EQ(nullptr, props);
-    // And a celix err msg is set
-    ASSERT_EQ(1, celix_err_getErrorCount());
-    celix_err_resetErrors();
-
-    // When a malloc error injection is set for 
celix_properties_loadWithStream (during properties create)
-    celix_ei_expect_malloc((void*)celix_properties_create, 0, nullptr);
-    // Then the celix_properties_loadWithStream call fails
-    props = celix_properties_loadWithStream(memStream);
-    ASSERT_EQ(nullptr, props);
-    // And a celix err msg is set
-    ASSERT_EQ(1, celix_err_getErrorCount());
-    celix_err_resetErrors();
-
-    // When a fseek error injection is set for celix_properties_loadWithStream
-    celix_ei_expect_fseek((void*)celix_properties_loadWithStream, 0, -1);
-    // Then the celix_properties_loadWithStream call fails
-    props = celix_properties_loadWithStream(memStream);
-    ASSERT_EQ(nullptr, props);
-    // And a celix err msg is set
-    ASSERT_EQ(1, celix_err_getErrorCount());
-    celix_err_resetErrors();
-
-    // When a fseek error injection is set for 
celix_properties_loadWithStream, ordinal 2
-    celix_ei_expect_fseek((void*)celix_properties_loadWithStream, 0, -1, 2);
-    // Then the celix_properties_loadWithStream call fails
-    props = celix_properties_loadWithStream(memStream);
-    ASSERT_EQ(nullptr, props);
-    // And a celix err msg is set
-    ASSERT_EQ(1, celix_err_getErrorCount());
-    celix_err_resetErrors();
-
-    // When a ftell error injection is set for celix_properties_loadWithStream
-    celix_ei_expect_ftell((void*)celix_properties_loadWithStream, 0, -1);
-    // Then the celix_properties_loadWithStream call fails
-    props = celix_properties_loadWithStream(memStream);
-    ASSERT_EQ(nullptr, props);
-    // And a celix err msg is set
-    ASSERT_EQ(1, celix_err_getErrorCount());
-    celix_err_resetErrors();
-
-    // When a malloc error injection is set for celix_properties_loadWithStream
-    celix_ei_expect_malloc((void*)celix_properties_loadWithStream, 0, nullptr);
-    // Then the celix_properties_loadWithStream call fails
-    props = celix_properties_loadWithStream(memStream);
-    ASSERT_EQ(nullptr, props);
-    // And a celix err msg is set
-    ASSERT_EQ(1, celix_err_getErrorCount());
-    celix_err_resetErrors();
-
-    //C++ API
-    // When a fopen error injection is set for celix_properties_load (during 
fopen)
-    celix_ei_expect_fopen((void*)celix_properties_load, 0, nullptr);
-    // Then the celix::Properties::load call throws a celix::IOException 
exception
-    EXPECT_THROW(celix::Properties::load("file"), celix::IOException);
-    // And a celix err msg is set
-    ASSERT_EQ(1, celix_err_getErrorCount());
-    celix_err_resetErrors();
-
-    fclose(memStream);
-}
-
 TEST_F(PropertiesErrorInjectionTestSuite, 
GetAsVersionWithVersionCopyFailedTest) {
     //Given a properties set with a version
     celix_autoptr(celix_properties_t) props = celix_properties_create();
@@ -428,17 +312,6 @@ TEST_F(PropertiesErrorInjectionTestSuite, 
AssignFailureTest) {
     celix_err_resetErrors();
 }
 
-TEST_F(PropertiesErrorInjectionTestSuite, LoadFromStringFailureTest) {
-    // When a strdup error injection is set for 
celix_properties_loadFromString (during strdup)
-    celix_ei_expect_celix_utils_strdup((void*)celix_properties_loadFromString, 
0, nullptr);
-    // Then the celix_properties_loadFromString call fails
-    auto props = celix_properties_loadFromString("key=value");
-    ASSERT_EQ(nullptr, props);
-    // And a celix err msg is set
-    ASSERT_EQ(1, celix_err_getErrorCount());
-    celix_err_resetErrors();
-}
-
 TEST_F(PropertiesErrorInjectionTestSuite, SetVersionFailureTest) {
     // Given a celix properties object
     celix_autoptr(celix_properties_t) props = celix_properties_create();
diff --git a/libs/utils/gtest/src/PropertiesTestSuite.cc 
b/libs/utils/gtest/src/PropertiesTestSuite.cc
index f44e0b077..391488c4c 100644
--- a/libs/utils/gtest/src/PropertiesTestSuite.cc
+++ b/libs/utils/gtest/src/PropertiesTestSuite.cc
@@ -54,69 +54,6 @@ TEST_F(PropertiesTestSuite, CreateTest) {
     celix_properties_destroy(properties);
 }
 
-TEST_F(PropertiesTestSuite, LoadTest) {
-    char propertiesFile[] = "resources-test/properties.txt";
-    auto* properties = celix_properties_load(propertiesFile);
-    EXPECT_EQ(4, celix_properties_size(properties));
-
-    const char keyA[] = "a";
-    const char *valueA = celix_properties_get(properties, keyA, nullptr);
-    EXPECT_STREQ("b", valueA);
-
-    const char keyNiceA[] = "nice_a";
-    const char *valueNiceA = celix_properties_get(properties, keyNiceA, 
nullptr);
-    EXPECT_STREQ("nice_b", valueNiceA);
-
-    const char keyB[] = "b";
-    const char *valueB = celix_properties_get(properties, keyB, nullptr);
-    EXPECT_STREQ("c \t d", valueB);
-
-    celix_properties_destroy(properties);
-}
-
-TEST_F(PropertiesTestSuite, LoadFromStringTest) {
-    const char* string = "key1=value1\nkey2=value2";
-    auto* props = celix_properties_loadFromString(string);
-    EXPECT_EQ(2, celix_properties_size(props));
-    EXPECT_STREQ("value1", celix_properties_get(props, "key1", ""));
-    EXPECT_STREQ("value2", celix_properties_get(props, "key2", ""));
-    celix_properties_destroy(props);
-}
-
-
-TEST_F(PropertiesTestSuite, StoreTest) {
-    const char* propertiesFile = "resources-test/properties_out.txt";
-    celix_autoptr(celix_properties_t) properties = celix_properties_create();
-    celix_properties_set(properties, "keyA", "valueA");
-    celix_properties_set(properties, "keyB", "valueB");
-    celix_properties_store(properties, propertiesFile, nullptr);
-
-    celix_autoptr(celix_properties_t) properties2 = 
celix_properties_load(propertiesFile);
-    EXPECT_EQ(celix_properties_size(properties), 
celix_properties_size(properties2));
-    EXPECT_STREQ(celix_properties_get(properties, "keyA", ""), 
celix_properties_get(properties2, "keyA", ""));
-    EXPECT_STREQ(celix_properties_get(properties, "keyB", ""), 
celix_properties_get(properties2, "keyB", ""));
-}
-
-TEST_F(PropertiesTestSuite, StoreWithHeaderTest) {
-    const char* propertiesFile = 
"resources-test/properties_with_header_out.txt";
-    celix_autoptr(celix_properties_t) properties = celix_properties_create();
-    celix_properties_set(properties, "keyA", "valueA");
-    celix_properties_set(properties, "keyB", "valueB");
-    celix_properties_store(properties, propertiesFile, "header");
-
-    celix_autoptr(celix_properties_t) properties2 = 
celix_properties_load(propertiesFile);
-    EXPECT_EQ(celix_properties_size(properties), 
celix_properties_size(properties2));
-    EXPECT_STREQ(celix_properties_get(properties, "keyA", ""), 
celix_properties_get(properties2, "keyA", ""));
-    EXPECT_STREQ(celix_properties_get(properties, "keyB", ""), 
celix_properties_get(properties2, "keyB", ""));
-
-    //check if provided header text is present in file
-    FILE *f = fopen(propertiesFile, "r");
-    char line[1024];
-    fgets(line, sizeof(line), f);
-    EXPECT_STREQ("#header\n", line);
-    fclose(f);
-}
-
 TEST_F(PropertiesTestSuite, GetAsLongTest) {
     celix_properties_t *props = celix_properties_create();
     celix_properties_set(props, "t1", "42");
@@ -662,11 +599,6 @@ TEST_F(PropertiesTestSuite, PropertiesAutoCleanupTest) {
     celix_autoptr(celix_properties_t) props = celix_properties_create();
 }
 
-TEST_F(PropertiesTestSuite, NullArgumentsTest) {
-    auto props = celix_properties_loadWithStream(nullptr);
-    EXPECT_EQ(nullptr, props);
-}
-
 TEST_F(PropertiesTestSuite, PropertiesEqualsTest) {
     EXPECT_TRUE(celix_properties_equals(nullptr, nullptr));
 
diff --git a/libs/utils/include/celix/Properties.h 
b/libs/utils/include/celix/Properties.h
index ee71925ea..2ca9672d1 100644
--- a/libs/utils/include/celix/Properties.h
+++ b/libs/utils/include/celix/Properties.h
@@ -932,21 +932,6 @@ namespace celix {
             return result;
         }
 
-        /**
-         * @brief Store the property set to the given file path.
-         *
-         * This function writes the properties in the given set to the 
specified file path in a format suitable
-         * for loading with the load() function.
-         * If a non-empty header string is provided, it will be written as a 
comment at the beginning of the file.
-         *
-         * @param[in] file The file to store the properties to.
-         * @param[in] header An optional (single line) header string to 
include as a comment at the beginning of the file.
-         * @throws celix::IOException If an error occurs while writing to the 
file.
-         */
-        void store(const std::string& path, const std::string& header = {}) 
const {
-            storeTo(path.data(), header.empty() ? nullptr : header.data());
-        }
-
         /**
          * @brief Enum class for encoding flags used in Celix properties JSON 
encoding.
          *
@@ -1044,16 +1029,6 @@ namespace celix {
             Strict = CELIX_PROPERTIES_DECODE_STRICT /**< If set, decoding will 
fail if there are any errors. */
         };
 
-        /**
-         * @brief Loads properties from the file at the given path.
-         * @param[in] path The path to the file containing the properties.
-         * @return A new Properties object containing the properties from the 
file.
-         * @throws celix::IOException If the file cannot be opened or read.
-         * @throws celix::IllegalArgumentException if the provided input 
cannot be decoded to a properties object.
-         * @throws std::bad_alloc If there was not enough memory to load the 
properties.
-         */
-        static Properties load(const std::string& path) { return 
loadFrom(path.data()); }
-
         /**
          * @brief Load a Properties object from a file.
          *
@@ -1153,21 +1128,6 @@ namespace celix {
             }
         }
 
-        static celix::Properties loadFrom(const char* path) {
-            auto* cProps = celix_properties_load(path);
-            if (cProps) {
-                return celix::Properties::own(cProps);
-            }
-            throw celix::IOException{"Cannot load celix::Properties from path 
" + std::string{path}};
-        }
-
-        void storeTo(const char* path, const char* header) const {
-            auto status = celix_properties_store(cProps.get(), path, header);
-            if (status != CELIX_SUCCESS) {
-                throw celix::IOException{"Cannot store celix::Properties to " 
+ std::string{path}};
-            }
-        }
-
         template<typename T>
         std::vector<T> convertToVector(const celix_array_list_t* list, const 
std::vector<T>& defaultValue, T (*get)(const celix_array_list_t*, int index)) 
const {
             if (list) {
diff --git a/libs/utils/include/celix_properties.h 
b/libs/utils/include/celix_properties.h
index f49d4628b..bf927935e 100644
--- a/libs/utils/include/celix_properties.h
+++ b/libs/utils/include/celix_properties.h
@@ -129,57 +129,6 @@ CELIX_UTILS_EXPORT void 
celix_properties_destroy(celix_properties_t* properties)
 
 CELIX_DEFINE_AUTOPTR_CLEANUP_FUNC(celix_properties_t, celix_properties_destroy)
 
-/**
- * @brief Load properties from a file.
- *
- * If the return status is an error, an error message is logged to celix_err.
- *
- * @param[in] filename The name of the file to load properties from.
- * @return A property set containing the properties from the file.
- * @retval NULL If an error occurred (e.g. file not found).
- */
-CELIX_UTILS_EXPORT celix_properties_t* celix_properties_load(const char* 
filename);
-
-/**
- * @brief Load properties from a stream.
- *
- * If the return status is an error, an error message is logged to celix_err.
- *
- * @param[in,out] stream The stream to load properties from.
- * @return A property set containing the properties from the stream.
- * @retval NULL If an error occurred (e.g. invalid format).
- */
-CELIX_UTILS_EXPORT celix_properties_t* celix_properties_loadWithStream(FILE* 
stream);
-
-/**
- * @brief Load properties from a string.
- *
- * If the return status is an error, an error message is logged to celix_err.
- *
- * @param[in] input The string to load properties from.
- * @return A property set containing the properties from the string.
- * @retval NULL If an error occurred (e.g. invalid format).
- */
-CELIX_UTILS_EXPORT celix_properties_t* celix_properties_loadFromString(const 
char* input);
-
-/**
- * @brief Store properties to a file.
- *
- * @note Properties values are always stored as string values, regardless of 
their actual underlining types.
- *
- * If the return status is an error, an error message is logged to celix_err.
- *
- * @param[in] properties The property set to store.
- * @param[in] file The name of the file to store the properties to.
- * @param[in] header An optional - single line - header to write to the file 
before the properties.
- *                   Will be prefix with a '#' character.
- * @return CELIX_SUCCESS if the operation was successful, 
CELIX_FILE_IO_EXCEPTION if there was an error writing to the
- *         file.
- */
-CELIX_UTILS_EXPORT celix_status_t celix_properties_store(celix_properties_t* 
properties,
-                                                         const char* file,
-                                                         const char* header);
-
 /**
  * @brief Get the entry for a given key in a property set.
  *
diff --git a/libs/utils/src/properties.c b/libs/utils/src/properties.c
index 5c8b657e0..53f84fff1 100644
--- a/libs/utils/src/properties.c
+++ b/libs/utils/src/properties.c
@@ -74,27 +74,6 @@ struct celix_properties {
     int currentEntriesBufferIndex;
 };
 
-#define MALLOC_BLOCK_SIZE 5
-
-static celix_status_t celix_properties_parseLine(const char* line, 
celix_properties_t* props);
-
-static void
-celix_properties_updateBuffers(char** key, char** value, char** output, int 
outputPos, int* key_len, int* value_len) {
-    if (*output == *key) {
-        if (outputPos == (*key_len) - 1) {
-            (*key_len) += MALLOC_BLOCK_SIZE;
-            *key = realloc(*key, *key_len);
-            *output = *key;
-        }
-    } else {
-        if (outputPos == (*value_len) - 1) {
-            (*value_len) += MALLOC_BLOCK_SIZE;
-            *value = realloc(*value, *value_len);
-            *output = *value;
-        }
-    }
-}
-
 /**
  * Create a new string from the provided str by either using strdup or storing 
the string the short properties
  * optimization string buffer.
@@ -347,249 +326,6 @@ void celix_properties_destroy(celix_properties_t* props) {
     }
 }
 
-celix_properties_t* celix_properties_load(const char* filename) {
-    FILE* file = fopen(filename, "r");
-    if (file == NULL) {
-        celix_err_pushf("Cannot open file '%s'", filename);
-        return NULL;
-    }
-    celix_properties_t* props = celix_properties_loadWithStream(file);
-    fclose(file);
-    return props;
-}
-
-static celix_status_t celix_properties_parseLine(const char* line, 
celix_properties_t* props) {
-    int linePos;
-    int outputPos;
-
-    bool precedingCharIsBackslash = false;
-    char* output = NULL;
-    int key_len = MALLOC_BLOCK_SIZE;
-    int value_len = MALLOC_BLOCK_SIZE;
-    linePos = 0;
-    precedingCharIsBackslash = false;
-    output = NULL;
-    outputPos = 0;
-
-    // Ignore empty lines
-    if (line[0] == '\n' && line[1] == '\0') {
-        return CELIX_SUCCESS;
-    }
-
-    celix_autofree char* key = calloc(1, key_len);
-    celix_autofree char* value = calloc(1, value_len);
-    if (!key || !value) {
-        celix_err_pushf("Cannot allocate memory for key or value. Got error 
%i", errno);
-        return CELIX_ENOMEM;
-    }
-
-    key[0] = '\0';
-    value[0] = '\0';
-
-    while (line[linePos] != '\0') {
-        if (line[linePos] == ' ' || line[linePos] == '\t') {
-            if (output == NULL) {
-                // ignore
-                linePos += 1;
-                continue;
-            }
-        } else {
-            if (output == NULL) {
-                output = key;
-            }
-        }
-        if (line[linePos] == '=' || line[linePos] == ':' || line[linePos] == 
'#' || line[linePos] == '!') {
-            if (precedingCharIsBackslash) {
-                // escaped special character
-                output[outputPos++] = line[linePos];
-                celix_properties_updateBuffers(&key, &value, &output, 
outputPos, &key_len, &value_len);
-                precedingCharIsBackslash = false;
-            } else {
-                if (line[linePos] == '#' || line[linePos] == '!') {
-                    if (outputPos == 0) {
-                        // comment line, ignore
-                        return CELIX_SUCCESS;
-                    } else {
-                        output[outputPos++] = line[linePos];
-                        celix_properties_updateBuffers(&key, &value, &output, 
outputPos, &key_len, &value_len);
-                    }
-                } else {                   // = or :
-                    if (output == value) { // already have a seperator
-                        output[outputPos++] = line[linePos];
-                        celix_properties_updateBuffers(&key, &value, &output, 
outputPos, &key_len, &value_len);
-                    } else {
-                        output[outputPos++] = '\0';
-                        celix_properties_updateBuffers(&key, &value, &output, 
outputPos, &key_len, &value_len);
-                        output = value;
-                        outputPos = 0;
-                    }
-                }
-            }
-        } else if (line[linePos] == '\\') {
-            if (precedingCharIsBackslash) { // double backslash -> backslash
-                output[outputPos++] = '\\';
-                celix_properties_updateBuffers(&key, &value, &output, 
outputPos, &key_len, &value_len);
-            }
-            precedingCharIsBackslash = true;
-        } else { // normal character
-            precedingCharIsBackslash = false;
-            output[outputPos++] = line[linePos];
-            celix_properties_updateBuffers(&key, &value, &output, outputPos, 
&key_len, &value_len);
-        }
-        linePos += 1;
-    }
-    if (output != NULL) {
-        output[outputPos] = '\0';
-    }
-
-    return celix_properties_set(props, celix_utils_trimInPlace(key), 
celix_utils_trimInPlace(value));
-}
-
-celix_properties_t* celix_properties_loadWithStream(FILE* file) {
-    if (file == NULL) {
-        return NULL;
-    }
-
-
-    celix_autoptr(celix_properties_t) props = celix_properties_create();
-    if (!props) {
-        return NULL;
-    }
-
-    int rc = fseek(file, 0, SEEK_END);
-    if (rc != 0) {
-        celix_err_pushf("Cannot seek to end of file. Got error %i", errno);
-        return NULL;
-    }
-
-    long fileSize = ftell(file);
-    if (fileSize < 0) {
-        celix_err_pushf("Cannot get file size. Got error %i", errno);
-        return NULL;
-    }
-
-    rc = fseek(file, 0, SEEK_SET);
-    if (rc != 0) {
-        celix_err_pushf("Cannot seek to start of file. Got error %i", errno);
-        return NULL;
-    }
-
-    celix_autofree char* fileBuffer = malloc(fileSize + 1);
-    if (fileBuffer == NULL) {
-        celix_err_pushf("Cannot allocate memory for file buffer. Got error 
%i", errno);
-        return NULL;
-    }
-
-    size_t rs = fread(fileBuffer, sizeof(char), fileSize, file);
-    if (rs < fileSize) {
-        celix_err_pushf("fread read only %zu bytes out of %zu\n", rs, 
fileSize);
-        return NULL;
-    }
-    fileBuffer[fileSize] = '\0'; // ensure a '\0' at the end of the fileBuffer
-
-    char* savePtr = NULL;
-    char* line = strtok_r(fileBuffer, "\n", &savePtr);
-    while (line != NULL) {
-        celix_status_t status = celix_properties_parseLine(line, props);
-        if (status != CELIX_SUCCESS) {
-            celix_err_pushf("Failed to parse line '%s'", line);
-            return NULL;
-        }
-        line = strtok_r(NULL, "\n", &savePtr);
-    }
-
-    return celix_steal_ptr(props);
-}
-
-celix_properties_t* celix_properties_loadFromString(const char* input) {
-    celix_autoptr(celix_properties_t) props = celix_properties_create();
-    celix_autofree char* in = celix_utils_strdup(input);
-    if (!props || !in) {
-        celix_err_push("Failed to create properties or duplicate input 
string");
-        return NULL;
-    }
-
-    char* line = NULL;
-    char* saveLinePointer = NULL;
-    line = strtok_r(in, "\n", &saveLinePointer);
-    while (line != NULL) {
-        celix_status_t status = celix_properties_parseLine(line, props);
-        if (status != CELIX_SUCCESS) {
-            celix_err_pushf("Failed to parse line '%s'", line);
-            return NULL;
-        }
-        line = strtok_r(NULL, "\n", &saveLinePointer);
-    }
-    return celix_steal_ptr(props);
-}
-
-/**
- * @brief Store properties string to file and escape the characters '#', '!', 
'=' and ':' if encountered.
- */
-static int celix_properties_storeEscapedString(FILE* file, const char* str) {
-    int rc = 0;
-    size_t len = strlen(str);
-    for (size_t i = 0; i < len && rc != EOF; i += 1) {
-        if (str[i] == '#' || str[i] == '!' || str[i] == '=' || str[i] == ':') {
-            rc = fputc('\\', file);
-            if (rc == EOF) {
-                continue;
-            }
-        }
-        rc = fputc(str[i], file);
-    }
-    return rc;
-}
-
-celix_status_t celix_properties_store(celix_properties_t* properties, const 
char* filename, const char* header) {
-    FILE* file = fopen(filename, "w+");
-
-    if (file == NULL) {
-        celix_err_pushf("Cannot open file '%s'", filename);
-        return CELIX_FILE_IO_EXCEPTION;
-    }
-
-    int rc = 0;
-
-    if (header && strstr("\n", header)) {
-        celix_err_push("Header cannot contain newlines. Ignoring header.");
-    } else if (header) {
-        rc = fputc('#', file);
-        if (rc != EOF) {
-            rc = fputs(header, file);
-        }
-        if (rc != EOF) {
-            rc = fputc('\n', file);
-        }
-    }
-
-    CELIX_PROPERTIES_ITERATE(properties, iter) {
-        const char* val = iter.entry.value;
-        if (rc != EOF) {
-            rc = celix_properties_storeEscapedString(file, iter.key);
-        }
-        if (rc != EOF) {
-            rc = fputc('=', file);
-        }
-        if (rc != EOF) {
-            rc = celix_properties_storeEscapedString(file, val);
-        }
-        if (rc != EOF) {
-            rc = fputc('\n', file);
-        }
-    }
-    if (rc != EOF) {
-        rc = fclose(file);
-    } else {
-        fclose(file);
-    }
-    if (rc == EOF) {
-        celix_err_push("Failed to write properties to file");
-        return CELIX_FILE_IO_EXCEPTION;
-    }
-    return CELIX_SUCCESS;
-}
-
 celix_properties_t* celix_properties_copy(const celix_properties_t* 
properties) {
     celix_properties_t* copy = celix_properties_create();
 

Reply via email to