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:24 UTC

[celix] branch feature/print_function_for_dm_info created (now d6afb40a)

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

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


      at d6afb40a Adds print functions for dependency manager and dm cmp and refactors dm command to use these functions

This branch includes the following new commits:

     new d6afb40a Adds print functions for dependency manager and dm cmp and refactors dm command to use these functions

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



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

Posted by pn...@apache.org.
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.
      *