summaryrefslogtreecommitdiff
path: root/src/CommonAPI/DBus/DBusFactory.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/CommonAPI/DBus/DBusFactory.cpp')
-rw-r--r--src/CommonAPI/DBus/DBusFactory.cpp459
1 files changed, 294 insertions, 165 deletions
diff --git a/src/CommonAPI/DBus/DBusFactory.cpp b/src/CommonAPI/DBus/DBusFactory.cpp
index c0b2cdd..4f7e0b9 100644
--- a/src/CommonAPI/DBus/DBusFactory.cpp
+++ b/src/CommonAPI/DBus/DBusFactory.cpp
@@ -1,217 +1,346 @@
-/* Copyright (C) 2013 BMW Group
- * Author: Manfred Bathelt (manfred.bathelt@bmw.de)
- * Author: Juergen Gehring (juergen.gehring@bmw.de)
- * This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-#include "DBusProxy.h"
-#include "DBusConnection.h"
-#include "DBusFactory.h"
-#include "DBusServiceRegistry.h"
-#include "DBusUtils.h"
-#include "DBusServicePublisher.h"
-
-#include <algorithm>
-#include <cassert>
+// Copyright (C) 2013-2015 Bayerische Motoren Werke Aktiengesellschaft (BMW AG)
+// This Source Code Form is subject to the terms of the Mozilla Public
+// License, v. 2.0. If a copy of the MPL was not distributed with this
+// file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+#include <iostream>
#include <sstream>
-#include <unordered_map>
-#include <vector>
+
+#include <CommonAPI/Logger.hpp>
+#include <CommonAPI/Runtime.hpp>
+#include <CommonAPI/DBus/DBusAddressTranslator.hpp>
+#include <CommonAPI/DBus/DBusConnection.hpp>
+#include <CommonAPI/DBus/DBusFactory.hpp>
+#include <CommonAPI/DBus/DBusProxy.hpp>
+#include <CommonAPI/DBus/DBusStubAdapter.hpp>
namespace CommonAPI {
namespace DBus {
-
-std::unordered_map<std::string, DBusProxyFactoryFunction>* registeredProxyFactoryFunctions_;
-std::unordered_map<std::string, DBusAdapterFactoryFunction>* registeredAdapterFactoryFunctions_;
-
-
-void DBusFactory::registerProxyFactoryMethod(std::string interfaceName, DBusProxyFactoryFunction proxyFactoryMethod) {
- if(!registeredProxyFactoryFunctions_) {
- registeredProxyFactoryFunctions_ = new std::unordered_map<std::string, DBusProxyFactoryFunction>();
- }
- registeredProxyFactoryFunctions_->insert({interfaceName, proxyFactoryMethod});
+INITIALIZER(FactoryInit) {
+ Runtime::get()->registerFactory("dbus", Factory::get());
}
-void DBusFactory::registerAdapterFactoryMethod(std::string interfaceName, DBusAdapterFactoryFunction adapterFactoryMethod) {
- if(!registeredAdapterFactoryFunctions_) {
- registeredAdapterFactoryFunctions_ = new std::unordered_map<std::string, DBusAdapterFactoryFunction>();
- }
- registeredAdapterFactoryFunctions_->insert({interfaceName, adapterFactoryMethod});
+std::shared_ptr<CommonAPI::DBus::Factory>
+Factory::get() {
+ static std::shared_ptr<Factory> theFactory = std::make_shared<Factory>();
+ return theFactory;
}
-
-DBusFactory::DBusFactory(std::shared_ptr<Runtime> runtime,
- const MiddlewareInfo* middlewareInfo,
- std::shared_ptr<MainLoopContext> mainLoopContext,
- const DBusFactoryConfig& DBusFactoryConfig) :
- CommonAPI::Factory(runtime, middlewareInfo),
- mainLoopContext_(mainLoopContext),
- DBusFactoryConfig_(DBusFactoryConfig){
-
- dbusConnection_ = CommonAPI::DBus::DBusConnection::getBus(DBusFactoryConfig_.busType_);
- bool startDispatchThread = !mainLoopContext_;
- dbusConnection_->connect(startDispatchThread);
- if (mainLoopContext_) {
- dbusConnection_->attachMainLoopContext(mainLoopContext_);
- }
+Factory::Factory()
+ : defaultBusType_(DBusType_t::SESSION) {
}
-
-DBusFactory::~DBusFactory() {
+Factory::~Factory() {
}
-
-std::vector<std::string> DBusFactory::getAvailableServiceInstances(const std::string& serviceName,
- const std::string& domainName) {
- return dbusConnection_->getDBusServiceRegistry()->getAvailableServiceInstances(serviceName, domainName);
+void
+Factory::registerProxyCreateMethod(
+ const std::string &_interface, ProxyCreateFunction _function) {
+ proxyCreateFunctions_[_interface] = _function;
}
-
-void DBusFactory::getAvailableServiceInstancesAsync(Factory::GetAvailableServiceInstancesCallback callback, const std::string& serviceName, const std::string& serviceDomainName) {
- dbusConnection_->getDBusServiceRegistry()->getAvailableServiceInstancesAsync(callback, serviceName, serviceDomainName);
+void
+Factory::registerStubAdapterCreateMethod(
+ const std::string &_interface, StubAdapterCreateFunction _function) {
+ stubAdapterCreateFunctions_[_interface] = _function;
}
-
-bool DBusFactory::isServiceInstanceAlive(const std::string& serviceAddress) {
- std::vector<std::string> parts = split(serviceAddress, ':');
- assert(parts[0] == "local");
-
- std::string interfaceName;
- std::string connectionName;
- std::string objectPath;
- DBusAddressTranslator::getInstance().searchForDBusAddress(serviceAddress, interfaceName, connectionName, objectPath);
-
- return dbusConnection_->getDBusServiceRegistry()->isServiceInstanceAlive(interfaceName, connectionName, objectPath);
+std::shared_ptr<Proxy>
+Factory::createProxy(
+ const std::string &_domain, const std::string &_interface, const std::string &_instance,
+ const ConnectionId_t &_connectionId) {
+ auto proxyCreateFunctionsIterator = proxyCreateFunctions_.find(_interface);
+ if (proxyCreateFunctionsIterator != proxyCreateFunctions_.end()) {
+ CommonAPI::Address address(_domain, _interface, _instance);
+ DBusAddress dbusAddress;
+
+ if (DBusAddressTranslator::get()->translate(address, dbusAddress)) {
+ std::shared_ptr<DBusProxy> proxy
+ = proxyCreateFunctionsIterator->second(dbusAddress, getConnection(_connectionId));
+ if (proxy)
+ proxy->init();
+ return proxy;
+ }
+ }
+ return nullptr;
}
-
-bool DBusFactory::isServiceInstanceAlive(const std::string& participantId,
- const std::string& serviceName,
- const std::string& domainName) {
- std::string serviceAddress = domainName + ":" + serviceName + ":" + participantId;
- return isServiceInstanceAlive(serviceAddress);
+std::shared_ptr<Proxy>
+Factory::createProxy(
+ const std::string &_domain, const std::string &_interface, const std::string &_instance,
+ std::shared_ptr<MainLoopContext> _context) {
+
+ auto proxyCreateFunctionsIterator = proxyCreateFunctions_.find(_interface);
+ if (proxyCreateFunctionsIterator != proxyCreateFunctions_.end()) {
+ CommonAPI::Address address(_domain, _interface, _instance);
+ DBusAddress dbusAddress;
+
+ if (DBusAddressTranslator::get()->translate(address, dbusAddress)) {
+ std::shared_ptr<DBusProxy> proxy
+ = proxyCreateFunctionsIterator->second(dbusAddress, getConnection(_context));
+ if (proxy)
+ proxy->init();
+ return proxy;
+ }
+ }
+
+ return nullptr;
}
-
-SubscriptionStatus DBusFactory::isServiceInstanceAliveCallbackThunk(Factory::IsServiceInstanceAliveCallback callback, const AvailabilityStatus& status, std::shared_ptr<DBusServiceRegistry> serviceRegistry) {
- callback(status == AvailabilityStatus::AVAILABLE);
- return SubscriptionStatus::CANCEL;
+bool
+Factory::registerStub(
+ const std::string &_domain, const std::string &_interface, const std::string &_instance,
+ std::shared_ptr<StubBase> _stub, const ConnectionId_t &_connectionId) {
+ auto stubAdapterCreateFunctionsIterator = stubAdapterCreateFunctions_.find(_interface);
+ if (stubAdapterCreateFunctionsIterator != stubAdapterCreateFunctions_.end()) {
+ CommonAPI::Address address(_domain, _interface, _instance);
+ DBusAddress dbusAddress;
+ if (DBusAddressTranslator::get()->translate(address, dbusAddress)) {
+ std::shared_ptr<DBusStubAdapter> adapter
+ = stubAdapterCreateFunctionsIterator->second(dbusAddress, getConnection(_connectionId), _stub);
+ if (adapter) {
+ adapter->init(adapter);
+ return registerStubAdapter(adapter);
+ }
+ }
+ }
+
+ return false;
}
-void DBusFactory::isServiceInstanceAliveAsync(Factory::IsServiceInstanceAliveCallback callback, const std::string& serviceAddress) {
- std::string interfaceName;
- std::string connectionName;
- std::string objectPath;
-
- DBusAddressTranslator::getInstance().searchForDBusAddress(serviceAddress, interfaceName, connectionName, objectPath);
-
- std::shared_ptr<DBusServiceRegistry> serviceRegistry = dbusConnection_->getDBusServiceRegistry();
-
- serviceRegistry->subscribeAvailabilityListener(
- serviceAddress,
- std::bind(&DBusFactory::isServiceInstanceAliveCallbackThunk,
- this,
- callback,
- std::placeholders::_1,
- serviceRegistry)
- );
+bool
+Factory::registerStub(
+ const std::string &_domain, const std::string &_interface, const std::string &_instance,
+ std::shared_ptr<StubBase> _stub, std::shared_ptr<MainLoopContext> _context) {
+ auto stubAdapterCreateFunctionsIterator = stubAdapterCreateFunctions_.find(_interface);
+ if (stubAdapterCreateFunctionsIterator != stubAdapterCreateFunctions_.end()) {
+ CommonAPI::Address address(_domain, _interface, _instance);
+ DBusAddress dbusAddress;
+ if (DBusAddressTranslator::get()->translate(address, dbusAddress)) {
+ std::shared_ptr<DBusStubAdapter> adapter
+ = stubAdapterCreateFunctionsIterator->second(dbusAddress, getConnection(_context), _stub);
+ if (adapter) {
+ adapter->init(adapter);
+ return registerStubAdapter(adapter);
+ }
+ }
+ }
+ return false;
}
-std::shared_ptr<CommonAPI::DBus::DBusConnection> DBusFactory::getDbusConnection() {
- return dbusConnection_;
+bool
+Factory::unregisterStub(const std::string &_domain, const std::string &_interface, const std::string &_instance) {
+ CommonAPI::Address address(_domain, _interface, _instance);
+ const auto &adapterResult = services_.find(address.getAddress());
+ if (adapterResult != services_.end()) {
+ const auto _adapter = adapterResult->second;
+ const auto &connection = _adapter->getDBusConnection();
+ const auto objectManager = connection->getDBusObjectManager();
+
+ if (!objectManager->unregisterDBusStubAdapter(_adapter)) {
+ return false;
+ }
+
+ if (!connection->releaseServiceName(_adapter->getDBusAddress().getService())) {
+ return false;
+ }
+
+ if (!unregisterStubAdapter(_adapter)) {
+ return false;
+ }
+
+ services_.erase(adapterResult->first);
+
+ return true;
+ }
+
+ return false;
}
-void DBusFactory::isServiceInstanceAliveAsync(Factory::IsServiceInstanceAliveCallback callback,
- const std::string& serviceInstanceID,
- const std::string& serviceName,
- const std::string& serviceDomainName) {
- std::string commonApiAddress = serviceDomainName + ":" + serviceName + ":" + serviceInstanceID;
- isServiceInstanceAliveAsync(callback, commonApiAddress);
+bool
+Factory::registerStubAdapter(std::shared_ptr<DBusStubAdapter> _adapter) {
+ CommonAPI::Address address;
+ DBusAddress dbusAddress = _adapter->getDBusAddress();
+ if (DBusAddressTranslator::get()->translate(dbusAddress, address)) {
+ const auto &insertResult = services_.insert( { address.getAddress(), _adapter } );
+
+ const auto &connection = _adapter->getDBusConnection();
+ const auto objectManager = connection->getDBusObjectManager();
+ if (!objectManager->registerDBusStubAdapter(_adapter)) {
+ services_.erase(insertResult.first);
+ return false;
+ }
+
+ const bool isServiceNameAcquired
+ = connection->requestServiceNameAndBlock(dbusAddress.getService());
+ if (!isServiceNameAcquired) {
+ (void)objectManager->unregisterDBusStubAdapter(_adapter);
+ services_.erase(insertResult.first);
+ return false;
+ }
+
+ std::shared_ptr<DBusObjectManagerStub> root
+ = connection->getDBusObjectManager()->getRootDBusObjectManagerStub();
+ if (!root->exportManagedDBusStubAdapter(_adapter)) {
+ (void)unregisterManagedService(address.getAddress());
+ return false;
+ }
+
+ return true;
+ }
+
+ return false;
}
+bool
+Factory::unregisterStubAdapter(std::shared_ptr<DBusStubAdapter> _adapter) {
+ CommonAPI::Address address;
+ DBusAddress dbusAddress = _adapter->getDBusAddress();
+ if (DBusAddressTranslator::get()->translate(dbusAddress, address)) {
+ const auto &connection = _adapter->getDBusConnection();
+
+ std::shared_ptr<DBusObjectManagerStub> root
+ = connection->getDBusObjectManager()->getRootDBusObjectManagerStub();
+ if (!root->unexportManagedDBusStubAdapter(_adapter)) {
+ //(void)unregisterManagedService(address.getAddress());
+ return false;
+ }
+
+ return true;
+ }
+ return false;
+}
-std::shared_ptr<Proxy> DBusFactory::createProxy(const char* interfaceId,
- const std::string& participantId,
- const std::string& serviceName,
- const std::string& domain) {
- std::string commonApiAddress = domain + ":" + serviceName + ":" + participantId;
-
- std::string interfaceName;
- std::string connectionName;
- std::string objectPath;
-
- DBusAddressTranslator::getInstance().searchForDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
+///////////////////////////////////////////////////////////////////////////////
+// Connections
+///////////////////////////////////////////////////////////////////////////////
+std::shared_ptr<DBusConnection>
+Factory::getConnection(const ConnectionId_t &_connectionId) {
- if(!registeredProxyFactoryFunctions_) {
- registeredProxyFactoryFunctions_ = new std::unordered_map<std::string, DBusProxyFactoryFunction> {};
- }
+ auto itsConnectionIterator = connections_.find(_connectionId);
+ if (itsConnectionIterator != connections_.end()) {
+ return itsConnectionIterator->second;
+ }
- for (auto it = registeredProxyFactoryFunctions_->begin(); it != registeredProxyFactoryFunctions_->end(); ++it) {
- if(it->first == interfaceId) {
- std::shared_ptr<DBusProxy> proxy = (it->second)(shared_from_this(), commonApiAddress, interfaceName, connectionName, objectPath, dbusConnection_);
- proxy->init();
- return proxy;
- }
- }
+ // No connection found, lets create and initialize one
+ std::shared_ptr<DBusConnection> itsConnection
+ = std::make_shared<DBusConnection>(defaultBusType_);
+ connections_.insert({ _connectionId, itsConnection });
- return NULL;
+ itsConnection->connect(true);
+ return itsConnection;
}
-std::shared_ptr<DBusStubAdapter> DBusFactory::createDBusStubAdapter(const std::shared_ptr<StubBase>& stubBase,
- const char* interfaceId,
- const std::string& participantId,
- const std::string& serviceName,
- const std::string& domain) {
- assert(dbusConnection_->isConnected());
-
- std::string commonApiAddress = domain + ":" + serviceName + ":" + participantId;
+std::shared_ptr<DBusConnection>
+Factory::getConnection(std::shared_ptr<MainLoopContext> _context) {
+ if (!_context)
+ return getConnection(DEFAULT_CONNECTION_ID);
- std::string interfaceName;
- std::string connectionName;
- std::string objectPath;
+ auto itsConnectionIterator = contextConnections_.find(_context.get());
+ if (itsConnectionIterator != contextConnections_.end()) {
+ return itsConnectionIterator->second;
+ }
- DBusAddressTranslator::getInstance().searchForDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
+ // No connection found, lets create and initialize one
+ std::shared_ptr<DBusConnection> itsConnection
+ = std::make_shared<DBusConnection>(defaultBusType_);
+ contextConnections_.insert({ _context.get(), itsConnection } );
- if (!registeredAdapterFactoryFunctions_) {
- registeredAdapterFactoryFunctions_ = new std::unordered_map<std::string, DBusAdapterFactoryFunction> {};
- }
-
- auto registeredAdapterFactoryFunctionsIter = registeredAdapterFactoryFunctions_->find(interfaceId);
- const bool hasRegisteredAdapterFactoryFunctions = (registeredAdapterFactoryFunctionsIter != registeredAdapterFactoryFunctions_->end());
- std::shared_ptr<DBusStubAdapter> dbusStubAdapter;
+ itsConnection->connect(false);
+ if (_context)
+ itsConnection->attachMainLoopContext(_context);
- if (hasRegisteredAdapterFactoryFunctions) {
- const auto& dbusAdapterFactoryFunction = registeredAdapterFactoryFunctionsIter->second;
+ return itsConnection;
+}
- dbusStubAdapter = dbusAdapterFactoryFunction(shared_from_this(), commonApiAddress, interfaceName, connectionName, objectPath, dbusConnection_, stubBase);
- dbusStubAdapter->init(dbusStubAdapter);
+///////////////////////////////////////////////////////////////////////////////
+// Service registration
+///////////////////////////////////////////////////////////////////////////////
+std::shared_ptr<DBusStubAdapter>
+Factory::getRegisteredService(const std::string &_address) {
+ auto serviceIterator = services_.find(_address);
+ if (serviceIterator != services_.end()) {
+ return serviceIterator->second;
}
+ return nullptr;
+}
- return dbusStubAdapter;
+///////////////////////////////////////////////////////////////////////////////
+// Managed Services
+///////////////////////////////////////////////////////////////////////////////
+std::shared_ptr<DBusStubAdapter>
+Factory::createDBusStubAdapter(
+ const std::shared_ptr<StubBase> &_stub,
+ const std::string &_interface,
+ const DBusAddress &_dbusAddress,
+ const std::shared_ptr<DBusProxyConnection> &_connection) {
+
+ std::shared_ptr<DBusStubAdapter> stubAdapter;
+ auto stubAdapterCreateFunctionsIterator = stubAdapterCreateFunctions_.find(_interface);
+ if (stubAdapterCreateFunctionsIterator != stubAdapterCreateFunctions_.end()) {
+ stubAdapter = stubAdapterCreateFunctionsIterator->second(
+ _dbusAddress, _connection, _stub);
+ if (stubAdapter)
+ stubAdapter->init(stubAdapter);
+ }
+ return stubAdapter;
}
-bool DBusFactory::unregisterService(const std::string& participantId, const std::string& serviceName, const std::string& domain) {
- std::string serviceAddress(domain + ":" + serviceName + ":" + participantId);
- return DBusServicePublisher::getInstance()->unregisterService(serviceAddress);
+bool
+Factory::registerManagedService(const std::shared_ptr<DBusStubAdapter> &_stubAdapter) {
+ auto itsAddress = _stubAdapter->getAddress().getAddress();
+
+ const auto &insertResult = services_.insert( { itsAddress, _stubAdapter} );
+ if (insertResult.second) {
+ const auto &connection = _stubAdapter->getDBusConnection();
+ const auto objectManager = connection->getDBusObjectManager();
+ const bool isRegistered = objectManager->registerDBusStubAdapter(_stubAdapter);
+ if (!isRegistered) {
+ services_.erase(insertResult.first);
+ return false;
+ }
+
+ const auto &serviceName = _stubAdapter->getDBusAddress().getService();
+ const bool isAcquired = connection->requestServiceNameAndBlock(serviceName);
+ if (!isAcquired) {
+ const bool isDeregistered = objectManager->unregisterDBusStubAdapter(_stubAdapter);
+ assert(isDeregistered);
+
+ services_.erase(insertResult.first);
+ }
+
+ return isAcquired;
+ }
+
+ return false;
}
-COMMONAPI_DEPRECATED bool DBusFactory::registerAdapter(std::shared_ptr<StubBase> stubBase,
- const char* interfaceId,
- const std::string& participantId,
- const std::string& serviceName,
- const std::string& domain) {
- std::shared_ptr<DBusServicePublisher> pub = std::dynamic_pointer_cast<DBusServicePublisher>(runtime_->getServicePublisher());
- return pub->registerService(
- stubBase,
- interfaceId,
- participantId,
- serviceName,
- domain,
- shared_from_this());
+bool
+Factory::unregisterManagedService(const std::string &_address) {
+ return unregisterManagedService(services_.find(_address));
}
+bool
+Factory::unregisterManagedService(const ServicesMap::iterator &iterator) {
+ if (iterator == services_.end())
+ return true;
+
+ const auto &stubAdapter = iterator->second;
+ const auto &connection = stubAdapter->getDBusConnection();
+ const auto objectManager = connection->getDBusObjectManager();
+ const auto &serviceName = stubAdapter->getDBusAddress().getService();
+
+ const bool isUnregistered
+ = objectManager->unregisterDBusStubAdapter(stubAdapter);
+ if (isUnregistered) {
+ connection->releaseServiceName(serviceName);
+ services_.erase(iterator);
+ }
+ // TODO: log error
+ return isUnregistered;
+}
} // namespace DBus
} // namespace CommonAPI