You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2019/10/02 18:46:32 UTC

[celix] 01/02: gh-80: Adds exception check and handle for bundle start

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

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

commit 87c387ad03eb4004f79300af514131f107f60804
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Tue Oct 1 20:11:18 2019 +0200

    gh-80: Adds exception check and handle for bundle start
---
 cmake/Modules/FindCUnit.cmake                      | 65 ----------------------
 libs/framework/include/celix_bundle_context.h      |  5 +-
 libs/framework/include/celix_framework.h           | 27 +++++++++
 libs/framework/private/mock/bundle_context_mock.c  |  3 +-
 libs/framework/private/mock/framework_mock.c       |  3 +-
 libs/framework/src/bundle_context.c                |  8 +--
 libs/framework/src/framework.c                     | 16 ++++--
 libs/framework/src/framework_private.h             |  2 -
 libs/framework/tst/CMakeLists.txt                  |  3 +-
 .../framework/tst/bundle_context_bundles_tests.cpp | 12 ++++
 libs/framework/tst/nop_activator.c                 | 35 ++++++++++++
 11 files changed, 95 insertions(+), 84 deletions(-)

diff --git a/cmake/Modules/FindCUnit.cmake b/cmake/Modules/FindCUnit.cmake
deleted file mode 100644
index 830f551..0000000
--- a/cmake/Modules/FindCUnit.cmake
+++ /dev/null
@@ -1,65 +0,0 @@
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements.  See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership.  The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License.  You may obtain a copy of the License at
-# 
-#   http://www.apache.org/licenses/LICENSE-2.0
-# 
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied.  See the License for the
-# specific language governing permissions and limitations
-# under the License.
-
-if (NOT WIN32)
-	include(FindCurses)
-endif (NOT WIN32)
-
-FIND_PATH(CUNIT_INCLUDE_DIR CUnit/Basic.h
-  /usr/local/include
-  /usr/include
-  /opt/local/include  
-)
-
-FIND_PATH(CUNIT_SHARE_DIR CUnit-List.dtd
-	/usr/local/share/Cunit
-  	/usr/share/CUnit
-  	/opt/local/share/CUnit
-)
-
-# On unix system, debug and release have the same name
-FIND_LIBRARY(CUNIT_LIBRARY cunit
-             ${CUNIT_INCLUDE_DIR}/../../lib
-             /usr/local/lib
-             /usr/lib
-             )
-FIND_LIBRARY(CUNIT_DEBUG_LIBRARY cunit
-             ${CUNIT_INCLUDE_DIR}/../../lib
-             /usr/local/lib
-             /usr/lib
-             )
-
-IF(CUNIT_INCLUDE_DIR)
-  IF(CUNIT_LIBRARY)
-    SET(CUNIT_FOUND "YES")
-    if (WIN32)
-    	SET(CUNIT_LIBRARIES ${CUNIT_LIBRARY})
-	    SET(CUNIT_DEBUG_LIBRARIES ${CUNIT_DEBUG_LIBRARY})
-    else (WIN32)
-    	SET(CUNIT_LIBRARIES ${CUNIT_LIBRARY} ${CURSES_LIBRARY})
-	    SET(CUNIT_DEBUG_LIBRARIES ${CUNIT_DEBUG_LIBRARY} ${CURSES_DEBUG_LIBRARY})
-    endif (WIN32)
-  ENDIF(CUNIT_LIBRARY)
-  IF(CUNIT_INCLUDE_DIR)
-  	if (WIN32)
-    	SET(CUNIT_INCLUDE_DIRS ${CUNIT_INCLUDE_DIR})
-	else (WIN32)
-		MESSAGE(STATUS "Found CUNIT: ${CUNIT_INCLUDE_DIR}")
-		SET(CUNIT_INCLUDE_DIRS ${CUNIT_INCLUDE_DIR} ${CURSES_INCLUDE_DIR})
-	endif (WIN32)
-  ENDIF(CUNIT_INCLUDE_DIR)
-ENDIF(CUNIT_INCLUDE_DIR)
diff --git a/libs/framework/include/celix_bundle_context.h b/libs/framework/include/celix_bundle_context.h
index 0c845a2..779c134 100644
--- a/libs/framework/include/celix_bundle_context.h
+++ b/libs/framework/include/celix_bundle_context.h
@@ -716,8 +716,9 @@ long celix_bundleContext_trackBundlesWithOptions(
  * @param callbackHandle    The data pointer, which will be used in the callbacks
  * @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.
+ * @return                  Returns true if the bundle is found and the callback is called.
  */
-void celix_bundleContext_useBundle(
+bool celix_bundleContext_useBundle(
         celix_bundle_context_t *ctx,
         long bundleId,
         void *callbackHandle,
@@ -726,7 +727,7 @@ void celix_bundleContext_useBundle(
 
 /**
  * Use the currently active (started) bundles.
- * The provided callback will be called for all the currently started bundles.
+ * The provided callback will be called for all the currently started bundles (excluding the framework bundle).
  *
  * @param ctx               The bundle context.
  * @param callbackHandle    The data pointer, which will be used in the callbacks
diff --git a/libs/framework/include/celix_framework.h b/libs/framework/include/celix_framework.h
index 76ebcb5..470de9b 100644
--- a/libs/framework/include/celix_framework.h
+++ b/libs/framework/include/celix_framework.h
@@ -50,6 +50,33 @@ celix_bundle_context_t* celix_framework_getFrameworkContext(const celix_framewor
  */
 celix_bundle_t* celix_framework_getFrameworkBundle(const celix_framework_t *fw);
 
+/**
+ * Use the currently active (started) bundles.
+ * The provided callback will be called for all the currently started bundles.
+ *
+ * @param ctx                       The bundle context.
+ * @param includeFrameworkBundle    If true the callback will also be triggered for the framework bundle.
+ * @param callbackHandle            The data pointer, which will be used in the callbacks
+ * @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_framework_useBundles(celix_framework_t *fw, bool includeFrameworkBundle, void *callbackHandle, void(*use)(void *handle, const celix_bundle_t *bnd));
+
+/**
+ * Use the bundle with the provided bundle id
+ * The provided callback will be called if the bundle is found.
+ *
+ * @param fw                The framework.
+ * @param onlyActive        If true only starting and active bundles will trigger the callback.
+ * @param bundleId          The bundle id.
+ * @param callbackHandle    The data pointer, which will be used in the callbacks
+ * @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.
+ * @return                  Returns true if the bundle is found and the callback is called.
+ */
+bool celix_framework_useBundle(celix_framework_t *fw, bool onlyActive, long bndId, void *callbackHandle, void(*use)(void *handle, const celix_bundle_t *bnd));
+
+
 
 #ifdef __cplusplus
 }
diff --git a/libs/framework/private/mock/bundle_context_mock.c b/libs/framework/private/mock/bundle_context_mock.c
index 4dec7db..8644a1a 100644
--- a/libs/framework/private/mock/bundle_context_mock.c
+++ b/libs/framework/private/mock/bundle_context_mock.c
@@ -273,7 +273,7 @@ void celix_bundleContext_useBundles(
 }
 
 
-void celix_bundleContext_useBundle(
+bool celix_bundleContext_useBundle(
 		bundle_context_t *ctx,
 		long bundleId,
 		void *callbackHandle,
@@ -283,6 +283,7 @@ void celix_bundleContext_useBundle(
 			->withLongIntParameters("bundleId", bundleId)
 			->withPointerParameters("callbackHandle", callbackHandle)
 			->withPointerParameters("use", use);
+	return mock_c()->returnValue().value.boolValue;
 }
 
 void celix_bundleContext_stopTracker(bundle_context_t *ctx, long trackerId) {
diff --git a/libs/framework/private/mock/framework_mock.c b/libs/framework/private/mock/framework_mock.c
index d651b94..8e49218 100644
--- a/libs/framework/private/mock/framework_mock.c
+++ b/libs/framework/private/mock/framework_mock.c
@@ -329,13 +329,14 @@ void celix_framework_useBundles(framework_t *fw, bool includeFrameworkBundle, vo
 			->withPointerParameters("use", use);
 }
 
-void celix_framework_useBundle(framework_t *fw, bool onlyActive, long bundleId, void *callbackHandle, void(*use)(void *handle, const bundle_t *bnd)) {
+bool celix_framework_useBundle(framework_t *fw, bool onlyActive, long bundleId, void *callbackHandle, void(*use)(void *handle, const bundle_t *bnd)) {
 	mock_c()->actualCall("celix_framework_useBundle")
 			->withPointerParameters("fw", fw)
 			->withBoolParameters("onlyActive", onlyActive)
 			->withLongIntParameters("bundleId", bundleId)
 			->withPointerParameters("callbackHandle", callbackHandle)
 			->withPointerParameters("use", use);
+	return mock_c()->returnValue().value.boolValue;
 }
 
 service_registration_t* celix_framework_registerServiceFactory(framework_t *fw , const celix_bundle_t *bnd, const char* serviceName, celix_service_factory_t *factory, celix_properties_t *properties) {
diff --git a/libs/framework/src/bundle_context.c b/libs/framework/src/bundle_context.c
index 3098884..dd76ba1 100644
--- a/libs/framework/src/bundle_context.c
+++ b/libs/framework/src/bundle_context.c
@@ -602,12 +602,12 @@ void celix_bundleContext_useBundles(
     celix_framework_useBundles(ctx->framework, false, callbackHandle, use);
 }
 
-void celix_bundleContext_useBundle(
+bool celix_bundleContext_useBundle(
         bundle_context_t *ctx,
         long bundleId,
         void *callbackHandle,
         void (*use)(void *handle, const bundle_t *bundle)) {
-    celix_framework_useBundle(ctx->framework, true, bundleId, callbackHandle, use);
+    return celix_framework_useBundle(ctx->framework, true, bundleId, callbackHandle, use);
 }
 
 static void bundleContext_cleanupBundleTrackers(bundle_context_t *ctx) {
@@ -690,10 +690,6 @@ long celix_bundleContext_installBundle(bundle_context_t *ctx, const char *bundle
         status = bundle_getBundleId(bnd, &bundleId);
         if (status == CELIX_SUCCESS && autoStart) {
             status = bundle_start(bnd);
-            if (status != CELIX_SUCCESS) {
-                bundleId = -1;
-                bundle_uninstall(bnd);
-            }
         }
     }
 
diff --git a/libs/framework/src/framework.c b/libs/framework/src/framework.c
index 35f0cef..17d56f3 100644
--- a/libs/framework/src/framework.c
+++ b/libs/framework/src/framework.c
@@ -930,7 +930,6 @@ celix_status_t fw_startBundle(framework_pt framework, bundle_pt bundle, int opti
                         status = CELIX_ENOMEM;
                     } else {
                         void * userData = NULL;
-                        bundle_context_t *context;
                         create_function_fp create = (create_function_fp) celix_libloader_getSymbol((celix_library_handle_t*) bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_CREATE);
                         if (create == NULL) {
                             create = celix_libloader_getSymbol(bundle_getHandle(bundle), OSGI_FRAMEWORK_DEPRECATED_BUNDLE_ACTIVATOR_CREATE);
@@ -976,6 +975,11 @@ celix_status_t fw_startBundle(framework_pt framework, bundle_pt bundle, int opti
 
                         status = CELIX_DO_IF(status, framework_setBundleStateAndNotify(framework, bundle, OSGI_FRAMEWORK_BUNDLE_ACTIVE));
                         status = CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_STARTED, bundle));
+
+                        if (status != CELIX_SUCCESS) {
+                            //state is still STARTING, back to resolved
+                            framework_setBundleStateAndNotify(framework, bundle, OSGI_FRAMEWORK_BUNDLE_RESOLVED);
+                        }
                     }
                 }
 
@@ -986,7 +990,6 @@ celix_status_t fw_startBundle(framework_pt framework, bundle_pt bundle, int opti
     fw_bundleEntry_decreaseUseCount(framework, bndId);
 
 	if (status != CELIX_SUCCESS) {
-	    module_pt module = NULL;
 	    const char *symbolicName = NULL;
 	    long id = 0;
 	    bundle_getCurrentModule(bundle, &module);
@@ -997,9 +1000,6 @@ celix_status_t fw_startBundle(framework_pt framework, bundle_pt bundle, int opti
 	    } else {
 	        fw_logCode(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, status, "Could not start bundle: %s [%ld]", symbolicName, id);
 	    }
-	    if(activator!=NULL){
-	    	free(activator);
-	    }
 	}
 
 	return status;
@@ -2584,7 +2584,8 @@ void celix_framework_useBundles(framework_t *fw, bool includeFrameworkBundle, vo
     celix_arrayList_destroy(bundleIds);
 }
 
-void celix_framework_useBundle(framework_t *fw, bool onlyActive, long bundleId, void *callbackHandle, void(*use)(void *handle, const bundle_t *bnd)) {
+bool celix_framework_useBundle(framework_t *fw, bool onlyActive, long bundleId, void *callbackHandle, void(*use)(void *handle, const bundle_t *bnd)) {
+    bool called = false;
     if (bundleId >= 0) {
         fw_bundleEntry_increaseUseCount(fw, bundleId);
         bundle_t *bnd = framework_getBundleById(fw, bundleId);
@@ -2592,14 +2593,17 @@ void celix_framework_useBundle(framework_t *fw, bool onlyActive, long bundleId,
             celix_bundle_state_e bndState = celix_bundle_getState(bnd);
             if (onlyActive && (bndState == OSGI_FRAMEWORK_BUNDLE_ACTIVE || bndState == OSGI_FRAMEWORK_BUNDLE_STARTING)) {
                 use(callbackHandle, bnd);
+                called = true;
             } else if (!onlyActive) {
                 use(callbackHandle, bnd);
+                called = true;
             }
         } else {
             framework_logIfError(fw->logger, CELIX_FRAMEWORK_EXCEPTION, NULL, "Bundle with id %li is not installed", bundleId);
         }
         fw_bundleEntry_decreaseUseCount(fw, bundleId);
     }
+    return called;
 }
 
 service_registration_t* celix_framework_registerServiceFactory(framework_t *fw , const celix_bundle_t *bnd, const char* serviceName, celix_service_factory_t *factory, celix_properties_t *properties) {
diff --git a/libs/framework/src/framework_private.h b/libs/framework/src/framework_private.h
index 20dad52..6728ff7 100644
--- a/libs/framework/src/framework_private.h
+++ b/libs/framework/src/framework_private.h
@@ -153,8 +153,6 @@ FRAMEWORK_EXPORT bundle_pt framework_getBundleById(framework_pt framework, long
  **********************************************************************************************************************
  **********************************************************************************************************************/
 
-void celix_framework_useBundles(framework_t *fw, bool includeFrameworkBundle, void *callbackHandle, void(*use)(void *handle, const bundle_t *bnd));
-void celix_framework_useBundle(framework_t *fw, bool onlyActive, long bundleId, void *callbackHandle, void(*use)(void *handle, const bundle_t *bnd));
 service_registration_t* celix_framework_registerServiceFactory(framework_t *fw , const celix_bundle_t *bnd, const char* serviceName, celix_service_factory_t *factory, celix_properties_t *properties);
 
 #endif /* FRAMEWORK_PRIVATE_H_ */
diff --git a/libs/framework/tst/CMakeLists.txt b/libs/framework/tst/CMakeLists.txt
index efd919e..7ef1ceb 100644
--- a/libs/framework/tst/CMakeLists.txt
+++ b/libs/framework/tst/CMakeLists.txt
@@ -18,6 +18,7 @@
 add_celix_bundle(simple_test_bundle1 NO_ACTIVATOR VERSION 1.0.0)
 add_celix_bundle(simple_test_bundle2 NO_ACTIVATOR VERSION 1.0.0)
 add_celix_bundle(simple_test_bundle3 NO_ACTIVATOR VERSION 1.0.0)
+add_celix_bundle(bundle_with_exception SOURCES nop_activator.c VERSION 1.0.0)
 add_subdirectory(subdir) #simple_test_bundle4 and simeple_test_bundle5
 
 add_executable(test_framework
@@ -30,7 +31,7 @@ add_executable(test_framework
 )
 
 target_link_libraries(test_framework Celix::framework ${CURL_LIBRARIES} ${CPPUTEST_LIBRARY})
-add_dependencies(test_framework simple_test_bundle1_bundle simple_test_bundle2_bundle simple_test_bundle3_bundle simple_test_bundle4_bundle simple_test_bundle5_bundle)
+add_dependencies(test_framework simple_test_bundle1_bundle simple_test_bundle2_bundle simple_test_bundle3_bundle simple_test_bundle4_bundle simple_test_bundle5_bundle bundle_with_exception)
 target_include_directories(test_framework PRIVATE ../src)
 
 configure_file(config.properties.in config.properties @ONLY)
diff --git a/libs/framework/tst/bundle_context_bundles_tests.cpp b/libs/framework/tst/bundle_context_bundles_tests.cpp
index 6887418..f193173 100644
--- a/libs/framework/tst/bundle_context_bundles_tests.cpp
+++ b/libs/framework/tst/bundle_context_bundles_tests.cpp
@@ -41,6 +41,7 @@ TEST_GROUP(CelixBundleContextBundlesTests) {
     const char * const TEST_BND3_LOC = "simple_test_bundle3.zip";
     const char * const TEST_BND4_LOC = "simple_test_bundle4.zip";
     const char * const TEST_BND5_LOC = "simple_test_bundle5.zip";
+    const char * const TEST_BND_WITH_EXCEPTION_LOC = "bundle_with_exception.zip";
 
     void setup() {
         properties = properties_create();
@@ -90,6 +91,17 @@ TEST(CelixBundleContextBundlesTests, useBundlesTest) {
     CHECK_EQUAL(1, count);
 };
 
+TEST(CelixBundleContextBundlesTests, startBundleWithException) {
+    long bndId = celix_bundleContext_installBundle(ctx, TEST_BND_WITH_EXCEPTION_LOC, true);
+    CHECK(bndId > 0); //bundle is installed, but not started
+
+    bool called = celix_framework_useBundle(fw, false, bndId, nullptr, [](void */*handle*/, const celix_bundle_t *bnd) {
+        auto state = celix_bundle_getState(bnd);
+        CHECK_EQUAL(state, OSGI_FRAMEWORK_BUNDLE_RESOLVED);
+    });
+    CHECK_TRUE(called);
+}
+
 TEST(CelixBundleContextBundlesTests, useBundleTest) {
     int count = 0;
 
diff --git a/libs/framework/tst/nop_activator.c b/libs/framework/tst/nop_activator.c
new file mode 100644
index 0000000..ad2b57d
--- /dev/null
+++ b/libs/framework/tst/nop_activator.c
@@ -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.
+ */
+
+#include "celix_api.h"
+
+struct bundle_act {
+
+};
+
+static celix_status_t act_start(struct bundle_act *act __attribute__((unused)), celix_bundle_context_t *ctx __attribute__((unused))) {
+    printf("Return a bundle 'exception'\n");
+    return CELIX_BUNDLE_EXCEPTION;
+}
+
+static celix_status_t act_stop(struct bundle_act *act __attribute__((unused)), celix_bundle_context_t *ctx __attribute__((unused))) {
+    return CELIX_SUCCESS;
+}
+
+CELIX_GEN_BUNDLE_ACTIVATOR(struct bundle_act, act_start, act_stop);
\ No newline at end of file