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 2021/05/05 20:45:05 UTC
[celix] branch feature/cxx_rsa_update updated: Refactors rsa
configured discovery
This is an automated email from the ASF dual-hosted git repository.
pnoltes pushed a commit to branch feature/cxx_rsa_update
in repository https://gitbox.apache.org/repos/asf/celix.git
The following commit(s) were added to refs/heads/feature/cxx_rsa_update by this push:
new a1e711f Refactors rsa configured discovery
a1e711f is described below
commit a1e711f2012e7ff98bd37dfca89c7ba205e8cd16
Author: Pepijn Noltes <pe...@gmail.com>
AuthorDate: Wed May 5 22:44:39 2021 +0200
Refactors rsa configured discovery
---
bundles/cxx_remote_services/CMakeLists.txt | 3 +-
bundles/cxx_remote_services/admin/CMakeLists.txt | 13 +-
.../admin/gtest/src/RemoteServiceAdminTestSuite.cc | 26 ++-
.../admin/include/RemoteServiceAdmin.h | 8 +-
.../admin/src/RemoteServiceAdmin.cc | 26 +--
.../common/include/ExportedServiceFactory.h | 2 +-
.../discovery_configured/CMakeLists.txt | 44 ++---
.../discovery_configured/gtest/CMakeLists.txt | 30 ++++
.../gtest/resources/endpoint_discovery.json | 28 ++++
.../gtest/src/RsaConfiguredDiscoveryTestSuite.cc | 66 ++++++++
.../include/ConfiguredDiscoveryManagerActivator.h | 41 -----
.../include/ConfiguredEndpoint.h | 52 ------
.../include/ConfiguredEndpointProperties.h | 99 -----------
.../celix/rsa/IConfiguredDiscoveryManager.h} | 23 +--
.../src/ConfiguredDiscoveryManager.cc | 99 +++++++----
.../{include => src}/ConfiguredDiscoveryManager.h | 49 ++----
.../src/ConfiguredDiscoveryManagerActivator.cc | 23 +--
.../discovery_configured/src/ConfiguredEndpoint.cc | 89 ----------
.../rsa_spi/include/celix/rsa/Endpoint.h | 66 --------
.../include/celix/rsa/EndpointDescription.h | 186 +++++++++++++++++++++
.../rsa_spi/include/celix/rsa/IEndpointAnnouncer.h | 6 +-
.../include/celix/rsa/IExportServiceFactory.h | 2 +-
.../rsa_spi/include/celix/rsa/IExportedService.h | 4 +-
.../include/celix/rsa/IImportServiceFactory.h | 4 +-
.../rsa_spi/include/celix/rsa/RemoteConstants.h | 133 +++++++++++++++
.../include/celix/rsa/RemoteServicesException.h | 2 +-
libs/framework/gtest/CMakeLists.txt | 1 +
.../gtest/src/CxxBundleContextTestSuite.cc | 1 -
libs/framework/gtest/src/CxxUtilsTestSuite.cc | 62 +++++++
libs/framework/include/celix/Utils.h | 20 +++
30 files changed, 707 insertions(+), 501 deletions(-)
diff --git a/bundles/cxx_remote_services/CMakeLists.txt b/bundles/cxx_remote_services/CMakeLists.txt
index 2257092..eadbd41 100644
--- a/bundles/cxx_remote_services/CMakeLists.txt
+++ b/bundles/cxx_remote_services/CMakeLists.txt
@@ -17,10 +17,11 @@
celix_subproject(REMOTE_SERVICE_ADMIN "Option to enable building the C++17 Remote Service Admin Service bundles" OFF)
if (REMOTE_SERVICE_ADMIN)
+ message(WARNING "The C++ Remote Service Admin is still experimental; The API, SPI and implementation is not stable and will change")
#add_subdirectory(common)
add_subdirectory(rsa_spi)
add_subdirectory(admin)
+ add_subdirectory(discovery_configured)
#add_subdirectory(topology_manager)
- #add_subdirectory(discovery_configured)
#add_subdirectory(examples)
endif()
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/admin/CMakeLists.txt b/bundles/cxx_remote_services/admin/CMakeLists.txt
index 8cc9658..38bae70 100644
--- a/bundles/cxx_remote_services/admin/CMakeLists.txt
+++ b/bundles/cxx_remote_services/admin/CMakeLists.txt
@@ -17,7 +17,7 @@
add_celix_bundle(RemoteServiceAdmin
VERSION 0.9.0
- SYMBOLIC_NAME "celix::RemoteServiceAdmin"
+ SYMBOLIC_NAME "apache::celix::RemoteServiceAdmin"
NAME "Apache Celix Remote Service Admin"
GROUP "Celix/RSA"
FILENAME "Celix_RemoteServiceAdmin"
@@ -31,11 +31,10 @@ target_link_libraries(RemoteServiceAdmin PRIVATE
Celix::log_service_api
)
-if (ENABLE_TESTING)
- add_subdirectory(gtest)
-endif()
-
-
install_celix_bundle(RemoteServiceAdmin EXPORT celix COMPONENT rsa)
#Setup target aliases to match external usage
-add_library(Celix::RemoteServiceAdmin ALIAS RemoteServiceAdmin)
\ No newline at end of file
+add_library(Celix::RemoteServiceAdmin ALIAS RemoteServiceAdmin)
+
+if (ENABLE_TESTING)
+ add_subdirectory(gtest)
+endif()
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/admin/gtest/src/RemoteServiceAdminTestSuite.cc b/bundles/cxx_remote_services/admin/gtest/src/RemoteServiceAdminTestSuite.cc
index 22ff43e..c9d5c4e 100644
--- a/bundles/cxx_remote_services/admin/gtest/src/RemoteServiceAdminTestSuite.cc
+++ b/bundles/cxx_remote_services/admin/gtest/src/RemoteServiceAdminTestSuite.cc
@@ -23,7 +23,7 @@
#include "celix/rsa/IExportServiceFactory.h"
#include "celix/rsa/IExportedService.h"
#include "celix/rsa/IImportServiceFactory.h"
-#include "celix/rsa/Constants.h"
+#include "celix/rsa/RemoteConstants.h"
class RemoteServiceAdminTestSuite : public ::testing::Test {
public:
@@ -52,11 +52,9 @@ TEST_F(RemoteServiceAdminTestSuite, startStopStartStopBundle) {
class StubExportedService : public celix::rsa::IExportedService {
public:
~StubExportedService() noexcept override = default;
- std::shared_ptr<celix::rsa::Endpoint> getEndpoint() override {
- return endpoint;
+ std::shared_ptr<celix::rsa::EndpointDescription> getEndpoint() override {
+ return nullptr; //can by nullptr for dummy
}
-private:
- std::shared_ptr<celix::rsa::Endpoint> endpoint = std::make_shared<celix::rsa::Endpoint>(celix::Properties{}); //can be empty for stub
};
@@ -148,7 +146,7 @@ TEST_F(RemoteServiceAdminTestSuite, exportService) {
EXPECT_EQ(0, count);
auto reg2 = ctx->registerService<IDummyService>(std::make_shared<DummyServiceImpl>())
- .addProperty(celix::rsa::REMOTE_SERVICE_EXPORTED_PROPERTY_NAME, true)
+ .addProperty(celix::rsa::SERVICE_EXPORTED_INTERFACES, "*")
.build();
//rsa called export service factory which created a IExportServiceRegistration, which register the marker interface IExportedService indicating an exported service
@@ -181,7 +179,7 @@ TEST_F(RemoteServiceAdminTestSuite, exportServiceDifferentOrder) {
EXPECT_EQ(0, count);
auto reg1 = ctx->registerService<IDummyService>(std::make_shared<DummyServiceImpl>())
- .addProperty(celix::rsa::REMOTE_SERVICE_EXPORTED_PROPERTY_NAME, true)
+ .addProperty(celix::rsa::SERVICE_EXPORTED_INTERFACES, "*")
.build();
count = ctx->useService<celix::rsa::IExportedService>()
@@ -216,7 +214,7 @@ public:
explicit StubImportedServiceEntry(std::shared_ptr<celix::BundleContext> _ctx) : ctx{std::move(_ctx)} {
auto& cmp = ctx->getDependencyManager()->createComponent<StubImportedService>();
cmp.createProvidedService<IDummyService>()
- .addProperty(celix::rsa::REMOTE_SERVICE_IMPORTED_PROPERTY_NAME, true);
+ .addProperty(celix::rsa::SERVICE_EXPORTED_INTERFACES, "*");
cmp.buildAsync();
cmpUUID = cmp.getUUID();
}
@@ -254,8 +252,8 @@ class StubImportServiceFactory : public celix::rsa::IImportServiceFactory {
public:
explicit StubImportServiceFactory(std::shared_ptr<celix::BundleContext> _ctx) : ctx{std::move(_ctx)} {}
- virtual std::unique_ptr<celix::rsa::IImportServiceGuard> importService(const celix::rsa::Endpoint& endpoint) {
- if (endpoint.getExportedInterfaces() == celix::typeName<IDummyService>()) {
+ virtual std::unique_ptr<celix::rsa::IImportServiceGuard> importService(const celix::rsa::EndpointDescription& endpoint) {
+ if (endpoint.getInterface() == celix::typeName<IDummyService>()) {
std::lock_guard<std::mutex> lock{mutex};
auto entry = std::make_shared<StubImportedServiceEntry>(ctx);
entries.emplace_back(entry);
@@ -291,10 +289,10 @@ TEST_F(RemoteServiceAdminTestSuite, importService) {
.build();
EXPECT_EQ(0, count);
- auto endpoint = std::make_shared<celix::rsa::Endpoint>(celix::Properties{
- {celix::rsa::Endpoint::IDENTIFIER, "endpoint-id-1"},
- {celix::rsa::Endpoint::EXPORTS, celix::typeName<IDummyService>()}});
- auto reg2 = ctx->registerService<celix::rsa::Endpoint>(std::move(endpoint))
+ auto endpoint = std::make_shared<celix::rsa::EndpointDescription>(celix::Properties{
+ {celix::rsa::ENDPOINT_ID, "endpoint-id-1"},
+ {celix::SERVICE_NAME,celix::typeName<IDummyService>()}});
+ auto reg2 = ctx->registerService<celix::rsa::EndpointDescription>(std::move(endpoint))
.build();
//rsa called import service factory which created a IImportService, which register a IDummtService
diff --git a/bundles/cxx_remote_services/admin/include/RemoteServiceAdmin.h b/bundles/cxx_remote_services/admin/include/RemoteServiceAdmin.h
index f741af3..2d6b866 100644
--- a/bundles/cxx_remote_services/admin/include/RemoteServiceAdmin.h
+++ b/bundles/cxx_remote_services/admin/include/RemoteServiceAdmin.h
@@ -17,7 +17,7 @@
* under the License.
*/
-#include "celix/rsa/Endpoint.h"
+#include "celix/rsa/EndpointDescription.h"
#include <celix_api.h>
#include <mutex>
#include "celix_log_service.h"
@@ -38,8 +38,8 @@ namespace celix::rsa {
class RemoteServiceAdmin {
public:
// Imported endpoint add/remove functions
- void addEndpoint(const std::shared_ptr<celix::rsa::Endpoint>& endpoint);
- void removeEndpoint(const std::shared_ptr<celix::rsa::Endpoint>& endpoint);
+ void addEndpoint(const std::shared_ptr<celix::rsa::EndpointDescription>& endpoint);
+ void removeEndpoint(const std::shared_ptr<celix::rsa::EndpointDescription>& endpoint);
// import service factory. used to create new imported services
void addImportedServiceFactory(const std::shared_ptr<celix::rsa::IImportServiceFactory>& factory, const std::shared_ptr<const celix::Properties>& properties);
@@ -75,7 +75,7 @@ namespace celix::rsa {
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
#endif
- std::vector<std::shared_ptr<celix::rsa::Endpoint>> _toBeImportedServices{};
+ 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/RemoteServiceAdmin.cc b/bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.cc
index be35f71..4bdcc49 100644
--- a/bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.cc
+++ b/bundles/cxx_remote_services/admin/src/RemoteServiceAdmin.cc
@@ -18,7 +18,9 @@
*/
#include "RemoteServiceAdmin.h"
-#include "celix/rsa/Constants.h"
+#include "celix/rsa/RemoteConstants.h"
+#include "celix/rsa/IImportServiceFactory.h"
+#include "celix/rsa/IExportServiceFactory.h"
#define L_DEBUG(...) \
if (_logService) { \
@@ -37,16 +39,16 @@
_logService->error(_logService->handle, __VA_ARGS__); \
}
-void celix::rsa::RemoteServiceAdmin::addEndpoint(const std::shared_ptr<celix::rsa::Endpoint>& endpoint) {
+void celix::rsa::RemoteServiceAdmin::addEndpoint(const std::shared_ptr<celix::rsa::EndpointDescription>& endpoint) {
assert(endpoint);
- auto interface = endpoint->getExportedInterfaces();
+ auto interface = endpoint->getInterface();
if (interface.empty()) {
L_WARN("Adding endpoint but missing exported interfaces");
return;
}
- auto endpointId = endpoint->getEndpointId();
+ auto endpointId = endpoint->getId();
if (endpointId.empty()) {
L_WARN("Adding endpoint but missing service id");
return;
@@ -57,10 +59,10 @@ void celix::rsa::RemoteServiceAdmin::addEndpoint(const std::shared_ptr<celix::rs
createImportServices();
}
-void celix::rsa::RemoteServiceAdmin::removeEndpoint(const std::shared_ptr<celix::rsa::Endpoint>& endpoint) {
+void celix::rsa::RemoteServiceAdmin::removeEndpoint(const std::shared_ptr<celix::rsa::EndpointDescription>& endpoint) {
assert(endpoint);
- auto id = endpoint->getEndpointId();
+ auto id = endpoint->getId();
if (id.empty()) {
L_WARN("Cannot remove endpoint without a valid id");
return;
@@ -71,7 +73,7 @@ void celix::rsa::RemoteServiceAdmin::removeEndpoint(const std::shared_ptr<celix:
std::lock_guard l(_m);
_toBeImportedServices.erase(std::remove_if(_toBeImportedServices.begin(), _toBeImportedServices.end(), [&id](auto const &endpoint){
- return id == endpoint->getEndpointId();
+ return id == endpoint->getId();
}), _toBeImportedServices.end());
auto it = _importedServices.find(id);
@@ -176,7 +178,7 @@ void celix::rsa::RemoteServiceAdmin::removeService(const std::shared_ptr<void>&
//remove to be exported endpoint (if present)
for (auto it = _toBeExportedServices.begin(); it != _toBeExportedServices.end(); ++it) {
- if ((*it)->getAsBool(celix::SERVICE_ID, -1) == svcId) {
+ if ((*it)->getAsLong(celix::SERVICE_ID, -1) == svcId) {
_toBeExportedServices.erase(it);
break;
}
@@ -186,14 +188,14 @@ void celix::rsa::RemoteServiceAdmin::removeService(const std::shared_ptr<void>&
void celix::rsa::RemoteServiceAdmin::createImportServices() {
auto it = _toBeImportedServices.begin();
while (it != _toBeImportedServices.end()) {
- auto interface = (*it)->getExportedInterfaces();
+ 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;
}
- auto endpointId = (*it)->getEndpointId();
+ auto endpointId = (*it)->getId();
L_DEBUG("Adding endpoint, created service");
_importedServices.emplace(endpointId, existingFactory->second->importService(**it));
it = _toBeImportedServices.erase(it);
@@ -231,7 +233,7 @@ public:
auto admin = std::make_shared<celix::rsa::RemoteServiceAdmin>();
auto& cmp = ctx->getDependencyManager()->createComponent(admin);
- cmp.createServiceDependency<celix::rsa::Endpoint>()
+ cmp.createServiceDependency<celix::rsa::EndpointDescription>()
.setRequired(false)
.setStrategy(celix::dm::DependencyUpdateStrategy::locking)
.setCallbacks(&celix::rsa::RemoteServiceAdmin::addEndpoint, &celix::rsa::RemoteServiceAdmin::removeEndpoint);
@@ -252,7 +254,7 @@ public:
//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::REMOTE_SERVICE_EXPORTED_PROPERTY_NAME).append("=*)"))
+ .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);
})
diff --git a/bundles/cxx_remote_services/common/include/ExportedServiceFactory.h b/bundles/cxx_remote_services/common/include/ExportedServiceFactory.h
index 6dcc0c9..1db4bae 100644
--- a/bundles/cxx_remote_services/common/include/ExportedServiceFactory.h
+++ b/bundles/cxx_remote_services/common/include/ExportedServiceFactory.h
@@ -21,7 +21,7 @@
#include <celix/dm/DependencyManager.h>
#include <pubsub_endpoint.h>
#include <IExportedService.h>
-#include "celix/rsa/Endpoint.h"
+#include "celix/rsa/EndpointDescription.h"
namespace celix::async_rsa {
/// Service factory interface.
diff --git a/bundles/cxx_remote_services/discovery_configured/CMakeLists.txt b/bundles/cxx_remote_services/discovery_configured/CMakeLists.txt
index 8a38a11..5301efb 100644
--- a/bundles/cxx_remote_services/discovery_configured/CMakeLists.txt
+++ b/bundles/cxx_remote_services/discovery_configured/CMakeLists.txt
@@ -17,27 +17,31 @@
find_package(RapidJSON REQUIRED)
-add_celix_bundle(async_rsa_discovery_configured
- VERSION 0.9.0
- SYMBOLIC_NAME "apache_celix_async_remote_service_admin_discovery_configured"
- NAME "Apache Celix Async Configured Discovery"
- GROUP "Celix/AsyncRSA"
- SOURCES
- src/ConfiguredEndpoint.cc
+#TODO alias and install lib
+add_library(RsaConfiguredDiscovery_api INTERFACE)
+target_include_directories(RsaConfiguredDiscovery_api INTERFACE
+ include
+)
+
+add_celix_bundle(RsaConfiguredDiscovery
+ VERSION 0.9.0
+ SYMBOLIC_NAME "apache::celix::RsaConfiguredDiscovery"
+ NAME "Apache Celix Async Configured Discovery"
+ GROUP "Celix/RSA"
+ SOURCES
src/ConfiguredDiscoveryManager.cc
src/ConfiguredDiscoveryManagerActivator.cc
- )
-target_include_directories(async_rsa_discovery_configured PUBLIC
- $<BUILD_INTERFACE:${RapidJSON_INCLUDE_DIR}>
- $<BUILD_INTERFACE:${CMAKE_CURRENT_LIST_DIR}/include>
- $<INSTALL_INTERFACE:include/celix/async_rsa_discovery_configured>)
-target_link_libraries(async_rsa_discovery_configured PUBLIC
- Celix::async_rsa_common
+)
+target_link_libraries(RsaConfiguredDiscovery PRIVATE
+ RsaConfiguredDiscovery_api
Celix::framework
Celix::rsa_spi
- )
-install_celix_bundle(async_rsa_discovery_configured EXPORT celix COMPONENT async_rsa_discovery_configured)
-target_compile_options(async_rsa_discovery_configured INTERFACE -std=c++17)
-add_library(Celix::async_rsa_discovery_configured ALIAS async_rsa_discovery_configured)
-install(TARGETS async_rsa_discovery_configured EXPORT celix DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT async_rsa_discovery_configured)
-install(DIRECTORY include/ DESTINATION include/celix/async_rsa_discovery_configured COMPONENT async_rsa_discovery_configured)
\ No newline at end of file
+)
+target_include_directories(RsaConfiguredDiscovery PRIVATE src)
+install_celix_bundle(RsaConfiguredDiscovery EXPORT celix COMPONENT rsa)
+target_compile_options(RsaConfiguredDiscovery INTERFACE -std=c++17)
+add_library(Celix::RsaConfiguredDiscovery ALIAS RsaConfiguredDiscovery)
+
+if (ENABLE_TESTING)
+ add_subdirectory(gtest)
+endif()
diff --git a/bundles/cxx_remote_services/discovery_configured/gtest/CMakeLists.txt b/bundles/cxx_remote_services/discovery_configured/gtest/CMakeLists.txt
new file mode 100644
index 0000000..710440b
--- /dev/null
+++ b/bundles/cxx_remote_services/discovery_configured/gtest/CMakeLists.txt
@@ -0,0 +1,30 @@
+# 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_executable(test_cxx_rsa_configured_discovery
+ src/RsaConfiguredDiscoveryTestSuite.cc
+)
+
+target_link_libraries(test_cxx_rsa_configured_discovery PRIVATE Celix::framework GTest::gtest GTest::gtest_main Celix::rsa_spi RsaConfiguredDiscovery_api)
+
+add_dependencies(test_cxx_rsa_configured_discovery RsaConfiguredDiscovery_bundle)
+celix_get_bundle_file(RsaConfiguredDiscovery RSA_CONFIGURED_DISCOVERY_BUNDLE_LOCATION)
+target_compile_definitions(test_cxx_rsa_configured_discovery PRIVATE RSA_CONFIGURED_DISCOVERY_BUNDLE_LOCATION="${RSA_CONFIGURED_DISCOVERY_BUNDLE_LOCATION}")
+target_compile_definitions(test_cxx_rsa_configured_discovery PRIVATE RSA_CONFIGURED_DISCOVERY_DISCOVERY_FILE="${CMAKE_CURRENT_SOURCE_DIR}/resources/endpoint_discovery.json")
+
+add_test(NAME test_cxx_rsa_configured_discovery COMMAND test_cxx_rsa_configured_discovery)
+setup_target_for_coverage(test_cxx_rsa_configured_discovery SCAN_DIR ..)
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/discovery_configured/gtest/resources/endpoint_discovery.json b/bundles/cxx_remote_services/discovery_configured/gtest/resources/endpoint_discovery.json
new file mode 100644
index 0000000..a491180
--- /dev/null
+++ b/bundles/cxx_remote_services/discovery_configured/gtest/resources/endpoint_discovery.json
@@ -0,0 +1,28 @@
+{
+ "endpoints": [
+ {
+ "endpoint.id": "id-01",
+ "service.imported": true,
+ "service.imported.configs": [
+ "pubsub"
+ ],
+ "service.exported.interfaces": "IHardcodedService",
+ "endpoint.objectClass": "TestComponentName",
+ "endpoint.scope": "default",
+ "endpoint.topic": "default",
+ "endpoint.anykey" : "anyval"
+ },
+ {
+ "endpoint.id": "id-02",
+ "service.imported": true,
+ "service.imported.configs": [
+ "pubsub"
+ ],
+ "service.exported.interfaces": "*",
+ "endpoint.objectClass": "TestComponentName",
+ "endpoint.scope": "default",
+ "endpoint.topic": "default",
+ "endpoint.anykey" : "anyval"
+ }
+ ]
+}
\ 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
new file mode 100644
index 0000000..cd67aef
--- /dev/null
+++ b/bundles/cxx_remote_services/discovery_configured/gtest/src/RsaConfiguredDiscoveryTestSuite.cc
@@ -0,0 +1,66 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include "celix/FrameworkFactory.h"
+#include "celix/rsa/EndpointDescription.h"
+#include "celix/rsa/IConfiguredDiscoveryManager.h"
+
+class RsaConfiguredDiscoveryTestSuite : public ::testing::Test {
+public:
+ RsaConfiguredDiscoveryTestSuite() {
+ celix::Properties config{};
+ config[celix::rsa::CONFIGURED_DISCOVERY_DISCOVERY_FILES] = std::string{RSA_CONFIGURED_DISCOVERY_DISCOVERY_FILE}.append(" , garbage_path, garbage_path2 ");
+ fw = celix::createFramework(config);
+ ctx = fw->getFrameworkBundleContext();
+ }
+
+ std::shared_ptr<celix::Framework> fw{};
+ std::shared_ptr<celix::BundleContext> ctx{};
+};
+
+TEST_F(RsaConfiguredDiscoveryTestSuite, startStopStartStopBundle) {
+ auto bndId = ctx->installBundle(RSA_CONFIGURED_DISCOVERY_BUNDLE_LOCATION);
+ EXPECT_GE(bndId, 0);
+ ctx->stopBundle(bndId);
+ ctx->startBundle(bndId);
+}
+
+TEST_F(RsaConfiguredDiscoveryTestSuite, discoverConfiguredEndpoints) {
+ auto bndId = ctx->installBundle(RSA_CONFIGURED_DISCOVERY_BUNDLE_LOCATION);
+ EXPECT_GE(bndId, 0);
+
+ //When I start the RSA Configured Discovery bundle with a endpoint discovery file with 2 endpoints
+ //there will be 2 Endpoint services in the framework.
+ auto count = ctx->useServices<celix::rsa::EndpointDescription>()
+ .addUseCallback([](auto& endpoint) {
+ EXPECT_NE(endpoint.getId(), "");
+ //TODO EXPECT_NE(endpoint.getConfigurationTypes(), "");
+ EXPECT_NE(endpoint.getInterface(), "");
+ EXPECT_NE(endpoint.getFrameworkUUID(), "");
+ EXPECT_NE(endpoint.getProperties().get("endpoint.scope"), ""); //note async specific
+ EXPECT_NE(endpoint.getProperties().get("endpoint.topic"), ""); //note async specific
+ EXPECT_NE(endpoint.getProperties().get("endpoint.anykey"), ""); //note test specific
+ })
+ .build();
+ EXPECT_EQ(count, 2);
+}
+
+//TODO test add/remove of adding configured discovery file
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/discovery_configured/include/ConfiguredDiscoveryManagerActivator.h b/bundles/cxx_remote_services/discovery_configured/include/ConfiguredDiscoveryManagerActivator.h
deleted file mode 100644
index a5307f8..0000000
--- a/bundles/cxx_remote_services/discovery_configured/include/ConfiguredDiscoveryManagerActivator.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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
-
-#include <ConfiguredDiscoveryManager.h>
-#include <celix_api.h>
-
-namespace {
-
-class ConfiguredDiscoveryManagerActivator {
-public:
- explicit ConfiguredDiscoveryManagerActivator(const std::shared_ptr<celix::dm::DependencyManager>& dependencyManager);
-
- ~ConfiguredDiscoveryManagerActivator();
-
- ConfiguredDiscoveryManagerActivator(const ConfiguredDiscoveryManagerActivator&) = default;
- ConfiguredDiscoveryManagerActivator(ConfiguredDiscoveryManagerActivator&&) = default;
-
-private:
-
- celix::dm::Component<celix::rsa::ConfiguredDiscoveryManager>& _component;
- std::shared_ptr<celix::dm::DependencyManager> _mng;
-};
-
-} // end anonymous namespace.
diff --git a/bundles/cxx_remote_services/discovery_configured/include/ConfiguredEndpoint.h b/bundles/cxx_remote_services/discovery_configured/include/ConfiguredEndpoint.h
deleted file mode 100644
index a107397..0000000
--- a/bundles/cxx_remote_services/discovery_configured/include/ConfiguredEndpoint.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * 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
-
-#include "celix/rsa/Endpoint.h"
-#include <ConfiguredEndpointProperties.h>
-
-#include <optional>
-#include <string>
-
-#include <rapidjson/document.h>
-
-namespace celix::rsa {
-
-/**
- * This subclass of Endpoint contains logic to parse (rapid) JSON values into endpoint celix properties.
- */
-class ConfiguredEndpoint : public Endpoint {
-public:
-
- ConfiguredEndpoint() = delete;
-
- explicit ConfiguredEndpoint(const rapidjson::Value& endpointJson);
-
- const ConfiguredEndpointProperties& getConfiguredProperties() const;
-
- std::string ToString() const {
- return "[ConfiguredEndpoint (" + _configuredProperties->ToString() + ")]";
- }
-
-private:
-
- std::optional<ConfiguredEndpointProperties> _configuredProperties;
-};
-
-} // end namespace celix::rsa.
diff --git a/bundles/cxx_remote_services/discovery_configured/include/ConfiguredEndpointProperties.h b/bundles/cxx_remote_services/discovery_configured/include/ConfiguredEndpointProperties.h
deleted file mode 100644
index 63cce90..0000000
--- a/bundles/cxx_remote_services/discovery_configured/include/ConfiguredEndpointProperties.h
+++ /dev/null
@@ -1,99 +0,0 @@
-/*
- * 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
-
-#include <string>
-#include <vector>
-
-namespace celix::rsa {
-
-/**
- * Data object for the ConfiguredEndpoint class, containing all data parsed from input JSON objects.
- */
-class ConfiguredEndpointProperties {
-public:
-
- ConfiguredEndpointProperties(
- std::string id, bool imported, std::vector <std::string> importConfigs,
- std::string exports, std::vector <std::string> objectClass,
- std::string scope, std::string topic) :
- _id{std::move(id)},
- _imported{imported},
- _importConfigs{std::move(importConfigs)},
- _exports{std::move(exports)},
- _objectClass{std::move(objectClass)},
- _scope{std::move(scope)},
- _topic{std::move(topic)} {
- }
-
- std::string getId() const {
-
- return _id;
- }
-
- bool isImported() const {
-
- return _imported;
- }
-
- const std::vector <std::string>& getImportConfigs() const {
-
- return _importConfigs;
- }
-
- const std::string& getExports() const {
-
- return _exports;
- }
-
- const std::vector <std::string>& getObjectClass() const {
-
- return _objectClass;
- }
-
- const std::string& getScope() const {
-
- return _scope;
- }
-
- const std::string& getTopic() const {
-
- return _topic;
- }
-
- std::string ToString() const {
-
- return "id: " + _id + ", imported: " + std::to_string(_imported) +
- ", imports (size): " + std::to_string(_importConfigs.size()) + ", exports: " + _exports +
- ", objclass (size) " + std::to_string(_objectClass.size()) + ", scope: "
- + _scope + ", topic: " + _topic;
- }
-
-private:
-
- std::string _id;
- bool _imported;
- std::vector <std::string> _importConfigs;
- std::string _exports;
- std::vector <std::string> _objectClass;
- std::string _scope;
- std::string _topic;
-};
-
-} // end namespace celix::rsa.
diff --git a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/Constants.h b/bundles/cxx_remote_services/discovery_configured/include/celix/rsa/IConfiguredDiscoveryManager.h
similarity index 59%
rename from bundles/cxx_remote_services/rsa_spi/include/celix/rsa/Constants.h
rename to bundles/cxx_remote_services/discovery_configured/include/celix/rsa/IConfiguredDiscoveryManager.h
index 5ae1c9f..4e7967a 100644
--- a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/Constants.h
+++ b/bundles/cxx_remote_services/discovery_configured/include/celix/rsa/IConfiguredDiscoveryManager.h
@@ -16,22 +16,25 @@
* specific language governing permissions and limitations
* under the License.
*/
-
#pragma once
-
namespace celix::rsa {
-
/**
- * @brief Service property (named "service.exported") to mark a service as wanting to be exported (remote).
- * Present means -> export service as a remote service.
+ * @brief Config property for the ',' seperated paths for configured endpoints files.
*/
- constexpr const char * const REMOTE_SERVICE_EXPORTED_PROPERTY_NAME = "service.exported";
+ constexpr const char *const CONFIGURED_DISCOVERY_DISCOVERY_FILES = "CELIX_RSA_CONFIGURED_DISCOVERY_DISCOVERY_FILES";
/**
- * @brief Service property (named "remote") to mark a service as a imported service.
- * Present means -> service is a imported service (proxy of a remote service).
+ * @brief The IConfiguredDiscoveryManager interface.
+ *
+ * TODO document the expect json format.
*/
- constexpr const char * const REMOTE_SERVICE_IMPORTED_PROPERTY_NAME = "service.imported";
+ class IConfiguredDiscoveryManager {
+ public:
+ virtual ~IConfiguredDiscoveryManager() noexcept = default;
+
+ virtual void addConfiguredDiscoveryFile(const std::string& path) = 0;
-}
\ No newline at end of file
+ virtual void removeConfiguredDiscoveryFile(const std::string& path) = 0;
+ };
+}
diff --git a/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManager.cc b/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManager.cc
index fc3207c..53d4d9e 100644
--- a/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManager.cc
+++ b/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManager.cc
@@ -22,16 +22,13 @@
#include <fstream>
#include <filesystem>
-#include <ConfiguredEndpoint.h>
#include <celix_bundle_context.h>
#include <rapidjson/writer.h>
-namespace celix::rsa {
+static constexpr const char* ENDPOINT_ARRAY = "endpoints";
-constexpr const char* ENDPOINT_ARRAY = "endpoints";
-
-std::optional<std::string> readFile(const std::string& path) {
+static std::optional<std::string> readFile(const std::string& path) {
std::string contents;
std::ifstream file(path);
@@ -41,51 +38,97 @@ std::optional<std::string> readFile(const std::string& path) {
file.seekg(0, std::ios::end);
contents.resize(file.tellg());
file.seekg(0, std::ios::beg);
- file.read(&contents[0], contents.size());
+ file.read(&contents[0], (std::streamsize)contents.size());
file.close();
return contents;
}
-rapidjson::Document parseJSONFile(std::string& contents) {
+static rapidjson::Document parseJSONFile(std::string& contents) {
rapidjson::Document resultDocument{};
resultDocument.ParseInsitu(contents.data());
return resultDocument;
}
-ConfiguredDiscoveryManager::ConfiguredDiscoveryManager(std::shared_ptr<DependencyManager> dependencyManager) :
- _dependencyManager{std::move(dependencyManager)},
- _configurationFilePath{} {
-
- _configurationFilePath = celix_bundleContext_getProperty(
- _dependencyManager->bundleContext(),
- CELIX_ASYNC_RSA_CONFIGURED_DISCOVERY_FILE,
- "");
+celix::rsa::ConfiguredDiscoveryManager::ConfiguredDiscoveryManager(std::shared_ptr<celix::BundleContext> _ctx) :
+ ctx{std::move(_ctx)},
+ configuredDiscoveryFiles{ctx->getConfigProperty(celix::rsa::CONFIGURED_DISCOVERY_DISCOVERY_FILES, "")} {
+ readConfiguredDiscoveryFiles();
+}
- discoverEndpoints();
+void celix::rsa::ConfiguredDiscoveryManager::readConfiguredDiscoveryFiles() {
+ //TODO split configuredDiscoveryFiles
+ if (!configuredDiscoveryFiles.empty()) {
+ for (auto path : celix::split(configuredDiscoveryFiles)) {
+ addConfiguredDiscoveryFile(path);
+ }
+ }
}
-void ConfiguredDiscoveryManager::discoverEndpoints() {
+//static std::vector<std::string> parseJSONStringArray(const rapidjson::Value& jsonArray) {
+// std::vector<std::string> resultVec{};
+// if (jsonArray.IsArray()) {
+// resultVec.reserve(jsonArray.Size());
+// for (auto& element : jsonArray.GetArray()) {
+// if (element.IsString()) {
+// resultVec.emplace_back(element.GetString());
+// }
+// }
+// }
+// return resultVec;
+//}
+
+celix::Properties celix::rsa::ConfiguredDiscoveryManager::convertToEndpointProperties(const rapidjson::Value &endpointJSON) {
+ celix::Properties result{};
+ result.set(celix::rsa::ENDPOINT_FRAMEWORK_UUID, ctx->getFramework()->getUUID());
+ for (auto it = endpointJSON.MemberBegin(); it != endpointJSON.MemberEnd(); ++it) {
+ if (it->value.GetType() == rapidjson::Type::kStringType) {
+ if (celix_utils_stringEquals(it->name.GetString(), "endpoint.objectClass")) { //TODO improve
+ result.set(celix::SERVICE_NAME, it->value.GetString());
+ } else {
+ result.set(it->name.GetString(), it->value.GetString());
+ }
+ } else if (it->value.GetType() == rapidjson::Type::kTrueType || it->value.GetType() == rapidjson::Type::kFalseType) {
+ result.set(it->name.GetString(), it->value.GetBool());
+ } else {
+ std::cout << "TODO member " << it->name.GetString() << std::endl;
+ }
+ }
+ return result;
+}
- auto contents = readFile(_configurationFilePath);
+void celix::rsa::ConfiguredDiscoveryManager::addConfiguredDiscoveryFile(const std::string& path) {
+ std::vector<std::shared_ptr<celix::ServiceRegistration>> newEndpoints{};
+ auto contents = readFile(path);
if (contents) {
auto parsedJson = parseJSONFile(contents.value());
if (parsedJson.IsObject()) {
if (parsedJson.HasMember(ENDPOINT_ARRAY) && parsedJson[ENDPOINT_ARRAY].IsArray()) {
- for (auto& endpoint : parsedJson[ENDPOINT_ARRAY].GetArray()) {
- const auto& configuredEndpointPtr = std::make_shared<ConfiguredEndpoint>(endpoint.GetObject());
- const auto endpointProperties = configuredEndpointPtr->getProperties();
-
- std::cout << configuredEndpointPtr->ToString() << std::endl;
-
- _dependencyManager->createComponent<Endpoint>(configuredEndpointPtr)
- .addInterface<Endpoint>("1.0.0", endpointProperties)
- .build();
+ for (auto& jsonEndpoint : parsedJson[ENDPOINT_ARRAY].GetArray()) {
+ try {
+ auto endpointProperties = convertToEndpointProperties(jsonEndpoint);
+ auto endpointDescription = std::make_shared<EndpointDescription>(std::move(endpointProperties));
+
+ //TODO log service
+ std::cout << endpointDescription->toString() << std::endl;
+
+ auto reg = ctx->registerService<celix::rsa::EndpointDescription>(std::move(endpointDescription))
+ .build();
+ newEndpoints.emplace_back(std::move(reg));
+ } catch (celix::rsa::RemoteServicesException& exp) {
+ //TODO log service
+ std::cerr << exp.what() << std::endl;
+ }
}
}
}
+ std::lock_guard<std::mutex> lock{mutex};
+ endpointRegistrations.emplace(path, std::move(newEndpoints));
}
}
-} // end namespace celix::rsa.
+void celix::rsa::ConfiguredDiscoveryManager::removeConfiguredDiscoveryFile(const std::string& path) {
+ std::lock_guard<std::mutex> lock{mutex};
+ endpointRegistrations.erase(path);
+}
diff --git a/bundles/cxx_remote_services/discovery_configured/include/ConfiguredDiscoveryManager.h b/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManager.h
similarity index 53%
rename from bundles/cxx_remote_services/discovery_configured/include/ConfiguredDiscoveryManager.h
rename to bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManager.h
index f4646c6..7797471 100644
--- a/bundles/cxx_remote_services/discovery_configured/include/ConfiguredDiscoveryManager.h
+++ b/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManager.h
@@ -24,16 +24,14 @@
#include <vector>
#include <string>
-#include "celix/rsa/Endpoint.h"
-#include <celix_api.h>
-
-#include <ConfiguredEndpoint.h>
+#include "celix/rsa/EndpointDescription.h"
+#include "celix/rsa/IConfiguredDiscoveryManager.h"
+#include "celix_api.h"
#include <rapidjson/document.h>
#include <rapidjson/stringbuffer.h>
-/** Path for configured endpoint file. */
-#define CELIX_ASYNC_RSA_CONFIGURED_DISCOVERY_FILE "CELIX_ASYNC_RSA_CONFIGURED_DISCOVERY_FILE"
+/** Path for configured endpoints file. */
namespace celix::rsa {
@@ -42,45 +40,30 @@ namespace celix::rsa {
* a local configuration JSON file.
* This configured discovery manager announces local exported endpoints and imported endpoints from the JSON file.
*/
-class ConfiguredDiscoveryManager final : public IEndpointAnnouncer {
+class ConfiguredDiscoveryManager final : public IConfiguredDiscoveryManager, public IEndpointAnnouncer {
public:
-
- /**
- * Deleted default constructor, dependencyManager parameter is required.
- */
- ConfiguredDiscoveryManager() = delete;
-
/**
* Constructor for the ConfiguredDiscoveryManager.
* @param dependencyManager shared_ptr to the context/container dependency manager.
*/
- explicit ConfiguredDiscoveryManager(std::shared_ptr<DependencyManager> dependencyManager);
+ explicit ConfiguredDiscoveryManager(std::shared_ptr<celix::BundleContext> ctx);
- /**
- * Deleted copy-constructor, since rapidjson members have no copy-constructor.
- */
- ConfiguredDiscoveryManager(const ConfiguredDiscoveryManager&) = delete;
-
- /**
- * Defaulted move-constructor.
- */
- ConfiguredDiscoveryManager(ConfiguredDiscoveryManager&&) = default;
-
- /**
- * Deleted assignment-operator, since rapidjson members have no copy-constructor.
- */
- ConfiguredDiscoveryManager& operator=(const ConfiguredDiscoveryManager&) = delete;
+ void announceEndpoint(std::unique_ptr<EndpointDescription> /*endpoint*/) override {/*nop*/}
- void announceEndpoint(std::unique_ptr<Endpoint> /*endpoint*/) override {/*nop*/}
+ void revokeEndpoint(std::unique_ptr<EndpointDescription> /*endpoint*/) override {/*nop*/}
- void revokeEndpoint(std::unique_ptr<Endpoint> /*endpoint*/) override {/*nop*/}
+ void addConfiguredDiscoveryFile(const std::string& path) override;
+ void removeConfiguredDiscoveryFile(const std::string& path) override;
private:
+ celix::Properties convertToEndpointProperties(const rapidjson::Value &endpointJSON);
+ void readConfiguredDiscoveryFiles();
- void discoverEndpoints();
+ const std::shared_ptr<celix::BundleContext> ctx;
+ const std::string configuredDiscoveryFiles;
- std::shared_ptr<DependencyManager> _dependencyManager;
- std::string _configurationFilePath;
+ std::mutex mutex{}; //protects below
+ std::unordered_map<std::string, std::vector<std::shared_ptr<celix::ServiceRegistration>>> endpointRegistrations{}; //key = configured discovery file path
};
} // end namespace celix::rsa.
diff --git a/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManagerActivator.cc b/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManagerActivator.cc
index e5758f6..ab61c8b 100644
--- a/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManagerActivator.cc
+++ b/bundles/cxx_remote_services/discovery_configured/src/ConfiguredDiscoveryManagerActivator.cc
@@ -17,23 +17,18 @@
* under the License.
*/
-#include <ConfiguredDiscoveryManagerActivator.h>
+#include "celix/BundleActivator.h"
#include <ConfiguredDiscoveryManager.h>
-namespace {
-
-ConfiguredDiscoveryManagerActivator::ConfiguredDiscoveryManagerActivator(
- const std::shared_ptr<celix::dm::DependencyManager>& dependencyManager) :
- _component{dependencyManager->createComponent(
- std::make_unique<celix::rsa::ConfiguredDiscoveryManager>(dependencyManager))
- .addInterface<celix::rsa::IEndpointAnnouncer>().build()}, _mng(dependencyManager) {
-}
-
- ConfiguredDiscoveryManagerActivator::~ConfiguredDiscoveryManagerActivator() {
- _mng->destroyComponent(_component);
+class ConfiguredDiscoveryManagerActivator {
+public:
+ explicit ConfiguredDiscoveryManagerActivator(const std::shared_ptr<celix::BundleContext>& ctx) {
+ auto &cmp = ctx->getDependencyManager()->createComponent(
+ std::make_unique<celix::rsa::ConfiguredDiscoveryManager>(ctx));
+ cmp.addInterface<celix::rsa::IEndpointAnnouncer>();
+ cmp.build();
}
+};
// define this class as the bundle activator.
CELIX_GEN_CXX_BUNDLE_ACTIVATOR(ConfiguredDiscoveryManagerActivator)
-
-} // end anonymous namespace.
diff --git a/bundles/cxx_remote_services/discovery_configured/src/ConfiguredEndpoint.cc b/bundles/cxx_remote_services/discovery_configured/src/ConfiguredEndpoint.cc
deleted file mode 100644
index 0ded5c1..0000000
--- a/bundles/cxx_remote_services/discovery_configured/src/ConfiguredEndpoint.cc
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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 <ConfiguredEndpoint.h>
-
-namespace celix::rsa {
-
-celix::dm::Properties convertEndpointPropertiesToCelix(const ConfiguredEndpointProperties& endpointProperties) {
-
- return celix::dm::Properties{{celix::rsa::Endpoint::IMPORTED, std::to_string(endpointProperties.isImported()).c_str()},
- {celix::rsa::Endpoint::EXPORTS, endpointProperties.getExports()},
- {celix::rsa::Endpoint::IDENTIFIER, endpointProperties.getId()}};
-}
-
-ConfiguredEndpointProperties convertCelixPropertiesToEndpoint(const celix::dm::Properties& celixProperties) {
-
- auto endpointId = celixProperties.get(celix::rsa::Endpoint::IDENTIFIER);
- auto exports = celixProperties.get(celix::rsa::Endpoint::EXPORTS);
- auto imported = celixProperties.get(celix::rsa::Endpoint::IMPORTED);
- return ConfiguredEndpointProperties{endpointId,
- (imported == "true"),
- {}, exports, {}, "", ""};
-}
-
-bool isValidEndpointJson(const rapidjson::Value& endpointJson) {
-
- return (endpointJson.HasMember(celix::rsa::Endpoint::IDENTIFIER)
- && endpointJson.HasMember(celix::rsa::Endpoint::IMPORTED)
- && endpointJson.HasMember(celix::rsa::Endpoint::IMPORT_CONFIGS)
- && endpointJson.HasMember(celix::rsa::Endpoint::EXPORTS)
- && endpointJson.HasMember(celix::rsa::Endpoint::OBJECTCLASS)
- && endpointJson.HasMember(celix::rsa::Endpoint::SCOPE)
- && endpointJson.HasMember(celix::rsa::Endpoint::TOPIC));
-}
-
-std::vector<std::string> parseJSONStringArray(const rapidjson::Value& jsonArray) {
-
- std::vector<std::string> resultVec{};
- if(jsonArray.IsArray()) {
- resultVec.reserve(jsonArray.Size());
- for(auto& element : jsonArray.GetArray()) {
- if(element.IsString()) {
- resultVec.emplace_back(element.GetString());
- }
- }
- }
- return resultVec;
-}
-
-ConfiguredEndpoint::ConfiguredEndpoint(const rapidjson::Value& endpointJson) :
- Endpoint(celix::dm::Properties{}),
- _configuredProperties{} {
-
- if (isValidEndpointJson(endpointJson)) {
-
- _configuredProperties = {endpointJson[celix::rsa::Endpoint::IDENTIFIER].GetString(),
- endpointJson[celix::rsa::Endpoint::IMPORTED].GetBool(),
- parseJSONStringArray(endpointJson[celix::rsa::Endpoint::IMPORT_CONFIGS]),
- endpointJson[celix::rsa::Endpoint::EXPORTS].GetString(),
- parseJSONStringArray(endpointJson[celix::rsa::Endpoint::OBJECTCLASS]),
- endpointJson[celix::rsa::Endpoint::SCOPE].GetString(),
- endpointJson[celix::rsa::Endpoint::TOPIC].GetString()};
-
- _celixProperties = convertEndpointPropertiesToCelix(*_configuredProperties);
- }
-}
-
-const ConfiguredEndpointProperties& ConfiguredEndpoint::getConfiguredProperties() const {
-
- return *_configuredProperties;
-}
-
-} // end namespace celix::rsa.
diff --git a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/Endpoint.h b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/Endpoint.h
deleted file mode 100644
index 6035823..0000000
--- a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/Endpoint.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * 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
-
-#include <string>
-#include <map>
-
-#include <celix/dm/Properties.h>
-
-namespace celix::rsa {
-
- /**
- * @brief Endpoint class which represent a remote endpoint discovered by the framework.
- */
- class Endpoint {
- public:
- static constexpr const char * const IDENTIFIER = "endpoint.id";
-// static constexpr const char * const IMPORTED = "service.imported";
-// static constexpr const char * const IMPORT_CONFIGS = "service.imported.configs";
- static constexpr const char * const EXPORTS = "service.exported.interfaces";
-// static constexpr const char * const OBJECTCLASS = "endpoint.objectClass";
-// static constexpr const char * const SCOPE = "endpoint.scope";
-// static constexpr const char * const TOPIC = "endpoint.topic";
-
-
- /**
- * Endpoint constructor.
- * @param properties celix properties with information about this endpoint and what its documenting.
- */
- explicit Endpoint(celix::Properties properties) : _celixProperties{std::move(properties)} {
- // TODO validate mandatory properties are set.
- }
-
- [[nodiscard]] const celix::dm::Properties& getProperties() const {
- return _celixProperties;
- }
-
- [[nodiscard]] std::string getEndpointId() const {
- return _celixProperties.get(IDENTIFIER);
- }
-
- [[nodiscard]] std::string getExportedInterfaces() const {
- return _celixProperties.get(EXPORTS);
- }
-
- protected:
- celix::dm::Properties _celixProperties;
-
- };
-} // end namespace celix::rsa.
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
new file mode 100644
index 0000000..4b43142
--- /dev/null
+++ b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/EndpointDescription.h
@@ -0,0 +1,186 @@
+/*
+ * 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
+
+#include <string>
+#include <map>
+
+#include "celix/Constants.h"
+#include "celix/Properties.h"
+#include "celix/rsa/RemoteConstants.h"
+#include "celix/rsa/RemoteServicesException.h"
+
+namespace celix::rsa {
+
+ /**
+ * @brief A description of an endpoint that provides sufficient information for a compatible distribution provider to create a connection to this endpoint.
+ *
+ * An Endpoint Description is easy to transfer between different systems because it is property based where
+ * the property keys are strings and the values are simple types.
+ * This allows it to be used as a communications device to convey available endpoint information
+ * to nodes in a network. An Endpoint Description reflects the perspective of an importer.
+ * That is, the property keys have been chosen to match filters that are created by client bundles that need a service.
+ *
+ * Therefore the map must not contain any service.exported.* property and must contain the corresponding service.imported.* ones.
+ * The service.intents property must contain the intents provided by the service itself combined with the intents
+ * added by the exporting distribution provider. Qualified intents appear fully expanded on this property.
+ */
+ class EndpointDescription {
+ public:
+
+ /**
+ * @brief Create an Endpoint Description from properties
+ *
+ * The endpoint.id, service.imported.configs and objectClass properties must be set. .
+ *
+ * @param The properties from which to create the Endpoint Description.
+ */
+ explicit EndpointDescription(celix::Properties properties) : endpointProperties{std::move(properties)} {
+ checkValidEndpoint();
+ }
+
+ /**
+ * @brief Create an Endpoint Description based on service properties and optional provided rsa properties.
+ *
+ * The properties in the rsa properties take precedence over the service properties.
+ * the the service.imported property will be set.
+ * The endpoint.id, service.imported.configs and objectClass properties must be set after construction.
+ *
+ * @param frameworkUUID the framework uuid used for endpoint ids.
+ * @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)} {
+ checkValidEndpoint();
+ }
+
+ /**
+ * @brief Returns the endpoint's id.
+ *
+ * The id is an opaque id for an endpoint.
+ * No two different endpoints must have the same id.
+ * 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);
+ }
+
+ /**
+ * @brief Returns the configuration types.
+ *
+ * A distribution provider exports a service with an endpoint.
+ * This endpoint uses some kind of communications protocol with a set of configuration parameters.
+ * There are many different types but each endpoint is configured by only one configuration type.
+ * However, a distribution provider can be aware of different configuration types and provide synonyms to
+ * 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);
+ }
+
+ /**
+ * @brief Return the framework UUID for the remote service, if present.
+ *
+ * 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);
+ }
+
+ /**
+ * @brief Return the list of intents implemented by this endpoint.
+ *
+ * The intents are based on the service.intents on an imported service, except for any intents that are
+ * additionally provided by the importing distribution provider.
+ * 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);
+ }
+
+ /**
+ * @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);
+ }
+
+ /**
+ * @brief Returns all endpoint properties.
+ */
+ [[nodiscard]] const celix::Properties& getProperties() const {
+ return endpointProperties;
+ }
+
+ /**
+ * @brief converts the EndpointDescription to a printable string.
+ */
+ [[nodiscard]] std::string toString() const {
+ std::string result{"Endpoint["};
+ for (auto& prop : endpointProperties) {
+ result.append(prop.first);
+ result.append("=");
+ result.append(prop.second);
+ result.append(", ");
+ }
+ result.append("]");
+ return result;
+ }
+ protected:
+ celix::Properties importedProperties(std::string_view frameworkUUID, const celix::Properties& serviceProperties, const celix::Properties& rsaProperties) {
+ celix::Properties result{};
+
+ for (const auto& entry: serviceProperties) {
+ result.set(entry.first, entry.second); //TODO filter and remove service.export.* entries
+ }
+ for (const auto& entry: rsaProperties) {
+ result.set(entry.first, entry.second);
+ }
+
+ result.set(celix::rsa::SERVICE_IMPORTED, true);
+
+ if (result.get(celix::rsa::ENDPOINT_ID).empty()) {
+ result.set(celix::rsa::ENDPOINT_ID, std::string{frameworkUUID} + "-" + serviceProperties.get(celix::SERVICE_ID));
+ }
+
+ return result;
+ }
+
+ void checkValidEndpoint() const {
+ std::string baseMsg = "Invalid properties for EndpointDescription, missing mandatory property ";
+ if (endpointProperties.get(celix::rsa::ENDPOINT_ID).empty()) {
+ throw celix::rsa::RemoteServicesException{baseMsg.append(celix::rsa::ENDPOINT_ID)};
+ }
+ if (endpointProperties.get(celix::rsa::ENDPOINT_ID).empty()) {
+ throw celix::rsa::RemoteServicesException{baseMsg.append(celix::rsa::SERVICE_IMPORTED_CONFIGS)};
+ }
+ if (endpointProperties.get(celix::SERVICE_NAME).empty()) {
+ throw celix::rsa::RemoteServicesException{baseMsg.append(celix::SERVICE_NAME)};
+ }
+ }
+
+ const celix::Properties endpointProperties;
+ };
+} // end namespace celix::rsa.
diff --git a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IEndpointAnnouncer.h b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IEndpointAnnouncer.h
index 425a6e4..6559b67 100644
--- a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IEndpointAnnouncer.h
+++ b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IEndpointAnnouncer.h
@@ -20,7 +20,7 @@
#include <memory>
-#include "celix/rsa/Endpoint.h"
+#include "celix/rsa/EndpointDescription.h"
#include "celix/dm/Properties.h"
namespace celix::rsa {
@@ -39,13 +39,13 @@ public:
* Task the endpoint announcer to make the given endpoint visible for discovery by other managers/ frameworks.
* @param endpoint The endpoint pointer in question, with valid properties within.
*/
- virtual void announceEndpoint(std::unique_ptr<Endpoint> endpoint) = 0;
+ virtual void announceEndpoint(std::unique_ptr<EndpointDescription> endpoint) = 0;
/**
* Task the endpoint announcer to remove the discoverability of a given endpoint.
* @param endpoint The endpoint pointer in question, with valid properties within.
*/
- virtual void revokeEndpoint(std::unique_ptr<Endpoint> endpoint) = 0;
+ virtual void revokeEndpoint(std::unique_ptr<EndpointDescription> endpoint) = 0;
};
} // end namespace celix::rsa.
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 7b386fe..66383b6 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,7 +19,7 @@
#pragma once
#include <memory>
-#include "celix/rsa/Endpoint.h"
+#include "celix/rsa/EndpointDescription.h"
namespace celix::rsa {
diff --git a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IExportedService.h b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IExportedService.h
index 50b3159..a7d1166 100644
--- a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IExportedService.h
+++ b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/IExportedService.h
@@ -18,7 +18,7 @@
*/
#pragma once
-#include "celix/rsa/Endpoint.h"
+#include "celix/rsa/EndpointDescription.h"
namespace celix::rsa {
@@ -32,6 +32,6 @@ namespace celix::rsa {
/**
* @brief the endpoint which can be used to announce this exported service to the network.
*/
- virtual std::shared_ptr<celix::rsa::Endpoint> getEndpoint() = 0;
+ virtual std::shared_ptr<celix::rsa::EndpointDescription> getEndpoint() = 0;
};
}
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 e3c15c2..7c6f3a1 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,7 +19,7 @@
#pragma once
#include <memory>
-#include "celix/rsa/Endpoint.h"
+#include "celix/rsa/EndpointDescription.h"
namespace celix::rsa {
@@ -54,6 +54,6 @@ namespace celix::rsa {
* @return A ImportService.
* @throws celix::rsa::RemoteServicesException if the import failed.
*/
- virtual std::unique_ptr<celix::rsa::IImportServiceGuard> importService(const celix::rsa::Endpoint& endpoint) = 0;
+ virtual std::unique_ptr<celix::rsa::IImportServiceGuard> 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
new file mode 100644
index 0000000..9dae5e3
--- /dev/null
+++ b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/RemoteConstants.h
@@ -0,0 +1,133 @@
+/*
+ * 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
+
+//TODO move header to rsa_api library
+
+namespace celix::rsa {
+
+
+ /**
+ * @brief Endpoint property identifying the universally unique id of the exporting framework.
+ *
+ * Can be absent if the corresponding endpoint is not for an OSGi service.
+ * The value of this property must be of type string.
+ */
+ constexpr const char * const ENDPOINT_FRAMEWORK_UUID = "endpoint.framework.uuid";
+
+ /**
+ * @brief Endpoint property identifying the id for this endpoint.
+ *
+ * This service property must always be set.
+ * The value of this property must be of type string.
+ */
+ constexpr const char * const ENDPOINT_ID = "endpoint.id";
+
+ /**
+ * @brief Endpoint property identifying the service id of the exported service.
+ *
+ * Can be absent or 0 if the corresponding endpoint is not for an OSGi service.
+ * The value of this property must be of type long.
+ */
+ constexpr const char * const ENDPOINT_SERVICE_ID = "endpoint.service.id";
+
+ /**
+ * @brief Service property identifying the configuration types supported by a distribution provider.
+ *
+ * Registered by the distribution provider on one of its services to indicate the supported configuration types.
+ * The value of this property must be of type string and can be a ',' separated list.
+ */
+ constexpr const char * const REMOTE_CONFIGS_SUPPORTED = "remote.configs.supported";
+
+ /**
+ * @brief Service property identifying the configuration types that should be used to export the service.
+ *
+ * Each configuration type represents the configuration parameters for an endpoint.
+ * A distribution provider should create an endpoint for each configuration type that it supports.
+ * This property may be supplied in the properties object passed to a registerService method.
+ * The value of this property must be of type string and can be a ',' separated list.
+ */
+ constexpr const char * const REMOTE_INTENTS_SUPPORTED = "remote.intents.supported";
+
+ /**
+ * @brief Service property identifying the intents that the distribution provider must implement to distribute the service.
+ *
+ * Intents listed in this property are reserved for intents that are critical for the code to function correctly,
+ * for example, ordering of messages. These intents should not be configurable.
+ * This property may be supplied in the properties object passed to the a registerService method.
+ * The value of this property must be of type string and can be a ',' separated list.
+ */
+ constexpr const char * const SERVICE_EXPORTED_INTENTS = "service.exported.intents";
+
+ /**
+ * @brief Service property identifying the extra intents that the distribution provider must implement to distribute the service.
+ *
+ * This property is merged with the service.exported.intents property before the distribution provider interprets
+ * the listed intents; it has therefore the same semantics but the property should be configurable so the
+ * administrator can choose the intents based on the topology.
+ * Bundles should therefore make this property configurable, for example through the Configuration Admin service.
+ * This property may be supplied in the properties object passed to the a registerService method.
+ * The value of this property must be of type string and can be a ',' separated list.
+ */
+ constexpr const char * const SERVICE_EXPORTED_INTENTS_EXTRA = "service.exported.intents.extra";
+
+ /**
+ * @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
+ * 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.
+ */
+ constexpr const char * const SERVICE_EXPORTED_INTERFACES = "service.exported.interfaces";
+
+ /**
+ * @brief Service property identifying the service as imported.
+ *
+ * This service property must be set by a distribution provider to any value when it registers the endpoint proxy as an imported service.
+ * A bundle can use this property to filter out imported services. The value of this property may be of any type.
+ */
+ constexpr const char * const SERVICE_IMPORTED = "service.imported";
+
+ /**
+ * @brief Service property identifying the configuration types used to import the service.
+ *
+ * Any associated properties for this configuration types must be properly mapped to the importing system.
+ * For example, a URL in these properties must point to a valid resource when used in the importing framework.
+ * If multiple configuration types are listed in this property, then they must be synonyms for exactly the same
+ * remote endpoint that is used to export this service.
+ * The value of this property must be of type string and can be a ',' separated list.
+ */
+ constexpr const char * const SERVICE_IMPORTED_CONFIGS = "service.imported.configs";
+
+ /**
+ * @brief Service property identifying the intents that this service implement.
+ *
+ * This property has a dual purpose:
+ * A bundle can use this service property to notify the distribution provider that these intents are already
+ * implemented by the exported service object.
+ * A distribution provider must use this property to convey the combined intents of: The exporting service,
+ * and the intents that the exporting distribution provider adds, and the intents that the importing distribution provider adds.
+ * To export a service, a distribution provider must expand any qualified intents. Both the exporting and
+ * importing distribution providers must recognize all intents before a service can be distributed.
+ * The value of this property must be of type string and can be a ',' separated list.
+ */
+ constexpr const char * const SERVICE_INTENTS = "service.intents";
+}
\ No newline at end of file
diff --git a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/RemoteServicesException.h b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/RemoteServicesException.h
index bc30a1f..e9a6b0c 100644
--- a/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/RemoteServicesException.h
+++ b/bundles/cxx_remote_services/rsa_spi/include/celix/rsa/RemoteServicesException.h
@@ -9,7 +9,7 @@ namespace celix::rsa {
*/
class RemoteServicesException : public std::exception {
public:
- explicit Exception(std::string msg) : w{std::move(msg)} {}
+ explicit RemoteServicesException(std::string msg) : w{std::move(msg)} {}
const char* what() const noexcept override {
return w.c_str();
diff --git a/libs/framework/gtest/CMakeLists.txt b/libs/framework/gtest/CMakeLists.txt
index e1045b7..178735a 100644
--- a/libs/framework/gtest/CMakeLists.txt
+++ b/libs/framework/gtest/CMakeLists.txt
@@ -43,6 +43,7 @@ add_executable(test_framework
src/HelloWorldCxxActivator.cc
src/CxxFilterTestSuite.cc
src/CxxFrameworkFactoryTestSuite.cc
+ src/CxxUtilsTestSuite.cc
)
target_link_libraries(test_framework Celix::framework CURL::libcurl GTest::gtest GTest::gtest_main)
diff --git a/libs/framework/gtest/src/CxxBundleContextTestSuite.cc b/libs/framework/gtest/src/CxxBundleContextTestSuite.cc
index ce019aa..8f059fd 100644
--- a/libs/framework/gtest/src/CxxBundleContextTestSuite.cc
+++ b/libs/framework/gtest/src/CxxBundleContextTestSuite.cc
@@ -104,7 +104,6 @@ TEST_F(CxxBundleContextTestSuite, RegisterCServiceTest) {
auto svcReg = ctx->registerService<CInterface>(svc).build();
svcReg->wait();
- std::cout << "Name is " << celix::typeName<CInterface>() << std::endl;
long svcId = ctx->findService<CInterface>();
EXPECT_GE(svcId, 0L);
diff --git a/libs/framework/gtest/src/CxxUtilsTestSuite.cc b/libs/framework/gtest/src/CxxUtilsTestSuite.cc
new file mode 100644
index 0000000..28d8594
--- /dev/null
+++ b/libs/framework/gtest/src/CxxUtilsTestSuite.cc
@@ -0,0 +1,62 @@
+/*
+ * 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 <gtest/gtest.h>
+
+#include "celix/Utils.h"
+
+class CxxUtilsTestSuite : public ::testing::Test {
+public:
+};
+
+namespace example {
+ class TestType {
+
+ };
+}
+
+
+TEST_F(CxxUtilsTestSuite, TypenameTest) {
+ auto name = celix::typeName<example::TestType>();
+ EXPECT_FALSE(name.empty());
+}
+
+TEST_F(CxxUtilsTestSuite, SplitTest) {
+ auto tokens = celix::split("item1,item2,item3");
+ ASSERT_EQ(tokens.size(), 3);
+ EXPECT_EQ(tokens[0], "item1");
+ EXPECT_EQ(tokens[1], "item2");
+ EXPECT_EQ(tokens[2], "item3");
+
+ tokens = celix::split(" item1 , item2 , item3 ");
+ ASSERT_EQ(tokens.size(), 3);
+ EXPECT_EQ(tokens[0], "item1");
+ EXPECT_EQ(tokens[1], "item2");
+ EXPECT_EQ(tokens[2], "item3");
+
+ tokens = celix::split(" item1 , ");
+ ASSERT_EQ(tokens.size(), 1);
+ EXPECT_EQ(tokens[0], "item1");
+
+ tokens = celix::split("");
+ EXPECT_EQ(tokens.size(), 0);
+
+ tokens = celix::split(" , , ");
+ EXPECT_EQ(tokens.size(), 0);
+}
\ No newline at end of file
diff --git a/libs/framework/include/celix/Utils.h b/libs/framework/include/celix/Utils.h
index bf4be75..db00a03 100644
--- a/libs/framework/include/celix/Utils.h
+++ b/libs/framework/include/celix/Utils.h
@@ -23,6 +23,7 @@
#include <string>
#include <string.h>
#include <iostream>
+#include <vector>
//NOTE based on has_rtti.cpp
#if defined(__clang__)
@@ -97,6 +98,25 @@ namespace celix {
std::string typeName(const std::string& providedTypeName) {
return providedTypeName.empty() ? celix::typeName<I>() : providedTypeName;
}
+
+ /**
+ * @brief Splits a string using the provided delim.
+ *
+ * Also trims the entries from whitespaces.
+ * @param str The string to split
+ * @param delimiter The delimiter to use (default ",")
+ */
+ inline std::vector<std::string> split(const std::string& str, const std::string& delimiter = ",") {
+ std::vector<std::string> result{};
+ std::string delimiters = delimiter + " \t";
+ size_t found;
+ size_t pos = 0;
+ while ((found = str.find_first_not_of(delimiters, pos)) != std::string::npos) {
+ pos = str.find_first_of(", ", found);
+ result.emplace_back(str.substr(found, pos - found));
+ }
+ return result;
+ }
}
#undef CELIX_RTTI_ENABLED
\ No newline at end of file