| /** |
| *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. |
| */ |
| /* |
| * bundle.c |
| * |
| * \date Mar 23, 2010 |
| * \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a> |
| * \copyright Apache License, Version 2.0 |
| */ |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "framework_private.h" |
| #include "bundle_private.h" |
| #include "resolver.h" |
| #include "utils.h" |
| |
| celix_status_t bundle_createModule(bundle_pt bundle, module_pt *module); |
| celix_status_t bundle_closeRevisions(bundle_pt bundle); |
| |
| celix_status_t bundle_create(bundle_pt * bundle) { |
| celix_status_t status; |
| bundle_archive_pt archive = NULL; |
| |
| *bundle = (bundle_pt) malloc(sizeof(**bundle)); |
| if (*bundle == NULL) { |
| return CELIX_ENOMEM; |
| } |
| status = bundleArchive_createSystemBundleArchive(&archive); |
| if (status == CELIX_SUCCESS) { |
| module_pt module; |
| |
| (*bundle)->archive = archive; |
| (*bundle)->activator = NULL; |
| (*bundle)->context = NULL; |
| (*bundle)->framework = NULL; |
| (*bundle)->state = OSGI_FRAMEWORK_BUNDLE_INSTALLED; |
| (*bundle)->modules = NULL; |
| arrayList_create(&(*bundle)->modules); |
| (*bundle)->handle = NULL; |
| (*bundle)->manifest = NULL; |
| |
| module = module_createFrameworkModule((*bundle)); |
| bundle_addModule(*bundle, module); |
| |
| status = celixThreadMutex_create(&(*bundle)->lock, NULL); |
| if (status != CELIX_SUCCESS) { |
| status = CELIX_ILLEGAL_STATE; |
| } else { |
| (*bundle)->lockCount = 0; |
| (*bundle)->lockThread = celix_thread_default; |
| } |
| } |
| framework_logIfError(logger, status, NULL, "Failed to create bundle"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_createFromArchive(bundle_pt * bundle, framework_pt framework, bundle_archive_pt archive) { |
| module_pt module; |
| |
| celix_status_t status; |
| |
| *bundle = (bundle_pt) malloc(sizeof(**bundle)); |
| if (*bundle == NULL) { |
| return CELIX_ENOMEM; |
| } |
| (*bundle)->archive = archive; |
| (*bundle)->activator = NULL; |
| (*bundle)->context = NULL; |
| (*bundle)->handle = NULL; |
| (*bundle)->manifest = NULL; |
| (*bundle)->framework = framework; |
| (*bundle)->state = OSGI_FRAMEWORK_BUNDLE_INSTALLED; |
| (*bundle)->modules = NULL; |
| arrayList_create(&(*bundle)->modules); |
| |
| status = bundle_createModule(*bundle, &module); |
| if (status == CELIX_SUCCESS) { |
| bundle_addModule(*bundle, module); |
| status = celixThreadMutex_create(&(*bundle)->lock, NULL); |
| if (status != CELIX_SUCCESS) { |
| status = CELIX_ILLEGAL_STATE; |
| } else { |
| (*bundle)->lockCount = 0; |
| (*bundle)->lockThread = celix_thread_default; |
| } |
| } else { |
| status = CELIX_FILE_IO_EXCEPTION; |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to create bundle"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_destroy(bundle_pt bundle) { |
| array_list_iterator_pt iter = arrayListIterator_create(bundle->modules); |
| while (arrayListIterator_hasNext(iter)) { |
| module_pt module = arrayListIterator_next(iter); |
| module_destroy(module); |
| } |
| arrayListIterator_destroy(iter); |
| arrayList_destroy(bundle->modules); |
| celixThreadMutex_destroy(&bundle->lock); |
| |
| free(bundle); |
| |
| return CELIX_SUCCESS; |
| } |
| |
| celix_status_t bundle_getArchive(bundle_pt bundle, bundle_archive_pt *archive) { |
| celix_status_t status = CELIX_SUCCESS; |
| |
| if (bundle != NULL && *archive == NULL) { |
| *archive = bundle->archive; |
| } else { |
| status = CELIX_ILLEGAL_ARGUMENT; |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to get bundle archive"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_getCurrentModule(bundle_pt bundle, module_pt *module) { |
| celix_status_t status = CELIX_SUCCESS; |
| |
| if (bundle == NULL || arrayList_size(bundle->modules)==0 ) { |
| status = CELIX_ILLEGAL_ARGUMENT; |
| } else { |
| *module = arrayList_get(bundle->modules, arrayList_size(bundle->modules) - 1); |
| } |
| |
| return status; |
| } |
| |
| array_list_pt bundle_getModules(bundle_pt bundle) { |
| return bundle->modules; |
| } |
| |
| void * bundle_getHandle(bundle_pt bundle) { |
| return bundle->handle; |
| } |
| |
| void bundle_setHandle(bundle_pt bundle, void * handle) { |
| bundle->handle = handle; |
| } |
| |
| activator_pt bundle_getActivator(bundle_pt bundle) { |
| return bundle->activator; |
| } |
| |
| celix_status_t bundle_setActivator(bundle_pt bundle, activator_pt activator) { |
| bundle->activator = activator; |
| return CELIX_SUCCESS; |
| } |
| |
| celix_status_t bundle_getContext(bundle_pt bundle, bundle_context_pt *context) { |
| *context = bundle->context; |
| return CELIX_SUCCESS; |
| } |
| |
| celix_status_t bundle_setContext(bundle_pt bundle, bundle_context_pt context) { |
| bundle->context = context; |
| return CELIX_SUCCESS; |
| } |
| |
| celix_status_t bundle_getEntry(bundle_pt bundle, const char* name, char** entry) { |
| return framework_getBundleEntry(bundle->framework, bundle, name, entry); |
| } |
| |
| celix_status_t bundle_getState(bundle_pt bundle, bundle_state_e *state) { |
| if(bundle==NULL){ |
| *state = OSGI_FRAMEWORK_BUNDLE_UNKNOWN; |
| return CELIX_BUNDLE_EXCEPTION; |
| } |
| *state = bundle->state; |
| return CELIX_SUCCESS; |
| } |
| |
| celix_status_t bundle_setState(bundle_pt bundle, bundle_state_e state) { |
| bundle->state = state; |
| return CELIX_SUCCESS; |
| } |
| |
| celix_status_t bundle_createModule(bundle_pt bundle, module_pt *module) { |
| celix_status_t status = CELIX_SUCCESS; |
| bundle_archive_pt archive = NULL; |
| bundle_revision_pt revision = NULL; |
| manifest_pt headerMap = NULL; |
| |
| status = CELIX_DO_IF(status, bundle_getArchive(bundle, &archive)); |
| status = CELIX_DO_IF(status, bundleArchive_getCurrentRevision(archive, &revision)); |
| status = CELIX_DO_IF(status, bundleRevision_getManifest(revision, &headerMap)); |
| if (status == CELIX_SUCCESS) { |
| long bundleId = 0; |
| status = bundleArchive_getId(bundle->archive, &bundleId); |
| if (status == CELIX_SUCCESS) { |
| int revision = 0; |
| char moduleId[512]; |
| |
| snprintf(moduleId, sizeof(moduleId), "%ld.%d", bundleId, revision); |
| *module = module_create(headerMap, moduleId, bundle); |
| |
| if (*module != NULL) { |
| version_pt bundleVersion = module_getVersion(*module); |
| const char * symName = NULL; |
| status = module_getSymbolicName(*module, &symName); |
| if (status == CELIX_SUCCESS) { |
| array_list_pt bundles = framework_getBundles(bundle->framework); |
| unsigned int i; |
| for (i = 0; i < arrayList_size(bundles); i++) { |
| bundle_pt check = (bundle_pt) arrayList_get(bundles, i); |
| |
| long id; |
| if (bundleArchive_getId(check->archive, &id) == CELIX_SUCCESS) { |
| if (id != bundleId) { |
| module_pt mod = NULL; |
| const char * sym = NULL; |
| version_pt version; |
| int cmp; |
| status = bundle_getCurrentModule(check, &mod); |
| status = module_getSymbolicName(mod, &sym); |
| |
| version = module_getVersion(mod); |
| version_compareTo(bundleVersion, version, &cmp); |
| if ((symName != NULL) && (sym != NULL) && !strcmp(symName, sym) && |
| !cmp) { |
| char *versionString = NULL; |
| version_toString(version, &versionString); |
| printf("Bundle symbolic name and version are not unique: %s:%s\n", sym, versionString); |
| free(versionString); |
| status = CELIX_BUNDLE_EXCEPTION; |
| break; |
| } |
| } |
| } |
| } |
| arrayList_destroy(bundles); |
| } |
| } |
| } |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to create module"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_start(bundle_pt bundle) { |
| return bundle_startWithOptions(bundle, 0); |
| } |
| |
| celix_status_t bundle_startWithOptions(bundle_pt bundle, int options) { |
| celix_status_t status = CELIX_SUCCESS; |
| if (bundle != NULL) { |
| bool systemBundle = false; |
| status = bundle_isSystemBundle(bundle, &systemBundle); |
| if (status == CELIX_SUCCESS) { |
| if (systemBundle) { |
| framework_start(bundle->framework); |
| } else { |
| status = fw_startBundle(bundle->framework, bundle, options); |
| } |
| } |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to start bundle"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_update(bundle_pt bundle, const char *inputFile) { |
| celix_status_t status = CELIX_SUCCESS; |
| if (bundle != NULL) { |
| bool systemBundle = false; |
| status = bundle_isSystemBundle(bundle, &systemBundle); |
| if (status == CELIX_SUCCESS) { |
| if (systemBundle) { |
| // #TODO: Support framework update |
| status = CELIX_BUNDLE_EXCEPTION; |
| } else { |
| status = framework_updateBundle(bundle->framework, bundle, inputFile); |
| } |
| } |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to update bundle"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_stop(bundle_pt bundle) { |
| return bundle_stopWithOptions(bundle, 0); |
| } |
| |
| celix_status_t bundle_stopWithOptions(bundle_pt bundle, int options) { |
| celix_status_t status = CELIX_SUCCESS; |
| if (bundle != NULL) { |
| bool systemBundle = false; |
| status = bundle_isSystemBundle(bundle, &systemBundle); |
| if (status == CELIX_SUCCESS) { |
| if (systemBundle) { |
| framework_stop(bundle->framework); |
| } else { |
| status = fw_stopBundle(bundle->framework, bundle, options); |
| } |
| } |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to stop bundle"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_uninstall(bundle_pt bundle) { |
| celix_status_t status = CELIX_SUCCESS; |
| if (bundle != NULL) { |
| bool systemBundle = false; |
| status = bundle_isSystemBundle(bundle, &systemBundle); |
| if (status == CELIX_SUCCESS) { |
| if (systemBundle) { |
| status = CELIX_BUNDLE_EXCEPTION; |
| } else { |
| status = fw_uninstallBundle(bundle->framework, bundle); |
| } |
| } |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to uninstall bundle"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_setPersistentStateInactive(bundle_pt bundle) { |
| celix_status_t status; |
| bool systemBundle; |
| |
| status = bundle_isSystemBundle(bundle, &systemBundle); |
| if (status == CELIX_SUCCESS) { |
| if (!systemBundle) { |
| status = bundleArchive_setPersistentState(bundle->archive, OSGI_FRAMEWORK_BUNDLE_INSTALLED); |
| } |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to set persistent state to inactive"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_setPersistentStateUninstalled(bundle_pt bundle) { |
| celix_status_t status; |
| bool systemBundle; |
| |
| status = bundle_isSystemBundle(bundle, &systemBundle); |
| if (status == CELIX_SUCCESS) { |
| if (!systemBundle) { |
| status = bundleArchive_setPersistentState(bundle->archive, OSGI_FRAMEWORK_BUNDLE_UNINSTALLED); |
| } |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to set persistent state to uninstalled"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_revise(bundle_pt bundle, const char * location, const char *inputFile) { |
| celix_status_t status; |
| |
| bundle_archive_pt archive = NULL; |
| status = bundle_getArchive(bundle, &archive); |
| if (status == CELIX_SUCCESS) { |
| status = bundleArchive_revise(archive, location, inputFile); |
| if (status == CELIX_SUCCESS) { |
| module_pt module; |
| status = bundle_createModule(bundle, &module); |
| if (status == CELIX_SUCCESS) { |
| status = bundle_addModule(bundle, module); |
| } else { |
| bool rolledback; |
| status = bundleArchive_rollbackRevise(archive, &rolledback); |
| if (status == CELIX_SUCCESS) { |
| status = CELIX_BUNDLE_EXCEPTION; |
| } |
| } |
| } |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to revise bundle"); |
| |
| return status; |
| } |
| |
| //bool bundle_rollbackRevise(bundle_pt bundle) { |
| // module_pt module = arrayList_remove(bundle->modules, arrayList_set(bundle->modules) - 1); |
| // return resolver_removeModule(module); |
| //} |
| |
| celix_status_t bundle_addModule(bundle_pt bundle, module_pt module) { |
| arrayList_add(bundle->modules, module); |
| resolver_addModule(module); |
| return CELIX_SUCCESS; |
| } |
| |
| celix_status_t bundle_isSystemBundle(bundle_pt bundle, bool *systemBundle) { |
| celix_status_t status; |
| long bundleId; |
| bundle_archive_pt archive = NULL; |
| |
| status = bundle_getArchive(bundle, &archive); |
| if (status == CELIX_SUCCESS) { |
| status = bundleArchive_getId(archive, &bundleId); |
| if (status == CELIX_SUCCESS) { |
| *systemBundle = (bundleId == 0); |
| } |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to check if bundle is the systembundle"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_isLockable(bundle_pt bundle, bool *lockable) { |
| celix_status_t status; |
| |
| status = celixThreadMutex_lock(&bundle->lock); |
| if (status != CELIX_SUCCESS) { |
| status = CELIX_BUNDLE_EXCEPTION; |
| } else { |
| bool equals; |
| status = thread_equalsSelf(bundle->lockThread, &equals); |
| if (status == CELIX_SUCCESS) { |
| *lockable = (bundle->lockCount == 0) || (equals); |
| } |
| |
| status = celixThreadMutex_unlock(&bundle->lock); |
| if (status != CELIX_SUCCESS) { |
| status = CELIX_BUNDLE_EXCEPTION; |
| } |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to check if bundle is lockable"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_getLockingThread(bundle_pt bundle, celix_thread_t *thread) { |
| celix_status_t status; |
| |
| status = celixThreadMutex_lock(&bundle->lock); |
| if (status != CELIX_SUCCESS) { |
| status = CELIX_BUNDLE_EXCEPTION; |
| } else { |
| *thread = bundle->lockThread; |
| |
| status = celixThreadMutex_unlock(&bundle->lock); |
| if (status != CELIX_SUCCESS) { |
| status = CELIX_BUNDLE_EXCEPTION; |
| } |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to get locking thread"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_lock(bundle_pt bundle, bool *locked) { |
| celix_status_t status; |
| bool equals; |
| |
| celixThreadMutex_lock(&bundle->lock); |
| |
| status = thread_equalsSelf(bundle->lockThread, &equals); |
| if (status == CELIX_SUCCESS) { |
| if ((bundle->lockCount > 0) && !equals) { |
| *locked = false; |
| } else { |
| bundle->lockCount++; |
| bundle->lockThread = celixThread_self(); |
| *locked = true; |
| } |
| } |
| |
| celixThreadMutex_unlock(&bundle->lock); |
| |
| framework_logIfError(logger, status, NULL, "Failed to lock bundle"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_unlock(bundle_pt bundle, bool *unlocked) { |
| celix_status_t status = CELIX_SUCCESS; |
| |
| bool equals; |
| |
| celixThreadMutex_lock(&bundle->lock); |
| |
| if (bundle->lockCount == 0) { |
| *unlocked = false; |
| } else { |
| status = thread_equalsSelf(bundle->lockThread, &equals); |
| if (status == CELIX_SUCCESS) { |
| if ((bundle->lockCount > 0) && !equals) { |
| *unlocked = false; |
| } |
| else{ |
| bundle->lockCount--; |
| if (bundle->lockCount == 0) { |
| bundle->lockThread = celix_thread_default; |
| } |
| *unlocked = true; |
| } |
| } |
| } |
| |
| celixThreadMutex_unlock(&bundle->lock); |
| |
| framework_logIfError(logger, status, NULL, "Failed to unlock bundle"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_close(bundle_pt bundle) { |
| bundle_archive_pt archive = NULL; |
| |
| celix_status_t status; |
| |
| bundle_closeModules(bundle); |
| bundle_closeRevisions(bundle); |
| status = bundle_getArchive(bundle, &archive); |
| if (status == CELIX_SUCCESS) { |
| bundleArchive_close(archive); |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to close bundle"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_closeAndDelete(bundle_pt bundle) { |
| celix_status_t status; |
| |
| bundle_archive_pt archive = NULL; |
| |
| bundle_closeModules(bundle); |
| bundle_closeRevisions(bundle); |
| status = bundle_getArchive(bundle, &archive); |
| if (status == CELIX_SUCCESS) { |
| bundleArchive_closeAndDelete(archive); |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to close and delete bundle"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_closeRevisions(bundle_pt bundle) { |
| celix_status_t status = CELIX_SUCCESS; |
| |
| // TODO implement this |
| return status; |
| } |
| |
| celix_status_t bundle_closeModules(bundle_pt bundle) { |
| celix_status_t status = CELIX_SUCCESS; |
| |
| unsigned int i = 0; |
| for (i = 0; i < arrayList_size(bundle->modules); i++) { |
| module_pt module = (module_pt) arrayList_get(bundle->modules, i); |
| resolver_removeModule(module); |
| module_setWires(module, NULL); |
| } |
| |
| return status; |
| } |
| |
| celix_status_t bundle_refresh(bundle_pt bundle) { |
| celix_status_t status; |
| module_pt module; |
| |
| status = bundle_closeModules(bundle); |
| if (status == CELIX_SUCCESS) { |
| arrayList_clear(bundle->modules); |
| status = bundle_createModule(bundle, &module); |
| if (status == CELIX_SUCCESS) { |
| status = bundle_addModule(bundle, module); |
| if (status == CELIX_SUCCESS) { |
| bundle->state = OSGI_FRAMEWORK_BUNDLE_INSTALLED; |
| } |
| } |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to refresh bundle"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_getBundleId(bundle_pt bundle, long *id) { |
| celix_status_t status; |
| bundle_archive_pt archive = NULL; |
| status = bundle_getArchive(bundle, &archive); |
| if (status == CELIX_SUCCESS) { |
| status = bundleArchive_getId(archive, id); |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to get bundle id"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_getRegisteredServices(bundle_pt bundle, array_list_pt *list) { |
| celix_status_t status; |
| |
| status = fw_getBundleRegisteredServices(bundle->framework, bundle, list); |
| |
| framework_logIfError(bundle->framework->logger, status, NULL, "Failed to get registered services"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_getServicesInUse(bundle_pt bundle, array_list_pt *list) { |
| celix_status_t status; |
| |
| status = fw_getBundleServicesInUse(bundle->framework, bundle, list); |
| |
| framework_logIfError(logger, status, NULL, "Failed to get in use services"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_setFramework(bundle_pt bundle, framework_pt framework) { |
| celix_status_t status = CELIX_SUCCESS; |
| |
| if (bundle != NULL && framework != NULL) { |
| bundle->framework = framework; |
| } else { |
| status = CELIX_ILLEGAL_ARGUMENT; |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to set framework"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_getFramework(bundle_pt bundle, framework_pt *framework) { |
| celix_status_t status = CELIX_SUCCESS; |
| |
| if (bundle != NULL && *framework == NULL) { |
| *framework = bundle->framework; |
| } else { |
| status = CELIX_ILLEGAL_ARGUMENT; |
| } |
| |
| framework_logIfError(logger, status, NULL, "Failed to get framework"); |
| |
| return status; |
| } |
| |
| celix_status_t bundle_getBundleLocation(bundle_pt bundle, const char **location){ |
| |
| celix_status_t status; |
| |
| bundle_archive_pt archive = NULL; |
| |
| status = bundle_getArchive(bundle, &archive); |
| if (status != CELIX_SUCCESS){ |
| printf("[ ERROR ]: Bundle - getBundleLocation (BundleArchive) \n"); |
| return status; |
| } |
| |
| status = bundleArchive_getLocation(archive, location); |
| if (status != CELIX_SUCCESS){ |
| printf("[ ERROR ]: Bundle - getBundleLocation (BundleArchiveLocation) \n"); |
| return status; |
| } |
| |
| return CELIX_SUCCESS; |
| } |