http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/attribute.c ---------------------------------------------------------------------- diff --git a/framework/src/attribute.c b/framework/src/attribute.c new file mode 100644 index 0000000..318d8f5 --- /dev/null +++ b/framework/src/attribute.c @@ -0,0 +1,71 @@ +/** + *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. + */ +/* + * attribute.c + * + * \date Jul 27, 2010 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ +#include <stdlib.h> +#include <stdio.h> + +#include "attribute_private.h" +#include "celix_log.h" + +celix_status_t attribute_create(char * key, char * value, attribute_pt *attribute) { + celix_status_t status = CELIX_SUCCESS; + char *error = NULL; + + if (key == NULL || value == NULL || *attribute != NULL) { + status = CELIX_ILLEGAL_ARGUMENT; + error = "Missing required arguments and/or values"; + } else { + attribute_pt attr = malloc(sizeof(*attr)); + if (!attr) { + status = CELIX_ENOMEM; + } else { + attr->key = key; + attr->value = value; + + *attribute = attr; + } + } + + framework_logIfError(logger, status, error, "Could not create attribute: [key=%s;value=%s]", key, value); + + return status; +} + +celix_status_t attribute_destroy(attribute_pt attribute) { + free(attribute->key); + free(attribute->value); + free(attribute); + return CELIX_SUCCESS; +} + +celix_status_t attribute_getKey(attribute_pt attribute, char **key) { + *key = attribute->key; + return CELIX_SUCCESS; +} + +celix_status_t attribute_getValue(attribute_pt attribute, char **value) { + *value = attribute->value; + return CELIX_SUCCESS; +}
http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/attribute.h ---------------------------------------------------------------------- diff --git a/framework/src/attribute.h b/framework/src/attribute.h new file mode 100644 index 0000000..6f41f0c --- /dev/null +++ b/framework/src/attribute.h @@ -0,0 +1,39 @@ +/** + *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. + */ +/* + * attribute.h + * + * \date Jul 27, 2010 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ +#ifndef ATTRIBUTE_H_ +#define ATTRIBUTE_H_ + +#include "celix_errno.h" + +typedef struct attribute *attribute_pt; + +celix_status_t attribute_create(char * key, char * value, attribute_pt *attribute); +celix_status_t attribute_destroy(attribute_pt attribute); + +celix_status_t attribute_getKey(attribute_pt attribute, char **key); +celix_status_t attribute_getValue(attribute_pt attribute, char **value); + +#endif /* ATTRIBUTE_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/attribute_private.h ---------------------------------------------------------------------- diff --git a/framework/src/attribute_private.h b/framework/src/attribute_private.h new file mode 100644 index 0000000..339833f --- /dev/null +++ b/framework/src/attribute_private.h @@ -0,0 +1,39 @@ +/** + *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. + */ +/* + * attribute_private.h + * + * \date Feb 11, 2013 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + + +#ifndef ATTRIBUTE_PRIVATE_H_ +#define ATTRIBUTE_PRIVATE_H_ + +#include "attribute.h" + +struct attribute { + char * key; + char * value; +}; + + +#endif /* ATTRIBUTE_PRIVATE_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/bundle.c ---------------------------------------------------------------------- diff --git a/framework/src/bundle.c b/framework/src/bundle.c new file mode 100644 index 0000000..a0e6b3d --- /dev/null +++ b/framework/src/bundle.c @@ -0,0 +1,695 @@ +/** + *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:[email protected]">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; +} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/bundle_archive.c ---------------------------------------------------------------------- diff --git a/framework/src/bundle_archive.c b/framework/src/bundle_archive.c new file mode 100644 index 0000000..cde727e --- /dev/null +++ b/framework/src/bundle_archive.c @@ -0,0 +1,792 @@ +/** + *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_archive.c + * + * \date Aug 8, 2010 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <stdio.h> +#include <time.h> +#include <sys/stat.h> +#include <dirent.h> +#include <unistd.h> + +#include "bundle_archive.h" +#include "linked_list_iterator.h" + +struct bundleArchive { + long id; + char * location; + DIR *archiveRootDir; + char * archiveRoot; + linked_list_pt revisions; + long refreshCount; + time_t lastModified; + + bundle_state_e persistentState; +}; + +static celix_status_t bundleArchive_getRevisionLocation(bundle_archive_pt archive, long revNr, char **revision_location); +static celix_status_t bundleArchive_setRevisionLocation(bundle_archive_pt archive, const char * location, long revNr); + +static celix_status_t bundleArchive_initialize(bundle_archive_pt archive); + +static celix_status_t bundleArchive_deleteTree(bundle_archive_pt archive, const char * directory); + +static celix_status_t bundleArchive_createRevisionFromLocation(bundle_archive_pt archive, const char *location, const char *inputFile, long revNr, bundle_revision_pt *bundle_revision); +static celix_status_t bundleArchive_reviseInternal(bundle_archive_pt archive, bool isReload, long revNr, const char * location, const char *inputFile); + +static celix_status_t bundleArchive_readLastModified(bundle_archive_pt archive, time_t *time); +static celix_status_t bundleArchive_writeLastModified(bundle_archive_pt archive); + +celix_status_t bundleArchive_createSystemBundleArchive(bundle_archive_pt *bundle_archive) { + celix_status_t status = CELIX_SUCCESS; + char *error = NULL; + bundle_archive_pt archive = NULL; + + if (*bundle_archive != NULL) { + status = CELIX_ILLEGAL_ARGUMENT; + error = "Missing required arguments and/or incorrect values"; + } else { + archive = (bundle_archive_pt) calloc(1,sizeof(*archive)); + if (archive == NULL) { + status = CELIX_ENOMEM; + } else { + status = linkedList_create(&archive->revisions); + if (status == CELIX_SUCCESS) { + archive->id = 0l; + archive->location = strdup("System Bundle"); + archive->archiveRoot = NULL; + archive->archiveRootDir = NULL; + archive->refreshCount = -1; + archive->persistentState = OSGI_FRAMEWORK_BUNDLE_UNKNOWN; + time(&archive->lastModified); + + *bundle_archive = archive; + } + } + } + + if(status != CELIX_SUCCESS && archive != NULL){ + bundleArchive_destroy(archive); + } + + framework_logIfError(logger, status, error, "Could not create archive"); + + return status; +} + +celix_status_t bundleArchive_create(const char *archiveRoot, long id, const char * location, const char *inputFile, bundle_archive_pt *bundle_archive) { + celix_status_t status = CELIX_SUCCESS; + char *error = NULL; + bundle_archive_pt archive = NULL; + + if (*bundle_archive != NULL) { + status = CELIX_ILLEGAL_ARGUMENT; + error = "bundle_archive_pt must be NULL"; + } else { + archive = (bundle_archive_pt) calloc(1,sizeof(*archive)); + if (archive == NULL) { + status = CELIX_ENOMEM; + } else { + status = linkedList_create(&archive->revisions); + if (status == CELIX_SUCCESS) { + archive->id = id; + archive->location = strdup(location); + archive->archiveRootDir = NULL; + archive->archiveRoot = strdup(archiveRoot); + archive->refreshCount = -1; + time(&archive->lastModified); + + status = bundleArchive_initialize(archive); + if (status == CELIX_SUCCESS) { + status = bundleArchive_revise(archive, location, inputFile); + + if (status == CELIX_SUCCESS) { + *bundle_archive = archive; + } + else{ + bundleArchive_closeAndDelete(archive); + } + } + } + } + } + + if(status != CELIX_SUCCESS && archive != NULL){ + bundleArchive_destroy(archive); + } + + framework_logIfError(logger, status, error, "Could not create archive"); + + return status; +} + +celix_status_t bundleArchive_destroy(bundle_archive_pt archive) { + celix_status_t status = CELIX_SUCCESS; + + if(archive != NULL){ + if (archive->revisions != NULL) { + linked_list_iterator_pt iter = linkedListIterator_create(archive->revisions, 0); + while(linkedListIterator_hasNext(iter)) { + bundle_revision_pt rev = linkedListIterator_next(iter); + bundleRevision_destroy(rev); + } + linkedListIterator_destroy(iter); + linkedList_destroy(archive->revisions); + } + if (archive->archiveRoot != NULL) { + free(archive->archiveRoot); + } + if (archive->location != NULL) { + free(archive->location); + } + + free(archive); + archive = NULL; + } + + framework_logIfError(logger, status, NULL, "Could not create archive"); + + return status; +} + +celix_status_t bundleArchive_recreate(const char * archiveRoot, bundle_archive_pt *bundle_archive) { + celix_status_t status = CELIX_SUCCESS; + + bundle_archive_pt archive = NULL; + + archive = (bundle_archive_pt) calloc(1,sizeof(*archive)); + if (archive == NULL) { + status = CELIX_ENOMEM; + } else { + status = linkedList_create(&archive->revisions); + if (status == CELIX_SUCCESS) { + archive->archiveRoot = strdup(archiveRoot); + archive->archiveRootDir = NULL; + archive->id = -1; + archive->persistentState = -1; + archive->location = NULL; + archive->refreshCount = -1; + archive->lastModified = (time_t) NULL; + + archive->archiveRootDir = opendir(archiveRoot); + if (archive->archiveRootDir == NULL) { + status = CELIX_FRAMEWORK_EXCEPTION; + } else { + + long idx = 0; + long highestId = -1; + char *location = NULL; + + struct dirent *dent = NULL; + struct stat st; + + errno = 0; + dent = readdir(archive->archiveRootDir); + while (errno == 0 && dent != NULL) { + char subdir[512]; + snprintf(subdir, 512, "%s/%s", archiveRoot, dent->d_name); + int rv = stat(subdir, &st); + if (rv == 0 && S_ISDIR(st.st_mode) && (strncmp(dent->d_name, "version", 7) == 0)) { + sscanf(dent->d_name, "version%*d.%ld", &idx); + if (idx > highestId) { + highestId = idx; + } + } + errno = 0; + dent = readdir(archive->archiveRootDir); + } + + status = CELIX_DO_IF(status, bundleArchive_getRevisionLocation(archive, 0, &location)); + status = CELIX_DO_IF(status, bundleArchive_reviseInternal(archive, true, highestId, location, NULL)); + if (location) { + free(location); + } + if (status == CELIX_SUCCESS) { + *bundle_archive = archive; + } + closedir(archive->archiveRootDir); + } + } + } + + if(status != CELIX_SUCCESS && archive != NULL){ + bundleArchive_destroy(archive); + } + + framework_logIfError(logger, status, NULL, "Could not create archive"); + + return status; +} + +celix_status_t bundleArchive_getId(bundle_archive_pt archive, long *id) { + celix_status_t status = CELIX_SUCCESS; + + if (archive->id < 0) { + FILE *bundleIdFile; + char id[256]; + char bundleId[512]; + snprintf(bundleId, sizeof(bundleId), "%s/bundle.id", archive->archiveRoot); + + bundleIdFile = fopen(bundleId, "r"); + if(bundleIdFile!=NULL){ + fgets(id, sizeof(id), bundleIdFile); + fclose(bundleIdFile); + sscanf(id, "%ld", &archive->id); + } + else{ + status = CELIX_FILE_IO_EXCEPTION; + } + } + + if (status == CELIX_SUCCESS) { + *id = archive->id; + } + + framework_logIfError(logger, status, NULL, "Could not get archive id"); + + return status; +} + +celix_status_t bundleArchive_getLocation(bundle_archive_pt archive, const char **location) { + celix_status_t status = CELIX_SUCCESS; + if (archive->location == NULL) { + FILE *bundleLocationFile; + char bundleLocation[512]; + char loc[256]; + + snprintf(bundleLocation, sizeof(bundleLocation), "%s/bundle.location", archive->archiveRoot); + + bundleLocationFile = fopen(bundleLocation, "r"); + if(bundleLocationFile!=NULL){ + fgets(loc, sizeof(loc), bundleLocationFile); + fclose(bundleLocationFile); + archive->location = strdup(loc); + } + else{ + status = CELIX_FILE_IO_EXCEPTION; + } + } + + if (status == CELIX_SUCCESS) { + *location = archive->location; + } + + framework_logIfError(logger, status, NULL, "Could not get archive location"); + + return status; +} + +celix_status_t bundleArchive_getArchiveRoot(bundle_archive_pt archive, const char **archiveRoot) { + *archiveRoot = archive->archiveRoot; + return CELIX_SUCCESS; +} + +celix_status_t bundleArchive_getCurrentRevisionNumber(bundle_archive_pt archive, long *revisionNumber) { + celix_status_t status = CELIX_SUCCESS; + bundle_revision_pt revision; + *revisionNumber = -1; + + status = CELIX_DO_IF(status, bundleArchive_getCurrentRevision(archive, &revision)); + status = CELIX_DO_IF(status, bundleRevision_getNumber(revision, revisionNumber)); + + framework_logIfError(logger, status, NULL, "Could not get current revision number"); + + return status; +} + +celix_status_t bundleArchive_getCurrentRevision(bundle_archive_pt archive, bundle_revision_pt *revision) { + *revision = linkedList_isEmpty(archive->revisions) ? NULL : linkedList_getLast(archive->revisions); + return CELIX_SUCCESS; +} + +celix_status_t bundleArchive_getRevision(bundle_archive_pt archive, long revNr, bundle_revision_pt *revision) { + *revision = linkedList_get(archive->revisions, revNr); + return CELIX_SUCCESS; +} + +celix_status_t bundleArchive_getPersistentState(bundle_archive_pt archive, bundle_state_e *state) { + celix_status_t status = CELIX_SUCCESS; + + if (archive->persistentState != OSGI_FRAMEWORK_BUNDLE_UNKNOWN) { + *state = archive->persistentState; + } else { + FILE *persistentStateLocationFile; + char persistentStateLocation[512]; + char stateString[256]; + snprintf(persistentStateLocation, sizeof(persistentStateLocation), "%s/bundle.state", archive->archiveRoot); + + persistentStateLocationFile = fopen(persistentStateLocation, "r"); + if (persistentStateLocationFile == NULL) { + status = CELIX_FILE_IO_EXCEPTION; + } else { + if (fgets(stateString, sizeof(stateString), persistentStateLocationFile) == NULL) { + status = CELIX_FILE_IO_EXCEPTION; + } + fclose(persistentStateLocationFile); + } + + if (status == CELIX_SUCCESS) { + if (strncmp(stateString, "active", 256) == 0) { + archive->persistentState = OSGI_FRAMEWORK_BUNDLE_ACTIVE; + } else if (strncmp(stateString, "starting", 256) == 0) { + archive->persistentState = OSGI_FRAMEWORK_BUNDLE_STARTING; + } else if (strncmp(stateString, "uninstalled", 256) == 0) { + archive->persistentState = OSGI_FRAMEWORK_BUNDLE_UNINSTALLED; + } else { + archive->persistentState = OSGI_FRAMEWORK_BUNDLE_INSTALLED; + } + + *state = archive->persistentState; + } + } + + framework_logIfError(logger, status, NULL, "Could not get persistent state"); + + return status; +} + +celix_status_t bundleArchive_setPersistentState(bundle_archive_pt archive, bundle_state_e state) { + celix_status_t status = CELIX_SUCCESS; + char persistentStateLocation[512]; + FILE *persistentStateLocationFile; + + snprintf(persistentStateLocation, sizeof(persistentStateLocation), "%s/bundle.state", archive->archiveRoot); + + persistentStateLocationFile = fopen(persistentStateLocation, "w"); + if (persistentStateLocationFile == NULL) { + status = CELIX_FILE_IO_EXCEPTION; + } else { + char * s; + switch (state) { + case OSGI_FRAMEWORK_BUNDLE_ACTIVE: + s = "active"; + break; + case OSGI_FRAMEWORK_BUNDLE_STARTING: + s = "starting"; + break; + case OSGI_FRAMEWORK_BUNDLE_UNINSTALLED: + s = "uninstalled"; + break; + default: + s = "installed"; + break; + } + fprintf(persistentStateLocationFile, "%s", s); + if (fclose(persistentStateLocationFile) == 0) { + archive->persistentState = state; + } + } + + framework_logIfError(logger, status, NULL, "Could not set persistent state"); + + return status; +} + +celix_status_t bundleArchive_getRefreshCount(bundle_archive_pt archive, long *refreshCount) { + celix_status_t status = CELIX_SUCCESS; + + if (archive->refreshCount == -1) { + FILE *refreshCounterFile; + char refreshCounter[512]; + snprintf(refreshCounter, sizeof(refreshCounter), "%s/refresh.counter", archive->archiveRoot); + + refreshCounterFile = fopen(refreshCounter, "r"); + if (refreshCounterFile == NULL) { + archive->refreshCount = 0; + } else { + char counterStr[256]; + if (fgets(counterStr, sizeof(counterStr), refreshCounterFile) == NULL) { + status = CELIX_FILE_IO_EXCEPTION; + } + fclose(refreshCounterFile); + if (status == CELIX_SUCCESS) { + sscanf(counterStr, "%ld", &archive->refreshCount); + } + } + } + + if (status == CELIX_SUCCESS) { + *refreshCount = archive->refreshCount; + } + + framework_logIfError(logger, status, NULL, "Could not get refresh count"); + + return status; +} + +celix_status_t bundleArchive_setRefreshCount(bundle_archive_pt archive) { + FILE *refreshCounterFile; + celix_status_t status = CELIX_SUCCESS; + char refreshCounter[512]; + + snprintf(refreshCounter, sizeof(refreshCounter), "%s/refresh.counter", archive->archiveRoot); + + refreshCounterFile = fopen(refreshCounter, "w"); + if (refreshCounterFile == NULL) { + status = CELIX_FILE_IO_EXCEPTION; + } else { + fprintf(refreshCounterFile, "%ld", archive->refreshCount); + if (fclose(refreshCounterFile) == 0) { + } + } + + framework_logIfError(logger, status, NULL, "Could not set refresh count"); + + return status; +} + +celix_status_t bundleArchive_getLastModified(bundle_archive_pt archive, time_t *lastModified) { + celix_status_t status = CELIX_SUCCESS; + + if (archive->lastModified == (time_t) NULL) { + status = CELIX_DO_IF(status, bundleArchive_readLastModified(archive, &archive->lastModified)); + } + + if (status == CELIX_SUCCESS) { + *lastModified = archive->lastModified; + } + + framework_logIfError(logger, status, NULL, "Could not get last modified"); + + return status; +} + +celix_status_t bundleArchive_setLastModified(bundle_archive_pt archive, time_t lastModifiedTime) { + celix_status_t status = CELIX_SUCCESS; + + archive->lastModified = lastModifiedTime; + status = CELIX_DO_IF(status, bundleArchive_writeLastModified(archive)); + + framework_logIfError(logger, status, NULL, "Could not set last modified"); + + return status; +} + +static celix_status_t bundleArchive_readLastModified(bundle_archive_pt archive, time_t *time) { + FILE *lastModifiedFile; + char lastModified[512]; + + celix_status_t status = CELIX_SUCCESS; + + snprintf(lastModified, sizeof(lastModified), "%s/bundle.lastmodified", archive->archiveRoot); + + lastModifiedFile = fopen(lastModified, "r"); + if (lastModifiedFile == NULL) { + status = CELIX_FILE_IO_EXCEPTION; + } else { + char timeStr[20]; + int year, month, day, hours, minutes, seconds; + struct tm tm_time; + memset(&tm_time,0,sizeof(struct tm)); + + if (fgets(timeStr, sizeof(timeStr), lastModifiedFile) == NULL) { + status = CELIX_FILE_IO_EXCEPTION; + } + fclose(lastModifiedFile); + if (status == CELIX_SUCCESS) { + sscanf(timeStr, "%d %d %d %d:%d:%d", &year, &month, &day, &hours, &minutes, &seconds); + tm_time.tm_year = year - 1900; + tm_time.tm_mon = month - 1; + tm_time.tm_mday = day; + tm_time.tm_hour = hours; + tm_time.tm_min = minutes; + tm_time.tm_sec = seconds; + + *time = mktime(&tm_time); + } + } + + framework_logIfError(logger, status, NULL, "Could not read last modified"); + + return status; +} + +static celix_status_t bundleArchive_writeLastModified(bundle_archive_pt archive) { + celix_status_t status = CELIX_SUCCESS; + FILE *lastModifiedFile; + char lastModified[512]; + + snprintf(lastModified, sizeof(lastModified), "%s/bundle.lastmodified", archive->archiveRoot); + lastModifiedFile = fopen(lastModified, "w"); + if (lastModifiedFile == NULL) { + status = CELIX_FILE_IO_EXCEPTION; + } else { + char timeStr[20]; + strftime(timeStr, 20, "%Y %m %d %H:%M:%S", localtime(&archive->lastModified)); + fprintf(lastModifiedFile, "%s", timeStr); + fclose(lastModifiedFile); + } + + framework_logIfError(logger, status, NULL, "Could not write last modified"); + + return status; +} + +celix_status_t bundleArchive_revise(bundle_archive_pt archive, const char * location, const char *inputFile) { + celix_status_t status = CELIX_SUCCESS; + long revNr = 0l; + if (!linkedList_isEmpty(archive->revisions)) { + long revisionNr; + status = bundleRevision_getNumber(linkedList_getLast(archive->revisions), &revisionNr); + revNr = revisionNr + 1; + } + if (status == CELIX_SUCCESS) { + status = bundleArchive_reviseInternal(archive, false, revNr, location, inputFile); + } + + framework_logIfError(logger, status, NULL, "Could not revise bundle archive"); + + return status; +} + +static celix_status_t bundleArchive_reviseInternal(bundle_archive_pt archive, bool isReload, long revNr, const char * location, const char *inputFile) { + celix_status_t status = CELIX_SUCCESS; + bundle_revision_pt revision = NULL; + + if (inputFile != NULL) { + location = "inputstream:"; + } + + status = bundleArchive_createRevisionFromLocation(archive, location, inputFile, revNr, &revision); + + if (status == CELIX_SUCCESS) { + if (!isReload) { + status = bundleArchive_setRevisionLocation(archive, location, revNr); + } + + linkedList_addElement(archive->revisions, revision); + } + + framework_logIfError(logger, status, NULL, "Could not revise bundle archive"); + + return status; +} + +celix_status_t bundleArchive_rollbackRevise(bundle_archive_pt archive, bool *rolledback) { + *rolledback = true; + return CELIX_SUCCESS; +} + +static celix_status_t bundleArchive_createRevisionFromLocation(bundle_archive_pt archive, const char *location, const char *inputFile, long revNr, bundle_revision_pt *bundle_revision) { + celix_status_t status = CELIX_SUCCESS; + char root[256]; + long refreshCount; + + status = bundleArchive_getRefreshCount(archive, &refreshCount); + if (status == CELIX_SUCCESS) { + bundle_revision_pt revision = NULL; + + sprintf(root, "%s/version%ld.%ld", archive->archiveRoot, refreshCount, revNr); + status = bundleRevision_create(root, location, revNr, inputFile, &revision); + + if (status == CELIX_SUCCESS) { + *bundle_revision = revision; + } + } + + framework_logIfError(logger, status, NULL, "Could not create revision [location=%s,inputFile=%s]", location, inputFile); + + return status; +} + +static celix_status_t bundleArchive_getRevisionLocation(bundle_archive_pt archive, long revNr, char **revision_location) { + celix_status_t status = CELIX_SUCCESS; + char revisionLocation[256]; + long refreshCount; + + status = bundleArchive_getRefreshCount(archive, &refreshCount); + if (status == CELIX_SUCCESS) { + FILE *revisionLocationFile; + + snprintf(revisionLocation, sizeof(revisionLocation), "%s/version%ld.%ld/revision.location", archive->archiveRoot, refreshCount, revNr); + + revisionLocationFile = fopen(revisionLocation, "r"); + if (revisionLocationFile != NULL) { + char location[256]; + fgets(location , sizeof(location) , revisionLocationFile); + fclose(revisionLocationFile); + + *revision_location = strdup(location); + status = CELIX_SUCCESS; + } else { + // revision file not found + printf("Failed to open revision file at: %s\n", revisionLocation); + status = CELIX_FILE_IO_EXCEPTION; + } + } + + + framework_logIfError(logger, status, NULL, "Failed to get revision location"); + + return status; +} + +static celix_status_t bundleArchive_setRevisionLocation(bundle_archive_pt archive, const char * location, long revNr) { + celix_status_t status = CELIX_SUCCESS; + + char revisionLocation[256]; + long refreshCount; + + status = bundleArchive_getRefreshCount(archive, &refreshCount); + if (status == CELIX_SUCCESS) { + FILE * revisionLocationFile; + + snprintf(revisionLocation, sizeof(revisionLocation), "%s/version%ld.%ld/revision.location", archive->archiveRoot, refreshCount, revNr); + + revisionLocationFile = fopen(revisionLocation, "w"); + if (revisionLocationFile == NULL) { + status = CELIX_FILE_IO_EXCEPTION; + } else { + fprintf(revisionLocationFile, "%s", location); + fclose(revisionLocationFile); + } + } + + framework_logIfError(logger, status, NULL, "Failed to set revision location"); + + return status; +} + +celix_status_t bundleArchive_close(bundle_archive_pt archive) { + // close revision + // not yet needed/possible + return CELIX_SUCCESS; +} + +celix_status_t bundleArchive_closeAndDelete(bundle_archive_pt archive) { + celix_status_t status = CELIX_SUCCESS; + + status = bundleArchive_close(archive); + if (status == CELIX_SUCCESS) { + status = bundleArchive_deleteTree(archive, archive->archiveRoot); + } + + framework_logIfError(logger, status, NULL, "Failed to close and delete archive"); + + return status; +} + +static celix_status_t bundleArchive_initialize(bundle_archive_pt archive) { + celix_status_t status = CELIX_SUCCESS; + + if (archive->archiveRootDir == NULL) { + int err = mkdir(archive->archiveRoot, S_IRWXU) ; + if (err != 0) { + char *errmsg = strerror(errno); + fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Error mkdir: %s\n", errmsg); + status = CELIX_FILE_IO_EXCEPTION; + } else { + archive->archiveRootDir = opendir(archive->archiveRoot); + if (archive->archiveRootDir == NULL) { + status = CELIX_FILE_IO_EXCEPTION; + } else { + FILE *bundleIdFile; + char bundleId[512]; + + snprintf(bundleId, sizeof(bundleId), "%s/bundle.id", archive->archiveRoot); + bundleIdFile = fopen(bundleId, "w"); + + if (bundleIdFile == NULL) { + status = CELIX_FILE_IO_EXCEPTION; + } else { + FILE *bundleLocationFile; + char bundleLocation[512]; + + fprintf(bundleIdFile, "%ld", archive->id); + // Ignore close status, let it fail if needed again + fclose(bundleIdFile); + + snprintf(bundleLocation, sizeof(bundleLocation), "%s/bundle.location", archive->archiveRoot); + bundleLocationFile = fopen(bundleLocation, "w"); + + if (bundleLocationFile == NULL) { + status = CELIX_FILE_IO_EXCEPTION; + } else { + fprintf(bundleLocationFile, "%s", archive->location); + // Ignore close status, let it fail if needed again + fclose(bundleLocationFile); + + status = bundleArchive_writeLastModified(archive); + } + } + closedir(archive->archiveRootDir); + } + } + } + + framework_logIfError(logger, status, NULL, "Failed to initialize archive"); + + return status; +} + +static celix_status_t bundleArchive_deleteTree(bundle_archive_pt archive, const char * directory) { + DIR *dir; + celix_status_t status = CELIX_SUCCESS; + dir = opendir(directory); + if (dir == NULL) { + status = CELIX_FILE_IO_EXCEPTION; + } else { + + struct dirent* dent = NULL; + + errno = 0; + dent = readdir(dir); + while (errno == 0 && dent != NULL) { + if ((strcmp((dent->d_name), ".") != 0) && (strcmp((dent->d_name), "..") != 0)) { + char subdir[512]; + snprintf(subdir, 512, "%s/%s", directory, dent->d_name); + + struct stat st; + if (stat(subdir, &st) == 0) { + if (S_ISDIR (st.st_mode)) { + status = bundleArchive_deleteTree(archive, subdir); + } else { + if (remove(subdir) != 0) { + status = CELIX_FILE_IO_EXCEPTION; + break; + } + } + } + } + errno = 0; + dent = readdir(dir); + } + + if (errno != 0) { + status = CELIX_FILE_IO_EXCEPTION; + } else if (closedir(dir) != 0) { + status = CELIX_FILE_IO_EXCEPTION; + } else if (status == CELIX_SUCCESS) { + if (rmdir(directory) != 0) { + status = CELIX_FILE_IO_EXCEPTION; + } + } + } + + framework_logIfError(logger, status, NULL, "Failed to delete tree"); + + return status; +} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/bundle_cache.c ---------------------------------------------------------------------- diff --git a/framework/src/bundle_cache.c b/framework/src/bundle_cache.c new file mode 100644 index 0000000..39875b5 --- /dev/null +++ b/framework/src/bundle_cache.c @@ -0,0 +1,218 @@ +/** + *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_cache.c + * + * \date Aug 6, 2010 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ +#include <string.h> +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <dirent.h> +#include <unistd.h> + +#include "bundle_cache_private.h" +#include "bundle_archive.h" +#include "constants.h" +#include "celix_log.h" + +static celix_status_t bundleCache_deleteTree(bundle_cache_pt cache, char * directory); + +celix_status_t bundleCache_create(properties_pt configurationMap, bundle_cache_pt *bundle_cache) { + celix_status_t status; + bundle_cache_pt cache; + + if (configurationMap == NULL || *bundle_cache != NULL) { + return CELIX_ILLEGAL_ARGUMENT; + } + + cache = (bundle_cache_pt) calloc(1, sizeof(*cache)); + if (cache == NULL) { + status = CELIX_ENOMEM; + } else { + char* cacheDir = (char*)properties_get(configurationMap, (char *) OSGI_FRAMEWORK_FRAMEWORK_STORAGE); + cache->configurationMap = configurationMap; + if (cacheDir == NULL) { + cacheDir = ".cache"; + } + cache->cacheDir = cacheDir; + + *bundle_cache = cache; + status = CELIX_SUCCESS; + } + + framework_logIfError(logger, status, NULL, "Failed to create bundle cache"); + + return status; +} + +celix_status_t bundleCache_destroy(bundle_cache_pt *cache) { + + free(*cache); + *cache = NULL; + + return CELIX_SUCCESS; +} + +celix_status_t bundleCache_delete(bundle_cache_pt cache) { + return bundleCache_deleteTree(cache, cache->cacheDir); +} + +celix_status_t bundleCache_getArchives(bundle_cache_pt cache, array_list_pt *archives) { + celix_status_t status = CELIX_SUCCESS; + + DIR *dir; + struct stat st; + + dir = opendir(cache->cacheDir); + + if (dir == NULL && errno == ENOENT) { + if(mkdir(cache->cacheDir, S_IRWXU) == 0 ){ + dir = opendir(cache->cacheDir); + } + } + + if (dir != NULL) { + array_list_pt list = NULL; + arrayList_create(&list); + + struct dirent* dent = NULL; + + errno = 0; + dent = readdir(dir); + while (errno == 0 && dent != NULL) { + char archiveRoot[512]; + + snprintf(archiveRoot, sizeof(archiveRoot), "%s/%s", cache->cacheDir, dent->d_name); + + if (stat (archiveRoot, &st) == 0) { + if (S_ISDIR (st.st_mode) + && (strcmp((dent->d_name), ".") != 0) + && (strcmp((dent->d_name), "..") != 0) + && (strncmp(dent->d_name, "bundle", 6) == 0) + && (strcmp(dent->d_name, "bundle0") != 0)) { + + bundle_archive_pt archive = NULL; + status = bundleArchive_recreate(archiveRoot, &archive); + if (status == CELIX_SUCCESS) { + arrayList_add(list, archive); + } + } + } + + errno = 0; + dent = readdir(dir); + } + + if (errno != 0) { + fw_log(logger, OSGI_FRAMEWORK_LOG_ERROR, "Error reading dir"); + status = CELIX_FILE_IO_EXCEPTION; + } else { + status = CELIX_SUCCESS; + } + + closedir(dir); + + if (status == CELIX_SUCCESS) { + *archives = list; + } + else{ + int idx = 0; + for(;idx<arrayList_size(list);idx++){ + bundleArchive_destroy((bundle_archive_pt)arrayList_get(list,idx)); + } + arrayList_destroy(list); + *archives = NULL; + } + + } else { + status = CELIX_FILE_IO_EXCEPTION; + } + + framework_logIfError(logger, status, NULL, "Failed to get bundle archives"); + + return status; +} + +celix_status_t bundleCache_createArchive(bundle_cache_pt cache, long id, const char * location, const char *inputFile, bundle_archive_pt *bundle_archive) { + celix_status_t status = CELIX_SUCCESS; + char archiveRoot[512]; + + if (cache && location) { + snprintf(archiveRoot, sizeof(archiveRoot), "%s/bundle%ld", cache->cacheDir, id); + status = bundleArchive_create(archiveRoot, id, location, inputFile, bundle_archive); + } + + framework_logIfError(logger, status, NULL, "Failed to create archive"); + + return status; +} + +static celix_status_t bundleCache_deleteTree(bundle_cache_pt cache, char * directory) { + DIR *dir; + celix_status_t status = CELIX_SUCCESS; + struct stat st; + + errno = 0; + dir = opendir(directory); + if (dir == NULL) { + status = CELIX_FILE_IO_EXCEPTION; + } else { + struct dirent* dent = NULL; + dent = readdir(dir); + while (errno == 0 && dent != NULL) { + if ((strcmp((dent->d_name), ".") != 0) && (strcmp((dent->d_name), "..") != 0)) { + char subdir[512]; + snprintf(subdir, sizeof(subdir), "%s/%s", directory, dent->d_name); + + if (stat(subdir, &st) == 0) { + if (S_ISDIR (st.st_mode)) { + status = bundleCache_deleteTree(cache, subdir); + } else { + if (remove(subdir) != 0) { + status = CELIX_FILE_IO_EXCEPTION; + break; + } + } + } + } + errno = 0; + dent = readdir(dir); + } + + if (errno != 0) { + status = CELIX_FILE_IO_EXCEPTION; + } + else if (closedir(dir) != 0) { + status = CELIX_FILE_IO_EXCEPTION; + } + if (status == CELIX_SUCCESS) { + if (rmdir(directory) != 0) { + status = CELIX_FILE_IO_EXCEPTION; + } + } + } + + framework_logIfError(logger, status, NULL, "Failed to delete tree at dir '%s'", directory); + + return status; +} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/bundle_cache.h ---------------------------------------------------------------------- diff --git a/framework/src/bundle_cache.h b/framework/src/bundle_cache.h new file mode 100644 index 0000000..350f33b --- /dev/null +++ b/framework/src/bundle_cache.h @@ -0,0 +1,115 @@ +/** + *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_cache.h + * + * \date Aug 8, 2010 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + +#ifndef BUNDLE_CACHE_H_ +#define BUNDLE_CACHE_H_ + +/** + * @defgroup BundleCache BundleCache + * @ingroup framework + * @{ + */ + +#include "properties.h" +#include "array_list.h" +#include "bundle_archive.h" +#include "celix_log.h" + +/** + * Type definition for the bundle_cache_pt abstract data type. + */ +typedef struct bundleCache *bundle_cache_pt; + +/** + * Creates the bundle cache using the supplied configuration map. + * + * @param configurationMap Set with properties to use for this cache + * @param mp The memory pool to use for allocation the cache + * @param bundle_cache Output parameter for the created cache + * @return Status code indication failure or success: + * - CELIX_SUCCESS when no errors are encountered. + * - CELIX_ILLEGAL_ARGUMENT If <code>bundle_cache</code> not is null. + * - CELIX_ENOMEM If allocating memory for <code>bundle_cache</code> failed. + */ +celix_status_t bundleCache_create(properties_pt configurationMap, bundle_cache_pt *bundle_cache); + +/** + * Frees the bundle_cache memory allocated in bundleCache_create + * + * @param bundle_cache Output parameter for the created cache + * @return Status code indication failure or success: + * - CELIX_SUCCESS when no errors are encountered. + */ +celix_status_t bundleCache_destroy(bundle_cache_pt *cache); + +/** + * Recreates and retrieves the list of archives for the given bundle cache. + * Archives are recreated on the bundle cache memory pool, the list for the results is created on the suplied pool, and is owned by the caller. + * + * @param cache The cache to recreate archives out + * @param pool The pool on which the list of archives is created + * @param archives List with recreated archives + * @return Status code indication failure or success: + * - CELIX_SUCCESS when no errors are encountered. + * - CELIX_ILLEGAL_ARGUMENT If <code>archives</code> not is null. + * - CELIX_ENOMEM If allocating memory for <code>archives</code> failed. + * - CELIX_FILE_IO_EXCEPTION If the cache cannot be opened or read. + */ +celix_status_t bundleCache_getArchives(bundle_cache_pt cache, array_list_pt *archives); + +/** + * Creates a new archive for the given bundle (using the id and location). The archive is created on the supplied bundlePool. + * + * @param cache The cache to create an archive in + * @param bundlePool The pool to use for the archive creation + * @param id The id of the bundle + * @param location The location identifier of the bundle + * @param inputFile Input identifier to read the bundle data from + * @param archive The archive to create + * + * @return Status code indication failure or success: + * - CELIX_SUCCESS when no errors are encountered. + * - CELIX_ILLEGAL_ARGUMENT If <code>bundle_archive</code> not is null. + * - CELIX_ENOMEM If allocating memory for <code>bundle_archive</code> failed. + */ +celix_status_t bundleCache_createArchive(bundle_cache_pt cache, long id, const char* location, const char* inputFile, bundle_archive_pt *archive); + +/** + * Deletes the entire bundle cache. + * + * @param cache the cache to delete + * @return Status code indication failure or success: + * - CELIX_SUCCESS when no errors are encountered. + * - CELIX_ILLEGAL_ARGUMENT If the cache is invalid + * - CELIX_FILE_IO_EXCEPTION If the cache cannot be opened or read. + */ +celix_status_t bundleCache_delete(bundle_cache_pt cache); + +/** + * @} + */ + +#endif /* BUNDLE_CACHE_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/bundle_cache_private.h ---------------------------------------------------------------------- diff --git a/framework/src/bundle_cache_private.h b/framework/src/bundle_cache_private.h new file mode 100644 index 0000000..69e26ee --- /dev/null +++ b/framework/src/bundle_cache_private.h @@ -0,0 +1,39 @@ +/** + *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_cache_private.h + * + * \date Feb 12, 2013 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + + +#ifndef BUNDLE_CACHE_PRIVATE_H_ +#define BUNDLE_CACHE_PRIVATE_H_ + +#include "bundle_cache.h" + +struct bundleCache { + properties_pt configurationMap; + char * cacheDir; +}; + + +#endif /* BUNDLE_CACHE_PRIVATE_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/bundle_context.c ---------------------------------------------------------------------- diff --git a/framework/src/bundle_context.c b/framework/src/bundle_context.c new file mode 100644 index 0000000..face85d --- /dev/null +++ b/framework/src/bundle_context.c @@ -0,0 +1,384 @@ +/** + *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_context.c + * + * \date Mar 26, 2010 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#include "bundle_context_private.h" +#include "framework_private.h" +#include "bundle.h" +#include "celix_log.h" + +celix_status_t bundleContext_create(framework_pt framework, framework_logger_pt logger, bundle_pt bundle, bundle_context_pt *bundle_context) { + celix_status_t status = CELIX_SUCCESS; + bundle_context_pt context = NULL; + + if (*bundle_context != NULL && framework == NULL && bundle == NULL) { + status = CELIX_ILLEGAL_ARGUMENT; + } else { + context = malloc(sizeof(*context)); + if (!context) { + status = CELIX_ENOMEM; + } else { + context->framework = framework; + context->bundle = bundle; + + *bundle_context = context; + } + } + + framework_logIfError(logger, status, NULL, "Failed to create context"); + + return status; +} + +celix_status_t bundleContext_destroy(bundle_context_pt context) { + celix_status_t status = CELIX_SUCCESS; + + if (context != NULL) { + free(context); + context = NULL; + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + + framework_logIfError(logger, status, NULL, "Failed to destroy context"); + + return status; +} + +celix_status_t bundleContext_getBundle(bundle_context_pt context, bundle_pt *bundle) { + celix_status_t status = CELIX_SUCCESS; + + if (context == NULL) { + status = CELIX_ILLEGAL_ARGUMENT; + } else { + *bundle = context->bundle; + } + + framework_logIfError(logger, status, NULL, "Failed to get bundle"); + + return status; +} + +celix_status_t bundleContext_getFramework(bundle_context_pt context, framework_pt *framework) { + celix_status_t status = CELIX_SUCCESS; + + if (context == NULL) { + status = CELIX_ILLEGAL_ARGUMENT; + } else { + *framework = context->framework; + } + + framework_logIfError(logger, status, NULL, "Failed to get framework"); + + return status; +} + +celix_status_t bundleContext_installBundle(bundle_context_pt context, const char * location, bundle_pt *bundle) { + return bundleContext_installBundle2(context, location, NULL, bundle); +} + +celix_status_t bundleContext_installBundle2(bundle_context_pt context, const char * location, const char *inputFile, bundle_pt *bundle) { + celix_status_t status = CELIX_SUCCESS; + bundle_pt b = NULL; + + if (context != NULL && *bundle == NULL) { + if (fw_installBundle(context->framework, &b, location, inputFile) != CELIX_SUCCESS) { + status = CELIX_FRAMEWORK_EXCEPTION; + } else { + *bundle = b; + } + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + + framework_logIfError(logger, status, NULL, "Failed to install bundle"); + + return status; +} + +celix_status_t bundleContext_registerService(bundle_context_pt context, const char * serviceName, const void * svcObj, + properties_pt properties, service_registration_pt *service_registration) { + service_registration_pt registration = NULL; + celix_status_t status = CELIX_SUCCESS; + + if (context != NULL) { + fw_registerService(context->framework, ®istration, context->bundle, serviceName, svcObj, properties); + *service_registration = registration; + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + + framework_logIfError(logger, status, NULL, "Failed to register service. serviceName '%s'", serviceName); + + return status; +} + +celix_status_t bundleContext_registerServiceFactory(bundle_context_pt context, const char * serviceName, service_factory_pt factory, + properties_pt properties, service_registration_pt *service_registration) { + service_registration_pt registration = NULL; + celix_status_t status = CELIX_SUCCESS; + + if (context != NULL && *service_registration == NULL) { + fw_registerServiceFactory(context->framework, ®istration, context->bundle, serviceName, factory, properties); + *service_registration = registration; + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + + framework_logIfError(logger, status, NULL, "Failed to register service factory"); + + return status; +} + +celix_status_t bundleContext_getServiceReferences(bundle_context_pt context, const char * serviceName, const char * filter, array_list_pt *service_references) { + celix_status_t status = CELIX_SUCCESS; + + if (context != NULL && *service_references == NULL) { + fw_getServiceReferences(context->framework, service_references, context->bundle, serviceName, filter); + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + + framework_logIfError(logger, status, NULL, "Failed to get service references"); + + return status; +} + +celix_status_t bundleContext_getServiceReference(bundle_context_pt context, const char * serviceName, service_reference_pt *service_reference) { + service_reference_pt reference = NULL; + array_list_pt services = NULL; + celix_status_t status = CELIX_SUCCESS; + + if (serviceName != NULL) { + if (bundleContext_getServiceReferences(context, serviceName, NULL, &services) == CELIX_SUCCESS) { + reference = (arrayList_size(services) > 0) ? arrayList_get(services, 0) : NULL; + arrayList_destroy(services); + *service_reference = reference; + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + + framework_logIfError(logger, status, NULL, "Failed to get service reference"); + + return status; +} + +FRAMEWORK_EXPORT celix_status_t bundleContext_retainServiceReference(bundle_context_pt context, service_reference_pt ref) { + celix_status_t status = CELIX_SUCCESS; + + if (context != NULL && ref != NULL) { + serviceRegistry_retainServiceReference(context->framework->registry, context->bundle, ref); + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + + framework_logIfError(logger, status, NULL, "Failed to get service references"); + + return status; +} + +celix_status_t bundleContext_ungetServiceReference(bundle_context_pt context, service_reference_pt reference) { + celix_status_t status = CELIX_SUCCESS; + + if (context != NULL && reference != NULL) { + status = framework_ungetServiceReference(context->framework, context->bundle, reference); + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + + framework_logIfError(logger, status, NULL, "Failed to unget service_reference"); + + return status; +} + +celix_status_t bundleContext_getService(bundle_context_pt context, service_reference_pt reference, void** service_instance) { + celix_status_t status = CELIX_SUCCESS; + + if (context != NULL && reference != NULL && *service_instance == NULL) { + /*NOTE argument service_instance should be considerd a 'const void**'. + To ensure backwards compatiblity a cast is made instead. + */ + status = fw_getService(context->framework, context->bundle, reference, (const void**) service_instance); + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + + framework_logIfError(logger, status, NULL, "Failed to get service"); + + return status; +} + +celix_status_t bundleContext_ungetService(bundle_context_pt context, service_reference_pt reference, bool *result) { + celix_status_t status = CELIX_SUCCESS; + + if (context != NULL && reference != NULL) { + status = framework_ungetService(context->framework, context->bundle, reference, result); + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + + framework_logIfError(logger, status, NULL, "Failed to unget service"); + + return status; +} + +celix_status_t bundleContext_getBundles(bundle_context_pt context, array_list_pt *bundles) { + celix_status_t status = CELIX_SUCCESS; + + if (context == NULL || *bundles != NULL) { + status = CELIX_ILLEGAL_ARGUMENT; + } else { + *bundles = framework_getBundles(context->framework); + } + + framework_logIfError(logger, status, NULL, "Failed to get bundles"); + + return status; +} + +celix_status_t bundleContext_getBundleById(bundle_context_pt context, long id, bundle_pt *bundle) { + celix_status_t status = CELIX_SUCCESS; + + if (context == NULL || *bundle != NULL) { + status = CELIX_ILLEGAL_ARGUMENT; + } else { + *bundle = framework_getBundleById(context->framework, id); + if (*bundle == NULL) { + status = CELIX_BUNDLE_EXCEPTION; + } + } + + framework_logIfError(logger, status, NULL, "Failed to get bundle [id=%ld]", id); + + return status; +} + +celix_status_t bundleContext_addServiceListener(bundle_context_pt context, service_listener_pt listener, const char* filter) { + celix_status_t status = CELIX_SUCCESS; + + if (context != NULL && listener != NULL) { + fw_addServiceListener(context->framework, context->bundle, listener, filter); + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + + framework_logIfError(logger, status, NULL, "Failed to add service listener"); + + return status; +} + +celix_status_t bundleContext_removeServiceListener(bundle_context_pt context, service_listener_pt listener) { + celix_status_t status = CELIX_SUCCESS; + + if (context != NULL && listener != NULL) { + fw_removeServiceListener(context->framework, context->bundle, listener); + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + + framework_logIfError(logger, status, NULL, "Failed to remove service listener"); + + return status; +} + +celix_status_t bundleContext_addBundleListener(bundle_context_pt context, bundle_listener_pt listener) { + celix_status_t status = CELIX_SUCCESS; + + if (context != NULL && listener != NULL) { + fw_addBundleListener(context->framework, context->bundle, listener); + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + + framework_logIfError(logger, status, NULL, "Failed to add bundle listener"); + + return status; +} + +celix_status_t bundleContext_removeBundleListener(bundle_context_pt context, bundle_listener_pt listener) { + celix_status_t status = CELIX_SUCCESS; + + if (context != NULL && listener != NULL) { + fw_removeBundleListener(context->framework, context->bundle, listener); + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + + framework_logIfError(logger, status, NULL, "Failed to remove bundle listener"); + + return status; +} + +celix_status_t bundleContext_addFrameworkListener(bundle_context_pt context, framework_listener_pt listener) { + celix_status_t status = CELIX_SUCCESS; + + if (context != NULL && listener != NULL) { + fw_addFrameworkListener(context->framework, context->bundle, listener); + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + + framework_logIfError(logger, status, NULL, "Failed to add framework listener"); + + return status; +} + +celix_status_t bundleContext_removeFrameworkListener(bundle_context_pt context, framework_listener_pt listener) { + celix_status_t status = CELIX_SUCCESS; + + if (context != NULL && listener != NULL) { + fw_removeFrameworkListener(context->framework, context->bundle, listener); + } else { + status = CELIX_ILLEGAL_ARGUMENT; + } + + framework_logIfError(logger, status, NULL, "Failed to remove framework listener"); + + return status; +} + +celix_status_t bundleContext_getProperty(bundle_context_pt context, const char *name, const char** value) { + return bundleContext_getPropertyWithDefault(context, name, NULL, value); +} + +celix_status_t bundleContext_getPropertyWithDefault(bundle_context_pt context, const char* name, const char* defaultValue, const char** value) { + celix_status_t status = CELIX_SUCCESS; + + if (context == NULL || name == NULL || *value != NULL) { + status = CELIX_ILLEGAL_ARGUMENT; + } else { + fw_getProperty(context->framework, name, defaultValue, value); + } + + framework_logIfError(logger, status, NULL, "Failed to get property [name=%s]", name); + + return status; +} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/bundle_context_private.h ---------------------------------------------------------------------- diff --git a/framework/src/bundle_context_private.h b/framework/src/bundle_context_private.h new file mode 100644 index 0000000..3810cd0 --- /dev/null +++ b/framework/src/bundle_context_private.h @@ -0,0 +1,43 @@ +/** + *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_context_private.h + * + * \date Feb 12, 2013 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + + +#ifndef BUNDLE_CONTEXT_PRIVATE_H_ +#define BUNDLE_CONTEXT_PRIVATE_H_ + +#include "bundle_context.h" +#include "celix_log.h" + +struct bundleContext { +#ifdef WITH_APR + apr_pool_t *pool; +#endif + struct framework * framework; + struct bundle * bundle; +}; + + +#endif /* BUNDLE_CONTEXT_PRIVATE_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/bundle_private.h ---------------------------------------------------------------------- diff --git a/framework/src/bundle_private.h b/framework/src/bundle_private.h new file mode 100644 index 0000000..8085609 --- /dev/null +++ b/framework/src/bundle_private.h @@ -0,0 +1,48 @@ +/** + *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_private.h + * + * \date Feb 18, 2011 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + +#ifndef BUNDLE_PRIVATE_H_ +#define BUNDLE_PRIVATE_H_ + +#include "bundle.h" + +struct bundle { + bundle_context_pt context; + activator_pt activator; + bundle_state_e state; + void * handle; + bundle_archive_pt archive; + array_list_pt modules; + manifest_pt manifest; + + celix_thread_mutex_t lock; + int lockCount; + celix_thread_t lockThread; + + struct framework * framework; +}; + +#endif /* BUNDLE_PRIVATE_H_ */ http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/bundle_revision.c ---------------------------------------------------------------------- diff --git a/framework/src/bundle_revision.c b/framework/src/bundle_revision.c new file mode 100644 index 0000000..cfa10aa --- /dev/null +++ b/framework/src/bundle_revision.c @@ -0,0 +1,153 @@ +/** + *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_revision.c + * + * \date Apr 12, 2011 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + +#include <stdio.h> +#include <stdlib.h> +#include <sys/stat.h> +#include <archive.h> +#include <string.h> + +#include "bundle_revision_private.h" + +celix_status_t bundleRevision_create(const char *root, const char *location, long revisionNr, const char *inputFile, bundle_revision_pt *bundle_revision) { + celix_status_t status = CELIX_SUCCESS; + bundle_revision_pt revision = NULL; + + revision = (bundle_revision_pt) malloc(sizeof(*revision)); + if (!revision) { + status = CELIX_ENOMEM; + } else { + // TODO: This overwrites an existing revision, is this supposed to happen? + int state = mkdir(root, S_IRWXU); + if ((state != 0) && (errno != EEXIST)) { + free(revision); + status = CELIX_FILE_IO_EXCEPTION; + } else { + if (inputFile != NULL) { + status = extractBundle(inputFile, root); + } else if (strcmp(location, "inputstream:") != 0) { + // TODO how to handle this correctly? + // If location != inputstream, extract it, else ignore it and assume this is a cache entry. + status = extractBundle(location, root); + } + + status = CELIX_DO_IF(status, arrayList_create(&(revision->libraryHandles))); + if (status == CELIX_SUCCESS) { + revision->revisionNr = revisionNr; + revision->root = strdup(root); + revision->location = strdup(location); + + *bundle_revision = revision; + + char manifest[512]; + snprintf(manifest, sizeof(manifest), "%s/META-INF/MANIFEST.MF", revision->root); + status = manifest_createFromFile(manifest, &revision->manifest); + } + else { + free(revision); + } + + } + } + + framework_logIfError(logger, status, NULL, "Failed to create revision"); + + return status; +} + +celix_status_t bundleRevision_destroy(bundle_revision_pt revision) { + arrayList_destroy(revision->libraryHandles); + manifest_destroy(revision->manifest); + free(revision->root); + free(revision->location); + free(revision); + return CELIX_SUCCESS; +} + +celix_status_t bundleRevision_getNumber(bundle_revision_pt revision, long *revisionNr) { + celix_status_t status = CELIX_SUCCESS; + if (revision == NULL) { + status = CELIX_ILLEGAL_ARGUMENT; + } else { + *revisionNr = revision->revisionNr; + } + + framework_logIfError(logger, status, NULL, "Failed to get revision number"); + + return status; +} + +celix_status_t bundleRevision_getLocation(bundle_revision_pt revision, const char **location) { + celix_status_t status = CELIX_SUCCESS; + if (revision == NULL) { + status = CELIX_ILLEGAL_ARGUMENT; + } else { + *location = revision->location; + } + + framework_logIfError(logger, status, NULL, "Failed to get revision location"); + + return status; +} + +celix_status_t bundleRevision_getRoot(bundle_revision_pt revision, const char **root) { + celix_status_t status = CELIX_SUCCESS; + if (revision == NULL) { + status = CELIX_ILLEGAL_ARGUMENT; + } else { + *root = revision->root; + } + + framework_logIfError(logger, status, NULL, "Failed to get revision root"); + + return status; +} + +celix_status_t bundleRevision_getManifest(bundle_revision_pt revision, manifest_pt *manifest) { + celix_status_t status = CELIX_SUCCESS; + if (revision == NULL) { + status = CELIX_ILLEGAL_ARGUMENT; + } else { + *manifest = revision->manifest; + } + + framework_logIfError(logger, status, NULL, "Failed to get manifest"); + + return status; +} + +celix_status_t bundleRevision_getHandles(bundle_revision_pt revision, array_list_pt *handles) { + celix_status_t status = CELIX_SUCCESS; + if (revision == NULL) { + status = CELIX_ILLEGAL_ARGUMENT; + } else { + *handles = revision->libraryHandles; + } + + framework_logIfError(logger, status, NULL, "Failed to get handles"); + + return status; +} http://git-wip-us.apache.org/repos/asf/celix/blob/a1c30887/framework/src/bundle_revision_private.h ---------------------------------------------------------------------- diff --git a/framework/src/bundle_revision_private.h b/framework/src/bundle_revision_private.h new file mode 100644 index 0000000..cb1dcd8 --- /dev/null +++ b/framework/src/bundle_revision_private.h @@ -0,0 +1,42 @@ +/** + *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_revision_private.h + * + * \date Feb 12, 2013 + * \author <a href="mailto:[email protected]">Apache Celix Project Team</a> + * \copyright Apache License, Version 2.0 + */ + + +#ifndef BUNDLE_REVISION_PRIVATE_H_ +#define BUNDLE_REVISION_PRIVATE_H_ + +#include "bundle_revision.h" + +struct bundleRevision { + long revisionNr; + char *root; + char *location; + manifest_pt manifest; + + array_list_pt libraryHandles; +}; + +#endif /* BUNDLE_REVISION_PRIVATE_H_ */
