libs/framework/include/celix_bundle_context.h (341 lines of code) (raw):
/*
* 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.
*/
#ifndef CELIX_BUNDLE_CONTEXT_H_
#define CELIX_BUNDLE_CONTEXT_H_
#include "celix_bundle_context_type.h"
#include "celix_framework_export.h"
#include "celix_filter.h"
#include "celix_service_factory.h"
#include "celix_bundle_event.h"
#include "celix_log_level.h"
#ifdef __cplusplus
extern "C" {
#endif
/**
* Init macro so that the opts are correctly initialized for C++ compilers
*/
#ifdef __cplusplus
#define CELIX_OPTS_INIT {}
#else
#define CELIX_OPTS_INIT
#endif
/**
* @brief Register a service to the Celix framework.
*
* The service will be registered async on the Celix event loop thread. This means that service registration is (probably)
* not yet concluded when this function returns, but is added to the event loop.
* Use celix_bundleContext_waitForAsyncRegistration to synchronise with the
* actual service registration in the framework's service registry.
*
* @param ctx The bundle context
* @param svc the service object. Normally a pointer to a service struct (i.e. a struct with function pointers)
* @param serviceName the service name, cannot be NULL
* @param properties The meta properties associated with the service. The service registration will take ownership of the properties (i.e. no destroy needed)
* @return The serviceId (>=0) or -1 if the registration was unsuccessful.
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_registerServiceAsync(celix_bundle_context_t *ctx, void *svc, const char* serviceName, celix_properties_t *properties);
/**
* @brief Register a service to the Celix framework.
*
* Note: Please use the celix_bundleContext_registerServiceAsync instead.
*
* @param ctx The bundle context
* @param svc the service object. Normally a pointer to a service struct (i.e. a struct with function pointers)
* @param serviceName the service name, cannot be NULL
* @param properties The meta properties associated with the service. The service registration will take ownership of the properties (i.e. no destroy needed)
* @return The serviceId (>=0) or -1 if the registration was unsuccessful.
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_registerService(celix_bundle_context_t *ctx, void *svc, const char* serviceName, celix_properties_t *properties);
/**
* @brief Register a service factory in the framework.
*
* The service factory will be called for every bundle requesting/de-requesting a service. This gives the provider the
* option to create bundle specific service instances.
*
* When a service is requested for a bundle the getService of the factory service will be called. This function must
* return a valid pointer to a service conform the registered service name or NULL.
* When a service in no longer needed for a bundle (e.g. ending the useService(s) calls or when a service tracker is stopped)
* the ungetService function of the service factory will be called.
*
* The service will be registered async on the Celix event loop thread. This means that service registration is (probably)
* not yet concluded when this function returns, but is added to the event loop.
* Use celix_bundleContext_waitForAsyncRegistration to synchronise with the
* actual service registration in the framework's service registry.
*
* @param ctx The bundle context
* @param factory The pointer to the factory service.
* @param serviceName The required service name of the services this factory will produce.
* @param properties The optional service factory properties. For a service consumer this will be seen as the service properties.
* @return The serviceId (>= 0) or < 0 if the registration was unsuccessful.
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_registerServiceFactoryAsync(celix_bundle_context_t *ctx, celix_service_factory_t *factory, const char* serviceName, celix_properties_t *props);
/**
* @brief Register a service factory in the framework.
*
* The service factory will be called for every bundle requesting/de-requesting a service. This gives the provider the
* option to create bundle specific service instances.
* Note: Please use the celix_bundleContext_registerServiceFactoryAsync instead.
*
* When a service is requested for a bundle the getService of the factory service will be called. This function must
* return a valid pointer to a service conform the registered service name or NULL.
* When a service in no longer needed for a bundle (e.g. ending the useService(s) calls or when a service tracker is stopped)
* the ungetService function of the service factory will be called.
*
* @param ctx The bundle context
* @param factory The pointer to the factory service.
* @param serviceName The required service name of the services this factory will produce.
* @param properties The optional service factory properties. For a service consumer this will be seen as the service properties.
* @return The serviceId (>= 0) or < 0 if the registration was unsuccessful.
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_registerServiceFactory(celix_bundle_context_t *ctx, celix_service_factory_t *factory, const char* serviceName, celix_properties_t *props);
/**
* @brief Service Registration Options when registering services to the Celix framework.
*/
typedef struct celix_service_registration_options {
/**
* @brief The service pointer.
*
* The actual pointer to the service. For C this is normally a pointer to a struct
* with function pointers, but theoretically this can be a pointer to anything (e.g. a pointer to a single function,
* or a pointer to a C++ interface implementation, or just a pointer to a data structure).
*
* The bundle is responsible to keep the service pointer valid as long as it is registered in the Celix framework.
*/
void *svc CELIX_OPTS_INIT;
/**
* @brief The service factory pointer.
*
* Note if the factory service is set, the svc field will not be used.
*
* The service factory will be called for every bundle requesting/de-requesting a service. This gives the provider the
* option to create bundle specific service instances.
*
* When a service is requested for a bundle the getService of the factory service will be called. This function must
* return a valid pointer to a service conform the registered service name or NULL.
* When a service in no longer needed for a bundle (e.g. ending the useService(s) calls when a service tacker is stopped)
* the ungetService function of the service factory will be called.
*
* The bundle is responsible to keep the service factory pointer valid as long as it is registered in the Celix framework.
*/
celix_service_factory_t *factory CELIX_OPTS_INIT;
/**
* @brief The required service name.
*
* This is used to identify the service. A fully qualified name with a namespace is
* advisable to prevent name collision. (e.g. EXAMPLE_PRESSURE_SENSOR).
*/
const char* serviceName CELIX_OPTS_INIT;
/**
* @brief The optional service properties.
*
* These contain meta information about the service in the
* form of string key/values. (e.g. the location of a pressure sensor: location=left-tire).
*
* When a service is registered the Celix framework will take ownership of the provided properties.
* If a registration fails, the properties will be destroyed (freed) by the Celix framework.
*/
celix_properties_t *properties CELIX_OPTS_INIT;
/**
* @brief The optional service version (in the form of <MAJOR>.<MINOR>.<MICRO>.<QUALIFIER>).
*
* If present consumer of the service can specific which service version range of
* a specific service they are interested in. Note that it is the responsibility of the users to ensure that
* service in those version range are compatible (binary of source). It is advisable to use semantic versioning
* for this.
*/
const char* serviceVersion CELIX_OPTS_INIT;
/**
* @brief Async data pointer for the async register callback.
*/
void *asyncData CELIX_OPTS_INIT;
/**
* @brief Async callback.
*
* Will be called after the a service is registered in the service registry using a async call.
* Will be called on the Celix event loop.
*
* If a asyns service registration is combined with a _sync_ service unregistration, it can happen that
* unregistration happens before the registration event is processed. In this case the asyncCallback
* will not be called.
*/
void (*asyncCallback)(void *data, long serviceId) CELIX_OPTS_INIT;
} celix_service_registration_options_t;
#ifndef __cplusplus
/*!
* @brief C Macro to create a empty celix_service_registration_options_t type.
*/
#define CELIX_EMPTY_SERVICE_REGISTRATION_OPTIONS { .svc = NULL, \
.factory = NULL, \
.serviceName = NULL, \
.properties = NULL, \
.serviceVersion = NULL, \
.asyncData = NULL, \
.asyncCallback = NULL }
#endif
/**
* @brief Register a service to the Celix framework using the provided service registration options.
*
* The service will be registered async on the Celix event loop thread. This means that service registration is (probably)
* not yet concluded when this function returns, but is added to the event loop..
* Use celix_bundleContext_waitForAsyncRegistration to synchronise with the
* actual service registration in the framework's service registry.
*
* @param ctx The bundle context
* @param opts The pointer to the registration options. The options are only in the during registration call.
* @return The serviceId (>= 0) or -1 if the registration was unsuccessful and -2 if the registration was cancelled (@see celix_bundleContext_reserveSvcId).
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_registerServiceWithOptionsAsync(celix_bundle_context_t *ctx, const celix_service_registration_options_t *opts);
/**
* @brief Register a service to the Celix framework using the provided service registration options.
*
* Note: Please use the celix_bundleContext_registerServiceAsyncWithOptions instead.
*
* @param ctx The bundle context
* @param opts The pointer to the registration options. The options are only in the during registration call.
* @return The serviceId (>= 0) or -1 if the registration was unsuccessful and -2 if the registration was cancelled (@see celix_bundleContext_reserveSvcId).
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_registerServiceWithOptions(celix_bundle_context_t *ctx, const celix_service_registration_options_t *opts);
/**
* @brief Waits til the async service registration for the provided serviceId is done.
*
* Silently ignore service ids < 0.
* Will directly return if there is no pending service registration for the provided service id.
*/
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_waitForAsyncRegistration(celix_bundle_context_t *ctx, long serviceId);
/**
* @brief Checks whether a service for the provided service id is registered in the service registry.
*
* Note return false if the service for the provided service id is still pending in the event loop.
* Silently ignore service ids < 0 (returns false).
*
* Returns true if the service is registered in the service registry.
*/
CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_isServiceRegistered(celix_bundle_context_t *ctx, long serviceId);
/**
* @brief Unregister the service or service factory with service id.
*
* The service will only be unregistered if the bundle of the bundle context is the owner of the service.
*
* Will log an error if service id is unknown. Will silently ignore services ids < 0.
*
* @param ctx The bundle context
* @param serviceId The service id
*/
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_unregisterService(celix_bundle_context_t *ctx, long serviceId);
/**
* @brief Service registration guard.
*/
typedef struct celix_service_registration_guard {
celix_bundle_context_t* ctx;
long svcId;
} celix_service_registration_guard_t;
/**
* @brief Initialize a a scope guard for an existing service registration.
* @param [in] ctx The bundle context associated with the service registration.
* @param [in] serviceId The service id.
* @return An initialized service registration guard.
*/
static CELIX_UNUSED inline celix_service_registration_guard_t
celix_serviceRegistrationGuard_init(celix_bundle_context_t* ctx, long serviceId) {
return (celix_service_registration_guard_t) { .ctx = ctx, .svcId = serviceId };
}
/**
* @brief Deinitialize a service registration guard.
* Will unregister the service if the service id is >= 0.
* @param [in] reg A service registration guard
*/
static CELIX_UNUSED inline void celix_serviceRegistrationGuard_deinit(celix_service_registration_guard_t* reg) {
if (reg->svcId >= 0) {
celix_bundleContext_unregisterService(reg->ctx, reg->svcId);
}
}
CELIX_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(celix_service_registration_guard_t, celix_serviceRegistrationGuard_deinit)
/**
* @brief Unregister the service or service factory with service id.
*
* The service will only be unregistered if the bundle of the bundle context is the owner of the service.
*
* The service will be umregistered async on the Celix event loop thread. This means that service unregistration is (probably)
* not yet concluded when this function returns. Use celix_bundleContext_waitForAsyncUnregistration to synchronise with the
* actual service unregistration in the framework's service registry.
*
* @param ctx The bundle context
* @param serviceId The service id
* @param doneData The data used on the doneCallback (if present)
* @param doneCallback If not NULL, this callback will be called when the unregisration is done. (will be called on the event loop thread)
*/
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_unregisterServiceAsync(celix_bundle_context_t *ctx, long serviceId, void* doneData, void (*doneCallback)(void* doneData));
/**
* @brief Waits til the async service unregistration for the provided serviceId is done.
*
* Silently ignore service < 0.
*/
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_waitForAsyncUnregistration(celix_bundle_context_t *ctx, long serviceId);
/**
* @brief Finds the highest ranking service and returns the service id.
*
* @param ctx The bundle context
* @param serviceName The required service name
* @return If found a valid service id (>= 0) if not found -1.
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_findService(celix_bundle_context_t *ctx, const char* serviceName);
/**
* @brief Finds the services with the provided service name and returns a list of the found service ids.
*
* @param ctx The bundle context
* @param serviceName The required service name
* @return A array list with as value a long int.
*/
CELIX_FRAMEWORK_EXPORT celix_array_list_t* celix_bundleContext_findServices(celix_bundle_context_t *ctx, const char* serviceName);
/**
* @brief Service filter options which can be used to query for certain services.
*/
typedef struct celix_service_filter_options {
/**
* @brief The service name.
*
* If NULL is used any services which matches the filter string will be tracked.
*/
const char* serviceName CELIX_OPTS_INIT;
/**
* @brief The optional version range.
*
* If service are registered with a service version this attribute can be used to
* only select service with a version in the version range.
* It uses the maven version range format, e.g. [1.0.0,2.0.0) or [1.1.1], etc.
*/
const char* versionRange CELIX_OPTS_INIT;
/**
* @brief LDAP filter to use for fine tuning the filtering, e.g. (|(location=middle)(location=front))
*
* The filter will be applied to all the user provided and framework provided service properties.
*/
const char* filter CELIX_OPTS_INIT;
} celix_service_filter_options_t;
#ifndef __cplusplus
/*!
* @brief C Macro to create a empty celix_service_filter_options_t type.
*/
#define CELIX_EMPTY_SERVICE_FILTER_OPTIONS {.serviceName = NULL, .versionRange = NULL, .filter = NULL}
#endif
/**
* @brief Finds the highest ranking service and returns the service id.
*
* @param ctx The bundle context
* @param opts The pointer to the filter options.
* @return If found a valid service id (>= 0) if not found -1.
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_findServiceWithOptions(celix_bundle_context_t* ctx,
const celix_service_filter_options_t* opts);
/**
* @brief Finds the services conform the provider filter options and returns a list of the found service ids.
*
* @param ctx The bundle context
* @param opts The pointer to the filter options.
* @return A array list with as value a long int.
*/
CELIX_FRAMEWORK_EXPORT celix_array_list_t*
celix_bundleContext_findServicesWithOptions(celix_bundle_context_t* ctx, const celix_service_filter_options_t* opts);
/**
* @brief Use the service with the provided service id using the provided callback. The Celix framework will ensure that
* the targeted service cannot be removed during the callback.
*
* @warning Cannot be called from the Celix event thread.
*
* @deprecated celix_bundleContext_useServiceWithId is deprecated and should be considered test utils functions. In
* operational code use celix_bundleContext_trackService* combined with celix_bundleContext_useTrackedService*
* functions instead.
*
* The Celix framework will ensure that the targeted service cannot be removed during the callback and the callback
* is called on the calling thread.
*
* This function will block until the callback is finished. As result it is possible to provide callback data from the
* stack.
*
* @param ctx The bundle context
* @param serviceId the service id.
* @param serviceName the service name of the service. Should match with the registered service name of the provided
* service id (sanity check)
* @param callbackHandle The data pointer, which will be used in the callbacks
* @param use The callback, which will be called when service is retrieved.
* @param bool returns true if a service was found and the callback was called.
*/
CELIX_FRAMEWORK_DEPRECATED_EXPORT bool celix_bundleContext_useServiceWithId(celix_bundle_context_t* ctx,
long serviceId,
const char* serviceName /*sanity check*/,
void* callbackHandle,
void (*use)(void* handle, void* svc));
/**
* @brief Use the highest ranking service with the provided service name using the provided callback.
*
* @warning Cannot be called from the Celix event thread.
*
* @deprecated celix_bundleContext_useService is deprecated and should be considered test utils functions. In
* operational code use celix_bundleContext_trackService* combined with celix_bundleContext_useTrackedService* functions
* instead.
*
* The Celix framework will ensure that the targeted service cannot be removed during the callback and the callback
* is called on the calling thread.
*
* The svc is should only be considered valid during the callback.
* If no service is found, the callback will not be invoked and this function will return false immediately.
*
* This function will block until the callback is finished. As result it is possible to provide callback data from the
* stack.
*
* @param ctx The bundle context
* @param serviceName the required service name.
* @param callbackHandle The data pointer, which will be used in the callbacks
* @param use The callback, which will be called when service is retrieved.
* @return True if a service was found and the callback was called.
*/
CELIX_FRAMEWORK_DEPRECATED_EXPORT bool celix_bundleContext_useService(
celix_bundle_context_t *ctx,
const char* serviceName,
void *callbackHandle,
void (*use)(void *handle, void *svc)
);
/**
* @brief Use the services with the provided service name using the provided callback.
*
* @warning Cannot be called from the Celix event thread.
*
* @deprecated celix_bundleContext_useServices is deprecated and should be considered test utils functions. In
* operational code use celix_bundleContext_trackService* combined with celix_bundleContext_useTrackedService* functions
* instead.
*
* The Celix framework will ensure that the targeted service cannot be removed during the callback and the callback
* is called on the calling thread.
*
* The svc is should only be considered valid during the callback.
* If no service is found, the callback will not be invoked and this function will return 0 immediately.
*
* This function will block until the callback is finished. As result it is possible to provide callback data from the
* stack.
*
* @param ctx The bundle context
* @param serviceName the required service name.
* @param callbackHandle The data pointer, which will be used in the callbacks
* @param use The callback, which will be called for every service found.
* @return The number of services found and called.
*/
CELIX_FRAMEWORK_DEPRECATED_EXPORT size_t celix_bundleContext_useServices(
celix_bundle_context_t *ctx,
const char* serviceName,
void *callbackHandle,
void (*use)(void *handle, void *svc)
);
/**
* @brief Service Use Options used to fine tune which services to use and which callbacks to use.
*
* If multiple use callbacks are set, all set callbacks will be called for every service found.
*/
typedef struct celix_service_use_options {
/**
* @brief The service filter options, used to setup the filter for the service to track.
*/
celix_service_filter_options_t filter CELIX_OPTS_INIT;
/**
* @brief An optional timeout (in seconds), if > 0 the use service call will block until the timeout is expired or
* when at least one service is found. Note that it will be ignored when use service on the event loop.
* Default (0)
*
* Only applicable when using the celix_bundleContext_useService or
* celix_bundleContext_useServiceWithOptions (use single service calls).
*/
double waitTimeoutInSeconds CELIX_OPTS_INIT;
/**
* @brief The optional callback pointer used in all the provided callback function (use, useWithProperties, and
* useWithOwner).
*/
void* callbackHandle CELIX_OPTS_INIT;
/**
* @brief The optional use callback will be called when for every services found conform the service filter options
* - in case of findServices - or only for the highest ranking service found - in case of findService -.
*
* @param handle The callbackHandle pointer as provided in the service tracker options.
* @param svc The service pointer of the highest ranking service.
*/
void (*use)(void* handle, void* svc) CELIX_OPTS_INIT;
/**
* @brief The optional useWithProperties callback is handled as the use callback, but with the addition that the
* service properties will also be provided to the callback.
*/
void (*useWithProperties)(void* handle, void* svc, const celix_properties_t* props) CELIX_OPTS_INIT;
/**
* @brief The optional useWithOwner callback is handled as the yse callback, but with the addition that the service
* properties and the bundle owning the service will also be provided to the callback.
*/
void (*useWithOwner)(void* handle, void* svc, const celix_properties_t* props, const celix_bundle_t* svcOwner)
CELIX_OPTS_INIT;
} celix_service_use_options_t;
#ifndef __cplusplus
/*!
* @brief C Macro to create a empty celix_service_use_options_t type.
*/
#define CELIX_EMPTY_SERVICE_USE_OPTIONS {.filter.serviceName = NULL, \
.filter.versionRange = NULL, \
.filter.filter = NULL, \
.waitTimeoutInSeconds = 0.0F, \
.callbackHandle = NULL, \
.use = NULL, \
.useWithProperties = NULL, \
.useWithOwner = NULL}
#endif
/**
* @brief Use the highest ranking service satisfying the provided service filter options using the provided callback.
*
* @note celix_bundleContext_useService should be considered a test util function.
* For production code, use celix_bundleContext_trackService* combined with celix_bundleContext_useTrackedService*
* functions instead.
*
* The Celix framework will ensure that the targeted service cannot be removed during the callback.
*
* The svc is should only be considered valid during the callback.
* If no service is found the callback will not be invoked. In such cases, if a non-zero waitTimeoutInSeconds is specified in opts,
* this function will block until the timeout is expired or when at least one service is found, otherwise it will return false immediately.
*
* This function will block until the callback is finished. As result it is possible to provide callback data from the
* stack.
*
* @param ctx The bundle context.
* @param opts The required options. Note that the serviceName is required.
* @return True if a service was found.
*/
CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_useServiceWithOptions(
celix_bundle_context_t *ctx,
const celix_service_use_options_t *opts);
/**
* @brief Use the services with the provided service filter options using the provided callback.
*
* @note celix_bundleContext_useService should be considered test utils functions.
* For production code, use celix_bundleContext_trackService* combined with celix_bundleContext_useTrackedService*
* functions instead.
*
* The Celix framework will ensure that the targeted service cannot be removed during the callback.
*
* The svc is should only be considered valid during the callback.
* If no service is found, the callback will not be invoked and this function will return 0 immediately.
* Note that waitTimeoutInSeconds in opts has no effect.
*
* This function will block until the callback is finished. As result it is possible to provide callback data from the
* stack.
*
* @param ctx The bundle context.
* @param opts The required options. Note that the serviceName is required.
* @return The number of services found and called
*/
CELIX_FRAMEWORK_EXPORT size_t celix_bundleContext_useServicesWithOptions(
celix_bundle_context_t *ctx,
const celix_service_use_options_t *opts);
/**
* @brief Track services with the provided serviceName.
*
* The service tracker will be created async on the Celix event loop thread. This means that the function can return
* before the tracker is created.
*
* @param ctx The bundle context.
* @param serviceName The required service name to track
* If NULL is all service are tracked.
* @return the tracker id (>=0) or < 0 if unsuccessful.
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_trackServicesAsync(celix_bundle_context_t* ctx,
const char* serviceName);
/**
* @brief Track services with the provided serviceName.
*
* Note: If possible, use the celix_bundleContext_trackServicesAsync instead.
*
* @param ctx The bundle context.
* @param serviceName The required service name to track
* If NULL is all service are tracked.
* @return the tracker id (>=0) or < 0 if unsuccessful.
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_trackServices(celix_bundle_context_t* ctx, const char* serviceName);
/**
* @brief Service Tracker Options used to fine tune which services to track and the callback to be used for the tracked
* services.
*/
typedef struct celix_service_tracking_options {
/**
* @brief The service filter options, used to setup the filter for the service to track.
*/
celix_service_filter_options_t filter CELIX_OPTS_INIT;
/**
* @brief The optional callback pointer used in all the provided callback function (set, add, remove,
* setWithProperties, etc).
*/
void* callbackHandle CELIX_OPTS_INIT;
/**
* @brief The optional set callback will be called when a new highest ranking service is available conform the
* provided service filter options.
* @param handle The callbackHandle pointer as provided in the service tracker options.
* @param svc The service pointer of the highest ranking service.
*/
void (*set)(void* handle, void* svc) CELIX_OPTS_INIT;
/**
* @brief The optional setWithProperties callback is handled as the set callback, but with the addition that the
* service properties will also be provided to the callback.
*/
void (*setWithProperties)(void* handle,
void* svc,
const celix_properties_t* props) CELIX_OPTS_INIT; // highest ranking
/**
* @brief The optional setWithOwner callback is handled as the set callback, but with the addition that the service
* properties and the bundle owning the service will also be provided to the callback.
*/
void (*setWithOwner)(void* handle, void* svc, const celix_properties_t* props, const celix_bundle_t* svcOwner)
CELIX_OPTS_INIT;
/**
* @brief The optional add callback will be called for every current and future service found conform the provided
* service filter options as long as the tracker is active.
* @param handle The callbackHandle pointer as provided in the service tracker options.
* @param svc The service pointer of a service matching the provided service filter options.
*/
void (*add)(void* handle, void* svc) CELIX_OPTS_INIT;
/**
* @brief The optional addWithProperties callback is handled as the add callback, but with the addition that the
* service properties will also be provided to the callback.
*/
void (*addWithProperties)(void* handle, void* svc, const celix_properties_t* props) CELIX_OPTS_INIT;
/**
* @brief The optional addWithOwner callback is handled as the add callback, but with the addition that the service
* properties and the bundle owning the service will also be provided to the callback.
*/
void (*addWithOwner)(void* handle, void* svc, const celix_properties_t* props, const celix_bundle_t* svcOwner)
CELIX_OPTS_INIT;
/**
* @brief The optional remove callback will be called for every service conform the provided service filter options
* that is unregistered. When the remove call is finished the removed services should be considered invalid. This
* means that the callback provider should ensure that the removed service is not in use or going to be used after
* the remove callback is finished.
*
* @param handle The callbackHandle pointer as provided in the service tracker options.
* @param svc The service pointer of a service matching the provided service filter options.
*/
void (*remove)(void* handle, void* svc) CELIX_OPTS_INIT;
/**
* @brief The optional removeWithProperties callback is handled as the remove callback, but with the addition that
* the service properties will also be provided to the callback.
*/
void (*removeWithProperties)(void* handle, void* svc, const celix_properties_t* props) CELIX_OPTS_INIT;
/**
* @brief The optional removeWithOwner callback is handled as the remove callback, but with the addition that the
* service properties and the bundle owning the service will also be provided to the callback.
*/
void (*removeWithOwner)(void* handle, void* svc, const celix_properties_t* props, const celix_bundle_t* svcOwner)
CELIX_OPTS_INIT;
/**
* @brief Data for the trackerCreatedCallback.
*/
void* trackerCreatedCallbackData CELIX_OPTS_INIT;
/**
* @brief The callback called when the tracker has ben created (and is active) when using a async call.
*
* If a asyns track service is combined with a _sync_ stop tracker, it can happen that
* "stop tracker" happens before the "create tracker" event is processed. In this case the asyncCallback
* will not be called.
*/
void (*trackerCreatedCallback)(void* trackerCreatedCallbackData) CELIX_OPTS_INIT;
} celix_service_tracking_options_t;
#ifndef __cplusplus
/*!
* @brief C Macro to create a empty celix_service_tracking_options_t type.
*/
#define CELIX_EMPTY_SERVICE_TRACKING_OPTIONS { .filter.serviceName = NULL, \
.filter.versionRange = NULL, \
.filter.filter = NULL, \
.callbackHandle = NULL, \
.set = NULL, \
.add = NULL, \
.remove = NULL, \
.setWithProperties = NULL, \
.addWithProperties = NULL, \
.removeWithProperties = NULL, \
.setWithOwner = NULL, \
.addWithOwner = NULL, \
.removeWithOwner = NULL, \
.trackerCreatedCallbackData = NULL, \
.trackerCreatedCallback = NULL }
#endif
/**
* @brief Tracks services using the provided tracker options.
*
* The tracker options are only using during this call and can safely be freed/reused after this call returns.
*
* The service tracker will be created async on the Celix event loop thread. This means that the function can return
* before the tracker is created.
*
* @param ctx The bundle context.
* @param opts The pointer to the tracker options.
* @return the tracker id (>=0) or < 0 if unsuccessful.
*/
CELIX_FRAMEWORK_EXPORT long
celix_bundleContext_trackServicesWithOptionsAsync(celix_bundle_context_t* ctx,
const celix_service_tracking_options_t* opts);
/**
* @brief Tracks services using the provided tracker options.
*
* The tracker options are only using during this call and can safely be freed/reused after this call returns.
* Note: Please use the celix_bundleContext_registerServiceFactoryAsync instead.
*
* @param ctx The bundle context.
* @param opts The pointer to the tracker options.
* @return the tracker id (>=0) or < 0 if unsuccessful.
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_trackServicesWithOptions(celix_bundle_context_t* ctx,
const celix_service_tracking_options_t* opts);
/**
* @brief Use the highest-ranking service tracked by the specified tracker id by invoking the provided use callback.
*
* The callback is executed on the thread that invokes this function, and the function waits until the use callback
* is completed before returning.
*
* A tracker id less than 0 is ignored without action. An invalid (non-existent) tracker id of 0 or greater results
* in a logged error, and the function returns false.
*
* @param[in] ctx The bundle context.
* @param[in] trackerId The service tracker id.
* @param[in] callbackHandle An optional pointer to a user-defined context or data structure, passed to the provided use
* callback function.
* @param[in] use The use callback invoked for highest-ranking service tracked.
* @return True if a service was found and the provided use callback was executed; false if the tracker is not yet
* active (asynchronous tracker creation), the are no matching services tracked or if the tracker id is invalid.
*/
CELIX_FRAMEWORK_EXPORT
bool celix_bundleContext_useTrackedService(celix_bundle_context_t* ctx,
long trackerId,
void* callbackHandle,
void (*use)(void* handle, void* svc));
/**
* @brief Use the services tracked by the specified tracker id by invoking the provided use callback.
*
* The callback is executed on the thread that invokes this function, and the function waits until the use callback,
* called for all tracked. services, is completed before returning.
*
* A tracker id less than 0 is ignored without action. An invalid (non-existent) tracker id of 0 or greater results
* in a logged error, and the function returns 0.
*
* @param[in] ctx The bundle context.
* @param[in] trackerId The service tracker id.
* @param[in] callbackHandle An optional pointer to a user-defined context or data structure, passed to the provided use
* callback function.
* @param[in] use The use callback invoked for all tracked services.
* @return The number of services found. Returns 0 if the tracker
* is not yet active (asynchronous tracker creation), 0 services are found or if the tracker id is invalid.
*/
CELIX_FRAMEWORK_EXPORT
size_t celix_bundleContext_useTrackedServices(celix_bundle_context_t* ctx,
long trackerId,
void* callbackHandle,
void (*use)(void* handle, void* svc));
/**
* @brief Options for using services tracked by a service tracker. These options enable specifying callbacks
* to be invoked for each tracked service that matches the selection criteria. If multiple callbacks are provided,
* each will be called for every matching service.
*/
typedef struct celix_tracked_service_use_options {
/**
* @brief An optional pointer to a user-defined context or data structure, passed to all specified callback
* functions (use, useWithProperties, and useWithOwner).
*
* Default value: NULL.
*/
void* callbackHandle CELIX_OPTS_INIT;
/**
* @brief An optional callback invoked for each tracked service that matches the selection criteria.
* This callback does not receive the service's properties or information about the service's owning bundle.
*
* The svc pointer is only valid during the callback.
*
* Default value: NULL.
*/
void (*use)(void* handle, void* svc) CELIX_OPTS_INIT;
/**
* @brief An optional callback invoked for each tracked service that matches the selection criteria,
* providing the service's properties. This enables the callback to utilize additional metadata associated
* with the service.
*
* The svc and props pointers are only valid during the callback.
*
* Default value: NULL.
*/
void (*useWithProperties)(void* handle, void* svc, const celix_properties_t* props) CELIX_OPTS_INIT;
/**
* @brief An optional callback invoked for each tracked service that matches the selection criteria,
* along with the service's properties and the service's owning bundle.
*
* The svc, props, and svcOwner pointers are only valid during the callback.
*
* Default value: NULL.
*/
void (*useWithOwner)(void* handle, void* svc, const celix_properties_t* props, const celix_bundle_t* svcOwner)
CELIX_OPTS_INIT;
} celix_tracked_service_use_options_t;
#ifndef __cplusplus
/**
* @brief Macro to initialize a celix_tracked_service_use_options_t structure with default values.
*/
#define CELIX_EMPTY_TRACKER_SERVICE_USE_OPTIONS \
{ .callbackHandle = NULL, .use = NULL, .useWithProperties = NULL, .useWithOwner = NULL }
#endif
/**
* @brief Use the highest-ranking service tracked by the specified tracker id by invoking the callbacks
* specified in the provided options.
*
* The callbacks are executed on the thread that invokes this function, and the function waits until all callbacks
* are completed before returning.
*
* A tracker id less than 0 is ignored without action. An invalid (non-existent) tracker id of 0 or greater results
* in a logged error, and the function returns false.
*
* @param[in] ctx The bundle context.
* @param[in] trackerId The service tracker id.
* @param[in] opts The service use options containing callbacks and additional configurations.
* @return True if a service was found and the specified callbacks were executed; false if the tracker is not yet
* active (asynchronous tracker creation), the are no matching services tracked or if the tracker id is invalid.
*/
CELIX_FRAMEWORK_EXPORT
bool celix_bundleContext_useTrackedServiceWithOptions(celix_bundle_context_t* ctx,
long trackerId,
const celix_tracked_service_use_options_t* opts);
/**
* @brief Use the services tracked by the specified tracker id by invoking the callbacks specified in the
* provided options for each matching service.
*
* The callbacks are executed on the thread that invokes this function, and the function waits until all callbacks
* for all found services are completed before returning.
*
* A tracker id less than 0 is ignored without action. An invalid (non-existent) tracker id of 0 or greater results
* in a logged error, and the function returns 0.
*
* @param[in] ctx The bundle context.
* @param[in] trackerId The service tracker id.
* @param[in] opts The service use options containing callbacks and additional configurations.
* @return The number of services found and for which the specified callbacks were executed. Returns 0 if the tracker
* is not yet active (asynchronous tracker creation), 0 services are found or if the tracker id is invalid.
*/
CELIX_FRAMEWORK_EXPORT
size_t celix_bundleContext_useTrackedServicesWithOptions(celix_bundle_context_t* ctx,
long trackerId,
const celix_tracked_service_use_options_t* opts);
/**
* @brief Get the number of tracked services for the provided tracker id.
*
* Silently ignore tracker ids < 0 and invalid tracker ids.
*
* @param[in] ctx The bundle context.
* @param[in] trackerId The tracker id.
* @return The number of tracked services or 0 if the tracker id is unknown or < 0.
*/
CELIX_FRAMEWORK_EXPORT
size_t celix_bundleContext_getTrackedServiceCount(celix_bundle_context_t *ctx, long trackerId);
/**
* @brief Get the service name of the tracked services for the provided tracker id.
*
* Silently ignore tracker ids < 0 and invalid tracker ids.
*
* @param ctx The bundle context.
* @param trackerId The tracker id.
* @return The service name of the tracked services or NULL if the tracker id is unknown or < 0.
*/
CELIX_FRAMEWORK_EXPORT
const char* celix_bundleContext_getTrackedServiceName(celix_bundle_context_t *ctx, long trackerId);
/**
* @brief Get the service filter of the tracked services for the provided tracker id.
*
* The returned filter is the combination of the service name and the filter from the provided service filter options.
* For example serviceName="foo" and filter="(location=middle)" will result in a filter of
* "(&(objectClass=foo)(location=middle))"
*
* Silently ignore tracker ids < 0 and invalid tracker ids.
*
* @param ctx The bundle context.
* @param trackerId The tracker id.
* @return The service filter of the tracked services or NULL if the tracker id is unknown or < 0.
*/
CELIX_FRAMEWORK_EXPORT
const char* celix_bundleContext_getTrackedServiceFilter(celix_bundle_context_t* ctx, long trackerId);
/**
* @brief Stop the tracker with the provided track id.
*
* Could be a service tracker, bundle tracker or service tracker tracker.
* Only works for the trackers owned by the bundle of the bundle context.
*
* The service tracker will be destroyed async on the Celix event loop thread. This means that the function can return
* before the tracker is destroyed.
*
* if the doneCallback is not NULL, this will be called when the destruction of the service tracker is done.
* (will be called on the event loop thread).
*
* Will log a error if the provided tracker id is unknown. Will silently ignore trackerId < 0.
*/
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_stopTrackerAsync(
celix_bundle_context_t *ctx,
long trackerId,
void *doneCallbackData,
void (*doneCallback)(void* doneCallbackData));
/**
* @brief Wait, if able, for (async) creation of a tracker.
*
* Will silently ignore trackerId < 0 and log an error if the tracker id is unknown.
* If called on the Apache Celix event loop thread, the function will log a warning and return immediately.
*
* @param[in] ctx The bundle context.
* @param[in] trackerId The tracker id.
*/
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_waitForAsyncTracker(celix_bundle_context_t *ctx, long trackerId);
/**
* @brief Wait, if able, for (async) stopping of tracking.
*
* Will silently ignore trackerId < 0 and log an error if the tracker id is unknown.
* If called on the Apache Celix event loop thread, the function will log a warning and return immediately.
*
* @param[in] ctx The bundle context.
* @param[in] trackerId The tracker id.
*/
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_waitForAsyncStopTracker(celix_bundle_context_t *ctx, long trackerId);
/**
* @brief Stop the tracker with the provided track id.
*
* Could be a service tracker, bundle tracker or service tracker tracker.
* Only works for the trackers owned by the bundle of the bundle context.
* Note: Please use the celix_bundleContext_stopTrackerAsync instead.
*
* Will log a error if the provided tracker id is unknown. Will silently ignore trackerId < 0.
*/
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_stopTracker(celix_bundle_context_t *ctx, long trackerId);
/**
* @brief Returns true if the provided tracker id is a tracker id for an existing tracker for the provided bundle
* context.
* @param ctx The bundle context.
* @param trackerId The tracker id.
* @return True if the tracker id is valid.
*/
CELIX_FRAMEWORK_EXPORT
bool celix_bundleContext_isValidTrackerId(celix_bundle_context_t* ctx, long trackerId);
/**
* @brief Tracker guard.
*/
typedef struct celix_tracker_guard {
celix_bundle_context_t* ctx;
long trackerId;
} celix_tracker_guard_t;
/**
* @brief Initialize a scope guard for an existing bundle, service or meta tracker.
* @param [in] ctx The bundle context associated with the service registration.
* @param [in] trackerId The tracker id.
* @return An initialized service registration guard.
*/
static CELIX_UNUSED inline celix_tracker_guard_t
celix_trackerGuard_init(celix_bundle_context_t* ctx, long trackerId) {
return (celix_tracker_guard_t) { .ctx = ctx, .trackerId = trackerId };
}
/**
* @brief De-initialize a tracker guard.
* Will stop the tracker if the tracker id is >= 0.
* @param [in] trackerGuard A tracker guard
*/
static CELIX_UNUSED inline void celix_trackerGuard_deinit(celix_tracker_guard_t* trackerGuard) {
if (trackerGuard->trackerId >= 0) {
celix_bundleContext_stopTracker(trackerGuard->ctx, trackerGuard->trackerId);
}
}
CELIX_DEFINE_AUTO_CLEANUP_CLEAR_FUNC(celix_tracker_guard_t, celix_trackerGuard_deinit)
/**
* @brief List the installed and started bundle ids.
* The bundle ids does not include the framework bundle (bundle id CELIX_FRAMEWORK_BUNDLE_ID).
*
* @param ctx The bundle context.
* @return A array with bundle ids (long). The caller is responsible for destroying the array.
*/
CELIX_FRAMEWORK_EXPORT celix_array_list_t* celix_bundleContext_listBundles(celix_bundle_context_t *ctx);
/**
* @brief List the installed bundle ids.
* The bundle ids does not include the framework bundle (bundle id CELIX_FRAMEWORK_BUNDLE_ID).
*
* @param ctx The bundle context.
* @return A array with bundle ids (long). The caller is responsible for destroying the array.
*/
CELIX_FRAMEWORK_EXPORT celix_array_list_t* celix_bundleContext_listInstalledBundles(celix_bundle_context_t *ctx);
/**
* @brief Check whether a bundle is installed.
* @param ctx The bundle context.
* @param bndId The bundle id to check
* @return true if the bundle is installed.
*/
CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_isBundleInstalled(celix_bundle_context_t *ctx, long bndId);
/**
* @brief Check whether the bundle is active.
* @param ctx The bundle context.
* @param bndId The bundle id to check
* @return true if the bundle is installed and active.
*/
CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_isBundleActive(celix_bundle_context_t *ctx, long bndId);
/**
* @brief Install and optional start a bundle.
* Will silently ignore bundle ids < 0.
*
* If this function is called on the Celix event thread and autoStart is true,
* the actual starting of the bundle will be done async and on a separate thread.
* If this function is called from a different thread than the Celix event thread and the autoStart is true,
* then the function will return after the bundle is started.
*
* @param ctx The bundle context
* @param bundleUrl The bundle location to the bundle zip file.
* @param autoStart If the bundle should also be started.
* @return the bundleId (>= 0) or < 0 if the bundle could not be installed and possibly started.
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_installBundle(celix_bundle_context_t *ctx, const char* bundleUrl, bool autoStart);
/**
* @brief Uninstall the bundle with the provided bundle id. If needed the bundle will be stopped first.
* Will silently ignore bundle ids < 0.
*
* If this function is called on the Celix event thread, the actual stopping of the bundle will be done async and
* on a separate thread.
* If this function is called from a different thread than the Celix event thread, then the function will return after
* the bundle is stopped.
*
* @param ctx The bundle context
* @param bndId The bundle id to uninstall.
* @return true if the bundle is correctly uninstalled. False if not.
*/
CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_uninstallBundle(celix_bundle_context_t *ctx, long bndId);
/**
* @brief Stop the bundle with the provided bundle id.
* Will silently ignore bundle ids < 0.
*
* If this function is called on the Celix event thread, the actual stopping of the bundle will be done async and
* on a separate thread.
* If this function is called from a different thread than the Celix event thread, then the function will return after
* the bundle is stopped.
*
* @param ctx The bundle context
* @param bndId The bundle id to stop.
* @return true if the bundle is found & correctly stop. False if not.
*/
CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_stopBundle(celix_bundle_context_t *ctx, long bndId);
/**
* @brief Start the bundle with the provided bundle id.
* Will silently ignore bundle ids < 0.
*
* If this function is called on the Celix event thread, the actual starting of the bundle will be done async and
* on a separate thread.
* If this function is called from a different thread than the Celix event thread, then the function will return after
* the bundle is started.
*
* @param ctx The bundle context
* @param bndId The bundle id to start.
* @return true if the bundle is found & correctly started. False if not.
*/
CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_startBundle(celix_bundle_context_t *ctx, long bndId);
/**
* @brief Update the bundle with the provided bundle id.
*
* This will do the following:
* - unload the bundle with the specified bundle id;
* - reload the bundle from the specified location with the specified bundle id;
* - start the bundle, if it was previously active.
*
* Will silently ignore bundle ids < 0.
*
* Note if specified bundle location already exists in the bundle cache but with a different bundle id, the bundle
* will NOT be reinstalled, and the update is cancelled.
*
* If this function is called on the Celix event thread, the actual updating of the bundle will be done async and
* on a separate thread.
* If this function is called from a different thread than the Celix event thread, then the function will
* return after the bundle update is completed.
*
* @param ctx The bundle context
* @param bndId The bundle id to update.
* @param updatedBundleUrl The optional updated bundle url to the bundle zip file.
* If NULL, the existing bundle url from the bundle cache will be used, and the cache will only be updated if the zip file is newer.
* @return true if the bundle is found & correctly started. False if not.
*/
CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_updateBundle(celix_bundle_context_t *ctx, long bndId, const char* updatedBundleUrl);
/**
* @brief Returns the bundle symbolic name for the provided bundle id.
* The caller is owner of the return string.
*
* @param ctx The bundle context
* @param bndId The bundle id to retrieve the symbolic name for.
* @return The bundle symbolic name or NULL if the bundle for the provided bundle id does not exist.
*/
CELIX_FRAMEWORK_EXPORT char* celix_bundleContext_getBundleSymbolicName(celix_bundle_context_t *ctx, long bndId);
/**
* @brief Track bundles.
*
* The add bundle callback will also be called for already installed bundles.
*
* The bundle tracker will be created async on the Celix event loop thread. This means that the function can return
* before the tracker is created.
*
* @param ctx The bundle context.
* @param callbackHandle The data pointer, which will be used in the callbacks
* @param add The callback which will be called for started bundles.
* @param remove The callback which will be called when bundles are stopped.
* @return The bundle tracker id or < 0 if unsuccessful.
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_trackBundlesAsync(
celix_bundle_context_t *ctx,
void* callbackHandle,
void (*onStarted)(void* handle, const celix_bundle_t *bundle),
void (*onStopped)(void *handle, const celix_bundle_t *bundle)
);
/**
* @brief Track bundles.
*
* The add bundle callback will also be called for already installed bundles.
*
* Note: please use celix_bundleContext_trackBundlesAsync instead.
*
* @param ctx The bundle context.
* @param callbackHandle The data pointer, which will be used in the callbacks
* @param add The callback which will be called for started bundles.
* @param remove The callback which will be called when bundles are stopped.
* @return The bundle tracker id or < 0 if unsuccessful.
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_trackBundles(
celix_bundle_context_t *ctx,
void* callbackHandle,
void (*onStarted)(void* handle, const celix_bundle_t *bundle),
void (*onStopped)(void *handle, const celix_bundle_t *bundle)
);
/**
* @brief The Service Bundle Tracking options can be used to fine tune the requested bundle tracker options.
*/
typedef struct celix_bundle_tracker_options {
/**
* @brief The optional callback pointer used in all the provided callback function (set, add, remove, setWithProperties, etc).
*/
void* callbackHandle CELIX_OPTS_INIT;
/**
* @brief Tracker callback when a bundle is installed.
* @param handle The handle, contains the value of the callbackHandle.
* @param bundle The bundle which has been installed.
* The bundle pointer is only guaranteed to be valid during the callback.
*/
void (*onInstalled)(void *handle, const celix_bundle_t *bundle) CELIX_OPTS_INIT;
/**
* @brief Tracker callback when a bundle is started.
* @param handle The handle, contains the value of the callbackHandle.
* @param bundle The bundle which has been started.
* The bundle pointer is only guaranteed to be valid during the callback.
*/
void (*onStarted)(void *handle, const celix_bundle_t *bundle) CELIX_OPTS_INIT;
/**
* @brief Tracker callback when a bundle is stopped.
* @param handle The handle, contains the value of the callbackHandle.
* @param bundle The bundle which has been stopped.
* The bundle pointer is only guaranteed to be valid during the callback.
*/
void (*onStopped)(void *handle, const celix_bundle_t *bundle) CELIX_OPTS_INIT;
/**
*
* @param handle The handle, contains the value of the callbackHandle.
* @param event The bundle event. Is only valid during the callback.
*/
void (*onBundleEvent)(void *handle, const celix_bundle_event_t *event) CELIX_OPTS_INIT;
/**
* @brief Default the framework bundle (bundle id 0) will not trigger the callbacks.
* This is done, because the framework bundle is a special bundle which is generally not needed in the callbacks.
*/
bool includeFrameworkBundle CELIX_OPTS_INIT;
/**
* @brief Data for the trackerCreatedCallback.
*/
void *trackerCreatedCallbackData CELIX_OPTS_INIT;
/**
* @brief The callback called when the tracker has ben created (and is active) when using the
* track bundles ascync calls.
*
* If a asyns track service is combined with a _sync_ stop tracker, it can happen that
* "stop tracker" happens before the "create tracker" event is processed. In this case the asyncCallback
* will not be called.
*/
void (*trackerCreatedCallback)(void *trackerCreatedCallbackData) CELIX_OPTS_INIT;
} celix_bundle_tracking_options_t;
#ifndef __cplusplus
/*!
* @brief C Macro to create a empty celix_service_filter_options_t type.
*/
#define CELIX_EMPTY_BUNDLE_TRACKING_OPTIONS {.callbackHandle = NULL, .onInstalled = NULL, .onStarted = NULL, .onStopped = NULL, .onBundleEvent = NULL, .includeFrameworkBundle = false, .trackerCreatedCallbackData = NULL, .trackerCreatedCallback = NULL}
#endif
/**
* @brief Tracks bundles using the provided bundle tracker options.
*
* The tracker options are only using during this call and can safely be freed/reused after this call returns.
* (i.e. can be on the stack)
*
* The bundle tracker will be created async on the Celix event loop thread. This means that the function can return
* before the tracker is created.
*
* @param ctx The bundle context.
* @param opts The pointer to the bundle tracker options.
* @return The bundle tracker id (>=0) or < 0 if unsuccessful.
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_trackBundlesWithOptionsAsync(
celix_bundle_context_t *ctx,
const celix_bundle_tracking_options_t *opts
);
/**
* @brief Tracks bundles using the provided bundle tracker options.
*
* The tracker options are only using during this call and can safely be freed/reused after this call returns.
* (i.e. can be on the stack)
*
* Note: please use celix_bundleContext_trackBundlesWithOptionsAsync instead;
*
* @param ctx The bundle context.
* @param opts The pointer to the bundle tracker options.
* @return The bundle tracker id (>=0) or < 0 if unsuccessful.
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_trackBundlesWithOptions(
celix_bundle_context_t *ctx,
const celix_bundle_tracking_options_t *opts
);
/**
* @brief Use the bundle with the provided bundle id.
*
* The provided callback will be called if the bundle is found (installed).
* Call with CELIX_FRAMEWORK_BUNDLE_ID as bundleId to use the framework bundle.
*
* @param ctx The bundle context.
* @param bundleId The bundle id.
* @param callbackHandle The data pointer, which will be used in the callbacks
* @param use The callback which will be called for the currently started bundles.
* The bundle pointers are only guaranteed to be valid during the callback.
* @return Returns true if the bundle is found and the callback is called.
*/
CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_useBundle(
celix_bundle_context_t *ctx,
long bundleId,
void *callbackHandle,
void (*use)(void *handle, const celix_bundle_t *bundle));
/**
* @brief Use the currently installed bundles.
*
* The provided callback will be called for all the currently installed bundles, expect the framework bundle.
*
* @param ctx The bundle context.
* @param callbackHandle The data pointer, which will be used in the callbacks
* @param use The callback which will be called for the currently started bundles.
* The bundle pointers are only guaranteed to be valid during the callback.
* @return The number of times the use callback is called (nr of installed bundles).
*/
CELIX_FRAMEWORK_EXPORT size_t celix_bundleContext_useBundles(
celix_bundle_context_t *ctx,
void *callbackHandle,
void (*use)(void *handle, const celix_bundle_t *bundle));
/**
* @brief Service Tracker Info provided to the service tracker tracker callbacks.
*/
typedef struct celix_service_tracker_info {
/**
* @brief The parsed service filter, e.g. parsed "(&(objectClass=example_calc)(meta.info=foo))"
*/
celix_filter_t *filter;
/**
* @brief The service name filter attribute parsed from the service filter (i.e. the value of the objectClass attribute key)
*/
const char* serviceName;
/**
* @brief Bundle id of the owner of the service tracker.
*/
long bundleId;
} celix_service_tracker_info_t;
/**
* @brief Track the service tracker targeting the provided service name.
*
* This can be used to track if there is an interest in a certain service and ad-hoc act on that interest.
*
* Note that the celix_service_tracker_info_t pointer in the trackerAdd/trackerRemove callbacks are only valid during
* the callback.
*
* This tracker can be stopped with the celix_bundleContext_stopTracker function.
*
* The service tracker tracker will be created async on the Celix event loop thread. This means that the function can return
* before the tracker is created.
*
* @param ctx The bundle context
* @param serviceName The target service name for the service tracker to track.
* If NULL is provided, add/remove callbacks will be called for all service trackers in the framework.
* @param callbackHandle The callback handle which will be provided as handle in the trackerAdd and trackerRemove callback.
* @param trackerAdd Called when a service tracker is added, which tracks the provided service name. Will also be called
* for all existing service tracker when this tracker is started.
* @param trackerRemove Called when a service tracker is removed, which tracks the provided service name
* @param doneCallbackData call back data argument provided to the done callback function.
* @param doneCallback If not NULL will be called when the service tracker tracker is created.
* If a asyns track service is combined with a _sync_ stop tracker, it can happen that
* "stop tracker" happens before the "create tracker" event is processed.
* In this case the doneCallback will not be called.
* @return The tracker id or <0 if something went wrong (will log an error).
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_trackServiceTrackersAsync(
celix_bundle_context_t *ctx,
const char* serviceName,
void *callbackHandle,
void (*trackerAdd)(void *handle, const celix_service_tracker_info_t *info),
void (*trackerRemove)(void *handle, const celix_service_tracker_info_t *info),
void *doneCallbackData,
void (*doneCallback)(void* doneCallbackData));
/**
* @brief Track the service tracker targeting the provided service name.
*
* This can be used to track if there is an interest in a certain service and ad-hoc act on that interest.
*
* Note that the celix_service_tracker_info_t pointer in the trackerAdd/trackerRemove callbacks are only valid during
* the callback.
*
* Note: Please use celix_bundleContext_trackServiceTrackersAsync instead.
*
* This tracker can be stopped with the celix_bundleContext_stopTracker function.
*
* @param ctx The bundle context.
* @param serviceName The target service name for the service tracker to track.
* If NULL is provided, add/remove callbacks will be called for all service trackers in the framework.
* @param callbackHandle The callback handle which will be provided as handle in the trackerAdd and trackerRemove callback.
* @param trackerAdd Called when a service tracker is added, which tracks the provided service name. Will also be called
* for all existing service tracker when this tracker is started.
* @param trackerRemove Called when a service tracker is removed, which tracks the provided service name
* @return The tracker id or <0 if something went wrong (will log an error).
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_trackServiceTrackers(
celix_bundle_context_t *ctx,
const char* serviceName,
void *callbackHandle,
void (*trackerAdd)(void *handle, const celix_service_tracker_info_t *info),
void (*trackerRemove)(void *handle, const celix_service_tracker_info_t *info));
/**
* @brief Gets the dependency manager for this bundle context.
*
* @return the dependency manager or NULL if unsuccessful.
*/
CELIX_FRAMEWORK_EXPORT celix_dependency_manager_t* celix_bundleContext_getDependencyManager(celix_bundle_context_t *ctx);
/**
* @brief Wait until all Celix event for this bundle are completed.
*/
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_waitForEvents(celix_bundle_context_t *ctx);
/**
* @struct celix_scheduled_event_options
* @brief Celix scheduled event options, used for creating scheduling events with the celix framework.
*/
typedef struct celix_scheduled_event_options {
const char* name CELIX_OPTS_INIT; /**<
* @brief The name of the event, used for logging and debugging.
*
* Expected to be const char* that is valid during the celix_bundleContext_scheduleEvent
* call. Can be NULL. */
double initialDelayInSeconds CELIX_OPTS_INIT; /**< @brief Initial delay in seconds before the event is processed.*/
double intervalInSeconds CELIX_OPTS_INIT; /**< @brief Schedule interval in seconds.
* 0 means one-shot scheduled event.
*/
void* callbackData CELIX_OPTS_INIT; /**< @brief Data passed to the callback function when a event is scheduled.*/
void (*callback)(void* callbackData) CELIX_OPTS_INIT; /**< @brief Callback function called to process a scheduled
event. Will be called on the event thread.*/
void* removeCallbackData
CELIX_OPTS_INIT; /**< @brief Data passed to the done callback function when a scheduled event is removed.*/
void (*removeCallback)(void* removeCallbackData)
CELIX_OPTS_INIT; /**< @brief Callback function called when a scheduled event is removed. Will be called on
the event thread.*/
} celix_scheduled_event_options_t;
#define CELIX_EMPTY_SCHEDULED_EVENT_OPTIONS {NULL, 0.0, 0.0, NULL, NULL, NULL, NULL}
/**
* @brief Add a scheduled event to the Celix framework.
*
* The scheduled event will be called on the Celix framework event thread, repeatedly using the provided interval or
* once if only a initial delay is provided.
* The event callback should be relatively fast and the scheduled event interval should be relatively long, otherwise
* the framework event queue will be blocked and framework will not function properly.
*
* Scheduled events can be scheduled later than the provided initial delay and interval, because they are processed
* after other events in the Celix event thread.
* The target - but not guaranteed - precision of the scheduled event trigger is 1 microsecond.
*
* If the provided interval is 0, the scheduled event will a one-shot scheduled event and will be called once
* after the provided initial delay. If a bundle stops before the one-shot scheduled event is called, the scheduled
* event will be removed and not called.
*
* Scheduled events should be removed by the caller when not needed anymore, except for one-shot scheduled events.
* one-shot are automatically removed after the event callback is called.
*
* Note during bundle stop the framework will check if all scheduled events for the bundle are removed.
* For every not removed scheduled event that is not a one-shot event, a warning will be logged and the
* scheduled event will be removed.
*
* @param[in] ctx The bundle context.
* @param[in] options The scheduled event options, which describe the to be added scheduled event.
* @return The scheduled event id of the scheduled event. Can be used to cancel the event.
* @retval <0 If the event could not be added.
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_scheduleEvent(celix_bundle_context_t* ctx,
const celix_scheduled_event_options_t* options);
/**
* @brief Wakeup a scheduled event and returns immediately, not waiting for the scheduled event callback to be
* called.
*
* Silently ignored if the scheduled event ids < 0.
*
* @param[in] ctx The bundle context.
* @param[in] scheduledEventId The scheduled event id to wakeup.
* @return CELIX_SUCCESS if the scheduled event is woken up, CELIX_ILLEGAL_ARGUMENT if the scheduled event id is not known.
*/
CELIX_FRAMEWORK_EXPORT celix_status_t celix_bundleContext_wakeupScheduledEvent(celix_bundle_context_t* ctx,
long scheduledEventId);
/**
* @brief Wait until the next scheduled event is processed.
*
* Silently ignored if the scheduled event ids < 0.
*
* @param[in] ctx The bundle context.
* @param[in] scheduledEventId The scheduled event id to wait for.
* @param[in] waitTimeInSeconds The maximum time to wait for the next scheduled event. If <= 0 the function will return
* immediately.
* @return CELIX_SUCCESS if the scheduled event is woken up, CELIX_ILLEGAL_ARGUMENT if the scheduled event id is not
* known and ETIMEDOUT if the waitTimeInSeconds is reached.
*/
CELIX_FRAMEWORK_EXPORT celix_status_t celix_bundleContext_waitForScheduledEvent(celix_bundle_context_t* ctx,
long scheduledEventId,
double waitTimeInSeconds);
/**
* @brief Cancel and remove a scheduled event.
*
* Silently ignored if the scheduled event ids < 0.
*
* This function will block until a possible in-progress scheduled event callback is finished, the scheduled event
* is removed and, if configured, the remove callback is called.
*
* @param[in] ctx The bundle context.
* @param[in] scheduledEventId The scheduled event id to cancel and remove.
* @return true if a scheduled event is cancelled, false if the scheduled event id is not known.
*/
CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_removeScheduledEvent(celix_bundle_context_t* ctx,
long scheduledEventId);
/**
* @brief Cancel and remove a scheduled event asynchronously.
*
* When this function returns, no new scheduled event callbacks will be called, but it is not guaranteed that there
* is still a scheduled event callback in progress and that the remove callback is called.
*
* Silently ignored if the scheduled event ids < 0.
*
* @param[in] ctx The bundle context.
* @param[in] scheduledEventId The scheduled event id to cancel and remove.
* @return true if a scheduled event is cancelled, false if the scheduled event id is not known.
*/
CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_removeScheduledEventAsync(celix_bundle_context_t* ctx,
long scheduledEventId);
/**
* @brief Try to cancel and remove a scheduled event asynchronously.
*
* Silently ignored if the scheduled event ids < 0.
*
* When this function returns, no new scheduled event callbacks will be called, but it is not guaranteed that there
* is still a scheduled event callback in progress and that the remove callback is called.
* Will not log an error if the scheduled event id is not known.
*
* @param[in] ctx The bundle context.
* @param[in] scheduledEventId The scheduled event id to cancel.
* @return true if a scheduled event is cancelled, false if the scheduled event id is not known.
*/
CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_tryRemoveScheduledEventAsync(celix_bundle_context_t* ctx,
long scheduledEventId);
/**
* @brief Returns the bundle for this bundle context.
*/
CELIX_FRAMEWORK_EXPORT celix_bundle_t* celix_bundleContext_getBundle(const celix_bundle_context_t *ctx);
/**
* @brief Returns the bundle if for the bundle of this bundle context.
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_getBundleId(const celix_bundle_context_t *ctx);
CELIX_FRAMEWORK_EXPORT celix_framework_t* celix_bundleContext_getFramework(const celix_bundle_context_t *ctx);
/**
* @brief Logs a message to Celix framework logger with the provided log level.
* @param ctx The bundle context
* @param level The log level to use
* @param format printf style format string
* @param ... printf style format arguments
*/
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_log(
const celix_bundle_context_t *ctx,
celix_log_level_e level,
const char* format,
...) __attribute__((format(printf,3,4)));
/**
* @brief Logs a message to Celix framework logger with the provided log level.
*/
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_vlog(
const celix_bundle_context_t *ctx,
celix_log_level_e level,
const char* format,
va_list formatArgs) __attribute__((format(printf,3,0)));
/**
*
* @brief Logs celix thread-specific storage error messages(celix_err) ith the provided celix log level.
* Silently ignores log level CELIX_LOG_LEVEL_DISABLED.
*/
CELIX_FRAMEWORK_EXPORT void celix_bundleContext_logTssErrors(const celix_bundle_context_t* ctx,
celix_log_level_e level);
/**
* @brief Get the config property for the given key.
*
* The config property is a property from the framework configuration or a system property.
* If a system property is found, the system property is returned.
* Otherwise the framework configuration property - if found - is returned.
*
* @param ctx The bundle context.
* @param name The name of the property.
* @param defaultValue The default value if the property is not found.
* @return The property value or the default value if the property is not found.
*/
CELIX_FRAMEWORK_EXPORT const char* celix_bundleContext_getProperty(celix_bundle_context_t *ctx, const char* key, const char* defaultVal);
/**
* @brief Get the config property for the given key converted as long value.
*
* The config property is a property from the framework configuration or a system property.
* If a system property is found, the system property is returned.
* Otherwise the framework configuration property - if found - is returned.
*
* @param framework The framework.
* @param name The name of the property.
* @param defaultValue The default value if the property is not found.
* @return The property value or the default value if the property is not found or the property value cannot be converted
* to a long value.
*/
CELIX_FRAMEWORK_EXPORT long celix_bundleContext_getPropertyAsLong(celix_bundle_context_t *ctx, const char* name, long defaultValue);
/**
* @brief Get the config property for the given key converted as double value.
*
* The config property is a property from the framework configuration or a system property.
* If a system property is found, the system property is returned.
* Otherwise the framework configuration property - if found - is returned.
*
* @param framework The framework.
* @param name The name of the property.
* @param defaultValue The default value if the property is not found.
* @return The property value or the default value if the property is not found or the property value cannot be converted
* to a double value.
*/
CELIX_FRAMEWORK_EXPORT double celix_bundleContext_getPropertyAsDouble(celix_bundle_context_t *ctx, const char* name, double defaultValue);
/**
* @brief Get the config property for the given key converted as bool value.
*
* The config property is a property from the framework configuration or a system property.
* If a system property is found, the system property is returned.
* Otherwise the framework configuration property - if found - is returned.
*
* @param framework The framework.
* @param name The name of the property.
* @param defaultValue The default value if the property is not found.
* @return The property value or the default value if the property is not found or the property value cannot be converted
* to a bool value.
*/
CELIX_FRAMEWORK_EXPORT bool celix_bundleContext_getPropertyAsBool(celix_bundle_context_t *ctx, const char* name, bool defaultValue);
#undef CELIX_OPTS_INIT
#ifdef __cplusplus
}
#endif
#endif //CELIX_BUNDLE_CONTEXT_H_