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 2019/01/07 20:11:48 UTC

[celix] branch feature/cxx created (now 807b88b)

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

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


      at 807b88b  CELIX-458: Updates travis config to install libzip

This branch includes the following new commits:

     new e27350f  CELIX-438: Separates ServiceRegistry & Framework
     new 9231430  CELIX-438: Adds the C++ shell/shell_tui initial impl and a small test application
     new 01613bd  CELIX-438: Removes prev C++ impl and adds a sync/race condition test for the svc reg.
     new 9e854fd  CELIX-438: Updates to compile on gcc, adds glog as external project and fixes code coverage setup
     new 34dac36  CELIX-438: Adds an initial setup for handling resources in bundles
     new 5e04c17  CELIX-438: Updates travis config
     new d80808b  CELIX-438: Updates travis config
     new eec8e08  CELIX-438: Adds bundle register for __APPLE__
     new e4dab31  CELIX-438; Adds CppuTest as external cmake project
     new fa43b32  CELIX-438: Updates external project configuration, so that building of external libs do not generated compiler warnings
     new 9f0369b  CELIX-438: Small refactoring for gcc 5 compiler
     new cc671b6  CELIX-438: Adds a assert and warning log for wrong useage of the use(Funcion)Service(s) calls and adds some unit tests for the C++ shell.
     new 82b453b  CELIX-438: Update travis config
     new 23d6e67  CELIX-438: Some refactoring
     new 795217b  CELIX-438: Adds some missing include statements
     new f378f17  CELIX-438: Reanables the c bundles, libs and examples.
     new 7c425db  CELIX-438: Adds some shell tui gtests
     new 9deecd8  CELIX-438: Disabling cpputest based tests, so that the cpputest dep can be removed and the coverage only shows the cxx implementation coverage
     new 20b047d  CELIX-438: Fixes some test setup
     new aeb19ff  CELIX-438: Removes OSX (for now) from travis config
     new 4eebbdc  CELIX-438: Convert libzip external project setup to a FindLIBZIP cmake file
     new 807b88b  CELIX-458: Updates travis config to install libzip

The 22 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] 02/22: CELIX-438: Adds the C++ shell/shell_tui initial impl and a small test application

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 9231430205ed008ae79342e25b49d1178e793e67
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Wed Jan 2 14:53:06 2019 +0100

    CELIX-438: Adds the C++ shell/shell_tui initial impl and a small test application
---
 bundles/shell/CMakeLists.txt                       |   1 +
 bundles/shell/cxx_shell/CMakeLists.txt             |  18 +-
 bundles/shell/cxx_shell/include/celix/IShell.h     |   2 +-
 .../shell/cxx_shell/include/celix/IShellCommand.h  |  18 +-
 bundles/shell/cxx_shell/src/HelpCommand.cc         |  86 +++++++++
 bundles/shell/cxx_shell/src/InspectCommand.cc      |  70 +++++++
 bundles/shell/cxx_shell/src/LbCommand.cc           |  54 ++++++
 bundles/shell/cxx_shell/src/ShellActivator.cc      | 157 ++++++---------
 bundles/shell/cxx_shell/src/StopAndStartCommand.cc |  75 ++++++++
 .../shell/cxx_shell/src/commands.h                 |  27 ++-
 .../{cxx_shell => cxx_shell_tui}/CMakeLists.txt    |  29 +--
 .../shell/{ => cxx_shell_tui/gtest}/CMakeLists.txt |  16 +-
 .../IShell.h => cxx_shell_tui/gtest/src/main.cc}   |  23 +--
 .../shell/cxx_shell_tui/src/ShellTuiActivator.cc   | 150 +++++++++++++++
 .../IShell.h => cxx_shell_tui/src/shell_test.cc}   |  23 ++-
 cmake/celix_project/AddGTest.cmake                 |   4 +-
 libs/framework_cxx/gtest/src/Framework_tests.cc    |  81 ++++----
 libs/framework_cxx/include/celix/Framework.h       |  45 +++--
 libs/framework_cxx/include/celix/IBundle.h         |   1 -
 .../framework_cxx/include/celix/IBundleActivator.h |  12 +-
 libs/framework_cxx/include/celix/IBundleContext.h  |   7 +-
 libs/framework_cxx/src/BundleImpl.h                |  67 +++----
 libs/framework_cxx/src/Framework.cc                | 114 +++++++----
 .../gtest/src/RegistryConcurrency_tests.cc         |   3 +-
 libs/registry/gtest/src/Registry_tests.cc          |  23 ++-
 libs/registry/gtest/src/ServiceTracking_tests.cc   |  64 +++----
 libs/registry/include/celix/Constants.h            |   7 +-
 libs/registry/include/celix/Properties.h           |   6 +
 libs/registry/include/celix/ServiceRegistry.h      | 155 ++++++++-------
 libs/registry/src/ServiceRegistry.cc               | 211 ++++++++++++++-------
 30 files changed, 1048 insertions(+), 501 deletions(-)

diff --git a/bundles/shell/CMakeLists.txt b/bundles/shell/CMakeLists.txt
index 2fd81dc..851d601 100644
--- a/bundles/shell/CMakeLists.txt
+++ b/bundles/shell/CMakeLists.txt
@@ -21,3 +21,4 @@ add_subdirectory(shell_bonjour)
 add_subdirectory(shell_tui)
 
 add_subdirectory(cxx_shell)
+add_subdirectory(cxx_shell_tui)
diff --git a/bundles/shell/cxx_shell/CMakeLists.txt b/bundles/shell/cxx_shell/CMakeLists.txt
index 070f05e..5373caf 100644
--- a/bundles/shell/cxx_shell/CMakeLists.txt
+++ b/bundles/shell/cxx_shell/CMakeLists.txt
@@ -19,18 +19,22 @@ find_package(glog REQUIRED)
 
 #TODO rename to celix::shell && celix::shell_api
 
-add_library(shell_api_cxx INTERFACE)
-target_include_directories(shell_api INTERFACE
+add_library(celix_cxx_shell_api INTERFACE)
+target_include_directories(celix_cxx_shell_api INTERFACE
     $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
     $<INSTALL_INTERFACE:include/celix/shell>
 )
 
-add_library(celix_shell_cxx STATIC
+add_library(celix_cxx_shell SHARED
         src/ShellActivator.cc
-        include/celix/IShell.h)
-target_include_directories(celix_shell_cxx PRIVATE src)
-target_include_directories(celix_shell_cxx PUBLIC include)
-target_link_libraries(celix_shell_cxx PRIVATE glog::glog celix_framework_cxx)
+        src/LbCommand.cc
+        src/HelpCommand.cc
+        src/StopAndStartCommand.cc
+        src/InspectCommand.cc
+)
+target_include_directories(celix_cxx_shell PRIVATE src)
+target_link_libraries(celix_cxx_shell PRIVATE celix_cxx_shell_api)
+target_link_libraries(celix_cxx_shell PUBLIC glog::glog celix_framework_cxx)
 
 #if (ENABLE_TESTING)
 #    add_subdirectory(gtest)
diff --git a/bundles/shell/cxx_shell/include/celix/IShell.h b/bundles/shell/cxx_shell/include/celix/IShell.h
index 9809ac5..f272c52 100644
--- a/bundles/shell/cxx_shell/include/celix/IShell.h
+++ b/bundles/shell/cxx_shell/include/celix/IShell.h
@@ -29,7 +29,7 @@ namespace celix {
 
         virtual ~IShell() = default;
 
-        virtual bool executeCommand(const std::string &commandLine, std::ostream &out, std::ostream &err) noexcept = 0;
+        virtual bool executeCommandLine(const std::string &commandLine, std::ostream &out, std::ostream &err) noexcept = 0;
     };
 }
 
diff --git a/bundles/shell/cxx_shell/include/celix/IShellCommand.h b/bundles/shell/cxx_shell/include/celix/IShellCommand.h
index 8a30133..ec98c73 100644
--- a/bundles/shell/cxx_shell/include/celix/IShellCommand.h
+++ b/bundles/shell/cxx_shell/include/celix/IShellCommand.h
@@ -18,6 +18,7 @@
  */
 
 #include <string>
+#include <vector>
 #include <iostream>
 
 #ifndef CXX_CELIX_ISHELLCOMMAND_H
@@ -29,20 +30,21 @@ namespace celix {
     public:
         static constexpr const char * const SERVICE_FQN = "celix::IShellCommand [Version 1]";
 
-        static constexpr const char * const COMMAND_NAME = "name";
-        static constexpr const char * const COMMAND_USAGE = "usage";
-        static constexpr const char * const COMMAND_DESCRIPTION = "description";
+        static constexpr const char * const COMMAND_NAME = "COMMAND_NAME";
+        static constexpr const char * const COMMAND_USAGE = "COMMAND_USAGE";
+        static constexpr const char * const COMMAND_DESCRIPTION = "COMMAND_DESCRIPTION";
 
         virtual ~IShellCommand() = default;
 
-        virtual void executeCommand(const std::string &commandLine, std::ostream &out, std::ostream &err) noexcept = 0;
+        virtual void executeCommand(const std::string &cmdName, const std::vector<std::string> &cmdArgs, std::ostream &out, std::ostream &err) noexcept = 0;
     };
 
-    using ShellCommandFunction = std::function<void(const std::string &commandLine, std::ostream &out, std::ostream &err)>;
     static constexpr const char * const SHELL_COMMAND_FUNCTION_SERVICE_FQN = "celix::ShellFunction [Version 1]";
-    static constexpr const char * const SHELL_COMMAND_FUNCTION_COMMAND_NAME = "name";
-    static constexpr const char * const SHELL_COMMAND_FUNCTION_COMMAND_USAGE = "usage";
-    static constexpr const char * const SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION = "description";
+    static constexpr const char * const SHELL_COMMAND_FUNCTION_COMMAND_NAME = "COMMAND_NAME";
+    static constexpr const char * const SHELL_COMMAND_FUNCTION_COMMAND_USAGE = "COMMAND_USAGE";
+    static constexpr const char * const SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION = "COMMAND_DESCRIPTION";
+    using ShellCommandFunction = std::function<void(const std::string &cmdName, const std::vector<std::string> &cmdArgs, std::ostream &out, std::ostream &err)>;
+
 }
 
 #endif //CXX_CELIX_ISHELLCOMMAND_H
diff --git a/bundles/shell/cxx_shell/src/HelpCommand.cc b/bundles/shell/cxx_shell/src/HelpCommand.cc
new file mode 100644
index 0000000..3f5f5e9
--- /dev/null
+++ b/bundles/shell/cxx_shell/src/HelpCommand.cc
@@ -0,0 +1,86 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "commands.h"
+
+#include "celix/api.h"
+#include "celix/IShellCommand.h"
+
+celix::ServiceRegistration impl::registerHelp(std::shared_ptr<celix::IBundleContext> ctx) {
+
+    celix::ShellCommandFunction help = [ctx](const std::string &, const std::vector<std::string> &commandArguments, std::ostream &out, std::ostream &) {
+
+        if (commandArguments.empty()) { //only command -> overview
+
+            std::string hasCommandNameFilter = std::string{"("} + celix::IShellCommand::COMMAND_NAME + "=*)";
+            std::vector<std::string> commands{};
+            ctx->useServices<celix::IShellCommand>([&](celix::IShellCommand &, const celix::Properties &props) {
+                commands.push_back(celix::getProperty(props, celix::IShellCommand::COMMAND_NAME, "!Error!"));
+            }, hasCommandNameFilter);
+
+            hasCommandNameFilter = std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=*)";
+
+            std::function<void(celix::ShellCommandFunction &, const celix::Properties &)> use = [&](
+                    celix::ShellCommandFunction &, const celix::Properties &props) {
+                commands.push_back(celix::getProperty(props, celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME, "!Error!"));
+            };
+            ctx->useFunctionServices(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, use, hasCommandNameFilter);
+
+            //TODO useCService with a shell command service struct
+
+            out << "Available commands: " << std::endl;
+            for (auto &name : commands) {
+                out << "|- " << name << std::endl;
+            }
+        } else { //details
+            for (auto &cmd : commandArguments) {
+                std::string commandNameFilter = std::string{"("} + celix::IShellCommand::COMMAND_NAME + "=" + cmd + ")";
+                bool found = ctx->useService<celix::IShellCommand>([&](celix::IShellCommand &, const celix::Properties &props) {
+                    out << "Command Name       : " << celix::getProperty(props, celix::IShellCommand::COMMAND_NAME, "!Error!") << std::endl;
+                    out << "Command Usage      : " << celix::getProperty(props, celix::IShellCommand::COMMAND_USAGE, "!Error!") << std::endl;
+                    out << "Command Description: " << celix::getProperty(props, celix::IShellCommand::COMMAND_DESCRIPTION, "!Error!") << std::endl;
+
+                }, commandNameFilter);
+                if (!found) {
+                    commandNameFilter = std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=" + cmd + ")";
+                    std::function<void(celix::ShellCommandFunction &, const celix::Properties &)> use = [&](
+                            celix::ShellCommandFunction &, const celix::Properties &props) {
+                        out << "Command Name       : " << celix::getProperty(props, celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME, "!Error!") << std::endl;
+                        out << "Command Usage      : " << celix::getProperty(props, celix::SHELL_COMMAND_FUNCTION_COMMAND_USAGE, "!Error!") << std::endl;
+                        out << "Command Description: " << celix::getProperty(props, celix::SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION, "!Error!") << std::endl;
+                    };
+                    found = ctx->useFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, use, commandNameFilter);
+                }
+                if (!found) {
+                    //TODO use C cmd service
+                }
+                if (!found) {
+                    out << "Command '" << cmd << "' not available" << std::endl;
+                }
+                out << std::endl;
+            }
+        }
+    };
+
+    celix::Properties props{};
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME] = "help";
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_USAGE] = "help [command name]";
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION] = "display available commands and description.";
+    return ctx->registerFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, std::move(help), std::move(props));
+}
\ No newline at end of file
diff --git a/bundles/shell/cxx_shell/src/InspectCommand.cc b/bundles/shell/cxx_shell/src/InspectCommand.cc
new file mode 100644
index 0000000..da3bf24
--- /dev/null
+++ b/bundles/shell/cxx_shell/src/InspectCommand.cc
@@ -0,0 +1,70 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "commands.h"
+
+#include <functional>
+
+#include "celix/api.h"
+#include "celix/IShellCommand.h"
+
+namespace {
+
+    void inspect(std::shared_ptr<celix::IBundleContext> ctx, const std::string &, const std::vector<std::string> &cmdArgs, std::ostream &out, std::ostream &) {
+        if (cmdArgs.empty()) {
+            out << "Provide a bundle id" << std::endl;
+        } else {
+            auto &bndId = cmdArgs[0];
+            auto servicesNames = ctx->registry().listAllRegisteredServiceNames();
+
+            const std::string *what{nullptr};
+            if (cmdArgs.size() >= 2) {
+                what = &cmdArgs[1];
+            }
+
+            if (what == nullptr || *what == "provided") {
+                out << "Provided Services: \n";
+                for (auto &svcName : servicesNames) {
+                    std::string filter = std::string{"("} + celix::SERVICE_BUNDLE + "=" + bndId + ")";
+                    ctx->registry().useAnyServices(svcName, [&out](std::shared_ptr<void>, const celix::Properties &props, const celix::IResourceBundle &) {
+                        out << "|- Service " << celix::getProperty(props, celix::SERVICE_ID, "!Error") << ":\n";
+                        for (auto &pair : props) {
+                            out << "   |- " << pair.first << " = " << pair.second << std::endl;
+                        }
+                    }, filter, ctx->bundle());
+                }
+            }
+            if (what == nullptr || *what == "tracked") {
+                //TODO trackers
+            }
+        }
+    }
+}
+
+
+celix::ServiceRegistration impl::registerInspect(std::shared_ptr<celix::IBundleContext> ctx) {
+    using namespace std::placeholders;
+    celix::ShellCommandFunction cmd = std::bind(&inspect, ctx, _1, _2, _3, _4);
+
+    celix::Properties props{};
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME] = "inspect";
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_USAGE] = "inspect bndId [provided|tracked]";
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION] = "Inspects a bundle. Showing the provided and/or tracked services";
+    return ctx->registerFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, std::move(cmd), std::move(props));
+}
\ No newline at end of file
diff --git a/bundles/shell/cxx_shell/src/LbCommand.cc b/bundles/shell/cxx_shell/src/LbCommand.cc
new file mode 100644
index 0000000..5c1b07c
--- /dev/null
+++ b/bundles/shell/cxx_shell/src/LbCommand.cc
@@ -0,0 +1,54 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "commands.h"
+
+#include "celix/IShellCommand.h"
+
+namespace {
+    class LbCommand : public celix::IShellCommand {
+    public:
+        LbCommand(std::shared_ptr<celix::IBundleContext> _ctx) : ctx{std::move(_ctx)} {}
+
+        void executeCommand(const std::string &, const std::vector<std::string> &cmdArgs, std::ostream &out,
+                            std::ostream &) noexcept override {
+            if (cmdArgs.empty()) {
+                out << "Bundles: " << std::endl;
+                ctx->useBundles([&out](const celix::IBundle &bnd) {
+                    //TODO make aligned text table
+                    out << "|- " << bnd.id() << ": " << bnd.name() << std::endl;
+                }, true);
+            }
+            //TODO parse args
+        }
+
+    private:
+        std::shared_ptr<celix::IBundleContext> ctx;
+    };
+}
+
+celix::ServiceRegistration impl::registerLb(std::shared_ptr<celix::IBundleContext> ctx) {
+    celix::Properties props{};
+    props[celix::IShellCommand::COMMAND_NAME] = "lb";
+    props[celix::IShellCommand::COMMAND_USAGE] = "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.";
+    props[celix::IShellCommand::COMMAND_DESCRIPTION] = "lb [-l | -s | -u | -a] [group]";
+    return ctx->registerService(std::shared_ptr<celix::IShellCommand>{new LbCommand{ctx}}, std::move(props));
+}
\ No newline at end of file
diff --git a/bundles/shell/cxx_shell/src/ShellActivator.cc b/bundles/shell/cxx_shell/src/ShellActivator.cc
index 5fd4f1f..ee89d98 100644
--- a/bundles/shell/cxx_shell/src/ShellActivator.cc
+++ b/bundles/shell/cxx_shell/src/ShellActivator.cc
@@ -21,125 +21,82 @@
 #include "celix/IShellCommand.h"
 #include "celix/IShell.h"
 
+#include "commands.h"
+
 namespace {
 
-    class LbCommand : public celix::IShellCommand {
+    class Shell : public celix::IShell {
     public:
-        LbCommand(std::shared_ptr<celix::IBundleContext> _ctx) : ctx{std::move(_ctx)} {}
-        void executeCommand(const std::string &/*command line*/, std::ostream &out, std::ostream &) noexcept override {
-            //TODO parse commandLine
-            out << "Bundles: " << std::endl;
-            ctx->useBundles([&out](const celix::IBundle &bnd) {
-                out << "|- " << bnd.id() << ": " << bnd.name() << std::endl;
-            }, true);
-        }
-    private:
-        std::shared_ptr<celix::IBundleContext> ctx;
-    };
-
-    celix::ServiceRegistration registerLb(std::shared_ptr<celix::IBundleContext> ctx) {
-        celix::Properties props{};
-        props[celix::IShellCommand::COMMAND_NAME] = "lb";
-        props[celix::IShellCommand::COMMAND_USAGE] = "list installed bundles";
-        props[celix::IShellCommand::COMMAND_DESCRIPTION] = "TODO";
-        return ctx->registerService(std::shared_ptr<celix::IShellCommand>{new LbCommand{ctx}}, std::move(props));
-    }
-
-    celix::ServiceRegistration registerHelp(std::shared_ptr<celix::IBundleContext> ctx) {
-
-        celix::ShellCommandFunction help = [ctx](const std::string &, std::ostream &out, std::ostream &) {
-
-            std::string hasCommandNameFilter = std::string{"("} + celix::IShellCommand::COMMAND_NAME + "=*)";
-            //TODO parse command line to see if details is requested instead of overview
-            std::vector<std::string> commands{};
-            ctx->useServices<celix::IShellCommand>([&](celix::IShellCommand&, const celix::Properties &props) {
-                commands.push_back(celix::getProperty(props, celix::IShellCommand::COMMAND_NAME, "!Error!"));
-            }, hasCommandNameFilter);
-
-            hasCommandNameFilter = std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=*)";
-
-            std::function<void(celix::ShellCommandFunction&, const celix::Properties&)> use = [&](celix::ShellCommandFunction&, const celix::Properties &props) {
-                commands.push_back(celix::getProperty(props, celix::IShellCommand::COMMAND_NAME, "!Error!"));
-            };
-            ctx->useFunctionServices(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, use, hasCommandNameFilter);
+        Shell(std::shared_ptr<celix::IBundleContext> _ctx) : ctx{std::move(_ctx)} {}
+
+        bool executeCommandLine(const std::string &commandLine, std::ostream &out, std::ostream &err) noexcept override {
+            std::string cmdName{};
+            std::vector<std::string> cmdArgs{};
+
+            char *savePtr = nullptr;
+            char *cl = strndup(commandLine.c_str(), 1024*1024);
+            char *token = strtok_r(cl, " ", &savePtr);
+            while (token != nullptr) {
+                if (cmdName.empty()) {
+                    cmdName = std::string{token};
+                } else {
+                    cmdArgs.emplace_back(std::string{token});
+                }
+                token = strtok_r(nullptr, " ", &savePtr);
+            }
 
-            //TODO useCService with a shell command service struct
+            bool commandCalled = false;
 
-            out << "Available commands: " << std::endl;
-            for (auto &name : commands) {
-                out << "|- " << name << std::endl;
+            if (!cmdName.empty()) {
+                std::string filter =
+                        std::string{"("} + celix::IShellCommand::COMMAND_NAME + "=" + cmdName + ")";
+                commandCalled = ctx->useService<celix::IShellCommand>([&](celix::IShellCommand &cmd) {
+                    cmd.executeCommand(cmdName, cmdArgs, out, err);
+                }, filter);
+            }
+            if (!cmdName.empty() && !commandCalled) {
+                std::string filter =
+                        std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=" + cmdName + ")";
+                std::function<void(celix::ShellCommandFunction&)> use = [&](celix::ShellCommandFunction &cmd) -> void {
+                    cmd(cmdName, cmdArgs, out, err);
+                };
+                commandCalled = ctx->useFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, use, filter);
             }
-        };
-
-        celix::Properties props{};
-        props[celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME] = "help";
-        props[celix::SHELL_COMMAND_FUNCTION_COMMAND_USAGE] = "help [command name]";
-        props[celix::SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION] = "TODO";
-        return ctx->registerFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, std::move(help), std::move(props));
-    }
 
-    class Shell : public celix::IShell {
-    public:
-        Shell(std::shared_ptr<celix::IBundleContext> _ctx) : ctx{std::move(_ctx)} {
-            celix::ServiceTrackerOptions<celix::IShellCommand> opts1{};
-            opts1.updateWithProperties = [this](std::vector<std::tuple<celix::IShellCommand*,const celix::Properties*>> services) {
-                std::lock_guard<std::mutex> lck(commands.mutex);
-                commands.commands = std::move(services);
-            };
-            trk1 = ctx->trackServices(opts1);
+            //TODO C command service struct
+            if (!cmdName.empty() && !commandCalled) {
+                out << "Command '" << cmdName << "' not available. Type 'help' to see a list of available commands." << std::endl;
+            }
 
-            celix::ServiceTrackerOptions<celix::ShellCommandFunction> opts2{};
-            opts2.updateWithProperties = [this](std::vector<std::tuple<celix::ShellCommandFunction*,const celix::Properties*>> services) {
-                std::lock_guard<std::mutex> lck(commands.mutex);
-                commands.commandFunctions = std::move(services);
-            };
-            trk2 = ctx->trackFunctionServices(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, opts2);
-        }
 
-        bool executeCommand(const std::string &commandLine, std::ostream &out, std::ostream &) noexcept override {
-            out << "TODO call command '" << commandLine << "'" << std::endl;
-            return false;
+            return commandCalled;
         }
     private:
         std::shared_ptr<celix::IBundleContext> ctx;
-
-        celix::ServiceTracker trk1{};
-        celix::ServiceTracker trk2{};
-
-        struct {
-            mutable std::mutex mutex{};
-            std::vector<std::tuple<celix::IShellCommand*, const celix::Properties*>> commands;
-            std::vector<std::tuple<celix::ShellCommandFunction*, const celix::Properties*>> commandFunctions;
-        } commands{};
     };
 
     class ShellBundleActivator : public celix::IBundleActivator {
     public:
-        bool start(std::shared_ptr<celix::IBundleContext> ctx) noexcept override {
-            //TODO ensure fixed framework thread that call bundle activators
-            registrations.push_back(registerLb(ctx));
-            registrations.push_back(registerHelp(ctx));
+        ShellBundleActivator(std::shared_ptr<celix::IBundleContext> ctx) {
+            //TODO ensure fixed framework thread that call ctor/dtor bundle activators
+            registrations.push_back(impl::registerLb(ctx));
+            registrations.push_back(impl::registerHelp(ctx));
+            registrations.push_back(impl::registerStop(ctx));
+            registrations.push_back(impl::registerStart(ctx));
+            registrations.push_back(impl::registerInspect(ctx));
 
             registrations.push_back(ctx->registerService(std::shared_ptr<celix::IShell>{new Shell{ctx}}));
-
-            return true;
-        }
-
-        bool stop(std::shared_ptr<celix::IBundleContext>) noexcept override {
-            registrations.clear();
-            return true;
         }
     private:
-        std::vector<celix::ServiceRegistration> registrations;
+        std::vector<celix::ServiceRegistration> registrations{};
     };
-}
 
-__attribute__((constructor))
-static void registerShellBundle() {
-    celix::StaticBundleOptions opts{};
-    opts.bundleActivatorFactory = [](){
-        return new ShellBundleActivator{};
-    };
-    opts.manifest[celix::MANIFEST_BUNDLE_VERSION] = "1.0.0";
-    celix::registerStaticBundle("celix::Shell", opts);
-}
\ No newline at end of file
+    __attribute__((constructor))
+    static void registerShellBundle() {
+        celix::Properties manifest{};
+        manifest[celix::MANIFEST_BUNDLE_NAME] = "Shell";
+        manifest[celix::MANIFEST_BUNDLE_GROUP] = "Celix";
+        manifest[celix::MANIFEST_BUNDLE_VERSION] = "1.0.0";
+        celix::registerStaticBundle<ShellBundleActivator>("celix::Shell", manifest);
+    }
+}
diff --git a/bundles/shell/cxx_shell/src/StopAndStartCommand.cc b/bundles/shell/cxx_shell/src/StopAndStartCommand.cc
new file mode 100644
index 0000000..aae5a69
--- /dev/null
+++ b/bundles/shell/cxx_shell/src/StopAndStartCommand.cc
@@ -0,0 +1,75 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "commands.h"
+
+#include <functional>
+
+#include "celix/api.h"
+#include "celix/IShellCommand.h"
+
+namespace {
+
+    void stopOrStart(std::shared_ptr<celix::IBundleContext> ctx, const std::string &cmdName, const std::vector<std::string> &cmdArgs, std::ostream &out, std::ostream &err) {
+        if (cmdArgs.empty()) {
+            out << "Provide a bundle id name to " << cmdName << std::endl;
+        } else {
+            for (const auto &bndId : cmdArgs) {
+                bool isNum = true;
+                for(const char &c : bndId) {
+                    isNum = isNum && isdigit(c);
+                }
+
+                if (isNum) {
+                    long id = atoi(bndId.c_str());
+                    if (cmdName == "stop") {
+                        ctx->stopBundle(id);
+                    } else {
+                        ctx->startBundle(id);
+                    }
+                } else {
+                    err << "Cannot parse '" << bndId << "' to bundle id" << std::endl;
+                }
+            }
+        }
+    }
+}
+
+
+celix::ServiceRegistration impl::registerStop(std::shared_ptr<celix::IBundleContext> ctx) {
+    using namespace std::placeholders;
+    celix::ShellCommandFunction stop = std::bind(&stopOrStart, ctx, _1, _2, _3, _4);
+
+    celix::Properties props{};
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME] = "stop";
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_USAGE] = "stop (bndId)+";
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION] = "Stops the provided bundles, identified by the bundle ids";
+    return ctx->registerFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, std::move(stop), std::move(props));
+}
+
+celix::ServiceRegistration impl::registerStart(std::shared_ptr<celix::IBundleContext> ctx) {
+    using namespace std::placeholders;
+    celix::ShellCommandFunction stop = std::bind(&stopOrStart, ctx, _1, _2, _3, _4);
+
+    celix::Properties props{};
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME] = "start";
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_USAGE] = "start (bndId)+";
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION] = "Starts the provided bundles, identified by the bundle ids";
+    return ctx->registerFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, std::move(stop), std::move(props));
+}
\ No newline at end of file
diff --git a/libs/framework_cxx/include/celix/IBundleActivator.h b/bundles/shell/cxx_shell/src/commands.h
similarity index 53%
copy from libs/framework_cxx/include/celix/IBundleActivator.h
copy to bundles/shell/cxx_shell/src/commands.h
index 1196e99..5f641b8 100644
--- a/libs/framework_cxx/include/celix/IBundleActivator.h
+++ b/bundles/shell/cxx_shell/src/commands.h
@@ -17,22 +17,21 @@
  *under the License.
  */
 
-#ifndef CXX_CELIX_IBUNDLEACTIVATOR_H
-#define CXX_CELIX_IBUNDLEACTIVATOR_H
+#ifndef CELIX_COMMANDS_H
+#define CELIX_COMMANDS_H
 
-#include <memory>
+#include "celix/api.h"
 
-#include "IBundleContext.h"
+namespace impl {
+    celix::ServiceRegistration registerLb(std::shared_ptr<celix::IBundleContext> ctx);
+    celix::ServiceRegistration registerHelp(std::shared_ptr<celix::IBundleContext> ctx);
+    celix::ServiceRegistration registerStop(std::shared_ptr<celix::IBundleContext> ctx);
+    celix::ServiceRegistration registerStart(std::shared_ptr<celix::IBundleContext> ctx);
+    celix::ServiceRegistration registerInspect(std::shared_ptr<celix::IBundleContext> ctx);
 
-namespace celix {
-    class IBundleActivator {
-    public:
-        virtual ~IBundleActivator() = default;
-
-        virtual bool resolve(std::shared_ptr<celix::IBundleContext> /*ctx*/) noexcept { return true; };
-        virtual bool start(std::shared_ptr<celix::IBundleContext> ctx) noexcept = 0;
-        virtual bool stop(std::shared_ptr<celix::IBundleContext> /*ctx*/) noexcept { return true; }
-    };
+    //query services, trackers & meta trackers TODO
+    // celix::ServiceRegistration registerQuery(std::shared_ptr<celix::IBundleContext> ctx);
 }
 
-#endif //CXX_CELIX_IBUNDLEACTIVATOR_H
+
+#endif //CELIX_COMMANDS_H
diff --git a/bundles/shell/cxx_shell/CMakeLists.txt b/bundles/shell/cxx_shell_tui/CMakeLists.txt
similarity index 60%
copy from bundles/shell/cxx_shell/CMakeLists.txt
copy to bundles/shell/cxx_shell_tui/CMakeLists.txt
index 070f05e..df20046 100644
--- a/bundles/shell/cxx_shell/CMakeLists.txt
+++ b/bundles/shell/cxx_shell_tui/CMakeLists.txt
@@ -17,21 +17,22 @@
 
 find_package(glog REQUIRED)
 
-#TODO rename to celix::shell && celix::shell_api
+#TODO rename to celix::shell_tui
 
-add_library(shell_api_cxx INTERFACE)
-target_include_directories(shell_api INTERFACE
-    $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
-    $<INSTALL_INTERFACE:include/celix/shell>
-)
-
-add_library(celix_shell_cxx STATIC
-        src/ShellActivator.cc
-        include/celix/IShell.h)
-target_include_directories(celix_shell_cxx PRIVATE src)
-target_include_directories(celix_shell_cxx PUBLIC include)
-target_link_libraries(celix_shell_cxx PRIVATE glog::glog celix_framework_cxx)
+#OR static lib, but then with all symbols to force constructor attribute
+add_library(celix_cxx_shell_tui SHARED
+        src/ShellTuiActivator.cc
+        src/shell_test.cc)
+target_include_directories(celix_cxx_shell_tui PRIVATE src)
+target_link_libraries(celix_cxx_shell_tui PRIVATE celix_cxx_shell_api)
+target_link_libraries(celix_cxx_shell_tui PUBLIC glog::glog celix_framework_cxx)
 
 #if (ENABLE_TESTING)
 #    add_subdirectory(gtest)
-#endif ()
\ No newline at end of file
+#endif ()
+
+
+add_executable(shell_test
+        src/shell_test.cc
+)
+target_link_libraries(shell_test PRIVATE celix_cxx_shell celix_cxx_shell_tui)
\ No newline at end of file
diff --git a/bundles/shell/CMakeLists.txt b/bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt
similarity index 66%
copy from bundles/shell/CMakeLists.txt
copy to bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt
index 2fd81dc..b4a7204 100644
--- a/bundles/shell/CMakeLists.txt
+++ b/bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt
@@ -5,9 +5,9 @@
 # to you under the Apache License, Version 2.0 (the
 # "License"); you may not use this file except in compliance
 # with the License.  You may obtain a copy of the License at
-#
+# 
 #   http://www.apache.org/licenses/LICENSE-2.0
-#
+# 
 # Unless required by applicable law or agreed to in writing,
 # software distributed under the License is distributed on an
 # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -15,9 +15,11 @@
 # specific language governing permissions and limitations
 # under the License.
 
-add_subdirectory(shell)
-add_subdirectory(remote_shell)
-add_subdirectory(shell_bonjour)
-add_subdirectory(shell_tui)
+set(SOURCES
+        src/main.cc
+)
+add_executable(celix_shell_cxx_tests ${SOURCES})
+target_link_libraries(celix_shell_cxx_tests PRIVATE gtest celix_framework_cxx celix_shell_cxx)
 
-add_subdirectory(cxx_shell)
+add_test(NAME celix_shell_cxx_tests COMMAND celix_shell_cxx_tests)
+SETUP_TARGET_FOR_COVERAGE(celix_shell_cxx_tests_cov celix_shell_cxx_tests ${CMAKE_BINARY_DIR}/coverage/celix_shell_cxx_tests/celix_shell_cxx_tests)
\ No newline at end of file
diff --git a/bundles/shell/cxx_shell/include/celix/IShell.h b/bundles/shell/cxx_shell_tui/gtest/src/main.cc
similarity index 66%
copy from bundles/shell/cxx_shell/include/celix/IShell.h
copy to bundles/shell/cxx_shell_tui/gtest/src/main.cc
index 9809ac5..a76daa7 100644
--- a/bundles/shell/cxx_shell/include/celix/IShell.h
+++ b/bundles/shell/cxx_shell_tui/gtest/src/main.cc
@@ -17,20 +17,17 @@
  *under the License.
  */
 
-#ifndef CXX_CELIX_ISHELL_H
-#define CXX_CELIX_ISHELL_H
+#include <gtest/gtest.h>
+#include <glog/logging.h>
 
-#include <iostream>
+int main(int argc, char **argv) {
+    google::InitGoogleLogging(argv[0]);
+    google::LogToStderr();
 
-namespace celix {
-    class IShell {
-    public:
-        static constexpr const char * const SERVICE_FQN = "celix::IShell [Version 1]";
+    ::testing::InitGoogleTest(&argc, argv);
+    int rc = RUN_ALL_TESTS();
 
-        virtual ~IShell() = default;
+    google::ShutdownGoogleLogging();
 
-        virtual bool executeCommand(const std::string &commandLine, std::ostream &out, std::ostream &err) noexcept = 0;
-    };
-}
-
-#endif //CXX_CELIX_ISHELL_H
+    return rc;
+}
\ No newline at end of file
diff --git a/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc b/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc
new file mode 100644
index 0000000..dc71faa
--- /dev/null
+++ b/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc
@@ -0,0 +1,150 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <thread>
+#include <cstdio>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include <glog/logging.h>
+
+#include "celix/api.h"
+#include "celix/IShellCommand.h"
+#include "celix/IShell.h"
+
+static constexpr int LINE_SIZE = 256;
+static constexpr const char * const PROMPT = "-> ";
+
+static constexpr int KEY_ENTER = '\n';
+
+namespace {
+
+    class ShellTui {
+    public:
+        ShellTui() {
+            int fds[2];
+            int rc  = pipe(fds);
+            if (rc == 0) {
+                readPipeFd = fds[0];
+                writePipeFd = fds[1];
+                if(fcntl(writePipeFd, F_SETFL, O_NONBLOCK) == 0) {
+                    readThread = std::thread{&ShellTui::runnable, this};
+                } else {
+                    LOG(ERROR) << "fcntl on pipe failed" << std::endl;
+                }
+            } else {
+                LOG(ERROR) << "fcntl on pipe failed" << std::endl;
+            }
+        }
+
+        ~ShellTui() {
+            write(writePipeFd, "\0", 1); //trigger select to stop
+            readThread.join();
+        }
+
+        void runnable() {
+            //setup file descriptors
+            fd_set rfds;
+            int nfds = writePipeFd > STDIN_FILENO ? (writePipeFd +1) : (STDIN_FILENO + 1);
+
+            for (;;) {
+                writePrompt();
+                FD_ZERO(&rfds);
+                FD_SET(STDIN_FILENO, &rfds);
+                FD_SET(readPipeFd, &rfds);
+
+                if (select(nfds, &rfds, NULL, NULL, NULL) > 0) {
+                    if (FD_ISSET(readPipeFd, &rfds)) {
+                        break; //something is written to the pipe -> exit thread
+                    } else if (FD_ISSET(STDIN_FILENO, &rfds)) {
+                       parseInput();
+                    }
+                }
+            }
+        }
+
+        void writePrompt() {
+            std::cout << PROMPT;
+            std::flush(std::cout);
+        }
+
+        void parseInput() {
+            char* line = NULL;
+            int nr_chars = (int)read(STDIN_FILENO, buffer, LINE_SIZE-pos-1);
+            for (int bufpos = 0; bufpos < nr_chars; bufpos++) {
+                if (buffer[bufpos] == KEY_ENTER) { //end of line -> forward command
+                    line = in; // todo trim string
+                    std::lock_guard<std::mutex> lck{mutex};
+                    if (shell) {
+                        shell->executeCommandLine(line, std::cout, std::cerr);
+                    } else {
+                        std::cerr << "Shell service not available\n";
+                    }
+                    pos = 0;
+                    in[pos] = '\0';
+                } else { //text
+                    in[pos] = buffer[bufpos];
+                    in[pos + 1] = '\0';
+                    pos++;
+                    continue;
+                }
+            } //for
+        }
+
+        void setShell(std::shared_ptr<celix::IShell> _shell) {
+           std::lock_guard<std::mutex> lck{mutex};
+           shell = _shell;
+        }
+    private:
+        std::mutex mutex{};
+        std::shared_ptr<celix::IShell> shell{};
+
+        std::thread readThread;
+
+        int readPipeFd;
+        int writePipeFd;
+
+
+        char in[LINE_SIZE+1]{};
+        char buffer[LINE_SIZE+1]{};
+        int pos{};
+    };
+
+
+    class ShellTuiBundleActivator : public celix::IBundleActivator {
+    public:
+        ShellTuiBundleActivator(std::shared_ptr<celix::IBundleContext> ctx) {
+            celix::ServiceTrackerOptions<celix::IShell> opts{};
+            opts.set = std::bind(&ShellTui::setShell, &tui, std::placeholders::_1);
+            trk = ctx->trackServices(opts);
+        }
+    private:
+        ShellTui tui{};
+        celix::ServiceTracker trk;
+    };
+
+    __attribute__((constructor))
+    static void registerShellBundle() {
+        celix::Properties manifest{};
+        manifest[celix::MANIFEST_BUNDLE_NAME] = "Shell Tui";
+        manifest[celix::MANIFEST_BUNDLE_GROUP] = "Celix";
+        manifest[celix::MANIFEST_BUNDLE_VERSION] = "1.0.0";
+        celix::registerStaticBundle<ShellTuiBundleActivator>("celix::ShellTui", manifest);
+    }
+}
\ No newline at end of file
diff --git a/bundles/shell/cxx_shell/include/celix/IShell.h b/bundles/shell/cxx_shell_tui/src/shell_test.cc
similarity index 68%
copy from bundles/shell/cxx_shell/include/celix/IShell.h
copy to bundles/shell/cxx_shell_tui/src/shell_test.cc
index 9809ac5..cd3af3c 100644
--- a/bundles/shell/cxx_shell/include/celix/IShell.h
+++ b/bundles/shell/cxx_shell_tui/src/shell_test.cc
@@ -17,20 +17,19 @@
  *under the License.
  */
 
-#ifndef CXX_CELIX_ISHELL_H
-#define CXX_CELIX_ISHELL_H
-
 #include <iostream>
 
-namespace celix {
-    class IShell {
-    public:
-        static constexpr const char * const SERVICE_FQN = "celix::IShell [Version 1]";
+#include <glog/logging.h>
+
+#include "celix/api.h"
 
-        virtual ~IShell() = default;
 
-        virtual bool executeCommand(const std::string &commandLine, std::ostream &out, std::ostream &err) noexcept = 0;
-    };
-}
+int main(int /*argc*/, char **argv) {
+    google::InitGoogleLogging(argv[0]);
+    google::LogToStderr();
 
-#endif //CXX_CELIX_ISHELL_H
+    auto fw = celix::Framework{};
+    std::cout << "Waiting for Framework shutdown\n";
+    fw.waitForShutdown();
+    return 0;
+}
\ No newline at end of file
diff --git a/cmake/celix_project/AddGTest.cmake b/cmake/celix_project/AddGTest.cmake
index a1753a8..93227c1 100644
--- a/cmake/celix_project/AddGTest.cmake
+++ b/cmake/celix_project/AddGTest.cmake
@@ -30,7 +30,7 @@ file(MAKE_DIRECTORY ${source_dir}/googletest/include)
 add_library(gtest IMPORTED STATIC GLOBAL)
 add_dependencies(gtest googletest_project)
 set_target_properties(gtest PROPERTIES
-        IMPORTED_LOCATION "${binary_dir}/lib/libgtest.a"
+        IMPORTED_LOCATION "${binary_dir}/googlemock/gtest/libgtest.a"
         INTERFACE_INCLUDE_DIRECTORIES "${source_dir}/googletest/include"
 )
 
@@ -38,6 +38,6 @@ file(MAKE_DIRECTORY ${source_dir}/googlemock/include)
 add_library(gmock IMPORTED STATIC GLOBAL)
 add_dependencies(gmock googletest_project)
 set_target_properties(gmock PROPERTIES
-        IMPORTED_LOCATION "${binary_dir}/lib/libgmock.a"
+        IMPORTED_LOCATION "${binary_dir}/googlemock/libgmock.a"
         INTERFACE_INCLUDE_DIRECTORIES "${source_dir}/googlemock/include"
 )
diff --git a/libs/framework_cxx/gtest/src/Framework_tests.cc b/libs/framework_cxx/gtest/src/Framework_tests.cc
index 34cad54..7afd9a1 100644
--- a/libs/framework_cxx/gtest/src/Framework_tests.cc
+++ b/libs/framework_cxx/gtest/src/Framework_tests.cc
@@ -44,80 +44,71 @@ TEST_F(FrameworkTest, CreateDestroy) {
     EXPECT_TRUE(isFramework);
 }
 
-TEST_F(FrameworkTest, InstallBundle) {
+class EmbeddedActivator : public celix::IBundleActivator {
+public:
+    EmbeddedActivator(std::shared_ptr<celix::IBundleContext>) {
+        startCount++;
+    }
 
-    class EmbeddedActivator : public celix::IBundleActivator {
-    public:
-        virtual ~EmbeddedActivator() = default;
+    virtual ~EmbeddedActivator() {
+        stopCount++;
+    }
 
-        bool resolve(std::shared_ptr<celix::IBundleContext> ctx) noexcept override {
-            EXPECT_GE(ctx->bundle()->id(), 1);
-            resolveCalled = true;
-            return true;
-        }
-
-        bool start(std::shared_ptr<celix::IBundleContext>) noexcept override {
-            startCalled = true;
-            return true;
-        }
-
-        bool stop(std::shared_ptr<celix::IBundleContext>) noexcept override {
-            stopCalled = true;
-            return true;
-        }
-
-        bool resolveCalled = false;
-        bool startCalled = false;
-        bool stopCalled = false;
-    };
+    static std::atomic<int> startCount;
+    static std::atomic<int> stopCount;
+};
 
-    long bndId1 = framework().installBundle<EmbeddedActivator>("embedded");
+std::atomic<int> EmbeddedActivator::startCount{0};
+std::atomic<int> EmbeddedActivator::stopCount{0};
+
+TEST_F(FrameworkTest, InstallBundle) {
+    EmbeddedActivator::startCount = 0;
+    EmbeddedActivator::stopCount = 0;
+
+    auto actFactory = [](std::shared_ptr<celix::IBundleContext> ctx) -> celix::IBundleActivator* {
+        return new EmbeddedActivator{std::move(ctx)};
+    };
+    long bndId1 = framework().installBundle("embedded", actFactory);
     EXPECT_GE(bndId1, 0);
+    EXPECT_EQ(1, EmbeddedActivator::startCount);
+    EXPECT_EQ(0, EmbeddedActivator::stopCount);
 
-    std::shared_ptr<EmbeddedActivator> act{new EmbeddedActivator};
-    long bndId2 = framework().installBundle("embedded2", act);
+    long bndId2 = framework().installBundle<EmbeddedActivator>("embedded2");
     EXPECT_GE(bndId2, 0);
     EXPECT_NE(bndId1, bndId2);
-    EXPECT_TRUE(act->resolveCalled);
-    EXPECT_TRUE(act->startCalled);
-    EXPECT_FALSE(act->stopCalled);
+    EXPECT_EQ(2, EmbeddedActivator::startCount);
+    EXPECT_EQ(0, EmbeddedActivator::stopCount);
 
     framework().stopBundle(bndId2);
-    EXPECT_TRUE(act->stopCalled);
+    EXPECT_EQ(1, EmbeddedActivator::stopCount);
 
-    std::shared_ptr<EmbeddedActivator> act3{new EmbeddedActivator};
     {
         celix::Framework fw{};
-        fw.installBundle("embedded3", act3);
-        EXPECT_TRUE(act3->resolveCalled);
-        EXPECT_TRUE(act3->startCalled);
-        EXPECT_FALSE(act3->stopCalled);
+        fw.installBundle<EmbeddedActivator>("embedded3");
+        EXPECT_EQ(3, EmbeddedActivator::startCount);
+        EXPECT_EQ(1, EmbeddedActivator::stopCount);
 
         //NOTE fw out of scope -> bundle stopped
     }
-    EXPECT_TRUE(act3->stopCalled);
+    EXPECT_EQ(3, EmbeddedActivator::startCount);
+    EXPECT_EQ(2, EmbeddedActivator::stopCount);
 }
 
 TEST_F(FrameworkTest, StaticBundleTest) {
     class EmbeddedActivator : public celix::IBundleActivator {
     public:
+        EmbeddedActivator() {}
         virtual ~EmbeddedActivator() = default;
-
-        bool start(std::shared_ptr<celix::IBundleContext>) noexcept override {
-            return true;
-        }
     };
 
     int count = 0;
-    auto factory = [&]() -> celix::IBundleActivator * {
+    auto factory = [&](std::shared_ptr<celix::IBundleContext>) -> celix::IBundleActivator * {
         count++;
         return new EmbeddedActivator{};
     };
 
     EXPECT_EQ(0, framework().listBundles().size()); //no bundles installed;
-    celix::StaticBundleOptions opts;
-    opts.bundleActivatorFactory = std::move(factory);
-    celix::registerStaticBundle("static", opts);
+    celix::registerStaticBundle("static", factory);
     EXPECT_EQ(1, framework().listBundles().size()); //static bundle instance installed
     EXPECT_EQ(1, count);
 
diff --git a/libs/framework_cxx/include/celix/Framework.h b/libs/framework_cxx/include/celix/Framework.h
index 60b6fca..a2d9b13 100644
--- a/libs/framework_cxx/include/celix/Framework.h
+++ b/libs/framework_cxx/include/celix/Framework.h
@@ -30,25 +30,25 @@
 
 namespace celix {
 
-    struct StaticBundleOptions {
-        std::string name{};
-        std::string group{};
-        std::string version{};
-        celix::Properties manifest{};
-
-        std::function<celix::IBundleActivator*()> bundleActivatorFactory{};
-
-        //TODO resources. poiting to bundle specific symbols which is linked zip file
-        char * const resoucreZip = nullptr;
-        size_t resourceZipLength = 0;
-    };
-
-    void registerStaticBundle(std::string symbolicName, const StaticBundleOptions &opts);
-    //TODO useFrameworks with a callback with as argument a fw ref
+    //TODO resources. resolved from bundle specific symbols which is linked zip file to the library
+    void registerStaticBundle(
+            std::string symbolicName,
+            std::function<celix::IBundleActivator*(std::shared_ptr<celix::IBundleContext>)> bundleActivatorFactory = {},
+            celix::Properties manifest = {});
+
+    template<typename T>
+    void registerStaticBundle(
+            std::string symbolicName,
+            celix::Properties manifest = {}) {
+        auto actFactory = [](std::shared_ptr<celix::IBundleContext> ctx) {
+            return new T{std::move(ctx)};
+        };
+        celix::registerStaticBundle(std::move(symbolicName), actFactory, std::move(manifest));
+    }
 
     class Framework {
     public:
-        Framework();
+        Framework(celix::Properties config = {});
         ~Framework();
         Framework(Framework &&rhs);
         Framework& operator=(Framework&& rhs);
@@ -56,14 +56,15 @@ namespace celix {
         Framework(const Framework& rhs) = delete;
         Framework& operator=(const Framework &rhs) = delete;
 
-
         template<typename T>
-        long installBundle(std::string symbolicName, celix::Properties manifest = {}, bool autoStart = true) {
-            std::shared_ptr<celix::IBundleActivator> activator{new T{}};
-            return installBundle(std::move(symbolicName), std::move(activator), std::move(manifest), autoStart);
+        long installBundle(std::string name, celix::Properties manifest = {}, bool autoStart = true) {
+            auto actFactory = [](std::shared_ptr<celix::IBundleContext> ctx) {
+                return new T{std::move(ctx)};
+            };
+            return installBundle(name, std::move(actFactory), manifest, autoStart);
         }
 
-        long installBundle(std::string symbolicName, std::shared_ptr<celix::IBundleActivator> activator, celix::Properties manifest = {}, bool autoStart = true);
+        long installBundle(std::string name, std::function<celix::IBundleActivator*(std::shared_ptr<celix::IBundleContext>)> actFactory, celix::Properties manifest = {}, bool autoStart = true);
 
 
         //long installBundle(const std::string &path);
@@ -78,6 +79,8 @@ namespace celix {
         std::vector<long> listBundles(bool includeFrameworkBundle = false) const;
 
         celix::ServiceRegistry& registry(const std::string &lang);
+
+        bool waitForShutdown() const;
     private:
         class Impl;
         std::unique_ptr<Impl> pimpl;
diff --git a/libs/framework_cxx/include/celix/IBundle.h b/libs/framework_cxx/include/celix/IBundle.h
index a8d0de1..9f2e8a8 100644
--- a/libs/framework_cxx/include/celix/IBundle.h
+++ b/libs/framework_cxx/include/celix/IBundle.h
@@ -27,7 +27,6 @@ namespace celix {
 
     enum class BundleState {
         INSTALLED,
-        RESOLVED,
         ACTIVE,
     };
 
diff --git a/libs/framework_cxx/include/celix/IBundleActivator.h b/libs/framework_cxx/include/celix/IBundleActivator.h
index 1196e99..a3ccd92 100644
--- a/libs/framework_cxx/include/celix/IBundleActivator.h
+++ b/libs/framework_cxx/include/celix/IBundleActivator.h
@@ -25,13 +25,17 @@
 #include "IBundleContext.h"
 
 namespace celix {
+    /**
+     * The BundleActivator.
+     *
+     * This is a marker interface and contains no virtual methods.
+     *
+     * The Celix Framework will expect a constructor with a std::shared_ptr<celix::IBundleContext> argument on the
+     * contrete bundle activator. RAII will be used to start (on ctor) and stop (on dtor) a bundle.
+     */
     class IBundleActivator {
     public:
         virtual ~IBundleActivator() = default;
-
-        virtual bool resolve(std::shared_ptr<celix::IBundleContext> /*ctx*/) noexcept { return true; };
-        virtual bool start(std::shared_ptr<celix::IBundleContext> ctx) noexcept = 0;
-        virtual bool stop(std::shared_ptr<celix::IBundleContext> /*ctx*/) noexcept { return true; }
     };
 }
 
diff --git a/libs/framework_cxx/include/celix/IBundleContext.h b/libs/framework_cxx/include/celix/IBundleContext.h
index e77623a..553372a 100644
--- a/libs/framework_cxx/include/celix/IBundleContext.h
+++ b/libs/framework_cxx/include/celix/IBundleContext.h
@@ -51,6 +51,10 @@ namespace celix {
         virtual bool useBundle(long bndId, std::function<void(const celix::IBundle &bnd)> use) const noexcept = 0;
         virtual int useBundles(std::function<void(const celix::IBundle &bnd)> use, bool includeFrameworkBundle = true) const noexcept = 0;
 
+        virtual bool stopBundle(long bndId) noexcept = 0;
+        virtual bool startBundle(long bndId) noexcept = 0;
+        //TODO install / uninstall bundles
+
         template<typename I>
         bool useService(std::function<void(I &svc)> use, const std::string &filter = "") const noexcept {
             return registry().useService<I>(std::move(use), filter, bundle());
@@ -128,7 +132,8 @@ namespace celix {
         //TODO track trackers
 
         //TODO track c trackers
-    private:
+
+
         virtual celix::ServiceRegistry& registry() const noexcept = 0;
         virtual celix::ServiceRegistry& cRegistry() const noexcept = 0;
     };
diff --git a/libs/framework_cxx/src/BundleImpl.h b/libs/framework_cxx/src/BundleImpl.h
index ab49636..dd2c53f 100644
--- a/libs/framework_cxx/src/BundleImpl.h
+++ b/libs/framework_cxx/src/BundleImpl.h
@@ -47,20 +47,29 @@ namespace impl {
             int useBundles(std::function<void(const celix::IBundle &bnd)> use, bool includeFrameworkBundle = true) const noexcept override {
                 return bnd->framework().useBundles(std::move(use), includeFrameworkBundle);
             }
+
+            bool stopBundle(long bndId) noexcept override {
+                return bnd->framework().stopBundle(bndId);
+            }
+
+            bool startBundle(long bndId) noexcept override {
+                return bnd->framework().startBundle(bndId);
+            }
+
         private:
             celix::ServiceRegistry& registry() const noexcept override { return *reg; }
             celix::ServiceRegistry& cRegistry() const noexcept override { return *cReg; }
 
             const std::shared_ptr<celix::IBundle> bnd;
-            const std::shared_ptr<celix::ServiceRegistry> reg;
-            const std::shared_ptr<celix::ServiceRegistry> cReg;
+            celix::ServiceRegistry * const reg; //TODO make weak_ptr
+            celix::ServiceRegistry * const cReg; //TODO make weak_ptr
         };
 
 
         class Bundle : public celix::IBundle {
         public:
-            Bundle(long _bndId, celix::Framework *_fw, celix::Properties _manifest, std::shared_ptr<celix::IBundleActivator> _activator) :
-            bndId{_bndId}, fw{_fw}, bndManifest{std::move(_manifest)}, activator{std::move(_activator)} {
+            Bundle(long _bndId, celix::Framework *_fw, celix::Properties _manifest) :
+            bndId{_bndId}, fw{_fw}, bndManifest{std::move(_manifest)} {
                 bndState.store(BundleState::INSTALLED, std::memory_order_release);
             }
 
@@ -100,7 +109,6 @@ namespace impl {
             const long bndId;
             celix::Framework * const fw;
             const celix::Properties bndManifest;
-            const std::shared_ptr<celix::IBundleActivator> activator;
             std::weak_ptr<celix::IBundleContext> context;
 
             std::atomic<BundleState> bndState;
@@ -109,10 +117,10 @@ namespace impl {
     class BundleController {
     public:
         BundleController(
-                std::shared_ptr<celix::IBundleActivator> _act,
+                std::function<celix::IBundleActivator*(std::shared_ptr<celix::IBundleContext>)> _actFactory,
                 std::shared_ptr<celix::impl::Bundle> _bnd,
                 std::shared_ptr<celix::impl::BundleContext> _ctx) :
-                act{std::move(_act)}, bnd{std::move(_bnd)}, ctx{std::move(_ctx)} {}
+                actFactory{std::move(_actFactory)}, bnd{std::move(_bnd)}, ctx{std::move(_ctx)} {}
 
         //specific part
         bool transitionTo(BundleState desired) {
@@ -122,39 +130,14 @@ namespace impl {
             if (state == desired) {
                 //nop
                 success = true;
-            } else if (state == BundleState::INSTALLED && desired == BundleState::RESOLVED) {
-                //TODO create cache dir for bundle
-                bool resolved = act->resolve(ctx);
-                if (resolved) {
-                    bnd->setState(BundleState::RESOLVED);
-                    success = true;
-                } else {
-                    LOG(WARNING) << "Transition to resolved state for bundle " << bnd->symbolicName() << " (" << bnd->id() << ") failed." << std::endl;
-                }
-
-            } else if (state == BundleState::RESOLVED && desired == BundleState::ACTIVE) {
-                bool started = act->start(ctx);
-                if (started) {
-                    bnd->setState(BundleState::ACTIVE);
-                    success = true;
-                } else {
-                    LOG(WARNING) << "Transition to active state for bundle " << bnd->symbolicName() << " (" << bnd->id() << ") failed." << std::endl;
-                }
-            } else if (state == BundleState::ACTIVE && desired == BundleState::RESOLVED ) {
-                bool stopped = act->stop(ctx);
-                if (stopped) {
-                    bnd->setState(BundleState::RESOLVED);
-                    success = true;
-
-                    //TODO use custom deleter to check this (use_count call is a race condition)
-                    bool unique  = ctx.use_count() == 1;
-                    if (!unique) {
-                        LOG(WARNING) << "Bundle Context is not unique. ";
-                        LOG(WARNING) << "Check if there are still some dangling references to the context of the stopped bundle." << std::endl;
-                    }
-                } else {
-                    LOG(WARNING) << "Transition to resolved state for bundle " << bnd->symbolicName() << " (" << bnd->id() << ") failed." << std::endl;
-                }
+            } else if (state == BundleState::INSTALLED && desired == BundleState::ACTIVE) {
+                act = std::unique_ptr<celix::IBundleActivator>{actFactory(ctx)};
+                bnd->setState(BundleState::ACTIVE);
+                success = true;
+            } else if (state == BundleState::ACTIVE && desired == BundleState::INSTALLED ) {
+                act = nullptr;
+                bnd->setState(BundleState::INSTALLED);
+                success = true;
             } else {
                 //LOG(ERROR) << "Unexpected desired state " << desired << " from state " << bndState << std::endl;
                 LOG(ERROR) << "Unexpected desired/form state combination " << std::endl;
@@ -162,15 +145,15 @@ namespace impl {
             return success;
         }
 
-        std::shared_ptr<celix::IBundleActivator> activator() const { return act; }
         std::shared_ptr<celix::impl::Bundle> bundle() const { return bnd; }
         std::shared_ptr<celix::impl::BundleContext> context() const { return ctx; }
     private:
-        const std::shared_ptr<celix::IBundleActivator> act;
+        const std::function<celix::IBundleActivator*(std::shared_ptr<celix::IBundleContext>)> actFactory;
         const std::shared_ptr<celix::impl::Bundle> bnd;
         const std::shared_ptr<celix::impl::BundleContext> ctx;
 
         mutable std::mutex mutex{};
+        std::unique_ptr<celix::IBundleActivator> act{nullptr};
     };
 }
 };
diff --git a/libs/framework_cxx/src/Framework.cc b/libs/framework_cxx/src/Framework.cc
index a224720..cb5b6ed 100644
--- a/libs/framework_cxx/src/Framework.cc
+++ b/libs/framework_cxx/src/Framework.cc
@@ -26,6 +26,7 @@
 #include <iostream>
 #include <set>
 #include <vector>
+#include <future>
 
 #include <glog/logging.h>
 
@@ -36,7 +37,7 @@
 struct StaticBundleEntry {
     const std::string symbolicName;
     const celix::Properties manifest;
-    const std::function<celix::IBundleActivator*()> activatorFactory;
+    const std::function<celix::IBundleActivator*(std::shared_ptr<celix::IBundleContext>)> activatorFactory;
 };
 
 static struct {
@@ -51,10 +52,11 @@ static void unregisterFramework(celix::Framework *fw);
 
 class celix::Framework::Impl : public IBundle {
 public:
-    Impl(celix::Framework *_fw) : fw{_fw}, bndManifest{createManifest()}, cwd{createCwd()} {}
+    Impl(celix::Framework *_fw, celix::Properties _config) : fw{_fw}, config{std::move(_config)}, bndManifest{createManifest()}, cwd{createCwd()} {}
 
     ~Impl() {
         stopFramework();
+        waitForShutdown();
     }
 
     std::vector<long> listBundles(bool includeFrameworkBundle) const {
@@ -70,9 +72,15 @@ public:
         return result;
     }
 
-    long installBundle(std::string symbolicName, std::shared_ptr<celix::IBundleActivator> activator, celix::Properties manifest, bool autoStart) {
+    long installBundle(std::string symbolicName, std::function<celix::IBundleActivator*(std::shared_ptr<celix::IBundleContext>)> actFactory, celix::Properties manifest, bool autoStart) {
+        //TODO if activator is nullptr -> use empty activator
         //TODO on separate thread ?? specific bundle resolve thread ??
         long bndId = -1L;
+        if (symbolicName.empty()) {
+            LOG(WARNING) << "Cannot install bundle with a empty symbolic name" << std::endl;
+            return bndId;
+        }
+
         std::shared_ptr<celix::impl::BundleController> bndController{nullptr};
         {
             manifest[celix::MANIFEST_BUNDLE_SYMBOLIC_NAME] = symbolicName;
@@ -88,9 +96,9 @@ public:
 
             std::lock_guard<std::mutex> lck{bundles.mutex};
             bndId = bundles.nextBundleId++;
-            auto bnd = std::shared_ptr<celix::impl::Bundle>{new celix::impl::Bundle{bndId, this->fw, std::move(manifest), std::move(activator)}};
+            auto bnd = std::shared_ptr<celix::impl::Bundle>{new celix::impl::Bundle{bndId, this->fw, std::move(manifest)}};
             auto ctx = std::shared_ptr<celix::impl::BundleContext>{new celix::impl::BundleContext{bnd}};
-            bndController = std::shared_ptr<celix::impl::BundleController>{new celix::impl::BundleController{activator, bnd, ctx}};
+            bndController = std::shared_ptr<celix::impl::BundleController>{new celix::impl::BundleController{std::move(actFactory), bnd, ctx}};
             bundles.entries.emplace(std::piecewise_construct,
                                      std::forward_as_tuple(bndId),
                                      std::forward_as_tuple(bndController));
@@ -99,26 +107,32 @@ public:
         }
 
         if (bndController) {
-            bool successful = bndController->transitionTo(BundleState::RESOLVED);
-            if (successful && autoStart) {
-                successful = bndController->transitionTo(BundleState::ACTIVE);
+            if (autoStart) {
+                bool successful = bndController->transitionTo(BundleState::ACTIVE);
                 if (!successful) {
                     LOG(WARNING) << "Cannot start bundle " << bndController->bundle()->symbolicName() << std::endl;
                 }
-            } else {
-                LOG(WARNING) << "Cannot resolve bundle " << bndController->bundle()->symbolicName() << std::endl;
             }
-            //TODO decrease bnd entry usage
         }
+
         return bndId;
     }
 
     bool startBundle(long bndId) {
-        return transitionBundleTo(bndId, BundleState::ACTIVE);
+        if (bndId == this->fwBndId) {
+            //TODO
+            return false;
+        } else {
+            return transitionBundleTo(bndId, BundleState::ACTIVE);
+        }
     }
 
     bool stopBundle(long bndId) {
-        return transitionBundleTo(bndId, BundleState::RESOLVED);
+        if (bndId == this->fwBndId) {
+            return stopFramework();
+        } else {
+            return transitionBundleTo(bndId, BundleState::INSTALLED);
+        }
     }
 
     bool uninstallBundle(long bndId) {
@@ -134,11 +148,10 @@ public:
             }
         }
         if (removed) {
-            bool resolved = removed->transitionTo(BundleState::RESOLVED);
-            if (resolved) {
-                uninstalled = true;
-                bool unique = removed.unique();
-                assert(unique); //TODO cond / wait ?
+            bool stopped = removed->transitionTo(BundleState::INSTALLED);
+            if (stopped) {
+                //TODO check and wait till bundle is not used anymore. is this needed (shared_ptr) or just let access
+                //to filesystem fail ...
             } else {
                 //add bundle again -> not uninstalled
                 std::lock_guard<std::mutex> lck{bundles.mutex};
@@ -245,15 +258,29 @@ public:
     celix::Framework& framework() const noexcept override { return *fw; }
 
     bool stopFramework() {
-        std::vector<long> bundles = listBundles(false);
-        while (!bundles.empty()) {
-            for (auto it = bundles.rbegin(); it != bundles.rend(); ++it) {
-                stopBundle(*it);
-                uninstallBundle(*it);
-            }
-            bundles = listBundles(false);
+        std::lock_guard<std::mutex> lck{shutdown.mutex};
+        if (!shutdown.shutdownStarted) {
+            shutdown.future = std::async(std::launch::async, [this]{
+                std::vector<long> bundles = listBundles(false);
+                while (!bundles.empty()) {
+                    for (auto it = bundles.rbegin(); it != bundles.rend(); ++it) {
+                        stopBundle(*it);
+                        uninstallBundle(*it);
+                    }
+                    bundles = listBundles(false);
+                }
+            });
+            shutdown.shutdownStarted = true;
+            shutdown.cv.notify_all();
         }
+        return true;
+    }
 
+    bool waitForShutdown() const {
+        std::unique_lock<std::mutex> lck{shutdown.mutex};
+        shutdown.cv.wait(lck, [this]{return this->shutdown.shutdownStarted;});
+        shutdown.future.wait();
+        lck.unlock();
         return true;
     }
 private:
@@ -275,10 +302,22 @@ private:
         }
     }
 
+    const long fwBndId = 1L;
     celix::Framework * const fw;
+    const celix::Properties config;
     const celix::Properties bndManifest;
     const std::string cwd;
 
+
+    struct {
+        mutable std::mutex mutex{};
+        mutable std::condition_variable cv{};
+        std::future<void> future{};
+        bool shutdownStarted = false;
+    } shutdown{};
+
+
+
     struct {
         std::unordered_map<long, std::shared_ptr<celix::impl::BundleController>> entries{};
         long nextBundleId = 2;
@@ -295,9 +334,9 @@ private:
  * Framework
  **********************************************************************************************************************/
 
-celix::Framework::Framework() {
-    pimpl = std::unique_ptr<Impl>{new Impl{this}};
-    registerFramework(this); //TODO improve ugly.. maybe register impl.. but that is private -> so make register static member functions of impl...
+celix::Framework::Framework(celix::Properties config) {
+    pimpl = std::unique_ptr<Impl>{new Impl{this, std::move(config)}};
+    registerFramework(this);
 }
 celix::Framework::~Framework() {
     unregisterFramework(this);
@@ -305,10 +344,12 @@ celix::Framework::~Framework() {
 celix::Framework::Framework(Framework &&rhs) = default;
 celix::Framework& celix::Framework::operator=(Framework&& rhs) = default;
 
-long celix::Framework::installBundle(std::string name, std::shared_ptr<celix::IBundleActivator> activator, celix::Properties manifest, bool autoStart) {
-    return pimpl->installBundle(std::move(name), std::move(activator), std::move(manifest), autoStart);
+
+long celix::Framework::installBundle(std::string name, std::function<celix::IBundleActivator*(std::shared_ptr<celix::IBundleContext>)> actFactory, celix::Properties manifest, bool autoStart) {
+    return pimpl->installBundle(std::move(name), actFactory, std::move(manifest), autoStart);
 }
 
+
 std::vector<long> celix::Framework::listBundles(bool includeFrameworkBundle) const { return pimpl->listBundles(includeFrameworkBundle); }
 
 bool celix::Framework::useBundle(long bndId, std::function<void(const celix::IBundle &bnd)> use) const {
@@ -324,23 +365,28 @@ bool celix::Framework::stopBundle(long bndId) { return pimpl->stopBundle(bndId);
 bool celix::Framework::uninstallBundle(long bndId) { return pimpl->uninstallBundle(bndId); }
 celix::ServiceRegistry& celix::Framework::registry(const std::string &lang) { return pimpl->registry(lang); }
 
+bool celix::Framework::waitForShutdown() const { return pimpl->waitForShutdown(); }
+
 /***********************************************************************************************************************
  * Celix 'global' functions
  **********************************************************************************************************************/
 
-void celix::registerStaticBundle(std::string symbolicName, const celix::StaticBundleOptions &opts) {
+void celix::registerStaticBundle(
+        std::string symbolicName,
+        std::function<celix::IBundleActivator*(std::shared_ptr<celix::IBundleContext>)> bundleActivatorFactory,
+        celix::Properties manifest) {
     std::lock_guard<std::mutex> lck{staticRegistry.mutex};
-    staticRegistry.bundles.emplace_back(StaticBundleEntry{.symbolicName = std::move(symbolicName), .manifest = opts.manifest, .activatorFactory = opts.bundleActivatorFactory});
     for (auto fw : staticRegistry.frameworks) {
-        fw->installBundle(symbolicName, std::shared_ptr<celix::IBundleActivator>{opts.bundleActivatorFactory()}, opts.manifest);
+        fw->installBundle(symbolicName, bundleActivatorFactory, manifest);
     }
+    staticRegistry.bundles.emplace_back(StaticBundleEntry{.symbolicName = std::move(symbolicName), .manifest = std::move(manifest), .activatorFactory = std::move(bundleActivatorFactory)});
 }
 
 static void registerFramework(celix::Framework *fw) {
     std::lock_guard<std::mutex> lck{staticRegistry.mutex};
     staticRegistry.frameworks.insert(fw);
     for (auto &entry : staticRegistry.bundles) {
-        fw->installBundle(entry.symbolicName, std::shared_ptr<celix::IBundleActivator>{entry.activatorFactory()}, entry.manifest);
+        fw->installBundle(entry.symbolicName, entry.activatorFactory, entry.manifest);
     }
 }
 
diff --git a/libs/registry/gtest/src/RegistryConcurrency_tests.cc b/libs/registry/gtest/src/RegistryConcurrency_tests.cc
index c77c198..f7e86d3 100644
--- a/libs/registry/gtest/src/RegistryConcurrency_tests.cc
+++ b/libs/registry/gtest/src/RegistryConcurrency_tests.cc
@@ -29,8 +29,7 @@ public:
 
     celix::ServiceRegistry& registry() { return reg; }
 private:
-    celix::ServiceRegistry reg{"C/C++"};
-};
+    celix::ServiceRegistry reg{"C++"};
 
 class ICalc {
 public:
diff --git a/libs/registry/gtest/src/Registry_tests.cc b/libs/registry/gtest/src/Registry_tests.cc
index 8c00b11..9bbb899 100644
--- a/libs/registry/gtest/src/Registry_tests.cc
+++ b/libs/registry/gtest/src/Registry_tests.cc
@@ -30,7 +30,7 @@ public:
 
     celix::ServiceRegistry& registry() { return reg; }
 private:
-    celix::ServiceRegistry reg{"C/C++"};
+    celix::ServiceRegistry reg{"C++"};
 };
 
 class MarkerInterface1 {
@@ -264,6 +264,27 @@ TEST_F(RegistryTest, StdFunctionTest) {
     });
 }
 
+TEST_F(RegistryTest, ListServicesTest) {
+    std::vector<std::string> serviceNames = registry().listAllRegisteredServiceNames();
+    EXPECT_EQ(0, serviceNames.size());
+
+    std::function<void()> nop = []{/*nop*/};
+    class MarkerInterface1 {};
+    MarkerInterface1 intf1;
+
+    {
+        auto reg1 = registry().registerFunctionService("nop", nop);
+        serviceNames = registry().listAllRegisteredServiceNames();
+        EXPECT_EQ(1, serviceNames.size());
+
+        auto reg2 = registry().registerService(intf1);
+        serviceNames = registry().listAllRegisteredServiceNames();
+        EXPECT_EQ(2, serviceNames.size());
+    }
+    serviceNames = registry().listAllRegisteredServiceNames();
+    EXPECT_EQ(0, serviceNames.size());
+}
+
 //TODO function use with props and bnd
 //TODO use with filter
 //TODO use with sync test (see BundleContext tests)
\ No newline at end of file
diff --git a/libs/registry/gtest/src/ServiceTracking_tests.cc b/libs/registry/gtest/src/ServiceTracking_tests.cc
index 7a88f1b..035e8a9 100644
--- a/libs/registry/gtest/src/ServiceTracking_tests.cc
+++ b/libs/registry/gtest/src/ServiceTracking_tests.cc
@@ -28,7 +28,7 @@ class ServiceTrackingTest : public ::testing::Test {
 public:
     celix::ServiceRegistry& registry() { return reg; }
 private:
-    celix::ServiceRegistry reg{"C/C++"};
+    celix::ServiceRegistry reg{"C++"};
 };
 
 class MarkerInterface1 {
@@ -62,9 +62,9 @@ TEST_F(ServiceTrackingTest, CreateTrackersTest) {
 }
 
 TEST_F(ServiceTrackingTest, ServicesCountTrackersTest) {
-    MarkerInterface1 intf1;
-    MarkerInterface2 intf2;
-    MarkerInterface3 intf3;
+    MarkerInterface1 intf1{};
+    MarkerInterface2 intf2{};
+    MarkerInterface3 intf3{};
 
     auto trk1 = registry().trackServices<MarkerInterface1>();
     ASSERT_EQ(0, trk1.trackCount());
@@ -103,17 +103,17 @@ TEST_F(ServiceTrackingTest, ServicesCountTrackersTest) {
 }
 
 TEST_F(ServiceTrackingTest, SetServiceTest) {
-    MarkerInterface1 intf1;
-    MarkerInterface2 intf2;
-    MarkerInterface3 intf3;
+    MarkerInterface1 intf1{};
+    MarkerInterface2 intf2{};
+    MarkerInterface3 intf3{};
 
     MarkerInterface1 *ptrToSvc = nullptr;
     //const celix::Properties *ptrToProps = nullptr;
     //const celix::IBundle *ptrToBnd = nullptr;
 
     celix::ServiceTrackerOptions<MarkerInterface1> opts{};
-    opts.set = [&ptrToSvc](MarkerInterface1* svc) {
-        ptrToSvc = svc;
+    opts.set = [&ptrToSvc](std::shared_ptr<MarkerInterface1> svc) {
+        ptrToSvc = svc.get();
     };
 
     auto reg1 = registry().registerService(intf1);
@@ -162,17 +162,17 @@ TEST_F(ServiceTrackingTest, SetServiceWithPropsAndOwnderTest) {
 }
 
 TEST_F(ServiceTrackingTest, AddRemoveTest) {
-    MarkerInterface1 intf1;
-    MarkerInterface2 intf2;
-    MarkerInterface3 intf3;
+    MarkerInterface1 intf1{};
+    MarkerInterface2 intf2{};
+    MarkerInterface3 intf3{};
 
-    std::vector<MarkerInterface1*> services{};
+    std::vector<std::shared_ptr<MarkerInterface1>> services{};
 
     celix::ServiceTrackerOptions<MarkerInterface1> opts{};
-    opts.add = [&services](MarkerInterface1* svc) {
+    opts.add = [&services](std::shared_ptr<MarkerInterface1> svc) {
         services.push_back(svc);
     };
-    opts.remove = [&services](MarkerInterface1* svc) {
+    opts.remove = [&services](std::shared_ptr<MarkerInterface1> svc) {
         services.erase(std::remove(services.begin(), services.end(), svc), services.end());
     };
 
@@ -182,24 +182,24 @@ TEST_F(ServiceTrackingTest, AddRemoveTest) {
 
     auto trk1 = registry().trackServices(opts);
     ASSERT_EQ(1, services.size());
-    EXPECT_EQ(&intf1, services[0]); //should be intf1
+    EXPECT_EQ(&intf1, services[0].get()); //should be intf1
 
     reg1.unregister();
     EXPECT_EQ(0, services.size());
 
     reg1 = registry().registerService(intf1);
     ASSERT_EQ(1, services.size());
-    EXPECT_EQ(&intf1, services[0]); //should be intf1 again
+    EXPECT_EQ(&intf1, services[0].get()); //should be intf1 again
 
     MarkerInterface1 intf4{};
     auto reg4 = registry().registerService(intf4);
     ASSERT_EQ(2, services.size());
-    EXPECT_EQ(&intf1, services[0]);
-    EXPECT_EQ(&intf4, services[1]);
+    EXPECT_EQ(&intf1, services[0].get());
+    EXPECT_EQ(&intf4, services[1].get());
 
     reg1.unregister();
     ASSERT_EQ(1, services.size());
-    EXPECT_EQ(&intf4, services[0]); //intf1 gone -> index 0: intf4
+    EXPECT_EQ(&intf4, services[0].get()); //intf1 gone -> index 0: intf4
 
     trk1.stop();
     EXPECT_EQ(0, services.size());
@@ -207,7 +207,7 @@ TEST_F(ServiceTrackingTest, AddRemoveTest) {
     {
         auto trk2 = registry().trackServices(opts);
         ASSERT_EQ(1, services.size());
-        EXPECT_EQ(&intf4, services[0]);
+        EXPECT_EQ(&intf4, services[0].get());
         //out of scope -> tracker stopped
     }
     EXPECT_EQ(0, services.size()); //stop tracking -> services removed
@@ -218,14 +218,14 @@ TEST_F(ServiceTrackingTest, AddRemoveServicesWithPropsAndOwnderTest) {
 }
 
 TEST_F(ServiceTrackingTest, UpdateTest) {
-    MarkerInterface1 intf1;
-    MarkerInterface2 intf2;
-    MarkerInterface3 intf3;
+    MarkerInterface1 intf1{};
+    MarkerInterface2 intf2{};
+    MarkerInterface3 intf3{};
 
-    std::vector<MarkerInterface1*> services{};
+    std::vector<std::shared_ptr<MarkerInterface1>> services{};
 
     celix::ServiceTrackerOptions<MarkerInterface1> opts{};
-    opts.update = [&services](std::vector<MarkerInterface1*> rankedServices) {
+    opts.update = [&services](std::vector<std::shared_ptr<MarkerInterface1>> rankedServices) {
         services = rankedServices;
     };
 
@@ -236,25 +236,25 @@ TEST_F(ServiceTrackingTest, UpdateTest) {
     auto trk1 = registry().trackServices(opts);
     EXPECT_EQ(1, trk1.trackCount());
     ASSERT_EQ(1, services.size());
-    EXPECT_EQ(&intf1, services[0]); //should be intf1
+    EXPECT_EQ(&intf1, services[0].get()); //should be intf1
 
     reg1.unregister();
     EXPECT_EQ(0, services.size());
 
     reg1 = registry().registerService(intf1);
     ASSERT_EQ(1, services.size());
-    EXPECT_EQ(&intf1, services[0]); //should be intf1 again
+    EXPECT_EQ(&intf1, services[0].get()); //should be intf1 again
 
     MarkerInterface1 intf4{};
     celix::Properties props{std::make_pair(celix::SERVICE_RANKING, "100")};
     auto reg4 = registry().registerService(intf4, std::move(props));
     ASSERT_EQ(2, services.size());
-    EXPECT_EQ(&intf4, services[0]); //note 4 higher ranking
-    EXPECT_EQ(&intf1, services[1]);
+    EXPECT_EQ(&intf4, services[0].get()); //note 4 higher ranking
+    EXPECT_EQ(&intf1, services[1].get());
 
     reg1.unregister();
     ASSERT_EQ(1, services.size());
-    EXPECT_EQ(&intf4, services[0]); //intf1 gone -> index 0: intf4
+    EXPECT_EQ(&intf4, services[0].get()); //intf1 gone -> index 0: intf4
 
     trk1.stop();
     EXPECT_EQ(0, services.size());
@@ -262,7 +262,7 @@ TEST_F(ServiceTrackingTest, UpdateTest) {
     {
         auto trk2 = registry().trackServices(opts);
         ASSERT_EQ(1, services.size());
-        EXPECT_EQ(&intf4, services[0]);
+        EXPECT_EQ(&intf4, services[0].get());
         //out of scope -> tracker stopped
     }
     EXPECT_EQ(0, services.size()); //stop tracking -> services removed
diff --git a/libs/registry/include/celix/Constants.h b/libs/registry/include/celix/Constants.h
index f1fcad3..517a372 100644
--- a/libs/registry/include/celix/Constants.h
+++ b/libs/registry/include/celix/Constants.h
@@ -24,9 +24,10 @@
 namespace celix {
 
     //NOTE manually aligned with celix_constants.h
-    static constexpr const char *const SERVICE_NAME = "service.name";
-    static constexpr const char *const SERVICE_ID = "service.id";
-    static constexpr const char *const SERVICE_RANKING = "service.ranking";
+    static constexpr const char *const SERVICE_NAME = "SERVICE_NAME";
+    static constexpr const char *const SERVICE_ID = "SERVICE_ID";
+    static constexpr const char *const SERVICE_RANKING = "SERVICE_RANKING";
+    static constexpr const char *const SERVICE_BUNDLE = "SERVICE_BUNDLE";
 
     static constexpr const char *const FRAMEWORK_UUID = "framework.uuid";
 
diff --git a/libs/registry/include/celix/Properties.h b/libs/registry/include/celix/Properties.h
index 65fd4ef..1002bfc 100644
--- a/libs/registry/include/celix/Properties.h
+++ b/libs/registry/include/celix/Properties.h
@@ -55,6 +55,12 @@ namespace celix {
         std::string val = getProperty(props, key, std::to_string(defaultValue));
         return std::stoul(val, nullptr, 10);
     }
+
+    /*TODO
+    celix::Properties loadProperties(const std::string &path);
+    celix::Properties loadProperties(std::istream stream);
+    bool storeProperties(const celix::Properties &props, const std::string &path);
+     */
 }
 
 #endif //CXX_CELIX_PROPERTIES_H
diff --git a/libs/registry/include/celix/ServiceRegistry.h b/libs/registry/include/celix/ServiceRegistry.h
index 7bbe16c..710b218 100644
--- a/libs/registry/include/celix/ServiceRegistry.h
+++ b/libs/registry/include/celix/ServiceRegistry.h
@@ -70,25 +70,23 @@ namespace celix {
 
         std::string filter{};
 
-        /*TODO maybe refactor all I* to std::shared_ptr and use a custom deleter to sync whether a bundle is done using
-        all the functions -> i.e. safe delete and possible lock free? Not sure, because a std::shared_ptr instance
-        access it not thread safe?. Investigate */
+        std::function<void(std::shared_ptr<I> svc)> set{};
+        std::function<void(std::shared_ptr<I> svc, const celix::Properties &props)> setWithProperties{};
+        std::function<void(std::shared_ptr<I> svc, const celix::Properties &props, const celix::IResourceBundle &owner)> setWithOwner{};
 
-        std::function<void(I *svc)> set = {};
-        std::function<void(I *svc, const celix::Properties &props)> setWithProperties = {};
-        std::function<void(I *svc, const celix::Properties &props, const celix::IResourceBundle &owner)> setWithOwner = {};
+        std::function<void(std::shared_ptr<I> svc)> add{};
+        std::function<void(std::shared_ptr<I> svc, const celix::Properties &props)> addWithProperties{};
+        std::function<void(std::shared_ptr<I> svc, const celix::Properties &props, const celix::IResourceBundle &owner)> addWithOwner{};
 
-        std::function<void(I *svc)> add = {};
-        std::function<void(I *svc, const celix::Properties &props)> addWithProperties = {};
-        std::function<void(I *svc, const celix::Properties &props, const celix::IResourceBundle &owner)> addWithOwner = {};
+        std::function<void(std::shared_ptr<I> svc)> remove{};
+        std::function<void(std::shared_ptr<I> svc, const celix::Properties &props)> removeWithProperties{};
+        std::function<void(std::shared_ptr<I> svc, const celix::Properties &props, const celix::IResourceBundle &owner)> removeWithOwner{};
 
-        std::function<void(I *svc)> remove = {};
-        std::function<void(I *svc, const celix::Properties &props)> removeWithProperties = {};
-        std::function<void(I *svc, const celix::Properties &props, const celix::IResourceBundle &owner)> removeWithOwner = {};
+        std::function<void(std::vector<std::shared_ptr<I>> rankedServices)> update{};
+        std::function<void(std::vector<std::tuple<std::shared_ptr<I>, const celix::Properties*>> rankedServices)> updateWithProperties{};
+        std::function<void(std::vector<std::tuple<std::shared_ptr<I>, const celix::Properties*, const celix::IResourceBundle *>> rankedServices)> updateWithOwner{};
 
-        std::function<void(std::vector<I*> rankedServices)> update = {};
-        std::function<void(std::vector<std::tuple<I*, const celix::Properties*>> rankedServices)> updateWithProperties = {};
-        std::function<void(std::vector<std::tuple<I*, const celix::Properties*, const celix::IResourceBundle *>> rankedServices)> updateWithOwner = {};
+        //TODO lock free update calls atomics, rcu, hazard pointers ??
     };
 
     //RAII service tracker: out of scope -> stop tracker
@@ -107,7 +105,7 @@ namespace celix {
         const std::string& filter() const;
         bool valid() const;
 
-        //TODO useService(s) calls
+        //TODO use(Function)Service(s) calls
 
         void stop();
     private:
@@ -140,7 +138,8 @@ namespace celix {
         celix::ServiceRegistration registerService(std::shared_ptr<I> svc, celix::Properties props = {}, std::shared_ptr<const celix::IResourceBundle> owner = {}) {
             //TOOD refactor to using a service factory to store the shared or unique_ptr
             auto svcName = celix::serviceName<I>();
-            return registerService(svcName, static_cast<std::shared_ptr<void>>(svc), std::move(props), std::move(owner));
+            auto voidSvc = std::static_pointer_cast<I>(svc);
+            return registerService(svcName, voidSvc, std::move(props), std::move(owner));
         }
 
         template<typename F>
@@ -159,7 +158,7 @@ namespace celix {
         template<typename I>
         //NOTE C++17 typename std::enable_if<std::is_callable<I>::value, long>::type
         long findFunctionService(const std::string &functionName, const std::string &filter = "") const {
-            auto services = functionServiceName<I>(functionName, filter);
+            auto services = findFunctionService<I>(functionName, filter);
             return services.size() > 0 ? services[0] : -1L;
         }
 
@@ -167,14 +166,14 @@ namespace celix {
         //NOTE C++17 typename std::enable_if<!std::is_callable<I>::value, std::vector<long>>::type
         std::vector<long> findServices(const std::string &filter = "") const {
             auto svcName = celix::serviceName<I>();
-            return findServices(svcName, filter);
+            return findAnyServices(svcName, filter);
         }
 
         template<typename F>
         //NOTE C++17 typename std::enable_if<std::is_callable<I>::value, std::vector<long>>::type
         std::vector<long> findFunctionServices(const std::string &functionName, const std::string &filter = "") const {
             auto svcName = celix::functionServiceName<F>(functionName);
-            return findServices(svcName, filter);
+            return findAnyServices(svcName, filter);
         }
 
         template<typename I>
@@ -264,6 +263,30 @@ namespace celix {
         }
 
 
+        //GENERIC / ANY calls. note these work on void
+
+        int useAnyServices(
+                const std::string &svcName,
+                std::function<void(std::shared_ptr<void> svc, const celix::Properties &props,const celix::IResourceBundle &bnd)> use,
+                const std::string &filter = {},
+                std::shared_ptr<const celix::IResourceBundle> requester = {}) const;
+
+        bool useAnyService(
+                const std::string &svcName,
+                std::function<void(std::shared_ptr<void> svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> use,
+                const std::string &filter = {},
+                std::shared_ptr<const celix::IResourceBundle> requester = {}) const;
+
+        std::vector<long> findAnyServices(const std::string &name, const std::string &filter = {}) const;
+
+
+        celix::ServiceTracker trackAnyServices(
+                std::string svcName,
+                ServiceTrackerOptions<void> options,
+                std::shared_ptr<const celix::IResourceBundle> requester = {});
+
+        //some aditional registry info
+        std::vector<std::string> listAllRegisteredServiceNames() const;
         long nrOfRegisteredServices() const;
         long nrOfServiceTrackers() const;
     private:
@@ -283,7 +306,6 @@ namespace celix {
                 std::function<void(I &svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> useWithOwner,
                 const std::string &filter,
                 std::shared_ptr<const celix::IResourceBundle> requester) const;
-        int useServices(const std::string &svcName, std::function<void(void *svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> &use, const std::string &filter, std::shared_ptr<const celix::IResourceBundle> requester) const;
 
         template<typename I>
         bool useService(
@@ -293,16 +315,14 @@ namespace celix {
                 std::function<void(I &svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> useWithOwner,
                 const std::string &filter,
                 std::shared_ptr<const celix::IResourceBundle> requester) const;
-        bool useService(const std::string &svcName, std::function<void(void *svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> &use, const std::string &filter, std::shared_ptr<const celix::IResourceBundle> requester) const;
-
-        //find Services
-        std::vector<long> findServices(const std::string &name, const std::string &filter) const;
-
 
         //track services
         template<typename I>
-        celix::ServiceTracker trackServices(std::string svcName, celix::ServiceTrackerOptions<I> options, std::shared_ptr<const celix::IResourceBundle> requester);
-        celix::ServiceTracker trackServices(std::string svcName, ServiceTrackerOptions<void> options, std::shared_ptr<const celix::IResourceBundle> requester);
+        celix::ServiceTracker trackServices(
+                std::string svcName,
+                celix::ServiceTrackerOptions<I> options,
+                std::shared_ptr<const celix::IResourceBundle> requester);
+
     };
 }
 
@@ -360,8 +380,9 @@ inline int celix::ServiceRegistry::useServices(
         std::function<void(I &svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> useWithOwner,
         const std::string &filter,
         std::shared_ptr<const celix::IResourceBundle> requester) const {
-    std::function<void(void*,const celix::Properties&, const celix::IResourceBundle&)> voidUse = [&](void *svc, const celix::Properties &props, const celix::IResourceBundle &bnd) {
-        I* typedSvc = static_cast<I*>(svc);
+
+    std::function<void(std::shared_ptr<void>, const celix::Properties&, const celix::IResourceBundle&)> voidUse = [&](std::shared_ptr<void> svc, const celix::Properties &props, const celix::IResourceBundle &bnd) {
+        std::shared_ptr<I> typedSvc = std::static_pointer_cast<I>(svc);
         if (use) {
             use(*typedSvc);
         }
@@ -372,7 +393,7 @@ inline int celix::ServiceRegistry::useServices(
             useWithOwner(*typedSvc, props, bnd);
         }
     };
-    return useServices(svcName, voidUse, filter, requester);
+    return useAnyServices(svcName, std::move(voidUse), filter, std::move(requester));
 }
 
 template<typename I>
@@ -383,8 +404,9 @@ inline bool celix::ServiceRegistry::useService(
         std::function<void(I &svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> useWithOwner,
         const std::string &filter,
         std::shared_ptr<const celix::IResourceBundle> requester) const {
-    std::function<void(void*,const celix::Properties&, const celix::IResourceBundle&)> voidUse = [&](void *svc, const celix::Properties &props, const celix::IResourceBundle &bnd) -> void {
-        I* typedSvc = static_cast<I*>(svc);
+
+    std::function<void(std::shared_ptr<void>,const celix::Properties&, const celix::IResourceBundle&)> voidUse = [&](std::shared_ptr<void> svc, const celix::Properties &props, const celix::IResourceBundle &bnd) -> void {
+        std::shared_ptr<I> typedSvc = std::static_pointer_cast<I>(svc);
         if (use) {
             use(*typedSvc);
         }
@@ -395,115 +417,120 @@ inline bool celix::ServiceRegistry::useService(
             useWithOwner(*typedSvc, props, bnd);
         }
     };
-    return useService(svcName, voidUse, filter, requester);
+    return useAnyService(svcName, std::move(voidUse), filter, std::move(requester));
 }
 
 template<typename I>
-inline celix::ServiceTracker celix::ServiceRegistry::trackServices(std::string svcName, const celix::ServiceTrackerOptions<I> options, std::shared_ptr<const celix::IResourceBundle> requester) {
+inline celix::ServiceTracker celix::ServiceRegistry::trackServices(std::string svcName,
+                                                                      ServiceTrackerOptions<I> options,
+                                                                      std::shared_ptr<const celix::IResourceBundle> requester) {
     ServiceTrackerOptions<void> opts{};
     opts.filter = std::move(options.filter);
 
     if (options.set != nullptr) {
         auto set = std::move(options.set);
-        opts.set = [set](void *svc){
-            I *typedSvc = static_cast<I*>(svc);
+        opts.set = [set](std::shared_ptr<void> svc){
+            auto typedSvc = std::static_pointer_cast<I>(svc);
             set(typedSvc);
         };
     }
     if (options.setWithProperties != nullptr) {
         auto set = std::move(options.setWithProperties);
-        opts.setWithProperties = [set](void *svc, const celix::Properties &props){
-            I *typedSvc = static_cast<I*>(svc);
+        opts.setWithProperties = [set](std::shared_ptr<void> svc, const celix::Properties &props){
+            auto typedSvc = std::static_pointer_cast<I>(svc);
             set(typedSvc, props);
         };
     }
     if (options.setWithOwner != nullptr) {
         auto set = std::move(options.setWithOwner);
-        opts.setWithOwner = [set](void *svc, const celix::Properties &props, const celix::IResourceBundle &owner){
-            I *typedSvc = static_cast<I*>(svc);
+        opts.setWithOwner = [set](std::shared_ptr<void> svc, const celix::Properties &props, const celix::IResourceBundle &owner){
+            auto typedSvc = std::static_pointer_cast<I>(svc);
             set(typedSvc, props, owner);
         };
     }
 
     if (options.add != nullptr) {
         auto add = std::move(options.add);
-        opts.add = [add](void *svc) {
-            I *typedSvc = static_cast<I*>(svc); //note actual argument is I*
+        opts.add = [add](std::shared_ptr<void> svc) {
+            auto typedSvc = std::static_pointer_cast<I>(svc);
             add(typedSvc);
         };
     }
     if (options.addWithProperties != nullptr) {
         auto add = std::move(options.addWithProperties);
-        opts.addWithProperties = [add](void *svc, const celix::Properties &props) {
-            I *typedSvc = static_cast<I*>(svc); //note actual argument is I*
+        opts.addWithProperties = [add](std::shared_ptr<void> svc, const celix::Properties &props) {
+            auto typedSvc = std::static_pointer_cast<I>(svc);
             add(typedSvc, props);
         };
     }
     if (options.addWithOwner != nullptr) {
         auto add = std::move(options.addWithOwner);
-        opts.addWithOwner = [add](void *svc, const celix::Properties &props, const celix::IResourceBundle &bnd) {
-            I *typedSvc = static_cast<I*>(svc); //note actual argument is I*
+        opts.addWithOwner = [add](std::shared_ptr<void> svc, const celix::Properties &props, const celix::IResourceBundle &bnd) {
+            auto typedSvc = std::static_pointer_cast<I>(svc);
             add(typedSvc, props, bnd);
         };
     }
 
     if (options.remove != nullptr) {
         auto rem = std::move(options.remove);
-        opts.remove = [rem](void *svc) {
-            I *typedSvc = static_cast<I*>(svc); //note actual argument is I*
+        opts.remove = [rem](std::shared_ptr<void> svc) {
+            auto typedSvc = std::static_pointer_cast<I>(svc);
             rem(typedSvc);
         };
     }
     if (options.removeWithProperties != nullptr) {
         auto rem = std::move(options.removeWithProperties);
-        opts.removeWithProperties = [rem](void *svc, const celix::Properties &props) {
-            I *typedSvc = static_cast<I*>(svc); //note actual argument is I*
+        opts.removeWithProperties = [rem](std::shared_ptr<void> svc, const celix::Properties &props) {
+            auto typedSvc = std::static_pointer_cast<I>(svc);
             rem(typedSvc, props);
         };
     }
     if (options.removeWithOwner != nullptr) {
         auto rem = std::move(options.removeWithOwner);
-        opts.removeWithOwner = [rem](void *svc, const celix::Properties &props, const celix::IResourceBundle &bnd) {
-            I *typedSvc = static_cast<I*>(svc); //note actual argument is I*
+        opts.removeWithOwner = [rem](std::shared_ptr<void> svc, const celix::Properties &props, const celix::IResourceBundle &bnd) {
+            auto typedSvc = std::static_pointer_cast<I>(svc);
             rem(typedSvc, props, bnd);
         };
     }
 
     if (options.update != nullptr) {
         auto update = std::move(options.update);
-        opts.update = [update](std::vector<void*> rankedServices) {
-            std::vector<I*> typedServices{};
+        opts.update = [update](std::vector<std::shared_ptr<void>> rankedServices) {
+            std::vector<std::shared_ptr<I>> typedServices{};
             typedServices.reserve(rankedServices.size());
-            for (void *svc : rankedServices) {
-                typedServices.push_back(static_cast<I*>(svc));
+            for (auto &svc : rankedServices) {
+                auto typedSvc = std::static_pointer_cast<I>(svc);
+                typedServices.push_back(typedSvc);
             }
             update(std::move(typedServices));
         };
     }
     if (options.updateWithProperties != nullptr) {
         auto update = std::move(options.updateWithProperties);
-        opts.updateWithProperties = [update](std::vector<std::tuple<void*, const celix::Properties *>> rankedServices) {
-            std::vector<std::tuple<I*, const celix::Properties*>> typedServices{};
+        opts.updateWithProperties = [update](std::vector<std::tuple<std::shared_ptr<void>, const celix::Properties *>> rankedServices) {
+            std::vector<std::tuple<std::shared_ptr<I>, const celix::Properties*>> typedServices{};
             typedServices.reserve(rankedServices.size());
             for (auto &tuple : rankedServices) {
-                typedServices.push_back(std::make_tuple(static_cast<I*>(std::get<0>(tuple)), std::get<1>(tuple)));
+                auto typedSvc = std::static_pointer_cast<I>(std::get<0>(tuple));
+                typedServices.push_back(std::make_tuple(typedSvc, std::get<1>(tuple)));
             }
             update(std::move(typedServices));
         };
     }
     if (options.updateWithOwner != nullptr) {
         auto update = std::move(options.updateWithOwner);
-        opts.updateWithOwner = [update](std::vector<std::tuple<void*, const celix::Properties *, const celix::IResourceBundle*>> rankedServices) {
-            std::vector<std::tuple<I*, const celix::Properties*, const celix::IResourceBundle*>> typedServices{};
+        opts.updateWithOwner = [update](std::vector<std::tuple<std::shared_ptr<void>, const celix::Properties *, const celix::IResourceBundle*>> rankedServices) {
+            std::vector<std::tuple<std::shared_ptr<I>, const celix::Properties*, const celix::IResourceBundle*>> typedServices{};
             typedServices.reserve(rankedServices.size());
             for (auto &tuple : rankedServices) {
-                typedServices.push_back(std::make_tuple(static_cast<I*>(std::get<0>(tuple)), std::get<1>(tuple), std::get<2>(tuple)));
+                auto typedSvc = std::static_pointer_cast<I>(std::get<0>(tuple));
+                typedServices.push_back(std::make_tuple(typedSvc, std::get<1>(tuple), std::get<2>(tuple)));
             }
             update(std::move(typedServices));
         };
     }
 
-    return trackServices(std::move(svcName), std::move(opts), requester);
+    return trackAnyServices(std::move(svcName), std::move(opts), requester);
 }
 
 #endif //CXX_CELIX_SERVICEREGISTRY_H
diff --git a/libs/registry/src/ServiceRegistry.cc b/libs/registry/src/ServiceRegistry.cc
index 862013f..ac9a9dd 100644
--- a/libs/registry/src/ServiceRegistry.cc
+++ b/libs/registry/src/ServiceRegistry.cc
@@ -23,7 +23,7 @@
 #include <mutex>
 #include <set>
 #include <utility>
-#include <thread>
+#include <future>
 
 #include <glog/logging.h>
 
@@ -85,13 +85,12 @@ namespace {
         bool factory() const { return svcFactory != nullptr; }
 
         void incrUsage() const {
-            LOG(WARNING) << "TODO use shared_ptr unique instead ?? how to sync?";
+            //TODO look at atomics or shared_ptr to handled to counts / sync
             std::lock_guard<std::mutex> lck{mutex};
             usage += 1;
         }
 
         void decrUsage() const {
-            LOG(WARNING) << "TODO use shared_ptr unique instead ?? how is sync?";
             std::lock_guard<std::mutex> lck{mutex};
             usage -= 1;
             cond.notify_all();
@@ -140,17 +139,15 @@ namespace {
         ~SvcTrackerEntry() {}
 
         void clear() {
-            //TODO update, make special rem (e.g. only call the use set callbacks once with a nullptr)
             std::vector<std::shared_ptr<const SvcEntry>> removeEntries{};
             {
                 std::lock_guard<std::mutex> lck{tracked.mutex};
-                for (auto &entry : tracked.entries) {
-                    removeEntries.push_back(entry);
+                for (const auto &entry : tracked.entries) {
+                    removeEntries.push_back(entry.first);
                 }
-                tracked.entries.clear();
             }
             for (auto &entry : removeEntries) {
-                remMatch(entry); //note fill try to erase entry from entries again, TODO check if this is safe
+                remMatch(entry);
             }
         }
 
@@ -171,56 +168,74 @@ namespace {
 
         void addMatch(std::shared_ptr<const SvcEntry> entry) {
             //increase usage so that services cannot be removed while a service tracker is still active
+
+            //new custom deleter which arranges the count & sync for the used services
+
             entry->incrUsage();
 
+            void *rawSvc = entry->service(*owner);
+            //NOTE creating a shared_ptr with a custom deleter, so that the SvcEntry usage is synced with this shared_ptr.
+            auto svc = std::shared_ptr<void>{rawSvc, [entry](void *) {
+                entry->decrUsage();
+            }};
+
             {
                 std::lock_guard<std::mutex> lck{tracked.mutex};
-                tracked.entries.insert(entry);
+                tracked.entries.emplace(entry, svc);
             }
 
             //call callbacks
             callSetCallbacks();
-            callAddRemoveCallbacks(entry, true);
+            callAddRemoveCallbacks(entry, svc, true);
             callUpdateCallbacks();
         }
 
         void remMatch(const std::shared_ptr<const SvcEntry> &entry) {
+            std::shared_ptr<void> svc{};
             {
                 std::lock_guard<std::mutex> lck{tracked.mutex};
-                tracked.entries.erase(entry);
+                auto it = tracked.entries.find(entry);
+                svc = it->second;
+                tracked.entries.erase(it);
             }
 
             //call callbacks
-            callSetCallbacks();
-            callAddRemoveCallbacks(entry, false);
+            callSetCallbacks(); //note also removed highest if that was set to this svc
+            callAddRemoveCallbacks(entry, svc, false);
             callUpdateCallbacks();
 
-            //decrease usage so that services cannot be removed while a service tracker is still active
-            entry->decrUsage();
+
+            //note sync will be done on the SvcEntry usage, which is controlled by the tracker svc shared ptr
         }
 
-        void callAddRemoveCallbacks(const std::shared_ptr<const SvcEntry> &updatedEntry, bool add) {
+        void callAddRemoveCallbacks(const std::shared_ptr<const SvcEntry> &entry, std::shared_ptr<void> &svc, bool add) {
             auto &update = add ? opts.add : opts.remove;
-            if (update != nullptr) {
-                void *svc = updatedEntry->service(*owner);
+            auto &updateWithProps = add ? opts.addWithProperties : opts.removeWithProperties;
+            auto &updateWithOwner = add ? opts.addWithOwner : opts.removeWithOwner;
+            if (update) {
                 update(svc);
             }
-            //TODO rest of add/remove
+            if (updateWithProps) {
+                updateWithProps(svc, entry->props);
+            }
+            if (updateWithOwner) {
+                updateWithOwner(svc, entry->props, *entry->owner);
+            }
         }
 
         void callSetCallbacks() {
-            std::shared_ptr<const SvcEntry> currentHighest;
+            std::shared_ptr<void> currentHighestSvc{};
+            std::shared_ptr<const SvcEntry> currentHighestSvcEntry{};
             bool highestUpdated = false;
             {
                 std::lock_guard<std::mutex> lck{tracked.mutex};
                 auto begin = tracked.entries.begin();
-                if (begin == tracked.entries.end()) {
-                    currentHighest = nullptr;
-                } else {
-                    currentHighest = *begin;
+                if (begin != tracked.entries.end()) {
+                    currentHighestSvc = begin->second;
+                    currentHighestSvcEntry = begin->first;
                 }
-                if (currentHighest != tracked.highest) {
-                    tracked.highest = currentHighest;
+                if (currentHighestSvc != tracked.highest) {
+                    tracked.highest = currentHighestSvc;
                     highestUpdated = true;
                 }
             }
@@ -228,43 +243,58 @@ namespace {
             //TODO race condition. highest can be updated because lock is released.
 
             if (highestUpdated) {
-                void *svc = currentHighest == nullptr ? nullptr : currentHighest->service(*owner);
-                if (opts.set != nullptr) {
-                    opts.set(svc);
+                if (opts.set) {
+                    opts.set(currentHighestSvc); //note can be nullptr
+                }
+                if (opts.setWithProperties) {
+                    opts.setWithProperties(currentHighestSvc, currentHighestSvcEntry->props);
+                }
+                if (opts.setWithOwner) {
+                    opts.setWithOwner(currentHighestSvc, currentHighestSvcEntry->props, *currentHighestSvcEntry->owner);
                 }
-                //TODO rest of set
             }
         }
 
         void callUpdateCallbacks() {
+            std::vector<std::tuple<std::shared_ptr<void>, const celix::Properties*, const celix::IResourceBundle*>> rankedServices{};
+            if (opts.update || opts.updateWithProperties || opts.updateWithOwner) {
+                //fill vector
+                std::lock_guard<std::mutex> lck{tracked.mutex};
+                rankedServices.reserve(tracked.entries.size());
+                for (auto &tracked : tracked.entries) {
+                    rankedServices.push_back(std::make_tuple(tracked.second, &tracked.first->props, tracked.first->owner.get()));
+                }
+            }
             if (opts.update) {
-                std::vector<void *> rankedServices{};
-                {
-                    std::lock_guard<std::mutex> lck{tracked.mutex};
-                    rankedServices.reserve(tracked.entries.size());
-                    for (auto &tracked : tracked.entries) {
-                        rankedServices.push_back(tracked->service(*owner));
-                    }
+                std::vector<std::shared_ptr<void>> rnk{};
+                for (auto &tuple : rankedServices) {
+                    rnk.push_back(std::get<0>(tuple));
+                }
+                opts.update(std::move(rnk));
+            }
+            if (opts.updateWithProperties) {
+                std::vector<std::tuple<std::shared_ptr<void>, const celix::Properties*>> rnk{};
+                for (auto &tuple : rankedServices) {
+                    rnk.push_back(std::make_pair(std::get<0>(tuple), std::get<1>(tuple)));
                 }
-                opts.update(std::move(rankedServices));
+                opts.updateWithProperties(std::move(rnk));
+            }
+            if (opts.updateWithOwner) {
+                opts.updateWithOwner(std::move(rankedServices));
             }
-            //TODO rest of the update calls
         }
 
         int count() const {
-            LOG(INFO) << "TODO use shared_ptr count instead";
             std::lock_guard<std::mutex> lck{tracked.mutex};
             return (int)tracked.entries.size();
         }
 
         void incrUsage() const {
-            LOG(INFO) << "TODO use shared_ptr count instead";
             std::lock_guard<std::mutex> lck{mutex};
             usage += 1;
         }
 
         void decrUsage() const {
-            LOG(INFO) << "TODO use shared_ptr count instead";
             std::lock_guard<std::mutex> lck{mutex};
             usage -= 1;
             cond.notify_all();
@@ -277,12 +307,11 @@ namespace {
     private:
         struct {
             mutable std::mutex mutex; //protects matchedEntries & highestRanking
-            std::set<std::shared_ptr<const SvcEntry>, SvcEntryLess> entries{};
-            std::shared_ptr<const SvcEntry> highest{};
+            std::map<std::shared_ptr<const SvcEntry>, std::shared_ptr<void>, SvcEntryLess> entries{};
+            std::shared_ptr<void> highest{};
         } tracked{};
 
 
-        //sync TODO refactor to atomics
         mutable std::mutex mutex{};
         mutable std::condition_variable cond{};
         mutable int usage{1};
@@ -354,6 +383,7 @@ public:
 
         //Add to registry
         std::shared_ptr<const celix::IResourceBundle> bnd = owner ? owner : emptyBundle;
+        props[celix::SERVICE_BUNDLE] = std::to_string(bnd->id());
 
         if (factory) {
             VLOG(1) << "Registering service factory '" << svcName << "' from bundle id " << owner->id() << std::endl;
@@ -369,8 +399,8 @@ public:
         services.cache[entry->svcId] = entry;
 
         //update trackers
-        std::thread updateThread{[&]{updateTrackers(entry, true);}};
-        updateThread.join();
+        auto future = std::async([&]{updateTrackers(entry, true);});
+        future.wait();
         entry->decrUsage(); //note usage started at 1 during creation
 
 
@@ -395,17 +425,22 @@ public:
 
         {
             std::lock_guard<std::mutex> lock{services.mutex};
-            const auto it = services.cache.find(svcId);
-            if (it != services.cache.end()) {
-                match = it->second;
-                services.cache.erase(it);
-                services.registry.at(match->svcName).erase(match);
+            const auto cacheIter = services.cache.find(svcId);
+            if (cacheIter != services.cache.end()) {
+                match = cacheIter->second;
+                services.cache.erase(cacheIter);
+                const auto svcSetIter = services.registry.find(match->svcName);
+                svcSetIter->second.erase(match);
+                if (svcSetIter->second.empty()) {
+                    //last entry in the registry for this service name.
+                    services.registry.erase(svcSetIter);
+                }
             }
         }
 
         if (match) {
-            std::thread updateThread{[&]{updateTrackers(match, false);}};
-            updateThread.join();
+            auto future = std::async([&]{updateTrackers(match, false);});
+            future.wait();
             match->waitTillUnused();
         } else {
             LOG(WARNING) << "Cannot unregister service. Unknown service id: " << svcId << "." << std::endl;
@@ -430,8 +465,8 @@ public:
 
         if (match) {
             match->waitTillUnused();
-            std::thread clearThread{[&]{match->clear();}}; //ensure that all service are removed using the callbacks
-            clearThread.join();
+            auto future = std::async([&]{match->clear();}); //ensure that all service are removed using the callbacks
+            future.wait();
         } else {
             LOG(WARNING) << "Cannot remove tracker. Unknown tracker id: " << trkId << "." << std::endl;
         }
@@ -458,6 +493,15 @@ public:
             match->decrUsage();
         }
     }
+
+    std::vector<std::string> listAllRegisteredServiceNames() const {
+        std::vector<std::string> result{};
+        std::lock_guard<std::mutex> lck{services.mutex};
+        for (const auto& pair : services.registry) {
+            result.emplace_back(std::string{pair.first});
+        }
+        return result;
+    }
 };
 
 
@@ -496,7 +540,9 @@ celix::ServiceRegistration celix::ServiceRegistry::registerServiceFactory(std::s
 //TODO add useService(s) call to ServiceTracker object for fast service access
 
 //TODO move to Impl
-celix::ServiceTracker celix::ServiceRegistry::trackServices(std::string svcName, celix::ServiceTrackerOptions<void> options, std::shared_ptr<const celix::IResourceBundle> requester) {
+celix::ServiceTracker celix::ServiceRegistry::trackAnyServices(std::string svcName,
+                                                               celix::ServiceTrackerOptions<void> options,
+                                                               std::shared_ptr<const celix::IResourceBundle> requester) {
     //TODO create new tracker event and start new thread to update track trackers
     long trkId = 0;
     {
@@ -523,13 +569,13 @@ celix::ServiceTracker celix::ServiceRegistry::trackServices(std::string svcName,
             pimpl->trackers.registry[trkEntry->svcName].insert(trkEntry);
             pimpl->trackers.cache[trkEntry->id] = trkEntry;
         }
-        std::thread updateThread{[&]{
+        auto future = std::async([&]{
             for (auto &svcEntry : services) {
                 trkEntry->addMatch(svcEntry);
                 svcEntry->decrUsage();
             }
-        }};
-        updateThread.join();
+        });
+        future.wait();
         trkEntry->decrUsage(); //note trkEntry usage started at 1
 
         auto untrack = [this, trkId]() -> void {
@@ -556,16 +602,16 @@ long celix::ServiceRegistry::nrOfServiceTrackers() const {
         
 //TODO unregister tracker with remove tracker event in a new thread
 //TODO move to Impl
-std::vector<long> celix::ServiceRegistry::findServices(const std::string &svcName, const std::string &rawFilter) const {
+std::vector<long> celix::ServiceRegistry::findAnyServices(const std::string &name, const std::string &f) const {
     std::vector<long> result{};
-    celix::Filter filter = rawFilter;
+    celix::Filter filter = f;
     if (!filter.valid()) {
-        LOG(WARNING) << "Invalid filter (" << rawFilter << ") provided. Cannot find services" << std::endl;
+        LOG(WARNING) << "Invalid filter (" << f << ") provided. Cannot find services" << std::endl;
         return result;
     }
 
     std::lock_guard<std::mutex> lock{pimpl->services.mutex};
-    const auto it = pimpl->services.registry.find(svcName);
+    const auto it = pimpl->services.registry.find(name);
     if (it != pimpl->services.registry.end()) {
         const auto &services = it->second;
         for (const auto &visit : services) {
@@ -584,10 +630,14 @@ long celix::ServiceRegistry::nrOfRegisteredServices() const {
 }
 
 //TODO move to Impl
-int celix::ServiceRegistry::useServices(const std::string &svcName, std::function<void(void *svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> &use, const std::string &rawFilter, std::shared_ptr<const celix::IResourceBundle> requester) const {
-    celix::Filter filter = rawFilter;
+int celix::ServiceRegistry::useAnyServices(const std::string &svcName,
+                                           std::function<void(std::shared_ptr<void> svc, const celix::Properties &props,
+                                                              const celix::IResourceBundle &bnd)> use,
+                                           const std::string &f,
+                                           std::shared_ptr<const celix::IResourceBundle> requester) const {
+    celix::Filter filter = f;
     if (!filter.valid()) {
-        LOG(WARNING) << "Invalid filter (" << rawFilter << ") provided. Cannot find services" << std::endl;
+        LOG(WARNING) << "Invalid filter (" << f << ") provided. Cannot find services" << std::endl;
         return 0;
     }
 
@@ -607,7 +657,11 @@ int celix::ServiceRegistry::useServices(const std::string &svcName, std::functio
     }
 
     for (const std::shared_ptr<const SvcEntry> &entry : matches) {
-        use(entry->service(*requester), entry->props, *entry->owner);
+        void *rawSvc = entry->service(*requester);
+        std::shared_ptr<void> svc{rawSvc, [entry](void *) {
+            entry->decrUsage();
+        }};
+        use(svc, entry->props, *entry->owner);
         entry->decrUsage();
     }
 
@@ -615,10 +669,14 @@ int celix::ServiceRegistry::useServices(const std::string &svcName, std::functio
 }
 
 //TODO move to Impl
-bool celix::ServiceRegistry::useService(const std::string &svcName, std::function<void(void *svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> &use, const std::string &rawFilter, std::shared_ptr<const celix::IResourceBundle> requester) const {
-    celix::Filter filter = rawFilter;
+bool celix::ServiceRegistry::useAnyService(const std::string &svcName,
+                                           std::function<void(std::shared_ptr<void> svc, const celix::Properties &props,
+                                                              const celix::IResourceBundle &bnd)> use,
+                                           const std::string &f,
+                                           std::shared_ptr<const celix::IResourceBundle> requester) const {
+    celix::Filter filter = f;
     if (!filter.valid()) {
-        LOG(WARNING) << "Invalid filter (" << rawFilter << ") provided. Cannot find services" << std::endl;
+        LOG(WARNING) << "Invalid filter (" << f << ") provided. Cannot find services" << std::endl;
         return false;
     }
 
@@ -639,13 +697,20 @@ bool celix::ServiceRegistry::useService(const std::string &svcName, std::functio
     }
 
     if (match != nullptr) {
-        use(match->service(*requester), match->props, *match->owner);
-        match->decrUsage();
+        void *rawSvc = match->service(*requester);
+        std::shared_ptr<void> svc{rawSvc, [match](void *) {
+            match->decrUsage();
+        }};
+        use(svc, match->props, *match->owner);
     }
 
     return match != nullptr;
 }
 
+std::vector<std::string> celix::ServiceRegistry::listAllRegisteredServiceNames() const {
+    return pimpl->listAllRegisteredServiceNames();
+}
+
 /**********************************************************************************************************************
   Service Registration
  **********************************************************************************************************************/


[celix] 11/22: CELIX-438: Small refactoring for gcc 5 compiler

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 9f0369b66b6e21608dd56d983a2a37bbcdbb559d
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Sat Jan 5 18:45:23 2019 +0100

    CELIX-438: Small refactoring for gcc 5 compiler
---
 bundles/shell/cxx_shell/src/ShellActivator.cc        | 2 +-
 bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc | 2 +-
 libs/registry/src/ServiceRegistry.cc                 | 6 +++---
 3 files changed, 5 insertions(+), 5 deletions(-)

diff --git a/bundles/shell/cxx_shell/src/ShellActivator.cc b/bundles/shell/cxx_shell/src/ShellActivator.cc
index 807a9b3..8d5d3fe 100644
--- a/bundles/shell/cxx_shell/src/ShellActivator.cc
+++ b/bundles/shell/cxx_shell/src/ShellActivator.cc
@@ -155,7 +155,7 @@ namespace {
         manifest[celix::MANIFEST_BUNDLE_NAME] = "Shell";
         manifest[celix::MANIFEST_BUNDLE_GROUP] = "Celix";
         manifest[celix::MANIFEST_BUNDLE_VERSION] = "1.0.0";
-        celix::registerStaticBundle<ShellBundleActivator>("celix::Shell", manifest, resources, resourcesLen);
+        celix::registerStaticBundle<ShellBundleActivator>("celix::Shell", std::move(manifest), resources, resourcesLen);
     }
 
     __attribute__((destructor))
diff --git a/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc b/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc
index ec48f6b..0958ab0 100644
--- a/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc
+++ b/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc
@@ -147,6 +147,6 @@ namespace {
         manifest[celix::MANIFEST_BUNDLE_NAME] = "Shell Tui";
         manifest[celix::MANIFEST_BUNDLE_GROUP] = "Celix";
         manifest[celix::MANIFEST_BUNDLE_VERSION] = "1.0.0";
-        celix::registerStaticBundle<ShellTuiBundleActivator>("celix::ShellTui", manifest);
+        celix::registerStaticBundle<ShellTuiBundleActivator>("celix::ShellTui", std::move(manifest));
     }
 }
\ No newline at end of file
diff --git a/libs/registry/src/ServiceRegistry.cc b/libs/registry/src/ServiceRegistry.cc
index 001b08e..58d5778 100644
--- a/libs/registry/src/ServiceRegistry.cc
+++ b/libs/registry/src/ServiceRegistry.cc
@@ -263,8 +263,8 @@ namespace {
                 //fill vector
                 std::lock_guard<std::mutex> lck{tracked.mutex};
                 rankedServices.reserve(tracked.entries.size());
-                for (auto &tracked : tracked.entries) {
-                    rankedServices.push_back(std::make_tuple(tracked.second, &tracked.first->props, tracked.first->owner.get()));
+                for (auto &entry : tracked.entries) {
+                    rankedServices.push_back(std::make_tuple(entry.second, &entry.first->props, entry.first->owner.get()));
                 }
             }
             if (opts.update) {
@@ -780,4 +780,4 @@ celix::ServiceTracker& celix::ServiceTracker::operator=(celix::ServiceTracker &&
 int celix::ServiceTracker::trackCount() const { return pimpl ? pimpl->entry->count() : 0; }
 const std::string& celix::ServiceTracker::serviceName() const { return pimpl? pimpl->entry->svcName : emptyString; }
 const std::string& celix::ServiceTracker::filter() const { return pimpl ? pimpl->entry->filter.filterStr : emptyString; }
-bool celix::ServiceTracker::valid() const { return pimpl != nullptr; }
\ No newline at end of file
+bool celix::ServiceTracker::valid() const { return pimpl != nullptr; }


[celix] 03/22: CELIX-438: Removes prev C++ impl and adds a sync/race condition test for the svc reg.

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 01613bd9e0ab03503c67d57528e0d772e08a0452
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Wed Jan 2 22:37:54 2019 +0100

    CELIX-438: Removes prev C++ impl and adds a sync/race condition test for the svc reg.
---
 bundles/shell/cxx_shell/CMakeLists.txt             |   1 +
 bundles/shell/cxx_shell/src/HelpCommand.cc         |   2 +-
 bundles/shell/cxx_shell/src/InspectCommand.cc      |   4 +-
 bundles/shell/cxx_shell/src/LbCommand.cc           |   6 +-
 bundles/shell/cxx_shell/src/QueryCommand.cc        |  76 +++
 bundles/shell/cxx_shell/src/ShellActivator.cc      |   7 +-
 bundles/shell/cxx_shell/src/StopAndStartCommand.cc |   6 +-
 bundles/shell/cxx_shell/src/commands.h             |  14 +-
 .../shell/cxx_shell_tui/src/ShellTuiActivator.cc   |   2 +-
 examples/celix-examples/CMakeLists.txt             |   6 +-
 .../shell_command_example/CMakeLists.txt           |   6 +-
 libs/framework/CMakeLists.txt                      |   4 -
 libs/framework/gtest/CMakeLists.txt                |  42 --
 .../framework/gtest/src/cxx_BundleContext_tests.cc | 252 --------
 libs/framework/gtest/src/cxx_Bundle_tests.cc       |  65 --
 .../gtest/src/cxx_FrameworkFactory_tests.cc        |  54 --
 libs/framework/gtest/src/cxx_Framework_tests.cc    |  45 --
 .../gtest/src/cxx_ServiceAdapter_tests.cc          | 302 ---------
 libs/framework/gtest/src/main.cc                   |  25 -
 libs/framework/include/celix/Bundle.h              |  73 ---
 libs/framework/include/celix/BundleActivator.h     | 104 ---
 libs/framework/include/celix/BundleContext.h       | 291 ---------
 libs/framework/include/celix/Celix.h               |  37 --
 libs/framework/include/celix/Constants.h           |  40 --
 libs/framework/include/celix/Framework.h           |  52 --
 libs/framework/include/celix/FrameworkFactory.h    |  66 --
 libs/framework/include/celix/IBundleActivator.h    |  37 --
 libs/framework/include/celix/Properties.h          |  60 --
 libs/framework/include/celix/ServiceAdapter.h      | 152 -----
 libs/framework/include/celix/dm/Properties.h       |   5 +-
 .../include/celix/impl/BundleContextImpl.h         | 710 ---------------------
 libs/framework/include/celix/impl/BundleImpl.h     | 180 ------
 libs/framework/include/celix/impl/FrameworkImpl.h  | 127 ----
 libs/framework_cxx/CMakeLists.txt                  |   3 +-
 libs/framework_cxx/gtest/src/Framework_tests.cc    |   6 +-
 .../celix/{IBundleContext.h => BundleContext.h}    |  80 ++-
 libs/framework_cxx/include/celix/Framework.h       |  15 +-
 .../framework_cxx/include/celix/IBundleActivator.h |   4 -
 libs/framework_cxx/include/celix/api.h             |   4 +-
 .../src/Bundle.cc}                                 |  25 +-
 libs/framework_cxx/src/Bundle.h                    |  85 +++
 libs/framework_cxx/src/BundleContext.cc            |  56 ++
 libs/framework_cxx/src/BundleController.h          |  73 +++
 libs/framework_cxx/src/BundleImpl.h                | 161 -----
 libs/framework_cxx/src/Framework.cc                |  28 +-
 libs/registry/gtest/CMakeLists.txt                 |   1 +
 .../gtest/src/RegistryConcurrency_tests.cc         |  99 ++-
 libs/registry/include/celix/IResourceBundle.h      |   2 +
 libs/registry/include/celix/ServiceRegistry.h      |  48 +-
 49 files changed, 566 insertions(+), 2977 deletions(-)

diff --git a/bundles/shell/cxx_shell/CMakeLists.txt b/bundles/shell/cxx_shell/CMakeLists.txt
index 5373caf..ccdf03b 100644
--- a/bundles/shell/cxx_shell/CMakeLists.txt
+++ b/bundles/shell/cxx_shell/CMakeLists.txt
@@ -31,6 +31,7 @@ add_library(celix_cxx_shell SHARED
         src/HelpCommand.cc
         src/StopAndStartCommand.cc
         src/InspectCommand.cc
+        src/QueryCommand.cc
 )
 target_include_directories(celix_cxx_shell PRIVATE src)
 target_link_libraries(celix_cxx_shell PRIVATE celix_cxx_shell_api)
diff --git a/bundles/shell/cxx_shell/src/HelpCommand.cc b/bundles/shell/cxx_shell/src/HelpCommand.cc
index 3f5f5e9..0ed5fea 100644
--- a/bundles/shell/cxx_shell/src/HelpCommand.cc
+++ b/bundles/shell/cxx_shell/src/HelpCommand.cc
@@ -22,7 +22,7 @@
 #include "celix/api.h"
 #include "celix/IShellCommand.h"
 
-celix::ServiceRegistration impl::registerHelp(std::shared_ptr<celix::IBundleContext> ctx) {
+celix::ServiceRegistration impl::registerHelp(std::shared_ptr<celix::BundleContext> ctx) {
 
     celix::ShellCommandFunction help = [ctx](const std::string &, const std::vector<std::string> &commandArguments, std::ostream &out, std::ostream &) {
 
diff --git a/bundles/shell/cxx_shell/src/InspectCommand.cc b/bundles/shell/cxx_shell/src/InspectCommand.cc
index da3bf24..e31e4a8 100644
--- a/bundles/shell/cxx_shell/src/InspectCommand.cc
+++ b/bundles/shell/cxx_shell/src/InspectCommand.cc
@@ -26,7 +26,7 @@
 
 namespace {
 
-    void inspect(std::shared_ptr<celix::IBundleContext> ctx, const std::string &, const std::vector<std::string> &cmdArgs, std::ostream &out, std::ostream &) {
+    void inspect(std::shared_ptr<celix::BundleContext> ctx, const std::string &, const std::vector<std::string> &cmdArgs, std::ostream &out, std::ostream &) {
         if (cmdArgs.empty()) {
             out << "Provide a bundle id" << std::endl;
         } else {
@@ -58,7 +58,7 @@ namespace {
 }
 
 
-celix::ServiceRegistration impl::registerInspect(std::shared_ptr<celix::IBundleContext> ctx) {
+celix::ServiceRegistration impl::registerInspect(std::shared_ptr<celix::BundleContext> ctx) {
     using namespace std::placeholders;
     celix::ShellCommandFunction cmd = std::bind(&inspect, ctx, _1, _2, _3, _4);
 
diff --git a/bundles/shell/cxx_shell/src/LbCommand.cc b/bundles/shell/cxx_shell/src/LbCommand.cc
index 5c1b07c..4b39cf1 100644
--- a/bundles/shell/cxx_shell/src/LbCommand.cc
+++ b/bundles/shell/cxx_shell/src/LbCommand.cc
@@ -24,7 +24,7 @@
 namespace {
     class LbCommand : public celix::IShellCommand {
     public:
-        LbCommand(std::shared_ptr<celix::IBundleContext> _ctx) : ctx{std::move(_ctx)} {}
+        LbCommand(std::shared_ptr<celix::BundleContext> _ctx) : ctx{std::move(_ctx)} {}
 
         void executeCommand(const std::string &, const std::vector<std::string> &cmdArgs, std::ostream &out,
                             std::ostream &) noexcept override {
@@ -39,11 +39,11 @@ namespace {
         }
 
     private:
-        std::shared_ptr<celix::IBundleContext> ctx;
+        std::shared_ptr<celix::BundleContext> ctx;
     };
 }
 
-celix::ServiceRegistration impl::registerLb(std::shared_ptr<celix::IBundleContext> ctx) {
+celix::ServiceRegistration impl::registerLb(std::shared_ptr<celix::BundleContext> ctx) {
     celix::Properties props{};
     props[celix::IShellCommand::COMMAND_NAME] = "lb";
     props[celix::IShellCommand::COMMAND_USAGE] = "list bundles. Default only the groupless bundles are listed. Use -a to list all bundles." \
diff --git a/bundles/shell/cxx_shell/src/QueryCommand.cc b/bundles/shell/cxx_shell/src/QueryCommand.cc
new file mode 100644
index 0000000..225709c
--- /dev/null
+++ b/bundles/shell/cxx_shell/src/QueryCommand.cc
@@ -0,0 +1,76 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "commands.h"
+
+#include <functional>
+
+#include "celix/api.h"
+#include "celix/IShellCommand.h"
+
+namespace {
+
+    void query(std::shared_ptr<celix::BundleContext> ctx, const std::string &, const std::vector<std::string> &cmdArgs, std::ostream &out, std::ostream &) {
+        if (cmdArgs.empty()) {
+            auto names = ctx->registry().listAllRegisteredServiceNames();
+            out << "Available Service Names:" << std::endl;
+            for (auto &name : names) {
+                out << "|- " << name << std::endl;
+            }
+        } else if (cmdArgs.size() == 1) {
+            //need no of minimal 2 args
+            out << "Provide a service name and filter" << std::endl;
+        } else {
+            std::string lang{};
+            std::string svcName{};
+            std::string filter{};
+            if (cmdArgs.size() >= 3) {
+                lang = cmdArgs[0];
+                svcName = cmdArgs[1];
+                filter = cmdArgs[2];
+            } else {
+                lang = celix::CXX_LANG;
+                svcName = cmdArgs[0];
+                filter = cmdArgs[1];
+            }
+
+
+            auto &reg = ctx->bundle()->framework().registry(lang);
+            out << "Result '" << svcName << " " << filter << "':" << std::endl;
+            reg.useAnyServices(svcName, [&](std::shared_ptr<void>, const celix::Properties& props, const celix::IResourceBundle&) {
+                out << "|- Service: " << celix::getProperty(props, celix::SERVICE_NAME, "!Error") << std::endl;
+                for (auto &pair : props) {
+                    out << "   |- " << pair.first << " = " << pair.second << std::endl;
+                }
+            }, filter, ctx->bundle());
+        }
+    }
+}
+
+
+celix::ServiceRegistration impl::registerQuery(std::shared_ptr<celix::BundleContext> ctx) {
+    using namespace std::placeholders;
+    celix::ShellCommandFunction cmd = std::bind(&query, ctx, _1, _2, _3, _4);
+
+    celix::Properties props{};
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME] = "query";
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_USAGE] = "query [lang] [serviceName serviceFilter]";
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION] = "Query the service registry. If no argumenst are provided list the available services names.";
+    return ctx->registerFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, std::move(cmd), std::move(props));
+}
\ No newline at end of file
diff --git a/bundles/shell/cxx_shell/src/ShellActivator.cc b/bundles/shell/cxx_shell/src/ShellActivator.cc
index ee89d98..58c8f2f 100644
--- a/bundles/shell/cxx_shell/src/ShellActivator.cc
+++ b/bundles/shell/cxx_shell/src/ShellActivator.cc
@@ -27,7 +27,7 @@ namespace {
 
     class Shell : public celix::IShell {
     public:
-        Shell(std::shared_ptr<celix::IBundleContext> _ctx) : ctx{std::move(_ctx)} {}
+        Shell(std::shared_ptr<celix::BundleContext> _ctx) : ctx{std::move(_ctx)} {}
 
         bool executeCommandLine(const std::string &commandLine, std::ostream &out, std::ostream &err) noexcept override {
             std::string cmdName{};
@@ -72,18 +72,19 @@ namespace {
             return commandCalled;
         }
     private:
-        std::shared_ptr<celix::IBundleContext> ctx;
+        std::shared_ptr<celix::BundleContext> ctx;
     };
 
     class ShellBundleActivator : public celix::IBundleActivator {
     public:
-        ShellBundleActivator(std::shared_ptr<celix::IBundleContext> ctx) {
+        ShellBundleActivator(std::shared_ptr<celix::BundleContext> ctx) {
             //TODO ensure fixed framework thread that call ctor/dtor bundle activators
             registrations.push_back(impl::registerLb(ctx));
             registrations.push_back(impl::registerHelp(ctx));
             registrations.push_back(impl::registerStop(ctx));
             registrations.push_back(impl::registerStart(ctx));
             registrations.push_back(impl::registerInspect(ctx));
+            registrations.push_back(impl::registerQuery(ctx));
 
             registrations.push_back(ctx->registerService(std::shared_ptr<celix::IShell>{new Shell{ctx}}));
         }
diff --git a/bundles/shell/cxx_shell/src/StopAndStartCommand.cc b/bundles/shell/cxx_shell/src/StopAndStartCommand.cc
index aae5a69..b674972 100644
--- a/bundles/shell/cxx_shell/src/StopAndStartCommand.cc
+++ b/bundles/shell/cxx_shell/src/StopAndStartCommand.cc
@@ -26,7 +26,7 @@
 
 namespace {
 
-    void stopOrStart(std::shared_ptr<celix::IBundleContext> ctx, const std::string &cmdName, const std::vector<std::string> &cmdArgs, std::ostream &out, std::ostream &err) {
+    void stopOrStart(std::shared_ptr<celix::BundleContext> ctx, const std::string &cmdName, const std::vector<std::string> &cmdArgs, std::ostream &out, std::ostream &err) {
         if (cmdArgs.empty()) {
             out << "Provide a bundle id name to " << cmdName << std::endl;
         } else {
@@ -52,7 +52,7 @@ namespace {
 }
 
 
-celix::ServiceRegistration impl::registerStop(std::shared_ptr<celix::IBundleContext> ctx) {
+celix::ServiceRegistration impl::registerStop(std::shared_ptr<celix::BundleContext> ctx) {
     using namespace std::placeholders;
     celix::ShellCommandFunction stop = std::bind(&stopOrStart, ctx, _1, _2, _3, _4);
 
@@ -63,7 +63,7 @@ celix::ServiceRegistration impl::registerStop(std::shared_ptr<celix::IBundleCont
     return ctx->registerFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, std::move(stop), std::move(props));
 }
 
-celix::ServiceRegistration impl::registerStart(std::shared_ptr<celix::IBundleContext> ctx) {
+celix::ServiceRegistration impl::registerStart(std::shared_ptr<celix::BundleContext> ctx) {
     using namespace std::placeholders;
     celix::ShellCommandFunction stop = std::bind(&stopOrStart, ctx, _1, _2, _3, _4);
 
diff --git a/bundles/shell/cxx_shell/src/commands.h b/bundles/shell/cxx_shell/src/commands.h
index 5f641b8..b9d9a8f 100644
--- a/bundles/shell/cxx_shell/src/commands.h
+++ b/bundles/shell/cxx_shell/src/commands.h
@@ -23,14 +23,12 @@
 #include "celix/api.h"
 
 namespace impl {
-    celix::ServiceRegistration registerLb(std::shared_ptr<celix::IBundleContext> ctx);
-    celix::ServiceRegistration registerHelp(std::shared_ptr<celix::IBundleContext> ctx);
-    celix::ServiceRegistration registerStop(std::shared_ptr<celix::IBundleContext> ctx);
-    celix::ServiceRegistration registerStart(std::shared_ptr<celix::IBundleContext> ctx);
-    celix::ServiceRegistration registerInspect(std::shared_ptr<celix::IBundleContext> ctx);
-
-    //query services, trackers & meta trackers TODO
-    // celix::ServiceRegistration registerQuery(std::shared_ptr<celix::IBundleContext> ctx);
+    celix::ServiceRegistration registerLb(std::shared_ptr<celix::BundleContext> ctx);
+    celix::ServiceRegistration registerHelp(std::shared_ptr<celix::BundleContext> ctx);
+    celix::ServiceRegistration registerStop(std::shared_ptr<celix::BundleContext> ctx);
+    celix::ServiceRegistration registerStart(std::shared_ptr<celix::BundleContext> ctx);
+    celix::ServiceRegistration registerInspect(std::shared_ptr<celix::BundleContext> ctx);
+    celix::ServiceRegistration registerQuery(std::shared_ptr<celix::BundleContext> ctx);
 }
 
 
diff --git a/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc b/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc
index dc71faa..a1ddf5a 100644
--- a/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc
+++ b/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc
@@ -129,7 +129,7 @@ namespace {
 
     class ShellTuiBundleActivator : public celix::IBundleActivator {
     public:
-        ShellTuiBundleActivator(std::shared_ptr<celix::IBundleContext> ctx) {
+        ShellTuiBundleActivator(std::shared_ptr<celix::BundleContext> ctx) {
             celix::ServiceTrackerOptions<celix::IShell> opts{};
             opts.set = std::bind(&ShellTui::setShell, &tui, std::placeholders::_1);
             trk = ctx->trackServices(opts);
diff --git a/examples/celix-examples/CMakeLists.txt b/examples/celix-examples/CMakeLists.txt
index 9421e4b..0975a60 100644
--- a/examples/celix-examples/CMakeLists.txt
+++ b/examples/celix-examples/CMakeLists.txt
@@ -24,13 +24,13 @@ if (EXAMPLES)
     add_definitions(-DADD_CELIX_DEPRECATED_WARNING) #ensure that no deprecated api is used in the examples
 
     add_subdirectory(bundle_example_c)
-    add_subdirectory(bundle_example_cxx)
+    #TODO add_subdirectory(bundle_example_cxx)
 
     add_subdirectory(services_example_c)
-    add_subdirectory(services_example_cxx)
+    #TODO add_subdirectory(services_example_cxx)
 
     add_subdirectory(dm_example)
-    add_subdirectory(dm_example_cxx)
+    #TODO add_subdirectory(dm_example_cxx)
 
     if (NOT ANDROID)
         add_subdirectory(civetweb)
diff --git a/examples/celix-examples/shell_command_example/CMakeLists.txt b/examples/celix-examples/shell_command_example/CMakeLists.txt
index 467bc0d..331ea54 100644
--- a/examples/celix-examples/shell_command_example/CMakeLists.txt
+++ b/examples/celix-examples/shell_command_example/CMakeLists.txt
@@ -18,13 +18,13 @@
 add_celix_bundle(shell_example_c SOURCES src/activator.c VERSION 1.0.0)
 target_link_libraries(shell_example_c PRIVATE Celix::shell_api)
 
-add_celix_bundle(shell_example_cxx SOURCES src/Activator.cc VERSION 1.0.0)
-target_link_libraries(shell_example_cxx PRIVATE Celix::shell_api)
+#TODO add_celix_ bundle(shell_example_cxx SOURCES src/Activator.cc VERSION 1.0.0)
+#TODO target_link_libraries(shell_example_cxx PRIVATE Celix::shell_api)
 
 add_celix_container(shell_example
     BUNDLES
         Celix::shell
         Celix::shell_tui
         shell_example_c
-        shell_example_cxx
+        #shell_example_cxx
 )
\ No newline at end of file
diff --git a/libs/framework/CMakeLists.txt b/libs/framework/CMakeLists.txt
index ecfc795..812b4e6 100644
--- a/libs/framework/CMakeLists.txt
+++ b/libs/framework/CMakeLists.txt
@@ -72,10 +72,6 @@ if (ENABLE_TESTING)
     add_subdirectory(tst)
 endif()
 
-if (ENABLE_TESTING AND ENABLE_GTESTING)
-    add_subdirectory(gtest)
-endif ()
-
 celix_subproject(FRAMEWORK_TESTS "Option to build the framework tests" "OFF" DEPS)
 if (ENABLE_TESTING AND FRAMEWORK_TESTS)
     find_package(CppUTest REQUIRED)
diff --git a/libs/framework/gtest/CMakeLists.txt b/libs/framework/gtest/CMakeLists.txt
deleted file mode 100644
index 26af024..0000000
--- a/libs/framework/gtest/CMakeLists.txt
+++ /dev/null
@@ -1,42 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-# 
-#   http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-set(SOURCES
-        src/main.cc
-        src/cxx_Framework_tests.cc
-        src/cxx_FrameworkFactory_tests.cc
-        src/cxx_BundleContext_tests.cc
-        src/cxx_Bundle_tests.cc
-        src/cxx_ServiceAdapter_tests.cc
-)
-add_executable(cxx_framework_tests ${SOURCES})
-target_link_libraries(cxx_framework_tests PRIVATE gtest Celix::framework)
-
-
-add_celix_bundle(cxx_fwm_test_bundle1
-        VERSION 1.0.0
-        NO_ACTIVATOR
-)
-
-add_custom_command(TARGET cxx_framework_tests POST_BUILD
-        COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_PROPERTY:cxx_fwm_test_bundle1,BUNDLE_FILE> ${CMAKE_CURRENT_BINARY_DIR}/bundle1.zip
-)
-add_celix_bundle_dependencies(cxx_framework_tests cxx_fwm_test_bundle1)
-
-
-add_test(NAME cxx_framework_tests COMMAND cxx_framework_tests)
-SETUP_TARGET_FOR_COVERAGE(cxx_framework_tests_cov cxx_framework_tests ${CMAKE_BINARY_DIR}/coverage/cxx_framework_tests/cxx_framework_tests)
diff --git a/libs/framework/gtest/src/cxx_BundleContext_tests.cc b/libs/framework/gtest/src/cxx_BundleContext_tests.cc
deleted file mode 100644
index ec3bdb7..0000000
--- a/libs/framework/gtest/src/cxx_BundleContext_tests.cc
+++ /dev/null
@@ -1,252 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#include "gtest/gtest.h"
-
-#include "celix/FrameworkFactory.h"
-
-class BundleContextTest : public ::testing::Test {
-public:
-    BundleContextTest() {
-        celix::Properties config{};
-        config["org.osgi.framework.storage"] = "test-cache";
-        this->fw_ptr = std::unique_ptr<celix::Framework>{celix::FrameworkFactory::newFramework(std::move(config))};
-    }
-
-    ~BundleContextTest(){}
-
-    celix::Framework& framework() { return *(this->fw_ptr); }
-private:
-    std::unique_ptr<celix::Framework> fw_ptr{nullptr};
-};
-
-//Test interface
-class ITestSvc {
-public:
-    static constexpr const char * const NAME = "ITestSvc";
-
-    virtual ~ITestSvc(){};
-    virtual int calc(int input) = 0;
-};
-
-//Test implementation
-class TestImpl : public ITestSvc {
-public:
-    virtual ~TestImpl(){};
-    int calc(int input) override { return input * 42; }
-};
-
-
-TEST_F(BundleContextTest, TestInstallBundle) {
-    auto &ctx = this->framework().getFrameworkContext();
-
-    long id;
-
-    //invalid
-    id = ctx.installBundle("Invalid loc", false);
-    EXPECT_TRUE(id < 0);
-
-    id = ctx.installBundle("bundle1.zip", false);
-    EXPECT_TRUE(id > 0);
-
-    long again = ctx.installBundle("bundle1.zip", false);
-    EXPECT_EQ(id, again);
-}
-
-TEST_F(BundleContextTest, RegisterCServiceTest) {
-    struct test_svc {
-        void *dummy;
-    };
-
-    auto &ctx = this->framework().getFrameworkContext();
-
-    test_svc svc1;
-
-    long svcId = ctx.registerCService(&svc1, "test service");
-    EXPECT_TRUE(svcId > 0);
-    ctx.unregisterService(svcId);
-
-    long svcId2 = ctx.registerCService(&svc1, "test service");
-    EXPECT_TRUE(svcId2 > 0);
-    EXPECT_NE(svcId, svcId2); //new registration new id
-    ctx.unregisterService(svcId2);
-
-    //NOTE compile error -> cxxSvc is not POD
-    //TestImpl cxxSvc{};
-    //ctx.registerCService(ITestSvc::NAME, &cxxSvc);
-}
-
-TEST_F(BundleContextTest, RegisterServiceTest) {
-    auto &ctx = this->framework().getFrameworkContext();
-
-    TestImpl svc1;
-
-    long svcId = ctx.registerService<ITestSvc>(&svc1, ITestSvc::NAME);
-    EXPECT_TRUE(svcId > 0);
-    ctx.unregisterService(svcId);
-
-    long svcId2 = ctx.registerService<ITestSvc>(&svc1, ITestSvc::NAME);
-    EXPECT_TRUE(svcId2 > 0);
-    EXPECT_NE(svcId, svcId2); //new registration new id
-    ctx.unregisterService(svcId2);
-}
-
-TEST_F(BundleContextTest, UseService) {
-    auto &ctx = this->framework().getFrameworkContext();
-
-    TestImpl svc1;
-
-    long svcId = ctx.registerService<ITestSvc>(&svc1, ITestSvc::NAME);
-    EXPECT_TRUE(svcId > 0);
-
-
-    int result = -1;
-    std::function<void(ITestSvc &svc, const celix::Properties&, const celix::Bundle&)> func = [&result](ITestSvc &svc, const celix::Properties&, const celix::Bundle&) {
-        result = svc.calc(1);
-    };
-    bool called = ctx.useService<ITestSvc>(ITestSvc::NAME, func);
-    EXPECT_TRUE(called);
-    EXPECT_EQ(result, 42);
-
-//    result = -1;
-//    called = ctx.useServiceWithId<ITestSvc>(svcId, ITestSvc::NAME, [&result](ITestSvc &svc, const celix::Properties&, const celix::Bundle&) {
-//        result = svc.calc(2);
-//    });
-//    EXPECT_TRUE(called);
-//    EXPECT_EQ(result, 84);
-
-    ctx.unregisterService(svcId);
-}
-
-TEST_F(BundleContextTest, UseServices) {
-    auto &ctx = this->framework().getFrameworkContext();
-
-    TestImpl svc;
-
-    long svcId1 = ctx.registerService<ITestSvc>(&svc, "test service");
-    EXPECT_TRUE(svcId1 > 0);
-
-    long svcId2 = ctx.registerService<ITestSvc>(&svc, "test service");
-    EXPECT_TRUE(svcId2 > 0);
-
-
-    int result = 0;
-    auto func = [&result](ITestSvc &svc, const celix::Properties&, const celix::Bundle&) {
-        result += svc.calc(1);
-    };
-    ctx.useServices<ITestSvc>("test service", func);
-    EXPECT_EQ(result, 84); //two times
-
-    ctx.unregisterService(svcId1);
-
-    ctx.useServices<ITestSvc>("test service", func);
-    EXPECT_EQ(result, 126); //one time
-
-    ctx.unregisterService(svcId2);
-}
-
-
-TEST_F(BundleContextTest, TrackService) {
-    auto &ctx = this->framework().getFrameworkContext();
-
-    int count = 0;
-
-    ITestSvc *svc1 = (ITestSvc*)0x100; //no ranking
-    ITestSvc *svc2 = (ITestSvc*)0x200; //no ranking
-    ITestSvc *svc3 = (ITestSvc*)0x300; //10 ranking
-    ITestSvc *svc4 = (ITestSvc*)0x400; //5 ranking
-
-
-    auto set = [&](ITestSvc *svc) {
-        static int callCount = 0;
-        callCount += 1;
-        if (callCount == 1) {
-            //first time svc1 should be set (oldest service with equal ranking
-            EXPECT_EQ(svc1, svc);
-        } else if (callCount == 2) {
-            EXPECT_EQ(svc3, svc);
-            //second time svc3 should be set (highest ranking)
-        } else if (callCount == 3) {
-            //third time svc4 should be set (highest ranking
-            EXPECT_EQ(svc4, svc);
-        }
-
-        count = callCount;
-    };
-
-    long svcId1 = ctx.registerService(svc1, "NA");
-    long svcId2 = ctx.registerService(svc2, "NA");
-
-    //starting tracker should lead to first set call
-    long trackerId = ctx.trackService<ITestSvc>("NA", set);
-    EXPECT_TRUE(trackerId > 0);
-
-    //register svc3 should lead to second set call
-    celix::Properties props3{};
-    props3[OSGI_FRAMEWORK_SERVICE_RANKING] = "10";
-    long svcId3 = ctx.registerService(svc3, "NA", std::move(props3));
-
-    //register svc4 should lead to no set (lower ranking)
-    celix::Properties props4{};
-    props4[OSGI_FRAMEWORK_SERVICE_RANKING] = "10";
-    long svcId4 = ctx.registerService(svc4, "NA", props4);
-
-    //unregister svc3 should lead to set (new highest ranking)
-    ctx.unregisterService(svcId3);
-
-    ctx.stopTracker(trackerId);
-    ctx.unregisterService(svcId1);
-    ctx.unregisterService(svcId4);
-    ctx.unregisterService(svcId2);
-
-    EXPECT_EQ(3, count); //check if the set is called the expected times
-}
-
-TEST_F(BundleContextTest, useBundleTest) {
-    auto &ctx = this->framework().getFrameworkContext();
-    int count = 0;
-
-    ctx.useBundle(0, [&count](const celix::Bundle &bnd) {
-        count++;
-        long id = bnd.getBundleId();
-        EXPECT_EQ(0, id);
-    });
-
-    EXPECT_EQ(1, count);
-};
-
-
-TEST_F(BundleContextTest, useBundlesTest) {
-    auto &ctx = this->framework().getFrameworkContext();
-    int count = 0;
-
-    auto use = [&count](const celix::Bundle &bnd) {
-        count++;
-        long id = bnd.getBundleId();
-        EXPECT_TRUE(id >= 0);
-    };
-
-    ctx.useBundles(use);
-    EXPECT_EQ(0, count); //note framework bundle is by default not used in the useBundles callback
-
-    count = 0;
-    ctx.installBundle("bundle1.zip", true);
-    ctx.useBundles(use);
-    EXPECT_EQ(1, count);
-};
diff --git a/libs/framework/gtest/src/cxx_Bundle_tests.cc b/libs/framework/gtest/src/cxx_Bundle_tests.cc
deleted file mode 100644
index 2f037bf..0000000
--- a/libs/framework/gtest/src/cxx_Bundle_tests.cc
+++ /dev/null
@@ -1,65 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#include "gtest/gtest.h"
-
-#include "celix/FrameworkFactory.h"
-
-class BundleTest : public ::testing::Test {
-public:
-    BundleTest() {
-        celix::Properties config{};
-        config["org.osgi.framework.storage"] = "test-cache"; //TODO tmp dir?
-        this->fw_ptr = std::unique_ptr<celix::Framework>{celix::FrameworkFactory::newFramework(std::move(config))};
-    }
-
-    ~BundleTest(){}
-
-    celix::Framework& framework() { return *(this->fw_ptr); }
-private:
-    std::unique_ptr<celix::Framework> fw_ptr{nullptr};
-};
-
-TEST_F(BundleTest, getInfoFromFrameworkBundle) {
-    auto &bnd = this->framework().getFrameworkBundle();
-
-    long id = bnd.getBundleId();
-    EXPECT_EQ(0, id); //framework bundle is 0
-
-    //TODO FIXME returned name is id
-//    std::string name = bnd.getBundleName();
-//    EXPECT_EQ("system", name);
-
-    std::string sym = bnd.getBundleSymbolicName();
-    EXPECT_EQ("Framework", sym);
-
-    std::string loc = bnd.getBundleLocation();
-    EXPECT_EQ("System Bundle", loc);
-
-    celix::BundleState state = bnd.getState();
-    EXPECT_EQ(celix::BundleState::ACTIVE, state);
-
-    //TODO
-//    std::string cache = bnd.getBundleCache(); //TODO make getCacheLoc?
-//    EXPECT_TRUE(!cache.emtpy());
-
-    //TODO returns "" should be framework version
-//    std::string version = bnd.getBundleVersion();
-//    EXPECT_EQ("2.2.0", version);
-}
\ No newline at end of file
diff --git a/libs/framework/gtest/src/cxx_FrameworkFactory_tests.cc b/libs/framework/gtest/src/cxx_FrameworkFactory_tests.cc
deleted file mode 100644
index 3920efb..0000000
--- a/libs/framework/gtest/src/cxx_FrameworkFactory_tests.cc
+++ /dev/null
@@ -1,54 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#include "gtest/gtest.h"
-
-#include "celix/FrameworkFactory.h"
-
-TEST(FrameworkFactoryTest, CreateDestroyTest) {
-    celix::Framework *fw1 = celix::FrameworkFactory::newFramework();
-    EXPECT_NE(fw1, nullptr);
-    delete fw1;
-
-    fw1 = celix::FrameworkFactory::newFramework();
-    EXPECT_NE(fw1, nullptr);
-    fw1->start(); //NOTE should already be done
-    fw1->stop();
-    fw1->waitForStop();
-    delete fw1;
-}
-
-TEST(FrameworkFactoryTest, StartStopTest) {
-    celix::Properties config1{};
-    config1["org.osgi.framework.storage.clean"] = "onFirstInit";
-    config1["org.osgi.framework.storage"] = "test-cache1";
-
-    celix::Properties config2 = config1;
-    config2["org.osgi.framework.storage"] = "test-cache2";
-
-    celix::Framework *fw1 = celix::FrameworkFactory::newFramework(config1);
-    celix::Framework *fw2 = celix::FrameworkFactory::newFramework(config2);
-
-    EXPECT_NE(fw1, nullptr);
-    EXPECT_NE(fw2, nullptr);
-    EXPECT_NE(fw1, fw2);
-
-    delete fw1;
-    delete fw2;
-}
\ No newline at end of file
diff --git a/libs/framework/gtest/src/cxx_Framework_tests.cc b/libs/framework/gtest/src/cxx_Framework_tests.cc
deleted file mode 100644
index c8c88b4..0000000
--- a/libs/framework/gtest/src/cxx_Framework_tests.cc
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#include "gtest/gtest.h"
-
-#include "celix/Framework.h"
-#include "celix/FrameworkFactory.h"
-
-class FrameworkTest : public ::testing::Test {
-public:
-    FrameworkTest() {
-        celix::Properties config{};
-        config["org.osgi.framework.storage.clean"] = "onFirstInit";
-        config["org.osgi.framework.storage"] = "test-cache"; //TODO tmp dir?
-        this->fw_ptr = std::unique_ptr<celix::Framework>{celix::FrameworkFactory::newFramework(std::move(config))};
-    }
-
-    ~FrameworkTest(){}
-
-    celix::Framework& framework() { return *(this->fw_ptr); }
-private:
-    std::unique_ptr<celix::Framework> fw_ptr{nullptr};
-};
-
-TEST_F(FrameworkTest, TestFrameworkUUID) {
-    auto &fw = this->framework();
-    std::string uuid = fw.getUUID();
-    EXPECT_NE(uuid, "");
-}
\ No newline at end of file
diff --git a/libs/framework/gtest/src/cxx_ServiceAdapter_tests.cc b/libs/framework/gtest/src/cxx_ServiceAdapter_tests.cc
deleted file mode 100644
index 9eac3e2..0000000
--- a/libs/framework/gtest/src/cxx_ServiceAdapter_tests.cc
+++ /dev/null
@@ -1,302 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#include "gtest/gtest.h"
-
-#include "celix/FrameworkFactory.h"
-
-class ServiceAdapterTest : public ::testing::Test {
-public:
-    ServiceAdapterTest() {
-        celix::Properties config{};
-        config["org.osgi.framework.storage.clean"] = "onFirstInit";
-        config["org.osgi.framework.storage"] = "test-cache"; //TODO tmp dir?
-        this->fw_ptr = std::unique_ptr<celix::Framework>{celix::FrameworkFactory::newFramework(std::move(config))};
-    }
-
-    ~ServiceAdapterTest(){}
-
-    celix::Framework& framework() { return *(this->fw_ptr); }
-private:
-    std::unique_ptr<celix::Framework> fw_ptr{nullptr};
-};
-
-//Test interface
-class ITestSvc {
-public:
-    static constexpr const char * const NAME = "ITestSvc";
-
-    virtual ~ITestSvc(){};
-    virtual int calc(int input) = 0;
-};
-
-//Test implementation
-class TestImpl : public ITestSvc {
-public:
-    virtual ~TestImpl(){};
-    int calc(int input) override { return input * 42; }
-};
-
-
-/*This service can be used with the DefaulServiceWrapper*/
-class IHelloService {
-public:
-    static constexpr const char * const SERVICE_NAME = "IHelloService";
-    static constexpr const char * const SERVICE_VERSION = "1.0.0";
-
-    virtual ~IHelloService() = default;
-    virtual std::string hello() = 0;
-};
-
-TEST_F(ServiceAdapterTest, RegisterServiceWithWrapperTest) {
-    auto &ctx = this->framework().getFrameworkContext();
-
-    class HelloServiceImpl : public IHelloService {
-    public:
-        virtual ~HelloServiceImpl() = default;
-        std::string hello() override {
-            return std::string{"hello1"};
-        }
-    };
-
-    HelloServiceImpl svc{};
-    IHelloService* svcPointer = &svc;
-    long svcId = ctx.registerService<IHelloService>(svcPointer);
-
-    //use without wrapper
-    bool called;
-    called = ctx.useService<IHelloService>(IHelloService::SERVICE_NAME, [](IHelloService &svc) {
-        ASSERT_EQ(std::string{"hello1"}, svc.hello());
-    });
-    ASSERT_TRUE(called);
-
-    //use with wrapper
-    called = ctx.useService<IHelloService>([](IHelloService &svc) {
-        auto result = svc.hello();
-        ASSERT_EQ(std::string{"hello1"}, result);
-    });
-    ASSERT_TRUE(called);
-
-    ctx.unregisterService(svcId);
-}
-
-/* Because this service has no SERVICE_NAME/SERVICE_VERSION is can not be wrapped by the DefaultServiceWrapper.
- * Custom wrapper is needed to achieve the same effect
- */
-class IHelloServiceNoDefaultWrapper {
-public:
-    virtual ~IHelloServiceNoDefaultWrapper() = default;
-    virtual std::string hello() = 0;
-};
-
-class HelloServiceRegistrationAdapter : public celix::IServiceRegistrationAdapterFactory<IHelloServiceNoDefaultWrapper, IHelloServiceNoDefaultWrapper> {
-public:
-    class ServiceAdapter : public celix::IServiceAdapter<IHelloServiceNoDefaultWrapper> {
-    public:
-        ServiceAdapter(IHelloServiceNoDefaultWrapper *_svc) : svc{_svc} {}
-        virtual ~ServiceAdapter() = default;
-
-        ServiceAdapter(const ServiceAdapter&) = delete;
-        ServiceAdapter& operator=(const ServiceAdapter&) = delete;
-
-        IHelloServiceNoDefaultWrapper* adapt() override { return svc; }
-    private:
-        IHelloServiceNoDefaultWrapper* svc;
-    };
-
-    virtual ~HelloServiceRegistrationAdapter() = default;
-    std::string serviceName() override { return "HelloService"; }
-    std::string serviceVersion() override { return "1.0.0"; }
-    std::string serviceLanguage() override { return celix::Constants::SERVICE_CXX_LANG; }
-    celix::IServiceAdapter<IHelloServiceNoDefaultWrapper>* createAdapter(IHelloServiceNoDefaultWrapper *svc) override { return new ServiceAdapter{svc}; }
-};
-
-celix::IServiceRegistrationAdapterFactory<IHelloServiceNoDefaultWrapper,IHelloServiceNoDefaultWrapper>& serviceRegistrationAdapterFactoryFor(IHelloServiceNoDefaultWrapper */*dummy*/) {
-    static HelloServiceRegistrationAdapter factory{};
-    return factory;
-}
-
-class HelloServiceUsageAdapter : public celix::IServiceUsageAdapterFactory<IHelloServiceNoDefaultWrapper> {
-public:
-    class ServiceAdapter : public celix::IServiceAdapter<IHelloServiceNoDefaultWrapper> {
-    public:
-        ServiceAdapter(void *_svc) : svc{static_cast<IHelloServiceNoDefaultWrapper*>(_svc)} {}
-        virtual ~ServiceAdapter() = default;
-
-        ServiceAdapter(const ServiceAdapter&) = delete;
-        ServiceAdapter& operator=(const ServiceAdapter&) = delete;
-
-        IHelloServiceNoDefaultWrapper* adapt() override { return svc; }
-    private:
-        IHelloServiceNoDefaultWrapper* svc;
-    };
-
-    virtual ~HelloServiceUsageAdapter() = default;
-    std::string serviceName() override { return "HelloService"; }
-    std::string serviceVersionRange() override { return "[1,2)"; }
-    std::string serviceLanguage() override { return celix::Constants::SERVICE_CXX_LANG; }
-    celix::IServiceAdapter<IHelloServiceNoDefaultWrapper>* createAdapter(void *registeredSvc) override { return new ServiceAdapter(registeredSvc); }
-};
-
-
-
-celix::IServiceUsageAdapterFactory<IHelloServiceNoDefaultWrapper>& serviceUsageAdapterFactoryFor(IHelloServiceNoDefaultWrapper*) {
-    static HelloServiceUsageAdapter factory{};
-    return factory;
-}
-
-TEST_F(ServiceAdapterTest, RegisterServiceWithCustomWrapperTest) {
-    auto &ctx = this->framework().getFrameworkContext();
-
-    class HelloServiceImpl : public IHelloServiceNoDefaultWrapper {
-    public:
-        virtual ~HelloServiceImpl() = default;
-        std::string hello() override {
-            return std::string{"hello1"};
-        }
-    };
-
-    HelloServiceImpl svc{};
-    long svcId = ctx.registerService<IHelloServiceNoDefaultWrapper>(&svc);
-
-    //use without wrapper
-    bool called = ctx.useService<IHelloServiceNoDefaultWrapper>("HelloService", [](IHelloServiceNoDefaultWrapper &svc) {
-        ASSERT_EQ(std::string{"hello1"}, svc.hello());
-    });
-    ASSERT_TRUE(called);
-
-    //use with wrapper
-    called = ctx.useService<IHelloServiceNoDefaultWrapper>([](IHelloServiceNoDefaultWrapper &svc) {
-        ASSERT_EQ(std::string{"hello1"}, svc.hello());
-    });
-    ASSERT_TRUE(called);
-
-    ctx.unregisterService(svcId);
-}
-
-#define HELLO_SERVICE_NAME "hello_service"
-#define HELLO_SERVICE_VERSION "1.0.0"
-
-//The underlining c service
-typedef struct do_service {
-    void *handle;
-    int (*do_something)(void* handle);
-} do_service_t;
-
-//The C++ service to use in the C++ context
-class IDoService {
-public:
-    virtual ~IDoService() = default;
-    virtual int do_something() = 0;
-};
-
-class DoServiceToCWrapper : public celix::IServiceRegistrationAdapterFactory<IDoService, do_service_t> {
-public:
-    class ServiceAdapter : public celix::IServiceAdapter<do_service_t> {
-    public:
-        ServiceAdapter(IDoService *svc) {
-            cSvc.handle = static_cast<void*>(svc);
-            cSvc.do_something = [](void *handle) -> int {
-                auto* s = static_cast<IDoService*>(handle);
-                return s->do_something();
-            };
-        }
-        virtual ~ServiceAdapter() = default;
-        do_service_t* adapt() override { return &cSvc; }
-    private:
-        do_service_t cSvc{};
-    };
-
-    virtual ~DoServiceToCWrapper() = default;
-    std::string serviceName() override { return "do_service"; }
-    std::string serviceVersion() override { return "1.0.0"; }
-    std::string serviceLanguage() override { return celix::Constants::SERVICE_C_LANG; }
-    celix::IServiceAdapter<do_service_t>* createAdapter(IDoService* svc) override { return new ServiceAdapter{svc}; }
-};
-
-celix::IServiceRegistrationAdapterFactory<IDoService, do_service_t>& serviceRegistrationAdapterFactoryFor(IDoService */*dummy*/) {
-    static DoServiceToCWrapper factory{};
-    return factory;
-}
-
-class DoServiceFromCWrapper : public celix::IServiceUsageAdapterFactory<IDoService> {
-public:
-    class ServiceAdapter : public celix::IServiceAdapter<IDoService>, public IDoService {
-    public:
-        ServiceAdapter(void *_svc) : cSvc{static_cast<do_service_t*>(_svc)} {}
-        virtual ~ServiceAdapter() = default;
-
-        ServiceAdapter(const ServiceAdapter&) = delete;
-        ServiceAdapter& operator=(const ServiceAdapter&) = delete;
-
-        IDoService* adapt() override { return this; }
-
-        int do_something() override {
-            return cSvc->do_something(cSvc->handle);
-        }
-    private:
-        do_service_t* cSvc;
-    };
-
-    virtual ~DoServiceFromCWrapper() = default;
-    std::string serviceName() override { return "do_service"; }
-    std::string serviceVersionRange() override { return "[1,2)"; }
-    std::string serviceLanguage() override { return celix::Constants::SERVICE_C_LANG; }
-    celix::IServiceAdapter<IDoService>* createAdapter(void *registeredSvc) override { return new ServiceAdapter{registeredSvc}; }
-};
-
-celix::IServiceUsageAdapterFactory<IDoService>& serviceUsageAdapterFactoryFor(IDoService* /*dummy_used_for_infer*/) {
-    static DoServiceFromCWrapper factory{};
-    return factory;
-}
-
-TEST_F(ServiceAdapterTest, RegisterServiceWithCxxToCWrapperTest) {
-    auto &ctx = this->framework().getFrameworkContext();
-
-    class DoServiceImpl : public IDoService {
-    public:
-        virtual ~DoServiceImpl() = default;
-        int do_something() override {
-            return 42;
-        }
-    };
-
-    DoServiceImpl svc{};
-    long svcId = ctx.registerService<IDoService>(&svc);
-    ASSERT_TRUE(svcId >= 0);
-    //TODO assert properties has C as svc lang
-
-    bool called = ctx.useService<IDoService>([](IDoService &svc) {
-        int result = svc.do_something();
-        ASSERT_EQ(42, result);
-    });
-    ASSERT_TRUE(called);
-
-
-    called = false;
-    long trkId = ctx.trackService<IDoService>([&](IDoService *svc) {
-        called = true;
-        ASSERT_EQ(42, svc->do_something());
-    });
-    ASSERT_TRUE(trkId >= 0);
-    ASSERT_TRUE(called);
-    ctx.stopTracker(trkId);
-
-    ctx.unregisterService(svcId);
-}
\ No newline at end of file
diff --git a/libs/framework/gtest/src/main.cc b/libs/framework/gtest/src/main.cc
deleted file mode 100644
index 63b9a5b..0000000
--- a/libs/framework/gtest/src/main.cc
+++ /dev/null
@@ -1,25 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#include "gtest/gtest.h"
-
-int main(int argc, char **argv) {
-    ::testing::InitGoogleTest(&argc, argv);
-    return RUN_ALL_TESTS();
-}
\ No newline at end of file
diff --git a/libs/framework/include/celix/Bundle.h b/libs/framework/include/celix/Bundle.h
deleted file mode 100644
index 511f6d7..0000000
--- a/libs/framework/include/celix/Bundle.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#ifndef CXX_CELIX_BUNDLE_H
-#define CXX_CELIX_BUNDLE_H
-
-#include "celix/Properties.h"
-
-namespace celix {
-
-    enum class BundleState {
-        UNKNOWN,
-        UNINSTALLED,
-        INSTALLED,
-        RESOLVED,
-        STARTING,
-        STOPPING,
-        ACTIVE
-    };
-
-    class Bundle {
-    public:
-        virtual ~Bundle() = default;
-
-        virtual bool isSystemBundle() const noexcept  = 0;
-
-        virtual void * getHandle() const noexcept = 0;
-
-        virtual BundleState getState() const noexcept  = 0;
-
-        virtual long getBundleId() const noexcept  = 0;
-
-        virtual std::string getBundleLocation() const noexcept  = 0;
-
-        virtual std::string getBundleCache() const noexcept  = 0;
-
-        virtual std::string getBundleName() const noexcept = 0;
-
-        virtual std::string getBundleSymbolicName() const noexcept = 0;
-
-        virtual std::string getBundleVersion() const noexcept = 0;
-
-        virtual celix::Properties getManifestAsProperties() const noexcept  = 0;
-
-        virtual void start() noexcept = 0;
-
-        virtual void stop() noexcept = 0;
-
-        virtual void uninstall() noexcept = 0;
-
-    };
-
-}
-
-#endif //CXX_CELIX_BUNDLE_H
-
-#include "celix/impl/BundleImpl.h"
diff --git a/libs/framework/include/celix/BundleActivator.h b/libs/framework/include/celix/BundleActivator.h
deleted file mode 100644
index 7c36448..0000000
--- a/libs/framework/include/celix/BundleActivator.h
+++ /dev/null
@@ -1,104 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#include <memory>
-
-#include "celix/IBundleActivator.h"
-#include "celix/Framework.h"
-
-#ifndef CXX_CELIX_BUNDLEACTIVATOR_H
-#define CXX_CELIX_BUNDLEACTIVATOR_H
-
-namespace celix {
-    /**
-     * The BundleActivatorAdapter adapts the C bundle activator calls to a C++ bundle activator.
-     * The Type parameter (T) is the C++ bundle activator and needs to support:
-     * - A public default constructor.
-     * - Implementing the celix::IBundleActivator interface, which contains:
-     *      - A public destructor.
-     *      - A public 'celix_status_t start(celix::BundleContext &ctx)` method.
-     *      - A public 'celix_status_t start(celix::BundleContext &ctx)` method.
-     */
-    template<typename T>
-    class BundleActivatorAdapter {
-    private:
-        std::unique_ptr<celix::Framework> fw{};
-        std::unique_ptr<celix::BundleContext> ctx{};
-        std::unique_ptr<celix::IBundleActivator> activator{};
-    public:
-        BundleActivatorAdapter(celix_bundle_context_t *c_ctx) {
-            this->fw = std::unique_ptr<celix::Framework>{new celix::impl::FrameworkImpl{c_ctx}}; \
-            this->ctx = std::unique_ptr<celix::BundleContext>{new celix::BundleContext{c_ctx, *this->fw}}; \
-            this->activator = nullptr;
-        }
-
-        ~BundleActivatorAdapter() {
-            this->ctx = nullptr;
-            this->fw = nullptr;
-            this->activator = nullptr;
-        }
-
-        celix_status_t start() noexcept  {
-            this->activator = std::unique_ptr<celix::IBundleActivator>{new T};
-            celix_status_t status = this->activator->start(*this->ctx);
-            if (status == CELIX_SUCCESS) {
-                this->ctx->getDependencyManager().start();
-            }
-            return status;
-        }
-
-        celix_status_t stop() noexcept {
-            celix_status_t status = this->activator->stop(*this->ctx);
-            if (status == CELIX_SUCCESS) {
-                this->ctx->getDependencyManager().stop();
-            }
-            this->activator = nullptr; //implicit delete
-            return status;
-        }
-    };
-}
-
-/**
- * This macro generated the required bundle activator symbols, which uses the celix::BundleActivatorAdapter to
- * adapt the C bundle activator calls to the provided C++ bundle activator class.
- */
-#define CELIX_GEN_CXX_BUNDLE_ACTIVATOR(clazz)                                                                          \
-extern "C" celix_status_t bundleActivator_create(celix_bundle_context_t *c_ctx, void **userData) {                           \
-    auto *data = new celix::BundleActivatorAdapter<clazz>{c_ctx};                                                      \
-    *userData = data;                                                                                                  \
-    return CELIX_SUCCESS;                                                                                              \
-}                                                                                                                      \
-                                                                                                                       \
-extern "C" celix_status_t bundleActivator_start(void *userData, celix_bundle_context_t *) {                                  \
-    auto *data = static_cast<celix::BundleActivatorAdapter<clazz>*>(userData);                                         \
-    return data->start();                                                                                              \
-}                                                                                                                      \
-                                                                                                                       \
-extern "C" celix_status_t bundleActivator_stop(void *userData, celix_bundle_context_t *) {                                   \
-    auto *data = static_cast<celix::BundleActivatorAdapter<clazz>*>(userData);                                         \
-    return data->stop();                                                                                               \
-}                                                                                                                      \
-                                                                                                                       \
-extern "C" celix_status_t bundleActivator_destroy(void *userData, celix_bundle_context_t*) {                                 \
-    auto *data = static_cast<celix::BundleActivatorAdapter<clazz>*>(userData);                                         \
-    delete data;                                                                                                       \
-    return CELIX_SUCCESS;                                                                                              \
-}                                                                                                                      \
-
-#endif //CXX_CELIX_BUNDLEACTIVATOR_H
diff --git a/libs/framework/include/celix/BundleContext.h b/libs/framework/include/celix/BundleContext.h
deleted file mode 100644
index b5d4e2a..0000000
--- a/libs/framework/include/celix/BundleContext.h
+++ /dev/null
@@ -1,291 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#include <string>
-#include <vector>
-#include <functional>
-#include <memory>
-
-#include "celix/Constants.h"
-#include "celix/Properties.h"
-#include "celix/Bundle.h"
-#include "celix/IServiceFactory.h"
-#include "celix/ServiceAdapter.h"
-
-#ifndef CXX_CELIX_BUNDLECONTEXT_H
-#define CXX_CELIX_BUNDLECONTEXT_H
-
-namespace celix {
-
-    //forward declarations
-    class BundleContext;
-    class Framework;
-    namespace dm {
-        class DependencyManager;
-    }
-
-    template<typename I>
-    struct ServiceRegistrationOptions {
-        using type = I;
-
-        ServiceRegistrationOptions(I& _svc, const std::string& _serviceName) : svc{&_svc}, serviceName{_serviceName} {};
-        ServiceRegistrationOptions(celix::IServiceFactory<I>& _factory, const std::string& _serviceName) : factory{&_factory}, serviceName{_serviceName} {};
-
-        ServiceRegistrationOptions(const ServiceRegistrationOptions&) = delete;
-        ServiceRegistrationOptions& operator=(const ServiceRegistrationOptions&) = delete;
-        ServiceRegistrationOptions(ServiceRegistrationOptions&&) = delete;
-        ServiceRegistrationOptions& operator=(ServiceRegistrationOptions&) = delete;
-
-        I *svc{nullptr};
-        celix::IServiceFactory<I> *factory{nullptr};
-
-        const std::string serviceName;
-
-        celix::Properties properties{};
-        std::string serviceVersion{};
-        std::string serviceLanguage{celix::Constants::SERVICE_CXX_LANG};
-    };
-
-    template<typename I>
-    struct ServiceFilterOptions {
-        using type = I;
-
-        ServiceFilterOptions(const std::string &_serviceName) : serviceName{_serviceName} {};
-
-        std::string serviceName;
-
-        std::string versionRange{};
-        std::string filter{};
-        std::string serviceLanguage{celix::Constants::SERVICE_CXX_LANG};
-    };
-
-
-    template<typename I>
-    struct ServiceUseOptions {
-        using type = I;
-
-        ServiceUseOptions(const std::string &serviceName) : filter{ServiceFilterOptions<I>{serviceName}} {};
-
-        ServiceFilterOptions<I> filter;
-
-        /*
-         * Callbacks
-         */
-        std::function<void(I &svc)> use{};
-        std::function<void(I &svc, const celix::Properties &props)> useWithProperties{};
-        std::function<void(I &svc, const celix::Properties &props, celix::Bundle &svcOwner)> useWithOwner{};
-    };
-
-    template<typename I>
-    struct ServiceTrackingOptions {
-        using type = I;
-
-        ServiceTrackingOptions(const std::string serviceName) : filter{ServiceFilterOptions<I>{serviceName}} {};
-
-        ServiceFilterOptions<I> filter;
-
-        std::function<void(I* svc)> set{};
-        std::function<void(I* svc)> add{};
-        std::function<void(I* svc)> remove{};
-
-        std::function<void(I* svc, const celix::Properties &props)> setWithProperties{};
-        std::function<void(I* svc, const celix::Properties &props)> addWithProperties{};
-        std::function<void(I* svc, const celix::Properties &props)> removeWithProperties{};
-
-        std::function<void(I* svc, const celix::Properties &props, const celix::Bundle &svcOwner)> setWithOwner{};
-        std::function<void(I* svc, const celix::Properties &props, const celix::Bundle &svcOwner)> addWithOwner{};
-        std::function<void(I* svc, const celix::Properties &props, const celix::Bundle &svcOwner)> removeWithOwner{};
-    };
-
-
-    struct BundleRegistrationOptions {
-        std::string id{};
-        std::string name{};
-        std::string version{};
-
-        bool autoStart{true};
-
-        std::function<void(celix::BundleContext &ctx)> start{};
-        std::function<void(celix::BundleContext &ctx)> stop{};
-
-        celix::Properties manifest{};
-
-        //If manifest symbol and manifest len symbol is set, this is used instead of the properties as manifest
-        std::string manifestSymbol{};
-        std::string manifestLenSymbol{};
-
-        std::string resourceSymbol{};
-        std::string resourceLenSymbol{};
-    };
-
-    class BundleContext {
-    public:
-        BundleContext(celix_bundle_context_t *ctx, celix::Framework& fw); //TODO hide somehow ... friend ?
-        virtual ~BundleContext();
-
-        //TODO document, only possible if a service wrapper is available
-        template<typename I>
-        long registerService(I *svcWithWrapper, celix::Properties props = {}) noexcept;
-
-        template<typename I>
-        long registerService(I *svc, const std::string &serviceName, celix::Properties props = {}) noexcept;
-
-        template<typename I>
-        long registerCService(I *svc, const std::string &serviceName, celix::Properties props = {}) noexcept;
-
-        template<typename I>
-        long registerServiceFactory(celix::IServiceFactory<I> *svc, const std::string &serviceName, celix::Properties props = {});
-
-        template<typename I>
-        long registerCServiceFactory(celix::IServiceFactory<I> *svc, const std::string &serviceName, celix::Properties props = {});
-
-        template<typename I>
-        long registerServiceWithOptions(const celix::ServiceRegistrationOptions<I>& opts) noexcept;
-
-        //TODO register std::function ?
-
-        void unregisterService(long serviceId) noexcept;
-
-
-        /**
-        * track service for the provided service type, service name, optional version range and optional filter.
-        * The highest ranking services will used for the callback.
-        * If a new and higher ranking services the callback with be called again with the new service.
-        * If a service is removed a the callback with be called with next highest ranking service or NULL as service.
-        *
-        * @param serviceName The required service name to track
-        * @param set is a required callback, which will be called when a new highest ranking service is set.
-        * @return the tracker id or < 0 if unsuccessful.
-        */
-        template<typename I>
-        long trackService(const std::string &serviceName, std::function<void(I *svc)> set) noexcept;
-
-        /**
-        * track service for the provided service type using a ServiceUsageAdaptor.
-        * The highest ranking services will used for the callback.
-        * If a new and higher ranking services the callback with be called again with the new service.
-        * If a service is removed a the callback with be called with next highest ranking service or NULL as service.
-        *
-        * @param serviceName The required service name to track
-        * @param set is a required callback, which will be called when a new highest ranking service is set.
-        * @return the tracker id or < 0 if unsuccessful.
-        */
-        template<typename I>
-        long trackService(std::function<void(I *svc)> set) noexcept;
-
-        /**
-         * track services for the provided serviceName and/or filter.
-         *
-         * @param serviceName The required service name to track
-         * @param add is a required callback, which will be called when a service is added and initially for the existing service.
-         * @param remove is a required callback, which will be called when a service is removed
-         * @return the tracker id or < 0 if unsuccessful.
-         */
-        template<typename I>
-        long trackServices(const std::string &serviceName, std::function<void(I *svc)> add, std::function<void(I *svc)> remove) noexcept;
-
-        //TODO add trackCService(s) variants
-
-        /**
-         * track services using the provided tracking options
-         *
-         * @param opts The tracking options
-         * @return the tracker id or < 0 if unsuccessful.
-         */
-        template<typename I>
-        long trackServicesWithOptions(const celix::ServiceTrackingOptions<I>& opts) noexcept;
-
-        //TODO remove if WithOptions is available
-        template<typename I>
-        bool useServiceWithId(long serviceId, const std::string &/*serviceName*/ /*sanity*/, const std::function<void(I &svc, const celix::Properties &props, const celix::Bundle &svcOwner)> &use) noexcept;
-
-        template<typename I>
-        bool useServiceWithId(long serviceId, const std::string &/*serviceName*/ /*sanity*/, const std::function<void(I &svc)> &use) noexcept;
-
-        //TODO remove if WithOptions is available
-        template<typename I>
-        bool useService(const std::string &serviceName, const std::function<void(I &svc, const celix::Properties &props, const celix::Bundle &svcOwner)> &use) noexcept;
-
-        template<typename I>
-        bool useService(const std::string &serviceName, const std::function<void(I &svc)> &use) noexcept;
-
-        //TODO remove if WithOptions is available
-        template<typename I>
-        void useServices(const std::string &serviceName, const std::function<void(I &svc, const celix::Properties &props, const celix::Bundle &svcOwner)> &use) noexcept;
-
-        template<typename I>
-        void useServices(const std::string &serviceName, const std::function<void(I &svc)> &use) noexcept;
-
-        //TODO rest of variants with service & wrapper for useServiceWithId, useService and useServices
-        template<typename I>
-        bool useService(const std::function<void(I &svc)> &use) noexcept;
-
-        template<typename I>
-        void useServices(const std::function<void(I &svc)> &use) noexcept;
-
-
-        //TODO add useService(s)WithOptions
-        //TODO add useCService(s) variants
-
-        /**
-         * Note ordered by service rank.
-         */
-        std::vector<long> findServices(const std::string &serviceName, const std::string &versionRange = "", const std::string &filter = "", const std::string &lang = "") noexcept;
-
-        //TODO also support getting int, long, unsigned int, etc??
-        std::string getProperty(const std::string &key, std::string defaultValue = "") noexcept;
-
-        //TODO options
-
-        //track bundle
-        //TODO
-
-        //track service tracker
-        //TODO
-
-        /**
-         * Stop the tracker with the provided track id.
-         * Could be a service tracker, bundle tracker or service tracker tracker.
-         * Only works for the trackers owned by the bundle of the bundle context.
-         *
-         * Will log a error if the provided tracker id is unknown. Will silently ignore trackerId < 0.
-         */
-        void stopTracker(long trackerId) noexcept;
-
-        celix::Framework& getFramework() noexcept;
-
-        celix::Bundle& getBundle() noexcept;
-
-        celix::dm::DependencyManager& getDependencyManager() noexcept;
-
-        long installBundle(const std::string &bundleLocation, bool autoStart = true) noexcept;
-
-        void useBundles(const std::function<void(const celix::Bundle &bnd)> &use) noexcept;
-
-        void useBundle(long bundleId, const std::function<void(const celix::Bundle &bnd)> &use) noexcept;
-    private:
-        struct Impl;
-        std::unique_ptr<celix::BundleContext::Impl> pimpl{nullptr};
-    };
-
-}
-
-#endif //CXX_CELIX_BUNDLECONTEXT_H
-
-#include "celix/impl/BundleContextImpl.h"
diff --git a/libs/framework/include/celix/Celix.h b/libs/framework/include/celix/Celix.h
deleted file mode 100644
index 8a6a0c9..0000000
--- a/libs/framework/include/celix/Celix.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#ifndef CXX_CELIX_CELIX_H
-#define CXX_CELIX_CELIX_H
-
-/**
- * Celix C++ API header
- */
-
-
-#include "celix/Constants.h"
-#include "celix/Properties.h"
-#include "celix/Bundle.h"
-#include "celix/IServiceFactory.h"
-#include "celix/BundleContext.h"
-#include "celix/Framework.h"
-#include "celix/FrameworkFactory.h"
-#include "celix/dm/DependencyManager.h"
-
-#endif //CXX_CELIX_CELIX_H
diff --git a/libs/framework/include/celix/Constants.h b/libs/framework/include/celix/Constants.h
deleted file mode 100644
index adcb6a3..0000000
--- a/libs/framework/include/celix/Constants.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-
-#ifndef CXX_CELIX_CONSTANTS_H
-#define CXX_CELIX_CONSTANTS_H
-
-namespace celix {
-    class Constants {
-    public:
-        //NOTE manually aligned with celix_constants.h
-        static constexpr const char *const SERVICE_NAME = "objectClass"; //TODO rename to service.name
-        static constexpr const char *const SERVICE_LANGUAGE = "service.version";
-        static constexpr const char *const SERVICE_ID = "service.id";
-        static constexpr const char *const SERVICE_RANKING = "service.ranking";
-
-        static constexpr const char *const SERVICE_C_LANG = "C";
-        static constexpr const char *const SERVICE_CXX_LANG = "C++";
-
-        static constexpr const char *const FRAMEWORK_UUID = "framework.uuid";
-    };
-}
-
-#endif //CXX_CELIX_CONSTANTS_H
diff --git a/libs/framework/include/celix/Framework.h b/libs/framework/include/celix/Framework.h
deleted file mode 100644
index 790cfc0..0000000
--- a/libs/framework/include/celix/Framework.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#include <functional>
-
-#include "celix/Constants.h"
-#include "celix/Properties.h"
-#include "Bundle.h"
-#include "celix/BundleContext.h"
-
-#ifndef CXX_CELIX_FRAMEWORK_H
-#define CXX_CELIX_FRAMEWORK_H
-
-namespace celix {
-
-    class Framework  {
-    public:
-        virtual ~Framework() = default;
-
-        virtual void start() noexcept = 0;
-        virtual void stop() noexcept = 0;
-
-        virtual void waitForStop() noexcept = 0;
-        //TODO also in c virtual void breakWaitForStops() noexcept = 0;
-
-        virtual std::string getUUID() const noexcept = 0;
-
-        virtual celix::BundleContext& getFrameworkContext() noexcept = 0;
-        virtual celix::Bundle& getFrameworkBundle() noexcept = 0;
-    };
-
-}
-
-#endif //CXX_CELIX_FRAMEWORK_H
-
-#include "celix/impl/FrameworkImpl.h"
diff --git a/libs/framework/include/celix/FrameworkFactory.h b/libs/framework/include/celix/FrameworkFactory.h
deleted file mode 100644
index b7bc9b7..0000000
--- a/libs/framework/include/celix/FrameworkFactory.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#ifndef CXX_CELIX_FRAMEWORKFACTORY_H
-#define CXX_CELIX_FRAMEWORKFACTORY_H
-
-#include "celix/Properties.h"
-#include "celix/Framework.h"
-
-//include implementations
-#include "celix/impl/BundleImpl.h"
-#include "celix/impl/BundleContextImpl.h"
-#include "celix/impl/FrameworkImpl.h"
-
-namespace celix {
-    class FrameworkFactory {
-    public:
-        static celix::Framework *newFramework(celix::Properties config = {}) noexcept;
-
-        static void registerEmbeddedBundle(
-                std::string id,
-                std::function<void(celix::BundleContext &ctx)> start,
-                std::function<void(celix::BundleContext &ctx)> stop,
-                celix::Properties manifest = {},
-                bool autoStart = true
-        ) noexcept;
-
-        static void registerEmbeddedBundle(const celix::BundleRegistrationOptions &opts) noexcept;
-    };
-}
-
-inline celix::Framework* celix::FrameworkFactory::newFramework(celix::Properties config) noexcept {
-    return new celix::impl::FrameworkImpl(std::move(config));
-}
-
-inline void celix::FrameworkFactory::registerEmbeddedBundle(
-        std::string /*id*/,
-        std::function<void(celix::BundleContext& ctx)> /*start*/,
-        std::function<void(celix::BundleContext& ctx)> /*stop*/,
-        celix::Properties /*manifest*/,
-        bool /*autoStart*/
-) noexcept {
-    //TODO
-}
-
-inline void celix::FrameworkFactory::registerEmbeddedBundle(const celix::BundleRegistrationOptions &/*opts*/) noexcept {
-    //TODO
-};
-
-#endif //CXX_CELIX_FRAMEWORKFACTORY_H
\ No newline at end of file
diff --git a/libs/framework/include/celix/IBundleActivator.h b/libs/framework/include/celix/IBundleActivator.h
deleted file mode 100644
index 6e8d2a3..0000000
--- a/libs/framework/include/celix/IBundleActivator.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#include "celix/BundleContext.h"
-
-#ifndef CXX_CELIX_IBUNDLEACTIVATOR_H
-#define CXX_CELIX_IBUNDLEACTIVATOR_H
-
-namespace celix {
-
-    class IBundleActivator {
-
-    public:
-        virtual ~IBundleActivator(){}
-
-        virtual celix_status_t start(celix::BundleContext &ctx) = 0;
-        virtual celix_status_t stop(celix::BundleContext &ctx) = 0;
-    };
-}
-
-#endif //CXX_CELIX_IBUNDLEACTIVATOR_H
\ No newline at end of file
diff --git a/libs/framework/include/celix/Properties.h b/libs/framework/include/celix/Properties.h
deleted file mode 100644
index 65fd4ef..0000000
--- a/libs/framework/include/celix/Properties.h
+++ /dev/null
@@ -1,60 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#ifndef CXX_CELIX_PROPERTIES_H
-#define CXX_CELIX_PROPERTIES_H
-
-#include <string>
-#include <map>
-
-namespace celix {
-
-    using Properties = std::map<std::string, std::string>;
-
-    inline const std::string& getProperty(const Properties& props, const std::string &key, const std::string &defaultValue) noexcept {
-        auto it = props.find(key);
-        if (it != props.end()) {
-            return props.at(key);
-        } else {
-            return defaultValue;
-        }
-    }
-
-    inline int getProperty(const Properties& props, const std::string &key, int defaultValue)  noexcept {
-        std::string val = getProperty(props, key, std::to_string(defaultValue));
-        return std::stoi(val, nullptr, 10);
-    }
-
-    inline unsigned int getProperty(const Properties& props, const std::string &key, unsigned int defaultValue) noexcept {
-        std::string val = getProperty(props, key, std::to_string(defaultValue));
-        return static_cast<unsigned  int>(std::stoul(val, nullptr, 10)); //NOTE no std::stou ??
-    }
-
-    inline long getProperty(const Properties& props, const std::string &key, long defaultValue) noexcept {
-        std::string val = getProperty(props, key, std::to_string(defaultValue));
-        return std::stol(val, nullptr, 10);
-    }
-
-    inline unsigned int getProperty(const Properties& props, const std::string &key, unsigned long defaultValue) noexcept {
-        std::string val = getProperty(props, key, std::to_string(defaultValue));
-        return std::stoul(val, nullptr, 10);
-    }
-}
-
-#endif //CXX_CELIX_PROPERTIES_H
diff --git a/libs/framework/include/celix/ServiceAdapter.h b/libs/framework/include/celix/ServiceAdapter.h
deleted file mode 100644
index dd905e2..0000000
--- a/libs/framework/include/celix/ServiceAdapter.h
+++ /dev/null
@@ -1,152 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#include <string>
-
-#include "celix/Constants.h"
-
-#ifndef CXX_CELIX_SERIVCEADAPTOR_H
-#define CXX_CELIX_SERIVCEADAPTOR_H
-
-namespace celix {
-
-    class IServiceAdapterFactoryBase {
-    public:
-        virtual ~IServiceAdapterFactoryBase() = default;
-        virtual std::string serviceName() = 0; //TODO make const std::string?
-        virtual std::string serviceLanguage() = 0;
-
-    };
-
-    class IServiceAdapterBase {
-    public:
-        virtual ~IServiceAdapterBase() = default;
-    };
-
-    template<typename I>
-    class IServiceAdapter : public IServiceAdapterBase {
-    public:
-        virtual ~IServiceAdapter() = default;
-        virtual I* adapt() = 0;
-    };
-
-    template<typename I /*from*/, typename T /*to -> register version*/>
-    class IServiceRegistrationAdapterFactory : public IServiceAdapterFactoryBase {
-    public:
-        using fromType = I;
-        using registeringType = T;
-        virtual ~IServiceRegistrationAdapterFactory() = default;
-        virtual std::string serviceVersion() = 0;
-        virtual IServiceAdapter<T>* createAdapter(I *fromSvc) = 0;
-    };
-
-    template<typename I>
-    class IServiceUsageAdapterFactory : public IServiceAdapterFactoryBase {
-    public:
-        using type = I;
-        virtual ~IServiceUsageAdapterFactory() = default;
-        virtual std::string serviceVersionRange() = 0;
-        virtual IServiceAdapter<I>* createAdapter(void *registeredSvc) = 0;
-    };
-
-    /**
-     * The default Service Registration Adaptor. This wrapper assumes that a SERVICE_NAME, SERVICE_VERSION is available.
-     * It also assumes the service is a C++ service for registering and for using.
-     *
-     * It is valid to create the wrapper with a nulllptr svc object, but then the servicePointer() method result
-     * will also be a nullptr.
-     *
-     * @tparam I The C++ Service Type
-     */
-    template<typename I>
-    class DefaultServiceRegistrationAdapterFactory : public IServiceRegistrationAdapterFactory<I, I> {
-    public:
-        class DefaultServiceAdapter : public IServiceAdapter<I> {
-        public:
-            DefaultServiceAdapter(I *_svc) : svc{_svc} {}
-            virtual ~DefaultServiceAdapter() = default;
-            DefaultServiceAdapter(const DefaultServiceAdapter&) = delete;
-            DefaultServiceAdapter& operator=(const DefaultServiceAdapter&) = delete;
-            I* adapt() override { return svc; }
-        private:
-            I* svc;
-        };
-
-        virtual ~DefaultServiceRegistrationAdapterFactory() = default;
-        std::string serviceName() override { return I::SERVICE_NAME; }
-        std::string serviceVersion() override { return I::SERVICE_VERSION; }
-        std::string serviceLanguage() override { return celix::Constants::SERVICE_CXX_LANG; }
-        IServiceAdapter<I>* createAdapter(I* svc) override { return new DefaultServiceAdapter{svc}; }
-    };
-
-
-    template<typename I>
-    IServiceRegistrationAdapterFactory<I,I>& serviceRegistrationAdapterFactoryFor(I */*dummy for infer*/) {
-        static DefaultServiceRegistrationAdapterFactory<I> factory{};
-        return factory;
-    }
-
-    /**
-     * The default Service Usage Adaptor. This wrapper assumes that a SERVICE_NAME, SERVICE_VERSION is available.
-     * It also assumes the service is a registered C++ service to be used for C++.
-     *
-     * @tparam I The C++ Service Type
-     */
-    template<typename I>
-    class DefaultServiceUsageAdapterFactory : public IServiceUsageAdapterFactory<I> {
-    public:
-        class DefaultServiceAdapter : public IServiceAdapter<I> {
-        public:
-            DefaultServiceAdapter(void *_svc) : svc{static_cast<I*>(_svc)} {}
-            virtual ~DefaultServiceAdapter() = default;
-            DefaultServiceAdapter(const DefaultServiceAdapter&) = delete;
-            DefaultServiceAdapter& operator=(const DefaultServiceAdapter&) = delete;
-            I* adapt() override { return svc; }
-        private:
-            I* svc;
-        };
-
-        virtual ~DefaultServiceUsageAdapterFactory() = default;
-        std::string serviceName() override { return I::SERVICE_NAME; }
-        std::string serviceVersionRange() override { return ""; /* TODO std::string{"["} + I::SERVICE_VERSION + std::string{"]"};*/ }
-        std::string serviceLanguage() override { return celix::Constants::SERVICE_CXX_LANG; }
-        IServiceAdapter<I>* createAdapter(void *registeredSvc) override { return new DefaultServiceAdapter{registeredSvc}; }
-    };
-
-    template<typename I>
-    IServiceUsageAdapterFactory<I>& serviceUsageAdapterFactoryFor(I* /*dummy_used_for_infer*/) {
-        static DefaultServiceUsageAdapterFactory<I> factory{};
-        return factory;
-    }
-
-    /* TODO enable/improve for a better error message when function using adaptors are used, but no adaptor can be created
-    void* createServiceUsageAdapter(void *) {
-        static_assert(false, "No matching createServiceUsageAdaptor found. Please provide one!");
-        return nullptr;
-    }
-
-    void* createServiceRegistrationAdapter(void *) {
-        static_assert(false, "No matching createServiceRegistrationAdaptor   found. Please provide one!");
-        return nullptr;
-    }
-     */
-
-}
-
-#endif //CXX_CELIX_SERIVCEADAPTOR_H
diff --git a/libs/framework/include/celix/dm/Properties.h b/libs/framework/include/celix/dm/Properties.h
index fc485ca..d505db3 100644
--- a/libs/framework/include/celix/dm/Properties.h
+++ b/libs/framework/include/celix/dm/Properties.h
@@ -20,10 +20,11 @@
 #ifndef CXX_CELIX_DM_PROPERTIES_H
 #define CXX_CELIX_DM_PROPERTIES_H
 
-#include "celix/Properties.h"
+#include <unordered_map>
+#include <string>
 
 namespace celix { namespace dm {
-    using Properties = celix::Properties;
+    using Properties = std::unordered_map<std::string,std::string>;
 }}
 
 #endif //CXX_CELIX_DM_PROPERTIES_H
diff --git a/libs/framework/include/celix/impl/BundleContextImpl.h b/libs/framework/include/celix/impl/BundleContextImpl.h
deleted file mode 100644
index 63d54e2..0000000
--- a/libs/framework/include/celix/impl/BundleContextImpl.h
+++ /dev/null
@@ -1,710 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#ifndef CELIX_IMPL_BUNDLECONTEXTIMPL_H
-#define CELIX_IMPL_BUNDLECONTEXTIMPL_H
-
-#include <cstring>
-#include <mutex>
-#include <memory>
-
-#include "bundle_context.h"
-#include "service_tracker.h"
-
-#include "celix/impl/BundleImpl.h"
-#include "celix/dm/DependencyManager.h"
-#include "celix_service_factory.h"
-
-namespace celix {
-
-    namespace impl {
-        struct ServiceTrackingEntryFunctions {
-            std::function<void(void *)> set{};
-            std::function<void(void *, const celix::Properties &)> setWithProperties{};
-            std::function<void(void *, const celix::Properties &, const celix::Bundle &)> setWithOwner{};
-
-            std::function<void(void *)> add{};
-            std::function<void(void *, const celix::Properties &)> addWithProperties{};
-            std::function<void(void *, const celix::Properties &, const celix::Bundle &)> addWithOwner{};
-
-            std::function<void(void *)> remove{};
-            std::function<void(void *, const celix::Properties &)> removeWithProperties{};
-            std::function<void(void *, const celix::Properties &, const celix::Bundle &)> removeWithOwner{};
-        };
-
-        struct ServiceRegistrationEntry {
-            ServiceRegistrationEntry() {
-                std::memset(&this->cOpts, 0, sizeof(this->cOpts));
-                std::memset(&this->factory, 0, sizeof(this->factory));
-            }
-
-            celix_service_factory_t factory = {nullptr, nullptr, nullptr};
-            celix_service_registration_options_t cOpts = {nullptr, nullptr, nullptr, nullptr, nullptr, nullptr};
-            std::unique_ptr<IServiceAdapterBase> adapter{nullptr};
-        };
-
-        struct ServiceTrackingEntry {
-            ServiceTrackingEntry() { std::memset(&cOpts, 0, sizeof(cOpts));}
-            celix_service_tracking_options cOpts;
-            std::unique_ptr<ServiceTrackingEntryFunctions> functions{nullptr};
-            std::unique_ptr<celix::IServiceAdapterFactoryBase> adapter{nullptr};
-            std::map<void*, std::unique_ptr<celix::IServiceAdapterBase>> setAdaptersCache{};
-            std::map<void*, std::unique_ptr<celix::IServiceAdapterBase>> addAndRemoveAdaptersCache{};
-        };
-    }
-
-    struct BundleContext::Impl {
-        Impl(celix_bundle_context_t *_c_ctx, celix::Framework &_fw) : c_ctx(_c_ctx), fw(_fw), bnd(c_ctx), dm(c_ctx) {}
-        ~Impl() = default;
-
-        Impl(const Impl&) = delete;
-        Impl& operator=(const Impl&) = delete;
-        Impl(Impl&&) = delete;
-        Impl& operator=(Impl&&) = delete;
-
-        //initialized in ctor
-        celix_bundle_context_t *c_ctx;
-        celix::Framework& fw;
-        celix::impl::BundleImpl bnd;
-        celix::dm::DependencyManager dm;
-
-        std::mutex mutex{};
-        std::map<long,std::unique_ptr<celix::impl::ServiceTrackingEntry>> trackingEntries{};
-        std::map<long,celix::impl::ServiceRegistrationEntry> registrationEntries{};
-
-        long registerServiceInternal(celix::impl::ServiceRegistrationEntry &&entry) noexcept;
-
-        template<typename I>
-        long trackServicesInternal(const celix::ServiceTrackingOptions<I> &opts, celix::IServiceUsageAdapterFactory<I> *factory);
-        long trackServicesInternal(std::unique_ptr<celix::impl::ServiceTrackingEntry> entry) noexcept;
-        bool useServiceInternal(const std::string &serviceName, const std::string &serviceVersionRange, const std::string &serviceLang, const std::function<void(void *svc, const celix::Properties &props, const celix::Bundle &svcOwner)> &use) noexcept;
-        void useServicesInternal(const std::string &serviceName, const std::string &serviceVersionRange, const std::string &serviceLang, const std::function<void(void *svc, const celix::Properties &props, const celix::Bundle &svcOwner)> &use) noexcept;
-    };
-}
-
-namespace {
-    static celix::Properties createFromCProps(const celix_properties_t *c_props) {
-        celix::Properties result{};
-        const char *key = nullptr;
-        CELIX_PROPERTIES_FOR_EACH(const_cast<celix_properties_t *>(c_props), key) {
-            result[key] = celix_properties_get(c_props, key, nullptr);
-        }
-        return result;
-    }
-}
-
-inline celix::BundleContext::BundleContext(celix_bundle_context_t *ctx, celix::Framework& fw) {
-    this->pimpl = std::unique_ptr<celix::BundleContext::Impl>{new celix::BundleContext::Impl(ctx, fw)};
-}
-
-inline celix::BundleContext::~BundleContext() {
-    //NOTE no need to destroy the c bundle context -> done by c framework
-    {
-        //clearing service registration
-        std::lock_guard<std::mutex> lock{this->pimpl->mutex};
-        for (auto &pair : this->pimpl->registrationEntries) {
-            celix_bundleContext_unregisterService(this->pimpl->c_ctx, pair.first);
-        }
-        this->pimpl->registrationEntries.clear();
-    }
-
-    {
-        //clearing tracker entries
-        std::lock_guard<std::mutex> lock{this->pimpl->mutex};
-        for (auto &pair : this->pimpl->trackingEntries) {
-            celix_bundleContext_stopTracker(this->pimpl->c_ctx, pair.first);
-        }
-        this->pimpl->trackingEntries.clear();
-    }
-
-    this->pimpl->c_ctx = nullptr;
-    this->pimpl = nullptr;
-}
-
-
-inline void celix::BundleContext::unregisterService(long serviceId) noexcept {
-    std::lock_guard<std::mutex> lock{this->pimpl->mutex};
-    celix_bundleContext_unregisterService(this->pimpl->c_ctx, serviceId);
-    auto it = this->pimpl->registrationEntries.find(serviceId);
-    if (it != this->pimpl->registrationEntries.end()) {
-        this->pimpl->registrationEntries.erase(it);
-    }
-}
-
-inline std::vector<long> celix::BundleContext::findServices(const std::string &/*serviceName*/, const std::string &/*versionRange*/, const std::string &/*filter*/, const std::string &/*lang = ""*/) noexcept {
-    std::vector<long> result{};
-//                auto use = [&result](void *, const celix::Properties &props, const celix::Bundle &) {
-//                    long id = celix::getProperty(props, OSGI_FRAMEWORK_SERVICE_ID, -1);
-//                    if (id >= 0) {
-//                        result.push_back(id);
-//                    }
-//                };
-    //TODO useServicesWithOptions this->useServicesInternal(serviceName, versionRange, filter, use);
-    return result;
-}
-
-inline void celix::BundleContext::stopTracker(long trackerId) noexcept {
-    std::lock_guard<std::mutex> lock{this->pimpl->mutex};
-    celix_bundleContext_stopTracker(this->pimpl->c_ctx, trackerId);
-    auto it = this->pimpl->trackingEntries.find(trackerId);
-    if (it != this->pimpl->trackingEntries.end()) {
-        this->pimpl->trackingEntries.erase(it);
-    }
-}
-
-inline std::string celix::BundleContext::getProperty(const std::string &key, std::string defaultValue) noexcept {
-    const char *val = nullptr;
-    bundleContext_getPropertyWithDefault(this->pimpl->c_ctx, key.c_str(), defaultValue.c_str(), &val);
-    return std::string{val};
-}
-
-
-//    long celix::BundleContext::registerEmbeddedBundle(
-//            std::string /*id*/,
-//            std::function<void(celix::BundleContext & ctx)> /*start*/,
-//            std::function<void(celix::BundleContext & ctx)> /*stop*/,
-//            celix::Properties /*manifest*/,
-//            bool /*autoStart*/
-//    ) noexcept  {
-//        return -1; //TODO
-//    };
-//
-//    void registerEmbeddedBundle(const celix::BundleRegistrationOptions &/*opts*/) noexcept override {
-//        //TODO
-//    }
-
-inline long celix::BundleContext::installBundle(const std::string &bundleLocation, bool autoStart) noexcept {
-    long bndId = -1;
-    if (this->pimpl->c_ctx != nullptr) {
-        celix_bundle_t *bnd = nullptr;
-        bundleContext_installBundle(this->pimpl->c_ctx, bundleLocation.c_str(), &bnd);
-        if (bnd != nullptr) {
-            bundle_getBundleId(bnd, &bndId);
-            if (autoStart) {
-                bundle_start(bnd);
-            }
-        }
-    }
-    return bndId;
-}
-
-
-inline void celix::BundleContext::useBundles(const std::function<void(const celix::Bundle &bnd)> &use) noexcept {
-    auto c_use = [](void *handle, const celix_bundle_t *c_bnd) {
-        auto *func =  static_cast<std::function<void(const celix::Bundle &bnd)>*>(handle);
-        auto m_bnd = const_cast<celix_bundle_t*>(c_bnd);
-        celix::impl::BundleImpl bnd{m_bnd};
-        (*func)(bnd);
-    };
-    celix_bundleContext_useBundles(this->pimpl->c_ctx, (void*)(&use), c_use);
-}
-
-inline void celix::BundleContext::useBundle(long bundleId, const std::function<void(const celix::Bundle &bnd)> &use) noexcept {
-    auto c_use = [](void *handle, const celix_bundle_t *c_bnd) {
-        auto *func =  static_cast<std::function<void(const celix::Bundle &bnd)>*>(handle);
-        auto m_bnd = const_cast<celix_bundle_t*>(c_bnd);
-        celix::impl::BundleImpl bnd{m_bnd};
-        (*func)(bnd);
-    };
-    celix_bundleContext_useBundle(this->pimpl->c_ctx, bundleId, (void*)(&use), c_use);
-}
-
-inline celix::Framework& celix::BundleContext::getFramework() noexcept {
-    return this->pimpl->fw;
-}
-
-inline celix::Bundle& celix::BundleContext::getBundle() noexcept {
-    return this->pimpl->bnd;
-};
-
-inline celix::dm::DependencyManager& celix::BundleContext::getDependencyManager() noexcept {
-    return this->pimpl->dm;
-}
-
-inline long celix::BundleContext::Impl::registerServiceInternal(celix::impl::ServiceRegistrationEntry&& entry) noexcept {
-    long svcId = celix_bundleContext_registerServiceWithOptions(this->c_ctx, &entry.cOpts);
-    if (svcId >= 0) {
-        std::lock_guard<std::mutex> lock{this->mutex};
-        this->registrationEntries[svcId] = std::move(entry);
-    }
-    return svcId;
-}
-
-inline long celix::BundleContext::Impl::trackServicesInternal(std::unique_ptr<celix::impl::ServiceTrackingEntry> entry) noexcept {
-    long trkId = celix_bundleContext_trackServicesWithOptions(this->c_ctx, &entry->cOpts);
-    if (trkId >= 0) {
-        std::lock_guard<std::mutex> lock{this->mutex};
-        this->trackingEntries[trkId] = std::move(entry);
-    }
-    return trkId;
-}
-
-inline bool celix::BundleContext::Impl::useServiceInternal(
-        const std::string &serviceName,
-        const std::string &serviceVersionRange,
-        const std::string &serviceLang,
-        const std::function<void(void *svc, const celix::Properties &props, const celix::Bundle &svcOwner)> &use) noexcept {
-    auto c_use = [](void *handle, void *svc, const celix_properties_t *c_props, const celix_bundle_t *c_svcOwner) {
-        auto *fn = static_cast<const std::function<void(void *svc, const celix::Properties &props, const celix::Bundle &svcOwner)> *>(handle);
-        celix::Properties props = createFromCProps(c_props);
-        celix_bundle_t *m_bnd = const_cast<celix_bundle_t*>(c_svcOwner);
-        celix::impl::BundleImpl bnd{m_bnd};
-        (*fn)(svc, props, bnd);
-    };
-
-    celix_service_use_options_t opts;
-    std::memset(&opts, 0, sizeof(opts));
-
-    opts.filter.serviceName = serviceName.empty() ? nullptr : serviceName.c_str();;
-    opts.filter.versionRange = serviceVersionRange.empty() ? nullptr : serviceVersionRange.c_str();
-    opts.filter.serviceLanguage = serviceLang.empty() ? celix::Constants::SERVICE_CXX_LANG : serviceLang.c_str();
-    opts.callbackHandle = (void*)&use;
-    opts.useWithOwner = c_use;
-
-    return celix_bundleContext_useServiceWithOptions(this->c_ctx, &opts);
-}
-
-inline void celix::BundleContext::Impl::useServicesInternal(
-        const std::string &serviceName,
-        const std::string &serviceVersionRange,
-        const std::string &serviceLang,
-        const std::function<void(void *svc, const celix::Properties &props, const celix::Bundle &svcOwner)> &use) noexcept {
-    auto c_use = [](void *handle, void *svc, const celix_properties_t *c_props, const celix_bundle_t *c_svcOwner) {
-        auto *fn = static_cast<const std::function<void(void *svc, const celix::Properties &props, const celix::Bundle &svcOwner)> *>(handle);
-        celix::Properties props = createFromCProps(c_props);
-        celix_bundle_t *m_bnd = const_cast<celix_bundle_t*>(c_svcOwner);
-        celix::impl::BundleImpl bnd{m_bnd};
-        (*fn)(svc, props, bnd);
-    };
-
-    celix_service_use_options_t opts;
-    std::memset(&opts, 0, sizeof(opts));
-
-    opts.filter.serviceName = serviceName.empty() ? nullptr : serviceName.c_str();;
-    opts.filter.versionRange = serviceVersionRange.empty() ? nullptr : serviceVersionRange.c_str();
-    opts.filter.serviceLanguage = serviceLang.empty() ? celix::Constants::SERVICE_CXX_LANG : serviceLang.c_str();
-    opts.callbackHandle = (void*)&use;
-    opts.useWithOwner = c_use;
-
-    celix_bundleContext_useServicesWithOptions(this->c_ctx, &opts);
-}
-
-template<typename I>
-long celix::BundleContext::registerService(I *svc, Properties props) noexcept {
-    using namespace celix;
-    auto &factory = serviceRegistrationAdapterFactoryFor(svc /*note svc value not used, just the pointer type*/);
-    auto *adapter = factory.createAdapter(svc);
-
-    celix_properties_t *c_props = celix_properties_create();
-    for (auto &pair : props) {
-        celix_properties_set(c_props, pair.first.c_str(), pair.second.c_str());
-    }
-
-    celix::impl::ServiceRegistrationEntry re{};
-    re.cOpts = CELIX_EMPTY_SERVICE_REGISTRATION_OPTIONS;
-    re.cOpts.svc = static_cast<void*>(adapter->adapt());
-    re.cOpts.serviceName = factory.serviceName().c_str();
-    re.cOpts.serviceVersion = factory.serviceVersion().c_str();
-    re.cOpts.serviceLanguage = factory.serviceLanguage().c_str();
-    re.cOpts.properties = c_props;
-    re.adapter = std::unique_ptr<IServiceAdapterBase>{adapter};
-
-    return this->pimpl->registerServiceInternal(std::move(re));
-}
-
-template<typename I>
-long celix::BundleContext::registerService(I *svc, const std::string &serviceName, Properties props) noexcept {
-    celix::ServiceRegistrationOptions<I> opts{*svc, serviceName};
-    opts.properties = std::move(props);
-    return this->registerServiceWithOptions(opts);
-}
-
-template<typename I>
-long celix::BundleContext::registerCService(I *svc, const std::string &serviceName, Properties props) noexcept {
-    static_assert(std::is_pod<I>::value, "Service I must be a 'Plain Old Data' object");
-    celix::ServiceRegistrationOptions<I> opts{*svc, serviceName};
-    opts.properties = std::move(props);
-    opts.serviceLanguage = celix::Constants::SERVICE_C_LANG;
-    return this->registerServiceWithOptions(opts);
-}
-
-template<typename I>
-long celix::BundleContext::registerServiceFactory(celix::IServiceFactory<I> *factory, const std::string &serviceName, celix::Properties props) {
-    celix::ServiceRegistrationOptions<I> opts{factory, serviceName};
-    opts.properties = std::move(props);
-    return this->registerServiceWithOptions(opts);
-}
-
-template<typename I>
-long celix::BundleContext::registerCServiceFactory(IServiceFactory<I> *factory, const std::string &serviceName, celix::Properties props) {
-    static_assert(std::is_pod<I>::value, "Service I must be a 'Plain Old Data' object");
-    celix::ServiceRegistrationOptions<I> opts{factory, serviceName};
-    opts.properties = std::move(props);
-    opts.serviceLanguage = celix::Constants::SERVICE_C_LANG;
-    return this->registerServiceWithOptions(opts);
-}
-
-template<typename I>
-long celix::BundleContext::registerServiceWithOptions(const celix::ServiceRegistrationOptions<I>& opts) noexcept {
-    celix_properties_t *c_props = celix_properties_create();
-    for (auto &pair : opts.properties) {
-        celix_properties_set(c_props, pair.first.c_str(), pair.second.c_str());
-    }
-
-    celix::impl::ServiceRegistrationEntry re{};
-
-    re.cOpts = CELIX_EMPTY_SERVICE_REGISTRATION_OPTIONS;
-    if (opts.svc != nullptr) {
-        re.cOpts.svc = static_cast<void *>(opts.svc);
-    } else if (opts.factory != nullptr) {
-        auto c_getService = [](void *handle, const celix_bundle_t *requestingBundle, const celix_properties_t *svcProperties) -> void* {
-            celix::IServiceFactory<I> *f = static_cast<celix::IServiceFactory<I>*>(handle);
-            auto mbnd = const_cast<celix_bundle_t*>(requestingBundle);
-            celix::impl::BundleImpl bundle{mbnd};
-            celix::Properties props = createFromCProps(svcProperties);
-            I *svc = f->getService(bundle, props);
-            return static_cast<void*>(svc);
-        };
-        auto c_ungetService = [](void *handle, const celix_bundle_t *requestingBundle, const celix_properties_t *svcProperties) {
-            celix::IServiceFactory<I> *f = static_cast<celix::IServiceFactory<I>*>(handle);
-            auto mbnd = const_cast<celix_bundle_t*>(requestingBundle);
-            celix::impl::BundleImpl bundle{mbnd};
-            celix::Properties props = createFromCProps(svcProperties);
-            f->ungetService(bundle, props);
-        };
-        re.factory.handle = static_cast<void*>(opts.factory);
-        re.factory.getService = c_getService;
-        re.factory.ungetService = c_ungetService;
-        re.cOpts.factory = &re.factory;
-    }
-
-    re.cOpts.serviceName = opts.serviceName.c_str();
-    re.cOpts.serviceVersion = opts.serviceVersion.c_str();
-    re.cOpts.serviceLanguage = opts.serviceLanguage.c_str();
-    re.cOpts.properties = c_props;
-
-    return this->pimpl->registerServiceInternal(std::move(re));
-}
-
-template<typename I>
-long celix::BundleContext::trackService(std::function<void(I *svc)> set) noexcept {
-    using namespace celix;
-    I* dummy = nullptr;
-    auto &factory = serviceUsageAdapterFactoryFor(dummy);
-
-    celix::ServiceTrackingOptions<I> opts{factory.serviceName()};
-    opts.filter.serviceLanguage = factory.serviceLanguage();
-    opts.filter.versionRange = factory.serviceVersionRange();
-    opts.set = set;
-    return this->pimpl->trackServicesInternal<I>(opts, &factory);
-}
-
-template<typename I>
-long celix::BundleContext::trackService(const std::string &serviceName, std::function<void(I *svc)> set) noexcept {
-    celix::ServiceTrackingOptions<I> opts{serviceName};
-    opts.set = std::move(set);
-    return this->trackServicesWithOptions<I>(opts);
-}
-
-template<typename I>
-long celix::BundleContext::trackServices(const std::string &serviceName,
-        std::function<void(I *svc)> add, std::function<void(I *svc)> remove) noexcept {
-    celix::ServiceTrackingOptions<I> opts{serviceName};
-    opts.add = std::move(add);
-    opts.remove = std::move(remove);
-    return this->trackServicesWithOptions<I>(opts);
-}
-
-template<typename I>
-long celix::BundleContext::trackServicesWithOptions(const celix::ServiceTrackingOptions<I> &opts) {
-    return this->pimpl->trackServicesInternal<I>(opts, nullptr);
-}
-
-template<typename I>
-static I* svcFor(celix::IServiceUsageAdapterFactory<I> *factory, std::map<void*, std::unique_ptr<celix::IServiceAdapterBase>> &cache, void *svc) {
-    I* result = nullptr;
-    if (svc != nullptr) {
-        if (factory != nullptr) {
-            //checking cache
-            auto it = cache.find(svc);
-            if (it != cache.end()) {
-                celix::IServiceAdapterBase *base = it->second.get();
-                auto *adapter = static_cast<celix::IServiceAdapter<I>*>(base);
-                result = adapter->adapt();
-            } else {
-                celix::IServiceAdapter<I> *adapter = factory->createAdapter(svc);
-                cache[svc] = std::unique_ptr<celix::IServiceAdapterBase>{adapter};
-                result = adapter->adapt();
-            }
-        } else {
-            result = static_cast<I*>(svc);
-        }
-    }
-    return result;
-}
-
-static inline void updateSetCache(std::map<void*, std::unique_ptr<celix::IServiceAdapterBase>> &cache, void *currentSetSvc) {
-    if (currentSetSvc == nullptr) {
-        cache.clear();
-    } else {
-        auto it = cache.begin();
-        while (it != cache.end()) {
-            if (it->first != currentSetSvc) {
-                cache.erase(it++);
-            } else {
-                ++it;
-            }
-        }
-    }
-}
-
-static inline void removeFromCache(std::map<void*, std::unique_ptr<celix::IServiceAdapterBase>> &cache, void *removedSvc) {
-    auto it = cache.find(removedSvc);
-    if (it != cache.end()) {
-        cache.erase(it);
-    }
-}
-
-template<typename I>
-long celix::BundleContext::Impl::trackServicesInternal(const celix::ServiceTrackingOptions<I> &opts, celix::IServiceUsageAdapterFactory<I> *factory) {
-    auto entry = std::unique_ptr<celix::impl::ServiceTrackingEntry>{new celix::impl::ServiceTrackingEntry()};
-    auto *entryPtr = entry.get();
-    entry->functions = std::unique_ptr<celix::impl::ServiceTrackingEntryFunctions>{new celix::impl::ServiceTrackingEntryFunctions()};
-
-    auto set = opts.set;
-    if (set) {
-        auto voidfunc = [entryPtr, factory, set](void *voidSvc) {
-            I *typedSvc = svcFor<I>(factory, entryPtr->setAdaptersCache, voidSvc);
-            set(typedSvc);
-            updateSetCache(entryPtr->setAdaptersCache, voidSvc);
-        };
-        entry->functions->set = voidfunc;
-        entry->cOpts.set = [](void *handle, void *svc) {
-            auto *fentry = static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
-            (fentry->set)(svc);
-        };
-    }
-
-    auto setWithProperties = opts.setWithProperties;
-    if (setWithProperties) {
-        auto voidfunc = [entryPtr, factory, setWithProperties](void *voidSvc, const celix::Properties &props) {
-            I *typedSvc = svcFor<I>(factory, entryPtr->setAdaptersCache, voidSvc);
-            setWithProperties(typedSvc, props);
-            updateSetCache(entryPtr->setAdaptersCache, voidSvc);
-        };
-        entry->functions->setWithProperties = voidfunc;
-        entry->cOpts.setWithProperties = [](void *handle, void *svc, const celix_properties_t *c_props) {
-            auto *fentry = static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
-            celix::Properties props = createFromCProps(c_props);
-            (fentry->setWithProperties)(svc, props);
-        };
-    }
-
-    auto setWithOwner = opts.setWithOwner;
-    if (setWithOwner) {
-        auto voidfunc = [entryPtr, factory, setWithOwner](void *voidSvc, const celix::Properties &props, const celix::Bundle &bnd) {
-            I *typedSvc = svcFor<I>(factory, entryPtr->setAdaptersCache, voidSvc);
-            setWithOwner(typedSvc, props, bnd);
-            updateSetCache(entryPtr->setAdaptersCache, voidSvc);
-        };
-        entry->functions->setWithOwner = voidfunc;
-        entry->cOpts.setWithOwner = [](void *handle, void *svc, const celix_properties_t *c_props, const celix_bundle_t *c_bnd) {
-            auto *fentry = static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
-            celix::Properties props = createFromCProps(c_props);
-            auto m_bnd = const_cast<celix_bundle_t *>(c_bnd);
-            celix::impl::BundleImpl bnd{m_bnd};
-            (fentry->setWithOwner)(svc, props, bnd);
-        };
-    }
-
-    auto add = opts.add;
-    if (add) {
-        auto voidfunc = [entryPtr, factory, add](void *voidSvc) {
-            I *typedSvc = svcFor<I>(factory, entryPtr->addAndRemoveAdaptersCache, voidSvc);
-            add(typedSvc);
-        };
-        entry->functions->add = voidfunc;
-        entry->cOpts.add = [](void *handle, void *svc) {
-            auto *fentry = static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
-            (fentry->add)(svc);
-        };
-    }
-
-    auto addWithProperties = opts.addWithProperties;
-    if (addWithProperties) {
-        auto voidfunc = [entryPtr, factory, addWithProperties](void *voidSvc, const celix::Properties &props) {
-            I *typedSvc = svcFor<I>(factory, entryPtr->addAndRemoveAdaptersCache, voidSvc);
-            addWithProperties(typedSvc, props);
-        };
-        entry->functions->addWithProperties = voidfunc;
-        entry->cOpts.addWithProperties = [](void *handle, void *svc, const celix_properties_t *c_props) {
-            auto *fentry = static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
-            celix::Properties props = createFromCProps(c_props);
-            (fentry->addWithProperties)(svc, props);
-        };
-    }
-
-    auto addWithOwner = opts.addWithOwner;
-    if (addWithOwner) {
-        auto voidfunc = [entryPtr, factory, addWithOwner](void *voidSvc, const celix::Properties &props, const celix::Bundle &bnd) {
-            I *typedSvc = svcFor<I>(factory, entryPtr->addAndRemoveAdaptersCache, voidSvc);
-            addWithOwner(typedSvc, props, bnd);
-        };
-        entry->functions->addWithOwner = voidfunc;
-        entry->cOpts.addWithOwner = [](void *handle, void *svc, const celix_properties_t *c_props, const celix_bundle_t *c_bnd) {
-            auto *fentry = static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
-            celix::Properties props = createFromCProps(c_props);
-            auto m_bnd = const_cast<celix_bundle_t *>(c_bnd);
-            celix::impl::BundleImpl bnd{m_bnd};
-            (fentry->addWithOwner)(svc, props, bnd);
-        };
-    }
-
-    auto remove = opts.remove;
-    if (remove) {
-        auto voidfunc = [entryPtr, factory, remove](void *voidSvc) {
-            I *typedSvc = svcFor<I>(factory, entryPtr->addAndRemoveAdaptersCache, voidSvc);
-            remove(typedSvc);
-            removeFromCache(entryPtr->addAndRemoveAdaptersCache, voidSvc);
-        };
-        entry->functions->remove = voidfunc;
-        entry->cOpts.remove = [](void *handle, void *svc) {
-            auto *fentry = static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
-            (fentry->add)(svc);
-        };
-    }
-
-    auto removeWithProperties = opts.removeWithProperties;
-    if (removeWithProperties) {
-        auto voidfunc = [entryPtr, factory, removeWithProperties](void *voidSvc, const celix::Properties &props) {
-            I *typedSvc = svcFor<I>(factory, entryPtr->addAndRemoveAdaptersCache, voidSvc);
-            removeWithProperties(typedSvc, props);
-            removeFromCache(entryPtr->addAndRemoveAdaptersCache, voidSvc);
-        };
-        entry->functions->removeWithProperties = voidfunc;
-        entry->cOpts.removeWithProperties = [](void *handle, void *svc, const celix_properties_t *c_props) {
-            auto *fentry = static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
-            celix::Properties props = createFromCProps(c_props);
-            (fentry->removeWithProperties)(svc, props);
-        };
-    }
-
-    auto removeWithOwner = opts.removeWithOwner;
-    if (removeWithOwner) {
-        auto voidfunc = [entryPtr, factory, removeWithOwner](void *voidSvc, const celix::Properties &props, const celix::Bundle &bnd) {
-            I *typedSvc = svcFor<I>(factory, entryPtr->addAndRemoveAdaptersCache, voidSvc);
-            removeWithOwner(typedSvc, props, bnd);
-            removeFromCache(entryPtr->addAndRemoveAdaptersCache, voidSvc);
-        };
-        entry->functions->removeWithOwner = voidfunc;
-        entry->cOpts.removeWithOwner = [](void *handle, void *svc, const celix_properties_t *c_props, const celix_bundle_t *c_bnd) {
-            auto *fentry = static_cast<celix::impl::ServiceTrackingEntryFunctions*>(handle);
-            celix::Properties props = createFromCProps(c_props);
-            auto m_bnd = const_cast<celix_bundle_t *>(c_bnd);
-            celix::impl::BundleImpl bnd{m_bnd};
-            (fentry->removeWithOwner)(svc, props, bnd);
-        };
-    }
-
-    entry->cOpts.filter.serviceName = opts.filter.serviceName.c_str();
-    entry->cOpts.filter.serviceLanguage = opts.filter.serviceLanguage.c_str();
-    entry->cOpts.filter.versionRange = opts.filter.versionRange.c_str();
-    entry->cOpts.filter.filter = opts.filter.filter.c_str();
-
-    entry->cOpts.callbackHandle = entry->functions.get();
-
-    return this->trackServicesInternal(std::move(entry));
-}
-
-template<typename I>
-bool celix::BundleContext::useServiceWithId(long serviceId, const std::string &/*serviceName*/ /*sanity*/, const std::function<void(I &svc, const celix::Properties &props, const celix::Bundle &svcOwner)> &/*use*/) noexcept {
-    std::string filter = std::string{"(service.id="} + std::to_string(serviceId) + std::string{")"};
-    //TODO use useServiceWithOptions return this->useService<I>(serviceName, "", filter, use);
-    return false;
-}
-
-template<typename I>
-bool celix::BundleContext::useServiceWithId(long serviceId, const std::string &/*serviceName*/ /*sanity*/, const std::function<void(I &svc)> &/*use*/) noexcept {
-    std::string filter = std::string{"(service.id="} + std::to_string(serviceId) + std::string{")"};
-    //TODO use useServiceWithOptions return this->useService<I>(serviceName, "", filter, use);
-    return false;
-}
-
-template<typename I>
-bool celix::BundleContext::useService(const std::string &serviceName, const std::function<void(I &svc, const celix::Properties &props, const celix::Bundle &svcOwner)> &use) noexcept {
-    return this->pimpl->useServiceInternal(serviceName, "", "", [use](void *voidSvc, const celix::Properties &props, const celix::Bundle &svcOwner) {
-        I *typedSvc = static_cast<I*>(voidSvc);
-        use(*typedSvc, props, svcOwner);
-    });
-}
-
-template<typename I>
-bool celix::BundleContext::useService(const std::string &serviceName, const std::function<void(I &svc)> &use) noexcept {
-    return this->pimpl->useServiceInternal(serviceName, "", "", [use](void *voidSvc, const celix::Properties &, const celix::Bundle &) {
-        I *typedSvc = static_cast<I*>(voidSvc);
-        use(*typedSvc);
-    });
-}
-
-template<typename I>
-bool celix::BundleContext::useService(const std::function<void(I &svc)> &use) noexcept {
-    using namespace celix;
-    I* dummy = nullptr;
-    auto &factory = serviceUsageAdapterFactoryFor(dummy);
-    bool called = this->pimpl->useServiceInternal(factory.serviceName(), factory.serviceVersionRange(), factory.serviceLanguage(), [&](void *voidSvc, const celix::Properties&, const celix::Bundle&){
-        auto *adapter = factory.createAdapter(voidSvc);
-        auto *adapted = adapter->adapt();
-        use(*adapted);
-        free(adapter);
-    });
-    return called;
-}
-
-template<typename I>
-void celix::BundleContext::useServices(const std::function<void(I &svc)> &use) noexcept {
-    using namespace celix;
-    I* dummy = nullptr;
-    auto &factory = serviceUsageAdapterFactoryFor(dummy);
-    this->pimpl->useServicesInternal(factory.serviceName(), factory.serviceVersionRange(), factory.serviceLanguage(), [&](void *voidSvc, const celix::Properties&, const celix::Bundle&){
-        auto *adapter = factory.createAdapter(voidSvc);
-        auto *adapted = adapter->adapt();
-        use(*adapted);
-        free(adapter);
-    });
-}
-
-template<typename I>
-void celix::BundleContext::useServices(const std::string &serviceName, const std::function<void(I &svc, const celix::Properties &props, const celix::Bundle &svcOwner)> &use) noexcept {
-    this->pimpl->useServicesInternal(serviceName, "", "", [use](void *voidSvc, const celix::Properties &props, const celix::Bundle &svcOwner) {
-        I *typedSvc = static_cast<I*>(voidSvc);
-        use(*typedSvc, props, svcOwner);
-    });
-}
-
-template<typename I>
-void celix::BundleContext::useServices(const std::string &serviceName, const std::function<void(I &svc)> &use) noexcept {
-    this->pimpl->useServicesInternal(serviceName, "", "", [use](void *voidSvc, const celix::Properties &, const celix::Bundle &) {
-        I *typedSvc = static_cast<I*>(voidSvc);
-        use(*typedSvc);
-    });
-}
-
-
-
-#endif //CELIX_IMPL_BUNDLECONTEXTIMPL_H
diff --git a/libs/framework/include/celix/impl/BundleImpl.h b/libs/framework/include/celix/impl/BundleImpl.h
deleted file mode 100644
index e56a5b7..0000000
--- a/libs/framework/include/celix/impl/BundleImpl.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#ifndef CELIX_IMPL_BUNDLEIMPL_H
-#define CELIX_IMPL_BUNDLEIMPL_H
-
-#include "celix_bundle.h"
-#include "celix_bundle_context.h"
-
-namespace celix {
-
-    //forward declaration
-
-    namespace impl {
-        class BundleImpl : public celix::Bundle {
-        public:
-            BundleImpl(celix_bundle_context_t *c_ctx) : c_bnd(nullptr) {
-                bundleContext_getBundle(c_ctx, &this->c_bnd);
-            }
-
-            BundleImpl(celix_bundle_t *b) : c_bnd(b) {
-            }
-
-            virtual ~BundleImpl() {
-                //no need to destroy the c bundle context -> done by c framework
-                this->c_bnd = nullptr;
-            }
-
-            BundleImpl(const BundleImpl&) = delete;
-            BundleImpl& operator=(const BundleImpl&) = delete;
-
-            BundleImpl(BundleImpl&& rhs) : c_bnd{nullptr} {
-                using std::swap;
-                swap(this->c_bnd, rhs.c_bnd);
-            }
-
-            BundleImpl& operator=(BundleImpl&& rhs) {
-                using std::swap;
-                swap(this->c_bnd, rhs.c_bnd);
-                return *this;
-            }
-
-            bool isSystemBundle() const noexcept  override {
-                bool r;
-                bundle_isSystemBundle(this->c_bnd, &r);
-                return r;
-            }
-
-            void * getHandle() const noexcept override {
-                return bundle_getHandle(this->c_bnd);
-            }
-
-            BundleState getState() const noexcept  override {
-                bundle_state_e c_state;
-                bundle_getState(this->c_bnd, &c_state);
-                return this->fromCState(c_state);
-            }
-
-            long getBundleId() const noexcept  override {
-                long id{-1};
-                bundle_getBundleId(this->c_bnd, &id);
-                return id;
-            }
-
-            std::string getBundleLocation() const noexcept  override {
-                std::string location{};
-                const char *loc = nullptr;
-                bundle_getBundleLocation(this->c_bnd, &loc);
-                if (loc != nullptr) {
-                    location = std::string{loc};
-                }
-                return location;
-            }
-
-            std::string getBundleCache() const noexcept  override {
-                std::string cache{};
-                const char *c = celix_bundle_getEntry(this->c_bnd, ".");
-                if (c != nullptr) {
-                    cache = std::string{c};
-                }
-                return cache;
-            }
-
-            std::string getBundleName() const noexcept override {
-                std::string name{};
-                module_pt mod = nullptr;
-                bundle_getCurrentModule(this->c_bnd, &mod);
-                if (mod != nullptr) {
-                    name = module_getId(mod);
-                }
-                return name;
-            }
-
-            std::string getBundleSymbolicName() const noexcept override {
-                std::string name{};
-                module_pt mod = nullptr;
-                bundle_getCurrentModule(this->c_bnd, &mod);
-                if (mod != nullptr) {
-                    const char *n = nullptr;
-                    module_getSymbolicName(mod, &n);
-                    if (n != nullptr) {
-                        name = n;
-                    }
-                }
-                return name;
-            }
-
-            std::string getBundleVersion() const noexcept override {
-                return std::string{}; //TODO
-//                std::string version{};
-//                module_pt mod = nullptr;
-//                bundle_getCurrentModule(this->c_bnd, &mod);
-//                if (mod != nullptr) {
-//                    auto version = module_getVersion(mod);
-//                    //TODO
-//                }
-//                return version;
-            }
-
-            celix::Properties getManifestAsProperties() const noexcept  override {
-                return celix::Properties{}; //TODO
-            }
-
-            void start() noexcept override {
-                bundle_start(this->c_bnd);
-            }
-
-            void stop() noexcept override {
-                bundle_stop(this->c_bnd);
-            }
-
-            void uninstall() noexcept override {
-                bundle_uninstall(this->c_bnd);
-            }
-
-        private:
-            BundleState fromCState(bundle_state_e c_state) const {
-                switch(c_state) {
-                    case OSGI_FRAMEWORK_BUNDLE_UNKNOWN:
-                        return BundleState::UNKNOWN;
-                    case OSGI_FRAMEWORK_BUNDLE_UNINSTALLED:
-                        return BundleState::INSTALLED;
-                    case OSGI_FRAMEWORK_BUNDLE_INSTALLED:
-                        return BundleState::INSTALLED;
-                    case OSGI_FRAMEWORK_BUNDLE_RESOLVED:
-                        return BundleState::RESOLVED;
-                    case OSGI_FRAMEWORK_BUNDLE_STOPPING:
-                        return BundleState::STOPPING;
-                    case OSGI_FRAMEWORK_BUNDLE_ACTIVE:
-                        return BundleState::ACTIVE;
-                    case OSGI_FRAMEWORK_BUNDLE_STARTING:
-                        return BundleState::STARTING;
-                    default:
-                        ;//passs
-                }
-                return BundleState::UNKNOWN;
-            };
-
-            celix_bundle_t *c_bnd;
-        };
-    }
-}
-
-#endif //CELIX_IMPL_BUNDLEIMPL_H
diff --git a/libs/framework/include/celix/impl/FrameworkImpl.h b/libs/framework/include/celix/impl/FrameworkImpl.h
deleted file mode 100644
index ba1f636..0000000
--- a/libs/framework/include/celix/impl/FrameworkImpl.h
+++ /dev/null
@@ -1,127 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#ifndef CXX_CELIX_IMPL_FRAMEWORKIMPL_H
-#define CXX_CELIX_IMPL_FRAMEWORKIMPL_H
-
-#include "celix_framework_factory.h"
-#include "framework.h"
-
-#include "celix/impl/BundleContextImpl.h"
-#include "celix/impl/BundleImpl.h"
-
-namespace celix {
-
-    namespace impl {
-
-        class FrameworkImpl : public celix::Framework {
-        public:
-            FrameworkImpl(celix_bundle_context_t *c_ctx) : owner(false) {
-                bundleContext_getFramework(c_ctx, &this->c_fwm);
-                this->setFrameworkContext();
-            }
-
-            FrameworkImpl(celix_framework_t *c_fw) : owner(false) {
-                //wrapper framework
-                this->c_fwm = c_fw;
-                //assume started framework
-                this->setFrameworkContext();
-            }
-
-            FrameworkImpl(const FrameworkImpl&) = delete;
-            FrameworkImpl& operator=(const FrameworkImpl&) = delete;
-            FrameworkImpl(FrameworkImpl&&) = delete;
-            FrameworkImpl& operator=(FrameworkImpl&&) = delete;
-
-            FrameworkImpl(celix::Properties config) : owner(true) {
-                //framework which also owns the underlining c framework
-                auto c_config = properties_create();
-                for (auto &pair : config) {
-                    properties_set(c_config, pair.first.c_str(), pair.second.c_str());
-                }
-                this->c_fwm = frameworkFactory_newFramework(c_config); //should be started
-
-                this->setFrameworkContext();
-            };
-
-            virtual ~FrameworkImpl() {
-                if (this->owner && this->c_fwm != nullptr) {
-                    framework_stop(this->c_fwm);
-                    framework_waitForStop(this->c_fwm);
-                    framework_destroy(this->c_fwm);
-                }
-            }
-
-            virtual void start() noexcept override {
-                framework_start(this->c_fwm);
-            }
-
-            virtual void stop() noexcept override {
-                framework_stop(this->c_fwm);
-            }
-
-            virtual void waitForStop() noexcept override {
-                framework_waitForStop(this->c_fwm);
-            }
-            //TODO also in c virtual void breakWaitForStops() noexcept = 0;
-
-            std::string getUUID() const noexcept override {
-                //TODO return std::string{celix_framework_getUUID(this->c_fwm)};
-                return "TODO";
-            }
-
-            celix::BundleContext& getFrameworkContext() noexcept override {
-                BundleContext &ctx = this->bundleContextsCache.at(0);
-                return ctx;
-            }
-
-            celix::Bundle& getFrameworkBundle() noexcept override {
-                if (this->fwBundle.size() == 0) {
-                    celix_bundle_t* c_bnd = nullptr;
-                    framework_getFrameworkBundle(this->c_fwm, &c_bnd);
-                    this->fwBundle.emplace_back(c_bnd);
-
-                }
-                return this->fwBundle[0];
-            }
-
-        private:
-
-            void setFrameworkContext() {
-                //create and set framework bundle context (replace invalid bundle context)
-                celix_bundle_t *fwmBundle = nullptr;
-                celix_bundle_context_t *fwmCtx = nullptr;
-                framework_getFrameworkBundle(this->c_fwm, &fwmBundle);
-                bundle_getContext(fwmBundle, &fwmCtx);
-                this->bundleContextsCache.emplace(std::piecewise_construct,
-                                                    std::forward_as_tuple(0L),
-                                                    std::forward_as_tuple(fwmCtx, *this));
-            }
-
-
-            bool owner;
-            celix_framework_t *c_fwm{nullptr};
-            std::map<long,celix::BundleContext> bundleContextsCache{};
-            std::vector<celix::impl::BundleImpl> fwBundle{}; //optional entry
-
-        };
-    }
-}
-
-#endif //CXX_CELIX_IMPL_FRAMEWORKIMPL_H
diff --git a/libs/framework_cxx/CMakeLists.txt b/libs/framework_cxx/CMakeLists.txt
index e5fbe8a..472bd60 100644
--- a/libs/framework_cxx/CMakeLists.txt
+++ b/libs/framework_cxx/CMakeLists.txt
@@ -20,7 +20,8 @@ find_package(glog REQUIRED)
 #TODO rename to celix::framework
 add_library(celix_framework_cxx SHARED
         src/Framework.cc
-)
+        src/BundleContext.cc
+        src/Bundle.cc)
 target_include_directories(celix_framework_cxx PRIVATE src)
 target_include_directories(celix_framework_cxx PUBLIC include)
 target_link_libraries(celix_framework_cxx PUBLIC celix::registry glog::glog) #TODO glog private and static lib
diff --git a/libs/framework_cxx/gtest/src/Framework_tests.cc b/libs/framework_cxx/gtest/src/Framework_tests.cc
index 7afd9a1..5bf8cdb 100644
--- a/libs/framework_cxx/gtest/src/Framework_tests.cc
+++ b/libs/framework_cxx/gtest/src/Framework_tests.cc
@@ -46,7 +46,7 @@ TEST_F(FrameworkTest, CreateDestroy) {
 
 class EmbeddedActivator : public celix::IBundleActivator {
 public:
-    EmbeddedActivator(std::shared_ptr<celix::IBundleContext>) {
+    EmbeddedActivator(std::shared_ptr<celix::BundleContext>) {
         startCount++;
     }
 
@@ -65,7 +65,7 @@ TEST_F(FrameworkTest, InstallBundle) {
     EmbeddedActivator::startCount = 0;
     EmbeddedActivator::stopCount = 0;
 
-    auto actFactory = [](std::shared_ptr<celix::IBundleContext> ctx) -> celix::IBundleActivator* {
+    auto actFactory = [](std::shared_ptr<celix::BundleContext> ctx) -> celix::IBundleActivator* {
         return new EmbeddedActivator{std::move(ctx)};
     };
     long bndId1 = framework().installBundle("embedded", actFactory);
@@ -102,7 +102,7 @@ TEST_F(FrameworkTest, StaticBundleTest) {
     };
 
     int count = 0;
-    auto factory = [&](std::shared_ptr<celix::IBundleContext>) -> celix::IBundleActivator * {
+    auto factory = [&](std::shared_ptr<celix::BundleContext>) -> celix::IBundleActivator * {
         count++;
         return new EmbeddedActivator{};
     };
diff --git a/libs/framework_cxx/include/celix/IBundleContext.h b/libs/framework_cxx/include/celix/BundleContext.h
similarity index 65%
rename from libs/framework_cxx/include/celix/IBundleContext.h
rename to libs/framework_cxx/include/celix/BundleContext.h
index 553372a..296b5c0 100644
--- a/libs/framework_cxx/include/celix/IBundleContext.h
+++ b/libs/framework_cxx/include/celix/BundleContext.h
@@ -17,19 +17,26 @@
  *under the License.
  */
 
-#ifndef CXX_CELIX_IBUNDLECONTEXT_H
-#define CXX_CELIX_IBUNDLECONTEXT_H
+#ifndef CXX_CELIX_BUNDLECONTEXT_H
+#define CXX_CELIX_BUNDLECONTEXT_H
 
+
+#include "celix/Framework.h"
 #include "celix/IBundle.h"
 
 namespace celix {
 
-    //TODO rename and drop I, because it not a complete interface (templates)
-    class IBundleContext {
+    class BundleContext {
     public:
-        virtual ~IBundleContext() = default;
+        explicit BundleContext(std::shared_ptr<celix::IBundle>);
+        ~BundleContext();
+
+        BundleContext(celix::BundleContext &&) = delete;
+        BundleContext(const celix::BundleContext &) = delete;
+        BundleContext& operator=(celix::BundleContext &&) = delete;
+        BundleContext& operator=(const celix::BundleContext &) = delete;
 
-        virtual std::shared_ptr<celix::IBundle> bundle() const noexcept = 0;
+        std::shared_ptr<celix::IBundle> bundle() const;
 
         template<typename I>
         celix::ServiceRegistration registerService(I &svc, celix::Properties props = {}) {
@@ -48,12 +55,38 @@ namespace celix {
 
         //TODO register C services
 
-        virtual bool useBundle(long bndId, std::function<void(const celix::IBundle &bnd)> use) const noexcept = 0;
-        virtual int useBundles(std::function<void(const celix::IBundle &bnd)> use, bool includeFrameworkBundle = true) const noexcept = 0;
+        bool useBundle(long bndId, std::function<void(const celix::IBundle &bnd)> use) const {
+            return bundle()->framework().useBundle(bndId, std::move(use));
+        }
+
+        int useBundles(std::function<void(const celix::IBundle &bnd)> use, bool includeFrameworkBundle = true) const {
+            return bundle()->framework().useBundles(std::move(use), includeFrameworkBundle);
+        }
+
+        bool stopBundle(long bndId) {
+            return bundle()->framework().stopBundle(bndId);
+        }
+
+        bool startBundle(long bndId) {
+            return bundle()->framework().startBundle(bndId);
+        }
+
+        //TODO install / uninstall bundles, trackb undles
+
+        template<typename I>
+        bool useServiceWithId(long svcId, std::function<void(I& svc)> use) const {
+            return registry().useServiceWithId<I>(svcId, use, bundle());
+        }
+
+        template<typename I>
+        bool useServiceWithId(long svcId, std::function<void(I& svc, const celix::Properties &props)> use) const {
+            return registry().useServiceWithId<I>(svcId, use, bundle());
+        }
 
-        virtual bool stopBundle(long bndId) noexcept = 0;
-        virtual bool startBundle(long bndId) noexcept = 0;
-        //TODO install / uninstall bundles
+        template<typename I>
+        bool useServiceWithId(long svcId, std::function<void(I& svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> use) const {
+            return registry().useServiceWithId<I>(svcId, use, bundle());
+        }
 
         template<typename I>
         bool useService(std::function<void(I &svc)> use, const std::string &filter = "") const noexcept {
@@ -71,6 +104,21 @@ namespace celix {
         }
 
         template<typename F>
+        bool useFunctionServiceWithId(const std::string &functionName, long svcId, std::function<void(F &function)> use) const {
+            return registry().useFunctionServiceWithId<F>(functionName, svcId, use, bundle());
+        }
+
+        template<typename F>
+        bool useFunctionServiceWithId(const std::string &functionName, long svcId, std::function<void(F &function, const celix::Properties&)> use) const {
+            return registry().useFunctionServiceWithId<F>(functionName, svcId, use, bundle());
+        }
+
+        template<typename F>
+        bool useFunctionServiceWithId(const std::string &functionName, long svcId, std::function<void(F &function, const celix::Properties&, const celix::IResourceBundle&)> use) const {
+            return registry().useFunctionServiceWithId<F>(functionName, svcId, use, bundle());
+        }
+
+        template<typename F>
         bool useFunctionService(const std::string &functionName, std::function<void(F &function)> use, const std::string &filter = "") const noexcept {
             return registry().useFunctionService<F>(functionName, std::move(use), filter, bundle());
         }
@@ -134,9 +182,13 @@ namespace celix {
         //TODO track c trackers
 
 
-        virtual celix::ServiceRegistry& registry() const noexcept = 0;
-        virtual celix::ServiceRegistry& cRegistry() const noexcept = 0;
+        celix::ServiceRegistry& registry() const;
+        celix::ServiceRegistry& cRegistry() const;
+    private:
+
+        class Impl;
+        std::unique_ptr<Impl> pimpl;
     };
 }
 
-#endif //CXX_CELIX_IBUNDLECONTEXT_H
+#endif //CXX_CELIX_BUNDLECONTEXT_H
diff --git a/libs/framework_cxx/include/celix/Framework.h b/libs/framework_cxx/include/celix/Framework.h
index a2d9b13..27718f8 100644
--- a/libs/framework_cxx/include/celix/Framework.h
+++ b/libs/framework_cxx/include/celix/Framework.h
@@ -24,23 +24,24 @@
 
 #include "celix/Constants.h"
 #include "celix/ServiceRegistry.h"
-#include "celix/IBundleContext.h"
-#include "celix/IBundle.h"
 #include "celix/IBundleActivator.h"
+#include "celix/IBundle.h"
 
 namespace celix {
 
+    class BundleContext; //forward declaration
+
     //TODO resources. resolved from bundle specific symbols which is linked zip file to the library
     void registerStaticBundle(
             std::string symbolicName,
-            std::function<celix::IBundleActivator*(std::shared_ptr<celix::IBundleContext>)> bundleActivatorFactory = {},
+            std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> bundleActivatorFactory = {},
             celix::Properties manifest = {});
 
     template<typename T>
     void registerStaticBundle(
             std::string symbolicName,
             celix::Properties manifest = {}) {
-        auto actFactory = [](std::shared_ptr<celix::IBundleContext> ctx) {
+        auto actFactory = [](std::shared_ptr<celix::BundleContext> ctx) {
             return new T{std::move(ctx)};
         };
         celix::registerStaticBundle(std::move(symbolicName), actFactory, std::move(manifest));
@@ -58,13 +59,13 @@ namespace celix {
 
         template<typename T>
         long installBundle(std::string name, celix::Properties manifest = {}, bool autoStart = true) {
-            auto actFactory = [](std::shared_ptr<celix::IBundleContext> ctx) {
+            auto actFactory = [](std::shared_ptr<celix::BundleContext> ctx) {
                 return new T{std::move(ctx)};
             };
             return installBundle(name, std::move(actFactory), manifest, autoStart);
         }
 
-        long installBundle(std::string name, std::function<celix::IBundleActivator*(std::shared_ptr<celix::IBundleContext>)> actFactory, celix::Properties manifest = {}, bool autoStart = true);
+        long installBundle(std::string name, std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory, celix::Properties manifest = {}, bool autoStart = true);
 
 
         //long installBundle(const std::string &path);
@@ -75,6 +76,8 @@ namespace celix {
         bool useBundle(long bndId, std::function<void(const celix::IBundle &bnd)> use) const;
         int useBundles(std::function<void(const celix::IBundle &bnd)> use, bool includeFrameworkBundle = false) const;
 
+        //TODO trackBundles
+
         //long bundleIdForName(const std::string &bndName) const;
         std::vector<long> listBundles(bool includeFrameworkBundle = false) const;
 
diff --git a/libs/framework_cxx/include/celix/IBundleActivator.h b/libs/framework_cxx/include/celix/IBundleActivator.h
index a3ccd92..d2b05ec 100644
--- a/libs/framework_cxx/include/celix/IBundleActivator.h
+++ b/libs/framework_cxx/include/celix/IBundleActivator.h
@@ -20,10 +20,6 @@
 #ifndef CXX_CELIX_IBUNDLEACTIVATOR_H
 #define CXX_CELIX_IBUNDLEACTIVATOR_H
 
-#include <memory>
-
-#include "IBundleContext.h"
-
 namespace celix {
     /**
      * The BundleActivator.
diff --git a/libs/framework_cxx/include/celix/api.h b/libs/framework_cxx/include/celix/api.h
index 63b19d4..fa0a8b9 100644
--- a/libs/framework_cxx/include/celix/api.h
+++ b/libs/framework_cxx/include/celix/api.h
@@ -23,7 +23,9 @@
 #include "celix/Constants.h"
 #include "celix/Filter.h"
 #include "celix/ServiceRegistry.h"
-#include "celix/Framework.h"
 #include "celix/IBundleActivator.h"
+#include "celix/Framework.h"
+#include "celix/BundleContext.h"
+
 
 #endif //CXX_CELIX_API_H
diff --git a/libs/framework/include/celix/IServiceFactory.h b/libs/framework_cxx/src/Bundle.cc
similarity index 59%
rename from libs/framework/include/celix/IServiceFactory.h
rename to libs/framework_cxx/src/Bundle.cc
index 8ac8a11..6f167f7 100644
--- a/libs/framework/include/celix/IServiceFactory.h
+++ b/libs/framework_cxx/src/Bundle.cc
@@ -17,24 +17,21 @@
  *under the License.
  */
 
-#ifndef CXX_CELIX_ISERVICEFACTORY_H
-#define CXX_CELIX_ISERVICEFACTORY_H
+#include <string>
 
-#include "celix/Bundle.h"
+#include "Bundle.h"
 
-namespace celix {
+bool celix::Bundle::has(const std::string &) const noexcept { return false; } //TODO
 
-    template<typename I>
-    class IServiceFactory {
-    public:
-        using type = I;
+bool celix::Bundle::isDir(const std::string &) const noexcept { return false; } //TODO
 
-        virtual ~IServiceFactory() = default;
-
-        virtual I* getService(const celix::Bundle &bundle, const celix::Properties &properties) = 0;
-        virtual void ungetService(const celix::Bundle& bundle, const celix::Properties &properties) = 0;
-    };
+bool celix::Bundle::isFile(const std::string &) const noexcept { return false; } //TODO
 
+std::vector <std::string> celix::Bundle::readDir(const std::string &) const noexcept { //TODO
+    return std::vector < std::string > {};
 }
 
-#endif //CXX_CELIX_ISERVICEFACTORY_H
+const std::string& celix::Bundle::root() const noexcept { //TODO
+    static std::string empty{};
+    return empty;
+}
\ No newline at end of file
diff --git a/libs/framework_cxx/src/Bundle.h b/libs/framework_cxx/src/Bundle.h
new file mode 100644
index 0000000..2ee1af6
--- /dev/null
+++ b/libs/framework_cxx/src/Bundle.h
@@ -0,0 +1,85 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CXX_CELIX_BUNDLE_H
+#define CXX_CELIX_BUNDLE_H
+
+#include "celix/Constants.h"
+#include "celix/IBundle.h"
+#include "celix/BundleContext.h"
+
+namespace celix {
+    class Bundle : public celix::IBundle {
+    public:
+        Bundle(long _bndId, celix::Framework *_fw, celix::Properties _manifest) :
+                bndId{_bndId}, fw{_fw}, bndManifest{std::move(_manifest)} {
+            bndState.store(BundleState::INSTALLED, std::memory_order_release);
+        }
+
+        //resource part
+        bool has(const std::string &) const noexcept override;
+        bool isDir(const std::string &) const noexcept override;
+        bool isFile(const std::string &) const noexcept override;
+        std::vector <std::string> readDir(const std::string &) const noexcept override;
+        const std::string &root() const noexcept override;
+
+        //bundle part
+        bool isFrameworkBundle() const noexcept override { return false; }
+
+        void *handle() const noexcept override { return nullptr; } //TODO
+
+        long id() const noexcept override { return bndId; }
+
+        const std::string &name() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_NAME); }
+
+        const std::string &symbolicName() const noexcept override {
+            return bndManifest.at(celix::MANIFEST_BUNDLE_SYMBOLIC_NAME);
+        }
+
+        const std::string &group() const noexcept override {
+            return bndManifest.at(celix::MANIFEST_BUNDLE_SYMBOLIC_NAME);
+        }
+
+        const std::string &version() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_VERSION); }
+
+        const celix::Properties &manifest() const noexcept override { return bndManifest; }
+
+        bool isValid() const noexcept override { return bndId >= 0; }
+
+        celix::Framework &framework() const noexcept override { return *fw; }
+
+        celix::BundleState state() const noexcept override {
+            return bndState.load(std::memory_order_acquire);
+        }
+
+        void setState(celix::BundleState state) {
+            bndState.store(state, std::memory_order_release);
+        }
+
+    private:
+        const long bndId;
+        celix::Framework *const fw;
+        const celix::Properties bndManifest;
+        std::weak_ptr <celix::BundleContext> context;
+
+        std::atomic <BundleState> bndState;
+    };
+}
+
+#endif //CXX_CELIX_BUNDLE_H
diff --git a/libs/framework_cxx/src/BundleContext.cc b/libs/framework_cxx/src/BundleContext.cc
new file mode 100644
index 0000000..1d5a0a7
--- /dev/null
+++ b/libs/framework_cxx/src/BundleContext.cc
@@ -0,0 +1,56 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "celix/BundleContext.h"
+
+#include <celix/IBundle.h>
+
+namespace celix {
+    class BundleContext::Impl {
+    public:
+        Impl(std::shared_ptr<celix::IBundle> _bnd) :
+            bnd{std::move(_bnd)},
+            reg{&bnd->framework().registry(celix::CXX_LANG)},
+            cReg(&bnd->framework().registry(celix::C_LANG)){}
+
+        const std::shared_ptr<celix::IBundle> bnd;
+        celix::ServiceRegistry * const reg; //TODO make weak_ptr
+        celix::ServiceRegistry * const cReg; //TODO make weak_ptr
+
+    };
+}
+
+celix::BundleContext::BundleContext(std::shared_ptr<celix::IBundle> bnd) {
+    pimpl = std::unique_ptr<celix::BundleContext::Impl>{new celix::BundleContext::Impl{std::move(bnd)}};
+}
+
+celix::BundleContext::~BundleContext() = default;
+
+std::shared_ptr<celix::IBundle> celix::BundleContext::bundle() const {
+    return pimpl->bnd;
+}
+
+celix::ServiceRegistry& celix::BundleContext::registry() const {
+    return *pimpl->reg;
+}
+
+celix::ServiceRegistry& celix::BundleContext::cRegistry() const {
+    return *pimpl->cReg;
+}
+
diff --git a/libs/framework_cxx/src/BundleController.h b/libs/framework_cxx/src/BundleController.h
new file mode 100644
index 0000000..3f4e1b7
--- /dev/null
+++ b/libs/framework_cxx/src/BundleController.h
@@ -0,0 +1,73 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CXX_CELIX_BUNDLECONTROLLER_H
+#define CXX_CELIX_BUNDLECONTROLLER_H
+
+#include <glog/logging.h>
+
+#include "celix/IBundle.h"
+#include "celix/BundleContext.h"
+#include "Bundle.h"
+
+namespace celix {
+    class BundleController {
+    public:
+        BundleController(
+                std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> _actFactory,
+                std::shared_ptr<celix::Bundle> _bnd,
+                std::shared_ptr<celix::BundleContext> _ctx) :
+                actFactory{std::move(_actFactory)}, bnd{std::move(_bnd)}, ctx{std::move(_ctx)} {}
+
+        //specific part
+        bool transitionTo(BundleState desired) {
+            bool success = false;
+            std::lock_guard<std::mutex> lck{mutex};
+            const BundleState state = bnd->state();
+            if (state == desired) {
+                //nop
+                success = true;
+            } else if (state == BundleState::INSTALLED && desired == BundleState::ACTIVE) {
+                act = std::unique_ptr<celix::IBundleActivator>{actFactory(ctx)};
+                bnd->setState(BundleState::ACTIVE);
+                success = true;
+            } else if (state == BundleState::ACTIVE && desired == BundleState::INSTALLED ) {
+                act = nullptr;
+                bnd->setState(BundleState::INSTALLED);
+                success = true;
+            } else {
+                //LOG(ERROR) << "Unexpected desired state " << desired << " from state " << bndState << std::endl;
+                LOG(ERROR) << "Unexpected desired/form state combination " << std::endl;
+            }
+            return success;
+        }
+
+        std::shared_ptr<celix::Bundle> bundle() const { return bnd; }
+        std::shared_ptr<celix::BundleContext> context() const { return ctx; }
+    private:
+        const std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory;
+        const std::shared_ptr<celix::Bundle> bnd;
+        const std::shared_ptr<celix::BundleContext> ctx;
+
+        mutable std::mutex mutex{};
+        std::unique_ptr<celix::IBundleActivator> act{nullptr};
+    };
+}
+
+#endif //CXX_CELIX_BUNDLECONTROLLER_H
diff --git a/libs/framework_cxx/src/BundleImpl.h b/libs/framework_cxx/src/BundleImpl.h
deleted file mode 100644
index dd2c53f..0000000
--- a/libs/framework_cxx/src/BundleImpl.h
+++ /dev/null
@@ -1,161 +0,0 @@
-/**
- *Licensed to the Apache Software Foundation (ASF) under one
- *or more contributor license agreements.  See the NOTICE file
- *distributed with this work for additional information
- *regarding copyright ownership.  The ASF licenses this file
- *to you under the Apache License, Version 2.0 (the
- *"License"); you may not use this file except in compliance
- *with the License.  You may obtain a copy of the License at
- *
- *  http://www.apache.org/licenses/LICENSE-2.0
- *
- *Unless required by applicable law or agreed to in writing,
- *software distributed under the License is distributed on an
- *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- *specific language governing permissions and limitations
- *under the License.
- */
-
-#ifndef CXX_CELIX_IMPL_BUNDLE_H
-#define CXX_CELIX_IMPL_BUNDLE_H
-
-#include <glog/logging.h>
-
-#include "celix/IBundle.h"
-#include "celix/IBundleContext.h"
-
-namespace celix {
-namespace impl {
-
-        class BundleContext : public celix::IBundleContext {
-        public:
-            BundleContext(std::shared_ptr<celix::IBundle> _bnd) : bnd{std::move(_bnd)},
-                reg{&bnd->framework().registry(celix::CXX_LANG)},
-                cReg(&bnd->framework().registry(celix::C_LANG)){}
-
-            virtual ~BundleContext() = default;
-
-            std::shared_ptr<celix::IBundle> bundle() const noexcept override {
-                return bnd;
-            }
-
-            bool useBundle(long bndId, std::function<void(const celix::IBundle &bnd)> use) const noexcept override {
-                return bnd->framework().useBundle(bndId, std::move(use));
-            }
-
-            int useBundles(std::function<void(const celix::IBundle &bnd)> use, bool includeFrameworkBundle = true) const noexcept override {
-                return bnd->framework().useBundles(std::move(use), includeFrameworkBundle);
-            }
-
-            bool stopBundle(long bndId) noexcept override {
-                return bnd->framework().stopBundle(bndId);
-            }
-
-            bool startBundle(long bndId) noexcept override {
-                return bnd->framework().startBundle(bndId);
-            }
-
-        private:
-            celix::ServiceRegistry& registry() const noexcept override { return *reg; }
-            celix::ServiceRegistry& cRegistry() const noexcept override { return *cReg; }
-
-            const std::shared_ptr<celix::IBundle> bnd;
-            celix::ServiceRegistry * const reg; //TODO make weak_ptr
-            celix::ServiceRegistry * const cReg; //TODO make weak_ptr
-        };
-
-
-        class Bundle : public celix::IBundle {
-        public:
-            Bundle(long _bndId, celix::Framework *_fw, celix::Properties _manifest) :
-            bndId{_bndId}, fw{_fw}, bndManifest{std::move(_manifest)} {
-                bndState.store(BundleState::INSTALLED, std::memory_order_release);
-            }
-
-            //resource part
-            bool has(const std::string&) const noexcept override { return false; } //TODO
-            bool isDir(const std::string&) const noexcept override { return false; } //TODO
-            bool isFile(const std::string&) const noexcept override { return false; } //TODO
-            std::vector<std::string> readDir(const std::string&) const noexcept override { return std::vector<std::string>{};} //TODO
-            const std::string& root() const noexcept override { //TODO
-                static std::string empty{};
-                return empty;
-            }
-
-            //bundle part
-            bool isFrameworkBundle() const noexcept override { return false; }
-
-            void* handle() const noexcept override { return nullptr; } //TODO
-
-            long id() const noexcept override { return bndId; }
-            const std::string& name() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_NAME); }
-            const std::string& symbolicName() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_SYMBOLIC_NAME); }
-            const std::string& group() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_SYMBOLIC_NAME); }
-            const std::string& version() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_VERSION); }
-            const celix::Properties& manifest() const noexcept  override { return bndManifest;}
-            bool isValid() const noexcept override { return bndId >= 0; }
-            celix::Framework& framework() const noexcept override { return *fw; }
-
-            celix::BundleState state() const noexcept override {
-                return bndState.load(std::memory_order_acquire);
-            }
-
-            void setState(celix::BundleState state) {
-                bndState.store(state, std::memory_order_release);
-            }
-
-        private:
-            const long bndId;
-            celix::Framework * const fw;
-            const celix::Properties bndManifest;
-            std::weak_ptr<celix::IBundleContext> context;
-
-            std::atomic<BundleState> bndState;
-    };
-
-    class BundleController {
-    public:
-        BundleController(
-                std::function<celix::IBundleActivator*(std::shared_ptr<celix::IBundleContext>)> _actFactory,
-                std::shared_ptr<celix::impl::Bundle> _bnd,
-                std::shared_ptr<celix::impl::BundleContext> _ctx) :
-                actFactory{std::move(_actFactory)}, bnd{std::move(_bnd)}, ctx{std::move(_ctx)} {}
-
-        //specific part
-        bool transitionTo(BundleState desired) {
-            bool success = false;
-            std::lock_guard<std::mutex> lck{mutex};
-            const BundleState state = bnd->state();
-            if (state == desired) {
-                //nop
-                success = true;
-            } else if (state == BundleState::INSTALLED && desired == BundleState::ACTIVE) {
-                act = std::unique_ptr<celix::IBundleActivator>{actFactory(ctx)};
-                bnd->setState(BundleState::ACTIVE);
-                success = true;
-            } else if (state == BundleState::ACTIVE && desired == BundleState::INSTALLED ) {
-                act = nullptr;
-                bnd->setState(BundleState::INSTALLED);
-                success = true;
-            } else {
-                //LOG(ERROR) << "Unexpected desired state " << desired << " from state " << bndState << std::endl;
-                LOG(ERROR) << "Unexpected desired/form state combination " << std::endl;
-            }
-            return success;
-        }
-
-        std::shared_ptr<celix::impl::Bundle> bundle() const { return bnd; }
-        std::shared_ptr<celix::impl::BundleContext> context() const { return ctx; }
-    private:
-        const std::function<celix::IBundleActivator*(std::shared_ptr<celix::IBundleContext>)> actFactory;
-        const std::shared_ptr<celix::impl::Bundle> bnd;
-        const std::shared_ptr<celix::impl::BundleContext> ctx;
-
-        mutable std::mutex mutex{};
-        std::unique_ptr<celix::IBundleActivator> act{nullptr};
-    };
-}
-};
-
-#endif //CXX_CELIX_IMPL_BUNDLE_H
diff --git a/libs/framework_cxx/src/Framework.cc b/libs/framework_cxx/src/Framework.cc
index cb5b6ed..64fa7d5 100644
--- a/libs/framework_cxx/src/Framework.cc
+++ b/libs/framework_cxx/src/Framework.cc
@@ -32,12 +32,12 @@
 
 #include "celix/Framework.h"
 
-#include "BundleImpl.h"
+#include "BundleController.h"
 
 struct StaticBundleEntry {
     const std::string symbolicName;
     const celix::Properties manifest;
-    const std::function<celix::IBundleActivator*(std::shared_ptr<celix::IBundleContext>)> activatorFactory;
+    const std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> activatorFactory;
 };
 
 static struct {
@@ -72,7 +72,7 @@ public:
         return result;
     }
 
-    long installBundle(std::string symbolicName, std::function<celix::IBundleActivator*(std::shared_ptr<celix::IBundleContext>)> actFactory, celix::Properties manifest, bool autoStart) {
+    long installBundle(std::string symbolicName, std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory, celix::Properties manifest, bool autoStart) {
         //TODO if activator is nullptr -> use empty activator
         //TODO on separate thread ?? specific bundle resolve thread ??
         long bndId = -1L;
@@ -81,7 +81,7 @@ public:
             return bndId;
         }
 
-        std::shared_ptr<celix::impl::BundleController> bndController{nullptr};
+        std::shared_ptr<celix::BundleController> bndController{nullptr};
         {
             manifest[celix::MANIFEST_BUNDLE_SYMBOLIC_NAME] = symbolicName;
             if (manifest.find(celix::MANIFEST_BUNDLE_NAME) == manifest.end()) {
@@ -96,9 +96,9 @@ public:
 
             std::lock_guard<std::mutex> lck{bundles.mutex};
             bndId = bundles.nextBundleId++;
-            auto bnd = std::shared_ptr<celix::impl::Bundle>{new celix::impl::Bundle{bndId, this->fw, std::move(manifest)}};
-            auto ctx = std::shared_ptr<celix::impl::BundleContext>{new celix::impl::BundleContext{bnd}};
-            bndController = std::shared_ptr<celix::impl::BundleController>{new celix::impl::BundleController{std::move(actFactory), bnd, ctx}};
+            auto bnd = std::shared_ptr<celix::Bundle>{new celix::Bundle{bndId, this->fw, std::move(manifest)}};
+            auto ctx = std::shared_ptr<celix::BundleContext>{new celix::BundleContext{bnd}};
+            bndController = std::shared_ptr<celix::BundleController>{new celix::BundleController{std::move(actFactory), bnd, ctx}};
             bundles.entries.emplace(std::piecewise_construct,
                                      std::forward_as_tuple(bndId),
                                      std::forward_as_tuple(bndController));
@@ -137,7 +137,7 @@ public:
 
     bool uninstallBundle(long bndId) {
         bool uninstalled = false;
-        std::shared_ptr<celix::impl::BundleController> removed{nullptr};
+        std::shared_ptr<celix::BundleController> removed{nullptr};
         {
             std::lock_guard<std::mutex> lck{bundles.mutex};
             auto it = bundles.entries.find(bndId);
@@ -163,7 +163,7 @@ public:
 
     bool transitionBundleTo(long bndId, BundleState desired) {
         bool successful = false;
-        std::shared_ptr<celix::impl::BundleController> match{nullptr};
+        std::shared_ptr<celix::BundleController> match{nullptr};
         {
             std::lock_guard<std::mutex> lck{bundles.mutex};
             auto it = bundles.entries.find(bndId);
@@ -184,7 +184,7 @@ public:
             use(*this);
             called = true;
         } else {
-            std::shared_ptr<celix::impl::BundleController> match = nullptr;
+            std::shared_ptr<celix::BundleController> match = nullptr;
             {
                 std::lock_guard<std::mutex> lck{bundles.mutex};
                 auto it = bundles.entries.find(bndId);
@@ -203,7 +203,7 @@ public:
     }
 
     int useBundles(std::function<void(const celix::IBundle &bnd)> use, bool includeFramework) const {
-        std::map<long, std::shared_ptr<celix::impl::BundleController>> useBundles{};
+        std::map<long, std::shared_ptr<celix::BundleController>> useBundles{};
         {
             std::lock_guard<std::mutex> lck{bundles.mutex};
             for (const auto &it : bundles.entries) {
@@ -319,7 +319,7 @@ private:
 
 
     struct {
-        std::unordered_map<long, std::shared_ptr<celix::impl::BundleController>> entries{};
+        std::unordered_map<long, std::shared_ptr<celix::BundleController>> entries{};
         long nextBundleId = 2;
         mutable std::mutex mutex{};
     } bundles{};
@@ -345,7 +345,7 @@ celix::Framework::Framework(Framework &&rhs) = default;
 celix::Framework& celix::Framework::operator=(Framework&& rhs) = default;
 
 
-long celix::Framework::installBundle(std::string name, std::function<celix::IBundleActivator*(std::shared_ptr<celix::IBundleContext>)> actFactory, celix::Properties manifest, bool autoStart) {
+long celix::Framework::installBundle(std::string name, std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory, celix::Properties manifest, bool autoStart) {
     return pimpl->installBundle(std::move(name), actFactory, std::move(manifest), autoStart);
 }
 
@@ -373,7 +373,7 @@ bool celix::Framework::waitForShutdown() const { return pimpl->waitForShutdown()
 
 void celix::registerStaticBundle(
         std::string symbolicName,
-        std::function<celix::IBundleActivator*(std::shared_ptr<celix::IBundleContext>)> bundleActivatorFactory,
+        std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> bundleActivatorFactory,
         celix::Properties manifest) {
     std::lock_guard<std::mutex> lck{staticRegistry.mutex};
     for (auto fw : staticRegistry.frameworks) {
diff --git a/libs/registry/gtest/CMakeLists.txt b/libs/registry/gtest/CMakeLists.txt
index 80f0159..4f3076e 100644
--- a/libs/registry/gtest/CMakeLists.txt
+++ b/libs/registry/gtest/CMakeLists.txt
@@ -22,6 +22,7 @@ set(SOURCES
         src/Registry_tests.cc
         src/Filter_tests.cc
         src/ServiceTracking_tests.cc
+        src/RegistryConcurrency_tests.cc
 )
 add_executable(celix_registry_tests ${SOURCES})
 target_link_libraries(celix_registry_tests PRIVATE gtest glog::glog celix::registry)
diff --git a/libs/registry/gtest/src/RegistryConcurrency_tests.cc b/libs/registry/gtest/src/RegistryConcurrency_tests.cc
index f7e86d3..b460bf3 100644
--- a/libs/registry/gtest/src/RegistryConcurrency_tests.cc
+++ b/libs/registry/gtest/src/RegistryConcurrency_tests.cc
@@ -17,19 +17,100 @@
  *under the License.
  */
 
+
+#include <thread>
+
 #include "gtest/gtest.h"
 
 #include "celix/ServiceRegistry.h"
 #include "celix/Constants.h"
 
-class RegistryConcurrentcyTest : public ::testing::Test {
+class RegistryConcurrencyTest : public ::testing::Test {
 public:
-    RegistryConcurrentcyTest() {}
-    ~RegistryConcurrentcyTest(){}
+    RegistryConcurrencyTest() {}
+
+    ~RegistryConcurrencyTest() {}
+
+    celix::ServiceRegistry &registry() { return reg; }
 
-    celix::ServiceRegistry& registry() { return reg; }
 private:
     celix::ServiceRegistry reg{"C++"};
+};
+
+
+TEST_F(RegistryConcurrencyTest, ServiceRegistrationTest) {
+    struct calc {
+        int (*calc)(int);
+    };
+
+    calc svc{};
+    svc.calc = [](int a) {
+        return a * 42;
+    };
+
+    auto svcReg = registry().registerService(svc);
+    EXPECT_GE(svcReg.serviceId(), 0);
+
+    struct sync {
+        std::mutex mutex{};
+        std::condition_variable sync{};
+        bool inUseCall{false};
+        bool readyToExitUseCall{false};
+        bool unregister{false};
+        int result{0};
+    };
+    struct sync callInfo{};
+
+    auto use = [&callInfo](calc &svc) {
+        std::cout << "setting isUseCall to true and syncing on readyToExitUseCall" << std::endl;
+        std::unique_lock<std::mutex> lock(callInfo.mutex);
+        callInfo.inUseCall = true;
+        callInfo.sync.notify_all();
+        callInfo.sync.wait(lock, [&callInfo]{return callInfo.readyToExitUseCall;});
+        lock.unlock();
+
+        std::cout << "Calling calc " << std::endl;
+        int tmp = svc.calc(2);
+        callInfo.result = tmp;
+    };
+
+    auto call = [&] {
+        bool called = registry().useServiceWithId<calc>(svcReg.serviceId(), use);
+        EXPECT_TRUE(called);
+        EXPECT_EQ(84, callInfo.result);
+    };
+    std::thread useThread{call};
+
+
+    std::thread unregisterThread{[&]{
+        std::cout << "syncing to wait if use function is called ..." << std::endl;
+        std::unique_lock<std::mutex> lock(callInfo.mutex);
+        callInfo.sync.wait(lock, [&]{return callInfo.inUseCall;});
+        lock.unlock();
+        std::cout << "trying to unregister ..." << std::endl;
+        svcReg.unregister();
+        std::cout << "done unregistering" << std::endl;
+    }};
+
+
+    //sleep 100 milli to give unregister a change to sink in
+    std::cout << "before sleep" << std::endl;
+    std::this_thread::sleep_for(std::chrono::milliseconds(100));
+    std::cout << "after sleep" << std::endl;
+
+
+    std::cout << "setting readyToExitUseCall and notify" << std::endl;
+    std::unique_lock<std::mutex> lock(callInfo.mutex);
+    callInfo.readyToExitUseCall = true;
+    lock.unlock();
+    callInfo.sync.notify_all();
+
+    useThread.join();
+    std::cout << "use thread joined" << std::endl;
+    unregisterThread.join();
+    std::cout << "unregister thread joined" << std::endl;
+};
+
 
 class ICalc {
 public:
@@ -44,17 +125,18 @@ public:
     double calc() override {
         double val = 1.0;
         std::lock_guard<std::mutex> lck{mutex};
-        for (auto *calc : childern) {
+        for (auto *calc : childs) {
             val *= calc->calc();
         }
         return val;
     }
 private:
-    std::mutex mutex{}
-    std::vector<ICalc*> childern{};
+    std::mutex mutex{};
+    std::vector<ICalc*> childs{};
 };
 
 class LeafCalc : public ICalc {
+
 public:
     virtual ~LeafCalc() = default;
 
@@ -65,8 +147,7 @@ private:
     double const seed = std::rand() / 100.0;
 };
 
-
-TEST_F(RegistryConcurrentcyTest, ServiceRegistrationTest) {
+TEST_F(RegistryConcurrencyTest, ManyThreadsTest) {
 //TODO start many thread and cals using the tiers of other calcs eventually leading ot leafs and try to break the registry.
 //tier 1 : NodeCalc
 //tier 2 : NodeCalc
diff --git a/libs/registry/include/celix/IResourceBundle.h b/libs/registry/include/celix/IResourceBundle.h
index 6352736..97c64de 100644
--- a/libs/registry/include/celix/IResourceBundle.h
+++ b/libs/registry/include/celix/IResourceBundle.h
@@ -20,6 +20,8 @@
 #ifndef CXX_CELIX_IRESOURCEBUNDLE_H
 #define CXX_CELIX_IRESOURCEBUNDLE_H
 
+#include <string>
+
 namespace celix {
 
     class IResourceBundle {
diff --git a/libs/registry/include/celix/ServiceRegistry.h b/libs/registry/include/celix/ServiceRegistry.h
index 710b218..ae7aeb2 100644
--- a/libs/registry/include/celix/ServiceRegistry.h
+++ b/libs/registry/include/celix/ServiceRegistry.h
@@ -227,6 +227,27 @@ namespace celix {
         }
 
         template<typename I>
+        bool useServiceWithId(long svcId, std::function<void(I& svc)> use, std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::serviceName<I>();
+            std::string filter = std::string{"("} + celix::SERVICE_ID + "=" + std::to_string(svcId) + ")";
+            return useService<I>(svcName, use, nullptr, nullptr, filter, std::move(requester));
+        }
+
+        template<typename I>
+        bool useServiceWithId(long svcId, std::function<void(I& svc, const celix::Properties &props)> use, std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::serviceName<I>();
+            std::string filter = std::string{"("} + celix::SERVICE_ID + "=" + std::to_string(svcId) + ")";
+            return useService<I>(svcName, nullptr, use, nullptr, filter, std::move(requester));
+        }
+
+        template<typename I>
+        bool useServiceWithId(long svcId, std::function<void(I& svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> use, std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::serviceName<I>();
+            std::string filter = std::string{"("} + celix::SERVICE_ID + "=" + std::to_string(svcId) + ")";
+            return useService<I>(svcName, nullptr, nullptr, use, filter, std::move(requester));
+        }
+
+        template<typename I>
         bool useService(std::function<void(I& svc)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
             auto svcName = celix::serviceName<I>();
             return useService<I>(svcName, use, nullptr, nullptr, filter, std::move(requester));
@@ -245,19 +266,40 @@ namespace celix {
         }
 
         template<typename F>
-        int useFunctionService(const std::string &functionName, std::function<void(F &function)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+        bool useFunctionServiceWithId(const std::string &functionName, long svcId, std::function<void(F &function)> use, std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::functionServiceName<F>(functionName);
+            std::string filter = std::string{"("} + celix::SERVICE_ID + "=" + std::to_string(svcId) + ")";
+            return useService<F>(svcName, use, nullptr, nullptr, filter, std::move(requester));
+        }
+
+        template<typename F>
+        bool useFunctionServiceWithId(const std::string &functionName, long svcId, std::function<void(F &function, const celix::Properties&)> use, std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::functionServiceName<F>(functionName);
+            std::string filter = std::string{"("} + celix::SERVICE_ID + "=" + std::to_string(svcId) + ")";
+            return useService<F>(svcName, nullptr, use, nullptr, filter, std::move(requester));
+        }
+
+        template<typename F>
+        bool useFunctionServiceWithId(const std::string &functionName, long svcId, std::function<void(F &function, const celix::Properties&, const celix::IResourceBundle&)> use, std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::functionServiceName<F>(functionName);
+            std::string filter = std::string{"("} + celix::SERVICE_ID + "=" + std::to_string(svcId) + ")";
+            return useService<F>(svcName, nullptr, nullptr, use, filter, std::move(requester));
+        }
+
+        template<typename F>
+        bool useFunctionService(const std::string &functionName, std::function<void(F &function)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
             auto svcName = celix::functionServiceName<F>(functionName);
             return useService<F>(svcName, use, nullptr, nullptr, filter, std::move(requester));
         }
 
         template<typename F>
-        int useFunctionService(const std::string &functionName, std::function<void(F &function, const celix::Properties&)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+        bool useFunctionService(const std::string &functionName, std::function<void(F &function, const celix::Properties&)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
             auto svcName = celix::functionServiceName<F>(functionName);
             return useService<F>(svcName, nullptr, use, nullptr, filter, std::move(requester));
         }
 
         template<typename F>
-        int useFunctionService(const std::string &functionName, std::function<void(F &function, const celix::Properties&, const celix::IResourceBundle&)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+        bool useFunctionService(const std::string &functionName, std::function<void(F &function, const celix::Properties&, const celix::IResourceBundle&)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
             auto svcName = celix::functionServiceName<F>(functionName);
             return useService<F>(svcName, nullptr, nullptr, use, filter, std::move(requester));
         }


[celix] 18/22: CELIX-438: Disabling cpputest based tests, so that the cpputest dep can be removed and the coverage only shows the cxx implementation coverage

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 9deecd86d9c79728536360911219cdcd5ca4b0b7
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Mon Jan 7 16:44:42 2019 +0100

    CELIX-438: Disabling cpputest based tests, so that the cpputest dep can be removed and the coverage only shows the cxx implementation coverage
---
 .travis.yml                                                     | 4 ----
 bundles/pubsub/CMakeLists.txt                                   | 7 ++++---
 bundles/remote_services/remote_service_admin_dfi/CMakeLists.txt | 2 +-
 bundles/remote_services/topology_manager/CMakeLists.txt         | 3 ++-
 libs/dfi/CMakeLists.txt                                         | 3 ++-
 libs/framework/CMakeLists.txt                                   | 6 +++---
 libs/utils/CMakeLists.txt                                       | 3 ++-
 7 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 3c0f470..843e946 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -44,10 +44,6 @@ before_install:
   - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update && brew install lcov libffi zeromq czmq glog cpputest jansson && brew link --force libffi; fi
 
 before_script:
-    - wget https://github.com/cpputest/cpputest/releases/download/v3.8/cpputest-3.8.tar.gz -O /tmp/cpputest.tar.gz
-    - tar -xzvf /tmp/cpputest.tar.gz -C /tmp
-    - if [ "$CC" = "clang" ]; then export CXX="clang++"; fi && cd /tmp/cpputest-* && ./configure --prefix=/usr/local && make && sudo make install && cd -
-    - cd /tmp/cpputest-* && ./configure --prefix=/usr/local && make && sudo make install && cd -
     - mkdir build install
     - export BUILD_OPTIONS=" \
         -DBUILD_RSA_REMOTE_SERVICE_ADMIN_DFI=ON \
diff --git a/bundles/pubsub/CMakeLists.txt b/bundles/pubsub/CMakeLists.txt
index e3db995..ee3ad8b 100644
--- a/bundles/pubsub/CMakeLists.txt
+++ b/bundles/pubsub/CMakeLists.txt
@@ -36,9 +36,10 @@ if (PUBSUB)
 
 	add_subdirectory(examples)
 
-	if (ENABLE_TESTING)
-		option(BUILD_PUBSUB_TESTS "Enable Tests for PUBSUB" OFF)
-	endif()
+	#if (ENABLE_TESTING)
+	#	option(BUILD_PUBSUB_TESTS "Enable Tests for PUBSUB" OFF)
+	#endif()
+	set(BUILD_PUBSUB_TESTS OFF) #disabling all cpputest based tests
 	if (ENABLE_TESTING AND BUILD_PUBSUB_TESTS AND BUILD_PUBSUB_PSA_ZMQ)
 		add_subdirectory(test)
 	endif()
diff --git a/bundles/remote_services/remote_service_admin_dfi/CMakeLists.txt b/bundles/remote_services/remote_service_admin_dfi/CMakeLists.txt
index 480768b..99b9bfd 100644
--- a/bundles/remote_services/remote_service_admin_dfi/CMakeLists.txt
+++ b/bundles/remote_services/remote_service_admin_dfi/CMakeLists.txt
@@ -46,7 +46,7 @@ if (RSA_REMOTE_SERVICE_ADMIN_DFI)
             ${CURL_LIBRARIES} ${JANSSON_LIBRARIES})
 
     if (ENABLE_TESTING)
-        add_subdirectory(test)
+        #add_subdirectory(test) disabling all cpputest based tests
     endif()
 
 
diff --git a/bundles/remote_services/topology_manager/CMakeLists.txt b/bundles/remote_services/topology_manager/CMakeLists.txt
index 8a4661d..9ee218f 100644
--- a/bundles/remote_services/topology_manager/CMakeLists.txt
+++ b/bundles/remote_services/topology_manager/CMakeLists.txt
@@ -32,7 +32,8 @@ if (RSA_TOPOLOGY_MANAGER)
     target_link_libraries(rsa_topology_manager PRIVATE Celix::log_helper Celix::rsa_spi)
 
 
-    if (ENABLE_TESTING)
+    set(RSA_TESTS OFF) #disabling all cpputest based tests
+    if (ENABLE_TESTING AND RSA_TESTS)
         find_package(CppUTest REQUIRED)
 	    find_package(Jansson REQUIRED)
  
diff --git a/libs/dfi/CMakeLists.txt b/libs/dfi/CMakeLists.txt
index 4451ff7..b738730 100644
--- a/libs/dfi/CMakeLists.txt
+++ b/libs/dfi/CMakeLists.txt
@@ -50,7 +50,8 @@ install(DIRECTORY include/ DESTINATION include/celix/dfi COMPONENT dfi)
 #Alias setup to match external usage
 add_library(Celix::dfi ALIAS dfi)
 
-if (ENABLE_TESTING)
+set(DFI_TESTS OFF) #disabling all cpputest based test
+if (ENABLE_TESTING AND DFI_TESTS)
     find_package(CppUTest REQUIRED)
         
     include_directories(${CPPUTEST_INCLUDE_DIR})
diff --git a/libs/framework/CMakeLists.txt b/libs/framework/CMakeLists.txt
index 812b4e6..d5a48d8 100644
--- a/libs/framework/CMakeLists.txt
+++ b/libs/framework/CMakeLists.txt
@@ -66,13 +66,13 @@ install(DIRECTORY include/ DESTINATION include/celix COMPONENT framework)
 add_library(Celix::framework ALIAS framework)
 
 
-if (ENABLE_TESTING)
+#celix_subproject(FRAMEWORK_TESTS "Option to build the framework tests" "OFF" DEPS)
+set(FRAMEWORK_TESTS OFF) #disabling all cpputest based test
+if (ENABLE_TESTING AND FRAMEWORK_TESTS)
     find_package(CppUTest REQUIRED)
     include_directories(${CPPUTEST_INCLUDE_DIR})
     add_subdirectory(tst)
 endif()
-
-celix_subproject(FRAMEWORK_TESTS "Option to build the framework tests" "OFF" DEPS)
 if (ENABLE_TESTING AND FRAMEWORK_TESTS)
     find_package(CppUTest REQUIRED)
 
diff --git a/libs/utils/CMakeLists.txt b/libs/utils/CMakeLists.txt
index e0afe41..3a695e9 100644
--- a/libs/utils/CMakeLists.txt
+++ b/libs/utils/CMakeLists.txt
@@ -69,7 +69,8 @@ install(DIRECTORY include/ DESTINATION include/celix COMPONENT framework
 add_library(Celix::utils ALIAS utils)
 
 
-celix_subproject(UTILS-TESTS "Option to build the utilities library tests" "OFF")
+#celix_subproject(UTILS-TESTS "Option to build the utilities library tests" "OFF")
+set(UTILS-TEST OFF) #disabling all cpputest based test
 if (ENABLE_TESTING AND UTILS-TESTS)
     #find_package(CppUTest REQUIRED)
 


[celix] 01/22: CELIX-438: Separates ServiceRegistry & Framework

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit e27350fa503355d43d8ca5a18734932dea26d49c
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Sun Dec 30 15:44:25 2018 +0100

    CELIX-438: Separates ServiceRegistry & Framework
---
 .travis.yml                                        |  35 +-
 CMakeLists.txt                                     |   2 -
 .../service/private/include/framework_patch.h      |   2 +-
 .../private/test/rsa_client_server_tests.cpp       |   2 +-
 bundles/shell/CMakeLists.txt                       |   2 +
 {libs => bundles/shell/cxx_shell}/CMakeLists.txt   |  28 +-
 .../shell/cxx_shell/gtest}/CMakeLists.txt          |  24 +-
 .../cxx_shell/gtest/src/main.cc}                   |  26 +-
 .../cxx_shell/include/celix/IShell.h}              |  27 +-
 .../shell/cxx_shell/include/celix/IShellCommand.h  |  48 ++
 bundles/shell/cxx_shell/src/ShellActivator.cc      | 145 +++++
 bundles/shell/shell_bonjour/CMakeLists.txt         |   2 +-
 cmake/celix_project/AddGTest.cmake                 |   2 +-
 libs/CMakeLists.txt                                |   3 +
 libs/framework/CMakeLists.txt                      |   4 +-
 libs/framework/include/celix/Constants.h           |  21 +-
 libs/framework/src/{bundle.c => BundleImpl.c}      |   0
 libs/framework/src/bundle_context.c.orig           |   2 +-
 libs/{ => framework_cxx}/CMakeLists.txt            |  23 +-
 libs/{ => framework_cxx/gtest}/CMakeLists.txt      |  25 +-
 libs/framework_cxx/gtest/src/Framework_tests.cc    | 127 ++++
 .../framework_cxx/gtest/src/main.cc                |  26 +-
 libs/framework_cxx/include/celix/Framework.h       |  88 +++
 libs/framework_cxx/include/celix/IBundle.h         |  63 ++
 .../framework_cxx/include/celix/IBundleActivator.h |  29 +-
 libs/framework_cxx/include/celix/IBundleContext.h  | 137 ++++
 .../framework_cxx/include/celix/api.h              |  26 +-
 libs/framework_cxx/src/BundleImpl.h                | 178 +++++
 libs/framework_cxx/src/Framework.cc                | 350 ++++++++++
 libs/{ => registry}/CMakeLists.txt                 |  23 +-
 libs/{ => registry/gtest}/CMakeLists.txt           |  27 +-
 libs/registry/gtest/src/Filter_tests.cc            | 207 ++++++
 .../gtest/src/RegistryConcurrency_tests.cc         |  75 +++
 libs/registry/gtest/src/Registry_tests.cc          | 269 ++++++++
 libs/registry/gtest/src/ServiceTracking_tests.cc   | 275 ++++++++
 .../registry/gtest/src/main.cc                     |  26 +-
 libs/registry/include/celix/Constants.h            |  43 ++
 libs/registry/include/celix/Filter.h               |  73 +++
 libs/registry/include/celix/IResourceBundle.h      |  57 ++
 .../registry/include/celix/IServiceFactory.h       |  32 +-
 libs/registry/include/celix/Properties.h           |  60 ++
 libs/registry/include/celix/ServiceRegistry.h      | 509 +++++++++++++++
 libs/registry/include/celix/Utils.h                | 102 +++
 libs/registry/src/Filter.cc                        | 464 +++++++++++++
 libs/registry/src/ServiceRegistry.cc               | 716 +++++++++++++++++++++
 45 files changed, 4166 insertions(+), 239 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index ff86367..e3536d2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,9 +1,3 @@
-
-sudo: required
-group: deprecated-2017Q2
-
-language: c
-
 env:
     global:
         - COVERITY_SCAN_BUILD_COMMAND="make"
@@ -19,17 +13,17 @@ env:
 matrix:
     include:
        - os: linux
-         dist: trusty
+         dist: xenial
          compiler: gcc
        - os: linux
-         dist: trusty
+         dist: xenial
          compiler: clang
        - os: osx
          osx_image: xcode7.3
          compiler: clang
          env: MACOSX_DEPLOYMENT_TARGET=10.11
        - os: linux
-         dist: trusty
+         dist: xenial
          compiler: gcc
          env: SANITIZE=1
 
@@ -41,27 +35,12 @@ matrix:
 #services: docker
 
 before_install:
-  - if [ "$TRAVIS_OS_NAME" = "linux" ] &&  [ -z "$ANDROID" ]; then sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y && sudo apt-get -qq update && sudo apt-get install -y uuid-dev libxml2-dev lcov libffi-dev gcc-4.8 g++-4.8; fi
-  - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update && brew install lcov libffi zeromq czmq && brew link --force libffi; fi
+  - if [ "$TRAVIS_OS_NAME" = "linux" ] sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
+  - if [ "$TRAVIS_OS_NAME" = "linux" ] sudo apt-get update -qq
+  - if [ "$TRAVIS_OS_NAME" = "linux" ] sudo apt-get install -qq uuid-dev libxml2-dev lcov libffi-dev libgoogle-glog-dev libczmq-dev libcpputest-dev libjansson-dev
+  - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update && brew install lcov libffi zeromq czmq glog cpputest jansson && brew link --force libffi; fi
 
 before_script:
-    - wget https://github.com/cpputest/cpputest/releases/download/v3.8/cpputest-3.8.tar.gz -O /tmp/cpputest.tar.gz
-    - tar -xzvf /tmp/cpputest.tar.gz -C /tmp
-    - if [ "$CC" = "clang" ]; then export CXX="clang++"; fi && cd /tmp/cpputest-* && ./configure --prefix=/usr/local && make && sudo make install && cd -
-    - cd /tmp/cpputest-* && ./configure --prefix=/usr/local && make && sudo make install && cd -
-    - wget https://github.com/zeromq/libzmq/releases/download/v4.2.1/zeromq-4.2.1.tar.gz -O /tmp/zeromq.tar.gz
-    - tar -xzvf /tmp/zeromq.tar.gz -C /tmp && cd /tmp/zeromq-* && mkdir build && cd build
-    - if [ "$TRAVIS_OS_NAME" = "linux" ] &&  [ -z "$ANDROID" ]; then cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DENABLE_CURVE=ON .. && make && sudo make install; fi 
-    - cd $TRAVIS_BUILD_DIR
-    - wget https://github.com/zeromq/czmq/releases/download/v4.0.2/czmq-4.0.2.tar.gz -O /tmp/czmq.tar.gz
-    - tar -xzvf /tmp/czmq.tar.gz -C /tmp && cd /tmp/czmq-* && mkdir build && cd build
-    - if [ "$TRAVIS_OS_NAME" = "linux" ] &&  [ -z "$ANDROID" ]; then cmake -DCMAKE_INSTALL_PREFIX=/usr/local .. && make && sudo make install; fi
-    - cd $TRAVIS_BUILD_DIR
-    - git clone https://github.com/akheron/jansson.git jansson-build
-    - cd jansson-build && git checkout 2.7
-    - cmake -DJANSSON_BUILD_SHARED_LIBS=ON -DCMAKE_INSTALL_PREFIX=/usr/local . && make
-    - sudo make install
-    - cd -
     - mkdir build install
     - export BUILD_OPTIONS=" \
         -DBUILD_RSA_REMOTE_SERVICE_ADMIN_DFI=ON \
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 50bd853..9ba636e 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -56,8 +56,6 @@ option(ENABLE_GTESTING "Enables unit testing using GTest" ON)
 
 if (ENABLE_TESTING)
 	enable_testing()
-endif ()
-if (ENABLE_TESTING AND ENABLE_GTESTING)
     include(cmake/celix_project/AddGTest.cmake)
 endif ()
 
diff --git a/bundles/config_admin/service/private/include/framework_patch.h b/bundles/config_admin/service/private/include/framework_patch.h
index 98194e1..8017f51 100644
--- a/bundles/config_admin/service/private/include/framework_patch.h
+++ b/bundles/config_admin/service/private/include/framework_patch.h
@@ -31,7 +31,7 @@
 
 /* celix.framework.public */
 #include "celix_errno.h"
-#include "bundle.h"
+#include "BundleImpl.h"
 #include "service_reference.h"
 
 celix_status_t bundle_getBundleLocation(bundle_pt bundle, const char **location);
diff --git a/bundles/remote_services/remote_service_admin_shm/private/test/rsa_client_server_tests.cpp b/bundles/remote_services/remote_service_admin_shm/private/test/rsa_client_server_tests.cpp
index 13c6941..fd3dd03 100644
--- a/bundles/remote_services/remote_service_admin_shm/private/test/rsa_client_server_tests.cpp
+++ b/bundles/remote_services/remote_service_admin_shm/private/test/rsa_client_server_tests.cpp
@@ -35,7 +35,7 @@ extern "C" {
 	#include "framework.h"
 	#include "remote_service_admin.h"
 	#include "calculator_service.h"
-	#include "bundle.h"
+	#include "BundleImpl.h"
 
 	#define DISCOVERY_CFG_NAME      "apache_celix_rsa_discovery_shm"
 	#define RSA_HTTP_NAME           "apache_celix_remote_service_admin_shm"
diff --git a/bundles/shell/CMakeLists.txt b/bundles/shell/CMakeLists.txt
index ae2d39a..2fd81dc 100644
--- a/bundles/shell/CMakeLists.txt
+++ b/bundles/shell/CMakeLists.txt
@@ -19,3 +19,5 @@ add_subdirectory(shell)
 add_subdirectory(remote_shell)
 add_subdirectory(shell_bonjour)
 add_subdirectory(shell_tui)
+
+add_subdirectory(cxx_shell)
diff --git a/libs/CMakeLists.txt b/bundles/shell/cxx_shell/CMakeLists.txt
similarity index 56%
copy from libs/CMakeLists.txt
copy to bundles/shell/cxx_shell/CMakeLists.txt
index 5df35a2..070f05e 100644
--- a/libs/CMakeLists.txt
+++ b/bundles/shell/cxx_shell/CMakeLists.txt
@@ -15,17 +15,23 @@
 # specific language governing permissions and limitations
 # under the License.
 
-#utils, dfi and etcdlib are standalone
-#(e.g. no dependency on celix framework
-add_subdirectory(utils)
-add_subdirectory(dfi)
-add_subdirectory(etcdlib)
+find_package(glog REQUIRED)
 
-add_subdirectory(framework)
+#TODO rename to celix::shell && celix::shell_api
 
-#launcher
-add_subdirectory(launcher)
+add_library(shell_api_cxx INTERFACE)
+target_include_directories(shell_api INTERFACE
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
+    $<INSTALL_INTERFACE:include/celix/shell>
+)
 
-#add_subdirectory(event_admin)# event_admin is unstable
-add_subdirectory(dependency_manager)
-add_subdirectory(dependency_manager_cxx)
\ No newline at end of file
+add_library(celix_shell_cxx STATIC
+        src/ShellActivator.cc
+        include/celix/IShell.h)
+target_include_directories(celix_shell_cxx PRIVATE src)
+target_include_directories(celix_shell_cxx PUBLIC include)
+target_link_libraries(celix_shell_cxx PRIVATE glog::glog celix_framework_cxx)
+
+#if (ENABLE_TESTING)
+#    add_subdirectory(gtest)
+#endif ()
\ No newline at end of file
diff --git a/libs/CMakeLists.txt b/bundles/shell/cxx_shell/gtest/CMakeLists.txt
similarity index 66%
copy from libs/CMakeLists.txt
copy to bundles/shell/cxx_shell/gtest/CMakeLists.txt
index 5df35a2..b4a7204 100644
--- a/libs/CMakeLists.txt
+++ b/bundles/shell/cxx_shell/gtest/CMakeLists.txt
@@ -5,9 +5,9 @@
 # to you under the Apache License, Version 2.0 (the
 # "License"); you may not use this file except in compliance
 # with the License.  You may obtain a copy of the License at
-#
+# 
 #   http://www.apache.org/licenses/LICENSE-2.0
-#
+# 
 # Unless required by applicable law or agreed to in writing,
 # software distributed under the License is distributed on an
 # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -15,17 +15,11 @@
 # specific language governing permissions and limitations
 # under the License.
 
-#utils, dfi and etcdlib are standalone
-#(e.g. no dependency on celix framework
-add_subdirectory(utils)
-add_subdirectory(dfi)
-add_subdirectory(etcdlib)
+set(SOURCES
+        src/main.cc
+)
+add_executable(celix_shell_cxx_tests ${SOURCES})
+target_link_libraries(celix_shell_cxx_tests PRIVATE gtest celix_framework_cxx celix_shell_cxx)
 
-add_subdirectory(framework)
-
-#launcher
-add_subdirectory(launcher)
-
-#add_subdirectory(event_admin)# event_admin is unstable
-add_subdirectory(dependency_manager)
-add_subdirectory(dependency_manager_cxx)
\ No newline at end of file
+add_test(NAME celix_shell_cxx_tests COMMAND celix_shell_cxx_tests)
+SETUP_TARGET_FOR_COVERAGE(celix_shell_cxx_tests_cov celix_shell_cxx_tests ${CMAKE_BINARY_DIR}/coverage/celix_shell_cxx_tests/celix_shell_cxx_tests)
\ No newline at end of file
diff --git a/bundles/config_admin/service/private/include/framework_patch.h b/bundles/shell/cxx_shell/gtest/src/main.cc
similarity index 63%
copy from bundles/config_admin/service/private/include/framework_patch.h
copy to bundles/shell/cxx_shell/gtest/src/main.cc
index 98194e1..a76daa7 100644
--- a/bundles/config_admin/service/private/include/framework_patch.h
+++ b/bundles/shell/cxx_shell/gtest/src/main.cc
@@ -16,24 +16,18 @@
  *specific language governing permissions and limitations
  *under the License.
  */
-/*
- * framework_patch.h
- *
- *  \date       Aug 12, 2013
- *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright	Apache License, Version 2.0
- */
-
 
-#ifndef BUNDLE_PATCH_H_
-#define BUNDLE_PATCH_H_
+#include <gtest/gtest.h>
+#include <glog/logging.h>
 
+int main(int argc, char **argv) {
+    google::InitGoogleLogging(argv[0]);
+    google::LogToStderr();
 
-/* celix.framework.public */
-#include "celix_errno.h"
-#include "bundle.h"
-#include "service_reference.h"
+    ::testing::InitGoogleTest(&argc, argv);
+    int rc = RUN_ALL_TESTS();
 
-celix_status_t bundle_getBundleLocation(bundle_pt bundle, const char **location);
+    google::ShutdownGoogleLogging();
 
-#endif /* BUNDLE_PATCH_H_ */
+    return rc;
+}
\ No newline at end of file
diff --git a/bundles/config_admin/service/private/include/framework_patch.h b/bundles/shell/cxx_shell/include/celix/IShell.h
similarity index 64%
copy from bundles/config_admin/service/private/include/framework_patch.h
copy to bundles/shell/cxx_shell/include/celix/IShell.h
index 98194e1..9809ac5 100644
--- a/bundles/config_admin/service/private/include/framework_patch.h
+++ b/bundles/shell/cxx_shell/include/celix/IShell.h
@@ -16,24 +16,21 @@
  *specific language governing permissions and limitations
  *under the License.
  */
-/*
- * framework_patch.h
- *
- *  \date       Aug 12, 2013
- *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright	Apache License, Version 2.0
- */
 
+#ifndef CXX_CELIX_ISHELL_H
+#define CXX_CELIX_ISHELL_H
 
-#ifndef BUNDLE_PATCH_H_
-#define BUNDLE_PATCH_H_
+#include <iostream>
 
+namespace celix {
+    class IShell {
+    public:
+        static constexpr const char * const SERVICE_FQN = "celix::IShell [Version 1]";
 
-/* celix.framework.public */
-#include "celix_errno.h"
-#include "bundle.h"
-#include "service_reference.h"
+        virtual ~IShell() = default;
 
-celix_status_t bundle_getBundleLocation(bundle_pt bundle, const char **location);
+        virtual bool executeCommand(const std::string &commandLine, std::ostream &out, std::ostream &err) noexcept = 0;
+    };
+}
 
-#endif /* BUNDLE_PATCH_H_ */
+#endif //CXX_CELIX_ISHELL_H
diff --git a/bundles/shell/cxx_shell/include/celix/IShellCommand.h b/bundles/shell/cxx_shell/include/celix/IShellCommand.h
new file mode 100644
index 0000000..8a30133
--- /dev/null
+++ b/bundles/shell/cxx_shell/include/celix/IShellCommand.h
@@ -0,0 +1,48 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <string>
+#include <iostream>
+
+#ifndef CXX_CELIX_ISHELLCOMMAND_H
+#define CXX_CELIX_ISHELLCOMMAND_H
+
+namespace celix {
+
+    class IShellCommand {
+    public:
+        static constexpr const char * const SERVICE_FQN = "celix::IShellCommand [Version 1]";
+
+        static constexpr const char * const COMMAND_NAME = "name";
+        static constexpr const char * const COMMAND_USAGE = "usage";
+        static constexpr const char * const COMMAND_DESCRIPTION = "description";
+
+        virtual ~IShellCommand() = default;
+
+        virtual void executeCommand(const std::string &commandLine, std::ostream &out, std::ostream &err) noexcept = 0;
+    };
+
+    using ShellCommandFunction = std::function<void(const std::string &commandLine, std::ostream &out, std::ostream &err)>;
+    static constexpr const char * const SHELL_COMMAND_FUNCTION_SERVICE_FQN = "celix::ShellFunction [Version 1]";
+    static constexpr const char * const SHELL_COMMAND_FUNCTION_COMMAND_NAME = "name";
+    static constexpr const char * const SHELL_COMMAND_FUNCTION_COMMAND_USAGE = "usage";
+    static constexpr const char * const SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION = "description";
+}
+
+#endif //CXX_CELIX_ISHELLCOMMAND_H
diff --git a/bundles/shell/cxx_shell/src/ShellActivator.cc b/bundles/shell/cxx_shell/src/ShellActivator.cc
new file mode 100644
index 0000000..5fd4f1f
--- /dev/null
+++ b/bundles/shell/cxx_shell/src/ShellActivator.cc
@@ -0,0 +1,145 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "celix/api.h"
+#include "celix/IShellCommand.h"
+#include "celix/IShell.h"
+
+namespace {
+
+    class LbCommand : public celix::IShellCommand {
+    public:
+        LbCommand(std::shared_ptr<celix::IBundleContext> _ctx) : ctx{std::move(_ctx)} {}
+        void executeCommand(const std::string &/*command line*/, std::ostream &out, std::ostream &) noexcept override {
+            //TODO parse commandLine
+            out << "Bundles: " << std::endl;
+            ctx->useBundles([&out](const celix::IBundle &bnd) {
+                out << "|- " << bnd.id() << ": " << bnd.name() << std::endl;
+            }, true);
+        }
+    private:
+        std::shared_ptr<celix::IBundleContext> ctx;
+    };
+
+    celix::ServiceRegistration registerLb(std::shared_ptr<celix::IBundleContext> ctx) {
+        celix::Properties props{};
+        props[celix::IShellCommand::COMMAND_NAME] = "lb";
+        props[celix::IShellCommand::COMMAND_USAGE] = "list installed bundles";
+        props[celix::IShellCommand::COMMAND_DESCRIPTION] = "TODO";
+        return ctx->registerService(std::shared_ptr<celix::IShellCommand>{new LbCommand{ctx}}, std::move(props));
+    }
+
+    celix::ServiceRegistration registerHelp(std::shared_ptr<celix::IBundleContext> ctx) {
+
+        celix::ShellCommandFunction help = [ctx](const std::string &, std::ostream &out, std::ostream &) {
+
+            std::string hasCommandNameFilter = std::string{"("} + celix::IShellCommand::COMMAND_NAME + "=*)";
+            //TODO parse command line to see if details is requested instead of overview
+            std::vector<std::string> commands{};
+            ctx->useServices<celix::IShellCommand>([&](celix::IShellCommand&, const celix::Properties &props) {
+                commands.push_back(celix::getProperty(props, celix::IShellCommand::COMMAND_NAME, "!Error!"));
+            }, hasCommandNameFilter);
+
+            hasCommandNameFilter = std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=*)";
+
+            std::function<void(celix::ShellCommandFunction&, const celix::Properties&)> use = [&](celix::ShellCommandFunction&, const celix::Properties &props) {
+                commands.push_back(celix::getProperty(props, celix::IShellCommand::COMMAND_NAME, "!Error!"));
+            };
+            ctx->useFunctionServices(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, use, hasCommandNameFilter);
+
+            //TODO useCService with a shell command service struct
+
+            out << "Available commands: " << std::endl;
+            for (auto &name : commands) {
+                out << "|- " << name << std::endl;
+            }
+        };
+
+        celix::Properties props{};
+        props[celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME] = "help";
+        props[celix::SHELL_COMMAND_FUNCTION_COMMAND_USAGE] = "help [command name]";
+        props[celix::SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION] = "TODO";
+        return ctx->registerFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, std::move(help), std::move(props));
+    }
+
+    class Shell : public celix::IShell {
+    public:
+        Shell(std::shared_ptr<celix::IBundleContext> _ctx) : ctx{std::move(_ctx)} {
+            celix::ServiceTrackerOptions<celix::IShellCommand> opts1{};
+            opts1.updateWithProperties = [this](std::vector<std::tuple<celix::IShellCommand*,const celix::Properties*>> services) {
+                std::lock_guard<std::mutex> lck(commands.mutex);
+                commands.commands = std::move(services);
+            };
+            trk1 = ctx->trackServices(opts1);
+
+            celix::ServiceTrackerOptions<celix::ShellCommandFunction> opts2{};
+            opts2.updateWithProperties = [this](std::vector<std::tuple<celix::ShellCommandFunction*,const celix::Properties*>> services) {
+                std::lock_guard<std::mutex> lck(commands.mutex);
+                commands.commandFunctions = std::move(services);
+            };
+            trk2 = ctx->trackFunctionServices(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, opts2);
+        }
+
+        bool executeCommand(const std::string &commandLine, std::ostream &out, std::ostream &) noexcept override {
+            out << "TODO call command '" << commandLine << "'" << std::endl;
+            return false;
+        }
+    private:
+        std::shared_ptr<celix::IBundleContext> ctx;
+
+        celix::ServiceTracker trk1{};
+        celix::ServiceTracker trk2{};
+
+        struct {
+            mutable std::mutex mutex{};
+            std::vector<std::tuple<celix::IShellCommand*, const celix::Properties*>> commands;
+            std::vector<std::tuple<celix::ShellCommandFunction*, const celix::Properties*>> commandFunctions;
+        } commands{};
+    };
+
+    class ShellBundleActivator : public celix::IBundleActivator {
+    public:
+        bool start(std::shared_ptr<celix::IBundleContext> ctx) noexcept override {
+            //TODO ensure fixed framework thread that call bundle activators
+            registrations.push_back(registerLb(ctx));
+            registrations.push_back(registerHelp(ctx));
+
+            registrations.push_back(ctx->registerService(std::shared_ptr<celix::IShell>{new Shell{ctx}}));
+
+            return true;
+        }
+
+        bool stop(std::shared_ptr<celix::IBundleContext>) noexcept override {
+            registrations.clear();
+            return true;
+        }
+    private:
+        std::vector<celix::ServiceRegistration> registrations;
+    };
+}
+
+__attribute__((constructor))
+static void registerShellBundle() {
+    celix::StaticBundleOptions opts{};
+    opts.bundleActivatorFactory = [](){
+        return new ShellBundleActivator{};
+    };
+    opts.manifest[celix::MANIFEST_BUNDLE_VERSION] = "1.0.0";
+    celix::registerStaticBundle("celix::Shell", opts);
+}
\ No newline at end of file
diff --git a/bundles/shell/shell_bonjour/CMakeLists.txt b/bundles/shell/shell_bonjour/CMakeLists.txt
index 771ccdb..2f40c7e 100644
--- a/bundles/shell/shell_bonjour/CMakeLists.txt
+++ b/bundles/shell/shell_bonjour/CMakeLists.txt
@@ -33,7 +33,7 @@ if (SHELL_BONJOUR)
 		 	private/src/activator.c
 		 	private/src/bonjour_shell.c
 	)
-	add_library(Celix::bonjour_shell ALIAS bonjour_shell)
+	add_library(Celix::bonjour_shell ALIAS bonjour_shell ../cxx_shell/src/ShellActivator.cc)
 
 
 	target_include_directories(bonjour_shell PRIVATE
diff --git a/cmake/celix_project/AddGTest.cmake b/cmake/celix_project/AddGTest.cmake
index 2b91c54..a1753a8 100644
--- a/cmake/celix_project/AddGTest.cmake
+++ b/cmake/celix_project/AddGTest.cmake
@@ -19,7 +19,7 @@ include(ExternalProject)
 ExternalProject_Add(
         googletest_project
         GIT_REPOSITORY https://github.com/google/googletest.git
-        GIT_TAG master
+        GIT_TAG release-1.8.1
         PREFIX ${CMAKE_CURRENT_BINARY_DIR}/gtest
         INSTALL_COMMAND ""
 )
diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt
index 5df35a2..88d1928 100644
--- a/libs/CMakeLists.txt
+++ b/libs/CMakeLists.txt
@@ -23,6 +23,9 @@ add_subdirectory(etcdlib)
 
 add_subdirectory(framework)
 
+add_subdirectory(registry)
+add_subdirectory(framework_cxx)
+
 #launcher
 add_subdirectory(launcher)
 
diff --git a/libs/framework/CMakeLists.txt b/libs/framework/CMakeLists.txt
index 75aab2d..ecfc795 100644
--- a/libs/framework/CMakeLists.txt
+++ b/libs/framework/CMakeLists.txt
@@ -24,7 +24,7 @@ if(WIN32)
 endif(WIN32)
 
 set(SOURCES
-        src/attribute.c src/bundle.c src/bundle_archive.c src/bundle_cache.c
+        src/attribute.c src/BundleImpl.c src/bundle_archive.c src/bundle_cache.c
         src/bundle_context.c src/bundle_revision.c src/capability.c src/celix_errorcodes.c
         src/framework.c src/manifest.c src/ioapi.c
         src/manifest_parser.c src/miniunz.c src/module.c
@@ -148,7 +148,7 @@ if (ENABLE_TESTING AND FRAMEWORK_TESTS)
         private/mock/bundle_revision_mock.c
         private/mock/resolver_mock.c
         private/mock/version_mock.c
-            src/bundle.c
+            src/BundleImpl.c
         src/celix_errorcodes.c
         private/mock/celix_log_mock.c)
     target_link_libraries(bundle_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::utils pthread)
diff --git a/libs/framework/include/celix/Constants.h b/libs/framework/include/celix/Constants.h
index 6788b7e..adcb6a3 100644
--- a/libs/framework/include/celix/Constants.h
+++ b/libs/framework/include/celix/Constants.h
@@ -21,24 +21,19 @@
 #ifndef CXX_CELIX_CONSTANTS_H
 #define CXX_CELIX_CONSTANTS_H
 
-#include "celix_constants.h"
-
 namespace celix {
     class Constants {
     public:
-        static constexpr const char *const SERVICE_NAME = OSGI_FRAMEWORK_OBJECTCLASS;
-        static constexpr const char *const SERVICE_ID = OSGI_FRAMEWORK_SERVICE_ID;
-        static constexpr const char *const SERVICE_PID = OSGI_FRAMEWORK_SERVICE_PID;
-        static constexpr const char *const SERVICE_RANKING = OSGI_FRAMEWORK_SERVICE_RANKING;
+        //NOTE manually aligned with celix_constants.h
+        static constexpr const char *const SERVICE_NAME = "objectClass"; //TODO rename to service.name
+        static constexpr const char *const SERVICE_LANGUAGE = "service.version";
+        static constexpr const char *const SERVICE_ID = "service.id";
+        static constexpr const char *const SERVICE_RANKING = "service.ranking";
 
-        static constexpr const char *const SERVICE_VERSION = CELIX_FRAMEWORK_SERVICE_VERSION;
-        static constexpr const char *const SERVICE_LANGUAGE = CELIX_FRAMEWORK_SERVICE_LANGUAGE;
-        static constexpr const char *const SERVICE_C_LANG = CELIX_FRAMEWORK_SERVICE_C_LANGUAGE;
-        static constexpr const char *const SERVICE_CXX_LANG = CELIX_FRAMEWORK_SERVICE_CXX_LANGUAGE;
+        static constexpr const char *const SERVICE_C_LANG = "C";
+        static constexpr const char *const SERVICE_CXX_LANG = "C++";
 
-        static constexpr const char *const FRAMEWORK_STORAGE = OSGI_FRAMEWORK_FRAMEWORK_STORAGE;
-        static constexpr const char *const FRAMEWORK_CLEAN = OSGI_FRAMEWORK_FRAMEWORK_STORAGE_CLEAN_NAME;
-        static constexpr const char *const FRAMEWORK_UUID = OSGI_FRAMEWORK_FRAMEWORK_UUID;
+        static constexpr const char *const FRAMEWORK_UUID = "framework.uuid";
     };
 }
 
diff --git a/libs/framework/src/bundle.c b/libs/framework/src/BundleImpl.c
similarity index 100%
rename from libs/framework/src/bundle.c
rename to libs/framework/src/BundleImpl.c
diff --git a/libs/framework/src/bundle_context.c.orig b/libs/framework/src/bundle_context.c.orig
index 8d3a0cc..8866472 100644
--- a/libs/framework/src/bundle_context.c.orig
+++ b/libs/framework/src/bundle_context.c.orig
@@ -26,7 +26,7 @@
 #include "constants.h"
 #include "bundle_context_private.h"
 #include "framework_private.h"
-#include "bundle.h"
+#include "BundleImpl.h"
 #include "celix_bundle.h"
 #include "celix_log.h"
 #include "service_tracker.h"
diff --git a/libs/CMakeLists.txt b/libs/framework_cxx/CMakeLists.txt
similarity index 65%
copy from libs/CMakeLists.txt
copy to libs/framework_cxx/CMakeLists.txt
index 5df35a2..e5fbe8a 100644
--- a/libs/CMakeLists.txt
+++ b/libs/framework_cxx/CMakeLists.txt
@@ -15,17 +15,16 @@
 # specific language governing permissions and limitations
 # under the License.
 
-#utils, dfi and etcdlib are standalone
-#(e.g. no dependency on celix framework
-add_subdirectory(utils)
-add_subdirectory(dfi)
-add_subdirectory(etcdlib)
+find_package(glog REQUIRED)
 
-add_subdirectory(framework)
+#TODO rename to celix::framework
+add_library(celix_framework_cxx SHARED
+        src/Framework.cc
+)
+target_include_directories(celix_framework_cxx PRIVATE src)
+target_include_directories(celix_framework_cxx PUBLIC include)
+target_link_libraries(celix_framework_cxx PUBLIC celix::registry glog::glog) #TODO glog private and static lib
 
-#launcher
-add_subdirectory(launcher)
-
-#add_subdirectory(event_admin)# event_admin is unstable
-add_subdirectory(dependency_manager)
-add_subdirectory(dependency_manager_cxx)
\ No newline at end of file
+if (ENABLE_TESTING)
+    add_subdirectory(gtest)
+endif ()
\ No newline at end of file
diff --git a/libs/CMakeLists.txt b/libs/framework_cxx/gtest/CMakeLists.txt
similarity index 64%
copy from libs/CMakeLists.txt
copy to libs/framework_cxx/gtest/CMakeLists.txt
index 5df35a2..0f407cc 100644
--- a/libs/CMakeLists.txt
+++ b/libs/framework_cxx/gtest/CMakeLists.txt
@@ -5,9 +5,9 @@
 # to you under the Apache License, Version 2.0 (the
 # "License"); you may not use this file except in compliance
 # with the License.  You may obtain a copy of the License at
-#
+# 
 #   http://www.apache.org/licenses/LICENSE-2.0
-#
+# 
 # Unless required by applicable law or agreed to in writing,
 # software distributed under the License is distributed on an
 # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -15,17 +15,12 @@
 # specific language governing permissions and limitations
 # under the License.
 
-#utils, dfi and etcdlib are standalone
-#(e.g. no dependency on celix framework
-add_subdirectory(utils)
-add_subdirectory(dfi)
-add_subdirectory(etcdlib)
+set(SOURCES
+        src/main.cc
+        src/Framework_tests.cc
+)
+add_executable(celix_framework_cxx_tests ${SOURCES})
+target_link_libraries(celix_framework_cxx_tests PRIVATE gtest celix_framework_cxx)
 
-add_subdirectory(framework)
-
-#launcher
-add_subdirectory(launcher)
-
-#add_subdirectory(event_admin)# event_admin is unstable
-add_subdirectory(dependency_manager)
-add_subdirectory(dependency_manager_cxx)
\ No newline at end of file
+add_test(NAME celix_framework_cxx_tests COMMAND celix_framework_cxx_tests)
+SETUP_TARGET_FOR_COVERAGE(celix_framework_cxx_tests_cov celix_framework_cxx_tests ${CMAKE_BINARY_DIR}/coverage/framework/celix_framework_cxx_tests)
\ No newline at end of file
diff --git a/libs/framework_cxx/gtest/src/Framework_tests.cc b/libs/framework_cxx/gtest/src/Framework_tests.cc
new file mode 100644
index 0000000..34cad54
--- /dev/null
+++ b/libs/framework_cxx/gtest/src/Framework_tests.cc
@@ -0,0 +1,127 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "gtest/gtest.h"
+
+#include "celix/Framework.h"
+
+class FrameworkTest : public ::testing::Test {
+public:
+    FrameworkTest() {}
+    ~FrameworkTest(){}
+
+    celix::Framework& framework() { return fw; }
+private:
+    celix::Framework fw{};
+};
+
+
+TEST_F(FrameworkTest, CreateDestroy) {
+    //no bundles installed bundle (framework bundle)
+    EXPECT_EQ(1, framework().listBundles(true).size());
+    EXPECT_EQ(0, framework().listBundles(false).size());
+
+    bool isFramework = false;
+    framework().useBundle(0L, [&](const celix::IBundle &bnd) {
+       isFramework = bnd.isFrameworkBundle();
+    });
+    EXPECT_TRUE(isFramework);
+}
+
+TEST_F(FrameworkTest, InstallBundle) {
+
+    class EmbeddedActivator : public celix::IBundleActivator {
+    public:
+        virtual ~EmbeddedActivator() = default;
+
+        bool resolve(std::shared_ptr<celix::IBundleContext> ctx) noexcept override {
+            EXPECT_GE(ctx->bundle()->id(), 1);
+            resolveCalled = true;
+            return true;
+        }
+
+        bool start(std::shared_ptr<celix::IBundleContext>) noexcept override {
+            startCalled = true;
+            return true;
+        }
+
+        bool stop(std::shared_ptr<celix::IBundleContext>) noexcept override {
+            stopCalled = true;
+            return true;
+        }
+
+        bool resolveCalled = false;
+        bool startCalled = false;
+        bool stopCalled = false;
+    };
+
+    long bndId1 = framework().installBundle<EmbeddedActivator>("embedded");
+    EXPECT_GE(bndId1, 0);
+
+    std::shared_ptr<EmbeddedActivator> act{new EmbeddedActivator};
+    long bndId2 = framework().installBundle("embedded2", act);
+    EXPECT_GE(bndId2, 0);
+    EXPECT_NE(bndId1, bndId2);
+    EXPECT_TRUE(act->resolveCalled);
+    EXPECT_TRUE(act->startCalled);
+    EXPECT_FALSE(act->stopCalled);
+
+    framework().stopBundle(bndId2);
+    EXPECT_TRUE(act->stopCalled);
+
+    std::shared_ptr<EmbeddedActivator> act3{new EmbeddedActivator};
+    {
+        celix::Framework fw{};
+        fw.installBundle("embedded3", act3);
+        EXPECT_TRUE(act3->resolveCalled);
+        EXPECT_TRUE(act3->startCalled);
+        EXPECT_FALSE(act3->stopCalled);
+
+        //NOTE fw out of scope -> bundle stopped
+    }
+    EXPECT_TRUE(act3->stopCalled);
+}
+
+TEST_F(FrameworkTest, StaticBundleTest) {
+    class EmbeddedActivator : public celix::IBundleActivator {
+    public:
+        virtual ~EmbeddedActivator() = default;
+
+        bool start(std::shared_ptr<celix::IBundleContext>) noexcept override {
+            return true;
+        }
+    };
+
+    int count = 0;
+    auto factory = [&]() -> celix::IBundleActivator * {
+        count++;
+        return new EmbeddedActivator{};
+    };
+
+    EXPECT_EQ(0, framework().listBundles().size()); //no bundles installed;
+    celix::StaticBundleOptions opts;
+    opts.bundleActivatorFactory = std::move(factory);
+    celix::registerStaticBundle("static", opts);
+    EXPECT_EQ(1, framework().listBundles().size()); //static bundle instance installed
+    EXPECT_EQ(1, count);
+
+    celix::Framework fw{};
+    EXPECT_EQ(1, framework().listBundles().size()); //already registered static bundle instance installed.
+    EXPECT_EQ(2, count);
+}
\ No newline at end of file
diff --git a/bundles/config_admin/service/private/include/framework_patch.h b/libs/framework_cxx/gtest/src/main.cc
similarity index 63%
copy from bundles/config_admin/service/private/include/framework_patch.h
copy to libs/framework_cxx/gtest/src/main.cc
index 98194e1..a76daa7 100644
--- a/bundles/config_admin/service/private/include/framework_patch.h
+++ b/libs/framework_cxx/gtest/src/main.cc
@@ -16,24 +16,18 @@
  *specific language governing permissions and limitations
  *under the License.
  */
-/*
- * framework_patch.h
- *
- *  \date       Aug 12, 2013
- *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright	Apache License, Version 2.0
- */
-
 
-#ifndef BUNDLE_PATCH_H_
-#define BUNDLE_PATCH_H_
+#include <gtest/gtest.h>
+#include <glog/logging.h>
 
+int main(int argc, char **argv) {
+    google::InitGoogleLogging(argv[0]);
+    google::LogToStderr();
 
-/* celix.framework.public */
-#include "celix_errno.h"
-#include "bundle.h"
-#include "service_reference.h"
+    ::testing::InitGoogleTest(&argc, argv);
+    int rc = RUN_ALL_TESTS();
 
-celix_status_t bundle_getBundleLocation(bundle_pt bundle, const char **location);
+    google::ShutdownGoogleLogging();
 
-#endif /* BUNDLE_PATCH_H_ */
+    return rc;
+}
\ No newline at end of file
diff --git a/libs/framework_cxx/include/celix/Framework.h b/libs/framework_cxx/include/celix/Framework.h
new file mode 100644
index 0000000..60b6fca
--- /dev/null
+++ b/libs/framework_cxx/include/celix/Framework.h
@@ -0,0 +1,88 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CXX_CELIX_FRAMEWORK_H
+#define CXX_CELIX_FRAMEWORK_H
+
+#include <memory>
+
+#include "celix/Constants.h"
+#include "celix/ServiceRegistry.h"
+#include "celix/IBundleContext.h"
+#include "celix/IBundle.h"
+#include "celix/IBundleActivator.h"
+
+namespace celix {
+
+    struct StaticBundleOptions {
+        std::string name{};
+        std::string group{};
+        std::string version{};
+        celix::Properties manifest{};
+
+        std::function<celix::IBundleActivator*()> bundleActivatorFactory{};
+
+        //TODO resources. poiting to bundle specific symbols which is linked zip file
+        char * const resoucreZip = nullptr;
+        size_t resourceZipLength = 0;
+    };
+
+    void registerStaticBundle(std::string symbolicName, const StaticBundleOptions &opts);
+    //TODO useFrameworks with a callback with as argument a fw ref
+
+    class Framework {
+    public:
+        Framework();
+        ~Framework();
+        Framework(Framework &&rhs);
+        Framework& operator=(Framework&& rhs);
+
+        Framework(const Framework& rhs) = delete;
+        Framework& operator=(const Framework &rhs) = delete;
+
+
+        template<typename T>
+        long installBundle(std::string symbolicName, celix::Properties manifest = {}, bool autoStart = true) {
+            std::shared_ptr<celix::IBundleActivator> activator{new T{}};
+            return installBundle(std::move(symbolicName), std::move(activator), std::move(manifest), autoStart);
+        }
+
+        long installBundle(std::string symbolicName, std::shared_ptr<celix::IBundleActivator> activator, celix::Properties manifest = {}, bool autoStart = true);
+
+
+        //long installBundle(const std::string &path);
+        bool startBundle(long bndId);
+        bool stopBundle(long bndId);
+        bool uninstallBundle(long bndId);
+
+        bool useBundle(long bndId, std::function<void(const celix::IBundle &bnd)> use) const;
+        int useBundles(std::function<void(const celix::IBundle &bnd)> use, bool includeFrameworkBundle = false) const;
+
+        //long bundleIdForName(const std::string &bndName) const;
+        std::vector<long> listBundles(bool includeFrameworkBundle = false) const;
+
+        celix::ServiceRegistry& registry(const std::string &lang);
+    private:
+        class Impl;
+        std::unique_ptr<Impl> pimpl;
+    };
+
+};
+
+#endif //CXX_CELIX_FRAMEWORK_H
diff --git a/libs/framework_cxx/include/celix/IBundle.h b/libs/framework_cxx/include/celix/IBundle.h
new file mode 100644
index 0000000..a8d0de1
--- /dev/null
+++ b/libs/framework_cxx/include/celix/IBundle.h
@@ -0,0 +1,63 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CXX_CELIX_IBUNDLE_H
+#define CXX_CELIX_IBUNDLE_H
+
+#include "celix/IResourceBundle.h"
+#include "celix/Properties.h"
+
+namespace celix {
+
+    enum class BundleState {
+        INSTALLED,
+        RESOLVED,
+        ACTIVE,
+    };
+
+    class Framework; //forward declaration
+
+    class IBundle : public celix::IResourceBundle {
+    public:
+        virtual ~IBundle() = default;
+
+        virtual const std::string& name() const noexcept = 0;
+
+        virtual const std::string& symbolicName() const noexcept = 0;
+
+        virtual const std::string& group() const noexcept = 0;
+
+        virtual bool isFrameworkBundle() const noexcept  = 0;
+
+        virtual void* handle() const noexcept = 0;
+
+        virtual celix::BundleState state() const noexcept  = 0;
+
+        virtual const std::string& version() const noexcept = 0;
+
+        virtual const celix::Properties& manifest() const noexcept  = 0;
+
+        virtual bool isValid() const noexcept = 0;
+
+        virtual celix::Framework& framework() const noexcept = 0;
+    };
+
+}
+
+#endif //CXX_CELIX_IBUNDLE_H
diff --git a/bundles/config_admin/service/private/include/framework_patch.h b/libs/framework_cxx/include/celix/IBundleActivator.h
similarity index 58%
copy from bundles/config_admin/service/private/include/framework_patch.h
copy to libs/framework_cxx/include/celix/IBundleActivator.h
index 98194e1..1196e99 100644
--- a/bundles/config_admin/service/private/include/framework_patch.h
+++ b/libs/framework_cxx/include/celix/IBundleActivator.h
@@ -16,24 +16,23 @@
  *specific language governing permissions and limitations
  *under the License.
  */
-/*
- * framework_patch.h
- *
- *  \date       Aug 12, 2013
- *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright	Apache License, Version 2.0
- */
 
+#ifndef CXX_CELIX_IBUNDLEACTIVATOR_H
+#define CXX_CELIX_IBUNDLEACTIVATOR_H
 
-#ifndef BUNDLE_PATCH_H_
-#define BUNDLE_PATCH_H_
+#include <memory>
 
+#include "IBundleContext.h"
 
-/* celix.framework.public */
-#include "celix_errno.h"
-#include "bundle.h"
-#include "service_reference.h"
+namespace celix {
+    class IBundleActivator {
+    public:
+        virtual ~IBundleActivator() = default;
 
-celix_status_t bundle_getBundleLocation(bundle_pt bundle, const char **location);
+        virtual bool resolve(std::shared_ptr<celix::IBundleContext> /*ctx*/) noexcept { return true; };
+        virtual bool start(std::shared_ptr<celix::IBundleContext> ctx) noexcept = 0;
+        virtual bool stop(std::shared_ptr<celix::IBundleContext> /*ctx*/) noexcept { return true; }
+    };
+}
 
-#endif /* BUNDLE_PATCH_H_ */
+#endif //CXX_CELIX_IBUNDLEACTIVATOR_H
diff --git a/libs/framework_cxx/include/celix/IBundleContext.h b/libs/framework_cxx/include/celix/IBundleContext.h
new file mode 100644
index 0000000..e77623a
--- /dev/null
+++ b/libs/framework_cxx/include/celix/IBundleContext.h
@@ -0,0 +1,137 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CXX_CELIX_IBUNDLECONTEXT_H
+#define CXX_CELIX_IBUNDLECONTEXT_H
+
+#include "celix/IBundle.h"
+
+namespace celix {
+
+    //TODO rename and drop I, because it not a complete interface (templates)
+    class IBundleContext {
+    public:
+        virtual ~IBundleContext() = default;
+
+        virtual std::shared_ptr<celix::IBundle> bundle() const noexcept = 0;
+
+        template<typename I>
+        celix::ServiceRegistration registerService(I &svc, celix::Properties props = {}) {
+            return registry().registerService<I>(svc, std::move(props), bundle());
+        }
+
+        template<typename I>
+        celix::ServiceRegistration registerService(std::shared_ptr<I> svc, celix::Properties props = {}) {
+            return registry().registerService<I>(svc, std::move(props), bundle());
+        }
+
+        template<typename F>
+        celix::ServiceRegistration registerFunctionService(std::string functionName, F&& function, celix::Properties props = {}) {
+            return registry().registerFunctionService(std::move(functionName), std::forward<F>(function), std::move(props), bundle());
+        }
+
+        //TODO register C services
+
+        virtual bool useBundle(long bndId, std::function<void(const celix::IBundle &bnd)> use) const noexcept = 0;
+        virtual int useBundles(std::function<void(const celix::IBundle &bnd)> use, bool includeFrameworkBundle = true) const noexcept = 0;
+
+        template<typename I>
+        bool useService(std::function<void(I &svc)> use, const std::string &filter = "") const noexcept {
+            return registry().useService<I>(std::move(use), filter, bundle());
+        }
+
+        template<typename I>
+        bool useService(std::function<void(I &svc, const celix::Properties &props)> use, const std::string &filter = "") const noexcept {
+            return registry().useService<I>(std::move(use), filter, bundle());
+        }
+
+        template<typename I>
+        bool useService(std::function<void(I &svc, const celix::Properties &props, const celix::IResourceBundle &owner)> use, const std::string &filter = "") const noexcept {
+            return registry().useService<I>(std::move(use), filter, bundle());
+        }
+
+        template<typename F>
+        bool useFunctionService(const std::string &functionName, std::function<void(F &function)> use, const std::string &filter = "") const noexcept {
+            return registry().useFunctionService<F>(functionName, std::move(use), filter, bundle());
+        }
+
+        template<typename F>
+        bool useFunctionService(const std::string &functionName, std::function<void(F &function, const celix::Properties &props)> use, const std::string &filter = "") const noexcept {
+            return registry().useFunctionService<F>(functionName, std::move(use), filter, bundle());
+        }
+
+        template<typename F>
+        bool useFunctionService(const std::string &functionName, std::function<void(F &function, const celix::Properties &props, const celix::IResourceBundle &owner)> use, const std::string &filter = "") const noexcept {
+            return registry().useFunctionService<F>(functionName, std::move(use), filter, bundle());
+        }
+
+        template<typename I>
+        int useServices(std::function<void(I &svc)> use, const std::string &filter = "") const noexcept {
+            return registry().useServices<I>(std::move(use), filter, bundle());
+        }
+
+        template<typename I>
+        int useServices(std::function<void(I &svc, const celix::Properties &props)> use, const std::string &filter = "") const noexcept {
+            return registry().useServices<I>(std::move(use), filter, bundle());
+        }
+
+        template<typename I>
+        int useServices(std::function<void(I &svc, const celix::Properties &props, const celix::IResourceBundle &owner)> use, const std::string &filter = "") const noexcept {
+            return registry().useServices<I>(std::move(use), filter, bundle());
+        }
+
+        template<typename F>
+        int useFunctionServices(const std::string &functionName, std::function<void(F &function)> use, const std::string &filter = "") const noexcept {
+            return registry().useFunctionServices<F>(functionName, std::move(use), filter, bundle());
+        }
+
+        template<typename F>
+        int useFunctionServices(const std::string &functionName, std::function<void(F &function, const celix::Properties &props)> use, const std::string &filter = "") const noexcept {
+            return registry().useFunctionServices<F>(functionName, std::move(use), filter, bundle());
+        }
+
+        template<typename F>
+        int useFunctionServices(const std::string &functionName, std::function<void(F &function, const celix::Properties &props, const celix::IResourceBundle &owner)> use, const std::string &filter = "") const noexcept {
+            return registry().useFunctionServices<F>(functionName, std::move(use), filter, bundle());
+        }
+
+        //TODO use C services
+
+        template<typename I>
+        celix::ServiceTracker trackServices(celix::ServiceTrackerOptions<I> options = {}) {
+            return registry().trackServices<I>(std::move(options), bundle());
+        }
+
+        template<typename F>
+        celix::ServiceTracker trackFunctionServices(std::string functionName, celix::ServiceTrackerOptions<F> options = {}) {
+            return registry().trackFunctionServices<F>(functionName, std::move(options), bundle());
+        }
+
+        //TODO track C Services
+
+        //TODO track trackers
+
+        //TODO track c trackers
+    private:
+        virtual celix::ServiceRegistry& registry() const noexcept = 0;
+        virtual celix::ServiceRegistry& cRegistry() const noexcept = 0;
+    };
+}
+
+#endif //CXX_CELIX_IBUNDLECONTEXT_H
diff --git a/bundles/config_admin/service/private/include/framework_patch.h b/libs/framework_cxx/include/celix/api.h
similarity index 63%
copy from bundles/config_admin/service/private/include/framework_patch.h
copy to libs/framework_cxx/include/celix/api.h
index 98194e1..63b19d4 100644
--- a/bundles/config_admin/service/private/include/framework_patch.h
+++ b/libs/framework_cxx/include/celix/api.h
@@ -16,24 +16,14 @@
  *specific language governing permissions and limitations
  *under the License.
  */
-/*
- * framework_patch.h
- *
- *  \date       Aug 12, 2013
- *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright	Apache License, Version 2.0
- */
-
-
-#ifndef BUNDLE_PATCH_H_
-#define BUNDLE_PATCH_H_
-
 
-/* celix.framework.public */
-#include "celix_errno.h"
-#include "bundle.h"
-#include "service_reference.h"
+#ifndef CXX_CELIX_API_H
+#define CXX_CELIX_API_H
 
-celix_status_t bundle_getBundleLocation(bundle_pt bundle, const char **location);
+#include "celix/Constants.h"
+#include "celix/Filter.h"
+#include "celix/ServiceRegistry.h"
+#include "celix/Framework.h"
+#include "celix/IBundleActivator.h"
 
-#endif /* BUNDLE_PATCH_H_ */
+#endif //CXX_CELIX_API_H
diff --git a/libs/framework_cxx/src/BundleImpl.h b/libs/framework_cxx/src/BundleImpl.h
new file mode 100644
index 0000000..ab49636
--- /dev/null
+++ b/libs/framework_cxx/src/BundleImpl.h
@@ -0,0 +1,178 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CXX_CELIX_IMPL_BUNDLE_H
+#define CXX_CELIX_IMPL_BUNDLE_H
+
+#include <glog/logging.h>
+
+#include "celix/IBundle.h"
+#include "celix/IBundleContext.h"
+
+namespace celix {
+namespace impl {
+
+        class BundleContext : public celix::IBundleContext {
+        public:
+            BundleContext(std::shared_ptr<celix::IBundle> _bnd) : bnd{std::move(_bnd)},
+                reg{&bnd->framework().registry(celix::CXX_LANG)},
+                cReg(&bnd->framework().registry(celix::C_LANG)){}
+
+            virtual ~BundleContext() = default;
+
+            std::shared_ptr<celix::IBundle> bundle() const noexcept override {
+                return bnd;
+            }
+
+            bool useBundle(long bndId, std::function<void(const celix::IBundle &bnd)> use) const noexcept override {
+                return bnd->framework().useBundle(bndId, std::move(use));
+            }
+
+            int useBundles(std::function<void(const celix::IBundle &bnd)> use, bool includeFrameworkBundle = true) const noexcept override {
+                return bnd->framework().useBundles(std::move(use), includeFrameworkBundle);
+            }
+        private:
+            celix::ServiceRegistry& registry() const noexcept override { return *reg; }
+            celix::ServiceRegistry& cRegistry() const noexcept override { return *cReg; }
+
+            const std::shared_ptr<celix::IBundle> bnd;
+            const std::shared_ptr<celix::ServiceRegistry> reg;
+            const std::shared_ptr<celix::ServiceRegistry> cReg;
+        };
+
+
+        class Bundle : public celix::IBundle {
+        public:
+            Bundle(long _bndId, celix::Framework *_fw, celix::Properties _manifest, std::shared_ptr<celix::IBundleActivator> _activator) :
+            bndId{_bndId}, fw{_fw}, bndManifest{std::move(_manifest)}, activator{std::move(_activator)} {
+                bndState.store(BundleState::INSTALLED, std::memory_order_release);
+            }
+
+            //resource part
+            bool has(const std::string&) const noexcept override { return false; } //TODO
+            bool isDir(const std::string&) const noexcept override { return false; } //TODO
+            bool isFile(const std::string&) const noexcept override { return false; } //TODO
+            std::vector<std::string> readDir(const std::string&) const noexcept override { return std::vector<std::string>{};} //TODO
+            const std::string& root() const noexcept override { //TODO
+                static std::string empty{};
+                return empty;
+            }
+
+            //bundle part
+            bool isFrameworkBundle() const noexcept override { return false; }
+
+            void* handle() const noexcept override { return nullptr; } //TODO
+
+            long id() const noexcept override { return bndId; }
+            const std::string& name() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_NAME); }
+            const std::string& symbolicName() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_SYMBOLIC_NAME); }
+            const std::string& group() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_SYMBOLIC_NAME); }
+            const std::string& version() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_VERSION); }
+            const celix::Properties& manifest() const noexcept  override { return bndManifest;}
+            bool isValid() const noexcept override { return bndId >= 0; }
+            celix::Framework& framework() const noexcept override { return *fw; }
+
+            celix::BundleState state() const noexcept override {
+                return bndState.load(std::memory_order_acquire);
+            }
+
+            void setState(celix::BundleState state) {
+                bndState.store(state, std::memory_order_release);
+            }
+
+        private:
+            const long bndId;
+            celix::Framework * const fw;
+            const celix::Properties bndManifest;
+            const std::shared_ptr<celix::IBundleActivator> activator;
+            std::weak_ptr<celix::IBundleContext> context;
+
+            std::atomic<BundleState> bndState;
+    };
+
+    class BundleController {
+    public:
+        BundleController(
+                std::shared_ptr<celix::IBundleActivator> _act,
+                std::shared_ptr<celix::impl::Bundle> _bnd,
+                std::shared_ptr<celix::impl::BundleContext> _ctx) :
+                act{std::move(_act)}, bnd{std::move(_bnd)}, ctx{std::move(_ctx)} {}
+
+        //specific part
+        bool transitionTo(BundleState desired) {
+            bool success = false;
+            std::lock_guard<std::mutex> lck{mutex};
+            const BundleState state = bnd->state();
+            if (state == desired) {
+                //nop
+                success = true;
+            } else if (state == BundleState::INSTALLED && desired == BundleState::RESOLVED) {
+                //TODO create cache dir for bundle
+                bool resolved = act->resolve(ctx);
+                if (resolved) {
+                    bnd->setState(BundleState::RESOLVED);
+                    success = true;
+                } else {
+                    LOG(WARNING) << "Transition to resolved state for bundle " << bnd->symbolicName() << " (" << bnd->id() << ") failed." << std::endl;
+                }
+
+            } else if (state == BundleState::RESOLVED && desired == BundleState::ACTIVE) {
+                bool started = act->start(ctx);
+                if (started) {
+                    bnd->setState(BundleState::ACTIVE);
+                    success = true;
+                } else {
+                    LOG(WARNING) << "Transition to active state for bundle " << bnd->symbolicName() << " (" << bnd->id() << ") failed." << std::endl;
+                }
+            } else if (state == BundleState::ACTIVE && desired == BundleState::RESOLVED ) {
+                bool stopped = act->stop(ctx);
+                if (stopped) {
+                    bnd->setState(BundleState::RESOLVED);
+                    success = true;
+
+                    //TODO use custom deleter to check this (use_count call is a race condition)
+                    bool unique  = ctx.use_count() == 1;
+                    if (!unique) {
+                        LOG(WARNING) << "Bundle Context is not unique. ";
+                        LOG(WARNING) << "Check if there are still some dangling references to the context of the stopped bundle." << std::endl;
+                    }
+                } else {
+                    LOG(WARNING) << "Transition to resolved state for bundle " << bnd->symbolicName() << " (" << bnd->id() << ") failed." << std::endl;
+                }
+            } else {
+                //LOG(ERROR) << "Unexpected desired state " << desired << " from state " << bndState << std::endl;
+                LOG(ERROR) << "Unexpected desired/form state combination " << std::endl;
+            }
+            return success;
+        }
+
+        std::shared_ptr<celix::IBundleActivator> activator() const { return act; }
+        std::shared_ptr<celix::impl::Bundle> bundle() const { return bnd; }
+        std::shared_ptr<celix::impl::BundleContext> context() const { return ctx; }
+    private:
+        const std::shared_ptr<celix::IBundleActivator> act;
+        const std::shared_ptr<celix::impl::Bundle> bnd;
+        const std::shared_ptr<celix::impl::BundleContext> ctx;
+
+        mutable std::mutex mutex{};
+    };
+}
+};
+
+#endif //CXX_CELIX_IMPL_BUNDLE_H
diff --git a/libs/framework_cxx/src/Framework.cc b/libs/framework_cxx/src/Framework.cc
new file mode 100644
index 0000000..a224720
--- /dev/null
+++ b/libs/framework_cxx/src/Framework.cc
@@ -0,0 +1,350 @@
+#include <utility>
+
+#include <utility>
+
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <unordered_map>
+#include <mutex>
+#include <iostream>
+#include <set>
+#include <vector>
+
+#include <glog/logging.h>
+
+#include "celix/Framework.h"
+
+#include "BundleImpl.h"
+
+struct StaticBundleEntry {
+    const std::string symbolicName;
+    const celix::Properties manifest;
+    const std::function<celix::IBundleActivator*()> activatorFactory;
+};
+
+static struct {
+    std::mutex mutex{};
+    std::vector<StaticBundleEntry> bundles{};
+    std::set<celix::Framework *> frameworks{};
+} staticRegistry{};
+
+
+static void registerFramework(celix::Framework *fw);
+static void unregisterFramework(celix::Framework *fw);
+
+class celix::Framework::Impl : public IBundle {
+public:
+    Impl(celix::Framework *_fw) : fw{_fw}, bndManifest{createManifest()}, cwd{createCwd()} {}
+
+    ~Impl() {
+        stopFramework();
+    }
+
+    std::vector<long> listBundles(bool includeFrameworkBundle) const {
+        std::vector<long> result{};
+        if (includeFrameworkBundle) {
+            result.push_back(0L); //framework bundle id
+        }
+        std::lock_guard<std::mutex> lock{bundles.mutex};
+        for (auto &entry : bundles.entries) {
+            result.push_back(entry.first);
+        }
+        std::sort(result.begin(), result.end());//ensure that the bundles are order by bndId -> i.e. time of install
+        return result;
+    }
+
+    long installBundle(std::string symbolicName, std::shared_ptr<celix::IBundleActivator> activator, celix::Properties manifest, bool autoStart) {
+        //TODO on separate thread ?? specific bundle resolve thread ??
+        long bndId = -1L;
+        std::shared_ptr<celix::impl::BundleController> bndController{nullptr};
+        {
+            manifest[celix::MANIFEST_BUNDLE_SYMBOLIC_NAME] = symbolicName;
+            if (manifest.find(celix::MANIFEST_BUNDLE_NAME) == manifest.end()) {
+                manifest[celix::MANIFEST_BUNDLE_NAME] = symbolicName;
+            }
+            if (manifest.find(celix::MANIFEST_BUNDLE_VERSION) == manifest.end()) {
+                manifest[celix::MANIFEST_BUNDLE_NAME] = "0.0.0";
+            }
+            if (manifest.find(celix::MANIFEST_BUNDLE_GROUP) == manifest.end()) {
+                manifest[celix::MANIFEST_BUNDLE_GROUP] = "";
+            }
+
+            std::lock_guard<std::mutex> lck{bundles.mutex};
+            bndId = bundles.nextBundleId++;
+            auto bnd = std::shared_ptr<celix::impl::Bundle>{new celix::impl::Bundle{bndId, this->fw, std::move(manifest), std::move(activator)}};
+            auto ctx = std::shared_ptr<celix::impl::BundleContext>{new celix::impl::BundleContext{bnd}};
+            bndController = std::shared_ptr<celix::impl::BundleController>{new celix::impl::BundleController{activator, bnd, ctx}};
+            bundles.entries.emplace(std::piecewise_construct,
+                                     std::forward_as_tuple(bndId),
+                                     std::forward_as_tuple(bndController));
+
+            //TODO increase bnd entry usage
+        }
+
+        if (bndController) {
+            bool successful = bndController->transitionTo(BundleState::RESOLVED);
+            if (successful && autoStart) {
+                successful = bndController->transitionTo(BundleState::ACTIVE);
+                if (!successful) {
+                    LOG(WARNING) << "Cannot start bundle " << bndController->bundle()->symbolicName() << std::endl;
+                }
+            } else {
+                LOG(WARNING) << "Cannot resolve bundle " << bndController->bundle()->symbolicName() << std::endl;
+            }
+            //TODO decrease bnd entry usage
+        }
+        return bndId;
+    }
+
+    bool startBundle(long bndId) {
+        return transitionBundleTo(bndId, BundleState::ACTIVE);
+    }
+
+    bool stopBundle(long bndId) {
+        return transitionBundleTo(bndId, BundleState::RESOLVED);
+    }
+
+    bool uninstallBundle(long bndId) {
+        bool uninstalled = false;
+        std::shared_ptr<celix::impl::BundleController> removed{nullptr};
+        {
+            std::lock_guard<std::mutex> lck{bundles.mutex};
+            auto it = bundles.entries.find(bndId);
+            if (it != bundles.entries.end()) {
+                removed = std::move(it->second);
+                bundles.entries.erase(it);
+
+            }
+        }
+        if (removed) {
+            bool resolved = removed->transitionTo(BundleState::RESOLVED);
+            if (resolved) {
+                uninstalled = true;
+                bool unique = removed.unique();
+                assert(unique); //TODO cond / wait ?
+            } else {
+                //add bundle again -> not uninstalled
+                std::lock_guard<std::mutex> lck{bundles.mutex};
+                bundles.entries[bndId] = std::move(removed);
+            }
+        }
+        return uninstalled;
+    }
+
+    bool transitionBundleTo(long bndId, BundleState desired) {
+        bool successful = false;
+        std::shared_ptr<celix::impl::BundleController> match{nullptr};
+        {
+            std::lock_guard<std::mutex> lck{bundles.mutex};
+            auto it = bundles.entries.find(bndId);
+            if (it != bundles.entries.end()) {
+                match = it->second;
+            }
+        }
+        if (match) {
+            successful = match->transitionTo(desired);
+        }
+        return successful;
+    }
+
+    bool useBundle(long bndId, std::function<void(const celix::IBundle &bnd)> use) const {
+        bool called = false;
+        if (bndId == 0) {
+            //framework bundle
+            use(*this);
+            called = true;
+        } else {
+            std::shared_ptr<celix::impl::BundleController> match = nullptr;
+            {
+                std::lock_guard<std::mutex> lck{bundles.mutex};
+                auto it = bundles.entries.find(bndId);
+                if (it != bundles.entries.end()) {
+                    match = it->second;
+                    //TODO increase usage
+                }
+            }
+            if (match) {
+                use(*match->bundle());
+                called = true;
+                //TODO decrease usage -> use shared ptr instead
+            }
+        }
+        return called;
+    }
+
+    int useBundles(std::function<void(const celix::IBundle &bnd)> use, bool includeFramework) const {
+        std::map<long, std::shared_ptr<celix::impl::BundleController>> useBundles{};
+        {
+            std::lock_guard<std::mutex> lck{bundles.mutex};
+            for (const auto &it : bundles.entries) {
+                useBundles[it.first] = it.second;
+            }
+        }
+
+        if (includeFramework) {
+            use(*this);
+        }
+        for (const auto &cntr : useBundles) {
+            use(*cntr.second->bundle());
+        }
+        int count = (int)useBundles.size();
+        if (includeFramework) {
+            count += 1;
+        }
+        return count;
+    }
+
+    celix::ServiceRegistry& registry(const std::string &lang) {
+        std::lock_guard<std::mutex> lck{registries.mutex};
+        auto it = registries.entries.find(lang);
+        if (it == registries.entries.end()) {
+            registries.entries.emplace(std::string{lang}, celix::ServiceRegistry{std::string{lang}});
+            return registries.entries.at(lang);
+        } else {
+            return it->second;
+        }
+    }
+
+    //resource bundle part
+    long id() const noexcept override { return 1L /*note registry empty bundle is id 0, framework is id 1*/; }
+    bool has(const std::string&) const override { return false; }
+    bool isDir(const std::string&) const override { return false; }
+    bool isFile(const std::string&) const override { return false; }
+    std::vector<std::string> readDir(const std::string&) const override { return std::vector<std::string>{};}
+    const std::string& root() const noexcept override { //TODO
+        return cwd;
+    }
+
+    //bundle stuff
+    bool isFrameworkBundle() const noexcept override { return true; }
+    void* handle() const noexcept override { return nullptr; }
+    celix::BundleState state() const noexcept override { return BundleState::ACTIVE ; }
+    const std::string& name() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_NAME); }
+    const std::string& symbolicName() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_SYMBOLIC_NAME); }
+    const std::string& group() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_GROUP); }
+    const std::string& version() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_VERSION); }
+    const celix::Properties& manifest() const noexcept  override { return bndManifest;}
+    bool isValid() const noexcept override { return true; }
+    celix::Framework& framework() const noexcept override { return *fw; }
+
+    bool stopFramework() {
+        std::vector<long> bundles = listBundles(false);
+        while (!bundles.empty()) {
+            for (auto it = bundles.rbegin(); it != bundles.rend(); ++it) {
+                stopBundle(*it);
+                uninstallBundle(*it);
+            }
+            bundles = listBundles(false);
+        }
+
+        return true;
+    }
+private:
+    celix::Properties createManifest() {
+        celix::Properties m{};
+        m[celix::MANIFEST_BUNDLE_SYMBOLIC_NAME] = "framework";
+        m[celix::MANIFEST_BUNDLE_NAME] = "Framework";
+        m[MANIFEST_BUNDLE_GROUP] = "Celix";
+        m[celix::MANIFEST_BUNDLE_VERSION] = "3.0.0";
+        return m;
+    }
+
+    std::string createCwd() {
+        char workdir[PATH_MAX];
+        if (getcwd(workdir, sizeof(workdir)) != NULL) {
+            return std::string{workdir};
+        } else {
+            return std::string{};
+        }
+    }
+
+    celix::Framework * const fw;
+    const celix::Properties bndManifest;
+    const std::string cwd;
+
+    struct {
+        std::unordered_map<long, std::shared_ptr<celix::impl::BundleController>> entries{};
+        long nextBundleId = 2;
+        mutable std::mutex mutex{};
+    } bundles{};
+
+    struct {
+        mutable std::mutex mutex{};
+        std::unordered_map<std::string, celix::ServiceRegistry> entries;
+    } registries;
+};
+
+/***********************************************************************************************************************
+ * Framework
+ **********************************************************************************************************************/
+
+celix::Framework::Framework() {
+    pimpl = std::unique_ptr<Impl>{new Impl{this}};
+    registerFramework(this); //TODO improve ugly.. maybe register impl.. but that is private -> so make register static member functions of impl...
+}
+celix::Framework::~Framework() {
+    unregisterFramework(this);
+}
+celix::Framework::Framework(Framework &&rhs) = default;
+celix::Framework& celix::Framework::operator=(Framework&& rhs) = default;
+
+long celix::Framework::installBundle(std::string name, std::shared_ptr<celix::IBundleActivator> activator, celix::Properties manifest, bool autoStart) {
+    return pimpl->installBundle(std::move(name), std::move(activator), std::move(manifest), autoStart);
+}
+
+std::vector<long> celix::Framework::listBundles(bool includeFrameworkBundle) const { return pimpl->listBundles(includeFrameworkBundle); }
+
+bool celix::Framework::useBundle(long bndId, std::function<void(const celix::IBundle &bnd)> use) const {
+    return pimpl->useBundle(bndId, use);
+}
+
+int celix::Framework::useBundles(std::function<void(const celix::IBundle &bnd)> use, bool includeFrameworkBundle) const {
+    return pimpl->useBundles(use, includeFrameworkBundle);
+}
+
+bool celix::Framework::startBundle(long bndId) { return pimpl->stopBundle(bndId); }
+bool celix::Framework::stopBundle(long bndId) { return pimpl->stopBundle(bndId); }
+bool celix::Framework::uninstallBundle(long bndId) { return pimpl->uninstallBundle(bndId); }
+celix::ServiceRegistry& celix::Framework::registry(const std::string &lang) { return pimpl->registry(lang); }
+
+/***********************************************************************************************************************
+ * Celix 'global' functions
+ **********************************************************************************************************************/
+
+void celix::registerStaticBundle(std::string symbolicName, const celix::StaticBundleOptions &opts) {
+    std::lock_guard<std::mutex> lck{staticRegistry.mutex};
+    staticRegistry.bundles.emplace_back(StaticBundleEntry{.symbolicName = std::move(symbolicName), .manifest = opts.manifest, .activatorFactory = opts.bundleActivatorFactory});
+    for (auto fw : staticRegistry.frameworks) {
+        fw->installBundle(symbolicName, std::shared_ptr<celix::IBundleActivator>{opts.bundleActivatorFactory()}, opts.manifest);
+    }
+}
+
+static void registerFramework(celix::Framework *fw) {
+    std::lock_guard<std::mutex> lck{staticRegistry.mutex};
+    staticRegistry.frameworks.insert(fw);
+    for (auto &entry : staticRegistry.bundles) {
+        fw->installBundle(entry.symbolicName, std::shared_ptr<celix::IBundleActivator>{entry.activatorFactory()}, entry.manifest);
+    }
+}
+
+static void unregisterFramework(celix::Framework *fw) {
+    std::lock_guard<std::mutex> lck{staticRegistry.mutex};
+    staticRegistry.frameworks.erase(fw);
+}
\ No newline at end of file
diff --git a/libs/CMakeLists.txt b/libs/registry/CMakeLists.txt
similarity index 64%
copy from libs/CMakeLists.txt
copy to libs/registry/CMakeLists.txt
index 5df35a2..ee537cc 100644
--- a/libs/CMakeLists.txt
+++ b/libs/registry/CMakeLists.txt
@@ -15,17 +15,18 @@
 # specific language governing permissions and limitations
 # under the License.
 
-#utils, dfi and etcdlib are standalone
-#(e.g. no dependency on celix framework
-add_subdirectory(utils)
-add_subdirectory(dfi)
-add_subdirectory(etcdlib)
+find_package(glog REQUIRED)
 
-add_subdirectory(framework)
+add_library(celix_registry STATIC
+        src/ServiceRegistry.cc
+        src/Filter.cc
+)
+target_include_directories(celix_registry PRIVATE src)
+target_include_directories(celix_registry PUBLIC include)
+target_link_libraries(celix_registry PRIVATE glog::glog) #TODO make glog static and private
 
-#launcher
-add_subdirectory(launcher)
+add_library(celix::registry ALIAS celix_registry)
 
-#add_subdirectory(event_admin)# event_admin is unstable
-add_subdirectory(dependency_manager)
-add_subdirectory(dependency_manager_cxx)
\ No newline at end of file
+if (ENABLE_TESTING)
+    add_subdirectory(gtest)
+endif ()
\ No newline at end of file
diff --git a/libs/CMakeLists.txt b/libs/registry/gtest/CMakeLists.txt
similarity index 62%
copy from libs/CMakeLists.txt
copy to libs/registry/gtest/CMakeLists.txt
index 5df35a2..80f0159 100644
--- a/libs/CMakeLists.txt
+++ b/libs/registry/gtest/CMakeLists.txt
@@ -5,9 +5,9 @@
 # to you under the Apache License, Version 2.0 (the
 # "License"); you may not use this file except in compliance
 # with the License.  You may obtain a copy of the License at
-#
+# 
 #   http://www.apache.org/licenses/LICENSE-2.0
-#
+# 
 # Unless required by applicable law or agreed to in writing,
 # software distributed under the License is distributed on an
 # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -15,17 +15,16 @@
 # specific language governing permissions and limitations
 # under the License.
 
-#utils, dfi and etcdlib are standalone
-#(e.g. no dependency on celix framework
-add_subdirectory(utils)
-add_subdirectory(dfi)
-add_subdirectory(etcdlib)
+find_package(glog REQUIRED)
 
-add_subdirectory(framework)
+set(SOURCES
+        src/main.cc
+        src/Registry_tests.cc
+        src/Filter_tests.cc
+        src/ServiceTracking_tests.cc
+)
+add_executable(celix_registry_tests ${SOURCES})
+target_link_libraries(celix_registry_tests PRIVATE gtest glog::glog celix::registry)
 
-#launcher
-add_subdirectory(launcher)
-
-#add_subdirectory(event_admin)# event_admin is unstable
-add_subdirectory(dependency_manager)
-add_subdirectory(dependency_manager_cxx)
\ No newline at end of file
+add_test(NAME celix_registry_tests COMMAND celix_registry_tests)
+SETUP_TARGET_FOR_COVERAGE(celix_registry_tests_cov celix_registry_tests ${CMAKE_BINARY_DIR}/coverage/registry)
\ No newline at end of file
diff --git a/libs/registry/gtest/src/Filter_tests.cc b/libs/registry/gtest/src/Filter_tests.cc
new file mode 100644
index 0000000..0e481db
--- /dev/null
+++ b/libs/registry/gtest/src/Filter_tests.cc
@@ -0,0 +1,207 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "gtest/gtest.h"
+
+#include "celix/Filter.h"
+
+class FilterTest : public ::testing::Test {
+public:
+    FilterTest() {}
+    ~FilterTest(){}
+};
+
+TEST_F(FilterTest, CreateFilterTest) {
+    const char *input1 = "(test_attr1=attr1)";
+    celix::Filter filter{input1};
+    EXPECT_TRUE(filter.valid());
+    EXPECT_EQ("test_attr1", filter.criteria->attribute);
+    EXPECT_EQ(celix::FilterOperator::EQUAL, filter.criteria->op);
+    EXPECT_EQ("attr1", filter.criteria->value);
+    EXPECT_EQ(0, filter.criteria->subcriteria.size());
+
+
+    const char *input2 = "(&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3=attr3)))";
+    celix::Filter filter2{input2};
+    EXPECT_TRUE(filter2.valid());
+    EXPECT_EQ(input2, filter2.filterStr);
+    EXPECT_EQ(celix::FilterOperator::AND, filter2.criteria->op);
+    EXPECT_EQ(2, filter2.criteria->subcriteria.size());
+    EXPECT_EQ(2, filter2.criteria->subcriteria[1]->subcriteria.size());
+    EXPECT_EQ("test_attr1", filter2.criteria->subcriteria[0]->attribute);
+    EXPECT_EQ(celix::FilterOperator::EQUAL, filter2.criteria->subcriteria[0]->op);
+    EXPECT_EQ("attr1", filter2.criteria->subcriteria[0]->value);
+
+    //test last criteria
+    EXPECT_EQ("test_attr3", filter2.criteria->subcriteria[1]->subcriteria[1]->attribute);
+    EXPECT_EQ(celix::FilterOperator::EQUAL, filter2.criteria->subcriteria[1]->subcriteria[1]->op);
+    EXPECT_EQ("attr3", filter2.criteria->subcriteria[1]->subcriteria[1]->value);
+    EXPECT_EQ(0, filter2.criteria->subcriteria[1]->subcriteria[1]->subcriteria.size());
+
+
+    //creation using a const char* literal and additional white spaces
+    celix::Filter filter3 = "    (   &  (test_attr1=attr1)  (   |    (test_attr2=attr2)   (test_attr3=attr3   ) )  )    ";
+    filter3.valid();
+
+
+    //test PRESENT operator with trailing chars (should just register as substrings: "*" and "attr3")
+    celix::Filter f3 = "(test_attr3=*attr3)";
+    EXPECT_TRUE(f3.valid());
+    EXPECT_EQ(celix::FilterOperator::SUBSTRING, f3.criteria->op);
+    EXPECT_EQ("*attr3", f3.criteria->value);
+
+    //test parsing a value with a escaped closing bracket "\)"
+    celix::Filter f4 = "(test_attr3>=strWith\\)inIt)";
+    EXPECT_TRUE(f4.valid());
+    EXPECT_EQ(celix::FilterOperator::GREATER_EQUAL, f4.criteria->op);
+    EXPECT_EQ("strWith)inIt", f4.criteria->value);
+
+    //test parsing a equal with a escaped closing bracket "\)"
+    celix::Filter f5 = "(test_attr3=strWith\\)inIt)";
+    EXPECT_TRUE(f5.valid());
+    EXPECT_EQ(celix::FilterOperator::EQUAL, f5.criteria->op);
+    EXPECT_EQ("strWith)inIt", f5.criteria->value);
+
+    //test parsing a substring with a escaped closing bracket "\)"
+    celix::Filter f6 = "(test_attr3=*strWith\\)inIt)";
+    EXPECT_TRUE(f6.valid());
+    EXPECT_EQ(celix::FilterOperator::SUBSTRING, f6.criteria->op);
+    EXPECT_EQ("*strWith)inIt", f6.criteria->value);
+
+    celix::Filter f7 = ""; //empty is considered a valid filter
+    f7.valid();
+}
+
+TEST_F(FilterTest, CreateInvalidFilterTest) {
+
+    auto check = [](const char *filter) {
+        celix::Filter f = filter;
+        EXPECT_FALSE(f.valid());
+    };
+
+    check("no-parentheses");
+
+    //empty with whitespaces is also an invalid filter.
+    check(" ");
+
+    check("(attr=trailing_stuff) fdafa");
+
+    //test missing opening brackets in main filter
+    check("&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3=attr3))");
+
+    //test missing opening brackets in AND comparator
+    check("(&test_attr1=attr1|(test_attr2=attr2)(test_attr3=attr3))");
+
+    //test missing opening brackets in AND comparator
+    check("(&(test_attr1=attr1)(|test_attr2=attr2(test_attr3=attr3))");
+
+    //test missing opening brackets in NOT comparator
+    check("(&(test_attr1=attr1)(!test_attr2=attr2)");
+
+    //test missing closing brackets in substring
+    check("(&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3=attr3");
+
+    //test missing closing brackets in value
+    check("(&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3>=attr3");
+
+    //test missing closing brackets in substring
+    check("(&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3=at(tr3)))");
+
+    //test missing closing brackets in value
+    check("(&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3>=att(r3)))");
+
+    //test trailing chars
+    check("(&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3=attr3))) oh no! trailing chars");
+
+    //test half APPROX operator (should be "~=", instead is "~")
+    check("(&(test_attr1=attr1)(|(test_attr2=attr2)(test_attr3~attr3)))");;
+
+    //test parsing a attribute of 0 length
+    check("(>=attr3)");
+
+    //test parsing a value of 0 length
+    check("(test_attr3>=)");
+}
+
+TEST_F(FilterTest, MatchComparators) {
+    celix::Properties props{};
+
+    props["test_attr1"] = "attr1";
+    props["test_attr2"] = "attr2";
+
+    //test present
+    {
+        celix::Filter f1 = "(test_attr1=*)"; //match true
+        celix::Filter f2 = "(test_attr3=*)"; //match false
+        EXPECT_TRUE(f1.valid());
+        EXPECT_TRUE(f2.valid());
+        EXPECT_TRUE(f1.match(props));
+        EXPECT_FALSE(f2.match(props));
+    }
+
+    //test equal
+    {
+        celix::Filter f1 = "(test_attr1=attr1)"; //match true
+        celix::Filter f2 = "(test_attr1=bla)"; //match false
+        EXPECT_TRUE(f1.valid());
+        EXPECT_TRUE(f2.valid());
+        EXPECT_TRUE(f1.match(props));
+        EXPECT_FALSE(f2.match(props));
+    }
+
+    //test not
+    {
+        celix::Filter f1 = "(!(test_attr1=bla))"; //match true
+        celix::Filter f2 = "(!(test_attr1=attr1))"; //match false
+        EXPECT_TRUE(f1.valid());
+        EXPECT_TRUE(f2.valid());
+        EXPECT_TRUE(f1.match(props));
+        EXPECT_FALSE(f2.match(props));
+    }
+
+    //test AND
+    {
+        celix::Filter f1 = "(&(test_attr1=attr1)(test_attr2=attr2))"; //match true
+        celix::Filter f2 = "(&(test_attr1=attr1)(test_attr3=attr3))"; //match false
+        EXPECT_TRUE(f1.valid());
+        EXPECT_TRUE(f2.valid());
+        EXPECT_TRUE(f1.match(props));
+        EXPECT_FALSE(f2.match(props));
+    }
+
+    //test OR
+    {
+        celix::Filter f1 = "(|(test_attr3=attr3)(test_attr2=attr2))"; //match true
+        celix::Filter f2 = "(|(test_attr4=attr4)(test_attr3=attr3))"; //match false
+        EXPECT_TRUE(f1.valid());
+        EXPECT_TRUE(f2.valid());
+        EXPECT_TRUE(f1.match(props));
+        EXPECT_FALSE(f2.match(props));
+    }
+
+    //test COMBINE
+    {
+        celix::Filter f1 = "(|(test_attr3=attr3)(&(!(test_attr4=*))(test_attr2=attr2)))"; //match true
+        celix::Filter f2 = "(|(test_attr3=attr3)(&(test_attr4=*)(test_attr2=attr2)))"; //match false
+        EXPECT_TRUE(f1.valid());
+        EXPECT_TRUE(f2.valid());
+        EXPECT_TRUE(f1.match(props));
+        EXPECT_FALSE(f2.match(props));
+    }
+}
diff --git a/libs/registry/gtest/src/RegistryConcurrency_tests.cc b/libs/registry/gtest/src/RegistryConcurrency_tests.cc
new file mode 100644
index 0000000..c77c198
--- /dev/null
+++ b/libs/registry/gtest/src/RegistryConcurrency_tests.cc
@@ -0,0 +1,75 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "gtest/gtest.h"
+
+#include "celix/ServiceRegistry.h"
+#include "celix/Constants.h"
+
+class RegistryConcurrentcyTest : public ::testing::Test {
+public:
+    RegistryConcurrentcyTest() {}
+    ~RegistryConcurrentcyTest(){}
+
+    celix::ServiceRegistry& registry() { return reg; }
+private:
+    celix::ServiceRegistry reg{"C/C++"};
+};
+
+class ICalc {
+public:
+    virtual ~ICalc() = default;
+    virtual double calc();
+};
+
+class NodeCalc : public ICalc {
+public:
+    virtual ~NodeCalc() = default;
+
+    double calc() override {
+        double val = 1.0;
+        std::lock_guard<std::mutex> lck{mutex};
+        for (auto *calc : childern) {
+            val *= calc->calc();
+        }
+        return val;
+    }
+private:
+    std::mutex mutex{}
+    std::vector<ICalc*> childern{};
+};
+
+class LeafCalc : public ICalc {
+public:
+    virtual ~LeafCalc() = default;
+
+    double calc() override {
+        return seed;
+    }
+private:
+    double const seed = std::rand() / 100.0;
+};
+
+
+TEST_F(RegistryConcurrentcyTest, ServiceRegistrationTest) {
+//TODO start many thread and cals using the tiers of other calcs eventually leading ot leafs and try to break the registry.
+//tier 1 : NodeCalc
+//tier 2 : NodeCalc
+//tier 3 : LeafCalc
+}
diff --git a/libs/registry/gtest/src/Registry_tests.cc b/libs/registry/gtest/src/Registry_tests.cc
new file mode 100644
index 0000000..8c00b11
--- /dev/null
+++ b/libs/registry/gtest/src/Registry_tests.cc
@@ -0,0 +1,269 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "gtest/gtest.h"
+
+#include <glog/logging.h>
+
+#include "celix/ServiceRegistry.h"
+
+class RegistryTest : public ::testing::Test {
+public:
+    RegistryTest() {}
+    ~RegistryTest(){}
+
+    celix::ServiceRegistry& registry() { return reg; }
+private:
+    celix::ServiceRegistry reg{"C/C++"};
+};
+
+class MarkerInterface1 {
+  //nop
+};
+class MarkerInterface2 {
+    //nop
+};
+class MarkerInterface3 {
+    //nop
+};
+
+
+TEST_F(RegistryTest, ServiceRegistrationTest) {
+    //empty registry
+    EXPECT_EQ(0, registry().nrOfRegisteredServices());
+
+    MarkerInterface1 intf1{};
+    {
+        celix::Properties props{};
+        props["TEST"] = "VAL";
+        celix::ServiceRegistration reg = registry().registerService(intf1, props);
+        //no copy possible celix::ServiceRegistration copy = reg;
+
+        long svcId = reg.serviceId();
+        EXPECT_GE(svcId, -1L);
+        EXPECT_TRUE(reg.valid());
+        EXPECT_EQ(reg.properties().at(celix::SERVICE_NAME), celix::serviceName<MarkerInterface1>());
+        EXPECT_EQ("VAL", celix::getProperty(reg.properties(), "TEST", ""));
+
+        EXPECT_EQ(1, registry().nrOfRegisteredServices());
+        EXPECT_EQ(1, registry().findServices<MarkerInterface1>().size());
+
+
+
+        celix::ServiceRegistration moved = std::move(reg); //moving is valid
+        EXPECT_EQ(svcId, moved.serviceId());
+        EXPECT_EQ(1, registry().nrOfRegisteredServices());
+
+        celix::ServiceRegistration moved2{std::move(moved)};
+        EXPECT_EQ(1, registry().nrOfRegisteredServices());
+
+        //out of scope -> deregister
+    }
+    EXPECT_EQ(0, registry().nrOfRegisteredServices());
+    EXPECT_EQ(0, registry().findServices<MarkerInterface1>().size());
+
+    MarkerInterface1 intf2{};
+    MarkerInterface2 intf3{};
+    {
+        celix::ServiceRegistration reg1 = registry().registerService(intf1);
+        EXPECT_EQ(1, registry().nrOfRegisteredServices());
+        celix::ServiceRegistration reg2 = registry().registerService(intf2);
+        EXPECT_EQ(2, registry().nrOfRegisteredServices());
+        celix::ServiceRegistration reg3 = registry().registerService(intf3);
+        EXPECT_EQ(3, registry().nrOfRegisteredServices());
+
+        EXPECT_GT(reg1.serviceId(), 0);
+        EXPECT_GT(reg2.serviceId(), 0);
+        EXPECT_GT(reg3.serviceId(), 0);
+        EXPECT_TRUE(reg1.valid());
+        EXPECT_TRUE(reg2.valid());
+        EXPECT_TRUE(reg3.valid());
+
+        EXPECT_EQ(3, registry().nrOfRegisteredServices());
+        EXPECT_EQ(2, registry().findServices<MarkerInterface1>().size());
+        EXPECT_EQ(1, registry().findServices<MarkerInterface2>().size());
+        EXPECT_EQ(0, registry().findServices<MarkerInterface3>().size());
+
+        //out of scope -> deregister
+    }
+    EXPECT_EQ(0, registry().nrOfRegisteredServices());
+    EXPECT_EQ(0, registry().findServices<MarkerInterface1>().size());
+    EXPECT_EQ(0, registry().findServices<MarkerInterface2>().size());
+    EXPECT_EQ(0, registry().findServices<MarkerInterface3>().size());
+}
+
+TEST_F(RegistryTest, SimpleFindServicesTest) {
+    MarkerInterface1 intf1{};
+    MarkerInterface2 intf2{};
+
+    auto reg1 = registry().registerService(intf1);
+    auto reg2 = registry().registerService(intf2);
+
+    long firstSvc = registry().findService<MarkerInterface1>();
+    EXPECT_GT(firstSvc, 0);
+    std::vector<long> services = registry().findServices<MarkerInterface1>();
+    EXPECT_EQ(1, services.size());
+
+    auto reg3 = registry().registerService(intf1);
+    auto reg4 = registry().registerService(intf2);
+
+    long foundSvc = registry().findService<MarkerInterface1>(); //should find the first services
+    EXPECT_GT(foundSvc, 0);
+    EXPECT_EQ(firstSvc, foundSvc);
+    services = registry().findServices<MarkerInterface1>();
+    EXPECT_EQ(2, services.size());
+}
+
+TEST_F(RegistryTest, FindServicesTest) {
+    MarkerInterface1 intf1{};
+
+    celix::Properties props1{};
+    props1["loc"] = "front";
+    props1["answer"] = "42";
+
+    celix::Properties props2{};
+    props2["loc"] = "back";
+
+    auto reg1 = registry().registerService(intf1, props1);
+    auto reg2 = registry().registerService(intf1, std::move(props2));
+    auto reg3 = registry().registerService(intf1);
+
+    auto find1 = registry().findServices<MarkerInterface1>("(loc=*)"); // expecting 2
+    auto find2 = registry().findServices<MarkerInterface1>("(answer=42)"); // expecting 1
+    auto find3 = registry().findServices<MarkerInterface1>("(!(loc=*))"); // expecting 1
+
+    EXPECT_EQ(2, find1.size());
+    EXPECT_EQ(1, find2.size());
+    EXPECT_EQ(1, find3.size());
+}
+
+TEST_F(RegistryTest, UseServices) {
+    MarkerInterface1 intf1{};
+    auto reg1 = registry().registerService(intf1);
+    auto reg2 = registry().registerService(intf1);
+    auto reg3 = registry().registerService(intf1);
+
+    long svcId1 = reg1.serviceId();
+
+    bool called = registry().useService<MarkerInterface1>([&](MarkerInterface1& svc) -> void {
+        EXPECT_EQ(&svc, &intf1);
+    });
+    EXPECT_TRUE(called);
+
+    called = registry().useService<MarkerInterface1>([&](MarkerInterface1& svc, const celix::Properties &props) -> void {
+        EXPECT_EQ(&svc, &intf1);
+        long id = celix::getProperty(props, celix::SERVICE_ID, 0);
+        EXPECT_EQ(svcId1, id);
+    });
+    EXPECT_TRUE(called);
+
+    called = registry().useService<MarkerInterface1>([&](MarkerInterface1& svc, const celix::Properties &props, const celix::IResourceBundle &bnd) -> void {
+        EXPECT_EQ(&svc, &intf1);
+        long id = celix::getProperty(props, celix::SERVICE_ID, 0);
+        EXPECT_EQ(svcId1, id);
+        EXPECT_EQ(0, bnd.id()); //not nullptr -> use empty bundle (bndId 0)
+    });
+    EXPECT_TRUE(called);
+}
+
+TEST_F(RegistryTest, RankingTest) {
+    MarkerInterface1 intf1{};
+    auto reg1 = registry().registerService(intf1); //no props -> ranking 0
+    auto reg2 = registry().registerService(intf1); //no props -> ranking 0
+
+    {
+        auto reg3 = registry().registerService(intf1); //no props -> ranking 0
+        auto find = registry().findServices<MarkerInterface1>(); // expecting 3
+        EXPECT_EQ(3, find.size());
+        EXPECT_EQ(reg1.serviceId(), find[0]); //first registered service should be found first
+        EXPECT_EQ(reg2.serviceId(), find[1]); //first registered service should be found first
+        EXPECT_EQ(reg3.serviceId(), find[2]); //first registered service should be found first
+
+        //note reg 3 out of scope
+    }
+
+    celix::Properties props{};
+    props[celix::SERVICE_RANKING] = "100";
+    auto reg4 = registry().registerService(intf1, props); // ranking 100 -> before services with ranking 0
+
+    {
+        auto reg5 = registry().registerService(intf1, props); // ranking 100 -> before services with ranking 0
+        auto find = registry().findServices<MarkerInterface1>();
+        EXPECT_EQ(4, find.size());
+        EXPECT_EQ(reg4.serviceId(), find[0]); //ranking 100, oldest (i.e. highest ranking with lowest svcId)
+        EXPECT_EQ(reg5.serviceId(), find[1]); //ranking 100, newest
+        EXPECT_EQ(reg1.serviceId(), find[2]); //ranking 0, oldest
+        EXPECT_EQ(reg2.serviceId(), find[3]); //ranking 0, newest
+
+        //note reg 5 out of scope
+    }
+
+    props[celix::SERVICE_RANKING] = "-100";
+    auto reg6 = registry().registerService(intf1, props); // ranking -100 -> after the rest
+    auto reg7 = registry().registerService(intf1, props); // ranking -100 -> after the rest
+    props[celix::SERVICE_RANKING] = "110";
+    auto reg8 = registry().registerService(intf1, props); // ranking 110 -> before the rest
+    props[celix::SERVICE_RANKING] = "80";
+    auto reg9 = registry().registerService(intf1, props); // ranking 80 -> between ranking 0 adn 100
+    {
+        auto find = registry().findServices<MarkerInterface1>();
+        EXPECT_EQ(7, find.size());
+        EXPECT_EQ(reg8.serviceId(), find[0]); //ranking 110
+        EXPECT_EQ(reg4.serviceId(), find[1]); //ranking 100
+        EXPECT_EQ(reg9.serviceId(), find[2]); //ranking 80
+        EXPECT_EQ(reg1.serviceId(), find[3]); //ranking 0, oldest
+        EXPECT_EQ(reg2.serviceId(), find[4]); //ranking 0, newest
+        EXPECT_EQ(reg6.serviceId(), find[5]); //ranking -100, oldest
+        EXPECT_EQ(reg7.serviceId(), find[6]); //ranking -100, newest
+    }
+}
+
+TEST_F(RegistryTest, StdFunctionTest) {
+    int count = 0;
+    std::function<void()> func1 = [&count]{
+        count++;
+    };
+
+    auto reg1 = registry().registerFunctionService("count", func1);
+    LOG(INFO) << reg1.serviceName() << std::endl;
+    EXPECT_TRUE(reg1.valid());
+    EXPECT_EQ(1, registry().nrOfRegisteredServices());
+
+    std::function<int(long,double,const std::string&)> funcWithReturnAndArgs = [](long a, double b, const std::string &ref) -> int {
+        return (int)(a/b) + (int)ref.size();
+    };
+    auto reg2 = registry().registerFunctionService("yet another function", std::move(funcWithReturnAndArgs));
+    EXPECT_TRUE(reg2.valid());
+    EXPECT_EQ(2, registry().nrOfRegisteredServices());
+    LOG(INFO) << reg2.serviceName() << std::endl;
+
+    std::function<void(std::function<void()>&)> use = [](std::function<void()> &count) {
+        count();
+    };
+    EXPECT_EQ(0, count);
+    registry().useFunctionService("count", use);
+    EXPECT_EQ(1, count);
+    registry().useFunctionService<std::function<void()>>("count", [](std::function<void()> &count) {
+        count();
+    });
+}
+
+//TODO function use with props and bnd
+//TODO use with filter
+//TODO use with sync test (see BundleContext tests)
\ No newline at end of file
diff --git a/libs/registry/gtest/src/ServiceTracking_tests.cc b/libs/registry/gtest/src/ServiceTracking_tests.cc
new file mode 100644
index 0000000..7a88f1b
--- /dev/null
+++ b/libs/registry/gtest/src/ServiceTracking_tests.cc
@@ -0,0 +1,275 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <iostream>
+
+#include "gtest/gtest.h"
+
+#include "celix/ServiceRegistry.h"
+#include "celix/Constants.h"
+
+class ServiceTrackingTest : public ::testing::Test {
+public:
+    celix::ServiceRegistry& registry() { return reg; }
+private:
+    celix::ServiceRegistry reg{"C/C++"};
+};
+
+class MarkerInterface1 {
+  //nop
+};
+class MarkerInterface2 {
+    //nop
+};
+class MarkerInterface3 {
+    //nop
+};
+
+
+TEST_F(ServiceTrackingTest, CreateTrackersTest) {
+    EXPECT_EQ(0, registry().nrOfServiceTrackers());
+    {
+        celix::ServiceTracker trk1 = registry().trackServices<MarkerInterface1>();
+        EXPECT_EQ(1, registry().nrOfServiceTrackers());
+
+        celix::ServiceTracker moved = std::move(trk1);
+        EXPECT_EQ(1, registry().nrOfServiceTrackers());
+
+        celix::ServiceTracker moved2 = celix::ServiceTracker{std::move(moved)};
+        EXPECT_EQ(1, registry().nrOfServiceTrackers());
+
+        auto trk2 = registry().trackServices<MarkerInterface1>();
+        auto trk3 = registry().trackServices<MarkerInterface2>();
+        EXPECT_EQ(3, registry().nrOfServiceTrackers());
+    }
+    EXPECT_EQ(0, registry().nrOfServiceTrackers());
+}
+
+TEST_F(ServiceTrackingTest, ServicesCountTrackersTest) {
+    MarkerInterface1 intf1;
+    MarkerInterface2 intf2;
+    MarkerInterface3 intf3;
+
+    auto trk1 = registry().trackServices<MarkerInterface1>();
+    ASSERT_EQ(0, trk1.trackCount());
+
+    auto reg1 = registry().registerService(intf1);
+    auto reg2 = registry().registerService(intf2);
+
+    auto trk2 = registry().trackServices<MarkerInterface2>();
+    ASSERT_EQ(1, trk1.trackCount());
+    ASSERT_EQ(1, trk2.trackCount());
+
+    {
+
+        auto reg3 = registry().registerService(intf1);
+        ASSERT_EQ(2, trk1.trackCount());
+        ASSERT_EQ(1, trk2.trackCount());
+
+        {
+            auto reg4 = registry().registerService(intf1);
+            auto reg5 = registry().registerService(intf2);
+            auto reg6 = registry().registerService(intf3);
+
+            ASSERT_EQ(3, trk1.trackCount());
+            ASSERT_EQ(2, trk2.trackCount());
+
+            //out of scope -> services are deregistered
+        }
+
+        ASSERT_EQ(2, trk1.trackCount());
+        ASSERT_EQ(1, trk2.trackCount());
+        //out of scope -> services are deregistered
+    }
+
+    ASSERT_EQ(1, trk1.trackCount());
+    ASSERT_EQ(1, trk2.trackCount());
+}
+
+TEST_F(ServiceTrackingTest, SetServiceTest) {
+    MarkerInterface1 intf1;
+    MarkerInterface2 intf2;
+    MarkerInterface3 intf3;
+
+    MarkerInterface1 *ptrToSvc = nullptr;
+    //const celix::Properties *ptrToProps = nullptr;
+    //const celix::IBundle *ptrToBnd = nullptr;
+
+    celix::ServiceTrackerOptions<MarkerInterface1> opts{};
+    opts.set = [&ptrToSvc](MarkerInterface1* svc) {
+        ptrToSvc = svc;
+    };
+
+    auto reg1 = registry().registerService(intf1);
+    auto reg2 = registry().registerService(intf2);
+    auto reg3 = registry().registerService(intf3);
+
+    auto trk1 = registry().trackServices(opts);
+    EXPECT_EQ(&intf1, ptrToSvc); //should be intf1
+
+    reg1.unregister();
+    EXPECT_EQ(nullptr, ptrToSvc); //unregistered -> nullptr
+
+
+    reg1 = registry().registerService(intf1);
+    EXPECT_EQ(&intf1, ptrToSvc); //set to intf1 again
+
+    MarkerInterface1 intf4;
+    auto reg4 = registry().registerService(intf4);
+    EXPECT_EQ(&intf1, ptrToSvc); //no change -> intf1 is older
+
+    reg1.unregister();
+    EXPECT_EQ(&intf4, ptrToSvc); //intf1 is gone, intf4 should be set
+
+    trk1.stop();
+    EXPECT_EQ(nullptr, ptrToSvc); //stop tracking nullptr svc is set
+
+    {
+        auto trk2 = registry().trackServices(opts);
+        EXPECT_EQ(&intf4, ptrToSvc); //intf1 is gone, intf4 should be set
+        //out of scope -> tracker stopped
+    }
+    EXPECT_EQ(nullptr, ptrToSvc); //stop tracking nullptr svc is set
+}
+
+TEST_F(ServiceTrackingTest, SetServiceWithPropsAndOwnderTest) {
+    /*
+    MarkerInterface1 intf1;
+    MarkerInterface2 intf2;
+    MarkerInterface3 intf3;
+
+    MarkerInterface1 *ptrToSvc = nullptr;
+    const celix::Properties *ptrToProps = nullptr;
+    const celix::IBundle *ptrToBnd = nullptr;
+    */
+    //TODO
+}
+
+TEST_F(ServiceTrackingTest, AddRemoveTest) {
+    MarkerInterface1 intf1;
+    MarkerInterface2 intf2;
+    MarkerInterface3 intf3;
+
+    std::vector<MarkerInterface1*> services{};
+
+    celix::ServiceTrackerOptions<MarkerInterface1> opts{};
+    opts.add = [&services](MarkerInterface1* svc) {
+        services.push_back(svc);
+    };
+    opts.remove = [&services](MarkerInterface1* svc) {
+        services.erase(std::remove(services.begin(), services.end(), svc), services.end());
+    };
+
+    auto reg1 = registry().registerService(intf1);
+    auto reg2 = registry().registerService(intf2);
+    auto reg3 = registry().registerService(intf3);
+
+    auto trk1 = registry().trackServices(opts);
+    ASSERT_EQ(1, services.size());
+    EXPECT_EQ(&intf1, services[0]); //should be intf1
+
+    reg1.unregister();
+    EXPECT_EQ(0, services.size());
+
+    reg1 = registry().registerService(intf1);
+    ASSERT_EQ(1, services.size());
+    EXPECT_EQ(&intf1, services[0]); //should be intf1 again
+
+    MarkerInterface1 intf4{};
+    auto reg4 = registry().registerService(intf4);
+    ASSERT_EQ(2, services.size());
+    EXPECT_EQ(&intf1, services[0]);
+    EXPECT_EQ(&intf4, services[1]);
+
+    reg1.unregister();
+    ASSERT_EQ(1, services.size());
+    EXPECT_EQ(&intf4, services[0]); //intf1 gone -> index 0: intf4
+
+    trk1.stop();
+    EXPECT_EQ(0, services.size());
+
+    {
+        auto trk2 = registry().trackServices(opts);
+        ASSERT_EQ(1, services.size());
+        EXPECT_EQ(&intf4, services[0]);
+        //out of scope -> tracker stopped
+    }
+    EXPECT_EQ(0, services.size()); //stop tracking -> services removed
+}
+
+TEST_F(ServiceTrackingTest, AddRemoveServicesWithPropsAndOwnderTest) {
+    //TODO
+}
+
+TEST_F(ServiceTrackingTest, UpdateTest) {
+    MarkerInterface1 intf1;
+    MarkerInterface2 intf2;
+    MarkerInterface3 intf3;
+
+    std::vector<MarkerInterface1*> services{};
+
+    celix::ServiceTrackerOptions<MarkerInterface1> opts{};
+    opts.update = [&services](std::vector<MarkerInterface1*> rankedServices) {
+        services = rankedServices;
+    };
+
+    auto reg1 = registry().registerService(intf1);
+    auto reg2 = registry().registerService(intf2);
+    auto reg3 = registry().registerService(intf3);
+
+    auto trk1 = registry().trackServices(opts);
+    EXPECT_EQ(1, trk1.trackCount());
+    ASSERT_EQ(1, services.size());
+    EXPECT_EQ(&intf1, services[0]); //should be intf1
+
+    reg1.unregister();
+    EXPECT_EQ(0, services.size());
+
+    reg1 = registry().registerService(intf1);
+    ASSERT_EQ(1, services.size());
+    EXPECT_EQ(&intf1, services[0]); //should be intf1 again
+
+    MarkerInterface1 intf4{};
+    celix::Properties props{std::make_pair(celix::SERVICE_RANKING, "100")};
+    auto reg4 = registry().registerService(intf4, std::move(props));
+    ASSERT_EQ(2, services.size());
+    EXPECT_EQ(&intf4, services[0]); //note 4 higher ranking
+    EXPECT_EQ(&intf1, services[1]);
+
+    reg1.unregister();
+    ASSERT_EQ(1, services.size());
+    EXPECT_EQ(&intf4, services[0]); //intf1 gone -> index 0: intf4
+
+    trk1.stop();
+    EXPECT_EQ(0, services.size());
+
+    {
+        auto trk2 = registry().trackServices(opts);
+        ASSERT_EQ(1, services.size());
+        EXPECT_EQ(&intf4, services[0]);
+        //out of scope -> tracker stopped
+    }
+    EXPECT_EQ(0, services.size()); //stop tracking -> services removed
+}
+
+TEST_F(ServiceTrackingTest, UpdateTestWithPropsAndOwner) {
+    //TODO
+}
+
+//TODO function service tracking tests
diff --git a/bundles/config_admin/service/private/include/framework_patch.h b/libs/registry/gtest/src/main.cc
similarity index 63%
copy from bundles/config_admin/service/private/include/framework_patch.h
copy to libs/registry/gtest/src/main.cc
index 98194e1..a76daa7 100644
--- a/bundles/config_admin/service/private/include/framework_patch.h
+++ b/libs/registry/gtest/src/main.cc
@@ -16,24 +16,18 @@
  *specific language governing permissions and limitations
  *under the License.
  */
-/*
- * framework_patch.h
- *
- *  \date       Aug 12, 2013
- *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright	Apache License, Version 2.0
- */
-
 
-#ifndef BUNDLE_PATCH_H_
-#define BUNDLE_PATCH_H_
+#include <gtest/gtest.h>
+#include <glog/logging.h>
 
+int main(int argc, char **argv) {
+    google::InitGoogleLogging(argv[0]);
+    google::LogToStderr();
 
-/* celix.framework.public */
-#include "celix_errno.h"
-#include "bundle.h"
-#include "service_reference.h"
+    ::testing::InitGoogleTest(&argc, argv);
+    int rc = RUN_ALL_TESTS();
 
-celix_status_t bundle_getBundleLocation(bundle_pt bundle, const char **location);
+    google::ShutdownGoogleLogging();
 
-#endif /* BUNDLE_PATCH_H_ */
+    return rc;
+}
\ No newline at end of file
diff --git a/libs/registry/include/celix/Constants.h b/libs/registry/include/celix/Constants.h
new file mode 100644
index 0000000..f1fcad3
--- /dev/null
+++ b/libs/registry/include/celix/Constants.h
@@ -0,0 +1,43 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+
+#ifndef CXX_CELIX_CONSTANTS_H
+#define CXX_CELIX_CONSTANTS_H
+
+namespace celix {
+
+    //NOTE manually aligned with celix_constants.h
+    static constexpr const char *const SERVICE_NAME = "service.name";
+    static constexpr const char *const SERVICE_ID = "service.id";
+    static constexpr const char *const SERVICE_RANKING = "service.ranking";
+
+    static constexpr const char *const FRAMEWORK_UUID = "framework.uuid";
+
+    static constexpr const char *const CXX_LANG = "C++";
+    static constexpr const char *const C_LANG = "C";
+
+
+    static constexpr const char *const MANIFEST_BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName";
+    static constexpr const char *const MANIFEST_BUNDLE_NAME = "Bundle-Name";
+    static constexpr const char *const MANIFEST_BUNDLE_VERSION = "Bundle-Version";
+    static constexpr const char *const MANIFEST_BUNDLE_GROUP = "Bundle-Group";
+}
+
+#endif //CXX_CELIX_CONSTANTS_H
diff --git a/libs/registry/include/celix/Filter.h b/libs/registry/include/celix/Filter.h
new file mode 100644
index 0000000..db851ba
--- /dev/null
+++ b/libs/registry/include/celix/Filter.h
@@ -0,0 +1,73 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CXX_CELIX_FILTER_H
+#define CXX_CELIX_FILTER_H
+
+#include <string>
+#include <vector>
+
+#include "celix/Properties.h"
+
+namespace celix {
+
+    enum class FilterOperator {
+        EQUAL,
+        APPROX,
+        GREATER,
+        GREATER_EQUAL,
+        LESS,
+        LESS_EQUAL,
+        PRESENT,
+        SUBSTRING,
+        AND,
+        OR,
+        NOT
+    };
+
+    struct FilterCriteria; //forward declr
+    struct FilterCriteria {
+        const std::string attribute;
+        const celix::FilterOperator op;
+        const std::string value;
+        const std::vector<std::shared_ptr<FilterCriteria>> subcriteria;
+    };
+
+    class Filter {
+    public:
+        Filter(const char* f) : filterStr{f}, criteria{parseFilter()} {}
+        Filter(std::string f) : filterStr{std::move(f)}, criteria{parseFilter()} {}
+        Filter(const Filter &rhs) = default;
+        Filter(Filter &&rhs) = default;
+
+        Filter& operator=(const Filter& rhs) = default;
+        Filter& operator=(Filter&& rhs) = default;
+
+        bool empty() const { return filterStr.empty(); }
+        bool valid() const { return filterStr.empty() || criteria != nullptr; }
+        bool match(const celix::Properties &props) const;
+
+        const std::string filterStr;
+        const std::shared_ptr<FilterCriteria> criteria;
+    private:
+        FilterCriteria* parseFilter();
+    };
+}
+
+#endif //CXX_CELIX_FILTER_H
diff --git a/libs/registry/include/celix/IResourceBundle.h b/libs/registry/include/celix/IResourceBundle.h
new file mode 100644
index 0000000..6352736
--- /dev/null
+++ b/libs/registry/include/celix/IResourceBundle.h
@@ -0,0 +1,57 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CXX_CELIX_IRESOURCEBUNDLE_H
+#define CXX_CELIX_IRESOURCEBUNDLE_H
+
+namespace celix {
+
+    class IResourceBundle {
+    public:
+        virtual ~IResourceBundle() = default;
+
+        virtual long id() const noexcept  = 0;
+
+        virtual const std::string& root() const noexcept = 0;
+
+        virtual bool has(const std::string &path) const noexcept = 0;
+        virtual bool isDir(const std::string &path) const noexcept = 0;
+        virtual bool isFile(const std::string &path) const noexcept = 0;
+
+        //virtual bool storeResource(const std::string &path, std::ostream content) noexcept = 0;
+        //virtual std::istream open(const std::string &path) const noexcept = 0;
+        //virtual std::fstream open(const std::string &path) noexcept = 0;
+        virtual std::vector<std::string> readDir(const std::string &path) const noexcept = 0;
+    };
+
+
+    /*
+     * void read_directory(const std::string& name, stringvec& v)
+{
+    DIR* dirp = opendir(name.c_str());
+    struct dirent * dp;
+    while ((dp = readdir(dirp)) != NULL) {
+        v.push_back(dp->d_name);
+    }
+    closedir(dirp);
+}
+     */
+}
+
+#endif //CXX_CELIX_IRESOURCEBUNDLE_H
diff --git a/bundles/config_admin/service/private/include/framework_patch.h b/libs/registry/include/celix/IServiceFactory.h
similarity index 57%
copy from bundles/config_admin/service/private/include/framework_patch.h
copy to libs/registry/include/celix/IServiceFactory.h
index 98194e1..af27312 100644
--- a/bundles/config_admin/service/private/include/framework_patch.h
+++ b/libs/registry/include/celix/IServiceFactory.h
@@ -16,24 +16,26 @@
  *specific language governing permissions and limitations
  *under the License.
  */
-/*
- * framework_patch.h
- *
- *  \date       Aug 12, 2013
- *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright	Apache License, Version 2.0
- */
 
+#ifndef CXX_CELIX_ISERVICEFACTORY_H
+#define CXX_CELIX_ISERVICEFACTORY_H
+
+#include "celix/Properties.h"
+#include "celix/IResourceBundle.h"
+
+namespace celix {
 
-#ifndef BUNDLE_PATCH_H_
-#define BUNDLE_PATCH_H_
+    template<typename I>
+    class IServiceFactory {
+    public:
+        using type = I;
 
+        virtual ~IServiceFactory() = default;
 
-/* celix.framework.public */
-#include "celix_errno.h"
-#include "bundle.h"
-#include "service_reference.h"
+        virtual I* getService(const celix::IResourceBundle &requestingBundle, const celix::Properties &properties) noexcept = 0;
+        virtual void ungetService(const celix::IResourceBundle &requestingBundle, const celix::Properties &properties) noexcept = 0;
+    };
 
-celix_status_t bundle_getBundleLocation(bundle_pt bundle, const char **location);
+}
 
-#endif /* BUNDLE_PATCH_H_ */
+#endif //CXX_CELIX_ISERVICEFACTORY_H
diff --git a/libs/registry/include/celix/Properties.h b/libs/registry/include/celix/Properties.h
new file mode 100644
index 0000000..65fd4ef
--- /dev/null
+++ b/libs/registry/include/celix/Properties.h
@@ -0,0 +1,60 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CXX_CELIX_PROPERTIES_H
+#define CXX_CELIX_PROPERTIES_H
+
+#include <string>
+#include <map>
+
+namespace celix {
+
+    using Properties = std::map<std::string, std::string>;
+
+    inline const std::string& getProperty(const Properties& props, const std::string &key, const std::string &defaultValue) noexcept {
+        auto it = props.find(key);
+        if (it != props.end()) {
+            return props.at(key);
+        } else {
+            return defaultValue;
+        }
+    }
+
+    inline int getProperty(const Properties& props, const std::string &key, int defaultValue)  noexcept {
+        std::string val = getProperty(props, key, std::to_string(defaultValue));
+        return std::stoi(val, nullptr, 10);
+    }
+
+    inline unsigned int getProperty(const Properties& props, const std::string &key, unsigned int defaultValue) noexcept {
+        std::string val = getProperty(props, key, std::to_string(defaultValue));
+        return static_cast<unsigned  int>(std::stoul(val, nullptr, 10)); //NOTE no std::stou ??
+    }
+
+    inline long getProperty(const Properties& props, const std::string &key, long defaultValue) noexcept {
+        std::string val = getProperty(props, key, std::to_string(defaultValue));
+        return std::stol(val, nullptr, 10);
+    }
+
+    inline unsigned int getProperty(const Properties& props, const std::string &key, unsigned long defaultValue) noexcept {
+        std::string val = getProperty(props, key, std::to_string(defaultValue));
+        return std::stoul(val, nullptr, 10);
+    }
+}
+
+#endif //CXX_CELIX_PROPERTIES_H
diff --git a/libs/registry/include/celix/ServiceRegistry.h b/libs/registry/include/celix/ServiceRegistry.h
new file mode 100644
index 0000000..7bbe16c
--- /dev/null
+++ b/libs/registry/include/celix/ServiceRegistry.h
@@ -0,0 +1,509 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CXX_CELIX_SERVICEREGISTRY_H
+#define CXX_CELIX_SERVICEREGISTRY_H
+
+#include <utility>
+#include <vector>
+
+#include "celix/Constants.h"
+#include "celix/Properties.h"
+#include "celix/Utils.h"
+#include "celix/IResourceBundle.h"
+#include "celix/IServiceFactory.h"
+
+namespace celix {
+
+    //forward declaration
+    class ServiceRegistry;
+
+    // RAII service registration: out of scope -> deregister service
+    // NOTE access not thread safe -> TODO make thread save?
+    class ServiceRegistration {
+    public:
+        ServiceRegistration();
+        ServiceRegistration(ServiceRegistration &&rhs) noexcept;
+        ServiceRegistration(const ServiceRegistration &rhs) = delete;
+        ~ServiceRegistration();
+        ServiceRegistration& operator=(ServiceRegistration &&rhs) noexcept;
+        ServiceRegistration& operator=(const ServiceRegistration &rhs) = delete;
+
+        long serviceId() const;
+        bool valid() const;
+        const celix::Properties& properties() const;
+        const std::string& serviceName() const;
+        bool factory() const;
+        bool registered() const;
+
+        void unregister();
+    private:
+        class Impl; //opaque impl class
+        std::unique_ptr<celix::ServiceRegistration::Impl> pimpl;
+        explicit ServiceRegistration(celix::ServiceRegistration::Impl *impl);
+        friend ServiceRegistry;
+    };
+
+    template<typename I>
+    struct ServiceTrackerOptions {
+        ServiceTrackerOptions() = default;
+        ServiceTrackerOptions(ServiceTrackerOptions &&rhs) noexcept = default;
+        ServiceTrackerOptions(const ServiceTrackerOptions &rhs) = default;
+        ServiceTrackerOptions& operator=(ServiceTrackerOptions &&rhs) = default;
+        ServiceTrackerOptions& operator=(const ServiceTrackerOptions &rhs) = default;
+
+        std::string filter{};
+
+        /*TODO maybe refactor all I* to std::shared_ptr and use a custom deleter to sync whether a bundle is done using
+        all the functions -> i.e. safe delete and possible lock free? Not sure, because a std::shared_ptr instance
+        access it not thread safe?. Investigate */
+
+        std::function<void(I *svc)> set = {};
+        std::function<void(I *svc, const celix::Properties &props)> setWithProperties = {};
+        std::function<void(I *svc, const celix::Properties &props, const celix::IResourceBundle &owner)> setWithOwner = {};
+
+        std::function<void(I *svc)> add = {};
+        std::function<void(I *svc, const celix::Properties &props)> addWithProperties = {};
+        std::function<void(I *svc, const celix::Properties &props, const celix::IResourceBundle &owner)> addWithOwner = {};
+
+        std::function<void(I *svc)> remove = {};
+        std::function<void(I *svc, const celix::Properties &props)> removeWithProperties = {};
+        std::function<void(I *svc, const celix::Properties &props, const celix::IResourceBundle &owner)> removeWithOwner = {};
+
+        std::function<void(std::vector<I*> rankedServices)> update = {};
+        std::function<void(std::vector<std::tuple<I*, const celix::Properties*>> rankedServices)> updateWithProperties = {};
+        std::function<void(std::vector<std::tuple<I*, const celix::Properties*, const celix::IResourceBundle *>> rankedServices)> updateWithOwner = {};
+    };
+
+    //RAII service tracker: out of scope -> stop tracker
+    // NOTE access not thread safe -> TODO make thread save?
+    class ServiceTracker {
+    public:
+        ServiceTracker();
+        ServiceTracker(ServiceTracker &&rhs) noexcept;
+        ServiceTracker(const ServiceTracker &rhs) = delete;
+        ~ServiceTracker();
+        ServiceTracker& operator=(ServiceTracker &&rhs) noexcept;
+        ServiceTracker& operator=(const ServiceTracker &rhs) = delete;
+
+        int trackCount() const;
+        const std::string& serviceName() const;
+        const std::string& filter() const;
+        bool valid() const;
+
+        //TODO useService(s) calls
+
+        void stop();
+    private:
+        class Impl; //opaque impl class
+        std::unique_ptr<celix::ServiceTracker::Impl> pimpl;
+        explicit ServiceTracker(celix::ServiceTracker::Impl *impl);
+        friend ServiceRegistry;
+    };
+
+    //NOTE access thread safe
+    class ServiceRegistry {
+    public:
+        explicit ServiceRegistry(std::string name);
+        ~ServiceRegistry();
+        ServiceRegistry(celix::ServiceRegistry &&rhs) noexcept;
+        ServiceRegistry& operator=(celix::ServiceRegistry&& rhs);
+        ServiceRegistry& operator=(ServiceRegistry &rhs) = delete;
+        ServiceRegistry(const ServiceRegistry &rhs) = delete;
+
+        const std::string& name() const;
+
+        template<typename I>
+        celix::ServiceRegistration registerService(I &svc, celix::Properties props = {}, std::shared_ptr<const celix::IResourceBundle> owner = {}) {
+            auto svcName = celix::serviceName<I>();
+            auto voidSvc = std::shared_ptr<void>(static_cast<void*>(&svc), [](void*){/*nop*/}); //transform to std::shared_ptr to minimize the underlining impl needed.
+            return registerService(svcName, std::move(voidSvc), std::move(props), std::move(owner));
+        }
+
+        template<typename I>
+        celix::ServiceRegistration registerService(std::shared_ptr<I> svc, celix::Properties props = {}, std::shared_ptr<const celix::IResourceBundle> owner = {}) {
+            //TOOD refactor to using a service factory to store the shared or unique_ptr
+            auto svcName = celix::serviceName<I>();
+            return registerService(svcName, static_cast<std::shared_ptr<void>>(svc), std::move(props), std::move(owner));
+        }
+
+        template<typename F>
+        celix::ServiceRegistration registerFunctionService(const std::string &functionName, F&& func, celix::Properties props = {}, std::shared_ptr<const celix::IResourceBundle> owner = {});
+
+        template<typename I>
+        celix::ServiceRegistration registerServiceFactory(std::shared_ptr<celix::IServiceFactory<I>> factory, celix::Properties props = {}, std::shared_ptr<const celix::IResourceBundle> owner = {});
+
+        template<typename I>
+        //NOTE C++17 typename std::enable_if<!std::is_callable<I>::value, long>::type
+        long findService(const std::string &filter = "") const {
+            auto services = findServices<I>(filter);
+            return services.size() > 0 ? services[0] : -1L;
+        }
+
+        template<typename I>
+        //NOTE C++17 typename std::enable_if<std::is_callable<I>::value, long>::type
+        long findFunctionService(const std::string &functionName, const std::string &filter = "") const {
+            auto services = functionServiceName<I>(functionName, filter);
+            return services.size() > 0 ? services[0] : -1L;
+        }
+
+        template<typename I>
+        //NOTE C++17 typename std::enable_if<!std::is_callable<I>::value, std::vector<long>>::type
+        std::vector<long> findServices(const std::string &filter = "") const {
+            auto svcName = celix::serviceName<I>();
+            return findServices(svcName, filter);
+        }
+
+        template<typename F>
+        //NOTE C++17 typename std::enable_if<std::is_callable<I>::value, std::vector<long>>::type
+        std::vector<long> findFunctionServices(const std::string &functionName, const std::string &filter = "") const {
+            auto svcName = celix::functionServiceName<F>(functionName);
+            return findServices(svcName, filter);
+        }
+
+        template<typename I>
+        celix::ServiceTracker trackServices(celix::ServiceTrackerOptions<I> options = {}, std::shared_ptr<const celix::IResourceBundle> requester = {}) {
+            auto svcName = celix::serviceName<I>();
+            return trackServices<I>(svcName, std::move(options), std::move(requester));
+        }
+
+        template<typename F>
+        celix::ServiceTracker trackFunctionServices(std::string functionName, celix::ServiceTrackerOptions<F> options = {}, std::shared_ptr<const celix::IResourceBundle> requester = {}) {
+            auto svcName = celix::functionServiceName<F>(functionName);
+            return trackServices<F>(svcName, std::move(options), std::move(requester));
+        }
+
+        //TODO trackTrackers
+
+        template<typename I>
+        int useServices(std::function<void(I& svc)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::serviceName<I>();
+            return useServices<I>(svcName, use, nullptr, nullptr, filter, std::move(requester));
+        }
+
+        template<typename I>
+        int useServices(std::function<void(I& svc, const celix::Properties &props)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::serviceName<I>();
+            return useServices<I>(svcName, nullptr, use, nullptr, filter, std::move(requester));
+        }
+
+        template<typename I>
+        int useServices(std::function<void(I& svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::serviceName<I>();
+            return useServices<I>(svcName, nullptr, nullptr, use, filter, std::move(requester));
+        }
+
+        template<typename F>
+        int useFunctionServices(const std::string &functionName, std::function<void(F &function)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::functionServiceName<F>(functionName);
+            return useServices<F>(svcName, use, nullptr, nullptr, filter, std::move(requester));
+        }
+
+        template<typename F>
+        int useFunctionServices(const std::string &functionName, std::function<void(F &function, const celix::Properties&)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::functionServiceName<F>(functionName);
+            return useServices<F>(svcName, nullptr, use, nullptr, filter, std::move(requester));
+        }
+
+        template<typename F>
+        int useFunctionServices(const std::string &functionName, std::function<void(F &function, const celix::Properties&, const celix::IResourceBundle&)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::functionServiceName<F>(functionName);
+            return useServices<F>(svcName, nullptr, nullptr, use, filter, std::move(requester));
+        }
+
+        template<typename I>
+        bool useService(std::function<void(I& svc)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::serviceName<I>();
+            return useService<I>(svcName, use, nullptr, nullptr, filter, std::move(requester));
+        }
+
+        template<typename I>
+        bool useService(std::function<void(I& svc, const celix::Properties &props)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::serviceName<I>();
+            return useService<I>(svcName, nullptr, use, nullptr, filter, std::move(requester));
+        }
+
+        template<typename I>
+        bool useService(std::function<void(I& svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::serviceName<I>();
+            return useService<I>(svcName, nullptr, nullptr, use, filter, std::move(requester));
+        }
+
+        template<typename F>
+        int useFunctionService(const std::string &functionName, std::function<void(F &function)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::functionServiceName<F>(functionName);
+            return useService<F>(svcName, use, nullptr, nullptr, filter, std::move(requester));
+        }
+
+        template<typename F>
+        int useFunctionService(const std::string &functionName, std::function<void(F &function, const celix::Properties&)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::functionServiceName<F>(functionName);
+            return useService<F>(svcName, nullptr, use, nullptr, filter, std::move(requester));
+        }
+
+        template<typename F>
+        int useFunctionService(const std::string &functionName, std::function<void(F &function, const celix::Properties&, const celix::IResourceBundle&)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
+            auto svcName = celix::functionServiceName<F>(functionName);
+            return useService<F>(svcName, nullptr, nullptr, use, filter, std::move(requester));
+        }
+
+
+        long nrOfRegisteredServices() const;
+        long nrOfServiceTrackers() const;
+    private:
+        class Impl;
+        std::unique_ptr<celix::ServiceRegistry::Impl> pimpl;
+
+        //register services
+        celix::ServiceRegistration registerService(std::string svcName, std::shared_ptr<void> svc, celix::Properties props, std::shared_ptr<const celix::IResourceBundle> owner);
+        celix::ServiceRegistration registerServiceFactory(std::string svcName, std::shared_ptr<celix::IServiceFactory<void>> factory, celix::Properties props, std::shared_ptr<const celix::IResourceBundle> owner);
+
+        //use Services
+        template<typename I>
+        int useServices(
+                const std::string &svcName,
+                std::function<void(I &svc)> use,
+                std::function<void(I &svc, const celix::Properties &props)> useWithProps,
+                std::function<void(I &svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> useWithOwner,
+                const std::string &filter,
+                std::shared_ptr<const celix::IResourceBundle> requester) const;
+        int useServices(const std::string &svcName, std::function<void(void *svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> &use, const std::string &filter, std::shared_ptr<const celix::IResourceBundle> requester) const;
+
+        template<typename I>
+        bool useService(
+                const std::string &svcName,
+                std::function<void(I &svc)> use,
+                std::function<void(I &svc, const celix::Properties &props)> useWithProps,
+                std::function<void(I &svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> useWithOwner,
+                const std::string &filter,
+                std::shared_ptr<const celix::IResourceBundle> requester) const;
+        bool useService(const std::string &svcName, std::function<void(void *svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> &use, const std::string &filter, std::shared_ptr<const celix::IResourceBundle> requester) const;
+
+        //find Services
+        std::vector<long> findServices(const std::string &name, const std::string &filter) const;
+
+
+        //track services
+        template<typename I>
+        celix::ServiceTracker trackServices(std::string svcName, celix::ServiceTrackerOptions<I> options, std::shared_ptr<const celix::IResourceBundle> requester);
+        celix::ServiceTracker trackServices(std::string svcName, ServiceTrackerOptions<void> options, std::shared_ptr<const celix::IResourceBundle> requester);
+    };
+}
+
+
+template<typename F>
+inline celix::ServiceRegistration celix::ServiceRegistry::registerFunctionService(const std::string &functionName, F&& func, celix::Properties props, std::shared_ptr<const celix::IResourceBundle> owner) {
+    class FunctionServiceFactory : public celix::IServiceFactory<void> {
+    public:
+        FunctionServiceFactory(F&& _function) : function{std::forward<F>(_function)} {}
+
+        void* getService(const celix::IResourceBundle &, const celix::Properties &) noexcept override {
+            return static_cast<void*>(&function);
+        }
+        void ungetService(const celix::IResourceBundle &, const celix::Properties &) noexcept override {
+            //nop;
+        }
+    private:
+        F function;
+    };
+    auto factory = std::shared_ptr<celix::IServiceFactory<void>>{new FunctionServiceFactory{std::forward<F>(func)}};
+
+    std::string svcName = celix::functionServiceName<typename std::remove_reference<F>::type>(functionName);
+
+    return registerServiceFactory(std::move(svcName), factory, std::move(props), std::move(owner));
+}
+
+template<typename I>
+inline celix::ServiceRegistration celix::ServiceRegistry::registerServiceFactory(std::shared_ptr<celix::IServiceFactory<I>> factory, celix::Properties props, std::shared_ptr<const celix::IResourceBundle> owner) {
+    std::string svcName = celix::serviceName<I>();
+
+    class VoidServiceFactory : public celix::IServiceFactory<void> {
+    public:
+        VoidServiceFactory(std::shared_ptr<celix::IServiceFactory<I>> _factory) : factory{std::move(_factory)} {}
+
+        void* getService(const celix::IResourceBundle &bnd, const celix::Properties &props) noexcept override {
+            I* service = factory->getService(bnd, props);
+            return static_cast<void*>(service);
+        }
+        void ungetService(const celix::IResourceBundle &bnd, const celix::Properties &props) noexcept override {
+            factory->ungetService(bnd, props);
+        }
+    private:
+        std::shared_ptr<celix::IServiceFactory<I>> factory;
+    };
+
+    auto voidFactory = std::shared_ptr<celix::IServiceFactory<void>>{new VoidServiceFactory{std::move(factory)}};
+    return registerServiceFactory(std::move(svcName), std::move(voidFactory), std::move(props), std::move(owner));
+}
+
+template<typename I>
+inline int celix::ServiceRegistry::useServices(
+        const std::string &svcName,
+        std::function<void(I &svc)> use,
+        std::function<void(I &svc, const celix::Properties &props)> useWithProps,
+        std::function<void(I &svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> useWithOwner,
+        const std::string &filter,
+        std::shared_ptr<const celix::IResourceBundle> requester) const {
+    std::function<void(void*,const celix::Properties&, const celix::IResourceBundle&)> voidUse = [&](void *svc, const celix::Properties &props, const celix::IResourceBundle &bnd) {
+        I* typedSvc = static_cast<I*>(svc);
+        if (use) {
+            use(*typedSvc);
+        }
+        if (useWithProps) {
+            useWithProps(*typedSvc, props);
+        }
+        if (useWithOwner) {
+            useWithOwner(*typedSvc, props, bnd);
+        }
+    };
+    return useServices(svcName, voidUse, filter, requester);
+}
+
+template<typename I>
+inline bool celix::ServiceRegistry::useService(
+        const std::string &svcName,
+        std::function<void(I &svc)> use,
+        std::function<void(I &svc, const celix::Properties &props)> useWithProps,
+        std::function<void(I &svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> useWithOwner,
+        const std::string &filter,
+        std::shared_ptr<const celix::IResourceBundle> requester) const {
+    std::function<void(void*,const celix::Properties&, const celix::IResourceBundle&)> voidUse = [&](void *svc, const celix::Properties &props, const celix::IResourceBundle &bnd) -> void {
+        I* typedSvc = static_cast<I*>(svc);
+        if (use) {
+            use(*typedSvc);
+        }
+        if (useWithProps) {
+            useWithProps(*typedSvc, props);
+        }
+        if (useWithOwner) {
+            useWithOwner(*typedSvc, props, bnd);
+        }
+    };
+    return useService(svcName, voidUse, filter, requester);
+}
+
+template<typename I>
+inline celix::ServiceTracker celix::ServiceRegistry::trackServices(std::string svcName, const celix::ServiceTrackerOptions<I> options, std::shared_ptr<const celix::IResourceBundle> requester) {
+    ServiceTrackerOptions<void> opts{};
+    opts.filter = std::move(options.filter);
+
+    if (options.set != nullptr) {
+        auto set = std::move(options.set);
+        opts.set = [set](void *svc){
+            I *typedSvc = static_cast<I*>(svc);
+            set(typedSvc);
+        };
+    }
+    if (options.setWithProperties != nullptr) {
+        auto set = std::move(options.setWithProperties);
+        opts.setWithProperties = [set](void *svc, const celix::Properties &props){
+            I *typedSvc = static_cast<I*>(svc);
+            set(typedSvc, props);
+        };
+    }
+    if (options.setWithOwner != nullptr) {
+        auto set = std::move(options.setWithOwner);
+        opts.setWithOwner = [set](void *svc, const celix::Properties &props, const celix::IResourceBundle &owner){
+            I *typedSvc = static_cast<I*>(svc);
+            set(typedSvc, props, owner);
+        };
+    }
+
+    if (options.add != nullptr) {
+        auto add = std::move(options.add);
+        opts.add = [add](void *svc) {
+            I *typedSvc = static_cast<I*>(svc); //note actual argument is I*
+            add(typedSvc);
+        };
+    }
+    if (options.addWithProperties != nullptr) {
+        auto add = std::move(options.addWithProperties);
+        opts.addWithProperties = [add](void *svc, const celix::Properties &props) {
+            I *typedSvc = static_cast<I*>(svc); //note actual argument is I*
+            add(typedSvc, props);
+        };
+    }
+    if (options.addWithOwner != nullptr) {
+        auto add = std::move(options.addWithOwner);
+        opts.addWithOwner = [add](void *svc, const celix::Properties &props, const celix::IResourceBundle &bnd) {
+            I *typedSvc = static_cast<I*>(svc); //note actual argument is I*
+            add(typedSvc, props, bnd);
+        };
+    }
+
+    if (options.remove != nullptr) {
+        auto rem = std::move(options.remove);
+        opts.remove = [rem](void *svc) {
+            I *typedSvc = static_cast<I*>(svc); //note actual argument is I*
+            rem(typedSvc);
+        };
+    }
+    if (options.removeWithProperties != nullptr) {
+        auto rem = std::move(options.removeWithProperties);
+        opts.removeWithProperties = [rem](void *svc, const celix::Properties &props) {
+            I *typedSvc = static_cast<I*>(svc); //note actual argument is I*
+            rem(typedSvc, props);
+        };
+    }
+    if (options.removeWithOwner != nullptr) {
+        auto rem = std::move(options.removeWithOwner);
+        opts.removeWithOwner = [rem](void *svc, const celix::Properties &props, const celix::IResourceBundle &bnd) {
+            I *typedSvc = static_cast<I*>(svc); //note actual argument is I*
+            rem(typedSvc, props, bnd);
+        };
+    }
+
+    if (options.update != nullptr) {
+        auto update = std::move(options.update);
+        opts.update = [update](std::vector<void*> rankedServices) {
+            std::vector<I*> typedServices{};
+            typedServices.reserve(rankedServices.size());
+            for (void *svc : rankedServices) {
+                typedServices.push_back(static_cast<I*>(svc));
+            }
+            update(std::move(typedServices));
+        };
+    }
+    if (options.updateWithProperties != nullptr) {
+        auto update = std::move(options.updateWithProperties);
+        opts.updateWithProperties = [update](std::vector<std::tuple<void*, const celix::Properties *>> rankedServices) {
+            std::vector<std::tuple<I*, const celix::Properties*>> typedServices{};
+            typedServices.reserve(rankedServices.size());
+            for (auto &tuple : rankedServices) {
+                typedServices.push_back(std::make_tuple(static_cast<I*>(std::get<0>(tuple)), std::get<1>(tuple)));
+            }
+            update(std::move(typedServices));
+        };
+    }
+    if (options.updateWithOwner != nullptr) {
+        auto update = std::move(options.updateWithOwner);
+        opts.updateWithOwner = [update](std::vector<std::tuple<void*, const celix::Properties *, const celix::IResourceBundle*>> rankedServices) {
+            std::vector<std::tuple<I*, const celix::Properties*, const celix::IResourceBundle*>> typedServices{};
+            typedServices.reserve(rankedServices.size());
+            for (auto &tuple : rankedServices) {
+                typedServices.push_back(std::make_tuple(static_cast<I*>(std::get<0>(tuple)), std::get<1>(tuple), std::get<2>(tuple)));
+            }
+            update(std::move(typedServices));
+        };
+    }
+
+    return trackServices(std::move(svcName), std::move(opts), requester);
+}
+
+#endif //CXX_CELIX_SERVICEREGISTRY_H
diff --git a/libs/registry/include/celix/Utils.h b/libs/registry/include/celix/Utils.h
new file mode 100644
index 0000000..ae61cd7
--- /dev/null
+++ b/libs/registry/include/celix/Utils.h
@@ -0,0 +1,102 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CXX_CELIX_UTILS_H
+#define CXX_CELIX_UTILS_H
+
+
+#include <string>
+#include <iostream>
+
+namespace {
+
+    template<typename INTERFACE_TYPENAME>
+    std::string typeName() {
+        std::string result;
+
+        const char *templateStr = "INTERFACE_TYPENAME = ";
+        const size_t templateStrLen = strlen(templateStr);
+
+        result = __PRETTY_FUNCTION__; //USING pretty function to retrieve the filled in template argument without using typeid()
+        size_t bpos = result.find(templateStr) + templateStrLen; //find begin pos after INTERFACE_TYPENAME = entry
+        size_t epos = bpos;
+        while (isalnum(result[epos]) || result[epos] == '_' || result[epos] == ':' || result[epos] == ' ' || result[epos] == '*' || result[epos] == '&' || result[epos] == '<' || result[epos] == '>') {
+            epos += 1;
+        }
+        size_t len = epos - bpos;
+        result = result.substr(bpos, len);
+
+        if (result.empty()) {
+            std::cerr << "Cannot infer type name in function call '" << __PRETTY_FUNCTION__ << "'\n'";
+        }
+
+        return result;
+    }
+
+    template<typename Arg>
+    std::string argName() {
+        return typeName<Arg>(); //terminal;
+    }
+
+    template<typename Arg1, typename Arg2, typename... Args>
+    std::string argName() {
+        return typeName<Arg1>() + ", " + argName<Arg2, Args...>();
+    }
+
+    template<typename R>
+    std::string functionName(const std::string &funcName) {
+        return funcName + " [std::function<" + typeName<R>() + "()>]";
+    }
+
+    template<typename R, typename Arg1, typename... Args>
+    std::string functionName(const std::string &funcName) {
+        return funcName + " [std::function<" + typeName<R>() + "("  + argName<Arg1, Args...>() + ")>]";
+    }
+};
+
+namespace celix {
+
+    /* TODO
+    template<typename I>
+    typename std::enable_if<I::FQN, std::string>::type
+    serviceName() {
+        return I::FQN;
+    }*/
+
+    /**
+    * Returns the service name for a type I
+    */
+    template<typename I>
+    //NOTE C++17 typename std::enable_if<!std::is_callable<I>::value, std::string>::type
+    std::string serviceName() {
+        return typeName<I>();
+    }
+
+    /**
+    * Returns the service name for a std::function I.
+    * Note that for a std::function the additional function name is needed to get a fully qualified service name;
+    */
+    template<typename F>
+    //NOTE C++17 typename std::enable_if<std::is_callable<I>::value, std::string>::type
+    std::string functionServiceName(const std::string &fName) {
+        return functionName<decltype(&F::operator())>(fName);
+    }
+}
+
+#endif //CXX_CELIX_UTILS_H
diff --git a/libs/registry/src/Filter.cc b/libs/registry/src/Filter.cc
new file mode 100644
index 0000000..b92cf32
--- /dev/null
+++ b/libs/registry/src/Filter.cc
@@ -0,0 +1,464 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "celix/Filter.h"
+
+#include <glog/logging.h>
+
+static celix::FilterCriteria* filter_parseFilter(const char *filterString, int *pos);
+static void filter_skipWhiteSpace(const char *filterString, int *pos);
+static celix::FilterCriteria* filter_parseAndOrOr(const char *filterString, celix::FilterOperator andOrOr, int *pos);
+static celix::FilterCriteria* filter_parseFilterComp(const char *filterString, int *pos);
+static celix::FilterCriteria* filter_parseItem(const char *filterString, int *pos);
+static std::string filter_parseAttr(const char *filterString, int *pos);
+static std::string filter_parseValue(const char *filterString, int *pos);
+
+static void filter_skipWhiteSpace(const char *filterString, int *pos) {
+    size_t length;
+    for (length = strlen(filterString); (*pos < (int)(length)) && isspace(filterString[*pos]);) {
+        (*pos)++;
+    }
+}
+
+static celix::FilterCriteria* filter_parseAndOrOr(const char *filterString, celix::FilterOperator andOrOr, int *pos) {
+
+    filter_skipWhiteSpace(filterString, pos);
+    bool failure = false;
+
+    if (filterString[*pos] != '(') {
+        LOG(ERROR) << "Filter Error: Missing '('.\n";
+        return nullptr;
+    }
+
+    std::vector<std::shared_ptr<celix::FilterCriteria>> subcriteria{};
+    while (filterString[*pos] == '(') {
+        celix::FilterCriteria *cr = filter_parseFilter(filterString, pos);
+        if (cr == nullptr) {
+            failure = true;
+            break;
+        }
+        subcriteria.push_back(std::unique_ptr<celix::FilterCriteria>{cr});
+    }
+
+
+    celix::FilterCriteria* criteria = nullptr;
+    if (!failure) {
+        criteria = new celix::FilterCriteria{
+            .attribute = "",
+            .op = andOrOr,
+            .value = "",
+            .subcriteria = std::move(subcriteria)
+        };
+    }
+
+    return criteria;
+}
+
+static celix::FilterCriteria* filter_parseNot(const char * filterString, int * pos) {
+    celix::FilterCriteria *criteria = nullptr;
+
+    filter_skipWhiteSpace(filterString, pos);
+    if (filterString[*pos] != '(') {
+        LOG(ERROR) << "Filter Error: Missing '('.\n";
+        return nullptr;
+    }
+
+    std::vector<std::shared_ptr<celix::FilterCriteria>> subcriteria{};
+    celix::FilterCriteria *cr = filter_parseFilter(filterString, pos);
+    if (cr != nullptr) {
+        subcriteria.push_back(std::unique_ptr<celix::FilterCriteria>(cr));
+        criteria = new celix::FilterCriteria {
+            .attribute = "",
+            .op = celix::FilterOperator::NOT,
+            .value = "",
+            .subcriteria = std::move(subcriteria)
+        };
+    }
+
+    return criteria;
+}
+
+static std::string filter_parseAttr(const char *filterString, int *pos) {
+    std::string attr{};
+    char c;
+    int begin = *pos;
+    int end = *pos;
+    int length = 0;
+
+    filter_skipWhiteSpace(filterString, pos);
+    c = filterString[*pos];
+
+    while (c != '~' && c != '<' && c != '>' && c != '=' && c != '(' && c != ')') {
+        (*pos)++;
+
+        if (!isspace(c)) {
+            end = *pos;
+        }
+
+        c = filterString[*pos];
+    }
+
+    length = end - begin;
+
+    if (length == 0) {
+        LOG(ERROR) << "Filter Error: Missing attr.\n";
+    } else {
+        attr.assign(filterString+begin, (size_t)length);
+    }
+
+    return attr;
+}
+
+static std::string filter_parseValue(const char *filterString, int *pos) {
+    std::string val{};
+    int keepRunning = 1;
+
+    while (keepRunning) {
+        char c = filterString[*pos];
+
+        switch (c) {
+            case ')': {
+                keepRunning = 0;
+                break;
+            }
+            case '(': {
+                LOG(ERROR) << "Filter Error: Invalid value.\n";
+                val = "";
+                keepRunning = 0;
+                break;
+            }
+            case '\0':{
+                LOG(ERROR) << "Filter Error: Unclosed bracket.\n";
+                val = "";
+                keepRunning = 0;
+                break;
+            }
+            case '\\': {
+                (*pos)++;
+                c = filterString[*pos];
+                char ch[2];
+                ch[0] = c;
+                ch[1] = '\0';
+                val.append(ch);
+                (*pos)++;
+                break;
+            }
+            default: {
+                char ch[2];
+                ch[0] = c;
+                ch[1] = '\0';
+                val.append(ch);
+                (*pos)++;
+                break;
+            }
+        }
+    }
+
+    if (val.empty()) {
+        LOG(ERROR) << "Filter Error: Missing value.\n";
+    }
+    return val;
+}
+
+static celix::FilterCriteria* filter_parseItem(const char * filterString, int * pos) {
+    celix::FilterCriteria* criteria = nullptr;
+
+    std::string attr = filter_parseAttr(filterString, pos);
+    if (attr.empty()) {
+        return nullptr;
+    }
+
+    filter_skipWhiteSpace(filterString, pos);
+    switch(filterString[*pos]) {
+        case '~': {
+            if (filterString[*pos + 1] == '=') {
+                *pos += 2; //skip ~=
+                std::string val = filter_parseValue(filterString, pos);
+                if (val.empty()) {
+                    LOG(ERROR) << "Unexpected emtpy value after ~= operator in filter '" << filterString << "'\n";
+                } else {
+                    criteria = new celix::FilterCriteria{
+                            .attribute = std::move(attr),
+                            .op = celix::FilterOperator::APPROX,
+                            .value = std::move(val),
+                            .subcriteria = {}
+                    };
+                }
+            } else {
+                LOG(ERROR) << "Unexpected ~ char without the expected = in filter '" << filterString << "'\n";
+            }
+            break;
+        }
+        case '>': {
+            auto op = celix::FilterOperator::GREATER;
+            if (filterString[*pos + 1] == '=') {
+                *pos += 2; //skip >=
+                op = celix::FilterOperator::GREATER_EQUAL;
+            } else {
+                *pos += 1; //skip >
+            }
+            std::string val = filter_parseValue(filterString, pos);
+            if (val.empty()) {
+                LOG(ERROR) << "Unexpected empty value in > or >= operator for filter '" << filterString << "'\n";
+            } else {
+                criteria = new celix::FilterCriteria{
+                        .attribute = std::move(attr),
+                        .op = op,
+                        .value = std::move(val),
+                        .subcriteria = {}
+                };
+            }
+            break;
+        }
+        case '<': {
+            celix::FilterOperator op = celix::FilterOperator::LESS;
+            if (filterString[*pos + 1] == '=') {
+                *pos += 2; //skip <=
+                op = celix::FilterOperator::LESS_EQUAL;
+            } else {
+                *pos += 1; //skip <
+            }
+            std::string val = filter_parseValue(filterString, pos);
+            if (val.empty()) {
+                LOG(ERROR) << "Unexpected emtpy value after < or <= operator in filter '" << filterString <<"'\n";
+            } else {
+                criteria = new celix::FilterCriteria {
+                        .attribute = std::move(attr),
+                        .op = op,
+                        .value = std::move(val),
+                        .subcriteria = {}
+                };
+            }
+            break;
+        }
+        case '=': {
+            if (filterString[*pos + 1] == '*') {
+                int oldPos = *pos;
+                *pos += 2; //skip =*
+                filter_skipWhiteSpace(filterString, pos);
+                if (filterString[*pos] == ')') {
+                    criteria = new celix::FilterCriteria{
+                            .attribute = attr,
+                            .op = celix::FilterOperator::PRESENT,
+                            .value = "",
+                            .subcriteria = {}
+                    };
+                } else {
+                    *pos = oldPos; //no present criteria -> reset
+                }
+            }
+            if (criteria == nullptr) { //i.e. no present criteria set
+                //note that the value can start and end with a wildchar *. this is not parsed specifically, but tested
+                *pos += 1; //skip =
+                filter_skipWhiteSpace(filterString, pos);
+                std::string val = filter_parseValue(filterString, pos);
+                bool substring = val.size() > 2 && (val.front() == '*' || val.back() == '*');
+                if (val.empty()) {
+                    LOG(ERROR) << "Unexpected emtpy value after = operator in filter '" << filterString << "'\n";
+                } else {
+                    criteria = new celix::FilterCriteria{
+                            .attribute = std::move(attr),
+                            .op = substring ? celix::FilterOperator::SUBSTRING : celix::FilterOperator::EQUAL,
+                            .value = std::move(val),
+                            .subcriteria = {}
+                    };
+                }
+            }
+            break;
+        }
+        default: {
+            LOG(ERROR) << "Unexpected operator " << *pos << std::endl;
+            break;
+        }
+    }
+
+    if (criteria == nullptr) {
+        LOG(ERROR) << "Filter Error: Invalid operator.\n";
+    }
+
+    return criteria;
+}
+
+static celix::FilterCriteria* filter_parseFilterComp(const char *filterString, int *pos) {
+    celix::FilterCriteria* criteria = nullptr;
+    char c;
+    filter_skipWhiteSpace(filterString, pos);
+
+    c = filterString[*pos];
+
+    switch (c) {
+        case '&': {
+            (*pos)++;
+            criteria = filter_parseAndOrOr(filterString, celix::FilterOperator::AND, pos);
+            break;
+        }
+        case '|': {
+            (*pos)++;
+            criteria = filter_parseAndOrOr(filterString, celix::FilterOperator::OR, pos);
+            break;
+        }
+        case '!': {
+            (*pos)++;
+            criteria = filter_parseNot(filterString, pos);
+            break;
+        }
+        default : {
+            criteria =filter_parseItem(filterString, pos);
+            break;
+        }
+    }
+    return criteria;
+}
+
+
+static celix::FilterCriteria* filter_parseFilter(const char *filterString, int *pos) {
+    celix::FilterCriteria *criteria = nullptr;
+    filter_skipWhiteSpace(filterString, pos);
+    if (filterString[*pos] != '(') {
+        LOG(ERROR) << "Filter Error: Missing '(' in filter string '" << filterString << "'.\n";
+        return NULL;
+    }
+    (*pos)++; //consume (
+
+    criteria = filter_parseFilterComp(filterString, pos);
+
+    filter_skipWhiteSpace(filterString, pos);
+
+    if (filterString[*pos] != ')') {
+        LOG(ERROR) << "Filter Error: Missing ')' in filter string '" << filterString << "'.\n";
+        if (criteria != NULL) {
+            delete criteria;
+        }
+        return NULL;
+    }
+    (*pos)++;
+    filter_skipWhiteSpace(filterString, pos);
+
+    return criteria;
+}
+
+celix::FilterCriteria* celix::Filter::parseFilter() {
+    celix::FilterCriteria* criteria = nullptr;
+    if (!filterStr.empty()) {
+        int pos = 0;
+        criteria = filter_parseFilter(filterStr.c_str(), &pos);
+        if (criteria != nullptr && pos != (int) filterStr.size()) {
+            LOG(ERROR) << "Filter Error: Missing '(' in filter string '" << filterStr << "'.'n";
+            delete criteria;
+            criteria = nullptr;
+        }
+    }
+    return criteria;
+}
+
+static bool match_criteria(const celix::Properties &props, const celix::FilterCriteria &criteria) {
+    bool result;
+    switch (criteria.op) {
+        case celix::FilterOperator::AND: {
+            result = true;
+            for (const auto &sc : criteria.subcriteria) {
+                if (!match_criteria(props, *sc)) {
+                    result = false;
+                    break;
+                }
+            }
+            break;
+        }
+        case celix::FilterOperator::OR: {
+            result = false;
+            for (const auto &sc : criteria.subcriteria) {
+                if (match_criteria(props, *sc)) {
+                    result = true;
+                    break;
+                }
+            }
+            break;
+        }
+        case celix::FilterOperator::NOT: {
+            result = !match_criteria(props, *criteria.subcriteria[0]);
+            break;
+        }
+        case celix::FilterOperator::SUBSTRING: {
+            const std::string &val = celix::getProperty(props, criteria.attribute, "");
+            if (val.empty()) {
+                result = false;
+            } else {
+                bool wildcharAtFront = criteria.value.front() == '*';
+                bool wildcharAtBack = criteria.value.back() == '*';
+                std::string needle = wildcharAtFront ? criteria.value.substr(1) : criteria.value;
+                needle = wildcharAtBack ? needle.substr(0, needle.size() - 1) : needle;
+                const char *ptr = strstr(val.c_str(), needle.c_str());
+                if (wildcharAtFront && wildcharAtBack) {
+                    result = ptr != nullptr;
+                } else if (wildcharAtFront) { //-> end must match
+                    result = ptr != nullptr && ptr + strlen(ptr) == val.c_str() + strlen(val.c_str());
+                } else { //wildCharAtBack -> begin must match
+                    result = ptr != nullptr && ptr == val.c_str();
+                }
+            }
+            break;
+        }
+        case celix::FilterOperator::EQUAL: {
+            const std::string &val = celix::getProperty(props, criteria.attribute, "");
+            result = !val.empty() && val == criteria.value;
+            break;
+        }
+        case celix::FilterOperator::GREATER_EQUAL: {
+            const std::string &val = celix::getProperty(props, criteria.attribute, "");
+            result = !val.empty() && val >= criteria.value;
+            break;
+        }
+        case celix::FilterOperator::LESS: {
+            const std::string &val = celix::getProperty(props, criteria.attribute, "");
+            result = !val.empty() && val < criteria.value;
+            break;
+        }
+        case celix::FilterOperator::LESS_EQUAL: {
+            const std::string &val = celix::getProperty(props, criteria.attribute, "");
+            result = !val.empty() && val <= criteria.value;
+            break;
+        }
+        case celix::FilterOperator::PRESENT: {
+            const std::string &val = celix::getProperty(props, criteria.attribute, "");
+            result = !val.empty();
+            break;
+        }
+        case celix::FilterOperator::APPROX: {
+            const std::string &val = celix::getProperty(props, criteria.attribute, "");
+            result = !val.empty() && strcasecmp(val.c_str(), criteria.value.c_str()) == 0;
+            break;
+        }
+        default: {
+            result = false;
+            break;
+        }
+    }
+
+    return result;
+}
+
+bool celix::Filter::match(const celix::Properties &props) const {
+    if (!valid()) {
+        return false;
+    } else if (filterStr.empty()) {
+        return true;
+    }
+
+    return match_criteria(props, *criteria);
+}
\ No newline at end of file
diff --git a/libs/registry/src/ServiceRegistry.cc b/libs/registry/src/ServiceRegistry.cc
new file mode 100644
index 0000000..862013f
--- /dev/null
+++ b/libs/registry/src/ServiceRegistry.cc
@@ -0,0 +1,716 @@
+#include <utility>
+
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <unordered_map>
+#include <mutex>
+#include <set>
+#include <utility>
+#include <thread>
+
+#include <glog/logging.h>
+
+#include "celix/Constants.h"
+#include "celix/ServiceRegistry.h"
+#include "celix/Filter.h"
+
+static std::string emptyString{};
+
+namespace {
+
+    class EmptyBundle : public celix::IResourceBundle {
+    public:
+        ~EmptyBundle() override = default;
+
+        long id() const noexcept override { return 0; }
+
+        const std::string& root() const noexcept override {
+            static std::string empty{};
+            return empty;
+        }
+
+        bool has(const std::string&) const noexcept override { return false; }
+        bool isDir(const std::string&) const noexcept override { return false; }
+        bool isFile(const std::string&) const noexcept override { return false; }
+
+        //std::istream& open(const std::string &path) override {}
+        //std::fstream& open(const std::string &path) override {}
+        std::vector<std::string> readDir(const std::string&) const noexcept override { return std::vector<std::string>{};}
+    };
+
+    struct SvcEntry {
+        explicit SvcEntry(std::shared_ptr<const celix::IResourceBundle> _owner, long _svcId, std::string _svcName, std::shared_ptr<void> _svc, std::shared_ptr<celix::IServiceFactory<void>> _svcFac,
+                 celix::Properties &&_props) :
+                owner{std::move(_owner)}, svcId{_svcId}, svcName{std::move(_svcName)},
+                props{std::forward<celix::Properties>(_props)},
+                ranking{celix::getProperty(props, celix::SERVICE_RANKING, 0L)},
+                svc{_svc}, svcFactory{_svcFac} {}
+
+        SvcEntry(SvcEntry &&rhs) = delete;
+        SvcEntry &operator=(SvcEntry &&rhs) = delete;
+        SvcEntry(const SvcEntry &rhs) = delete;
+        SvcEntry &operator=(const SvcEntry &rhs) = delete;
+
+        const std::shared_ptr<const celix::IResourceBundle> owner;
+        const long svcId;
+        const std::string svcName;
+        const celix::Properties props;
+        const long ranking;
+
+        void *service(const celix::IResourceBundle &requester) const {
+            if (svcFactory) {
+                return svcFactory->getService(requester, props);
+            } else {
+                return svc.get();
+            }
+        }
+
+        bool factory() const { return svcFactory != nullptr; }
+
+        void incrUsage() const {
+            LOG(WARNING) << "TODO use shared_ptr unique instead ?? how to sync?";
+            std::lock_guard<std::mutex> lck{mutex};
+            usage += 1;
+        }
+
+        void decrUsage() const {
+            LOG(WARNING) << "TODO use shared_ptr unique instead ?? how is sync?";
+            std::lock_guard<std::mutex> lck{mutex};
+            usage -= 1;
+            cond.notify_all();
+        }
+
+        void waitTillUnused() const {
+            std::unique_lock<std::mutex> lock{mutex};
+            cond.wait(lock, [this]{return usage == 0;});
+        }
+    private:
+        //svc, svcSharedPtr or svcFactory is set
+        const std::shared_ptr<void> svc;
+        const std::shared_ptr<celix::IServiceFactory<void>> svcFactory;
+
+
+        //sync TODO refactor to atomics
+        mutable std::mutex mutex{};
+        mutable std::condition_variable cond{};
+        mutable int usage{1};
+    };
+
+    struct SvcEntryLess {
+        bool operator()( const std::shared_ptr<const SvcEntry>& lhs, const std::shared_ptr<const SvcEntry>& rhs ) const {
+            if (lhs->ranking == rhs->ranking) {
+                return lhs->svcId < rhs->svcId;
+            } else {
+                return lhs->ranking > rhs->ranking; //note inverse -> higher rank first in set
+            }
+        }
+    };
+
+    struct SvcTrackerEntry {
+        const long id;
+        const std::shared_ptr<const celix::IResourceBundle> owner;
+        const std::string svcName;
+        const celix::ServiceTrackerOptions<void> opts;
+        const celix::Filter filter;
+
+        explicit SvcTrackerEntry(long _id, std::shared_ptr<const celix::IResourceBundle> _owner, std::string _svcName, celix::ServiceTrackerOptions<void> _opts) :
+            id{_id}, owner{std::move(_owner)}, svcName{std::move(_svcName)}, opts{std::move(_opts)}, filter{opts.filter} {}
+
+        SvcTrackerEntry(SvcTrackerEntry &&rhs) = delete;
+        SvcTrackerEntry &operator=(SvcTrackerEntry &&rhs) = delete;
+        SvcTrackerEntry(const SvcTrackerEntry &rhs) = delete;
+        SvcTrackerEntry &operator=(const SvcTrackerEntry &rhs) = delete;
+        ~SvcTrackerEntry() {}
+
+        void clear() {
+            //TODO update, make special rem (e.g. only call the use set callbacks once with a nullptr)
+            std::vector<std::shared_ptr<const SvcEntry>> removeEntries{};
+            {
+                std::lock_guard<std::mutex> lck{tracked.mutex};
+                for (auto &entry : tracked.entries) {
+                    removeEntries.push_back(entry);
+                }
+                tracked.entries.clear();
+            }
+            for (auto &entry : removeEntries) {
+                remMatch(entry); //note fill try to erase entry from entries again, TODO check if this is safe
+            }
+        }
+
+        bool valid() const {
+            return !svcName.empty() && filter.valid();
+        }
+
+        bool match(const SvcEntry& entry) const {
+            //note should only called for the correct svcName
+            assert(svcName == entry.svcName);
+
+            if (filter.empty()) {
+                return true;
+            } else {
+                return filter.match(entry.props);
+            }
+        }
+
+        void addMatch(std::shared_ptr<const SvcEntry> entry) {
+            //increase usage so that services cannot be removed while a service tracker is still active
+            entry->incrUsage();
+
+            {
+                std::lock_guard<std::mutex> lck{tracked.mutex};
+                tracked.entries.insert(entry);
+            }
+
+            //call callbacks
+            callSetCallbacks();
+            callAddRemoveCallbacks(entry, true);
+            callUpdateCallbacks();
+        }
+
+        void remMatch(const std::shared_ptr<const SvcEntry> &entry) {
+            {
+                std::lock_guard<std::mutex> lck{tracked.mutex};
+                tracked.entries.erase(entry);
+            }
+
+            //call callbacks
+            callSetCallbacks();
+            callAddRemoveCallbacks(entry, false);
+            callUpdateCallbacks();
+
+            //decrease usage so that services cannot be removed while a service tracker is still active
+            entry->decrUsage();
+        }
+
+        void callAddRemoveCallbacks(const std::shared_ptr<const SvcEntry> &updatedEntry, bool add) {
+            auto &update = add ? opts.add : opts.remove;
+            if (update != nullptr) {
+                void *svc = updatedEntry->service(*owner);
+                update(svc);
+            }
+            //TODO rest of add/remove
+        }
+
+        void callSetCallbacks() {
+            std::shared_ptr<const SvcEntry> currentHighest;
+            bool highestUpdated = false;
+            {
+                std::lock_guard<std::mutex> lck{tracked.mutex};
+                auto begin = tracked.entries.begin();
+                if (begin == tracked.entries.end()) {
+                    currentHighest = nullptr;
+                } else {
+                    currentHighest = *begin;
+                }
+                if (currentHighest != tracked.highest) {
+                    tracked.highest = currentHighest;
+                    highestUpdated = true;
+                }
+            }
+
+            //TODO race condition. highest can be updated because lock is released.
+
+            if (highestUpdated) {
+                void *svc = currentHighest == nullptr ? nullptr : currentHighest->service(*owner);
+                if (opts.set != nullptr) {
+                    opts.set(svc);
+                }
+                //TODO rest of set
+            }
+        }
+
+        void callUpdateCallbacks() {
+            if (opts.update) {
+                std::vector<void *> rankedServices{};
+                {
+                    std::lock_guard<std::mutex> lck{tracked.mutex};
+                    rankedServices.reserve(tracked.entries.size());
+                    for (auto &tracked : tracked.entries) {
+                        rankedServices.push_back(tracked->service(*owner));
+                    }
+                }
+                opts.update(std::move(rankedServices));
+            }
+            //TODO rest of the update calls
+        }
+
+        int count() const {
+            LOG(INFO) << "TODO use shared_ptr count instead";
+            std::lock_guard<std::mutex> lck{tracked.mutex};
+            return (int)tracked.entries.size();
+        }
+
+        void incrUsage() const {
+            LOG(INFO) << "TODO use shared_ptr count instead";
+            std::lock_guard<std::mutex> lck{mutex};
+            usage += 1;
+        }
+
+        void decrUsage() const {
+            LOG(INFO) << "TODO use shared_ptr count instead";
+            std::lock_guard<std::mutex> lck{mutex};
+            usage -= 1;
+            cond.notify_all();
+        }
+
+        void waitTillUnused() const {
+            std::unique_lock<std::mutex> lock{mutex};
+            cond.wait(lock, [this]{return usage == 0;});
+        }
+    private:
+        struct {
+            mutable std::mutex mutex; //protects matchedEntries & highestRanking
+            std::set<std::shared_ptr<const SvcEntry>, SvcEntryLess> entries{};
+            std::shared_ptr<const SvcEntry> highest{};
+        } tracked{};
+
+
+        //sync TODO refactor to atomics
+        mutable std::mutex mutex{};
+        mutable std::condition_variable cond{};
+        mutable int usage{1};
+    };
+}
+
+/**********************************************************************************************************************
+  Impl classes
+ **********************************************************************************************************************/
+
+class celix::ServiceRegistration::Impl {
+public:
+    const std::shared_ptr<const SvcEntry> entry;
+    const std::function<void()> unregisterCallback;
+    bool registered; //TODO make atomic?
+};
+
+class celix::ServiceTracker::Impl {
+public:
+    const std::shared_ptr<SvcTrackerEntry> entry;
+    const std::function<void()> untrackCallback;
+    bool active; //TODO make atomic?
+};
+
+class celix::ServiceRegistry::Impl {
+public:
+    const std::shared_ptr<const celix::IResourceBundle> emptyBundle = std::shared_ptr<const celix::IResourceBundle>{new EmptyBundle{}};
+    std::string regName;
+
+    struct {
+        mutable std::mutex mutex{};
+        long nextSvcId = 1L;
+
+        /* Services entries are always stored for it specific svc name.
+         * When using services is it always expected that the svc name is provided, and as such
+         * storing per svc name is more logical.
+         *
+         * Note that this also means that the classic 99% use cases used OSGi filter (objectClass=<svcName>)
+         * is not needed anymore -> simpler and faster.
+         *
+         * map key is svcName and the map value is a set of SvcEntry structs.
+         * note: The SvcEntry set is ordered (i.e. not a hashset with O(1) access) to ensure that service ranking and
+         * service id can be used for their position in the set (see SvcEntryLess).
+         */
+        std::unordered_map<std::string, std::set<std::shared_ptr<const SvcEntry>, SvcEntryLess>> registry{};
+
+        //Cache map for faster and easier access based on svcId.
+        std::unordered_map<long, std::shared_ptr<const SvcEntry>> cache{};
+    } services{};
+
+    struct {
+        mutable std::mutex mutex{};
+        long nextTrackerId = 1L;
+
+        /* Note same ordering as services registry, expect the ranking order requirement,
+         * so that it is easier and faster to update the trackers.
+         */
+        std::unordered_map<std::string, std::set<std::shared_ptr<SvcTrackerEntry>>> registry{};
+        std::unordered_map<long, std::shared_ptr<SvcTrackerEntry>> cache{};
+    } trackers{};
+
+    celix::ServiceRegistration registerService(std::string serviceName, std::shared_ptr<void> svc, std::shared_ptr<celix::IServiceFactory<void>> factory, celix::Properties props, std::shared_ptr<const celix::IResourceBundle> owner) {
+        props[celix::SERVICE_NAME] = std::move(serviceName);
+        std::string &svcName = props[celix::SERVICE_NAME];
+
+        std::lock_guard<std::mutex> lock{services.mutex};
+        long svcId = services.nextSvcId++;
+        props[celix::SERVICE_ID] = std::to_string(svcId);
+
+        //Add to registry
+        std::shared_ptr<const celix::IResourceBundle> bnd = owner ? owner : emptyBundle;
+
+        if (factory) {
+            VLOG(1) << "Registering service factory '" << svcName << "' from bundle id " << owner->id() << std::endl;
+        } else {
+            VLOG(1) << "Registering service '" << svcName << "' from bundle id " << owner->id() << std::endl;
+        }
+
+        const auto it = services.registry[svcName].emplace(new SvcEntry{std::move(bnd), svcId, svcName, std::move(svc), std::move(factory), std::move(props)});
+        assert(it.second); //should always lead to a new entry
+        const std::shared_ptr<const SvcEntry> &entry = *it.first;
+
+        //Add to svcId cache
+        services.cache[entry->svcId] = entry;
+
+        //update trackers
+        std::thread updateThread{[&]{updateTrackers(entry, true);}};
+        updateThread.join();
+        entry->decrUsage(); //note usage started at 1 during creation
+
+
+        //create unregister callback
+        std::function<void()> unreg = [this, svcId]() -> void {
+            this->unregisterService(svcId);
+        };
+        auto *impl = new celix::ServiceRegistration::Impl{
+                .entry = entry,
+                .unregisterCallback = std::move(unreg),
+                .registered = true
+        };
+        return celix::ServiceRegistration{impl};
+    }
+
+    void unregisterService(long svcId) {
+        if (svcId <= 0) {
+            return; //silent ignore
+        }
+
+        std::shared_ptr<const SvcEntry> match{nullptr};
+
+        {
+            std::lock_guard<std::mutex> lock{services.mutex};
+            const auto it = services.cache.find(svcId);
+            if (it != services.cache.end()) {
+                match = it->second;
+                services.cache.erase(it);
+                services.registry.at(match->svcName).erase(match);
+            }
+        }
+
+        if (match) {
+            std::thread updateThread{[&]{updateTrackers(match, false);}};
+            updateThread.join();
+            match->waitTillUnused();
+        } else {
+            LOG(WARNING) << "Cannot unregister service. Unknown service id: " << svcId << "." << std::endl;
+        }
+    }
+
+    void removeTracker(long trkId) {
+        if (trkId <= 0) {
+            return; //silent ignore
+        }
+
+        std::shared_ptr<SvcTrackerEntry> match{nullptr};
+        {
+            std::lock_guard<std::mutex> lock{trackers.mutex};
+            const auto it = trackers.cache.find(trkId);
+            if (it != trackers.cache.end()) {
+                match = it->second;
+                trackers.cache.erase(it);
+                trackers.registry.at(match->svcName).erase(match);
+            }
+        }
+
+        if (match) {
+            match->waitTillUnused();
+            std::thread clearThread{[&]{match->clear();}}; //ensure that all service are removed using the callbacks
+            clearThread.join();
+        } else {
+            LOG(WARNING) << "Cannot remove tracker. Unknown tracker id: " << trkId << "." << std::endl;
+        }
+    }
+
+    void updateTrackers(const std::shared_ptr<const SvcEntry> &entry, bool adding) {
+        std::vector<std::shared_ptr<SvcTrackerEntry>> matchedTrackers{};
+        {
+            std::lock_guard<std::mutex> lock{trackers.mutex};
+            for (auto &tracker : trackers.registry[entry->svcName]) {
+                if (tracker->match(*entry)) {
+                    tracker->incrUsage();
+                    matchedTrackers.push_back(tracker);
+                }
+            }
+        }
+
+        for (auto &match : matchedTrackers) {
+            if (adding) {
+                match->addMatch(entry);
+            } else {
+                match->remMatch(entry);
+            }
+            match->decrUsage();
+        }
+    }
+};
+
+
+
+/**********************************************************************************************************************
+  Service Registry
+ **********************************************************************************************************************/
+
+
+celix::ServiceRegistry::ServiceRegistry(std::string name) : pimpl{new ServiceRegistry::Impl{}} {
+    pimpl->regName = std::move(name);
+}
+celix::ServiceRegistry::ServiceRegistry(celix::ServiceRegistry &&rhs) = default;
+celix::ServiceRegistry& celix::ServiceRegistry::operator=(celix::ServiceRegistry &&rhs) = default;
+celix::ServiceRegistry::~ServiceRegistry() {
+    if (pimpl) {
+        //TODO
+    }
+}
+
+const std::string& celix::ServiceRegistry::name() const { return pimpl->regName; }
+
+/*
+celix::ServiceRegistration celix::ServiceRegistry::registerService(const std::string &svcName, std::unique_ptr<void> svc, celix::Properties props, std::shared_ptr<const celix::IResourceBundle> owner) {
+    return pimpl->registerService(std::move(svcName), nullptr, {}, std::move(svc), std::move(props), std::move(owner));
+}*/
+
+celix::ServiceRegistration celix::ServiceRegistry::registerService(std::string svcName, std::shared_ptr<void> svc, celix::Properties props, std::shared_ptr<const celix::IResourceBundle> owner) {
+    return pimpl->registerService(std::move(svcName), std::move(svc), {}, std::move(props), std::move(owner));
+}
+
+celix::ServiceRegistration celix::ServiceRegistry::registerServiceFactory(std::string svcName, std::shared_ptr<celix::IServiceFactory<void>> factory, celix::Properties props, std::shared_ptr<const celix::IResourceBundle> owner) {
+    return pimpl->registerService(std::move(svcName), {}, std::move(factory), std::move(props), std::move(owner));
+}
+
+//TODO add useService(s) call to ServiceTracker object for fast service access
+
+//TODO move to Impl
+celix::ServiceTracker celix::ServiceRegistry::trackServices(std::string svcName, celix::ServiceTrackerOptions<void> options, std::shared_ptr<const celix::IResourceBundle> requester) {
+    //TODO create new tracker event and start new thread to update track trackers
+    long trkId = 0;
+    {
+        std::lock_guard<std::mutex> lck{pimpl->trackers.mutex};
+        trkId = pimpl->trackers.nextTrackerId++;
+    }
+
+    auto trkEntry = std::shared_ptr<SvcTrackerEntry>{new SvcTrackerEntry{trkId, requester, std::move(svcName), std::move(options)}};
+    if (trkEntry->valid()) {
+
+        //find initial services and add new tracker to registry.
+        //NOTE two locks to ensure no new services can be added/removed during initial tracker setup
+        std::vector<std::shared_ptr<const SvcEntry>> services{};
+        {
+            std::lock_guard<std::mutex> lck1{pimpl->services.mutex};
+            for (auto &svcEntry : pimpl->services.registry[trkEntry->svcName]) {
+                if (trkEntry->match(*svcEntry)) {
+                    svcEntry->incrUsage();
+                    services.push_back(svcEntry);
+                }
+            }
+
+            std::lock_guard<std::mutex> lck2{pimpl->trackers.mutex};
+            pimpl->trackers.registry[trkEntry->svcName].insert(trkEntry);
+            pimpl->trackers.cache[trkEntry->id] = trkEntry;
+        }
+        std::thread updateThread{[&]{
+            for (auto &svcEntry : services) {
+                trkEntry->addMatch(svcEntry);
+                svcEntry->decrUsage();
+            }
+        }};
+        updateThread.join();
+        trkEntry->decrUsage(); //note trkEntry usage started at 1
+
+        auto untrack = [this, trkId]() -> void {
+            this->pimpl->removeTracker(trkId);
+        };
+        auto *impl = new celix::ServiceTracker::Impl{
+                .entry = trkEntry,
+                .untrackCallback = std::move(untrack),
+                .active = true
+        };
+        return celix::ServiceTracker{impl};
+    } else {
+        trkEntry->decrUsage(); //note usage is 1 at creation
+        LOG(ERROR) << "Cannot create tracker. Invalid filter?" << std::endl;
+        return celix::ServiceTracker{nullptr};
+    }
+}
+
+//TODO move to Impl
+long celix::ServiceRegistry::nrOfServiceTrackers() const {
+    std::lock_guard<std::mutex> lck{pimpl->trackers.mutex};
+    return pimpl->trackers.cache.size();
+}
+        
+//TODO unregister tracker with remove tracker event in a new thread
+//TODO move to Impl
+std::vector<long> celix::ServiceRegistry::findServices(const std::string &svcName, const std::string &rawFilter) const {
+    std::vector<long> result{};
+    celix::Filter filter = rawFilter;
+    if (!filter.valid()) {
+        LOG(WARNING) << "Invalid filter (" << rawFilter << ") provided. Cannot find services" << std::endl;
+        return result;
+    }
+
+    std::lock_guard<std::mutex> lock{pimpl->services.mutex};
+    const auto it = pimpl->services.registry.find(svcName);
+    if (it != pimpl->services.registry.end()) {
+        const auto &services = it->second;
+        for (const auto &visit : services) {
+            if (filter.empty() || filter.match(visit->props)) {
+                result.push_back(visit->svcId);
+            }
+        }
+    }
+    return result;
+}
+
+//TODO move to Impl
+long celix::ServiceRegistry::nrOfRegisteredServices() const {
+    std::lock_guard<std::mutex> lock{pimpl->services.mutex};
+    return pimpl->services.cache.size();
+}
+
+//TODO move to Impl
+int celix::ServiceRegistry::useServices(const std::string &svcName, std::function<void(void *svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> &use, const std::string &rawFilter, std::shared_ptr<const celix::IResourceBundle> requester) const {
+    celix::Filter filter = rawFilter;
+    if (!filter.valid()) {
+        LOG(WARNING) << "Invalid filter (" << rawFilter << ") provided. Cannot find services" << std::endl;
+        return 0;
+    }
+
+    std::vector<std::shared_ptr<const SvcEntry>> matches{};
+    {
+        std::lock_guard<std::mutex> lock{pimpl->services.mutex};
+        const auto it = pimpl->services.registry.find(svcName);
+        if (it != pimpl->services.registry.end()) {
+            const auto &services = it->second;
+            for (const std::shared_ptr<const SvcEntry> &entry : services) {
+                if (filter.empty() || filter.match(entry->props)) {
+                    entry->incrUsage();
+                    matches.push_back(entry);
+                }
+            }
+        }
+    }
+
+    for (const std::shared_ptr<const SvcEntry> &entry : matches) {
+        use(entry->service(*requester), entry->props, *entry->owner);
+        entry->decrUsage();
+    }
+
+    return (int)matches.size();
+}
+
+//TODO move to Impl
+bool celix::ServiceRegistry::useService(const std::string &svcName, std::function<void(void *svc, const celix::Properties &props, const celix::IResourceBundle &bnd)> &use, const std::string &rawFilter, std::shared_ptr<const celix::IResourceBundle> requester) const {
+    celix::Filter filter = rawFilter;
+    if (!filter.valid()) {
+        LOG(WARNING) << "Invalid filter (" << rawFilter << ") provided. Cannot find services" << std::endl;
+        return false;
+    }
+
+    std::shared_ptr<const SvcEntry> match = nullptr;
+    {
+        std::lock_guard<std::mutex> lock{pimpl->services.mutex};
+        const auto it = pimpl->services.registry.find(svcName);
+        if (it != pimpl->services.registry.end()) {
+            const auto &services = it->second;
+            for (const std::shared_ptr<const SvcEntry> &visit : services) {
+                if (filter.empty() || filter.match(visit->props)) {
+                    visit->incrUsage();
+                    match = visit;
+                    break;
+                }
+            }
+        }
+    }
+
+    if (match != nullptr) {
+        use(match->service(*requester), match->props, *match->owner);
+        match->decrUsage();
+    }
+
+    return match != nullptr;
+}
+
+/**********************************************************************************************************************
+  Service Registration
+ **********************************************************************************************************************/
+
+celix::ServiceRegistration::ServiceRegistration() : pimpl{nullptr} {}
+
+celix::ServiceRegistration::ServiceRegistration(celix::ServiceRegistration::Impl *impl) : pimpl{impl} {}
+celix::ServiceRegistration::ServiceRegistration(celix::ServiceRegistration &&rhs) noexcept = default;
+celix::ServiceRegistration& celix::ServiceRegistration::operator=(celix::ServiceRegistration &&rhs) noexcept = default;
+celix::ServiceRegistration::~ServiceRegistration() { unregister(); }
+
+long celix::ServiceRegistration::serviceId() const { return pimpl ? pimpl->entry->svcId : -1L; }
+bool celix::ServiceRegistration::valid() const { return serviceId() >= 0; }
+bool celix::ServiceRegistration::factory() const { return pimpl && pimpl->entry->factory(); }
+bool celix::ServiceRegistration::registered() const {return pimpl && pimpl->registered; }
+
+void celix::ServiceRegistration::unregister() {
+    if (pimpl && pimpl->registered) {
+        pimpl->registered = false; //TODO make thread safe
+        pimpl->unregisterCallback();
+    }
+}
+
+const celix::Properties& celix::ServiceRegistration::properties() const {
+    static const celix::Properties empty{};
+    return pimpl ? pimpl->entry->props : empty;
+}
+
+const std::string& celix::ServiceRegistration::serviceName() const {
+    static const std::string empty{};
+    if (pimpl) {
+        return celix::getProperty(pimpl->entry->props, celix::SERVICE_NAME, empty);
+    }
+    return empty;
+}
+
+
+
+
+/**********************************************************************************************************************
+  Service Tracker
+ **********************************************************************************************************************/
+
+celix::ServiceTracker::ServiceTracker() : pimpl{nullptr} {}
+
+celix::ServiceTracker::ServiceTracker(celix::ServiceTracker::Impl *impl) : pimpl{impl} {}
+
+celix::ServiceTracker::~ServiceTracker() {
+    if (pimpl && pimpl->active) {
+        pimpl->untrackCallback();
+    }
+}
+
+
+void celix::ServiceTracker::stop() {
+    if (pimpl && pimpl->active) { //TODO make thread safe
+        pimpl->untrackCallback();
+        pimpl->active = false;
+    }
+}
+
+celix::ServiceTracker::ServiceTracker(celix::ServiceTracker &&rhs) noexcept = default;
+celix::ServiceTracker& celix::ServiceTracker::operator=(celix::ServiceTracker &&rhs) noexcept = default;
+
+int celix::ServiceTracker::trackCount() const { return pimpl ? pimpl->entry->count() : 0; }
+const std::string& celix::ServiceTracker::serviceName() const { return pimpl? pimpl->entry->svcName : emptyString; }
+const std::string& celix::ServiceTracker::filter() const { return pimpl ? pimpl->entry->filter.filterStr : emptyString; }
+bool celix::ServiceTracker::valid() const { return pimpl != nullptr; }
\ No newline at end of file


[celix] 06/22: CELIX-438: Updates travis config

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 5e04c17232db048cb5f73f9988741eff2548d1f0
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Thu Jan 3 22:43:17 2019 +0100

    CELIX-438: Updates travis config
---
 .travis.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index a95432b..e5ec93a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -35,8 +35,8 @@ matrix:
 #services: docker
 
 before_install:
-  - if [ "$TRAVIS_OS_NAME" = "linux" ] sudo apt-get update -qq
-  - if [ "$TRAVIS_OS_NAME" = "linux" ] sudo apt-get install -qq uuid-dev libxml2-dev lcov libffi-dev libczmq-dev libcpputest-dev libjansson-dev
+  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq; fi
+  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install -qq uuid-dev libxml2-dev lcov libffi-dev libczmq-dev libcpputest-dev libjansson-dev; fi
   - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update && brew install lcov libffi zeromq czmq glog cpputest jansson && brew link --force libffi; fi
 
 before_script:


[celix] 05/22: CELIX-438: Adds an initial setup for handling resources in bundles

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 34dac36bbc4462ec3c4bb3adcf656a05c905352a
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Thu Jan 3 22:40:58 2019 +0100

    CELIX-438: Adds an initial setup for handling resources in bundles
---
 .travis.yml                                        |   3 +-
 CMakeLists.txt                                     |   1 +
 bundles/shell/cxx_shell/CMakeLists.txt             |  21 +-
 .../shell/cxx_shell/resources/version.properties   |   3 +
 bundles/shell/cxx_shell/src/ShellActivator.cc      |  10 +-
 bundles/shell/cxx_shell/src/VersionCommand.cc      |  51 +++++
 bundles/shell/cxx_shell/src/commands.h             |   1 +
 bundles/shell/cxx_shell_tui/CMakeLists.txt         |   2 -
 .../shell/cxx_shell_tui/src/ShellTuiActivator.cc   |   1 +
 bundles/shell/cxx_shell_tui/src/shell_test.cc      |   1 -
 cmake/celix_project/AddGLog.cmake                  |   8 +-
 cmake/celix_project/AddGTest.cmake                 |   1 +
 .../{AddGLog.cmake => AddLibzip.cmake}             |  20 +-
 libs/framework_cxx/CMakeLists.txt                  |  10 +-
 libs/framework_cxx/include/celix/Framework.h       |  25 ++-
 libs/framework_cxx/src/Bundle.cc                   |  24 ++-
 libs/framework_cxx/src/Bundle.h                    |  18 +-
 libs/framework_cxx/src/BundleController.h          | 196 ++++++++++++++++++-
 libs/framework_cxx/src/Framework.cc                | 103 ++++++++--
 libs/registry/CMakeLists.txt                       |   3 +-
 libs/registry/include/celix/IResourceBundle.h      |  11 +-
 libs/registry/include/celix/Properties.h           |   8 +-
 libs/registry/src/Properties.cc                    | 215 +++++++++++++++++++++
 libs/registry/src/ServiceRegistry.cc               |  11 +-
 24 files changed, 665 insertions(+), 82 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index e3536d2..a95432b 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -35,9 +35,8 @@ matrix:
 #services: docker
 
 before_install:
-  - if [ "$TRAVIS_OS_NAME" = "linux" ] sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
   - if [ "$TRAVIS_OS_NAME" = "linux" ] sudo apt-get update -qq
-  - if [ "$TRAVIS_OS_NAME" = "linux" ] sudo apt-get install -qq uuid-dev libxml2-dev lcov libffi-dev libgoogle-glog-dev libczmq-dev libcpputest-dev libjansson-dev
+  - if [ "$TRAVIS_OS_NAME" = "linux" ] sudo apt-get install -qq uuid-dev libxml2-dev lcov libffi-dev libczmq-dev libcpputest-dev libjansson-dev
   - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update && brew install lcov libffi zeromq czmq glog cpputest jansson && brew link --force libffi; fi
 
 before_script:
diff --git a/CMakeLists.txt b/CMakeLists.txt
index c1c4a43..7025630 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -58,6 +58,7 @@ if (ENABLE_TESTING)
     include(cmake/celix_project/AddGTest.cmake)
 endif ()
 include(cmake/celix_project/AddGLog.cmake)
+include(cmake/celix_project/AddLibzip.cmake)
 
 # Default bundle version
 set(DEFAULT_VERSION 1.0.0)
diff --git a/bundles/shell/cxx_shell/CMakeLists.txt b/bundles/shell/cxx_shell/CMakeLists.txt
index a4ad2df..d2b2113 100644
--- a/bundles/shell/cxx_shell/CMakeLists.txt
+++ b/bundles/shell/cxx_shell/CMakeLists.txt
@@ -15,8 +15,6 @@
 # specific language governing permissions and limitations
 # under the License.
 
-find_package(glog REQUIRED)
-
 #TODO rename to celix::shell && celix::shell_api
 
 add_library(celix_cxx_shell_api INTERFACE)
@@ -25,6 +23,17 @@ target_include_directories(celix_cxx_shell_api INTERFACE
     $<INSTALL_INTERFACE:include/celix/shell>
 )
 
+#TODO should eventually be done by a CMake command (i.e. bundle_add_resources)
+add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/celix_cxx_shell_resources.zip
+        COMMAND zip -rq ${CMAKE_CURRENT_BINARY_DIR}/celix_cxx_shell_resources.zip *
+        COMMENT "Packaging Resources"
+        WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/resources
+)
+
+add_custom_target(create_resources ALL
+    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/celix_cxx_shell_resources.zip
+)
+
 add_library(celix_cxx_shell SHARED
         src/ShellActivator.cc
         src/LbCommand.cc
@@ -32,10 +41,18 @@ add_library(celix_cxx_shell SHARED
         src/StopAndStartCommand.cc
         src/InspectCommand.cc
         src/QueryCommand.cc
+        src/VersionCommand.cc
 )
 target_include_directories(celix_cxx_shell PRIVATE src)
 target_link_libraries(celix_cxx_shell PRIVATE celix_cxx_shell_api glog::glog)
 target_link_libraries(celix_cxx_shell PUBLIC celix_framework_cxx)
+add_dependencies(celix_cxx_shell create_resources)
+if (UNIX AND NOT APPLE)
+    target_link_libraries(celix_cxx_shell PRIVATE -Wl,--format=binary -Wl,celix_cxx_shell_resources.zip -Wl,--format=default)
+else ()
+    #TODO apple
+endif ()
+
 
 #if (ENABLE_TESTING)
 #    add_subdirectory(gtest)
diff --git a/bundles/shell/cxx_shell/resources/version.properties b/bundles/shell/cxx_shell/resources/version.properties
new file mode 100644
index 0000000..2840a93
--- /dev/null
+++ b/bundles/shell/cxx_shell/resources/version.properties
@@ -0,0 +1,3 @@
+CELIX_VERSION=3.0.0
+COMMIT_ID=TODO
+COMMIT_DATA=TODO
\ No newline at end of file
diff --git a/bundles/shell/cxx_shell/src/ShellActivator.cc b/bundles/shell/cxx_shell/src/ShellActivator.cc
index bfbbb8f..ea54219 100644
--- a/bundles/shell/cxx_shell/src/ShellActivator.cc
+++ b/bundles/shell/cxx_shell/src/ShellActivator.cc
@@ -17,12 +17,17 @@
  *under the License.
  */
 
+#include <glog/logging.h>
+
 #include "celix/api.h"
 #include "celix/IShellCommand.h"
 #include "celix/IShell.h"
 
 #include "commands.h"
 
+extern const uint8_t resources[]       asm("_binary_celix_cxx_shell_resources_zip_start");
+extern const uint8_t resources_end[]   asm("_binary_celix_cxx_shell_resources_zip_end");
+
 namespace {
 
     class Shell : public celix::IShell {
@@ -86,6 +91,7 @@ namespace {
             registrations.push_back(impl::registerStart(ctx));
             registrations.push_back(impl::registerInspect(ctx));
             registrations.push_back(impl::registerQuery(ctx));
+            registrations.push_back(impl::registerVersion(ctx));
 
             registrations.push_back(ctx->registerService(std::shared_ptr<celix::IShell>{new Shell{ctx}}));
         }
@@ -93,12 +99,14 @@ namespace {
         std::vector<celix::ServiceRegistration> registrations{};
     };
 
+    //NOTE that eventually the (ctor) bundle register will be generated by a CMake command (i.e. add_bundle)
+    //This also applies for the resources, resources_end asm entries.
     __attribute__((constructor))
     static void registerShellBundle() {
         celix::Properties manifest{};
         manifest[celix::MANIFEST_BUNDLE_NAME] = "Shell";
         manifest[celix::MANIFEST_BUNDLE_GROUP] = "Celix";
         manifest[celix::MANIFEST_BUNDLE_VERSION] = "1.0.0";
-        celix::registerStaticBundle<ShellBundleActivator>("celix::Shell", manifest);
+        celix::registerStaticBundle<ShellBundleActivator>("celix::Shell", manifest, resources, resources_end - resources);
     }
 }
diff --git a/bundles/shell/cxx_shell/src/VersionCommand.cc b/bundles/shell/cxx_shell/src/VersionCommand.cc
new file mode 100644
index 0000000..d95b7a4
--- /dev/null
+++ b/bundles/shell/cxx_shell/src/VersionCommand.cc
@@ -0,0 +1,51 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "commands.h"
+
+#include <functional>
+
+#include "celix/api.h"
+#include "celix/IShellCommand.h"
+
+namespace {
+
+    void version(std::shared_ptr<celix::BundleContext> ctx, const std::string &, const std::vector<std::string> &, std::ostream &out, std::ostream &err) {
+        if (ctx->bundle()->hasCacheEntry("version.properties")) {
+            auto path = ctx->bundle()->absPathForCacheEntry("version.properties");
+            celix::Properties versionInfo = celix::loadProperties(path);
+            std::string version = celix::getProperty(versionInfo, "CELIX_VERSION", "");
+            out << "Celix Version: " << version << std::endl;
+        } else {
+            err << "Cannot find version.properties entry in the " << ctx->bundle()->group() << " " << ctx->bundle()->name() << " bundle" << std::endl;
+        }
+    }
+}
+
+
+celix::ServiceRegistration impl::registerVersion(std::shared_ptr<celix::BundleContext> ctx) {
+    using namespace std::placeholders;
+    celix::ShellCommandFunction cmd = std::bind(&version, ctx, _1, _2, _3, _4);
+
+    celix::Properties props{};
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME] = "version";
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_USAGE] = "version";
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION] = "Show version information about the framework (TODO and installed bundles)";
+    return ctx->registerFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, std::move(cmd), std::move(props));
+}
\ No newline at end of file
diff --git a/bundles/shell/cxx_shell/src/commands.h b/bundles/shell/cxx_shell/src/commands.h
index b9d9a8f..9f1f18b 100644
--- a/bundles/shell/cxx_shell/src/commands.h
+++ b/bundles/shell/cxx_shell/src/commands.h
@@ -29,6 +29,7 @@ namespace impl {
     celix::ServiceRegistration registerStart(std::shared_ptr<celix::BundleContext> ctx);
     celix::ServiceRegistration registerInspect(std::shared_ptr<celix::BundleContext> ctx);
     celix::ServiceRegistration registerQuery(std::shared_ptr<celix::BundleContext> ctx);
+    celix::ServiceRegistration registerVersion(std::shared_ptr<celix::BundleContext> ctx);
 }
 
 
diff --git a/bundles/shell/cxx_shell_tui/CMakeLists.txt b/bundles/shell/cxx_shell_tui/CMakeLists.txt
index cfbf6cf..e9fa13b 100644
--- a/bundles/shell/cxx_shell_tui/CMakeLists.txt
+++ b/bundles/shell/cxx_shell_tui/CMakeLists.txt
@@ -15,8 +15,6 @@
 # specific language governing permissions and limitations
 # under the License.
 
-find_package(glog REQUIRED)
-
 #TODO rename to celix::shell_tui
 
 #OR static lib, but then with all symbols to force constructor attribute
diff --git a/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc b/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc
index a66bea5..ec48f6b 100644
--- a/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc
+++ b/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc
@@ -140,6 +140,7 @@ namespace {
         celix::ServiceTracker trk{};
     };
 
+    //NOTE that eventually the (ctor) bundle register will be generated by a CMake command (i.e. add_bundle)
     __attribute__((constructor))
     static void registerShellBundle() {
         celix::Properties manifest{};
diff --git a/bundles/shell/cxx_shell_tui/src/shell_test.cc b/bundles/shell/cxx_shell_tui/src/shell_test.cc
index cd3af3c..8e92107 100644
--- a/bundles/shell/cxx_shell_tui/src/shell_test.cc
+++ b/bundles/shell/cxx_shell_tui/src/shell_test.cc
@@ -29,7 +29,6 @@ int main(int /*argc*/, char **argv) {
     google::LogToStderr();
 
     auto fw = celix::Framework{};
-    std::cout << "Waiting for Framework shutdown\n";
     fw.waitForShutdown();
     return 0;
 }
\ No newline at end of file
diff --git a/cmake/celix_project/AddGLog.cmake b/cmake/celix_project/AddGLog.cmake
index 8cc3414..4897f35 100644
--- a/cmake/celix_project/AddGLog.cmake
+++ b/cmake/celix_project/AddGLog.cmake
@@ -21,9 +21,15 @@ ExternalProject_Add(
         googlelog_project
         GIT_REPOSITORY https://github.com/google/glog.git
         GIT_TAG v0.3.5
+        UPDATE_DISCONNECTED TRUE
         PREFIX ${CMAKE_CURRENT_BINARY_DIR}/glog
         CMAKE_ARGS -DWITH_GFLAGS=OFF -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/glog -DCMAKE_CXX_FLAGS=-w
 )
 
-set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/glog ${CMAKE_PREFIX_PATH}")
+add_library(glog::glog IMPORTED STATIC GLOBAL)
+add_dependencies(glog::glog googlelog_project)
+set_target_properties(glog::glog PROPERTIES
+    IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/glog/lib/libglog.a"
+    INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/glog/include"
+)
 
diff --git a/cmake/celix_project/AddGTest.cmake b/cmake/celix_project/AddGTest.cmake
index 93227c1..2da1a47 100644
--- a/cmake/celix_project/AddGTest.cmake
+++ b/cmake/celix_project/AddGTest.cmake
@@ -20,6 +20,7 @@ ExternalProject_Add(
         googletest_project
         GIT_REPOSITORY https://github.com/google/googletest.git
         GIT_TAG release-1.8.1
+        UPDATE_DISCONNECTED TRUE
         PREFIX ${CMAKE_CURRENT_BINARY_DIR}/gtest
         INSTALL_COMMAND ""
 )
diff --git a/cmake/celix_project/AddGLog.cmake b/cmake/celix_project/AddLibzip.cmake
similarity index 54%
copy from cmake/celix_project/AddGLog.cmake
copy to cmake/celix_project/AddLibzip.cmake
index 8cc3414..7d14cb6 100644
--- a/cmake/celix_project/AddGLog.cmake
+++ b/cmake/celix_project/AddLibzip.cmake
@@ -15,15 +15,19 @@
 # specific language governing permissions and limitations
 # under the License.
 
-
 include(ExternalProject)
 ExternalProject_Add(
-        googlelog_project
-        GIT_REPOSITORY https://github.com/google/glog.git
-        GIT_TAG v0.3.5
-        PREFIX ${CMAKE_CURRENT_BINARY_DIR}/glog
-        CMAKE_ARGS -DWITH_GFLAGS=OFF -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/glog -DCMAKE_CXX_FLAGS=-w
+        libzip_project
+        GIT_REPOSITORY https://github.com/nih-at/libzip.git
+        GIT_TAG rel-1-5-1
+        UPDATE_DISCONNECTED TRUE
+        PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libzip
+        CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/libzip -DCMAKE_C_FLAGS=-fPIC -DBUILD_SHARED_LIBS=OFF -DENABLE_COMMONCRYPTO=OFF -DENABLE_GNUTLS=OFF -DENABLE_OPENSSL=OFF -Wno-dev
 )
 
-set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/glog ${CMAKE_PREFIX_PATH}")
-
+add_library(libzip::libzip IMPORTED STATIC GLOBAL)
+add_dependencies(libzip::libzip libzip_project)
+set_target_properties(libzip::libzip PROPERTIES
+        IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/libzip/lib64/libzip.a"
+        INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/libzip/include"
+)
\ No newline at end of file
diff --git a/libs/framework_cxx/CMakeLists.txt b/libs/framework_cxx/CMakeLists.txt
index c47ae80..f3c116e 100644
--- a/libs/framework_cxx/CMakeLists.txt
+++ b/libs/framework_cxx/CMakeLists.txt
@@ -15,17 +15,19 @@
 # specific language governing permissions and limitations
 # under the License.
 
-find_package(glog REQUIRED)
+find_package(UUID REQUIRED)
 
 #TODO rename to celix::framework
 add_library(celix_framework_cxx SHARED
         src/Framework.cc
         src/BundleContext.cc
-        src/Bundle.cc)
+        src/Bundle.cc
+)
 target_include_directories(celix_framework_cxx PRIVATE src)
 target_include_directories(celix_framework_cxx PUBLIC include)
-target_link_libraries(celix_framework_cxx PRIVATE glog::glog)
-target_link_libraries(celix_framework_cxx PUBLIC celix::registry)
+target_link_libraries(celix_framework_cxx PRIVATE glog::glog libzip::libzip)
+#NOTE because of libzil libbz2 and libz is also needed. maybe more to other form of resources (i.e. tar)
+target_link_libraries(celix_framework_cxx PUBLIC celix::registry bz2 z ${UUID_LIBRARY})
 
 if (ENABLE_TESTING)
     add_subdirectory(gtest)
diff --git a/libs/framework_cxx/include/celix/Framework.h b/libs/framework_cxx/include/celix/Framework.h
index 27718f8..89e9a3b 100644
--- a/libs/framework_cxx/include/celix/Framework.h
+++ b/libs/framework_cxx/include/celix/Framework.h
@@ -35,16 +35,20 @@ namespace celix {
     void registerStaticBundle(
             std::string symbolicName,
             std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> bundleActivatorFactory = {},
-            celix::Properties manifest = {});
+            celix::Properties manifest = {},
+            const uint8_t *resourcesZip = nullptr,
+            size_t resourcesZipLen = 0);
 
     template<typename T>
     void registerStaticBundle(
             std::string symbolicName,
-            celix::Properties manifest = {}) {
+            celix::Properties manifest = {},
+            const uint8_t *resourcesZip = nullptr,
+            size_t resourcesZipLen = 0) {
         auto actFactory = [](std::shared_ptr<celix::BundleContext> ctx) {
             return new T{std::move(ctx)};
         };
-        celix::registerStaticBundle(std::move(symbolicName), actFactory, std::move(manifest));
+        celix::registerStaticBundle(std::move(symbolicName), std::move(actFactory), std::move(manifest), resourcesZip, resourcesZipLen);
     }
 
     class Framework {
@@ -58,14 +62,20 @@ namespace celix {
         Framework& operator=(const Framework &rhs) = delete;
 
         template<typename T>
-        long installBundle(std::string name, celix::Properties manifest = {}, bool autoStart = true) {
+        long installBundle(std::string name, celix::Properties manifest = {}, bool autoStart = true, const uint8_t *resourcesZip = nullptr, size_t resourcesZipLen = 0) {
             auto actFactory = [](std::shared_ptr<celix::BundleContext> ctx) {
                 return new T{std::move(ctx)};
             };
-            return installBundle(name, std::move(actFactory), manifest, autoStart);
+            return installBundle(name, std::move(actFactory), std::move(manifest), autoStart, resourcesZip, resourcesZipLen);
         }
 
-        long installBundle(std::string name, std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory, celix::Properties manifest = {}, bool autoStart = true);
+        long installBundle(
+                std::string name,
+                std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory,
+                celix::Properties manifest = {},
+                bool autoStart = true,
+                const uint8_t *resourcesZip = nullptr,
+                const size_t resourcesZipLen = 0);
 
 
         //long installBundle(const std::string &path);
@@ -76,6 +86,9 @@ namespace celix {
         bool useBundle(long bndId, std::function<void(const celix::IBundle &bnd)> use) const;
         int useBundles(std::function<void(const celix::IBundle &bnd)> use, bool includeFrameworkBundle = false) const;
 
+        std::string cacheDir() const;
+        std::string uuid() const;
+
         //TODO trackBundles
 
         //long bundleIdForName(const std::string &bndName) const;
diff --git a/libs/framework_cxx/src/Bundle.cc b/libs/framework_cxx/src/Bundle.cc
index 6f167f7..aba14a2 100644
--- a/libs/framework_cxx/src/Bundle.cc
+++ b/libs/framework_cxx/src/Bundle.cc
@@ -18,20 +18,30 @@
  */
 
 #include <string>
+#include <sys/stat.h>
+#include <unistd.h>
 
 #include "Bundle.h"
 
-bool celix::Bundle::has(const std::string &) const noexcept { return false; } //TODO
+bool celix::Bundle::hasCacheEntry(const std::string &path) const noexcept {
+    auto abs = absPathForCacheEntry(path);
+    struct stat st;
+    bool exists = stat(abs.c_str(), &st) == 0;
+    return exists;
+}
 
-bool celix::Bundle::isDir(const std::string &) const noexcept { return false; } //TODO
+bool celix::Bundle::isCacheEntryDir(const std::string &) const noexcept { return false; } //TODO
 
-bool celix::Bundle::isFile(const std::string &) const noexcept { return false; } //TODO
+bool celix::Bundle::isCacheEntryFile(const std::string &) const noexcept { return false; } //TODO
 
-std::vector <std::string> celix::Bundle::readDir(const std::string &) const noexcept { //TODO
+std::vector <std::string> celix::Bundle::readCacheDir(const std::string &) const noexcept { //TODO
     return std::vector < std::string > {};
 }
 
-const std::string& celix::Bundle::root() const noexcept { //TODO
-    static std::string empty{};
-    return empty;
+const std::string& celix::Bundle::cacheRoot() const noexcept {
+    return bundleCache;
+}
+
+std::string celix::Bundle::absPathForCacheEntry(const std::string &entryPath) const noexcept {
+    return bundleCache + "/" + entryPath;
 }
\ No newline at end of file
diff --git a/libs/framework_cxx/src/Bundle.h b/libs/framework_cxx/src/Bundle.h
index 5541013..ce5e456 100644
--- a/libs/framework_cxx/src/Bundle.h
+++ b/libs/framework_cxx/src/Bundle.h
@@ -30,7 +30,9 @@ namespace celix {
     class Bundle : public celix::IBundle {
     public:
         Bundle(long _bndId, celix::Framework *_fw, celix::Properties _manifest) :
-                bndId{_bndId}, fw{_fw}, bndManifest{std::move(_manifest)}, bndState{BundleState::INSTALLED} {
+                bndId{_bndId}, fw{_fw}, bndManifest{std::move(_manifest)},
+                bundleCache{framework().cacheDir() + "/bundle" + std::to_string(_bndId)},
+                bndState{BundleState::INSTALLED} {
             bndState.store(BundleState::INSTALLED, std::memory_order_release);
         }
 
@@ -38,11 +40,12 @@ namespace celix {
         Bundle& operator=(const Bundle&) = delete;
 
         //resource part
-        bool has(const std::string &) const noexcept override;
-        bool isDir(const std::string &) const noexcept override;
-        bool isFile(const std::string &) const noexcept override;
-        std::vector <std::string> readDir(const std::string &) const noexcept override;
-        const std::string &root() const noexcept override;
+        bool hasCacheEntry(const std::string &) const noexcept override;
+        bool isCacheEntryDir(const std::string &) const noexcept override;
+        bool isCacheEntryFile(const std::string &) const noexcept override;
+        std::string absPathForCacheEntry(const std::string &) const noexcept override;
+        std::vector <std::string> readCacheDir(const std::string &) const noexcept override;
+        const std::string &cacheRoot() const noexcept override;
 
         //bundle part
         bool isFrameworkBundle() const noexcept override { return false; }
@@ -58,7 +61,7 @@ namespace celix {
         }
 
         const std::string &group() const noexcept override {
-            return bndManifest.at(celix::MANIFEST_BUNDLE_SYMBOLIC_NAME);
+            return bndManifest.at(celix::MANIFEST_BUNDLE_GROUP);
         }
 
         const std::string &version() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_VERSION); }
@@ -81,6 +84,7 @@ namespace celix {
         const long bndId;
         celix::Framework *const fw;
         const celix::Properties bndManifest;
+        const std::string bundleCache;
 
         std::atomic<BundleState> bndState;
     };
diff --git a/libs/framework_cxx/src/BundleController.h b/libs/framework_cxx/src/BundleController.h
index 3f4e1b7..1228066 100644
--- a/libs/framework_cxx/src/BundleController.h
+++ b/libs/framework_cxx/src/BundleController.h
@@ -20,7 +20,14 @@
 #ifndef CXX_CELIX_BUNDLECONTROLLER_H
 #define CXX_CELIX_BUNDLECONTROLLER_H
 
+#include <fstream>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
 #include <glog/logging.h>
+#include <zip.h>
+#include <dirent.h>
 
 #include "celix/IBundle.h"
 #include "celix/BundleContext.h"
@@ -32,8 +39,13 @@ namespace celix {
         BundleController(
                 std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> _actFactory,
                 std::shared_ptr<celix::Bundle> _bnd,
-                std::shared_ptr<celix::BundleContext> _ctx) :
-                actFactory{std::move(_actFactory)}, bnd{std::move(_bnd)}, ctx{std::move(_ctx)} {}
+                std::shared_ptr<celix::BundleContext> _ctx,
+                const uint8_t *rZip,
+                size_t rZipLen) :
+                actFactory{std::move(_actFactory)}, bnd{std::move(_bnd)}, ctx{std::move(_ctx)}, resourcesZip{rZip}, resourcesZipLen{rZipLen} {}
+
+        BundleController(const BundleController&) = delete;
+        BundleController& operator=(const BundleController&) = delete;
 
         //specific part
         bool transitionTo(BundleState desired) {
@@ -44,13 +56,15 @@ namespace celix {
                 //nop
                 success = true;
             } else if (state == BundleState::INSTALLED && desired == BundleState::ACTIVE) {
-                act = std::unique_ptr<celix::IBundleActivator>{actFactory(ctx)};
-                bnd->setState(BundleState::ACTIVE);
-                success = true;
+                success = createBundleCache();
+                if (success) {
+                    act = std::unique_ptr<celix::IBundleActivator>{actFactory(ctx)};
+                    bnd->setState(BundleState::ACTIVE);
+                }
             } else if (state == BundleState::ACTIVE && desired == BundleState::INSTALLED ) {
                 act = nullptr;
-                bnd->setState(BundleState::INSTALLED);
-                success = true;
+                success = deleteBundleCache();
+                bnd->setState(BundleState::INSTALLED); //note still going to installed
             } else {
                 //LOG(ERROR) << "Unexpected desired state " << desired << " from state " << bndState << std::endl;
                 LOG(ERROR) << "Unexpected desired/form state combination " << std::endl;
@@ -61,9 +75,177 @@ namespace celix {
         std::shared_ptr<celix::Bundle> bundle() const { return bnd; }
         std::shared_ptr<celix::BundleContext> context() const { return ctx; }
     private:
+        bool createBundleCache() {
+            auto bundleCache =  bundle()->cacheRoot();
+            bool success = createDir(bundleCache);
+            if (success) {
+                //auto manifestPath = bundle()->absPathForCacheEntry("META-INF/manifest.mf");
+                //TODO success = celix::storeProperties(bundle()->manifest(), manifestPath);
+            }
+            if (success) {
+                success = extractResources(bundleCache);
+            }
+            return success;
+        }
+
+        bool deleteBundleCache() {
+            return deleteDir(bundle()->cacheRoot());
+        }
+
+        bool deleteDir(const std::string &path) {
+            bool success = false;
+            DIR *dir;
+            dir = opendir(path.c_str());
+            if (dir == NULL) {
+                LOG(WARNING) << "Cannot delete dir " << path << ". " << strerror(errno) << std::endl;
+            } else {
+                struct dirent* dent = NULL;
+                errno = 0;
+                dent = readdir(dir);
+                while (errno == 0 && dent != NULL) {
+                    if ((strcmp((dent->d_name), ".") != 0) && (strcmp((dent->d_name), "..") != 0)) {
+                        char subdir[512];
+                        snprintf(subdir, 512, "%s/%s", path.c_str(), dent->d_name);
+
+                        struct stat st;
+                        if (stat(subdir, &st) == 0) {
+                            if (S_ISDIR (st.st_mode)) {
+                                std::string sd{subdir};
+                                success = deleteDir(sd);
+                            } else {
+                                if (remove(subdir) != 0) {
+                                    LOG(WARNING) << "Cannot delete dir " << path << ". " << strerror(errno) << std::endl;
+                                }
+                            }
+                        }
+                    }
+                    errno = 0;
+                    dent = readdir(dir);
+                }
+
+                if (errno != 0) {
+                    LOG(WARNING) << "Cannot delete dir " << path << ". " << strerror(errno) << std::endl;
+                } else if (closedir(dir) != 0) {
+                    LOG(WARNING) << "Cannot close dir " << path << ". " << strerror(errno) << std::endl;
+                } else {
+                    if (rmdir(path.c_str()) != 0) {
+                        LOG(WARNING) << "Cannot delete dir " << path << ". " << strerror(errno) << std::endl;
+                    } else {
+                        success = true;
+                    }
+                }
+            }
+
+            return success;
+        }
+
+        bool createDir(const std::string &path) {
+            bool success = false;
+
+            struct stat st;
+            bool exists = stat(path.c_str(), &st) == 0 && S_ISDIR(st.st_mode);
+
+            if (!exists) {
+                const char *slashAt = strrchr(path.c_str(), '/');
+                if (slashAt == nullptr) {
+                    //no sub dir
+                    if (mkdir(path.c_str(), S_IRWXU) == 0) {
+                        success = true;
+                    } else {
+                        LOG(WARNING) << "Cannot create dir " << path << ". " << strerror(errno) << std::endl;
+                    }
+                } else {
+                    std::string subdir = path.substr(0, slashAt - path.c_str());
+                    bool subdirCreated = createDir(subdir);
+                    if (subdirCreated) {
+                        if (mkdir(path.c_str(), S_IRWXU) == 0) {
+                            success = true;
+                        } else {
+                            LOG(WARNING) << "Cannot create dir " << path << ". " << strerror(errno) << std::endl;
+                        }
+                    } else {
+                        //nop, error should be reported in the recursion
+                    }
+                }
+            } else {
+                //exists, so true
+                success = true;
+            }
+
+
+            return success;
+        }
+
+        bool extractResources(const std::string &bundleCache) {
+            bool success = false;
+            if (resourcesZip != nullptr) {
+                zip_error_t error;
+                zip_source_t *source = zip_source_buffer_create(resourcesZip, resourcesZipLen, 1, &error);
+                if (source != nullptr) {
+                    zip_t *zip = zip_open_from_source(source, ZIP_RDONLY, &error);
+                    if (zip != nullptr) {
+                        extractZipSource(zip, bundleCache);
+                        //zip_close(zip); ? not needed on zip_source ?
+                        zip_source_close(source);
+                        success = true;
+                    } else {
+                        LOG(WARNING) << "Cannot create zip from source: " << zip_error_strerror(&error) << std::endl;
+                    }
+                } else {
+                    LOG(WARNING) << "Cannot create zip source: " << zip_error_strerror(&error) << std::endl;
+                }
+            } else {
+                //no resources
+                success = true;
+            }
+            return success;
+        }
+
+        bool extractZipSource(zip_t *zip, const std::string &bundleCache) {
+            bool succes = true;
+            char buf[128];
+            zip_int64_t nrOfEntries = zip_get_num_entries(zip, 0);
+            for (int i = 0; i < nrOfEntries; ++i) {
+                zip_stat_t st;
+                zip_stat_index(zip, i, 0, &st);
+                if (st.name[strlen(st.name) - 1] == '/') {
+                    //dir
+                    //TODO
+                    LOG(ERROR) << "TODO extract dirs" << std::endl;
+                    succes = false;
+                } else {
+                    //file
+                    zip_file_t *f = zip_fopen_index(zip, i, 0);
+                    if (f != nullptr) {
+                        std::ofstream outf;
+                        std::string p = bundleCache + "/" + st.name;
+                        outf.open(p);
+                        if (!outf.fail()) {
+                            zip_int64_t read = zip_fread(f, buf, 128);
+                            while (read != 0) {
+                                outf.write(buf, read);
+                                read = zip_fread(f, buf, 128);
+                            }
+                            outf.close();
+                        } else {
+                            LOG(WARNING) << "Cannot open file '" << p << "': " << std::endl;
+                        }
+                        zip_fclose(f);
+                    } else {
+                        LOG(WARNING) << "Cannot read file from zip: " << zip_strerror(zip) << std::endl;
+                        succes = false;
+                        break;
+                    }
+                }
+            }
+            return succes;
+        }
+
         const std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory;
         const std::shared_ptr<celix::Bundle> bnd;
         const std::shared_ptr<celix::BundleContext> ctx;
+        const uint8_t *resourcesZip;
+        const size_t resourcesZipLen;
 
         mutable std::mutex mutex{};
         std::unique_ptr<celix::IBundleActivator> act{nullptr};
diff --git a/libs/framework_cxx/src/Framework.cc b/libs/framework_cxx/src/Framework.cc
index a96ce86..0b1d856 100644
--- a/libs/framework_cxx/src/Framework.cc
+++ b/libs/framework_cxx/src/Framework.cc
@@ -21,6 +21,8 @@
  *under the License.
  */
 
+#include "celix/Framework.h"
+
 #include <unordered_map>
 #include <mutex>
 #include <iostream>
@@ -32,15 +34,20 @@
 #include <linux/limits.h>
 
 #include <glog/logging.h>
-
-#include "celix/Framework.h"
+#include <uuid/uuid.h>
 
 #include "BundleController.h"
 
+
+extern bool extractBundle(const char *bundleZip, const char *targetPath); //FROM miniunz.c
+
+
 struct StaticBundleEntry {
     const std::string symbolicName;
     const celix::Properties manifest;
     const std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> activatorFactory;
+    const uint8_t *resourcesZip;
+    const size_t resourcesZipLen;
 };
 
 static struct {
@@ -55,7 +62,9 @@ static void unregisterFramework(celix::Framework *fw);
 
 class celix::Framework::Impl : public IBundle {
 public:
-    Impl(celix::Framework *_fw, celix::Properties _config) : fw{_fw}, config{std::move(_config)}, bndManifest{createManifest()}, cwd{createCwd()} {}
+    Impl(celix::Framework *_fw, celix::Properties _config) : fw{_fw}, config{std::move(_config)}, bndManifest{createManifest()}, cwd{cwdString()}, fwUUID{uuidString()}{
+        startFramework();
+    }
 
     Impl(const Impl&) = delete;
     Impl& operator=(const Impl&) = delete;
@@ -78,8 +87,13 @@ public:
         return result;
     }
 
-    long installBundle(std::string symbolicName, std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory, celix::Properties manifest, bool autoStart) {
-        //TODO if activator is nullptr -> use empty activator
+    long installBundle(
+            std::string symbolicName,
+            std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory,
+            celix::Properties manifest,
+            bool autoStart,
+            const uint8_t *resourcesZip,
+            size_t resourcesZipLen) {
         //TODO on separate thread ?? specific bundle resolve thread ??
         long bndId = -1L;
         if (symbolicName.empty()) {
@@ -104,7 +118,7 @@ public:
             bndId = bundles.nextBundleId++;
             auto bnd = std::shared_ptr<celix::Bundle>{new celix::Bundle{bndId, this->fw, std::move(manifest)}};
             auto ctx = std::shared_ptr<celix::BundleContext>{new celix::BundleContext{bnd}};
-            bndController = std::shared_ptr<celix::BundleController>{new celix::BundleController{std::move(actFactory), bnd, ctx}};
+            bndController = std::shared_ptr<celix::BundleController>{new celix::BundleController{std::move(actFactory), bnd, ctx, resourcesZip, resourcesZipLen}};
             bundles.entries.emplace(std::piecewise_construct,
                                      std::forward_as_tuple(bndId),
                                      std::forward_as_tuple(bndController));
@@ -243,11 +257,15 @@ public:
 
     //resource bundle part
     long id() const noexcept override { return 1L /*note registry empty bundle is id 0, framework is id 1*/; }
-    bool has(const std::string&) const noexcept override { return false; }
-    bool isDir(const std::string&) const noexcept override { return false; }
-    bool isFile(const std::string&) const noexcept override { return false; }
-    std::vector<std::string> readDir(const std::string&) const noexcept override { return std::vector<std::string>{};}
-    const std::string& root() const noexcept override { //TODO
+    bool hasCacheEntry(const std::string &) const noexcept override { return false; }
+    bool isCacheEntryDir(const std::string &) const noexcept override { return false; }
+    bool isCacheEntryFile(const std::string &) const noexcept override { return false; }
+
+    //virtual bool storeResource(const std::string &path, std::ostream content) noexcept = 0;
+    //virtual std::istream open(const std::string &path) const noexcept = 0;
+    //virtual std::fstream open(const std::string &path) noexcept = 0;
+    std::string absPathForCacheEntry(const std::string &) const noexcept override { return {}; }
+    const std::string& cacheRoot() const noexcept override { //TODO
         return cwd;
     }
 
@@ -263,7 +281,25 @@ public:
     bool isValid() const noexcept override { return true; }
     celix::Framework& framework() const noexcept override { return *fw; }
 
+    std::string cacheDir() const {
+        return cwd + "/.cache"; //TODO make configurable
+    }
+
+    std::vector<std::string> readCacheDir(const std::string &) const noexcept override { return {}; } //TODO
+
+    std::string uuid() const {
+        return fwUUID;
+    }
+
+    bool startFramework() {
+        //TODO create cache dir using a process id (and  lock file?).
+        //Maybe also move to /var/cache or /tmp and when framework stop delete all framework caches of not running processes
+        std::cout << "Celix Framework Started";
+        return true;
+    }
+
     bool stopFramework() {
+        //TODO create cache dir
         std::lock_guard<std::mutex> lck{shutdown.mutex};
         if (!shutdown.shutdownStarted) {
             shutdown.future = std::async(std::launch::async, [this]{
@@ -279,6 +315,7 @@ public:
             shutdown.shutdownStarted = true;
             shutdown.cv.notify_all();
         }
+        std::cout << "Celix Framework Stopped";
         return true;
     }
 
@@ -299,7 +336,15 @@ private:
         return m;
     }
 
-    std::string createCwd() {
+    std::string uuidString() {
+        char uuidStr[37];
+        uuid_t uuid;
+        uuid_generate_time_safe(uuid);
+        uuid_unparse(uuid, uuidStr);
+        return std::string{uuidStr};
+    }
+
+    std::string cwdString() {
         char workdir[PATH_MAX];
         if (getcwd(workdir, sizeof(workdir)) != NULL) {
             return std::string{workdir};
@@ -313,6 +358,7 @@ private:
     const celix::Properties config;
     const celix::Properties bndManifest;
     const std::string cwd;
+    const std::string fwUUID;
 
 
     struct {
@@ -352,8 +398,14 @@ celix::Framework::Framework(Framework &&rhs) = default;
 celix::Framework& celix::Framework::operator=(Framework&& rhs) = default;
 
 
-long celix::Framework::installBundle(std::string name, std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory, celix::Properties manifest, bool autoStart) {
-    return pimpl->installBundle(std::move(name), actFactory, std::move(manifest), autoStart);
+long celix::Framework::installBundle(
+        std::string name,
+        std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> actFactory,
+        celix::Properties manifest,
+        bool autoStart,
+        const uint8_t *resourcesZip,
+        size_t resourcesZipLen) {
+    return pimpl->installBundle(std::move(name), std::move(actFactory), std::move(manifest), autoStart, resourcesZip, resourcesZipLen);
 }
 
 
@@ -373,6 +425,14 @@ bool celix::Framework::uninstallBundle(long bndId) { return pimpl->uninstallBund
 celix::ServiceRegistry& celix::Framework::registry(const std::string &lang) { return pimpl->registry(lang); }
 
 bool celix::Framework::waitForShutdown() const { return pimpl->waitForShutdown(); }
+std::string celix::Framework::cacheDir() const {
+    return pimpl->cacheDir();
+}
+
+std::string celix::Framework::uuid() const {
+    return pimpl->uuid();
+}
+
 
 /***********************************************************************************************************************
  * Celix 'global' functions
@@ -381,19 +441,26 @@ bool celix::Framework::waitForShutdown() const { return pimpl->waitForShutdown()
 void celix::registerStaticBundle(
         std::string symbolicName,
         std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> bundleActivatorFactory,
-        celix::Properties manifest) {
+        celix::Properties manifest,
+        const uint8_t *resourcesZip,
+        size_t resourcesZipLen) {
     std::lock_guard<std::mutex> lck{staticRegistry.mutex};
     for (auto fw : staticRegistry.frameworks) {
-        fw->installBundle(symbolicName, bundleActivatorFactory, manifest);
+        fw->installBundle(symbolicName, bundleActivatorFactory, manifest, true, resourcesZip, resourcesZipLen);
     }
-    staticRegistry.bundles.emplace_back(StaticBundleEntry{.symbolicName = std::move(symbolicName), .manifest = std::move(manifest), .activatorFactory = std::move(bundleActivatorFactory)});
+    staticRegistry.bundles.emplace_back(StaticBundleEntry{
+        .symbolicName = std::move(symbolicName),
+        .manifest = std::move(manifest),
+        .activatorFactory = std::move(bundleActivatorFactory),
+        .resourcesZip = resourcesZip,
+        .resourcesZipLen = resourcesZipLen});
 }
 
 static void registerFramework(celix::Framework *fw) {
     std::lock_guard<std::mutex> lck{staticRegistry.mutex};
     staticRegistry.frameworks.insert(fw);
     for (auto &entry : staticRegistry.bundles) {
-        fw->installBundle(entry.symbolicName, entry.activatorFactory, entry.manifest);
+        fw->installBundle(entry.symbolicName, entry.activatorFactory, entry.manifest, true, entry.resourcesZip, entry.resourcesZipLen);
     }
 }
 
diff --git a/libs/registry/CMakeLists.txt b/libs/registry/CMakeLists.txt
index 2a279de..5880f52 100644
--- a/libs/registry/CMakeLists.txt
+++ b/libs/registry/CMakeLists.txt
@@ -15,11 +15,10 @@
 # specific language governing permissions and limitations
 # under the License.
 
-find_package(glog REQUIRED)
-
 add_library(celix_registry STATIC
         src/ServiceRegistry.cc
         src/Filter.cc
+        src/Properties.cc
 )
 target_include_directories(celix_registry PRIVATE src)
 target_include_directories(celix_registry PUBLIC include)
diff --git a/libs/registry/include/celix/IResourceBundle.h b/libs/registry/include/celix/IResourceBundle.h
index 38b76b3..2b97c65 100644
--- a/libs/registry/include/celix/IResourceBundle.h
+++ b/libs/registry/include/celix/IResourceBundle.h
@@ -31,16 +31,17 @@ namespace celix {
 
         virtual long id() const noexcept  = 0;
 
-        virtual const std::string& root() const noexcept = 0;
+        virtual const std::string& cacheRoot() const noexcept = 0;
 
-        virtual bool has(const std::string &path) const noexcept = 0;
-        virtual bool isDir(const std::string &path) const noexcept = 0;
-        virtual bool isFile(const std::string &path) const noexcept = 0;
+        virtual bool hasCacheEntry(const std::string &entryPath) const noexcept = 0;
+        virtual bool isCacheEntryDir(const std::string &path) const noexcept = 0;
+        virtual bool isCacheEntryFile(const std::string &path) const noexcept = 0;
 
         //virtual bool storeResource(const std::string &path, std::ostream content) noexcept = 0;
         //virtual std::istream open(const std::string &path) const noexcept = 0;
         //virtual std::fstream open(const std::string &path) noexcept = 0;
-        virtual std::vector<std::string> readDir(const std::string &path) const noexcept = 0;
+        virtual std::string absPathForCacheEntry(const std::string &entry) const noexcept = 0;
+        virtual std::vector<std::string> readCacheDir(const std::string &path) const noexcept = 0;
     };
 
 
diff --git a/libs/registry/include/celix/Properties.h b/libs/registry/include/celix/Properties.h
index 1002bfc..649cf4c 100644
--- a/libs/registry/include/celix/Properties.h
+++ b/libs/registry/include/celix/Properties.h
@@ -56,11 +56,11 @@ namespace celix {
         return std::stoul(val, nullptr, 10);
     }
 
-    /*TODO
+
     celix::Properties loadProperties(const std::string &path);
-    celix::Properties loadProperties(std::istream stream);
-    bool storeProperties(const celix::Properties &props, const std::string &path);
-     */
+    celix::Properties loadProperties(std::istream &stream);
+    //bool storeProperties(const celix::Properties &props, const std::string &path); TODO
+    //bool storeProperties(const celix::Properties &props, std::ofstream &stream); TODO
 }
 
 #endif //CXX_CELIX_PROPERTIES_H
diff --git a/libs/registry/src/Properties.cc b/libs/registry/src/Properties.cc
new file mode 100644
index 0000000..403dee7
--- /dev/null
+++ b/libs/registry/src/Properties.cc
@@ -0,0 +1,215 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <fstream>
+#include <string>
+#include <cstring>
+
+#include <glog/logging.h>
+
+#include "celix/Properties.h"
+
+#define MALLOC_BLOCK_SIZE		5
+
+
+static char * utils_stringTrim(char * string) {
+    char* copy = string;
+
+    char *end;
+    // Trim leading space
+    while (isspace(*copy)) {
+        copy++;
+    }
+
+    // Trim trailing space
+    end = copy + strlen(copy) - 1;
+    while(end > copy && isspace(*end)) {
+        *(end) = '\0';
+        end--;
+    }
+
+    if (copy != string) {
+        //beginning whitespaces -> move char in copy to to begin string
+        //This to ensure free still works on the same pointer.
+        char* nstring = string;
+        while(*copy != '\0') {
+            *(nstring++) = *(copy++);
+        }
+        (*nstring) = '\0';
+    }
+
+    return string;
+}
+
+static void updateBuffers(char **key, char ** value, char **output, int outputPos, int *key_len, int *value_len) {
+    if (*output == *key) {
+        if (outputPos == (*key_len) - 1) {
+            (*key_len) += MALLOC_BLOCK_SIZE;
+            *key = (char*)realloc(*key, *key_len);
+            *output = *key;
+        }
+    }
+    else {
+        if (outputPos == (*value_len) - 1) {
+            (*value_len) += MALLOC_BLOCK_SIZE;
+            *value = (char*)realloc(*value, *value_len);
+            *output = *value;
+        }
+    }
+}
+
+static void parseLine(const char* line, celix::Properties &props) {
+    int linePos = 0;
+    bool precedingCharIsBackslash = false;
+    bool isComment = false;
+    int outputPos = 0;
+    char *output = NULL;
+    int key_len = MALLOC_BLOCK_SIZE;
+    int value_len = MALLOC_BLOCK_SIZE;
+    linePos = 0;
+    precedingCharIsBackslash = false;
+    isComment = false;
+    output = NULL;
+    outputPos = 0;
+
+    //Ignore empty lines
+    if (line[0] == '\n' && line[1] == '\0') {
+        return;
+    }
+
+    char *key = (char*)calloc(1, key_len);
+    char *value = (char*)calloc(1, value_len);
+    key[0] = '\0';
+    value[0] = '\0';
+
+    while (line[linePos] != '\0') {
+        if (line[linePos] == ' ' || line[linePos] == '\t') {
+            if (output == NULL) {
+                //ignore
+                linePos += 1;
+                continue;
+            }
+        }
+        else {
+            if (output == NULL) {
+                output = key;
+            }
+        }
+        if (line[linePos] == '=' || line[linePos] == ':' || line[linePos] == '#' || line[linePos] == '!') {
+            if (precedingCharIsBackslash) {
+                //escaped special character
+                output[outputPos++] = line[linePos];
+                updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
+                precedingCharIsBackslash = false;
+            }
+            else {
+                if (line[linePos] == '#' || line[linePos] == '!') {
+                    if (outputPos == 0) {
+                        isComment = true;
+                        break;
+                    }
+                    else {
+                        output[outputPos++] = line[linePos];
+                        updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
+                    }
+                }
+                else { // = or :
+                    if (output == value) { //already have a seperator
+                        output[outputPos++] = line[linePos];
+                        updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
+                    }
+                    else {
+                        output[outputPos++] = '\0';
+                        updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
+                        output = value;
+                        outputPos = 0;
+                    }
+                }
+            }
+        }
+        else if (line[linePos] == '\\') {
+            if (precedingCharIsBackslash) { //double backslash -> backslash
+                output[outputPos++] = '\\';
+                updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
+            }
+            precedingCharIsBackslash = true;
+        }
+        else { //normal character
+            precedingCharIsBackslash = false;
+            output[outputPos++] = line[linePos];
+            updateBuffers(&key, &value, &output, outputPos, &key_len, &value_len);
+        }
+        linePos += 1;
+    }
+    if (output != NULL) {
+        output[outputPos] = '\0';
+    }
+
+    if (!isComment) {
+        //printf("putting 'key'/'value' '%s'/'%s' in properties\n", utils_stringTrim(key), utils_stringTrim(value));
+        props[std::string{utils_stringTrim(key)}] = std::string{utils_stringTrim(value)};
+    }
+    if(key) {
+        free(key);
+    }
+    if(value) {
+        free(value);
+    }
+
+}
+
+celix::Properties celix::loadProperties(const std::string &path) {
+    std::ifstream file;
+    file.open(path);
+    if (file.fail()) {
+        LOG(WARNING) << "Cannot open file " << path << ". " << file.failbit << std::endl;
+        return celix::Properties{};
+    } else {
+        return celix::loadProperties(file);
+    }
+}
+
+celix::Properties celix::loadProperties(std::istream &stream) {
+    celix::Properties props{};
+
+    if (!stream.fail()) {
+        stream.seekg(0, stream.end);
+        long size = stream.tellg();
+        stream.seekg(0, stream.beg);
+
+        if (size > 0){
+            while (!stream.eof()) {
+                std::string line;
+                std::getline(stream, line);
+                parseLine(line.c_str(), props);
+            }
+        }
+    }
+
+    //TODO howto singal an error with parsing ...
+    return props;
+}
+
+//bool celix::storeProperties(const celix::Properties &props, const std::string &path) {
+//    return false; //TODO
+//}
+//
+//bool celix::storeProperties(const celix::Properties &props, std::ofstream &stream) {
+//    return false; //TODO
+//}
\ No newline at end of file
diff --git a/libs/registry/src/ServiceRegistry.cc b/libs/registry/src/ServiceRegistry.cc
index a7465e2..001b08e 100644
--- a/libs/registry/src/ServiceRegistry.cc
+++ b/libs/registry/src/ServiceRegistry.cc
@@ -42,18 +42,19 @@ namespace {
 
         long id() const noexcept override { return 0; }
 
-        const std::string& root() const noexcept override {
+        const std::string& cacheRoot() const noexcept override {
             static std::string empty{};
             return empty;
         }
 
-        bool has(const std::string&) const noexcept override { return false; }
-        bool isDir(const std::string&) const noexcept override { return false; }
-        bool isFile(const std::string&) const noexcept override { return false; }
+        bool hasCacheEntry(const std::string&) const noexcept override { return false; }
+        bool isCacheEntryDir(const std::string&) const noexcept override { return false; }
+        bool isCacheEntryFile(const std::string&) const noexcept override { return false; }
 
         //std::istream& open(const std::string &path) override {}
         //std::fstream& open(const std::string &path) override {}
-        std::vector<std::string> readDir(const std::string&) const noexcept override { return std::vector<std::string>{};}
+        std::string absPathForCacheEntry(const std::string &) const noexcept override { return {}; }
+        std::vector<std::string> readCacheDir(const std::string&) const noexcept override { return std::vector<std::string>{};}
     };
 
     struct SvcEntry {


[celix] 20/22: CELIX-438: Removes OSX (for now) from travis config

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit aeb19ff6696fe311d17bc4511a40aff83cfd1c74
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Mon Jan 7 17:05:55 2019 +0100

    CELIX-438: Removes OSX (for now) from travis config
---
 .travis.yml                         | 10 +++++-----
 libs/framework_cxx/src/Framework.cc |  4 ++--
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 843e946..dafc512 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -20,11 +20,11 @@ matrix:
          dist: xenial
          compiler: clang
          language: cpp
-       - os: osx
-         osx_image: xcode7.3
-         compiler: clang
-         env: MACOSX_DEPLOYMENT_TARGET=10.11
-         language: cpp
+         #- os: osx
+         #osx_image: xcode7.3
+         #compiler: clang
+         #env: MACOSX_DEPLOYMENT_TARGET=10.11
+         #language: cpp
        - os: linux
          dist: xenial
          compiler: gcc
diff --git a/libs/framework_cxx/src/Framework.cc b/libs/framework_cxx/src/Framework.cc
index 1b3ab87..9128c0e 100644
--- a/libs/framework_cxx/src/Framework.cc
+++ b/libs/framework_cxx/src/Framework.cc
@@ -408,8 +408,8 @@ celix::Framework::~Framework() {
     pimpl->waitForShutdown();
 }
 
-celix::Framework::Framework(Framework &&rhs) = default;
-celix::Framework& celix::Framework::operator=(Framework&& rhs) = default;
+celix::Framework::Framework(Framework &&) = default;
+celix::Framework& celix::Framework::operator=(Framework&&) = default;
 
 
 long celix::Framework::installBundle(


[celix] 19/22: CELIX-438: Fixes some test setup

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 20b047dcbba38e36708608805630d90c201c1e00
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Mon Jan 7 17:02:10 2019 +0100

    CELIX-438: Fixes some test setup
---
 bundles/pubsub/mock/CMakeLists.txt               | 16 +++++++++-------
 bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt |  2 +-
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/bundles/pubsub/mock/CMakeLists.txt b/bundles/pubsub/mock/CMakeLists.txt
index c310e1b..f77b2cd 100644
--- a/bundles/pubsub/mock/CMakeLists.txt
+++ b/bundles/pubsub/mock/CMakeLists.txt
@@ -28,14 +28,16 @@ if (CPPUTEST_FOUND)
         ${CPPUTEST_INCLUDE_DIR}
     )
 
+
     if (ENABLE_TESTING)
-        add_executable(pubsubmock_test
-            tst/pubsubmock_test.cc
-            tst/run_tests.cc
-        )
-        target_include_directories(pubsubmock_test PRIVATE ${CMAKE_CURRENT_LIST_DIR}/api)
-	target_link_libraries(pubsubmock_test PRIVATE Celix::pubsub_api pubsub_mock ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::framework)
-        add_test(NAME pubsubmock_test COMMAND pubsubmock_test)
+        #disabling cpputest based tests
+#        add_executable(pubsubmock_test
+#            tst/pubsubmock_test.cc
+#            tst/run_tests.cc
+#        )
+#        target_include_directories(pubsubmock_test PRIVATE ${CMAKE_CURRENT_LIST_DIR}/api)
+#	    target_link_libraries(pubsubmock_test PRIVATE Celix::pubsub_api pubsub_mock ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} Celix::framework)
+#        add_test(NAME pubsubmock_test COMMAND pubsubmock_test)
     endif()
 endif()
 
diff --git a/bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt b/bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt
index 7626eb5..710af05 100644
--- a/bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt
+++ b/bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt
@@ -20,7 +20,7 @@ set(SOURCES
         src/ShellTui_tests.cc
 )
 add_executable(celix_cxx_shell_tui_tests ${SOURCES})
-target_link_libraries(celix_cxx_shell_tui_tests PRIVATE gtest celix_framework_cxx shell_tui_static celix_cxx_shell_api)
+target_link_libraries(celix_cxx_shell_tui_tests PRIVATE gtest celix_framework_cxx shell_tui_static celix_cxx_shell_api glog::glog)
 
 add_test(NAME celix_cxx_shell_tui_tests COMMAND celix_cxx_shell_tui_tests)
 SETUP_TARGET_FOR_COVERAGE(celix_cxx_shell_tui_tests_cov celix_cxx_shell_tui_tests ${CMAKE_BINARY_DIR}/coverage/celix_cxx_shell_tui_tests/celix_cxx_shell_tui_tests ..)
\ No newline at end of file


[celix] 13/22: CELIX-438: Update travis config

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 82b453bbec5477ca5fe808dc184d82c4726253b3
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Sun Jan 6 20:36:46 2019 +0100

    CELIX-438: Update travis config
---
 .travis.yml                | 4 ++++
 libs/registry/src/Utils.cc | 1 +
 2 files changed, 5 insertions(+)

diff --git a/.travis.yml b/.travis.yml
index e5ec93a..843e946 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,17 +15,21 @@ matrix:
        - os: linux
          dist: xenial
          compiler: gcc
+         language: cpp
        - os: linux
          dist: xenial
          compiler: clang
+         language: cpp
        - os: osx
          osx_image: xcode7.3
          compiler: clang
          env: MACOSX_DEPLOYMENT_TARGET=10.11
+         language: cpp
        - os: linux
          dist: xenial
          compiler: gcc
          env: SANITIZE=1
+         language: cpp
 
 #DISABLED ANDROID BUILD
 #       - os: linux
diff --git a/libs/registry/src/Utils.cc b/libs/registry/src/Utils.cc
index 27feccb..c0c5ea9 100644
--- a/libs/registry/src/Utils.cc
+++ b/libs/registry/src/Utils.cc
@@ -20,6 +20,7 @@
 #include "celix/Utils.h"
 
 #include <string>
+#include <cassert>
 
 #include <glog/logging.h>
 


[celix] 21/22: CELIX-438: Convert libzip external project setup to a FindLIBZIP cmake file

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 4eebbdc5df936f8bc8208918b14bd05defa76429
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Mon Jan 7 20:48:00 2019 +0100

    CELIX-438: Convert libzip external project setup to a FindLIBZIP cmake file
---
 .travis.yml                                        |  2 -
 CMakeLists.txt                                     |  2 +-
 bundles/shell/cxx_shell/src/QueryCommand.cc        |  2 +-
 cmake/Modules/FindLIBZIP.cmake                     | 52 ++++++++++++++++++++++
 examples/celix-examples/CMakeLists.txt             |  5 ++-
 .../cxx_shell_example}/CMakeLists.txt              | 21 ++-------
 .../celix-examples/cxx_shell_example/src/main.cc   | 34 ++++++++++++++
 libs/dfi/CMakeLists.txt                            |  2 +-
 libs/framework_cxx/CMakeLists.txt                  |  2 +
 9 files changed, 98 insertions(+), 24 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index dafc512..ead5d89 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -81,8 +81,6 @@ script:
     - if [ "$CC" = "gcc" ] && [ "$TRAVIS_OS_NAME" = "linux" ]; then export BUILD_OPTS="${BUILD_OPTS} -DENABLE_CODE_COVERAGE=ON"; fi
     - if [ "$TRAVIS_OS_NAME" = "linux" ] && [ -z "$ANDROID" ]; then cmake -DCMAKE_BUILD_TYPE=Debug ${BUILD_OPTIONS} ${BUILD_OPTIONS_LINUX} -DBUILD_FRAMEWORK_TESTS=ON -DBUILD_UTILS-TESTS=ON -DENABLE_TESTING=ON ${BUILD_OPTS} -DCMAKE_INSTALL_PREFIX=../install ..; fi
     - if [ "$TRAVIS_OS_NAME" = "osx" ]; then cmake -DCMAKE_BUILD_TYPE=Debug ${BUILD_OPTIONS} ${BUILD_OPTIONS_OSX} -DBUILD_FRAMEWORK_TESTS=ON -DBUILD_UTILS-TESTS=ON -DENABLE_TESTING=ON -DFFI_LIBRARY=/usr/local/opt/libffi/lib/libffi.dylib ${BUILD_OPTS} -DCMAKE_INSTALL_PREFIX=../install ..; fi
-    - if [ -z "$ANDROID" ]; then make all && make deploy && sudo make install; else cd .. && docker build -t celixandroid - < misc/Dockerfile.Android ; fi
-    - if [ -z "$ANDROID" ]; then export LD_LIBRARY_PATH=/usr/local/lib:$LD_LIBRARY_PATH:`pwd`/utils:`pwd`/framework:`pwd`/dfi && make test ARGS="-V"; else docker run celixandroid; fi 
 
 after_success:
     - if [ "$CC" = "gcc" ] && [ "$TRAVIS_OS_NAME" = "linux" ]; then 
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 669cc43..b728c86 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -59,7 +59,7 @@ if (ENABLE_TESTING)
     #include(cmake/celix_project/AddCppUTest.cmake)
 endif ()
 include(cmake/celix_project/AddGLog.cmake)
-include(cmake/celix_project/AddLibzip.cmake)
+#include(cmake/celix_project/AddLibzip.cmake)
 
 # Default bundle version
 set(DEFAULT_VERSION 1.0.0)
diff --git a/bundles/shell/cxx_shell/src/QueryCommand.cc b/bundles/shell/cxx_shell/src/QueryCommand.cc
index 67206bc..f90b5c7 100644
--- a/bundles/shell/cxx_shell/src/QueryCommand.cc
+++ b/bundles/shell/cxx_shell/src/QueryCommand.cc
@@ -71,6 +71,6 @@ celix::ServiceRegistration impl::registerQuery(std::shared_ptr<celix::BundleCont
     celix::Properties props{};
     props[celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME] = "query";
     props[celix::SHELL_COMMAND_FUNCTION_COMMAND_USAGE] = "query [lang] [serviceName serviceFilter]";
-    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION] = "Query the service registry. If no argumenst are provided list the available services names.";
+    props[celix::SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION] = "Query the service registry. If no arguments are provided list the available services names.";
     return ctx->registerFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, std::move(cmd), std::move(props));
 }
\ No newline at end of file
diff --git a/cmake/Modules/FindLIBZIP.cmake b/cmake/Modules/FindLIBZIP.cmake
new file mode 100644
index 0000000..e13dd0f
--- /dev/null
+++ b/cmake/Modules/FindLIBZIP.cmake
@@ -0,0 +1,52 @@
+
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+# 
+#   http://www.apache.org/licenses/LICENSE-2.0
+# 
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+
+# - Try to find libffi define the variables for the binaries/headers and include 
+#
+# Once done this will define
+#  LIBZIP_FOUND - System has libffi
+#  libzip::libzip target
+
+mark_as_advanced(GNUTLS_INCLUDE_DIR GNUTLS_LIBRARY)
+
+find_library(LIBZIP_LIBRARY NAMES zip
+        PATHS $ENV{LIBZIP_DIR} ${LIBZIP_DIR} /usr /usr/local /opt/local
+        PATH_SUFFIXES lib lib64 x86_64-linux-gnu lib/x86_64-linux-gnu
+)
+
+find_path(LIBZIP_INCLUDE_DIR zip.h
+		PATHS $ENV{LIBZIP_DIR} ${LIBZIP_DIR} /usr /usr/local /opt/local
+        PATH_SUFFIXES include include/ffi include/x86_64-linux-gnu x86_64-linux-gnu
+)
+
+include(FindPackageHandleStandardArgs)
+# handle the QUIETLY and REQUIRED arguments and set LIBZIP_FOUND to TRUE
+# if all listed variables are TRUE
+find_package_handle_standard_args(LIBZIP  DEFAULT_MSG
+                                  LIBZIP_LIBRARY LIBZIP_INCLUDE_DIR)
+
+if(LIBZIP_FOUND)
+    add_library(libzip::libzip IMPORTED STATIC GLOBAL)
+    set_target_properties(libzip::libzip PROPERTIES
+            IMPORTED_LOCATION "${LIBZIP_LIBRARY}"
+            INTERFACE_INCLUDE_DIRECTORIES "${LIBZIP_INCLUDE_DIR}"
+    )
+endif()
+
+unset(LIBZIP_LIBRARY)
+unset(LIBZIP_INCLUDE_DIR)
diff --git a/examples/celix-examples/CMakeLists.txt b/examples/celix-examples/CMakeLists.txt
index 0975a60..d36116e 100644
--- a/examples/celix-examples/CMakeLists.txt
+++ b/examples/celix-examples/CMakeLists.txt
@@ -38,8 +38,11 @@ if (EXAMPLES)
     add_subdirectory(embedding)
     add_subdirectory(service_hook_example)
     add_subdirectory(log_service_example)
+    add_subdirectory(shell_command_example)
 
 
-    add_subdirectory(shell_command_example)
+    #Example for the C++ framework
+    add_subdirectory(cxx_shell_example)
+
 
 endif(EXAMPLES)
diff --git a/libs/framework_cxx/CMakeLists.txt b/examples/celix-examples/cxx_shell_example/CMakeLists.txt
similarity index 54%
copy from libs/framework_cxx/CMakeLists.txt
copy to examples/celix-examples/cxx_shell_example/CMakeLists.txt
index 98c857d..d0e9aa4 100644
--- a/libs/framework_cxx/CMakeLists.txt
+++ b/examples/celix-examples/cxx_shell_example/CMakeLists.txt
@@ -15,23 +15,8 @@
 # specific language governing permissions and limitations
 # under the License.
 
-find_package(UUID REQUIRED)
-if(NOT APPLE)
-    set(UUID ${UUID_LIBRARY})
-endif()
 
-#TODO rename to celix::framework
-add_library(celix_framework_cxx SHARED
-        src/Framework.cc
-        src/BundleContext.cc
-        src/Bundle.cc
+add_executable(cxx_shell_example
+        src/main.cc
 )
-target_include_directories(celix_framework_cxx PRIVATE src)
-target_include_directories(celix_framework_cxx PUBLIC include)
-target_link_libraries(celix_framework_cxx PRIVATE glog::glog libzip::libzip)
-#NOTE because of libzil libbz2 and libz is also needed. maybe more to other form of resources (i.e. tar)
-target_link_libraries(celix_framework_cxx PUBLIC celix::registry bz2 z ${UUID})
-
-if (ENABLE_TESTING)
-    add_subdirectory(gtest)
-endif ()
\ No newline at end of file
+target_link_libraries(cxx_shell_example PRIVATE celix_cxx_shell celix_cxx_shell_tui glog::glog)
\ No newline at end of file
diff --git a/examples/celix-examples/cxx_shell_example/src/main.cc b/examples/celix-examples/cxx_shell_example/src/main.cc
new file mode 100644
index 0000000..b4b50da
--- /dev/null
+++ b/examples/celix-examples/cxx_shell_example/src/main.cc
@@ -0,0 +1,34 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <glog/logging.h>
+
+#include "celix/api.h"
+
+
+int main(int /*argc*/, char **argv) {
+    //TODO move glog init to framework (a pthread_once?), so that glog::glog dep can be removed from executables.
+    google::InitGoogleLogging(argv[0]);
+    google::LogToStderr();
+
+    //TODO create launcher, which handles config.properties and command args
+    auto fw = celix::Framework{};
+    fw.waitForShutdown();
+    return 0;
+}
\ No newline at end of file
diff --git a/libs/dfi/CMakeLists.txt b/libs/dfi/CMakeLists.txt
index b738730..ee75635 100644
--- a/libs/dfi/CMakeLists.txt
+++ b/libs/dfi/CMakeLists.txt
@@ -74,5 +74,5 @@ if (ENABLE_TESTING AND DFI_TESTS)
 
 	add_test(NAME run_test_dfi COMMAND test_dfi)
 	SETUP_TARGET_FOR_COVERAGE(test_dfi_cov test_dfi ${CMAKE_BINARY_DIR}/coverage/test_dfi/test_dfi)
-endif(ENABLE_TESTING)
+endif ()
 
diff --git a/libs/framework_cxx/CMakeLists.txt b/libs/framework_cxx/CMakeLists.txt
index 98c857d..c4604ac 100644
--- a/libs/framework_cxx/CMakeLists.txt
+++ b/libs/framework_cxx/CMakeLists.txt
@@ -16,6 +16,8 @@
 # under the License.
 
 find_package(UUID REQUIRED)
+find_package(LIBZIP REQUIRED)
+
 if(NOT APPLE)
     set(UUID ${UUID_LIBRARY})
 endif()


[celix] 04/22: CELIX-438: Updates to compile on gcc, adds glog as external project and fixes code coverage setup

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 9e854fdaf08a04f51d42a34d37e7964c056703a8
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Thu Jan 3 11:40:54 2019 +0100

    CELIX-438: Updates to compile on gcc, adds glog as external project and fixes code coverage setup
---
 CMakeLists.txt                                     |  8 ++++----
 bundles/shell/cxx_shell/CMakeLists.txt             |  4 ++--
 bundles/shell/cxx_shell/src/ShellActivator.cc      |  1 +
 bundles/shell/cxx_shell_tui/CMakeLists.txt         |  4 ++--
 .../shell/cxx_shell_tui/src/ShellTuiActivator.cc   |  9 +++++----
 .../celix_project/AddGLog.cmake                    | 19 ++++++++----------
 cmake/celix_project/CodeCoverage.cmake             | 11 +++++++++--
 libs/framework/tst/CMakeLists.txt                  |  3 ++-
 libs/framework_cxx/CMakeLists.txt                  |  3 ++-
 libs/framework_cxx/gtest/CMakeLists.txt            |  3 ++-
 libs/framework_cxx/gtest/src/Framework_tests.cc    |  8 +++++---
 libs/framework_cxx/src/Bundle.h                    | 10 +++++++---
 libs/framework_cxx/src/BundleContext.cc            |  8 +++++---
 libs/framework_cxx/src/Framework.cc                | 23 ++++++++++++++--------
 libs/registry/CMakeLists.txt                       |  3 ++-
 libs/registry/gtest/CMakeLists.txt                 |  3 ++-
 .../gtest/src/RegistryConcurrency_tests.cc         |  2 ++
 libs/registry/gtest/src/Registry_tests.cc          |  5 ++++-
 libs/registry/include/celix/Filter.h               |  1 +
 libs/registry/include/celix/IResourceBundle.h      |  1 +
 libs/registry/include/celix/ServiceRegistry.h      |  2 ++
 libs/registry/include/celix/Utils.h                |  2 +-
 libs/registry/src/ServiceRegistry.cc               | 11 ++++++-----
 23 files changed, 90 insertions(+), 54 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 9ba636e..c1c4a43 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -47,17 +47,17 @@ ELSE ()
 ENDIF()
 
 # Set version for the framework package/release
-set(CELIX_MAJOR "2")
-set(CELIX_MINOR "2")
+set(CELIX_MAJOR "3")
+set(CELIX_MINOR "0")
 set(CELIX_MICRO "0")
 
-option(ENABLE_TESTING "Enables unit testing using CPPUTEST" OFF)
-option(ENABLE_GTESTING "Enables unit testing using GTest" ON)
+option(ENABLE_TESTING "Enables unit testing" OFF)
 
 if (ENABLE_TESTING)
 	enable_testing()
     include(cmake/celix_project/AddGTest.cmake)
 endif ()
+include(cmake/celix_project/AddGLog.cmake)
 
 # Default bundle version
 set(DEFAULT_VERSION 1.0.0)
diff --git a/bundles/shell/cxx_shell/CMakeLists.txt b/bundles/shell/cxx_shell/CMakeLists.txt
index ccdf03b..a4ad2df 100644
--- a/bundles/shell/cxx_shell/CMakeLists.txt
+++ b/bundles/shell/cxx_shell/CMakeLists.txt
@@ -34,8 +34,8 @@ add_library(celix_cxx_shell SHARED
         src/QueryCommand.cc
 )
 target_include_directories(celix_cxx_shell PRIVATE src)
-target_link_libraries(celix_cxx_shell PRIVATE celix_cxx_shell_api)
-target_link_libraries(celix_cxx_shell PUBLIC glog::glog celix_framework_cxx)
+target_link_libraries(celix_cxx_shell PRIVATE celix_cxx_shell_api glog::glog)
+target_link_libraries(celix_cxx_shell PUBLIC celix_framework_cxx)
 
 #if (ENABLE_TESTING)
 #    add_subdirectory(gtest)
diff --git a/bundles/shell/cxx_shell/src/ShellActivator.cc b/bundles/shell/cxx_shell/src/ShellActivator.cc
index 58c8f2f..bfbbb8f 100644
--- a/bundles/shell/cxx_shell/src/ShellActivator.cc
+++ b/bundles/shell/cxx_shell/src/ShellActivator.cc
@@ -44,6 +44,7 @@ namespace {
                 }
                 token = strtok_r(nullptr, " ", &savePtr);
             }
+            free(cl);
 
             bool commandCalled = false;
 
diff --git a/bundles/shell/cxx_shell_tui/CMakeLists.txt b/bundles/shell/cxx_shell_tui/CMakeLists.txt
index df20046..cfbf6cf 100644
--- a/bundles/shell/cxx_shell_tui/CMakeLists.txt
+++ b/bundles/shell/cxx_shell_tui/CMakeLists.txt
@@ -24,8 +24,8 @@ add_library(celix_cxx_shell_tui SHARED
         src/ShellTuiActivator.cc
         src/shell_test.cc)
 target_include_directories(celix_cxx_shell_tui PRIVATE src)
-target_link_libraries(celix_cxx_shell_tui PRIVATE celix_cxx_shell_api)
-target_link_libraries(celix_cxx_shell_tui PUBLIC glog::glog celix_framework_cxx)
+target_link_libraries(celix_cxx_shell_tui PRIVATE celix_cxx_shell_api glog::glog)
+target_link_libraries(celix_cxx_shell_tui PUBLIC celix_framework_cxx)
 
 #if (ENABLE_TESTING)
 #    add_subdirectory(gtest)
diff --git a/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc b/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc
index a1ddf5a..a66bea5 100644
--- a/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc
+++ b/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc
@@ -21,6 +21,7 @@
 #include <cstdio>
 #include <unistd.h>
 #include <fcntl.h>
+#include <mutex>
 
 #include <glog/logging.h>
 
@@ -115,10 +116,10 @@ namespace {
         std::mutex mutex{};
         std::shared_ptr<celix::IShell> shell{};
 
-        std::thread readThread;
+        std::thread readThread{};
 
-        int readPipeFd;
-        int writePipeFd;
+        int readPipeFd{};
+        int writePipeFd{};
 
 
         char in[LINE_SIZE+1]{};
@@ -136,7 +137,7 @@ namespace {
         }
     private:
         ShellTui tui{};
-        celix::ServiceTracker trk;
+        celix::ServiceTracker trk{};
     };
 
     __attribute__((constructor))
diff --git a/libs/registry/CMakeLists.txt b/cmake/celix_project/AddGLog.cmake
similarity index 64%
copy from libs/registry/CMakeLists.txt
copy to cmake/celix_project/AddGLog.cmake
index ee537cc..8cc3414 100644
--- a/libs/registry/CMakeLists.txt
+++ b/cmake/celix_project/AddGLog.cmake
@@ -15,18 +15,15 @@
 # specific language governing permissions and limitations
 # under the License.
 
-find_package(glog REQUIRED)
 
-add_library(celix_registry STATIC
-        src/ServiceRegistry.cc
-        src/Filter.cc
+include(ExternalProject)
+ExternalProject_Add(
+        googlelog_project
+        GIT_REPOSITORY https://github.com/google/glog.git
+        GIT_TAG v0.3.5
+        PREFIX ${CMAKE_CURRENT_BINARY_DIR}/glog
+        CMAKE_ARGS -DWITH_GFLAGS=OFF -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/glog -DCMAKE_CXX_FLAGS=-w
 )
-target_include_directories(celix_registry PRIVATE src)
-target_include_directories(celix_registry PUBLIC include)
-target_link_libraries(celix_registry PRIVATE glog::glog) #TODO make glog static and private
 
-add_library(celix::registry ALIAS celix_registry)
+set(CMAKE_PREFIX_PATH "${CMAKE_CURRENT_BINARY_DIR}/glog ${CMAKE_PREFIX_PATH}")
 
-if (ENABLE_TESTING)
-    add_subdirectory(gtest)
-endif ()
\ No newline at end of file
diff --git a/cmake/celix_project/CodeCoverage.cmake b/cmake/celix_project/CodeCoverage.cmake
index 51b5001..d9e5002 100644
--- a/cmake/celix_project/CodeCoverage.cmake
+++ b/cmake/celix_project/CodeCoverage.cmake
@@ -103,6 +103,13 @@ FUNCTION(SETUP_TARGET_FOR_COVERAGE _targetname _testrunner _outputname)
     		MESSAGE(FATAL_ERROR "genhtml not found! Aborting...")
     	ENDIF() # NOT GENHTML_PATH
 
+        set(SCAN_DIR ".")
+        if (NOT ARGV3)
+            set(SCAN_DIR ".")
+        else()
+            set(SCAN_DIR "${ARGV3}")
+        endif ()
+
     	# Setup target
       ADD_CUSTOM_TARGET(${_targetname}_coverage
 
@@ -115,8 +122,8 @@ FUNCTION(SETUP_TARGET_FOR_COVERAGE _targetname _testrunner _outputname)
     		# Capturing lcov counters and generating report
     		COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/coverage
     		COMMAND ${CMAKE_COMMAND} -E make_directory ${CMAKE_BINARY_DIR}/coverage/${_testrunner}
-    		COMMAND ${LCOV_PATH} --directory . --capture --output-file ${_outputname}.info
-    		COMMAND ${LCOV_PATH} --remove ${_outputname}.info 'mock/*' 'test/*' '/usr/*' --output-file ${_outputname}.info.cleaned
+    		COMMAND ${LCOV_PATH} --directory ${SCAN_DIR} --capture --output-file ${_outputname}.info
+    		COMMAND ${LCOV_PATH} --remove ${_outputname}.info 'mock/*' '**/test/*' '**/gtest/*' '**/tst/*' '**/googletest_project/*' '**/glog/*' '/usr/*' --output-file ${_outputname}.info.cleaned
 
     		WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
     		COMMENT "Resetting code coverage counters to zero.\nProcessing code coverage counters and generating report."
diff --git a/libs/framework/tst/CMakeLists.txt b/libs/framework/tst/CMakeLists.txt
index 48f0d05..9837bdc 100644
--- a/libs/framework/tst/CMakeLists.txt
+++ b/libs/framework/tst/CMakeLists.txt
@@ -36,6 +36,7 @@ configure_file(config.properties.in config.properties @ONLY)
 configure_file(framework1.properties.in framework1.properties @ONLY)
 configure_file(framework2.properties.in framework2.properties @ONLY)
 
+
 add_test(NAME run_test_framework COMMAND test_framework)
-SETUP_TARGET_FOR_COVERAGE(test_framework_cov test_framework ${CMAKE_BINARY_DIR}/coverage/test_framework/test_framework)
+SETUP_TARGET_FOR_COVERAGE(test_framework_cov test_framework ${CMAKE_BINARY_DIR}/coverage/test_framework/test_framework ..)
 
diff --git a/libs/framework_cxx/CMakeLists.txt b/libs/framework_cxx/CMakeLists.txt
index 472bd60..c47ae80 100644
--- a/libs/framework_cxx/CMakeLists.txt
+++ b/libs/framework_cxx/CMakeLists.txt
@@ -24,7 +24,8 @@ add_library(celix_framework_cxx SHARED
         src/Bundle.cc)
 target_include_directories(celix_framework_cxx PRIVATE src)
 target_include_directories(celix_framework_cxx PUBLIC include)
-target_link_libraries(celix_framework_cxx PUBLIC celix::registry glog::glog) #TODO glog private and static lib
+target_link_libraries(celix_framework_cxx PRIVATE glog::glog)
+target_link_libraries(celix_framework_cxx PUBLIC celix::registry)
 
 if (ENABLE_TESTING)
     add_subdirectory(gtest)
diff --git a/libs/framework_cxx/gtest/CMakeLists.txt b/libs/framework_cxx/gtest/CMakeLists.txt
index 0f407cc..23fdfb7 100644
--- a/libs/framework_cxx/gtest/CMakeLists.txt
+++ b/libs/framework_cxx/gtest/CMakeLists.txt
@@ -22,5 +22,6 @@ set(SOURCES
 add_executable(celix_framework_cxx_tests ${SOURCES})
 target_link_libraries(celix_framework_cxx_tests PRIVATE gtest celix_framework_cxx)
 
+#NOTE last .. argument for the setup coverage is the scan dir (i.e. not gtest dir, but a dir higher)
 add_test(NAME celix_framework_cxx_tests COMMAND celix_framework_cxx_tests)
-SETUP_TARGET_FOR_COVERAGE(celix_framework_cxx_tests_cov celix_framework_cxx_tests ${CMAKE_BINARY_DIR}/coverage/framework/celix_framework_cxx_tests)
\ No newline at end of file
+SETUP_TARGET_FOR_COVERAGE(celix_framework_cxx_tests_cov celix_framework_cxx_tests ${CMAKE_BINARY_DIR}/coverage/celix_framework_cxx_tests/celix_framework_cxx_tests ..)
\ No newline at end of file
diff --git a/libs/framework_cxx/gtest/src/Framework_tests.cc b/libs/framework_cxx/gtest/src/Framework_tests.cc
index 5bf8cdb..88580f3 100644
--- a/libs/framework_cxx/gtest/src/Framework_tests.cc
+++ b/libs/framework_cxx/gtest/src/Framework_tests.cc
@@ -17,6 +17,8 @@
  *under the License.
  */
 
+#include <atomic>
+
 #include "gtest/gtest.h"
 
 #include "celix/Framework.h"
@@ -46,12 +48,12 @@ TEST_F(FrameworkTest, CreateDestroy) {
 
 class EmbeddedActivator : public celix::IBundleActivator {
 public:
-    EmbeddedActivator(std::shared_ptr<celix::BundleContext>) {
-        startCount++;
+    explicit EmbeddedActivator(std::shared_ptr<celix::BundleContext>) {
+        startCount.fetch_add(1);
     }
 
     virtual ~EmbeddedActivator() {
-        stopCount++;
+        stopCount.fetch_add(1);
     }
 
     static std::atomic<int> startCount;
diff --git a/libs/framework_cxx/src/Bundle.h b/libs/framework_cxx/src/Bundle.h
index 2ee1af6..5541013 100644
--- a/libs/framework_cxx/src/Bundle.h
+++ b/libs/framework_cxx/src/Bundle.h
@@ -20,6 +20,8 @@
 #ifndef CXX_CELIX_BUNDLE_H
 #define CXX_CELIX_BUNDLE_H
 
+#include <atomic>
+
 #include "celix/Constants.h"
 #include "celix/IBundle.h"
 #include "celix/BundleContext.h"
@@ -28,10 +30,13 @@ namespace celix {
     class Bundle : public celix::IBundle {
     public:
         Bundle(long _bndId, celix::Framework *_fw, celix::Properties _manifest) :
-                bndId{_bndId}, fw{_fw}, bndManifest{std::move(_manifest)} {
+                bndId{_bndId}, fw{_fw}, bndManifest{std::move(_manifest)}, bndState{BundleState::INSTALLED} {
             bndState.store(BundleState::INSTALLED, std::memory_order_release);
         }
 
+        Bundle(const Bundle&) = delete;
+        Bundle& operator=(const Bundle&) = delete;
+
         //resource part
         bool has(const std::string &) const noexcept override;
         bool isDir(const std::string &) const noexcept override;
@@ -76,9 +81,8 @@ namespace celix {
         const long bndId;
         celix::Framework *const fw;
         const celix::Properties bndManifest;
-        std::weak_ptr <celix::BundleContext> context;
 
-        std::atomic <BundleState> bndState;
+        std::atomic<BundleState> bndState;
     };
 }
 
diff --git a/libs/framework_cxx/src/BundleContext.cc b/libs/framework_cxx/src/BundleContext.cc
index 1d5a0a7..5b9b192 100644
--- a/libs/framework_cxx/src/BundleContext.cc
+++ b/libs/framework_cxx/src/BundleContext.cc
@@ -29,6 +29,9 @@ namespace celix {
             reg{&bnd->framework().registry(celix::CXX_LANG)},
             cReg(&bnd->framework().registry(celix::C_LANG)){}
 
+        Impl(const Impl&) = delete;
+        Impl& operator=(const Impl&) = delete;
+
         const std::shared_ptr<celix::IBundle> bnd;
         celix::ServiceRegistry * const reg; //TODO make weak_ptr
         celix::ServiceRegistry * const cReg; //TODO make weak_ptr
@@ -36,9 +39,8 @@ namespace celix {
     };
 }
 
-celix::BundleContext::BundleContext(std::shared_ptr<celix::IBundle> bnd) {
-    pimpl = std::unique_ptr<celix::BundleContext::Impl>{new celix::BundleContext::Impl{std::move(bnd)}};
-}
+celix::BundleContext::BundleContext(std::shared_ptr<celix::IBundle> bnd) :
+    pimpl{std::unique_ptr<celix::BundleContext::Impl>{new celix::BundleContext::Impl{std::move(bnd)}}} {}
 
 celix::BundleContext::~BundleContext() = default;
 
diff --git a/libs/framework_cxx/src/Framework.cc b/libs/framework_cxx/src/Framework.cc
index 64fa7d5..a96ce86 100644
--- a/libs/framework_cxx/src/Framework.cc
+++ b/libs/framework_cxx/src/Framework.cc
@@ -27,6 +27,9 @@
 #include <set>
 #include <vector>
 #include <future>
+#include <algorithm>
+
+#include <linux/limits.h>
 
 #include <glog/logging.h>
 
@@ -54,6 +57,9 @@ class celix::Framework::Impl : public IBundle {
 public:
     Impl(celix::Framework *_fw, celix::Properties _config) : fw{_fw}, config{std::move(_config)}, bndManifest{createManifest()}, cwd{createCwd()} {}
 
+    Impl(const Impl&) = delete;
+    Impl& operator=(const Impl&) = delete;
+
     ~Impl() {
         stopFramework();
         waitForShutdown();
@@ -237,10 +243,10 @@ public:
 
     //resource bundle part
     long id() const noexcept override { return 1L /*note registry empty bundle is id 0, framework is id 1*/; }
-    bool has(const std::string&) const override { return false; }
-    bool isDir(const std::string&) const override { return false; }
-    bool isFile(const std::string&) const override { return false; }
-    std::vector<std::string> readDir(const std::string&) const override { return std::vector<std::string>{};}
+    bool has(const std::string&) const noexcept override { return false; }
+    bool isDir(const std::string&) const noexcept override { return false; }
+    bool isFile(const std::string&) const noexcept override { return false; }
+    std::vector<std::string> readDir(const std::string&) const noexcept override { return std::vector<std::string>{};}
     const std::string& root() const noexcept override { //TODO
         return cwd;
     }
@@ -326,21 +332,22 @@ private:
 
     struct {
         mutable std::mutex mutex{};
-        std::unordered_map<std::string, celix::ServiceRegistry> entries;
-    } registries;
+        std::unordered_map<std::string, celix::ServiceRegistry> entries{};
+    } registries{};
 };
 
 /***********************************************************************************************************************
  * Framework
  **********************************************************************************************************************/
 
-celix::Framework::Framework(celix::Properties config) {
-    pimpl = std::unique_ptr<Impl>{new Impl{this, std::move(config)}};
+celix::Framework::Framework(celix::Properties config) : pimpl{std::unique_ptr<Impl>{new Impl{this, std::move(config)}}} {
     registerFramework(this);
 }
+
 celix::Framework::~Framework() {
     unregisterFramework(this);
 }
+
 celix::Framework::Framework(Framework &&rhs) = default;
 celix::Framework& celix::Framework::operator=(Framework&& rhs) = default;
 
diff --git a/libs/registry/CMakeLists.txt b/libs/registry/CMakeLists.txt
index ee537cc..2a279de 100644
--- a/libs/registry/CMakeLists.txt
+++ b/libs/registry/CMakeLists.txt
@@ -23,7 +23,8 @@ add_library(celix_registry STATIC
 )
 target_include_directories(celix_registry PRIVATE src)
 target_include_directories(celix_registry PUBLIC include)
-target_link_libraries(celix_registry PRIVATE glog::glog) #TODO make glog static and private
+target_link_libraries(celix_registry PRIVATE glog::glog)
+target_compile_options(celix_registry PRIVATE -fPIC)
 
 add_library(celix::registry ALIAS celix_registry)
 
diff --git a/libs/registry/gtest/CMakeLists.txt b/libs/registry/gtest/CMakeLists.txt
index 4f3076e..cdf666b 100644
--- a/libs/registry/gtest/CMakeLists.txt
+++ b/libs/registry/gtest/CMakeLists.txt
@@ -27,5 +27,6 @@ set(SOURCES
 add_executable(celix_registry_tests ${SOURCES})
 target_link_libraries(celix_registry_tests PRIVATE gtest glog::glog celix::registry)
 
+#NOTE last .. argument for the setup coverage is the scan dir (i.e. not gtest dir, but a dir higher)
 add_test(NAME celix_registry_tests COMMAND celix_registry_tests)
-SETUP_TARGET_FOR_COVERAGE(celix_registry_tests_cov celix_registry_tests ${CMAKE_BINARY_DIR}/coverage/registry)
\ No newline at end of file
+SETUP_TARGET_FOR_COVERAGE(celix_registry_tests_cov celix_registry_tests ${CMAKE_BINARY_DIR}/coverage/celix_registry_tests/celix_registry_tests ..)
\ No newline at end of file
diff --git a/libs/registry/gtest/src/RegistryConcurrency_tests.cc b/libs/registry/gtest/src/RegistryConcurrency_tests.cc
index b460bf3..d2626ec 100644
--- a/libs/registry/gtest/src/RegistryConcurrency_tests.cc
+++ b/libs/registry/gtest/src/RegistryConcurrency_tests.cc
@@ -19,6 +19,8 @@
 
 
 #include <thread>
+#include <mutex>
+#include <condition_variable>
 
 #include "gtest/gtest.h"
 
diff --git a/libs/registry/gtest/src/Registry_tests.cc b/libs/registry/gtest/src/Registry_tests.cc
index 9bbb899..d8fad0e 100644
--- a/libs/registry/gtest/src/Registry_tests.cc
+++ b/libs/registry/gtest/src/Registry_tests.cc
@@ -17,8 +17,11 @@
  *under the License.
  */
 
-#include "gtest/gtest.h"
 
+
+#include <memory>
+
+#include <gtest/gtest.h>
 #include <glog/logging.h>
 
 #include "celix/ServiceRegistry.h"
diff --git a/libs/registry/include/celix/Filter.h b/libs/registry/include/celix/Filter.h
index db851ba..8d8fab0 100644
--- a/libs/registry/include/celix/Filter.h
+++ b/libs/registry/include/celix/Filter.h
@@ -20,6 +20,7 @@
 #ifndef CXX_CELIX_FILTER_H
 #define CXX_CELIX_FILTER_H
 
+#include <memory>
 #include <string>
 #include <vector>
 
diff --git a/libs/registry/include/celix/IResourceBundle.h b/libs/registry/include/celix/IResourceBundle.h
index 97c64de..38b76b3 100644
--- a/libs/registry/include/celix/IResourceBundle.h
+++ b/libs/registry/include/celix/IResourceBundle.h
@@ -21,6 +21,7 @@
 #define CXX_CELIX_IRESOURCEBUNDLE_H
 
 #include <string>
+#include <vector>
 
 namespace celix {
 
diff --git a/libs/registry/include/celix/ServiceRegistry.h b/libs/registry/include/celix/ServiceRegistry.h
index ae7aeb2..76b277d 100644
--- a/libs/registry/include/celix/ServiceRegistry.h
+++ b/libs/registry/include/celix/ServiceRegistry.h
@@ -22,6 +22,8 @@
 
 #include <utility>
 #include <vector>
+#include <functional>
+#include <memory>
 
 #include "celix/Constants.h"
 #include "celix/Properties.h"
diff --git a/libs/registry/include/celix/Utils.h b/libs/registry/include/celix/Utils.h
index ae61cd7..5640636 100644
--- a/libs/registry/include/celix/Utils.h
+++ b/libs/registry/include/celix/Utils.h
@@ -20,7 +20,7 @@
 #ifndef CXX_CELIX_UTILS_H
 #define CXX_CELIX_UTILS_H
 
-
+#include <cstring>
 #include <string>
 #include <iostream>
 
diff --git a/libs/registry/src/ServiceRegistry.cc b/libs/registry/src/ServiceRegistry.cc
index ac9a9dd..a7465e2 100644
--- a/libs/registry/src/ServiceRegistry.cc
+++ b/libs/registry/src/ServiceRegistry.cc
@@ -26,6 +26,7 @@
 #include <future>
 
 #include <glog/logging.h>
+#include <assert.h>
 
 #include "celix/Constants.h"
 #include "celix/ServiceRegistry.h"
@@ -306,7 +307,7 @@ namespace {
         }
     private:
         struct {
-            mutable std::mutex mutex; //protects matchedEntries & highestRanking
+            mutable std::mutex mutex{}; //protects matchedEntries & highestRanking
             std::map<std::shared_ptr<const SvcEntry>, std::shared_ptr<void>, SvcEntryLess> entries{};
             std::shared_ptr<void> highest{};
         } tracked{};
@@ -338,8 +339,10 @@ public:
 
 class celix::ServiceRegistry::Impl {
 public:
+    Impl(std::string _regName) : regName{_regName} {}
+
     const std::shared_ptr<const celix::IResourceBundle> emptyBundle = std::shared_ptr<const celix::IResourceBundle>{new EmptyBundle{}};
-    std::string regName;
+    const std::string regName;
 
     struct {
         mutable std::mutex mutex{};
@@ -511,9 +514,7 @@ public:
  **********************************************************************************************************************/
 
 
-celix::ServiceRegistry::ServiceRegistry(std::string name) : pimpl{new ServiceRegistry::Impl{}} {
-    pimpl->regName = std::move(name);
-}
+celix::ServiceRegistry::ServiceRegistry(std::string name) : pimpl{new ServiceRegistry::Impl{std::move(name)}} {}
 celix::ServiceRegistry::ServiceRegistry(celix::ServiceRegistry &&rhs) = default;
 celix::ServiceRegistry& celix::ServiceRegistry::operator=(celix::ServiceRegistry &&rhs) = default;
 celix::ServiceRegistry::~ServiceRegistry() {


[celix] 08/22: CELIX-438: Adds bundle register for __APPLE__

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit eec8e08ca39f6211a0eeb156c35c8edc7b6df9e8
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Sat Jan 5 11:56:05 2019 +0100

    CELIX-438: Adds bundle register for __APPLE__
---
 CMakeLists.txt                                | 12 ++---
 bundles/CMakeLists.txt                        | 14 +++---
 bundles/shell/CMakeLists.txt                  |  8 ++--
 bundles/shell/cxx_shell/CMakeLists.txt        |  6 ++-
 bundles/shell/cxx_shell/src/ShellActivator.cc | 67 ++++++++++++++++++++++++---
 bundles/shell/cxx_shell_tui/CMakeLists.txt    |  2 +-
 bundles/shell/cxx_shell_tui/src/shell_test.cc |  3 +-
 cmake/celix_project/AddGLog.cmake             | 10 ++--
 cmake/celix_project/AddGTest.cmake            |  2 +-
 cmake/celix_project/AddLibzip.cmake           | 10 ++--
 libs/CMakeLists.txt                           |  9 ++--
 libs/framework/src/bundle_archive.c           |  5 +-
 libs/framework_cxx/CMakeLists.txt             |  5 +-
 libs/framework_cxx/gtest/CMakeLists.txt       |  2 +-
 libs/framework_cxx/src/Framework.cc           |  4 +-
 15 files changed, 114 insertions(+), 45 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 7025630..8d0b790 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,7 +51,7 @@ set(CELIX_MAJOR "3")
 set(CELIX_MINOR "0")
 set(CELIX_MICRO "0")
 
-option(ENABLE_TESTING "Enables unit testing" OFF)
+option(ENABLE_TESTING "Enables unit testing" ON)
 
 if (ENABLE_TESTING)
 	enable_testing()
@@ -70,15 +70,15 @@ add_subdirectory(libs)
 add_subdirectory(bundles)
 
 #Example as last, because some example will check if underlining options are enabled
-add_subdirectory(examples/celix-examples examples)
+#TODO add_subdirectory(examples/celix-examples examples)
 
 #export targets
-install(EXPORT celix NAMESPACE Celix:: DESTINATION share/celix/cmake FILE Targets.cmake COMPONENT cmake)
-install_celix_targets(celix NAMESPACE Celix:: DESTINATION share/celix/cmake FILE CelixTargets.cmake COMPONENT cmake)
+#install(EXPORT celix NAMESPACE Celix:: DESTINATION share/celix/cmake FILE Targets.cmake COMPONENT cmake)
+#install_celix_targets(celix NAMESPACE Celix:: DESTINATION share/celix/cmake FILE CelixTargets.cmake COMPONENT cmake)
 
 #install celix cmake modules
-install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/Modules/ DESTINATION share/celix/cmake/Modules)
-install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/cmake_celix/ DESTINATION share/celix/cmake/cmake_celix)
+#install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/Modules/ DESTINATION share/celix/cmake/Modules)
+#install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/cmake_celix/ DESTINATION share/celix/cmake/cmake_celix)
 
 #configure and install CelixConfig and CelixConfigVersion files
 configure_file(cmake/CelixConfigVersion.cmake.in
diff --git a/bundles/CMakeLists.txt b/bundles/CMakeLists.txt
index 5ed4054..847b1f0 100644
--- a/bundles/CMakeLists.txt
+++ b/bundles/CMakeLists.txt
@@ -15,11 +15,11 @@
 # specific language governing permissions and limitations
 # under the License.
 
-add_subdirectory(config_admin)
-add_subdirectory(device_access)
-add_subdirectory(deployment_admin)
-add_subdirectory(remote_services)
+#add_subdirectory(config_admin)
+#add_subdirectory(device_access)
+#add_subdirectory(deployment_admin)
+#add_subdirectory(remote_services)
 add_subdirectory(shell)
-add_subdirectory(log_writer)
-add_subdirectory(log_service)
-add_subdirectory(pubsub)
\ No newline at end of file
+#add_subdirectory(log_writer)
+#add_subdirectory(log_service)
+#add_subdirectory(pubsub)
\ No newline at end of file
diff --git a/bundles/shell/CMakeLists.txt b/bundles/shell/CMakeLists.txt
index 851d601..c3d0196 100644
--- a/bundles/shell/CMakeLists.txt
+++ b/bundles/shell/CMakeLists.txt
@@ -15,10 +15,10 @@
 # specific language governing permissions and limitations
 # under the License.
 
-add_subdirectory(shell)
-add_subdirectory(remote_shell)
-add_subdirectory(shell_bonjour)
-add_subdirectory(shell_tui)
+#add_subdirectory(shell)
+#add_subdirectory(remote_shell)
+#add_subdirectory(shell_bonjour)
+#add_subdirectory(shell_tui)
 
 add_subdirectory(cxx_shell)
 add_subdirectory(cxx_shell_tui)
diff --git a/bundles/shell/cxx_shell/CMakeLists.txt b/bundles/shell/cxx_shell/CMakeLists.txt
index d2b2113..c82d2ef 100644
--- a/bundles/shell/cxx_shell/CMakeLists.txt
+++ b/bundles/shell/cxx_shell/CMakeLists.txt
@@ -23,7 +23,7 @@ target_include_directories(celix_cxx_shell_api INTERFACE
     $<INSTALL_INTERFACE:include/celix/shell>
 )
 
-#TODO should eventually be done by a CMake command (i.e. bundle_add_resources)
+#TODO should eventually be done by a CMake command (i.e. celix_bundle_add_resources)
 add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/celix_cxx_shell_resources.zip
         COMMAND zip -rq ${CMAKE_CURRENT_BINARY_DIR}/celix_cxx_shell_resources.zip *
         COMMENT "Packaging Resources"
@@ -47,10 +47,12 @@ target_include_directories(celix_cxx_shell PRIVATE src)
 target_link_libraries(celix_cxx_shell PRIVATE celix_cxx_shell_api glog::glog)
 target_link_libraries(celix_cxx_shell PUBLIC celix_framework_cxx)
 add_dependencies(celix_cxx_shell create_resources)
+
+#TODO should eventually be done by a CMake command (i.e. the add_celix_bundle)
 if (UNIX AND NOT APPLE)
     target_link_libraries(celix_cxx_shell PRIVATE -Wl,--format=binary -Wl,celix_cxx_shell_resources.zip -Wl,--format=default)
 else ()
-    #TODO apple
+    target_link_libraries(celix_cxx_shell PRIVATE -Wl,-sectcreate -Wl,resources -Wl,celix_cxx_shell -Wl,celix_cxx_shell_resources.zip)
 endif ()
 
 
diff --git a/bundles/shell/cxx_shell/src/ShellActivator.cc b/bundles/shell/cxx_shell/src/ShellActivator.cc
index ea54219..807a9b3 100644
--- a/bundles/shell/cxx_shell/src/ShellActivator.cc
+++ b/bundles/shell/cxx_shell/src/ShellActivator.cc
@@ -25,8 +25,15 @@
 
 #include "commands.h"
 
+#ifdef __APPLE__
+#include <mach-o/getsect.h>
+#include <dlfcn.h>
+static uint8_t *resources = nullptr;
+#else
 extern const uint8_t resources[]       asm("_binary_celix_cxx_shell_resources_zip_start");
 extern const uint8_t resources_end[]   asm("_binary_celix_cxx_shell_resources_zip_end");
+#endif
+
 
 namespace {
 
@@ -54,15 +61,15 @@ namespace {
             bool commandCalled = false;
 
             if (!cmdName.empty()) {
-                std::string filter =
-                        std::string{"("} + celix::IShellCommand::COMMAND_NAME + "=" + cmdName + ")";
+                //first try to call IShellCommand services.
+                std::string filter = std::string{"("} + celix::IShellCommand::COMMAND_NAME + "=" + cmdName + ")";
                 commandCalled = ctx->useService<celix::IShellCommand>([&](celix::IShellCommand &cmd) {
                     cmd.executeCommand(cmdName, cmdArgs, out, err);
                 }, filter);
             }
             if (!cmdName.empty() && !commandCalled) {
-                std::string filter =
-                        std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=" + cmdName + ")";
+                //if no IShellCommand service is found for the command name, try calling a ShellCommandFunction service.
+                std::string filter = std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=" + cmdName + ")";
                 std::function<void(celix::ShellCommandFunction&)> use = [&](celix::ShellCommandFunction &cmd) -> void {
                     cmd(cmdName, cmdArgs, out, err);
                 };
@@ -100,13 +107,61 @@ namespace {
     };
 
     //NOTE that eventually the (ctor) bundle register will be generated by a CMake command (i.e. add_bundle)
-    //This also applies for the resources, resources_end asm entries.
+    //This also applies for the resources, resources_end asm entries or the __APPLE__ variant
     __attribute__((constructor))
     static void registerShellBundle() {
+
+#ifdef __APPLE__
+        //get library info using a addr in the lib (the bundle register function)
+        Dl_info info;
+        const void *addr = reinterpret_cast<void*>(&registerShellBundle);
+        dladdr(addr, &info);
+
+        //get mach header from Dl_info
+        struct mach_header_64 *header = static_cast<struct mach_header_64*>(info.dli_fbase);
+
+        //get section from mach header based on the seg and sect name
+        const struct section_64 *sect = getsectbynamefromheader_64(header, "resources", "celix_cxx_shell");
+
+        //NOTE reading directly form the sect->addr is not possible (BAD_ACCESS), so copy sect part from dylib file.
+
+        //alloc buffer to store resources zip
+        size_t resourcesLen = sect->size;
+        resources = (uint8_t*)malloc(resourcesLen);
+
+        //read from dylib. note that the dylib location is in the Dl_info struct.
+        errno = 0;
+        FILE *dylib = fopen(info.dli_fname, "r");
+        size_t read = 0;
+        if (dylib != nullptr) {
+            fseek(dylib, sect->offset, SEEK_SET);
+            read = fread(resources, 1, sect->size, dylib);
+        }
+        if (dylib == nullptr || read != sect->size) {
+            LOG(WARNING) << "Error reading resources from dylib " << info.dli_fname << ": " << strerror(errno) << std::endl;
+            free(resources);
+            resources = nullptr;
+            resourcesLen = 0;
+        }
+        if (dylib != nullptr) {
+            fclose(dylib);
+        }
+#else
+        size_t resourcesLen = resources_end - resources;
+#endif
+
+
         celix::Properties manifest{};
         manifest[celix::MANIFEST_BUNDLE_NAME] = "Shell";
         manifest[celix::MANIFEST_BUNDLE_GROUP] = "Celix";
         manifest[celix::MANIFEST_BUNDLE_VERSION] = "1.0.0";
-        celix::registerStaticBundle<ShellBundleActivator>("celix::Shell", manifest, resources, resources_end - resources);
+        celix::registerStaticBundle<ShellBundleActivator>("celix::Shell", manifest, resources, resourcesLen);
+    }
+
+    __attribute__((destructor))
+    static void cleanupShellBundle() {
+#ifdef __APPLE__
+        free(resources);
+#endif
     }
 }
diff --git a/bundles/shell/cxx_shell_tui/CMakeLists.txt b/bundles/shell/cxx_shell_tui/CMakeLists.txt
index e9fa13b..d5b65f7 100644
--- a/bundles/shell/cxx_shell_tui/CMakeLists.txt
+++ b/bundles/shell/cxx_shell_tui/CMakeLists.txt
@@ -33,4 +33,4 @@ target_link_libraries(celix_cxx_shell_tui PUBLIC celix_framework_cxx)
 add_executable(shell_test
         src/shell_test.cc
 )
-target_link_libraries(shell_test PRIVATE celix_cxx_shell celix_cxx_shell_tui)
\ No newline at end of file
+target_link_libraries(shell_test PRIVATE celix_cxx_shell celix_cxx_shell_tui glog::glog)
\ No newline at end of file
diff --git a/bundles/shell/cxx_shell_tui/src/shell_test.cc b/bundles/shell/cxx_shell_tui/src/shell_test.cc
index 8e92107..ab44a00 100644
--- a/bundles/shell/cxx_shell_tui/src/shell_test.cc
+++ b/bundles/shell/cxx_shell_tui/src/shell_test.cc
@@ -17,14 +17,13 @@
  *under the License.
  */
 
-#include <iostream>
-
 #include <glog/logging.h>
 
 #include "celix/api.h"
 
 
 int main(int /*argc*/, char **argv) {
+    //TODO move glog init to framework (a pthread_once?)
     google::InitGoogleLogging(argv[0]);
     google::LogToStderr();
 
diff --git a/cmake/celix_project/AddGLog.cmake b/cmake/celix_project/AddGLog.cmake
index 4897f35..df0f3ab 100644
--- a/cmake/celix_project/AddGLog.cmake
+++ b/cmake/celix_project/AddGLog.cmake
@@ -22,14 +22,16 @@ ExternalProject_Add(
         GIT_REPOSITORY https://github.com/google/glog.git
         GIT_TAG v0.3.5
         UPDATE_DISCONNECTED TRUE
-        PREFIX ${CMAKE_CURRENT_BINARY_DIR}/glog
-        CMAKE_ARGS -DWITH_GFLAGS=OFF -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/glog -DCMAKE_CXX_FLAGS=-w
+        PREFIX ${CMAKE_BINARY_DIR}/glog
+        CMAKE_ARGS -DWITH_GFLAGS=OFF -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/glog -DCMAKE_CXX_FLAGS=-w
 )
 
+file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/glog/include/dummy.txt CONTENT "//Dummy file to ensure the include dir exists")
+
 add_library(glog::glog IMPORTED STATIC GLOBAL)
 add_dependencies(glog::glog googlelog_project)
 set_target_properties(glog::glog PROPERTIES
-    IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/glog/lib/libglog.a"
-    INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/glog/include"
+    IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/glog/lib/libglog.a"
+    INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_BINARY_DIR}/glog/include"
 )
 
diff --git a/cmake/celix_project/AddGTest.cmake b/cmake/celix_project/AddGTest.cmake
index 2da1a47..1b48d8a 100644
--- a/cmake/celix_project/AddGTest.cmake
+++ b/cmake/celix_project/AddGTest.cmake
@@ -21,7 +21,7 @@ ExternalProject_Add(
         GIT_REPOSITORY https://github.com/google/googletest.git
         GIT_TAG release-1.8.1
         UPDATE_DISCONNECTED TRUE
-        PREFIX ${CMAKE_CURRENT_BINARY_DIR}/gtest
+        PREFIX ${CMAKE_BINARY_DIR}/gtest
         INSTALL_COMMAND ""
 )
 
diff --git a/cmake/celix_project/AddLibzip.cmake b/cmake/celix_project/AddLibzip.cmake
index 7d14cb6..aec4be7 100644
--- a/cmake/celix_project/AddLibzip.cmake
+++ b/cmake/celix_project/AddLibzip.cmake
@@ -21,13 +21,15 @@ ExternalProject_Add(
         GIT_REPOSITORY https://github.com/nih-at/libzip.git
         GIT_TAG rel-1-5-1
         UPDATE_DISCONNECTED TRUE
-        PREFIX ${CMAKE_CURRENT_BINARY_DIR}/libzip
-        CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}/libzip -DCMAKE_C_FLAGS=-fPIC -DBUILD_SHARED_LIBS=OFF -DENABLE_COMMONCRYPTO=OFF -DENABLE_GNUTLS=OFF -DENABLE_OPENSSL=OFF -Wno-dev
+        PREFIX ${CMAKE_BINARY_DIR}/libzip
+        CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/libzip -DCMAKE_C_FLAGS=-fPIC -DBUILD_SHARED_LIBS=OFF -DENABLE_COMMONCRYPTO=OFF -DENABLE_GNUTLS=OFF -DENABLE_OPENSSL=OFF -Wno-dev
 )
 
+file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/libzip/include/dummy.txt CONTENT "//Dummy file to ensure the include dir exists")
+
 add_library(libzip::libzip IMPORTED STATIC GLOBAL)
 add_dependencies(libzip::libzip libzip_project)
 set_target_properties(libzip::libzip PROPERTIES
-        IMPORTED_LOCATION "${CMAKE_CURRENT_BINARY_DIR}/libzip/lib64/libzip.a"
-        INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_BINARY_DIR}/libzip/include"
+        IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/libzip/lib/libzip.a"
+        INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_BINARY_DIR}/libzip/include"
 )
\ No newline at end of file
diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt
index 88d1928..928932a 100644
--- a/libs/CMakeLists.txt
+++ b/libs/CMakeLists.txt
@@ -21,14 +21,15 @@ add_subdirectory(utils)
 add_subdirectory(dfi)
 add_subdirectory(etcdlib)
 
-add_subdirectory(framework)
+#add_subdirectory(framework)
 
+#C++ stuff
 add_subdirectory(registry)
 add_subdirectory(framework_cxx)
 
 #launcher
-add_subdirectory(launcher)
+#add_subdirectory(launcher)
 
 #add_subdirectory(event_admin)# event_admin is unstable
-add_subdirectory(dependency_manager)
-add_subdirectory(dependency_manager_cxx)
\ No newline at end of file
+#add_subdirectory(dependency_manager)
+#add_subdirectory(dependency_manager_cxx)
\ No newline at end of file
diff --git a/libs/framework/src/bundle_archive.c b/libs/framework/src/bundle_archive.c
index e2fc658..addea63 100644
--- a/libs/framework/src/bundle_archive.c
+++ b/libs/framework/src/bundle_archive.c
@@ -29,12 +29,15 @@
 #include <stdio.h>
 #include <time.h>
 #include <sys/stat.h>
+#include <sys/errno.h>
 #include <dirent.h>
 #include <unistd.h>
 
 #include "bundle_archive.h"
 #include "linked_list_iterator.h"
 
+#include <string.h>
+
 struct bundleArchive {
 	long id;
 	char * location;
@@ -76,7 +79,7 @@ celix_status_t bundleArchive_createSystemBundleArchive(bundle_archive_pt *bundle
 			status = linkedList_create(&archive->revisions);
 			if (status == CELIX_SUCCESS) {
 				archive->id = 0L;
-				archive->location = strdup("System Bundle");
+				archive->location = strndup("System Bundle", 1024*1024);
 				archive->archiveRoot = NULL;
 				archive->archiveRootDir = NULL;
 				archive->refreshCount = -1;
diff --git a/libs/framework_cxx/CMakeLists.txt b/libs/framework_cxx/CMakeLists.txt
index f3c116e..98c857d 100644
--- a/libs/framework_cxx/CMakeLists.txt
+++ b/libs/framework_cxx/CMakeLists.txt
@@ -16,6 +16,9 @@
 # under the License.
 
 find_package(UUID REQUIRED)
+if(NOT APPLE)
+    set(UUID ${UUID_LIBRARY})
+endif()
 
 #TODO rename to celix::framework
 add_library(celix_framework_cxx SHARED
@@ -27,7 +30,7 @@ target_include_directories(celix_framework_cxx PRIVATE src)
 target_include_directories(celix_framework_cxx PUBLIC include)
 target_link_libraries(celix_framework_cxx PRIVATE glog::glog libzip::libzip)
 #NOTE because of libzil libbz2 and libz is also needed. maybe more to other form of resources (i.e. tar)
-target_link_libraries(celix_framework_cxx PUBLIC celix::registry bz2 z ${UUID_LIBRARY})
+target_link_libraries(celix_framework_cxx PUBLIC celix::registry bz2 z ${UUID})
 
 if (ENABLE_TESTING)
     add_subdirectory(gtest)
diff --git a/libs/framework_cxx/gtest/CMakeLists.txt b/libs/framework_cxx/gtest/CMakeLists.txt
index 23fdfb7..4e76ed2 100644
--- a/libs/framework_cxx/gtest/CMakeLists.txt
+++ b/libs/framework_cxx/gtest/CMakeLists.txt
@@ -20,7 +20,7 @@ set(SOURCES
         src/Framework_tests.cc
 )
 add_executable(celix_framework_cxx_tests ${SOURCES})
-target_link_libraries(celix_framework_cxx_tests PRIVATE gtest celix_framework_cxx)
+target_link_libraries(celix_framework_cxx_tests PRIVATE gtest celix_framework_cxx glog::glog)
 
 #NOTE last .. argument for the setup coverage is the scan dir (i.e. not gtest dir, but a dir higher)
 add_test(NAME celix_framework_cxx_tests COMMAND celix_framework_cxx_tests)
diff --git a/libs/framework_cxx/src/Framework.cc b/libs/framework_cxx/src/Framework.cc
index 0b1d856..0740e5b 100644
--- a/libs/framework_cxx/src/Framework.cc
+++ b/libs/framework_cxx/src/Framework.cc
@@ -31,7 +31,9 @@
 #include <future>
 #include <algorithm>
 
+#ifndef __APPLE__
 #include <linux/limits.h>
+#endif
 
 #include <glog/logging.h>
 #include <uuid/uuid.h>
@@ -339,7 +341,7 @@ private:
     std::string uuidString() {
         char uuidStr[37];
         uuid_t uuid;
-        uuid_generate_time_safe(uuid);
+        uuid_generate(uuid);
         uuid_unparse(uuid, uuidStr);
         return std::string{uuidStr};
     }


[celix] 07/22: CELIX-438: Updates travis config

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit d80808b4326f150a0933959e4917630ca07c6b7c
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Thu Jan 3 22:50:44 2019 +0100

    CELIX-438: Updates travis config
---
 libs/registry/gtest/CMakeLists.txt | 2 --
 1 file changed, 2 deletions(-)

diff --git a/libs/registry/gtest/CMakeLists.txt b/libs/registry/gtest/CMakeLists.txt
index cdf666b..b534c50 100644
--- a/libs/registry/gtest/CMakeLists.txt
+++ b/libs/registry/gtest/CMakeLists.txt
@@ -15,8 +15,6 @@
 # specific language governing permissions and limitations
 # under the License.
 
-find_package(glog REQUIRED)
-
 set(SOURCES
         src/main.cc
         src/Registry_tests.cc


[celix] 17/22: CELIX-438: Adds some shell tui gtests

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 7c425db376c8707ee7b80246ee6be7de1d0781e9
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Mon Jan 7 15:51:24 2019 +0100

    CELIX-438: Adds some shell tui gtests
---
 .travis.yml                                        |  10 +-
 bundles/pubsub/test/CMakeLists.txt                 |   1 +
 bundles/shell/cxx_shell_tui/CMakeLists.txt         |  18 ++--
 bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt   |   9 +-
 .../cxx_shell_tui/gtest/src/ShellTui_tests.cc      |  65 ++++++++++++
 .../shell/cxx_shell_tui/include/celix/ShellTui.h   |  69 ++++++++++++
 bundles/shell/cxx_shell_tui/src/ShellTui.cc        | 116 +++++++++++++++++++++
 .../shell/cxx_shell_tui/src/ShellTuiActivator.cc   | 109 +------------------
 8 files changed, 277 insertions(+), 120 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index eb92e78..3c0f470 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -44,11 +44,11 @@ before_install:
   - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update && brew install lcov libffi zeromq czmq glog cpputest jansson && brew link --force libffi; fi
 
 before_script:
-  - wget https://github.com/cpputest/cpputest/releases/download/v3.8/cpputest-3.8.tar.gz -O /tmp/cpputest.tar.gz
-  - tar -xzvf /tmp/cpputest.tar.gz -C /tmp
-  - if [ "$CC" = "clang" ]; then export CXX="clang++"; fi && cd /tmp/cpputest-* && ./configure --prefix=/usr/local && make && sudo make install && cd -
-  - cd /tmp/cpputest-* && ./configure --prefix=/usr/local && make && sudo make install && cd -
-  - mkdir build install
+    - wget https://github.com/cpputest/cpputest/releases/download/v3.8/cpputest-3.8.tar.gz -O /tmp/cpputest.tar.gz
+    - tar -xzvf /tmp/cpputest.tar.gz -C /tmp
+    - if [ "$CC" = "clang" ]; then export CXX="clang++"; fi && cd /tmp/cpputest-* && ./configure --prefix=/usr/local && make && sudo make install && cd -
+    - cd /tmp/cpputest-* && ./configure --prefix=/usr/local && make && sudo make install && cd -
+    - mkdir build install
     - export BUILD_OPTIONS=" \
         -DBUILD_RSA_REMOTE_SERVICE_ADMIN_DFI=ON \
         -DBUILD_DEPLOYMENT_ADMIN=ON \
diff --git a/bundles/pubsub/test/CMakeLists.txt b/bundles/pubsub/test/CMakeLists.txt
index 39e5575..5f72d1f 100644
--- a/bundles/pubsub/test/CMakeLists.txt
+++ b/bundles/pubsub/test/CMakeLists.txt
@@ -86,6 +86,7 @@ add_celix_container(pubsub_udpmc_tst
     DIR ${PROJECT_BINARY_DIR}/runtimes/test/pubsub/udpmc
     LAUNCHER celix_test_runner
 )
+
 add_celix_container(pubsub_zmq_tst
     NAME deploy_tst
     BUNDLES
diff --git a/bundles/shell/cxx_shell_tui/CMakeLists.txt b/bundles/shell/cxx_shell_tui/CMakeLists.txt
index d5b65f7..97d98b5 100644
--- a/bundles/shell/cxx_shell_tui/CMakeLists.txt
+++ b/bundles/shell/cxx_shell_tui/CMakeLists.txt
@@ -15,19 +15,25 @@
 # specific language governing permissions and limitations
 # under the License.
 
-#TODO rename to celix::shell_tui
+add_library(shell_tui_static STATIC
+        src/ShellTui.cc
+)
+target_include_directories(shell_tui_static PUBLIC include)
+target_link_libraries(shell_tui_static PRIVATE celix_framework_cxx glog::glog celix_cxx_shell_api)
+target_compile_options(shell_tui_static PRIVATE -fPIC)
+
 
 #OR static lib, but then with all symbols to force constructor attribute
 add_library(celix_cxx_shell_tui SHARED
         src/ShellTuiActivator.cc
-        src/shell_test.cc)
+)
 target_include_directories(celix_cxx_shell_tui PRIVATE src)
-target_link_libraries(celix_cxx_shell_tui PRIVATE celix_cxx_shell_api glog::glog)
+target_link_libraries(celix_cxx_shell_tui PRIVATE shell_tui_static celix_cxx_shell_api glog::glog)
 target_link_libraries(celix_cxx_shell_tui PUBLIC celix_framework_cxx)
 
-#if (ENABLE_TESTING)
-#    add_subdirectory(gtest)
-#endif ()
+if (ENABLE_TESTING)
+    add_subdirectory(gtest)
+endif ()
 
 
 add_executable(shell_test
diff --git a/bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt b/bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt
index b4a7204..7626eb5 100644
--- a/bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt
+++ b/bundles/shell/cxx_shell_tui/gtest/CMakeLists.txt
@@ -17,9 +17,10 @@
 
 set(SOURCES
         src/main.cc
+        src/ShellTui_tests.cc
 )
-add_executable(celix_shell_cxx_tests ${SOURCES})
-target_link_libraries(celix_shell_cxx_tests PRIVATE gtest celix_framework_cxx celix_shell_cxx)
+add_executable(celix_cxx_shell_tui_tests ${SOURCES})
+target_link_libraries(celix_cxx_shell_tui_tests PRIVATE gtest celix_framework_cxx shell_tui_static celix_cxx_shell_api)
 
-add_test(NAME celix_shell_cxx_tests COMMAND celix_shell_cxx_tests)
-SETUP_TARGET_FOR_COVERAGE(celix_shell_cxx_tests_cov celix_shell_cxx_tests ${CMAKE_BINARY_DIR}/coverage/celix_shell_cxx_tests/celix_shell_cxx_tests)
\ No newline at end of file
+add_test(NAME celix_cxx_shell_tui_tests COMMAND celix_cxx_shell_tui_tests)
+SETUP_TARGET_FOR_COVERAGE(celix_cxx_shell_tui_tests_cov celix_cxx_shell_tui_tests ${CMAKE_BINARY_DIR}/coverage/celix_cxx_shell_tui_tests/celix_cxx_shell_tui_tests ..)
\ No newline at end of file
diff --git a/bundles/shell/cxx_shell_tui/gtest/src/ShellTui_tests.cc b/bundles/shell/cxx_shell_tui/gtest/src/ShellTui_tests.cc
new file mode 100644
index 0000000..6989f27
--- /dev/null
+++ b/bundles/shell/cxx_shell_tui/gtest/src/ShellTui_tests.cc
@@ -0,0 +1,65 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <sstream>
+
+#include "gtest/gtest.h"
+
+#include "celix/api.h"
+#include "celix/ShellTui.h"
+
+class ShellTuiTest : public ::testing::Test {
+public:
+    ShellTuiTest() {}
+    ~ShellTuiTest(){}
+
+    celix::Framework& framework() { return fw; }
+private:
+    celix::Framework fw{};
+};
+
+
+
+
+TEST_F(ShellTuiTest, AcceptCommand) {
+    {
+        std::stringstream stream{};
+        celix::ShellTui tui{&stream, &stream};
+        usleep(100000);//IMPROVE, for now wait till stdin reading thread is started
+
+        stream.flush();
+        std::string output = stream.str();
+        size_t pos = output.find("->"); //prompt should be printed
+        EXPECT_LE(pos, output.size());
+    }
+
+    //TODO make working
+//    {
+//        std::stringstream stream{};
+//        celix::ShellTui tui{&stream, &stream};
+//        std::string cmd = "lb\n";
+//        write(STDIN_FILENO, cmd.c_str(), cmd.size());
+//        usleep(100000);//IMPROVE, for now wait till stdin command is processed on other thread.
+//        stream.flush();
+//        std::string output = stream.str();
+//        size_t pos = output.find("1: Framework"); //expect lb result
+//        EXPECT_LE(pos, output.size());
+//    }
+
+}
\ No newline at end of file
diff --git a/bundles/shell/cxx_shell_tui/include/celix/ShellTui.h b/bundles/shell/cxx_shell_tui/include/celix/ShellTui.h
new file mode 100644
index 0000000..67db882
--- /dev/null
+++ b/bundles/shell/cxx_shell_tui/include/celix/ShellTui.h
@@ -0,0 +1,69 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef CELIX_SHELLTUI_H
+#define CELIX_SHELLTUI_H
+
+#include <sstream>
+#include <mutex>
+#include <thread>
+
+#include "celix/api.h"
+#include "celix/IShellCommand.h"
+#include "celix/IShell.h"
+
+
+
+
+namespace celix {
+    static constexpr int SHELL_TUI_LINE_SIZE = 256;
+
+    class ShellTui {
+    public:
+        ShellTui(std::ostream *_outStream, std::ostream *_errStream);
+        ~ShellTui();
+
+        ShellTui(const ShellTui&) = delete;
+        ShellTui& operator=(const ShellTui&) = delete;
+
+        void setShell(std::shared_ptr<celix::IShell> _shell);
+    private:
+        void runnable();
+        void writePrompt();
+        void parseInput();
+
+        std::ostream * const outStream;
+        std::ostream * const errStream;
+
+        std::mutex mutex{};
+        std::shared_ptr<celix::IShell> shell{};
+
+        std::thread readThread{};
+
+        int readPipeFd{};
+        int writePipeFd{};
+
+
+        char in[SHELL_TUI_LINE_SIZE+1]{};
+        char buffer[SHELL_TUI_LINE_SIZE+1]{};
+        int pos{};
+    };
+}
+
+#endif //CELIX_SHELLTUI_H
diff --git a/bundles/shell/cxx_shell_tui/src/ShellTui.cc b/bundles/shell/cxx_shell_tui/src/ShellTui.cc
new file mode 100644
index 0000000..d9358d3
--- /dev/null
+++ b/bundles/shell/cxx_shell_tui/src/ShellTui.cc
@@ -0,0 +1,116 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+
+#include "celix/ShellTui.h"
+
+#include <memory>
+#include <sstream>
+
+#include <thread>
+#include <cstdio>
+#include <unistd.h>
+#include <fcntl.h>
+#include <mutex>
+
+#include <glog/logging.h>
+
+#include "celix/api.h"
+#include "celix/IShellCommand.h"
+#include "celix/IShell.h"
+
+static constexpr const char * const PROMPT = "-> ";
+static constexpr int KEY_ENTER = '\n';
+
+celix::ShellTui::ShellTui(std::ostream *_outStream, std::ostream *_errStream) : outStream{_outStream}, errStream{_errStream} {
+    int fds[2];
+    int rc  = pipe(fds);
+    if (rc == 0) {
+        readPipeFd = fds[0];
+        writePipeFd = fds[1];
+    if(fcntl(writePipeFd, F_SETFL, O_NONBLOCK) == 0) {
+        readThread = std::thread{&ShellTui::runnable, this};
+    } else {
+        LOG(ERROR) << "fcntl on pipe failed" << std::endl;
+    }
+    } else {
+        LOG(ERROR) << "fcntl on pipe failed" << std::endl;
+    }
+}
+
+
+celix::ShellTui::~ShellTui() {
+    write(writePipeFd, "\0", 1); //trigger select to stop
+    readThread.join();
+}
+
+void celix::ShellTui::runnable() {
+    //setup file descriptors
+    fd_set rfds;
+    int nfds = writePipeFd > STDIN_FILENO ? (writePipeFd +1) : (STDIN_FILENO + 1);
+
+    for (;;) {
+        writePrompt();
+        FD_ZERO(&rfds);
+        FD_SET(STDIN_FILENO, &rfds);
+        FD_SET(readPipeFd, &rfds);
+
+        if (select(nfds, &rfds, NULL, NULL, NULL) > 0) {
+            if (FD_ISSET(readPipeFd, &rfds)) {
+                break; //something is written to the pipe -> exit thread
+            } else if (FD_ISSET(STDIN_FILENO, &rfds)) {
+                parseInput();
+            }
+        }
+    }
+}
+
+void celix::ShellTui::writePrompt() {
+    *outStream << PROMPT;
+    std::flush(*outStream);
+    outStream->flush();
+}
+
+void celix::ShellTui::parseInput() {
+    char* line = NULL;
+    int nr_chars = (int)read(STDIN_FILENO, buffer, SHELL_TUI_LINE_SIZE-pos-1);
+    for (int bufpos = 0; bufpos < nr_chars; bufpos++) {
+        if (buffer[bufpos] == KEY_ENTER) { //end of line -> forward command
+            line = in; // todo trim string
+            std::lock_guard<std::mutex> lck{mutex};
+            if (shell) {
+                shell->executeCommandLine(line, *outStream, *errStream);
+            } else {
+                *errStream << "Shell service not available\n";
+            }
+            pos = 0;
+            in[pos] = '\0';
+        } else { //text
+            in[pos] = buffer[bufpos];
+            in[pos + 1] = '\0';
+            pos++;
+            continue;
+        }
+    } //for
+}
+
+void celix::ShellTui::setShell(std::shared_ptr<celix::IShell> _shell) {
+    std::lock_guard<std::mutex> lck{mutex};
+    shell = std::move(_shell);
+}
\ No newline at end of file
diff --git a/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc b/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc
index 0958ab0..70b3cce 100644
--- a/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc
+++ b/bundles/shell/cxx_shell_tui/src/ShellTuiActivator.cc
@@ -17,126 +17,25 @@
  *under the License.
  */
 
-#include <thread>
-#include <cstdio>
-#include <unistd.h>
-#include <fcntl.h>
-#include <mutex>
-
-#include <glog/logging.h>
+#include <iostream>
 
 #include "celix/api.h"
 #include "celix/IShellCommand.h"
 #include "celix/IShell.h"
 
-static constexpr int LINE_SIZE = 256;
-static constexpr const char * const PROMPT = "-> ";
-
-static constexpr int KEY_ENTER = '\n';
+#include "celix/ShellTui.h"
 
 namespace {
 
-    class ShellTui {
-    public:
-        ShellTui() {
-            int fds[2];
-            int rc  = pipe(fds);
-            if (rc == 0) {
-                readPipeFd = fds[0];
-                writePipeFd = fds[1];
-                if(fcntl(writePipeFd, F_SETFL, O_NONBLOCK) == 0) {
-                    readThread = std::thread{&ShellTui::runnable, this};
-                } else {
-                    LOG(ERROR) << "fcntl on pipe failed" << std::endl;
-                }
-            } else {
-                LOG(ERROR) << "fcntl on pipe failed" << std::endl;
-            }
-        }
-
-        ~ShellTui() {
-            write(writePipeFd, "\0", 1); //trigger select to stop
-            readThread.join();
-        }
-
-        void runnable() {
-            //setup file descriptors
-            fd_set rfds;
-            int nfds = writePipeFd > STDIN_FILENO ? (writePipeFd +1) : (STDIN_FILENO + 1);
-
-            for (;;) {
-                writePrompt();
-                FD_ZERO(&rfds);
-                FD_SET(STDIN_FILENO, &rfds);
-                FD_SET(readPipeFd, &rfds);
-
-                if (select(nfds, &rfds, NULL, NULL, NULL) > 0) {
-                    if (FD_ISSET(readPipeFd, &rfds)) {
-                        break; //something is written to the pipe -> exit thread
-                    } else if (FD_ISSET(STDIN_FILENO, &rfds)) {
-                       parseInput();
-                    }
-                }
-            }
-        }
-
-        void writePrompt() {
-            std::cout << PROMPT;
-            std::flush(std::cout);
-        }
-
-        void parseInput() {
-            char* line = NULL;
-            int nr_chars = (int)read(STDIN_FILENO, buffer, LINE_SIZE-pos-1);
-            for (int bufpos = 0; bufpos < nr_chars; bufpos++) {
-                if (buffer[bufpos] == KEY_ENTER) { //end of line -> forward command
-                    line = in; // todo trim string
-                    std::lock_guard<std::mutex> lck{mutex};
-                    if (shell) {
-                        shell->executeCommandLine(line, std::cout, std::cerr);
-                    } else {
-                        std::cerr << "Shell service not available\n";
-                    }
-                    pos = 0;
-                    in[pos] = '\0';
-                } else { //text
-                    in[pos] = buffer[bufpos];
-                    in[pos + 1] = '\0';
-                    pos++;
-                    continue;
-                }
-            } //for
-        }
-
-        void setShell(std::shared_ptr<celix::IShell> _shell) {
-           std::lock_guard<std::mutex> lck{mutex};
-           shell = _shell;
-        }
-    private:
-        std::mutex mutex{};
-        std::shared_ptr<celix::IShell> shell{};
-
-        std::thread readThread{};
-
-        int readPipeFd{};
-        int writePipeFd{};
-
-
-        char in[LINE_SIZE+1]{};
-        char buffer[LINE_SIZE+1]{};
-        int pos{};
-    };
-
-
     class ShellTuiBundleActivator : public celix::IBundleActivator {
     public:
         ShellTuiBundleActivator(std::shared_ptr<celix::BundleContext> ctx) {
             celix::ServiceTrackerOptions<celix::IShell> opts{};
-            opts.set = std::bind(&ShellTui::setShell, &tui, std::placeholders::_1);
+            opts.set = std::bind(&celix::ShellTui::setShell, &tui, std::placeholders::_1);
             trk = ctx->trackServices(opts);
         }
     private:
-        ShellTui tui{};
+        celix::ShellTui tui{&std::cout, &std::cerr};
         celix::ServiceTracker trk{};
     };
 


[celix] 10/22: CELIX-438: Updates external project configuration, so that building of external libs do not generated compiler warnings

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit fa43b32e961103b8bae6f9152694b26756d8c933
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Sat Jan 5 18:37:40 2019 +0100

    CELIX-438: Updates external project configuration, so that building of external libs do not generated compiler warnings
---
 cmake/celix_project/AddCppUTest.cmake | 4 ++--
 cmake/celix_project/AddGLog.cmake     | 4 ++--
 cmake/celix_project/AddLibzip.cmake   | 4 ++--
 3 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/cmake/celix_project/AddCppUTest.cmake b/cmake/celix_project/AddCppUTest.cmake
index f989e73..b6a0285 100644
--- a/cmake/celix_project/AddCppUTest.cmake
+++ b/cmake/celix_project/AddCppUTest.cmake
@@ -22,14 +22,14 @@ ExternalProject_Add(
         GIT_TAG v3.8
         UPDATE_DISCONNECTED TRUE
         PREFIX ${CMAKE_BINARY_DIR}/cpputest
-        CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/cpputest
+        CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/cpputest -DCMAKE_C_FLAGS=-w -DCMAKE_CXX_FLAGS=-w
 )
 
 file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/cpputest/include)
 
 set(CPPUTEST_LIBRARY cpputest::cpputest)
 set(CPPUTEST_EXT_LIBRARY cpputest::ext)
-set(CPPUTEST_INCLUDE_DIR ${binary_dir}/cpputest)
+set(CPPUTEST_INCLUDE_DIR ${CMAKE_BINARY_DIR}/cpputest/include)
 
 add_library(cpputest::cpputest IMPORTED STATIC GLOBAL)
 add_dependencies(cpputest::cpputest cpputest_project)
diff --git a/cmake/celix_project/AddGLog.cmake b/cmake/celix_project/AddGLog.cmake
index fe0137f..bdc6532 100644
--- a/cmake/celix_project/AddGLog.cmake
+++ b/cmake/celix_project/AddGLog.cmake
@@ -23,10 +23,10 @@ ExternalProject_Add(
         GIT_TAG v0.3.5
         UPDATE_DISCONNECTED TRUE
         PREFIX ${CMAKE_BINARY_DIR}/glog
-        CMAKE_ARGS -DWITH_GFLAGS=OFF -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/glog -DCMAKE_CXX_FLAGS=-w
+        CMAKE_ARGS -DWITH_GFLAGS=OFF -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/glog -DCMAKE_C_FLAGS=-w -DCMAKE_CXX_FLAGS=-w
 )
 
-file(MAKE_DIRECTORY ${source_dir}/glog/include)
+file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/glog/include)
 
 add_library(glog::glog IMPORTED STATIC GLOBAL)
 add_dependencies(glog::glog googlelog_project)
diff --git a/cmake/celix_project/AddLibzip.cmake b/cmake/celix_project/AddLibzip.cmake
index 19f8f15..5b31a79 100644
--- a/cmake/celix_project/AddLibzip.cmake
+++ b/cmake/celix_project/AddLibzip.cmake
@@ -22,10 +22,10 @@ ExternalProject_Add(
         GIT_TAG rel-1-5-1
         UPDATE_DISCONNECTED TRUE
         PREFIX ${CMAKE_BINARY_DIR}/libzip
-        CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/libzip -DCMAKE_C_FLAGS=-fPIC -DBUILD_SHARED_LIBS=OFF -DENABLE_COMMONCRYPTO=OFF -DENABLE_GNUTLS=OFF -DENABLE_OPENSSL=OFF -Wno-dev
+        CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/libzip -DCMAKE_C_FLAGS=-w\ -fPIC  -DBUILD_SHARED_LIBS=OFF -DENABLE_COMMONCRYPTO=OFF -DENABLE_GNUTLS=OFF -DENABLE_OPENSSL=OFF
 )
 
-file(MAKE_DIRECTORY ${source_dir}/libzip/include)
+file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/libzip/include)
 
 add_library(libzip::libzip IMPORTED STATIC GLOBAL)
 add_dependencies(libzip::libzip libzip_project)


[celix] 14/22: CELIX-438: Some refactoring

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 23d6e67638e1ef87f1f62c82e0f29b90fd11689e
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Sun Jan 6 21:10:44 2019 +0100

    CELIX-438: Some refactoring
---
 .../shell/cxx_shell/include/celix/IShellCommand.h  |  2 +-
 bundles/shell/cxx_shell/src/HelpCommand.cc         | 17 ++++++++----
 bundles/shell/cxx_shell/src/ShellActivator.cc      | 32 ++++++++++++++--------
 libs/framework_cxx/include/celix/BundleContext.h   |  4 +--
 libs/framework_cxx/include/celix/Framework.h       |  1 -
 .../framework_cxx/include/celix/IBundleActivator.h |  8 ++----
 libs/framework_cxx/include/celix/api.h             |  1 +
 libs/registry/include/celix/Utils.h                |  2 +-
 libs/registry/src/ServiceRegistry.cc               |  6 ++++
 9 files changed, 45 insertions(+), 28 deletions(-)

diff --git a/bundles/shell/cxx_shell/include/celix/IShellCommand.h b/bundles/shell/cxx_shell/include/celix/IShellCommand.h
index ec98c73..434fdfd 100644
--- a/bundles/shell/cxx_shell/include/celix/IShellCommand.h
+++ b/bundles/shell/cxx_shell/include/celix/IShellCommand.h
@@ -39,7 +39,7 @@ namespace celix {
         virtual void executeCommand(const std::string &cmdName, const std::vector<std::string> &cmdArgs, std::ostream &out, std::ostream &err) noexcept = 0;
     };
 
-    static constexpr const char * const SHELL_COMMAND_FUNCTION_SERVICE_FQN = "celix::ShellFunction [Version 1]";
+    static constexpr const char * const SHELL_COMMAND_FUNCTION_SERVICE_FQN = "celix::ShellCommandFunction [Version 1]";
     static constexpr const char * const SHELL_COMMAND_FUNCTION_COMMAND_NAME = "COMMAND_NAME";
     static constexpr const char * const SHELL_COMMAND_FUNCTION_COMMAND_USAGE = "COMMAND_USAGE";
     static constexpr const char * const SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION = "COMMAND_DESCRIPTION";
diff --git a/bundles/shell/cxx_shell/src/HelpCommand.cc b/bundles/shell/cxx_shell/src/HelpCommand.cc
index 0ed5fea..9b7dc9e 100644
--- a/bundles/shell/cxx_shell/src/HelpCommand.cc
+++ b/bundles/shell/cxx_shell/src/HelpCommand.cc
@@ -22,9 +22,10 @@
 #include "celix/api.h"
 #include "celix/IShellCommand.h"
 
-celix::ServiceRegistration impl::registerHelp(std::shared_ptr<celix::BundleContext> ctx) {
 
-    celix::ShellCommandFunction help = [ctx](const std::string &, const std::vector<std::string> &commandArguments, std::ostream &out, std::ostream &) {
+namespace {
+
+    void help(std::shared_ptr<celix::BundleContext> ctx, const std::string &, const std::vector<std::string> &commandArguments, std::ostream &out, std::ostream &) {
 
         if (commandArguments.empty()) { //only command -> overview
 
@@ -59,8 +60,7 @@ celix::ServiceRegistration impl::registerHelp(std::shared_ptr<celix::BundleConte
                 }, commandNameFilter);
                 if (!found) {
                     commandNameFilter = std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=" + cmd + ")";
-                    std::function<void(celix::ShellCommandFunction &, const celix::Properties &)> use = [&](
-                            celix::ShellCommandFunction &, const celix::Properties &props) {
+                    std::function<void(celix::ShellCommandFunction &, const celix::Properties &)> use = [&](celix::ShellCommandFunction &, const celix::Properties &props) {
                         out << "Command Name       : " << celix::getProperty(props, celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME, "!Error!") << std::endl;
                         out << "Command Usage      : " << celix::getProperty(props, celix::SHELL_COMMAND_FUNCTION_COMMAND_USAGE, "!Error!") << std::endl;
                         out << "Command Description: " << celix::getProperty(props, celix::SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION, "!Error!") << std::endl;
@@ -76,11 +76,16 @@ celix::ServiceRegistration impl::registerHelp(std::shared_ptr<celix::BundleConte
                 out << std::endl;
             }
         }
-    };
+    }
+}
+
+celix::ServiceRegistration impl::registerHelp(std::shared_ptr<celix::BundleContext> ctx) {
+    using namespace std::placeholders;
+    celix::ShellCommandFunction cmd = std::bind(&help, ctx, _1, _2, _3, _4);
 
     celix::Properties props{};
     props[celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME] = "help";
     props[celix::SHELL_COMMAND_FUNCTION_COMMAND_USAGE] = "help [command name]";
     props[celix::SHELL_COMMAND_FUNCTION_COMMAND_DESCRIPTION] = "display available commands and description.";
-    return ctx->registerFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, std::move(help), std::move(props));
+    return ctx->registerFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, std::move(cmd), std::move(props));
 }
\ No newline at end of file
diff --git a/bundles/shell/cxx_shell/src/ShellActivator.cc b/bundles/shell/cxx_shell/src/ShellActivator.cc
index 8d5d3fe..9d28070 100644
--- a/bundles/shell/cxx_shell/src/ShellActivator.cc
+++ b/bundles/shell/cxx_shell/src/ShellActivator.cc
@@ -46,7 +46,7 @@ namespace {
             std::vector<std::string> cmdArgs{};
 
             char *savePtr = nullptr;
-            char *cl = strndup(commandLine.c_str(), 1024*1024);
+            char *cl = strndup(commandLine.c_str(), 1024 * 1024);
             char *token = strtok_r(cl, " ", &savePtr);
             while (token != nullptr) {
                 if (cmdName.empty()) {
@@ -58,16 +58,24 @@ namespace {
             }
             free(cl);
 
+            if (cmdName.empty()) {
+                return true; /*nop, just enter and maybe some white spaces*/
+            } else {
+                return callShellCommands(cmdName, cmdArgs, out, err);
+            }
+        }
+
+    private:
+        bool callShellCommands(const std::string &cmdName, const std::vector<std::string> cmdArgs, std::ostream &out, std::ostream &err) {
             bool commandCalled = false;
 
-            if (!cmdName.empty()) {
-                //first try to call IShellCommand services.
-                std::string filter = std::string{"("} + celix::IShellCommand::COMMAND_NAME + "=" + cmdName + ")";
-                commandCalled = ctx->useService<celix::IShellCommand>([&](celix::IShellCommand &cmd) {
-                    cmd.executeCommand(cmdName, cmdArgs, out, err);
-                }, filter);
-            }
-            if (!cmdName.empty() && !commandCalled) {
+            //first try to call IShellCommand services.
+            std::string filter = std::string{"("} + celix::IShellCommand::COMMAND_NAME + "=" + cmdName + ")";
+            commandCalled = ctx->useService<celix::IShellCommand>([&](celix::IShellCommand &cmd) {
+                cmd.executeCommand(cmdName, cmdArgs, out, err);
+            }, filter);
+
+            if (!commandCalled) {
                 //if no IShellCommand service is found for the command name, try calling a ShellCommandFunction service.
                 std::string filter = std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=" + cmdName + ")";
                 std::function<void(celix::ShellCommandFunction&)> use = [&](celix::ShellCommandFunction &cmd) -> void {
@@ -76,12 +84,12 @@ namespace {
                 commandCalled = ctx->useFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, use, filter);
             }
 
-            //TODO C command service struct
-            if (!cmdName.empty() && !commandCalled) {
+            // TODO use C command service struct
+
+            if (!commandCalled) {
                 out << "Command '" << cmdName << "' not available. Type 'help' to see a list of available commands." << std::endl;
             }
 
-
             return commandCalled;
         }
     private:
diff --git a/libs/framework_cxx/include/celix/BundleContext.h b/libs/framework_cxx/include/celix/BundleContext.h
index 21a879e..2cdbf97 100644
--- a/libs/framework_cxx/include/celix/BundleContext.h
+++ b/libs/framework_cxx/include/celix/BundleContext.h
@@ -53,7 +53,7 @@ namespace celix {
             return registry().registerFunctionService(std::move(functionName), std::forward<F>(function), std::move(props), bundle());
         }
 
-        //TODO reg svc fatories
+        //TODO reg svc factories
 
         bool useBundle(long bndId, std::function<void(const celix::IBundle &bnd)> use) const {
             return bundle()->framework().useBundle(bndId, std::move(use));
@@ -71,7 +71,7 @@ namespace celix {
             return bundle()->framework().startBundle(bndId);
         }
 
-        //TODO install / uninstall bundles, trackb undles
+        //TODO install / uninstall bundles, use & track bundles
 
         template<typename I>
         bool useServiceWithId(long svcId, std::function<void(I& svc)> use) const {
diff --git a/libs/framework_cxx/include/celix/Framework.h b/libs/framework_cxx/include/celix/Framework.h
index 22d6aef..8689be7 100644
--- a/libs/framework_cxx/include/celix/Framework.h
+++ b/libs/framework_cxx/include/celix/Framework.h
@@ -31,7 +31,6 @@ namespace celix {
 
     class BundleContext; //forward declaration
 
-    //TODO resources. resolved from bundle specific symbols which is linked zip file to the library
     void registerStaticBundle(
             std::string symbolicName,
             std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> bundleActivatorFactory = {},
diff --git a/libs/framework_cxx/include/celix/IBundleActivator.h b/libs/framework_cxx/include/celix/IBundleActivator.h
index d2b05ec..b91978e 100644
--- a/libs/framework_cxx/include/celix/IBundleActivator.h
+++ b/libs/framework_cxx/include/celix/IBundleActivator.h
@@ -22,12 +22,10 @@
 
 namespace celix {
     /**
-     * The BundleActivator.
+     * The BundleActivator is a marker interface and contains no virtual methods.
      *
-     * This is a marker interface and contains no virtual methods.
-     *
-     * The Celix Framework will expect a constructor with a std::shared_ptr<celix::IBundleContext> argument on the
-     * contrete bundle activator. RAII will be used to start (on ctor) and stop (on dtor) a bundle.
+     * The Celix Framework will expect a constructor with a std::shared_ptr<celix:IBundleContext> argument for the
+     * concrete bundle activator. RAII will be used to start (on ctor) and stop (on dtor) a bundle.
      */
     class IBundleActivator {
     public:
diff --git a/libs/framework_cxx/include/celix/api.h b/libs/framework_cxx/include/celix/api.h
index fa0a8b9..606d165 100644
--- a/libs/framework_cxx/include/celix/api.h
+++ b/libs/framework_cxx/include/celix/api.h
@@ -24,6 +24,7 @@
 #include "celix/Filter.h"
 #include "celix/ServiceRegistry.h"
 #include "celix/IBundleActivator.h"
+#include "celix/IBundle.h"
 #include "celix/Framework.h"
 #include "celix/BundleContext.h"
 
diff --git a/libs/registry/include/celix/Utils.h b/libs/registry/include/celix/Utils.h
index 09d674d..ce72e4f 100644
--- a/libs/registry/include/celix/Utils.h
+++ b/libs/registry/include/celix/Utils.h
@@ -91,7 +91,7 @@ namespace celix {
     //NOTE C++17 typename std::enable_if<std::is_callable<I>::value, std::string>::type
     std::string functionServiceName(const std::string &fName) {
         std::string func = functionName<decltype(&F::operator())>();
-        return fName + "[" + func + "]";
+        return fName + " [" + func + "]";
     }
 }
 
diff --git a/libs/registry/src/ServiceRegistry.cc b/libs/registry/src/ServiceRegistry.cc
index 6ed83f7..b809e8f 100644
--- a/libs/registry/src/ServiceRegistry.cc
+++ b/libs/registry/src/ServiceRegistry.cc
@@ -25,6 +25,12 @@
 #include <utility>
 #include <future>
 
+#ifndef __APPLE__
+#include <linux/limits.h>
+#else
+#include <limits.h>
+#endif
+
 #include <glog/logging.h>
 #include <assert.h>
 


[celix] 12/22: CELIX-438: Adds a assert and warning log for wrong useage of the use(Funcion)Service(s) calls and adds some unit tests for the C++ shell.

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit cc671b6deb823fa06c79b1f88ac6a732eebab261
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Sun Jan 6 20:29:25 2019 +0100

    CELIX-438: Adds a assert and warning log for wrong useage of the use(Funcion)Service(s) calls and adds some unit tests for the C++ shell.
---
 CMakeLists.txt                                   |   2 +-
 bundles/shell/cxx_shell/CMakeLists.txt           |   6 +-
 bundles/shell/cxx_shell/gtest/CMakeLists.txt     |   7 +-
 bundles/shell/cxx_shell/gtest/src/Shell_tests.cc | 163 ++++++++++++++++++
 bundles/shell/cxx_shell/src/QueryCommand.cc      |   2 +-
 libs/CMakeLists.txt                              |   6 +-
 libs/framework_cxx/gtest/src/Framework_tests.cc  |   2 +-
 libs/framework_cxx/include/celix/BundleContext.h |  29 +++-
 libs/framework_cxx/include/celix/Framework.h     |   2 +
 libs/framework_cxx/src/Bundle.h                  |   6 +-
 libs/framework_cxx/src/BundleContext.cc          |   7 +-
 libs/framework_cxx/src/BundleController.h        |   2 +-
 libs/framework_cxx/src/Framework.cc              | 209 ++++++++++++-----------
 libs/registry/CMakeLists.txt                     |   5 +-
 libs/registry/gtest/CMakeLists.txt               |   3 +-
 libs/registry/gtest/src/Registry_tests.cc        |   2 +-
 libs/registry/gtest/src/Utils_tests.cc           |  56 ++++++
 libs/registry/include/celix/Constants.h          |   6 +-
 libs/registry/include/celix/ServiceRegistry.h    |  47 +++--
 libs/registry/include/celix/Utils.h              |  46 +++--
 libs/registry/src/ServiceRegistry.cc             |  44 +++--
 libs/registry/src/Utils.cc                       |  51 ++++++
 22 files changed, 518 insertions(+), 185 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 968e74c..f1807f7 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -56,7 +56,7 @@ option(ENABLE_TESTING "Enables unit testing" ON)
 if (ENABLE_TESTING)
 	enable_testing()
     include(cmake/celix_project/AddGTest.cmake)
-    include(cmake/celix_project/AddCppUTest.cmake)
+    #include(cmake/celix_project/AddCppUTest.cmake)
 endif ()
 include(cmake/celix_project/AddGLog.cmake)
 include(cmake/celix_project/AddLibzip.cmake)
diff --git a/bundles/shell/cxx_shell/CMakeLists.txt b/bundles/shell/cxx_shell/CMakeLists.txt
index c82d2ef..3dced30 100644
--- a/bundles/shell/cxx_shell/CMakeLists.txt
+++ b/bundles/shell/cxx_shell/CMakeLists.txt
@@ -56,6 +56,6 @@ else ()
 endif ()
 
 
-#if (ENABLE_TESTING)
-#    add_subdirectory(gtest)
-#endif ()
\ No newline at end of file
+if (ENABLE_TESTING)
+    add_subdirectory(gtest)
+endif ()
\ No newline at end of file
diff --git a/bundles/shell/cxx_shell/gtest/CMakeLists.txt b/bundles/shell/cxx_shell/gtest/CMakeLists.txt
index b4a7204..c95f364 100644
--- a/bundles/shell/cxx_shell/gtest/CMakeLists.txt
+++ b/bundles/shell/cxx_shell/gtest/CMakeLists.txt
@@ -17,9 +17,10 @@
 
 set(SOURCES
         src/main.cc
+        src/Shell_tests.cc
 )
 add_executable(celix_shell_cxx_tests ${SOURCES})
-target_link_libraries(celix_shell_cxx_tests PRIVATE gtest celix_framework_cxx celix_shell_cxx)
+target_link_libraries(celix_shell_cxx_tests PRIVATE gtest celix_framework_cxx celix_cxx_shell celix_cxx_shell_api glog::glog)
 
-add_test(NAME celix_shell_cxx_tests COMMAND celix_shell_cxx_tests)
-SETUP_TARGET_FOR_COVERAGE(celix_shell_cxx_tests_cov celix_shell_cxx_tests ${CMAKE_BINARY_DIR}/coverage/celix_shell_cxx_tests/celix_shell_cxx_tests)
\ No newline at end of file
+add_test(NAME celix_cxx_shell_tests COMMAND celix_cxx_shell_tests)
+SETUP_TARGET_FOR_COVERAGE(celix_cxx_shell_tests_cov celix_cxx_shell_tests ${CMAKE_BINARY_DIR}/coverage/celix_cxx_shell_tests/celix_cxx_shell_tests ..)
\ No newline at end of file
diff --git a/bundles/shell/cxx_shell/gtest/src/Shell_tests.cc b/bundles/shell/cxx_shell/gtest/src/Shell_tests.cc
new file mode 100644
index 0000000..b6bbd8b
--- /dev/null
+++ b/bundles/shell/cxx_shell/gtest/src/Shell_tests.cc
@@ -0,0 +1,163 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include <sstream>
+
+#include "gtest/gtest.h"
+
+#include "celix/api.h"
+#include "celix/IShellCommand.h"
+#include "celix/IShell.h"
+
+class ShellTest : public ::testing::Test {
+public:
+    ShellTest() {}
+    ~ShellTest(){}
+
+    celix::Framework& framework() { return fw; }
+private:
+    celix::Framework fw{};
+};
+
+
+
+
+TEST_F(ShellTest, AreCommandsAndShellRegistered) {
+
+    std::string filter = std::string{"("} + celix::IShellCommand::COMMAND_NAME + "=lb)";
+    long svcId = framework().context().findService<celix::IShellCommand>(filter);
+    EXPECT_TRUE(svcId > 0);
+
+    filter = std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=help)";
+    svcId = framework().context().findFunctionService<celix::ShellCommandFunction>(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, filter);
+    EXPECT_TRUE(svcId > 0);
+
+    filter = std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=inspect)";
+    svcId = framework().context().findFunctionService<celix::ShellCommandFunction>(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, filter);
+    EXPECT_TRUE(svcId > 0);
+
+    filter = std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=query)";
+    svcId = framework().context().findFunctionService<celix::ShellCommandFunction>(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, filter);
+    EXPECT_TRUE(svcId > 0);
+
+    filter = std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=stop)";
+    svcId = framework().context().findFunctionService<celix::ShellCommandFunction>(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, filter);
+    EXPECT_TRUE(svcId > 0);
+
+    filter = std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=start)";
+    svcId = framework().context().findFunctionService<celix::ShellCommandFunction>(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, filter);
+    EXPECT_TRUE(svcId > 0);
+
+    filter = std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=version)";
+    svcId = framework().context().findFunctionService<celix::ShellCommandFunction>(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, filter);
+    EXPECT_TRUE(svcId > 0);
+
+    svcId = framework().context().findService<celix::IShell>();
+    EXPECT_TRUE(svcId > 0);
+};
+
+TEST_F(ShellTest, LbCommandTest) {
+    std::stringstream ss{};
+    std::function<void(celix::IShellCommand&)> useLb = [&ss](celix::IShellCommand& cmd){
+        cmd.executeCommand("lb", {}, ss, ss);
+    };
+    std::string filter = std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=lb)";
+    bool called = framework().context().useService(useLb, filter);
+    EXPECT_TRUE(called);
+
+    ss.flush();
+    std::string output = ss.str();
+
+    size_t pos = output.find("1: Framework");
+    EXPECT_LE(pos, output.size());
+    pos = output.find("2: Shell");
+    EXPECT_LE(pos, output.size());
+
+}
+
+TEST_F(ShellTest, HelpCommandTest) {
+    std::string filter = std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=help)";
+    {
+        //call general help
+        std::stringstream ss{};
+        std::function<void(celix::ShellCommandFunction&)> useHelp = [&ss](celix::ShellCommandFunction& cmd){
+            cmd("help", {}, ss, ss);
+        };
+        bool called = framework().context().useFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, useHelp, filter);
+        EXPECT_TRUE(called);
+
+        ss.flush();
+        std::string output = ss.str();
+        size_t pos = output.find("help"); //Expect help as command
+        EXPECT_LE(pos, output.size());
+        pos = output.find("lb"); //Expect lb as command
+        EXPECT_LE(pos, output.size());
+        pos = output.find("inspect"); //Expect inspect as command
+        EXPECT_LE(pos, output.size());
+    }
+
+    {
+        //call help with arg
+        std::stringstream ss{};
+        std::vector<std::string> args{};
+        std::function<void(celix::ShellCommandFunction&)> useHelp = [&ss, &args](celix::ShellCommandFunction& cmd){
+            cmd("help", args, ss, ss);
+        };
+
+        args.emplace_back("lb");
+        bool called = framework().context().useFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, useHelp, filter);
+        EXPECT_TRUE(called);
+        ss.flush();
+        std::string output = ss.str();
+        size_t pos = output.find("list bundles.");
+        EXPECT_LE(pos, output.size());
+
+        args.clear();
+        args.emplace_back("unknown");
+        ss.clear();
+        called = framework().context().useFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, useHelp, filter);
+        EXPECT_TRUE(called);
+        ss.flush();
+        output = ss.str();
+        pos = output.find("not available");
+        EXPECT_LE(pos, output.size());
+    }
+}
+
+TEST_F(ShellTest, VersionCommandTest) {
+    //NOTE that this also test if the resources zip usage (extender pattern).
+
+    std::string filter = std::string{"("} + celix::SHELL_COMMAND_FUNCTION_COMMAND_NAME + "=version)";
+
+    //call general help
+    std::stringstream ss{};
+    std::function<void(celix::ShellCommandFunction &)> useHelp = [&ss](celix::ShellCommandFunction &cmd) {
+        cmd("version", {}, ss, ss);
+    };
+    bool called = framework().context().useFunctionService(celix::SHELL_COMMAND_FUNCTION_SERVICE_FQN, useHelp, filter);
+    EXPECT_TRUE(called);
+
+    ss.flush();
+    std::string output = ss.str();
+    size_t pos = output.find("3.0.0"); //Expect 3.0.0 as version
+    EXPECT_LE(pos, output.size());
+}
+
+
+//TODO rest of the commands
\ No newline at end of file
diff --git a/bundles/shell/cxx_shell/src/QueryCommand.cc b/bundles/shell/cxx_shell/src/QueryCommand.cc
index 225709c..67206bc 100644
--- a/bundles/shell/cxx_shell/src/QueryCommand.cc
+++ b/bundles/shell/cxx_shell/src/QueryCommand.cc
@@ -45,7 +45,7 @@ namespace {
                 svcName = cmdArgs[1];
                 filter = cmdArgs[2];
             } else {
-                lang = celix::CXX_LANG;
+                lang = celix::C_AND_CXX_LANG_REG;
                 svcName = cmdArgs[0];
                 filter = cmdArgs[1];
             }
diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt
index 928932a..c811b70 100644
--- a/libs/CMakeLists.txt
+++ b/libs/CMakeLists.txt
@@ -17,9 +17,9 @@
 
 #utils, dfi and etcdlib are standalone
 #(e.g. no dependency on celix framework
-add_subdirectory(utils)
-add_subdirectory(dfi)
-add_subdirectory(etcdlib)
+#add_subdirectory(utils)
+#add_subdirectory(dfi)
+#add_subdirectory(etcdlib)
 
 #add_subdirectory(framework)
 
diff --git a/libs/framework_cxx/gtest/src/Framework_tests.cc b/libs/framework_cxx/gtest/src/Framework_tests.cc
index 88580f3..ab14713 100644
--- a/libs/framework_cxx/gtest/src/Framework_tests.cc
+++ b/libs/framework_cxx/gtest/src/Framework_tests.cc
@@ -40,7 +40,7 @@ TEST_F(FrameworkTest, CreateDestroy) {
     EXPECT_EQ(0, framework().listBundles(false).size());
 
     bool isFramework = false;
-    framework().useBundle(0L, [&](const celix::IBundle &bnd) {
+    framework().useBundle(celix::FRAMEWORK_BUNDLE_ID, [&](const celix::IBundle &bnd) {
        isFramework = bnd.isFrameworkBundle();
     });
     EXPECT_TRUE(isFramework);
diff --git a/libs/framework_cxx/include/celix/BundleContext.h b/libs/framework_cxx/include/celix/BundleContext.h
index 296b5c0..21a879e 100644
--- a/libs/framework_cxx/include/celix/BundleContext.h
+++ b/libs/framework_cxx/include/celix/BundleContext.h
@@ -53,7 +53,7 @@ namespace celix {
             return registry().registerFunctionService(std::move(functionName), std::forward<F>(function), std::move(props), bundle());
         }
 
-        //TODO register C services
+        //TODO reg svc fatories
 
         bool useBundle(long bndId, std::function<void(const celix::IBundle &bnd)> use) const {
             return bundle()->framework().useBundle(bndId, std::move(use));
@@ -163,7 +163,25 @@ namespace celix {
             return registry().useFunctionServices<F>(functionName, std::move(use), filter, bundle());
         }
 
-        //TODO use C services
+        template<typename I>
+        long findService(const std::string &filter = "") {
+            return registry().findService<I>(filter);
+        }
+
+        template<typename F>
+        long findFunctionService(const std::string &functionName, const std::string &filter = "") {
+            return registry().findFunctionService<F>(functionName, filter);
+        }
+
+        template<typename I>
+        std::vector<long> findServices(const std::string &filter = "") {
+            return registry().findServices<I>(filter);
+        }
+
+        template<typename F>
+        std::vector<long> findFunctionServices(const std::string &functionName, const std::string &filter = "") {
+            return registry().findFunctionServices<F>(functionName, filter);
+        }
 
         template<typename I>
         celix::ServiceTracker trackServices(celix::ServiceTrackerOptions<I> options = {}) {
@@ -175,15 +193,8 @@ namespace celix {
             return registry().trackFunctionServices<F>(functionName, std::move(options), bundle());
         }
 
-        //TODO track C Services
-
-        //TODO track trackers
-
-        //TODO track c trackers
-
 
         celix::ServiceRegistry& registry() const;
-        celix::ServiceRegistry& cRegistry() const;
     private:
 
         class Impl;
diff --git a/libs/framework_cxx/include/celix/Framework.h b/libs/framework_cxx/include/celix/Framework.h
index 89e9a3b..22d6aef 100644
--- a/libs/framework_cxx/include/celix/Framework.h
+++ b/libs/framework_cxx/include/celix/Framework.h
@@ -89,6 +89,8 @@ namespace celix {
         std::string cacheDir() const;
         std::string uuid() const;
 
+        celix::BundleContext& context() const;
+
         //TODO trackBundles
 
         //long bundleIdForName(const std::string &bndName) const;
diff --git a/libs/framework_cxx/src/Bundle.h b/libs/framework_cxx/src/Bundle.h
index ce5e456..1adb2c7 100644
--- a/libs/framework_cxx/src/Bundle.h
+++ b/libs/framework_cxx/src/Bundle.h
@@ -29,9 +29,9 @@
 namespace celix {
     class Bundle : public celix::IBundle {
     public:
-        Bundle(long _bndId, celix::Framework *_fw, celix::Properties _manifest) :
+        Bundle(long _bndId, const std::string &cacheDir, celix::Framework *_fw, celix::Properties _manifest) :
                 bndId{_bndId}, fw{_fw}, bndManifest{std::move(_manifest)},
-                bundleCache{framework().cacheDir() + "/bundle" + std::to_string(_bndId)},
+                bundleCache{cacheDir + "/bundle" + std::to_string(_bndId)},
                 bndState{BundleState::INSTALLED} {
             bndState.store(BundleState::INSTALLED, std::memory_order_release);
         }
@@ -48,7 +48,7 @@ namespace celix {
         const std::string &cacheRoot() const noexcept override;
 
         //bundle part
-        bool isFrameworkBundle() const noexcept override { return false; }
+        bool isFrameworkBundle() const noexcept override { return bndId == 1 /*note 1 is the framework bundle id*/; }
 
         void *handle() const noexcept override { return nullptr; } //TODO
 
diff --git a/libs/framework_cxx/src/BundleContext.cc b/libs/framework_cxx/src/BundleContext.cc
index 5b9b192..045f2e3 100644
--- a/libs/framework_cxx/src/BundleContext.cc
+++ b/libs/framework_cxx/src/BundleContext.cc
@@ -26,15 +26,13 @@ namespace celix {
     public:
         Impl(std::shared_ptr<celix::IBundle> _bnd) :
             bnd{std::move(_bnd)},
-            reg{&bnd->framework().registry(celix::CXX_LANG)},
-            cReg(&bnd->framework().registry(celix::C_LANG)){}
+            reg{&bnd->framework().registry(celix::C_AND_CXX_LANG_REG)} {}
 
         Impl(const Impl&) = delete;
         Impl& operator=(const Impl&) = delete;
 
         const std::shared_ptr<celix::IBundle> bnd;
         celix::ServiceRegistry * const reg; //TODO make weak_ptr
-        celix::ServiceRegistry * const cReg; //TODO make weak_ptr
 
     };
 }
@@ -52,7 +50,4 @@ celix::ServiceRegistry& celix::BundleContext::registry() const {
     return *pimpl->reg;
 }
 
-celix::ServiceRegistry& celix::BundleContext::cRegistry() const {
-    return *pimpl->cReg;
-}
 
diff --git a/libs/framework_cxx/src/BundleController.h b/libs/framework_cxx/src/BundleController.h
index 1228066..01a821c 100644
--- a/libs/framework_cxx/src/BundleController.h
+++ b/libs/framework_cxx/src/BundleController.h
@@ -247,7 +247,7 @@ namespace celix {
         const uint8_t *resourcesZip;
         const size_t resourcesZipLen;
 
-        mutable std::mutex mutex{};
+        mutable std::mutex mutex{}; //protects act and lock access to the bundle for state transitions
         std::unique_ptr<celix::IBundleActivator> act{nullptr};
     };
 }
diff --git a/libs/framework_cxx/src/Framework.cc b/libs/framework_cxx/src/Framework.cc
index 0740e5b..1b3ab87 100644
--- a/libs/framework_cxx/src/Framework.cc
+++ b/libs/framework_cxx/src/Framework.cc
@@ -62,28 +62,67 @@ static struct {
 static void registerFramework(celix::Framework *fw);
 static void unregisterFramework(celix::Framework *fw);
 
-class celix::Framework::Impl : public IBundle {
-public:
-    Impl(celix::Framework *_fw, celix::Properties _config) : fw{_fw}, config{std::move(_config)}, bndManifest{createManifest()}, cwd{cwdString()}, fwUUID{uuidString()}{
-        startFramework();
+namespace {
+    //some utils function
+
+    celix::Properties createFwManifest() {
+        celix::Properties m{};
+        m[celix::MANIFEST_BUNDLE_SYMBOLIC_NAME] = "framework";
+        m[celix::MANIFEST_BUNDLE_NAME] = "Framework";
+        m[celix::MANIFEST_BUNDLE_GROUP] = "Celix";
+        m[celix::MANIFEST_BUNDLE_VERSION] = "3.0.0";
+        return m;
+    }
+
+    std::string genUUIDString() {
+        char uuidStr[37];
+        uuid_t uuid;
+        uuid_generate(uuid);
+        uuid_unparse(uuid, uuidStr);
+        return std::string{uuidStr};
+    }
+
+    std::string createCwdString() {
+        char workdir[PATH_MAX];
+        if (getcwd(workdir, sizeof(workdir)) != NULL) {
+            return std::string{workdir};
+        } else {
+            return std::string{};
+        }
     }
 
+    std::string genFwCacheDir(const celix::Properties &/*fwConfig*/) {
+        //TODO make configeruable
+        return createCwdString() + "/.cache";
+    }
+}
+
+class celix::Framework::Impl {
+public:
+    Impl(celix::Framework *_fw, celix::Properties _config) :
+            fw{_fw},
+            config{std::move(_config)},
+            bndManifest{createFwManifest()},
+            cwd{createCwdString()},
+            fwUUID{genUUIDString()},
+            fwCacheDir{genFwCacheDir(config)} {}
+
     Impl(const Impl&) = delete;
     Impl& operator=(const Impl&) = delete;
 
-    ~Impl() {
-        stopFramework();
-        waitForShutdown();
-    }
+    ~Impl() {}
 
     std::vector<long> listBundles(bool includeFrameworkBundle) const {
         std::vector<long> result{};
-        if (includeFrameworkBundle) {
-            result.push_back(0L); //framework bundle id
-        }
         std::lock_guard<std::mutex> lock{bundles.mutex};
         for (auto &entry : bundles.entries) {
-            result.push_back(entry.first);
+            if (entry.second->bundle()->id() == FRAMEWORK_BUNDLE_ID) {
+                if (includeFrameworkBundle) {
+                    result.push_back(entry.first);
+                }
+            } else {
+                result.push_back(entry.first);
+            }
         }
         std::sort(result.begin(), result.end());//ensure that the bundles are order by bndId -> i.e. time of install
         return result;
@@ -118,7 +157,7 @@ public:
 
             std::lock_guard<std::mutex> lck{bundles.mutex};
             bndId = bundles.nextBundleId++;
-            auto bnd = std::shared_ptr<celix::Bundle>{new celix::Bundle{bndId, this->fw, std::move(manifest)}};
+            auto bnd = std::shared_ptr<celix::Bundle>{new celix::Bundle{bndId, this->cacheDir(), this->fw, std::move(manifest)}};
             auto ctx = std::shared_ptr<celix::BundleContext>{new celix::BundleContext{bnd}};
             bndController = std::shared_ptr<celix::BundleController>{new celix::BundleController{std::move(actFactory), bnd, ctx, resourcesZip, resourcesZipLen}};
             bundles.entries.emplace(std::piecewise_construct,
@@ -141,16 +180,15 @@ public:
     }
 
     bool startBundle(long bndId) {
-        if (bndId == this->fwBndId) {
-            //TODO
-            return false;
+        if (bndId == FRAMEWORK_BUNDLE_ID) {
+            return startFramework();
         } else {
             return transitionBundleTo(bndId, BundleState::ACTIVE);
         }
     }
 
     bool stopBundle(long bndId) {
-        if (bndId == this->fwBndId) {
+        if (bndId == FRAMEWORK_BUNDLE_ID) {
             return stopFramework();
         } else {
             return transitionBundleTo(bndId, BundleState::INSTALLED);
@@ -201,26 +239,20 @@ public:
 
     bool useBundle(long bndId, std::function<void(const celix::IBundle &bnd)> use) const {
         bool called = false;
-        if (bndId == 0) {
-            //framework bundle
-            use(*this);
-            called = true;
-        } else {
-            std::shared_ptr<celix::BundleController> match = nullptr;
-            {
-                std::lock_guard<std::mutex> lck{bundles.mutex};
-                auto it = bundles.entries.find(bndId);
-                if (it != bundles.entries.end()) {
-                    match = it->second;
-                    //TODO increase usage
-                }
-            }
-            if (match) {
-                use(*match->bundle());
-                called = true;
-                //TODO decrease usage -> use shared ptr instead
+        std::shared_ptr<celix::BundleController> match = nullptr;
+        {
+            std::lock_guard<std::mutex> lck{bundles.mutex};
+            auto it = bundles.entries.find(bndId);
+            if (it != bundles.entries.end()) {
+                match = it->second;
+                //TODO increase usage
             }
         }
+        if (match) {
+            use(*match->bundle());
+            called = true;
+            //TODO decrease usage -> use shared ptr instead
+        }
         return called;
     }
 
@@ -229,13 +261,16 @@ public:
         {
             std::lock_guard<std::mutex> lck{bundles.mutex};
             for (const auto &it : bundles.entries) {
-                useBundles[it.first] = it.second;
+                if (it.second->bundle()->id() == FRAMEWORK_BUNDLE_ID) {
+                    if (includeFramework) {
+                        useBundles[it.first] = it.second;
+                    }
+                } else {
+                    useBundles[it.first] = it.second;
+                }
             }
         }
 
-        if (includeFramework) {
-            use(*this);
-        }
         for (const auto &cntr : useBundles) {
             use(*cntr.second->bundle());
         }
@@ -257,51 +292,45 @@ public:
         }
     }
 
-    //resource bundle part
-    long id() const noexcept override { return 1L /*note registry empty bundle is id 0, framework is id 1*/; }
-    bool hasCacheEntry(const std::string &) const noexcept override { return false; }
-    bool isCacheEntryDir(const std::string &) const noexcept override { return false; }
-    bool isCacheEntryFile(const std::string &) const noexcept override { return false; }
-
-    //virtual bool storeResource(const std::string &path, std::ostream content) noexcept = 0;
-    //virtual std::istream open(const std::string &path) const noexcept = 0;
-    //virtual std::fstream open(const std::string &path) noexcept = 0;
-    std::string absPathForCacheEntry(const std::string &) const noexcept override { return {}; }
-    const std::string& cacheRoot() const noexcept override { //TODO
-        return cwd;
-    }
-
-    //bundle stuff
-    bool isFrameworkBundle() const noexcept override { return true; }
-    void* handle() const noexcept override { return nullptr; }
-    celix::BundleState state() const noexcept override { return BundleState::ACTIVE ; }
-    const std::string& name() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_NAME); }
-    const std::string& symbolicName() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_SYMBOLIC_NAME); }
-    const std::string& group() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_GROUP); }
-    const std::string& version() const noexcept override { return bndManifest.at(celix::MANIFEST_BUNDLE_VERSION); }
-    const celix::Properties& manifest() const noexcept  override { return bndManifest;}
-    bool isValid() const noexcept override { return true; }
-    celix::Framework& framework() const noexcept override { return *fw; }
 
     std::string cacheDir() const {
-        return cwd + "/.cache"; //TODO make configurable
+        return fwCacheDir;
     }
 
-    std::vector<std::string> readCacheDir(const std::string &) const noexcept override { return {}; } //TODO
-
     std::string uuid() const {
         return fwUUID;
     }
 
+    celix::BundleContext& frameworkContext() const {
+        std::lock_guard<std::mutex> lck(bundles.mutex);
+        return *bundles.entries.at(celix::FRAMEWORK_BUNDLE_ID)->context();
+    }
+
     bool startFramework() {
         //TODO create cache dir using a process id (and  lock file?).
         //Maybe also move to /var/cache or /tmp and when framework stop delete all framework caches of not running processes
-        std::cout << "Celix Framework Started";
+
+        {
+            //Adding framework bundle to the bundles.
+            auto bnd = std::shared_ptr<celix::Bundle>{new celix::Bundle{FRAMEWORK_BUNDLE_ID, this->fwCacheDir, this->fw, bndManifest}};
+            bnd->setState(BundleState::ACTIVE);
+            auto ctx = std::shared_ptr<celix::BundleContext>{new celix::BundleContext{bnd}};
+            class EmptyActivator : public IBundleActivator {};
+            std::function<celix::IBundleActivator*(std::shared_ptr<celix::BundleContext>)> fac = [](std::shared_ptr<celix::BundleContext>) {
+                return new EmptyActivator{};
+            };
+            auto ctr = std::shared_ptr<celix::BundleController>{new celix::BundleController{std::move(fac), std::move(bnd), std::move(ctx), nullptr, 0}};
+            std::lock_guard<std::mutex> lck{bundles.mutex};
+            bundles.entries[FRAMEWORK_BUNDLE_ID] = std::move(ctr);
+        }
+
+        //TODO update state
+
+        std::cout << "Celix Framework Started\n";
         return true;
     }
 
     bool stopFramework() {
-        //TODO create cache dir
         std::lock_guard<std::mutex> lck{shutdown.mutex};
         if (!shutdown.shutdownStarted) {
             shutdown.future = std::async(std::launch::async, [this]{
@@ -317,7 +346,12 @@ public:
             shutdown.shutdownStarted = true;
             shutdown.cv.notify_all();
         }
-        std::cout << "Celix Framework Stopped";
+
+        //TODO update bundle state
+
+        //TODO clean cache dir
+
+        std::cout << "Celix Framework Stopped\n";
         return true;
     }
 
@@ -329,38 +363,13 @@ public:
         return true;
     }
 private:
-    celix::Properties createManifest() {
-        celix::Properties m{};
-        m[celix::MANIFEST_BUNDLE_SYMBOLIC_NAME] = "framework";
-        m[celix::MANIFEST_BUNDLE_NAME] = "Framework";
-        m[MANIFEST_BUNDLE_GROUP] = "Celix";
-        m[celix::MANIFEST_BUNDLE_VERSION] = "3.0.0";
-        return m;
-    }
 
-    std::string uuidString() {
-        char uuidStr[37];
-        uuid_t uuid;
-        uuid_generate(uuid);
-        uuid_unparse(uuid, uuidStr);
-        return std::string{uuidStr};
-    }
-
-    std::string cwdString() {
-        char workdir[PATH_MAX];
-        if (getcwd(workdir, sizeof(workdir)) != NULL) {
-            return std::string{workdir};
-        } else {
-            return std::string{};
-        }
-    }
-
-    const long fwBndId = 1L;
     celix::Framework * const fw;
     const celix::Properties config;
     const celix::Properties bndManifest;
     const std::string cwd;
     const std::string fwUUID;
+    const std::string fwCacheDir;
 
 
     struct {
@@ -374,7 +383,7 @@ private:
 
     struct {
         std::unordered_map<long, std::shared_ptr<celix::BundleController>> entries{};
-        long nextBundleId = 2;
+        long nextBundleId = FRAMEWORK_BUNDLE_ID + 1;
         mutable std::mutex mutex{};
     } bundles{};
 
@@ -389,11 +398,14 @@ private:
  **********************************************************************************************************************/
 
 celix::Framework::Framework(celix::Properties config) : pimpl{std::unique_ptr<Impl>{new Impl{this, std::move(config)}}} {
+    pimpl->startFramework();
     registerFramework(this);
 }
 
 celix::Framework::~Framework() {
     unregisterFramework(this);
+    pimpl->stopFramework();
+    pimpl->waitForShutdown();
 }
 
 celix::Framework::Framework(Framework &&rhs) = default;
@@ -435,6 +447,9 @@ std::string celix::Framework::uuid() const {
     return pimpl->uuid();
 }
 
+celix::BundleContext& celix::Framework::context() const {
+    return pimpl->frameworkContext();
+}
 
 /***********************************************************************************************************************
  * Celix 'global' functions
diff --git a/libs/registry/CMakeLists.txt b/libs/registry/CMakeLists.txt
index 5880f52..a7de533 100644
--- a/libs/registry/CMakeLists.txt
+++ b/libs/registry/CMakeLists.txt
@@ -16,10 +16,11 @@
 # under the License.
 
 add_library(celix_registry STATIC
-        src/ServiceRegistry.cc
+        src/Utils.cc
         src/Filter.cc
         src/Properties.cc
-)
+        src/ServiceRegistry.cc)
+
 target_include_directories(celix_registry PRIVATE src)
 target_include_directories(celix_registry PUBLIC include)
 target_link_libraries(celix_registry PRIVATE glog::glog)
diff --git a/libs/registry/gtest/CMakeLists.txt b/libs/registry/gtest/CMakeLists.txt
index b534c50..88a8b87 100644
--- a/libs/registry/gtest/CMakeLists.txt
+++ b/libs/registry/gtest/CMakeLists.txt
@@ -17,8 +17,9 @@
 
 set(SOURCES
         src/main.cc
-        src/Registry_tests.cc
+        src/Utils_tests.cc
         src/Filter_tests.cc
+        src/Registry_tests.cc
         src/ServiceTracking_tests.cc
         src/RegistryConcurrency_tests.cc
 )
diff --git a/libs/registry/gtest/src/Registry_tests.cc b/libs/registry/gtest/src/Registry_tests.cc
index d8fad0e..49941ea 100644
--- a/libs/registry/gtest/src/Registry_tests.cc
+++ b/libs/registry/gtest/src/Registry_tests.cc
@@ -180,7 +180,7 @@ TEST_F(RegistryTest, UseServices) {
         EXPECT_EQ(&svc, &intf1);
         long id = celix::getProperty(props, celix::SERVICE_ID, 0);
         EXPECT_EQ(svcId1, id);
-        EXPECT_EQ(0, bnd.id()); //not nullptr -> use empty bundle (bndId 0)
+        EXPECT_EQ(LONG_MAX, bnd.id()); //not nullptr -> use empty bundle (bndId 0)
     });
     EXPECT_TRUE(called);
 }
diff --git a/libs/registry/gtest/src/Utils_tests.cc b/libs/registry/gtest/src/Utils_tests.cc
new file mode 100644
index 0000000..3994109
--- /dev/null
+++ b/libs/registry/gtest/src/Utils_tests.cc
@@ -0,0 +1,56 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "gtest/gtest.h"
+
+#include "celix/Utils.h"
+
+class UtilsTest : public ::testing::Test {
+public:
+    UtilsTest() {}
+    ~UtilsTest(){}
+};
+
+class MarkerInterface;
+
+namespace example {
+    class MarkerInterface;
+}
+
+class SvcWithFqn {
+    static constexpr const char * const FQN = "SvcWithFqn[Version 1]";
+};
+
+TEST_F(UtilsTest, svcName) {
+    std::string name = celix::serviceName<MarkerInterface>();
+    EXPECT_EQ("MarkerInterface", name);
+
+    name = celix::serviceName<example::MarkerInterface>();
+    EXPECT_EQ("example::MarkerInterface", name);
+
+    name = celix::serviceName<SvcWithFqn>();
+    //TODO EXPECT_EQ("SvcWithFqn[Version 1]", name);
+
+    name = celix::functionServiceName<std::function<void()>>("do");
+    EXPECT_EQ("do[std::function<void()>]", name);
+
+
+    name = celix::functionServiceName<std::function<std::vector<std::vector<long>>(long, int, std::vector<double>)>>("collect");
+    //TODO EXPECT_EQ("collect[std::function<std::vector<std::vector<long>>(long, int, std::vector<double>)>]", name);
+}
\ No newline at end of file
diff --git a/libs/registry/include/celix/Constants.h b/libs/registry/include/celix/Constants.h
index 517a372..96f6326 100644
--- a/libs/registry/include/celix/Constants.h
+++ b/libs/registry/include/celix/Constants.h
@@ -31,14 +31,14 @@ namespace celix {
 
     static constexpr const char *const FRAMEWORK_UUID = "framework.uuid";
 
-    static constexpr const char *const CXX_LANG = "C++";
-    static constexpr const char *const C_LANG = "C";
-
+    static constexpr const char *const C_AND_CXX_LANG_REG = "C/C++";
 
     static constexpr const char *const MANIFEST_BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName";
     static constexpr const char *const MANIFEST_BUNDLE_NAME = "Bundle-Name";
     static constexpr const char *const MANIFEST_BUNDLE_VERSION = "Bundle-Version";
     static constexpr const char *const MANIFEST_BUNDLE_GROUP = "Bundle-Group";
+
+    static constexpr long FRAMEWORK_BUNDLE_ID = 1L;
 }
 
 #endif //CXX_CELIX_CONSTANTS_H
diff --git a/libs/registry/include/celix/ServiceRegistry.h b/libs/registry/include/celix/ServiceRegistry.h
index 76b277d..c9a9a8e 100644
--- a/libs/registry/include/celix/ServiceRegistry.h
+++ b/libs/registry/include/celix/ServiceRegistry.h
@@ -145,10 +145,29 @@ namespace celix {
         }
 
         template<typename F>
-        celix::ServiceRegistration registerFunctionService(const std::string &functionName, F&& func, celix::Properties props = {}, std::shared_ptr<const celix::IResourceBundle> owner = {});
+        celix::ServiceRegistration registerFunctionService(
+                const std::string &functionName,
+                F&& func, celix::Properties props = {},
+                std::shared_ptr<const celix::IResourceBundle> owner = {});
 
         template<typename I>
-        celix::ServiceRegistration registerServiceFactory(std::shared_ptr<celix::IServiceFactory<I>> factory, celix::Properties props = {}, std::shared_ptr<const celix::IResourceBundle> owner = {});
+        celix::ServiceRegistration registerServiceFactory(
+                std::shared_ptr<celix::IServiceFactory<I>> factory,
+                celix::Properties props = {},
+                std::shared_ptr<const celix::IResourceBundle> owner = {}) {
+            auto svcName = celix::serviceName<I>();
+            return registerServiceFactory(svcName, std::move(factory), std::move(props), std::move(owner));
+        }
+
+        template<typename F>
+        celix::ServiceRegistration registerFunctionServiceFactory(
+                const std::string &functionName,
+                std::shared_ptr<celix::IServiceFactory<F>> factory,
+                celix::Properties props = {},
+                std::shared_ptr<const celix::IResourceBundle> owner = {}) {
+            auto svcName = celix::functionServiceName<F>(functionName);
+            return registerServiceFactory(svcName, std::move(factory), std::move(props), std::move(owner));
+        }
 
         template<typename I>
         //NOTE C++17 typename std::enable_if<!std::is_callable<I>::value, long>::type
@@ -160,7 +179,7 @@ namespace celix {
         template<typename I>
         //NOTE C++17 typename std::enable_if<std::is_callable<I>::value, long>::type
         long findFunctionService(const std::string &functionName, const std::string &filter = "") const {
-            auto services = findFunctionService<I>(functionName, filter);
+            auto services = findFunctionServices<I>(functionName, filter);
             return services.size() > 0 ? services[0] : -1L;
         }
 
@@ -190,8 +209,6 @@ namespace celix {
             return trackServices<F>(svcName, std::move(options), std::move(requester));
         }
 
-        //TODO trackTrackers
-
         template<typename I>
         int useServices(std::function<void(I& svc)> use, const std::string &filter = "", std::shared_ptr<const celix::IResourceBundle> requester = {}) const {
             auto svcName = celix::serviceName<I>();
@@ -338,8 +355,18 @@ namespace celix {
         std::unique_ptr<celix::ServiceRegistry::Impl> pimpl;
 
         //register services
-        celix::ServiceRegistration registerService(std::string svcName, std::shared_ptr<void> svc, celix::Properties props, std::shared_ptr<const celix::IResourceBundle> owner);
-        celix::ServiceRegistration registerServiceFactory(std::string svcName, std::shared_ptr<celix::IServiceFactory<void>> factory, celix::Properties props, std::shared_ptr<const celix::IResourceBundle> owner);
+        celix::ServiceRegistration registerService(
+                std::string svcName,
+                std::shared_ptr<void> svc,
+                celix::Properties props,
+                std::shared_ptr<const celix::IResourceBundle> owner);
+
+        template<typename I>
+        celix::ServiceRegistration registerServiceFactory(
+                std::string svcName,
+                std::shared_ptr<celix::IServiceFactory<I>> factory,
+                celix::Properties props,
+                std::shared_ptr<const celix::IResourceBundle> owner);
 
         //use Services
         template<typename I>
@@ -351,6 +378,8 @@ namespace celix {
                 const std::string &filter,
                 std::shared_ptr<const celix::IResourceBundle> requester) const;
 
+        celix::ServiceRegistration registerServiceFactory(std::string svcName, std::shared_ptr<celix::IServiceFactory<void>> factory, celix::Properties props, std::shared_ptr<const celix::IResourceBundle> owner);
+
         template<typename I>
         bool useService(
                 const std::string &svcName,
@@ -394,9 +423,7 @@ inline celix::ServiceRegistration celix::ServiceRegistry::registerFunctionServic
 }
 
 template<typename I>
-inline celix::ServiceRegistration celix::ServiceRegistry::registerServiceFactory(std::shared_ptr<celix::IServiceFactory<I>> factory, celix::Properties props, std::shared_ptr<const celix::IResourceBundle> owner) {
-    std::string svcName = celix::serviceName<I>();
-
+inline celix::ServiceRegistration celix::ServiceRegistry::registerServiceFactory(std::string svcName, std::shared_ptr<celix::IServiceFactory<I>> factory, celix::Properties props, std::shared_ptr<const celix::IResourceBundle> owner) {
     class VoidServiceFactory : public celix::IServiceFactory<void> {
     public:
         VoidServiceFactory(std::shared_ptr<celix::IServiceFactory<I>> _factory) : factory{std::move(_factory)} {}
diff --git a/libs/registry/include/celix/Utils.h b/libs/registry/include/celix/Utils.h
index 5640636..09d674d 100644
--- a/libs/registry/include/celix/Utils.h
+++ b/libs/registry/include/celix/Utils.h
@@ -24,29 +24,20 @@
 #include <string>
 #include <iostream>
 
+namespace celix {
+namespace impl {
+    void assertIsNotFunctionService(const std::string &svcName);
+    std::string typeNameFromPrettyFunction(const std::string &templateName, const std::string &pretty);
+}
+}
+
 namespace {
 
     template<typename INTERFACE_TYPENAME>
     std::string typeName() {
-        std::string result;
-
-        const char *templateStr = "INTERFACE_TYPENAME = ";
-        const size_t templateStrLen = strlen(templateStr);
-
-        result = __PRETTY_FUNCTION__; //USING pretty function to retrieve the filled in template argument without using typeid()
-        size_t bpos = result.find(templateStr) + templateStrLen; //find begin pos after INTERFACE_TYPENAME = entry
-        size_t epos = bpos;
-        while (isalnum(result[epos]) || result[epos] == '_' || result[epos] == ':' || result[epos] == ' ' || result[epos] == '*' || result[epos] == '&' || result[epos] == '<' || result[epos] == '>') {
-            epos += 1;
-        }
-        size_t len = epos - bpos;
-        result = result.substr(bpos, len);
-
-        if (result.empty()) {
-            std::cerr << "Cannot infer type name in function call '" << __PRETTY_FUNCTION__ << "'\n'";
-        }
-
-        return result;
+        static const std::string templateStr = "INTERFACE_TYPENAME = ";
+        std::string pretty = __PRETTY_FUNCTION__;
+        return celix::impl::typeNameFromPrettyFunction(templateStr, __PRETTY_FUNCTION__);
     }
 
     template<typename Arg>
@@ -60,13 +51,13 @@ namespace {
     }
 
     template<typename R>
-    std::string functionName(const std::string &funcName) {
-        return funcName + " [std::function<" + typeName<R>() + "()>]";
+    std::string functionName() {
+        return "std::function<" + typeName<R>() + "()>";
     }
 
     template<typename R, typename Arg1, typename... Args>
-    std::string functionName(const std::string &funcName) {
-        return funcName + " [std::function<" + typeName<R>() + "("  + argName<Arg1, Args...>() + ")>]";
+    std::string functionName() {
+        return "std::function<" + typeName<R>() + "("  + argName<Arg1, Args...>() + ")>";
     }
 };
 
@@ -85,9 +76,13 @@ namespace celix {
     template<typename I>
     //NOTE C++17 typename std::enable_if<!std::is_callable<I>::value, std::string>::type
     std::string serviceName() {
-        return typeName<I>();
+        std::string svcName = typeName<I>();
+        celix::impl::assertIsNotFunctionService(svcName);
+        return svcName;
     }
 
+    //TODO resolve FQN for Function Service.
+
     /**
     * Returns the service name for a std::function I.
     * Note that for a std::function the additional function name is needed to get a fully qualified service name;
@@ -95,7 +90,8 @@ namespace celix {
     template<typename F>
     //NOTE C++17 typename std::enable_if<std::is_callable<I>::value, std::string>::type
     std::string functionServiceName(const std::string &fName) {
-        return functionName<decltype(&F::operator())>(fName);
+        std::string func = functionName<decltype(&F::operator())>();
+        return fName + "[" + func + "]";
     }
 }
 
diff --git a/libs/registry/src/ServiceRegistry.cc b/libs/registry/src/ServiceRegistry.cc
index 58d5778..6ed83f7 100644
--- a/libs/registry/src/ServiceRegistry.cc
+++ b/libs/registry/src/ServiceRegistry.cc
@@ -40,7 +40,11 @@ namespace {
     public:
         ~EmptyBundle() override = default;
 
-        long id() const noexcept override { return 0; }
+        long id() const noexcept override {
+            //TODO not sure what todo. 1 is reserved for the framework and I would like to keep <= 0 as invalid, so
+            //that default initialized long are not a valid bundle / svc id.
+            return LONG_MAX;
+        }
 
         const std::string& cacheRoot() const noexcept override {
             static std::string empty{};
@@ -94,7 +98,11 @@ namespace {
 
         void decrUsage() const {
             std::lock_guard<std::mutex> lck{mutex};
-            usage -= 1;
+            if (usage == 0) {
+                LOG(ERROR) << "Usage count decrease below 0!" << std::endl;
+            } else {
+                usage -= 1;
+            }
             cond.notify_all();
         }
 
@@ -298,7 +306,11 @@ namespace {
 
         void decrUsage() const {
             std::lock_guard<std::mutex> lck{mutex};
-            usage -= 1;
+            if (usage == 0) {
+                LOG(ERROR) << "Usage count decrease below 0!" << std::endl;
+            } else {
+                usage -= 1;
+            }
             cond.notify_all();
         }
 
@@ -516,8 +528,8 @@ public:
 
 
 celix::ServiceRegistry::ServiceRegistry(std::string name) : pimpl{new ServiceRegistry::Impl{std::move(name)}} {}
-celix::ServiceRegistry::ServiceRegistry(celix::ServiceRegistry &&rhs) = default;
-celix::ServiceRegistry& celix::ServiceRegistry::operator=(celix::ServiceRegistry &&rhs) = default;
+celix::ServiceRegistry::ServiceRegistry(celix::ServiceRegistry &&) = default;
+celix::ServiceRegistry& celix::ServiceRegistry::operator=(celix::ServiceRegistry &&) = default;
 celix::ServiceRegistry::~ServiceRegistry() {
     if (pimpl) {
         //TODO
@@ -637,6 +649,7 @@ int celix::ServiceRegistry::useAnyServices(const std::string &svcName,
                                                               const celix::IResourceBundle &bnd)> use,
                                            const std::string &f,
                                            std::shared_ptr<const celix::IResourceBundle> requester) const {
+
     celix::Filter filter = f;
     if (!filter.valid()) {
         LOG(WARNING) << "Invalid filter (" << f << ") provided. Cannot find services" << std::endl;
@@ -664,18 +677,19 @@ int celix::ServiceRegistry::useAnyServices(const std::string &svcName,
             entry->decrUsage();
         }};
         use(svc, entry->props, *entry->owner);
-        entry->decrUsage();
     }
 
     return (int)matches.size();
 }
 
 //TODO move to Impl
-bool celix::ServiceRegistry::useAnyService(const std::string &svcName,
-                                           std::function<void(std::shared_ptr<void> svc, const celix::Properties &props,
-                                                              const celix::IResourceBundle &bnd)> use,
-                                           const std::string &f,
-                                           std::shared_ptr<const celix::IResourceBundle> requester) const {
+bool celix::ServiceRegistry::useAnyService(
+        const std::string &svcName,
+        std::function<void(std::shared_ptr<void> svc, const celix::Properties &props,
+                const celix::IResourceBundle &bnd)> use,
+                const std::string &f,
+                std::shared_ptr<const celix::IResourceBundle> requester) const {
+
     celix::Filter filter = f;
     if (!filter.valid()) {
         LOG(WARNING) << "Invalid filter (" << f << ") provided. Cannot find services" << std::endl;
@@ -720,8 +734,8 @@ std::vector<std::string> celix::ServiceRegistry::listAllRegisteredServiceNames()
 celix::ServiceRegistration::ServiceRegistration() : pimpl{nullptr} {}
 
 celix::ServiceRegistration::ServiceRegistration(celix::ServiceRegistration::Impl *impl) : pimpl{impl} {}
-celix::ServiceRegistration::ServiceRegistration(celix::ServiceRegistration &&rhs) noexcept = default;
-celix::ServiceRegistration& celix::ServiceRegistration::operator=(celix::ServiceRegistration &&rhs) noexcept = default;
+celix::ServiceRegistration::ServiceRegistration(celix::ServiceRegistration &&) noexcept = default;
+celix::ServiceRegistration& celix::ServiceRegistration::operator=(celix::ServiceRegistration &&) noexcept = default;
 celix::ServiceRegistration::~ServiceRegistration() { unregister(); }
 
 long celix::ServiceRegistration::serviceId() const { return pimpl ? pimpl->entry->svcId : -1L; }
@@ -774,8 +788,8 @@ void celix::ServiceTracker::stop() {
     }
 }
 
-celix::ServiceTracker::ServiceTracker(celix::ServiceTracker &&rhs) noexcept = default;
-celix::ServiceTracker& celix::ServiceTracker::operator=(celix::ServiceTracker &&rhs) noexcept = default;
+celix::ServiceTracker::ServiceTracker(celix::ServiceTracker &&) noexcept = default;
+celix::ServiceTracker& celix::ServiceTracker::operator=(celix::ServiceTracker &&) noexcept = default;
 
 int celix::ServiceTracker::trackCount() const { return pimpl ? pimpl->entry->count() : 0; }
 const std::string& celix::ServiceTracker::serviceName() const { return pimpl? pimpl->entry->svcName : emptyString; }
diff --git a/libs/registry/src/Utils.cc b/libs/registry/src/Utils.cc
new file mode 100644
index 0000000..27feccb
--- /dev/null
+++ b/libs/registry/src/Utils.cc
@@ -0,0 +1,51 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#include "celix/Utils.h"
+
+#include <string>
+
+#include <glog/logging.h>
+
+void celix::impl::assertIsNotFunctionService(const std::string &svcName) {
+    size_t pos = svcName.find("::function"); //note could be std::fuction or st::__1::function, etc?
+    if (pos <= svcName.size()) {
+        //match
+        LOG(WARNING) << "Unexpected std::function as template argument. For function use the find/use/trackFunctionService instead of find/use/trackService!" << std::endl;
+        assert(false);
+    }
+}
+
+std::string celix::impl::typeNameFromPrettyFunction(const std::string &templateName, const std::string &prettyFunction) {
+    std::string result = prettyFunction; //USING pretty function to retrieve the filled in template argument without using typeid()
+    size_t bpos = result.find(templateName) + templateName.size(); //find begin pos after INTERFACE_TYPENAME = entry
+    size_t epos = bpos;
+    while (isalnum(result[epos]) || result[epos] == '_' || result[epos] == ':' || result[epos] == '*' || result[epos] == '&' || result[epos] == '<' || result[epos] == '>') {
+    epos += 1;
+    }
+    size_t len = epos - bpos;
+    result = result.substr(bpos, len);
+
+    if (result.empty()) {
+        LOG(WARNING) << "Cannot infer type name in function call '" << prettyFunction << "'\n'";
+    }
+
+    return result;
+}
+


[celix] 16/22: CELIX-438: Reanables the c bundles, libs and examples.

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit f378f179989700a5de1769078d13272abbcbb765
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Mon Jan 7 11:59:43 2019 +0100

    CELIX-438: Reanables the c bundles, libs and examples.
---
 .travis.yml                  |  6 +++++-
 CMakeLists.txt               | 10 +++++-----
 bundles/CMakeLists.txt       | 14 +++++++-------
 bundles/shell/CMakeLists.txt |  8 ++++----
 libs/CMakeLists.txt          | 14 +++++++-------
 5 files changed, 28 insertions(+), 24 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 843e946..eb92e78 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -44,7 +44,11 @@ before_install:
   - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update && brew install lcov libffi zeromq czmq glog cpputest jansson && brew link --force libffi; fi
 
 before_script:
-    - mkdir build install
+  - wget https://github.com/cpputest/cpputest/releases/download/v3.8/cpputest-3.8.tar.gz -O /tmp/cpputest.tar.gz
+  - tar -xzvf /tmp/cpputest.tar.gz -C /tmp
+  - if [ "$CC" = "clang" ]; then export CXX="clang++"; fi && cd /tmp/cpputest-* && ./configure --prefix=/usr/local && make && sudo make install && cd -
+  - cd /tmp/cpputest-* && ./configure --prefix=/usr/local && make && sudo make install && cd -
+  - mkdir build install
     - export BUILD_OPTIONS=" \
         -DBUILD_RSA_REMOTE_SERVICE_ADMIN_DFI=ON \
         -DBUILD_DEPLOYMENT_ADMIN=ON \
diff --git a/CMakeLists.txt b/CMakeLists.txt
index f1807f7..669cc43 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -71,15 +71,15 @@ add_subdirectory(libs)
 add_subdirectory(bundles)
 
 #Example as last, because some example will check if underlining options are enabled
-#TODO add_subdirectory(examples/celix-examples examples)
+add_subdirectory(examples/celix-examples examples)
 
 #export targets
-#install(EXPORT celix NAMESPACE Celix:: DESTINATION share/celix/cmake FILE Targets.cmake COMPONENT cmake)
-#install_celix_targets(celix NAMESPACE Celix:: DESTINATION share/celix/cmake FILE CelixTargets.cmake COMPONENT cmake)
+install(EXPORT celix NAMESPACE Celix:: DESTINATION share/celix/cmake FILE Targets.cmake COMPONENT cmake)
+install_celix_targets(celix NAMESPACE Celix:: DESTINATION share/celix/cmake FILE CelixTargets.cmake COMPONENT cmake)
 
 #install celix cmake modules
-#install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/Modules/ DESTINATION share/celix/cmake/Modules)
-#install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/cmake_celix/ DESTINATION share/celix/cmake/cmake_celix)
+install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/Modules/ DESTINATION share/celix/cmake/Modules)
+install(DIRECTORY ${CMAKE_SOURCE_DIR}/cmake/cmake_celix/ DESTINATION share/celix/cmake/cmake_celix)
 
 #configure and install CelixConfig and CelixConfigVersion files
 configure_file(cmake/CelixConfigVersion.cmake.in
diff --git a/bundles/CMakeLists.txt b/bundles/CMakeLists.txt
index 847b1f0..5ed4054 100644
--- a/bundles/CMakeLists.txt
+++ b/bundles/CMakeLists.txt
@@ -15,11 +15,11 @@
 # specific language governing permissions and limitations
 # under the License.
 
-#add_subdirectory(config_admin)
-#add_subdirectory(device_access)
-#add_subdirectory(deployment_admin)
-#add_subdirectory(remote_services)
+add_subdirectory(config_admin)
+add_subdirectory(device_access)
+add_subdirectory(deployment_admin)
+add_subdirectory(remote_services)
 add_subdirectory(shell)
-#add_subdirectory(log_writer)
-#add_subdirectory(log_service)
-#add_subdirectory(pubsub)
\ No newline at end of file
+add_subdirectory(log_writer)
+add_subdirectory(log_service)
+add_subdirectory(pubsub)
\ No newline at end of file
diff --git a/bundles/shell/CMakeLists.txt b/bundles/shell/CMakeLists.txt
index c3d0196..851d601 100644
--- a/bundles/shell/CMakeLists.txt
+++ b/bundles/shell/CMakeLists.txt
@@ -15,10 +15,10 @@
 # specific language governing permissions and limitations
 # under the License.
 
-#add_subdirectory(shell)
-#add_subdirectory(remote_shell)
-#add_subdirectory(shell_bonjour)
-#add_subdirectory(shell_tui)
+add_subdirectory(shell)
+add_subdirectory(remote_shell)
+add_subdirectory(shell_bonjour)
+add_subdirectory(shell_tui)
 
 add_subdirectory(cxx_shell)
 add_subdirectory(cxx_shell_tui)
diff --git a/libs/CMakeLists.txt b/libs/CMakeLists.txt
index c811b70..7188fcd 100644
--- a/libs/CMakeLists.txt
+++ b/libs/CMakeLists.txt
@@ -17,19 +17,19 @@
 
 #utils, dfi and etcdlib are standalone
 #(e.g. no dependency on celix framework
-#add_subdirectory(utils)
-#add_subdirectory(dfi)
-#add_subdirectory(etcdlib)
+add_subdirectory(utils)
+add_subdirectory(dfi)
+add_subdirectory(etcdlib)
 
-#add_subdirectory(framework)
+add_subdirectory(framework)
 
 #C++ stuff
 add_subdirectory(registry)
 add_subdirectory(framework_cxx)
 
 #launcher
-#add_subdirectory(launcher)
+add_subdirectory(launcher)
 
 #add_subdirectory(event_admin)# event_admin is unstable
-#add_subdirectory(dependency_manager)
-#add_subdirectory(dependency_manager_cxx)
\ No newline at end of file
+add_subdirectory(dependency_manager)
+add_subdirectory(dependency_manager_cxx)
\ No newline at end of file


[celix] 22/22: CELIX-458: Updates travis config to install libzip

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 807b88b5bb166e253dc1c517326d2865bc60584f
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Mon Jan 7 20:52:12 2019 +0100

    CELIX-458: Updates travis config to install libzip
---
 .travis.yml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index ead5d89..e4774d9 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -40,8 +40,8 @@ matrix:
 
 before_install:
   - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq; fi
-  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install -qq uuid-dev libxml2-dev lcov libffi-dev libczmq-dev libcpputest-dev libjansson-dev; fi
-  - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update && brew install lcov libffi zeromq czmq glog cpputest jansson && brew link --force libffi; fi
+  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get install -qq uuid-dev libxml2-dev lcov libffi-dev libczmq-dev libcpputest-dev libjansson-dev libzip-dev; fi
+  - if [ "$TRAVIS_OS_NAME" = "osx" ]; then brew update && brew install lcov libffi zeromq czmq glog cpputest jansson libzip && brew link --force libffi; fi
 
 before_script:
     - mkdir build install


[celix] 09/22: CELIX-438; Adds CppuTest as external cmake project

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit e4dab3190b04ae0f99b5e965247087360582736d
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Sat Jan 5 13:54:55 2019 +0100

    CELIX-438; Adds CppuTest as external cmake project
---
 CMakeLists.txt                        |  1 +
 cmake/celix_project/AddCppUTest.cmake | 46 +++++++++++++++++++++++++++++++++++
 cmake/celix_project/AddGLog.cmake     |  2 +-
 cmake/celix_project/AddLibzip.cmake   |  2 +-
 libs/dfi/CMakeLists.txt               |  4 +--
 libs/utils/CMakeLists.txt             |  2 +-
 6 files changed, 52 insertions(+), 5 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8d0b790..968e74c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -56,6 +56,7 @@ option(ENABLE_TESTING "Enables unit testing" ON)
 if (ENABLE_TESTING)
 	enable_testing()
     include(cmake/celix_project/AddGTest.cmake)
+    include(cmake/celix_project/AddCppUTest.cmake)
 endif ()
 include(cmake/celix_project/AddGLog.cmake)
 include(cmake/celix_project/AddLibzip.cmake)
diff --git a/cmake/celix_project/AddCppUTest.cmake b/cmake/celix_project/AddCppUTest.cmake
new file mode 100644
index 0000000..f989e73
--- /dev/null
+++ b/cmake/celix_project/AddCppUTest.cmake
@@ -0,0 +1,46 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements.  See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership.  The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License.  You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied.  See the License for the
+# specific language governing permissions and limitations
+# under the License.
+
+include(ExternalProject)
+ExternalProject_Add(
+        cpputest_project
+        GIT_REPOSITORY https://github.com/cpputest/cpputest.git
+        GIT_TAG v3.8
+        UPDATE_DISCONNECTED TRUE
+        PREFIX ${CMAKE_BINARY_DIR}/cpputest
+        CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/cpputest
+)
+
+file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/cpputest/include)
+
+set(CPPUTEST_LIBRARY cpputest::cpputest)
+set(CPPUTEST_EXT_LIBRARY cpputest::ext)
+set(CPPUTEST_INCLUDE_DIR ${binary_dir}/cpputest)
+
+add_library(cpputest::cpputest IMPORTED STATIC GLOBAL)
+add_dependencies(cpputest::cpputest cpputest_project)
+set_target_properties(cpputest::cpputest PROPERTIES
+        IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/cpputest/lib/libCppUTest.a"
+        INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_BINARY_DIR}/cpputest/include"
+)
+
+add_library(cpputest::ext IMPORTED STATIC GLOBAL)
+add_dependencies(cpputest::ext cpputest_project)
+set_target_properties(cpputest::ext PROPERTIES
+        IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/cpputest/lib/libCppUTestExt.a"
+        INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_BINARY_DIR}/cpputest/include"
+)
diff --git a/cmake/celix_project/AddGLog.cmake b/cmake/celix_project/AddGLog.cmake
index df0f3ab..fe0137f 100644
--- a/cmake/celix_project/AddGLog.cmake
+++ b/cmake/celix_project/AddGLog.cmake
@@ -26,7 +26,7 @@ ExternalProject_Add(
         CMAKE_ARGS -DWITH_GFLAGS=OFF -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/glog -DCMAKE_CXX_FLAGS=-w
 )
 
-file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/glog/include/dummy.txt CONTENT "//Dummy file to ensure the include dir exists")
+file(MAKE_DIRECTORY ${source_dir}/glog/include)
 
 add_library(glog::glog IMPORTED STATIC GLOBAL)
 add_dependencies(glog::glog googlelog_project)
diff --git a/cmake/celix_project/AddLibzip.cmake b/cmake/celix_project/AddLibzip.cmake
index aec4be7..19f8f15 100644
--- a/cmake/celix_project/AddLibzip.cmake
+++ b/cmake/celix_project/AddLibzip.cmake
@@ -25,7 +25,7 @@ ExternalProject_Add(
         CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/libzip -DCMAKE_C_FLAGS=-fPIC -DBUILD_SHARED_LIBS=OFF -DENABLE_COMMONCRYPTO=OFF -DENABLE_GNUTLS=OFF -DENABLE_OPENSSL=OFF -Wno-dev
 )
 
-file(GENERATE OUTPUT ${CMAKE_BINARY_DIR}/libzip/include/dummy.txt CONTENT "//Dummy file to ensure the include dir exists")
+file(MAKE_DIRECTORY ${source_dir}/libzip/include)
 
 add_library(libzip::libzip IMPORTED STATIC GLOBAL)
 add_dependencies(libzip::libzip libzip_project)
diff --git a/libs/dfi/CMakeLists.txt b/libs/dfi/CMakeLists.txt
index 4da08b0..4451ff7 100644
--- a/libs/dfi/CMakeLists.txt
+++ b/libs/dfi/CMakeLists.txt
@@ -65,8 +65,8 @@ if (ENABLE_TESTING)
 		test/json_rpc_tests.cpp
 		test/run_tests.cpp
 	)
-	target_link_libraries(test_dfi PRIVATE Celix::dfi Celix::utils ${FFI_LIBRARIES} ${CPPUTEST_LIBRARY})
-	target_include_directories(test_dfi PRIVATE ${FFI_INCLUDE_DIRS})
+	target_link_libraries(test_dfi PRIVATE Celix::dfi Celix::utils ${FFI_LIBRARIES} ${CPPUTEST_LIBRARY} ${JANSSON_LIBRARY})
+	target_include_directories(test_dfi PRIVATE ${FFI_INCLUDE_DIRS} ${JANSSON_INCLUDE_DIRS})
 
     file(COPY ${CMAKE_CURRENT_LIST_DIR}/test/schemas DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
     file(COPY ${CMAKE_CURRENT_LIST_DIR}/test/descriptors DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
diff --git a/libs/utils/CMakeLists.txt b/libs/utils/CMakeLists.txt
index 5f211bf..e0afe41 100644
--- a/libs/utils/CMakeLists.txt
+++ b/libs/utils/CMakeLists.txt
@@ -71,7 +71,7 @@ add_library(Celix::utils ALIAS utils)
 
 celix_subproject(UTILS-TESTS "Option to build the utilities library tests" "OFF")
 if (ENABLE_TESTING AND UTILS-TESTS)
-    find_package(CppUTest REQUIRED)
+    #find_package(CppUTest REQUIRED)
 
     include_directories(SYSTEM ${CPPUTEST_INCLUDE_DIR})
     include_directories(include)


[celix] 15/22: CELIX-438: Adds some missing include statements

Posted by pn...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 795217be21ccd225ac38837dda222aa26f213c6f
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Mon Jan 7 10:26:54 2019 +0100

    CELIX-438: Adds some missing include statements
---
 bundles/shell/cxx_shell/gtest/CMakeLists.txt | 4 ++--
 cmake/celix_project/AddLibzip.cmake          | 2 +-
 libs/registry/gtest/src/Registry_tests.cc    | 1 +
 libs/registry/gtest/src/Utils_tests.cc       | 4 +++-
 libs/registry/src/ServiceRegistry.cc         | 7 +------
 5 files changed, 8 insertions(+), 10 deletions(-)

diff --git a/bundles/shell/cxx_shell/gtest/CMakeLists.txt b/bundles/shell/cxx_shell/gtest/CMakeLists.txt
index c95f364..a163eca 100644
--- a/bundles/shell/cxx_shell/gtest/CMakeLists.txt
+++ b/bundles/shell/cxx_shell/gtest/CMakeLists.txt
@@ -19,8 +19,8 @@ set(SOURCES
         src/main.cc
         src/Shell_tests.cc
 )
-add_executable(celix_shell_cxx_tests ${SOURCES})
-target_link_libraries(celix_shell_cxx_tests PRIVATE gtest celix_framework_cxx celix_cxx_shell celix_cxx_shell_api glog::glog)
+add_executable(celix_cxx_shell_tests ${SOURCES})
+target_link_libraries(celix_cxx_shell_tests PRIVATE gtest celix_framework_cxx celix_cxx_shell celix_cxx_shell_api glog::glog)
 
 add_test(NAME celix_cxx_shell_tests COMMAND celix_cxx_shell_tests)
 SETUP_TARGET_FOR_COVERAGE(celix_cxx_shell_tests_cov celix_cxx_shell_tests ${CMAKE_BINARY_DIR}/coverage/celix_cxx_shell_tests/celix_cxx_shell_tests ..)
\ No newline at end of file
diff --git a/cmake/celix_project/AddLibzip.cmake b/cmake/celix_project/AddLibzip.cmake
index 5b31a79..93ea32a 100644
--- a/cmake/celix_project/AddLibzip.cmake
+++ b/cmake/celix_project/AddLibzip.cmake
@@ -30,6 +30,6 @@ file(MAKE_DIRECTORY ${CMAKE_BINARY_DIR}/libzip/include)
 add_library(libzip::libzip IMPORTED STATIC GLOBAL)
 add_dependencies(libzip::libzip libzip_project)
 set_target_properties(libzip::libzip PROPERTIES
-        IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/libzip/lib/libzip.a"
+        IMPORTED_LOCATION "${CMAKE_BINARY_DIR}/libzip/${CMAKE_INSTALL_LIBDIR}/libzip.a"
         INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_BINARY_DIR}/libzip/include"
 )
\ No newline at end of file
diff --git a/libs/registry/gtest/src/Registry_tests.cc b/libs/registry/gtest/src/Registry_tests.cc
index 49941ea..8e371c3 100644
--- a/libs/registry/gtest/src/Registry_tests.cc
+++ b/libs/registry/gtest/src/Registry_tests.cc
@@ -20,6 +20,7 @@
 
 
 #include <memory>
+#include <climits>
 
 #include <gtest/gtest.h>
 #include <glog/logging.h>
diff --git a/libs/registry/gtest/src/Utils_tests.cc b/libs/registry/gtest/src/Utils_tests.cc
index 3994109..89c8c62 100644
--- a/libs/registry/gtest/src/Utils_tests.cc
+++ b/libs/registry/gtest/src/Utils_tests.cc
@@ -17,6 +17,8 @@
  *under the License.
  */
 
+#include <functional>
+
 #include "gtest/gtest.h"
 
 #include "celix/Utils.h"
@@ -48,7 +50,7 @@ TEST_F(UtilsTest, svcName) {
     //TODO EXPECT_EQ("SvcWithFqn[Version 1]", name);
 
     name = celix::functionServiceName<std::function<void()>>("do");
-    EXPECT_EQ("do[std::function<void()>]", name);
+    EXPECT_EQ("do [std::function<void()>]", name);
 
 
     name = celix::functionServiceName<std::function<std::vector<std::vector<long>>(long, int, std::vector<double>)>>("collect");
diff --git a/libs/registry/src/ServiceRegistry.cc b/libs/registry/src/ServiceRegistry.cc
index b809e8f..33b2bb6 100644
--- a/libs/registry/src/ServiceRegistry.cc
+++ b/libs/registry/src/ServiceRegistry.cc
@@ -24,12 +24,7 @@
 #include <set>
 #include <utility>
 #include <future>
-
-#ifndef __APPLE__
-#include <linux/limits.h>
-#else
-#include <limits.h>
-#endif
+#include <climits>
 
 #include <glog/logging.h>
 #include <assert.h>