blob: a0e118b3c8a608f94e62d0b18b6fd7172ee19ed0 [file] [log] [blame]
/**
*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.
*/
/*
* listener_example.c
*
* \date Sep 22, 2011
* \author <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
* \copyright Apache License, Version 2.0
*/
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include "bundle_activator.h"
#include "log_service.h"
struct listenerActivator {
bundle_context_pt context;
service_listener_pt listener;
celix_thread_t logger;
celix_thread_mutex_t logServiceReferencesLock;
array_list_pt logServiceReferences;
bool running;
};
void listenerExample_serviceChanged(service_listener_pt listener, service_event_pt event);
celix_status_t listenerExample_getLogService(struct listenerActivator *activator, log_service_pt *service);
static void* listenerExample_logger(void* data);
celix_status_t listenerExample_alternativeLog(struct listenerActivator *activator, char *message);
celix_status_t ref_equals(void *a, void *b, bool *equals) {
return serviceReference_equals(a, b, equals);
}
celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) {
celix_status_t status = CELIX_SUCCESS;
*userData = calloc(1, sizeof(struct listenerActivator));
if (!*userData) {
status = CELIX_ENOMEM;
} else {
struct listenerActivator *activator = (*userData);
activator->context = context;
activator->listener = NULL;
activator->logServiceReferences = NULL;
arrayList_createWithEquals(ref_equals, &activator->logServiceReferences);
activator->running = false;
status = celixThreadMutex_create(&activator->logServiceReferencesLock, NULL);
}
return status;
}
celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
celix_status_t status = CELIX_SUCCESS;
struct listenerActivator *activator = userData;
service_listener_pt listener = calloc(1, sizeof(struct listenerActivator));
if (!listener) {
status = CELIX_ENOMEM;
} else {
char filter[30];
array_list_pt logServices = NULL;
sprintf(filter, "(objectClass=%s)", OSGI_LOGSERVICE_NAME);
listener->handle = activator;
listener->serviceChanged = (void *) listenerExample_serviceChanged;
status = bundleContext_addServiceListener(context, listener, filter);
if (status == CELIX_SUCCESS) {
activator->listener = listener;
}
status = bundleContext_getServiceReferences(context, NULL, filter, &logServices);
if (status == CELIX_SUCCESS) {
int i;
for (i = 0; i < arrayList_size(logServices); i++) {
service_reference_pt logService = (service_reference_pt) arrayList_get(logServices, i);
service_event_pt event = calloc(1, sizeof(*event));
event->reference = logService;
event->type = OSGI_FRAMEWORK_SERVICE_EVENT_REGISTERED;
listenerExample_serviceChanged(listener, event);
}
arrayList_destroy(logServices);
}
activator->running = true;
status = celixThread_create(&activator->logger, NULL, listenerExample_logger, activator);
}
return status;
}
celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) {
celix_status_t status = CELIX_SUCCESS;
struct listenerActivator *activator = userData;
activator->running = false;
celixThread_join(activator->logger, NULL);
bundleContext_removeServiceListener(context, activator->listener);
return status;
}
celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) {
celix_status_t status = CELIX_SUCCESS;
struct listenerActivator *activator = userData;
arrayList_destroy(activator->logServiceReferences);
return status;
}
void listenerExample_serviceChanged(service_listener_pt listener, service_event_pt event) {
struct listenerActivator *activator = listener->handle;
celixThreadMutex_lock(&activator->logServiceReferencesLock);
switch (event->type) {
case OSGI_FRAMEWORK_SERVICE_EVENT_REGISTERED:
arrayList_add(activator->logServiceReferences, event->reference);
break;
// case MODIFIED:
// // only the service metadata has changed, so no need to do anything here
// break;
case OSGI_FRAMEWORK_SERVICE_EVENT_UNREGISTERING:
arrayList_remove(activator->logServiceReferences, arrayList_indexOf(activator->logServiceReferences, event->reference));
break;
default:
break;
}
celixThreadMutex_unlock(&activator->logServiceReferencesLock);
}
celix_status_t listenerExample_getLogService(struct listenerActivator *activator, log_service_pt *service) {
celix_status_t status = CELIX_SUCCESS;
celixThreadMutex_lock(&activator->logServiceReferencesLock);
if (arrayList_size(activator->logServiceReferences) > 0) {
service_reference_pt reference = arrayList_get(activator->logServiceReferences, 0);
status = bundleContext_getService(activator->context, reference, (void *) service);
}
celixThreadMutex_unlock(&activator->logServiceReferencesLock);
return status;
}
static void* listenerExample_logger(void* data) {
struct listenerActivator *activator = data;
while (activator->running) {
log_service_pt logService = NULL;
listenerExample_getLogService(activator, &logService);
if (logService != NULL) {
(*(logService->log))(logService->logger, OSGI_LOGSERVICE_INFO, "ping");
} else {
listenerExample_alternativeLog(activator, "No LogService available. Printing to standard out.");
}
sleep(5);
}
return NULL;
}
celix_status_t listenerExample_alternativeLog(struct listenerActivator *activator, char *message) {
celix_status_t status = CELIX_SUCCESS;
printf("%s\n", message);
return status;
}