celix_status_t celix_framework_startBundleEntry()

in libs/framework/src/framework.c [2179:2299]


celix_status_t celix_framework_startBundleEntry(celix_framework_t* framework, celix_bundle_entry_t* bndEntry) {
    assert(!celix_framework_isCurrentThreadTheEventLoop(framework));
    celix_status_t status = CELIX_SUCCESS;
    const char* error = NULL;
    const char* name = "";
    celix_module_t* module = NULL;
    celix_bundle_context_t* context = NULL;
    celix_bundle_activator_t* activator = NULL;

    celixThreadRwlock_writeLock(&bndEntry->fsmMutex);
    celix_bundle_state_e state = celix_bundle_getState(bndEntry->bnd);

    switch (state) {
        case CELIX_BUNDLE_STATE_UNKNOWN:
            error = "state is unknown";
            status = CELIX_ILLEGAL_STATE;
            break;
        case CELIX_BUNDLE_STATE_UNINSTALLED:
            error = "bundle is uninstalled";
            status = CELIX_ILLEGAL_STATE;
            break;
        case CELIX_BUNDLE_STATE_STARTING:
            error = "bundle is starting";
            status = CELIX_BUNDLE_EXCEPTION;
            break;
        case CELIX_BUNDLE_STATE_STOPPING:
            error = "bundle is stopping";
            status = CELIX_BUNDLE_EXCEPTION;
            break;
        case CELIX_BUNDLE_STATE_ACTIVE:
            break;
        case CELIX_BUNDLE_STATE_INSTALLED:
            bundle_getCurrentModule(bndEntry->bnd, &module);
            module_getSymbolicName(module, &name);
            if (!module_isResolved(module)) {
                status = framework_markBundleResolved(framework, module);
                if (status == CELIX_SUCCESS) {
                    module_setResolved(module);
                } else {
                    break;
                }
            }
            /* no break */
        case CELIX_BUNDLE_STATE_RESOLVED:
            module = NULL;
            name = NULL;
            bundle_getCurrentModule(bndEntry->bnd, &module);
            module_getSymbolicName(module, &name);
            status = CELIX_DO_IF(status, bundleContext_create(framework, framework->logger, bndEntry->bnd, &context));
            CELIX_DO_IF(status, celix_bundle_setContext(bndEntry->bnd, context));

            if (status == CELIX_SUCCESS) {
                activator = calloc(1,(sizeof(*activator)));
                if (activator == NULL) {
                    status = CELIX_ENOMEM;
                } else {
                    void* userData = NULL;
                    void* bundleHandle = bundle_getHandle(bndEntry->bnd);

                    activator->create = celix_libloader_findBundleActivatorCreate(bundleHandle);
                    activator->start = celix_libloader_findBundleActivatorStart(bundleHandle);
                    activator->stop = celix_libloader_findBundleActivatorStop(bundleHandle);
                    activator->destroy = celix_libloader_findBundleActivatorDestroy(bundleHandle);

                    status = CELIX_DO_IF(status, bundle_setActivator(bndEntry->bnd, activator));

                    status = CELIX_DO_IF(status, bundle_setState(bndEntry->bnd, CELIX_BUNDLE_STATE_STARTING));
                    CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_STARTING, bndEntry));

                    if (status == CELIX_SUCCESS) {
                        context = celix_bundle_getContext(bndEntry->bnd);
                        if (activator->create != NULL) {
                            status = CELIX_DO_IF(status, activator->create(context, &userData));
                            if (status == CELIX_SUCCESS) {
                                activator->userData = userData;
                            }
                        }
                    }
                    if (status == CELIX_SUCCESS) {
                        if (activator->start != NULL) {
                            status = CELIX_DO_IF(status, activator->start(userData, context));
                        }
                        celix_framework_printCelixErrForBundleEntry(framework, bndEntry);
                    }

                    status = CELIX_DO_IF(status, bundle_setState(bndEntry->bnd, CELIX_BUNDLE_STATE_ACTIVE));
                    CELIX_DO_IF(status, fw_fireBundleEvent(framework, OSGI_FRAMEWORK_BUNDLE_EVENT_STARTED, bndEntry));

                    if (status != CELIX_SUCCESS) {
                        //state is still STARTING, back to resolved
                        bool createCalled = activator != NULL && activator->userData != NULL;
                        if (createCalled && activator->destroy) {
                            activator->destroy(activator->userData, context);
                        }
                        celix_bundle_setContext(bndEntry->bnd, NULL);
                        bundle_setActivator(bndEntry->bnd, NULL);
                        bundleContext_destroy(context);
                        free(activator);
                        (void)bundle_setState(bndEntry->bnd, CELIX_BUNDLE_STATE_RESOLVED);
                    }
                }
            }

            break;
    }

    if (status != CELIX_SUCCESS) {
        const char *symbolicName = NULL;
        long id = 0;
        bundle_getCurrentModule(bndEntry->bnd, &module);
        module_getSymbolicName(module, &symbolicName);
        bundle_getBundleId(bndEntry->bnd, &id);
        if (error != NULL) {
            fw_logCode(framework->logger, CELIX_LOG_LEVEL_ERROR, status, "Could not start bundle: %s [%ld]; cause: %s", symbolicName, id, error);
        } else {
            fw_logCode(framework->logger, CELIX_LOG_LEVEL_ERROR, status, "Could not start bundle: %s [%ld]", symbolicName, id);
        }
    }
    celixThreadRwlock_unlock(&bndEntry->fsmMutex);
    return status;
}