celix-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pnol...@apache.org
Subject [3/7] celix git commit: CELIX-425: Adds the c dependency manager to the framework. Also adds some empty interface libraries so that the changes are backwards compatible.
Date Wed, 25 Apr 2018 19:12:07 GMT
http://git-wip-us.apache.org/repos/asf/celix/blob/5992be15/framework/src/dm_service_dependency.c
----------------------------------------------------------------------
diff --git a/framework/src/dm_service_dependency.c b/framework/src/dm_service_dependency.c
new file mode 100644
index 0000000..65a0593
--- /dev/null
+++ b/framework/src/dm_service_dependency.c
@@ -0,0 +1,811 @@
+/**
+ *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.
+ */
+/*
+ * dm_service_dependency.c
+ *
+ *  \date       17 Oct 2014
+ *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright  Apache License, Version 2.0
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <assert.h>
+
+#include "constants.h"
+
+#include "dm_service_dependency_impl.h"
+#include "dm_component_impl.h"
+
+#define DEFAULT_RANKING     0
+#define DM_SERVICE_DEPENDENCY_DEFAULT_STRATEGY DM_SERVICE_DEPENDENCY_STRATEGY_SUSPEND
+
+static celix_status_t serviceDependency_addedService(void *_ptr, service_reference_pt reference, void *service);
+static celix_status_t serviceDependency_modifiedService(void *_ptr, service_reference_pt reference, void *service);
+static celix_status_t serviceDependency_removedService(void *_ptr, service_reference_pt reference, void *service);
+static void* serviceDependency_getCallbackHandle(dm_service_dependency_pt dep);
+
+celix_status_t serviceDependency_create(dm_service_dependency_pt *dependency_ptr) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	*dependency_ptr = calloc(1, sizeof(**dependency_ptr));
+	if (!*dependency_ptr) {
+		status = CELIX_ENOMEM;
+	} else {
+		(*dependency_ptr)->component = NULL;
+		(*dependency_ptr)->available = false;
+		(*dependency_ptr)->instanceBound = false;
+		(*dependency_ptr)->required = false;
+		(*dependency_ptr)->strategy = DM_SERVICE_DEPENDENCY_DEFAULT_STRATEGY;
+
+		(*dependency_ptr)->callbackHandle = NULL;
+		(*dependency_ptr)->set = NULL;
+		(*dependency_ptr)->add = NULL;
+		(*dependency_ptr)->change = NULL;
+		(*dependency_ptr)->remove = NULL;
+		(*dependency_ptr)->swap = NULL;
+
+		(*dependency_ptr)->add_with_ref = NULL;
+		(*dependency_ptr)->change_with_ref = NULL;
+		(*dependency_ptr)->remove_with_ref = NULL;
+		(*dependency_ptr)->swap_with_ref = NULL;
+
+		(*dependency_ptr)->autoConfigure = NULL;
+
+		(*dependency_ptr)->isStarted = false;
+
+        (*dependency_ptr)->addCLanguageFilter = false;
+		(*dependency_ptr)->tracked_service = NULL;
+		(*dependency_ptr)->tracked_filter_unmodified = NULL;
+		(*dependency_ptr)->tracked_filter = NULL;
+
+		(*dependency_ptr)->tracker = NULL;
+		(*dependency_ptr)->tracker_customizer = NULL;
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_destroy(dm_service_dependency_pt *dependency_ptr) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!*dependency_ptr) {
+		status = CELIX_ENOMEM;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		free((*dependency_ptr)->tracked_service);
+		free((*dependency_ptr)->tracked_filter);
+		free((*dependency_ptr)->tracked_filter_unmodified);
+		free(*dependency_ptr);
+		*dependency_ptr = NULL;
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_lock(dm_service_dependency_pt dependency) {
+	celixThreadMutex_lock(&dependency->lock);
+	return CELIX_SUCCESS;
+}
+
+celix_status_t serviceDependency_unlock(dm_service_dependency_pt dependency) {
+	celixThreadMutex_unlock(&dependency->lock);
+	return CELIX_SUCCESS;
+}
+
+celix_status_t serviceDependency_setRequired(dm_service_dependency_pt dependency, bool required) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		dependency->required = required;
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_setAddCLanguageFilter(dm_service_dependency_pt dependency, bool addCLangFilter) {
+    dependency->addCLanguageFilter = addCLangFilter;
+    return CELIX_SUCCESS;
+}
+
+celix_status_t serviceDependency_setStrategy(dm_service_dependency_pt dependency, dm_service_dependency_strategy_t strategy) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	} else {
+		dependency->strategy = strategy;
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_getStrategy(dm_service_dependency_pt dependency, dm_service_dependency_strategy_t* strategy) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	} else {
+		*strategy = dependency->strategy;
+	}
+
+	return status;
+
+}
+
+celix_status_t serviceDependency_setService(dm_service_dependency_pt dependency, const char* serviceName, const char* serviceVersionRange, const char* filter) {
+	celix_status_t status = CELIX_SUCCESS;
+	if (!dependency || !serviceName) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		array_list_pt filterElements = NULL;
+		arrayList_create(&filterElements);
+
+		free(dependency->tracked_service);
+		dependency->tracked_service = strdup(serviceName);
+
+		if (serviceVersionRange != NULL) {
+			version_range_pt versionRange = NULL;
+
+			if (versionRange_parse(serviceVersionRange, &versionRange) == CELIX_SUCCESS) {
+				version_pt lowVersion = NULL;
+				version_pt highVersion = NULL;
+
+				if ((versionRange_getHighVersion(versionRange, &highVersion) == CELIX_SUCCESS) && (highVersion != NULL)) {
+					bool isHighInclusive;
+					char* highOperator;
+					char* highVersionStr = NULL;
+
+					versionRange_isHighInclusive(versionRange, &isHighInclusive);
+					version_toString(highVersion, &highVersionStr);
+
+					highOperator = isHighInclusive ? "<=" : "<";
+
+					if(highVersionStr != NULL){
+						size_t len = strlen(CELIX_FRAMEWORK_SERVICE_VERSION) + strlen(highVersionStr) + strlen(highOperator) + 3;
+						char serviceVersionFilter[len];
+						snprintf(serviceVersionFilter, len, "(%s%s%s)", CELIX_FRAMEWORK_SERVICE_VERSION, highOperator, highVersionStr);
+						arrayList_add(filterElements, strdup(serviceVersionFilter));
+						free(highVersionStr);
+					}
+				}
+
+				if ((versionRange_getLowVersion(versionRange, &lowVersion) == CELIX_SUCCESS) && (lowVersion != NULL)) {
+					bool isLowInclusive;
+					char* lowOperator;
+					char* lowVersionStr = NULL;
+
+					versionRange_isLowInclusive(versionRange, &isLowInclusive);
+					version_toString(lowVersion, &lowVersionStr);
+
+					lowOperator = isLowInclusive ? ">=" : ">";
+
+					if(lowVersionStr != NULL){
+						size_t len = strlen(CELIX_FRAMEWORK_SERVICE_VERSION) + strlen(lowVersionStr) + strlen(lowOperator) + 3;
+						char serviceVersionFilter[len];
+						snprintf(serviceVersionFilter, len, "(%s%s%s)", CELIX_FRAMEWORK_SERVICE_VERSION, lowOperator, lowVersionStr);
+						arrayList_add(filterElements, strdup(serviceVersionFilter));
+						free(lowVersionStr);
+					}
+				}
+			}
+
+			if(versionRange!=NULL){
+				versionRange_destroy(versionRange);
+			}
+		}
+
+		if (filter != NULL) {
+			free(dependency->tracked_filter_unmodified);
+			dependency->tracked_filter_unmodified = strdup(filter);
+			arrayList_add(filterElements, strdup(filter));
+		}
+
+
+
+        bool needLangFilter = true;
+		if (filter != NULL) {
+            char needle[128];
+            snprintf(needle, sizeof(needle), "(%s=", CELIX_FRAMEWORK_SERVICE_LANGUAGE);
+            if (strstr(filter, needle) != NULL) {
+                needLangFilter = false;
+            }
+        }
+
+        if (needLangFilter && dependency->addCLanguageFilter) {
+			char langFilter[128];
+			snprintf(langFilter, sizeof(langFilter), "(%s=%s)", CELIX_FRAMEWORK_SERVICE_LANGUAGE, CELIX_FRAMEWORK_SERVICE_C_LANGUAGE);
+            arrayList_add(filterElements, strdup(langFilter));
+		}
+
+		if (arrayList_size(filterElements) > 0) {
+			array_list_iterator_pt filterElementsIter = arrayListIterator_create(filterElements);
+
+			size_t len = strlen(serviceName) + strlen(OSGI_FRAMEWORK_OBJECTCLASS) + 4;
+			free(dependency->tracked_filter);
+			dependency->tracked_filter = calloc(len, sizeof(*dependency->tracked_filter));
+			snprintf(dependency->tracked_filter, len, "(%s=%s)", OSGI_FRAMEWORK_OBJECTCLASS, serviceName);
+
+			while (arrayListIterator_hasNext(filterElementsIter) == true) {
+				char* filterElement = (char*) arrayListIterator_next(filterElementsIter);
+				size_t len = strnlen(dependency->tracked_filter, 1024*1024) + strnlen(filterElement, 1024*1024) + 4;
+				char* newFilter = calloc(len, sizeof(*newFilter));
+
+				if (dependency->tracked_filter[0] == '(' && dependency->tracked_filter[1] == '&') {
+					//already have an & (AND) can combine with additional filter -> easier to read
+					size_t orgLen = strnlen(dependency->tracked_filter, 1024*1024);
+					snprintf(newFilter, len, "%.*s%s)", (int)orgLen -1, dependency->tracked_filter, filterElement);
+				} else {
+					snprintf(newFilter, len, "(&%s%s)", dependency->tracked_filter, filterElement);
+				}
+
+				free(dependency->tracked_filter);
+				free(filterElement);
+
+				dependency->tracked_filter = newFilter;
+			}
+
+			arrayListIterator_destroy(filterElementsIter);
+		}
+		else {
+			free(dependency->tracked_filter);
+			dependency->tracked_filter = NULL;
+		}
+
+		arrayList_destroy(filterElements);
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_getFilter(dm_service_dependency_pt dependency, const char** filter) {
+	*filter = (const char*)dependency->tracked_filter;
+	return CELIX_SUCCESS;
+}
+
+celix_status_t serviceDependency_setCallbacks(dm_service_dependency_pt dependency, service_set_fpt set, service_add_fpt add, service_change_fpt change, service_remove_fpt remove, service_swap_fpt swap) {
+	celix_status_t status = CELIX_SUCCESS;
+
+    //printf("Setting callbacks set %p, add %p, change %p, remove %p and swap %p\n", set, add, change, remove, swap);
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		dependency->set = set;
+		dependency->add = add;
+		dependency->change = change;
+		dependency->remove = remove;
+		dependency->swap = swap;
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_setCallbacksWithServiceReference(dm_service_dependency_pt dependency, service_set_with_ref_fpt set, service_add_with_ref_fpt add, service_change_with_ref_fpt change, service_remove_with_ref_fpt remove,
+		service_swap_with_ref_fpt swap) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		dependency->set_with_ref = set;
+		dependency->add_with_ref = add;
+		dependency->change_with_ref = change;
+		dependency->remove_with_ref = remove;
+		dependency->swap_with_ref = swap;
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_setAutoConfigure(dm_service_dependency_pt dependency, celix_thread_mutex_t *service_lock, const void **field) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	celix_thread_mutex_t lock;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		dependency->autoConfigure = field;
+		celixThreadMutex_create(&lock, NULL);
+		*service_lock = lock;
+		dependency->lock = lock;
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_setComponent(dm_service_dependency_pt dependency, dm_component_pt component) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		dependency->component = component;
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_start(dm_service_dependency_pt dependency) {
+	celix_status_t status = CELIX_SUCCESS;
+	bundle_context_pt context = NULL;
+
+	if (!dependency || !dependency->component || (!dependency->tracked_service && !dependency->tracked_filter)) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+	if (status == CELIX_SUCCESS) {
+		status = component_getBundleContext(dependency->component, &context);
+		if (!context) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	}
+	if (status == CELIX_SUCCESS) {
+		dependency->tracker_customizer = NULL;
+		status = serviceTrackerCustomizer_create(dependency, NULL, serviceDependency_addedService, serviceDependency_modifiedService, serviceDependency_removedService, &dependency->tracker_customizer);
+	}
+	if (status == CELIX_SUCCESS) {
+		if (dependency->tracked_filter) {
+			status = serviceTracker_createWithFilter(context, dependency->tracked_filter, dependency->tracker_customizer, &dependency->tracker);
+		} else if (dependency->tracked_service) {
+			status = serviceTracker_create(context, dependency->tracked_service, dependency->tracker_customizer, &dependency->tracker);
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = serviceTracker_open(dependency->tracker);
+	}
+
+	if (status == CELIX_SUCCESS) {
+		dependency->isStarted = true;
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_stop(dm_service_dependency_pt dependency) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		dependency->isStarted = false;
+	}
+
+	if (status == CELIX_SUCCESS && dependency->tracker) {
+		status = serviceTracker_close(dependency->tracker);
+		if (status == CELIX_SUCCESS) {
+			serviceTracker_destroy(dependency->tracker);
+			dependency->tracker = NULL;
+		}
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_setInstanceBound(dm_service_dependency_pt dependency, bool instanceBound) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		dependency->instanceBound = instanceBound;
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_setAvailable(dm_service_dependency_pt dependency, bool available) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		dependency->available = available;
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_invokeSet(dm_service_dependency_pt dependency, dm_event_pt event) {
+	celix_status_t status = CELIX_SUCCESS;
+	assert(dependency->isStarted == true);
+	array_list_pt serviceReferences = NULL;
+	int i;
+	int curRanking = INT_MIN;
+	service_reference_pt curServRef = NULL;
+	void *service = NULL;
+
+	serviceReferences = serviceTracker_getServiceReferences(dependency->tracker);
+
+	/* Find the service with the higest ranking */
+	for (i = 0; i < arrayList_size(serviceReferences); i++) {
+		service_reference_pt serviceReference = arrayList_get(serviceReferences, i);
+		const char* ranking_value;
+		int ranking = 0;
+
+		status = serviceReference_getProperty(serviceReference, ((char *) OSGI_FRAMEWORK_SERVICE_RANKING), &ranking_value);
+
+		if (status == CELIX_SUCCESS) {
+			if (ranking_value == NULL) {
+				ranking = DEFAULT_RANKING;
+			} else {
+				char *end;
+				ranking = strtol(ranking_value, &end, 10);
+				if (end == ranking_value) {
+					ranking = DEFAULT_RANKING;
+				}
+			}
+
+			if (ranking > curRanking) {
+				curRanking = ranking;
+				curServRef = serviceReference;
+			}
+		} else {
+			break;
+		}
+
+	}
+
+	arrayList_destroy(serviceReferences);
+
+	if (status == CELIX_SUCCESS) {
+		if (curServRef) {
+			status = bundleContext_getService(event->context, curServRef, &service);
+		} else {
+			service = NULL;
+		}
+
+		if (dependency->set) {
+			dependency->set(serviceDependency_getCallbackHandle(dependency), service);
+		}
+		if (dependency->set_with_ref) {
+			dependency->set_with_ref(serviceDependency_getCallbackHandle(dependency), curServRef, service);
+		}
+
+		if (curServRef) {
+			bundleContext_ungetService(event->context, curServRef, NULL);
+		}
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_invokeAdd(dm_service_dependency_pt dependency, dm_event_pt event) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		if (dependency->add) {
+			dependency->add(serviceDependency_getCallbackHandle(dependency), event->service);
+		}
+		if (dependency->add_with_ref) {
+			dependency->add_with_ref(serviceDependency_getCallbackHandle(dependency), event->reference, event->service);
+		}
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_invokeChange(dm_service_dependency_pt dependency, dm_event_pt event) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		if (dependency->change) {
+			dependency->change(serviceDependency_getCallbackHandle(dependency), event->service);
+		}
+		if (dependency->change_with_ref) {
+			dependency->change_with_ref(serviceDependency_getCallbackHandle(dependency), event->reference, event->service);
+		}
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_invokeRemove(dm_service_dependency_pt dependency, dm_event_pt event) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		if (dependency->remove) {
+			dependency->remove(serviceDependency_getCallbackHandle(dependency), event->service);
+		}
+		if (dependency->remove_with_ref) {
+			dependency->remove_with_ref(serviceDependency_getCallbackHandle(dependency), event->reference, event->service);
+		}
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_invokeSwap(dm_service_dependency_pt dependency, dm_event_pt event, dm_event_pt newEvent) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		if (dependency->swap) {
+			dependency->swap(serviceDependency_getCallbackHandle(dependency), event->service, newEvent->service);
+		}
+		if (dependency->swap_with_ref) {
+			dependency->swap_with_ref(serviceDependency_getCallbackHandle(dependency), event->reference, event->service, newEvent->reference, newEvent->service);
+		}
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_isAvailable(dm_service_dependency_pt dependency, bool *available) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		*available = dependency->available;
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_isRequired(dm_service_dependency_pt dependency, bool *required) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		*required = dependency->required;
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_isInstanceBound(dm_service_dependency_pt dependency, bool *instanceBound) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		*instanceBound = dependency->instanceBound;
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_isAutoConfig(dm_service_dependency_pt dependency, bool *autoConfig) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		*autoConfig = dependency->autoConfigure != NULL;
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_getAutoConfig(dm_service_dependency_pt dependency, const void*** autoConfigure) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!dependency) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		*autoConfigure = dependency->autoConfigure;
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_addedService(void *_ptr, service_reference_pt reference, void *service) {
+	celix_status_t status = CELIX_SUCCESS;
+	bundle_context_pt context = NULL;
+	bundle_pt bundle = NULL;
+	dm_event_pt event = NULL;
+	dm_service_dependency_pt dependency = _ptr;
+
+	if (!dependency || !reference || !service) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = component_getBundleContext(dependency->component, &context);
+		if (!context) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = bundleContext_getBundle(context, &bundle);
+		if (!bundle) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = event_create(DM_EVENT_ADDED, bundle, context, reference, service, &event);
+	}
+
+	if (status == CELIX_SUCCESS) {
+		component_handleEvent(dependency->component, dependency, event);
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_modifiedService(void *_ptr, service_reference_pt reference, void *service) {
+	celix_status_t status = CELIX_SUCCESS;
+	bundle_context_pt context = NULL;
+	bundle_pt bundle = NULL;
+	dm_event_pt event = NULL;
+	dm_service_dependency_pt dependency = _ptr;
+
+	if (!dependency || !reference || !service) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = component_getBundleContext(dependency->component, &context);
+		if (!context) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = bundleContext_getBundle(context, &bundle);
+		if (!bundle) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = event_create(DM_EVENT_CHANGED, bundle, context, reference, service, &event);
+	}
+
+	if (status == CELIX_SUCCESS) {
+		component_handleEvent(dependency->component, dependency, event);
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_removedService(void *_ptr, service_reference_pt reference, void *service) {
+	celix_status_t status = CELIX_SUCCESS;
+	bundle_context_pt context = NULL;
+	bundle_pt bundle = NULL;
+	dm_event_pt event = NULL;
+	dm_service_dependency_pt dependency = _ptr;
+
+	if (!dependency || !reference || !service) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = component_getBundleContext(dependency->component, &context);
+		if (!context) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = bundleContext_getBundle(context, &bundle);
+		if (!bundle) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = event_create(DM_EVENT_REMOVED, bundle, context, reference, service, &event);
+	}
+
+	if (status == CELIX_SUCCESS) {
+		component_handleEvent(dependency->component, dependency, event);
+	}
+
+	return status;
+}
+
+celix_status_t serviceDependency_getServiceDependencyInfo(dm_service_dependency_pt dep, dm_service_dependency_info_pt *out) {
+	celix_status_t status = CELIX_SUCCESS;
+	dm_service_dependency_info_pt info = calloc(1, sizeof(*info));
+	if (info != NULL) {
+		celixThreadMutex_lock(&dep->lock);
+		info->available = dep->available;
+		info->filter = dep->tracked_filter != NULL ? strdup(dep->tracked_filter) : NULL;
+		if (info->filter == NULL) {
+			info->filter = dep->tracked_service != NULL ? strdup(dep->tracked_service) : NULL;
+		}
+		info->required = dep->required;
+
+		array_list_pt refs = serviceTracker_getServiceReferences(dep->tracker);
+		if (refs != NULL) {
+			info->count = arrayList_size(refs);
+		}
+		arrayList_destroy(refs);
+
+		celixThreadMutex_unlock(&dep->lock);
+	} else {
+		status = CELIX_ENOMEM;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		*out = info;
+	}
+
+	return status;
+}
+
+void dependency_destroyDependencyInfo(dm_service_dependency_info_pt info) {
+	if (info != NULL) {
+		free(info->filter);
+	}
+	free(info);
+}
+
+celix_status_t serviceDependency_setCallbackHandle(dm_service_dependency_pt dependency, void* handle) {
+	dependency->callbackHandle = handle;
+    return CELIX_SUCCESS;
+}
+
+static void* serviceDependency_getCallbackHandle(dm_service_dependency_pt dependency) {
+    return dependency->callbackHandle == NULL ? component_getImplementation(dependency->component) : dependency->callbackHandle;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/5992be15/framework/src/dm_service_dependency_impl.h
----------------------------------------------------------------------
diff --git a/framework/src/dm_service_dependency_impl.h b/framework/src/dm_service_dependency_impl.h
new file mode 100644
index 0000000..7026ebf
--- /dev/null
+++ b/framework/src/dm_service_dependency_impl.h
@@ -0,0 +1,104 @@
+/**
+ *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.
+ */
+/*
+ * dm_service_dependency_impl.h
+ *
+ *  \date       16 Oct 2015
+ *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright  Apache License, Version 2.0
+ */
+
+#ifndef DM_SERVICE_DEPENDENCY_IMPL_H_
+#define DM_SERVICE_DEPENDENCY_IMPL_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdbool.h>
+
+#include "dm_event.h"
+#include "service_tracker.h"
+#include "service_tracker_customizer.h"
+
+#include "dm_service_dependency.h"
+#include "dm_component.h"
+
+struct dm_service_dependency {
+	dm_component_pt component;
+	bool available;
+	bool instanceBound;
+	bool required;
+	dm_service_dependency_strategy_t strategy;
+
+	void* callbackHandle; //This handle can be set to be used instead of the component implementation
+	service_set_fpt set;
+	service_add_fpt add;
+	service_change_fpt change;
+	service_remove_fpt remove;
+	service_swap_fpt swap;
+
+	service_set_with_ref_fpt set_with_ref;
+	service_add_with_ref_fpt add_with_ref;
+	service_change_with_ref_fpt change_with_ref;
+	service_remove_with_ref_fpt remove_with_ref;
+	service_swap_with_ref_fpt swap_with_ref;
+
+	const void **autoConfigure;
+	celix_thread_mutex_t lock;
+
+	bool isStarted;
+
+	bool addCLanguageFilter;
+	char *tracked_service;
+	char *tracked_filter_unmodified;
+	char *tracked_filter;
+
+	service_tracker_pt tracker;
+	service_tracker_customizer_pt tracker_customizer;
+};
+
+celix_status_t serviceDependency_start(dm_service_dependency_pt dependency);
+celix_status_t serviceDependency_stop(dm_service_dependency_pt dependency);
+celix_status_t serviceDependency_setInstanceBound(dm_service_dependency_pt dependency, bool instanceBound);
+celix_status_t serviceDependency_setAutoConfig(dm_service_dependency_pt dependency, void **autoConfigure);
+celix_status_t serviceDependency_setAvailable(dm_service_dependency_pt dependency, bool available);
+
+celix_status_t serviceDependency_setComponent(dm_service_dependency_pt dependency, dm_component_pt component);
+//celix_status_t serviceDependency_removeComponent(dm_service_dependency_pt dependency, dm_component_pt component);
+
+celix_status_t serviceDependency_invokeSet(dm_service_dependency_pt dependency, dm_event_pt event);
+celix_status_t serviceDependency_invokeAdd(dm_service_dependency_pt dependency, dm_event_pt event);
+celix_status_t serviceDependency_invokeChange(dm_service_dependency_pt dependency, dm_event_pt event);
+celix_status_t serviceDependency_invokeRemove(dm_service_dependency_pt dependency, dm_event_pt event);
+celix_status_t serviceDependency_invokeSwap(dm_service_dependency_pt dependency, dm_event_pt event, dm_event_pt newEvent);
+celix_status_t serviceDependency_isAvailable(dm_service_dependency_pt dependency, bool *available);
+celix_status_t serviceDependency_isRequired(dm_service_dependency_pt dependency, bool *required);
+celix_status_t serviceDependency_isInstanceBound(dm_service_dependency_pt dependency, bool *instanceBound);
+celix_status_t serviceDependency_isAutoConfig(dm_service_dependency_pt dependency, bool *autoConfig);
+
+celix_status_t serviceDependency_getAutoConfig(dm_service_dependency_pt dependency, const void*** autoConfigure);
+celix_status_t serviceDependency_unlock(dm_service_dependency_pt dependency);
+celix_status_t serviceDependency_lock(dm_service_dependency_pt dependency);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* DM_SERVICE_DEPENDENCY_IMPL_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/5992be15/framework/src/framework.c
----------------------------------------------------------------------
diff --git a/framework/src/framework.c b/framework/src/framework.c
index 083fb81..eceff81 100644
--- a/framework/src/framework.c
+++ b/framework/src/framework.c
@@ -47,16 +47,28 @@
 #include "service_registration_private.h"
 #include "bundle_private.h"
 
-typedef celix_status_t (*create_function_pt)(bundle_context_pt context, void **userData);
-typedef celix_status_t (*start_function_pt)(void * handle, bundle_context_pt context);
-typedef celix_status_t (*stop_function_pt)(void * handle, bundle_context_pt context);
-typedef celix_status_t (*destroy_function_pt)(void * handle, bundle_context_pt context);
+typedef celix_status_t (*create_function_fp)(bundle_context_t *context, void **userData);
+typedef celix_status_t (*start_function_fp)(void *userData, bundle_context_t *context);
+typedef celix_status_t (*stop_function_fp)(void *userData, bundle_context_t *context);
+typedef celix_status_t (*destroy_function_fp)(void *userData, bundle_context_t *context);
+
+typedef celix_status_t (*dm_create_fp)(bundle_context_t *context, void ** userData);
+typedef celix_status_t (*dm_start_fp)(void * userData, bundle_context_pt context, dm_dependency_manager_pt manager);
+typedef celix_status_t (*dm_stop_fp)(void * userData, bundle_context_pt context, dm_dependency_manager_pt manager);
+typedef celix_status_t (*dm_destroy_fp)(void * userData, bundle_context_pt context, dm_dependency_manager_pt manager);
 
 struct activator {
     void * userData;
-    start_function_pt start;
-    stop_function_pt stop;
-    destroy_function_pt destroy;
+
+    create_function_fp create;
+    start_function_fp start;
+    stop_function_fp stop;
+    destroy_function_fp destroy;
+
+    dm_create_fp dmCreate;
+    dm_start_fp dmStart;
+    dm_stop_fp dmStop;
+    dm_destroy_fp dmDestroy;
 };
 
 celix_status_t framework_setBundleStateAndNotify(framework_pt framework, bundle_pt bundle, int state);
@@ -91,13 +103,15 @@ static celix_status_t framework_loadBundleLibraries(framework_pt framework, bund
 static celix_status_t framework_loadLibraries(framework_pt framework, const char* libraries, const char* activator, bundle_archive_pt archive, void **activatorHandle);
 static celix_status_t framework_loadLibrary(framework_pt framework, const char* library, bundle_archive_pt archive, void **handle);
 
-static celix_status_t frameworkActivator_start(void * userData, bundle_context_pt context);
-static celix_status_t frameworkActivator_stop(void * userData, bundle_context_pt context);
-static celix_status_t frameworkActivator_destroy(void * userData, bundle_context_pt context);
+static celix_status_t frameworkActivator_start(void * userData, bundle_context_t *context);
+static celix_status_t frameworkActivator_stop(void * userData, bundle_context_t *context);
+static celix_status_t frameworkActivator_destroy(void * userData, bundle_context_t *context);
 
 static void framework_autoStartConfiguredBundles(bundle_context_t *fwCtx);
 static void framework_autoStartConfiguredBundlesForList(bundle_context_t *fwCtx, const char *autoStart);
 
+static  celix_status_t framework_defaultDmStop(void * userData, bundle_context_pt context, dm_dependency_manager_pt manager);
+
 
 struct fw_refreshHelper {
     framework_pt framework;
@@ -281,7 +295,7 @@ celix_status_t framework_destroy(framework_pt framework) {
             bool systemBundle = false;
             bundle_isSystemBundle(bundle, &systemBundle);
             if (systemBundle) {
-                bundle_context_pt context = NULL;
+                bundle_context_t *context = NULL;
                 bundle_getContext(framework->bundle, &context);
                 bundleContext_destroy(context);
             }
@@ -452,20 +466,20 @@ celix_status_t fw_init(framework_pt framework) {
     status = CELIX_DO_IF(status, framework_setBundleStateAndNotify(framework, framework->bundle, OSGI_FRAMEWORK_BUNDLE_STARTING));
     status = CELIX_DO_IF(status, celixThreadCondition_init(&framework->shutdownGate, NULL));
 
-    bundle_context_pt context = NULL;
+    bundle_context_t *context = NULL;
     status = CELIX_DO_IF(status, bundleContext_create(framework, framework->logger, framework->bundle, &context));
     status = CELIX_DO_IF(status, bundle_setContext(framework->bundle, context));
     if (status == CELIX_SUCCESS) {
         activator_pt activator = NULL;
         activator = (activator_pt) calloc(1,(sizeof(*activator)));
         if (activator != NULL) {
-            bundle_context_pt context = NULL;
+            bundle_context_t *context = NULL;
             void * userData = NULL;
 
 			//create_function_pt create = NULL;
-			start_function_pt start = (start_function_pt) frameworkActivator_start;
-			stop_function_pt stop = (stop_function_pt) frameworkActivator_stop;
-			destroy_function_pt destroy = (destroy_function_pt) frameworkActivator_destroy;
+			start_function_fp start = (start_function_fp) frameworkActivator_start;
+			stop_function_fp stop = (stop_function_fp) frameworkActivator_stop;
+			destroy_function_fp destroy = (destroy_function_fp) frameworkActivator_destroy;
 
             activator->start = start;
             activator->stop = stop;
@@ -476,7 +490,7 @@ celix_status_t fw_init(framework_pt framework) {
             if (status == CELIX_SUCCESS) {
                 /* This code part is in principle dead, but in future it may do something.
                  * That's why it's outcommented and not deleted
-		if (create != NULL) {
+		        if (create != NULL) {
                     create(context, &userData);
                 }
                 */
@@ -726,7 +740,7 @@ celix_status_t fw_startBundle(framework_pt framework, bundle_pt bundle, int opti
 	celix_status_t status = CELIX_SUCCESS;
 
 	linked_list_pt wires = NULL;
-	bundle_context_pt context = NULL;
+	bundle_context_t *context = NULL;
 	bundle_state_e state;
 	module_pt module = NULL;
 	activator_pt activator = NULL;
@@ -783,15 +797,35 @@ celix_status_t fw_startBundle(framework_pt framework, bundle_pt bundle, int opti
                         status = CELIX_ENOMEM;
                     } else {
                         void * userData = NULL;
-                        bundle_context_pt context;
-                        create_function_pt create = (create_function_pt) fw_getSymbol((handle_t) bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_CREATE);
-                        start_function_pt start = (start_function_pt) fw_getSymbol((handle_t) bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_START);
-                        stop_function_pt stop = (stop_function_pt) fw_getSymbol((handle_t) bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_STOP);
-                        destroy_function_pt destroy = (destroy_function_pt) fw_getSymbol((handle_t) bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_DESTROY);
-
+                        bundle_context_t *context;
+                        create_function_fp create = (create_function_fp) fw_getSymbol((handle_t) bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_CREATE);
+                        start_function_fp start = (start_function_fp) fw_getSymbol((handle_t) bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_START);
+                        stop_function_fp stop = (stop_function_fp) fw_getSymbol((handle_t) bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_STOP);
+                        destroy_function_fp destroy = (destroy_function_fp) fw_getSymbol((handle_t) bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_ACTIVATOR_DESTROY);
+
+                        dm_create_fp dmCreate = fw_getSymbol((handle_t)bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_DM_ACTIVATOR_CREATE);
+                        dm_start_fp dmStart = fw_getSymbol((handle_t)bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_DM_ACTIVATOR_START);
+                        dm_stop_fp dmStop = framework_defaultDmStop;
+                        dm_destroy_fp dmDestroy = fw_getSymbol((handle_t)bundle_getHandle(bundle), OSGI_FRAMEWORK_BUNDLE_DM_ACTIVATOR_DESTROY);
+
+                        activator->create = create;
                         activator->start = start;
                         activator->stop = stop;
                         activator->destroy = destroy;
+
+                        activator->dmCreate = dmCreate;
+                        activator->dmStart = dmStart;
+                        activator->dmStop = dmStop;
+                        activator->dmDestroy = dmDestroy;
+
+                        if (activator->dmCreate != NULL) {
+                            //only allow one activator, if dm is used -> set other to NULL
+                            activator->create = NULL;
+                            activator->start = NULL;
+                            activator->stop = NULL;
+                            activator->destroy = NULL;
+                        }
+
                         status = CELIX_DO_IF(status, bundle_setActivator(bundle, activator));
 
                         status = CELIX_DO_IF(status, framework_setBundleStateAndNotify(framework, bundle, OSGI_FRAMEWORK_BUNDLE_STARTING));
@@ -805,11 +839,19 @@ celix_status_t fw_startBundle(framework_pt framework, bundle_pt bundle, int opti
                                 if (status == CELIX_SUCCESS) {
                                     activator->userData = userData;
                                 }
+                            } else if (dmCreate != NULL) {
+                                status = CELIX_DO_IF(status, dmCreate(context, &userData));
+                                if (status == CELIX_SUCCESS) {
+                                    activator->userData = userData;
+                                }
                             }
                         }
                         if (status == CELIX_SUCCESS) {
                             if (start != NULL) {
                                 status = CELIX_DO_IF(status, start(userData, context));
+                            } else if (dmStart != NULL) {
+                                dm_dependency_manager_t *mng = bundleContext_getDependencyManager(context);
+                                status = CELIX_DO_IF(status, dmStart(userData, context, mng));
                             }
                         }
 
@@ -922,7 +964,7 @@ celix_status_t fw_stopBundle(framework_pt framework, bundle_pt bundle, bool reco
 	celix_status_t status = CELIX_SUCCESS;
 	bundle_state_e state;
     activator_pt activator = NULL;
-    bundle_context_pt context = NULL;
+    bundle_context_t *context = NULL;
     bool wasActive = false;
     long id = 0;
     char *error = NULL;
@@ -973,11 +1015,17 @@ celix_status_t fw_stopBundle(framework_pt framework, bundle_pt bundle, bool reco
 	        if (status == CELIX_SUCCESS) {
                 if (activator->stop != NULL) {
                     status = CELIX_DO_IF(status, activator->stop(activator->userData, context));
+                } else if (activator->dmStop != NULL) {
+                    dm_dependency_manager_t *mng = bundleContext_getDependencyManager(context);
+                    status = CELIX_DO_IF(status, activator->dmStop(activator->userData, context, mng));
                 }
 	        }
             if (status == CELIX_SUCCESS) {
                 if (activator->destroy != NULL) {
                     status = CELIX_DO_IF(status, activator->destroy(activator->userData, context));
+                } else if (activator->dmDestroy != NULL) {
+                    dm_dependency_manager_t *mng = bundleContext_getDependencyManager(context);
+                    status = CELIX_DO_IF(status, activator->dmDestroy(activator->userData, context, mng));
                 }
 	        }
 
@@ -1345,7 +1393,7 @@ celix_status_t fw_registerService(framework_pt framework, service_registration_p
                 celixThreadMutex_lock(&framework->serviceListenersLock);
                 for (i = 0; i < arrayList_size(framework->serviceListeners); i++) {
                     fw_service_listener_pt listener =(fw_service_listener_pt) arrayList_get(framework->serviceListeners, i);
-                    bundle_context_pt context = NULL;
+                    bundle_context_t *context = NULL;
                     listener_hook_info_pt info = NULL;
                     bundle_context_pt lContext = NULL;
 
@@ -1484,7 +1532,7 @@ void fw_addServiceListener(framework_pt framework, bundle_pt bundle, service_lis
 	unsigned int i;
 
 	fw_service_listener_pt fwListener = (fw_service_listener_pt) calloc(1, sizeof(*fwListener));
-	bundle_context_pt context = NULL;
+	bundle_context_t *context = NULL;
 
 	fwListener->bundle = bundle;
     arrayList_create(&fwListener->retainedReferences);
@@ -1531,7 +1579,7 @@ void fw_addServiceListener(framework_pt framework, bundle_pt bundle, service_lis
 void fw_removeServiceListener(framework_pt framework, bundle_pt bundle, service_listener_pt listener) {
 	fw_service_listener_pt match = NULL;
 
-	bundle_context_pt context;
+	bundle_context_t *context;
 	bundle_getContext(bundle, &context);
 
     int i;
@@ -2523,12 +2571,12 @@ celix_status_t fw_invokeFrameworkListener(framework_pt framework, framework_list
 	return ret;
 }
 
-static celix_status_t frameworkActivator_start(void * userData, bundle_context_pt context) {
+static celix_status_t frameworkActivator_start(void * userData, bundle_context_t *context) {
 	// nothing to do
 	return CELIX_SUCCESS;
 }
 
-static celix_status_t frameworkActivator_stop(void * userData, bundle_context_pt context) {
+static celix_status_t frameworkActivator_stop(void * userData, bundle_context_t *context) {
     celix_status_t status = CELIX_SUCCESS;
 	framework_pt framework;
 
@@ -2548,7 +2596,7 @@ static celix_status_t frameworkActivator_stop(void * userData, bundle_context_pt
 	return status;
 }
 
-static celix_status_t frameworkActivator_destroy(void * userData, bundle_context_pt context) {
+static celix_status_t frameworkActivator_destroy(void * userData, bundle_context_t *context) {
 	return CELIX_SUCCESS;
 }
 
@@ -2702,3 +2750,8 @@ static celix_status_t framework_loadLibrary(framework_pt framework, const char *
 
     return status;
 }
+
+static  celix_status_t framework_defaultDmStop(void * userData __attribute__((unused)), bundle_context_pt context __attribute__((unused)), dm_dependency_manager_pt manager) {
+    dependencyManager_removeAllComponents(manager);
+    return CELIX_SUCCESS;
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/5992be15/shell/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt
index dbc9916..622e0ee 100644
--- a/shell/CMakeLists.txt
+++ b/shell/CMakeLists.txt
@@ -42,6 +42,7 @@ if (SHELL)
           src/log_command
           src/inspect_command
           src/help_command
+		  src/dm_shell_list_command
 	)
 	target_include_directories(shell PRIVATE src)
         target_include_directories(shell SYSTEM PRIVATE	${CURL_INCLUDE_DIRS})

http://git-wip-us.apache.org/repos/asf/celix/blob/5992be15/shell/include/dm_shell_list_command.h
----------------------------------------------------------------------
diff --git a/shell/include/dm_shell_list_command.h b/shell/include/dm_shell_list_command.h
new file mode 100644
index 0000000..6ab0581
--- /dev/null
+++ b/shell/include/dm_shell_list_command.h
@@ -0,0 +1,42 @@
+/**
+ *Licensed to the Apache Software Foundation (ASF) under one
+ *or more contributor license agreements.  See the NOTICE file
+ *distributed with this work for additional information
+ *regarding copyright ownership.  The ASF licenses this file
+ *to you under the Apache License, Version 2.0 (the
+ *"License"); you may not use this file except in compliance
+ *with the License.  You may obtain a copy of the License at
+ *
+ *  http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *Unless required by applicable law or agreed to in writing,
+ *software distributed under the License is distributed on an
+ *"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ *specific language governing permissions and limitations
+ *under the License.
+ */
+
+#ifndef DM_SHELL_LIST_COMMAND_H_
+#define DM_SHELL_LIST_COMMAND_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include "command.h"
+
+typedef struct dm_command_handle {
+    bundle_context_pt context;
+    bool useColors;
+} dm_command_handle_t;
+
+void dmListCommand_execute(dm_command_handle_t* handle, char * line, FILE *out, FILE *err);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //DM_SHELL_LSIT_COMMAND_H_
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/celix/blob/5992be15/shell/src/activator.c
----------------------------------------------------------------------
diff --git a/shell/src/activator.c b/shell/src/activator.c
index ac298d8..ddccff6 100644
--- a/shell/src/activator.c
+++ b/shell/src/activator.c
@@ -32,7 +32,7 @@
 #include "service_tracker.h"
 #include "constants.h"
 
-#define NUMBER_OF_COMMANDS 10
+#define NUMBER_OF_COMMANDS 11
 
 struct command {
     celix_status_t (*exec)(void *handle, char *commandLine, FILE *out, FILE *err);
@@ -139,6 +139,13 @@ celix_status_t bundleActivator_create(bundle_context_pt context_ptr, void **_ppt
                         .usage = "inspect (service) (capability|requirement) [<id> ...]"
                 };
         instance_ptr->std_commands[9] =
+                (struct command) {
+                        .exec = dmListCommand_execute,
+                        .name = "dm",
+                        .description = "Gives an overview of the component managemed by a dependency manager.",
+                        .usage = "dm [f|full] [<Bundle ID> [<Bundle ID> [...]]]"
+                };
+        instance_ptr->std_commands[10] =
                 (struct command) { NULL, NULL, NULL, NULL, NULL, NULL, NULL }; /*marker for last element*/
 
         unsigned int i = 0;

http://git-wip-us.apache.org/repos/asf/celix/blob/5992be15/shell/src/dm_shell_list_command.c
----------------------------------------------------------------------
diff --git a/shell/src/dm_shell_list_command.c b/shell/src/dm_shell_list_command.c
new file mode 100644
index 0000000..4fc7cf3
--- /dev/null
+++ b/shell/src/dm_shell_list_command.c
@@ -0,0 +1,189 @@
+/**
+ *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.
+ */
+
+#include <stdlib.h>
+#include <string.h>
+#include <shell_constants.h>
+#include "bundle_context.h"
+#include "dm_dependency_manager.h"
+
+
+static const char * const OK_COLOR = "\033[92m";
+static const char * const WARNING_COLOR = "\033[93m";
+static const char * const NOK_COLOR = "\033[91m";
+static const char * const END_COLOR = "\033[m";
+
+static void parseCommandLine(const char*line, array_list_pt *requestedBundleIds, bool *fullInfo, FILE *err) {
+    *fullInfo = false;
+    char *str = strdup(line);
+    // skip first argument since this is the command
+    strtok(str," ");
+    char* tok = strtok(NULL," ");
+    *requestedBundleIds = NULL;
+    arrayList_create(requestedBundleIds);
+    while (tok) {
+        if (tok[0] == 'f') { // f or full argument => show full info
+            *fullInfo = true;
+        } else if ( (tok[0] >= '0') && (tok[0] <= '9')) { // bundle id
+            long *id = malloc(sizeof(*id));
+            *id = strtol(tok, NULL, 10);
+            arrayList_add(*requestedBundleIds, id);
+        } else {
+            fprintf (err, "DM: Skipping unknown argument: %s", tok );
+        }
+        tok = strtok(NULL," ");
+    }
+    free (str);
+}
+
+static void destroyBundleIdList(array_list_pt ids) {
+    unsigned int size = arrayList_size(ids);
+    for (unsigned int i = 0; i < size; i++) {
+        free(arrayList_get(ids, i));
+    }
+    arrayList_destroy(ids);
+}
+
+/*
+ * Check if the ID is in the array list. If  arrayist is empty also true is returned so that all
+ * bundles are shown
+ */
+static bool is_bundleId_in_list(array_list_pt ids, long id) {
+    unsigned int size = arrayList_size(ids);
+    bool result = false;
+    if (size == 0) {
+        result = true;
+    }
+    for(unsigned int i = 0; i < size; ++i) {
+        if (*((long*)arrayList_get(ids, i))  == id) {
+            result = true;
+            break;
+        }
+    }
+    return result;
+}
+
+
+static void printFullInfo(FILE *out, bool colors, dm_component_info_pt compInfo) {
+    const char *startColors = "";
+    const char *endColors = "";
+    if (colors) {
+        startColors = compInfo->active ? OK_COLOR : NOK_COLOR;
+        endColors = END_COLOR;
+    }
+    fprintf(out, "Component: Name=%s\n|- ID=%s, %sActive=%s%s, State=%s\n", compInfo->name, compInfo->id,
+            startColors, compInfo->active ? "true " : "false", endColors, compInfo->state);
+    fprintf(out, "|- Interfaces (%d):\n", arrayList_size(compInfo->interfaces));
+    for (unsigned int interfCnt = 0; interfCnt < arrayList_size(compInfo->interfaces); interfCnt++) {
+        dm_interface_info_pt intfInfo = arrayList_get(compInfo->interfaces, interfCnt);
+        fprintf(out, "   |- Interface: %s\n", intfInfo->name);
+
+        hash_map_iterator_t iter = hashMapIterator_construct((hash_map_pt) intfInfo->properties);
+        char *key = NULL;
+        while ((key = hashMapIterator_nextKey(&iter)) != NULL) {
+            fprintf(out, "      | %15s = %s\n", key, properties_get(intfInfo->properties, key));
+        }
+    }
+
+    fprintf(out, "|- Dependencies (%d):\n", arrayList_size(compInfo->dependency_list));
+    for (unsigned int depCnt = 0; depCnt < arrayList_size(compInfo->dependency_list); depCnt++) {
+        dm_service_dependency_info_pt dependency;
+        dependency = arrayList_get(compInfo->dependency_list, depCnt);
+        const char *depStartColors = "";
+        const char *depEndColors = "";
+        if (colors) {
+            if (dependency->required) {
+                depStartColors = dependency->available ? OK_COLOR : NOK_COLOR;
+            } else {
+                depStartColors = dependency->available ? OK_COLOR : WARNING_COLOR;
+            }
+
+            depEndColors = END_COLOR;
+        }
+        fprintf(out, "   |- Dependency: %sAvailable = %s%s, Required = %s, Filter = %s\n", depStartColors,
+                dependency->available ? "true " : "false", depEndColors,
+                dependency->required ? "true " : "false", dependency->filter);
+    }
+    fprintf(out, "\n");
+
+}
+
+static void printBasicInfo(FILE *out, bool colors, dm_component_info_pt compInfo) {
+    const char *startColors = "";
+    const char *endColors = "";
+    if (colors) {
+        startColors = compInfo->active ? OK_COLOR : NOK_COLOR;
+        endColors = END_COLOR;
+    }
+    fprintf(out, "Component: Name=%s, ID=%s, %sActive=%s%s, State=%s\n", compInfo->name, compInfo->id,
+            startColors, compInfo->active ? "true " : "false", endColors, compInfo->state);
+
+}
+
+celix_status_t dmListCommand_execute(void* handle, char * line, FILE *out, FILE *err) {
+    bundle_context_t *ctx = handle;
+
+    array_list_t *bundles = NULL;
+    bundleContext_getBundles(ctx, &bundles);
+
+    const char *config = NULL;
+    bundleContext_getPropertyWithDefault(ctx, SHELL_USE_ANSI_COLORS, SHELL_USE_ANSI_COLORS_DEFAULT_VALUE, &config);
+    bool useColors = config != NULL && strncmp("true", config, 5) == 0;
+
+    array_list_pt bundleIds = NULL;
+    bool fullInfo = false;
+    parseCommandLine(line, &bundleIds, &fullInfo, err);
+
+    if (bundles != NULL) {
+        unsigned int size = arrayList_size(bundles);
+        for (unsigned int i = 0; i < size; ++i) {
+            long bndId = -1;
+            bundle_t *bnd = arrayList_get(bundles, i);
+            bundle_getBundleId(bnd, &bndId);
+            if (!is_bundleId_in_list(bundleIds, bndId)) {
+                continue;
+            }
+            bundle_context_t *bndCtx = NULL;
+            bundle_getContext(bnd, &bndCtx);
+            if (bndCtx != NULL) {
+                dm_dependency_manager_t *mng = bundleContext_getDependencyManager(bndCtx);
+                dm_dependency_manager_info_t *info = NULL;
+                dependencyManager_getInfo(mng, &info);
+                if (info != NULL) {
+                    fprintf(out, "[Bundle: %ld]\n", bndId);
+                    for (unsigned int cmpCnt = 0; cmpCnt < arrayList_size(info->components); cmpCnt++) {
+                        dm_component_info_pt compInfo = arrayList_get(info->components, cmpCnt);
+                        if (fullInfo) {
+                            printFullInfo(out, useColors, compInfo);
+                        } else {
+                            printBasicInfo(out, useColors, compInfo);
+                        }
+                    }
+                    fprintf(out, "\n");
+                    dependencyManager_destroyInfo(mng, info);
+                }
+
+            }
+        }
+    }
+
+    destroyBundleIdList(bundleIds);
+
+    return CELIX_SUCCESS;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/5992be15/shell/src/std_commands.h
----------------------------------------------------------------------
diff --git a/shell/src/std_commands.h b/shell/src/std_commands.h
index ef7f37e..2ac0959 100644
--- a/shell/src/std_commands.h
+++ b/shell/src/std_commands.h
@@ -40,5 +40,7 @@ celix_status_t updateCommand_execute(void *handle, char * commandline, FILE *out
 celix_status_t logCommand_execute(void *handle, char * commandline, FILE *outStream, FILE *errStream);
 celix_status_t inspectCommand_execute(void *handle, char * commandline, FILE *outStream, FILE *errStream);
 celix_status_t helpCommand_execute(void *handle, char * commandline, FILE *outStream, FILE *errStream);
+celix_status_t dmListCommand_execute(void* handle, char * line, FILE *out, FILE *err);
+
 
 #endif


Mime
View raw message