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/05/27 18:37:11 UTC

[28/51] [partial] celix git commit: CELIX-424: Cleans up the directory structure. Moves all libraries to the libs subdir and all bundles to the bundles subdir

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_common/src/import_registration_impl.c
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_common/src/import_registration_impl.c b/bundles/remote_services/rsa_common/src/import_registration_impl.c
new file mode 100644
index 0000000..9a84327
--- /dev/null
+++ b/bundles/remote_services/rsa_common/src/import_registration_impl.c
@@ -0,0 +1,274 @@
+/**
+ *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.
+ */
+/*
+ * import_registration_impl.c
+ *
+ *  \date       Oct 14, 2011
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <constants.h>
+
+#include "celix_errno.h"
+
+#include "import_registration_impl.h"
+#include "remote_service_admin_impl.h"
+
+struct import_reference {
+	endpoint_description_pt endpoint;
+	service_reference_pt reference;
+};
+
+
+
+celix_status_t importRegistration_proxyFactoryAdding(void * handle, service_reference_pt reference, void **service);
+celix_status_t importRegistration_proxyFactoryAdded(void * handle, service_reference_pt reference, void *service);
+celix_status_t importRegistration_proxyFactoryModified(void * handle, service_reference_pt reference, void *service);
+celix_status_t importRegistration_proxyFactoryRemoved(void * handle, service_reference_pt reference, void *service);
+
+celix_status_t importRegistration_create(endpoint_description_pt endpoint, remote_service_admin_pt rsa, sendToHandle sendToCallback, bundle_context_pt context, import_registration_pt *registration) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	*registration = calloc(1, sizeof(**registration));
+	if (!*registration) {
+		status = CELIX_ENOMEM;
+	} else {
+		(*registration)->context = context;
+		(*registration)->closed = false;
+		(*registration)->endpointDescription = endpoint;
+		(*registration)->rsa = rsa;
+		(*registration)->sendToCallback = sendToCallback;
+		(*registration)->reference = NULL;
+		(*registration)->importReference = NULL;
+	}
+
+	return status;
+}
+
+celix_status_t importRegistration_destroy(import_registration_pt registration)
+{
+	free(registration);
+
+	return CELIX_SUCCESS;
+}
+
+
+celix_status_t importRegistrationFactory_create(log_helper_pt helper, char* serviceName, bundle_context_pt context, import_registration_factory_pt *registration_factory) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	*registration_factory = calloc(1, sizeof(**registration_factory));
+	if (!*registration_factory) {
+		status = CELIX_ENOMEM;
+	} else {
+		(*registration_factory)->serviceName = strdup(serviceName);
+		(*registration_factory)->context = context;
+		(*registration_factory)->bundle = NULL;
+		(*registration_factory)->loghelper = helper;
+
+		arrayList_create(&(*registration_factory)->registrations);
+	}
+
+	return status;
+}
+
+
+
+celix_status_t importRegistrationFactory_destroy(import_registration_factory_pt* registration_factory) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (*registration_factory != NULL)
+	{
+		free((*registration_factory)->serviceName);
+		arrayList_destroy((*registration_factory)->registrations);
+
+		serviceTracker_destroy((*registration_factory)->proxyFactoryTracker);
+		free(*registration_factory);
+
+		*registration_factory = NULL;
+	}
+
+
+	return status;
+}
+
+
+celix_status_t importRegistrationFactory_open(import_registration_factory_pt registration_factory)
+{
+	celix_status_t status;
+
+	const char *bundleStore = NULL;
+	bundleContext_getProperty(registration_factory->context, BUNDLE_STORE_PROPERTY_NAME, &bundleStore);
+
+	if (bundleStore == NULL) {
+		bundleStore = DEFAULT_BUNDLE_STORE;
+	}
+
+	char name[256];
+	snprintf(name, 256, "%s/%s_proxy.zip", bundleStore, registration_factory->serviceName);
+
+	status = bundleContext_installBundle(registration_factory->context, name, &registration_factory->bundle);
+
+	if (status == CELIX_SUCCESS) {
+		status = bundle_start(registration_factory->bundle);
+		if (status == CELIX_SUCCESS) {
+			logHelper_log(registration_factory->loghelper, OSGI_LOGSERVICE_INFO, "%s successfully started.", name);
+		}
+	}
+	else {
+		logHelper_log(registration_factory->loghelper, OSGI_LOGSERVICE_ERROR, "%s could not be installed.", name);
+	}
+
+	return status;
+}
+
+celix_status_t importRegistrationFactory_close(import_registration_factory_pt registration_factory)
+{
+	celix_status_t status = CELIX_SUCCESS;
+
+
+	if (registration_factory->proxyFactoryTracker != NULL) {
+		serviceTracker_close(registration_factory->proxyFactoryTracker);
+	}
+
+	if (registration_factory->bundle != NULL) {
+		bundle_uninstall(registration_factory->bundle);
+	}
+
+	return status;
+}
+
+
+celix_status_t importRegistration_createProxyFactoryTracker(import_registration_factory_pt registration_factory, service_tracker_pt *tracker) {
+	celix_status_t status;
+	service_tracker_customizer_pt customizer = NULL;
+
+	status = serviceTrackerCustomizer_create(registration_factory, importRegistration_proxyFactoryAdding, importRegistration_proxyFactoryAdded, importRegistration_proxyFactoryModified, importRegistration_proxyFactoryRemoved, &customizer);
+
+	if (status == CELIX_SUCCESS) {
+		char filter[512];
+
+		snprintf(filter, 512, "(&(%s=%s)(proxy.interface=%s))", (char*) OSGI_FRAMEWORK_OBJECTCLASS, (char*) OSGI_RSA_REMOTE_PROXY_FACTORY, registration_factory->serviceName);
+		status = serviceTracker_createWithFilter(registration_factory->context, filter, customizer, tracker);
+
+		if (status == CELIX_SUCCESS)
+		{
+			serviceTracker_open(*tracker);
+		}
+	}
+
+	return status;
+}
+
+celix_status_t importRegistration_proxyFactoryAdding(void * handle, service_reference_pt reference, void **service) {
+	celix_status_t status = CELIX_SUCCESS;
+	import_registration_factory_pt registration_factory = (import_registration_factory_pt) handle;
+
+	bundleContext_getService(registration_factory->context, reference, service);
+
+	return status;
+}
+
+celix_status_t importRegistration_proxyFactoryAdded(void * handle, service_reference_pt reference, void *service) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	import_registration_factory_pt registration_factory = (import_registration_factory_pt) handle;
+	registration_factory->trackedFactory = (remote_proxy_factory_service_pt) service;
+
+	return status;
+}
+
+celix_status_t importRegistration_proxyFactoryModified(void * handle, service_reference_pt reference, void *service) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	return status;
+}
+
+celix_status_t importRegistration_proxyFactoryRemoved(void * handle, service_reference_pt reference, void *service) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	import_registration_factory_pt registration_factory = (import_registration_factory_pt) handle;
+	registration_factory->trackedFactory = NULL;
+
+	return status;
+}
+
+
+
+celix_status_t importRegistrationFactory_install(log_helper_pt helper, char* serviceName, bundle_context_pt context, import_registration_factory_pt *registration_factory)
+{
+	celix_status_t status;
+
+	if ( (status = importRegistrationFactory_create(helper, serviceName, context, registration_factory)) == CELIX_SUCCESS) {
+		// starting the proxy tracker first allows us to pick up already available proxy factories
+		importRegistration_createProxyFactoryTracker(*registration_factory, &((*registration_factory)->proxyFactoryTracker));
+		logHelper_log((*registration_factory)->loghelper, OSGI_LOGSERVICE_INFO, "remoteServiceAdmin_importService: new registration_factory added for %s at %p", serviceName, (*registration_factory)->proxyFactoryTracker);
+
+		// check whether factory is available
+		if (((*registration_factory)->trackedFactory == NULL) && ((status = importRegistrationFactory_open(*registration_factory)) != CELIX_SUCCESS)) {
+			logHelper_log((*registration_factory)->loghelper, OSGI_LOGSERVICE_ERROR, "remoteServiceAdmin_importService: cannot open registration_factory for %s.", serviceName);
+
+			importRegistrationFactory_close(*registration_factory);
+			importRegistrationFactory_destroy(registration_factory);
+		}
+	}
+
+	return status;
+}
+
+
+
+
+celix_status_t importRegistration_getException(import_registration_pt registration) {
+	celix_status_t status = CELIX_SUCCESS;
+	return status;
+}
+
+
+celix_status_t importRegistration_getImportReference(import_registration_pt registration, import_reference_pt *reference) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (registration->importReference == NULL) {
+		registration->importReference = calloc(1, sizeof(*registration->importReference));
+		if (registration->importReference == NULL) {
+			status = CELIX_ENOMEM;
+		} else {
+			registration->importReference->endpoint = registration->endpointDescription;
+			registration->importReference->reference = registration->reference;
+		}
+	}
+
+	*reference = registration->importReference;
+
+	return status;
+}
+
+
+celix_status_t importReference_getImportedEndpoint(import_reference_pt reference) {
+	celix_status_t status = CELIX_SUCCESS;
+	return status;
+}
+
+celix_status_t importReference_getImportedService(import_reference_pt reference) {
+	celix_status_t status = CELIX_SUCCESS;
+	return status;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_common/src/import_registration_impl.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_common/src/import_registration_impl.h b/bundles/remote_services/rsa_common/src/import_registration_impl.h
new file mode 100644
index 0000000..7aa397f
--- /dev/null
+++ b/bundles/remote_services/rsa_common/src/import_registration_impl.h
@@ -0,0 +1,81 @@
+/**
+ *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.
+ */
+/*
+ * import_registration_impl.h
+ *
+ *  \date       Oct 14, 2011
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef IMPORT_REGISTRATION_IMPL_H_
+#define IMPORT_REGISTRATION_IMPL_H_
+
+#include "remote_service_admin.h"
+#include "remote_proxy.h"
+#include "service_tracker.h"
+#include "log_helper.h"
+
+struct import_registration {
+	bundle_context_pt context;
+	endpoint_description_pt endpointDescription;
+
+	service_reference_pt reference;
+	import_reference_pt importReference;
+
+	remote_service_admin_pt rsa;
+	sendToHandle sendToCallback;
+
+	bool closed;
+};
+
+
+
+struct import_registration_factory
+{
+	char* serviceName;
+	log_helper_pt loghelper;
+	remote_proxy_factory_service_pt trackedFactory;
+	service_tracker_pt proxyFactoryTracker;
+	bundle_context_pt context;
+	array_list_pt registrations;
+	bundle_pt bundle;
+};
+
+
+celix_status_t importRegistration_create(endpoint_description_pt endpoint, remote_service_admin_pt rsa, sendToHandle callback, bundle_context_pt context, import_registration_pt *registration);
+celix_status_t importRegistration_destroy(import_registration_pt registration);
+
+celix_status_t importRegistration_setEndpointDescription(import_registration_pt registration, endpoint_description_pt endpointDescription);
+celix_status_t importRegistration_setHandler(import_registration_pt registration, void * handler);
+celix_status_t importRegistration_setCallback(import_registration_pt registration, sendToHandle callback);
+
+celix_status_t importRegistration_getException(import_registration_pt registration);
+celix_status_t importRegistration_getImportReference(import_registration_pt registration, import_reference_pt *reference);
+
+celix_status_t importRegistration_createProxyFactoryTracker(import_registration_factory_pt registration_factory, service_tracker_pt *tracker);
+
+celix_status_t importRegistrationFactory_destroy(import_registration_factory_pt* registration_factory);
+//celix_status_t importRegistrationFactory_open(import_registration_factory_pt registration_factory);
+celix_status_t importRegistrationFactory_close(import_registration_factory_pt registration_factory);
+celix_status_t importRegistrationFactory_install(log_helper_pt helper, char* serviceName, bundle_context_pt context, import_registration_factory_pt *registration_factory);
+
+
+
+#endif /* IMPORT_REGISTRATION_IMPL_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_common/src/remote_proxy_factory_impl.c
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_common/src/remote_proxy_factory_impl.c b/bundles/remote_services/rsa_common/src/remote_proxy_factory_impl.c
new file mode 100644
index 0000000..9f996d6
--- /dev/null
+++ b/bundles/remote_services/rsa_common/src/remote_proxy_factory_impl.c
@@ -0,0 +1,252 @@
+/**
+ * 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.
+ */
+
+/*
+ * remote_proxy_factory_impl.c
+ *
+ *  \date       22 Dec 2014
+ *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright  Apache License, Version 2.0
+ */
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "remote_proxy.h"
+
+typedef struct proxy_instance {
+	service_registration_pt registration_ptr;
+	void *service;
+	properties_pt properties;
+} *proxy_instance_pt;
+
+static celix_status_t remoteProxyFactory_registerProxyService(remote_proxy_factory_pt remote_proxy_factory_ptr, endpoint_description_pt endpointDescription, remote_service_admin_pt rsa, sendToHandle sendToCallback);
+static celix_status_t remoteProxyFactory_unregisterProxyService(remote_proxy_factory_pt remote_proxy_factory_ptr, endpoint_description_pt endpointDescription);
+
+celix_status_t remoteProxyFactory_create(bundle_context_pt context, char *service, void *handle,
+		createProxyService create, destroyProxyService destroy,
+		remote_proxy_factory_pt *remote_proxy_factory_ptr) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	*remote_proxy_factory_ptr = calloc(1, sizeof(**remote_proxy_factory_ptr));
+	if (!*remote_proxy_factory_ptr) {
+		status = CELIX_ENOMEM;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		(*remote_proxy_factory_ptr)->context_ptr = context;
+		(*remote_proxy_factory_ptr)->service = strdup(service);
+
+		(*remote_proxy_factory_ptr)->remote_proxy_factory_service_ptr = NULL;
+		(*remote_proxy_factory_ptr)->properties = NULL;
+		(*remote_proxy_factory_ptr)->registration = NULL;
+
+		(*remote_proxy_factory_ptr)->proxy_instances = hashMap_create(NULL, NULL, NULL, NULL);
+
+		(*remote_proxy_factory_ptr)->handle = handle;
+
+		(*remote_proxy_factory_ptr)->create_proxy_service_ptr = create;
+		(*remote_proxy_factory_ptr)->destroy_proxy_service_ptr = destroy;
+	}
+
+	return status;
+}
+
+celix_status_t remoteProxyFactory_destroy(remote_proxy_factory_pt *remote_proxy_factory_ptr) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!*remote_proxy_factory_ptr) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		if ((*remote_proxy_factory_ptr)->proxy_instances) {
+			hashMap_destroy((*remote_proxy_factory_ptr)->proxy_instances, false, false);
+			(*remote_proxy_factory_ptr)->proxy_instances = NULL;
+		}
+		if ((*remote_proxy_factory_ptr)->service) {
+			free((*remote_proxy_factory_ptr)->service);
+			(*remote_proxy_factory_ptr)->service = NULL;
+		}
+		free(*remote_proxy_factory_ptr);
+		*remote_proxy_factory_ptr = NULL;
+	}
+
+	return status;
+}
+
+celix_status_t remoteProxyFactory_register(remote_proxy_factory_pt remote_proxy_factory_ptr) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	remote_proxy_factory_ptr->remote_proxy_factory_service_ptr = calloc(1, sizeof(*remote_proxy_factory_ptr->remote_proxy_factory_service_ptr));
+	if (!remote_proxy_factory_ptr->remote_proxy_factory_service_ptr) {
+		status = CELIX_ENOMEM;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		remote_proxy_factory_ptr->remote_proxy_factory_service_ptr->factory = remote_proxy_factory_ptr;
+		remote_proxy_factory_ptr->remote_proxy_factory_service_ptr->registerProxyService = remoteProxyFactory_registerProxyService;
+		remote_proxy_factory_ptr->remote_proxy_factory_service_ptr->unregisterProxyService = remoteProxyFactory_unregisterProxyService;
+
+		remote_proxy_factory_ptr->properties = properties_create();
+		if (!remote_proxy_factory_ptr->properties) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		} else {
+			properties_set(remote_proxy_factory_ptr->properties, "proxy.interface", remote_proxy_factory_ptr->service);
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = bundleContext_registerService(remote_proxy_factory_ptr->context_ptr, OSGI_RSA_REMOTE_PROXY_FACTORY,
+				remote_proxy_factory_ptr->remote_proxy_factory_service_ptr, remote_proxy_factory_ptr->properties, &remote_proxy_factory_ptr->registration);
+	}
+
+	return status;
+}
+
+celix_status_t remoteProxyFactory_unregister(remote_proxy_factory_pt remote_proxy_factory_ptr) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	if (!remote_proxy_factory_ptr) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	// #TODO Remove proxy registrations
+	if (status == CELIX_SUCCESS) {
+
+		hash_map_iterator_pt iter = hashMapIterator_create(remote_proxy_factory_ptr->proxy_instances);
+		while(hashMapIterator_hasNext(iter)){
+			proxy_instance_pt proxy_instance_ptr = (proxy_instance_pt)hashMapIterator_nextValue(iter);
+
+			if (proxy_instance_ptr->service) {
+				remote_proxy_factory_ptr->destroy_proxy_service_ptr(remote_proxy_factory_ptr->handle, proxy_instance_ptr->service);
+			}
+			free(proxy_instance_ptr);
+		}
+		hashMapIterator_destroy(iter);
+
+		if (remote_proxy_factory_ptr->registration) {
+			status = serviceRegistration_unregister(remote_proxy_factory_ptr->registration);
+			remote_proxy_factory_ptr->properties = NULL;
+		}
+		if (remote_proxy_factory_ptr->properties) {
+			properties_destroy(remote_proxy_factory_ptr->properties);
+		}
+		if (remote_proxy_factory_ptr->remote_proxy_factory_service_ptr) {
+			free(remote_proxy_factory_ptr->remote_proxy_factory_service_ptr);
+		}
+	}
+
+	return status;
+}
+
+
+static celix_status_t remoteProxyFactory_registerProxyService(remote_proxy_factory_pt remote_proxy_factory_ptr, endpoint_description_pt endpointDescription, remote_service_admin_pt rsa, sendToHandle sendToCallback) {
+	celix_status_t status = CELIX_SUCCESS;
+	proxy_instance_pt proxy_instance_ptr = NULL;
+
+	if (!remote_proxy_factory_ptr || !remote_proxy_factory_ptr->create_proxy_service_ptr) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		proxy_instance_ptr = calloc(1, sizeof(*proxy_instance_ptr));
+		if (!proxy_instance_ptr) {
+			status = CELIX_ENOMEM;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		proxy_instance_ptr->properties = properties_create();
+		if (!proxy_instance_ptr->properties) {
+			status = CELIX_ENOMEM;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = remote_proxy_factory_ptr->create_proxy_service_ptr(remote_proxy_factory_ptr->handle, endpointDescription, rsa, sendToCallback, proxy_instance_ptr->properties, &proxy_instance_ptr->service);
+	}
+
+	if (status == CELIX_SUCCESS) {
+		properties_set(proxy_instance_ptr->properties, "proxy.interface", remote_proxy_factory_ptr->service);
+
+		hash_map_iterator_pt iter = hashMapIterator_create(endpointDescription->properties);
+		while (hashMapIterator_hasNext(iter)) {
+			hash_map_entry_pt entry = hashMapIterator_nextEntry(iter);
+			char *key = hashMapEntry_getKey(entry);
+			char *value = hashMapEntry_getValue(entry);
+
+			properties_set(proxy_instance_ptr->properties, key, value);
+		}
+		hashMapIterator_destroy(iter);
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = bundleContext_registerService(remote_proxy_factory_ptr->context_ptr, remote_proxy_factory_ptr->service, proxy_instance_ptr->service, proxy_instance_ptr->properties, &proxy_instance_ptr->registration_ptr);
+	}
+
+	if (status == CELIX_SUCCESS) {
+		hashMap_put(remote_proxy_factory_ptr->proxy_instances, endpointDescription, proxy_instance_ptr);
+	}
+
+	if(status!=CELIX_SUCCESS){
+		if(proxy_instance_ptr != NULL){
+			if(proxy_instance_ptr->properties != NULL){
+				properties_destroy(proxy_instance_ptr->properties);
+			}
+			free(proxy_instance_ptr);
+		}
+	}
+
+	return status;
+}
+
+static celix_status_t remoteProxyFactory_unregisterProxyService(remote_proxy_factory_pt remote_proxy_factory_ptr, endpoint_description_pt endpointDescription) {
+	celix_status_t status = CELIX_SUCCESS;
+	proxy_instance_pt proxy_instance_ptr = NULL;
+
+	if (!remote_proxy_factory_ptr || !endpointDescription || !remote_proxy_factory_ptr->proxy_instances || !remote_proxy_factory_ptr->handle) {
+		status = CELIX_ILLEGAL_ARGUMENT;
+	}
+
+	if (status == CELIX_SUCCESS) {
+		proxy_instance_ptr = hashMap_remove(remote_proxy_factory_ptr->proxy_instances, endpointDescription);
+		if (proxy_instance_ptr == NULL) {
+			status = CELIX_BUNDLE_EXCEPTION;
+		}
+	}
+
+	if (status == CELIX_SUCCESS) {
+		if (proxy_instance_ptr->registration_ptr) {
+			status = serviceRegistration_unregister(proxy_instance_ptr->registration_ptr);
+			proxy_instance_ptr->properties = NULL;
+		}
+		if (proxy_instance_ptr->service) {
+			status = remote_proxy_factory_ptr->destroy_proxy_service_ptr(remote_proxy_factory_ptr->handle, proxy_instance_ptr->service);
+		}
+		if (proxy_instance_ptr->properties) {
+			properties_destroy(proxy_instance_ptr->properties);
+		}
+        free(proxy_instance_ptr);
+	}
+
+	return status;
+}
+
+

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_common/src/remote_service_admin_impl.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_common/src/remote_service_admin_impl.h b/bundles/remote_services/rsa_common/src/remote_service_admin_impl.h
new file mode 100644
index 0000000..e8a5e1f
--- /dev/null
+++ b/bundles/remote_services/rsa_common/src/remote_service_admin_impl.h
@@ -0,0 +1,49 @@
+/**
+ *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.
+ */
+/*
+ * remote_service_admin_impl.h
+ *
+ *  \date       Dec 5, 2013
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef REMOTE_SERVICE_ADMIN_IMPL_H_
+#define REMOTE_SERVICE_ADMIN_IMPL_H_
+
+#include "remote_service_admin.h"
+
+#define BUNDLE_STORE_PROPERTY_NAME "ENDPOINTS"
+#define DEFAULT_BUNDLE_STORE "endpoints"
+
+celix_status_t remoteServiceAdmin_create(bundle_context_pt context, remote_service_admin_pt *admin);
+celix_status_t remoteServiceAdmin_destroy(remote_service_admin_pt *admin);
+
+celix_status_t remoteServiceAdmin_send(remote_service_admin_pt rsa, endpoint_description_pt endpointDescription, char *methodSignature, char **reply, int* replyStatus);
+
+celix_status_t remoteServiceAdmin_exportService(remote_service_admin_pt admin, char *serviceId, properties_pt properties, array_list_pt *registrations);
+celix_status_t remoteServiceAdmin_removeExportedService(remote_service_admin_pt admin, export_registration_pt registration);
+celix_status_t remoteServiceAdmin_getExportedServices(remote_service_admin_pt admin, array_list_pt *services);
+celix_status_t remoteServiceAdmin_getImportedEndpoints(remote_service_admin_pt admin, array_list_pt *services);
+celix_status_t remoteServiceAdmin_importService(remote_service_admin_pt admin, endpoint_description_pt endpoint, import_registration_pt *registration);
+celix_status_t remoteServiceAdmin_removeImportedService(remote_service_admin_pt admin, import_registration_pt registration);
+
+celix_status_t remoteServiceAdmin_destroyEndpointDescription(endpoint_description_pt *description);
+
+#endif /* REMOTE_SERVICE_ADMIN_IMPL_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_spi/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_spi/CMakeLists.txt b/bundles/remote_services/rsa_spi/CMakeLists.txt
new file mode 100644
index 0000000..ea4ec95
--- /dev/null
+++ b/bundles/remote_services/rsa_spi/CMakeLists.txt
@@ -0,0 +1,29 @@
+# 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.
+
+add_library(rsa_spi INTERFACE)
+target_include_directories(rsa_spi INTERFACE
+    $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
+    $<INSTALL_INTERFACE:include/celix/rsa>
+)
+target_link_libraries(rsa_spi INTERFACE Celix::remote_services_api)
+
+install(TARGETS rsa_spi EXPORT celix DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT rsa)
+install(DIRECTORY include/ DESTINATION include/celix/rsa COMPONENT rsa)
+
+#Setup target aliases to match external usage
+add_library(Celix::rsa_spi ALIAS rsa_spi)

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_spi/README.md
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_spi/README.md b/bundles/remote_services/rsa_spi/README.md
new file mode 100644
index 0000000..2e3d268
--- /dev/null
+++ b/bundles/remote_services/rsa_spi/README.md
@@ -0,0 +1,11 @@
+# Remote Service Admin
+
+The Remote Service Admin (RSA) provides the mechanisms to import and export services when instructed to do so by the Topology Manager. 
+
+To delegate method calls to the actual service implementation, the RSA_SHM and the RSA_HTTP are using "endpoint/proxy" bundles, which has all the knowledge about the marshalling and unmarshalling of data for the service. The RSA_DFI implementation combines a [foreign function interface](https://en.wikipedia.org/wiki/Foreign_function_interface) technique together with manualy created descriptors.  
+
+Note that this folder contains code commonly used by the RSA implementations and therefore does not include any CMAKE configuration.
+
+## Properties
+    ENDPOINTS				 defines the relative directory where endpoints and proxys can be found (default: endpoints)
+    CELIX_FRAMEWORK_EXTENDER_PATH  Used in RSA_DFI only. Can be used to define a path to use as an extender path point for the framework bundle. For normal bundles the bundle cache is used. 

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_spi/include/endpoint_description.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_spi/include/endpoint_description.h b/bundles/remote_services/rsa_spi/include/endpoint_description.h
new file mode 100644
index 0000000..de27d2e
--- /dev/null
+++ b/bundles/remote_services/rsa_spi/include/endpoint_description.h
@@ -0,0 +1,50 @@
+/**
+ *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.
+ */
+/*
+ * endpoint_description.h
+ *
+ *  \date       25 Jul 2014
+ *  \author     <a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright  Apache License, Version 2.0
+ */
+
+#ifndef ENDPOINT_DESCRIPTION_H_
+#define ENDPOINT_DESCRIPTION_H_
+
+#include "properties.h"
+#include "array_list.h"
+
+struct endpoint_description {
+    char *frameworkUUID;
+    char *id;
+    // array_list_pt intents;
+    char *service;
+    // HASH_MAP packageVersions;
+    properties_pt properties;
+    unsigned long serviceId;
+};
+
+typedef struct endpoint_description endpoint_description_t;
+typedef endpoint_description_t* endpoint_description_pt;
+
+celix_status_t endpointDescription_create(properties_pt properties, endpoint_description_pt *endpointDescription);
+celix_status_t endpointDescription_destroy(endpoint_description_pt description);
+
+
+#endif /* ENDPOINT_DESCRIPTION_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_spi/include/endpoint_listener.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_spi/include/endpoint_listener.h b/bundles/remote_services/rsa_spi/include/endpoint_listener.h
new file mode 100644
index 0000000..2e6359f
--- /dev/null
+++ b/bundles/remote_services/rsa_spi/include/endpoint_listener.h
@@ -0,0 +1,49 @@
+/**
+ *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.
+ */
+/*
+ * endpoint_listener.h
+ *
+ *  \date       Sep 29, 2011
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef ENDPOINT_LISTENER_H_
+#define ENDPOINT_LISTENER_H_
+
+#include "array_list.h"
+#include "properties.h"
+
+#include "endpoint_description.h"
+
+static const char * const OSGI_ENDPOINT_LISTENER_SERVICE = "endpoint_listener";
+
+static const char * const OSGI_ENDPOINT_LISTENER_SCOPE = "endpoint.listener.scope";
+
+struct endpoint_listener {
+	void *handle;
+	celix_status_t (*endpointAdded)(void *handle, endpoint_description_pt endpoint, char *machtedFilter);
+	celix_status_t (*endpointRemoved)(void *handle, endpoint_description_pt endpoint, char *machtedFilter);
+};
+
+typedef struct endpoint_listener endpoint_listener_t;
+typedef endpoint_listener_t *endpoint_listener_pt;
+
+
+#endif /* ENDPOINT_LISTENER_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_spi/include/export_registration.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_spi/include/export_registration.h b/bundles/remote_services/rsa_spi/include/export_registration.h
new file mode 100644
index 0000000..dc3882b
--- /dev/null
+++ b/bundles/remote_services/rsa_spi/include/export_registration.h
@@ -0,0 +1,22 @@
+/*
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#ifndef CELIX_EXPORT_REGISTRATION_H
+#define CELIX_EXPORT_REGISTRATION_H
+
+#include "celix_errno.h"
+#include "endpoint_description.h"
+#include "service_reference.h"
+
+typedef struct export_registration *export_registration_pt;
+
+typedef struct export_reference *export_reference_pt;
+
+celix_status_t exportRegistration_close(export_registration_pt registration);
+celix_status_t exportRegistration_getException(export_registration_pt registration);
+celix_status_t exportRegistration_getExportReference(export_registration_pt registration, export_reference_pt *reference);
+
+celix_status_t exportReference_getExportedEndpoint(export_reference_pt reference, endpoint_description_pt *endpoint);
+celix_status_t exportReference_getExportedService(export_reference_pt reference, service_reference_pt *service);
+
+#endif //CELIX_EXPORT_REGISTRATION_H

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_spi/include/import_registration.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_spi/include/import_registration.h b/bundles/remote_services/rsa_spi/include/import_registration.h
new file mode 100644
index 0000000..ef8193f
--- /dev/null
+++ b/bundles/remote_services/rsa_spi/include/import_registration.h
@@ -0,0 +1,22 @@
+/*
+ * Licensed under Apache License v2. See LICENSE for more information.
+ */
+#ifndef CELIX_IMPORT_REGISTRATION_H
+#define CELIX_IMPORT_REGISTRATION_H
+
+#include "celix_errno.h"
+#include "endpoint_description.h"
+#include "service_reference.h"
+
+typedef struct import_registration *import_registration_pt;
+
+typedef struct import_reference *import_reference_pt;
+
+celix_status_t importRegistration_close(import_registration_pt registration);
+celix_status_t importRegistration_getException(import_registration_pt registration);
+celix_status_t importRegistration_getImportReference(import_registration_pt registration, import_reference_pt *reference);
+
+celix_status_t importReference_getImportedEndpoint(import_reference_pt reference);
+celix_status_t importReference_getImportedService(import_reference_pt reference);
+
+#endif //CELIX_IMPORT_REGISTRATION_H

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_spi/include/remote_constants.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_spi/include/remote_constants.h b/bundles/remote_services/rsa_spi/include/remote_constants.h
new file mode 100644
index 0000000..0736685
--- /dev/null
+++ b/bundles/remote_services/rsa_spi/include/remote_constants.h
@@ -0,0 +1,38 @@
+/**
+ *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.
+ */
+/*
+ * remote_constants.h
+ *
+ *  \date       Sep 30, 2011
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef REMOTE_CONSTANTS_H_
+#define REMOTE_CONSTANTS_H_
+
+static const char * const OSGI_RSA_SERVICE_EXPORTED_INTERFACES = "service.exported.interfaces";
+static const char * const OSGI_RSA_ENDPOINT_FRAMEWORK_UUID = "endpoint.framework.uuid";
+static const char * const OSGI_RSA_ENDPOINT_SERVICE_ID = "endpoint.service.id";
+static const char * const OSGI_RSA_ENDPOINT_ID = "endpoint.id";
+static const char * const OSGI_RSA_SERVICE_IMPORTED = "service.imported";
+static const char * const OSGI_RSA_SERVICE_IMPORTED_CONFIGS = "service.imported.configs";
+static const char * const OSGI_RSA_SERVICE_LOCATION = "service.location";
+
+#endif /* REMOTE_CONSTANTS_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_spi/include/remote_endpoint.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_spi/include/remote_endpoint.h b/bundles/remote_services/rsa_spi/include/remote_endpoint.h
new file mode 100644
index 0000000..ab80abb
--- /dev/null
+++ b/bundles/remote_services/rsa_spi/include/remote_endpoint.h
@@ -0,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.
+ */
+/*
+ * remote_endpoint.h
+ *
+ *  \date       Oct 7, 2011
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef REMOTE_ENDPOINT_H_
+#define REMOTE_ENDPOINT_H_
+
+#define OSGI_RSA_REMOTE_ENDPOINT "remote_endpoint"
+
+typedef struct remote_endpoint remote_endpoint_t;
+typedef remote_endpoint_t* remote_endpoint_pt;
+
+struct remote_endpoint_service {
+	remote_endpoint_pt endpoint;
+	celix_status_t (*setService)(remote_endpoint_pt endpoint, void *service);
+	celix_status_t (*handleRequest)(remote_endpoint_pt endpoint, char *data, char **reply);
+};
+
+typedef struct remote_endpoint_service *remote_endpoint_service_pt;
+
+
+#endif /* REMOTE_ENDPOINT_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_spi/include/remote_endpoint_impl.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_spi/include/remote_endpoint_impl.h b/bundles/remote_services/rsa_spi/include/remote_endpoint_impl.h
new file mode 100644
index 0000000..3782d62
--- /dev/null
+++ b/bundles/remote_services/rsa_spi/include/remote_endpoint_impl.h
@@ -0,0 +1,38 @@
+/**
+ *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.
+ */
+/*
+ * remote_endpoint_impl.h
+ *
+ *  \date       Oct 11, 2011
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef REMOTE_ENDPOINT_IMPL_H_
+#define REMOTE_ENDPOINT_IMPL_H_
+
+#include "remote_endpoint.h"
+#include "celix_threads.h"
+
+struct remote_endpoint {
+	celix_thread_mutex_t serviceLock;
+	void *service;
+};
+
+#endif /* REMOTE_ENDPOINT_IMPL_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_spi/include/remote_proxy.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_spi/include/remote_proxy.h b/bundles/remote_services/rsa_spi/include/remote_proxy.h
new file mode 100644
index 0000000..4c3f5c3
--- /dev/null
+++ b/bundles/remote_services/rsa_spi/include/remote_proxy.h
@@ -0,0 +1,76 @@
+/**
+ *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.
+ */
+/*
+ * remote_proxy.h
+ *
+ *  \date       Oct 13, 2011
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef REMOTE_PROXY_H_
+#define REMOTE_PROXY_H_
+
+#include "endpoint_listener.h"
+#include "remote_service_admin.h"
+
+#define OSGI_RSA_REMOTE_PROXY_FACTORY 	"remote_proxy_factory"
+#define OSGI_RSA_REMOTE_PROXY_TIMEOUT   "remote_proxy_timeout"
+
+typedef celix_status_t (*sendToHandle)(remote_service_admin_pt remote_service_admin_ptr, endpoint_description_pt endpointDescription, char *request, char **reply, int* replyStatus);
+typedef celix_status_t (*createProxyService)(void *handle, endpoint_description_pt endpointDescription, remote_service_admin_pt rsa, sendToHandle sendToCallback, properties_pt properties, void **service);
+typedef celix_status_t (*destroyProxyService)(void *handle, void *service);
+
+typedef struct remote_proxy_factory *remote_proxy_factory_pt;
+typedef struct remote_proxy_factory_service *remote_proxy_factory_service_pt;
+
+struct remote_proxy_factory {
+	bundle_context_pt context_ptr;
+	char *service;
+
+	remote_proxy_factory_service_pt remote_proxy_factory_service_ptr;
+	properties_pt properties;
+	service_registration_pt registration;
+
+	hash_map_pt proxy_instances;
+
+	void *handle;
+
+	createProxyService create_proxy_service_ptr;
+	destroyProxyService destroy_proxy_service_ptr;
+};
+
+struct remote_proxy_factory_service {
+	remote_proxy_factory_pt factory;
+	celix_status_t (*registerProxyService)(remote_proxy_factory_pt proxyFactoryService, endpoint_description_pt endpoint, remote_service_admin_pt remote_service_admin_ptr, sendToHandle callback);
+	celix_status_t (*unregisterProxyService)(remote_proxy_factory_pt proxyFactoryService, endpoint_description_pt endpoint);
+};
+
+celix_status_t remoteProxyFactory_create(bundle_context_pt context, char *service, void *handle,
+		createProxyService create, destroyProxyService destroy,
+		remote_proxy_factory_pt *remote_proxy_factory_ptr);
+celix_status_t remoteProxyFactory_destroy(remote_proxy_factory_pt *remote_proxy_factory_ptr);
+
+celix_status_t remoteProxyFactory_register(remote_proxy_factory_pt remote_proxy_factory_ptr);
+celix_status_t remoteProxyFactory_unregister(remote_proxy_factory_pt remote_proxy_factory_ptr);
+
+
+
+
+#endif /* REMOTE_PROXY_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/rsa_spi/include/remote_service_admin.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/rsa_spi/include/remote_service_admin.h b/bundles/remote_services/rsa_spi/include/remote_service_admin.h
new file mode 100644
index 0000000..cc7fd98
--- /dev/null
+++ b/bundles/remote_services/rsa_spi/include/remote_service_admin.h
@@ -0,0 +1,73 @@
+/**
+ *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.
+ */
+/*
+ * remote_service_admin.h
+ *
+ *  \date       Sep 30, 2011
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef REMOTE_SERVICE_ADMIN_H_
+#define REMOTE_SERVICE_ADMIN_H_
+
+#include "endpoint_listener.h"
+#include "service_reference.h"
+#include "export_registration.h"
+#include "import_registration.h"
+
+#define OSGI_RSA_REMOTE_SERVICE_ADMIN "remote_service_admin"
+
+typedef struct import_registration_factory import_registration_factory_t;
+typedef import_registration_factory_t* import_registration_factory_pt;
+
+typedef struct remote_service_admin remote_service_admin_t;
+typedef remote_service_admin_t* remote_service_admin_pt;
+
+struct remote_service_admin_service {
+	remote_service_admin_pt admin;
+	celix_status_t (*exportService)(remote_service_admin_pt admin, char *serviceId, properties_pt properties, array_list_pt *registrations);
+	celix_status_t (*removeExportedService)(remote_service_admin_pt admin, export_registration_pt registration);
+	celix_status_t (*getExportedServices)(remote_service_admin_pt admin, array_list_pt *services);
+	celix_status_t (*getImportedEndpoints)(remote_service_admin_pt admin, array_list_pt *services);
+	celix_status_t (*importService)(remote_service_admin_pt admin, endpoint_description_pt endpoint, import_registration_pt *registration);
+
+	celix_status_t (*exportReference_getExportedEndpoint)(export_reference_pt reference, endpoint_description_pt *endpoint);
+	celix_status_t (*exportReference_getExportedService)(export_reference_pt reference, service_reference_pt *service);
+
+	celix_status_t (*exportRegistration_close)(remote_service_admin_pt admin, export_registration_pt registration);
+	celix_status_t (*exportRegistration_getException)(export_registration_pt registration);
+	celix_status_t (*exportRegistration_getExportReference)(export_registration_pt registration, export_reference_pt *reference);
+	celix_status_t (*exportRegistration_freeExportReference)(export_reference_pt *reference);
+	celix_status_t (*exportRegistration_getEndpointDescription)(export_registration_pt registration, endpoint_description_pt endpointDescription);
+
+	celix_status_t (*importReference_getImportedEndpoint)(import_reference_pt reference);
+	celix_status_t (*importReference_getImportedService)(import_reference_pt reference);
+
+	celix_status_t (*importRegistration_close)(remote_service_admin_pt admin, import_registration_pt registration);
+	celix_status_t (*importRegistration_getException)(import_registration_pt registration);
+	celix_status_t (*importRegistration_getImportReference)(import_registration_pt registration, import_reference_pt *reference);
+
+};
+
+typedef struct remote_service_admin_service remote_service_admin_service_t;
+typedef remote_service_admin_service_t* remote_service_admin_service_pt;
+
+
+#endif /* REMOTE_SERVICE_ADMIN_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/topology_manager/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/bundles/remote_services/topology_manager/CMakeLists.txt b/bundles/remote_services/topology_manager/CMakeLists.txt
new file mode 100644
index 0000000..fb22edb
--- /dev/null
+++ b/bundles/remote_services/topology_manager/CMakeLists.txt
@@ -0,0 +1,47 @@
+# 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_subproject(RSA_TOPOLOGY_MANAGER "Option to enable building the Remote Service Admin Service SHM bundle" ON DEPS REMOTE_SERVICE_ADMIN_DFI)
+if (RSA_TOPOLOGY_MANAGER)
+
+    add_celix_bundle(rsa_topology_manager
+        SOURCES
+            src/topology_manager
+            src/scope
+            src/activator
+        VERSION 0.9.0
+        SYMBOLIC_NAME "apache_celix_rs_topology_manager"
+        NAME "Apache Celix RS Topology Manager"
+    )
+    target_include_directories(rsa_topology_manager PRIVATE src)
+    target_include_directories(rsa_topology_manager PRIVATE include)
+    target_link_libraries(rsa_topology_manager PRIVATE Celix::log_helper Celix::rsa_spi)
+
+
+    if (ENABLE_TESTING)
+        find_package(CppUTest REQUIRED)
+	    find_package(Jansson REQUIRED)
+ 
+	    include_directories("${JANSSON_INCLUDE_DIR}")
+        include_directories(${CPPUTEST_INCLUDE_DIR})
+        include_directories(${CPPUTEST_EXT_INCLUDE_DIR})
+        add_subdirectory(tms_tst)
+   endif (ENABLE_TESTING)
+
+    install_celix_bundle(rsa_topology_manager EXPORT celix COMPONENT rsa)
+    #Setup target aliases to match external usage
+    add_library(Celix::rsa_topology_manager ALIAS rsa_topology_manager)
+endif (RSA_TOPOLOGY_MANAGER)

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/topology_manager/README.md
----------------------------------------------------------------------
diff --git a/bundles/remote_services/topology_manager/README.md b/bundles/remote_services/topology_manager/README.md
new file mode 100644
index 0000000..6200cc4
--- /dev/null
+++ b/bundles/remote_services/topology_manager/README.md
@@ -0,0 +1,23 @@
+<!--
+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.
+-->
+
+## Topology Manager
+
+The Topology Manager decides which services should be imported and exported according to a defined policy. Currently, only one policy is implemented in Celix, the *promiscuous* policy, which simply imports and exports all services. Note that the Topology Manager is essential to use remote services.
+
+###### CMake option
+    BUILD_RSA_TOPOLOGY_MANAGER=ON

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/topology_manager/include/tm_scope.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/topology_manager/include/tm_scope.h b/bundles/remote_services/topology_manager/include/tm_scope.h
new file mode 100644
index 0000000..d4f60ca
--- /dev/null
+++ b/bundles/remote_services/topology_manager/include/tm_scope.h
@@ -0,0 +1,46 @@
+/**
+ *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.
+ */
+/*
+ * tm_scope.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 TM_SCOPE_H_
+#define TM_SCOPE_H_
+
+#include "celix_errno.h"
+
+#define TOPOLOGYMANAGER_SCOPE_SERVICE "tm_scope"
+
+
+struct tm_scope_service {
+    void *handle;	// scope_pt
+    celix_status_t (*addExportScope)(void *handle, char *filter, properties_pt props);
+    celix_status_t (*removeExportScope)(void *handle, char *filter);
+    celix_status_t (*addImportScope)(void *handle, char *filter);
+    celix_status_t (*removeImportScope)(void *handle, char *filter);
+};
+
+typedef struct tm_scope_service tm_scope_service_t;
+typedef tm_scope_service_t *tm_scope_service_pt;
+
+#endif /* TM_SCOPE_H_ */

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/topology_manager/src/activator.c
----------------------------------------------------------------------
diff --git a/bundles/remote_services/topology_manager/src/activator.c b/bundles/remote_services/topology_manager/src/activator.c
new file mode 100644
index 0000000..7f39a25
--- /dev/null
+++ b/bundles/remote_services/topology_manager/src/activator.c
@@ -0,0 +1,289 @@
+/**
+ *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       Sep 29, 2011
+ *  \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 "constants.h"
+#include "bundle_activator.h"
+#include "service_tracker.h"
+#include "service_registration.h"
+
+#include "topology_manager.h"
+#include "endpoint_listener.h"
+#include "remote_constants.h"
+#include "listener_hook_service.h"
+#include "log_service.h"
+#include "log_helper.h"
+#include "scope.h"
+#include "tm_scope.h"
+#include "topology_manager.h"
+
+struct activator {
+	bundle_context_pt context;
+
+	topology_manager_pt manager;
+
+	service_tracker_pt endpointListenerTracker;
+	service_tracker_pt remoteServiceAdminTracker;
+	service_listener_pt serviceListener;
+
+	endpoint_listener_pt endpointListener;
+	service_registration_pt endpointListenerService;
+
+	listener_hook_service_pt hookService;
+	service_registration_pt hook;
+
+	tm_scope_service_pt	scopeService;
+	service_registration_pt scopeReg;
+
+	log_helper_pt loghelper;
+};
+
+
+static celix_status_t bundleActivator_createEPLTracker(struct activator *activator, service_tracker_pt *tracker);
+static celix_status_t bundleActivator_createRSATracker(struct activator *activator, service_tracker_pt *tracker);
+static celix_status_t bundleActivator_createServiceListener(struct activator *activator, service_listener_pt *listener);
+
+celix_status_t bundleActivator_create(bundle_context_pt context, void **userData) {
+	celix_status_t status = CELIX_SUCCESS;
+	struct activator *activator = NULL;
+	void *scope;
+
+	activator = calloc(1, sizeof(struct activator));
+
+	if (!activator) {
+		return CELIX_ENOMEM;
+	}
+
+	activator->context = context;
+	activator->endpointListenerService = NULL;
+	activator->endpointListenerTracker = NULL;
+	activator->hook = NULL;
+	activator->manager = NULL;
+	activator->remoteServiceAdminTracker = NULL;
+	activator->serviceListener = NULL;
+	activator->scopeService = calloc(1, sizeof(*(activator->scopeService)));
+	if (activator->scopeService == NULL)
+	{
+		free(activator);
+		return CELIX_ENOMEM;
+	}
+
+	activator->scopeService->addExportScope = tm_addExportScope;
+	activator->scopeService->removeExportScope = tm_removeExportScope;
+	activator->scopeService->addImportScope = tm_addImportScope;
+	activator->scopeService->removeImportScope = tm_removeImportScope;
+	activator->scopeReg = NULL; // explicitly needed, otherwise exception
+
+	logHelper_create(context, &activator->loghelper);
+	logHelper_start(activator->loghelper);
+
+	status = topologyManager_create(context, activator->loghelper, &activator->manager, &scope);
+	activator->scopeService->handle = scope;
+
+	if (status == CELIX_SUCCESS) {
+		status = bundleActivator_createEPLTracker(activator, &activator->endpointListenerTracker);
+		if (status == CELIX_SUCCESS) {
+			status = bundleActivator_createRSATracker(activator, &activator->remoteServiceAdminTracker);
+			if (status == CELIX_SUCCESS) {
+				status = bundleActivator_createServiceListener(activator, &activator->serviceListener);
+				if (status == CELIX_SUCCESS) {
+					*userData = activator;
+				}
+			}
+		}
+	}
+
+	if(status != CELIX_SUCCESS){
+		bundleActivator_destroy(activator,context);
+	}
+
+	return status;
+}
+
+static celix_status_t bundleActivator_createEPLTracker(struct activator *activator, service_tracker_pt *tracker) {
+	celix_status_t status;
+
+	service_tracker_customizer_pt customizer = NULL;
+
+	status = serviceTrackerCustomizer_create(activator->manager, topologyManager_endpointListenerAdding, topologyManager_endpointListenerAdded, topologyManager_endpointListenerModified,
+			topologyManager_endpointListenerRemoved, &customizer);
+
+	if (status == CELIX_SUCCESS) {
+		status = serviceTracker_create(activator->context, (char *) OSGI_ENDPOINT_LISTENER_SERVICE, customizer, tracker);
+	}
+
+	return status;
+}
+
+static celix_status_t bundleActivator_createRSATracker(struct activator *activator, service_tracker_pt *tracker) {
+	celix_status_t status;
+
+	service_tracker_customizer_pt customizer = NULL;
+
+	status = serviceTrackerCustomizer_create(activator->manager, topologyManager_rsaAdding, topologyManager_rsaAdded, topologyManager_rsaModified, topologyManager_rsaRemoved, &customizer);
+
+	if (status == CELIX_SUCCESS) {
+		status = serviceTracker_create(activator->context, OSGI_RSA_REMOTE_SERVICE_ADMIN, customizer, tracker);
+	}
+
+	return status;
+}
+
+static celix_status_t bundleActivator_createServiceListener(struct activator *activator, service_listener_pt *listener) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	*listener = malloc(sizeof(**listener));
+	if (!*listener) {
+		return CELIX_ENOMEM;
+	}
+
+	(*listener)->handle = activator->manager;
+	(*listener)->serviceChanged = topologyManager_serviceChanged;
+
+	return status;
+}
+
+celix_status_t bundleActivator_start(void * userData, bundle_context_pt context) {
+	celix_status_t status;
+	struct activator *activator = userData;
+
+	endpoint_listener_pt endpointListener = malloc(sizeof(*endpointListener));
+	endpointListener->handle = activator->manager;
+	endpointListener->endpointAdded = topologyManager_addImportedService;
+	endpointListener->endpointRemoved = topologyManager_removeImportedService;
+	activator->endpointListener = endpointListener;
+
+	const char *uuid = NULL;
+	status = bundleContext_getProperty(activator->context, OSGI_FRAMEWORK_FRAMEWORK_UUID, &uuid);
+	if (!uuid) {
+		logHelper_log(activator->loghelper, OSGI_LOGSERVICE_ERROR, "TOPOLOGY_MANAGER: no framework UUID defined?!");
+		return CELIX_ILLEGAL_STATE;
+	}
+
+	size_t len = 14 + strlen(OSGI_FRAMEWORK_OBJECTCLASS) + strlen(OSGI_RSA_ENDPOINT_FRAMEWORK_UUID) + strlen(uuid);
+	char *scope = malloc(len);
+	if (!scope) {
+		return CELIX_ENOMEM;
+	}
+
+	snprintf(scope, len, "(&(%s=*)(!(%s=%s)))", OSGI_FRAMEWORK_OBJECTCLASS, OSGI_RSA_ENDPOINT_FRAMEWORK_UUID, uuid);
+
+	logHelper_log(activator->loghelper, OSGI_LOGSERVICE_INFO, "TOPOLOGY_MANAGER: endpoint listener scope is %s", scope);
+
+	properties_pt props = properties_create();
+	properties_set(props, (char *) OSGI_ENDPOINT_LISTENER_SCOPE, scope);
+
+	// We can release the scope, as properties_set makes a copy of the key & value...
+	free(scope);
+
+	bundleContext_registerService(context, (char *) OSGI_ENDPOINT_LISTENER_SERVICE, endpointListener, props, &activator->endpointListenerService);
+
+	listener_hook_service_pt hookService = malloc(sizeof(*hookService));
+	hookService->handle = activator->manager;
+	hookService->added = topologyManager_listenerAdded;
+	hookService->removed = topologyManager_listenerRemoved;
+	activator->hookService = hookService;
+
+	bundleContext_registerService(context, (char *) OSGI_FRAMEWORK_LISTENER_HOOK_SERVICE_NAME, hookService, NULL, &activator->hook);
+	bundleContext_addServiceListener(context, activator->serviceListener, "(service.exported.interfaces=*)");
+
+	if (status == CELIX_SUCCESS) {
+		serviceTracker_open(activator->remoteServiceAdminTracker);
+	}
+
+	if (status == CELIX_SUCCESS) {
+		status = serviceTracker_open(activator->endpointListenerTracker);
+	}
+
+	bundleContext_registerService(context, (char *) TOPOLOGYMANAGER_SCOPE_SERVICE, activator->scopeService, NULL, &activator->scopeReg);
+
+	array_list_pt references = NULL;
+	bundleContext_getServiceReferences(context, NULL, "(service.exported.interfaces=*)", &references);
+	int i;
+	for (i = 0; i < arrayList_size(references); i++) {
+		service_reference_pt reference = arrayList_get(references, i);
+		const char* serviceId = NULL;
+		status = CELIX_DO_IF(status, serviceReference_getProperty(reference, OSGI_FRAMEWORK_SERVICE_ID, &serviceId));
+
+		CELIX_DO_IF(status, topologyManager_addExportedService(activator->manager, reference, (char*)serviceId));
+	}
+	arrayList_destroy(references);
+
+	return status;
+}
+
+celix_status_t bundleActivator_stop(void * userData, bundle_context_pt context) {
+	celix_status_t status = CELIX_SUCCESS;
+	struct activator *activator = userData;
+
+	if (serviceTracker_close(activator->remoteServiceAdminTracker) == CELIX_SUCCESS) {
+		serviceTracker_destroy(activator->remoteServiceAdminTracker);
+	}
+
+	if (serviceTracker_close(activator->endpointListenerTracker) == CELIX_SUCCESS) {
+		serviceTracker_destroy(activator->endpointListenerTracker);
+	}
+
+	bundleContext_removeServiceListener(context, activator->serviceListener);
+	free(activator->serviceListener);
+
+	serviceRegistration_unregister(activator->hook);
+	free(activator->hookService);
+
+	serviceRegistration_unregister(activator->endpointListenerService);
+	free(activator->endpointListener);
+
+	serviceRegistration_unregister(activator->scopeReg);
+
+	topologyManager_closeImports(activator->manager);
+
+	return status;
+}
+
+celix_status_t bundleActivator_destroy(void * userData, bundle_context_pt context) {
+	celix_status_t status = CELIX_SUCCESS;
+
+	struct activator *activator = userData;
+	if (!activator || !activator->manager) {
+		status = CELIX_BUNDLE_EXCEPTION;
+	} else {
+		logHelper_stop(activator->loghelper);
+		logHelper_destroy(&activator->loghelper);
+
+		status = topologyManager_destroy(activator->manager);
+
+		if (activator->scopeService) {
+			free(activator->scopeService);
+		}
+
+		free(activator);
+	}
+
+	return status;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/topology_manager/src/scope.c
----------------------------------------------------------------------
diff --git a/bundles/remote_services/topology_manager/src/scope.c b/bundles/remote_services/topology_manager/src/scope.c
new file mode 100644
index 0000000..b81d050
--- /dev/null
+++ b/bundles/remote_services/topology_manager/src/scope.c
@@ -0,0 +1,326 @@
+/**
+ *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.
+ */
+/*
+ * scope.c
+ *
+ *  \date       Sep 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 <string.h>
+#include "scope.h"
+#include "tm_scope.h"
+#include "topology_manager.h"
+#include "utils.h"
+
+struct scope_item {
+    properties_pt props;
+};
+
+struct scope {
+    void *manager;	// owner of the scope datastructure
+    celix_thread_mutex_t exportScopeLock;
+    hash_map_pt exportScopes;           // key is filter, value is scope_item (properties set)
+
+    celix_thread_mutex_t importScopeLock;
+    array_list_pt importScopes;			// list of filters
+
+    celix_status_t (*exportScopeChangedHandler)(void* manager, char *filter);
+    celix_status_t (*importScopeChangedHandler)(void* manager, char *filter);
+};
+
+static celix_status_t import_equal(const void *, const void *, bool *equals);
+
+/*
+ * SERVICES
+ */
+
+celix_status_t tm_addExportScope(void *handle, char *filter, properties_pt props) {
+    celix_status_t status = CELIX_SUCCESS;
+    scope_pt scope = (scope_pt) handle;
+    properties_pt present;
+
+    if (handle == NULL)
+        return CELIX_ILLEGAL_ARGUMENT;
+
+    if (celixThreadMutex_lock(&scope->exportScopeLock) == CELIX_SUCCESS) {
+        // For now we just don't allow two exactly the same filters
+        // TODO: What we actually need is the following
+        // If part of the new filter is already present in any of the filters in exportScopes
+        // we have to assure that the new filter defines other property keys than the property keys
+        // in the already defined filter!
+        present = (properties_pt) hashMap_get(scope->exportScopes, filter);
+        if (present == NULL) {
+            struct scope_item *item = calloc(1, sizeof(*item));
+            if (item == NULL) {
+                status = CELIX_ENOMEM;
+            } else {
+                item->props = props;
+                hashMap_put(scope->exportScopes, (void*) strdup(filter), (void*) item);
+            }
+        } else {
+            // don't allow the same filter twice
+            properties_destroy(props);
+            status = CELIX_ILLEGAL_ARGUMENT;
+        }
+        celixThreadMutex_unlock(&scope->exportScopeLock);
+    }
+
+    if (scope->exportScopeChangedHandler != NULL) {
+        status = CELIX_DO_IF(status, scope->exportScopeChangedHandler(scope->manager, filter));
+    }
+
+    return status;
+}
+
+celix_status_t tm_removeExportScope(void *handle, char *filter) {
+    celix_status_t status = CELIX_SUCCESS;
+    scope_pt scope = (scope_pt) handle;
+
+    if (handle == NULL)
+        return CELIX_ILLEGAL_ARGUMENT;
+
+    if (celixThreadMutex_lock(&scope->exportScopeLock) == CELIX_SUCCESS) {
+        struct scope_item *present = (struct scope_item *) hashMap_get(scope->exportScopes, filter);
+        if (present == NULL) {
+            status = CELIX_ILLEGAL_ARGUMENT;
+        } else {
+            properties_destroy(present->props);
+            hashMap_remove(scope->exportScopes, filter); // frees also the item!
+        }
+        celixThreadMutex_unlock(&scope->exportScopeLock);
+    }
+    if (scope->exportScopeChangedHandler != NULL) {
+        status = CELIX_DO_IF(status, scope->exportScopeChangedHandler(scope->manager, filter));
+    }
+    return status;
+}
+
+celix_status_t tm_addImportScope(void *handle, char *filter) {
+    celix_status_t status = CELIX_SUCCESS;
+    scope_pt scope = (scope_pt) handle;
+
+    filter_pt new;
+
+    if (handle == NULL)
+        return CELIX_ILLEGAL_ARGUMENT;
+    new = filter_create(filter);
+    if (new == NULL) {
+        return CELIX_ILLEGAL_ARGUMENT; // filter not parseble
+    }
+    if (celixThreadMutex_lock(&scope->importScopeLock) == CELIX_SUCCESS) {
+        int index = arrayList_indexOf(scope->importScopes, new);
+        filter_pt present = (filter_pt) arrayList_get(scope->importScopes, index);
+        if (present == NULL) {
+            arrayList_add(scope->importScopes, new);
+        } else {
+            filter_destroy(new);
+            status = CELIX_ILLEGAL_ARGUMENT;
+        }
+
+        celixThreadMutex_unlock(&scope->importScopeLock);
+    }
+    if (scope->importScopeChangedHandler != NULL) {
+        status = CELIX_DO_IF(status, scope->importScopeChangedHandler(scope->manager, filter));
+    }
+    return status;
+}
+
+celix_status_t tm_removeImportScope(void *handle, char *filter) {
+    celix_status_t status = CELIX_SUCCESS;
+    scope_pt scope = (scope_pt) handle;
+    filter_pt new;
+
+    if (handle == NULL)
+        return CELIX_ILLEGAL_ARGUMENT;
+
+    new = filter_create(filter);
+    if (new == NULL) {
+        return CELIX_ILLEGAL_ARGUMENT; // filter not parseble
+    }
+
+    if (celixThreadMutex_lock(&scope->importScopeLock) == CELIX_SUCCESS) {
+        int index = arrayList_indexOf(scope->importScopes, new);
+        filter_pt present = (filter_pt) arrayList_get(scope->importScopes, index);
+        if (present == NULL)
+            status = CELIX_ILLEGAL_ARGUMENT;
+        else {
+            arrayList_removeElement(scope->importScopes, present);
+            filter_destroy(present);
+        }
+        celixThreadMutex_unlock(&scope->importScopeLock);
+    }
+    if (scope->importScopeChangedHandler != NULL) {
+        status = CELIX_DO_IF(status, scope->importScopeChangedHandler(scope->manager, filter));
+    }
+    filter_destroy(new);
+    return status;
+}
+
+/*****************************************************************************
+ * GLOBAL FUNCTIONS
+ *****************************************************************************/
+
+void scope_setExportScopeChangedCallback(scope_pt scope, celix_status_t (*changed)(void *handle, char *servName)) {
+    scope->exportScopeChangedHandler = changed;
+}
+
+void scope_setImportScopeChangedCallback(scope_pt scope, celix_status_t (*changed)(void *handle, char *servName)) {
+    scope->importScopeChangedHandler = changed;
+}
+
+celix_status_t scope_scopeCreate(void *handle, scope_pt *scope) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    *scope = calloc(1, sizeof **scope);
+
+    if (*scope == NULL) {
+        return CELIX_ENOMEM;
+    }
+
+    (*scope)->manager = handle;
+    celixThreadMutex_create(&(*scope)->exportScopeLock, NULL);
+    celixThreadMutex_create(&(*scope)->importScopeLock, NULL);
+
+    (*scope)->exportScopes = hashMap_create(utils_stringHash, NULL, utils_stringEquals, NULL);
+    arrayList_createWithEquals(import_equal, &((*scope)->importScopes));
+    (*scope)->exportScopeChangedHandler = NULL;
+
+    return status;
+}
+
+celix_status_t scope_scopeDestroy(scope_pt scope) {
+    celix_status_t status = CELIX_SUCCESS;
+
+    if (celixThreadMutex_lock(&scope->exportScopeLock) == CELIX_SUCCESS) {
+        hash_map_iterator_pt iter = hashMapIterator_create(scope->exportScopes);
+        while (hashMapIterator_hasNext(iter)) {
+            hash_map_entry_pt scopedEntry = hashMapIterator_nextEntry(iter);
+            struct scope_item *item = (struct scope_item*) hashMapEntry_getValue(scopedEntry);
+            properties_destroy(item->props);
+        }
+        hashMapIterator_destroy(iter);
+        hashMap_destroy(scope->exportScopes, true, true); // free keys, free values
+        celixThreadMutex_unlock(&scope->exportScopeLock);
+    }
+
+    if (celixThreadMutex_lock(&scope->importScopeLock) == CELIX_SUCCESS) {
+        array_list_iterator_pt imp_iter = arrayListIterator_create(scope->importScopes);
+        while (arrayListIterator_hasNext(imp_iter)) {
+            filter_pt element = (filter_pt) arrayListIterator_next(imp_iter);
+            filter_destroy(element);
+            // no need to call arrayList_removeElement(element) because complete list is destroyed
+        }
+        arrayListIterator_destroy(imp_iter);
+        arrayList_destroy(scope->importScopes);
+        celixThreadMutex_unlock(&scope->importScopeLock);
+    }
+
+    celixThreadMutex_destroy(&scope->exportScopeLock);
+    celixThreadMutex_destroy(&scope->importScopeLock);
+    free(scope);
+    return status;
+}
+
+/*****************************************************************************
+ * STATIC FUNCTIONS
+ *****************************************************************************/
+static celix_status_t import_equal(const void *src, const void *dest, bool *equals) {
+    celix_status_t status;
+
+    filter_pt src_filter = (filter_pt) src;
+    filter_pt dest_filter = (filter_pt) dest;
+    status = filter_match_filter(src_filter, dest_filter, equals);
+    return status;
+}
+
+bool scope_allowImport(scope_pt scope, endpoint_description_pt endpoint) {
+    bool allowImport = false;
+    array_list_iterator_pt iter;
+
+    if (celixThreadMutex_lock(&(scope->importScopeLock)) == CELIX_SUCCESS) {
+        if (arrayList_size(scope->importScopes) == 0) {
+            allowImport = true;
+        } else {
+            iter = arrayListIterator_create(scope->importScopes);
+            while ((allowImport == false) && arrayListIterator_hasNext(iter)) {
+                filter_pt element = (filter_pt) arrayListIterator_next(iter);
+                filter_match(element, endpoint->properties, &allowImport);
+            }
+            arrayListIterator_destroy(iter);
+        }
+        celixThreadMutex_unlock(&scope->importScopeLock);
+    }
+    return allowImport;
+}
+
+celix_status_t scope_getExportProperties(scope_pt scope, service_reference_pt reference, properties_pt *props) {
+    celix_status_t status = CELIX_SUCCESS;
+    unsigned int size = 0;
+    char **keys;
+    bool found = false;
+
+    *props = NULL;
+    properties_pt serviceProperties = properties_create();  // GB: not sure if a copy is needed
+                                                            // or serviceReference_getProperties() is
+                                                            // is acceptable
+
+    serviceReference_getPropertyKeys(reference, &keys, &size);
+    for (int i = 0; i < size; i++) {
+        char *key = keys[i];
+        const char* value = NULL;
+
+        if (serviceReference_getProperty(reference, key, &value) == CELIX_SUCCESS) {
+//        		&& strcmp(key, (char*) OSGI_RSA_SERVICE_EXPORTED_INTERFACES) != 0
+//        		&& strcmp(key, (char*) OSGI_FRAMEWORK_OBJECTCLASS) != 0) {
+            properties_set(serviceProperties, key, value);
+        }
+
+    }
+
+    free(keys);
+
+    if (celixThreadMutex_lock(&(scope->exportScopeLock)) == CELIX_SUCCESS) {
+        hash_map_iterator_pt scopedPropIter = hashMapIterator_create(scope->exportScopes);
+        // TODO: now stopping if first filter matches, alternatively we could build up
+        //       the additional output properties for each filter that matches?
+        while ((!found) && hashMapIterator_hasNext(scopedPropIter)) {
+            hash_map_entry_pt scopedEntry = hashMapIterator_nextEntry(scopedPropIter);
+            char *filterStr = (char *) hashMapEntry_getKey(scopedEntry);
+            filter_pt filter = filter_create(filterStr);
+            if (filter != NULL) {
+                // test if the scope filter matches the exported service properties
+                status = filter_match(filter, serviceProperties, &found);
+                if (found) {
+                    struct scope_item *item = (struct scope_item *) hashMapEntry_getValue(scopedEntry);
+                    *props = item->props;
+                }
+            }
+            filter_destroy(filter);
+        }
+        hashMapIterator_destroy(scopedPropIter);
+        properties_destroy(serviceProperties);
+
+        celixThreadMutex_unlock(&(scope->exportScopeLock));
+    }
+
+    return status;
+}

http://git-wip-us.apache.org/repos/asf/celix/blob/3bce889b/bundles/remote_services/topology_manager/src/scope.h
----------------------------------------------------------------------
diff --git a/bundles/remote_services/topology_manager/src/scope.h b/bundles/remote_services/topology_manager/src/scope.h
new file mode 100644
index 0000000..4035e2c
--- /dev/null
+++ b/bundles/remote_services/topology_manager/src/scope.h
@@ -0,0 +1,150 @@
+/**
+ *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.
+ */
+/*
+ * scope.h
+ *
+ *  \date       Sep 29, 2015
+ *  \author    	<a href="mailto:dev@celix.apache.org">Apache Celix Project Team</a>
+ *  \copyright	Apache License, Version 2.0
+ */
+
+#ifndef TOPOLOGY_SCOPE_H_
+#define TOPOLOGY_SCOPE_H_
+
+#include "celixbool.h"
+#include "celix_errno.h"
+#include "celix_threads.h"
+#include "hash_map.h"
+#include "endpoint_description.h"
+#include "properties.h"
+#include "service_reference.h"
+#include "tm_scope.h"
+
+typedef struct scope *scope_pt;
+
+
+
+/* \brief  create scope structure
+ *
+ * \param  owning component pointer
+ * \param  scope to be created
+ *
+ * \return CELIX_SUCCESS
+ *         CELIX_ENOMEM
+ */
+celix_status_t scope_scopeCreate(void *handle, scope_pt *scope);
+
+/* \brief  destroy scope structure
+ *
+ * \param  scope to be destroyed
+ *
+ * \return CELIX_SUCCESS
+ */
+celix_status_t scope_scopeDestroy(scope_pt scope);
+
+/* \brief  register export scope change callback of topology manager
+ *
+ * \param  scope structure
+ * \param  changed function pointer
+ *
+ * \return -
+ */
+void scope_setExportScopeChangedCallback(scope_pt scope, celix_status_t (*changed)(void *handle, char *servName));
+
+/* \brief  register import scope change callback of topology manager
+ *
+ * \param  scope structure
+ * \param  changed function pointer
+ *
+ * \return -
+ */
+void scope_setImportScopeChangedCallback(scope_pt scope, celix_status_t (*changed)(void *handle, char *servName));
+
+
+/* \brief  Test if scope allows import of service
+ *
+ * \param  scope containing import rules
+ * \param  endpoint import service endpoint description
+ *
+ * \return true import allowed
+ *         false import not allowed
+ */
+bool scope_allowImport(scope_pt scope, endpoint_description_pt endpoint);
+
+/* \brief  Test if scope allows import of service
+ *
+ * \param  scope containing export rules
+ * \param  reference to service
+ * \param  props, additional properties defining restrictions for the exported service
+ *                NULL if no additional restrictions found
+ *
+ * \return CELIX_SUCCESS
+ *
+ */
+celix_status_t scope_getExportProperties(scope_pt scope, service_reference_pt reference, properties_pt *props);
+
+/* \brief  add restricted scope for specified exported service
+ *
+ * \param  handle pointer to scope
+ * \param  filter, filter string
+ * \param  props additional properties defining restrictions for the exported service
+ *
+ * \return CELIX_SUCCESS if added to scope
+ *         CELIX_ILLEGAL_ARGUMENT if service scope is already restricted before
+ *
+ */
+celix_status_t tm_addExportScope(void *handle, char *filter, properties_pt props);
+
+/* \brief  remove restricted scope for specified exported service
+ *
+ * \param  handle pointer to scope
+ * \param  filter, filter string
+ *
+ * \return CELIX_SUCCESS if removed
+ *         CELIX_ILLEGAL_ARGUMENT if service not found in scope
+ *
+ */
+celix_status_t tm_removeExportScope(void *handle, char *filter);
+
+/* \brief  add restricted scope for specified imported service
+ *
+ * \param  handle pointer to scope
+ * \param  filter, filter string
+ * \param  props additional properties defining restrictions for the imported service
+ *
+ * \return CELIX_SUCCESS if added to scope
+ *         CELIX_ILLEGAL_ARGUMENT if service scope is already restricted before
+ *
+ */
+celix_status_t tm_addImportScope(void *handle, char *filter);
+
+
+/* \brief  remove restricted scope for specified imported service
+ *
+ * \param  handle pointer to scope
+ * \param  filter, filter string
+ *
+ * \return CELIX_SUCCESS if removed
+ *         CELIX_ILLEGAL_ARGUMENT if service not found in scope
+ *
+ */
+celix_status_t tm_removeImportScope(void *handle, char *filter);
+
+
+#endif // TOPOLOGY_SCOPE_H_