You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2019/12/10 22:35:41 UTC
[celix] branch develop updated: #129: Fixes an issue with stopping
a bundle twice using the 'stop' shell command.
This is an automated email from the ASF dual-hosted git repository.
pnoltes pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/celix.git
The following commit(s) were added to refs/heads/develop by this push:
new 3239a05 #129: Fixes an issue with stopping a bundle twice using the 'stop' shell command.
3239a05 is described below
commit 3239a050c2b6920cd286397208dc122e9ebaef40
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Tue Dec 10 23:35:21 2019 +0100
#129: Fixes an issue with stopping a bundle twice using the 'stop' shell command.
---
bundles/shell/shell/src/install_command.c | 44 ++-----
bundles/shell/shell/src/start_command.c | 81 +++++--------
bundles/shell/shell/src/std_commands.h | 4 +-
bundles/shell/shell/src/stop_command.c | 81 +++++--------
bundles/shell/shell/src/uninstall_command.c | 25 ++--
libs/dfi/include/dyn_type.h | 127 ++++++++++++++++++++-
libs/dfi/src/dyn_type.c | 10 ++
libs/dfi/test/dyn_type_tests.cpp | 14 +++
libs/framework/include/celix_bundle_context.h | 8 ++
libs/framework/src/bundle_context.c | 5 +
.../framework/tst/bundle_context_bundles_tests.cpp | 55 ++++++++-
11 files changed, 288 insertions(+), 166 deletions(-)
diff --git a/bundles/shell/shell/src/install_command.c b/bundles/shell/shell/src/install_command.c
index 16d6182..48370ef 100644
--- a/bundles/shell/shell/src/install_command.c
+++ b/bundles/shell/shell/src/install_command.c
@@ -16,27 +16,22 @@
* specific language governing permissions and limitations
* under the License.
*/
-/**
- * install_command.c
- *
- * \date Apr 4, 2011
- * \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 "celix_api.h"
-#include "array_list.h"
-#include "bundle_context.h"
+static void printInstalledBundle(void *handle, const celix_bundle_t *bnd) {
+ FILE *outStream = handle;
+ fprintf(outStream, "Bundle '%s' installed with bundle id %li\n", celix_bundle_getSymbolicName(bnd), celix_bundle_getId(bnd));
+}
void installCommand_execute(void *handle, char * line, FILE *outStream, FILE *errStream) {
- bundle_context_pt context = handle;
+ celix_bundle_context_t *ctx = handle;
char delims[] = " ";
char * sub = NULL;
char *save_ptr = NULL;
- char info[256];
// ignore the command
sub = strtok_r(line, delims, &save_ptr);
@@ -45,33 +40,12 @@ void installCommand_execute(void *handle, char * line, FILE *outStream, FILE *er
if (sub == NULL) {
fprintf(errStream, "Incorrect number of arguments.\n");
} else {
- info[0] = '\0';
while (sub != NULL) {
- bundle_pt bundle = NULL;
- bundleContext_installBundle(context, sub, &bundle);
- if (bundle != NULL) {
- long id;
- bundle_archive_pt archive = NULL;
- char bundleId[sizeof(id) + 1];
-
- if (strlen(info) > 0) {
- strcat(info, ", ");
- }
- bundle_getArchive(bundle, &archive);
- bundleArchive_getId(archive, &id);
- sprintf(bundleId, "%ld", id);
- strcat(info, bundleId);
+ long bndId = celix_bundleContext_installBundle(ctx, sub, true);
+ if (bndId >= 0) {
+ celix_bundleContext_useBundle(ctx, bndId, outStream, printInstalledBundle);
}
sub = strtok_r(NULL, delims, &save_ptr);
}
- if (strchr(info, ',') != NULL) {
- fprintf(outStream, "Bundle IDs: ");
- fprintf(outStream, "%s", info);
- fprintf(outStream, "\n");
- } else if (strlen(info) > 0) {
- fprintf(outStream, "Bundle ID: ");
- fprintf(outStream, "%s", info);
- fprintf(outStream, "\n");
- }
}
}
\ No newline at end of file
diff --git a/bundles/shell/shell/src/start_command.c b/bundles/shell/shell/src/start_command.c
index 91d0b04..1bbcd92 100644
--- a/bundles/shell/shell/src/start_command.c
+++ b/bundles/shell/shell/src/start_command.c
@@ -16,70 +16,43 @@
* specific language governing permissions and limitations
* under the License.
*/
-/**
- * start_command.c
- *
- * \date Aug 20, 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 <stdio.h>
+#include "celix_api.h"
#include "std_commands.h"
-#include "bundle_context.h"
-
-celix_status_t startCommand_execute(void *_ptr, char *command_line_str, FILE *out_ptr, FILE *err_ptr) {
- celix_status_t status = CELIX_SUCCESS;
-
- bundle_context_pt context_ptr = _ptr;
-
- if (!context_ptr || !command_line_str || !out_ptr || !err_ptr) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- char *sub_str = NULL;
- char *save_ptr = NULL;
-
- strtok_r(command_line_str, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
- sub_str = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
-
- if (sub_str == NULL) {
- fprintf(out_ptr, "Incorrect number of arguments.\n");
- } else {
- while (sub_str != NULL) {
- celix_status_t sub_status = CELIX_SUCCESS;
-
- bundle_pt bundle_ptr = NULL;
- char *end_str = NULL;
- long id = strtol(sub_str, &end_str, 10);
- if (*end_str) {
- sub_status = CELIX_ILLEGAL_ARGUMENT;
- fprintf(err_ptr, "Bundle id '%s' is invalid, problem at %s\n", sub_str, end_str);
+celix_status_t startCommand_execute(void *handle, char *command, FILE *outStream, FILE *errStream) {
+ celix_bundle_context_t *ctx = handle;
+
+ char *sub_str = NULL;
+ char *save_ptr = NULL;
+
+ strtok_r(command, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
+ sub_str = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
+
+ if (sub_str == NULL) {
+ fprintf(outStream, "Incorrect number of arguments.\n");
+ } else {
+ while (sub_str != NULL) {
+ char *end_str = NULL;
+ long bndId = strtol(sub_str, &end_str, 10);
+ if (*end_str) {
+ fprintf(errStream, "Bundle id '%s' is invalid, problem at %s\n", sub_str, end_str);
+ } else {
+ bool exists = celix_bundleContext_isBundleInstalled(ctx, bndId);
+ if (exists) {
+ celix_bundleContext_startBundle(ctx, bndId);
+ } else {
+ fprintf(outStream, "No bundle with id %li.\n", bndId);
}
-
- if (sub_status == CELIX_SUCCESS) {
- sub_status = bundleContext_getBundleById(context_ptr, id, &bundle_ptr);
- }
-
- if (sub_status == CELIX_SUCCESS) {
- bundle_startWithOptions(bundle_ptr, 0);
- }
-
- if (sub_status != CELIX_SUCCESS) {
- status = sub_status;
- break;
- }
-
- sub_str = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
}
- }
+ sub_str = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
+ }
}
- return status;
+ return CELIX_SUCCESS;
}
diff --git a/bundles/shell/shell/src/std_commands.h b/bundles/shell/shell/src/std_commands.h
index 0568897..a0c66b4 100644
--- a/bundles/shell/shell/src/std_commands.h
+++ b/bundles/shell/shell/src/std_commands.h
@@ -32,8 +32,8 @@
#define OSGI_SHELL_COMMAND_SEPARATOR " "
celix_status_t lbCommand_execute(void *_ptr, char *command_line_str, FILE *out_ptr, FILE *err_ptr);
-celix_status_t startCommand_execute(void *_ptr, char *command_line_str, FILE *out_ptr, FILE *err_ptr);
-celix_status_t stopCommand_execute(void *handle, char * commandline, FILE *outStream, FILE *errStream);
+celix_status_t startCommand_execute(void *_ptr, char* command_line_str, FILE *out_ptr, FILE *err_ptr);
+celix_status_t stopCommand_execute(void *handle, char* commandline, FILE *outStream, FILE *errStream);
celix_status_t installCommand_execute(void *handle, char * commandline, FILE *outStream, FILE *errStream);
celix_status_t uninstallCommand_execute(void *handle, char * commandline, FILE *outStream, FILE *errStream);
celix_status_t updateCommand_execute(void *handle, char * commandline, FILE *outStream, FILE *errStream);
diff --git a/bundles/shell/shell/src/stop_command.c b/bundles/shell/shell/src/stop_command.c
index 4578e7a..687b8ef 100644
--- a/bundles/shell/shell/src/stop_command.c
+++ b/bundles/shell/shell/src/stop_command.c
@@ -16,68 +16,43 @@
* specific language governing permissions and limitations
* under the License.
*/
-/**
- * stop_command.c
- *
- * \date Aug 20, 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 "bundle_context.h"
+#include "celix_api.h"
#include "std_commands.h"
-celix_status_t stopCommand_execute(void *_ptr, char *command_line_str, FILE *out_ptr, FILE *err_ptr) {
- celix_status_t status = CELIX_SUCCESS;
-
- bundle_context_pt context_ptr = _ptr;
-
- if (!context_ptr || !command_line_str || !out_ptr || !err_ptr) {
- status = CELIX_ILLEGAL_ARGUMENT;
- }
-
- if (status == CELIX_SUCCESS) {
- char *sub_str = NULL;
- char *save_ptr = NULL;
-
- strtok_r(command_line_str, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
- sub_str = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
-
- if (sub_str == NULL) {
- fprintf(out_ptr, "Incorrect number of arguments.\n");
- } else {
- while (sub_str != NULL) {
- celix_status_t sub_status = CELIX_SUCCESS;
-
- bundle_pt bundle_ptr = NULL;
-
- char *end_str = NULL;
- long id = strtol(sub_str, &end_str, 10);
- if (*end_str) {
- sub_status = CELIX_ILLEGAL_ARGUMENT;
- fprintf(err_ptr, "Bundle id '%s' is invalid, problem at %s\n", sub_str, end_str);
- }
-
- if (sub_status == CELIX_SUCCESS) {
- sub_status = bundleContext_getBundleById(context_ptr, id, &bundle_ptr);
- }
-
- if (sub_status == CELIX_SUCCESS) {
- bundle_stopWithOptions(bundle_ptr, 0);
+celix_status_t stopCommand_execute(void *handle, char *command, FILE *outStream, FILE *errStream) {
+ celix_bundle_context_t *ctx = handle;
+
+ char *sub_str = NULL;
+ char *save_ptr = NULL;
+
+ strtok_r(command, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
+ sub_str = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
+
+ if (sub_str == NULL) {
+ fprintf(outStream, "Incorrect number of arguments.\n");
+ } else {
+ while (sub_str != NULL) {
+
+ char *end_str = NULL;
+ long bndId = strtol(sub_str, &end_str, 10);
+ if (*end_str) {
+ fprintf(errStream, "Bundle id '%s' is invalid, problem at %s\n", sub_str, end_str);
+ } else {
+ bool exists = celix_bundleContext_isBundleInstalled(ctx, bndId);
+ if (exists) {
+ celix_bundleContext_stopBundle(ctx, bndId);
+ } else {
+ fprintf(outStream, "No bundle with id %li.\n", bndId);
}
-
- if (sub_status != CELIX_SUCCESS) {
- status = sub_status;
- break;
- }
-
- sub_str = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
}
+
+ sub_str = strtok_r(NULL, OSGI_SHELL_COMMAND_SEPARATOR, &save_ptr);
}
}
- return status;
+ return CELIX_SUCCESS;
}
diff --git a/bundles/shell/shell/src/uninstall_command.c b/bundles/shell/shell/src/uninstall_command.c
index 8998b42..ea1ad79 100644
--- a/bundles/shell/shell/src/uninstall_command.c
+++ b/bundles/shell/shell/src/uninstall_command.c
@@ -27,33 +27,32 @@
#include <stdlib.h>
#include <string.h>
-#include "array_list.h"
-#include "bundle_context.h"
+#include "celix_api.h"
-celix_status_t uninstallCommand_execute(void *handle, char * line, FILE *outStream, FILE *errStream) {
- bundle_context_pt context = handle;
+
+celix_status_t uninstallCommand_execute(void *handle, char* command, FILE *outStream, FILE *errStream) {
+ celix_bundle_context_t *ctx = handle;
char delims[] = " ";
char * sub = NULL;
char *save_ptr = NULL;
celix_status_t status = CELIX_SUCCESS;
- sub = strtok_r(line, delims, &save_ptr);
+ sub = strtok_r(command, delims, &save_ptr);
sub = strtok_r(NULL, delims, &save_ptr);
if (sub == NULL) {
fprintf(errStream, "Incorrect number of arguments.\n");
} else {
while (sub != NULL) {
- long id = atol(sub);
- bundle_pt bundle = NULL;
- status = bundleContext_getBundleById(context, id, &bundle);
- if (status==CELIX_SUCCESS && bundle!=NULL) {
- bundle_uninstall(bundle);
+ long bndId = atol(sub);
+ bool exists = celix_bundleContext_isBundleInstalled(ctx, bndId);
+ if (exists) {
+ celix_bundleContext_uninstallBundle(ctx, bndId);
} else {
- fprintf(errStream, "Bundle id is invalid.");
- }
+ fprintf(outStream, "No bundle with id %li.\n", bndId);
+ }
sub = strtok_r(NULL, delims, &save_ptr);
}
}
return status;
-}
+}
\ No newline at end of file
diff --git a/libs/dfi/include/dyn_type.h b/libs/dfi/include/dyn_type.h
index 127c3ee..500764b 100644
--- a/libs/dfi/include/dyn_type.h
+++ b/libs/dfi/include/dyn_type.h
@@ -33,8 +33,15 @@
#include "memstream/fmemopen.h"
#endif
-/* Description string
+/**
+ * dyn type (dynamic type) represent a structure in memory. It can be used to calculate the needed memory size, the size
+ * and offset of struct members and can be used to dynamically alloc, initialize, dealloc, read & write structure
+ * in memory. In other words it can be used for reflection.
*
+ * Dyn types can be created by parsing a dyn type descriptor string.
+ * Dyn type descriptor strings are very compact description of a C structure.
+ *
+ * Descriptor strings grammar:
* Type = [TypeDef]* (MetaInfo)* (SimpleType | ComplexType | SequenceType | TypedPointer | PointerReference ) [TypeDef]*
* Name = alpha[(alpha|numeric)*]
* SPACE = ' '
@@ -128,28 +135,136 @@ struct meta_entry {
DFI_SETUP_LOG_HEADER(dynType);
DFI_SETUP_LOG_HEADER(dynAvprType);
-//generic
+/**
+ * Parses a descriptor stream and creates a dyn_type (dynamic type).
+ * If successful the type output argument points to the newly created dyn type.
+ * The caller is the owner of the dyn type and use dynType_destroy deallocate the memory.
+ *
+ * @param descriptorStream Stream to the descriptor.
+ * @param name name for the dyn_type. This can be used in references to dyn types.
+ * @param refTypes A list if reference-able dyn types.
+ * @param type Output argument for the parsed dyn type.
+ * @return 0 if successful.
+ */
int dynType_parse(FILE *descriptorStream, const char *name, struct types_head *refTypes, dyn_type **type);
+
+/**
+ * Parses a descriptor string and creates a dyn_type (dynamic type).
+ * If successful the type output argument points to the newly created dyn type.
+ * The caller is the owner of the dyn type and use dynType_destroy deallocate the memory.
+ *
+ * @param descriptor The descriptor.
+ * @param name name for the dyn_type. This can be used in references to dyn types.
+ * @param refTypes A list if reference-able dyn types.
+ * @param type Output argument for the parsed dyn type.
+ * @return 0 if successful.
+ */
int dynType_parseWithStr(const char *descriptor, const char *name, struct types_head *refTypes, dyn_type **type);
+
+/**
+ * Destroy a dyn type and de-allocates the memory.
+ * @param type The dyn type to destroy.
+ */
void dynType_destroy(dyn_type *type);
-int dynType_alloc(dyn_type *type, void **bufLoc);
-void dynType_free(dyn_type *type, void *loc);
+/**
+ * Allocates memory for a type instance described by a dyn type. The memory will be 0 allocated (calloc).
+
+ * @param type The dyn type for which structure to allocate.
+ * @param instance The output argument for the allocated memory.
+ * @return 0 on success.
+ */
+int dynType_alloc(dyn_type *type, void **instance);
+/**
+ * free the memory for a type instance described by a dyn type.
+ * This is a deep free.
+ *
+ * @param type The dyn type for which structure to allocate.
+ * @param instance The memory location of the type instance.
+ */
+void dynType_free(dyn_type *type, void *instance);
+
+/**
+ * Prints the dyn type information to the provided output stream.
+ * @param type The dyn type to print.
+ * @param stream The output stream (e.g. stdout).
+ */
void dynType_print(dyn_type *type, FILE *stream);
+
+/**
+ * Return the size of the structure descripbed by the dyn type.
+ * This this _not_ includes sizes of data where is only pointed to (i.e. content of sequences, strings, etc).
+ *
+ * @param type The dyn type.
+ * @return The size of the type instance described by dyn type.
+ */
size_t dynType_size(dyn_type *type);
+
+/**
+ * The type of the dyn type
+ * E.g. DYN_TYPE_SIMPLE, DYN_TYPE_COMPLEX, etc
+ * @param type The dyn type
+ * @return The type of the dyn type.
+ */
int dynType_type(dyn_type *type);
+
+/**
+ * Returns the char identifier of the dyn type type.
+ * E.g. 'D' for a double, or '{' for a complex type.
+ * @param type The dyn type
+ * @return The descriptor of the dyn type.
+ */
int dynType_descriptorType(dyn_type *type);
+
+/**
+ * Get the dyn type meta information for the provided name.
+ * @param type The dyn type.
+ * @param name The name of the requested meta information.
+ * @return The meta information or NULL if the meta information is not present.
+ */
const char * dynType_getMetaInfo(dyn_type *type, const char *name);
+
+/**
+ * Returns a list of meta entries.
+ * Note that dyn type is owner of the entries. Traversing the entries is not thread safe.
+ * @param type The dyn type.
+ * @param entries The output arguments for the meta entries.
+ * @return 0 on success.
+ */
int dynType_metaEntries(dyn_type *type, struct meta_properties_head **entries);
+
+/**
+ * Returns the name of the dyn type. Name can be NULL.
+ */
const char * dynType_getName(dyn_type *type);
-//complexType
+
+/**
+ * Returns the field index for a complex type.
+ *
+ * e.g. for a struct { int a; int b; }, a will have an index of 0 and b an index of 1.
+ * @param type The dyn type. Must be a complex type.
+ * @param name The field name.
+ * @return The field index or -1 if no field with the name was found.
+ */
int dynType_complex_indexForName(dyn_type *type, const char *name);
+
+/**
+ * Returns the field dyn type for a given complex type and a field index.
+ *
+ * @param type The dyn type. Must be a complex type.
+ * @param index The field index for which field the dyn type should be returned. The field index must be correct.
+ * @param subType The field dyn type as output.
+ * exists.
+ * @return 0 if successful.
+ */
int dynType_complex_dynTypeAt(dyn_type *type, int index, dyn_type **subType);
+
int dynType_complex_setValueAt(dyn_type *type, int index, void *inst, void *in);
int dynType_complex_valLocAt(dyn_type *type, int index, void *inst, void **valLoc);
int dynType_complex_entries(dyn_type *type, struct complex_type_entries_head **entries);
+size_t dynType_complex_nrOfEntries(dyn_type *type);
//sequence
int dynType_sequence_alloc(dyn_type *type, void *inst, uint32_t cap);
@@ -171,4 +286,4 @@ void dynType_simple_setValue(dyn_type *type, void *inst, void *in);
dyn_type * dynType_parseAvpr(FILE *avprStream, const char *fqn);
dyn_type * dynType_parseAvprWithStr(const char *avpr, const char *fqn);
-#endif
+#endif //_DYN_TYPE_H_
diff --git a/libs/dfi/src/dyn_type.c b/libs/dfi/src/dyn_type.c
index a3657bf..89a1fa9 100644
--- a/libs/dfi/src/dyn_type.c
+++ b/libs/dfi/src/dyn_type.c
@@ -24,6 +24,7 @@
#include <assert.h>
#include <errno.h>
#include <ffi.h>
+#include <dyn_type_common.h>
#include "dyn_type_common.h"
#include "dyn_common.h"
@@ -638,6 +639,15 @@ int dynType_complex_valLocAt(dyn_type *type, int index, void *inst, void **resul
return OK;
}
+size_t dynType_complex_nrOfEntries(dyn_type *type) {
+ size_t count = 0;
+ struct complex_type_entry *entry = NULL;
+ TAILQ_FOREACH(entry, &type->complex.entriesHead, entries) {
+ ++count;
+ }
+ return count;
+}
+
int dynType_complex_entries(dyn_type *type, struct complex_type_entries_head **entries) {
assert(type->type == DYN_TYPE_COMPLEX);
int status = OK;
diff --git a/libs/dfi/test/dyn_type_tests.cpp b/libs/dfi/test/dyn_type_tests.cpp
index 7b358a7..e1c2145 100644
--- a/libs/dfi/test/dyn_type_tests.cpp
+++ b/libs/dfi/test/dyn_type_tests.cpp
@@ -307,3 +307,17 @@ TEST(DynTypeTests, EnumTest) {
dynType_print(type, stdout);
dynType_destroy(type);
}
+
+TEST(DynTypeTests, NrOfEntriesTest) {
+ dyn_type *type = NULL;
+ int rc = dynType_parseWithStr("{DD}", NULL, NULL, &type);
+ CHECK_EQUAL(0, rc);
+ CHECK_EQUAL(2, dynType_complex_nrOfEntries(type));
+ dynType_destroy(type);
+
+ type = NULL;
+ rc = dynType_parseWithStr("{DDJJ}", NULL, NULL, &type);
+ CHECK_EQUAL(0, rc);
+ CHECK_EQUAL(4, dynType_complex_nrOfEntries(type));
+ dynType_destroy(type);
+}
\ No newline at end of file
diff --git a/libs/framework/include/celix_bundle_context.h b/libs/framework/include/celix_bundle_context.h
index 779c134..18c44c0 100644
--- a/libs/framework/include/celix_bundle_context.h
+++ b/libs/framework/include/celix_bundle_context.h
@@ -585,6 +585,14 @@ void celix_bundleContext_useServicesWithOptions(
*/
celix_array_list_t* celix_bundleContext_listBundles(celix_bundle_context_t *ctx);
+/**
+ * Check if whether a bundle is installed.
+ * @param ctx The bundle context.
+ * @param bndId The bundle id to check
+ * @return true if the bundle is installed.
+ */
+bool celix_bundleContext_isBundleInstalled(celix_bundle_context_t *ctx, long bndId);
+
/**
* Install and optional start a bundle.
diff --git a/libs/framework/src/bundle_context.c b/libs/framework/src/bundle_context.c
index dd76ba1..430781c 100644
--- a/libs/framework/src/bundle_context.c
+++ b/libs/framework/src/bundle_context.c
@@ -712,6 +712,11 @@ celix_array_list_t* celix_bundleContext_listBundles(celix_bundle_context_t *ctx)
return result;
}
+bool celix_bundleContext_isBundleInstalled(celix_bundle_context_t *ctx, long bndId) {
+ celix_bundle_t *bnd = framework_getBundleById(ctx->framework, bndId);
+ return bnd != NULL;
+}
+
static void bundleContext_startBundleCallback(void *handle, const bundle_t *c_bnd) {
bool *started = handle;
*started = false;
diff --git a/libs/framework/tst/bundle_context_bundles_tests.cpp b/libs/framework/tst/bundle_context_bundles_tests.cpp
index 8f462d9..d492875 100644
--- a/libs/framework/tst/bundle_context_bundles_tests.cpp
+++ b/libs/framework/tst/bundle_context_bundles_tests.cpp
@@ -139,9 +139,14 @@ TEST(CelixBundleContextBundlesTests, useBundleTest) {
};
TEST(CelixBundleContextBundlesTests, StopStartTest) {
- celix_bundleContext_installBundle(ctx, TEST_BND1_LOC, true);
- celix_bundleContext_installBundle(ctx, TEST_BND2_LOC, true);
- celix_bundleContext_installBundle(ctx, TEST_BND3_LOC, true);
+ long bndId1 = celix_bundleContext_installBundle(ctx, TEST_BND1_LOC, true);
+ long bndId2 = celix_bundleContext_installBundle(ctx, TEST_BND2_LOC, true);
+ long bndId3 = celix_bundleContext_installBundle(ctx, TEST_BND3_LOC, true);
+ CHECK_TRUE(celix_bundleContext_isBundleInstalled(ctx, bndId1));
+ CHECK_TRUE(celix_bundleContext_isBundleInstalled(ctx, bndId2));
+ CHECK_TRUE(celix_bundleContext_isBundleInstalled(ctx, bndId3));
+ CHECK_FALSE(celix_bundleContext_isBundleInstalled(ctx, 600 /*non existing*/));
+
celix_array_list_t *ids = celix_bundleContext_listBundles(ctx);
@@ -184,6 +189,50 @@ TEST(CelixBundleContextBundlesTests, StopStartTest) {
celix_arrayList_destroy(ids);
}
+TEST(CelixBundleContextBundlesTests, DoubleStopTest) {
+ long bndId = celix_bundleContext_installBundle(ctx, TEST_BND1_LOC, true);
+ CHECK_TRUE(bndId > 0);
+ CHECK_TRUE(celix_bundleContext_isBundleInstalled(ctx, bndId));
+
+ //TODO rewrite using celix_bundleContext_useBundlesWithOptions ....
+ bool called = celix_framework_useBundle(fw, false, bndId, nullptr, [](void *, const celix_bundle_t *bnd) {
+ CHECK_EQUAL(OSGI_FRAMEWORK_BUNDLE_ACTIVE, celix_bundle_getState(bnd));
+ });
+ CHECK_TRUE(called);
+
+ //first
+ celix_bundleContext_stopBundle(ctx, bndId);
+
+ called = celix_framework_useBundle(fw, false, bndId, nullptr, [](void *, const celix_bundle_t *bnd) {
+ CHECK_EQUAL(OSGI_FRAMEWORK_BUNDLE_RESOLVED, celix_bundle_getState(bnd));
+ });
+ CHECK_TRUE(called);
+
+ //second
+ celix_bundleContext_stopBundle(ctx, bndId);
+
+ called = celix_framework_useBundle(fw, false, bndId, nullptr, [](void *, const celix_bundle_t *bnd) {
+ CHECK_EQUAL(OSGI_FRAMEWORK_BUNDLE_RESOLVED, celix_bundle_getState(bnd));
+ });
+ CHECK_TRUE(called);
+
+ //first
+ celix_bundleContext_startBundle(ctx, bndId);
+
+ called = celix_framework_useBundle(fw, false, bndId, nullptr, [](void *, const celix_bundle_t *bnd) {
+ CHECK_EQUAL(OSGI_FRAMEWORK_BUNDLE_ACTIVE, celix_bundle_getState(bnd));
+ });
+ CHECK_TRUE(called);
+
+ //second
+ celix_bundleContext_startBundle(ctx, bndId);
+
+ called = celix_framework_useBundle(fw, false, bndId, nullptr, [](void *, const celix_bundle_t *bnd) {
+ CHECK_EQUAL(OSGI_FRAMEWORK_BUNDLE_ACTIVE, celix_bundle_getState(bnd));
+ });
+ CHECK_TRUE(called);
+}
+
TEST(CelixBundleContextBundlesTests, trackBundlesTest) {
struct data {
int count{0};