You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2018/01/30 19:30:16 UTC

[32/54] [abbrv] celix git commit: Merge commit 'ee29b00d7a80af43d351e61916d5a5aa90f97e46' into feature/CELIX-417-cmake-refactor

http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/dependency_manager/src/dm_component_impl.c
----------------------------------------------------------------------
diff --cc dependency_manager/src/dm_component_impl.c
index 13a2ee0,0000000..e0d9f52
mode 100644,000000..100644
--- a/dependency_manager/src/dm_component_impl.c
+++ b/dependency_manager/src/dm_component_impl.c
@@@ -1,1442 -1,0 +1,1451 @@@
 +/**
 + *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_component_impl.c
 + *
 + *  \date       9 Oct 2014
 + *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
 + *  \copyright  Apache License, Version 2.0
 + */
 +
 +#include <stdarg.h>
 +#include <stdlib.h>
 +#include <string.h>
 +
 +#include "constants.h"
 +#include "filter.h"
 +#include "dm_component_impl.h"
 +
 +
 +typedef struct dm_executor_struct * dm_executor_pt;
 +
 +struct dm_component_struct {
 +    char id[DM_COMPONENT_MAX_ID_LENGTH];
 +    char name[DM_COMPONENT_MAX_NAME_LENGTH];
 +    bundle_context_pt context;
-     array_list_pt dm_interfaces;
++    array_list_pt dm_interfaces;  //protected by mutex
 +
 +    void* implementation;
 +
 +    init_fpt callbackInit;
 +    start_fpt callbackStart;
 +    stop_fpt callbackStop;
 +    deinit_fpt callbackDeinit;
 +
 +    array_list_pt dependencies; //protected by mutex
 +    pthread_mutex_t mutex;
 +
 +    dm_component_state_t state;
 +    bool isStarted;
 +    bool active;
 +
 +    bool setCLanguageProperty;
 +
 +    hash_map_pt dependencyEvents; //protected by mutex
 +
 +    dm_executor_pt executor;
 +};
 +
 +typedef struct dm_interface_struct {
 +    char* serviceName;
 +    const void* service;
 +    properties_pt properties;
 +    service_registration_pt registration;
 +} dm_interface_t;
 +
 +struct dm_executor_struct {
 +    pthread_t runningThread;
 +    bool runningThreadSet;
 +    linked_list_pt workQueue;
 +    pthread_mutex_t mutex;
 +};
 +
 +typedef struct dm_executor_task_struct {
 +    dm_component_pt component;
 +    void (*command)(void *command_ptr, void *data);
 +    void *data;
 +} dm_executor_task_t;
 +
 +typedef struct dm_handle_event_type_struct {
 +	dm_service_dependency_pt dependency;
 +	dm_event_pt event;
 +	dm_event_pt newEvent;
 +} *dm_handle_event_type_pt;
 +
 +static celix_status_t executor_runTasks(dm_executor_pt executor, pthread_t  currentThread __attribute__((unused)));
 +static celix_status_t executor_execute(dm_executor_pt executor);
 +static celix_status_t executor_executeTask(dm_executor_pt executor, dm_component_pt component, void (*command), void *data);
 +static celix_status_t executor_schedule(dm_executor_pt executor, dm_component_pt component, void (*command), void *data);
 +static celix_status_t executor_create(dm_component_pt component __attribute__((unused)), dm_executor_pt *executor);
 +static void executor_destroy(dm_executor_pt executor);
 +
 +static celix_status_t component_invokeRemoveRequiredDependencies(dm_component_pt component);
 +static celix_status_t component_invokeRemoveInstanceBoundDependencies(dm_component_pt component);
 +static celix_status_t component_invokeRemoveOptionalDependencies(dm_component_pt component);
 +static celix_status_t component_registerServices(dm_component_pt component);
 +static celix_status_t component_unregisterServices(dm_component_pt component);
 +static celix_status_t component_invokeAddOptionalDependencies(dm_component_pt component);
 +static celix_status_t component_invokeAddRequiredInstanceBoundDependencies(dm_component_pt component);
 +static celix_status_t component_invokeAddRequiredDependencies(dm_component_pt component);
 +static celix_status_t component_invokeAutoConfigInstanceBoundDependencies(dm_component_pt component);
 +static celix_status_t component_invokeAutoConfigDependencies(dm_component_pt component);
 +static celix_status_t component_configureImplementation(dm_component_pt component, dm_service_dependency_pt dependency);
 +static celix_status_t component_allInstanceBoundAvailable(dm_component_pt component, bool *available);
 +static celix_status_t component_allRequiredAvailable(dm_component_pt component, bool *available);
 +static celix_status_t component_performTransition(dm_component_pt component, dm_component_state_t oldState, dm_component_state_t newState, bool *transition);
 +static celix_status_t component_calculateNewState(dm_component_pt component, dm_component_state_t currentState, dm_component_state_t *newState);
 +static celix_status_t component_handleChange(dm_component_pt component);
 +static celix_status_t component_startDependencies(dm_component_pt component __attribute__((unused)), array_list_pt dependencies);
 +static celix_status_t component_getDependencyEvent(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt *event_pptr);
 +static celix_status_t component_updateInstance(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event, bool update, bool add);
 +
 +static celix_status_t component_addTask(dm_component_pt component, dm_service_dependency_pt dep);
 +static celix_status_t component_startTask(dm_component_pt component, void * data __attribute__((unused)));
 +static celix_status_t component_stopTask(dm_component_pt component, void * data __attribute__((unused)));
 +static celix_status_t component_removeTask(dm_component_pt component, dm_service_dependency_pt dependency);
 +static celix_status_t component_handleEventTask(dm_component_pt component, dm_handle_event_type_pt data);
 +
 +static celix_status_t component_handleAdded(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event);
 +static celix_status_t component_handleChanged(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event);
 +static celix_status_t component_handleRemoved(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event);
 +static celix_status_t component_handleSwapped(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event, dm_event_pt newEvent);
 +
 +static celix_status_t component_suspend(dm_component_pt component, dm_service_dependency_pt dependency);
 +static celix_status_t component_resume(dm_component_pt component, dm_service_dependency_pt dependency);
 +
 +celix_status_t component_create(bundle_context_pt context, const char *name, dm_component_pt *out) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    dm_component_pt component = calloc(1, sizeof(*component));
 +
 +    if (!component) {
 +        status = CELIX_ENOMEM;
 +    } else {
 +        snprintf(component->id, DM_COMPONENT_MAX_ID_LENGTH, "%p", component);
 +        snprintf(component->name, DM_COMPONENT_MAX_NAME_LENGTH, "%s", name == NULL ? "n/a" : name);
 +
 +        component->context = context;
 +
 +	    arrayList_create(&component->dm_interfaces);
 +        arrayList_create(&(component)->dependencies);
 +        pthread_mutex_init(&(component)->mutex, NULL);
 +
 +        component->implementation = NULL;
 +
 +        component->callbackInit = NULL;
 +        component->callbackStart = NULL;
 +        component->callbackStop = NULL;
 +        component->callbackDeinit = NULL;
 +
 +        component->state = DM_CMP_STATE_INACTIVE;
 +        component->isStarted = false;
 +        component->active = false;
 +
 +        component->setCLanguageProperty = false;
 +
 +        component->dependencyEvents = hashMap_create(NULL, NULL, NULL, NULL);
 +
 +        component->executor = NULL;
 +        executor_create(component, &component->executor);
 +    }
 +
 +    if (status == CELIX_SUCCESS) {
 +        *out = component;
 +    }
 +
 +    return status;
 +}
 +
 +void component_destroy(dm_component_pt component) {
 +	if (component) {
 +		unsigned int i;
 +
 +		for (i = 0; i < arrayList_size(component->dm_interfaces); i++) {
 +		    dm_interface_t *interface = arrayList_get(component->dm_interfaces, i);
 +
 +			if(interface->properties!=NULL){
 +				properties_destroy(interface->properties);
 +			}
 +		    free (interface->serviceName);
 +            free (interface);
 +		}
 +		arrayList_destroy(component->dm_interfaces);
 +
 +		executor_destroy(component->executor);
 +
 +		hash_map_iterator_pt iter = hashMapIterator_create(component->dependencyEvents);
 +		while(hashMapIterator_hasNext(iter)){
 +			hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
 +			dm_service_dependency_pt sdep = (dm_service_dependency_pt)hashMapEntry_getKey(entry);
 +			array_list_pt eventList = (array_list_pt)hashMapEntry_getValue(entry);
 +			serviceDependency_destroy(&sdep);
 +			arrayList_destroy(eventList);
 +		}
 +		hashMapIterator_destroy(iter);
 +
 +		hashMap_destroy(component->dependencyEvents, false, false);
 +
 +		arrayList_destroy(component->dependencies);
 +		pthread_mutex_destroy(&component->mutex);
 +
 +		free(component);
 +	}
 +}
 +
 +celix_status_t component_addServiceDependency(dm_component_pt component, dm_service_dependency_pt dep) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +	executor_executeTask(component->executor, component, component_addTask, dep);
 +
 +    return status;
 +}
 +
 +
 +static celix_status_t component_addTask(dm_component_pt component, dm_service_dependency_pt dep) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    array_list_pt bounds = NULL;
 +    arrayList_create(&bounds);
 +
 +    array_list_pt events = NULL;
 +    arrayList_createWithEquals(event_equals, &events);
 +
 +    pthread_mutex_lock(&component->mutex);
 +    hashMap_put(component->dependencyEvents, dep, events);
 +    arrayList_add(component->dependencies, dep);
 +    pthread_mutex_unlock(&component->mutex);
 +
 +    serviceDependency_setComponent(dep, component);
 +
 +    if (component->state != DM_CMP_STATE_INACTIVE) {
 +        serviceDependency_setInstanceBound(dep, true);
 +        arrayList_add(bounds, dep);
 +    }
 +    component_startDependencies(component, bounds);
 +    component_handleChange(component);
 +
 +    arrayList_destroy(bounds);
 +
 +    return status;
 +}
 +
 +dm_component_state_t component_currentState(dm_component_pt cmp) {
 +    return cmp->state;
 +}
 +
 +void * component_getImplementation(dm_component_pt cmp) {
 +    return cmp->implementation;
 +}
 +
 +const char * component_getName(dm_component_pt cmp) {
 +    return cmp->name;
 +}
 +
 +celix_status_t component_removeServiceDependency(dm_component_pt component, dm_service_dependency_pt dependency) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    executor_executeTask(component->executor, component, component_removeTask, dependency);
 +
 +    return status;
 +}
 +
 +celix_status_t component_removeTask(dm_component_pt component, dm_service_dependency_pt dependency) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    pthread_mutex_lock(&component->mutex);
 +    arrayList_removeElement(component->dependencies, dependency);
 +    pthread_mutex_unlock(&component->mutex);
 +
 +    if (component->state != DM_CMP_STATE_INACTIVE) {
 +        serviceDependency_stop(dependency);
 +    }
 +
 +    pthread_mutex_lock(&component->mutex);
 +    array_list_pt events = hashMap_remove(component->dependencyEvents, dependency);
 +    pthread_mutex_unlock(&component->mutex);
 +
 +	serviceDependency_destroy(&dependency);
 +
 +    while (!arrayList_isEmpty(events)) {
 +    	dm_event_pt event = arrayList_remove(events, 0);
 +    	event_destroy(&event);
 +    }
 +    arrayList_destroy(events);
 +
 +    component_handleChange(component);
 +
 +    return status;
 +}
 +
 +celix_status_t component_start(dm_component_pt component) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    component->active = true;
 +    executor_executeTask(component->executor, component, component_startTask, NULL);
 +
 +    return status;
 +}
 +
 +celix_status_t component_startTask(dm_component_pt component, void  *data __attribute__((unused))) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    component->isStarted = true;
 +    component_handleChange(component);
 +
 +    return status;
 +}
 +
 +celix_status_t component_stop(dm_component_pt component) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    component->active = false;
 +    executor_executeTask(component->executor, component, component_stopTask, NULL);
 +
 +    return status;
 +}
 +
 +celix_status_t component_stopTask(dm_component_pt component, void *data __attribute__((unused))) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    component->isStarted = false;
 +    component_handleChange(component);
 +    component->active = false;
 +
 +    return status;
 +}
 +
 +celix_status_t component_setCLanguageProperty(dm_component_pt component, bool setCLangProp) {
 +    component->setCLanguageProperty = setCLangProp;
 +    return CELIX_SUCCESS;
 +}
 +
 +celix_status_t component_addInterface(dm_component_pt component, const char* serviceName, const char* serviceVersion, const void* service, properties_pt properties) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
-     if (component->active) {
-         return CELIX_ILLEGAL_STATE;
-     } else {
-         dm_interface_t *interface = (dm_interface_t *) calloc(1, sizeof(*interface));
-         char *name = strdup(serviceName);
++    dm_interface_t *interface = (dm_interface_t *) calloc(1, sizeof(*interface));
++    char *name = strdup(serviceName);
 +
-         if (properties == NULL) {
-             properties = properties_create();
-         }
++    if (properties == NULL) {
++        properties = properties_create();
++    }
 +
-         if ((properties_get(properties, CELIX_FRAMEWORK_SERVICE_VERSION) == NULL) && (serviceVersion != NULL)) {
-             properties_set(properties, CELIX_FRAMEWORK_SERVICE_VERSION, serviceVersion);
-         }
++    if ((properties_get(properties, CELIX_FRAMEWORK_SERVICE_VERSION) == NULL) && (serviceVersion != NULL)) {
++        properties_set(properties, CELIX_FRAMEWORK_SERVICE_VERSION, serviceVersion);
++    }
 +
-         if (component->setCLanguageProperty && properties_get(properties, CELIX_FRAMEWORK_SERVICE_LANGUAGE) == NULL) { //always set default lang to C
-             properties_set(properties, CELIX_FRAMEWORK_SERVICE_LANGUAGE, CELIX_FRAMEWORK_SERVICE_C_LANGUAGE);
-         }
++    if (component->setCLanguageProperty && properties_get(properties, CELIX_FRAMEWORK_SERVICE_LANGUAGE) == NULL) { //always set default lang to C
++        properties_set(properties, CELIX_FRAMEWORK_SERVICE_LANGUAGE, CELIX_FRAMEWORK_SERVICE_C_LANGUAGE);
++    }
 +
-         if (interface && name) {
-             interface->serviceName = name;
-             interface->service = service;
-             interface->properties = properties;
-             interface->registration = NULL;
-             arrayList_add(component->dm_interfaces, interface);
-         } else {
-             free(interface);
-             free(name);
-             status = CELIX_ENOMEM;
++    if (interface && name) {
++        interface->serviceName = name;
++        interface->service = service;
++        interface->properties = properties;
++        interface->registration = NULL;
++        celixThreadMutex_lock(&component->mutex);
++        arrayList_add(component->dm_interfaces, interface);
++        celixThreadMutex_unlock(&component->mutex);
++        if (component->state == DM_CMP_STATE_TRACKING_OPTIONAL) {
++            component_registerServices(component);
 +        }
++    } else {
++        free(interface);
++        free(name);
++        status = CELIX_ENOMEM;
 +    }
 +
 +    return status;
 +}
 +
++
 +celix_status_t component_getInterfaces(dm_component_pt component, array_list_pt *out) {
 +    celix_status_t status = CELIX_SUCCESS;
 +    array_list_pt names = NULL;
 +    arrayList_create(&names);
 +    celixThreadMutex_lock(&component->mutex);
 +    int size = arrayList_size(component->dm_interfaces);
 +    int i;
 +    for (i = 0; i < size; i += 1) {
 +        dm_interface_info_pt info = calloc(1, sizeof(*info));
 +        dm_interface_t *interface = arrayList_get(component->dm_interfaces, i);
 +        info->name = strdup(interface->serviceName);
 +        properties_copy(interface->properties, &info->properties);
 +        arrayList_add(names, info);
 +    }
 +    celixThreadMutex_unlock(&component->mutex);
 +
 +    if (status == CELIX_SUCCESS) {
 +        *out = names;
 +    }
 +
 +    return status;
 +}
 +
 +celix_status_t component_handleEvent(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	dm_handle_event_type_pt data = calloc(1, sizeof(*data));
 +	data->dependency = dependency;
 +	data->event = event;
 +	data->newEvent = NULL;
 +
 +	status = executor_executeTask(component->executor, component, component_handleEventTask, data);
 +//	component_handleEventTask(component, data);
 +
 +	return status;
 +}
 +
 +celix_status_t component_handleEventTask(dm_component_pt component, dm_handle_event_type_pt data) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	switch (data->event->event_type) {
 +		case DM_EVENT_ADDED:
 +			component_handleAdded(component,data->dependency, data->event);
 +			break;
 +		case DM_EVENT_CHANGED:
 +			component_handleChanged(component,data->dependency, data->event);
 +			break;
 +		case DM_EVENT_REMOVED:
 +			component_handleRemoved(component,data->dependency, data->event);
 +			break;
 +		case DM_EVENT_SWAPPED:
 +			component_handleSwapped(component,data->dependency, data->event, data->newEvent);
 +			break;
 +		default:
 +			break;
 +	}
 +
 +	free(data);
 +
 +	return status;
 +}
 +
 +static celix_status_t component_suspend(dm_component_pt component, dm_service_dependency_pt dependency) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	dm_service_dependency_strategy_t strategy;
 +	serviceDependency_getStrategy(dependency, &strategy);
 +	if (strategy == DM_SERVICE_DEPENDENCY_STRATEGY_SUSPEND &&  component->callbackStop != NULL) {
 +		status = component->callbackStop(component->implementation);
 +	}
 +
 +	return status;
 +}
 +
 +static celix_status_t component_resume(dm_component_pt component, dm_service_dependency_pt dependency) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	dm_service_dependency_strategy_t strategy;
 +	serviceDependency_getStrategy(dependency, &strategy);
 +	if (strategy == DM_SERVICE_DEPENDENCY_STRATEGY_SUSPEND &&  component->callbackStop != NULL) {
 +		status = component->callbackStart(component->implementation);
 +	}
 +
 +	return status;
 +}
 +
 +celix_status_t component_handleAdded(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    pthread_mutex_lock(&component->mutex);
 +    array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
 +    arrayList_add(events, event);
 +    pthread_mutex_unlock(&component->mutex);
 +
 +    serviceDependency_setAvailable(dependency, true);
 +
 +    switch (component->state) {
 +        case DM_CMP_STATE_WAITING_FOR_REQUIRED: {
 +            serviceDependency_invokeSet(dependency, event);
 +            bool required = false;
 +            serviceDependency_isRequired(dependency, &required);
 +            if (required) {
 +                component_handleChange(component);
 +            }
 +            break;
 +        }
 +        case DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED: {
 +            bool instanceBound = false;
 +            serviceDependency_isInstanceBound(dependency, &instanceBound);
 +            bool required = false;
 +            serviceDependency_isRequired(dependency, &required);
 +            if (!instanceBound) {
 +                if (required) {
 +                    serviceDependency_invokeSet(dependency, event);
 +                    serviceDependency_invokeAdd(dependency, event);
 +                }
 +                dm_event_pt event = NULL;
 +                component_getDependencyEvent(component, dependency, &event);
 +                component_updateInstance(component, dependency, event, false, true);
 +            }
 +
 +            if (required) {
 +                component_handleChange(component);
 +            }
 +            break;
 +        }
 +        case DM_CMP_STATE_TRACKING_OPTIONAL:
 +		    component_suspend(component,dependency);
 +            serviceDependency_invokeSet(dependency, event);
 +            serviceDependency_invokeAdd(dependency, event);
 +		    component_resume(component,dependency);
 +            dm_event_pt event = NULL;
 +            component_getDependencyEvent(component, dependency, &event);
 +            component_updateInstance(component, dependency, event, false, true);
 +            break;
 +        default:
 +            break;
 +    }
 +
 +    return status;
 +}
 +
 +celix_status_t component_handleChanged(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    pthread_mutex_lock(&component->mutex);
 +    array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
 +    int index = arrayList_indexOf(events, event);
 +    if (index < 0) {
 +	pthread_mutex_unlock(&component->mutex);
 +        status = CELIX_BUNDLE_EXCEPTION;
 +    } else {
 +        dm_event_pt old = arrayList_remove(events, (unsigned int) index);
 +        arrayList_add(events, event);
 +        pthread_mutex_unlock(&component->mutex);
 +
 +        serviceDependency_invokeSet(dependency, event);
 +        switch (component->state) {
 +            case DM_CMP_STATE_TRACKING_OPTIONAL:
 +			    component_suspend(component,dependency);
 +                serviceDependency_invokeChange(dependency, event);
 +			    component_resume(component,dependency);
 +                dm_event_pt hevent = NULL;
 +                component_getDependencyEvent(component, dependency, &hevent);
 +                component_updateInstance(component, dependency, hevent, true, false);
 +                break;
 +            case DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED: {
 +                bool instanceBound = false;
 +                serviceDependency_isInstanceBound(dependency, &instanceBound);
 +                if (!instanceBound) {
 +                    serviceDependency_invokeChange(dependency, event);
 +                    dm_event_pt hevent = NULL;
 +                    component_getDependencyEvent(component, dependency, &hevent);
 +                    component_updateInstance(component, dependency, hevent, true, false);
 +                }
 +                break;
 +            }
 +            default:
 +                break;
 +        }
 +
 +        event_destroy(&old);
 +    }
 +
 +    return status;
 +}
 +
 +celix_status_t component_handleRemoved(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    pthread_mutex_lock(&component->mutex);
 +    array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
 +    int size = arrayList_size(events);
 +    if (arrayList_contains(events, event)) {
 +        size--;
 +    }
 +    pthread_mutex_unlock(&component->mutex);
 +    serviceDependency_setAvailable(dependency, size > 0);
 +    component_handleChange(component);
 +
 +    pthread_mutex_lock(&component->mutex);
 +    int index = arrayList_indexOf(events, event);
 +    if (index < 0) {
 +	pthread_mutex_unlock(&component->mutex);
 +        status = CELIX_BUNDLE_EXCEPTION;
 +    } else {
 +        dm_event_pt old = arrayList_remove(events, (unsigned int) index);
 +        pthread_mutex_unlock(&component->mutex);
 +
 +
 +        switch (component->state) {
 +            case DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED: {
 +                serviceDependency_invokeSet(dependency, event);
 +                bool instanceBound = false;
 +                serviceDependency_isInstanceBound(dependency, &instanceBound);
 +                if (!instanceBound) {
 +                    bool required = false;
 +                    serviceDependency_isRequired(dependency, &required);
 +                    if (required) {
 +                        serviceDependency_invokeRemove(dependency, event);
 +                    }
 +                    dm_event_pt hevent = NULL;
 +                    component_getDependencyEvent(component, dependency, &hevent);
 +                    component_updateInstance(component, dependency, hevent, false, false);
 +                }
 +                break;
 +            }
 +            case DM_CMP_STATE_TRACKING_OPTIONAL:
 +			    component_suspend(component,dependency);
 +                serviceDependency_invokeSet(dependency, event);
 +                serviceDependency_invokeRemove(dependency, event);
 +			    component_resume(component,dependency);
 +                dm_event_pt hevent = NULL;
 +                component_getDependencyEvent(component, dependency, &hevent);
 +                component_updateInstance(component, dependency, hevent, false, false);
 +                break;
 +            default:
 +                break;
 +        }
 +
 +        event_destroy(&event);
 +        if (old) {
 +            event_destroy(&old);
 +        }
 +    }
 +
 +    return status;
 +}
 +
 +celix_status_t component_handleSwapped(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event, dm_event_pt newEvent) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    pthread_mutex_lock(&component->mutex);
 +    array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
 +    int index = arrayList_indexOf(events, event);
 +    if (index < 0) {
 +	pthread_mutex_unlock(&component->mutex);
 +        status = CELIX_BUNDLE_EXCEPTION;
 +    } else {
 +        dm_event_pt old = arrayList_remove(events, (unsigned int) index);
 +        arrayList_add(events, newEvent);
 +        pthread_mutex_unlock(&component->mutex);
 +
 +        serviceDependency_invokeSet(dependency, event);
 +
 +        switch (component->state) {
 +            case DM_CMP_STATE_WAITING_FOR_REQUIRED:
 +                break;
 +            case DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED: {
 +                bool instanceBound = false;
 +                serviceDependency_isInstanceBound(dependency, &instanceBound);
 +                if (!instanceBound) {
 +                    bool required = false;
 +                    serviceDependency_isRequired(dependency, &required);
 +                    if (required) {
 +                        serviceDependency_invokeSwap(dependency, event, newEvent);
 +                    }
 +                }
 +                break;
 +            }
 +            case DM_CMP_STATE_TRACKING_OPTIONAL:
 +			    component_suspend(component,dependency);
 +                serviceDependency_invokeSwap(dependency, event, newEvent);
 +			    component_resume(component,dependency);
 +                break;
 +            default:
 +                break;
 +        }
 +
 +        event_destroy(&event);
 +        if (old) {
 +            event_destroy(&old);
 +        }
 +    }
 +
 +    return status;
 +}
 +
 +celix_status_t component_updateInstance(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt event, bool update, bool add) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    bool autoConfig = false;
 +
 +    serviceDependency_isAutoConfig(dependency, &autoConfig);
 +
 +    if (autoConfig) {
 +        const void *service = NULL;
 +        const void **field = NULL;
 +
 +        if (event != NULL) {
 +            event_getService(event, &service);
 +        }
 +        serviceDependency_getAutoConfig(dependency, &field);
 +        serviceDependency_lock(dependency);
 +        *field = service;
 +        serviceDependency_unlock(dependency);
 +    }
 +
 +    return status;
 +}
 +
 +celix_status_t component_startDependencies(dm_component_pt component __attribute__((unused)), array_list_pt dependencies) {
 +    celix_status_t status = CELIX_SUCCESS;
 +    array_list_pt required_dependencies = NULL;
 +    arrayList_create(&required_dependencies);
 +
 +    for (unsigned int i = 0; i < arrayList_size(dependencies); i++) {
 +        dm_service_dependency_pt dependency = arrayList_get(dependencies, i);
 +        bool required = false;
 +        serviceDependency_isRequired(dependency, &required);
 +        if (required) {
 +            arrayList_add(required_dependencies, dependency);
 +            continue;
 +        }
 +
 +        serviceDependency_start(dependency);
 +    }
 +
 +    for (unsigned int i = 0; i < arrayList_size(required_dependencies); i++) {
 +        dm_service_dependency_pt dependency = arrayList_get(required_dependencies, i);
 +        serviceDependency_start(dependency);
 +    }
 +
 +    arrayList_destroy(required_dependencies);
 +
 +    return status;
 +}
 +
 +celix_status_t component_stopDependencies(dm_component_pt component) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    pthread_mutex_lock(&component->mutex);
 +    for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
 +        dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i);
 +        pthread_mutex_unlock(&component->mutex);
 +        serviceDependency_stop(dependency);
 +        pthread_mutex_lock(&component->mutex);
 +    }
 +    pthread_mutex_unlock(&component->mutex);
 +
 +    return status;
 +}
 +
 +celix_status_t component_handleChange(dm_component_pt component) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    dm_component_state_t oldState;
 +    dm_component_state_t newState;
 +
 +    bool transition = false;
 +    do {
 +        oldState = component->state;
 +        status = component_calculateNewState(component, oldState, &newState);
 +        if (status == CELIX_SUCCESS) {
 +            component->state = newState;
 +            status = component_performTransition(component, oldState, newState, &transition);
 +        }
 +
 +        if (status != CELIX_SUCCESS) {
 +            break;
 +        }
 +    } while (transition);
 +
 +    return status;
 +}
 +
 +celix_status_t component_calculateNewState(dm_component_pt component, dm_component_state_t currentState, dm_component_state_t *newState) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    if (currentState == DM_CMP_STATE_INACTIVE) {
 +        if (component->isStarted) {
 +            *newState = DM_CMP_STATE_WAITING_FOR_REQUIRED;
 +        } else {
 +            *newState = currentState;
 +        }
 +    } else if (currentState == DM_CMP_STATE_WAITING_FOR_REQUIRED) {
 +        if (!component->isStarted) {
 +            *newState = DM_CMP_STATE_INACTIVE;
 +        } else {
 +            bool available = false;
 +            component_allRequiredAvailable(component, &available);
 +
 +            if (available) {
 +                *newState = DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED;
 +            } else {
 +                *newState = currentState;
 +            }
 +        }
 +    } else if (currentState == DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
 +        if (!component->isStarted) {
 +            *newState = DM_CMP_STATE_WAITING_FOR_REQUIRED;
 +        } else {
 +            bool available = false;
 +            component_allRequiredAvailable(component, &available);
 +
 +            if (available) {
 +                bool instanceBoundAvailable = false;
 +                component_allInstanceBoundAvailable(component, &instanceBoundAvailable);
 +
 +                if (instanceBoundAvailable) {
 +                    *newState = DM_CMP_STATE_TRACKING_OPTIONAL;
 +                } else {
 +                    *newState = currentState;
 +                }
 +            } else {
 +                *newState = currentState;
 +            }
 +        }
 +    } else if (currentState == DM_CMP_STATE_TRACKING_OPTIONAL) {
 +        bool instanceBoundAvailable = false;
 +        bool available = false;
 +
 +        component_allInstanceBoundAvailable(component, &instanceBoundAvailable);
 +        component_allRequiredAvailable(component, &available);
 +
 +        if (component->isStarted && available && instanceBoundAvailable) {
 +            *newState = currentState;
 +        } else {
 +            *newState = DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED;
 +        }
 +    } else {
 +        //should not reach
 +        *newState = DM_CMP_STATE_INACTIVE;
 +        status = CELIX_BUNDLE_EXCEPTION;
 +    }
 +
 +    return status;
 +}
 +
 +celix_status_t component_performTransition(dm_component_pt component, dm_component_state_t oldState, dm_component_state_t newState, bool *transition) {
 +    celix_status_t status = CELIX_SUCCESS;
 +    //printf("performing transition for %s in thread %i from %i to %i\n", component->name, (int) pthread_self(), oldState, newState);
 +
 +    if (oldState == newState) {
 +        *transition = false;
 +    } else if (oldState == DM_CMP_STATE_INACTIVE && newState == DM_CMP_STATE_WAITING_FOR_REQUIRED) {
 +        component_startDependencies(component, component->dependencies);
 +        *transition = true;
 +    } else if (oldState == DM_CMP_STATE_WAITING_FOR_REQUIRED && newState == DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
 +        component_invokeAddRequiredDependencies(component);
 +        component_invokeAutoConfigDependencies(component);
 +        if (component->callbackInit) {
 +        	status = component->callbackInit(component->implementation);
 +        }
 +        *transition = true;
 +    } else if (oldState == DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED && newState == DM_CMP_STATE_TRACKING_OPTIONAL) {
 +        component_invokeAddRequiredInstanceBoundDependencies(component);
 +        component_invokeAutoConfigInstanceBoundDependencies(component);
 +		component_invokeAddOptionalDependencies(component);
 +        if (component->callbackStart) {
 +        	status = component->callbackStart(component->implementation);
 +        }
 +        component_registerServices(component);
 +        *transition = true;
 +    } else if (oldState == DM_CMP_STATE_TRACKING_OPTIONAL && newState == DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED) {
 +        component_unregisterServices(component);
 +        if (component->callbackStop) {
 +        	status = component->callbackStop(component->implementation);
 +        }
 +		component_invokeRemoveOptionalDependencies(component);
 +        component_invokeRemoveInstanceBoundDependencies(component);
 +        *transition = true;
 +    } else if (oldState == DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED && newState == DM_CMP_STATE_WAITING_FOR_REQUIRED) {
 +    	if (component->callbackDeinit) {
 +    		status = component->callbackDeinit(component->implementation);
 +    	}
 +        component_invokeRemoveRequiredDependencies(component);
 +        *transition = true;
 +    } else if (oldState == DM_CMP_STATE_WAITING_FOR_REQUIRED && newState == DM_CMP_STATE_INACTIVE) {
 +        component_stopDependencies(component);
 +        *transition = true;
 +    }
 +
 +    return status;
 +}
 +
 +celix_status_t component_allRequiredAvailable(dm_component_pt component, bool *available) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    pthread_mutex_lock(&component->mutex);
 +    *available = true;
 +    for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
 +        dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i);
 +        bool required = false;
 +        bool instanceBound = false;
 +
 +        serviceDependency_isRequired(dependency, &required);
 +        serviceDependency_isInstanceBound(dependency, &instanceBound);
 +
 +        if (required && !instanceBound) {
 +            bool isAvailable = false;
 +            serviceDependency_isAvailable(dependency, &isAvailable);
 +            if (!isAvailable) {
 +                *available = false;
 +                break;
 +            }
 +        }
 +    }
 +    pthread_mutex_unlock(&component->mutex);
 +
 +    return status;
 +}
 +
 +celix_status_t component_allInstanceBoundAvailable(dm_component_pt component, bool *available) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    pthread_mutex_lock(&component->mutex);
 +    *available = true;
 +    for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
 +        dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i);
 +        bool required = false;
 +        bool instanceBound = false;
 +
 +        serviceDependency_isRequired(dependency, &required);
 +        serviceDependency_isInstanceBound(dependency, &instanceBound);
 +
 +        if (required && instanceBound) {
 +            bool isAvailable = false;
 +            serviceDependency_isAvailable(dependency, &isAvailable);
 +            if (!isAvailable) {
 +                *available = false;
 +                break;
 +            }
 +        }
 +    }
 +    pthread_mutex_unlock(&component->mutex);
 +
 +    return status;
 +}
 +
 +celix_status_t component_invokeAddRequiredDependencies(dm_component_pt component) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    pthread_mutex_lock(&component->mutex);
 +    for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
 +        dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i);
 +
 +        bool required = false;
 +        bool instanceBound = false;
 +
 +        serviceDependency_isRequired(dependency, &required);
 +        serviceDependency_isInstanceBound(dependency, &instanceBound);
 +
 +        if (required && !instanceBound) {
 +            array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
 +            if (events) {
 +				for (unsigned int j = 0; j < arrayList_size(events); j++) {
 +					dm_event_pt event = arrayList_get(events, j);
 +					serviceDependency_invokeAdd(dependency, event);
 +				}
 +            }
 +        }
 +    }
 +    pthread_mutex_unlock(&component->mutex);
 +
 +    return status;
 +}
 +
 +celix_status_t component_invokeAutoConfigDependencies(dm_component_pt component) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    pthread_mutex_lock(&component->mutex);
 +    for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
 +        dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i);
 +
 +        bool autoConfig = false;
 +        bool instanceBound = false;
 +
 +        serviceDependency_isAutoConfig(dependency, &autoConfig);
 +        serviceDependency_isInstanceBound(dependency, &instanceBound);
 +
 +        if (autoConfig && !instanceBound) {
 +            component_configureImplementation(component, dependency);
 +        }
 +    }
 +    pthread_mutex_unlock(&component->mutex);
 +
 +    return status;
 +}
 +
 +celix_status_t component_invokeAutoConfigInstanceBoundDependencies(dm_component_pt component) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    pthread_mutex_lock(&component->mutex);
 +    for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
 +        dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i);
 +
 +        bool autoConfig = false;
 +        bool instanceBound = false;
 +
 +        serviceDependency_isAutoConfig(dependency, &autoConfig);
 +        serviceDependency_isInstanceBound(dependency, &instanceBound);
 +
 +        if (autoConfig && instanceBound) {
 +            component_configureImplementation(component, dependency);
 +        }
 +    }
 +    pthread_mutex_unlock(&component->mutex);
 +
 +    return status;
 +}
 +
 +celix_status_t component_invokeAddRequiredInstanceBoundDependencies(dm_component_pt component) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    pthread_mutex_lock(&component->mutex);
 +    for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
 +        dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i);
 +
 +        bool required = false;
 +        bool instanceBound = false;
 +
 +        serviceDependency_isRequired(dependency, &required);
 +        serviceDependency_isInstanceBound(dependency, &instanceBound);
 +
 +        if (instanceBound && required) {
 +            array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
 +            if (events) {
 +				for (unsigned int j = 0; j < arrayList_size(events); j++) {
 +					dm_event_pt event = arrayList_get(events, j);
 +					serviceDependency_invokeAdd(dependency, event);
 +				}
 +            }
 +        }
 +    }
 +    pthread_mutex_unlock(&component->mutex);
 +
 +    return status;
 +}
 +
 +celix_status_t component_invokeAddOptionalDependencies(dm_component_pt component) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    pthread_mutex_lock(&component->mutex);
 +    for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
 +        dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i);
 +
 +        bool required = false;
 +
 +        serviceDependency_isRequired(dependency, &required);
 +
 +        if (!required) {
 +            array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
 +            if (events) {
 +				for (unsigned int j = 0; j < arrayList_size(events); j++) {
 +					dm_event_pt event = arrayList_get(events, j);
 +					serviceDependency_invokeAdd(dependency, event);
 +				}
 +            }
 +        }
 +    }
 +    pthread_mutex_unlock(&component->mutex);
 +
 +    return status;
 +}
 +
 +celix_status_t component_invokeRemoveOptionalDependencies(dm_component_pt component) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    pthread_mutex_lock(&component->mutex);
 +    for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
 +        dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i);
 +
 +        bool required = false;
 +
 +        serviceDependency_isRequired(dependency, &required);
 +
 +        if (!required) {
 +            array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
 +            if (events) {
 +				for (unsigned int j = 0; j < arrayList_size(events); j++) {
 +					dm_event_pt event = arrayList_get(events, j);
 +					serviceDependency_invokeRemove(dependency, event);
 +				}
 +            }
 +        }
 +    }
 +    pthread_mutex_unlock(&component->mutex);
 +
 +    return status;
 +}
 +
 +celix_status_t component_invokeRemoveInstanceBoundDependencies(dm_component_pt component) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    pthread_mutex_lock(&component->mutex);
 +    for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
 +        dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i);
 +
 +        bool instanceBound = false;
 +
 +        serviceDependency_isInstanceBound(dependency, &instanceBound);
 +
 +        if (instanceBound) {
 +            array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
 +            if (events) {
 +				for (unsigned int j = 0; j < arrayList_size(events); j++) {
 +					dm_event_pt event = arrayList_get(events, j);
 +					serviceDependency_invokeRemove(dependency, event);
 +				}
 +            }
 +        }
 +    }
 +    pthread_mutex_unlock(&component->mutex);
 +
 +    return status;
 +}
 +
 +celix_status_t component_invokeRemoveRequiredDependencies(dm_component_pt component) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    pthread_mutex_lock(&component->mutex);
 +    for (unsigned int i = 0; i < arrayList_size(component->dependencies); i++) {
 +        dm_service_dependency_pt dependency = arrayList_get(component->dependencies, i);
 +
 +        bool required = false;
 +        bool instanceBound = false;
 +
 +        serviceDependency_isRequired(dependency, &required);
 +        serviceDependency_isInstanceBound(dependency, &instanceBound);
 +
 +        if (!instanceBound && required) {
 +            array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
 +            if (events) {
 +				for (unsigned int j = 0; j < arrayList_size(events); j++) {
 +					dm_event_pt event = arrayList_get(events, j);
 +					serviceDependency_invokeRemove(dependency, event);
 +				}
 +            }
 +        }
 +    }
 +    pthread_mutex_unlock(&component->mutex);
 +
 +    return status;
 +}
 +
 +celix_status_t component_getDependencyEvent(dm_component_pt component, dm_service_dependency_pt dependency, dm_event_pt *event_pptr) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
 +    *event_pptr = NULL;
 +
 +    if (events) {
 +        for (unsigned int j = 0; j < arrayList_size(events); j++) {
 +            dm_event_pt event_ptr = arrayList_get(events, j);
 +            if (*event_pptr != NULL) {
 +                int compare = 0;
 +                event_compareTo(event_ptr, *event_pptr, &compare);
 +                if (compare > 0) {
 +                    *event_pptr = event_ptr;
 +                }
 +            } else {
 +                *event_pptr = event_ptr;
 +            }
 +        }
 +    }
 +
 +    return status;
 +}
 +
 +celix_status_t component_configureImplementation(dm_component_pt component, dm_service_dependency_pt dependency) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    const void **field = NULL;
 +
 +    array_list_pt events = hashMap_get(component->dependencyEvents, dependency);
 +    if (events) {
 +        const void *service = NULL;
 +        dm_event_pt event = NULL;
 +        component_getDependencyEvent(component, dependency, &event);
 +        if (event != NULL) {
 +            event_getService(event, &service);
 +            serviceDependency_getAutoConfig(dependency, &field);
 +            serviceDependency_lock(dependency);
 +            *field = service;
 +            serviceDependency_unlock(dependency);
 +        }
 +    }
 +
 +    return status;
 +}
 +
 +celix_status_t component_registerServices(dm_component_pt component) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    if (component->context != NULL) {
 +	    unsigned int i;
++        celixThreadMutex_lock(&component->mutex);
 +        for (i = 0; i < arrayList_size(component->dm_interfaces); i++) {
 +            dm_interface_t *interface = arrayList_get(component->dm_interfaces, i);
++            if (interface->registration == NULL) {
 +                properties_pt regProps = NULL;
 +                properties_copy(interface->properties, &regProps);
-                 bundleContext_registerService(component->context, interface->serviceName, interface->service, regProps, &interface->registration);
++                bundleContext_registerService(component->context, interface->serviceName, interface->service, regProps,
++                                              &interface->registration);
++            }
 +        }
++        celixThreadMutex_unlock(&component->mutex);
 +    }
 +
 +    return status;
 +}
 +
 +celix_status_t component_unregisterServices(dm_component_pt component) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    unsigned int i;
 +
++    celixThreadMutex_lock(&component->mutex);
 +    for (i = 0; i < arrayList_size(component->dm_interfaces); i++) {
- 	dm_interface_t *interface = arrayList_get(component->dm_interfaces, i);
++	    dm_interface_t *interface = arrayList_get(component->dm_interfaces, i);
 +
- 	serviceRegistration_unregister(interface->registration);
- 	interface->registration = NULL;
++	    serviceRegistration_unregister(interface->registration);
++	    interface->registration = NULL;
 +    }
++    celixThreadMutex_unlock(&component->mutex);
 +
 +    return status;
 +}
 +
 +celix_status_t component_setCallbacks(dm_component_pt component, init_fpt init, start_fpt start, stop_fpt stop, deinit_fpt deinit) {
 +	if (component->active) {
 +		return CELIX_ILLEGAL_STATE;
 +	}
 +	component->callbackInit = init;
 +	component->callbackStart = start;
 +	component->callbackStop = stop;
 +	component->callbackDeinit = deinit;
 +	return CELIX_SUCCESS;
 +}
 +
 +celix_status_t component_isAvailable(dm_component_pt component, bool *available) {
 +    *available = component->state == DM_CMP_STATE_TRACKING_OPTIONAL;
 +    return CELIX_SUCCESS;
 +}
 +
 +celix_status_t component_setImplementation(dm_component_pt component, void *implementation) {
 +    component->implementation = implementation;
 +    return CELIX_SUCCESS;
 +}
 +
 +celix_status_t component_getBundleContext(dm_component_pt component, bundle_context_pt *context) {
 +	celix_status_t status = CELIX_SUCCESS;
 +
 +	if (!component) {
 +		status = CELIX_ILLEGAL_ARGUMENT;
 +	}
 +
 +	if (status == CELIX_SUCCESS) {
 +		*context = component->context;
 +	}
 +
 +	return status;
 +}
 +
 +
 +static celix_status_t executor_create(dm_component_pt component __attribute__((unused)), dm_executor_pt *executor) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    *executor = malloc(sizeof(**executor));
 +    if (!*executor) {
 +        status = CELIX_ENOMEM;
 +    } else {
 +        linkedList_create(&(*executor)->workQueue);
 +        pthread_mutex_init(&(*executor)->mutex, NULL);
 +        (*executor)->runningThreadSet = false;
 +    }
 +
 +    return status;
 +}
 +
 +static void executor_destroy(dm_executor_pt executor) {
 +
 +	if (executor) {
 +		pthread_mutex_destroy(&executor->mutex);
 +		linkedList_destroy(executor->workQueue);
 +
 +		free(executor);
 +	}
 +}
 +
 +static celix_status_t executor_schedule(dm_executor_pt executor, dm_component_pt component, void (*command), void *data) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    dm_executor_task_t *task = NULL;
 +    task = malloc(sizeof(*task));
 +    if (!task) {
 +        status = CELIX_ENOMEM;
 +    } else {
 +        task->component = component;
 +        task->command = command;
 +        task->data = data;
 +
 +        pthread_mutex_lock(&executor->mutex);
 +        linkedList_addLast(executor->workQueue, task);
 +        pthread_mutex_unlock(&executor->mutex);
 +    }
 +
 +    return status;
 +}
 +
 +static celix_status_t executor_executeTask(dm_executor_pt executor, dm_component_pt component, void (*command), void *data) {
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +    // Check thread and executor thread, if the same, execute immediately.
 +//    bool execute = false;
 +//    pthread_mutex_lock(&executor->mutex);
 +//    pthread_t currentThread = pthread_self();
 +//    if (pthread_equal(executor->runningThread, currentThread)) {
 +//        execute = true;
 +//    }
 +//    pthread_mutex_unlock(&executor->mutex);
 +
 +    // For now, just schedule.
 +    executor_schedule(executor, component, command, data);
 +    executor_execute(executor);
 +
 +    return status;
 +}
 +
 +static celix_status_t executor_execute(dm_executor_pt executor) {
 +    celix_status_t status = CELIX_SUCCESS;
 +    pthread_t currentThread = pthread_self();
 +
 +    pthread_mutex_lock(&executor->mutex);
 +    bool execute = false;
 +    if (!executor->runningThreadSet) {
 +        executor->runningThread = currentThread;
 +        executor->runningThreadSet = true;
 +        execute = true;
 +    }
 +    pthread_mutex_unlock(&executor->mutex);
 +    if (execute) {
 +        executor_runTasks(executor, currentThread);
 +    }
 +
 +    return status;
 +}
 +
 +static celix_status_t executor_runTasks(dm_executor_pt executor, pthread_t currentThread __attribute__((unused))) {
 +    celix_status_t status = CELIX_SUCCESS;
 +//    bool execute = false;
 +
 +    do {
 +        dm_executor_task_t *entry = NULL;
 +        pthread_mutex_lock(&executor->mutex);
 +        while ((entry = linkedList_removeFirst(executor->workQueue)) != NULL) {
 +            pthread_mutex_unlock(&executor->mutex);
 +
 +            entry->command(entry->component, entry->data);
 +
 +            pthread_mutex_lock(&executor->mutex);
 +
 +            free(entry);
 +        }
 +        executor->runningThreadSet = false;
 +        pthread_mutex_unlock(&executor->mutex);
 +
 +//        pthread_mutex_lock(&executor->mutex);
 +//        if (executor->runningThread == NULL) {
 +//            executor->runningThread = currentThread;
 +//            execute = true;
 +//        }
 +//        pthread_mutex_unlock(&executor->mutex);
 +    } while (!linkedList_isEmpty(executor->workQueue)); // && execute
 +
 +    return status;
 +}
 +
 +celix_status_t component_getComponentInfo(dm_component_pt component, dm_component_info_pt *out) {
 +    celix_status_t status = CELIX_SUCCESS;
 +    int i;
 +    int size;
 +    dm_component_info_pt info = NULL;
 +    info = calloc(1, sizeof(*info));
 +
 +    if (info == NULL) {
 +        return CELIX_ENOMEM;
 +    }
 +
 +    arrayList_create(&info->dependency_list);
 +    component_getInterfaces(component, &info->interfaces);
 +    info->active = false;
 +    memcpy(info->id, component->id, DM_COMPONENT_MAX_ID_LENGTH);
 +    memcpy(info->name, component->name, DM_COMPONENT_MAX_NAME_LENGTH);
 +
 +    switch (component->state) {
 +        case DM_CMP_STATE_INACTIVE :
 +            info->state = strdup("INACTIVE");
 +            break;
 +        case DM_CMP_STATE_WAITING_FOR_REQUIRED :
 +            info->state = strdup("WAITING_FOR_REQUIRED");
 +            break;
 +        case DM_CMP_STATE_INSTANTIATED_AND_WAITING_FOR_REQUIRED :
 +            info->state = strdup("INSTANTIATED_AND_WAITING_FOR_REQUIRED");
 +            break;
 +        case DM_CMP_STATE_TRACKING_OPTIONAL :
 +            info->state = strdup("TRACKING_OPTIONAL");
 +            info->active = true;
 +            break;
 +        default :
 +            info->state = strdup("UNKNOWN");
 +            break;
 +    }
 +
 +    celixThreadMutex_lock(&component->mutex);
 +    size = arrayList_size(component->dependencies);
 +    for (i = 0; i < size; i += 1) {
 +        dm_service_dependency_pt dep = arrayList_get(component->dependencies, i);
 +        dm_service_dependency_info_pt depInfo = NULL;
 +        status = serviceDependency_getServiceDependencyInfo(dep, &depInfo);
 +        if (status == CELIX_SUCCESS) {
 +            arrayList_add(info->dependency_list, depInfo);
 +        } else {
 +            break;
 +        }
 +    }
 +    celixThreadMutex_unlock(&component->mutex);
 +
 +    if (status == CELIX_SUCCESS) {
 +        *out = info;
 +    } else if (info != NULL) {
 +        component_destroyComponentInfo(info);
 +    }
 +
 +    return status;
 +}
 +
 +void component_destroyComponentInfo(dm_component_info_pt info) {
 +    int i;
 +    int size;
 +    if (info != NULL) {
 +        free(info->state);
 +
 +        if (info->interfaces != NULL) {
 +            size = arrayList_size(info->interfaces);
 +            for (i = 0; i < size; i += 1) {
 +                dm_interface_info_pt intfInfo = arrayList_get(info->interfaces, i);
 +                free(intfInfo->name);
 +                properties_destroy(intfInfo->properties);
 +                free(intfInfo);
 +            }
 +            arrayList_destroy(info->interfaces);
 +        }
 +        if (info->dependency_list != NULL) {
 +            size = arrayList_size(info->dependency_list);
 +            for (i = 0; i < size; i += 1) {
 +                dm_service_dependency_info_pt depInfo = arrayList_get(info->dependency_list, i);
 +                dependency_destroyDependencyInfo(depInfo);
 +            }
 +            arrayList_destroy(info->dependency_list);
 +        }
 +    }
 +    free(info);
 +}

http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/dfi/CMakeLists.txt
----------------------------------------------------------------------
diff --cc dfi/CMakeLists.txt
index 642ac68,676277c..950aaa5
--- a/dfi/CMakeLists.txt
+++ b/dfi/CMakeLists.txt
@@@ -18,57 -18,73 +18,65 @@@
  find_package(FFI REQUIRED)
  find_package(Jansson REQUIRED)
  
 -include_directories(
 -        ${FFI_INCLUDE_DIRS}
 -        ${JANSSON_INCLUDE_DIRS}
 -	    private/include
 -	    public/include
 -	    ${PROJECT_SOURCE_DIR}/utils/public/include
 +set(SOURCES
 +	src/dyn_common.c
 +	src/dyn_type.c
 +	src/dyn_function.c
 +	src/dyn_interface.c
 +	src/dyn_message.c
 +	src/json_serializer.c
 +	src/json_rpc.c
  )
  
- add_library(dfi SHARED ${SOURCES})
- set_target_properties(dfi PROPERTIES OUTPUT_NAME "celix_dfi")
- target_include_directories(dfi PUBLIC include ${JANSSON_INCLUDE_DIRS})
- target_include_directories(dfi PRIVATE src ${FFI_INCLUDE_DIRS})
- target_link_libraries(dfi PUBLIC ${JANSSON_LIBRARY})
- target_link_libraries(dfi PRIVATE Celix::utils ${FFI_LIBRARIES})
- set_target_properties(dfi PROPERTIES "SOVERSION" 1)
 -set(MEMSTREAM_SOURCES )
 -set(MEMSTREAM_INCLUDES )
 -if (APPLE OR ANDROID)
 -	set(MEMSTREAM_SOURCES ${PROJECT_SOURCE_DIR}/utils/private/src/memstream/open_memstream.c  ${PROJECT_SOURCE_DIR}/utils/private/src/memstream/fmemopen.c)
 -	set(MEMSTREAM_INCLUDES ${PROJECT_SOURCE_DIR}/utils/public/include/memstream/open_memstream.h ${PROJECT_SOURCE_DIR}/utils/public/include/memstream/fmemopen.h)
 -    include_directories(${PROJECT_SOURCE_DIR}/utils/public/include/memstream)
 -endif()
++add_library(celix_dfi SHARED ${SOURCES})
++set_target_properties(celix_dfi PROPERTIES OUTPUT_NAME "celix_dfi")
++target_include_directories(celix_dfi PUBLIC include ${JANSSON_INCLUDE_DIRS})
++target_include_directories(celix_dfi PRIVATE src ${FFI_INCLUDE_DIRS})
++target_link_libraries(celix_dfi PUBLIC ${JANSSON_LIBRARY})
++target_link_libraries(celix_dfi PRIVATE Celix::utils ${FFI_LIBRARIES})
++set_target_properties(celix_dfi PROPERTIES "SOVERSION" 1)
  
- add_library(dfi_static STATIC ${SOURCES})
- set_target_properties(dfi_static PROPERTIES OUTPUT_NAME "celix_dfi_static")
- target_include_directories(dfi_static PUBLIC include ${JANSSON_INCLUDE_DIRS})
- target_include_directories(dfi_static PRIVATE src ${FFI_INCLUDE_DIRS})
- target_link_libraries(dfi_static PUBLIC ${JANSSON_LIBRARY})
- target_link_libraries(dfi_static PRIVATE Celix::utils ${FFI_LIBRARIES})
 -add_library(celix_dfi SHARED
 -    private/src/dyn_common.c
 -    private/src/dyn_type.c
 -    private/src/dyn_function.c
 -    private/src/dyn_interface.c
 -    private/src/dyn_message.c
 -    private/src/json_serializer.c
 -    private/src/json_rpc.c
 -    ${MEMSTREAM_SOURCES}
++add_library(celix_dfi_static STATIC ${SOURCES})
++set_target_properties(celix_dfi_static PROPERTIES OUTPUT_NAME "celix_dfi_static")
++target_include_directories(celix_dfi_static PUBLIC include ${JANSSON_INCLUDE_DIRS})
++target_include_directories(celix_dfi_static PRIVATE src ${FFI_INCLUDE_DIRS})
++target_link_libraries(celix_dfi_static PUBLIC ${JANSSON_LIBRARY})
++target_link_libraries(celix_dfi_static PRIVATE Celix::utils ${FFI_LIBRARIES})
  
- install(TARGETS dfi dfi_static DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT framework)
 -    public/include/dyn_common.h
 -    public/include/dyn_type.h
 -    public/include/dyn_function.h
 -    public/include/dyn_interface.h
 -    public/include/dyn_message.h
 -    public/include/json_serializer.h
 -    public/include/json_rpc.h
 -    ${MEMSTREAM_INCLUDES}
 -)
 -set_target_properties(celix_dfi PROPERTIES "SOVERSION" 1)
 -set_target_properties(celix_dfi PROPERTIES "VERSION" 1.1.0)
 -target_link_libraries(celix_dfi celix_utils ${FFI_LIBRARIES} ${JANSSON_LIBRARY})
++install(TARGETS celix_dfi celix_dfi_static DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT framework)
  
+ install(TARGETS celix_dfi DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT framework)
 -FILE(GLOB files "public/include/*.h" ${MEMSTREAM_INCLUDES})
++FILE(GLOB files "include/*.h")
+ INSTALL(FILES ${files} DESTINATION include/celix/dfi COMPONENT framework)
  
 +#Alias setup to match external usage
- add_library(Celix::dfi ALIAS dfi)
- add_library(Celix::dfi_static ALIAS dfi_static)
++add_library(Celix::dfi ALIAS celix_dfi)
++add_library(Celix::dfi_static ALIAS celix_dfi_static)
  
  if (ENABLE_TESTING)
      find_package(CppUTest REQUIRED)
+         
      include_directories(${CPPUTEST_INCLUDE_DIR})
  
+ 	SET(CMAKE_SKIP_BUILD_RPATH  FALSE) #TODO needed?
+ 	SET(CMAKE_BUILD_WITH_INSTALL_RPATH TRUE) #TODO needed?
+     SET(CMAKE_INSTALL_RPATH "${PROJECT_BINARY_DIR}/dfi" "${PROJECT_BINARY_DIR}/utils")
+ 
  	add_executable(test_dfi
 -		private/test/dyn_type_tests.cpp
 -		private/test/dyn_function_tests.cpp
 -		private/test/dyn_closure_tests.cpp
 -		private/test/dyn_interface_tests.cpp
 -		private/test/dyn_message_tests.cpp
 -		private/test/json_serializer_tests.cpp
 -		private/test/json_rpc_tests.cpp
 -		private/test/run_tests.cpp
 +		test/dyn_type_tests.cpp
 +		test/dyn_function_tests.cpp
 +		test/dyn_closure_tests.cpp
 +		test/dyn_interface_tests.cpp
 +		test/dyn_message_tests.cpp
 +		test/json_serializer_tests.cpp
 +		test/json_rpc_tests.cpp
 +		test/run_tests.cpp
  	)
 -	target_link_libraries(test_dfi celix_dfi ${FFI_LIBRARIES} ${CPPUTEST_LIBRARY})
 +	target_link_libraries(test_dfi PRIVATE Celix::dfi Celix::utils ${FFI_LIBRARIES} ${CPPUTEST_LIBRARY})
 +	target_include_directories(test_dfi PRIVATE ${FFI_INCLUDE_DIRS})
  
 -    file(COPY ${CMAKE_CURRENT_LIST_DIR}/private/test/schemas DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
 -    file(COPY ${CMAKE_CURRENT_LIST_DIR}/private/test/descriptors DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
 +    file(COPY ${CMAKE_CURRENT_LIST_DIR}/test/schemas DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
 +    file(COPY ${CMAKE_CURRENT_LIST_DIR}/test/descriptors DESTINATION ${CMAKE_CURRENT_BINARY_DIR})
  
  	add_test(NAME run_test_dfi COMMAND test_dfi)
  	SETUP_TARGET_FOR_COVERAGE(test_dfi_cov test_dfi ${CMAKE_BINARY_DIR}/coverage/test_dfi/test_dfi)

http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/etcdlib/CMakeLists.txt
----------------------------------------------------------------------
diff --cc etcdlib/CMakeLists.txt
index 060eeb0,1904dea..fac356a
--- a/etcdlib/CMakeLists.txt
+++ b/etcdlib/CMakeLists.txt
@@@ -41,17 -41,19 +41,18 @@@ endif (
  find_package(CURL REQUIRED)
  find_package(Jansson REQUIRED)
  
 -include_directories(
 -        ${CURL_INCLUDE_DIRS}
 -        ${JANSSON_INCLUDE_DIRS}
 -        private/include
 -        public/include
 -)
 -
  add_library(etcdlib SHARED
 -    private/src/etcd.c
 +    src/etcd.c
 +)
 +target_include_directories(etcdlib PUBLIC api)
 +target_include_directories(etcdlib PRIVATE
 +    src
 +    ${CURL_INCLUDE_DIRS}
 +    ${JANSSON_INCLUDE_DIRS}
  )
  
- set_target_properties(etcdlib PROPERTIES "SOVERSION" 1)
+ set_target_properties(etcdlib PROPERTIES SOVERSION 1)
+ set_target_properties(etcdlib PROPERTIES VERSION 1.0.0)
  target_link_libraries(etcdlib ${CURL_LIBRARIES} ${JANSSON_LIBRARIES})
  
  add_library(etcdlib_static STATIC

http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/examples/dm_example/CMakeLists.txt
----------------------------------------------------------------------
diff --cc examples/dm_example/CMakeLists.txt
index 2cef7ec,fa6ec57..a18a675
--- a/examples/dm_example/CMakeLists.txt
+++ b/examples/dm_example/CMakeLists.txt
@@@ -24,42 -27,41 +24,40 @@@ if (BUILD_DEPENDENCY_MANAGER
      add_subdirectory(phase3)
  
  
--    add_deploy("dm_example"
++    add_deploy(dm_example
          COPY 
          BUNDLES
 -            shell
 -            shell_tui
 -            dm_shell
 -            phase1
 -            phase2a
 -            phase2b
 -            phase3
 +            Celix::shell
 +            Celix::shell_tui
 +            Celix::dm_shell
 +            dm_example_phase1
 +            dm_example_phase2a
 +            dm_example_phase2b
 +            dm_example_phase3
          PROPERTIES
              LOGHELPER_ENABLE_STDOUT_FALLBACK=true
      )
  
-     if (ENABLE_DOCKER)
-         add_celix_docker(dm_exmpl_base
-                 NAME dmbase
-                 IMAGE_NAME dmbase
-                 GROUP examples
-                 INSTRUCTIONS
-                     "LABEL exmpl=value"
-         )
-         add_celix_docker(dm_exmpl
-             FROM dmbase
+     add_celix_docker(dm_exmpl_base
+             NAME dmbase
+             IMAGE_NAME dmbase
              GROUP examples
-             BUNDLES
-                 Celix::shell
-                 Celix::shell_tui
-                 Celix::dm_shell
-                 dm_example_phase1
-                 dm_example_phase2a
-                 dm_example_phase2b
-                 dm_example_phase3
-             PROPERTIES
-                 LOGHELPER_ENABLE_STDOUT_FALLBACK=true
-         )
-     endif ()
+             INSTRUCTIONS
+                 "LABEL exmpl=value"
+     )
+     add_celix_docker(dm_exmpl
+         FROM dmbase
+         GROUP examples
+         BUNDLES
 -            shell
 -            shell_tui
 -            dm_shell
 -            phase1
 -            phase2a
 -            phase2b
 -            phase3
++            Celix::shell
++            Celix::shell_tui
++            Celix::dm_shell
++            dm_example_phase1
++            dm_example_phase2a
++            dm_example_phase2b
++            dm_example_phase3
+         PROPERTIES
+             LOGHELPER_ENABLE_STDOUT_FALLBACK=true
+     )
 -    add_dependencies(celix-build-dm_exmpl-docker-image celix-build-dm_exmpl_base-docker-image)
  
  endif ()

http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/examples/dm_example/phase1/src/phase1_activator.c
----------------------------------------------------------------------
diff --cc examples/dm_example/phase1/src/phase1_activator.c
index 783e642,0000000..31dcb16
mode 100644,000000..100644
--- a/examples/dm_example/phase1/src/phase1_activator.c
+++ b/examples/dm_example/phase1/src/phase1_activator.c
@@@ -1,85 -1,0 +1,86 @@@
 +/**
 + *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.
 + */
 +/*
 + * activator.c
 + *
 + *  \date       Oct 29, 2015
 + *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
 + *  \copyright	Apache License, Version 2.0
 + */
 +#include <stdlib.h>
 +#include <phase1_cmp.h>
 +
 +#include "bundle_activator.h"
 +#include "dm_activator.h"
 +
 +#include "phase1.h"
 +
 +struct phase1_activator_struct {
 +    phase1_cmp_t *phase1Cmp;
 +	phase1_t phase1Serv;
 +};
 +
 +celix_status_t dm_create(bundle_context_pt context, void **userData) {
 +	printf("PHASE1: dm_create\n");
 +	*userData = calloc(1, sizeof(struct phase1_activator_struct));
 +	return *userData != NULL ? CELIX_SUCCESS : CELIX_ENOMEM;
 +}
 +
 +celix_status_t dm_init(void * userData, bundle_context_pt context, dm_dependency_manager_pt manager) {
 +	printf("PHASE1: dm_init\n");
 +    celix_status_t status = CELIX_SUCCESS;
 +
 +
 +    struct phase1_activator_struct *act = (struct phase1_activator_struct *)userData;
 +
 +	act->phase1Cmp = phase1_create();
 +	if (act->phase1Cmp != NULL) {
 +
 +		act->phase1Serv.handle = act->phase1Cmp;
 +		act->phase1Serv.getData = (void *)phase1_getData;
 +
 +		properties_pt props = properties_create();
 +		properties_set(props, "id", "phase1");
 +
 +		dm_component_pt cmp;
 +		component_create(context, "PHASE1_PROCESSING_COMPONENT", &cmp);
 +		component_setImplementation(cmp, act->phase1Cmp);
 +		component_setCallbacksSafe(cmp, phase1_cmp_t *, phase1_init, phase1_start, phase1_stop, phase1_deinit);
++		phase1_setComp(act->phase1Cmp, cmp);
 +		component_addInterface(cmp, PHASE1_NAME, PHASE1_VERSION, &act->phase1Serv, props);
 +
 +		dependencyManager_add(manager, cmp);
 +	} else {
 +		status = CELIX_ENOMEM;
 +	}
 +
 +    return status;
 +}
 +
 +celix_status_t dm_destroy(void * userData, bundle_context_pt context, dm_dependency_manager_pt manager) {
 +	printf("PHASE1: dm-destroy\n");
 +
 +	struct phase1_activator_struct *act = (struct phase1_activator_struct *)userData;
 +	if (act->phase1Cmp != NULL) {
 +		phase1_destroy(act->phase1Cmp);
 +	}
 +	free(act);
 +
 +	return CELIX_SUCCESS;
 +}

http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/examples/dm_example/phase1/src/phase1_cmp.c
----------------------------------------------------------------------
diff --cc examples/dm_example/phase1/src/phase1_cmp.c
index 75de182,0000000..40da821
mode 100644,000000..100644
--- a/examples/dm_example/phase1/src/phase1_cmp.c
+++ b/examples/dm_example/phase1/src/phase1_cmp.c
@@@ -1,99 -1,0 +1,110 @@@
 +/**
 + *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.
 + */
 +/*
 + * publisher.c
 + *
 + *  \date       Oct 29, 2015
 + *  \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 <unistd.h>
 +#include <string.h>
 +#include <signal.h>
 +
 +#include "celix_threads.h"
 +#include "phase1_cmp.h"
++#include "dm_component.h"
 +
 +#define SLEEPTIME 1000
 +
 +struct phase1_cmp_struct {
 +	celix_thread_t thread;
 +    bool running;
 +	unsigned int counter;
++	dm_component_pt component;
++
 +};
 +
 +static void *phase1_thread(void *data);
 +
 +phase1_cmp_t *phase1_create(void) {
 +	phase1_cmp_t *cmp = calloc(1, sizeof(*cmp));
 +	if (cmp != NULL) {
 +		cmp->counter = 0;
 +        cmp->running = false;
 +	}
 +	return cmp;
 +}
 +
++void phase1_setComp(phase1_cmp_t *cmp, dm_component_pt dmCmp) {
++	cmp->component = dmCmp;
++}
++
 +int phase1_init(phase1_cmp_t *cmp) {
 +	printf("init phase1\n");
 +    return 0;
 +}
 +
 +int phase1_start(phase1_cmp_t *cmp) {
 +	printf("start phase1\n");
 +    cmp->running = true;
 +    celixThread_create(&cmp->thread, NULL, phase1_thread, cmp);
 +    return 0;
 +}
 +
 +int phase1_stop(phase1_cmp_t *cmp) {
 +	printf("stop phase1\n");
 +    cmp->running = false;
 +    celixThread_kill(cmp->thread, SIGUSR1);
 +    celixThread_join(cmp->thread, NULL);
 +    return 0;
 +}
 +
 +int phase1_deinit(phase1_cmp_t *cmp) {
 +    printf("deinit phase1\n");
 +    return 0;
 +}
 +
 +void phase1_destroy(phase1_cmp_t *cmp) {
 +    free(cmp);
 +	printf("destroy phase1\n");
 +}
 +
 +static void *phase1_thread(void *data) {
 +    phase1_cmp_t *cmp = data;
 +
 +    while (cmp->running) {
 +        cmp->counter += 1;
++        if (cmp->counter == 2) {
++        	static char *runtime_interface = "DUMMY INTERFACE: DO NOT USE\n";
++        	component_addInterface(cmp->component, "RUNTIME_ADDED_INTERFACE", "1.0.0", runtime_interface, NULL);
++        }
 +        usleep(SLEEPTIME);
 +    }
 +
 +    celixThread_exit(NULL);
 +    return NULL;
 +}
 +
 +int phase1_getData(phase1_cmp_t *cmp, unsigned int *data) {
 +    *data = cmp->counter;
 +    return 0;
 +}

http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/examples/dm_example/phase1/src/phase1_cmp.h
----------------------------------------------------------------------
diff --cc examples/dm_example/phase1/src/phase1_cmp.h
index 5715f6e,0000000..153eed1
mode 100644,000000..100644
--- a/examples/dm_example/phase1/src/phase1_cmp.h
+++ b/examples/dm_example/phase1/src/phase1_cmp.h
@@@ -1,43 -1,0 +1,44 @@@
 +/**
 + *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.
 + */
 +/*
 + * publisher.h
 + *
 + *  \date       Oct 29, 2015
 + *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
 + *  \copyright	Apache License, Version 2.0
 + */
 +
 +#ifndef PHASE1_CMP_H
 +#define PHASE1_CMP_H
- 
++#include "dm_component.h"
 +
 +typedef struct phase1_cmp_struct phase1_cmp_t;
 +
 +phase1_cmp_t *phase1_create(void);
++void phase1_setComp(phase1_cmp_t *cmp, dm_component_pt dmCmp);
 +int phase1_init(phase1_cmp_t *cmp);
 +int phase1_start(phase1_cmp_t *cmp);
 +int phase1_stop(phase1_cmp_t *cmp);
 +int phase1_deinit(phase1_cmp_t *cmp);
 +void phase1_destroy(phase1_cmp_t *cmp);
 +
 +int phase1_getData(phase1_cmp_t *cmp, unsigned int *data);
 +
 +
 +#endif //PHASE1_CMP_H

http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/examples/dm_example_cxx/CMakeLists.txt
----------------------------------------------------------------------
diff --cc examples/dm_example_cxx/CMakeLists.txt
index 9ef4c1e,b07f5cc..3f37373
--- a/examples/dm_example_cxx/CMakeLists.txt
+++ b/examples/dm_example_cxx/CMakeLists.txt
@@@ -24,45 -31,44 +24,45 @@@ if (BUILD_DEPENDENCY_MANAGER_CXX
      add_subdirectory(phase3_locking)
  
  
--    add_deploy("dm_example_cxx"
++    add_celix_container("dm_example_cxx"
          COPY 
 -        CXX
 +	    CXX
          BUNDLES
 -            shell
 -            shell_tui
 -            dm_shell
 -            log_service
 -            log_writer
 +            Celix::shell
 +            Celix::shell_tui
 +            Celix::dm_shell
 +            Celix::log_service
 +            Celix::log_writer_stdout
  
 -            phase1_cxx
 -            phase2a_cxx
 -            phase2b_cxx
 -            phase3_cxx
 -            phase3_locking_cxx
 +            dm_example_cxx_phase1
 +            dm_example_cxx_phase2a
 +            dm_example_cxx_phase2b
 +            dm_example_cxx_phase3
 +            dm_example_cxx_phase3_locking
          PROPERTIES
              LOGHELPER_ENABLE_STDOUT_FALLBACK=true
      )
  
-     if (ENABLE_DOCKER)
-         add_celix_docker(dm_exmpl_cxx
-             GROUP examples
-             BUNDLES_DIR /usr/share/bundles
-             WORKDIR /workspace
-             BUNDLES
-                 Celix::shell
-                 Celix::shell_tui
-                 Celix::dm_shell
-                 Celix::log_service
-                 Celix::log_writer_stdout
 -    add_celix_docker(dm_exmpl_cxx
 -        CXX
 -        GROUP examples
 -        BUNDLES_DIR /usr/share/bundles
 -        WORKDIR /workspace
 -        BUNDLES
 -            shell
 -            shell_tui
 -            dm_shell
 -            log_service
 -            log_writer
  
-                 dm_example_cxx_phase1
-                 dm_example_cxx_phase2a
-                 dm_example_cxx_phase2b
-                 dm_example_cxx_phase3
-                 dm_example_cxx_phase3_locking
-             PROPERTIES
-                 LOGHELPER_ENABLE_STDOUT_FALLBACK=true
-         )
-     endif ()
 -            phase1_cxx
 -            phase2a_cxx
 -            phase2b_cxx
 -            phase3_cxx
 -            phase3_locking_cxx
 -        PROPERTIES
 -            LOGHELPER_ENABLE_STDOUT_FALLBACK=true
 -    )
++   add_celix_docker(dm_exmpl_cxx_docker
++           IMAGE_NAME dm_exmpl_cxx
++           GROUP examples
++           BUNDLES_DIR /usr/share/bundles
++           WORKDIR /workspace
++           BUNDLES
++               Celix::shell
++               Celix::shell_tui
++               Celix::dm_shell
++               Celix::log_service
++               Celix::log_writer_stdout
++
++               dm_example_cxx_phase1
++               dm_example_cxx_phase2a
++               dm_example_cxx_phase2b
++               dm_example_cxx_phase3
++               dm_example_cxx_phase3_locking
++           PROPERTIES
++               LOGHELPER_ENABLE_STDOUT_FALLBACK=true
++   )
  
  endif ()

http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/examples/log_service_example/CMakeLists.txt
----------------------------------------------------------------------
diff --cc examples/log_service_example/CMakeLists.txt
index 0363da3,6b7e681..1326a0f
--- a/examples/log_service_example/CMakeLists.txt
+++ b/examples/log_service_example/CMakeLists.txt
@@@ -27,5 -30,7 +27,5 @@@ target_link_libraries(log_service_examp
  
  add_deploy(log_example
      GROUP log_service
 -    BUNDLES log_service_example log_service shell shell_tui
 +    BUNDLES log_service_example Celix::log_service Celix::shell Celix::shell_tui
- )
+ )
 -
 -target_link_libraries(log_service_example celix_framework celix_utils)

http://git-wip-us.apache.org/repos/asf/celix/blob/ac0d0d77/framework/include/celix_launcher.h
----------------------------------------------------------------------
diff --cc framework/include/celix_launcher.h
index 0d819c9,0000000..5c7cf4d
mode 100644,000000..100644
--- a/framework/include/celix_launcher.h
+++ b/framework/include/celix_launcher.h
@@@ -1,55 -1,0 +1,57 @@@
 +/**
 + *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.
 + */
 +/*
 + * celix_launcher.h
 + *
 + *  \date       Jul 30, 2015
 + *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
 + *  \copyright	Apache License, Version 2.0
 + */
 +
 +#ifndef CELIX_LAUNCHER_H
 +#define CELIX_LAUNCHER_H
 +
 +#include <stdio.h>
 +#include "framework.h"
 +
 +#ifdef __cplusplus
 +extern "C" {
 +#endif
 +
 +int celixLauncher_launchWithArgs(int argc, char *argv[]);
 +
++int celixLauncher_launchWithArgsAndProps(int argc, char *argv[], properties_pt config);
++
 +int celixLauncher_launch(const char *configFile, framework_pt *framework);
 +
 +int celixLauncher_launchWithStream(FILE *config, framework_pt *framework);
 +
 +int celixLauncher_launchWithProperties(properties_pt config, framework_pt *framework);
 +
 +void celixLauncher_stop(framework_pt framework);
 +
 +void celixLauncher_destroy(framework_pt framework);
 +
 +void celixLauncher_waitForShutdown(framework_pt framework);
 +
 +#ifdef __cplusplus
 +}
 +#endif
 +
 +#endif //CELIX_LAUNCHER_H