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 2020/02/09 13:11:29 UTC

[celix] branch feature/query_command updated: #144: Adds support for commands with namespace (e.g. celix::lb instead of lb)

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

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


The following commit(s) were added to refs/heads/feature/query_command by this push:
     new fc72865  #144: Adds support for commands with namespace (e.g. celix::lb instead of lb)
fc72865 is described below

commit fc72865cc7939aac763b181383c33e660e0d18af
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Sun Feb 9 14:11:07 2020 +0100

    #144: Adds support for commands with namespace (e.g. celix::lb instead of lb)
    
    - Updates existing to commands to include namespace
    - Updates shell so that local names can be used for command as long as there is no collision
    - Marks commandService->executeCommand as deprecated
---
 .../pubsub/pubsub_admin_tcp/src/psa_activator.c    |  12 +-
 .../pubsub/pubsub_admin_tcp/src/pubsub_tcp_admin.c |   2 +-
 .../pubsub/pubsub_admin_tcp/src/pubsub_tcp_admin.h |   2 +-
 .../pubsub/pubsub_admin_udp_mc/src/psa_activator.c |   2 +-
 .../pubsub_admin_udp_mc/src/pubsub_udpmc_admin.c   |   5 +-
 .../pubsub_admin_udp_mc/src/pubsub_udpmc_admin.h   |   2 +-
 .../pubsub_admin_websocket/src/psa_activator.c     |  12 +-
 .../src/pubsub_websocket_admin.c                   |   5 +-
 .../src/pubsub_websocket_admin.h                   |   2 +-
 .../pubsub/pubsub_admin_zmq/src/psa_activator.c    |  12 +-
 .../pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.c |   2 +-
 .../pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.h |   2 +-
 .../pubsub/pubsub_discovery/src/psd_activator.c    |  12 +-
 .../pubsub_discovery/src/pubsub_discovery_impl.c   |   4 +-
 .../pubsub_discovery/src/pubsub_discovery_impl.h   |   2 +-
 .../pubsub_topology_manager/src/pstm_activator.c   |  10 +-
 .../src/pubsub_topology_manager.c                  |  16 ++-
 .../src/pubsub_topology_manager.h                  |   4 +-
 bundles/shell/shell/CMakeLists.txt                 |   1 +
 bundles/shell/shell/deprecated_api/command.h       |   4 +-
 bundles/shell/shell/src/activator.c                |  24 ++--
 bundles/shell/shell/src/shell.c                    |  45 ++++++-
 bundles/shell/shell/src/shell_private.h            |   6 +-
 bundles/shell/shell/test/CMakeLists.txt            |   4 +
 bundles/shell/shell/test/src/shell_tests.cpp       | 134 ++++++++-------------
 libs/utils/include/celix_utils.h                   |  14 +++
 libs/utils/private/test/array_list_test.cpp        |   1 +
 libs/utils/private/test/celix_threads_test.cpp     |   1 +
 libs/utils/private/test/filter_test.cpp            |   1 +
 libs/utils/private/test/hash_map_test.cpp          |   1 +
 libs/utils/private/test/ip_utils_test.cpp          |   1 +
 libs/utils/private/test/linked_list_test.cpp       |   1 +
 libs/utils/private/test/properties_test.cpp        |   1 +
 libs/utils/private/test/thread_pool_test.cpp       |   1 +
 libs/utils/private/test/utils_test.cpp             |  79 ++++++++++--
 libs/utils/private/test/version_range_test.cpp     |   1 +
 libs/utils/private/test/version_test.cpp           |   1 +
 libs/utils/src/utils.c                             |  57 +++++++++
 38 files changed, 324 insertions(+), 162 deletions(-)

diff --git a/bundles/pubsub/pubsub_admin_tcp/src/psa_activator.c b/bundles/pubsub/pubsub_admin_tcp/src/psa_activator.c
index 0ea6a97..438c8e4 100644
--- a/bundles/pubsub/pubsub_admin_tcp/src/psa_activator.c
+++ b/bundles/pubsub/pubsub_admin_tcp/src/psa_activator.c
@@ -26,7 +26,7 @@
 #include "pubsub_admin.h"
 #include "pubsub_admin_metrics.h"
 #include "pubsub_tcp_admin.h"
-#include "command.h"
+#include "celix_shell_command.h"
 
 typedef struct psa_tcp_activator {
     log_helper_t *logHelper;
@@ -41,7 +41,7 @@ typedef struct psa_tcp_activator {
     pubsub_admin_metrics_service_t adminMetricsService;
     long adminMetricsSvcId;
 
-    command_service_t cmdSvc;
+    celix_shell_command_t cmdSvc;
     long cmdSvcId;
 } psa_tcp_activator_t;
 
@@ -102,10 +102,10 @@ int psa_tcp_start(psa_tcp_activator_t *act, celix_bundle_context_t *ctx) {
         act->cmdSvc.handle = act->admin;
         act->cmdSvc.executeCommand = pubsub_tcpAdmin_executeCommand;
         celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, OSGI_SHELL_COMMAND_NAME, "psa_tcp");
-        celix_properties_set(props, OSGI_SHELL_COMMAND_USAGE, "psa_tcp");
-        celix_properties_set(props, OSGI_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the TCP PSA");
-        act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, OSGI_SHELL_COMMAND_SERVICE_NAME, props);
+        celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psa_tcp");
+        celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psa_tcp");
+        celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the TCP PSA");
+        act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props);
     }
 
     return status;
diff --git a/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_admin.c b/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_admin.c
index d49c5eb..5c871de 100644
--- a/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_admin.c
+++ b/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_admin.c
@@ -619,7 +619,7 @@ celix_status_t pubsub_tcpAdmin_removeDiscoveredEndpoint(void *handle, const celi
     return status;
 }
 
-celix_status_t pubsub_tcpAdmin_executeCommand(void *handle, char *commandLine __attribute__((unused)), FILE *out, FILE *errStream __attribute__((unused))) {
+bool pubsub_tcpAdmin_executeCommand(void *handle, const char *commandLine __attribute__((unused)), FILE *out, FILE *errStream __attribute__((unused))) {
     pubsub_tcp_admin_t *psa = handle;
     celix_status_t  status = CELIX_SUCCESS;
 
diff --git a/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_admin.h b/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_admin.h
index 9c2be19..7ed1702 100644
--- a/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_admin.h
+++ b/bundles/pubsub/pubsub_admin_tcp/src/pubsub_tcp_admin.h
@@ -46,7 +46,7 @@ celix_status_t pubsub_tcpAdmin_removeDiscoveredEndpoint(void *handle, const celi
 void pubsub_tcpAdmin_addSerializerSvc(void *handle, void *svc, const celix_properties_t *props);
 void pubsub_tcpAdmin_removeSerializerSvc(void *handle, void *svc, const celix_properties_t *props);
 
-celix_status_t pubsub_tcpAdmin_executeCommand(void *handle, char *commandLine, FILE *outStream, FILE *errStream);
+bool pubsub_tcpAdmin_executeCommand(void *handle, const char *commandLine, FILE *outStream, FILE *errStream);
 
 pubsub_admin_metrics_t* pubsub_tcpAdmin_metrics(void *handle);
 
diff --git a/bundles/pubsub/pubsub_admin_udp_mc/src/psa_activator.c b/bundles/pubsub/pubsub_admin_udp_mc/src/psa_activator.c
index ef887c9..fec1558 100644
--- a/bundles/pubsub/pubsub_admin_udp_mc/src/psa_activator.c
+++ b/bundles/pubsub/pubsub_admin_udp_mc/src/psa_activator.c
@@ -89,7 +89,7 @@ int psa_udpmc_start(psa_udpmc_activator_t *act, celix_bundle_context_t *ctx) {
         act->cmdSvc.handle = act->admin;
         act->cmdSvc.executeCommand = pubsub_udpmcAdmin_executeCommand;
         celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "psa_udpmc");
+        celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psa_udpmc");
         celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psa_udpmc");
         celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the UDPMC PSA");
         act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props);
diff --git a/bundles/pubsub/pubsub_admin_udp_mc/src/pubsub_udpmc_admin.c b/bundles/pubsub/pubsub_admin_udp_mc/src/pubsub_udpmc_admin.c
index 86fe3c2..7dfd00f 100644
--- a/bundles/pubsub/pubsub_admin_udp_mc/src/pubsub_udpmc_admin.c
+++ b/bundles/pubsub/pubsub_admin_udp_mc/src/pubsub_udpmc_admin.c
@@ -554,9 +554,8 @@ celix_status_t pubsub_udpmcAdmin_removeEndpoint(void *handle, const celix_proper
     return status;
 }
 
-celix_status_t pubsub_udpmcAdmin_executeCommand(void *handle, char *commandLine __attribute__((unused)), FILE *out, FILE *errStream __attribute__((unused))) {
+bool pubsub_udpmcAdmin_executeCommand(void *handle, const char *commandLine __attribute__((unused)), FILE *out, FILE *errStream __attribute__((unused))) {
     pubsub_udpmc_admin_t *psa = handle;
-    celix_status_t  status = CELIX_SUCCESS;
 
     fprintf(out, "\n");
     fprintf(out, "Topic Senders:\n");
@@ -610,7 +609,7 @@ celix_status_t pubsub_udpmcAdmin_executeCommand(void *handle, char *commandLine
     fprintf(out, "\n");
 
 
-    return status;
+    return true;
 }
 
 void pubsub_udpmcAdmin_addSerializerSvc(void *handle, void *svc, const celix_properties_t *props) {
diff --git a/bundles/pubsub/pubsub_admin_udp_mc/src/pubsub_udpmc_admin.h b/bundles/pubsub/pubsub_admin_udp_mc/src/pubsub_udpmc_admin.h
index 84cc055..6a42c5e 100644
--- a/bundles/pubsub/pubsub_admin_udp_mc/src/pubsub_udpmc_admin.h
+++ b/bundles/pubsub/pubsub_admin_udp_mc/src/pubsub_udpmc_admin.h
@@ -45,7 +45,7 @@ void pubsub_udpmcAdmin_removeSerializerSvc(void *handle, void *svc, const celix_
 celix_status_t pubsub_udpmcAdmin_addEndpoint(void *handle, const celix_properties_t *endpoint);
 celix_status_t pubsub_udpmcAdmin_removeEndpoint(void *handle, const celix_properties_t *endpoint);
 
-celix_status_t pubsub_udpmcAdmin_executeCommand(void *handle, char *commandLine, FILE *outStream, FILE *errStream);
+bool pubsub_udpmcAdmin_executeCommand(void *handle, const char *commandLine, FILE *outStream, FILE *errStream);
 
 #endif //CELIX_PUBSUB_UDPMC_ADMIN_H
 
diff --git a/bundles/pubsub/pubsub_admin_websocket/src/psa_activator.c b/bundles/pubsub/pubsub_admin_websocket/src/psa_activator.c
index 4dca5a9..31143ee 100644
--- a/bundles/pubsub/pubsub_admin_websocket/src/psa_activator.c
+++ b/bundles/pubsub/pubsub_admin_websocket/src/psa_activator.c
@@ -26,7 +26,7 @@
 #include "pubsub_admin.h"
 #include "pubsub_admin_metrics.h"
 #include "pubsub_websocket_admin.h"
-#include "command.h"
+#include "celix_shell_command.h"
 
 typedef struct psa_websocket_activator {
     log_helper_t *logHelper;
@@ -41,7 +41,7 @@ typedef struct psa_websocket_activator {
     pubsub_admin_metrics_service_t adminMetricsService;
     long adminMetricsSvcId;
 
-    command_service_t cmdSvc;
+    celix_shell_command_t cmdSvc;
     long cmdSvcId;
 } psa_websocket_activator_t;
 
@@ -103,10 +103,10 @@ int psa_websocket_start(psa_websocket_activator_t *act, celix_bundle_context_t *
         act->cmdSvc.handle = act->admin;
         act->cmdSvc.executeCommand = pubsub_websocketAdmin_executeCommand;
         celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, OSGI_SHELL_COMMAND_NAME, "psa_websocket");
-        celix_properties_set(props, OSGI_SHELL_COMMAND_USAGE, "psa_websocket");
-        celix_properties_set(props, OSGI_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the websocket PSA");
-        act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, OSGI_SHELL_COMMAND_SERVICE_NAME, props);
+        celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psa_websocket");
+        celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psa_websocket");
+        celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the websocket PSA");
+        act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props);
     }
 
     return status;
diff --git a/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_admin.c b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_admin.c
index e0a4bb0..6fa32b7 100644
--- a/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_admin.c
+++ b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_admin.c
@@ -547,9 +547,8 @@ celix_status_t pubsub_websocketAdmin_removeDiscoveredEndpoint(void *handle, cons
     return status;
 }
 
-celix_status_t pubsub_websocketAdmin_executeCommand(void *handle, char *commandLine __attribute__((unused)), FILE *out, FILE *errStream __attribute__((unused))) {
+bool pubsub_websocketAdmin_executeCommand(void *handle, const char *commandLine __attribute__((unused)), FILE *out, FILE *errStream __attribute__((unused))) {
     pubsub_websocket_admin_t *psa = handle;
-    celix_status_t  status = CELIX_SUCCESS;
 
     fprintf(out, "\n");
     fprintf(out, "Topic Senders:\n");
@@ -609,7 +608,7 @@ celix_status_t pubsub_websocketAdmin_executeCommand(void *handle, char *commandL
     celixThreadMutex_unlock(&psa->serializers.mutex);
     fprintf(out, "\n");
 
-    return status;
+    return true;
 }
 
 pubsub_admin_metrics_t* pubsub_websocketAdmin_metrics(void *handle) {
diff --git a/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_admin.h b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_admin.h
index 120ef1e..c718a3b 100644
--- a/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_admin.h
+++ b/bundles/pubsub/pubsub_admin_websocket/src/pubsub_websocket_admin.h
@@ -46,7 +46,7 @@ celix_status_t pubsub_websocketAdmin_removeDiscoveredEndpoint(void *handle, cons
 void pubsub_websocketAdmin_addSerializerSvc(void *handle, void *svc, const celix_properties_t *props);
 void pubsub_websocketAdmin_removeSerializerSvc(void *handle, void *svc, const celix_properties_t *props);
 
-celix_status_t pubsub_websocketAdmin_executeCommand(void *handle, char *commandLine, FILE *outStream, FILE *errStream);
+bool pubsub_websocketAdmin_executeCommand(void *handle, const char *commandLine, FILE *outStream, FILE *errStream);
 
 pubsub_admin_metrics_t* pubsub_websocketAdmin_metrics(void *handle);
 
diff --git a/bundles/pubsub/pubsub_admin_zmq/src/psa_activator.c b/bundles/pubsub/pubsub_admin_zmq/src/psa_activator.c
index 9b8d26e..3e66f42 100644
--- a/bundles/pubsub/pubsub_admin_zmq/src/psa_activator.c
+++ b/bundles/pubsub/pubsub_admin_zmq/src/psa_activator.c
@@ -26,7 +26,7 @@
 #include "pubsub_admin.h"
 #include "pubsub_admin_metrics.h"
 #include "pubsub_zmq_admin.h"
-#include "command.h"
+#include "celix_shell_command.h"
 
 typedef struct psa_zmq_activator {
     log_helper_t *logHelper;
@@ -41,7 +41,7 @@ typedef struct psa_zmq_activator {
     pubsub_admin_metrics_service_t adminMetricsService;
     long adminMetricsSvcId;
 
-    command_service_t cmdSvc;
+    celix_shell_command_t cmdSvc;
     long cmdSvcId;
 } psa_zmq_activator_t;
 
@@ -102,10 +102,10 @@ int psa_zmq_start(psa_zmq_activator_t *act, celix_bundle_context_t *ctx) {
         act->cmdSvc.handle = act->admin;
         act->cmdSvc.executeCommand = pubsub_zmqAdmin_executeCommand;
         celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, OSGI_SHELL_COMMAND_NAME, "psa_zmq");
-        celix_properties_set(props, OSGI_SHELL_COMMAND_USAGE, "psa_zmq");
-        celix_properties_set(props, OSGI_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the ZMQ PSA");
-        act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, OSGI_SHELL_COMMAND_SERVICE_NAME, props);
+        celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psa_zmq");
+        celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psa_zmq");
+        celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Print the information about the TopicSender and TopicReceivers for the ZMQ PSA");
+        act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props);
     }
 
     return status;
diff --git a/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.c b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.c
index 83e38ea..e7241e6 100644
--- a/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.c
+++ b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.c
@@ -634,7 +634,7 @@ celix_status_t pubsub_zmqAdmin_removeDiscoveredEndpoint(void *handle, const celi
     return status;
 }
 
-celix_status_t pubsub_zmqAdmin_executeCommand(void *handle, char *commandLine __attribute__((unused)), FILE *out, FILE *errStream __attribute__((unused))) {
+bool pubsub_zmqAdmin_executeCommand(void *handle, const char *commandLine __attribute__((unused)), FILE *out, FILE *errStream __attribute__((unused))) {
     pubsub_zmq_admin_t *psa = handle;
     celix_status_t  status = CELIX_SUCCESS;
 
diff --git a/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.h b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.h
index 35c09ce..8d8c7c0 100644
--- a/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.h
+++ b/bundles/pubsub/pubsub_admin_zmq/src/pubsub_zmq_admin.h
@@ -46,7 +46,7 @@ celix_status_t pubsub_zmqAdmin_removeDiscoveredEndpoint(void *handle, const celi
 void pubsub_zmqAdmin_addSerializerSvc(void *handle, void *svc, const celix_properties_t *props);
 void pubsub_zmqAdmin_removeSerializerSvc(void *handle, void *svc, const celix_properties_t *props);
 
-celix_status_t pubsub_zmqAdmin_executeCommand(void *handle, char *commandLine, FILE *outStream, FILE *errStream);
+bool pubsub_zmqAdmin_executeCommand(void *handle, const char *commandLine, FILE *outStream, FILE *errStream);
 
 pubsub_admin_metrics_t* pubsub_zmqAdmin_metrics(void *handle);
 
diff --git a/bundles/pubsub/pubsub_discovery/src/psd_activator.c b/bundles/pubsub/pubsub_discovery/src/psd_activator.c
index 2a364f3..ef209cf 100644
--- a/bundles/pubsub/pubsub_discovery/src/psd_activator.c
+++ b/bundles/pubsub/pubsub_discovery/src/psd_activator.c
@@ -22,7 +22,7 @@
 #include <string.h>
 
 #include "log_helper.h"
-#include "command.h"
+#include "celix_shell_command.h"
 
 #include "celix_bundle_context.h"
 #include "celix_bundle_activator.h"
@@ -41,7 +41,7 @@ typedef struct psd_activator {
     pubsub_announce_endpoint_listener_t listenerSvc;
     long listenerSvcId;
 
-    command_service_t cmdSvc;
+    celix_shell_command_t cmdSvc;
     long cmdSvcId;
 
     log_helper_t *loghelper;
@@ -74,10 +74,10 @@ static celix_status_t psd_start(psd_activator_t *act, celix_bundle_context_t *ct
         act->cmdSvc.handle = act->pubsub_discovery;
         act->cmdSvc.executeCommand = pubsub_discovery_executeCommand;
         celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, OSGI_SHELL_COMMAND_NAME, "psd_etcd");
-        celix_properties_set(props, OSGI_SHELL_COMMAND_USAGE, "psd_etcd"); //TODO add search topic/scope option
-        celix_properties_set(props, OSGI_SHELL_COMMAND_DESCRIPTION, "Overview of discovered/announced endpoints from/to ETCD");
-        act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, OSGI_SHELL_COMMAND_SERVICE_NAME, props);
+        celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::psd_etcd");
+        celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "psd_etcd");
+        celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "Overview of discovered/announced endpoints from/to ETCD");
+        act->cmdSvcId = celix_bundleContext_registerService(ctx, &act->cmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props);
     }
 
     if (status == CELIX_SUCCESS) {
diff --git a/bundles/pubsub/pubsub_discovery/src/pubsub_discovery_impl.c b/bundles/pubsub/pubsub_discovery/src/pubsub_discovery_impl.c
index 7e847c5..3e9eab6 100644
--- a/bundles/pubsub/pubsub_discovery/src/pubsub_discovery_impl.c
+++ b/bundles/pubsub/pubsub_discovery/src/pubsub_discovery_impl.c
@@ -581,7 +581,7 @@ static char* pubsub_discovery_createJsonEndpoint(const celix_properties_t *props
     return str;
 }
 
-celix_status_t pubsub_discovery_executeCommand(void *handle, char * commandLine __attribute__((unused)), FILE *os, FILE *errorStream __attribute__((unused))) {
+bool pubsub_discovery_executeCommand(void *handle, const char * commandLine __attribute__((unused)), FILE *os, FILE *errorStream __attribute__((unused))) {
     pubsub_discovery_t *disc = handle;
 
     struct timespec now;
@@ -646,5 +646,5 @@ celix_status_t pubsub_discovery_executeCommand(void *handle, char * commandLine
     }
     celixThreadMutex_unlock(&disc->announcedEndpointsMutex);
 
-    return CELIX_SUCCESS;
+    return true;
 }
diff --git a/bundles/pubsub/pubsub_discovery/src/pubsub_discovery_impl.h b/bundles/pubsub/pubsub_discovery/src/pubsub_discovery_impl.h
index 6cc7151..6d69d0c 100644
--- a/bundles/pubsub/pubsub_discovery/src/pubsub_discovery_impl.h
+++ b/bundles/pubsub/pubsub_discovery/src/pubsub_discovery_impl.h
@@ -98,7 +98,7 @@ void pubsub_discovery_discoveredEndpointsListenerRemoved(void *handle, void *svc
 celix_status_t pubsub_discovery_announceEndpoint(void *handle, const celix_properties_t *endpoint);
 celix_status_t pubsub_discovery_revokeEndpoint(void *handle, const celix_properties_t *endpoint);
 
-celix_status_t pubsub_discovery_executeCommand(void *handle, char * commandLine, FILE *os, FILE *errorStream);
+bool pubsub_discovery_executeCommand(void *handle, const char * commandLine, FILE *os, FILE *errorStream);
 
 
 #endif /* PUBSUB_DISCOVERY_IMPL_H_ */
diff --git a/bundles/pubsub/pubsub_topology_manager/src/pstm_activator.c b/bundles/pubsub/pubsub_topology_manager/src/pstm_activator.c
index 40f3fa9..8c551aa 100644
--- a/bundles/pubsub/pubsub_topology_manager/src/pstm_activator.c
+++ b/bundles/pubsub/pubsub_topology_manager/src/pstm_activator.c
@@ -44,7 +44,7 @@ typedef struct pstm_activator {
     pubsub_discovered_endpoint_listener_t discListenerSvc;
     long discListenerSvcId;
 
-    command_service_t shellCmdSvc;
+    celix_shell_command_t shellCmdSvc;
     long shellCmdSvcId;
 
     log_helper_t *loghelper;
@@ -131,10 +131,10 @@ static int pstm_start(pstm_activator_t *act, celix_bundle_context_t *ctx) {
         act->shellCmdSvc.handle = act->manager;
         act->shellCmdSvc.executeCommand = pubsub_topologyManager_shellCommand;
         celix_properties_t *props = celix_properties_create();
-        celix_properties_set(props, OSGI_SHELL_COMMAND_NAME, "pstm");
-        celix_properties_set(props, OSGI_SHELL_COMMAND_USAGE, "pstm [topology|metrics]"); //TODO add search topic/scope option
-        celix_properties_set(props, OSGI_SHELL_COMMAND_DESCRIPTION, "pubsub_topology_info: Overview of Topology information for PubSub");
-        act->shellCmdSvcId = celix_bundleContext_registerService(ctx, &act->shellCmdSvc, OSGI_SHELL_COMMAND_SERVICE_NAME, props);
+        celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "celix::pstm");
+        celix_properties_set(props, CELIX_SHELL_COMMAND_USAGE, "pstm [topology|metrics]"); //TODO add search topic/scope option
+        celix_properties_set(props, CELIX_SHELL_COMMAND_DESCRIPTION, "pubsub_topology_info: Overview of Topology information for PubSub");
+        act->shellCmdSvcId = celix_bundleContext_registerService(ctx, &act->shellCmdSvc, CELIX_SHELL_COMMAND_SERVICE_NAME, props);
     }
 
     //TODO add tracker for pubsub_serializer and
diff --git a/bundles/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c b/bundles/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c
index b6bd10a..a8388bb 100644
--- a/bundles/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c
+++ b/bundles/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.c
@@ -972,7 +972,7 @@ void pubsub_topologyManager_removeMetricsService(void * handle, void *svc, const
 }
 
 
-static celix_status_t pubsub_topologyManager_topology(pubsub_topology_manager_t *manager, char *commandLine __attribute__((unused)), FILE *os, FILE *errorStream __attribute__((unused))) {
+static celix_status_t pubsub_topologyManager_topology(pubsub_topology_manager_t *manager, const char *commandLine __attribute__((unused)), FILE *os, FILE *errorStream __attribute__((unused))) {
     fprintf(os, "\n");
 
     fprintf(os, "Discovered Endpoints: \n");
@@ -1113,7 +1113,7 @@ static void fetchBundleName(void *handle, const bundle_t *bundle) {
     *out = celix_bundle_getSymbolicName(bundle);
 }
 
-static celix_status_t pubsub_topologyManager_metrics(pubsub_topology_manager_t *manager, char *commandLine __attribute__((unused)), FILE *os, FILE *errorStream __attribute__((unused))) {
+static celix_status_t pubsub_topologyManager_metrics(pubsub_topology_manager_t *manager, const char *commandLine __attribute__((unused)), FILE *os, FILE *errorStream __attribute__((unused))) {
     celix_array_list_t *psaMetrics = celix_arrayList_create();
     celixThreadMutex_lock(&manager->psaMetrics.mutex);
     hash_map_iterator_t iter = hashMapIterator_construct(manager->psaMetrics.map);
@@ -1177,17 +1177,21 @@ static celix_status_t pubsub_topologyManager_metrics(pubsub_topology_manager_t *
     return CELIX_SUCCESS;
 }
 
-celix_status_t pubsub_topologyManager_shellCommand(void *handle, char *commandLine, FILE *os, FILE *errorStream) {
+bool pubsub_topologyManager_shellCommand(void *handle, const char *commandLine, FILE *os, FILE *errorStream) {
     pubsub_topology_manager_t *manager = handle;
 
     static const char * topCmd = "pstm t"; //"topology";
     static const char * metricsCmd = "pstm m"; //"metrics"
 
+    celix_status_t status;
+
     if (strncmp(commandLine, topCmd, strlen(topCmd)) == 0) {
-        return pubsub_topologyManager_topology(manager, commandLine, os, errorStream);
+        status = pubsub_topologyManager_topology(manager, commandLine, os, errorStream);
     } else if (strncmp(commandLine, metricsCmd, strlen(metricsCmd)) == 0) {
-        return pubsub_topologyManager_metrics(manager, commandLine, os, errorStream);
+        status = pubsub_topologyManager_metrics(manager, commandLine, os, errorStream);
     } else { //default
-        return pubsub_topologyManager_topology(manager, commandLine, os, errorStream);
+        status = pubsub_topologyManager_topology(manager, commandLine, os, errorStream);
     }
+
+    return status == CELIX_SUCCESS;
 }
diff --git a/bundles/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.h b/bundles/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.h
index 92bb1e9..8e88641 100644
--- a/bundles/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.h
+++ b/bundles/pubsub/pubsub_topology_manager/src/pubsub_topology_manager.h
@@ -23,7 +23,7 @@
 #include "service_reference.h"
 #include "bundle_context.h"
 #include "log_helper.h"
-#include "command.h"
+#include "celix_shell_command.h"
 #include "celix_bundle_context.h"
 
 #include "pubsub_endpoint.h"
@@ -124,7 +124,7 @@ void pubsub_topologyManager_publisherTrackerRemoved(void *handle, const celix_se
 celix_status_t pubsub_topologyManager_addDiscoveredEndpoint(void *handle, const celix_properties_t *properties);
 celix_status_t pubsub_topologyManager_removeDiscoveredEndpoint(void *handle, const celix_properties_t *properties);
 
-celix_status_t pubsub_topologyManager_shellCommand(void *handle, char * commandLine, FILE *outStream, FILE *errorStream);
+bool pubsub_topologyManager_shellCommand(void *handle, const char * commandLine, FILE *outStream, FILE *errorStream);
 
 void pubsub_topologyManager_addMetricsService(void * handle, void *svc, const celix_properties_t *props);
 void pubsub_topologyManager_removeMetricsService(void * handle, void *svc, const celix_properties_t *props);
diff --git a/bundles/shell/shell/CMakeLists.txt b/bundles/shell/shell/CMakeLists.txt
index 35e4b53..1331823 100644
--- a/bundles/shell/shell/CMakeLists.txt
+++ b/bundles/shell/shell/CMakeLists.txt
@@ -53,6 +53,7 @@ if (SHELL)
 	)
 	target_include_directories(shell PRIVATE src)
 	target_link_libraries(shell PRIVATE Celix::shell_api CURL::libcurl Celix::log_service_api Celix::log_helper)
+	target_compile_options(shell PRIVATE -Wno-deprecated-declarations)
 	if (CELIX_ADD_DEPRECATED_API)
 		target_compile_definitions(shell PRIVATE CELIX_ADD_DEPRECATED_API)
 	endif ()
diff --git a/bundles/shell/shell/deprecated_api/command.h b/bundles/shell/shell/deprecated_api/command.h
index 3629c70..a65b3e3 100644
--- a/bundles/shell/shell/deprecated_api/command.h
+++ b/bundles/shell/shell/deprecated_api/command.h
@@ -44,7 +44,9 @@ typedef command_service_t * command_service_pt;
  */
 struct commandService {
     void *handle;
-    celix_status_t (*executeCommand)(void *handle, char * commandLine, FILE *outStream, FILE *errorStream);
+
+    celix_status_t (*executeCommand)(void *handle, char * commandLine, FILE *outStream, FILE *errorStream)
+        __attribute__((deprecated("command_service_t is replaced by celix_shell_command_t in celix_shell_command.h")));
 };
 
 
diff --git a/bundles/shell/shell/src/activator.c b/bundles/shell/shell/src/activator.c
index 25d74c1..6e0d80c 100644
--- a/bundles/shell/shell/src/activator.c
+++ b/bundles/shell/shell/src/activator.c
@@ -76,7 +76,7 @@ celix_status_t bundleActivator_create(celix_bundle_context_t* ctx, void **_pptr)
         activator->std_commands[0] =
                 (struct celix_shell_command_register_entry) {
                         .exec = lbCommand_execute,
-                        .name = "lb",
+                        .name = "celix::lb",
                         .description = "list bundles. Default only the groupless bundles are listed. Use -a to list all bundles." \
                             "\nIf a group string is provided only bundles matching the group string will be listed." \
                             "\nUse -l to print the bundle locations.\nUse -s to print the bundle symbolic names\nUse -u to print the bundle update location.",
@@ -85,63 +85,63 @@ celix_status_t bundleActivator_create(celix_bundle_context_t* ctx, void **_pptr)
         activator->std_commands[1] =
                 (struct celix_shell_command_register_entry) {
                         .exec = startCommand_execute,
-                        .name = "start",
+                        .name = "celix::start",
                         .description = "start bundle(s).",
                         .usage = "start <id> [<id> ...]"
                 };
         activator->std_commands[2] =
                 (struct celix_shell_command_register_entry) {
                         .exec = stopCommand_execute,
-                        .name = "stop",
+                        .name = "celix::stop",
                         .description = "stop bundle(s).",
                         .usage = "stop <id> [<id> ...]"
                 };
         activator->std_commands[3] =
                 (struct celix_shell_command_register_entry) {
                         .exec = installCommand_execute,
-                        .name = "install",
+                        .name = "celix::install",
                         .description = "install bundle(s).",
                         .usage = "install <file> [<file> ...]"
                 };
         activator->std_commands[4] =
                 (struct celix_shell_command_register_entry) {
                         .exec = uninstallCommand_execute,
-                        .name = "uninstall",
+                        .name = "celix::uninstall",
                         .description = "uninstall bundle(s).",
                         .usage = "uninstall <file> [<file> ...]"
                 };
         activator->std_commands[5] =
                 (struct celix_shell_command_register_entry) {
                         .exec = updateCommand_execute,
-                        .name = "update",
+                        .name = "celix::update",
                         .description = "update bundle(s).",
                         .usage = "update <id> [<URL>]"
                 };
         activator->std_commands[6] =
                 (struct celix_shell_command_register_entry) {
                         .exec = helpCommand_execute,
-                        .name = "help",
+                        .name = "celix::help",
                         .description = "display available commands and description.",
                         .usage = "help <command>]"
                 };
         activator->std_commands[7] =
                 (struct celix_shell_command_register_entry) {
                         .exec = logCommand_execute,
-                        .name = "log",
+                        .name = "celix::log",
                         .description = "print log.",
                         .usage = "log"
                 };
         activator->std_commands[8] =
                 (struct celix_shell_command_register_entry) {
                         .exec = dmListCommand_execute,
-                        .name = "dm",
+                        .name = "celix::dm",
                         .description = "Gives an overview of the component managed by a dependency manager.",
                         .usage = "dm [wtf] [f|full] [<Bundle ID> [<Bundle ID> [...]]]"
                 };
         activator->std_commands[9] =
                 (struct celix_shell_command_register_entry) {
                     .exec = queryCommand_execute,
-                    .name = "query",
+                    .name = "celix::query",
                     .description = "Query services. Query for registered and requested services" \
                     "\nIf a query is provided (or multiple), only service with a service name matching the query will be displayed." \
                     "\nIf a query is a (LDAP) filter, filter matching will be used."
@@ -154,14 +154,14 @@ celix_status_t bundleActivator_create(celix_bundle_context_t* ctx, void **_pptr)
         activator->std_commands[10] =
                 (struct celix_shell_command_register_entry) {
                         .exec = queryCommand_execute,
-                        .name = "q",
+                        .name = "celix::q",
                         .description = "Proxy for query command (see 'help query')",
                         .usage = "q [bundleId ...] [-v] [-p] [-r] [query ...]"
                 };
         activator->std_commands[11] =
               (struct celix_shell_command_register_entry) {
                       .exec = quitCommand_execute,
-                      .name = "quit",
+                      .name = "celix::quit",
                       .description = "Quit (exit) framework.",
                       .usage = "quit"
               };
diff --git a/bundles/shell/shell/src/shell.c b/bundles/shell/shell/src/shell.c
index b6a45b3..1c2375b 100644
--- a/bundles/shell/shell/src/shell.c
+++ b/bundles/shell/shell/src/shell.c
@@ -28,7 +28,6 @@
 #include "shell_private.h"
 #include "utils.h"
 
-
 shell_t* shell_create(celix_bundle_context_t *ctx) {
     shell_t *shell = calloc(1, sizeof(*shell));
 
@@ -55,6 +54,7 @@ void shell_destroy(shell_t *shell) {
     }
 }
 
+
 celix_status_t shell_addCommand(shell_t *shell, celix_shell_command_t *svc, const celix_properties_t *props) {
     celix_status_t status = CELIX_SUCCESS;
     const char *name = celix_properties_get(props, CELIX_SHELL_COMMAND_NAME, NULL);
@@ -69,9 +69,14 @@ celix_status_t shell_addCommand(shell_t *shell, celix_shell_command_t *svc, cons
             logHelper_log(shell->logHelper, OSGI_LOGSERVICE_WARNING, "Command with name %s already registered!", name);
         } else {
             celix_shell_command_entry_t *entry = calloc(1, sizeof(*entry));
+            char *localName = NULL;
+            char *ns = NULL;
+            celix_utils_extractLocalNameAndNamespaceFromFullyQualifiedName(name, "::", &localName, &ns);
             entry->svcId = svcId;
             entry->svc = svc;
             entry->props = props;
+            entry->namespace = ns;
+            entry->localName = localName;
             hashMap_put(shell->commandServices, (void*)name, entry);
         }
         celixThreadMutex_unlock(&shell->mutex);
@@ -94,6 +99,8 @@ celix_status_t shell_removeCommand(shell_t *shell, celix_shell_command_t *svc, c
             celix_shell_command_entry_t *entry = hashMap_get(shell->commandServices, name);
             if (entry->svcId == svcId) {
                 hashMap_remove(shell->commandServices, name);
+                free(entry->localName);
+                free(entry->namespace);
                 free(entry);
             } else {
                 logHelper_log(shell->logHelper, OSGI_LOGSERVICE_WARNING, "svc id for command with name %s does not match (%li == %li)!", name, svcId, entry->svcId);
@@ -227,6 +234,34 @@ celix_status_t shell_getCommandDescription(shell_t *shell, const char *commandNa
     return status;
 }
 
+static celix_shell_command_entry_t * shell_findEntry(shell_t *shell, const char *cmdName, FILE *err) {
+    //NOTE precondition shell->mutex locked
+    celix_shell_command_entry_t *result = NULL;
+    int entriesFound = 0;
+    const char *substr = strstr(cmdName, "::");
+    if (substr == NULL) {
+        //only local name given, need to search
+        hash_map_iterator_t iter = hashMapIterator_construct(shell->commandServices);
+        while (hashMapIterator_hasNext(&iter)) {
+            celix_shell_command_entry_t *visit = hashMapIterator_nextValue(&iter);
+            if (strncmp(visit->localName, cmdName, 1024) == 0) {
+                entriesFound ++;
+                result = visit;
+            }
+        }
+    } else {
+        //:: present, assuming fully qualified name given, can just lookup
+        result = hashMap_get(shell->commandServices, cmdName);
+    }
+
+    if (entriesFound > 1 ) {
+        fprintf(err, "Got more than 1 command with the name '%s', found %i. Please use the fully qualified name for the requested command.\n", cmdName, entriesFound);
+        result = NULL;
+    }
+
+    return result;
+}
+
 celix_status_t shell_executeCommand(shell_t *shell, const char *commandLine, FILE *out, FILE *err) {
 	celix_status_t status = CELIX_SUCCESS;
 
@@ -234,14 +269,16 @@ celix_status_t shell_executeCommand(shell_t *shell, const char *commandLine, FIL
 
     char *commandName = (pos != strlen(commandLine)) ? strndup(commandLine, pos) : strdup(commandLine);
 
+
     celixThreadMutex_lock(&shell->mutex);
-    celix_shell_command_entry_t *entry = hashMap_get(shell->commandServices, commandName);
+    celix_shell_command_entry_t *entry = shell_findEntry(shell, commandName, err);
     celix_legacy_command_entry_t *legacyEntry = hashMap_get(shell->legacyCommandServices, commandName);
     if (entry != NULL) {
-        entry->svc->executeCommand(entry->svc->handle, commandLine, out, err);
+        bool succeeded = entry->svc->executeCommand(entry->svc->handle, commandLine, out, err);
+        status = succeeded ? CELIX_SUCCESS : CELIX_BUNDLE_EXCEPTION;
     } else if (legacyEntry != NULL) {
         char *cl = (void*)commandLine; //NOTE this is needed for the legacy command services (also the reason why it is legacy/deprecated)
-        legacyEntry->svc->executeCommand(legacyEntry->svc->handle, cl, out, err);
+        status = legacyEntry->svc->executeCommand(legacyEntry->svc->handle, cl, out, err);
     } else {
         fprintf(err, "No command '%s'. Provided command line: %s\n", commandName, commandLine);
         status = CELIX_BUNDLE_EXCEPTION;
diff --git a/bundles/shell/shell/src/shell_private.h b/bundles/shell/shell/src/shell_private.h
index bc9479c..3b35c52 100644
--- a/bundles/shell/shell/src/shell_private.h
+++ b/bundles/shell/shell/src/shell_private.h
@@ -34,6 +34,8 @@ typedef struct celix_shell_command_entry {
     long svcId;
     celix_shell_command_t *svc;
     const celix_properties_t *props;
+    char *localName;
+    char *namespace;
 } celix_shell_command_entry_t;
 
 
@@ -49,7 +51,7 @@ typedef struct celix_legacy_command_entry {
 #define OSGI_SHELL_COMMAND_DESCRIPTION "command.description"
 struct celix_dummy_shell {
     void *handle;
-    void (*executeCommand)(void *, char*, FILE*, FILE*);
+    celix_status_t (*executeCommand)(void *, char*, FILE*, FILE*);
 };
 typedef struct celix_legacy_command_entry {
     long svcId;
@@ -62,7 +64,7 @@ struct shell {
 	celix_bundle_context_t *ctx;
     log_helper_t *logHelper;
     celix_thread_mutex_t mutex; //protects below
-    hash_map_t *commandServices; //key = char* (command name), value = celix_shell_command_entry_t*
+    hash_map_t *commandServices; //key = char* (fully qualified command name), value = celix_shell_command_entry_t*
     hash_map_t *legacyCommandServices; //key = char* (command name), value = celix_legacy_command_entry_t*
 };
 typedef struct shell shell_t;
diff --git a/bundles/shell/shell/test/CMakeLists.txt b/bundles/shell/shell/test/CMakeLists.txt
index e1acdc6..868b05e 100644
--- a/bundles/shell/shell/test/CMakeLists.txt
+++ b/bundles/shell/shell/test/CMakeLists.txt
@@ -26,6 +26,10 @@ target_link_libraries(test_shell PRIVATE Celix::framework CURL::libcurl ${CPPUTE
 target_include_directories(test_shell PRIVATE ${CPPUTEST_INCLUDE_DIRS})
 add_dependencies(test_shell shell_bundle)
 target_compile_definitions(test_shell PRIVATE -DSHELL_BUNDLE_LOCATION=\"$<TARGET_PROPERTY:shell,BUNDLE_FILE>\")
+target_compile_options(test_shell PRIVATE -Wno-deprecated-declarations)
+if (CELIX_ADD_DEPRECATED_API)
+    target_compile_definitions(test_shell PRIVATE CELIX_ADD_DEPRECATED_API)
+endif ()
 
 add_test(NAME test_shell COMMAND test_shell)
 SETUP_TARGET_FOR_COVERAGE(test_shell_cov test_shell ${CMAKE_BINARY_DIR}/coverage/test_shell/test_shell ..)
diff --git a/bundles/shell/shell/test/src/shell_tests.cpp b/bundles/shell/shell/test/src/shell_tests.cpp
index 370bee8..8074555 100644
--- a/bundles/shell/shell/test/src/shell_tests.cpp
+++ b/bundles/shell/shell/test/src/shell_tests.cpp
@@ -17,13 +17,14 @@
  * under the License.
  */
 
-#include <CppUTest/TestHarness.h>
-#include <CppUTest/CommandLineTestRunner.h>
 
 #include "celix_shell_command.h"
 #include "celix_api.h"
 #include "celix_shell.h"
 
+#include <CppUTest/TestHarness.h>
+#include <CppUTest/CommandLineTestRunner.h>
+
 #ifdef SHELL_BUNDLE_LOCATION
 const char * const SHELL_BUNDLE = SHELL_BUNDLE_LOCATION;
 #endif
@@ -64,10 +65,8 @@ TEST(CelixShellTests, shellBundleInstalledTest) {
     celix_arrayList_destroy(bndIds);
 }
 
-static bool callCommand(celix_bundle_context_t *ctx, const char *cmdName, const char *cmdLine, bool cmdShouldSucceed) {
+static void callCommand(celix_bundle_context_t *ctx, const char *cmdLine, bool cmdShouldSucceed) {
     celix_service_use_options_t opts{};
-    char filter[512];
-    snprintf(filter, 512, "(command.name=%s)", cmdName);
 
     struct callback_data {
         const char *cmdLine{};
@@ -77,83 +76,52 @@ static bool callCommand(celix_bundle_context_t *ctx, const char *cmdName, const
     data.cmdLine = cmdLine;
     data.cmdShouldSucceed = cmdShouldSucceed;
 
-    opts.filter.serviceName = CELIX_SHELL_COMMAND_SERVICE_NAME;
-    opts.filter.filter = filter;
+    opts.filter.serviceName = CELIX_SHELL_SERVICE_NAME;
     opts.callbackHandle = static_cast<void*>(&data);
     opts.waitTimeoutInSeconds = 1.0;
     opts.use = [](void *handle, void *svc) {
-        auto *cmd = static_cast<celix_shell_command_t*>(svc);
+        auto *shell = static_cast<celix_shell_t *>(svc);
         auto *d = static_cast<struct callback_data*>(handle);
-        CHECK_TRUE(cmd != nullptr);
-        bool succeeded = cmd->executeCommand(cmd->handle, d->cmdLine, stdout, stderr);
+        CHECK_TRUE(shell != nullptr);
+        celix_status_t status = shell->executeCommand(shell->handle, d->cmdLine, stdout, stderr);
         if (d->cmdShouldSucceed) {
-            CHECK_TRUE_TEXT(succeeded, d->cmdLine);
+            CHECK_EQUAL_TEXT(CELIX_SUCCESS, status, d->cmdLine);
         } else {
-            CHECK_FALSE_TEXT(succeeded, d->cmdLine);
+            CHECK_TRUE_TEXT(status != CELIX_SUCCESS, d->cmdLine);
         }
     };
     bool called = celix_bundleContext_useServiceWithOptions(ctx, &opts);
-    return called;
+    CHECK_TRUE(called);
 }
 
 TEST(CelixShellTests, testAllCommandsAreCallable) {
-    bool called = callCommand(ctx, "non-existing", "non-existing", false);
-    CHECK_FALSE(called);
-
-    called = callCommand(ctx, "install", "install a-bundle-loc.zip", false);
-    CHECK_TRUE(called);
-
-    called = callCommand(ctx, "help", "help", true);
-    CHECK_TRUE(called);
-
-    called = callCommand(ctx, "help", "help lb", true);
-    CHECK_TRUE(called);
-
-    called = callCommand(ctx, "help", "help non-existing-command", false);
-    CHECK_TRUE(called);
-
-    called = callCommand(ctx, "lb", "lb -a", true);
-    CHECK_TRUE(called);
-
-    called = callCommand(ctx, "lb", "lb -a", true);
-    CHECK_TRUE(called);
-
-    called = callCommand(ctx, "lb", "lb", true);
-    CHECK_TRUE(called);
-
-    called = callCommand(ctx, "query", "query", true);
-    CHECK_TRUE(called);
-
-    called = callCommand(ctx, "q", "q -v", true);
-    CHECK_TRUE(called);
-
-    called = callCommand(ctx, "stop", "stop 15", false);
-    CHECK_TRUE(called);
-
-    called = callCommand(ctx, "start", "start 15", false);
-    CHECK_TRUE(called);
-
-    called = callCommand(ctx, "uninstall", "uninstall 15", false);
-    CHECK_TRUE(called);
-
-    called = callCommand(ctx, "update", "update 15", false);
-    CHECK_TRUE(called);
+    callCommand(ctx, "non-existing", false);
+    callCommand(ctx, "install a-bundle-loc.zip", false);
+    callCommand(ctx, "help lb", false); //note need namespace
+    callCommand(ctx, "help celix::lb", true);
+    callCommand(ctx, "help non-existing-command", false);
+    callCommand(ctx, "lb -a", true);
+    callCommand(ctx, "lb", true);
+    callCommand(ctx, "query", true);
+    callCommand(ctx, "q -v", true);
+    callCommand(ctx, "stop 15", false);
+    callCommand(ctx, "start 15", false);
+    callCommand(ctx, "uninstall 15", false);
+    callCommand(ctx, "update 15", false);
 }
 
 TEST(CelixShellTests, quitTest) {
-    bool called = callCommand(ctx, "quit", "quit", true);
-    CHECK_TRUE(called);
+    callCommand(ctx, "quit", true);
 }
 
 TEST(CelixShellTests, stopFrameworkTest) {
-    bool called = callCommand(ctx, "stop", "stop 0", true);
-    CHECK_TRUE(called);
+    callCommand(ctx, "stop 0", true);
 }
 
 TEST(CelixShellTests, queryTest) {
     celix_service_use_options_t opts{};
     opts.filter.serviceName = CELIX_SHELL_COMMAND_SERVICE_NAME;
-    opts.filter.filter = "(command.name=query)";
+    opts.filter.filter = "(command.name=celix::query)";
     opts.waitTimeoutInSeconds = 1.0;
     opts.use = [](void */*handle*/, void *svc) {
         auto *command = static_cast<celix_shell_command_t*>(svc);
@@ -183,8 +151,31 @@ TEST(CelixShellTests, queryTest) {
     CHECK_TRUE(called);
 }
 
+TEST(CelixShellTests, localNameClashTest) {
+    callCommand(ctx, "lb", true);
+
+    celix_shell_command_t cmdService;
+    cmdService.handle = nullptr;
+    cmdService.executeCommand = [](void *, const char* cmdLine, FILE *, FILE *) -> bool {
+        CHECK_TRUE(cmdLine != NULL);
+        return true;
+    };
+
+    celix_properties_t *props = celix_properties_create();
+    celix_properties_set(props, CELIX_SHELL_COMMAND_NAME, "3rdparty::lb");
+    long svcId = celix_bundleContext_registerService(ctx, &cmdService, CELIX_SHELL_COMMAND_SERVICE_NAME, props);
+
+    //two lb commands, need namespace
+    callCommand(ctx, "lb", false);
+    callCommand(ctx, "celix::lb", true);
+    callCommand(ctx, "3rdparty::lb", true);
+
+    celix_bundleContext_unregisterService(ctx, svcId);
+
+}
+
 #ifdef CELIX_ADD_DEPRECATED_API
-#include "command.H"
+#include "command.h"
 TEST(CelixShellTests, legacyCommandTest) {
     command_service_t cmdService;
     cmdService.handle = nullptr;
@@ -197,28 +188,7 @@ TEST(CelixShellTests, legacyCommandTest) {
     celix_properties_set(props, OSGI_SHELL_COMMAND_NAME, "testCommand");
     long svcId = celix_bundleContext_registerService(ctx, &cmdService, OSGI_SHELL_COMMAND_SERVICE_NAME, props);
 
-    celix_service_use_options_t opts{};
-    opts.filter.serviceName = CELIX_SHELL_SERVICE_NAME;
-    opts.waitTimeoutInSeconds = 1.0;
-    opts.use = [](void */*handle*/, void *svc) {
-        auto *shell = static_cast<celix_shell_t*>(svc);
-        celix_array_list_t *commands = nullptr;
-        shell->getCommands(shell->handle, &commands);
-        bool commandFound = false;
-        for (int i = 0; i < celix_arrayList_size(commands); ++i) {
-            auto* name = static_cast<char*>(celix_arrayList_get(commands, i));
-            if (strncmp(name, "testCommand", 64) == 0) {
-                commandFound = true;
-            }
-            free(name);
-        }
-        celix_arrayList_destroy(commands);
-        CHECK_TRUE(commandFound);
-
-        shell->executeCommand(shell->handle, "testCommand withArg", stdout, stderr);
-    };
-    bool called = celix_bundleContext_useServiceWithOptions(ctx, &opts);
-    CHECK_TRUE(called);
+    callCommand(ctx, "testCommand", true);
 
     celix_bundleContext_unregisterService(ctx, svcId);
 }
diff --git a/libs/utils/include/celix_utils.h b/libs/utils/include/celix_utils.h
index 1b96cdf..5a19f18 100644
--- a/libs/utils/include/celix_utils.h
+++ b/libs/utils/include/celix_utils.h
@@ -33,6 +33,20 @@ extern "C" {
  */
 char* celix_utils_strdup(const char *str);
 
+
+/**
+ * Extract a local name and namespace from a fully qualified name using the provided namespace separator.
+ * so fully qualified name = celix::extra::lb, namespace separator = "::" -> local name = lb, namespace = celix::extra
+ *
+ * Note that if no namespace is present the output for namespace will be NULL.
+ *
+ * @param fullyQualifiedName    The fully qualified name to split
+ * @param namespaceSeparator    The namespace separator
+ * @param outLocalName          A output argument for the local name part. Caller is owner of the data.
+ * @param outNamespace          A output argument for the (optional) namespace part. Caller is owner of the data.
+ */
+void celix_utils_extractLocalNameAndNamespaceFromFullyQualifiedName(const char *fullyQualifiedName, const char *namespaceSeparator, char **outLocalName, char **outNamespace);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/libs/utils/private/test/array_list_test.cpp b/libs/utils/private/test/array_list_test.cpp
index e7ca0b1..99c120c 100644
--- a/libs/utils/private/test/array_list_test.cpp
+++ b/libs/utils/private/test/array_list_test.cpp
@@ -41,6 +41,7 @@ extern "C"
 }
 
 int main(int argc, char** argv) {
+    MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
     return RUN_ALL_TESTS(argc, argv);
 }
 
diff --git a/libs/utils/private/test/celix_threads_test.cpp b/libs/utils/private/test/celix_threads_test.cpp
index bdbdfed..1c07f70 100644
--- a/libs/utils/private/test/celix_threads_test.cpp
+++ b/libs/utils/private/test/celix_threads_test.cpp
@@ -96,6 +96,7 @@ struct func_param{
 }
 
 int main(int argc, char** argv) {
+    MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
     return RUN_ALL_TESTS(argc, argv);
 }
 
diff --git a/libs/utils/private/test/filter_test.cpp b/libs/utils/private/test/filter_test.cpp
index 4761e2e..651eda5 100644
--- a/libs/utils/private/test/filter_test.cpp
+++ b/libs/utils/private/test/filter_test.cpp
@@ -29,6 +29,7 @@
 #include "filter.h"
 
 int main(int argc, char** argv) {
+    MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
     return RUN_ALL_TESTS(argc, argv);
 }
 
diff --git a/libs/utils/private/test/hash_map_test.cpp b/libs/utils/private/test/hash_map_test.cpp
index cd9bf54..428777f 100644
--- a/libs/utils/private/test/hash_map_test.cpp
+++ b/libs/utils/private/test/hash_map_test.cpp
@@ -41,6 +41,7 @@ extern "C"
 }
 
 int main(int argc, char** argv) {
+    MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
     return RUN_ALL_TESTS(argc, argv);
 }
 
diff --git a/libs/utils/private/test/ip_utils_test.cpp b/libs/utils/private/test/ip_utils_test.cpp
index 606ed24..eec7d27 100644
--- a/libs/utils/private/test/ip_utils_test.cpp
+++ b/libs/utils/private/test/ip_utils_test.cpp
@@ -38,6 +38,7 @@ extern "C"
 }
 
 int main(int argc, char** argv) {
+    MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
     return RUN_ALL_TESTS(argc, argv);
 }
 
diff --git a/libs/utils/private/test/linked_list_test.cpp b/libs/utils/private/test/linked_list_test.cpp
index 57dee2d..10711db 100644
--- a/libs/utils/private/test/linked_list_test.cpp
+++ b/libs/utils/private/test/linked_list_test.cpp
@@ -40,6 +40,7 @@ extern "C"
 }
 
 int main(int argc, char** argv) {
+    MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
     return RUN_ALL_TESTS(argc, argv);
 }
 
diff --git a/libs/utils/private/test/properties_test.cpp b/libs/utils/private/test/properties_test.cpp
index 5e80300..df35f6f 100644
--- a/libs/utils/private/test/properties_test.cpp
+++ b/libs/utils/private/test/properties_test.cpp
@@ -38,6 +38,7 @@ extern "C" {
 }
 
 int main(int argc, char** argv) {
+    MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
     return RUN_ALL_TESTS(argc, argv);
 }
 
diff --git a/libs/utils/private/test/thread_pool_test.cpp b/libs/utils/private/test/thread_pool_test.cpp
index 2ffed98..aa42ebc 100644
--- a/libs/utils/private/test/thread_pool_test.cpp
+++ b/libs/utils/private/test/thread_pool_test.cpp
@@ -50,6 +50,7 @@ void * increment(void *) {
 }
 
 int main(int argc, char** argv) {
+    MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
     return RUN_ALL_TESTS(argc, argv);
 }
 
diff --git a/libs/utils/private/test/utils_test.cpp b/libs/utils/private/test/utils_test.cpp
index e1d7ff8..dfd9066 100644
--- a/libs/utils/private/test/utils_test.cpp
+++ b/libs/utils/private/test/utils_test.cpp
@@ -16,13 +16,7 @@
  * specific language governing permissions and limitations
  * under the License.
  */
-/**
- * utils_test.cpp
- *
- *  \date       Feb 6, 2013
- *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright  Apache License, Version 2.0
- */
+
 
 #include "string.h"
 #include <stdlib.h>
@@ -31,6 +25,7 @@
 #include "CppUTest/TestHarness.h"
 #include "CppUTest/TestHarness_c.h"
 #include "CppUTest/CommandLineTestRunner.h"
+#include "celix_utils.h"
 
 extern "C"
 {
@@ -38,6 +33,7 @@ extern "C"
 }
 
 int main(int argc, char** argv) {
+    MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
     return RUN_ALL_TESTS(argc, argv);
 }
 
@@ -298,4 +294,71 @@ TEST(utils, compareServiceIdsAndRanking){
 
 }
 
-
+TEST(utils, extractLocalNameAndNamespaceTest) {
+    const char *input = "lb";
+    char* name = NULL;
+    char *ns = NULL;
+    celix_utils_extractLocalNameAndNamespaceFromFullyQualifiedName(input, "::", &name, &ns);
+    CHECK_EQUAL_C_STRING("lb", name);
+    CHECK_TRUE(ns == NULL);
+    free(name);
+    free(ns);
+
+    input = "celix::lb";
+    name = NULL;
+    ns = NULL;
+    celix_utils_extractLocalNameAndNamespaceFromFullyQualifiedName(input, "::", &name, &ns);
+    CHECK_EQUAL_C_STRING("lb", name);
+    CHECK_EQUAL_C_STRING("celix", ns);
+    free(name);
+    free(ns);
+
+    input = "celix::extra::namespace::entries::lb";
+    name = NULL;
+    ns = NULL;
+    celix_utils_extractLocalNameAndNamespaceFromFullyQualifiedName(input, "::", &name, &ns);
+    CHECK_EQUAL_C_STRING("lb", name);
+    CHECK_EQUAL_C_STRING("celix::extra::namespace::entries", ns);
+    free(name);
+    free(ns);
+
+    input = "celix.extra.namespace.entries.lb";
+    name = NULL;
+    ns = NULL;
+    celix_utils_extractLocalNameAndNamespaceFromFullyQualifiedName(input, ".", &name, &ns);
+    CHECK_EQUAL_C_STRING("lb", name);
+    CHECK_EQUAL_C_STRING("celix.extra.namespace.entries", ns);
+    free(name);
+    free(ns);
+
+    //testing with non existing namespace
+    input = "celix.extra.namespace.entries.lb";
+    name = NULL;
+    ns = NULL;
+    celix_utils_extractLocalNameAndNamespaceFromFullyQualifiedName(input, "??", &name, &ns);
+    CHECK_EQUAL_C_STRING("celix.extra.namespace.entries.lb", name);
+    CHECK_TRUE(ns == NULL);
+    free(name);
+    free(ns);
+
+    //wrong input check
+    input = NULL;
+    name = NULL;
+    ns = NULL;
+    celix_utils_extractLocalNameAndNamespaceFromFullyQualifiedName(input, "??", &name, &ns);
+    CHECK_TRUE(name == NULL);
+    CHECK_TRUE(ns == NULL);
+    free(name);
+    free(ns);
+
+
+    //empty namespace check
+    input = "celix.extra.namespace.entries.lb";
+    name = NULL;
+    ns = NULL;
+    celix_utils_extractLocalNameAndNamespaceFromFullyQualifiedName(input, "", &name, &ns);
+    CHECK_EQUAL_C_STRING("celix.extra.namespace.entries.lb", name);
+    CHECK_TRUE(ns == NULL);
+    free(name);
+    free(ns);
+}
diff --git a/libs/utils/private/test/version_range_test.cpp b/libs/utils/private/test/version_range_test.cpp
index 5c81734..8577f7d 100644
--- a/libs/utils/private/test/version_range_test.cpp
+++ b/libs/utils/private/test/version_range_test.cpp
@@ -41,6 +41,7 @@ framework_logger_pt logger = (framework_logger_pt) 0x42;
 }
 
 int main(int argc, char** argv) {
+    MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
     return RUN_ALL_TESTS(argc, argv);
 }
 
diff --git a/libs/utils/private/test/version_test.cpp b/libs/utils/private/test/version_test.cpp
index d18b46c..46d33ff 100644
--- a/libs/utils/private/test/version_test.cpp
+++ b/libs/utils/private/test/version_test.cpp
@@ -40,6 +40,7 @@ framework_logger_pt logger = (framework_logger_pt) 0x666;
 }
 
 int main(int argc, char** argv) {
+    MemoryLeakWarningPlugin::turnOffNewDeleteOverloads();
     return RUN_ALL_TESTS(argc, argv);
 }
 
diff --git a/libs/utils/src/utils.c b/libs/utils/src/utils.c
index afb6107..2c4886d 100644
--- a/libs/utils/src/utils.c
+++ b/libs/utils/src/utils.c
@@ -24,6 +24,15 @@
 #include "utils.h"
 #include "celix_utils.h"
 
+
+#ifdef __APPLE__
+#include "memstream/open_memstream.h"
+#else
+#include <stdio.h>
+#include <assert.h>
+
+#endif
+
 unsigned int utils_stringHash(const void* strPtr) {
     const char* string = strPtr;
     unsigned int hc = 5381;
@@ -148,4 +157,52 @@ char* celix_utils_strdup(const char *str) {
     } else {
         return NULL;
     }
+}
+
+
+void celix_utils_extractLocalNameAndNamespaceFromFullyQualifiedName(const char *fullyQualifiedName, const char *namespaceSeparator, char **outLocalName, char **outNamespace) {
+    assert(namespaceSeparator != NULL);
+    if (fullyQualifiedName == NULL) {
+        *outLocalName = NULL;
+        *outNamespace = NULL;
+        return;
+    }
+
+    char *cpy = celix_utils_strdup(fullyQualifiedName);
+
+    char *local = NULL;
+    char *namespace = NULL;
+    size_t namespaceLen;
+    FILE *namespaceStream = open_memstream(&namespace, &namespaceLen);
+
+    char *savePtr = NULL;
+    char *nextSubStr = NULL;
+    char *currentSubStr = strtok_r(cpy, namespaceSeparator, &savePtr);
+    bool firstNamespaceEntry = true;
+    while (currentSubStr != NULL) {
+        nextSubStr = strtok_r(NULL, namespaceSeparator, &savePtr);
+        if (nextSubStr != NULL) {
+            //still more, so last is part of the namespace
+            if (firstNamespaceEntry) {
+                firstNamespaceEntry = false;
+            } else {
+                fprintf(namespaceStream, "%s", namespaceSeparator);
+            }
+            fprintf(namespaceStream, "%s", currentSubStr);
+        } else {
+            //end reached current is local name
+            local = celix_utils_strdup(currentSubStr);
+        }
+        currentSubStr = nextSubStr;
+    }
+    fclose(namespaceStream);
+    free(cpy);
+    *outLocalName = local;
+    if (strncmp("", namespace, 1) == 0)  {
+        //empty string -> set to NULL
+        *outNamespace = NULL;
+        free(namespace);
+    } else {
+        *outNamespace = namespace;
+    }
 }
\ No newline at end of file