Author: abroekhuis
Date: Wed Aug 8 13:39:26 2012
New Revision: 1370759
URL: http://svn.apache.org/viewvc?rev=1370759&view=rev
Log:
Added bundle listener
Added:
incubator/celix/trunk/framework/public/include/bundle_event.h
incubator/celix/trunk/framework/public/include/bundle_listener.h
Modified:
incubator/celix/trunk/framework/private/src/bundle_context.c
incubator/celix/trunk/framework/private/src/framework.c
incubator/celix/trunk/framework/public/include/bundle_context.h
incubator/celix/trunk/framework/public/include/framework.h
Modified: incubator/celix/trunk/framework/private/src/bundle_context.c
URL:
http://svn.apache.org/viewvc/incubator/celix/trunk/framework/private/src/bundle_context.c?rev=1370759&r1=1370758&r2=1370759&view=diff
==============================================================================
--- incubator/celix/trunk/framework/private/src/bundle_context.c (original)
+++ incubator/celix/trunk/framework/private/src/bundle_context.c Wed Aug 8
13:39:26 2012
@@ -278,6 +278,30 @@ celix_status_t bundleContext_removeServi
return status;
}
+celix_status_t bundleContext_addBundleListener(BUNDLE_CONTEXT context,
bundle_listener_t listener) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ if (context != NULL && listener != NULL) {
+ fw_addBundleListener(context->framework, context->bundle, listener);
+ } else {
+ status = CELIX_ILLEGAL_ARGUMENT;
+ }
+
+ return status;
+}
+
+celix_status_t bundleContext_removeBundleListener(BUNDLE_CONTEXT context,
bundle_listener_t listener) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ if (context != NULL && listener != NULL) {
+ fw_removeBundleListener(context->framework, context->bundle, listener);
+ } else {
+ status = CELIX_ILLEGAL_ARGUMENT;
+ }
+
+ return status;
+}
+
celix_status_t bundleContext_getProperty(BUNDLE_CONTEXT context, const char
*name, char **value) {
celix_status_t status = CELIX_SUCCESS;
Modified: incubator/celix/trunk/framework/private/src/framework.c
URL:
http://svn.apache.org/viewvc/incubator/celix/trunk/framework/private/src/framework.c?rev=1370759&r1=1370758&r2=1370759&view=diff
==============================================================================
--- incubator/celix/trunk/framework/private/src/framework.c (original)
+++ incubator/celix/trunk/framework/private/src/framework.c Wed Aug 8 13:39:26
2012
@@ -65,6 +65,7 @@ struct framework {
HASH_MAP installedBundleMap;
HASH_MAP installRequestMap;
ARRAY_LIST serviceListeners;
+ ARRAY_LIST bundleListeners;
long nextBundleId;
struct serviceRegistry * registry;
@@ -87,6 +88,11 @@ struct framework {
apr_pool_t *mp;
PROPERTIES configurationMap;
+
+ ARRAY_LIST requests;
+ apr_thread_cond_t *dispatcher;
+ apr_thread_mutex_t *dispatcherLock;
+ apr_thread_t *dispatcherThread;
};
struct activator {
@@ -117,6 +123,10 @@ celix_status_t fw_refreshBundle(FRAMEWOR
celix_status_t fw_populateDependentGraph(FRAMEWORK framework, BUNDLE exporter,
HASH_MAP *map);
+celix_status_t fw_fireBundleEvent(FRAMEWORK framework, bundle_event_type_e,
BUNDLE bundle);
+static void *APR_THREAD_FUNC fw_eventDispatcher(apr_thread_t *thd, void *fw);
+celix_status_t fw_invokeBundleListener(FRAMEWORK framework, bundle_listener_t
listener, bundle_event_t event, BUNDLE bundle);
+
struct fw_refreshHelper {
FRAMEWORK framework;
BUNDLE bundle;
@@ -135,6 +145,33 @@ struct fw_serviceListener {
typedef struct fw_serviceListener * FW_SERVICE_LISTENER;
+struct fw_bundleListener {
+ apr_pool_t *pool;
+ BUNDLE bundle;
+ bundle_listener_t listener;
+};
+
+typedef struct fw_bundleListener * fw_bundle_listener_t;
+
+enum event_type {
+ FRAMEWORK_EVENT_TYPE,
+ BUNDLE_EVENT_TYPE,
+ EVENT_TYPE_SERVICE,
+};
+
+typedef enum event_type event_type_e;
+
+struct request {
+ event_type_e type;
+ ARRAY_LIST listeners;
+
+ int eventType;
+ BUNDLE bundle;
+
+ char *filter;
+};
+
+typedef struct request *request_t;
celix_status_t framework_create(FRAMEWORK *framework, apr_pool_t *memoryPool,
PROPERTIES config) {
celix_status_t status = CELIX_SUCCESS;
@@ -173,27 +210,39 @@ celix_status_t framework_create(FRAMEWOR
if (apr_status != APR_SUCCESS) {
status = CELIX_FRAMEWORK_EXCEPTION;
} else {
- (*framework)->bundle = bundle;
-
- (*framework)->installedBundleMap = NULL;
- (*framework)->registry = NULL;
-
- (*framework)->interrupted = false;
- (*framework)->shutdown = false;
-
- (*framework)->globalLockWaitersList = NULL;
- arrayList_create((*framework)->mp,
&(*framework)->globalLockWaitersList);
- (*framework)->globalLockCount = 0;
- (*framework)->globalLockThread = 0;
- (*framework)->nextBundleId = 1l;
- (*framework)->cache = NULL;
-
- (*framework)->installRequestMap =
hashMap_create(string_hash, string_hash, string_equals, string_equals);
- (*framework)->serviceListeners = NULL;
- (*framework)->shutdownGate = NULL;
- (*framework)->configurationMap = config;
-
- status =
bundle_setFramework((*framework)->bundle, (*framework));
+ apr_status_t apr_status =
apr_thread_mutex_create(&(*framework)->dispatcherLock,
APR_THREAD_MUTEX_UNNESTED, (*framework)->mp);
+ if (apr_status != CELIX_SUCCESS) {
+
status = CELIX_FRAMEWORK_EXCEPTION;
+ } else {
+
apr_status_t apr_status = apr_thread_cond_create(&(*framework)->dispatcher,
(*framework)->mp);
+
if (apr_status != APR_SUCCESS) {
+
status = CELIX_FRAMEWORK_EXCEPTION;
+
} else {
+
(*framework)->bundle = bundle;
+
+
(*framework)->installedBundleMap = NULL;
+
(*framework)->registry = NULL;
+
+
(*framework)->interrupted = false;
+
(*framework)->shutdown = false;
+
+
(*framework)->globalLockWaitersList = NULL;
+
arrayList_create((*framework)->mp,
&(*framework)->globalLockWaitersList);
+
(*framework)->globalLockCount = 0;
+
(*framework)->globalLockThread = 0;
+
(*framework)->nextBundleId = 1l;
+
(*framework)->cache = NULL;
+
+
(*framework)->installRequestMap = hashMap_create(string_hash,
string_hash, string_equals, string_equals);
+
(*framework)->serviceListeners = NULL;
+
(*framework)->bundleListeners = NULL;
+
(*framework)->requests = NULL;
+
(*framework)->shutdownGate = NULL;
+
(*framework)->configurationMap = config;
+
+
status = bundle_setFramework((*framework)->bundle, (*framework));
+
}
+ }
}
}
}
@@ -244,6 +293,8 @@ celix_status_t framework_destroy(FRAMEWO
arrayList_destroy(framework->globalLockWaitersList);
arrayList_destroy(framework->serviceListeners);
+ arrayList_destroy(framework->bundleListeners);
+ arrayList_destroy(framework->requests);
hashMap_destroy(framework->installedBundleMap, false, false);
@@ -266,6 +317,12 @@ celix_status_t fw_init(FRAMEWORK framewo
return status;
}
+ framework->requests = NULL;
+ arrayList_create(framework->mp, &framework->requests);
+ if (apr_thread_create(&framework->dispatcherThread, NULL,
fw_eventDispatcher, framework, framework->mp) != APR_SUCCESS) {
+ return CELIX_FRAMEWORK_EXCEPTION;
+ }
+
bundle_getState(framework->bundle, &state);
if ((state == BUNDLE_INSTALLED) || (state == BUNDLE_RESOLVED)) {
PROPERTIES props = properties_create();
@@ -391,6 +448,11 @@ celix_status_t fw_init(FRAMEWORK framewo
framework->serviceListeners = NULL;
arrayList_create(framework->mp, &framework->serviceListeners);
+ framework->bundleListeners = NULL;
+ arrayList_create(framework->mp, &framework->bundleListeners);
+ framework->requests = NULL;
+ arrayList_create(framework->mp, &framework->requests);
+
framework_releaseBundleLock(framework, framework->bundle);
status = CELIX_SUCCESS;
@@ -422,6 +484,7 @@ celix_status_t framework_start(FRAMEWORK
}
framework_releaseBundleLock(framework, framework->bundle);
+
return CELIX_SUCCESS;
}
@@ -690,6 +753,8 @@ celix_status_t fw_startBundle(FRAMEWORK
}
framework_setBundleStateAndNotify(framework, bundle,
BUNDLE_ACTIVE);
+
+ fw_fireBundleEvent(framework, BUNDLE_EVENT_STARTED, bundle);
}
break;
@@ -874,14 +939,14 @@ celix_status_t fw_uninstallBundle(FRAMEW
}
framework_setBundleStateAndNotify(framework, bundle,
BUNDLE_INSTALLED);
- // TODO: fw_fireBundleEvent(framework BUNDLE_EVENT_UNRESOLVED,
bundle);
+ fw_fireBundleEvent(framework, BUNDLE_EVENT_UNRESOLVED, bundle);
framework_setBundleStateAndNotify(framework, bundle,
BUNDLE_UNINSTALLED);
status = bundleArchive_setLastModified(archive, time(NULL));
}
framework_releaseBundleLock(framework, bundle);
- // TODO: fw_fireBundleEvent(framework BUNDLE_EVENT_UNINSTALLED,
bundle);
+ fw_fireBundleEvent(framework, BUNDLE_EVENT_UNINSTALLED, bundle);
locked = framework_acquireGlobalLock(framework);
if (locked) {
@@ -1320,6 +1385,44 @@ void fw_removeServiceListener(FRAMEWORK
}
}
+celix_status_t fw_addBundleListener(FRAMEWORK framework, BUNDLE bundle,
bundle_listener_t listener) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ apr_pool_t *pool = NULL;
+ fw_bundle_listener_t bundleListener = NULL;
+
+ apr_pool_create(&pool, framework->mp);
+ bundleListener = apr_palloc(pool, sizeof(*bundleListener));
+ if (!bundleListener) {
+ status = CELIX_ENOMEM;
+ } else {
+ bundleListener->listener = listener;
+ bundleListener->bundle = bundle;
+ bundleListener->pool = pool;
+
+ arrayList_add(framework->bundleListeners, bundleListener);
+ }
+
+ return status;
+}
+
+celix_status_t fw_removeBundleListener(FRAMEWORK framework, BUNDLE bundle,
bundle_listener_t listener) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ int i;
+ fw_bundle_listener_t bundleListener;
+
+ for (i = 0; i < arrayList_size(framework->bundleListeners); i++) {
+ bundleListener = (fw_bundle_listener_t)
arrayList_get(framework->bundleListeners, i);
+ if (bundleListener->listener == listener &&
bundleListener->bundle == bundle) {
+ arrayList_remove(framework->bundleListeners, i);
+ apr_pool_destroy(bundleListener->pool);
+ }
+ }
+
+ return status;
+}
+
void fw_serviceChanged(FRAMEWORK framework, SERVICE_EVENT_TYPE eventType,
SERVICE_REGISTRATION registration, PROPERTIES oldprops) {
unsigned int i;
FW_SERVICE_LISTENER element;
@@ -1782,6 +1885,105 @@ celix_status_t framework_getFrameworkBun
return status;
}
+celix_status_t fw_fireBundleEvent(FRAMEWORK framework, bundle_event_type_e
eventType, BUNDLE bundle) {
+ celix_status_t status = CELIX_SUCCESS;
+
+ if ((eventType != BUNDLE_EVENT_STARTING)
+ && (eventType != BUNDLE_EVENT_STOPPING)
+ && (eventType != BUNDLE_EVENT_LAZY_ACTIVATION)) {
+ request_t request = malloc(sizeof(*request));
+ if (!request) {
+ status = CELIX_ENOMEM;
+ } else {
+ request->bundle = bundle;
+ request->eventType = eventType;
+ request->filter = NULL;
+ request->listeners = framework->bundleListeners;
+ request->type = BUNDLE_EVENT_TYPE;
+
+ arrayList_add(framework->requests, request);
+ if (apr_thread_mutex_lock(framework->dispatcherLock !=
APR_SUCCESS)) {
+ status = CELIX_FRAMEWORK_EXCEPTION;
+ } else {
+ if
(apr_thread_cond_broadcast(framework->dispatcher)) {
+ status = CELIX_FRAMEWORK_EXCEPTION;
+ } else {
+ if
(apr_thread_mutex_unlock(framework->dispatcherLock)) {
+ status =
CELIX_FRAMEWORK_EXCEPTION;
+ }
+ }
+ }
+ }
+ }
+
+ return status;
+}
+
+static void *APR_THREAD_FUNC fw_eventDispatcher(apr_thread_t *thd, void *fw) {
+ FRAMEWORK framework = (FRAMEWORK) fw;
+ request_t request = NULL;
+
+ while (true) {
+ if (apr_thread_mutex_lock(framework->dispatcherLock) != 0) {
+ celix_log("Error locking the dispatcher");
+ return NULL;
+ }
+
+ int size = arrayList_size(framework->requests);
+ while (size == 0 && !framework->shutdown) {
+ apr_status_t apr_status =
apr_thread_cond_wait(framework->dispatcher, framework->dispatcherLock);
+ // Ignore status and just keep waiting
+ size = arrayList_size(framework->requests);
+ }
+
+ if (size == 0 && framework->shutdown) {
+ apr_thread_exit(thd, APR_SUCCESS);
+ return NULL;
+ }
+
+ request = arrayList_remove(framework->requests, 0);
+
+ apr_status_t status;
+ if ((status =
apr_thread_mutex_unlock(framework->dispatcherLock)) != 0) {
+ celix_log("Error unlocking the dispatcher.");
+ apr_thread_exit(thd, status);
+ return NULL;
+ }
+
+ if (request != NULL) {
+ int i;
+ int size = arrayList_size(request->listeners);
+ for (i = 0; i < size; i++) {
+ if (request->type == BUNDLE_EVENT_TYPE) {
+ fw_bundle_listener_t listener =
arrayList_get(request->listeners, i);
+ bundle_event_t event =
apr_palloc(listener->listener->pool, sizeof(*event));
+ event->bundle = request->bundle;
+ event->type = request->type;
+
+ fw_invokeBundleListener(framework,
listener->listener, event, listener->bundle);
+ }
+ }
+ }
+ }
+
+ apr_thread_exit(thd, APR_SUCCESS);
+
+ return NULL;
+
+}
+
+celix_status_t fw_invokeBundleListener(FRAMEWORK framework, bundle_listener_t
listener, bundle_event_t event, BUNDLE bundle) {
+ // We only support async bundle listeners for now
+ BUNDLE_STATE state;
+ bundle_getState(bundle, &state);
+ if (state == BUNDLE_STARTING || state == BUNDLE_ACTIVE) {
+
+ listener->bundleChanged(listener, event);
+ }
+
+ return CELIX_SUCCESS;
+}
+
celix_status_t bundleActivator_start(void * userData, BUNDLE_CONTEXT context) {
// nothing to do
return CELIX_SUCCESS;
Modified: incubator/celix/trunk/framework/public/include/bundle_context.h
URL:
http://svn.apache.org/viewvc/incubator/celix/trunk/framework/public/include/bundle_context.h?rev=1370759&r1=1370758&r2=1370759&view=diff
==============================================================================
--- incubator/celix/trunk/framework/public/include/bundle_context.h (original)
+++ incubator/celix/trunk/framework/public/include/bundle_context.h Wed Aug 8
13:39:26 2012
@@ -35,6 +35,7 @@ typedef struct bundleContext *BUNDLE_CON
#include "service_factory.h"
#include "service_listener.h"
+#include "bundle_listener.h"
#include "properties.h"
#include "array_list.h"
@@ -65,6 +66,9 @@ celix_status_t bundleContext_getBundleBy
celix_status_t bundleContext_addServiceListener(BUNDLE_CONTEXT context,
SERVICE_LISTENER listener, char * filter);
celix_status_t bundleContext_removeServiceListener(BUNDLE_CONTEXT context,
SERVICE_LISTENER listener);
+celix_status_t bundleContext_addBundleListener(BUNDLE_CONTEXT context,
bundle_listener_t listener);
+celix_status_t bundleContext_removeBundleListener(BUNDLE_CONTEXT context,
bundle_listener_t listener);
+
celix_status_t bundleContext_getProperty(BUNDLE_CONTEXT context, const char
*name, char **value);
#endif /* BUNDLE_CONTEXT_H_ */
Added: incubator/celix/trunk/framework/public/include/bundle_event.h
URL:
http://svn.apache.org/viewvc/incubator/celix/trunk/framework/public/include/bundle_event.h?rev=1370759&view=auto
==============================================================================
--- incubator/celix/trunk/framework/public/include/bundle_event.h (added)
+++ incubator/celix/trunk/framework/public/include/bundle_event.h Wed Aug 8
13:39:26 2012
@@ -0,0 +1,35 @@
+/*
+ * bundle_event.h
+ *
+ * Created on: Jun 28, 2012
+ * Author: alexander
+ */
+
+#ifndef BUNDLE_EVENT_H_
+#define BUNDLE_EVENT_H_
+
+typedef enum bundle_event_type bundle_event_type_e;
+typedef struct bundle_event *bundle_event_t;
+
+#include "service_reference.h"
+
+enum bundle_event_type
+{
+ BUNDLE_EVENT_INSTALLED = 0x00000001,
+ BUNDLE_EVENT_STARTED = 0x00000002,
+ BUNDLE_EVENT_STOPPED = 0x00000004,
+ BUNDLE_EVENT_UPDATED = 0x00000008,
+ BUNDLE_EVENT_UNINSTALLED = 0x00000010,
+ BUNDLE_EVENT_RESOLVED = 0x00000020,
+ BUNDLE_EVENT_UNRESOLVED = 0x00000040,
+ BUNDLE_EVENT_STARTING = 0x00000080,
+ BUNDLE_EVENT_STOPPING = 0x00000100,
+ BUNDLE_EVENT_LAZY_ACTIVATION = 0x00000200,
+};
+
+struct bundle_event {
+ BUNDLE bundle;
+ bundle_event_type_e type;
+};
+
+#endif /* BUNDLE_EVENT_H_ */
Added: incubator/celix/trunk/framework/public/include/bundle_listener.h
URL:
http://svn.apache.org/viewvc/incubator/celix/trunk/framework/public/include/bundle_listener.h?rev=1370759&view=auto
==============================================================================
--- incubator/celix/trunk/framework/public/include/bundle_listener.h (added)
+++ incubator/celix/trunk/framework/public/include/bundle_listener.h Wed Aug 8
13:39:26 2012
@@ -0,0 +1,51 @@
+/*
+ *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.
+ */
+/**
+ *
+ * @defgroup BundleListener Bundle Listener
+ * @ingroup framework
+ * @{
+ *
+ * \author Alexander Broekhuis
+ * \date June 28, 2012
+ * \copyright Apache License, Version 2.0
+ */
+#ifndef BUNDLE_LISTENER_H_
+#define BUNDLE_LISTENER_H_
+
+#include <apr_general.h>
+
+typedef struct bundle_listener *bundle_listener_t;
+
+#include "celix_errno.h"
+#include "bundle_event.h"
+
+struct bundle_listener {
+ apr_pool_t *pool;
+ void * handle;
+ celix_status_t (*bundleChanged)(void * listener, bundle_event_t event);
+};
+
+
+
+#endif /* SERVICE_LISTENER_H_ */
+
+/**
+ * @}
+ */
Modified: incubator/celix/trunk/framework/public/include/framework.h
URL:
http://svn.apache.org/viewvc/incubator/celix/trunk/framework/public/include/framework.h?rev=1370759&r1=1370758&r2=1370759&view=diff
==============================================================================
--- incubator/celix/trunk/framework/public/include/framework.h (original)
+++ incubator/celix/trunk/framework/public/include/framework.h Wed Aug 8
13:39:26 2012
@@ -37,6 +37,7 @@ typedef struct framework * FRAMEWORK;
#include "service_factory.h"
#include "bundle_archive.h"
#include "service_listener.h"
+#include "bundle_listener.h"
#include "service_registration.h"
#include "bundle_context.h"
@@ -70,6 +71,10 @@ celix_status_t fw_getBundleServicesInUse
void fw_addServiceListener(FRAMEWORK framework, BUNDLE bundle,
SERVICE_LISTENER listener, char * filter);
void fw_removeServiceListener(FRAMEWORK framework, BUNDLE bundle,
SERVICE_LISTENER listener);
+
+celix_status_t fw_addBundleListener(FRAMEWORK framework, BUNDLE bundle,
bundle_listener_t listener);
+celix_status_t fw_removeBundleListener(FRAMEWORK framework, BUNDLE bundle,
bundle_listener_t listener);
+
void fw_serviceChanged(FRAMEWORK framework, SERVICE_EVENT_TYPE eventType,
SERVICE_REGISTRATION registration, PROPERTIES oldprops);
celix_status_t fw_isServiceAssignable(FRAMEWORK fw, BUNDLE requester,
SERVICE_REFERENCE reference, bool *assignable);