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 2017/11/20 20:33:13 UTC
[16/46] celix git commit: CELIX-417: Initial refactoring for CMake
usage
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/framework.c
----------------------------------------------------------------------
diff --git a/framework/src/framework.c b/framework/src/framework.c
new file mode 100644
index 0000000..b1db384
--- /dev/null
+++ b/framework/src/framework.c
@@ -0,0 +1,2620 @@
+/**
+ *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.
+ */
+/*
+ * framework.c
+ *
+ * \date Mar 23, 2010
+ * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ * \copyright Apache License, Version 2.0
+ */
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "celixbool.h"
+
+#ifdef _WIN32
+#include <winbase.h>
+#include <windows.h>
+#else
+#include <dlfcn.h>
+#endif
+#include <uuid/uuid.h>
+
+#include "framework_private.h"
+#include "constants.h"
+#include "resolver.h"
+#include "utils.h"
+#include "linked_list_iterator.h"
+#include "service_reference_private.h"
+#include "listener_hook_service.h"
+#include "service_registration_private.h"
+
+typedef celix_status_t (*create_function_pt)(bundle_context_pt context, void **userData);
+typedef celix_status_t (*start_function_pt)(void * handle, bundle_context_pt context);
+typedef celix_status_t (*stop_function_pt)(void * handle, bundle_context_pt context);
+typedef celix_status_t (*destroy_function_pt)(void * handle, bundle_context_pt context);
+
+struct activator {
+ void * userData;
+ start_function_pt start;
+ stop_function_pt stop;
+ destroy_function_pt destroy;
+};
+
+celix_status_t framework_setBundleStateAndNotify(framework_pt framework, bundle_pt bundle, int state);
+celix_status_t framework_markBundleResolved(framework_pt framework, module_pt module);
+
+celix_status_t framework_acquireBundleLock(framework_pt framework, bundle_pt bundle, int desiredStates);
+bool framework_releaseBundleLock(framework_pt framework, bundle_pt bundle);
+
+bool framework_acquireGlobalLock(framework_pt framework);
+celix_status_t framework_releaseGlobalLock(framework_pt framework);
+
+celix_status_t framework_acquireInstallLock(framework_pt framework, const char* location);
+celix_status_t framework_releaseInstallLock(framework_pt framework, const char* location);
+
+long framework_getNextBundleId(framework_pt framework);
+
+celix_status_t fw_installBundle2(framework_pt framework, bundle_pt * bundle, long id, const char * location, const char *inputFile, bundle_archive_pt archive);
+
+celix_status_t fw_refreshBundles(framework_pt framework, bundle_pt bundles[], int size);
+celix_status_t fw_refreshBundle(framework_pt framework, bundle_pt bundle);
+
+celix_status_t fw_populateDependentGraph(framework_pt framework, bundle_pt exporter, hash_map_pt *map);
+
+celix_status_t fw_fireBundleEvent(framework_pt framework, bundle_event_type_e, bundle_pt bundle);
+celix_status_t fw_fireFrameworkEvent(framework_pt framework, framework_event_type_e eventType, bundle_pt bundle, celix_status_t errorCode);
+static void *fw_eventDispatcher(void *fw);
+
+celix_status_t fw_invokeBundleListener(framework_pt framework, bundle_listener_pt listener, bundle_event_pt event, bundle_pt bundle);
+celix_status_t fw_invokeFrameworkListener(framework_pt framework, framework_listener_pt listener, framework_event_pt event, bundle_pt bundle);
+
+static celix_status_t framework_loadBundleLibraries(framework_pt framework, bundle_pt bundle);
+static celix_status_t framework_loadLibraries(framework_pt framework, const char* libraries, const char* activator, bundle_archive_pt archive, void **activatorHandle);
+static celix_status_t framework_loadLibrary(framework_pt framework, const char* library, bundle_archive_pt archive, void **handle);
+
+static celix_status_t frameworkActivator_start(void * userData, bundle_context_pt context);
+static celix_status_t frameworkActivator_stop(void * userData, bundle_context_pt context);
+static celix_status_t frameworkActivator_destroy(void * userData, bundle_context_pt context);
+
+
+struct fw_refreshHelper {
+ framework_pt framework;
+ bundle_pt bundle;
+ bundle_state_e oldState;
+};
+
+celix_status_t fw_refreshHelper_refreshOrRemove(struct fw_refreshHelper * refreshHelper);
+celix_status_t fw_refreshHelper_restart(struct fw_refreshHelper * refreshHelper);
+celix_status_t fw_refreshHelper_stop(struct fw_refreshHelper * refreshHelper);
+
+struct fw_serviceListener {
+ bundle_pt bundle;
+ service_listener_pt listener;
+ filter_pt filter;
+ array_list_pt retainedReferences;
+};
+
+typedef struct fw_serviceListener * fw_service_listener_pt;
+
+struct fw_bundleListener {
+ bundle_pt bundle;
+ bundle_listener_pt listener;
+};
+
+typedef struct fw_bundleListener * fw_bundle_listener_pt;
+
+struct fw_frameworkListener {
+ bundle_pt bundle;
+ framework_listener_pt listener;
+};
+
+typedef struct fw_frameworkListener * fw_framework_listener_pt;
+
+enum event_type {
+ FRAMEWORK_EVENT_TYPE,
+ BUNDLE_EVENT_TYPE,
+ EVENT_TYPE_SERVICE,
+};
+
+typedef enum event_type event_type_e;
+
+struct request {
+ event_type_e type;
+ array_list_pt listeners;
+
+ int eventType;
+ long bundleId;
+ char* bundleSymbolicName;
+ celix_status_t errorCode;
+ char *error;
+
+ char *filter;
+};
+
+typedef struct request *request_pt;
+
+framework_logger_pt logger;
+
+//TODO introduce a counter + mutex to control the freeing of the logger when mutiple threads are running a framework.
+static celix_thread_once_t loggerInit = CELIX_THREAD_ONCE_INIT;
+static void framework_loggerInit(void) {
+ logger = malloc(sizeof(*logger));
+ logger->logFunction = frameworkLogger_log;
+}
+
+/* Note: RTLD_NODELETE flag is needed in order to obtain a readable valgrind output.
+ * Valgrind output is written when the application terminates, so symbols resolving
+ * is impossible if dlopened libraries are unloaded before the application ends.
+ * RTLD_NODELETE closes the dynamic library but does not unload it from the memory space,
+ * so that symbols will be available until the application terminates.
+ * On the other hand, since the memory mapping is not destroyed after dlclose, calling again
+ * dlopen for the same library clashes with the previous mapping: this breaks the memory layout
+ * in case the user, for example, uninstall (dlclose) and install the bundle again (dlopen)
+ * So, RTLD_NODELETE should be used only for debugging purposes.
+ * Refer to dlopen manpage for additional details about libraries dynamic loading.
+ */
+#ifdef _WIN32
+ #define handle_t HMODULE
+ #define fw_openLibrary(path) LoadLibrary(path)
+ #define fw_closeLibrary(handle) FreeLibrary(handle)
+
+ #define fw_getSymbol(handle, name) GetProcAddress(handle, name)
+
+ #define fw_getLastError() GetLastError()
+
+ HMODULE fw_getCurrentModule() {
+ HMODULE hModule = NULL;
+ GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (LPCTSTR)fw_getCurrentModule, &hModule);
+ return hModule;
+ }
+#else
+ #define handle_t void *
+ #if defined(DEBUG) && !defined(ANDROID)
+ #define fw_openLibrary(path) dlopen(path, RTLD_LAZY|RTLD_LOCAL|RTLD_NODELETE)
+ #else
+ #define fw_openLibrary(path) dlopen(path, RTLD_LAZY|RTLD_LOCAL)
+ #endif
+ #define fw_closeLibrary(handle) dlclose(handle)
+ #define fw_getSymbol(handle, name) dlsym(handle, name)
+ #define fw_getLastError() dlerror()
+#endif
+
+celix_status_t framework_create(framework_pt *framework, properties_pt config) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ logger = hashMap_get(config, "logger");
+ if (logger == NULL) {
+ celixThread_once(&loggerInit, framework_loggerInit);
+ }
+
+ *framework = (framework_pt) malloc(sizeof(**framework));
+ if (*framework != NULL) {
+ 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)->bundleListenerLock, NULL));
+ status = CELIX_DO_IF(status, celixThreadCondition_init(&(*framework)->dispatcher, NULL));
+ if (status == CELIX_SUCCESS) {
+ (*framework)->bundle = NULL;
+ (*framework)->installedBundleMap = NULL;
+ (*framework)->registry = NULL;
+ (*framework)->interrupted = false;
+ (*framework)->shutdown = false;
+ (*framework)->globalLockWaitersList = NULL;
+ (*framework)->globalLockCount = 0;
+ (*framework)->globalLockThread = celix_thread_default;
+ (*framework)->nextBundleId = 1l;
+ (*framework)->cache = NULL;
+ (*framework)->installRequestMap = hashMap_create(utils_stringHash, utils_stringHash, utils_stringEquals, utils_stringEquals);
+ (*framework)->serviceListeners = NULL;
+ (*framework)->bundleListeners = NULL;
+ (*framework)->frameworkListeners = NULL;
+ (*framework)->requests = NULL;
+ (*framework)->configurationMap = config;
+ (*framework)->logger = logger;
+
+
+ status = CELIX_DO_IF(status, bundle_create(&(*framework)->bundle));
+ status = CELIX_DO_IF(status, arrayList_create(&(*framework)->globalLockWaitersList));
+ status = CELIX_DO_IF(status, bundle_setFramework((*framework)->bundle, (*framework)));
+ if (status == CELIX_SUCCESS) {
+ //
+ } else {
+ status = CELIX_FRAMEWORK_EXCEPTION;
+ fw_logCode((*framework)->logger, OSGI_FRAMEWORK_LOG_ERROR, status, "Could not create framework");
+ }
+ } else {
+ status = CELIX_FRAMEWORK_EXCEPTION;
+ fw_logCode((*framework)->logger, OSGI_FRAMEWORK_LOG_ERROR, status, "Could not create framework");
+ }
+ } else {
+ status = CELIX_FRAMEWORK_EXCEPTION;
+ fw_logCode(logger, OSGI_FRAMEWORK_LOG_ERROR, CELIX_ENOMEM, "Could not create framework");
+ }
+
+ return status;
+}
+
+celix_status_t framework_destroy(framework_pt framework) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ celixThreadMutex_lock(&framework->installedBundleMapLock);
+
+ if (framework->installedBundleMap != NULL) {
+ hash_map_iterator_pt iterator = hashMapIterator_create(framework->installedBundleMap);
+ while (hashMapIterator_hasNext(iterator)) {
+ hash_map_entry_pt entry = hashMapIterator_nextEntry(iterator);
+ bundle_pt bundle = (bundle_pt) hashMapEntry_getValue(entry);
+ char * key = hashMapEntry_getKey(entry);
+ bundle_archive_pt archive = NULL;
+
+ bool systemBundle = false;
+ bundle_isSystemBundle(bundle, &systemBundle);
+ if (systemBundle) {
+ bundle_context_pt context = NULL;
+ bundle_getContext(framework->bundle, &context);
+ bundleContext_destroy(context);
+ }
+
+ if (bundle_getArchive(bundle, &archive) == CELIX_SUCCESS) {
+ if (!systemBundle) {
+ bundle_revision_pt revision = NULL;
+ array_list_pt handles = NULL;
+ status = CELIX_DO_IF(status, bundleArchive_getCurrentRevision(archive, &revision));
+ status = CELIX_DO_IF(status, bundleRevision_getHandles(revision, &handles));
+ if (handles != NULL) {
+ for (int i = arrayList_size(handles) - 1; i >= 0; i--) {
+ void *handle = arrayList_get(handles, i);
+ fw_closeLibrary(handle);
+ }
+ }
+ }
+
+ bundleArchive_destroy(archive);
+ }
+ bundle_destroy(bundle);
+ hashMapIterator_remove(iterator);
+ free(key);
+ }
+ hashMapIterator_destroy(iterator);
+ }
+
+ celixThreadMutex_unlock(&framework->installedBundleMapLock);
+
+ hashMap_destroy(framework->installRequestMap, false, false);
+
+ serviceRegistry_destroy(framework->registry);
+
+ arrayList_destroy(framework->globalLockWaitersList);
+
+ if (framework->serviceListeners != NULL) {
+ arrayList_destroy(framework->serviceListeners);
+ }
+ if (framework->bundleListeners) {
+ arrayList_destroy(framework->bundleListeners);
+ }
+ if (framework->frameworkListeners) {
+ arrayList_destroy(framework->frameworkListeners);
+ }
+
+ if(framework->requests){
+ int i;
+ for (i = 0; i < arrayList_size(framework->requests); i++) {
+ request_pt request = arrayList_get(framework->requests, i);
+ free(request);
+ }
+ arrayList_destroy(framework->requests);
+ }
+ if(framework->installedBundleMap!=NULL){
+ hashMap_destroy(framework->installedBundleMap, true, false);
+ }
+
+ bundleCache_destroy(&framework->cache);
+
+ celixThreadCondition_destroy(&framework->dispatcher);
+ celixThreadMutex_destroy(&framework->bundleListenerLock);
+ celixThreadMutex_destroy(&framework->dispatcherLock);
+ celixThreadMutex_destroy(&framework->installRequestLock);
+ celixThreadMutex_destroy(&framework->bundleLock);
+ celixThreadMutex_destroy(&framework->installedBundleMapLock);
+ celixThreadMutex_destroy(&framework->mutex);
+ celixThreadCondition_destroy(&framework->condition);
+
+ logger = hashMap_get(framework->configurationMap, "logger");
+ if (logger == NULL) {
+ free(framework->logger);
+ }
+
+ properties_destroy(framework->configurationMap);
+
+ free(framework);
+
+ return status;
+}
+
+celix_status_t fw_init(framework_pt framework) {
+ bundle_state_e state;
+ const char *location = NULL;
+ module_pt module = NULL;
+ linked_list_pt wires = NULL;
+ array_list_pt archives = NULL;
+ bundle_archive_pt archive = NULL;
+
+ celix_status_t status = CELIX_SUCCESS;
+ status = CELIX_DO_IF(status, framework_acquireBundleLock(framework, framework->bundle, OSGI_FRAMEWORK_BUNDLE_INSTALLED|OSGI_FRAMEWORK_BUNDLE_RESOLVED|OSGI_FRAMEWORK_BUNDLE_STARTING|OSGI_FRAMEWORK_BUNDLE_ACTIVE));
+ status = CELIX_DO_IF(status, arrayList_create(&framework->serviceListeners));
+ status = CELIX_DO_IF(status, arrayList_create(&framework->bundleListeners));
+ status = CELIX_DO_IF(status, arrayList_create(&framework->frameworkListeners));
+ status = CELIX_DO_IF(status, arrayList_create(&framework->requests));
+ status = CELIX_DO_IF(status, celixThread_create(&framework->dispatcherThread, NULL, fw_eventDispatcher, framework));
+ status = CELIX_DO_IF(status, bundle_getState(framework->bundle, &state));
+ if (status == CELIX_SUCCESS) {
+ if ((state == OSGI_FRAMEWORK_BUNDLE_INSTALLED) || (state == OSGI_FRAMEWORK_BUNDLE_RESOLVED)) {
+ bundle_state_e state;
+ status = CELIX_DO_IF(status, bundleCache_create(framework->configurationMap,&framework->cache));
+ status = CELIX_DO_IF(status, bundle_getState(framework->bundle, &state));
+ if (status == CELIX_SUCCESS) {
+ if (state == OSGI_FRAMEWORK_BUNDLE_INSTALLED) {
+ const char *clean = properties_get(framework->configurationMap, OSGI_FRAMEWORK_FRAMEWORK_STORAGE_CLEAN);
+ if (clean != NULL && (strcmp(clean, OSGI_FRAMEWORK_FRAMEWORK_STORAGE_CLEAN_ONFIRSTINIT) == 0)) {
+ bundleCache_delete(framework->cache);
+ }
+ }
+ }
+ }
+ }
+
+ if (status == CELIX_SUCCESS) {
+ /*create and store framework uuid*/
+ char uuid[37];
+
+ uuid_t uid;
+ uuid_generate(uid);
+ uuid_unparse(uid, uuid);
+
+ properties_set(framework->configurationMap, (char*) OSGI_FRAMEWORK_FRAMEWORK_UUID, uuid);
+
+ framework->installedBundleMap = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
+ }
+
+ status = CELIX_DO_IF(status, bundle_getArchive(framework->bundle, &archive));
+ status = CELIX_DO_IF(status, bundleArchive_getLocation(archive, &location));
+ if (status == CELIX_SUCCESS) {
+ hashMap_put(framework->installedBundleMap, strdup(location), framework->bundle);
+ }
+ status = CELIX_DO_IF(status, bundle_getCurrentModule(framework->bundle, &module));
+ if (status == CELIX_SUCCESS) {
+ wires = resolver_resolve(module);
+ if (wires != NULL) {
+ framework_markResolvedModules(framework, wires);
+ } else {
+ status = CELIX_BUNDLE_EXCEPTION;
+ fw_logCode(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, status, "Unresolved constraints in System Bundle");
+ }
+ }
+
+ status = CELIX_DO_IF(status, bundleCache_getArchives(framework->cache, &archives));
+ if (status == CELIX_SUCCESS) {
+ unsigned int arcIdx;
+ for (arcIdx = 0; arcIdx < arrayList_size(archives); arcIdx++) {
+ bundle_archive_pt archive1 = (bundle_archive_pt) arrayList_get(archives, arcIdx);
+ long id;
+ bundle_state_e bundleState;
+ bundleArchive_getId(archive1, &id);
+ framework->nextBundleId = framework->nextBundleId > id + 1 ? framework->nextBundleId : id + 1;
+
+ bundleArchive_getPersistentState(archive1, &bundleState);
+ if (bundleState == OSGI_FRAMEWORK_BUNDLE_UNINSTALLED) {
+ bundleArchive_closeAndDelete(archive1);
+ } else {
+ bundle_pt bundle = NULL;
+ const char *location1 = NULL;
+ status = bundleArchive_getLocation(archive1, &location1);
+ fw_installBundle2(framework, &bundle, id, location1, NULL, archive1);
+ }
+ }
+ arrayList_destroy(archives);
+ }
+
+ status = CELIX_DO_IF(status, serviceRegistry_create(framework, fw_serviceChanged, &framework->registry));
+ status = CELIX_DO_IF(status, framework_setBundleStateAndNotify(framework, framework->bundle, OSGI_FRAMEWORK_BUNDLE_STARTING));
+ status = CELIX_DO_IF(status, celixThreadCondition_init(&framework->shutdownGate, NULL));
+
+ bundle_context_pt context = NULL;
+ status = CELIX_DO_IF(status, bundleContext_create(framework, framework->logger, framework->bundle, &context));
+ status = CELIX_DO_IF(status, bundle_setContext(framework->bundle, context));
+ if (status == CELIX_SUCCESS) {
+ activator_pt activator = NULL;
+ activator = (activator_pt) calloc(1,(sizeof(*activator)));
+ if (activator != NULL) {
+ bundle_context_pt context = NULL;
+ void * userData = NULL;
+
+ //create_function_pt create = NULL;
+ start_function_pt start = (start_function_pt) frameworkActivator_start;
+ stop_function_pt stop = (stop_function_pt) frameworkActivator_stop;
+ destroy_function_pt destroy = (destroy_function_pt) frameworkActivator_destroy;
+
+ activator->start = start;
+ activator->stop = stop;
+ activator->destroy = destroy;
+ status = CELIX_DO_IF(status, bundle_setActivator(framework->bundle, activator));
+ status = CELIX_DO_IF(status, bundle_getContext(framework->bundle, &context));
+
+ if (status == CELIX_SUCCESS) {
+ /* This code part is in principle dead, but in future it may do something.
+ * That's why it's outcommented and not deleted
+ if (create != NULL) {
+ create(context, &userData);
+ }
+ */
+ activator->userData = userData;
+
+ if (start != NULL) {
+ start(userData, context);
+ }
+ }
+ else{
+ free(activator);
+ }
+ } else {
+ status = CELIX_ENOMEM;
+ }
+ }
+
+ if (status != CELIX_SUCCESS) {
+ fw_logCode(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, status, "Could not init framework");
+ }
+
+ framework_releaseBundleLock(framework, framework->bundle);
+
+ return status;
+}
+
+celix_status_t framework_start(framework_pt framework) {
+ celix_status_t status = CELIX_SUCCESS;
+ bundle_state_e state = OSGI_FRAMEWORK_BUNDLE_UNKNOWN;
+
+ status = CELIX_DO_IF(status, framework_acquireBundleLock(framework, framework->bundle, OSGI_FRAMEWORK_BUNDLE_INSTALLED|OSGI_FRAMEWORK_BUNDLE_RESOLVED|OSGI_FRAMEWORK_BUNDLE_STARTING|OSGI_FRAMEWORK_BUNDLE_ACTIVE));
+ status = CELIX_DO_IF(status, bundle_getState(framework->bundle, &state));
+ if (status == CELIX_SUCCESS) {
+ if ((state == OSGI_FRAMEWORK_BUNDLE_INSTALLED) || (state == OSGI_FRAMEWORK_BUNDLE_RESOLVED)) {
+ status = CELIX_DO_IF(status, fw_init(framework));
+ }
+ }
+
+ status = CELIX_DO_IF(status, bundle_getState(framework->bundle, &state));
+ if (status == CELIX_SUCCESS) {
+ if (state == OSGI_FRAMEWORK_BUNDLE_STARTING) {
+ status = CELIX_DO_IF(status, framework_setBundleStateAndNotify(framework, framework->bundle, OSGI_FRAMEWORK_BUNDLE_ACTIVE));
+ }
+
+ framework_releaseBundleLock(framework, framework->bundle);
+ }
+
+ status = CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_STARTED, framework->bundle));
+ status = CELIX_DO_IF(status, fw_fireFrameworkEvent(framework, OSGI_FRAMEWORK_EVENT_STARTED, framework->bundle, 0));
+
+ if (status != CELIX_SUCCESS) {
+ status = CELIX_BUNDLE_EXCEPTION;
+ fw_logCode(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, status, "Could not start framework");
+ fw_fireFrameworkEvent(framework, OSGI_FRAMEWORK_EVENT_ERROR, framework->bundle, status);
+ }
+
+ return status;
+}
+
+void framework_stop(framework_pt framework) {
+ fw_stopBundle(framework, framework->bundle, true);
+}
+
+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) {
+ status = CELIX_ILLEGAL_ARGUMENT;
+ } else {
+ if (framework->configurationMap != NULL) {
+ *value = properties_get(framework->configurationMap, name);
+ }
+ if (*value == NULL) {
+ *value = getenv(name);
+ }
+ if (*value == NULL) {
+ *value = defaultValue;
+ }
+ }
+
+ return status;
+}
+
+celix_status_t fw_installBundle(framework_pt framework, bundle_pt * bundle, const char * location, const char *inputFile) {
+ return fw_installBundle2(framework, bundle, -1, location, inputFile, NULL);
+}
+
+celix_status_t fw_installBundle2(framework_pt framework, bundle_pt * bundle, long id, const char * location, const char *inputFile, bundle_archive_pt archive) {
+ celix_status_t status = CELIX_SUCCESS;
+// bundle_archive_pt bundle_archive = NULL;
+ bundle_state_e state = OSGI_FRAMEWORK_BUNDLE_UNKNOWN;
+ bool locked;
+
+ status = CELIX_DO_IF(status, framework_acquireInstallLock(framework, location));
+ status = CELIX_DO_IF(status, bundle_getState(framework->bundle, &state));
+ if (status == CELIX_SUCCESS) {
+ if (state == OSGI_FRAMEWORK_BUNDLE_STOPPING || state == OSGI_FRAMEWORK_BUNDLE_UNINSTALLED) {
+ fw_log(framework->logger, OSGI_FRAMEWORK_LOG_INFO, "The framework is being shutdown");
+ status = CELIX_DO_IF(status, framework_releaseInstallLock(framework, location));
+ status = CELIX_FRAMEWORK_SHUTDOWN;
+ }
+ }
+
+ if (status == CELIX_SUCCESS) {
+ *bundle = framework_getBundle(framework, location);
+ if (*bundle != NULL) {
+ framework_releaseInstallLock(framework, location);
+ return CELIX_SUCCESS;
+ }
+
+ if (archive == NULL) {
+ id = framework_getNextBundleId(framework);
+
+ status = CELIX_DO_IF(status, bundleCache_createArchive(framework->cache, id, location, inputFile, &archive));
+
+ if (status != CELIX_SUCCESS) {
+ bundleArchive_destroy(archive);
+ }
+ } else {
+ // purge revision
+ // multiple revisions not yet implemented
+ }
+
+ if (status == CELIX_SUCCESS) {
+ locked = framework_acquireGlobalLock(framework);
+ if (!locked) {
+ status = CELIX_BUNDLE_EXCEPTION;
+ } else {
+ status = CELIX_DO_IF(status, bundle_createFromArchive(bundle, framework, archive));
+
+ framework_releaseGlobalLock(framework);
+ if (status == CELIX_SUCCESS) {
+ celixThreadMutex_lock(&framework->installedBundleMapLock);
+ hashMap_put(framework->installedBundleMap, strdup(location), *bundle);
+ celixThreadMutex_unlock(&framework->installedBundleMapLock);
+
+ } else {
+ status = CELIX_BUNDLE_EXCEPTION;
+ status = CELIX_DO_IF(status, bundleArchive_closeAndDelete(archive));
+ }
+ }
+ }
+ }
+
+ framework_releaseInstallLock(framework, location);
+
+ if (status != CELIX_SUCCESS) {
+ fw_logCode(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, status, "Could not install bundle");
+ } else {
+ status = CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_INSTALLED, *bundle));
+ }
+
+ return status;
+}
+
+celix_status_t framework_getBundleEntry(framework_pt framework, bundle_pt bundle, const char* name, char** entry) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ bundle_revision_pt revision;
+ bundle_archive_pt archive = NULL;
+ const char *root;
+
+ status = CELIX_DO_IF(status, bundle_getArchive(bundle, &archive));
+ status = CELIX_DO_IF(status, bundleArchive_getCurrentRevision(archive, &revision));
+ status = CELIX_DO_IF(status, bundleRevision_getRoot(revision, &root));
+ if (status == CELIX_SUCCESS) {
+ char e[strlen(name) + strlen(root) + 2];
+ strcpy(e, root);
+ if ((strlen(name) > 0) && (name[0] == '/')) {
+ strcat(e, name);
+ } else {
+ strcat(e, "/");
+ strcat(e, name);
+ }
+
+ if (access(e, F_OK) == 0) {
+ (*entry) = strndup(e, 1024*10);
+ } else {
+ (*entry) = NULL;
+ }
+ }
+
+ return status;
+}
+
+celix_status_t fw_startBundle(framework_pt framework, bundle_pt bundle, int options) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ linked_list_pt wires = NULL;
+ bundle_context_pt context = NULL;
+ bundle_state_e state;
+ module_pt module = NULL;
+ activator_pt activator = NULL;
+ char *error = NULL;
+ const char *name = NULL;
+
+ status = CELIX_DO_IF(status, framework_acquireBundleLock(framework, bundle, OSGI_FRAMEWORK_BUNDLE_INSTALLED|OSGI_FRAMEWORK_BUNDLE_RESOLVED|OSGI_FRAMEWORK_BUNDLE_STARTING|OSGI_FRAMEWORK_BUNDLE_ACTIVE));
+ status = CELIX_DO_IF(status, bundle_getState(bundle, &state));
+
+ if (status == CELIX_SUCCESS) {
+ switch (state) {
+ case OSGI_FRAMEWORK_BUNDLE_UNKNOWN:
+ error = "state is unknown";
+ status = CELIX_ILLEGAL_STATE;
+ break;
+ case OSGI_FRAMEWORK_BUNDLE_UNINSTALLED:
+ error = "bundle is uninstalled";
+ status = CELIX_ILLEGAL_STATE;
+ break;
+ case OSGI_FRAMEWORK_BUNDLE_STARTING:
+ error = "bundle is starting";
+ status = CELIX_BUNDLE_EXCEPTION;
+ break;
+ case OSGI_FRAMEWORK_BUNDLE_STOPPING:
+ error = "bundle is stopping";
+ status = CELIX_BUNDLE_EXCEPTION;
+ break;
+ case OSGI_FRAMEWORK_BUNDLE_ACTIVE:
+ break;
+ case OSGI_FRAMEWORK_BUNDLE_INSTALLED:
+ bundle_getCurrentModule(bundle, &module);
+ module_getSymbolicName(module, &name);
+ if (!module_isResolved(module)) {
+ wires = resolver_resolve(module);
+ if (wires == NULL) {
+ framework_releaseBundleLock(framework, bundle);
+ return CELIX_BUNDLE_EXCEPTION;
+ }
+ framework_markResolvedModules(framework, wires);
+
+ }
+ /* no break */
+ case OSGI_FRAMEWORK_BUNDLE_RESOLVED:
+ module = NULL;
+ name = NULL;
+ bundle_getCurrentModule(bundle, &module);
+ module_getSymbolicName(module, &name);
+ status = CELIX_DO_IF(status, bundleContext_create(framework, framework->logger, bundle, &context));
+ status = CELIX_DO_IF(status, bundle_setContext(bundle, context));
+
+ if (status == CELIX_SUCCESS) {
+ activator = (activator_pt) calloc(1,(sizeof(*activator)));
+ if (activator == NULL) {
+ status = CELIX_ENOMEM;
+ } else {
+ void * userData = NULL;
+ bundle_context_pt context;
+ create_function_pt create = (create_function_pt) fw_getSymbol((handle_t) bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_CREATE);
+ start_function_pt start = (start_function_pt) fw_getSymbol((handle_t) bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_START);
+ stop_function_pt stop = (stop_function_pt) fw_getSymbol((handle_t) bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_STOP);
+ destroy_function_pt destroy = (destroy_function_pt) fw_getSymbol((handle_t) bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_DESTROY);
+
+ activator->start = start;
+ activator->stop = stop;
+ activator->destroy = destroy;
+ status = CELIX_DO_IF(status, bundle_setActivator(bundle, activator));
+
+ status = CELIX_DO_IF(status, framework_setBundleStateAndNotify(framework, bundle, OSGI_FRAMEWORK_BUNDLE_STARTING));
+ status = CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_STARTING, bundle));
+
+ status = CELIX_DO_IF(status, bundle_getContext(bundle, &context));
+
+ if (status == CELIX_SUCCESS) {
+ if (create != NULL) {
+ status = CELIX_DO_IF(status, create(context, &userData));
+ if (status == CELIX_SUCCESS) {
+ activator->userData = userData;
+ }
+ }
+ }
+ if (status == CELIX_SUCCESS) {
+ if (start != NULL) {
+ status = CELIX_DO_IF(status, start(userData, context));
+ }
+ }
+
+ 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));
+ }
+ }
+
+ break;
+ }
+ }
+
+ framework_releaseBundleLock(framework, bundle);
+
+ if (status != CELIX_SUCCESS) {
+ module_pt module = NULL;
+ const char *symbolicName = NULL;
+ long id = 0;
+ bundle_getCurrentModule(bundle, &module);
+ module_getSymbolicName(module, &symbolicName);
+ bundle_getBundleId(bundle, &id);
+ if (error != NULL) {
+ fw_logCode(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, status, "Could not start bundle: %s [%ld]; cause: %s", symbolicName, id, error);
+ } 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;
+}
+
+celix_status_t framework_updateBundle(framework_pt framework, bundle_pt bundle, const char *inputFile) {
+ celix_status_t status = CELIX_SUCCESS;
+ bundle_state_e oldState;
+ const char *location;
+ bundle_archive_pt archive = NULL;
+ char *error = NULL;
+
+ status = CELIX_DO_IF(status, framework_acquireBundleLock(framework, bundle, OSGI_FRAMEWORK_BUNDLE_INSTALLED|OSGI_FRAMEWORK_BUNDLE_RESOLVED|OSGI_FRAMEWORK_BUNDLE_ACTIVE));
+ status = CELIX_DO_IF(status, bundle_getState(bundle, &oldState));
+ if (status == CELIX_SUCCESS) {
+ if (oldState == OSGI_FRAMEWORK_BUNDLE_ACTIVE) {
+ fw_stopBundle(framework, bundle, false);
+ }
+ }
+ status = CELIX_DO_IF(status, bundle_getArchive(bundle, &archive));
+ status = CELIX_DO_IF(status, bundleArchive_getLocation(archive, &location));
+
+ if (status == CELIX_SUCCESS) {
+ bool locked = framework_acquireGlobalLock(framework);
+ if (!locked) {
+ status = CELIX_BUNDLE_EXCEPTION;
+ error = "Unable to acquire the global lock to update the bundle";
+ }
+ }
+
+ status = CELIX_DO_IF(status, bundle_revise(bundle, location, inputFile));
+ status = CELIX_DO_IF(status, framework_releaseGlobalLock(framework));
+
+ status = CELIX_DO_IF(status, bundleArchive_setLastModified(archive, time(NULL)));
+ status = CELIX_DO_IF(status, framework_setBundleStateAndNotify(framework, bundle, OSGI_FRAMEWORK_BUNDLE_INSTALLED));
+
+ bundle_revision_pt revision = NULL;
+ array_list_pt handles = NULL;
+ status = CELIX_DO_IF(status, bundleArchive_getCurrentRevision(archive, &revision));
+ status = CELIX_DO_IF(status, bundleRevision_getHandles(revision, &handles));
+ if (handles != NULL) {
+ int i;
+ for (i = arrayList_size(handles) - 1; i >= 0; i--) {
+ void* handle = arrayList_get(handles, i);
+ fw_closeLibrary(handle);
+ }
+ }
+
+
+ status = CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_UNRESOLVED, bundle));
+ status = CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_UPDATED, bundle));
+
+ // Refresh packages?
+
+ if (status == CELIX_SUCCESS) {
+ if (oldState == OSGI_FRAMEWORK_BUNDLE_ACTIVE) {
+ status = CELIX_DO_IF(status, fw_startBundle(framework, bundle, 1));
+ }
+ }
+
+ framework_releaseBundleLock(framework, bundle);
+
+ if (status != CELIX_SUCCESS) {
+ module_pt module = NULL;
+ const char *symbolicName = NULL;
+ long id = 0;
+ bundle_getCurrentModule(bundle, &module);
+ module_getSymbolicName(module, &symbolicName);
+ bundle_getBundleId(bundle, &id);
+ if (error != NULL) {
+ fw_logCode(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, status, "Cannot update bundle: %s [%ld]; cause: %s", symbolicName, id, error);
+ } else {
+ fw_logCode(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, status, "Cannot update bundle: %s [%ld]", symbolicName, id);
+ }
+ }
+
+ return status;
+}
+
+celix_status_t fw_stopBundle(framework_pt framework, bundle_pt bundle, bool record) {
+ celix_status_t status = CELIX_SUCCESS;
+ bundle_state_e state;
+ activator_pt activator = NULL;
+ bundle_context_pt context = NULL;
+ bool wasActive = false;
+ long id = 0;
+ char *error = NULL;
+
+ status = CELIX_DO_IF(status, framework_acquireBundleLock(framework, bundle, OSGI_FRAMEWORK_BUNDLE_INSTALLED|OSGI_FRAMEWORK_BUNDLE_RESOLVED|OSGI_FRAMEWORK_BUNDLE_STARTING|OSGI_FRAMEWORK_BUNDLE_ACTIVE));
+
+ if (record) {
+ status = CELIX_DO_IF(status, bundle_setPersistentStateInactive(bundle));
+ }
+
+ status = CELIX_DO_IF(status, bundle_getState(bundle, &state));
+ if (status == CELIX_SUCCESS) {
+ switch (state) {
+ case OSGI_FRAMEWORK_BUNDLE_UNKNOWN:
+ status = CELIX_ILLEGAL_STATE;
+ error = "state is unknown";
+ break;
+ case OSGI_FRAMEWORK_BUNDLE_UNINSTALLED:
+ status = CELIX_ILLEGAL_STATE;
+ error = "bundle is uninstalled";
+ break;
+ case OSGI_FRAMEWORK_BUNDLE_STARTING:
+ status = CELIX_BUNDLE_EXCEPTION;
+ error = "bundle is starting";
+ break;
+ case OSGI_FRAMEWORK_BUNDLE_STOPPING:
+ status = CELIX_BUNDLE_EXCEPTION;
+ error = "bundle is stopping";
+ break;
+ case OSGI_FRAMEWORK_BUNDLE_INSTALLED:
+ case OSGI_FRAMEWORK_BUNDLE_RESOLVED:
+ break;
+ case OSGI_FRAMEWORK_BUNDLE_ACTIVE:
+ wasActive = true;
+ break;
+ }
+ }
+
+
+ status = CELIX_DO_IF(status, framework_setBundleStateAndNotify(framework, bundle, OSGI_FRAMEWORK_BUNDLE_STOPPING));
+ status = CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_STOPPING, bundle));
+ status = CELIX_DO_IF(status, bundle_getBundleId(bundle, &id));
+ if (status == CELIX_SUCCESS) {
+ if (wasActive || (id == 0)) {
+ activator = bundle_getActivator(bundle);
+
+ status = CELIX_DO_IF(status, bundle_getContext(bundle, &context));
+ if (status == CELIX_SUCCESS) {
+ if (activator->stop != NULL) {
+ status = CELIX_DO_IF(status, activator->stop(activator->userData, context));
+ }
+ }
+ if (status == CELIX_SUCCESS) {
+ if (activator->destroy != NULL) {
+ status = CELIX_DO_IF(status, activator->destroy(activator->userData, context));
+ }
+ }
+
+ if (id != 0) {
+ status = CELIX_DO_IF(status, serviceRegistry_clearServiceRegistrations(framework->registry, bundle));
+ if (status == CELIX_SUCCESS) {
+ module_pt module = NULL;
+ const char *symbolicName = NULL;
+ long id = 0;
+ bundle_getCurrentModule(bundle, &module);
+ module_getSymbolicName(module, &symbolicName);
+ bundle_getBundleId(bundle, &id);
+
+ serviceRegistry_clearReferencesFor(framework->registry, bundle);
+ }
+ // #TODO remove listeners for bundle
+
+ if (context != NULL) {
+ status = CELIX_DO_IF(status, bundleContext_destroy(context));
+ status = CELIX_DO_IF(status, bundle_setContext(bundle, NULL));
+ }
+
+ status = CELIX_DO_IF(status, framework_setBundleStateAndNotify(framework, bundle, OSGI_FRAMEWORK_BUNDLE_RESOLVED));
+ }
+ }
+
+ if (activator != NULL) {
+ bundle_setActivator(bundle, NULL);
+ free(activator);
+ }
+ }
+
+ framework_releaseBundleLock(framework, bundle);
+
+ if (status != CELIX_SUCCESS) {
+ module_pt module = NULL;
+ const char *symbolicName = NULL;
+ long id = 0;
+ bundle_getCurrentModule(bundle, &module);
+ module_getSymbolicName(module, &symbolicName);
+ bundle_getBundleId(bundle, &id);
+ if (error != NULL) {
+ fw_logCode(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, status, "Cannot stop bundle: %s [%ld]; cause: %s", symbolicName, id, error);
+ } else {
+ fw_logCode(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, status, "Cannot stop bundle: %s [%ld]", symbolicName, id);
+ }
+ } else {
+ fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_STOPPED, bundle);
+ }
+
+ return status;
+}
+
+celix_status_t fw_uninstallBundle(framework_pt framework, bundle_pt bundle) {
+ celix_status_t status = CELIX_SUCCESS;
+ bool locked;
+ bundle_archive_pt archive = NULL;
+ const char * location = NULL;
+ bundle_pt target = NULL;
+ char *error = NULL;
+
+ status = CELIX_DO_IF(status, framework_acquireBundleLock(framework, bundle, OSGI_FRAMEWORK_BUNDLE_INSTALLED|OSGI_FRAMEWORK_BUNDLE_RESOLVED|OSGI_FRAMEWORK_BUNDLE_STARTING|OSGI_FRAMEWORK_BUNDLE_ACTIVE|OSGI_FRAMEWORK_BUNDLE_STOPPING));
+ status = CELIX_DO_IF(status, fw_stopBundle(framework, bundle, true));
+ if (status == CELIX_SUCCESS) {
+ locked = framework_acquireGlobalLock(framework);
+ if (!locked) {
+ status = CELIX_ILLEGAL_STATE;
+ error = "Unable to acquire the global lock to uninstall the bundle";
+ }
+ }
+
+ status = CELIX_DO_IF(status, bundle_getArchive(bundle, &archive));
+ status = CELIX_DO_IF(status, bundleArchive_getLocation(archive, &location));
+ if (status == CELIX_SUCCESS) {
+
+ celixThreadMutex_lock(&framework->installedBundleMapLock);
+
+ hash_map_entry_pt entry = hashMap_getEntry(framework->installedBundleMap, location);
+ char* entryLocation = hashMapEntry_getKey(entry);
+
+ target = (bundle_pt) hashMap_remove(framework->installedBundleMap, location);
+
+ free(entryLocation);
+ if (target != NULL) {
+ status = CELIX_DO_IF(status, bundle_setPersistentStateUninstalled(target));
+ // fw_rememberUninstalledBundle(framework, target);
+ }
+ celixThreadMutex_unlock(&framework->installedBundleMapLock);
+
+ }
+
+ framework_releaseGlobalLock(framework);
+
+ if (status == CELIX_SUCCESS) {
+ if (target == NULL) {
+ fw_log(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, "Could not remove bundle from installed map");
+ }
+ }
+
+ status = CELIX_DO_IF(status, framework_setBundleStateAndNotify(framework, bundle, OSGI_FRAMEWORK_BUNDLE_INSTALLED));
+
+ // TODO Unload all libraries for transition to unresolved
+ bundle_revision_pt revision = NULL;
+ array_list_pt handles = NULL;
+ status = CELIX_DO_IF(status, bundleArchive_getCurrentRevision(archive, &revision));
+ status = CELIX_DO_IF(status, bundleRevision_getHandles(revision, &handles));
+ if(handles != NULL){
+ for (int i = arrayList_size(handles) - 1; i >= 0; i--) {
+ void *handle = arrayList_get(handles, i);
+ fw_closeLibrary(handle);
+ }
+ }
+
+ status = CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_UNRESOLVED, bundle));
+
+ status = CELIX_DO_IF(status, framework_setBundleStateAndNotify(framework, bundle, OSGI_FRAMEWORK_BUNDLE_UNINSTALLED));
+ status = CELIX_DO_IF(status, bundleArchive_setLastModified(archive, time(NULL)));
+
+ framework_releaseBundleLock(framework, bundle);
+
+ status = CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_UNINSTALLED, bundle));
+
+ if (status == CELIX_SUCCESS) {
+ locked = framework_acquireGlobalLock(framework);
+ if (locked) {
+ bundle_pt bundles[] = { bundle };
+ celix_status_t refreshStatus = fw_refreshBundles(framework, bundles, 1);
+ if (refreshStatus != CELIX_SUCCESS) {
+ printf("Could not refresh bundle");
+ } else {
+ bundleArchive_destroy(archive);
+ status = CELIX_DO_IF(status, bundle_destroy(bundle));
+ }
+
+ status = CELIX_DO_IF(status, framework_releaseGlobalLock(framework));
+ }
+ }
+
+
+ if (status != CELIX_SUCCESS) {
+// module_pt module = NULL;
+// char *symbolicName = NULL;
+// long id = 0;
+// bundle_getCurrentModule(bundle, &module);
+// module_getSymbolicName(module, &symbolicName);
+// bundle_getBundleId(bundle, &id);
+
+ framework_logIfError(framework->logger, status, error, "Cannot uninstall bundle");
+ }
+
+ return status;
+}
+
+celix_status_t fw_refreshBundles(framework_pt framework, bundle_pt bundles[], int size) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ bool locked = framework_acquireGlobalLock(framework);
+ if (!locked) {
+ framework_releaseGlobalLock(framework);
+ status = CELIX_ILLEGAL_STATE;
+ } else {
+ hash_map_values_pt values;
+ bundle_pt *newTargets;
+ unsigned int nrofvalues;
+ bool restart = false;
+ hash_map_pt map = hashMap_create(NULL, NULL, NULL, NULL);
+ int targetIdx = 0;
+ for (targetIdx = 0; targetIdx < size; targetIdx++) {
+ bundle_pt bundle = bundles[targetIdx];
+ hashMap_put(map, bundle, bundle);
+ fw_populateDependentGraph(framework, bundle, &map);
+ }
+ values = hashMapValues_create(map);
+ hashMapValues_toArray(values, (void ***) &newTargets, &nrofvalues);
+ hashMapValues_destroy(values);
+
+ hashMap_destroy(map, false, false);
+
+ if (newTargets != NULL) {
+ int i = 0;
+ struct fw_refreshHelper * helpers;
+ for (i = 0; i < nrofvalues && !restart; i++) {
+ bundle_pt bundle = (bundle_pt) newTargets[i];
+ if (framework->bundle == bundle) {
+ restart = true;
+ }
+ }
+
+ helpers = (struct fw_refreshHelper * )malloc(nrofvalues * sizeof(struct fw_refreshHelper));
+ for (i = 0; i < nrofvalues && !restart; i++) {
+ bundle_pt bundle = (bundle_pt) newTargets[i];
+ helpers[i].framework = framework;
+ helpers[i].bundle = bundle;
+ helpers[i].oldState = OSGI_FRAMEWORK_BUNDLE_INSTALLED;
+ }
+
+ for (i = 0; i < nrofvalues; i++) {
+ struct fw_refreshHelper helper = helpers[i];
+ fw_refreshHelper_stop(&helper);
+ fw_refreshHelper_refreshOrRemove(&helper);
+ }
+
+ for (i = 0; i < nrofvalues; i++) {
+ struct fw_refreshHelper helper = helpers[i];
+ fw_refreshHelper_restart(&helper);
+ }
+
+ if (restart) {
+ bundle_update(framework->bundle, NULL);
+ }
+ free(helpers);
+ free(newTargets);
+ }
+
+ framework_releaseGlobalLock(framework);
+ }
+
+ framework_logIfError(framework->logger, status, NULL, "Cannot refresh bundles");
+
+ return status;
+}
+
+celix_status_t fw_refreshBundle(framework_pt framework, bundle_pt bundle) {
+ celix_status_t status = CELIX_SUCCESS;
+ bundle_state_e state;
+
+ status = framework_acquireBundleLock(framework, bundle, OSGI_FRAMEWORK_BUNDLE_INSTALLED | OSGI_FRAMEWORK_BUNDLE_RESOLVED);
+ if (status != CELIX_SUCCESS) {
+ printf("Cannot refresh bundle");
+ framework_releaseBundleLock(framework, bundle);
+ } else {
+ bool fire;
+ bundle_getState(bundle, &state);
+ fire = (state != OSGI_FRAMEWORK_BUNDLE_INSTALLED);
+ bundle_refresh(bundle);
+
+ if (fire) {
+ framework_setBundleStateAndNotify(framework, bundle, OSGI_FRAMEWORK_BUNDLE_INSTALLED);
+ fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_UNRESOLVED, bundle);
+ }
+
+ framework_releaseBundleLock(framework, bundle);
+ }
+
+ framework_logIfError(framework->logger, status, NULL, "Cannot refresh bundle");
+
+ return status;
+}
+
+celix_status_t fw_refreshHelper_stop(struct fw_refreshHelper * refreshHelper) {
+ bundle_state_e state;
+ bundle_getState(refreshHelper->bundle, &state);
+ if (state == OSGI_FRAMEWORK_BUNDLE_ACTIVE) {
+ refreshHelper->oldState = OSGI_FRAMEWORK_BUNDLE_ACTIVE;
+ fw_stopBundle(refreshHelper->framework, refreshHelper->bundle, false);
+ }
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t fw_refreshHelper_refreshOrRemove(struct fw_refreshHelper * refreshHelper) {
+ bundle_state_e state;
+ bundle_getState(refreshHelper->bundle, &state);
+ if (state == OSGI_FRAMEWORK_BUNDLE_UNINSTALLED) {
+ bundle_closeAndDelete(refreshHelper->bundle);
+ refreshHelper->bundle = NULL;
+ } else {
+ fw_refreshBundle(refreshHelper->framework, refreshHelper->bundle);
+ }
+ return CELIX_SUCCESS;
+}
+
+celix_status_t fw_refreshHelper_restart(struct fw_refreshHelper * refreshHelper) {
+ if ((refreshHelper->bundle != NULL) && (refreshHelper->oldState == OSGI_FRAMEWORK_BUNDLE_ACTIVE)) {
+ fw_startBundle(refreshHelper->framework, refreshHelper->bundle, 0);
+ }
+ return CELIX_SUCCESS;
+}
+
+celix_status_t fw_getDependentBundles(framework_pt framework, bundle_pt exporter, array_list_pt *list) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ if (*list != NULL || exporter == NULL || framework == NULL) {
+ return CELIX_ILLEGAL_ARGUMENT;
+ }
+
+ array_list_pt modules;
+ unsigned int modIdx = 0;
+ arrayList_create(list);
+
+ modules = bundle_getModules(exporter);
+ for (modIdx = 0; modIdx < arrayList_size(modules); modIdx++) {
+ module_pt module = (module_pt) arrayList_get(modules, modIdx);
+ array_list_pt dependents = module_getDependents(module);
+ if(dependents!=NULL){
+ unsigned int depIdx = 0;
+ for (depIdx = 0; depIdx < arrayList_size(dependents); depIdx++) {
+ module_pt dependent = (module_pt) arrayList_get(dependents, depIdx);
+ arrayList_add(*list, module_getBundle(dependent));
+ }
+ arrayList_destroy(dependents);
+ }
+ }
+
+ framework_logIfError(framework->logger, status, NULL, "Cannot get dependent bundles");
+
+ return status;
+}
+
+celix_status_t fw_populateDependentGraph(framework_pt framework, bundle_pt exporter, hash_map_pt *map) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ if(framework == NULL || exporter == NULL){
+ return CELIX_ILLEGAL_ARGUMENT;
+ }
+
+ array_list_pt dependents = NULL;
+ if ((status = fw_getDependentBundles(framework, exporter, &dependents)) == CELIX_SUCCESS) {
+ if(dependents!=NULL){
+ unsigned int depIdx = 0;
+ for (depIdx = 0; depIdx < arrayList_size(dependents); depIdx++) {
+ if (!hashMap_containsKey(*map, arrayList_get(dependents, depIdx))) {
+ hashMap_put(*map, arrayList_get(dependents, depIdx), arrayList_get(dependents, depIdx));
+ fw_populateDependentGraph(framework, (bundle_pt) arrayList_get(dependents, depIdx), map);
+ }
+ }
+ arrayList_destroy(dependents);
+ }
+ }
+
+ framework_logIfError(framework->logger, status, NULL, "Cannot populate dependent graph");
+
+ return status;
+}
+
+celix_status_t fw_registerService(framework_pt framework, service_registration_pt *registration, bundle_pt bundle, const char* serviceName, const void* svcObj, properties_pt properties) {
+ celix_status_t status = CELIX_SUCCESS;
+ char *error = NULL;
+ if (serviceName == NULL || svcObj == NULL) {
+ status = CELIX_ILLEGAL_ARGUMENT;
+ error = "ServiceName and SvcObj cannot be null";
+ }
+
+ status = CELIX_DO_IF(status, framework_acquireBundleLock(framework, bundle, OSGI_FRAMEWORK_BUNDLE_STARTING|OSGI_FRAMEWORK_BUNDLE_ACTIVE));
+ status = CELIX_DO_IF(status, serviceRegistry_registerService(framework->registry, bundle, serviceName, svcObj, properties, registration));
+ bool res = framework_releaseBundleLock(framework, bundle);
+ if (!res) {
+ status = CELIX_ILLEGAL_STATE;
+ error = "Could not release bundle lock";
+ }
+
+ if (status == CELIX_SUCCESS) {
+ // If this is a listener hook, invoke the callback with all current listeners
+ if (strcmp(serviceName, OSGI_FRAMEWORK_LISTENER_HOOK_SERVICE_NAME) == 0) {
+ unsigned int i;
+ array_list_pt infos = NULL;
+ service_reference_pt ref = NULL;
+ listener_hook_service_pt hook = NULL;
+
+ status = CELIX_DO_IF(status, arrayList_create(&infos));
+
+ if (status == CELIX_SUCCESS) {
+ celix_status_t subs = CELIX_SUCCESS;
+
+ 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;
+ listener_hook_info_pt info = NULL;
+ bundle_context_pt lContext = NULL;
+
+ subs = CELIX_DO_IF(subs, bundle_getContext(bundle, &context));
+ if (subs == CELIX_SUCCESS) {
+ info = (listener_hook_info_pt) malloc(sizeof(*info));
+ if (info == NULL) {
+ subs = CELIX_ENOMEM;
+ }
+ }
+
+ subs = CELIX_DO_IF(subs, bundle_getContext(listener->bundle, &lContext));
+ if (subs == CELIX_SUCCESS) {
+ info->context = lContext;
+ info->removed = false;
+ }
+ subs = CELIX_DO_IF(subs, filter_getString(listener->filter, (const char**)&info->filter));
+
+ if (subs == CELIX_SUCCESS) {
+ arrayList_add(infos, info);
+ }
+ else{
+ fw_logCode(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, status, "Could not pass all listeners to the hook: %s", serviceName);
+ free(info);
+ }
+ }
+
+ status = CELIX_DO_IF(status, serviceRegistry_getServiceReference(framework->registry, framework->bundle,
+ *registration, &ref));
+ status = CELIX_DO_IF(status, fw_getService(framework,framework->bundle, ref, (const void **) &hook));
+ if (status == CELIX_SUCCESS) {
+ hook->added(hook->handle, infos);
+ }
+ status = CELIX_DO_IF(status, serviceRegistry_ungetService(framework->registry, framework->bundle, ref, NULL));
+ status = CELIX_DO_IF(status, serviceRegistry_ungetServiceReference(framework->registry, framework->bundle, ref));
+
+ int i = 0;
+ for (i = 0; i < arrayList_size(infos); i++) {
+ listener_hook_info_pt info = arrayList_get(infos, i);
+ free(info);
+ }
+ arrayList_destroy(infos);
+ }
+ }
+ }
+
+ framework_logIfError(framework->logger, status, error, "Cannot register service: %s", serviceName);
+
+ return status;
+}
+
+celix_status_t fw_registerServiceFactory(framework_pt framework, service_registration_pt *registration, bundle_pt bundle, const char* serviceName, service_factory_pt factory, properties_pt properties) {
+ celix_status_t status = CELIX_SUCCESS;
+ char *error = NULL;
+ if (serviceName == NULL || factory == NULL) {
+ status = CELIX_ILLEGAL_ARGUMENT;
+ error = "Service name and factory cannot be null";
+ }
+
+ status = CELIX_DO_IF(status, framework_acquireBundleLock(framework, bundle, OSGI_FRAMEWORK_BUNDLE_STARTING|OSGI_FRAMEWORK_BUNDLE_ACTIVE));
+ status = CELIX_DO_IF(status, serviceRegistry_registerServiceFactory(framework->registry, bundle, serviceName, factory, properties, registration));
+ if (!framework_releaseBundleLock(framework, bundle)) {
+ status = CELIX_ILLEGAL_STATE;
+ error = "Could not release bundle lock";
+ }
+
+ framework_logIfError(framework->logger, status, error, "Cannot register service factory: %s", serviceName);
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t fw_getServiceReferences(framework_pt framework, array_list_pt *references, bundle_pt bundle, const char * serviceName, const char * sfilter) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ filter_pt filter = NULL;
+ unsigned int refIdx = 0;
+
+ if (sfilter != NULL) {
+ filter = filter_create(sfilter);
+ }
+
+ status = CELIX_DO_IF(status, serviceRegistry_getServiceReferences(framework->registry, bundle, serviceName, filter, references));
+
+ if (filter != NULL) {
+ filter_destroy(filter);
+ }
+
+ if (status == CELIX_SUCCESS) {
+ for (refIdx = 0; (*references != NULL) && refIdx < arrayList_size(*references); refIdx++) {
+ service_reference_pt ref = (service_reference_pt) arrayList_get(*references, refIdx);
+ service_registration_pt reg = NULL;
+ const char* serviceName;
+ properties_pt props = NULL;
+ status = CELIX_DO_IF(status, serviceReference_getServiceRegistration(ref, ®));
+ status = CELIX_DO_IF(status, serviceRegistration_getProperties(reg, &props));
+ if (status == CELIX_SUCCESS) {
+ serviceName = properties_get(props, OSGI_FRAMEWORK_OBJECTCLASS);
+ if (!serviceReference_isAssignableTo(ref, bundle, serviceName)) {
+ arrayList_remove(*references, refIdx);
+ refIdx--;
+ }
+ }
+ }
+ }
+
+ framework_logIfError(framework->logger, status, NULL, "Failed to get service references");
+
+ return status;
+}
+
+celix_status_t framework_ungetServiceReference(framework_pt framework, bundle_pt bundle, service_reference_pt reference) {
+ return serviceRegistry_ungetServiceReference(framework->registry, bundle, reference);
+}
+
+celix_status_t fw_getService(framework_pt framework, bundle_pt bundle, service_reference_pt reference, const void **service) {
+ return serviceRegistry_getService(framework->registry, bundle, reference, service);
+}
+
+celix_status_t fw_getBundleRegisteredServices(framework_pt framework, bundle_pt bundle, array_list_pt *services) {
+ return serviceRegistry_getRegisteredServices(framework->registry, bundle, services);
+}
+
+celix_status_t fw_getBundleServicesInUse(framework_pt framework, bundle_pt bundle, array_list_pt *services) {
+ celix_status_t status = CELIX_SUCCESS;
+ status = serviceRegistry_getServicesInUse(framework->registry, bundle, services);
+ return status;
+}
+
+celix_status_t framework_ungetService(framework_pt framework, bundle_pt bundle, service_reference_pt reference, bool *result) {
+ return serviceRegistry_ungetService(framework->registry, bundle, reference, result);
+}
+
+void fw_addServiceListener(framework_pt framework, bundle_pt bundle, service_listener_pt listener, const char* sfilter) {
+ array_list_pt listenerHooks = NULL;
+ listener_hook_info_pt info;
+ unsigned int i;
+
+ fw_service_listener_pt fwListener = (fw_service_listener_pt) calloc(1, sizeof(*fwListener));
+ bundle_context_pt context = NULL;
+
+ fwListener->bundle = bundle;
+ arrayList_create(&fwListener->retainedReferences);
+ if (sfilter != NULL) {
+ filter_pt filter = filter_create(sfilter);
+ fwListener->filter = filter;
+ } else {
+ fwListener->filter = NULL;
+ }
+ fwListener->listener = listener;
+
+ arrayList_add(framework->serviceListeners, fwListener);
+
+ serviceRegistry_getListenerHooks(framework->registry, framework->bundle, &listenerHooks);
+
+ info = (listener_hook_info_pt) malloc(sizeof(*info));
+
+ bundle_getContext(bundle, &context);
+ info->context = context;
+
+ info->removed = false;
+ info->filter = sfilter == NULL ? NULL : strdup(sfilter);
+
+ for (i = 0; i < arrayList_size(listenerHooks); i++) {
+ service_reference_pt ref = (service_reference_pt) arrayList_get(listenerHooks, i);
+ listener_hook_service_pt hook = NULL;
+ array_list_pt infos = NULL;
+ bool ungetResult = false;
+
+ fw_getService(framework, framework->bundle, ref, (const void **) &hook);
+
+ arrayList_create(&infos);
+ arrayList_add(infos, info);
+ hook->added(hook->handle, infos);
+ serviceRegistry_ungetService(framework->registry, framework->bundle, ref, &ungetResult);
+ serviceRegistry_ungetServiceReference(framework->registry, framework->bundle, ref);
+ arrayList_destroy(infos);
+ }
+
+ if (info->filter != NULL) {
+ free(info->filter);
+ }
+ free(info);
+
+ arrayList_destroy(listenerHooks);
+}
+
+void fw_removeServiceListener(framework_pt framework, bundle_pt bundle, service_listener_pt listener) {
+ listener_hook_info_pt info = NULL;
+ unsigned int i;
+ fw_service_listener_pt element;
+
+ bundle_context_pt context;
+ bundle_getContext(bundle, &context);
+
+ for (i = 0; i < arrayList_size(framework->serviceListeners); i++) {
+ element = (fw_service_listener_pt) arrayList_get(framework->serviceListeners, i);
+ if (element->listener == listener && element->bundle == bundle) {
+ bundle_context_pt lContext = NULL;
+
+ info = (listener_hook_info_pt) malloc(sizeof(*info));
+
+ bundle_getContext(element->bundle, &lContext);
+ info->context = lContext;
+
+ // TODO Filter toString;
+ filter_getString(element->filter, (const char**)&info->filter);
+ info->removed = true;
+
+ arrayList_remove(framework->serviceListeners, i);
+ i--;
+
+ //unregistering retained service references. For these refs a unregister event will not be triggered.
+ int k;
+ int rSize = arrayList_size(element->retainedReferences);
+ for (k = 0; k < rSize; k += 1) {
+ service_reference_pt ref = arrayList_get(element->retainedReferences, k);
+ if (ref != NULL) {
+ serviceRegistry_ungetServiceReference(framework->registry, element->bundle, ref); // decrease retain counter
+ }
+ }
+
+ element->bundle = NULL;
+ filter_destroy(element->filter);
+ arrayList_destroy(element->retainedReferences);
+ element->filter = NULL;
+ element->listener = NULL;
+ free(element);
+ element = NULL;
+ break;
+ }
+ }
+
+ if (info != NULL) {
+ unsigned int i;
+ array_list_pt listenerHooks = NULL;
+ serviceRegistry_getListenerHooks(framework->registry, framework->bundle, &listenerHooks);
+
+ for (i = 0; i < arrayList_size(listenerHooks); i++) {
+ service_reference_pt ref = (service_reference_pt) arrayList_get(listenerHooks, i);
+ listener_hook_service_pt hook = NULL;
+ array_list_pt infos = NULL;
+ bool ungetResult;
+
+ fw_getService(framework, framework->bundle, ref, (const void **) &hook);
+
+ arrayList_create(&infos);
+ arrayList_add(infos, info);
+ hook->removed(hook->handle, infos);
+ serviceRegistry_ungetService(framework->registry, framework->bundle, ref, &ungetResult);
+ serviceRegistry_ungetServiceReference(framework->registry, framework->bundle, ref);
+ arrayList_destroy(infos);
+ }
+
+ arrayList_destroy(listenerHooks);
+ free(info);
+ }
+}
+
+celix_status_t fw_addBundleListener(framework_pt framework, bundle_pt bundle, bundle_listener_pt listener) {
+ celix_status_t status = CELIX_SUCCESS;
+ fw_bundle_listener_pt bundleListener = NULL;
+
+ bundleListener = (fw_bundle_listener_pt) malloc(sizeof(*bundleListener));
+ if (!bundleListener) {
+ status = CELIX_ENOMEM;
+ } else {
+ bundleListener->listener = listener;
+ bundleListener->bundle = bundle;
+
+ if (celixThreadMutex_lock(&framework->bundleListenerLock) != CELIX_SUCCESS) {
+ status = CELIX_FRAMEWORK_EXCEPTION;
+ } else {
+ arrayList_add(framework->bundleListeners, bundleListener);
+
+ if (celixThreadMutex_unlock(&framework->bundleListenerLock)) {
+ status = CELIX_FRAMEWORK_EXCEPTION;
+ }
+ }
+ }
+
+ framework_logIfError(framework->logger, status, NULL, "Failed to add bundle listener");
+
+ return status;
+}
+
+celix_status_t fw_removeBundleListener(framework_pt framework, bundle_pt bundle, bundle_listener_pt listener) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ unsigned int i;
+ fw_bundle_listener_pt bundleListener;
+
+ if (celixThreadMutex_lock(&framework->bundleListenerLock) != CELIX_SUCCESS) {
+ status = CELIX_FRAMEWORK_EXCEPTION;
+ }
+ else {
+ for (i = 0; i < arrayList_size(framework->bundleListeners); i++) {
+ bundleListener = (fw_bundle_listener_pt) arrayList_get(framework->bundleListeners, i);
+ if (bundleListener->listener == listener && bundleListener->bundle == bundle) {
+ arrayList_remove(framework->bundleListeners, i);
+
+ bundleListener->bundle = NULL;
+ bundleListener->listener = NULL;
+ free(bundleListener);
+ }
+ }
+ if (celixThreadMutex_unlock(&framework->bundleListenerLock)) {
+ status = CELIX_FRAMEWORK_EXCEPTION;
+ }
+ }
+
+ framework_logIfError(framework->logger, status, NULL, "Failed to remove bundle listener");
+
+ return status;
+}
+
+celix_status_t fw_addFrameworkListener(framework_pt framework, bundle_pt bundle, framework_listener_pt listener) {
+ celix_status_t status = CELIX_SUCCESS;
+ fw_framework_listener_pt frameworkListener = NULL;
+
+ frameworkListener = (fw_framework_listener_pt) malloc(sizeof(*frameworkListener));
+ if (!frameworkListener) {
+ status = CELIX_ENOMEM;
+ } else {
+ frameworkListener->listener = listener;
+ frameworkListener->bundle = bundle;
+
+ arrayList_add(framework->frameworkListeners, frameworkListener);
+ }
+
+ framework_logIfError(framework->logger, status, NULL, "Failed to add framework listener");
+
+ return status;
+}
+
+celix_status_t fw_removeFrameworkListener(framework_pt framework, bundle_pt bundle, framework_listener_pt listener) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ unsigned int i;
+ fw_framework_listener_pt frameworkListener;
+
+ 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) {
+ arrayList_remove(framework->frameworkListeners, i);
+
+ frameworkListener->bundle = NULL;
+ frameworkListener->listener = NULL;
+ free(frameworkListener);
+ }
+ }
+
+ framework_logIfError(framework->logger, status, NULL, "Failed to remove framework listener");
+
+ return status;
+}
+
+void fw_serviceChanged(framework_pt framework, service_event_type_e eventType, service_registration_pt registration, properties_pt oldprops) {
+ unsigned int i;
+ fw_service_listener_pt element;
+
+ if (arrayList_size(framework->serviceListeners) > 0) {
+ for (i = 0; i < arrayList_size(framework->serviceListeners); i++) {
+ int matched = 0;
+ properties_pt props = NULL;
+ bool matchResult = false;
+
+ element = (fw_service_listener_pt) arrayList_get(framework->serviceListeners, i);
+ serviceRegistration_getProperties(registration, &props);
+ if (element->filter != NULL) {
+ filter_match(element->filter, props, &matchResult);
+ }
+ matched = (element->filter == NULL) || matchResult;
+ if (matched) {
+ service_reference_pt reference = NULL;
+ service_event_pt event;
+
+ event = (service_event_pt) malloc(sizeof (*event));
+
+ serviceRegistry_getServiceReference(framework->registry, element->bundle, registration, &reference);
+
+ //NOTE: that you are never sure that the UNREGISTERED event will by handle by an service_listener. listener could be gone
+ //Every reference retained is therefore stored and called when a service listener is removed from the framework.
+ if (eventType == OSGI_FRAMEWORK_SERVICE_EVENT_REGISTERED) {
+ serviceRegistry_retainServiceReference(framework->registry, element->bundle, reference);
+ arrayList_add(element->retainedReferences, reference); //TODO improve by using set (or hashmap) instead of list
+ }
+
+ event->type = eventType;
+ event->reference = reference;
+
+ element->listener->serviceChanged(element->listener, event);
+
+ serviceRegistry_ungetServiceReference(framework->registry, element->bundle, reference);
+
+ if (eventType == OSGI_FRAMEWORK_SERVICE_EVENT_UNREGISTERING) {
+ //if service listener was active when service was registered, release the retained reference
+ if (arrayList_removeElement(element->retainedReferences, reference)) {
+ serviceRegistry_ungetServiceReference(framework->registry, element->bundle, reference); // decrease retain counter
+ }
+ }
+
+ free(event);
+
+ } else if (eventType == OSGI_FRAMEWORK_SERVICE_EVENT_MODIFIED) {
+ bool matchResult = false;
+ int matched = 0;
+ if (element->filter != NULL) {
+ filter_match(element->filter, oldprops, &matchResult);
+ }
+ matched = (element->filter == NULL) || matchResult;
+ if (matched) {
+ service_reference_pt reference = NULL;
+ service_event_pt endmatch = (service_event_pt) malloc(sizeof (*endmatch));
+
+ serviceRegistry_getServiceReference(framework->registry, element->bundle, registration, &reference);
+
+ endmatch->reference = reference;
+ endmatch->type = OSGI_FRAMEWORK_SERVICE_EVENT_MODIFIED_ENDMATCH;
+ element->listener->serviceChanged(element->listener, endmatch);
+
+ serviceRegistry_ungetServiceReference(framework->registry, element->bundle, reference);
+ free(endmatch);
+
+ }
+ }
+ }
+ }
+
+}
+
+//celix_status_t fw_isServiceAssignable(framework_pt fw, bundle_pt requester, service_reference_pt reference, bool *assignable) {
+// celix_status_t status = CELIX_SUCCESS;
+//
+// *assignable = true;
+// service_registration_pt registration = NULL;
+// status = serviceReference_getServiceRegistration(reference, ®istration);
+// if (status == CELIX_SUCCESS) {
+// char *serviceName = properties_get(registration->properties, (char *) OBJECTCLASS);
+// if (!serviceReference_isAssignableTo(reference, requester, serviceName)) {
+// *assignable = false;
+// }
+// }
+//
+// return status;
+//}
+
+long framework_getNextBundleId(framework_pt framework) {
+ long id = framework->nextBundleId;
+ framework->nextBundleId++;
+ return id;
+}
+
+celix_status_t framework_markResolvedModules(framework_pt framework, linked_list_pt resolvedModuleWireMap) {
+ if (resolvedModuleWireMap != NULL) {
+ // hash_map_iterator_pt iterator = hashMapIterator_create(resolvedModuleWireMap);
+ linked_list_iterator_pt iterator = linkedListIterator_create(resolvedModuleWireMap, linkedList_size(resolvedModuleWireMap));
+ while (linkedListIterator_hasPrevious(iterator)) {
+ importer_wires_pt iw = linkedListIterator_previous(iterator);
+ // hash_map_entry_pt entry = hashMapIterator_nextEntry(iterator);
+ module_pt module = iw->importer;
+
+// bundle_pt bundle = module_getBundle(module);
+// bundle_archive_pt archive = NULL;
+// bundle_getArchive(bundle, &archive);
+// bundle_revision_pt revision = NULL;
+// bundleArchive_getCurrentRevision(archive, &revision);
+// char *root = NULL;
+// bundleRevision_getRoot(revision, &root);
+// manifest_pt manifest = NULL;
+// bundleRevision_getManifest(revision, &manifest);
+//
+// char *private = manifest_getValue(manifest, OSGI_FRAMEWORK_PRIVATE_LIBRARY);
+// char *export = manifest_getValue(manifest, OSGI_FRAMEWORK_EXPORT_LIBRARY);
+//
+// printf("Root %s\n", root);
+
+ // for each library update the reference to the wires, if there are any
+
+ linked_list_pt wires = iw->wires;
+
+// linked_list_iterator_pt wit = linkedListIterator_create(wires, 0);
+// while (linkedListIterator_hasNext(wit)) {
+// wire_pt wire = linkedListIterator_next(wit);
+// module_pt importer = NULL;
+// requirement_pt requirement = NULL;
+// module_pt exporter = NULL;
+// capability_pt capability = NULL;
+// wire_getImporter(wire, &importer);
+// wire_getRequirement(wire, &requirement);
+//
+// wire_getExporter(wire, &exporter);
+// wire_getCapability(wire, &capability);
+//
+// char *importerName = NULL;
+// module_getSymbolicName(importer, &importerName);
+//
+// char *exporterName = NULL;
+// module_getSymbolicName(exporter, &exporterName);
+//
+// version_pt version = NULL;
+// char *name = NULL;
+// capability_getServiceName(capability, &name);
+// capability_getVersion(capability, &version);
+// char *versionString = NULL;
+// version_toString(version, framework->mp, &versionString);
+//
+// printf("Module %s imports library %s:%s from %s\n", importerName, name, versionString, exporterName);
+// }
+
+ module_setWires(module, wires);
+
+ module_setResolved(module);
+ resolver_moduleResolved(module);
+
+ const char *mname = NULL;
+ module_getSymbolicName(module, &mname);
+ framework_markBundleResolved(framework, module);
+ linkedListIterator_remove(iterator);
+ free(iw);
+ }
+ linkedListIterator_destroy(iterator);
+ linkedList_destroy(resolvedModuleWireMap);
+ }
+ return CELIX_SUCCESS;
+}
+
+celix_status_t framework_markBundleResolved(framework_pt framework, module_pt module) {
+ celix_status_t status = CELIX_SUCCESS;
+ bundle_pt bundle = module_getBundle(module);
+ bundle_state_e state;
+ char *error = NULL;
+
+ if (bundle != NULL) {
+ framework_acquireBundleLock(framework, bundle, OSGI_FRAMEWORK_BUNDLE_INSTALLED|OSGI_FRAMEWORK_BUNDLE_RESOLVED|OSGI_FRAMEWORK_BUNDLE_ACTIVE);
+ bundle_getState(bundle, &state);
+ if (state != OSGI_FRAMEWORK_BUNDLE_INSTALLED) {
+ printf("Trying to resolve a resolved bundle");
+ status = CELIX_ILLEGAL_STATE;
+ } else {
+ // Load libraries of this module
+ bool isSystemBundle = false;
+ bundle_isSystemBundle(bundle, &isSystemBundle);
+ if (!isSystemBundle) {
+ status = CELIX_DO_IF(status, framework_loadBundleLibraries(framework, bundle));
+ }
+
+ status = CELIX_DO_IF(status, framework_setBundleStateAndNotify(framework, bundle, OSGI_FRAMEWORK_BUNDLE_RESOLVED));
+ status = CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_RESOLVED, bundle));
+ }
+
+ if (status != CELIX_SUCCESS) {
+ module_pt module = NULL;
+ const char *symbolicName = NULL;
+ long id = 0;
+ module_getSymbolicName(module, &symbolicName);
+ bundle_getBundleId(bundle, &id);
+ if (error != NULL) {
+ fw_logCode(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, status, "Could not start bundle: %s [%ld]; cause: %s", symbolicName, id, error);
+ } else {
+ fw_logCode(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, status, "Could not start bundle: %s [%ld]", symbolicName, id);
+ }
+ }
+
+ framework_releaseBundleLock(framework, bundle);
+ }
+
+ return CELIX_SUCCESS;
+}
+
+array_list_pt framework_getBundles(framework_pt framework) {
+ array_list_pt bundles = NULL;
+ hash_map_iterator_pt iterator;
+ arrayList_create(&bundles);
+
+ celixThreadMutex_lock(&framework->installedBundleMapLock);
+
+ iterator = hashMapIterator_create(framework->installedBundleMap);
+ while (hashMapIterator_hasNext(iterator)) {
+ bundle_pt bundle = (bundle_pt) hashMapIterator_nextValue(iterator);
+ arrayList_add(bundles, bundle);
+ }
+ hashMapIterator_destroy(iterator);
+
+ celixThreadMutex_unlock(&framework->installedBundleMapLock);
+
+ return bundles;
+}
+
+bundle_pt framework_getBundle(framework_pt framework, const char* location) {
+ celixThreadMutex_lock(&framework->installedBundleMapLock);
+ bundle_pt bundle = (bundle_pt) hashMap_get(framework->installedBundleMap, location);
+ celixThreadMutex_unlock(&framework->installedBundleMapLock);
+ return bundle;
+}
+
+bundle_pt framework_getBundleById(framework_pt framework, long id) {
+ celixThreadMutex_lock(&framework->installedBundleMapLock);
+ hash_map_iterator_pt iter = hashMapIterator_create(framework->installedBundleMap);
+ bundle_pt bundle = NULL;
+ while (hashMapIterator_hasNext(iter)) {
+ bundle_pt b = (bundle_pt) hashMapIterator_nextValue(iter);
+ bundle_archive_pt archive = NULL;
+ long bid;
+ bundle_getArchive(b, &archive);
+ bundleArchive_getId(archive, &bid);
+ if (bid == id) {
+ bundle = b;
+ break;
+ }
+ }
+ hashMapIterator_destroy(iter);
+ celixThreadMutex_unlock(&framework->installedBundleMapLock);
+
+ return bundle;
+}
+
+celix_status_t framework_acquireInstallLock(framework_pt framework, const char * location) {
+ celixThreadMutex_lock(&framework->installRequestLock);
+
+ while (hashMap_get(framework->installRequestMap, location) != NULL) {
+ celixThreadCondition_wait(&framework->condition, &framework->installRequestLock);
+ }
+ hashMap_put(framework->installRequestMap, (char*)location, (char*)location);
+
+ celixThreadMutex_unlock(&framework->installRequestLock);
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t framework_releaseInstallLock(framework_pt framework, const char* location) {
+ celixThreadMutex_lock(&framework->installRequestLock);
+
+ hashMap_remove(framework->installRequestMap, location);
+ celixThreadCondition_broadcast(&framework->condition);
+
+ celixThreadMutex_unlock(&framework->installRequestLock);
+
+ return CELIX_SUCCESS;
+}
+
+celix_status_t framework_setBundleStateAndNotify(framework_pt framework, bundle_pt bundle, int state) {
+ int ret = CELIX_SUCCESS;
+
+ int err = celixThreadMutex_lock(&framework->bundleLock);
+ if (err != 0) {
+ fw_log(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, "Failed to lock");
+ return CELIX_BUNDLE_EXCEPTION;
+ }
+
+ bundle_setState(bundle, state);
+ err = celixThreadCondition_broadcast(&framework->condition);
+ if (err != 0) {
+ fw_log(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, "Failed to broadcast");
+ ret = CELIX_BUNDLE_EXCEPTION;
+ }
+
+ err = celixThreadMutex_unlock(&framework->bundleLock);
+ if (err != 0) {
+ fw_log(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, "Failed to unlock");
+ return CELIX_BUNDLE_EXCEPTION;
+ }
+ return ret;
+}
+
+celix_status_t framework_acquireBundleLock(framework_pt framework, bundle_pt bundle, int desiredStates) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ bool locked;
+ celix_thread_t lockingThread = celix_thread_default;
+
+ int err = celixThreadMutex_lock(&framework->bundleLock);
+ if (err != CELIX_SUCCESS) {
+ fw_log(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, "Failed to lock");
+ status = CELIX_BUNDLE_EXCEPTION;
+ } else {
+ bool lockable = false;
+ bool isSelf = false;
+
+ bundle_isLockable(bundle, &lockable);
+ thread_equalsSelf(framework->globalLockThread, &isSelf);
+
+ while (!lockable
+ || (( celixThread_initalized(framework->globalLockThread) == true)
+ && !isSelf))
+ {
+ bundle_state_e state;
+ bundle_getState(bundle, &state);
+ if ((desiredStates & state) == 0) {
+ status = CELIX_ILLEGAL_STATE;
+ break;
+ }
+
+ bundle_getLockingThread(bundle, &lockingThread);
+ if (isSelf && (celixThread_initalized(lockingThread) == true)
+ && arrayList_contains(framework->globalLockWaitersList, &lockingThread)) {
+ framework->interrupted = true;
+// celixThreadCondition_signal_thread_np(&framework->condition, bundle_getLockingThread(bundle));
+ celixThreadCondition_signal(&framework->condition);
+ }
+
+ celixThreadCondition_wait(&framework->condition, &framework->bundleLock);
+
+ status = bundle_isLockable(bundle, &lockable);
+ if (status != CELIX_SUCCESS) {
+ break;
+ }
+ }
+
+ if (status == CELIX_SUCCESS) {
+ bundle_state_e state;
+ bundle_getState(bundle, &state);
+ if ((desiredStates & state) == 0) {
+ status = CELIX_ILLEGAL_STATE;
+ } else {
+ if (bundle_lock(bundle, &locked)) {
+ if (!locked) {
+ status = CELIX_ILLEGAL_STATE;
+ }
+ }
+ }
+ }
+ celixThreadMutex_unlock(&framework->bundleLock);
+ }
+
+ framework_logIfError(framework->logger, status, NULL, "Failed to get bundle lock");
+
+ return status;
+}
+
+bool framework_releaseBundleLock(framework_pt framework, bundle_pt bundle) {
+ bool unlocked;
+ celix_thread_t lockingThread = celix_thread_default;
+
+ celixThreadMutex_lock(&framework->bundleLock);
+
+ bundle_unlock(bundle, &unlocked);
+ if (!unlocked) {
+ celixThreadMutex_unlock(&framework->bundleLock);
+ return false;
+ }
+ bundle_getLockingThread(bundle, &lockingThread);
+ if (celixThread_initalized(lockingThread) == false) {
+ celixThreadCondition_broadcast(&framework->condition);
+ }
+
+ celixThreadMutex_unlock(&framework->bundleLock);
+
+ return true;
+}
+
+bool framework_acquireGlobalLock(framework_pt framework) {
+ bool interrupted = false;
+ bool isSelf = false;
+
+ celixThreadMutex_lock(&framework->bundleLock);
+
+ thread_equalsSelf(framework->globalLockThread, &isSelf);
+
+ while (!interrupted
+ && (celixThread_initalized(framework->globalLockThread) == true)
+ && (!isSelf)) {
+ celix_thread_t currentThread = celixThread_self();
+ arrayList_add(framework->globalLockWaitersList, ¤tThread);
+ celixThreadCondition_broadcast(&framework->condition);
+
+ celixThreadCondition_wait(&framework->condition, &framework->bundleLock);
+ if (framework->interrupted) {
+ interrupted = true;
+ framework->interrupted = false;
+ }
+
+ arrayList_removeElement(framework->globalLockWaitersList, ¤tThread);
+ }
+
+ if (!interrupted) {
+ framework->globalLockCount++;
+ framework->globalLockThread = celixThread_self();
+ }
+
+ celixThreadMutex_unlock(&framework->bundleLock);
+
+ return !interrupted;
+}
+
+celix_status_t framework_releaseGlobalLock(framework_pt framework) {
+ int status = CELIX_SUCCESS;
+ if (celixThreadMutex_lock(&framework->bundleLock) != 0) {
+ fw_log(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, "Error locking framework bundle lock");
+ return CELIX_FRAMEWORK_EXCEPTION;
+ }
+
+ if (celixThread_equals(framework->globalLockThread, celixThread_self())) {
+ framework->globalLockCount--;
+ if (framework->globalLockCount == 0) {
+ framework->globalLockThread = celix_thread_default;
+ if (celixThreadCondition_broadcast(&framework->condition) != 0) {
+ fw_log(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, "Failed to broadcast global lock release.");
+ status = CELIX_FRAMEWORK_EXCEPTION;
+ // still need to unlock before returning
+ }
+ }
+ } else {
+ printf("The current thread does not own the global lock");
+ }
+
+ if (celixThreadMutex_unlock(&framework->bundleLock) != 0) {
+ fw_log(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, "Error unlocking framework bundle lock");
+ return CELIX_FRAMEWORK_EXCEPTION;
+ }
+
+ framework_logIfError(framework->logger, status, NULL, "Failed to release global lock");
+
+ return status;
+}
+
+celix_status_t framework_waitForStop(framework_pt framework) {
+ if (celixThreadMutex_lock(&framework->mutex) != 0) {
+ fw_log(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, "Error locking the framework, shutdown gate not set.");
+ return CELIX_FRAMEWORK_EXCEPTION;
+ }
+ while (!framework->shutdown) {
+ celix_status_t status = celixThreadCondition_wait(&framework->shutdownGate, &framework->mutex);
+ if (status != 0) {
+ fw_log(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, "Error waiting for shutdown gate.");
+ return CELIX_FRAMEWORK_EXCEPTION;
+ }
+ }
+ if (celixThreadMutex_unlock(&framework->mutex) != 0) {
+ fw_log(framework->logger, OSGI_FRAMEWORK_LOG_ERROR, "Error unlocking the framework.");
+ return CELIX_FRAMEWORK_EXCEPTION;
+ }
+
+ celixThread_join(framework->shutdownThread, NULL);
+
+ fw_log(framework->logger, OSGI_FRAMEWORK_LOG_INFO, "FRAMEWORK: Successful shutdown");
+ return CELIX_SUCCESS;
+}
+
+static void *framework_shutdown(void *framework) {
+ framework_pt fw = (framework_pt) framework;
+ int err;
+
+ fw_log(fw->logger, OSGI_FRAMEWORK_LOG_INFO, "FRAMEWORK: Shutdown");
+ celixThreadMutex_lock(&fw->installedBundleMapLock);
+
+ hash_map_iterator_pt iter = hashMapIterator_create(fw->installedBundleMap);
+ bundle_pt bundle = NULL;
+ while ((bundle = hashMapIterator_nextValue(iter)) != NULL) {
+ bundle_state_e state;
+ bundle_getState(bundle, &state);
+ if (state == OSGI_FRAMEWORK_BUNDLE_ACTIVE || state == OSGI_FRAMEWORK_BUNDLE_STARTING) {
+ celixThreadMutex_unlock(&fw->installedBundleMapLock);
+ fw_stopBundle(fw, bundle, 0);
+ celixThreadMutex_lock(&fw->installedBundleMapLock);
+ hashMapIterator_destroy(iter);
+ iter = hashMapIterator_create(fw->installedBundleMap);
+ }
+ }
+ hashMapIterator_destroy(iter);
+
+ iter = hashMapIterator_create(fw->installedBundleMap);
+ bundle = NULL;
+ while ((bundle = hashMapIterator_nextValue(iter)) != NULL) {
+ bundle_close(bundle);
+ }
+ hashMapIterator_destroy(iter);
+ celixThreadMutex_unlock(&fw->installedBundleMapLock);
+
+ err = celixThreadMutex_lock(&fw->mutex);
+ if (err != 0) {
+ fw_log(fw->logger, OSGI_FRAMEWORK_LOG_ERROR, "Error locking the framework, cannot exit clean.");
+ celixThread_exit(NULL);
+ return NULL;
+ }
+
+ if (celixThreadMutex_lock(&fw->dispatcherLock) != CELIX_SUCCESS) {
+ fw_log(fw->logger, OSGI_FRAMEWORK_LOG_ERROR, "Error locking the dispatcherThread.");
+ }
+ else {
+ fw->shutdown = true;
+
+ if (celixThreadCondition_broadcast(&fw->dispatcher)) {
+ fw_log(fw->logger, OSGI_FRAMEWORK_LOG_ERROR, "Error broadcasting .");
+ }
+
+ if (celixThreadMutex_unlock(&fw->dispatcherLock)) {
+ fw_log(fw->logger, OSGI_FRAMEWORK_LOG_ERROR, "Error unlocking the dispatcherThread.");
+ }
+
+ celixThread_join(fw->dispatcherThread, NULL);
+ }
+
+
+ err = celixThreadCondition_broadcast(&fw->shutdownGate);
+ if (err != 0) {
+ fw_log(fw->logger, OSGI_FRAMEWORK_LOG_ERROR, "Error waking the shutdown gate, cannot exit clean.");
+ err = celixThreadMutex_unlock(&fw->mutex);
+ if (err != 0) {
+ fw_log(fw->logger, OSGI_FRAMEWORK_LOG_ERROR, "Error unlocking the framework, cannot exit clean.");
+ }
+
+ celixThread_exit(NULL);
+ return NULL;
+ }
+ err = celixThreadMutex_unlock(&fw->mutex);
+ if (err != 0) {
+// fw_log(fw->logger, OSGI_FRAMEWORK_LOG_ERROR, "Error unlocking the framework, cannot exit clean.");
+ }
+
+// fw_log(fw->logger, OSGI_FRAMEWORK_LOG_INFO, "FRAMEWORK: Shutdown done\n");
+ celixThread_exit((void *) CELIX_SUCCESS);
+
+ return NULL;
+}
+
+celix_status_t framework_getFrameworkBundle(framework_pt framework, bundle_pt *bundle) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ if (framework != NULL && *bundle == NULL) {
+ *bundle = framework->bundle;
+ } else {
+ status = CELIX_ILLEGAL_ARGUMENT;
+ }
+
+ return status;
+}
+
+celix_status_t fw_fireBundleEvent(framework_pt framework, bundle_event_type_e eventType, bundle_pt bundle) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ if ((eventType != OSGI_FRAMEWORK_BUNDLE_EVENT_STARTING)
+ && (eventType != OSGI_FRAMEWORK_BUNDLE_EVENT_STOPPING)
+ && (eventType != OSGI_FRAMEWORK_BUNDLE_EVENT_LAZY_ACTIVATION)) {
+ request_pt request = (request_pt) calloc(1, sizeof(*request));
+ if (!request) {
+ status = CELIX_ENOMEM;
+ } else {
+ bundle_archive_pt archive = NULL;
+ module_pt module = NULL;
+
+ request->eventType = eventType;
+ request->filter = NULL;
+ request->listeners = framework->bundleListeners;
+ request->type = BUNDLE_EVENT_TYPE;
+ request->error = NULL;
+ request->bundleId = -1;
+
+ status = bundle_getArchive(bundle, &archive);
+
+ if (status == CELIX_SUCCESS) {
+ long bundleId;
+
+ status = bundleArchive_getId(archive, &bundleId);
+
+ if (status == CELIX_SUCCESS) {
+ request->bundleId = bundleId;
+ }
+ }
+
+ if (status == CELIX_SUCCESS) {
+ status = bundle_getCurrentModule(bundle, &module);
+
+ if (status == CELIX_SUCCESS) {
+ const char *symbolicName = NULL;
+ status = module_getSymbolicName(module, &symbolicName);
+ if (status == CELIX_SUCCESS) {
+ request->bundleSymbolicName = strdup(symbolicName);
+ }
+ }
+ }
+
+ if (celixThreadMutex_lock(&framework->dispatcherLock) != CELIX_SUCCESS) {
+ status = CELIX_FRAMEWORK_EXCEPTION;
+ } else {
+ arrayList_add(framework->requests, request);
+
<TRUNCATED>