Merge pull request #347 from apache/feature/add_intent_to_cxx_rsa
Feature/add intent to cxx rsa
diff --git a/bundles/cxx_remote_services/admin/CMakeLists.txt b/bundles/cxx_remote_services/admin/CMakeLists.txt
index 4a6dac3..24b77ab 100644
--- a/bundles/cxx_remote_services/admin/CMakeLists.txt
+++ b/bundles/cxx_remote_services/admin/CMakeLists.txt
@@ -23,8 +23,8 @@
FILENAME "Celix_RemoteServiceAdmin"
SOURCES
src/RemoteServiceAdmin.cc
+ src/RemoteServiceAdminActivator.cc
)
-target_include_directories(RemoteServiceAdmin PRIVATE include)
target_link_libraries(RemoteServiceAdmin PRIVATE
Celix::rsa_spi
Celix::framework
diff --git a/bundles/cxx_remote_services/admin/gtest/src/RemoteServiceAdminTestSuite.cc b/bundles/cxx_remote_services/admin/gtest/src/RemoteServiceAdminTestSuite.cc
index 3ffdd18..d9b00cf 100644
--- a/bundles/cxx_remote_services/admin/gtest/src/RemoteServiceAdminTestSuite.cc
+++ b/bundles/cxx_remote_services/admin/gtest/src/RemoteServiceAdminTestSuite.cc
@@ -87,10 +87,10 @@
std::string cmpUUID{};
};
-class StubExportServiceGuard : public celix::rsa::IExportServiceGuard {
+class StubExportRegistration : public celix::rsa::IExportRegistration {
public:
- explicit StubExportServiceGuard(std::weak_ptr<StubExportedServiceEntry> _entry) : entry{std::move(_entry)} {}
- ~StubExportServiceGuard() noexcept override {
+ explicit StubExportRegistration(std::weak_ptr<StubExportedServiceEntry> _entry) : entry{std::move(_entry)} {}
+ ~StubExportRegistration() noexcept override {
auto e = entry.lock();
if (e) {
e->close();
@@ -101,28 +101,45 @@
const std::weak_ptr<StubExportedServiceEntry> entry;
};
-class StubExportServiceFactory : public celix::rsa::IExportServiceFactory {
-public:
- explicit StubExportServiceFactory(std::shared_ptr<celix::BundleContext> _ctx) : ctx{std::move(_ctx)} {}
-
- std::unique_ptr<celix::rsa::IExportServiceGuard> exportService(const celix::Properties& /*serviceProperties*/) override {
- auto entry = std::make_shared<StubExportedServiceEntry>(ctx);
- std::lock_guard<std::mutex> lock{mutex};
- entries.emplace_back(entry);
- return std::make_unique<StubExportServiceGuard>(entry);
- }
-
-private:
- const std::shared_ptr<celix::BundleContext> ctx;
- std::mutex mutex{};
- std::vector<std::shared_ptr<StubExportedServiceEntry>> entries{};
-};
-
class IDummyService {
public:
virtual ~IDummyService() noexcept = default;
};
+class StubExportServiceFactory : public celix::rsa::IExportServiceFactory {
+public:
+ explicit StubExportServiceFactory(std::shared_ptr<celix::BundleContext> _ctx) : ctx{std::move(_ctx)} {}
+ ~StubExportServiceFactory() noexcept override = default;
+
+ std::unique_ptr<celix::rsa::IExportRegistration> exportService(const celix::Properties& /*serviceProperties*/) override {
+ auto entry = std::make_shared<StubExportedServiceEntry>(ctx);
+ std::lock_guard<std::mutex> lock{mutex};
+ entries.emplace_back(entry);
+ return std::make_unique<StubExportRegistration>(entry);
+ }
+
+
+ [[nodiscard]] const std::string &getRemoteServiceType() const override {
+ return serviceType;
+ }
+
+ [[nodiscard]] const std::vector<std::string> &getSupportedIntents() const override {
+ return intents;
+ }
+
+ [[nodiscard]] const std::vector<std::string> &getSupportedConfigs() const override {
+ return configs;
+ }
+
+private:
+ const std::string serviceType = celix::typeName<IDummyService>();
+ const std::vector<std::string> configs = {"test"};
+ const std::vector<std::string> intents = {"osgi.basic"};
+ const std::shared_ptr<celix::BundleContext> ctx;
+ std::mutex mutex{};
+ std::vector<std::shared_ptr<StubExportedServiceEntry>> entries{};
+};
+
class DummyServiceImpl : public IDummyService {
public:
~DummyServiceImpl() noexcept override = default;
@@ -141,7 +158,7 @@
EXPECT_EQ(0, count);
auto reg1 = ctx->registerService<celix::rsa::IExportServiceFactory>(std::make_shared<StubExportServiceFactory>(ctx))
- .addProperty(celix::rsa::IExportServiceFactory::TARGET_SERVICE_NAME, celix::typeName<IDummyService>())
+ .addProperty(celix::rsa::IExportServiceFactory::REMOTE_SERVICE_TYPE, celix::typeName<IDummyService>())
.build();
count = ctx->useService<celix::rsa::IExportedService>()
@@ -190,7 +207,7 @@
EXPECT_EQ(0, count);
auto reg2 = ctx->registerService<celix::rsa::IExportServiceFactory>(std::make_shared<StubExportServiceFactory>(ctx))
- .addProperty(celix::rsa::IExportServiceFactory::TARGET_SERVICE_NAME, celix::typeName<IDummyService>())
+ .addProperty(celix::rsa::IExportServiceFactory::REMOTE_SERVICE_TYPE, celix::typeName<IDummyService>())
.build();
//rsa called export service factory which created a IExportServiceRegistration, which register the marker interface IExportedService indicating an exported service
@@ -199,7 +216,38 @@
EXPECT_EQ(1, count);
}
+TEST_F(RemoteServiceAdminTestSuite, exportServiceUsingConfig) {
+ auto bndId = ctx->installBundle(REMOTE_SERVICE_ADMIN_BUNDLE_LOCATION);
+ EXPECT_GE(bndId, 0);
+ auto factoryRegistration = ctx->registerService<celix::rsa::IExportServiceFactory>(std::make_shared<StubExportServiceFactory>(ctx))
+ .addProperty(celix::rsa::IExportServiceFactory::REMOTE_SERVICE_TYPE, celix::typeName<IDummyService>())
+ .build();
+
+ /**
+ * When I add a export service factory and register a service with exported interfaces and a mismatched
+ * service.export.configs this will no be exported.
+ */
+ auto reg = ctx->registerService<IDummyService>(std::make_shared<DummyServiceImpl>())
+ .addProperty(celix::rsa::SERVICE_EXPORTED_INTERFACES, "*")
+ .addProperty(celix::rsa::SERVICE_IMPORTED_CONFIGS, "non-existing-config")
+ .build();
+ auto count = ctx->useService<celix::rsa::IExportedService>()
+ .build();
+ EXPECT_EQ(0, count);
+
+ /**
+ * When I add a export service factory and register a service with exported interfaces and a correct
+ * service.export.configs the service will be exported
+ */
+ reg = ctx->registerService<IDummyService>(std::make_shared<DummyServiceImpl>())
+ .addProperty(celix::rsa::SERVICE_EXPORTED_INTERFACES, "*")
+ .addProperty(celix::rsa::SERVICE_IMPORTED_CONFIGS, "test")
+ .build();
+ count = ctx->useService<celix::rsa::IExportedService>()
+ .build();
+ EXPECT_EQ(1, count);
+}
/**
@@ -237,10 +285,10 @@
std::string cmpUUID{};
};
-class StubImportServiceGuard : public celix::rsa::IImportServiceGuard {
+class StubImportRegistration : public celix::rsa::IImportRegistration {
public:
- explicit StubImportServiceGuard(std::weak_ptr<StubImportedServiceEntry> _entry) : entry{std::move(_entry)} {}
- ~StubImportServiceGuard() noexcept override {
+ explicit StubImportRegistration(std::weak_ptr<StubImportedServiceEntry> _entry) : entry{std::move(_entry)} {}
+ ~StubImportRegistration() noexcept override {
auto e = entry.lock();
if (e) {
e->close();
@@ -254,19 +302,30 @@
class StubImportServiceFactory : public celix::rsa::IImportServiceFactory {
public:
explicit StubImportServiceFactory(std::shared_ptr<celix::BundleContext> _ctx) : ctx{std::move(_ctx)} {}
+ ~StubImportServiceFactory() noexcept override = default;
- virtual std::unique_ptr<celix::rsa::IImportServiceGuard> importService(const celix::rsa::EndpointDescription& endpoint) {
+ [[nodiscard]] std::unique_ptr<celix::rsa::IImportRegistration> importService(const celix::rsa::EndpointDescription& endpoint) override {
if (endpoint.getInterface() == celix::typeName<IDummyService>()) {
std::lock_guard<std::mutex> lock{mutex};
auto entry = std::make_shared<StubImportedServiceEntry>(ctx);
entries.emplace_back(entry);
- return std::make_unique<StubImportServiceGuard>(entry);
+ return std::make_unique<StubImportRegistration>(entry);
} else {
return {};
}
}
+ [[nodiscard]] const std::string &getRemoteServiceType() const override {
+ return serviceType;
+ }
+
+ [[nodiscard]] const std::vector<std::string> &getSupportedConfigs() const override {
+ return configs;
+ }
+
private:
+ const std::string serviceType{celix::typeName<IDummyService>()};
+ const std::vector<std::string> configs{"test"};
const std::shared_ptr<celix::BundleContext> ctx;
std::mutex mutex{};
std::vector<std::shared_ptr<StubImportedServiceEntry>> entries{};
@@ -285,7 +344,7 @@
EXPECT_EQ(0, count);
auto reg1 = ctx->registerService<celix::rsa::IImportServiceFactory>(std::make_shared<StubImportServiceFactory>(ctx))
- .addProperty(celix::rsa::IImportServiceFactory::TARGET_SERVICE_NAME, celix::typeName<IDummyService>())
+ .addProperty(celix::rsa::IImportServiceFactory::REMOTE_SERVICE_TYPE, celix::typeName<IDummyService>())
.build();
count = ctx->useService<IDummyService>()
@@ -294,7 +353,8 @@
auto endpoint = std::make_shared<celix::rsa::EndpointDescription>(celix::Properties{
{celix::rsa::ENDPOINT_ID, "endpoint-id-1"},
- {celix::SERVICE_NAME,celix::typeName<IDummyService>()}});
+ {celix::SERVICE_NAME,celix::typeName<IDummyService>()},
+ {celix::rsa::SERVICE_IMPORTED_CONFIGS, "test"}});
auto reg2 = ctx->registerService<celix::rsa::EndpointDescription>(std::move(endpoint))
.build();
diff --git a/bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.cc b/bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.cc
index 207feec..116820c 100644
--- a/bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.cc
+++ b/bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.cc
@@ -19,21 +19,20 @@
#include "RemoteServiceAdmin.h"
#include "celix/BundleContext.h"
-#include "celix/BundleActivator.h"
#include "celix/rsa/RemoteConstants.h"
-#include "celix/rsa/IImportServiceFactory.h"
-#include "celix/rsa/IExportServiceFactory.h"
+#define L_TRACE(...) \
+ logHelper.trace(__VA_ARGS__);
#define L_DEBUG(...) \
- _logHelper.debug(__VA_ARGS__);
+ logHelper.debug(__VA_ARGS__);
#define L_INFO(...) \
_logHelper.info(__VA_ARGS__);
#define L_WARN(...) \
- _logHelper.warning(__VA_ARGS__);
+ logHelper.warning(__VA_ARGS__);
#define L_ERROR(...) \
- _logHelper.error(__VA_ARGS__);
+ logHelper.error(__VA_ARGS__);
-celix::rsa::RemoteServiceAdmin::RemoteServiceAdmin(celix::LogHelper logHelper) : _logHelper{std::move(logHelper)} {}
+celix::rsa::RemoteServiceAdmin::RemoteServiceAdmin(celix::LogHelper logHelper) : logHelper{std::move(logHelper)} {}
void celix::rsa::RemoteServiceAdmin::addEndpoint(const std::shared_ptr<celix::rsa::EndpointDescription>& endpoint) {
assert(endpoint);
@@ -50,8 +49,8 @@
return;
}
- std::lock_guard l(_m);
- _toBeImportedServices.emplace_back(endpoint);
+ std::lock_guard l(mutex);
+ toBeImportedServices.emplace_back(endpoint);
createImportServices();
}
@@ -64,18 +63,18 @@
return;
}
- std::shared_ptr<celix::rsa::IImportServiceGuard> tmpStore{}; //to ensure destruction outside of lock
+ std::shared_ptr<celix::rsa::IImportRegistration> tmpStore{}; //to ensure destruction outside of lock
{
- std::lock_guard l(_m);
+ std::lock_guard l(mutex);
- _toBeImportedServices.erase(std::remove_if(_toBeImportedServices.begin(), _toBeImportedServices.end(), [&id](auto const &endpoint){
+ toBeImportedServices.erase(std::remove_if(toBeImportedServices.begin(), toBeImportedServices.end(), [&id](auto const &endpoint){
return id == endpoint->getId();
- }), _toBeImportedServices.end());
+ }), toBeImportedServices.end());
- auto it = _importedServices.find(id);
- if (it != _importedServices.end()) {
+ auto it = importedServices.find(id);
+ if (it != importedServices.end()) {
tmpStore = std::move(it->second);
- _importedServices.erase(it);
+ importedServices.erase(it);
}
}
}
@@ -83,21 +82,21 @@
void celix::rsa::RemoteServiceAdmin::addImportedServiceFactory(
const std::shared_ptr<celix::rsa::IImportServiceFactory> &factory,
const std::shared_ptr<const celix::Properties> &properties) {
- auto targetServiceName = properties->get(celix::rsa::IImportServiceFactory::TARGET_SERVICE_NAME);
+ auto targetServiceName = properties->get(celix::rsa::IImportServiceFactory::REMOTE_SERVICE_TYPE);
if (targetServiceName.empty()) {
- L_WARN("Adding service factory but missing %s property", celix::rsa::IImportServiceFactory::TARGET_SERVICE_NAME);
+ L_WARN("Adding service factory but missing %s property", celix::rsa::IImportServiceFactory::REMOTE_SERVICE_TYPE);
return;
}
- std::lock_guard l(_m);
- auto existingFactory = _importServiceFactories.find(targetServiceName);
- if (existingFactory != end(_importServiceFactories)) {
+ std::lock_guard l(mutex);
+ auto existingFactory = importServiceFactories.find(targetServiceName);
+ if (existingFactory != end(importServiceFactories)) {
L_WARN("Adding imported factory but factory already exists");
return;
}
- _importServiceFactories.emplace(targetServiceName, factory);
+ importServiceFactories.emplace(targetServiceName, factory);
createImportServices();
}
@@ -105,14 +104,14 @@
void celix::rsa::RemoteServiceAdmin::removeImportedServiceFactory(
const std::shared_ptr<celix::rsa::IImportServiceFactory> &/*factory*/,
const std::shared_ptr<const celix::Properties> &properties) {
- auto targetServiceName = properties->get(celix::rsa::IImportServiceFactory::TARGET_SERVICE_NAME);
+ auto targetServiceName = properties->get(celix::rsa::IImportServiceFactory::REMOTE_SERVICE_TYPE);
if (targetServiceName.empty()) {
- L_WARN("Removing service factory but missing %s property", celix::rsa::IImportServiceFactory::TARGET_SERVICE_NAME);
+ L_WARN("Removing service factory but missing %s property", celix::rsa::IImportServiceFactory::REMOTE_SERVICE_TYPE);
return;
}
- std::lock_guard l(_m);
- _importServiceFactories.erase(targetServiceName);
+ std::lock_guard l(mutex);
+ importServiceFactories.erase(targetServiceName);
//TODO remove imported services from this factory ??needed
}
@@ -120,28 +119,28 @@
void celix::rsa::RemoteServiceAdmin::addExportedServiceFactory(
const std::shared_ptr<celix::rsa::IExportServiceFactory> &factory,
const std::shared_ptr<const celix::Properties> &properties) {
- auto targetServiceName = properties->get(celix::rsa::IExportServiceFactory::TARGET_SERVICE_NAME);
+ auto targetServiceName = properties->get(celix::rsa::IExportServiceFactory::REMOTE_SERVICE_TYPE);
if (targetServiceName.empty()) {
- L_WARN("Adding service factory but missing %s property", celix::rsa::IExportServiceFactory::TARGET_SERVICE_NAME);
+ L_WARN("Adding service factory but missing %s property", celix::rsa::IExportServiceFactory::REMOTE_SERVICE_TYPE);
return;
}
- std::lock_guard<std::mutex> lock{_m};
- _exportServiceFactories.emplace(targetServiceName, factory);
+ std::lock_guard<std::mutex> lock{mutex};
+ exportServiceFactories.emplace(targetServiceName, factory);
createExportServices();
}
void celix::rsa::RemoteServiceAdmin::removeExportedServiceFactory(
const std::shared_ptr<celix::rsa::IExportServiceFactory> &/*factory*/,
const std::shared_ptr<const celix::Properties> &properties) {
- auto targetServiceName = properties->get(celix::rsa::IExportServiceFactory::TARGET_SERVICE_NAME);
+ auto targetServiceName = properties->get(celix::rsa::IExportServiceFactory::REMOTE_SERVICE_TYPE);
if (targetServiceName.empty()) {
- L_WARN("Removing service factory but missing %s property", celix::rsa::IExportServiceFactory::TARGET_SERVICE_NAME);
+ L_WARN("Removing service factory but missing %s property", celix::rsa::IExportServiceFactory::REMOTE_SERVICE_TYPE);
return;
}
- std::lock_guard l(_m);
- _exportServiceFactories.erase(targetServiceName);
+ std::lock_guard l(mutex);
+ exportServiceFactories.erase(targetServiceName);
//TODO remove exported services from this factory ??needed
}
@@ -153,8 +152,8 @@
return;
}
- std::lock_guard<std::mutex> lock{_m};
- _toBeExportedServices.emplace_back(props);
+ std::lock_guard<std::mutex> lock{mutex};
+ toBeExportedServices.emplace_back(props);
createExportServices();
}
@@ -165,94 +164,125 @@
return;
}
- std::lock_guard l(_m);
+ std::lock_guard l(mutex);
- auto instanceIt = _exportedServices.find(svcId);
- if (instanceIt != end(_exportedServices)) {
- _exportedServices.erase(instanceIt);
+ auto instanceIt = exportedServices.find(svcId);
+ if (instanceIt != end(exportedServices)) {
+ exportedServices.erase(instanceIt);
}
//remove to be exported endpoint (if present)
- for (auto it = _toBeExportedServices.begin(); it != _toBeExportedServices.end(); ++it) {
+ for (auto it = toBeExportedServices.begin(); it != toBeExportedServices.end(); ++it) {
if ((*it)->getAsLong(celix::SERVICE_ID, -1) == svcId) {
- _toBeExportedServices.erase(it);
+ toBeExportedServices.erase(it);
break;
}
}
}
-void celix::rsa::RemoteServiceAdmin::createImportServices() {
- auto it = _toBeImportedServices.begin();
- while (it != _toBeImportedServices.end()) {
- auto interface = (*it)->getInterface();
- auto existingFactory = _importServiceFactories.find(interface);
- if (existingFactory == end(_importServiceFactories)) {
- L_DEBUG("Adding endpoint to be imported but no factory available yet, delaying import");
- it++;
- continue;
+bool celix::rsa::RemoteServiceAdmin::isEndpointMatch(const celix::rsa::EndpointDescription& endpoint, const celix::rsa::IImportServiceFactory& factory) const {
+ if (factory.getSupportedConfigs().empty()) {
+ L_WARN("Matching endpoint with a import service factory with no supported configs, this will always fail");
+ return false;
+ }
+ if (endpoint.getConfigurationTypes().empty()) {
+ L_WARN("Matching endpoint with empty configuration types (%s), this will always fail", celix::rsa::SERVICE_IMPORTED_CONFIGS);
+ return false;
+ }
+ size_t matchCount = 0;
+ for (const auto& config : endpoint.getConfigurationTypes()) {
+ for (const auto& factoryConfig : factory.getSupportedConfigs()) {
+ if (config == factoryConfig) {
+ ++matchCount;
+ break;
+ }
}
- auto endpointId = (*it)->getId();
- L_DEBUG("Adding endpoint, created service");
- _importedServices.emplace(endpointId, existingFactory->second->importService(**it));
- it = _toBeImportedServices.erase(it);
+ }
+ return matchCount == factory.getSupportedConfigs().size(); //note must match all requested configurations
+}
+
+bool celix::rsa::RemoteServiceAdmin::isExportServiceMatch(const celix::Properties& svcProperties, const celix::rsa::IExportServiceFactory& factory) const {
+ auto providedConfigs = celix::split(svcProperties.get(celix::rsa::SERVICE_IMPORTED_CONFIGS));
+ auto providedIntents = celix::split(svcProperties.get(celix::rsa::SERVICE_EXPORTED_INTENTS, "osgi.basic"));
+ if (providedConfigs.empty() && providedIntents.empty()) {
+ //note cannot match export service with no config or intent
+ return false;
+ }
+ if (factory.getSupportedIntents().empty() && factory.getSupportedConfigs().empty()) {
+ L_WARN("Matching service marked for export with a export service factory with no supported intents or configs, this will always fail");
+ return false;
+ }
+ if (!providedConfigs.empty()) {
+ size_t matchCount = 0;
+ for (const auto& config : providedConfigs) {
+ for (const auto& factoryConfig : factory.getSupportedConfigs()) {
+ if (config == factoryConfig) {
+ ++matchCount;
+ break;
+ }
+ }
+ }
+ return matchCount == factory.getSupportedConfigs().size(); //note must match all requested configurations
+ } else /*match on intent*/ {
+ for (const auto& intent: providedIntents) {
+ for (const auto& factoryIntent: factory.getSupportedIntents()) {
+ if (intent == factoryIntent) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+}
+
+void celix::rsa::RemoteServiceAdmin::createImportServices() {
+ //precondition mutex taken
+ auto it = toBeImportedServices.begin();
+ while (it != toBeImportedServices.end()) {
+ auto interface = (*it)->getInterface();
+ bool match = false;
+ for (auto factoryIt = importServiceFactories.lower_bound(interface); factoryIt != importServiceFactories.end() && factoryIt->first == interface; ++factoryIt) {
+ if (isEndpointMatch(**it, *factoryIt->second)) {
+ match = true;
+ auto endpointId = (*it)->getId();
+ L_DEBUG("Adding endpoint %s, created export service for %s", endpointId.c_str(), (*it)->getInterface().c_str());
+ importedServices.emplace(endpointId, factoryIt->second->importService(**it));
+ break;
+ } else {
+ L_TRACE("Config mismatch.");
+ }
+ }
+ if (match) {
+ it = toBeImportedServices.erase(it);
+ } else {
+ L_DEBUG("Adding endpoint to be imported but no matching factory available yet, delaying import");
+ ++it;
+ }
}
}
void celix::rsa::RemoteServiceAdmin::createExportServices() {
- auto it = _toBeExportedServices.begin();
- while (it != _toBeExportedServices.end()) {
+ //precondition mutex taken
+ auto it = toBeExportedServices.begin();
+ while (it != toBeExportedServices.end()) {
const auto& svcProperties = **it;
auto serviceName = svcProperties.get(celix::SERVICE_NAME, "");
auto svcId = svcProperties.getAsLong(celix::SERVICE_ID, -1);
- if (serviceName.empty()) {
- L_WARN("Adding service to be exported but missing objectclass for svc id %li", svcId);
- it++;
- continue;
+ bool match = false;
+ for (auto factoryIt = exportServiceFactories.lower_bound(serviceName); factoryIt != exportServiceFactories.end() && factoryIt->first == serviceName; ++factoryIt) {
+ if (isExportServiceMatch(svcProperties, *factoryIt->second)) {
+ match = true;
+ exportedServices.emplace(svcId, factoryIt->second->exportService(svcProperties));
+ break;
+ } else {
+ L_TRACE("Intent mismatch");
+ }
}
- auto factory = _exportServiceFactories.find(serviceName);
- if (factory == end(_exportServiceFactories)) {
- L_DEBUG("Adding service to be exported but no factory available yet, delaying creation");
- it++;
- continue;
+ if (match) {
+ it = toBeExportedServices.erase(it);
+ } else {
+ L_DEBUG("Adding endpoint to be imported but no matching factory available yet, delaying import");
+ ++it;
}
- _exportedServices.emplace(svcId, factory->second->exportService(svcProperties));
- it = _toBeExportedServices.erase(it);
}
-}
-
-class AdminActivator {
-public:
- explicit AdminActivator(const std::shared_ptr<celix::BundleContext>& ctx) {
- auto admin = std::make_shared<celix::rsa::RemoteServiceAdmin>(celix::LogHelper{ctx, celix::typeName<celix::rsa::RemoteServiceAdmin>()});
-
- auto& cmp = ctx->getDependencyManager()->createComponent(admin);
- cmp.createServiceDependency<celix::rsa::EndpointDescription>()
- .setRequired(false)
- .setStrategy(celix::dm::DependencyUpdateStrategy::locking)
- .setCallbacks(&celix::rsa::RemoteServiceAdmin::addEndpoint, &celix::rsa::RemoteServiceAdmin::removeEndpoint);
- cmp.createServiceDependency<celix::rsa::IImportServiceFactory>()
- .setRequired(false)
- .setStrategy(celix::dm::DependencyUpdateStrategy::locking)
- .setCallbacks(&celix::rsa::RemoteServiceAdmin::addImportedServiceFactory, &celix::rsa::RemoteServiceAdmin::removeImportedServiceFactory);
- cmp.createServiceDependency<celix::rsa::IExportServiceFactory>()
- .setRequired(false)
- .setStrategy(celix::dm::DependencyUpdateStrategy::locking)
- .setCallbacks(&celix::rsa::RemoteServiceAdmin::addExportedServiceFactory, &celix::rsa::RemoteServiceAdmin::removeExportedServiceFactory);
- cmp.build();
-
- //note adding void service dependencies is not supported for the dependency manager, using a service tracker instead.
- _remoteServiceTracker = ctx->trackAnyServices()
- .setFilter(std::string{"("}.append(celix::rsa::SERVICE_EXPORTED_INTERFACES).append("=*)"))
- .addAddWithPropertiesCallback([admin](const std::shared_ptr<void>& svc, const std::shared_ptr<const celix::Properties>& properties) {
- admin->addService(svc, properties);
- })
- .addRemWithPropertiesCallback([admin](const std::shared_ptr<void>& svc, const std::shared_ptr<const celix::Properties>& properties) {
- admin->removeService(svc, properties);
- })
- .build();
- }
-private:
- std::shared_ptr<celix::ServiceTracker<void>> _remoteServiceTracker{};
-};
-
-CELIX_GEN_CXX_BUNDLE_ACTIVATOR(AdminActivator)
\ No newline at end of file
+}
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/admin/include/RemoteServiceAdmin.h b/bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.h
similarity index 63%
rename from bundles/cxx_remote_services/admin/include/RemoteServiceAdmin.h
rename to bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.h
index 969a095..6101799 100644
--- a/bundles/cxx_remote_services/admin/include/RemoteServiceAdmin.h
+++ b/bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.h
@@ -17,7 +17,6 @@
* under the License.
*/
-
#include <mutex>
#include "celix/LogHelper.h"
@@ -35,6 +34,15 @@
namespace celix::rsa {
+ /**
+ * @brief Remote Service Admin based on endpoint/proxy factories.
+ *
+ * A Remote Service Admin which does not contain on itself any technology, but relies on remote
+ * service endpoint/proxy factories to create exported/imported remote services.
+ *
+ * The RSA can be configured to use different remote service endpoint/proxy factories based on the
+ * intent of the remote service endpoint/proxy factories.
+ */
class RemoteServiceAdmin {
public:
explicit RemoteServiceAdmin(celix::LogHelper logHelper);
@@ -57,24 +65,26 @@
private:
void createExportServices();
void createImportServices();
+ bool isEndpointMatch(const celix::rsa::EndpointDescription& endpoint, const celix::rsa::IImportServiceFactory& factory) const;
+ bool isExportServiceMatch(const celix::Properties& svcProperties, const celix::rsa::IExportServiceFactory& factory) const;
- celix::LogHelper _logHelper;
- std::mutex _m{}; // protects below
+ celix::LogHelper logHelper;
+ std::mutex mutex{}; // protects below
#if __cpp_lib_memory_resource
- std::pmr::unsynchronized_pool_resource _memResource{};
+ std::pmr::unsynchronized_pool_resource memResource{};
- std::pmr::unordered_map<std::string, std::shared_ptr<celix::rsa::IExportServiceFactory>> _exportServiceFactories{&_memResource}; //key = service name
- std::pmr::unordered_map<std::string, std::shared_ptr<celix::rsa::IImportServiceFactory>> _importServiceFactories{&_memResource}; //key = service name
- std::pmr::unordered_map<std::string, std::unique_ptr<celix::rsa::IImportServiceGuard>> _importedServices{&_memResource}; //key = endpoint id
- std::pmr::unordered_map<long, std::unique_ptr<celix::rsa::IExportServiceGuard>> _exportedServices{&_memResource}; //key = service id
+ std::pmr::multimap<std::string, std::shared_ptr<celix::rsa::IExportServiceFactory>> exportServiceFactories{&memResource}; //key = service name
+ std::pmr::multimap<std::string, std::shared_ptr<celix::rsa::IImportServiceFactory>> importServiceFactories{&memResource}; //key = service name
+ std::pmr::unordered_map<std::string, std::unique_ptr<celix::rsa::IImportRegistration>> importedServices{&memResource}; //key = endpoint id
+ std::pmr::unordered_map<long, std::unique_ptr<celix::rsa::IExportRegistration>> exportedServices{&memResource}; //key = service id
#else
- std::unordered_map<std::string, std::shared_ptr<celix::rsa::IExportServiceFactory>> _exportServiceFactories{}; //key = service name
- std::unordered_map<std::string, std::shared_ptr<celix::rsa::IImportServiceFactory>> _importServiceFactories{}; //key = service name
- std::unordered_map<std::string, std::unique_ptr<celix::rsa::IImportServiceGuard>> _importedServices{}; //key = endpoint id
- std::unordered_map<long, std::unique_ptr<celix::rsa::IExportServiceGuard>> _exportedServices{}; //key = service id
+ std::multimap<std::string, std::shared_ptr<celix::rsa::IExportServiceFactory>> exportServiceFactories{}; //key = service name
+ std::multimap<std::string, std::shared_ptr<celix::rsa::IImportServiceFactory>> importServiceFactories{}; //key = service name
+ std::unordered_map<std::string, std::unique_ptr<celix::rsa::IImportRegistration>> importedServices{}; //key = endpoint id
+ std::unordered_map<long, std::unique_ptr<celix::rsa::IExportRegistration>> exportedServices{}; //key = service id
#endif
- std::vector<std::shared_ptr<celix::rsa::EndpointDescription>> _toBeImportedServices{};
- std::vector<std::shared_ptr<const celix::Properties>> _toBeExportedServices{};
+ std::vector<std::shared_ptr<celix::rsa::EndpointDescription>> toBeImportedServices{};
+ std::vector<std::shared_ptr<const celix::Properties>> toBeExportedServices{};
};
}
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/admin/src/RemoteServiceAdminActivator.cc b/bundles/cxx_remote_services/admin/src/RemoteServiceAdminActivator.cc
new file mode 100644
index 0000000..0b646ac
--- /dev/null
+++ b/bundles/cxx_remote_services/admin/src/RemoteServiceAdminActivator.cc
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+#include "celix/BundleActivator.h"
+#include "RemoteServiceAdmin.h"
+
+/**
+ * @Brief Remote Service Admin which use export/import service factories to import/export remote services.
+ *
+ * Supported intends and config are based on what is supported by the export/import service factories.
+ */
+class AdminActivator {
+public:
+ explicit AdminActivator(const std::shared_ptr<celix::BundleContext>& ctx) {
+ auto admin = std::make_shared<celix::rsa::RemoteServiceAdmin>(celix::LogHelper{ctx, celix::typeName<celix::rsa::RemoteServiceAdmin>()});
+
+ auto& cmp = ctx->getDependencyManager()->createComponent(admin);
+ cmp.createServiceDependency<celix::rsa::EndpointDescription>()
+ .setRequired(false)
+ .setStrategy(celix::dm::DependencyUpdateStrategy::locking)
+ .setCallbacks(&celix::rsa::RemoteServiceAdmin::addEndpoint, &celix::rsa::RemoteServiceAdmin::removeEndpoint);
+ cmp.createServiceDependency<celix::rsa::IImportServiceFactory>()
+ .setRequired(false)
+ .setStrategy(celix::dm::DependencyUpdateStrategy::locking)
+ .setCallbacks(&celix::rsa::RemoteServiceAdmin::addImportedServiceFactory, &celix::rsa::RemoteServiceAdmin::removeImportedServiceFactory);
+ cmp.createServiceDependency<celix::rsa::IExportServiceFactory>()
+ .setRequired(false)
+ .setStrategy(celix::dm::DependencyUpdateStrategy::locking)
+ .setCallbacks(&celix::rsa::RemoteServiceAdmin::addExportedServiceFactory, &celix::rsa::RemoteServiceAdmin::removeExportedServiceFactory);
+ cmp.build();
+
+ //note adding void service dependencies is not supported for the dependency manager, using a service tracker instead.
+ _remoteServiceTracker = ctx->trackAnyServices()
+ .setFilter(std::string{"("}.append(celix::rsa::SERVICE_EXPORTED_INTERFACES).append("=*)"))
+ .addAddWithPropertiesCallback([admin](const std::shared_ptr<void>& svc, const std::shared_ptr<const celix::Properties>& properties) {
+ admin->addService(svc, properties);
+ })
+ .addRemWithPropertiesCallback([admin](const std::shared_ptr<void>& svc, const std::shared_ptr<const celix::Properties>& properties) {
+ admin->removeService(svc, properties);
+ })
+ .build();
+ }
+private:
+ std::shared_ptr<celix::ServiceTracker<void>> _remoteServiceTracker{};
+};
+
+CELIX_GEN_CXX_BUNDLE_ACTIVATOR(AdminActivator)
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/discovery_configured/gtest/src/RsaConfiguredDiscoveryTestSuite.cc b/bundles/cxx_remote_services/discovery_configured/gtest/src/RsaConfiguredDiscoveryTestSuite.cc
index dcd900f..cd773be 100644
--- a/bundles/cxx_remote_services/discovery_configured/gtest/src/RsaConfiguredDiscoveryTestSuite.cc
+++ b/bundles/cxx_remote_services/discovery_configured/gtest/src/RsaConfiguredDiscoveryTestSuite.cc
@@ -54,7 +54,7 @@
auto count = ctx->useServices<celix::rsa::EndpointDescription>()
.addUseCallback([](auto& endpoint) {
EXPECT_NE(endpoint.getId(), "");
- EXPECT_NE(endpoint.getConfigurationTypes(), "");
+ EXPECT_NE(endpoint.getConfigurationTypes(), std::vector<std::string>{});
EXPECT_NE(endpoint.getInterface(), "");
EXPECT_NE(endpoint.getFrameworkUUID(), "");
EXPECT_NE(endpoint.getProperties().get("endpoint.scope"), ""); //note async specific
diff --git a/bundles/cxx_remote_services/integration/src/CalculatorProvider.cc b/bundles/cxx_remote_services/integration/src/CalculatorProvider.cc
index dd4a3a2..ec4ea86 100644
--- a/bundles/cxx_remote_services/integration/src/CalculatorProvider.cc
+++ b/bundles/cxx_remote_services/integration/src/CalculatorProvider.cc
@@ -50,7 +50,8 @@
cmp.createProvidedService<ICalculator>()
.addProperty("service.exported.interfaces", celix::typeName<ICalculator>())
.addProperty("endpoint.topic", "test")
- .addProperty("endpoint.scope", "default");
+ .addProperty("endpoint.scope", "default")
+ .addProperty("service.exported.intents", "osgi.async");
cmp.build();
}
};
diff --git a/bundles/cxx_remote_services/integration/src/TestExportImportRemoteServiceFactory.cc b/bundles/cxx_remote_services/integration/src/TestExportImportRemoteServiceFactory.cc
index 154e42b..d8a6962 100644
--- a/bundles/cxx_remote_services/integration/src/TestExportImportRemoteServiceFactory.cc
+++ b/bundles/cxx_remote_services/integration/src/TestExportImportRemoteServiceFactory.cc
@@ -158,10 +158,10 @@
/**
* A import service guard, which will remove the component if it goes out of scope.
*/
-class ComponentImportServiceGuard final : public celix::rsa::IImportServiceGuard {
+class ComponentImportRegistration final : public celix::rsa::IImportRegistration {
public:
- ComponentImportServiceGuard(std::shared_ptr<celix::BundleContext> _ctx, std::string _componentId) : ctx{std::move(_ctx)}, componentId{std::move(_componentId)} {}
- ~ComponentImportServiceGuard() noexcept override {
+ ComponentImportRegistration(std::shared_ptr<celix::BundleContext> _ctx, std::string _componentId) : ctx{std::move(_ctx)}, componentId{std::move(_componentId)} {}
+ ~ComponentImportRegistration() noexcept override {
auto context = ctx.lock();
if (context) {
context->getDependencyManager()->removeComponentAsync(componentId);
@@ -177,14 +177,12 @@
*/
class CalculatorImportServiceFactory final : public celix::rsa::IImportServiceFactory {
public:
+ static constexpr const char * const CONFIGS = "pubsub";
+
explicit CalculatorImportServiceFactory(std::shared_ptr<celix::BundleContext> _ctx) : ctx{std::move(_ctx)}, logHelper{ctx, "celix::rsa::RemoteServiceFactory"} {}
+ ~CalculatorImportServiceFactory() noexcept override = default;
- std::unique_ptr<celix::rsa::IImportServiceGuard> importService(const celix::rsa::EndpointDescription& endpoint) override {
- if (endpoint.getConfigurationTypes() != "pubsub") {
- ctx->logTrace("skipping endpoint, not pubsub configuration. Found config '%s'", endpoint.getConfigurationTypes().c_str());
- return nullptr;
- }
-
+ std::unique_ptr<celix::rsa::IImportRegistration> importService(const celix::rsa::EndpointDescription& endpoint) override {
auto topic = endpoint.getProperties().get("endpoint.topic");
auto scope = endpoint.getProperties().get("endpoint.topic");
if (topic.empty() || scope.empty()) {
@@ -193,8 +191,17 @@
}
auto componentId = createImportedCalculatorComponent(endpoint);
- return std::make_unique<ComponentImportServiceGuard>(ctx, std::move(componentId));
+ return std::make_unique<ComponentImportRegistration>(ctx, std::move(componentId));
}
+
+ [[nodiscard]] const std::string& getRemoteServiceType() const override {
+ return serviceType;
+ }
+
+ const std::vector<std::string>& getSupportedConfigs() const override {
+ return configs;
+ }
+
private:
std::string createImportedCalculatorComponent(const celix::rsa::EndpointDescription& endpoint) {
auto invokeTopic = endpoint.getProperties().get("endpoint.topic") + "_invoke";
@@ -243,6 +250,8 @@
return cmp.getUUID();
}
+ const std::string serviceType = celix::typeName<ICalculator>();
+ const std::vector<std::string> configs = celix::split(CONFIGS);
std::shared_ptr<celix::BundleContext> ctx;
celix::LogHelper logHelper;
std::mutex mutex{}; //protects below
@@ -341,10 +350,10 @@
/**
* A import service guard, which will remove the component if it goes out of scope.
*/
-class ComponentExportServiceGuard final : public celix::rsa::IExportServiceGuard {
+class ComponentExportRegistration final : public celix::rsa::IExportRegistration {
public:
- ComponentExportServiceGuard(std::shared_ptr<celix::BundleContext> _ctx, std::string _componentId) : ctx{std::move(_ctx)}, componentId{std::move(_componentId)} {}
- ~ComponentExportServiceGuard() noexcept override {
+ ComponentExportRegistration(std::shared_ptr<celix::BundleContext> _ctx, std::string _componentId) : ctx{std::move(_ctx)}, componentId{std::move(_componentId)} {}
+ ~ComponentExportRegistration() noexcept override {
auto context = ctx.lock();
if (context) {
context->getDependencyManager()->removeComponentAsync(componentId);
@@ -360,10 +369,14 @@
*/
class CalculatorExportServiceFactory final : public celix::rsa::IExportServiceFactory {
public:
+ static constexpr const char * const CONFIGS = "pubsub";
+ static constexpr const char * const INTENTS = "osgi.async";
+
explicit CalculatorExportServiceFactory(std::shared_ptr<celix::BundleContext> _ctx) : ctx{std::move(_ctx)},
logHelper{ctx, "celix::rsa::RemoteServiceFactory"} {}
+ ~CalculatorExportServiceFactory() noexcept override = default;
- std::unique_ptr<celix::rsa::IExportServiceGuard> exportService(const celix::Properties& serviceProperties) override {
+ std::unique_ptr<celix::rsa::IExportRegistration> exportService(const celix::Properties& serviceProperties) override {
auto topic = serviceProperties.get("endpoint.topic");
auto scope = serviceProperties.get("endpoint.topic");
if (topic.empty() || scope.empty()) {
@@ -372,8 +385,21 @@
}
auto componentId = createExportedCalculatorComponent(serviceProperties);
- return std::make_unique<ComponentExportServiceGuard>(ctx, std::move(componentId));
+ return std::make_unique<ComponentExportRegistration>(ctx, std::move(componentId));
}
+
+ [[nodiscard]] const std::string& getRemoteServiceType() const override {
+ return serviceType;
+ }
+
+ [[nodiscard]] const std::vector<std::string>& getSupportedIntents() const override {
+ return intents;
+ }
+
+ [[nodiscard]] const std::vector<std::string>& getSupportedConfigs() const override {
+ return configs;
+ }
+
private:
std::string createExportedCalculatorComponent(const celix::Properties& serviceProperties) {
auto invokeTopic = serviceProperties.get("endpoint.topic") + "_invoke";
@@ -417,6 +443,9 @@
return cmp.getUUID();
}
+ const std::string serviceType = celix::typeName<ICalculator>();
+ const std::vector<std::string> configs = celix::split(CONFIGS);
+ const std::vector<std::string> intents = celix::split(INTENTS);
std::shared_ptr<celix::BundleContext> ctx;
celix::LogHelper logHelper;
std::mutex mutex{}; //protects below
@@ -428,12 +457,15 @@
ctx->logInfo("Starting TestExportImportRemoteServiceFactory");
registrations.emplace_back(
ctx->registerService<celix::rsa::IImportServiceFactory>(std::make_shared<CalculatorImportServiceFactory>(ctx))
- .addProperty(celix::rsa::IImportServiceFactory::TARGET_SERVICE_NAME, celix::typeName<ICalculator>())
+ .addProperty(celix::rsa::IImportServiceFactory::REMOTE_SERVICE_TYPE, celix::typeName<ICalculator>())
+ .addProperty(celix::rsa::REMOTE_CONFIGS_SUPPORTED, CalculatorImportServiceFactory::CONFIGS)
.build()
);
registrations.emplace_back(
ctx->registerService<celix::rsa::IExportServiceFactory>(std::make_shared<CalculatorExportServiceFactory>(ctx))
- .addProperty(celix::rsa::IExportServiceFactory::TARGET_SERVICE_NAME, celix::typeName<ICalculator>())
+ .addProperty(celix::rsa::IExportServiceFactory::REMOTE_SERVICE_TYPE, celix::typeName<ICalculator>())
+ .addProperty(celix::rsa::REMOTE_CONFIGS_SUPPORTED, CalculatorExportServiceFactory::CONFIGS)
+ .addProperty(celix::rsa::REMOTE_INTENTS_SUPPORTED, CalculatorExportServiceFactory::INTENTS)
.build()
);
registrations.emplace_back(
diff --git a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/EndpointDescription.h b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/EndpointDescription.h
index 4b43142..a747deb 100644
--- a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/EndpointDescription.h
+++ b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/EndpointDescription.h
@@ -21,6 +21,7 @@
#include <string>
#include <map>
+#include "celix/Utils.h"
#include "celix/Constants.h"
#include "celix/Properties.h"
#include "celix/rsa/RemoteConstants.h"
@@ -51,7 +52,13 @@
*
* @param The properties from which to create the Endpoint Description.
*/
- explicit EndpointDescription(celix::Properties properties) : endpointProperties{std::move(properties)} {
+ explicit EndpointDescription(celix::Properties properties) :
+ endpointProperties{std::move(properties)},
+ endpointId{endpointProperties.get(celix::rsa::ENDPOINT_ID)},
+ configurationTypes{celix::split(endpointProperties.get(celix::rsa::SERVICE_IMPORTED_CONFIGS))},
+ frameworkUUID{endpointProperties.get(celix::rsa::ENDPOINT_FRAMEWORK_UUID)},
+ intents{celix::split(endpointProperties.get(celix::rsa::SERVICE_INTENTS))},
+ serviceName{endpointProperties.get(celix::SERVICE_NAME)} {
checkValidEndpoint();
}
@@ -66,8 +73,13 @@
* @param serviceProperties The service properties of a service that can be exported.
* @param rsaProperties The optional properties provided by the Remote Service Admin.
*/
- EndpointDescription(std::string_view frameworkUUID, const celix::Properties& serviceProperties, const celix::Properties& rsaProperties = {}) : endpointProperties{
- importedProperties(frameworkUUID, serviceProperties, rsaProperties)} {
+ EndpointDescription(std::string_view frameworkUUID, const celix::Properties& serviceProperties, const celix::Properties& rsaProperties = {}) :
+ endpointProperties{importedProperties(frameworkUUID, serviceProperties, rsaProperties)},
+ endpointId{endpointProperties.get(celix::rsa::ENDPOINT_ID)},
+ configurationTypes{celix::split(endpointProperties.get(celix::rsa::SERVICE_IMPORTED_CONFIGS))},
+ frameworkUUID{endpointProperties.get(celix::rsa::ENDPOINT_FRAMEWORK_UUID)},
+ intents{celix::split(endpointProperties.get(celix::rsa::SERVICE_INTENTS))},
+ serviceName{endpointProperties.get(celix::SERVICE_NAME)} {
checkValidEndpoint();
}
@@ -79,8 +91,8 @@
* Two Endpoint Descriptions with the same id must represent the same endpoint.
* The value of the id is stored in the RemoteConstants.ENDPOINT_ID property.
*/
- [[nodiscard]] std::string getId() const {
- return endpointProperties.get(celix::rsa::ENDPOINT_ID);
+ [[nodiscard]] const std::string& getId() const {
+ return endpointId;
}
/**
@@ -93,8 +105,8 @@
* increase the change a receiving distribution provider can create a connection to this endpoint.
* This value of the configuration types is stored in the celix::rsa::SERVICE_IMPORTED_CONFIGS service property.
*/
- [[nodiscard]] std::string getConfigurationTypes() const {
- return endpointProperties.get(celix::rsa::SERVICE_IMPORTED_CONFIGS);
+ [[nodiscard]] const std::vector<std::string>& getConfigurationTypes() const {
+ return configurationTypes;
}
/**
@@ -102,8 +114,8 @@
*
* The value of the remote framework UUID is stored in the celix::rsa::ENDPOINT_FRAMEWORK_UUID endpoint property.
*/
- [[nodiscard]] std::string getFrameworkUUID() const {
- return endpointProperties.get(celix::rsa::ENDPOINT_FRAMEWORK_UUID);
+ [[nodiscard]] const std::string& getFrameworkUUID() const {
+ return frameworkUUID;
}
/**
@@ -114,17 +126,16 @@
* All qualified intents must have been expanded.
* This value of the intents is stored in the RemoteConstants.SERVICE_INTENTS service property.
*/
- //TODO make std::vector<std::string>
- [[nodiscard]] std::string getIntents() const {
- return endpointProperties.get(celix::rsa::SERVICE_INTENTS);
+ [[nodiscard]] const std::vector<std::string>& getIntents() const {
+ return intents;
}
/**
* @brief Provide the interface implemented by the exported service.
* The value of the interface is derived from the objectClass property.
*/
- [[nodiscard]] std::string getInterface() const {
- return endpointProperties.get(celix::SERVICE_NAME);
+ [[nodiscard]] const std::string& getInterface() const {
+ return serviceName;
}
/**
@@ -170,17 +181,22 @@
void checkValidEndpoint() const {
std::string baseMsg = "Invalid properties for EndpointDescription, missing mandatory property ";
- if (endpointProperties.get(celix::rsa::ENDPOINT_ID).empty()) {
+ if (endpointId.empty()) {
throw celix::rsa::RemoteServicesException{baseMsg.append(celix::rsa::ENDPOINT_ID)};
}
- if (endpointProperties.get(celix::rsa::ENDPOINT_ID).empty()) {
+ if (configurationTypes.empty()) {
throw celix::rsa::RemoteServicesException{baseMsg.append(celix::rsa::SERVICE_IMPORTED_CONFIGS)};
}
- if (endpointProperties.get(celix::SERVICE_NAME).empty()) {
+ if (serviceName.empty()) {
throw celix::rsa::RemoteServicesException{baseMsg.append(celix::SERVICE_NAME)};
}
}
-
+
const celix::Properties endpointProperties;
+ const std::string endpointId;
+ const std::vector<std::string> configurationTypes;
+ const std::string frameworkUUID;
+ const std::vector<std::string> intents;
+ const std::string serviceName;
};
} // end namespace celix::rsa.
diff --git a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IExportRegistration.h b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IExportRegistration.h
new file mode 100644
index 0000000..81944c6
--- /dev/null
+++ b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IExportRegistration.h
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+#pragma once
+
+namespace celix::rsa {
+
+ /**
+ * @brief IExportRegistration class which represent a (opaque) exported service.
+ * If lifetime of this object expires it should remove the underlining exported service.
+ * */
+ class IExportRegistration {
+ public:
+ virtual ~IExportRegistration() noexcept = default;
+ };
+}
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IExportServiceFactory.h b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IExportServiceFactory.h
index 66383b6..73ebe28 100644
--- a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IExportServiceFactory.h
+++ b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IExportServiceFactory.h
@@ -19,24 +19,16 @@
#pragma once
#include <memory>
-#include "celix/rsa/EndpointDescription.h"
+
+#include "celix/rsa/IExportRegistration.h"
namespace celix::rsa {
/**
- * @brief IExportServiceGuard class which represent a (opaque) exported service.
- * If lifetime of this object expires it should remove the underlining exported service.
- * */
- class IExportServiceGuard {
- public:
- virtual ~IExportServiceGuard() noexcept = default;
- };
-
- /**
* @brief A export service factory for a specific service type.
*
- * The service type which this export service factory targets is provided with
- * the mandatory celix::rsa::IExportServiceFactory::TARGET_SERVICE_NAME service property.
+ * the mandatory service properties:
+ * - celix::rsa::IExportServiceFactory::REMOTE_SERVICE_TYPE
*
*/
class IExportServiceFactory {
@@ -44,16 +36,34 @@
/**
* @brief The service name for which this factory can created exported services.
*/
- static constexpr const char * const TARGET_SERVICE_NAME = "target.service.name";
+ static constexpr const char * const REMOTE_SERVICE_TYPE = "remote.service.type";
virtual ~IExportServiceFactory() noexcept = default;
/**
- * @brief Exports the service identified with svcId
- * @param svcId The service id of the exported service.
- * @return A ExportService.
+ * @brief The service name for which this factory can export services as remote services.
+ *
+ * The value should be based on the "remote.service.type" service property of
+ * this import service factory.
+ */
+ [[nodiscard]] virtual const std::string& getRemoteServiceType() const = 0;
+
+ /**
+ * @Brief The supported intents for this export service factory.
+ */
+ [[nodiscard]] virtual const std::vector<std::string>& getSupportedIntents() const = 0;
+
+ /**
+ * @Brief The supported configs for this export service factory.
+ */
+ [[nodiscard]] virtual const std::vector<std::string>& getSupportedConfigs() const = 0;
+
+ /**
+ * @brief Exports the service associated with the provided serviceProperties.
+ * @param serviceProperties The service properties of the to be exported service.
+ * @return A new export registration.
* @throws celix::rsa::RemoteServicesException if the export failed.
*/
- virtual std::unique_ptr<celix::rsa::IExportServiceGuard> exportService(const celix::Properties& serviceProperties) = 0;
+ [[nodiscard]] virtual std::unique_ptr<celix::rsa::IExportRegistration> exportService(const celix::Properties& serviceProperties) = 0;
};
}
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IImportRegistration.h b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IImportRegistration.h
new file mode 100644
index 0000000..cb366dc
--- /dev/null
+++ b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IImportRegistration.h
@@ -0,0 +1,31 @@
+/*
+ * 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.
+ */
+#pragma once
+
+namespace celix::rsa {
+
+ /**
+ * @brief IImportRegistration class which represent a (opaque) imported service.
+ * If lifetime of this object expires it should remove the underlining imported service.
+ */
+ class IImportRegistration {
+ public:
+ virtual ~IImportRegistration() noexcept = default;
+ };
+}
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IImportServiceFactory.h b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IImportServiceFactory.h
index 7c6f3a1..dd9d3c6 100644
--- a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IImportServiceFactory.h
+++ b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IImportServiceFactory.h
@@ -19,41 +19,47 @@
#pragma once
#include <memory>
+
#include "celix/rsa/EndpointDescription.h"
+#include "celix/rsa/IImportRegistration.h"
namespace celix::rsa {
/**
- * @brief IImportServiceGuard class which represent a (opaque) imported service.
- * If lifetime of this object expires it should remove the underlining imported service.
- */
- class IImportServiceGuard {
- public:
- virtual ~IImportServiceGuard() noexcept = default;
- };
-
- /**
* @brief A import service factory for a specific service type.
*
- * The service type which this import service factory targets is provided with
- * the mandatory celix::rsa::IImportServiceFactory::TARGET_SERVICE_NAME service property.
+ * The service type which this export service factory targets is provided with `REMOTE_SERVICE_TYPE` and
+ * the supported configs with `REMOTE_CONFIGS_SUPPORTED`.
*
*/
class IImportServiceFactory {
public:
/**
- * @brief The service name for which this factory can created exported services.
+ * @brief The service name for which this factory can import remote services.
*/
- static constexpr const char * const TARGET_SERVICE_NAME = "target.service.name";
+ static constexpr const char * const REMOTE_SERVICE_TYPE = "remote.service.type";
virtual ~IImportServiceFactory() noexcept = default;
/**
- * @brief Imports the service identified with svcId
- * @param svcId The service id of the exported service.
- * @return A ImportService.
+ * @brief The service name for which this factory can import remote services.
+ *
+ * The value should be based on the "remote.service.type" service property of
+ * this import service factory.
+ */
+ [[nodiscard]] virtual const std::string& getRemoteServiceType() const = 0;
+
+ /**
+ * @Brief The supported configs for this import service factory.
+ */
+ [[nodiscard]] virtual const std::vector<std::string>& getSupportedConfigs() const = 0;
+
+ /**
+ * @brief Imports a service for the provided remote service endpoint description.
+ * @param endpoint The endpoint description describing the remote service.
+ * @return A new import registration.
* @throws celix::rsa::RemoteServicesException if the import failed.
*/
- virtual std::unique_ptr<celix::rsa::IImportServiceGuard> importService(const celix::rsa::EndpointDescription& endpoint) = 0;
+ [[nodiscard]] virtual std::unique_ptr<celix::rsa::IImportRegistration> importService(const celix::rsa::EndpointDescription& endpoint) = 0;
};
}
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/RemoteConstants.h b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/RemoteConstants.h
index 9dae5e3..7cae240 100644
--- a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/RemoteConstants.h
+++ b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/RemoteConstants.h
@@ -91,7 +91,7 @@
/**
* @brief Service property marking the service for export. It defines the interfaces under which this service can be exported.
*
- * Note for Celix only 1 interface can be register per service regiration, so only 1 interface can be exported using
+ * Note for Celix only 1 interface can be register per service registration, so only 1 interface can be exported using
* the service.exported.interfaces property.
* This value must be the exported service type or the value of an asterisk ('*' \u002A).
* The value of this property must be of type string.
diff --git a/bundles/logging/log_helper/include/celix/LogHelper.h b/bundles/logging/log_helper/include/celix/LogHelper.h
index 3f447f2..c22cb35 100644
--- a/bundles/logging/log_helper/include/celix/LogHelper.h
+++ b/bundles/logging/log_helper/include/celix/LogHelper.h
@@ -32,7 +32,7 @@
/**
* @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_TRACE level, printf style
*/
- void trace(const char *format, ...) {
+ void trace(const char *format, ...) const {
va_list args;
va_start(args, format);
vlog(CELIX_LOG_LEVEL_TRACE, format, args);
@@ -42,7 +42,7 @@
/**
* @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_DEBUG level, printf style
*/
- void debug(const char *format, ...) {
+ void debug(const char *format, ...) const {
va_list args;
va_start(args, format);
vlog(CELIX_LOG_LEVEL_DEBUG, format, args);
@@ -52,7 +52,7 @@
/**
* @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_INFO level, printf style
*/
- void info(const char *format, ...) {
+ void info(const char *format, ...) const {
va_list args;
va_start(args, format);
vlog(CELIX_LOG_LEVEL_INFO, format, args);
@@ -62,7 +62,7 @@
/**
* @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_WARNING level, printf style
*/
- void warning(const char *format, ...) {
+ void warning(const char *format, ...) const {
va_list args;
va_start(args, format);
vlog(CELIX_LOG_LEVEL_WARNING, format, args);
@@ -72,7 +72,7 @@
/**
* @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_ERROR level, printf style
*/
- void error(const char *format, ...) {
+ void error(const char *format, ...) const {
va_list args;
va_start(args, format);
vlog(CELIX_LOG_LEVEL_ERROR, format, args);
@@ -82,7 +82,7 @@
/**
* @brief Logs to celix_logHelper_log using the CELIX_LOG_LEVEL_FATAL level, printf style
*/
- void fatal(const char *format, ...) {
+ void fatal(const char *format, ...) const {
va_list args;
va_start(args, format);
vlog(CELIX_LOG_LEVEL_FATAL, format, args);
@@ -94,7 +94,7 @@
*
* Silently ignores log level CELIX_LOG_LEVEL_DISABLED.
*/
- void vlog(celix_log_level_e level, const char *format, va_list formatArgs) {
+ void vlog(celix_log_level_e level, const char *format, va_list formatArgs) const {
celix_logHelper_vlog(logHelper.get(), level, format, formatArgs);
}