celix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pnol...@apache.org
Subject [2/2] celix git commit: CELIX-426: Initial commit for the C++ api
Date Sun, 06 May 2018 18:45:21 GMT
CELIX-426: Initial commit for the C++ api


Project: http://git-wip-us.apache.org/repos/asf/celix/repo
Commit: http://git-wip-us.apache.org/repos/asf/celix/commit/764bd7f7
Tree: http://git-wip-us.apache.org/repos/asf/celix/tree/764bd7f7
Diff: http://git-wip-us.apache.org/repos/asf/celix/diff/764bd7f7

Branch: refs/heads/feature/CELIX-426-cxx-api
Commit: 764bd7f7a8ef2648bfbc79531d1915bb26e87aaa
Parents: debb4b1
Author: Pepijn Noltes <pepijnnoltes@gmail.com>
Authored: Sun Apr 15 21:25:20 2018 +0200
Committer: Pepijn Noltes <pepijnnoltes@gmail.com>
Committed: Sun May 6 20:43:51 2018 +0200

----------------------------------------------------------------------
 CMakeLists.txt                                  |   8 +-
 cmake/celix_project/AddGTest.cmake              |  40 +
 cmake/cmake_celix/BundlePackaging.cmake         |   9 +
 framework/CMakeLists.txt                        |   9 +-
 framework/gtest/CMakeLists.txt                  |  37 +
 framework/gtest/src/cxx_BundleContext_tests.cc  | 233 ++++++
 framework/gtest/src/cxx_Bundle_tests.cc         |  66 ++
 .../gtest/src/cxx_FrameworkFactory_tests.cc     |  54 ++
 framework/gtest/src/cxx_Framework_tests.cc      |  45 ++
 framework/gtest/src/main.cc                     |  25 +
 framework/include/bundle.h                      | 135 +---
 framework/include/bundle_context.h              |  23 +-
 framework/include/celix/Bundle.h                |  77 ++
 framework/include/celix/BundleContext.h         | 241 ++++++
 framework/include/celix/Celix.h                 |  36 +
 framework/include/celix/Constants.h             |  47 ++
 framework/include/celix/Framework.h             |  51 ++
 framework/include/celix/FrameworkFactory.h      |  66 ++
 framework/include/celix/IServiceFactory.h       |  35 +
 framework/include/celix/Properties.h            |  60 ++
 framework/include/celix/dm/Properties.h         |   5 +-
 .../include/celix/impl/BundleContextImpl.h      | 293 +++++++
 framework/include/celix/impl/BundleImpl.h       | 171 ++++
 framework/include/celix/impl/FrameworkImpl.h    | 113 +++
 framework/include/celix_api.h                   |   4 +-
 framework/include/celix_bundle.h                | 153 ++++
 framework/include/celix_constants.h             |  79 ++
 framework/include/celix_launcher.h              |   6 +-
 framework/include/constants.h                   |  61 +-
 framework/include/framework.h                   |  13 +-
 framework/include/service_reference.h           |   1 +
 framework/private/mock/bundle_context_mock.c    |   3 +-
 framework/private/mock/bundle_mock.c            |  14 +
 framework/src/BundleImpl.c                      | 771 +++++++++++++++++++
 framework/src/bundle.c                          | 723 -----------------
 framework/src/bundle_context.c                  |   4 +-
 framework/src/framework.c                       |  29 +-
 framework/src/framework_private.h               |   7 +-
 shell/CMakeLists.txt                            |   2 +-
 utils/include/celix_exports.h                   |  25 +
 40 files changed, 2811 insertions(+), 963 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/CMakeLists.txt b/CMakeLists.txt
index d534a55..0da1b5d 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -51,11 +51,15 @@ set(CELIX_MAJOR "2")
 set(CELIX_MINOR "2")
 set(CELIX_MICRO "0")
 
-option(ENABLE_TESTING "Enables unit/bundle testing" FALSE)
+option(ENABLE_TESTING "Enables unit testing using CPPUTEST" OFF)
+option(ENABLE_GTESTING "Enables unit testing using GTest" ON)
 
 if (ENABLE_TESTING)
 	enable_testing()
-endif()
+endif ()
+if (ENABLE_TESTING AND ENABLE_GTESTING)
+    include(cmake/celix_project/AddGTest.cmake)
+endif ()
 
 # Default bundle version
 set(DEFAULT_VERSION 1.0.0)

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/cmake/celix_project/AddGTest.cmake
----------------------------------------------------------------------
diff --git a/cmake/celix_project/AddGTest.cmake b/cmake/celix_project/AddGTest.cmake
new file mode 100644
index 0000000..60705ed
--- /dev/null
+++ b/cmake/celix_project/AddGTest.cmake
@@ -0,0 +1,40 @@
+# 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(
+        googletest_project
+        GIT_REPOSITORY https://github.com/google/googletest.git
+        GIT_TAG master
+        PREFIX ${CMAKE_CURRENT_BINARY_DIR}/gtest
+        INSTALL_COMMAND ""
+)
+
+ExternalProject_Get_Property(googletest_project source_dir binary_dir)
+add_library(gtest IMPORTED STATIC GLOBAL)
+add_dependencies(gtest googletest_project)
+set_target_properties(gtest PROPERTIES
+        IMPORTED_LOCATION "${binary_dir}/googlemock/gtest/libgtest.a"
+        INTERFACE_INCLUDE_DIRECTORIES "${source_dir}/googletest/include"
+)
+
+add_library(gmock IMPORTED STATIC GLOBAL)
+add_dependencies(gmock googletest_project)
+set_target_properties(gmock PROPERTIES
+        IMPORTED_LOCATION "${binary_dir}/googlemock/libgmock.a"
+        INTERFACE_INCLUDE_DIRECTORIES "${source_dir}/googlemock/include"
+)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/cmake/cmake_celix/BundlePackaging.cmake
----------------------------------------------------------------------
diff --git a/cmake/cmake_celix/BundlePackaging.cmake b/cmake/cmake_celix/BundlePackaging.cmake
index 6666d20..bc65c68 100644
--- a/cmake/cmake_celix/BundlePackaging.cmake
+++ b/cmake/cmake_celix/BundlePackaging.cmake
@@ -280,6 +280,15 @@ function(add_celix_bundle)
     celix_bundle_headers(${BUNDLE_TARGET_NAME} ${BUNDLE_HEADERS})
 endfunction()
 
+function(add_celix_bundle_dependencies)
+    list(GET ARGN 0 TARGET)
+    list(REMOVE_AT ARGN 0)
+
+    foreach(BND IN ITEMS ${ARGN})
+        add_dependencies(${TARGET} ${BND}_bundle)
+    endforeach()
+endfunction()
+
 function(bundle_export_libs)
     message(DEPRECATION "bundle_export_libs is deprecated, use celix_bundle_export_libs instead.")
     celix_bundle_export_libs(${ARGN})

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/framework/CMakeLists.txt b/framework/CMakeLists.txt
index 9f237af..cdcd044 100644
--- a/framework/CMakeLists.txt
+++ b/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/filter.c src/framework.c src/manifest.c src/ioapi.c
         src/manifest_parser.c src/miniunz.c src/module.c
@@ -72,6 +72,9 @@ 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)
@@ -145,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)
@@ -189,7 +192,7 @@ if (ENABLE_TESTING AND FRAMEWORK_TESTS)
         private/mock/dm_dependency_manager_mock.c
         src/celix_errorcodes.c
         private/mock/celix_log_mock.c
-        src/framework.c)
+            src/framework.c)
     target_link_libraries(framework_test ${CPPUTEST_LIBRARY} ${CPPUTEST_EXT_LIBRARY} ${UUID} Celix::utils pthread dl)
 
     add_executable(manifest_parser_test

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/gtest/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/framework/gtest/CMakeLists.txt b/framework/gtest/CMakeLists.txt
new file mode 100644
index 0000000..a768f3f
--- /dev/null
+++ b/framework/gtest/CMakeLists.txt
@@ -0,0 +1,37 @@
+# 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
+)
+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)
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/gtest/src/cxx_BundleContext_tests.cc
----------------------------------------------------------------------
diff --git a/framework/gtest/src/cxx_BundleContext_tests.cc b/framework/gtest/src/cxx_BundleContext_tests.cc
new file mode 100644
index 0000000..d1a6a06
--- /dev/null
+++ b/framework/gtest/src/cxx_BundleContext_tests.cc
@@ -0,0 +1,233 @@
+/**
+ *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.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))};
+    }
+
+    ~BundleContextTest(){}
+
+    celix::Framework& framework() { return *(this->fw_ptr); }
+private:
+    std::unique_ptr<celix::Framework> fw_ptr{nullptr};
+};
+
+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("test service", &svc1);
+    EXPECT_TRUE(svcId > 0);
+    ctx.unregisterService(svcId);
+
+    long svcId2 = ctx.registerCService("test service", &svc1);
+    EXPECT_TRUE(svcId2 > 0);
+    EXPECT_NE(svcId, svcId2); //new registration new id
+    ctx.unregisterService(svcId2);
+}
+
+TEST_F(BundleContextTest, UseService) {
+    struct test_svc {
+        int (*calc)(int input);
+    };
+
+    auto &ctx = this->framework().getFrameworkContext();
+
+    test_svc svc1{};
+    svc1.calc = [](int input) -> int {
+        return input * 42;
+    };
+
+    long svcId = ctx.registerCService("test service", &svc1);
+    EXPECT_TRUE(svcId > 0);
+
+
+    int result = -1;
+    std::function<void(test_svc &svc, const celix::Properties&, const celix::Bundle&)> func = [&result](test_svc &svc, const celix::Properties&, const celix::Bundle&) {
+        result = svc.calc(1);
+    };
+    ctx.useService<test_svc>(svcId, "test service", func);
+    EXPECT_EQ(result, 42);
+
+    result = -1;
+    ctx.useService<test_svc>(svcId, "test service", [&result](test_svc &svc, const celix::Properties&, const celix::Bundle&) {
+        result = svc.calc(2);
+    });
+    EXPECT_EQ(result, 84);
+
+    ctx.unregisterService(svcId);
+}
+
+TEST_F(BundleContextTest, UseServices) {
+    auto &ctx = this->framework().getFrameworkContext();
+
+    struct test_svc {
+        int (*calc)(int input);
+    };
+
+    test_svc svc{};
+    svc.calc = [](int input) -> int {
+        return input * 42;
+    };
+
+    long svcId1 = ctx.registerCService("test service", &svc);
+    EXPECT_TRUE(svcId1 > 0);
+
+    long svcId2 = ctx.registerCService("test service", &svc);
+    EXPECT_TRUE(svcId2 > 0);
+
+
+    int result = 0;
+    std::function<void(test_svc &svc, const celix::Properties&, const celix::Bundle&)> func = [&result](test_svc &svc, const celix::Properties&, const celix::Bundle&) {
+        result += svc.calc(1);
+    };
+    ctx.useServices("test service", "", "", func);
+    EXPECT_EQ(result, 84); //two times
+
+    ctx.unregisterService(svcId1);
+
+    ctx.useServices("test service", "", "", func);
+    EXPECT_EQ(result, 126); //one time
+
+    ctx.unregisterService(svcId2);
+}
+
+
+TEST_F(BundleContextTest, TrackService) {
+    auto &ctx = this->framework().getFrameworkContext();
+
+    int count = 0;
+
+    struct test_svc {
+        int (*calc)(int input);
+    };
+
+    struct test_svc *svc1 = (struct test_svc*)0x100; //no ranking
+    struct test_svc *svc2 = (struct test_svc*)0x200; //no ranking
+    struct test_svc *svc3 = (struct test_svc*)0x300; //10 ranking
+    struct test_svc *svc4 = (struct test_svc*)0x400; //5 ranking
+
+
+    auto set = [&](struct test_svc *svc, const celix::Properties &, const celix::Bundle &) {
+        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("NA", svc1);
+    long svcId2 = ctx.registerService("NA", svc2);
+
+    //starting tracker should lead to first set call
+    long trackerId = ctx.trackService<struct test_svc>("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("NA", svc3, "", 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("NA", svc4, "", 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(1, count);
+
+    count = 0;
+    ctx.installBundle("bundle1.zip", true);
+    ctx.useBundles(use);
+    EXPECT_EQ(2, count);
+};

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/gtest/src/cxx_Bundle_tests.cc
----------------------------------------------------------------------
diff --git a/framework/gtest/src/cxx_Bundle_tests.cc b/framework/gtest/src/cxx_Bundle_tests.cc
new file mode 100644
index 0000000..e7eb0d8
--- /dev/null
+++ b/framework/gtest/src/cxx_Bundle_tests.cc
@@ -0,0 +1,66 @@
+/**
+ *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.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))};
+    }
+
+    ~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

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/gtest/src/cxx_FrameworkFactory_tests.cc
----------------------------------------------------------------------
diff --git a/framework/gtest/src/cxx_FrameworkFactory_tests.cc b/framework/gtest/src/cxx_FrameworkFactory_tests.cc
new file mode 100644
index 0000000..3920efb
--- /dev/null
+++ b/framework/gtest/src/cxx_FrameworkFactory_tests.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 "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

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/gtest/src/cxx_Framework_tests.cc
----------------------------------------------------------------------
diff --git a/framework/gtest/src/cxx_Framework_tests.cc b/framework/gtest/src/cxx_Framework_tests.cc
new file mode 100644
index 0000000..c8c88b4
--- /dev/null
+++ b/framework/gtest/src/cxx_Framework_tests.cc
@@ -0,0 +1,45 @@
+/**
+ *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

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/gtest/src/main.cc
----------------------------------------------------------------------
diff --git a/framework/gtest/src/main.cc b/framework/gtest/src/main.cc
new file mode 100644
index 0000000..63b9a5b
--- /dev/null
+++ b/framework/gtest/src/main.cc
@@ -0,0 +1,25 @@
+/**
+ *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

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/include/bundle.h
----------------------------------------------------------------------
diff --git a/framework/include/bundle.h b/framework/include/bundle.h
index 9cccd0c..d33a96d 100644
--- a/framework/include/bundle.h
+++ b/framework/include/bundle.h
@@ -16,138 +16,5 @@
  *specific language governing permissions and limitations
  *under the License.
  */
-/*
- * bundle.h
- *
- *  \date       Mar 23, 2010
- *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
- *  \copyright	Apache License, Version 2.0
- */
-
-#ifndef BUNDLE_H_
-#define BUNDLE_H_
-
-#include "celix_types.h"
-
-#include "celix_errno.h"
-#include "bundle_state.h"
-#include "bundle_archive.h"
-#include "framework.h"
-#include "wire.h"
-#include "module.h"
-#include "service_reference.h"
-#include "bundle_context.h"
-#include "celix_log.h"
-#include "celix_threads.h"
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-FRAMEWORK_EXPORT celix_status_t bundle_create(bundle_pt *bundle);
-
-FRAMEWORK_EXPORT celix_status_t
-bundle_createFromArchive(bundle_pt *bundle, framework_pt framework, bundle_archive_pt archive);
-
-FRAMEWORK_EXPORT celix_status_t bundle_destroy(bundle_pt bundle);
-
-FRAMEWORK_EXPORT celix_status_t bundle_isSystemBundle(bundle_pt bundle, bool *systemBundle);
-
-FRAMEWORK_EXPORT celix_status_t bundle_getArchive(bundle_pt bundle, bundle_archive_pt *archive);
-
-FRAMEWORK_EXPORT celix_status_t bundle_getCurrentModule(bundle_pt bundle, module_pt *module);
-
-FRAMEWORK_EXPORT array_list_pt bundle_getModules(bundle_pt bundle);
-
-FRAMEWORK_EXPORT void *bundle_getHandle(bundle_pt bundle);
-
-FRAMEWORK_EXPORT void bundle_setHandle(bundle_pt bundle, void *handle);
-
-FRAMEWORK_EXPORT activator_pt bundle_getActivator(bundle_pt bundle);
-
-FRAMEWORK_EXPORT celix_status_t bundle_setActivator(bundle_pt bundle, activator_pt activator);
-
-FRAMEWORK_EXPORT celix_status_t bundle_getContext(bundle_pt bundle, bundle_context_pt *context);
-
-FRAMEWORK_EXPORT celix_status_t bundle_setContext(bundle_pt bundle, bundle_context_pt context);
-
-FRAMEWORK_EXPORT celix_status_t bundle_getEntry(bundle_pt bundle, const char *name, char **entry);
-
-FRAMEWORK_EXPORT celix_status_t bundle_start(bundle_pt bundle);
-
-FRAMEWORK_EXPORT celix_status_t bundle_startWithOptions(bundle_pt bundle, int options);
-
-FRAMEWORK_EXPORT celix_status_t bundle_update(bundle_pt bundle, const char *inputFile);
-
-FRAMEWORK_EXPORT celix_status_t bundle_stop(bundle_pt bundle);
-
-FRAMEWORK_EXPORT celix_status_t bundle_stopWithOptions(bundle_pt bundle, int options);
-
-FRAMEWORK_EXPORT celix_status_t bundle_uninstall(bundle_pt bundle);
-
-FRAMEWORK_EXPORT celix_status_t bundle_setState(bundle_pt bundle, bundle_state_e state);
-
-FRAMEWORK_EXPORT celix_status_t bundle_setPersistentStateInactive(bundle_pt bundle);
-
-FRAMEWORK_EXPORT celix_status_t bundle_setPersistentStateUninstalled(bundle_pt bundle);
-
-FRAMEWORK_EXPORT void uninstallBundle(bundle_pt bundle);
-
-FRAMEWORK_EXPORT celix_status_t bundle_revise(bundle_pt bundle, const char *location, const char *inputFile);
-
-FRAMEWORK_EXPORT celix_status_t bundle_addModule(bundle_pt bundle, module_pt module);
-
-FRAMEWORK_EXPORT celix_status_t bundle_closeModules(bundle_pt bundle);
-
-// Service Reference Functions
-FRAMEWORK_EXPORT array_list_pt getUsingBundles(service_reference_pt reference);
-
-FRAMEWORK_EXPORT int compareTo(service_reference_pt a, service_reference_pt b);
-
-FRAMEWORK_EXPORT celix_status_t bundle_getState(bundle_pt bundle, bundle_state_e *state);
-
-FRAMEWORK_EXPORT celix_status_t bundle_isLockable(bundle_pt bundle, bool *lockable);
-
-FRAMEWORK_EXPORT celix_status_t bundle_getLockingThread(bundle_pt bundle, celix_thread_t *thread);
-
-FRAMEWORK_EXPORT celix_status_t bundle_lock(bundle_pt bundle, bool *locked);
-
-FRAMEWORK_EXPORT celix_status_t bundle_unlock(bundle_pt bundle, bool *unlocked);
-
-FRAMEWORK_EXPORT celix_status_t bundle_closeAndDelete(bundle_pt bundle);
-
-FRAMEWORK_EXPORT celix_status_t bundle_close(bundle_pt bundle);
-
-FRAMEWORK_EXPORT celix_status_t bundle_refresh(bundle_pt bundle);
-
-FRAMEWORK_EXPORT celix_status_t bundle_getBundleId(bundle_pt bundle, long *id);
-
-FRAMEWORK_EXPORT celix_status_t bundle_getRegisteredServices(bundle_pt bundle, array_list_pt *list);
-
-FRAMEWORK_EXPORT celix_status_t bundle_getServicesInUse(bundle_pt bundle, array_list_pt *list);
-
-FRAMEWORK_EXPORT celix_status_t bundle_setFramework(bundle_pt bundle, framework_pt framework);
-
-FRAMEWORK_EXPORT celix_status_t bundle_getFramework(bundle_pt bundle, framework_pt *framework);
-
-FRAMEWORK_EXPORT celix_status_t bundle_getBundleLocation(bundle_pt bundle, const char **location);
-
-
-
-/**********************************************************************************************************************
- **********************************************************************************************************************
- * Updated API
- **********************************************************************************************************************
- **********************************************************************************************************************/
-
-long celix_bundle_getId(const bundle_t *bnd);
-
-celix_bundle_state_e celix_bundle_getState(const bundle_t *bnd);
-
-
-
-#ifdef __cplusplus
-}
-#endif
 
-#endif /* BUNDLE_H_ */
+#include "celix_bundle.h"

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/include/bundle_context.h
----------------------------------------------------------------------
diff --git a/framework/include/bundle_context.h b/framework/include/bundle_context.h
index 36547c4..2bc582e 100644
--- a/framework/include/bundle_context.h
+++ b/framework/include/bundle_context.h
@@ -238,7 +238,7 @@ void celix_bundleContext_unregisterService(celix_bundle_context_t *ctx, long ser
  *
  * @param ctx The bundle context.
  * @param serviceName The required service name to track
- * @param serviceVersionRange Optional the service version range to track
+ * @param versionRange Optional the service version range to track
  * @param filter Optional the LDAP filter to use
  * @param callbackHandle The data pointer, which will be used in the callbacks
  * @param set is a required callback, which will be called when a new highest ranking service is set.
@@ -247,7 +247,7 @@ void celix_bundleContext_unregisterService(celix_bundle_context_t *ctx, long ser
 long celix_bundleContext_trackService(
         celix_bundle_context_t* ctx,
         const char* serviceName,
-        const char* versioRange,
+        const char* versionRange,
         const char* filter,
         void* callbackHandle,
         void (*set)(void* handle, void* svc)
@@ -258,7 +258,7 @@ long celix_bundleContext_trackService(
  *
  * @param ctx The bundle context.
  * @param serviceName The required service name to track
- * @param serviceVersionRange Optional the service version range to track
+ * @param versionRange Optional the service version range to track
  * @param filter Optional the LDAP filter to use
  * @param callbackHandle The data pointer, which will be used in the callbacks
  * @param add is a required callback, which will be called when a service is added and initially for the existing service.
@@ -268,7 +268,7 @@ long celix_bundleContext_trackService(
 long celix_bundleContext_trackServices(
         celix_bundle_context_t* ctx,
         const char* serviceName,
-        const char* versioRange,
+        const char* versionRange,
         const char* filter,
         void* callbackHandle,
         void (*add)(void* handle, void* svc),
@@ -312,6 +312,14 @@ typedef struct celix_service_tracker_options {
 long celix_bundleContext_trackServicesWithOptions(celix_bundle_context_t *ctx, const celix_service_tracker_options_t *opts);
 
 
+//TODO find services -> list of service ids.
+celix_array_list_t* celix_bundleContext_findServices(
+        celix_bundle_context_t *ctx,
+        const char *serviceName,
+        const char *versionRange,
+        const char *filter,
+        const char *lang
+);
 
 /**
  * Get and lock the service with the provided service id
@@ -439,8 +447,6 @@ typedef struct celix_bundle_tracker_options {
      */
     void (*onStopped)(void *handle, const celix_bundle_t *bundle);
 
-    //TODO callback for on installed, resolved, uninstalled ??
-
     /**
      *
      * @param handle    The handle, contains the value of the callbackHandle.
@@ -491,16 +497,13 @@ long celix_bundleContext_trackBundles(
  * @param use               The callback which will be called for the currently started bundles.
  *                          The bundle pointers are only guaranteed to be valid during the callback.
  */
-void celix_bundleContext_useBundle(
+bool celix_bundleContext_useBundle(
         celix_bundle_context_t *ctx,
         long bundleId,
         void *callbackHandle,
         void (*use)(void *handle, const celix_bundle_t *bundle)
 );
 
-//TODO add useBundleWithState (bit wise or?)
-
-
 //TODO except framework & own bundle
 /**
  * Use the currently active (started) bundles.

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/include/celix/Bundle.h
----------------------------------------------------------------------
diff --git a/framework/include/celix/Bundle.h b/framework/include/celix/Bundle.h
new file mode 100644
index 0000000..de65e4d
--- /dev/null
+++ b/framework/include/celix/Bundle.h
@@ -0,0 +1,77 @@
+/**
+ *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 {
+    class Framework; //forward declaration
+
+    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;
+
+        //TODO make ref?
+        virtual celix::Framework* getFramework() const noexcept = 0;
+
+        virtual void start() noexcept = 0;
+
+        virtual void stop() noexcept = 0;
+
+        virtual void uninstall() noexcept = 0;
+
+    };
+
+}
+
+#include "celix/impl/BundleImpl.h"
+
+#endif //CXX_CELIX_BUNDLE_H

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/include/celix/BundleContext.h
----------------------------------------------------------------------
diff --git a/framework/include/celix/BundleContext.h b/framework/include/celix/BundleContext.h
new file mode 100644
index 0000000..4169b0a
--- /dev/null
+++ b/framework/include/celix/BundleContext.h
@@ -0,0 +1,241 @@
+/**
+ *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_BUNDLECONTEXT_H
+#define CXX_CELIX_BUNDLECONTEXT_H
+
+#include <string>
+#include <vector>
+#include <functional>
+
+#include "celix/Constants.h"
+#include "celix/Properties.h"
+#include "celix/Bundle.h"
+
+namespace celix {
+
+    class BundleContext; //forward declaration
+
+    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:
+        virtual ~BundleContext(){};
+
+        template<typename I>
+        long registerService(const std::string &serviceName, I *svc, const std::string &version = "", Properties props = {}) noexcept {
+            return this->registerServiceInternal(serviceName, svc, version, celix::Constants::SERVICE_CXX_LANG, std::move(props));
+        }
+
+        template<typename I>
+        long registerCService(const std::string &serviceName, I *svc, const std::string &version = "", Properties props = {}) noexcept {
+            return this->registerServiceInternal(serviceName, svc, version, celix::Constants::SERVICE_C_LANG, std::move(props));
+        }
+
+        template<typename I>
+        long registerServiceForLang(const std::string &serviceName, I *svc, const std::string &version = "", const std::string &lang = celix::Constants::SERVICE_C_LANG, Properties props = {}) noexcept {
+            return this->registerServiceInternal(serviceName, svc, version, lang, std::move(props));
+        }
+
+        //TODO register std::function ?
+
+        virtual void unregisterService(long serviceId) noexcept = 0;
+
+        //register service factory
+
+        /**
+        * 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 ctx The bundle context.
+        * @param serviceName The required service name to track
+        * @param serviceVersionRange Optional the service version range to track. Can be empty ("")
+        * @param filter Optional the LDAP filter to use. Can be empty ("")
+        * @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,
+                const std::string &versionRange,
+                const std::string &filter,
+                std::function<void(I *svc, const celix::Properties& props, const celix::Bundle &bnd)> set
+        ) noexcept {
+            return this->trackServiceInternal(serviceName, versionRange, filter, [set](void *voidSvc, const celix::Properties& props, const celix::Bundle &bnd) {
+                I* typedSvc = static_cast<I*>(voidSvc);
+                set(typedSvc, props, bnd);
+            });
+        }
+
+        /**
+         * track services for the provided serviceName and/or filter.
+         *
+         * @param ctx The bundle context.
+         * @param serviceName The required service name to track
+         * @param serviceVersionRange Optional the service version range to track
+         * @param filter Optional the LDAP filter to use
+         * @param callbackHandle The data pointer, which will be used in the callbacks
+         * @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,
+                const std::string &versionRange,
+                const std::string &filter,
+                std::function<void(I *svc, const celix::Properties& props, const celix::Bundle &bnd)> add,
+                std::function<void(I *svc, const celix::Properties& props, const celix::Bundle &bnd)> remove
+        ) noexcept {
+            return this->trackServicesInternal(serviceName, versionRange, filter,
+                                               [add](void *voidSvc, const celix::Properties& props, const celix::Bundle &bnd) {
+                                                   I *typedSvc = static_cast<I *>(voidSvc);
+                                                   add(typedSvc, props, bnd);
+                                               },
+                                               [remove](void *voidSvc, const celix::Properties& props, const celix::Bundle &bnd) {
+                                                   I *typedSvc = static_cast<I *>(voidSvc);
+                                                   remove(typedSvc, props, bnd);
+                                               }
+            );
+        }
+
+        //TODO make add / remove service refs??
+        //TODO missing lang for track services
+
+        /**
+         * Note use fucntion by const reference. Only used during the call.
+         * @param serviceId
+         * @param I
+         * @return
+         */
+        template<typename I>
+        bool useService(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{")"};
+            return this->useService<I>(serviceName, "", filter, use);
+        }
+
+        template<typename I>
+        bool useService(const std::string &serviceName, const std::string &versionRange, const std::string &filter, const std::function<void(I &svc, const celix::Properties &props, const celix::Bundle &svcOwner)> &use) noexcept {
+            return this->useServiceInternal(serviceName, versionRange, filter, [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 useServices(const std::string &serviceName, const std::string &versionRange, const std::string &filter, const std::function<void(I &svc, const celix::Properties &props, const celix::Bundle &svcOwner)> &use) noexcept {
+            this->useServicesInternal(serviceName, filter, versionRange, [use](void *voidSvc, const celix::Properties &props, const celix::Bundle &svcOwner) {
+                I *typedSvc = static_cast<I*>(voidSvc);
+                use(*typedSvc, props, svcOwner);
+            });
+        }
+
+        /**
+         * Note ordered by service rank.
+         */
+        virtual std::vector<long> findServices(const std::string &serviceName, const std::string &versionRange = "", const std::string &filter = "", const std::string &lang = "") noexcept = 0;
+
+        //TODO also support getting int, long, unsigned int, etc??
+        virtual std::string getProperty(const std::string &key, std::string defaultValue = "") noexcept  = 0;
+
+        //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.
+         */
+        virtual void stopTracker(long trackerId) noexcept  = 0;
+
+        //TODO
+        //virtual Bundle& getBundle() const noexcept = 0;
+
+
+        //TODO
+        //class celix::DependencyManager; //forward declaration TODO create
+        //virtual celix::DependencyManager& getDependencyManager() const noexcept = 0;
+
+        virtual long 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 = 0;
+
+        virtual void registerEmbeddedBundle(const celix::BundleRegistrationOptions &opts) noexcept = 0;
+
+        virtual long installBundle(const std::string &bundleLocation, bool autoStart = true) noexcept = 0;
+
+        virtual void useBundles(const std::function<void(const celix::Bundle &bnd)> &use) noexcept = 0;
+
+        virtual bool useBundle(long bundleId, const std::function<void(const celix::Bundle &bnd)> &use) noexcept = 0;
+    protected:
+        virtual long registerServiceInternal(const std::string &serviceName, void *svc, const std::string &version, const std::string &lang, celix::Properties props) noexcept = 0;
+
+        virtual long trackServiceInternal(const std::string &serviceName,
+                                         const std::string &versionRange,
+                                         const std::string &filter,
+                                         std::function<void(void *svc, const celix::Properties &props, const celix::Bundle &bnd)> set) noexcept = 0;
+
+        virtual long trackServicesInternal(
+                const std::string &serviceName,
+                const std::string &versionRange,
+                const std::string &filter,
+                std::function<void(void *svc, const celix::Properties &props, const celix::Bundle &bnd)> add,
+                std::function<void(void *svc, const celix::Properties &props, const celix::Bundle &bnd)> remove
+        ) noexcept = 0;
+
+        virtual bool useServiceInternal(const std::string &serviceName, const std::string &versionRange, const std::string &filter, const std::function<void(void *svc, const celix::Properties &props, const celix::Bundle &svcOwner)> &use) noexcept = 0;
+        virtual void useServicesInternal(const std::string &serviceName, const std::string &versionRange, const std::string &filter, const std::function<void(void *svc, const celix::Properties &props, const celix::Bundle &svcOwner)> &use) noexcept = 0;
+    };
+
+}
+
+#include "celix/impl/BundleContextImpl.h"
+
+#endif //CXX_CELIX_BUNDLECONTEXT_H

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/include/celix/Celix.h
----------------------------------------------------------------------
diff --git a/framework/include/celix/Celix.h b/framework/include/celix/Celix.h
new file mode 100644
index 0000000..c27969f
--- /dev/null
+++ b/framework/include/celix/Celix.h
@@ -0,0 +1,36 @@
+/**
+ *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"
+
+#endif //CXX_CELIX_CELIX_H

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/include/celix/Constants.h
----------------------------------------------------------------------
diff --git a/framework/include/celix/Constants.h b/framework/include/celix/Constants.h
new file mode 100644
index 0000000..8317069
--- /dev/null
+++ b/framework/include/celix/Constants.h
@@ -0,0 +1,47 @@
+/**
+ *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
+
+#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;
+
+        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_SHARED_LANG = CELIX_FRAMEWORK_SERVICE_SHARED_LANGUAGE; //e.g. marker services
+
+        static constexpr const char *const FRAMEWORK_STORAGE = OSGI_FRAMEWORK_FRAMEWORK_STORAGE;
+        static constexpr const char *const FRAMEWORK_CLEAN = OSGI_FRAMEWORK_FRAMEWORK_STORAGE_CLEAN;
+        static constexpr const char *const FRAMEWORK_CLEAN_ON_FIRST_INIT = OSGI_FRAMEWORK_FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT;
+        static constexpr const char *const FRAMEWORK_UUID = OSGI_FRAMEWORK_FRAMEWORK_UUID;
+    };
+}
+
+#endif //CXX_CELIX_CONSTANTS_H

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/include/celix/Framework.h
----------------------------------------------------------------------
diff --git a/framework/include/celix/Framework.h b/framework/include/celix/Framework.h
new file mode 100644
index 0000000..ee7074b
--- /dev/null
+++ b/framework/include/celix/Framework.h
@@ -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.
+ */
+
+#ifndef CXX_CELIX_FRAMEWORK_H
+#define CXX_CELIX_FRAMEWORK_H
+
+#include <functional>
+
+#include "celix/Constants.h"
+#include "celix/Properties.h"
+#include "Bundle.h"
+#include "celix/BundleContext.h"
+
+namespace celix {
+    /*TODO make framework a bundle ??
+     * personally I was never a fan of the context that the framework is also a bundle
+     */
+    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

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/include/celix/FrameworkFactory.h
----------------------------------------------------------------------
diff --git a/framework/include/celix/FrameworkFactory.h b/framework/include/celix/FrameworkFactory.h
new file mode 100644
index 0000000..b7bc9b7
--- /dev/null
+++ b/framework/include/celix/FrameworkFactory.h
@@ -0,0 +1,66 @@
+/**
+ *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

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/include/celix/IServiceFactory.h
----------------------------------------------------------------------
diff --git a/framework/include/celix/IServiceFactory.h b/framework/include/celix/IServiceFactory.h
new file mode 100644
index 0000000..1adc8b5
--- /dev/null
+++ b/framework/include/celix/IServiceFactory.h
@@ -0,0 +1,35 @@
+/**
+ *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_ISERVICEFACTORY_H
+#define CXX_CELIX_ISERVICEFACTORY_H
+
+#include "celix/Bundle.h"
+
+namespace celix {
+
+    typename<I>
+    class IServiceFactory {
+        virtual I* getService(IBundle &bundle) = 0;
+        virtual void ungetService(IBundle* bundle, I* svc) = 0;
+    };
+
+}
+
+#endif //CXX_CELIX_ISERVICEFACTORY_H

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/include/celix/Properties.h
----------------------------------------------------------------------
diff --git a/framework/include/celix/Properties.h b/framework/include/celix/Properties.h
new file mode 100644
index 0000000..65fd4ef
--- /dev/null
+++ b/framework/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

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/include/celix/dm/Properties.h
----------------------------------------------------------------------
diff --git a/framework/include/celix/dm/Properties.h b/framework/include/celix/dm/Properties.h
index bb4fd78..77d2872 100644
--- a/framework/include/celix/dm/Properties.h
+++ b/framework/include/celix/dm/Properties.h
@@ -20,11 +20,10 @@
 #ifndef CELIX_DM_PROPERTIES_H
 #define CELIX_DM_PROPERTIES_H
 
-#include <map>
-#include <string>
+#include "celix/Properties.h"
 
 namespace celix { namespace dm {
-    using Properties = std::map<std::string, std::string>;
+    using Properties = celix::Properties;
 }}
 
 #endif //CELIX_DM_PROPERTIES_H

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/include/celix/impl/BundleContextImpl.h
----------------------------------------------------------------------
diff --git a/framework/include/celix/impl/BundleContextImpl.h b/framework/include/celix/impl/BundleContextImpl.h
new file mode 100644
index 0000000..8da3984
--- /dev/null
+++ b/framework/include/celix/impl/BundleContextImpl.h
@@ -0,0 +1,293 @@
+/**
+ *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_BUNDLECONTEXT_H
+#define CELIX_IMPL_BUNDLECONTEXT_H
+
+#include "bundle_context.h"
+#include "service_tracker.h"
+
+#include "celix/impl/BundleImpl.h"
+
+namespace celix {
+
+    namespace impl {
+
+        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);
+            }
+            return result;
+        }
+
+        class BundleContextImpl : public celix::BundleContext {
+        public:
+            BundleContextImpl(bundle_context_t *ctx) : c_ctx{ctx} {}
+
+            virtual ~BundleContextImpl() {
+                //NOTE no need to destroy the c bundle context -> done by c framework
+
+                //clearing tracker entries
+                {
+                    std::lock_guard<std::mutex> lock{this->mutex};
+                    for (auto &pair : this->trackEntries) {
+                        celix_bundleContext_stopTracker(this->c_ctx, pair.first);
+                    }
+                    this->trackEntries.clear();
+                }
+
+                this->c_ctx = nullptr;
+            }
+
+            void unregisterService(long serviceId) noexcept override {
+                celix_bundleContext_unregisterService(this->c_ctx, serviceId);
+            }
+
+            std::vector<long> findServices(const std::string &serviceName, const std::string &versionRange, const std::string &filter, const std::string &/*lang = ""*/) noexcept override  {
+                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);
+                    }
+                };
+                this->useServicesInternal(serviceName, versionRange, filter, use);
+                return result;
+            }
+
+            void stopTracker(long trackerId) noexcept override {
+                std::lock_guard<std::mutex> lock{this->mutex};
+                celix_bundleContext_stopTracker(this->c_ctx, trackerId);
+                auto it = this->trackEntries.find(trackerId);
+                if (it != this->trackEntries.end()) {
+                    this->trackEntries.erase(it);
+                }
+            }
+
+            std::string getProperty(const std::string &key, std::string defaultValue) noexcept  override  {
+                const char *val = nullptr;
+                bundleContext_getPropertyWithDefault(this->c_ctx, key.c_str(), defaultValue.c_str(), &val);
+                return std::string{val};
+            }
+
+            bool isInvalid() const noexcept {
+                return this->c_ctx == nullptr;
+            }
+
+            long registerEmbeddedBundle(
+                    std::string /*id*/,
+                    std::function<void(celix::BundleContext & ctx)> /*start*/,
+                    std::function<void(celix::BundleContext & ctx)> /*stop*/,
+                    celix::Properties /*manifest*/,
+                    bool /*autoStart*/
+            ) noexcept override {
+                return -1; //TODO
+            };
+
+            void registerEmbeddedBundle(const celix::BundleRegistrationOptions &/*opts*/) noexcept override {
+                //TODO
+            }
+
+            long installBundle(const std::string &bundleLocation, bool autoStart) noexcept override {
+                long bndId = -1;
+                if (this->c_ctx != nullptr) {
+                    bundle_t *bnd = nullptr;
+                    bundleContext_installBundle(this->c_ctx, bundleLocation.c_str(), &bnd);
+                    if (bnd != nullptr) {
+                        bundle_getBundleId(bnd, &bndId);
+                        if (autoStart) {
+                            bundle_start(bnd);
+                        }
+                    }
+                }
+                return bndId;
+            }
+
+
+            void useBundles(const std::function<void(const celix::Bundle &bnd)> &use) noexcept override {
+                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->c_ctx, (void*)(&use), c_use);
+            }
+
+            bool useBundle(long bundleId, const std::function<void(const celix::Bundle &bnd)> &use) noexcept override {
+                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);
+                };
+                return celix_bundleContext_useBundle(this->c_ctx, bundleId, (void*)(&use), c_use);
+            }
+
+        protected:
+
+            long registerServiceInternal(const std::string &serviceName, void *svc, const std::string &version, const std::string &lang, Properties props = {}) noexcept override {
+                properties_t *c_props = properties_create();
+                for (auto &pair : props) {
+                    properties_set(c_props, pair.first.c_str(), pair.second.c_str());
+                }
+                return celix_bundleContext_registerServiceForLang(this->c_ctx, serviceName.c_str(), svc, version.c_str(), lang.c_str(), c_props);
+            }
+
+            long trackServiceInternal(const std::string &serviceName,
+                                      const std::string &versionRange,
+                                      const std::string &filter,
+                                      std::function<void(void *svc, const celix::Properties &props, const celix::Bundle &bnd)> set) noexcept override  {
+                celix_service_tracker_options_t opts;
+                std::memset(&opts, 0, sizeof(opts));
+
+                auto c_set = [](void *handle, void *svc, const celix_properties_t *c_props, const celix_bundle_t *c_bnd) {
+                    auto *entry = static_cast<TrackEntry*>(handle);
+                    celix::Properties props = createFromCProps(c_props);
+                    auto m_bnd = const_cast<celix_bundle_t *>(c_bnd);
+                    auto bnd = celix::impl::BundleImpl(m_bnd);
+                    (entry->set)(svc, props, bnd);
+                };
+                const char *cname = serviceName.empty() ? nullptr : serviceName.c_str();
+                const char *crange = versionRange.empty() ? nullptr : versionRange.c_str();
+                const char *cfilter = filter.empty() ? nullptr : filter.c_str();
+
+                opts.serviceName = cname;
+                opts.versionRange = crange;
+                opts.filter = cfilter;
+                opts.lang = CELIX_FRAMEWORK_SERVICE_CXX_LANGUAGE;
+
+                auto te = std::unique_ptr<TrackEntry>{new TrackEntry{}};
+                te->set = std::move(set);
+
+                opts.callbackHandle = te.get();
+                opts.setWithOwner = c_set;
+
+                long id = celix_bundleContext_trackServicesWithOptions(this->c_ctx, &opts);
+                if (id >= 0) {
+                    std::lock_guard<std::mutex> lock{this->mutex};
+                    this->trackEntries[id] = std::move(te);
+                }
+                return id;
+            }
+
+            long trackServicesInternal(
+                    const std::string &serviceName,
+                    const std::string &versionRange,
+                    const std::string &filter,
+                    std::function<void(void *svc, const celix::Properties &props, const celix::Bundle &bnd)> add,
+                    std::function<void(void *svc, const celix::Properties &props, const celix::Bundle &bnd)> remove
+            ) noexcept override {
+                celix_service_tracker_options_t opts;
+                std::memset(&opts, 0, sizeof(opts));
+
+                auto c_add = [](void *handle, void *svc, const celix_properties_t *c_props, const celix_bundle_t *c_bnd) {
+                    auto *entry = static_cast<TrackEntry*>(handle);
+                    celix::Properties props = createFromCProps(c_props);
+                    auto m_bnd = const_cast<celix_bundle_t *>(c_bnd);
+                    auto bnd = celix::impl::BundleImpl(m_bnd);
+                    (entry->add)(svc, props, bnd);
+                };
+                auto c_remove = [](void *handle, void *svc, const celix_properties_t *c_props, const celix_bundle_t *c_bnd) {
+                    auto *entry = static_cast<TrackEntry*>(handle);
+                    celix::Properties props = createFromCProps(c_props);
+                    auto m_bnd = const_cast<celix_bundle_t *>(c_bnd);
+                    auto bnd = celix::impl::BundleImpl(m_bnd);
+                    (entry->remove)(svc, props, bnd);
+                };
+
+                const char *cname = serviceName.empty() ? nullptr : serviceName.c_str();
+                const char *crange = versionRange.empty() ? nullptr : versionRange.c_str();
+                const char *cfilter = filter.empty() ? nullptr : filter.c_str();
+
+                opts.serviceName = cname;
+                opts.versionRange = crange;
+                opts.filter = cfilter;
+                opts.lang = CELIX_FRAMEWORK_SERVICE_CXX_LANGUAGE;
+
+                auto te = std::unique_ptr<TrackEntry>{new TrackEntry{}};
+                te->add = std::move(add);
+                te->remove = std::move(remove);
+
+                opts.callbackHandle = te.get();
+                opts.addWithOwner = c_add;
+                opts.removeWithOwner = c_remove;
+
+                long id = celix_bundleContext_trackServicesWithOptions(this->c_ctx, &opts);
+                if (id >= 0) {
+                    std::lock_guard<std::mutex> lock{this->mutex};
+                    this->trackEntries[id] = std::move(te);
+                }
+                return id;
+            }
+
+            bool useServiceInternal(
+                    const std::string &serviceName,
+                    const std::string &versionRange,
+                    const std::string &filter,
+                    const std::function<void(void *svc, const celix::Properties &props, const celix::Bundle &svcOwner)> &use) noexcept override {
+                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 *c_bnd = const_cast<celix_bundle_t*>(c_svcOwner);
+                    auto bnd = celix::impl::BundleImpl{c_bnd};
+                    (*fn)(svc, props, bnd);
+                };
+                const char *cname = serviceName.empty() ? nullptr : serviceName.c_str();
+                const char *crange = versionRange.empty() ? nullptr : versionRange.c_str();
+                const char *cfilter = filter.empty() ? nullptr : filter.c_str();
+                return celix_bundleContext_useService(this->c_ctx, cname, crange, cfilter, (void*)(&use), c_use);
+            }
+
+            void useServicesInternal(
+                    const std::string &serviceName,
+                    const std::string &versionRange,
+                    const std::string &filter,
+                    const std::function<void(void *svc, const celix::Properties &props, const celix::Bundle &svcOwner)> &use) noexcept override {
+                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 *c_bnd = const_cast<celix_bundle_t*>(c_svcOwner);
+                    auto bnd = celix::impl::BundleImpl{c_bnd};
+                    (*fn)(svc, props, bnd);
+                };
+                const char *cname = serviceName.empty() ? nullptr : serviceName.c_str();
+                const char *crange = versionRange.empty() ? nullptr : versionRange.c_str();
+                const char *cfilter = filter.empty() ? nullptr : filter.c_str();
+                celix_bundleContext_useServices(this->c_ctx, cname, crange, cfilter, (void*)(&use), c_use);
+            }
+
+        private:
+            bundle_context_t *c_ctx;
+
+            struct TrackEntry {
+                std::function<void(void *, const celix::Properties &, const celix::Bundle &)> set{};
+                std::function<void(void *, const celix::Properties &, const celix::Bundle &)> add{};
+                std::function<void(void *, const celix::Properties &, const celix::Bundle &)> remove{};
+            };
+
+            std::mutex mutex{};
+            std::map<long,std::unique_ptr<TrackEntry>> trackEntries{};
+        };
+    }
+}
+
+#endif //CELIX_IMPL_BUNDLECONTEXT_H

http://git-wip-us.apache.org/repos/asf/celix/blob/764bd7f7/framework/include/celix/impl/BundleImpl.h
----------------------------------------------------------------------
diff --git a/framework/include/celix/impl/BundleImpl.h b/framework/include/celix/impl/BundleImpl.h
new file mode 100644
index 0000000..583ae25
--- /dev/null
+++ b/framework/include/celix/impl/BundleImpl.h
@@ -0,0 +1,171 @@
+/**
+ *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"
+
+namespace celix {
+
+    //forward declaration
+
+    namespace impl {
+        class BundleImpl : public celix::Bundle {
+        public:
+            BundleImpl(celix_bundle_t *b) : c_bnd{b} {
+                framework_t *c_fw{nullptr};
+                bundle_getFramework(this->c_bnd, &c_fw);
+                //this->fw = std::unique_ptr<celix::impl::Framework>{new celix::impl::Framework(c_fw, false)};
+            }
+
+            virtual ~BundleImpl() {
+                //no need to destroy the c bundle context -> done by c framework
+                this->c_bnd = nullptr;
+            }
+
+            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
+            }
+
+            celix::Framework* getFramework() const noexcept override {
+//                return this->fw;
+                return nullptr; //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;
+//            framework_t *c_fw{nullptr};
+//            std::unique_ptr<celix::impl::Framework> fw{nullptr};
+        };
+    }
+}
+
+#endif //CELIX_IMPL_BUNDLEIMPL_H


Mime
View raw message