celix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pnol...@apache.org
Subject [53/60] [abbrv] celix git commit: Merge branch 'develop' into feature/CELIX-426-cxx-api
Date Sun, 27 May 2018 18:53:01 GMT
http://git-wip-us.apache.org/repos/asf/celix/blob/2e04253d/libs/framework/src/framework.c.orig
----------------------------------------------------------------------
diff --cc libs/framework/src/framework.c.orig
index 0000000,0000000..eebb185
new file mode 100644
--- /dev/null
+++ b/libs/framework/src/framework.c.orig
@@@ -1,0 -1,0 +1,2829 @@@
++/**
++ *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 <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"
++#include "bundle_private.h"
++#include "celix_bundle_context.h"
++#include "bundle_context_private.h"
++
++typedef celix_status_t (*create_function_fp)(bundle_context_t *context, void **userData);
++typedef celix_status_t (*start_function_fp)(void *userData, bundle_context_t *context);
++typedef celix_status_t (*stop_function_fp)(void *userData, bundle_context_t *context);
++typedef celix_status_t (*destroy_function_fp)(void *userData, bundle_context_t *context);
++
++struct activator {
++    void * userData;
++    
++    create_function_fp create;
++    start_function_fp start;
++    stop_function_fp stop;
++    destroy_function_fp destroy;
++<<<<<<< HEAD:framework/src/framework.c
++    
++    dm_create_fp dmCreate;
++    dm_init_fp dmInit;
++    dm_destroy_fp dmDestroy;
++=======
++>>>>>>> develop:libs/framework/src/framework.c
++};
++
++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_t *context);
++static celix_status_t frameworkActivator_stop(void * userData, bundle_context_t *context);
++static celix_status_t frameworkActivator_destroy(void * userData, bundle_context_t *context);
++
++static void framework_autoStartConfiguredBundles(bundle_context_t *fwCtx);
++static void framework_autoStartConfiguredBundlesForList(bundle_context_t *fwCtx, const char *autoStart);
++
++struct fw_refreshHelper {
++    framework_pt framework;
++    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) {
++        celix_thread_mutexattr_t attr;
++        celixThreadMutexAttr_create(&attr);
++        celixThreadMutexAttr_settype(&attr, CELIX_THREAD_MUTEX_RECURSIVE);
++        
++        status = CELIX_DO_IF(status, celixThreadCondition_init(&(*framework)->condition, NULL));
++        status = CELIX_DO_IF(status, celixThreadMutex_create(&(*framework)->mutex, NULL));
++        status = CELIX_DO_IF(status, celixThreadMutex_create(&(*framework)->installedBundleMapLock, NULL));
++        status = CELIX_DO_IF(status, celixThreadMutex_create(&(*framework)->bundleLock, NULL));
++        status = CELIX_DO_IF(status, celixThreadMutex_create(&(*framework)->installRequestLock, NULL));
++        status = CELIX_DO_IF(status, celixThreadMutex_create(&(*framework)->dispatcherLock, NULL));
++        status = CELIX_DO_IF(status, celixThreadMutex_create(&(*framework)->serviceListenersLock, &attr));
++        status = CELIX_DO_IF(status, celixThreadMutex_create(&(*framework)->frameworkListenersLock, &attr));
++        status = CELIX_DO_IF(status, celixThreadMutex_create(&(*framework)->bundleListenerLock, NULL));
++        status = CELIX_DO_IF(status, celixThreadCondition_init(&(*framework)->dispatcher, NULL));
++        if (status == CELIX_SUCCESS) {
++            (*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; //system bundle is 0
++            (*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_t *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->serviceListenersLock);
++    celixThreadMutex_destroy(&framework->frameworkListenersLock);
++    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_t *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_t *context = NULL;
++            void * userData = NULL;
++            
++            //create_function_pt create = NULL;
++            start_function_fp start = (start_function_fp) frameworkActivator_start;
++            stop_function_fp stop = (stop_function_fp) frameworkActivator_stop;
++            destroy_function_fp destroy = (destroy_function_fp) 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);
++    }
++    
++    bundle_context_t *fwCtx = framework_getContext(framework);
++    if (fwCtx != NULL) {
++        framework_autoStartConfiguredBundles(fwCtx);
++    }
++    
++    return status;
++}
++
++static void framework_autoStartConfiguredBundles(bundle_context_t *fwCtx) {
++    const char* autoStart = NULL;
++    const char* cosgiKeys[] = {"cosgi.auto.start.0","cosgi.auto.start.1","cosgi.auto.start.2","cosgi.auto.start.3","cosgi.auto.start.4","cosgi.auto.start.5"};
++    const char* celixKeys[] = {CELIX_AUTO_START_0, CELIX_AUTO_START_1, CELIX_AUTO_START_2, CELIX_AUTO_START_3, CELIX_AUTO_START_4, CELIX_AUTO_START_5};
++    size_t len = 6;
++    for (int i = 0; i < len; ++i) {
++        bundleContext_getProperty(fwCtx, celixKeys[i], &autoStart);
++        if (autoStart == NULL) {
++            //trying cosgi.auto.start.<level> variants. TODO make this prop deprecated -> warning
++            bundleContext_getProperty(fwCtx, cosgiKeys[i], &autoStart);
++        }
++        if (autoStart != NULL) {
++            framework_autoStartConfiguredBundlesForList(fwCtx, autoStart);
++        }
++    }
++}
++
++static void framework_autoStartConfiguredBundlesForList(bundle_context_t *fwCtx, const char *autoStartIn)  {
++    char delims[] = " ";
++    char *save_ptr = NULL;
++    array_list_pt installed = NULL;
++    char *autoStart = strndup(autoStartIn, 1024*1024*10);
++    arrayList_create(&installed);
++    
++    if (autoStart != NULL) {
++        char *location = strtok_r(autoStart, delims, &save_ptr);
++        while (location != NULL) {
++            //first install
++            bundle_t *bnd = NULL;
++            celix_status_t  rc = bundleContext_installBundle(fwCtx, location, &bnd);
++            if (rc == CELIX_SUCCESS) {
++                arrayList_add(installed, bnd);
++            } else {
++                printf("Could not install bundle from %s\n", location); //TODO use logger
++            }
++            location = strtok_r(NULL, delims, &save_ptr);
++        }
++    }
++    
++    unsigned int i;
++    for (i = 0; i < arrayList_size(installed); ++i) {
++        long bndId = -1;
++        bundle_t *bnd = arrayList_get(installed, i);
++        bundle_getBundleId(bnd, &bndId);
++        celix_status_t rc = bundle_startWithOptions(bnd, 0);
++        if (rc != CELIX_SUCCESS) {
++            printf("Could not start bundle %li\n", bndId);
++        }
++    }
++    
++    free(autoStart);
++    arrayList_destroy(installed);
++}
++
++
++celix_status_t framework_stop(framework_pt framework) {
++    return fw_stopBundle(framework, framework->bundle, true);
++}
++
++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) {
++        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 __attribute__((unused))) {
++    celix_status_t status = CELIX_SUCCESS;
++    
++    linked_list_pt wires = NULL;
++    bundle_context_t *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_t *context;
++                        create_function_fp create = (create_function_fp) fw_getSymbol((handle_t) bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_CREATE);
++                        start_function_fp start = (start_function_fp) fw_getSymbol((handle_t) bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_START);
++                        stop_function_fp stop = (stop_function_fp) fw_getSymbol((handle_t) bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_STOP);
++                        destroy_function_fp destroy = (destroy_function_fp) fw_getSymbol((handle_t) bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_DESTROY);
++<<<<<<< HEAD:framework/src/framework.c
++                        
++                        dm_create_fp dmCreate = fw_getSymbol((handle_t)bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_DM_ACTIVATOR_CREATE);
++                        dm_init_fp dmInit = fw_getSymbol((handle_t)bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_DM_ACTIVATOR_INIT);
++                        dm_destroy_fp dmDestroy = fw_getSymbol((handle_t)bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_DM_ACTIVATOR_DESTROY);
++                        
++=======
++
++>>>>>>> develop:libs/framework/src/framework.c
++                        activator->create = create;
++                        activator->start = start;
++                        activator->stop = stop;
++                        activator->destroy = destroy;
++<<<<<<< HEAD:framework/src/framework.c
++                        
++                        activator->dmCreate = dmCreate;
++                        activator->dmInit = dmInit;
++                        activator->dmDestroy = dmDestroy;
++                        
++                        if (activator->dmCreate != NULL) {
++                            //only allow one activator, if dm is used -> set other to NULL
++                            activator->create = NULL;
++                            activator->start = NULL;
++                            activator->stop = NULL;
++                            activator->destroy = NULL;
++                        }
++                        
++=======
++
++>>>>>>> develop:libs/framework/src/framework.c
++                        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_t *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) {
++                        dm_dependency_manager_t *mng = celix_bundleContext_getDependencyManager(context);
++                        dependencyManager_removeAllComponents(mng);
++                    }
++                }
++            }
++            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;
++                
++                celixThreadMutex_lock(&framework->serviceListenersLock);
++                for (i = 0; i < arrayList_size(framework->serviceListeners); i++) {
++                    fw_service_listener_pt listener =(fw_service_listener_pt) arrayList_get(framework->serviceListeners, i);
++                    bundle_context_t *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, &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);
++                    }
++                }
++                celixThreadMutex_unlock(&framework->serviceListenersLock);
++                
++                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, &reg));
++            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;
++    unsigned int i;
++    
++    fw_service_listener_pt fwListener = (fw_service_listener_pt) calloc(1, sizeof(*fwListener));
++    bundle_context_t *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;
++    
++    celixThreadMutex_lock(&framework->serviceListenersLock);
++    arrayList_add(framework->serviceListeners, fwListener);
++    celixThreadMutex_unlock(&framework->serviceListenersLock);
++    
++    serviceRegistry_getListenerHooks(framework->registry, framework->bundle, &listenerHooks);
++    
++    struct listener_hook_info info;
++    
++    bundle_getContext(bundle, &context);
++    info.context = context;
++    info.removed = false;
++    info.filter = 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);
++    }
++    
++    arrayList_destroy(listenerHooks);
++}
++
++void fw_removeServiceListener(framework_pt framework, bundle_pt bundle, service_listener_pt listener) {
++    fw_service_listener_pt match = NULL;
++    
++    bundle_context_t *context;
++    bundle_getContext(bundle, &context);
++    
++    int i;
++    celixThreadMutex_lock(&framework->serviceListenersLock);
++    for (i = 0; i < arrayList_size(framework->serviceListeners); i++) {
++        fw_service_listener_pt visit = (fw_service_listener_pt) arrayList_get(framework->serviceListeners, i);
++        if (visit->listener == listener && visit->bundle == bundle) {
++            match = visit;
++            arrayList_remove(framework->serviceListeners, i);
++            break;
++        }
++    }
++    celixThreadMutex_unlock(&framework->serviceListenersLock);
++    
++    
++    if (match != NULL) {
++        //invoke listener hooks
++        
++        bundle_context_pt lContext = NULL;
++        
++        struct listener_hook_info info;
++        bundle_getContext(match->bundle, &lContext);
++        info.context = lContext;
++        filter_getString(match->filter, &info.filter);
++        info.removed = true;
++        
++        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);
++    }
++    
++    if (match != NULL) {
++        //unregistering retained service references. For these refs a unregister event will not be triggered.
++        int rSize = arrayList_size(match->retainedReferences);
++        for (i = 0; i < rSize; i += 1) {
++            service_reference_pt ref = arrayList_get(match->retainedReferences, i);
++            if (ref != NULL) {
++                serviceRegistry_ungetServiceReference(framework->registry, match->bundle, ref); // decrease retain counter
++            }
++        }
++        
++        match->bundle = NULL;
++        filter_destroy(match->filter);
++        arrayList_destroy(match->retainedReferences);
++        match->filter = NULL;
++        match->listener = NULL;
++        free(match);
++    }
++}
++
++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;
++        
++        celixThreadMutex_lock(&framework->frameworkListenersLock);
++        arrayList_add(framework->frameworkListeners, frameworkListener);
++        celixThreadMutex_unlock(&framework->frameworkListenersLock);
++    }
++    
++    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;
++    
++    celixThreadMutex_lock(&framework->frameworkListenersLock);
++    for (i = 0; i < arrayList_size(framework->frameworkListeners); i++) {
++        frameworkListener = (fw_framework_listener_pt) arrayList_get(framework->frameworkListeners, i);
++        if (frameworkListener->listener == listener && frameworkListener->bundle == bundle) {
++            arrayList_remove(framework->frameworkListeners, i);
++            
++            frameworkListener->bundle = NULL;
++            frameworkListener->listener = NULL;
++            free(frameworkListener);
++        }
++    }
++    celixThreadMutex_unlock(&framework->frameworkListenersLock);
++    
++    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;
++    
++    celixThreadMutex_lock(&framework->serviceListenersLock);
++    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);
++                    
++                }
++            }
++        }
++    }
++    celixThreadMutex_unlock(&framework->serviceListenersLock);
++    
++}
++
++//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, &registration);
++//	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-

<TRUNCATED>

Mime
View raw message