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 2022/06/26 17:15:25 UTC

[celix] 01/01: Adds print functions for dependency manager and dm cmp and refactors dm command to use these functions

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

pnoltes pushed a commit to branch feature/print_function_for_dm_info
in repository https://gitbox.apache.org/repos/asf/celix.git

commit d6afb40aa1b2cf00ba9f80cf8f2e4d800b12f55f
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Sun Jun 26 19:15:18 2022 +0200

    Adds print functions for dependency manager and dm cmp and refactors dm command to use these functions
---
 bundles/shell/shell/src/dm_shell_list_command.c    | 104 +--------------------
 .../gtest/src/DependencyManagerTestSuite.cc        |  64 +++++++++++++
 libs/framework/include/celix/dm/Component.h        |   8 +-
 libs/framework/include/celix/dm/Component_Impl.h   |  18 +++-
 .../framework/include/celix/dm/DependencyManager.h |  12 ++-
 .../include/celix/dm/DependencyManager_Impl.h      |  11 +++
 libs/framework/include/celix_dependency_manager.h  |  59 +++++++-----
 libs/framework/include/celix_dm_component.h        |  23 +++--
 libs/framework/include/celix_dm_info.h             |   6 +-
 libs/framework/src/dm_component_impl.c             |  95 +++++++++++++++++--
 libs/framework/src/dm_dependency_manager_impl.c    |  27 +++++-
 libs/utils/include/celix/Utils.h                   |  32 +++++++
 12 files changed, 317 insertions(+), 142 deletions(-)

diff --git a/bundles/shell/shell/src/dm_shell_list_command.c b/bundles/shell/shell/src/dm_shell_list_command.c
index df1fdcac..cfe625c9 100644
--- a/bundles/shell/shell/src/dm_shell_list_command.c
+++ b/bundles/shell/shell/src/dm_shell_list_command.c
@@ -23,12 +23,7 @@
 #include "celix_shell_constants.h"
 #include "celix_bundle_context.h"
 #include "celix_dependency_manager.h"
-
-
-static const char * const OK_COLOR = "\033[92m";
-static const char * const WARNING_COLOR = "\033[93m";
-static const char * const NOK_COLOR = "\033[91m";
-static const char * const END_COLOR = "\033[m";
+#include "celix_dm_component.h"
 
 static void parseCommandLine(const char*line, celix_array_list_t **requestedBundleIds, bool *fullInfo, bool *wtf, FILE *err) {
     *fullInfo = false;
@@ -54,91 +49,11 @@ static void parseCommandLine(const char*line, celix_array_list_t **requestedBund
     free (str);
 }
 
-static void printFullInfo(FILE *out, bool colors, long bundleId, const char* bndName, dm_component_info_pt compInfo) {
-    const char *startColors = "";
-    const char *endColors = "";
-    if (colors) {
-        startColors = compInfo->active ? OK_COLOR : NOK_COLOR;
-        endColors = END_COLOR;
-    }
-    fprintf(out, "%sComponent: Name=%s%s\n", startColors, compInfo->name, endColors);
-    fprintf(out, "|- UUID   = %s\n", compInfo->id);
-    fprintf(out, "|- Active = %s\n", compInfo->active ? "true" : "false");
-    fprintf(out, "|- State  = %s\n", compInfo->state);
-    fprintf(out, "|- Bundle = %li (%s)\n", bundleId, bndName);
-    fprintf(out, "|- Nr of times started = %i\n", (int)compInfo->nrOfTimesStarted);
-    fprintf(out, "|- Nr of times resumed = %i\n", (int)compInfo->nrOfTimesResumed);
-
-    fprintf(out, "|- Interfaces (%d):\n", celix_arrayList_size(compInfo->interfaces));
-    for (int interfCnt = 0; interfCnt < celix_arrayList_size(compInfo->interfaces); interfCnt++) {
-        dm_interface_info_pt intfInfo = celix_arrayList_get(compInfo->interfaces, interfCnt);
-        fprintf(out, "   |- %sInterface %i: %s%s\n", startColors, (interfCnt+1), intfInfo->name, endColors);
-
-        hash_map_iterator_t iter = hashMapIterator_construct((hash_map_pt) intfInfo->properties);
-        char *key = NULL;
-        while ((key = hashMapIterator_nextKey(&iter)) != NULL) {
-            fprintf(out, "      | %15s = %s\n", key, celix_properties_get(intfInfo->properties, key, "!ERROR!"));
-        }
-    }
-
-    fprintf(out, "|- Dependencies (%d):\n", celix_arrayList_size(compInfo->dependency_list));
-    for (int depCnt = 0; depCnt < celix_arrayList_size(compInfo->dependency_list); ++depCnt) {
-        dm_service_dependency_info_pt dependency;
-        dependency = celix_arrayList_get(compInfo->dependency_list, depCnt);
-        const char *depStartColors = "";
-        if (colors) {
-            if (dependency->required) {
-                depStartColors = dependency->available ? OK_COLOR : NOK_COLOR;
-            } else {
-                depStartColors = dependency->available ? OK_COLOR : WARNING_COLOR;
-            }
-        }
-        fprintf(out, "   |- %sDependency %i: %s%s\n", depStartColors, (depCnt+1), dependency->serviceName == NULL ? "(any)" : dependency->serviceName, endColors);
-        fprintf(out, "      | %15s = %s\n", "Available", dependency->available ? "true " : "false");
-        fprintf(out, "      | %15s = %s\n", "Required", dependency->required ? "true " : "false");
-        fprintf(out, "      | %15s = %s\n", "Version Range", dependency->versionRange == NULL ? "N/A" : dependency->versionRange);
-        fprintf(out, "      | %15s = %s\n", "Filter", dependency->filter == NULL ? "N/A" : dependency->filter);
-    }
-    fprintf(out, "\n");
-
-}
-
-static void printBasicInfo(FILE *out, bool colors, long bundleId, const char* bndName, dm_component_info_pt compInfo) {
-    const char *startColors = "";
-    const char *endColors = "";
-    if (colors) {
-        startColors = compInfo->active ? OK_COLOR : NOK_COLOR;
-        endColors = END_COLOR;
-    }
-    fprintf(out, "Component: Name=%s, ID=%s, %sActive=%s%s, State=%s, Bundle=%li (%s)\n", compInfo->name, compInfo->id,
-            startColors, compInfo->active ? "true " : "false", endColors, compInfo->state, bundleId, bndName);
-
-}
-
-static void dm_printInfo(FILE *out, bool useColors, bool fullInfo, celix_dependency_manager_info_t *info) {
-    if (info != NULL) {
-        int size = celix_arrayList_size(info->components);
-        if (size > 0) {
-            for (unsigned int cmpCnt = 0; cmpCnt < size; cmpCnt++) {
-                dm_component_info_pt compInfo = celix_arrayList_get(info->components, cmpCnt);
-                if (fullInfo) {
-                    printFullInfo(out, useColors, info->bndId, info->bndSymbolicName, compInfo);
-                } else {
-                    printBasicInfo(out, useColors, info->bndId, info->bndSymbolicName, compInfo);
-                }
-            }
-            fprintf(out, "\n");
-        }
-    }
-}
-
 celix_status_t dmListCommand_execute(void* handle, char * line, FILE *out, FILE *err) {
     celix_bundle_context_t *ctx = handle;
     celix_dependency_manager_t *mng = celix_bundleContext_getDependencyManager(ctx);
 
-    const char *config = NULL;
-    bundleContext_getPropertyWithDefault(ctx, CELIX_SHELL_USE_ANSI_COLORS, CELIX_SHELL_USE_ANSI_COLORS_DEFAULT_VALUE, &config);
-    bool useColors = config != NULL && strncmp("true", config, 5) == 0;
+    bool useColors = celix_bundleContext_getPropertyAsBool(ctx, CELIX_SHELL_USE_ANSI_COLORS, CELIX_SHELL_USE_ANSI_COLORS_DEFAULT_VALUE);
 
     celix_array_list_t *bundleIds = NULL;
     bool fullInfo = false;
@@ -157,7 +72,7 @@ celix_status_t dmListCommand_execute(void* handle, char * line, FILE *out, FILE
                 nrOfComponents += 1;
                 if (!cmpInfo->active) {
                     allActive = false;
-                    printFullInfo(out, useColors, info->bndId, info->bndSymbolicName, cmpInfo);
+                    celix_dmComponent_printComponentInfo(cmpInfo, true, useColors, out);
                 }
             }
         }
@@ -166,20 +81,11 @@ celix_status_t dmListCommand_execute(void* handle, char * line, FILE *out, FILE
             fprintf(out, "No problem all %i dependency manager components are active\n", nrOfComponents);
         }
     } else if (celix_arrayList_size(bundleIds) == 0) {
-        celix_array_list_t *infos = celix_dependencyManager_createInfos(mng);
-        for (int i = 0; i < celix_arrayList_size(infos); ++i) {
-            celix_dependency_manager_info_t *info = celix_arrayList_get(infos, i);
-            dm_printInfo(out, useColors, fullInfo, info);
-        }
-        celix_dependencyManager_destroyInfos(mng, infos);
+        celix_dependencyManager_printInfo(mng, fullInfo, useColors, out);
     } else {
         for (int i = 0; i < celix_arrayList_size(bundleIds); ++i) {
             long bndId = celix_arrayList_getLong(bundleIds, i);
-            celix_dependency_manager_info_t *info = celix_dependencyManager_createInfo(mng, bndId);
-            if (info != NULL) {
-                dm_printInfo(out, useColors, fullInfo, info);
-                celix_dependencyManager_destroyInfo(mng, info);
-            }
+            celix_dependencyManager_printInfoForBundle(mng, fullInfo, useColors, bndId, out);
         }
     }
 
diff --git a/libs/framework/gtest/src/DependencyManagerTestSuite.cc b/libs/framework/gtest/src/DependencyManagerTestSuite.cc
index d9939fbb..dab657a7 100644
--- a/libs/framework/gtest/src/DependencyManagerTestSuite.cc
+++ b/libs/framework/gtest/src/DependencyManagerTestSuite.cc
@@ -1117,4 +1117,68 @@ TEST_F(DependencyManagerTestSuite, CreateInterfaceWithStaticInfo) {
     EXPECT_EQ(it->second, "1.2.3");
 }
 
+TEST_F(DependencyManagerTestSuite, TestPrintInfo) {
+    celix::dm::DependencyManager dm{ctx};
+    auto& cmp = dm.createComponent<Cmp1>();
+    cmp.addInterface<TestService>();
+    cmp.createServiceDependency<TestInterfaceWithStaticInfo>();
+    cmp.build();
+
+    char* buf = nullptr;
+    size_t bufLen = 0;
+    FILE* testStream = open_memstream(&buf, &bufLen);
+    celix_dependencyManager_printInfo(celix_bundleContext_getDependencyManager(ctx), true, true, testStream);
+    fclose(testStream);
+    std::cout << buf << std::endl;
+    EXPECT_TRUE(strstr(buf, "Cmp1")); //cmp name
+    EXPECT_TRUE(strstr(buf, "TestService")); //provided service name
+    EXPECT_TRUE(strstr(buf, "TestName")); //service dependency name
+    free(buf);
+
+    buf = nullptr;
+    bufLen = 0;
+    testStream = open_memstream(&buf, &bufLen);
+    celix_dependencyManager_printInfo(celix_bundleContext_getDependencyManager(ctx), true, false, testStream);
+    fclose(testStream);
+    EXPECT_TRUE(strstr(buf, "Cmp1")); //cmp name
+    EXPECT_TRUE(strstr(buf, "TestService")); //provided service name
+    EXPECT_TRUE(strstr(buf, "TestName")); //service dependency name
+    free(buf);
+
+    buf = nullptr;
+    bufLen = 0;
+    testStream = open_memstream(&buf, &bufLen);
+    celix_dependencyManager_printInfo(celix_bundleContext_getDependencyManager(ctx), false, true, testStream);
+    fclose(testStream);
+    EXPECT_TRUE(strstr(buf, "Cmp1")); //cmp name
+    free(buf);
+
+    buf = nullptr;
+    bufLen = 0;
+    testStream = open_memstream(&buf, &bufLen);
+    celix_dependencyManager_printInfo(celix_bundleContext_getDependencyManager(ctx), false, false, testStream);
+    fclose(testStream);
+    EXPECT_TRUE(strstr(buf, "Cmp1")); //cmp name
+    free(buf);
+
+    buf = nullptr;
+    bufLen = 0;
+    testStream = open_memstream(&buf, &bufLen);
+    celix_dependencyManager_printInfoForBundle(celix_bundleContext_getDependencyManager(ctx), true, true, 0, testStream);
+    fclose(testStream);
+    EXPECT_TRUE(strstr(buf, "Cmp1")); //cmp name
+    free(buf);
+
+    //bundle does not exist -> empty print
+    celix_dependencyManager_printInfoForBundle(celix_bundleContext_getDependencyManager(ctx), true, true, 1 /*non existing*/, stdout);
+
+    std::stringstream ss{};
+    ss << dm;
+    EXPECT_TRUE(strstr(ss.str().c_str(), "Cmp1"));
+
+    ss = std::stringstream{};
+    ss << cmp;
+    EXPECT_TRUE(strstr(ss.str().c_str(), "Cmp1"));
+}
+
 #endif
\ No newline at end of file
diff --git a/libs/framework/include/celix/dm/Component.h b/libs/framework/include/celix/dm/Component.h
index d101b35f..f3780f8d 100644
--- a/libs/framework/include/celix/dm/Component.h
+++ b/libs/framework/include/celix/dm/Component.h
@@ -28,7 +28,7 @@
 #include <iostream>
 #include <type_traits>
 #include <algorithm>
-
+#include <cstdio>
 
 #include "dm_component.h"
 #include "celix/dm/types.h"
@@ -137,6 +137,8 @@ namespace celix { namespace dm {
          * The underlining service registration and service tracker will be registered/created async.
          */
         void runBuild();
+
+        friend std::ostream& operator<<(std::ostream& out, const BaseComponent& cmp);
     protected:
         celix_bundle_context_t* context;
         celix_dependency_manager_t* cDepMan;
@@ -152,6 +154,10 @@ namespace celix { namespace dm {
         std::vector<std::shared_ptr<void>> componentContexts{};
     };
 
+    /**
+     * Stream outputs the full component info.
+     */
+    inline std::ostream& operator<<(std::ostream& out, const BaseComponent& cmp);
 
     template<class T>
     class Component : public BaseComponent {
diff --git a/libs/framework/include/celix/dm/Component_Impl.h b/libs/framework/include/celix/dm/Component_Impl.h
index d860afa2..f56e2044 100644
--- a/libs/framework/include/celix/dm/Component_Impl.h
+++ b/libs/framework/include/celix/dm/Component_Impl.h
@@ -51,6 +51,20 @@ inline void BaseComponent::wait() const {
     celix_dependencyManager_wait(cDepMan);
 }
 
+std::ostream& celix::dm::operator<<(std::ostream &out, const BaseComponent &cmp) {
+    char* buf = nullptr;
+    size_t bufSize = 0;
+    FILE* stream = open_memstream(&buf, &bufSize);
+    celix_dm_component_info_t* cmpInfo = nullptr;
+    celix_dmComponent_getComponentInfo(cmp.cComponent(), &cmpInfo);
+    celix_dmComponent_printComponentInfo(cmpInfo, true, true, stream);
+    fclose(stream);
+    celix_dmComponent_destroyComponentInfo(cmpInfo);
+    out << buf;
+    free(buf);
+    return out;
+}
+
 template<class T>
 Component<T>::Component(
         celix_bundle_context_t *context,
@@ -59,7 +73,7 @@ Component<T>::Component(
         std::string uuid) : BaseComponent(
                 context,
                 cDepMan,
-                celix::typeName<T>(name),
+                celix::cmpTypeName<T>(name),
                 std::move(uuid)) {}
 
 template<class T>
@@ -167,7 +181,7 @@ Component<T>& Component<T>::remove(CServiceDependency<T,I>& dep) {
 
 template<class T>
 std::shared_ptr<Component<T>> Component<T>::create(celix_bundle_context_t *context, celix_dependency_manager_t* cDepMan, std::string name, std::string uuid) {
-    std::string cmpName = celix::typeName<T>(name);
+    std::string cmpName = celix::cmpTypeName<T>(name);
     return std::shared_ptr<Component<T>>{new Component<T>(context, cDepMan, std::move(cmpName), std::move(uuid)), [](Component<T>* cmp){
         //Using a callback of async destroy to ensure that the cmp instance is still exist while the
         //dm component is async disabled and destroyed.
diff --git a/libs/framework/include/celix/dm/DependencyManager.h b/libs/framework/include/celix/dm/DependencyManager.h
index d5dbaa6b..2b824c84 100644
--- a/libs/framework/include/celix/dm/DependencyManager.h
+++ b/libs/framework/include/celix/dm/DependencyManager.h
@@ -19,6 +19,10 @@
 
 #pragma once
 
+#include <cstdio>
+#include <iostream>
+#include <vector>
+
 #include "celix/dm/types.h"
 #include "celix/dm/Component.h"
 #include "celix/dm/ServiceDependency.h"
@@ -28,8 +32,6 @@
 #include "celix_bundle_context.h"
 #include "celix_dependency_manager.h"
 
-#include <vector>
-
 namespace celix { namespace dm {
 
     /**
@@ -215,6 +217,8 @@ namespace celix { namespace dm {
          * @return A vector of DependencyManagerInfo structs.
          */
         std::vector<celix::dm::DependencyManagerInfo> getInfos() const;
+
+        friend std::ostream& operator<<(std::ostream& out, const DependencyManager& mng);
     private:
         template<class T>
         Component<T>& createComponentInternal(std::string name, std::string uuid);
@@ -225,6 +229,10 @@ namespace celix { namespace dm {
         std::vector<std::shared_ptr<BaseComponent>> components{};
     };
 
+    /**
+     * Stream outputs the full dependency manager info.
+     */
+    inline std::ostream& operator<<(std::ostream& out, const DependencyManager& mng);
 }}
 
 #include "celix/dm/DependencyManager_Impl.h"
diff --git a/libs/framework/include/celix/dm/DependencyManager_Impl.h b/libs/framework/include/celix/dm/DependencyManager_Impl.h
index 6ff1da2e..f3e9f075 100644
--- a/libs/framework/include/celix/dm/DependencyManager_Impl.h
+++ b/libs/framework/include/celix/dm/DependencyManager_Impl.h
@@ -217,3 +217,14 @@ inline std::vector<celix::dm::DependencyManagerInfo> DependencyManager::getInfos
     celix_dependencyManager_destroyInfos(cDependencyManager(), cInfos);
     return result;
 }
+
+std::ostream& celix::dm::operator<<(std::ostream &out, const DependencyManager &mng) {
+    char* buf = nullptr;
+    size_t bufSize = 0;
+    FILE* stream = open_memstream(&buf, &bufSize);
+    celix_dependencyManager_printInfo(mng.cDepMan.get(), true, true, stream);
+    fclose(stream);
+    out << buf;
+    free(buf);
+    return out;
+}
diff --git a/libs/framework/include/celix_dependency_manager.h b/libs/framework/include/celix_dependency_manager.h
index d4cf37a5..9efa3794 100644
--- a/libs/framework/include/celix_dependency_manager.h
+++ b/libs/framework/include/celix_dependency_manager.h
@@ -102,6 +102,30 @@ celix_status_t celix_dependencyManager_removeAllComponents(celix_dependency_mana
  */
 celix_status_t celix_dependencyManager_removeAllComponentsAsync(celix_dependency_manager_t *manager, void *doneData, void (*doneCallback)(void *data));
 
+/**
+ * Check if all components for the bundle of the dependency manager are active (all required dependencies resolved).
+ */
+bool celix_dependencyManager_areComponentsActive(celix_dependency_manager_t *manager);
+
+/**
+ * Check if all components - for all bundles - are active (all required dependencies resolved).
+ */
+bool celix_dependencyManager_allComponentsActive(celix_dependency_manager_t *manager);
+
+/**
+ * Return the nr of components for this dependency manager
+ */
+size_t celix_dependencyManager_nrOfComponents(celix_dependency_manager_t *manager);
+
+/**
+ * Wait for an empty Celix event queue.
+ * Should not be called on the Celix event queue thread.
+ *
+ * Can be used to ensure that all created/updated components are completely processed (services registered
+ * and/or service trackers are created).
+ */
+void celix_dependencyManager_wait(celix_dependency_manager_t* manager);
+
 /**
  * Create and returns a dependency manager info struct for the specified bundle.
  * The dependency manager info contains information about the state of the dependency manager components
@@ -122,7 +146,6 @@ celix_dependency_manager_info_t* celix_dependencyManager_createInfo(celix_depend
  *
  * @param manager The dependency manager
  * @returns A Celix array of dependency manager infos (celix_dependency_manager_info_t*)
- * for the provided bundle id or NULL if the bundle id is invalid.
  */
 celix_array_list_t * /*celix_dependency_manager_info_t* entries*/ celix_dependencyManager_createInfos(celix_dependency_manager_t *manager);
 
@@ -136,30 +159,24 @@ void celix_dependencyManager_destroyInfo(celix_dependency_manager_t *manager, ce
  */
 void celix_dependencyManager_destroyInfos(celix_dependency_manager_t *manager, celix_array_list_t * infos /*entries celix_dependency_manager_info_t*/);
 
-
-/**
- * Check if all components for the bundle of the dependency manager are active (all required dependencies resolved).
- */
-bool celix_dependencyManager_areComponentsActive(celix_dependency_manager_t *manager);
-
-/**
- * Check if all components - for all bundles - are active (all required dependencies resolved).
- */
-bool celix_dependencyManager_allComponentsActive(celix_dependency_manager_t *manager);
-
 /**
- * Return the nr of components for this dependency manager
+ * Print the dependency manager info for all bundles to the provided output stream.
+ * @param manager The dependency manager.
+ * @param fullInfo Whether to print the full info or summary.
+ * @param useAnsiColors Whether to use ansi colors when printing info.
+ * @param stream The output stream (e.g. stdout)
  */
-size_t celix_dependencyManager_nrOfComponents(celix_dependency_manager_t *manager);
+void celix_dependencyManager_printInfo(celix_dependency_manager_t* manager, bool fullInfo, bool useAnsiColors, FILE* stream);
 
 /**
- * Wait for an empty Celix event queue.
- * Should not be called on the Celix event queue thread.
- *
- * Can be used to ensure that all created/updated components are completely processed (services registered
- * and/or service trackers are created).
- */
-void celix_dependencyManager_wait(celix_dependency_manager_t* manager);
+ * Print the dependency manager info for the provided bundle id to the provided output stream.
+ * @param manager The dependency manager.
+ * @param fullInfo whether to print the full info or summary.
+ * @param useAnsiColors Whether to use ansi colors when printing info.
+ * @param bundleId The bundle id for which the dependency manager info should be printed.
+ * @param stream The output stream (e.g. stdout)
+ */
+void celix_dependencyManager_printInfoForBundle(celix_dependency_manager_t* manager, bool fullInfo, bool useAnsiColors, long bundleId, FILE* stream);
 
 #ifdef __cplusplus
 }
diff --git a/libs/framework/include/celix_dm_component.h b/libs/framework/include/celix_dm_component.h
index 8302dca0..29ea96d9 100644
--- a/libs/framework/include/celix_dm_component.h
+++ b/libs/framework/include/celix_dm_component.h
@@ -172,23 +172,34 @@ celix_status_t celix_dmComponent_setCallbacks(celix_dm_component_t *component, c
         celix_dmComponent_setCallbacks((dmCmp), (celix_dm_cmp_lifecycle_fpt)tmp_init, (celix_dm_cmp_lifecycle_fpt)tmp_start, (celix_dm_cmp_lifecycle_fpt)tmp_stop, (celix_dm_cmp_lifecycle_fpt)tmp_deinit); \
     } while(0)
 
+
+bool celix_dmComponent_isActive(celix_dm_component_t *component);
+
+/**
+ * Returns the string value of a provided state
+ */
+const char* celix_dmComponent_stateToString(celix_dm_component_state_t state);
+
 /**
  * Create a DM Component info struct. Containing information about the component.
  * Caller has ownership.
  */
-celix_status_t celix_dmComponent_getComponentInfo(celix_dm_component_t *component, dm_component_info_pt *info);
+celix_status_t celix_dmComponent_getComponentInfo(celix_dm_component_t *component, celix_dm_component_info_t** infoOut);
 
-bool celix_dmComponent_isActive(celix_dm_component_t *component);
+/**
+ * Print the component info to the provided stream.
+ * @param info The component info to print.
+ * @param printFullInfo Whether to print the full info or summary.
+ * @param useAnsiColors Whether to use ansi colors when printing the component info.
+ * @param stream The stream to print to (e..g stdout).
+ */
+void celix_dmComponent_printComponentInfo(celix_dm_component_info_t* info, bool printFullInfo, bool useAnsiColors, FILE* stream);
 
 /**
  * Destroys a DM Component info struct.
  */
 void celix_dmComponent_destroyComponentInfo(dm_component_info_pt info);
 
-/**
- * Returns the string value of a provided state
- */
-const char* celix_dmComponent_stateToString(celix_dm_component_state_t state);
 
 #ifdef __cplusplus
 }
diff --git a/libs/framework/include/celix_dm_info.h b/libs/framework/include/celix_dm_info.h
index fa66d95c..2f7d2622 100644
--- a/libs/framework/include/celix_dm_info.h
+++ b/libs/framework/include/celix_dm_info.h
@@ -52,8 +52,10 @@ typedef struct celix_dm_service_dependency_info_struct dm_service_dependency_inf
 typedef struct celix_dm_service_dependency_info_struct celix_dm_service_dependency_info_t;
 
 struct celix_dm_component_info_struct {
-    char id[64];
-    char name[128];
+    long bundleId;
+    char* bundleSymbolicName;
+    char* id;
+    char* name;
     bool active;
     char* state;
     size_t nrOfTimesStarted;
diff --git a/libs/framework/src/dm_component_impl.c b/libs/framework/src/dm_component_impl.c
index d8838bba..d18396df 100644
--- a/libs/framework/src/dm_component_impl.c
+++ b/libs/framework/src/dm_component_impl.c
@@ -29,6 +29,11 @@
 #include "dm_component_impl.h"
 #include "celix_framework.h"
 
+static const char * const CELIX_DM_PRINT_OK_COLOR = "\033[92m";
+static const char * const CELIX_DM_PRINT_WARNING_COLOR = "\033[93m";
+static const char * const CELIX_DM_PRINT_NOK_COLOR = "\033[91m";
+static const char * const CELIX_DM_PRINT_END_COLOR = "\033[m";
+
 struct celix_dm_component_struct {
     char uuid[DM_COMPONENT_MAX_ID_LENGTH];
     char name[DM_COMPONENT_MAX_NAME_LENGTH];
@@ -982,19 +987,21 @@ celix_bundle_context_t* celix_dmComponent_getBundleContext(celix_dm_component_t
     return result;
 }
 
-celix_status_t component_getComponentInfo(celix_dm_component_t *component, dm_component_info_pt *out) {
+celix_status_t component_getComponentInfo(celix_dm_component_t *component, celix_dm_component_info_t** out) {
     return celix_dmComponent_getComponentInfo(component, out);
 }
 
-celix_status_t celix_dmComponent_getComponentInfo(celix_dm_component_t *component, dm_component_info_pt *out) {
-    dm_component_info_pt info = calloc(1, sizeof(*info));
+celix_status_t celix_dmComponent_getComponentInfo(celix_dm_component_t *component, celix_dm_component_info_t** out) {
+    celix_dm_component_info_t* info = calloc(1, sizeof(*info));
     info->dependency_list = celix_arrayList_create();
     celix_dmComponent_getInterfaces(component, &info->interfaces);
 
     celixThreadMutex_lock(&component->mutex);
+    info->bundleId = celix_bundleContext_getBundleId(component->context);
+    info->bundleSymbolicName = celix_bundleContext_getBundleSymbolicName(component->context, info->bundleId);
     info->active = false;
-    memcpy(info->id, component->uuid, DM_COMPONENT_MAX_ID_LENGTH);
-    memcpy(info->name, component->name, DM_COMPONENT_MAX_NAME_LENGTH);
+    info->id = celix_utils_strdup(component->uuid);
+    info->name = celix_utils_strdup(component->name);
     info->nrOfTimesStarted = component->nrOfTimesStarted;
     info->nrOfTimesResumed = component->nrOfTimesResumed;
     celix_dm_component_state_t state = celix_dmComponent_currentState(component);
@@ -1012,14 +1019,88 @@ celix_status_t celix_dmComponent_getComponentInfo(celix_dm_component_t *componen
     *out = info;
     return CELIX_SUCCESS;
 }
-void component_destroyComponentInfo(dm_component_info_pt info) {
+
+
+static void celix_dmComponent_printFullInfo(FILE *out, bool colors, celix_dm_component_info_t* compInfo) {
+    const char *startColors = "";
+    const char *endColors = "";
+    if (colors) {
+        startColors = compInfo->active ? CELIX_DM_PRINT_OK_COLOR : CELIX_DM_PRINT_NOK_COLOR;
+        endColors = CELIX_DM_PRINT_END_COLOR;
+    }
+    fprintf(out, "%sComponent: Name=%s%s\n", startColors, compInfo->name, endColors);
+    fprintf(out, "|- UUID   = %s\n", compInfo->id);
+    fprintf(out, "|- Active = %s\n", compInfo->active ? "true" : "false");
+    fprintf(out, "|- State  = %s\n", compInfo->state);
+    fprintf(out, "|- Bundle = %li (%s)\n", compInfo->bundleId, compInfo->bundleSymbolicName);
+    fprintf(out, "|- Nr of times started = %i\n", (int)compInfo->nrOfTimesStarted);
+    fprintf(out, "|- Nr of times resumed = %i\n", (int)compInfo->nrOfTimesResumed);
+
+    fprintf(out, "|- Interfaces (%d):\n", celix_arrayList_size(compInfo->interfaces));
+    for (int interfCnt = 0; interfCnt < celix_arrayList_size(compInfo->interfaces); interfCnt++) {
+        dm_interface_info_pt intfInfo = celix_arrayList_get(compInfo->interfaces, interfCnt);
+        fprintf(out, "   |- %sInterface %i: %s%s\n", startColors, (interfCnt+1), intfInfo->name, endColors);
+
+        hash_map_iterator_t iter = hashMapIterator_construct((hash_map_pt) intfInfo->properties);
+        char *key = NULL;
+        while ((key = hashMapIterator_nextKey(&iter)) != NULL) {
+            fprintf(out, "      | %15s = %s\n", key, celix_properties_get(intfInfo->properties, key, "!ERROR!"));
+        }
+    }
+
+    fprintf(out, "|- Dependencies (%d):\n", celix_arrayList_size(compInfo->dependency_list));
+    for (int depCnt = 0; depCnt < celix_arrayList_size(compInfo->dependency_list); ++depCnt) {
+        dm_service_dependency_info_pt dependency;
+        dependency = celix_arrayList_get(compInfo->dependency_list, depCnt);
+        const char *depStartColors = "";
+        if (colors) {
+            if (dependency->required) {
+                depStartColors = dependency->available ? CELIX_DM_PRINT_OK_COLOR : CELIX_DM_PRINT_NOK_COLOR;
+            } else {
+                depStartColors = dependency->available ? CELIX_DM_PRINT_OK_COLOR : CELIX_DM_PRINT_WARNING_COLOR;
+            }
+        }
+        fprintf(out, "   |- %sDependency %i: %s%s\n", depStartColors, (depCnt+1), dependency->serviceName == NULL ? "(any)" : dependency->serviceName, endColors);
+        fprintf(out, "      | %15s = %s\n", "Available", dependency->available ? "true " : "false");
+        fprintf(out, "      | %15s = %s\n", "Required", dependency->required ? "true " : "false");
+        fprintf(out, "      | %15s = %s\n", "Version Range", dependency->versionRange == NULL ? "N/A" : dependency->versionRange);
+        fprintf(out, "      | %15s = %s\n", "Filter", dependency->filter == NULL ? "N/A" : dependency->filter);
+    }
+    fprintf(out, "\n");
+}
+
+static void celix_dmComponent_printBasicInfo(FILE *out, bool colors, celix_dm_component_info_t* compInfo) {
+    const char *startColors = "";
+    const char *endColors = "";
+    if (colors) {
+        startColors = compInfo->active ? CELIX_DM_PRINT_OK_COLOR : CELIX_DM_PRINT_NOK_COLOR;
+        endColors = CELIX_DM_PRINT_END_COLOR;
+    }
+    fprintf(out, "Component: Name=%s, ID=%s, %sActive=%s%s, State=%s, Bundle=%li (%s)\n",
+            compInfo->name, compInfo->id, startColors, compInfo->active ? "true " : "false", endColors,
+            compInfo->state, compInfo->bundleId, compInfo->bundleSymbolicName);
+}
+
+
+void celix_dmComponent_printComponentInfo(celix_dm_component_info_t* info, bool printFullInfo, bool useAnsiColors, FILE* stream) {
+    if (printFullInfo) {
+        celix_dmComponent_printFullInfo(stream, useAnsiColors, info);
+    } else {
+        celix_dmComponent_printBasicInfo(stream, useAnsiColors, info);
+    }
+}
+
+void component_destroyComponentInfo(celix_dm_component_info_t* info) {
     return celix_dmComponent_destroyComponentInfo(info);
 }
 
-void celix_dmComponent_destroyComponentInfo(dm_component_info_pt info) {
+void celix_dmComponent_destroyComponentInfo(celix_dm_component_info_t* info) {
     int i;
     int size;
     if (info != NULL) {
+        free(info->bundleSymbolicName);
+        free(info->id);
+        free(info->name);
         free(info->state);
 
         if (info->interfaces != NULL) {
diff --git a/libs/framework/src/dm_dependency_manager_impl.c b/libs/framework/src/dm_dependency_manager_impl.c
index 1277a2f2..3c0be71f 100644
--- a/libs/framework/src/dm_dependency_manager_impl.c
+++ b/libs/framework/src/dm_dependency_manager_impl.c
@@ -373,7 +373,30 @@ celix_status_t dependencyManager_getInfo(celix_dependency_manager_t *manager, dm
 	return status;
 }
 
-
 void dependencyManager_destroyInfo(celix_dependency_manager_t *manager, celix_dependency_manager_info_t *info) {
     celix_dependencyManager_destroyInfo(manager, info);
-}
\ No newline at end of file
+}
+
+static void celix_dependencyManager_printInfoForEntry(bool fullInfo, bool useAnsiColors, FILE* stream, celix_dependency_manager_info_t* mngInfo) {
+	for (int i = 0; i < celix_arrayList_size(mngInfo->components); ++i) {
+		celix_dm_component_info_t *cmpInfo = celix_arrayList_get(mngInfo->components, i);
+        celix_dmComponent_printComponentInfo(cmpInfo, fullInfo, useAnsiColors, stream);
+	}
+}
+
+void celix_dependencyManager_printInfo(celix_dependency_manager_t* manager, bool fullInfo, bool useAnsiColors, FILE* stream) {
+	celix_array_list_t *infos = celix_dependencyManager_createInfos(manager);
+	for (int i = 0; i< celix_arrayList_size(infos); ++i) {
+		celix_dependency_manager_info_t* mngInfo = celix_arrayList_get(infos, i);
+		celix_dependencyManager_printInfoForEntry(fullInfo, useAnsiColors, stream, mngInfo);
+	}
+	celix_dependencyManager_destroyInfos(manager, infos);
+}
+
+void celix_dependencyManager_printInfoForBundle(celix_dependency_manager_t* manager, bool fullInfo, bool useAnsiColors, long bundleId, FILE* stream) {
+	celix_dependency_manager_info_t* mngInfo = celix_dependencyManager_createInfo(manager, bundleId);
+    if (mngInfo != NULL) {
+        celix_dependencyManager_printInfoForEntry(fullInfo, useAnsiColors, stream, mngInfo);
+        celix_dependencyManager_destroyInfo(manager, mngInfo);
+    }
+}
diff --git a/libs/utils/include/celix/Utils.h b/libs/utils/include/celix/Utils.h
index aae33bc5..5a72e36a 100644
--- a/libs/utils/include/celix/Utils.h
+++ b/libs/utils/include/celix/Utils.h
@@ -160,6 +160,22 @@ namespace celix {
         }
     }
 
+    /**
+     * @brief Returns the inferred cmp type name for the template T if the providedCmpTypeName is empty.
+     *
+     * If the a non empty providedCmpTypeName is provided this will be returned.
+     * Otherwise the celix::impl::typeName will be used to infer the type name.
+     * celix::impl::typeName uses the macro __PRETTY_FUNCTION__ to extract a type name.
+     */
+    template<typename T>
+    std::string cmpTypeName(std::string_view providedCmpTypeName = "") {
+        if (!providedCmpTypeName.empty()) {
+            return std::string{providedCmpTypeName};
+        } else {
+            return celix::impl::extractTypeName<T>();
+        }
+    }
+
     /**
      * @brief Returns the inferred type version for the template I if the providedVersion is empty.
      *
@@ -218,6 +234,22 @@ namespace celix {
         }
     }
 
+    /**
+     * @brief Returns the inferred cmp type name for the template T if the providedCmpTypeName is empty.
+     *
+     * If the a non empty providedCmpTypeName is provided this will be returned.
+     * Otherwise the celix::impl::typeName will be used to infer the type name.
+     * celix::impl::typeName uses the macro __PRETTY_FUNCTION__ to extract a type name.
+     */
+    template<typename T>
+    std::string cmpTypeName(const std::string &providedCmpTypeName = "") {
+        if (!providedCmpTypeName.empty()) {
+            return providedCmpTypeName;
+        } else {
+            return celix::impl::extractTypeName<T>();
+        }
+    }
+
     /**
      * @brief Returns the type version.
      *