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 2018/04/23 19:08:02 UTC

[2/2] celix git commit: CELIX-446: Adds a test for race condition issues for unregistering and using services and fixes the issue.

CELIX-446: Adds a test for race condition issues for unregistering and using services and fixes the issue.

- Renames DeplocPackaing to ContainerPackaging
- Adds celix_launcher api documentation.
- Adds support for multiple run level for auto starting bundles and adds support for the property names CELIX_AUTO_START_<num>.
- Update documentation for docker Celix CMake commands


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

Branch: refs/heads/develop
Commit: 985c35f2f6ef6cd48ba63e8d117a928dfda3fe6a
Parents: e17f8e6
Author: Pepijn Noltes <pe...@gmail.com>
Authored: Mon Apr 23 21:04:13 2018 +0200
Committer: Pepijn Noltes <pe...@gmail.com>
Committed: Mon Apr 23 21:04:13 2018 +0200

----------------------------------------------------------------------
 cmake/celix_project/CelixProject.cmake       |  11 +-
 cmake/cmake_celix/ContainerPackaging.cmake   | 396 ++++++++++++++++++++++
 cmake/cmake_celix/DeployPackaging.cmake      | 376 --------------------
 cmake/cmake_celix/DockerPackaging.cmake      |  42 ++-
 cmake/cmake_celix/UseCelix.cmake             |   2 +-
 documents/cmake_commands/readme.md           | 124 ++++---
 framework/include/bundle_context.h           |   6 +-
 framework/include/celix_api.h                |  36 ++
 framework/include/celix_launcher.h           |  75 +++-
 framework/include/constants.h                |   9 +-
 framework/private/mock/bundle_context_mock.c |  10 +-
 framework/src/bundle_context.c               |  26 +-
 framework/src/celix_launcher.c               | 103 +-----
 framework/src/framework.c                    |  92 ++++-
 framework/src/framework_private.h            |   4 +
 framework/src/service_registry.c             |  26 +-
 framework/src/service_tracker.c              |  21 +-
 framework/src/service_tracker_private.h      |   5 +-
 framework/tst/framework_bundle_context.cpp   |  96 +++++-
 framework/tst/single_framework_test.cpp      |   8 -
 launcher/README.md                           |  24 +-
 launcher/src/main.c                          |   2 +-
 utils/include/celix_utils_api.h              |  34 ++
 utils/src/memstream/open_memstream.c         |   2 +-
 24 files changed, 947 insertions(+), 583 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/celix/blob/985c35f2/cmake/celix_project/CelixProject.cmake
----------------------------------------------------------------------
diff --git a/cmake/celix_project/CelixProject.cmake b/cmake/celix_project/CelixProject.cmake
index 490c359..9d306a7 100644
--- a/cmake/celix_project/CelixProject.cmake
+++ b/cmake/celix_project/CelixProject.cmake
@@ -18,8 +18,13 @@
 option(ENABLE_ADDRESS_SANITIZER "Enabled building with address sanitizer. Note for gcc libasan must be installed" OFF)
 
 if (ENABLE_ADDRESS_SANITIZER)
-    set(CMAKE_C_FLAGS "-lasan -fsanitize=address ${CMAKE_C_FLAGS}")
-    set(CMAKE_CXX_FLAGS "-lasan -fsanitize=address ${CMAKE_CXX_FLAGS}")
+    if (APPLE)
+        set(CMAKE_C_FLAGS "-fsanitize=address ${CMAKE_C_FLAGS}")
+        set(CMAKE_CXX_FLAGS "-fsanitize=address ${CMAKE_CXX_FLAGS}")
+    else ()
+        set(CMAKE_C_FLAGS "-lasan -fsanitize=address ${CMAKE_C_FLAGS}")
+        set(CMAKE_CXX_FLAGS "-lasan -fsanitize=address ${CMAKE_CXX_FLAGS}")
+    endif ()
 endif()
 
 
@@ -77,4 +82,4 @@ MACRO(is_enabled name)
 ENDMACRO(is_enabled)
 
 include(${CMAKE_CURRENT_LIST_DIR}/ApacheRat.cmake)
-include(${CMAKE_CURRENT_LIST_DIR}/CodeCoverage.cmake)
\ No newline at end of file
+include(${CMAKE_CURRENT_LIST_DIR}/CodeCoverage.cmake)

http://git-wip-us.apache.org/repos/asf/celix/blob/985c35f2/cmake/cmake_celix/ContainerPackaging.cmake
----------------------------------------------------------------------
diff --git a/cmake/cmake_celix/ContainerPackaging.cmake b/cmake/cmake_celix/ContainerPackaging.cmake
new file mode 100644
index 0000000..28d63bc
--- /dev/null
+++ b/cmake/cmake_celix/ContainerPackaging.cmake
@@ -0,0 +1,396 @@
+# 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.
+
+##### setup bundles/container target
+if (NOT TARGET celix-containers)
+	add_custom_target(celix-containers ALL
+		DEPENDS $<TARGET_PROPERTY:celix-containers,CONTAINER_DEPLOYMENTS>
+	)
+	set_target_properties(celix-containers PROPERTIES "CONTAINER_DEPLOYMENTS" "") #initial empty deps list
+
+	get_directory_property(CLEANFILES ADDITIONAL_MAKE_CLEAN_FILES)
+	list(APPEND CLEANFILES "${CMAKE_BINARY_DIR}/deploy")
+	list(APPEND CLEANFILES "${CMAKE_BINARY_DIR}/celix")
+	set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CLEANFILES}")
+endif ()
+#####
+
+function(add_deploy)
+    message(DEPRECATION "deploy_bundles_dir is depecrated, use celix_container_bundles_dir instead.")
+    add_celix_container(${ARGN})
+endfunction()
+function(add_celix_container)
+    list(GET ARGN 0 CONTAINER_TARGET)
+    list(REMOVE_AT ARGN 0)
+
+    set(OPTIONS COPY CXX)
+    set(ONE_VAL_ARGS GROUP NAME LAUNCHER LAUNCHER_SRC DIR)
+    set(MULTI_VAL_ARGS BUNDLES PROPERTIES EMBEDDED_PROPERTIES)
+    cmake_parse_arguments(CONTAINER "${OPTIONS}" "${ONE_VAL_ARGS}" "${MULTI_VAL_ARGS}" ${ARGN})
+
+    ##### Check arguments #####
+    if (NOT CONTAINER_NAME)
+        set(CONTAINER_NAME "${CONTAINER_TARGET}")
+    endif ()
+    if (NOT CONTAINER_DIR)
+        set(CONTAINER_DIR "${CMAKE_BINARY_DIR}/deploy")
+    endif ()
+    ######
+
+    ##### Setting defaults #####
+    if (CONTAINER_GROUP)
+        set(CONTAINER_LOC "${CONTAINER_DIR}/${CONTAINER_GROUP}/${CONTAINER_NAME}")
+        set(CONTAINER_PRINT_NAME "${CONTAINER_GROUP}/${CONTAINER_NAME}")
+    else ()
+        set(CONTAINER_LOC "${CONTAINER_DIR}/${CONTAINER_NAME}")
+        set(CONTAINER_PRINT_NAME "${CONTAINER_NAME}")
+    endif ()
+    ######
+
+    #add this target as depependency to the celix-containers target
+    get_target_property(CONTAINERDEPS celix-containers "CONTAINER_DEPLOYMENTS")
+    list(APPEND CONTAINERDEPS ${CONTAINER_TARGET})
+    set_target_properties(celix-containers PROPERTIES "CONTAINER_DEPLOYMENTS" "${CONTAINERDEPS}")
+
+    #FILE TARGETS FOR CONTAINER
+    set(CONTAINER_PROPS "${CONTAINER_LOC}/config.properties")
+    set(CONTAINER_ECLIPSE_LAUNCHER "${CONTAINER_LOC}/${CONTAINER_NAME}.launch")
+
+    set(LAUNCHER_DEP )
+    if (CONTAINER_LAUNCHER)
+        if (IS_ABSOLUTE "${CONTAINER_LAUNCHER}")
+            set(LAUNCHER "${CONTAINER_LAUNCHER}")
+        else()
+            #assuming target
+            set(LAUNCHER "$<TARGET_FILE:${CONTAINER_LAUNCHER}>")
+            set(LAUNCHER_DEP ${CONTAINER_LAUNCHER})
+        endif()
+    elseif (CONTAINER_LAUNCHER_SRC)
+        get_filename_component(SRC_FILENAME ${CONTAINER_LAUNCHER_SRC} NAME)
+        set(LAUNCHER_SRC "${PROJECT_BINARY_DIR}/celix/gen/${CONTAINER_TARGET}/${SRC_FILENAME}")
+        set(LAUNCHER_ORG "${CONTAINER_LAUNCHER_SRC}")
+        add_custom_command(OUTPUT ${LAUNCHER_SRC}
+                COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LAUNCHER_ORG} ${LAUNCHER_SRC}
+        )
+    else () #generate custom launcher
+        if (CONTAINER_CXX)
+            set(LAUNCHER_SRC "${PROJECT_BINARY_DIR}/celix/gen/${CONTAINER_TARGET}/main.cc")
+        else()
+            set(LAUNCHER_SRC "${PROJECT_BINARY_DIR}/celix/gen/${CONTAINER_TARGET}/main.c")
+        endif()
+
+        file(GENERATE
+                OUTPUT "${LAUNCHER_SRC}"
+                CONTENT "#include <celix_launcher.h>
+int main(int argc, char *argv[]) {
+    const char * config = \"\\
+$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_EMBEDDED_PROPERTIES>,\\n\\
+>\";
+
+    properties_pt packedConfig = properties_loadFromString(config);
+    return celixLauncher_launchAndWaitForShutdown(argc, argv, packedConfig);
+}
+"
+        )
+    endif ()
+
+    if (LAUNCHER_SRC) #compilation needed
+        add_executable(${CONTAINER_TARGET} ${LAUNCHER_SRC})
+        set_target_properties(${CONTAINER_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CONTAINER_LOC})
+	    set_target_properties(${CONTAINER_TARGET} PROPERTIES OUTPUT_NAME ${CONTAINER_NAME})
+        target_link_libraries(${CONTAINER_TARGET} PRIVATE Celix::framework)
+        set(LAUNCHER "$<TARGET_FILE:${CONTAINER_TARGET}>")
+    else ()
+        #LAUNCHER already set
+        add_custom_target(${CONTAINER_TARGET}
+		COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LAUNCHER} ${CONTAINER_LOC}/${CONTAINER_NAME}
+        )
+    endif ()
+
+    #generate config.properties
+    set(STAGE1_PROPERTIES "${PROJECT_BINARY_DIR}/celix/gen/${CONTAINER_TARGET}/container-config-stage1.properties")
+    file(GENERATE 
+        OUTPUT "${STAGE1_PROPERTIES}"
+        CONTENT "CELIX_AUTO_START_0=$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_BUNDLES_LEVEL_0>, >
+CELIX_AUTO_START_1=$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_BUNDLES_LEVEL_1>, >
+CELIX_AUTO_START_2=$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_BUNDLES_LEVEL_2>, >
+CELIX_AUTO_START_3=$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_BUNDLES_LEVEL_3>, >
+CELIX_AUTO_START_4=$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_BUNDLES_LEVEL_4>, >
+CELIX_AUTO_START_5=$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_BUNDLES_LEVEL_5>, >
+$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_PROPERTIES>,
+>
+"
+    )
+    file(GENERATE
+        OUTPUT "${CONTAINER_PROPS}"
+        INPUT "${STAGE1_PROPERTIES}"
+    )
+
+    #needed in the release.sh & run.sh files
+    #Setting CELIX_LIB_DIRS, CELIX_BIN_DIR and CELIX_LAUNCHER
+    if (TARGET Celix::framework)
+        #Celix Main Project
+        set(CELIX_LIB_DIRS "$<TARGET_FILE_DIR:Celix::framework>:$<TARGET_FILE_DIR:Celix::utils>:$<TARGET_FILE_DIR:Celix::dfi>")
+        set(CELIX_BIN_DIR  "$<TARGET_FILE_DIR:Celix::launcher>")
+    else ()
+	message(FATAL_ERROR "No Celix::framework target is defined. Did you use find_package(Celix REQUIRED)?")
+    endif()
+
+    #generate release.sh and optional run.sh
+    if(APPLE)
+        set(LIB_PATH_NAME "DYLD_LIBRARY_PATH")
+    else()
+        set(LIB_PATH_NAME "LD_LIBRARY_PATH")
+    endif()
+
+    set(RELEASE_SH ${CONTAINER_LOC}/release.sh)
+    set(RELEASE_CONTENT "#!/bin/sh\nexport ${LIB_PATH_NAME}=${CELIX_LIB_DIRS}:\${${LIB_PATH_NAME}}\nexport PATH=${CELIX_BIN_DIR}:\${PATH}")
+    file(GENERATE
+        OUTPUT ${RELEASE_SH}
+        CONTENT ${RELEASE_CONTENT}
+    )
+
+    set(RUN_SH ${CONTAINER_LOC}/run.sh)
+    set(RUN_CONTENT "${RELEASE_CONTENT}\n${LAUNCHER} \$@\n")
+    file(GENERATE
+        OUTPUT ${RUN_SH}
+        CONTENT ${RUN_CONTENT}
+    )
+
+    #generate eclipse project launch file
+    set(PROGRAM_NAME "${LAUNCHER}")
+    set(PROJECT_ATTR "${CMAKE_PROJECT_NAME}-build")
+    set(WORKING_DIRECTORY ${CONTAINER_LOC})
+    include("${CELIX_CMAKE_DIRECTORY}/RunConfig.in.cmake") #set VAR RUN_CONFIG_IN
+    file(GENERATE
+        OUTPUT "${CONTAINER_ECLIPSE_LAUNCHER}"
+        CONTENT "${RUN_CONFIG_IN}"
+    )
+
+    #add a custom target which can depend on generation expressions
+    add_custom_target(${CONTAINER_TARGET}-deps
+        DEPENDS
+            ${RUN_SH}
+            ${CONTAINER_ECLIPSE_LAUNCHER}
+            ${RELEASE_SH}
+            ${CONTAINER_PROPS}
+            $<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_TARGET_DEPS>
+    )
+    add_dependencies(${CONTAINER_TARGET} ${CONTAINER_TARGET}-deps)
+
+
+    ##### Container Target Properties #####
+    #internal use
+    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_TARGET_DEPS" "") #target deps for the container.
+    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_BUNDLES_LEVEL_0" "") #bundles to deploy for the container for run level 0
+    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_BUNDLES_LEVEL_1" "") #bundles to deploy for the container for run level 0
+    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_BUNDLES_LEVEL_2" "") #bundles to deploy for the container for run level 0
+    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_BUNDLES_LEVEL_3" "") #bundles to deploy for the container for run level 0
+    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_BUNDLES_LEVEL_4" "") #bundles to deploy for the container for run level 0
+    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_BUNDLES_LEVEL_5" "") #bundles to deploy for the container for run level 0
+    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_COPY_BUNDLES" ${CONTAINER_COPY}) #copy bundles in bundle dir or link using abs paths. NOTE this cannot be changed after a add_deploy command
+
+    #deploy specific
+    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_NAME" "${CONTAINER_NAME}")
+    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_GROUP" "${CONTAINER_GROUP}")
+    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_LOC" "${CONTAINER_LOC}")
+    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_PROPERTIES" "")
+    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_EMBEDDED_PROPERTIES" "")
+    #####
+
+    celix_container_bundles(${CONTAINER_TARGET} LEVEL 1 ${CONTAINER_BUNDLES})
+    celix_container_properties(${CONTAINER_TARGET} ${CONTAINER_PROPERTIES})
+    celix_container_embedded_properties(${CONTAINER_TARGET} ${CONTAINER_EMBEDDED_PROPERTIES})
+
+
+    #ensure the container dir will be deleted during clean
+    get_directory_property(CLEANFILES ADDITIONAL_MAKE_CLEAN_FILES)
+    list(APPEND CLEANFILES "$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_LOC>")
+    set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CLEANFILES}")
+endfunction()
+
+
+#NOTE can be used for drivers/proxies/endpoints bundle dirs
+function(deploy_bundles_dir)
+    message(DEPRECATION "deploy_bundles_dir is depecrated, use celix_container_bundles_dir instead.")
+    celix_container_bundles_dir(${ARGN})
+endfunction()
+function(celix_container_bundles_dir)
+    list(GET ARGN 0 CONTAINER_TARGET)
+    list(REMOVE_AT ARGN 0)
+
+    set(OPTIONS)
+    set(ONE_VAL_ARGS DIR_NAME)
+    set(MULTI_VAL_ARGS BUNDLES)
+    cmake_parse_arguments(BD "${OPTIONS}" "${ONE_VAL_ARGS}" "${MULTI_VAL_ARGS}" ${ARGN})
+
+    if(NOT BD_DIR_NAME)
+        message(FATAL_ERROR "Missing mandatory DIR_NAME argument")
+    endif()
+
+    get_target_property(CONTAINER_LOC ${CONTAINER_TARGET} "CONTAINER_LOC")
+    get_target_property(DEPS ${CONTAINER_TARGET} "CONTAINER_TARGET_DEPS")
+
+    foreach(BUNDLE IN ITEMS ${BD_BUNDLES})
+        set(HANDLED FALSE)
+        if (IS_ABSOLUTE ${BUNDLE} AND EXISTS ${BUNDLE})
+            get_filename_component(BUNDLE_FILENAME ${BUNDLE} NAME) 
+            set(OUT "${CONTAINER_LOC}/${BD_DIR_NAME}/${BUNDLE_FILENAME}")
+            add_custom_command(OUTPUT ${OUT}
+                COMMAND ${CMAKE_COMMAND} -E copy_if_different ${BUNDLE} ${OUT}
+		        COMMENT "Copying (file) bundle '${BUNDLE}' to '${CONTAINER_LOC}/${BD_DIR_NAME}'"
+            )
+            set(HANDLED TRUE)
+        elseif (TARGET ${BUNDLE})
+            get_target_property(IMP ${BUNDLE} BUNDLE_IMPORTED)
+            if (IMP) #An imported bundle target -> handle target without DEPENDS
+                string(MAKE_C_IDENTIFIER ${BUNDLE} BUNDLE_ID) #Create id with no special chars (e.g. for target like Celix::shell)
+                set(OUT "${CMAKE_BINARY_DIR}/celix/gen/${CONTAINER_TARGET}/copy-bundle-for-target-${BUNDLE_ID}.timestamp")
+                set(DEST "${CONTAINER_LOC}/${BD_DIR_NAME}/$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILENAME>")
+                add_custom_command(OUTPUT ${OUT}
+                    COMMAND ${CMAKE_COMMAND} -E touch ${OUT}
+                    COMMAND ${CMAKE_COMMAND} -E make_directory ${CONTAINER_LOC}/${BD_DIR_NAME}
+                    COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILE>" ${DEST}
+                    COMMENT "Copying (imported) bundle '${BUNDLE}' to '${CONTAINER_LOC}/${BD_DIR_NAME}'"
+                )
+                set(HANDLED TRUE)
+            endif ()
+        endif ()
+
+        if (NOT HANDLED) #not a imported bundle target so (assuming) a future bundle target
+            string(MAKE_C_IDENTIFIER ${BUNDLE} BUNDLE_ID) #Create id with no special chars (e.g. for target like Celix::shell)
+            set(OUT "${CMAKE_BINARY_DIR}/celix/gen/${CONTAINER_TARGET}/copy-bundle-for-target-${BUNDLE_ID}.timestamp")
+            set(DEST "${CONTAINER_LOC}/${BD_DIR_NAME}/$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILENAME>")
+            add_custom_command(OUTPUT ${OUT}
+                COMMAND ${CMAKE_COMMAND} -E touch ${OUT}
+                COMMAND ${CMAKE_COMMAND} -E make_directory ${CONTAINER_LOC}/${BD_DIR_NAME}
+                COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILE>" ${DEST}
+                COMMENT "Copying (target) bundle '${BUNDLE}' to '${CONTAINER_LOC}/${BD_DIR_NAME}'"
+                DEPENDS ${BUNDLE} $<TARGET_PROPERTY:${BUNDLE},BUNDLE_CREATE_BUNDLE_TARGET>
+            )
+        endif()
+        list(APPEND DEPS "${OUT}")
+    endforeach()
+
+    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_TARGET_DEPS" "${DEPS}")
+endfunction()
+
+function(deploy_bundles)
+    message(DEPRECATION "deploy_bundles is depecrated, use celix_container_bundles instead.")
+    celix_container_bundles(${ARGN})
+endfunction()
+function(celix_container_bundles)
+    #0 is container TARGET
+    #1..n is bundles
+    list(GET ARGN 0 CONTAINER_TARGET)
+    list(REMOVE_AT ARGN 0)
+
+    set(OPTIONS )
+    set(ONE_VAL_ARGS LEVEL)
+    set(MULTI_VAL_ARGS )
+    cmake_parse_arguments(BUNDLES "${OPTIONS}" "${ONE_VAL_ARGS}" "${MULTI_VAL_ARGS}" ${ARGN})
+    set(BUNDLES_LIST ${BUNDLES_UNPARSED_ARGUMENTS})
+
+    if (NOT BUNDLES_LEVEL)
+        set(BUNDLES_LEVEL 1)
+    endif ()
+
+    get_target_property(BUNDLES ${CONTAINER_TARGET} "CONTAINER_BUNDLES_LEVEL_${BUNDLES_LEVEL}")
+    get_target_property(COPY ${CONTAINER_TARGET} "CONTAINER_COPY_BUNDLES")
+    get_target_property(DEPS ${CONTAINER_TARGET} "CONTAINER_TARGET_DEPS")
+
+    foreach(BUNDLE IN ITEMS ${BUNDLES_LIST})
+        set(HANDLED FALSE)
+        if (IS_ABSOLUTE ${BUNDLE} AND EXISTS ${BUNDLE})
+               get_filename_component(BUNDLE_FILENAME ${BUNDLE} NAME)
+               set(COPY_LOC "bundles/${BUNDLE_FILENAME}")
+               set(ABS_LOC "${BUNDLE}")
+               set(HANDLED TRUE)
+           elseif (TARGET ${BUNDLE})
+               get_target_property(IMP ${BUNDLE} BUNDLE_IMPORTED)
+               if (IMP) #An imported bundle target -> handle target without DEPENDS
+                   set(COPY_LOC "bundles/$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILENAME>")
+                   set(ABS_LOC "$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILE>")
+                   set(HANDLED TRUE)
+               endif ()
+           endif ()
+
+           if (NOT HANDLED) #not a imported bundle target, so assuming a (future) bundle target
+               set(COPY_LOC "bundles/$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILENAME>")
+               set(ABS_LOC "$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILE>")
+
+               if (NOT COPY) #in case of COPY dep will be added in celix_container_bundles_dir
+                   string(MAKE_C_IDENTIFIER ${BUNDLE} BUNDLE_ID) #Create id with no special chars (e.g. for target like Celix::shell)
+                   set(OUT "${CMAKE_BINARY_DIR}/celix/gen/${CONTAINER_TARGET}/check-bundle-for-target-${BUNDLE_ID}.timestamp")
+                   add_custom_command(OUTPUT ${OUT}
+                       COMMAND ${CMAKE_COMMAND} -E touch ${OUT}
+                       DEPENDS ${BUNDLE} $<TARGET_PROPERTY:${BUNDLE},BUNDLE_CREATE_BUNDLE_TARGET>
+                   )
+                   list(APPEND DEPS ${OUT})
+               endif ()
+           endif ()
+           if(COPY)
+                list(APPEND BUNDLES ${COPY_LOC})
+           else()
+                list(APPEND BUNDLES ${ABS_LOC})
+           endif()
+   endforeach()
+
+    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_BUNDLES_LEVEL_${BUNDLES_LEVEL}" "${BUNDLES}")
+    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_TARGET_DEPS" "${DEPS}")
+
+   if(COPY) 
+       celix_container_bundles_dir(${CONTAINER_TARGET} DIR_NAME bundles BUNDLES ${BUNDLES_LIST})
+   endif()
+endfunction()
+
+function(deploy_properties)
+    celix_container_properties(${ARGN})
+endfunction()
+function(celix_container_properties)
+    #0 is container TARGET
+    #1..n is bundles
+    list(GET ARGN 0 CONTAINER_TARGET)
+    list(REMOVE_AT ARGN 0)
+
+    get_target_property(PROPS ${CONTAINER_TARGET} "CONTAINER_PROPERTIES")
+
+    foreach(PROP IN ITEMS ${ARGN})
+        list(APPEND PROPS ${PROP})
+    endforeach()
+
+   set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_PROPERTIES" "${PROPS}")
+endfunction()
+
+function(deploy_embedded_properties)
+    message(DEPRECATION "deploy_embedded_properties is depecrated, use celix_container_embedded_properties instead.")
+    celix_container_embedded_properties(${ARGN})
+endfunction()
+function(celix_container_embedded_properties)
+    #0 is container TARGET
+    #1..n is bundles
+    list(GET ARGN 0 CONTAINER_TARGET)
+    list(REMOVE_AT ARGN 0)
+
+    get_target_property(PROPS ${CONTAINER_TARGET} "CONTAINER_EMBEDDED_PROPERTIES")
+
+    foreach(PROP IN ITEMS ${ARGN})
+        list(APPEND PROPS ${PROP})
+    endforeach()
+
+    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_EMBEDDED_PROPERTIES" "${PROPS}")
+endfunction()

http://git-wip-us.apache.org/repos/asf/celix/blob/985c35f2/cmake/cmake_celix/DeployPackaging.cmake
----------------------------------------------------------------------
diff --git a/cmake/cmake_celix/DeployPackaging.cmake b/cmake/cmake_celix/DeployPackaging.cmake
deleted file mode 100644
index ed7b20c..0000000
--- a/cmake/cmake_celix/DeployPackaging.cmake
+++ /dev/null
@@ -1,376 +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.
-
-##### setup bundles/container target
-if (NOT TARGET celix-containers)
-	add_custom_target(celix-containers ALL
-		DEPENDS $<TARGET_PROPERTY:celix-containers,CONTAINER_DEPLOYMENTS>
-	)
-	set_target_properties(celix-containers PROPERTIES "CONTAINER_DEPLOYMENTS" "") #initial empty deps list
-
-	get_directory_property(CLEANFILES ADDITIONAL_MAKE_CLEAN_FILES)
-	list(APPEND CLEANFILES "${CMAKE_BINARY_DIR}/deploy")
-	list(APPEND CLEANFILES "${CMAKE_BINARY_DIR}/celix")
-	set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CLEANFILES}")
-endif ()
-#####
-
-function(add_deploy)
-    message(DEPRECATION "deploy_bundles_dir is depecrated, use celix_container_bundles_dir instead.")
-    add_celix_container(${ARGN})
-endfunction()
-function(add_celix_container)
-    list(GET ARGN 0 CONTAINER_TARGET)
-    list(REMOVE_AT ARGN 0)
-
-    set(OPTIONS COPY CXX)
-    set(ONE_VAL_ARGS GROUP NAME LAUNCHER LAUNCHER_SRC DIR)
-    set(MULTI_VAL_ARGS BUNDLES PROPERTIES EMBEDDED_PROPERTIES)
-    cmake_parse_arguments(CONTAINER "${OPTIONS}" "${ONE_VAL_ARGS}" "${MULTI_VAL_ARGS}" ${ARGN})
-
-    ##### Check arguments #####
-    if (NOT CONTAINER_NAME)
-        set(CONTAINER_NAME "${CONTAINER_TARGET}")
-    endif ()
-    if (NOT CONTAINER_DIR)
-        set(CONTAINER_DIR "${CMAKE_BINARY_DIR}/deploy")
-    endif ()
-    ######
-
-    ##### Setting defaults #####
-    if (CONTAINER_GROUP)
-        set(CONTAINER_LOC "${CONTAINER_DIR}/${CONTAINER_GROUP}/${CONTAINER_NAME}")
-        set(CONTAINER_PRINT_NAME "${CONTAINER_GROUP}/${CONTAINER_NAME}")
-    else ()
-        set(CONTAINER_LOC "${CONTAINER_DIR}/${CONTAINER_NAME}")
-        set(CONTAINER_PRINT_NAME "${CONTAINER_NAME}")
-    endif ()
-    ######
-
-    #add this target as depependency to the celix-containers target
-    get_target_property(CONTAINERDEPS celix-containers "CONTAINER_DEPLOYMENTS")
-    list(APPEND CONTAINERDEPS ${CONTAINER_TARGET})
-    set_target_properties(celix-containers PROPERTIES "CONTAINER_DEPLOYMENTS" "${CONTAINERDEPS}")
-
-    #FILE TARGETS FOR CONTAINER
-    set(CONTAINER_PROPS "${CONTAINER_LOC}/config.properties")
-    set(CONTAINER_ECLIPSE_LAUNCHER "${CONTAINER_LOC}/${CONTAINER_NAME}.launch")
-
-    set(LAUNCHER_DEP )
-    if (CONTAINER_LAUNCHER)
-        if (IS_ABSOLUTE "${CONTAINER_LAUNCHER}")
-            set(LAUNCHER "${CONTAINER_LAUNCHER}")
-        else()
-            #assuming target
-            set(LAUNCHER "$<TARGET_FILE:${CONTAINER_LAUNCHER}>")
-            set(LAUNCHER_DEP ${CONTAINER_LAUNCHER})
-        endif()
-    elseif (CONTAINER_LAUNCHER_SRC)
-        get_filename_component(SRC_FILENAME ${CONTAINER_LAUNCHER_SRC} NAME)
-        set(LAUNCHER_SRC "${PROJECT_BINARY_DIR}/celix/gen/${CONTAINER_TARGET}-${SRC_FILENAME}")
-        set(LAUNCHER_ORG "${CONTAINER_LAUNCHER_SRC}")
-        add_custom_command(OUTPUT ${LAUNCHER_SRC}
-                COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LAUNCHER_ORG} ${LAUNCHER_SRC}
-        )
-    else () #generate custom launcher
-        if (CONTAINER_CXX)
-            set(LAUNCHER_SRC "${PROJECT_BINARY_DIR}/celix/gen/${CONTAINER_TARGET}-main.cc")
-        else()
-            set(LAUNCHER_SRC "${PROJECT_BINARY_DIR}/celix/gen/${CONTAINER_TARGET}-main.c")
-        endif()
-
-        file(GENERATE
-                OUTPUT "${LAUNCHER_SRC}"
-                CONTENT "#include <celix_launcher.h>
-int main(int argc, char *argv[]) {
-    const char * config = \"\\
-$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_EMBEDDED_PROPERTIES>,\\n\\
->\";
-
-    properties_pt packedConfig = properties_loadFromString(config);
-    return celixLauncher_launchWithArgsAndProps(argc, argv, packedConfig);
-}
-"
-        )
-    endif ()
-
-    if (LAUNCHER_SRC) #compilation needed
-        add_executable(${CONTAINER_TARGET} ${LAUNCHER_SRC})
-        set_target_properties(${CONTAINER_TARGET} PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${CONTAINER_LOC})
-	    set_target_properties(${CONTAINER_TARGET} PROPERTIES OUTPUT_NAME ${CONTAINER_NAME})
-        target_link_libraries(${CONTAINER_TARGET} PRIVATE Celix::framework)
-        set(LAUNCHER "$<TARGET_FILE:${CONTAINER_TARGET}>")
-    else ()
-        #LAUNCHER already set
-        add_custom_target(${CONTAINER_TARGET}
-		COMMAND ${CMAKE_COMMAND} -E copy_if_different ${LAUNCHER} ${CONTAINER_LOC}/${CONTAINER_NAME}
-        )
-    endif ()
-
-    #generate config.properties
-    set(STAGE1_PROPERTIES "${PROJECT_BINARY_DIR}/celix/gen/${CONTAINER_TARGET}-container-config-stage1.properties")
-    file(GENERATE 
-        OUTPUT "${STAGE1_PROPERTIES}"
-        CONTENT "cosgi.auto.start.1=$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_BUNDLES>, >
-$<JOIN:$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_PROPERTIES>,
->
-"
-    )
-    file(GENERATE
-        OUTPUT "${CONTAINER_PROPS}"
-        INPUT "${STAGE1_PROPERTIES}"
-    )
-
-    #needed in the release.sh & run.sh files
-    #Setting CELIX_LIB_DIRS, CELIX_BIN_DIR and CELIX_LAUNCHER
-    if (TARGET Celix::framework)
-        #Celix Main Project
-        set(CELIX_LIB_DIRS "$<TARGET_FILE_DIR:Celix::framework>:$<TARGET_FILE_DIR:Celix::utils>:$<TARGET_FILE_DIR:Celix::dfi>")
-        set(CELIX_BIN_DIR  "$<TARGET_FILE_DIR:Celix::launcher>")
-    else ()
-	message(FATAL_ERROR "No Celix::framework target is defined. Did you use find_package(Celix REQUIRED)?")
-    endif()
-
-    #generate release.sh and optional run.sh
-    if(APPLE)
-        set(LIB_PATH_NAME "DYLD_LIBRARY_PATH")
-    else()
-        set(LIB_PATH_NAME "LD_LIBRARY_PATH")
-    endif()
-
-    set(RELEASE_SH ${CONTAINER_LOC}/release.sh)
-    set(RELEASE_CONTENT "#!/bin/sh\nexport ${LIB_PATH_NAME}=${CELIX_LIB_DIRS}:\${${LIB_PATH_NAME}}\nexport PATH=${CELIX_BIN_DIR}:\${PATH}")
-    file(GENERATE
-        OUTPUT ${RELEASE_SH}
-        CONTENT ${RELEASE_CONTENT}
-    )
-
-    set(RUN_SH ${CONTAINER_LOC}/run.sh)
-    set(RUN_CONTENT "${RELEASE_CONTENT}\n${LAUNCHER} \$@\n")
-    file(GENERATE
-        OUTPUT ${RUN_SH}
-        CONTENT ${RUN_CONTENT}
-    )
-
-    #generate eclipse project launch file
-    set(PROGRAM_NAME "${LAUNCHER}")
-    set(PROJECT_ATTR "${CMAKE_PROJECT_NAME}-build")
-    set(WORKING_DIRECTORY ${CONTAINER_LOC})
-    include("${CELIX_CMAKE_DIRECTORY}/RunConfig.in.cmake") #set VAR RUN_CONFIG_IN
-    file(GENERATE
-        OUTPUT "${CONTAINER_ECLIPSE_LAUNCHER}"
-        CONTENT "${RUN_CONFIG_IN}"
-    )
-
-    #add a custom target which can depend on generation expressions
-    add_custom_target(${CONTAINER_TARGET}-deps
-        DEPENDS
-            ${RUN_SH}
-            ${CONTAINER_ECLIPSE_LAUNCHER}
-            ${RELEASE_SH}
-            ${CONTAINER_PROPS}
-            $<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_TARGET_DEPS>
-    )
-    add_dependencies(${CONTAINER_TARGET} ${CONTAINER_TARGET}-deps)
-
-
-    ##### Container Target Properties #####
-    #internal use
-    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_TARGET_DEPS" "") #target deps for the container.
-    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_BUNDLES" "") #bundles to deploy fro the container.
-    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_COPY_BUNDLES" ${CONTAINER_COPY}) #copy bundles in bundle dir or link using abs paths. NOTE this cannot be changed after a add_deploy command
-
-    #deploy specific
-    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_NAME" "${CONTAINER_NAME}")
-    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_GROUP" "${CONTAINER_GROUP}")
-    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_LOC" "${CONTAINER_LOC}")
-    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_PROPERTIES" "")
-    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_EMBEDDED_PROPERTIES" "")
-    #####
-
-    celix_container_bundles(${CONTAINER_TARGET} ${CONTAINER_BUNDLES})
-    celix_container_properties(${CONTAINER_TARGET} ${CONTAINER_PROPERTIES})
-    celix_container_embedded_properties(${CONTAINER_TARGET} ${CONTAINER_EMBEDDED_PROPERTIES})
-
-
-    #ensure the container dir will be deleted during clean
-    get_directory_property(CLEANFILES ADDITIONAL_MAKE_CLEAN_FILES)
-    list(APPEND CLEANFILES "$<TARGET_PROPERTY:${CONTAINER_TARGET},CONTAINER_LOC>")
-    set_directory_properties(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "${CLEANFILES}")
-endfunction()
-
-
-#NOTE can be used for drivers/proxies/endpoints bundle dirs
-function(deploy_bundles_dir)
-    message(DEPRECATION "deploy_bundles_dir is depecrated, use celix_container_bundles_dir instead.")
-    celix_container_bundles_dir(${ARGN})
-endfunction()
-function(celix_container_bundles_dir)
-    list(GET ARGN 0 CONTAINER_TARGET)
-    list(REMOVE_AT ARGN 0)
-
-    set(OPTIONS)
-    set(ONE_VAL_ARGS DIR_NAME)
-    set(MULTI_VAL_ARGS BUNDLES)
-    cmake_parse_arguments(BD "${OPTIONS}" "${ONE_VAL_ARGS}" "${MULTI_VAL_ARGS}" ${ARGN})
-
-    if(NOT BD_DIR_NAME)
-        message(FATAL_ERROR "Missing mandatory DIR_NAME argument")
-    endif()
-
-    get_target_property(CONTAINER_LOC ${CONTAINER_TARGET} "CONTAINER_LOC")
-    get_target_property(DEPS ${CONTAINER_TARGET} "CONTAINER_TARGET_DEPS")
-
-    foreach(BUNDLE IN ITEMS ${BD_BUNDLES})
-        set(HANDLED FALSE)
-        if (IS_ABSOLUTE ${BUNDLE} AND EXISTS ${BUNDLE})
-            get_filename_component(BUNDLE_FILENAME ${BUNDLE} NAME) 
-            set(OUT "${CONTAINER_LOC}/${BD_DIR_NAME}/${BUNDLE_FILENAME}")
-            add_custom_command(OUTPUT ${OUT}
-                COMMAND ${CMAKE_COMMAND} -E copy_if_different ${BUNDLE} ${OUT}
-		        COMMENT "Copying (file) bundle '${BUNDLE}' to '${CONTAINER_LOC}/${BD_DIR_NAME}'"
-            )
-            set(HANDLED TRUE)
-        elseif (TARGET ${BUNDLE})
-            get_target_property(IMP ${BUNDLE} BUNDLE_IMPORTED)
-            if (IMP) #An imported bundle target -> handle target without DEPENDS
-                string(MAKE_C_IDENTIFIER ${BUNDLE} BUNDLE_ID) #Create id with no special chars (e.g. for target like Celix::shell)
-                set(OUT "${CMAKE_BINARY_DIR}/celix/gen/${CONTAINER_TARGET}-copy-bundle-for-target-${BUNDLE_ID}.timestamp")
-                set(DEST "${CONTAINER_LOC}/${BD_DIR_NAME}/$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILENAME>")
-                add_custom_command(OUTPUT ${OUT}
-                    COMMAND ${CMAKE_COMMAND} -E touch ${OUT}
-                    COMMAND ${CMAKE_COMMAND} -E make_directory ${CONTAINER_LOC}/${BD_DIR_NAME}
-                    COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILE>" ${DEST}
-                    COMMENT "Copying (imported) bundle '${BUNDLE}' to '${CONTAINER_LOC}/${BD_DIR_NAME}'"
-                )
-                set(HANDLED TRUE)
-            endif ()
-        endif ()
-
-        if (NOT HANDLED) #not a imported bundle target so (assuming) a future bundle target
-            string(MAKE_C_IDENTIFIER ${BUNDLE} BUNDLE_ID) #Create id with no special chars (e.g. for target like Celix::shell)
-            set(OUT "${CMAKE_BINARY_DIR}/celix/gen/${CONTAINER_TARGET}-copy-bundle-for-target-${BUNDLE_ID}.timestamp")
-            set(DEST "${CONTAINER_LOC}/${BD_DIR_NAME}/$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILENAME>")
-            add_custom_command(OUTPUT ${OUT}
-                COMMAND ${CMAKE_COMMAND} -E touch ${OUT}
-                COMMAND ${CMAKE_COMMAND} -E make_directory ${CONTAINER_LOC}/${BD_DIR_NAME}
-                COMMAND ${CMAKE_COMMAND} -E copy_if_different "$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILE>" ${DEST}
-                COMMENT "Copying (target) bundle '${BUNDLE}' to '${CONTAINER_LOC}/${BD_DIR_NAME}'"
-                DEPENDS ${BUNDLE} $<TARGET_PROPERTY:${BUNDLE},BUNDLE_CREATE_BUNDLE_TARGET>
-            )
-        endif()
-        list(APPEND DEPS "${OUT}")
-    endforeach()
-
-    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_TARGET_DEPS" "${DEPS}")
-endfunction()
-
-function(deploy_bundles)
-    message(DEPRECATION "deploy_bundles is depecrated, use celix_container_bundles instead.")
-    celix_container_bundles(${ARGN})
-endfunction()
-function(celix_container_bundles)
-    #0 is container TARGET
-    #1..n is bundles
-    list(GET ARGN 0 CONTAINER_TARGET)
-    list(REMOVE_AT ARGN 0)
-
-    get_target_property(BUNDLES ${CONTAINER_TARGET} "CONTAINER_BUNDLES")
-    get_target_property(COPY ${CONTAINER_TARGET} "CONTAINER_COPY_BUNDLES")
-    get_target_property(DEPS ${CONTAINER_TARGET} "CONTAINER_TARGET_DEPS")
-
-    foreach(BUNDLE IN ITEMS ${ARGN})
-        set(HANDLED FALSE)
-        if (IS_ABSOLUTE ${BUNDLE} AND EXISTS ${BUNDLE})
-               get_filename_component(BUNDLE_FILENAME ${BUNDLE} NAME)
-               set(COPY_LOC "bundles/${BUNDLE_FILENAME}")
-               set(ABS_LOC "${BUNDLE}")
-               set(HANDLED TRUE)
-           elseif (TARGET ${BUNDLE})
-               get_target_property(IMP ${BUNDLE} BUNDLE_IMPORTED)
-               if (IMP) #An imported bundle target -> handle target without DEPENDS
-                   set(COPY_LOC "bundles/$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILENAME>")
-                   set(ABS_LOC "$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILE>")
-                   set(HANDLED TRUE)
-               endif ()
-           endif ()
-
-           if (NOT HANDLED) #not a imported bundle target, so assuming a (future) bundle target
-               set(COPY_LOC "bundles/$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILENAME>")
-               set(ABS_LOC "$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILE>")
-
-               if (NOT COPY) #in case of COPY dep will be added in celix_container_bundles_dir
-                   string(MAKE_C_IDENTIFIER ${BUNDLE} BUNDLE_ID) #Create id with no special chars (e.g. for target like Celix::shell)
-                   set(OUT "${CMAKE_BINARY_DIR}/celix/gen/${CONTAINER_TARGET}-check-bundle-for-target-${BUNDLE_ID}.timestamp")
-                   add_custom_command(OUTPUT ${OUT}
-                       COMMAND ${CMAKE_COMMAND} -E touch ${OUT}
-                       DEPENDS ${BUNDLE} $<TARGET_PROPERTY:${BUNDLE},BUNDLE_CREATE_BUNDLE_TARGET>
-                   )
-                   list(APPEND DEPS ${OUT})
-               endif ()
-           endif ()
-           if(COPY)
-                list(APPEND BUNDLES ${COPY_LOC})
-           else()
-                list(APPEND BUNDLES ${ABS_LOC})
-           endif()
-   endforeach()
-
-    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_BUNDLES" "${BUNDLES}")
-    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_TARGET_DEPS" "${DEPS}")
-
-   if(COPY) 
-       celix_container_bundles_dir(${CONTAINER_TARGET} DIR_NAME bundles BUNDLES ${ARGN})
-   endif()
-endfunction()
-
-function(deploy_properties)
-    celix_container_properties(${ARGN})
-endfunction()
-function(celix_container_properties)
-    #0 is container TARGET
-    #1..n is bundles
-    list(GET ARGN 0 CONTAINER_TARGET)
-    list(REMOVE_AT ARGN 0)
-
-    get_target_property(PROPS ${CONTAINER_TARGET} "CONTAINER_PROPERTIES")
-
-    foreach(PROP IN ITEMS ${ARGN})
-        list(APPEND PROPS ${PROP})
-    endforeach()
-
-   set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_PROPERTIES" "${PROPS}")
-endfunction()
-
-function(deploy_embedded_properties)
-    message(DEPRECATION "deploy_embedded_properties is depecrated, use celix_container_embedded_properties instead.")
-    celix_container_embedded_properties(${ARGN})
-endfunction()
-function(celix_container_embedded_properties)
-    #0 is container TARGET
-    #1..n is bundles
-    list(GET ARGN 0 CONTAINER_TARGET)
-    list(REMOVE_AT ARGN 0)
-
-    get_target_property(PROPS ${CONTAINER_TARGET} "CONTAINER_EMBEDDED_PROPERTIES")
-
-    foreach(PROP IN ITEMS ${ARGN})
-        list(APPEND PROPS ${PROP})
-    endforeach()
-
-    set_target_properties(${CONTAINER_TARGET} PROPERTIES "CONTAINER_EMBEDDED_PROPERTIES" "${PROPS}")
-endfunction()

http://git-wip-us.apache.org/repos/asf/celix/blob/985c35f2/cmake/cmake_celix/DockerPackaging.cmake
----------------------------------------------------------------------
diff --git a/cmake/cmake_celix/DockerPackaging.cmake b/cmake/cmake_celix/DockerPackaging.cmake
index af3cf71..2faca5c 100644
--- a/cmake/cmake_celix/DockerPackaging.cmake
+++ b/cmake/cmake_celix/DockerPackaging.cmake
@@ -112,7 +112,7 @@ $<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_EMBEDDED_PROPERTIES>,\\n\\
 >\";
 
     properties_pt packedConfig = properties_loadFromString(config);
-    return celixLauncher_launchWithArgsAndProps(argc, argv, packedConfig);
+    return celixLauncher_launchAndWaitForShutdown(argc, argv, packedConfig);
 }
 "
         )
@@ -152,7 +152,12 @@ $<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_EMBEDDED_PROPERTIES>,\\n\\
     set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_FROM" "${DOCKER_FROM}") #name of docker base, default celix-base
     set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_IMAGE_NAME" "${DOCKER_IMAGE_NAME}") #name of docker images, default deploy target name
     set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_BUNDLES_DIR" "${DOCKER_BUNDLES_DIR}") #bundles directory in docker image
-    set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_BUNDLES" "") #bundles
+    set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_BUNDLES_LEVEL_0" "") #bundles for runtime level 0
+    set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_BUNDLES_LEVEL_1" "") #bundles for runtime level 1
+    set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_BUNDLES_LEVEL_2" "") #bundles for runtime level 2
+    set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_BUNDLES_LEVEL_3" "") #bundles for runtime level 3
+    set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_BUNDLES_LEVEL_4" "") #bundles for runtime level 4
+    set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_BUNDLES_LEVEL_5" "") #bundles for runtime level 5
     set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_WORKDIR" "${DOCKER_WORKDIR}") #workdir in docker image, should also contain the config.properties
     set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_ENTRYPOINT" "${DOCKER_ENTRYPOINT}")
     set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_CREATE_FS" "${DOCKER_CREATE_FS}") #wether to create a fs with the minimal needed libraries / etc files
@@ -161,7 +166,7 @@ $<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_EMBEDDED_PROPERTIES>,\\n\\
     set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_EMBEDDED_PROPERTIES" "")
     set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_DEPS" "")
 
-    set(DOCKERFILE_STAGE1 ${CMAKE_BINARY_DIR}/celix/gen/${DOCKER_TARGET}-Dockerfile.in)
+    set(DOCKERFILE_STAGE1 ${CMAKE_BINARY_DIR}/celix/gen/${DOCKER_TARGET}/Dockerfile.in)
     set(DOCKERFILE "$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_LOC>/Dockerfile")
 
     file(GENERATE
@@ -182,10 +187,15 @@ $<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_INSTRUCTIONS>,
 
     #generate config.properties
     set(DOCKER_PROPERTIES_FILE "${DOCKER_LOC}/${DOCKER_WORKDIR}/config.properties")
-    set(STAGE1_PROPERTIES_FILE "${CMAKE_BINARY_DIR}/celix/gen/${DOCKER_TARGET}-docker-config-stage1.properties")
+    set(STAGE1_PROPERTIES_FILE "${CMAKE_BINARY_DIR}/celix/gen/${DOCKER_TARGET}/docker-config-stage1.properties")
     file(GENERATE
             OUTPUT "${STAGE1_PROPERTIES_FILE}"
-            CONTENT "cosgi.auto.start.1=$<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_BUNDLES>, >
+            CONTENT "CELIX_AUTO_START_0=$<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_BUNDLES_LEVEL_0>, >
+CELIX_AUTO_START_1=$<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_BUNDLES_LEVEL_1>, >
+CELIX_AUTO_START_2=$<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_BUNDLES_LEVEL_2>, >
+CELIX_AUTO_START_3=$<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_BUNDLES_LEVEL_3>, >
+CELIX_AUTO_START_4=$<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_BUNDLES_LEVEL_4>, >
+CELIX_AUTO_START_5=$<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_BUNDLES_LEVEL_5>, >
 $<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_PROPERTIES>,
 >
 "
@@ -196,7 +206,7 @@ $<JOIN:$<TARGET_PROPERTY:${DOCKER_TARGET},DOCKER_PROPERTIES>,
     )
 
     if (DOCKER_BUNDLES)
-        celix_docker_bundles(${DOCKER_TARGET} ${DOCKER_BUNDLES})
+        celix_docker_bundles(${DOCKER_TARGET} LEVEL 1 ${DOCKER_BUNDLES})
     endif()
     if (DOCKER_PROPERTIES)
         celix_docker_properties(${DOCKER_TARGET} ${DOCKER_PROPERTIES})
@@ -224,12 +234,22 @@ function(celix_docker_bundles)
     list(GET ARGN 0 DOCKER_TARGET)
     list(REMOVE_AT ARGN 0)
 
-    get_target_property(BUNDLES ${DOCKER_TARGET} "DOCKER_BUNDLES")
+    set(OPTIONS )
+    set(ONE_VAL_ARGS LEVEL)
+    set(MULTI_VAL_ARGS )
+    cmake_parse_arguments(BUNDLES "${OPTIONS}" "${ONE_VAL_ARGS}" "${MULTI_VAL_ARGS}" ${ARGN})
+    set(BUNDLES_LIST ${BUNDLES_UNPARSED_ARGUMENTS})
+
+    if (NOT BUNDLES_LEVEL)
+        set(BUNDLES_LEVEL 1)
+    endif ()
+
+    get_target_property(BUNDLES ${DOCKER_TARGET} "DOCKER_BUNDLES_LEVEL_${BUNDLES_LEVEL}")
     get_target_property(BUNDLES_DIR ${DOCKER_TARGET} "DOCKER_BUNDLES_DIR")
     get_target_property(LOC ${DOCKER_TARGET} "DOCKER_LOC")
     get_target_property(DEPS ${DOCKER_TARGET} "DOCKER_DEPS")
 
-    foreach(BUNDLE IN ITEMS ${ARGN})
+    foreach(BUNDLE IN ITEMS ${BUNDLES_LIST})
         set(HANDLED FALSE)
         if(IS_ABSOLUTE ${BUNDLE} AND EXISTS ${BUNDLE})
             get_filename_component(BUNDLE_FILENAME ${BUNDLE} NAME)
@@ -245,7 +265,7 @@ function(celix_docker_bundles)
             get_target_property(IMP ${BUNDLE} BUNDLE_IMPORTED)
             if (IMP) #An imported bundle target -> handle target without DEPENDS
                 string(MAKE_C_IDENTIFIER ${BUNDLE} BUNDLE_ID) #Create id with no special chars (e.g. for target like Celix::shell)
-                set(OUT "${CMAKE_BINARY_DIR}/celix/gen/${DOCKER_TARGET}-copy-bundle-for-target-${BUNDLE_ID}.timestamp")
+                set(OUT "${CMAKE_BINARY_DIR}/celix/gen/${DOCKER_TARGET}/copy-bundle-for-target-${BUNDLE_ID}.timestamp")
                 set(DEST "${LOC}/${BUNDLES_DIR}/$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILENAME>")
                 add_custom_command(OUTPUT ${OUT}
                     COMMAND ${CMAKE_COMMAND} -E touch ${OUT}
@@ -260,7 +280,7 @@ function(celix_docker_bundles)
 
         if(NOT HANDLED) #assuming (future) bundle target
             string(MAKE_C_IDENTIFIER ${BUNDLE} BUNDLE_ID) #Create id with no special chars (e.g. for target like Celix::shell)
-            set(OUT "${CMAKE_BINARY_DIR}/celix/gen/${DOCKER_TARGET}-copy-bundle-for-target-${BUNDLE_ID}.timestamp")
+            set(OUT "${CMAKE_BINARY_DIR}/celix/gen/${DOCKER_TARGET}/copy-bundle-for-target-${BUNDLE_ID}.timestamp")
             set(DEST "${LOC}/${BUNDLES_DIR}/$<TARGET_PROPERTY:${BUNDLE},BUNDLE_FILENAME>")
             add_custom_command(OUTPUT ${OUT}
                     COMMAND ${CMAKE_COMMAND} -E touch ${OUT}
@@ -274,7 +294,7 @@ function(celix_docker_bundles)
         list(APPEND DEPS "${OUT}")
     endforeach()
 
-    set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_BUNDLES" "${BUNDLES}")
+    set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_BUNDLES_LEVEL_${BUNDLES_LEVEL}" "${BUNDLES}")
     set_target_properties(${DOCKER_TARGET} PROPERTIES "DOCKER_DEPS" "${DEPS}")
 endfunction()
 

http://git-wip-us.apache.org/repos/asf/celix/blob/985c35f2/cmake/cmake_celix/UseCelix.cmake
----------------------------------------------------------------------
diff --git a/cmake/cmake_celix/UseCelix.cmake b/cmake/cmake_celix/UseCelix.cmake
index 6607c39..a68cd9c 100644
--- a/cmake/cmake_celix/UseCelix.cmake
+++ b/cmake/cmake_celix/UseCelix.cmake
@@ -21,7 +21,7 @@ include(CMakeParseArguments)
 set(CELIX_CMAKE_DIRECTORY ${CMAKE_CURRENT_LIST_DIR})
 set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} ${CELIX_CMAKE_DIRECTORY}/../Modules)
 include(${CELIX_CMAKE_DIRECTORY}/BundlePackaging.cmake)
-include(${CELIX_CMAKE_DIRECTORY}/DeployPackaging.cmake)
+include(${CELIX_CMAKE_DIRECTORY}/ContainerPackaging.cmake)
 include(${CELIX_CMAKE_DIRECTORY}/DockerPackaging.cmake)
 include(${CELIX_CMAKE_DIRECTORY}/Runtimes.cmake)
 include(${CELIX_CMAKE_DIRECTORY}/Generic.cmake)

http://git-wip-us.apache.org/repos/asf/celix/blob/985c35f2/documents/cmake_commands/readme.md
----------------------------------------------------------------------
diff --git a/documents/cmake_commands/readme.md b/documents/cmake_commands/readme.md
index df62ff3..205e10d 100644
--- a/documents/cmake_commands/readme.md
+++ b/documents/cmake_commands/readme.md
@@ -27,8 +27,6 @@ Add a Celix bundle to the project.  There are three variants:
 - With ACTIVATOR the bundle will be created using the library target or absolute path to existing library as activator library.
 - With no SOURCES or ACTIVATOR a bundle without a activator will be created.
 
-Also available under the add_bundle CMake function (deprecated).
-
 ```CMake
 add_celix_bundle(<bundle_target_name> 
     SOURCES source1 source2 ...
@@ -174,8 +172,6 @@ Celix containers can be used to run/test a selection of bundles in the celix fra
 A Celix container can be found in `<cmake_build_dir>/deploy[/<group_name>]/<celix_container_name>`. 
 Use the `<celix_container_name>` executable to run the deployments.
 
-Also available under the add_deploy CMake function (deprecated).
-
 ```CMake
 add_celix_container(<celix_container_name>
     [COPY] 
@@ -189,15 +185,6 @@ add_celix_container(<celix_container_name>
 )
 ```
 
-The provided bundle targets for a celix container do not have to exists (yet).
-This removes the need for correctly ordering the add_celix_bundle commands so that all bundle target are present before an add_celix_container command.
-If the bundle target is never added CMake will give an error:
-```
-  Error evaluating generator expression:
-
-    $<TARGET_PROPERTY:foo,BUNDLE_FILE>
-```
-
 - If the COPY option is provided the selected bundles will be copied in a bundles dir and the generated config.properties will use relative paths to the bundle locations. Default bundles will not be copied and the generated config.properties will use absolute references to the bundle locations.
 - If CXX option is provided the celix container launcher will be build as C++ executable and as result be linked with the required C++ libraries of the used compiler
 - If GROUP is provided the celix container will be grouped in the provided group name. 
@@ -207,30 +194,25 @@ If the bundle target is never added CMake will give an error:
 - If BUNDLES is provided the list of bundles will be added the the generated config.properties for startup. Combined with COPY the bundles will also be copied to a bundles dir.
 - If PROPERTIES is provided the list of properties will be appended to the generated config.properties
 
-## celix_container_bundles_dir
-Deploy a selection of bundles to the provided bundle dir. This can be used to create an endpoints / proxies bundles dir for the remote service admin or drivers bundles dir for the device access. 
-
-```CMake
-celix_container_bundles_dir(<celix_container_target_name>
-    DIR_NAME dir_name
-    BUNDLES 
-        bundle1 
-        bundle2 
-        ...
-)
-```
-
 ## celix_container_bundles
-Deploy the selected bundles. The bundles are configured for auto starting. 
+Add the selected bundles to the container.
+The bundles are configured for auto starting.
 
 ```CMake
 celix_container_bundles(<celix_container_target_name>
+    [LEVEL (0..5)]
     bundle1 
     bundle2 
     ...
 )
 ```
 
+- If the LEVEL is provided this will be used as the bundle run level.
+  If no run level is provided run level 1 is used.
+  Run levels can be used to control to start order of the bundles.
+  Bundles in run level 0 arre started first and bundles in run level 5
+  are started last.
+
 ## celix_container_properties
 Add the provided properties to the target Celix container config.properties.
 
@@ -255,6 +237,19 @@ celix_container_embedded_properties(<celix_container_target_name>
 )
 ```
 
+## celix_container_bundles_dir
+Deploy a selection of bundles to the provided bundle dir. This can be used to create an endpoints / proxies bundles dir for the remote service admin or drivers bundles dir for the device access.
+
+```CMake
+celix_container_bundles_dir(<celix_container_target_name>
+    DIR_NAME dir_name
+    BUNDLES
+        bundle1
+        bundle2
+        ...
+)
+```
+
 # Celix Docker Images
 It is possible the use the `add_celix_docker` Apache Celix CMake command to create Apache Celix docker directories,
 which in turn can be used to create very small Apache Celix docker images.
@@ -266,18 +261,16 @@ Also includes the selected bundles.
 
 The add_celix_docker target is a executable target and can be used to link libraries which are needed in the docker image.
 
-The docker dir can be found in `<cmake_build_dir>/docker[/<group_name>]/<docker_name>`. 
-  
-The provided bundle targets for a docker dir do not have to exists (yet).
-This removes the need for correctly order the add_celix_bundle commands so that all bundle target are present before 
-an `add_celix_docker` command.
-If the bundle target is never added CMake will give an error:
-  ```
-    Error evaluating generator expression:
-  
-      $<TARGET_PROPERTY:foo,BUNDLE_FILE>
-  ```
- 
+The docker dir can be found in `<cmake_build_dir>/docker[/<group_name>]/<docker_name>`.
+
+The docker directories are build with the target `celix-build-docker-dirs`, this does not create the
+docker images and can also be executed on systems without docker. The `celix-build-docker-dirs` is trigger
+with `make all`.
+
+The docker images are build with the target `celix-build-docker-images`. For this to work docker needs te installed
+and the user executing the `celix-build-docker-images` should have right to create docker images.
+The `celix-build-docker-images` is not triggered with `make all`
+
 ```CMake
 add_celix_docker(<docker_target_name>
     [CXX]
@@ -305,3 +298,56 @@ add_celix_docker(<docker_target_name>
  `config.properties`
 - If PROPERTIES is provided, the list of properties will added to the generated `config.properties` file
 - If INSTRUCTIONS id provided, the list of docker instructions will be added the the generated `Dockerfile`
+
+## celix_docker_bundles
+
+Same as `celix_container_bundles`, but then for the celix container
+in the docker image.
+
+```CMake
+celix_docker_bundles(<docker_target_name>
+    [LEVEL (0..5)]
+    bundle1
+    bundle2
+    ...
+)
+```
+
+## celix_docker_properties
+
+Same as `celix_container_properties`, but then for the celix container
+in the docker image.
+
+```CMake
+celix_docker_properties(<docker_target_name>
+    "prop1=val1"
+    "prop2=val2"
+    ...
+)
+```
+
+## celix_docker_embedded_properties
+
+Same as `celix_container_embedded_properties`, but then for the celix container
+in the docker image.
+
+```CMake
+celix_docker_embedded_properties(<docker_target_name>
+    "prop1=val1"
+    "prop2=val2"
+    ...
+)
+```
+
+## celix_docker_instructions
+
+Add the provided docker instruction to the end of the generated
+Dockerfile.
+
+```CMake
+celix_docker_instructions(<docker_target_name>
+    "instruction1"
+    "instruction2"
+    ...
+)
+```
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/985c35f2/framework/include/bundle_context.h
----------------------------------------------------------------------
diff --git a/framework/include/bundle_context.h b/framework/include/bundle_context.h
index 2844d7d..f806cb5 100644
--- a/framework/include/bundle_context.h
+++ b/framework/include/bundle_context.h
@@ -79,7 +79,7 @@ bundleContext_registerServiceFactory(bundle_context_pt context, const char *serv
  * @param properties The meta properties assiated with the service. The service registration will take ownership of the properties
  * @return The serviceId or < 0 if registration was unsuccessful.
  */
-long bundleContext_registerCService(bundle_context_t *ctx, const char *serviceName, void *svc, properties_t *properties);
+long bundleContext_registerCService(bundle_context_t *ctx, const char *serviceName, void *svc, properties_t *properties, const char *serviceVersion);
 
 /**
 * Register a service for the specified language to the framework.
@@ -90,7 +90,7 @@ long bundleContext_registerCService(bundle_context_t *ctx, const char *serviceNa
 * @param properties The meta properties assiated with the service. The service registration will take ownership of the properties
 * @return The serviceId or < 0 if registration was unsuccessful.
 */
-long bundleContext_registerServiceForLang(bundle_context_t *ctx, const char *serviceName, void *svc, properties_t *properties, const char* lang);
+long bundleContext_registerServiceForLang(bundle_context_t *ctx, const char *serviceName, void *svc, properties_t *properties, const char *serviceVersion, const char* lang);
 
 /**
  * Unregister the service with service id. The service will only be unregistered if the bundle of the bundle context
@@ -114,6 +114,7 @@ void bundleContext_unregisterService(bundle_context_t *ctx, long serviceId);
  *
  * @param ctx The bundle context
  * @param serviceId the service id.
+ * @param serviceName the service name of the service. Should match with the registered service name of the provided service id (sanity check)
  * @param callbackHandle The data pointer, which will be used in the callbacks
  * @param use The callback, which will be called when service is retrieved.
  * @param bool returns true if a service was found.
@@ -121,6 +122,7 @@ void bundleContext_unregisterService(bundle_context_t *ctx, long serviceId);
 bool bundleContext_useServiceWithId(
         bundle_context_t *ctx,
         long serviceId,
+        const char *serviceName,
         void *callbackHandle,
         void (*use)(void *handle, void* svc, const properties_t *props, const bundle_t *owner)
 );

http://git-wip-us.apache.org/repos/asf/celix/blob/985c35f2/framework/include/celix_api.h
----------------------------------------------------------------------
diff --git a/framework/include/celix_api.h b/framework/include/celix_api.h
new file mode 100644
index 0000000..266b57e
--- /dev/null
+++ b/framework/include/celix_api.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 CELIX_CELIX_API_H_
+#define CELIX_CELIX_API_H_
+
+#include "celix_utils_api.h"
+#include "bundle.h"
+#include "bundle_context.h"
+#include "service_registration.h"
+#include "service_factory.h"
+#include "service_reference.h"
+#include "service_tracker.h"
+#include "service_tracker_customizer.h"
+#include "listener_hook_service.h"
+#include "framework.h"
+#include "celix_framework_factory.h"
+#include "celix_launcher.h"
+
+#endif //CELIX_CELIX_API_H_

http://git-wip-us.apache.org/repos/asf/celix/blob/985c35f2/framework/include/celix_launcher.h
----------------------------------------------------------------------
diff --git a/framework/include/celix_launcher.h b/framework/include/celix_launcher.h
index 5c7cf4d..579eef7 100644
--- a/framework/include/celix_launcher.h
+++ b/framework/include/celix_launcher.h
@@ -34,21 +34,80 @@
 extern "C" {
 #endif
 
-int celixLauncher_launchWithArgs(int argc, char *argv[]);
 
-int celixLauncher_launchWithArgsAndProps(int argc, char *argv[], properties_pt config);
+/**
+ * Launched a celix framework and wait (block) till the framework is stopped.
+ * The function will also destroy the framework when it has been stopped.
+ *
+ * The launcher will also setup signal handlers for SIGINT, SIGTERM, SIGUSR1 and SIGUSR2 and initialize libcurl.
+ * For SIGINT and SIGTERM the framework will be stopped
+ * SIGUSR1 and SIGUSR2 will be ignored.
+ *
+ *
+ * @param argc argc as provided in a main function.
+ * @param argv argv as provided in a main function.
+ * @param embeddedConfig The optional embbeded config, will be overriden with the config.properties if found.
+ * @return CELIX_SUCCESS if successful.
+ */
+int celixLauncher_launchAndWaitForShutdown(int argc, char *argv[], properties_t *embeddedConfig);
+
 
-int celixLauncher_launch(const char *configFile, framework_pt *framework);
+/**
+ * Launches the a celix framework and returns the framework.
+ *
+ * The launcher will also setup signal handlers for SIGINT, SIGTERM, SIGUSR1 and SIGUSR2 and initialize libcurl.
+ * For SIGINT and SIGTERM the framework will be stopped
+ * SIGUSR1 and SIGUSR2 will be ignored.
+ *
+ * @param configFile Path to the config file (config.properties)
+ * @param framework Output parameter for the framework.
+ * @return CELIX_SUCCESS if successful. 
+ */
+int celixLauncher_launch(const char *configFile, framework_t **framework);
 
-int celixLauncher_launchWithStream(FILE *config, framework_pt *framework);
+/**
+ * Launches the a celix framework and returns the framework.
+ *
+ * The launcher will also setup signal handlers for SIGINT, SIGTERM, SIGUSR1 and SIGUSR2 and initialize libcurl.
+ * For SIGINT and SIGTERM the framework will be stopped
+ * SIGUSR1 and SIGUSR2 will be ignored.
+ *
+ * @param config FILE* to the config file (config.properties)
+ * @param framework Output parameter for the framework.
+ * @return CELIX_SUCCESS if successful.
+ */
+int celixLauncher_launchWithStream(FILE *config, framework_t **framework);
 
-int celixLauncher_launchWithProperties(properties_pt config, framework_pt *framework);
+/**
+ * Launches the a celix framework and returns the framework.
+ *
+ * The launcher will also setup signal handlers for SIGINT, SIGTERM, SIGUSR1 and SIGUSR2 and initialize libcurl.
+ * For SIGINT and SIGTERM the framework will be stopped
+ * SIGUSR1 and SIGUSR2 will be ignored.
+ *
+ * @param config the config properties.
+ * @param framework Output parameter for the framework.
+ * @return CELIX_SUCCESS if successful.
+ */
+int celixLauncher_launchWithProperties(properties_t *config, framework_t **framework);
 
-void celixLauncher_stop(framework_pt framework);
+/**
+ * Wait (blocks) for the shutdown of the provided celix framework.
+ * @param framework The framework to wait for.
+ */
+void celixLauncher_waitForShutdown(framework_t *framework);
 
-void celixLauncher_destroy(framework_pt framework);
+/**
+ * Stop the provided celix framework.
+ * @param framework The framework to stop.
+ */
+void celixLauncher_stop(framework_t *framework);
 
-void celixLauncher_waitForShutdown(framework_pt framework);
+/**
+ * Destroys the provided framework and if needed stops it first.
+ * @param framework The framework to stop.
+ */
+void celixLauncher_destroy(framework_t *framework);
 
 #ifdef __cplusplus
 }

http://git-wip-us.apache.org/repos/asf/celix/blob/985c35f2/framework/include/constants.h
----------------------------------------------------------------------
diff --git a/framework/include/constants.h b/framework/include/constants.h
index 5a01016..e0e56cf 100644
--- a/framework/include/constants.h
+++ b/framework/include/constants.h
@@ -54,12 +54,19 @@ static const char *const OSGI_FRAMEWORK_PRIVATE_LIBRARY = "Private-Library";
 static const char *const OSGI_FRAMEWORK_EXPORT_LIBRARY = "Export-Library";
 static const char *const OSGI_FRAMEWORK_IMPORT_LIBRARY = "Import-Library";
 
-
 static const char *const OSGI_FRAMEWORK_FRAMEWORK_STORAGE = "org.osgi.framework.storage";
 static const char *const OSGI_FRAMEWORK_FRAMEWORK_STORAGE_CLEAN = "org.osgi.framework.storage.clean";
 static const char *const OSGI_FRAMEWORK_FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT = "onFirstInit";
 static const char *const OSGI_FRAMEWORK_FRAMEWORK_UUID = "org.osgi.framework.uuid";
 
+#define CELIX_AUTO_START_0 "CELIX_AUTO_START_0"
+#define CELIX_AUTO_START_1 "CELIX_AUTO_START_1"
+#define CELIX_AUTO_START_2 "CELIX_AUTO_START_2"
+#define CELIX_AUTO_START_3 "CELIX_AUTO_START_3"
+#define CELIX_AUTO_START_4 "CELIX_AUTO_START_4"
+#define CELIX_AUTO_START_5 "CELIX_AUTO_START_5"
+
+
 #ifdef __cplusplus
 }
 #endif

http://git-wip-us.apache.org/repos/asf/celix/blob/985c35f2/framework/private/mock/bundle_context_mock.c
----------------------------------------------------------------------
diff --git a/framework/private/mock/bundle_context_mock.c b/framework/private/mock/bundle_context_mock.c
index 689f0bb..4ac6404 100644
--- a/framework/private/mock/bundle_context_mock.c
+++ b/framework/private/mock/bundle_context_mock.c
@@ -194,21 +194,23 @@ celix_status_t bundleContext_getProperty(bundle_context_pt context, const char *
 	return mock_c()->returnValue().value.intValue;
 }
 
-long bundleContext_registerCService(bundle_context_t *ctx, const char *serviceName, void *svc, properties_t *properties) {
+long bundleContext_registerCService(bundle_context_t *ctx, const char *serviceName, void *svc, properties_t *properties, const char *serviceVersion) {
 	mock_c()->actualCall("bundleContext_registerCService")
 			->withPointerParameters("ctx", ctx)
 			->withStringParameters("serviceName", serviceName)
 			->withPointerParameters("svc", svc)
-			->withPointerParameters("properties", properties);
+			->withPointerParameters("properties", properties)
+			->withStringParameters("serviceName", serviceVersion);
 	return mock_c()->returnValue().value.longIntValue;
 }
 
-long bundleContext_registerServiceForLang(bundle_context_t *ctx, const char *serviceName, void *svc, properties_t *properties, const char* lang) {
+long bundleContext_registerServiceForLang(bundle_context_t *ctx, const char *serviceName, void *svc, properties_t *properties, const char *serviceVersion, const char* lang) {
 	mock_c()->actualCall("bundleContext_registerServiceForLang")
 			->withPointerParameters("ctx", ctx)
 			->withStringParameters("serviceName", serviceName)
 			->withConstPointerParameters("svc", svc)
 			->withPointerParameters("properties", properties)
+			->withStringParameters("serviceName", serviceVersion)
 			->withStringParameters("lang", lang);
 	return mock_c()->returnValue().value.longIntValue;
 }
@@ -222,12 +224,14 @@ void bundleContext_unregisterService(bundle_context_t *ctx, long serviceId) {
 bool bundleContext_useServiceWithId(
 		bundle_context_t *ctx,
 		long serviceId,
+		const char *serviceName,
 		void *callbackHandle,
 		void (*use)(void *handle, void* svc, const properties_t *props, const bundle_t *owner)
 ) {
 	mock_c()->actualCall("bundleContext_registerServiceForLang")
 			->withPointerParameters("ctx", ctx)
 			->withLongIntParameters("serviceId", serviceId)
+			->withStringParameters("serviceName", serviceName)
 			->withPointerParameters("callbackHandle", callbackHandle)
 			->withPointerParameters("use", use);
 	return mock_c()->returnValue().value.boolValue;

http://git-wip-us.apache.org/repos/asf/celix/blob/985c35f2/framework/src/bundle_context.c
----------------------------------------------------------------------
diff --git a/framework/src/bundle_context.c b/framework/src/bundle_context.c
index 569691a..cf609c9 100644
--- a/framework/src/bundle_context.c
+++ b/framework/src/bundle_context.c
@@ -375,7 +375,7 @@ celix_status_t bundleContext_getProperty(bundle_context_pt context, const char *
 celix_status_t bundleContext_getPropertyWithDefault(bundle_context_pt context, const char* name, const char* defaultValue, const char** value) {
     celix_status_t status = CELIX_SUCCESS;
 
-    if (context == NULL || name == NULL || *value != NULL) {
+    if (context == NULL || name == NULL) {
         status = CELIX_ILLEGAL_ARGUMENT;
     } else {
         fw_getProperty(context->framework, name, defaultValue, value);
@@ -387,17 +387,20 @@ celix_status_t bundleContext_getPropertyWithDefault(bundle_context_pt context, c
 }
 
 
-long bundleContext_registerCService(bundle_context_t *ctx, const char *serviceName, void *svc, properties_t *properties) {
-    return bundleContext_registerServiceForLang(ctx, serviceName, svc, properties, CELIX_FRAMEWORK_SERVICE_C_LANGUAGE);
+long bundleContext_registerCService(bundle_context_t *ctx, const char *serviceName, void *svc, properties_t *properties, const char *serviceVersion) {
+    return bundleContext_registerServiceForLang(ctx, serviceName, svc, properties, serviceVersion, CELIX_FRAMEWORK_SERVICE_C_LANGUAGE);
 }
 
 
-long bundleContext_registerServiceForLang(bundle_context_t *ctx, const char *serviceName, void *svc, properties_t *properties, const char* lang) {
+long bundleContext_registerServiceForLang(bundle_context_t *ctx, const char *serviceName, void *svc, properties_t *properties, const char *serviceVersion, const char* lang) {
     long svcId = -1;
     if (properties == NULL) {
         properties = properties_create();
     }
     service_registration_t *reg = NULL;
+    if (serviceVersion != NULL) {
+        properties_set(properties, CELIX_FRAMEWORK_SERVICE_VERSION, serviceVersion);
+    }
     if (serviceName != NULL && lang != NULL) {
         properties_set(properties, CELIX_FRAMEWORK_SERVICE_LANGUAGE, lang);
         bundleContext_registerService(ctx, serviceName, svc, properties, &reg);
@@ -449,6 +452,7 @@ void bundleContext_unregisterService(bundle_context_t *ctx, long serviceId) {
 bool bundleContext_useServiceWithId(
         bundle_context_t *ctx,
         long serviceId,
+        const char *serviceName,
         void *callbackHandle,
         void (*use)(void *handle, void *svc, const properties_t *props, const bundle_t *owner)) {
     bool called = false;
@@ -460,12 +464,22 @@ bool bundleContext_useServiceWithId(
 	serviceTracker_open(trk);
         bundle_t *bnd = NULL;
         properties_t *props = NULL;
+        const char *registerServiceName = NULL;
+        bool sameName = false;
         void *svc = serviceTracker_lockAndGetService(trk, &props, &bnd);
-        if (svc != NULL) {
+        if (props != NULL) {
+            registerServiceName = properties_get(props, OSGI_FRAMEWORK_OBJECTCLASS);
+            sameName = strncmp(serviceName, registerServiceName, 1024*1024*10) == 0;
+        }
+        if (svc != NULL && sameName) {
             use(callbackHandle, svc, props, bnd);
             called = true;
-            serviceTracker_unlockAndUngetService(trk, svc);
+        } else if (svc != NULL) {
+            framework_logIfError(logger, CELIX_ILLEGAL_ARGUMENT, NULL,
+                                 "Service with id %li does not have service name '%s', but has service name '%s'",
+                                 serviceId, serviceName, registerServiceName);
         }
+        serviceTracker_unlockAndUngetService(trk, svc);
         serviceTracker_close(trk);
         serviceTracker_destroy(trk);
     }

http://git-wip-us.apache.org/repos/asf/celix/blob/985c35f2/framework/src/celix_launcher.c
----------------------------------------------------------------------
diff --git a/framework/src/celix_launcher.c b/framework/src/celix_launcher.c
index 6cff8ef..b67faad 100644
--- a/framework/src/celix_launcher.c
+++ b/framework/src/celix_launcher.c
@@ -55,14 +55,7 @@ static int celixLauncher_launchWithStreamAndProps(FILE *stream, framework_pt *fr
 
 static framework_pt framework = NULL;
 
-/**
- * Method kept because of usage in examples & unit tests
- */
-int celixLauncher_launchWithArgs(int argc, char *argv[]) {
-	return celixLauncher_launchWithArgsAndProps(argc, argv, NULL);
-}
-
-int celixLauncher_launchWithArgsAndProps(int argc, char *argv[], properties_pt packedConfig) {
+int celixLauncher_launchAndWaitForShutdown(int argc, char *argv[], properties_pt packedConfig) {
 	// Perform some minimal command-line option parsing...
 	char *opt = NULL;
 	if (argc > 1) {
@@ -123,35 +116,14 @@ int celixLauncher_launch(const char *configFile, framework_pt *framework) {
 static int celixLauncher_launchWithConfigAndProps(const char *configFile, framework_pt *framework, properties_pt packedConfig){
 	int status = 0;
 	FILE *config = fopen(configFile, "r");
+	if (packedConfig == NULL) {
+		packedConfig = properties_create();
+	}
 
-	if (config != NULL && packedConfig != NULL) {
+	if (config != NULL) {
 		status = celixLauncher_launchWithStreamAndProps(config, framework, packedConfig);
-	} else if (config != NULL) {
-		status = celixLauncher_launchWithStream(config, framework);
-	} else if (packedConfig != NULL) {
-		status = celixLauncher_launchWithProperties(packedConfig, framework);
 	} else {
-		fprintf(stderr, "Error: invalid or non-existing configuration file: '%s'.", configFile);
-		perror("");
-		status = 1;
-	}
-
-	return status;
-}
-
-int celixLauncher_launchWithStream(FILE *stream, framework_pt *framework) {
-	int status = 0;
-
-	properties_pt config = properties_loadWithStream(stream);
-	fclose(stream);
-	// Make sure we've read it and that nothing went wrong with the file access...
-	if (config == NULL) {
-		fprintf(stderr, "Error: invalid configuration file");
-		perror(NULL);
-		status = 1;
-	}
-	else {
-		status = celixLauncher_launchWithProperties(config, framework);
+		status = celixLauncher_launchWithProperties(packedConfig, framework);
 	}
 
 	return status;
@@ -221,74 +193,15 @@ int celixLauncher_launchWithProperties(properties_pt config, framework_pt *frame
 	curl_global_init(CURL_GLOBAL_NOTHING);
 #endif
 
-	const char* autoStartProp = properties_get(config, "cosgi.auto.start.1");
-	char* autoStart = NULL;
-	if (autoStartProp != NULL) {
-		autoStart = strndup(autoStartProp, 1024*10);
-	}
 
-    bundle_context_t *context = NULL;
 	status = framework_create(framework, config);
 	if (status == CELIX_SUCCESS) {
 		status = framework_start(*framework);
-
-	}
-    if (status == CELIX_SUCCESS) {
-        context = framework_getContext(*framework);
-    }
-
-	if (context != NULL && status == CELIX_SUCCESS) {
-		char delims[] = " ";
-		char *result = NULL;
-		char *save_ptr = NULL;
-		linked_list_pt bundles = NULL;
-		array_list_pt installed = NULL;
-		linked_list_iterator_pt iter = NULL;
-		unsigned int i;
-
-		linkedList_create(&bundles);
-		if (autoStart != NULL) {
-			result = strtok_r(autoStart, delims, &save_ptr);
-			while (result != NULL) {
-				char *location = strdup(result);
-				linkedList_addElement(bundles, location);
-				result = strtok_r(NULL, delims, &save_ptr);
-			}
-		}
-		// First install all bundles
-		// Afterwards start them
-		arrayList_create(&installed);
-		iter = linkedListIterator_create(bundles, 0);
-		while (linkedListIterator_hasNext(iter)) {
-			bundle_pt current = NULL;
-			char *location = (char *) linkedListIterator_next(iter);
-			if (bundleContext_installBundle(context, location, &current) == CELIX_SUCCESS) {
-				// Only add bundle if it is installed correctly
-				arrayList_add(installed, current);
-			} else {
-				printf("Could not install bundle from %s\n", location);
-			}
-			linkedListIterator_remove(iter);
-			free(location);
-		}
-		linkedListIterator_destroy(iter);
-		linkedList_destroy(bundles);
-
-		for (i = 0; i < arrayList_size(installed); i++) {
-			bundle_pt installedBundle = (bundle_pt) arrayList_get(installed, i);
-			bundle_startWithOptions(installedBundle, 0);
-		}
-
-		arrayList_destroy(installed);
 	}
 
-	if (status != CELIX_SUCCESS) {
-		printf("Problem creating framework\n");
+	if (status == CELIX_SUCCESS) {
+		printf("Launcher: Framework Started\n");
 	}
-
-	printf("Launcher: Framework Started\n");
-
-	free(autoStart);
 	
 	return status;
 }

http://git-wip-us.apache.org/repos/asf/celix/blob/985c35f2/framework/src/framework.c
----------------------------------------------------------------------
diff --git a/framework/src/framework.c b/framework/src/framework.c
index b745a8c..083fb81 100644
--- a/framework/src/framework.c
+++ b/framework/src/framework.c
@@ -95,6 +95,9 @@ static celix_status_t frameworkActivator_start(void * userData, bundle_context_p
 static celix_status_t frameworkActivator_stop(void * userData, bundle_context_pt context);
 static celix_status_t frameworkActivator_destroy(void * userData, bundle_context_pt context);
 
+static void framework_autoStartConfiguredBundles(bundle_context_t *fwCtx);
+static void framework_autoStartConfiguredBundlesForList(bundle_context_t *fwCtx, const char *autoStart);
+
 
 struct fw_refreshHelper {
     framework_pt framework;
@@ -208,12 +211,18 @@ celix_status_t framework_create(framework_pt *framework, properties_pt config) {
 
     *framework = (framework_pt) malloc(sizeof(**framework));
     if (*framework != NULL) {
+        celix_thread_mutexattr_t attr;
+        celixThreadMutexAttr_create(&attr);
+        celixThreadMutexAttr_settype(&attr, CELIX_THREAD_MUTEX_RECURSIVE);
+
         status = CELIX_DO_IF(status, celixThreadCondition_init(&(*framework)->condition, NULL));
         status = CELIX_DO_IF(status, celixThreadMutex_create(&(*framework)->mutex, NULL));
         status = CELIX_DO_IF(status, celixThreadMutex_create(&(*framework)->installedBundleMapLock, NULL));
         status = CELIX_DO_IF(status, celixThreadMutex_create(&(*framework)->bundleLock, NULL));
         status = CELIX_DO_IF(status, celixThreadMutex_create(&(*framework)->installRequestLock, NULL));
         status = CELIX_DO_IF(status, celixThreadMutex_create(&(*framework)->dispatcherLock, NULL));
+        status = CELIX_DO_IF(status, celixThreadMutex_create(&(*framework)->serviceListenersLock, &attr));
+        status = CELIX_DO_IF(status, celixThreadMutex_create(&(*framework)->frameworkListenersLock, &attr));
         status = CELIX_DO_IF(status, celixThreadMutex_create(&(*framework)->bundleListenerLock, NULL));
         status = CELIX_DO_IF(status, celixThreadCondition_init(&(*framework)->dispatcher, NULL));
         if (status == CELIX_SUCCESS) {
@@ -333,6 +342,8 @@ celix_status_t framework_destroy(framework_pt framework) {
 	bundleCache_destroy(&framework->cache);
 
 	celixThreadCondition_destroy(&framework->dispatcher);
+    celixThreadMutex_destroy(&framework->serviceListenersLock);
+    celixThreadMutex_destroy(&framework->frameworkListenersLock);
 	celixThreadMutex_destroy(&framework->bundleListenerLock);
 	celixThreadMutex_destroy(&framework->dispatcherLock);
 	celixThreadMutex_destroy(&framework->installRequestLock);
@@ -522,9 +533,69 @@ celix_status_t framework_start(framework_pt framework) {
        fw_fireFrameworkEvent(framework, OSGI_FRAMEWORK_EVENT_ERROR, framework->bundle, status);
     }
 
+    bundle_context_t *fwCtx = framework_getContext(framework);
+	if (fwCtx != NULL) {
+        framework_autoStartConfiguredBundles(fwCtx);
+    }
+
 	return status;
 }
 
+static void framework_autoStartConfiguredBundles(bundle_context_t *fwCtx) {
+    const char* autoStart = NULL;
+    const char* cosgiKeys[] = {"cosgi.auto.start.0","cosgi.auto.start.1","cosgi.auto.start.2","cosgi.auto.start.3","cosgi.auto.start.4","cosgi.auto.start.5"};
+    const char* celixKeys[] = {CELIX_AUTO_START_0, CELIX_AUTO_START_1, CELIX_AUTO_START_2, CELIX_AUTO_START_3, CELIX_AUTO_START_4, CELIX_AUTO_START_5};
+    size_t len = 6;
+    for (int i = 0; i < len; ++i) {
+        bundleContext_getProperty(fwCtx, celixKeys[i], &autoStart);
+        if (autoStart == NULL) {
+            //trying cosgi.auto.start.<level> variants. TODO make this prop deprecated -> warning
+            bundleContext_getProperty(fwCtx, cosgiKeys[i], &autoStart);
+        }
+        if (autoStart != NULL) {
+            framework_autoStartConfiguredBundlesForList(fwCtx, autoStart);
+        }
+    }
+}
+
+static void framework_autoStartConfiguredBundlesForList(bundle_context_t *fwCtx, const char *autoStartIn)  {
+    char delims[] = " ";
+    char *save_ptr = NULL;
+    array_list_pt installed = NULL;
+    char *autoStart = strndup(autoStartIn, 1024*1024*10);
+    arrayList_create(&installed);
+
+    if (autoStart != NULL) {
+        char *location = strtok_r(autoStart, delims, &save_ptr);
+        while (location != NULL) {
+            //first install
+            bundle_t *bnd = NULL;
+            celix_status_t  rc = bundleContext_installBundle(fwCtx, location, &bnd);
+            if (rc == CELIX_SUCCESS) {
+                arrayList_add(installed, bnd);
+            } else {
+                printf("Could not install bundle from %s\n", location); //TODO use logger
+            }
+            location = strtok_r(NULL, delims, &save_ptr);
+        }
+    }
+
+    unsigned int i;
+    for (i = 0; i < arrayList_size(installed); ++i) {
+        long bndId = -1;
+        bundle_t *bnd = arrayList_get(installed, i);
+        bundle_getBundleId(bnd, &bndId);
+        celix_status_t rc = bundle_startWithOptions(bnd, 0);
+        if (rc != CELIX_SUCCESS) {
+            printf("Could not start bundle %li\n", bndId);
+        }
+    }
+
+    free(autoStart);
+    arrayList_destroy(installed);
+}
+
+
 celix_status_t framework_stop(framework_pt framework) {
 	return fw_stopBundle(framework, framework->bundle, true);
 }
@@ -532,7 +603,7 @@ celix_status_t framework_stop(framework_pt framework) {
 celix_status_t fw_getProperty(framework_pt framework, const char* name, const char* defaultValue, const char** value) {
 	celix_status_t status = CELIX_SUCCESS;
 
-	if (framework == NULL || name == NULL || *value != NULL) {
+	if (framework == NULL || name == NULL) {
 		status = CELIX_ILLEGAL_ARGUMENT;
 	} else {
 		if (framework->configurationMap != NULL) {
@@ -1271,6 +1342,7 @@ celix_status_t fw_registerService(framework_pt framework, service_registration_p
             if (status == CELIX_SUCCESS) {
                 celix_status_t subs = CELIX_SUCCESS;
 
+                celixThreadMutex_lock(&framework->serviceListenersLock);
                 for (i = 0; i < arrayList_size(framework->serviceListeners); i++) {
                     fw_service_listener_pt listener =(fw_service_listener_pt) arrayList_get(framework->serviceListeners, i);
                     bundle_context_pt context = NULL;
@@ -1300,6 +1372,7 @@ celix_status_t fw_registerService(framework_pt framework, service_registration_p
                         free(info);
                     }
                 }
+                celixThreadMutex_unlock(&framework->serviceListenersLock);
 
                 status = CELIX_DO_IF(status, serviceRegistry_getServiceReference(framework->registry, framework->bundle,
                                                                                  *registration, &ref));
@@ -1423,7 +1496,9 @@ void fw_addServiceListener(framework_pt framework, bundle_pt bundle, service_lis
 	}
 	fwListener->listener = listener;
 
+    celixThreadMutex_lock(&framework->serviceListenersLock);
 	arrayList_add(framework->serviceListeners, fwListener);
+    celixThreadMutex_unlock(&framework->serviceListenersLock);
 
 	serviceRegistry_getListenerHooks(framework->registry, framework->bundle, &listenerHooks);
 
@@ -1460,7 +1535,8 @@ void fw_removeServiceListener(framework_pt framework, bundle_pt bundle, service_
 	bundle_getContext(bundle, &context);
 
     int i;
-	for (i = 0; i < arrayList_size(framework->serviceListeners); i++) {
+    celixThreadMutex_lock(&framework->serviceListenersLock);
+    for (i = 0; i < arrayList_size(framework->serviceListeners); i++) {
         fw_service_listener_pt visit = (fw_service_listener_pt) arrayList_get(framework->serviceListeners, i);
         if (visit->listener == listener && visit->bundle == bundle) {
             match = visit;
@@ -1468,6 +1544,8 @@ void fw_removeServiceListener(framework_pt framework, bundle_pt bundle, service_
             break;
         }
     }
+    celixThreadMutex_unlock(&framework->serviceListenersLock);
+
 
     if (match != NULL) {
         //invoke listener hooks
@@ -1588,7 +1666,9 @@ celix_status_t fw_addFrameworkListener(framework_pt framework, bundle_pt bundle,
 		frameworkListener->listener = listener;
 		frameworkListener->bundle = bundle;
 
+        celixThreadMutex_lock(&framework->frameworkListenersLock);
 		arrayList_add(framework->frameworkListeners, frameworkListener);
+        celixThreadMutex_unlock(&framework->frameworkListenersLock);
 	}
 
 	framework_logIfError(framework->logger, status, NULL, "Failed to add framework listener");
@@ -1602,6 +1682,7 @@ celix_status_t fw_removeFrameworkListener(framework_pt framework, bundle_pt bund
 	unsigned int i;
 	fw_framework_listener_pt frameworkListener;
 
+    celixThreadMutex_lock(&framework->frameworkListenersLock);
 	for (i = 0; i < arrayList_size(framework->frameworkListeners); i++) {
 		frameworkListener = (fw_framework_listener_pt) arrayList_get(framework->frameworkListeners, i);
 		if (frameworkListener->listener == listener && frameworkListener->bundle == bundle) {
@@ -1612,6 +1693,7 @@ celix_status_t fw_removeFrameworkListener(framework_pt framework, bundle_pt bund
             free(frameworkListener);
 		}
 	}
+    celixThreadMutex_unlock(&framework->frameworkListenersLock);
 
 	framework_logIfError(framework->logger, status, NULL, "Failed to remove framework listener");
 
@@ -1622,6 +1704,7 @@ void fw_serviceChanged(framework_pt framework, service_event_type_e eventType, s
     unsigned int i;
     fw_service_listener_pt element;
 
+    celixThreadMutex_lock(&framework->serviceListenersLock);
     if (arrayList_size(framework->serviceListeners) > 0) {
         for (i = 0; i < arrayList_size(framework->serviceListeners); i++) {
             int matched = 0;
@@ -1689,6 +1772,7 @@ void fw_serviceChanged(framework_pt framework, service_event_type_e eventType, s
             }
         }
     }
+    celixThreadMutex_unlock(&framework->serviceListenersLock);
 
 }
 
@@ -2368,6 +2452,7 @@ static void *fw_eventDispatcher(void *fw) {
             int size = arrayList_size(request->listeners);
             for (i = 0; i < size; i++) {
                 if (request->type == BUNDLE_EVENT_TYPE) {
+                    celixThreadMutex_lock(&framework->bundleListenerLock);
                     fw_bundle_listener_pt listener = (fw_bundle_listener_pt) arrayList_get(request->listeners, i);
                     bundle_event_pt event = (bundle_event_pt) calloc(1, sizeof(*event));
                     event->bundleId = request->bundleId;
@@ -2375,10 +2460,12 @@ static void *fw_eventDispatcher(void *fw) {
                     event->type = request->eventType;
 
                     fw_invokeBundleListener(framework, listener->listener, event, listener->bundle);
+                    celixThreadMutex_unlock(&framework->bundleListenerLock);
 
                     free(event->bundleSymbolicName);
                     free(event);
                 } else if (request->type == FRAMEWORK_EVENT_TYPE) {
+                    celixThreadMutex_lock(&framework->frameworkListenersLock);
                     fw_framework_listener_pt listener = (fw_framework_listener_pt) arrayList_get(request->listeners, i);
                     framework_event_pt event = (framework_event_pt) calloc(1, sizeof(*event));
                     event->bundleId = request->bundleId;
@@ -2388,6 +2475,7 @@ static void *fw_eventDispatcher(void *fw) {
                     event->errorCode = request->errorCode;
 
                     fw_invokeFrameworkListener(framework, listener->listener, event, listener->bundle);
+                    celixThreadMutex_unlock(&framework->frameworkListenersLock);
                     free(event->bundleSymbolicName);
                     free(event);
                 }

http://git-wip-us.apache.org/repos/asf/celix/blob/985c35f2/framework/src/framework_private.h
----------------------------------------------------------------------
diff --git a/framework/src/framework_private.h b/framework/src/framework_private.h
index 910ba4c..afc9fac 100644
--- a/framework/src/framework_private.h
+++ b/framework/src/framework_private.h
@@ -54,8 +54,12 @@ struct framework {
     struct bundle * bundle;
     hash_map_pt installedBundleMap;
     hash_map_pt installRequestMap;
+
+    celix_thread_mutex_t serviceListenersLock;
     array_list_pt serviceListeners;
+
     array_list_pt frameworkListeners;
+    celix_thread_mutex_t frameworkListenersLock;
 
     array_list_pt bundleListeners;
     celix_thread_mutex_t bundleListenerLock;