Added and integrated necessary D-Bus Mainloop Context
[profile/ivi/common-api-dbus-runtime.git] / src / CommonAPI / DBus / DBusFactory.cpp
1 /* Copyright (C) 2013 BMW Group
2  * Author: Manfred Bathelt (manfred.bathelt@bmw.de)
3  * Author: Juergen Gehring (juergen.gehring@bmw.de)
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7
8 #include "DBusProxy.h"
9 #include "DBusConnection.h"
10 #include "DBusFactory.h"
11 #include "DBusAddressTranslator.h"
12 #include "DBusServiceRegistry.h"
13 #include "DBusUtils.h"
14
15 #include <algorithm>
16 #include <cassert>
17 #include <sstream>
18 #include <unordered_map>
19 #include <vector>
20
21 namespace CommonAPI {
22 namespace DBus {
23
24
25 std::unordered_map<std::string, DBusProxyFactoryFunction>* registeredProxyFactoryFunctions_;
26 std::unordered_map<std::string, DBusAdapterFactoryFunction>* registeredAdapterFactoryFunctions_;
27
28
29 void DBusFactory::registerProxyFactoryMethod(std::string interfaceName, DBusProxyFactoryFunction proxyFactoryMethod) {
30     if(!registeredProxyFactoryFunctions_) {
31         registeredProxyFactoryFunctions_ = new std::unordered_map<std::string, DBusProxyFactoryFunction>();
32     }
33     registeredProxyFactoryFunctions_->insert({interfaceName, proxyFactoryMethod});
34 }
35
36 void DBusFactory::registerAdapterFactoryMethod(std::string interfaceName, DBusAdapterFactoryFunction adapterFactoryMethod) {
37     if(!registeredAdapterFactoryFunctions_) {
38         registeredAdapterFactoryFunctions_ = new std::unordered_map<std::string, DBusAdapterFactoryFunction>();
39     }
40     registeredAdapterFactoryFunctions_->insert({interfaceName, adapterFactoryMethod});
41 }
42
43
44 DBusFactory::DBusFactory(std::shared_ptr<Runtime> runtime, const MiddlewareInfo* middlewareInfo, std::shared_ptr<MainLoopContext> mainLoopContext) :
45                 CommonAPI::Factory(runtime, middlewareInfo),
46                 dbusConnection_(CommonAPI::DBus::DBusConnection::getSessionBus()),
47                 acquiredConnectionName_(""),
48                 mainLoopContext_(mainLoopContext) {
49     bool startDispatchThread = !mainLoopContext_;
50     dbusConnection_->connect(startDispatchThread);
51     if(mainLoopContext_) {
52         dbusConnection_->attachMainLoopContext(mainLoopContext);
53     }
54 }
55
56
57 DBusFactory::~DBusFactory() {
58 }
59
60
61 std::vector<std::string> DBusFactory::getAvailableServiceInstances(const std::string& serviceName,
62                                                                    const std::string& domainName) {
63     return dbusConnection_->getDBusServiceRegistry()->getAvailableServiceInstances(serviceName, domainName);
64 }
65
66
67 bool DBusFactory::isServiceInstanceAlive(const std::string& serviceAddress) {
68     std::vector<std::string> parts = split(serviceAddress, ':');
69     assert(parts[0] == "local");
70
71     std::string interfaceName;
72     std::string connectionName;
73     std::string objectPath;
74     DBusAddressTranslator::getInstance().searchForDBusAddress(serviceAddress, interfaceName, connectionName, objectPath);
75
76     return dbusConnection_->getDBusServiceRegistry()->isServiceInstanceAlive(interfaceName, connectionName, objectPath);
77 }
78
79
80 bool DBusFactory::isServiceInstanceAlive(const std::string& participantId,
81                                          const std::string& serviceName,
82                                          const std::string& domainName) {
83     std::string serviceAddress = domainName + ":" + serviceName + ":" + participantId;
84     return isServiceInstanceAlive(serviceAddress);
85 }
86
87
88 std::shared_ptr<Proxy> DBusFactory::createProxy(const char* interfaceId,
89                                                 const std::string& participantId,
90                                                 const std::string& serviceName,
91                                                 const std::string& domain) {
92     std::string commonApiAddress = domain + ":" + serviceName + ":" + participantId;
93
94     std::string interfaceName;
95     std::string connectionName;
96     std::string objectPath;
97
98     DBusAddressTranslator::getInstance().searchForDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
99
100     if(!registeredProxyFactoryFunctions_) {
101         registeredProxyFactoryFunctions_ = new std::unordered_map<std::string, DBusProxyFactoryFunction> {};
102     }
103
104     for (auto it = registeredProxyFactoryFunctions_->begin(); it != registeredProxyFactoryFunctions_->end(); ++it) {
105         if(it->first == interfaceId) {
106             return (it->second)(commonApiAddress, interfaceName, connectionName, objectPath, dbusConnection_);
107         }
108     }
109
110     return NULL;
111 }
112
113 bool DBusFactory::registerAdapter(std::shared_ptr<StubBase> stubBase,
114                                                                   const char* interfaceId,
115                                                                   const std::string& participantId,
116                                                                   const std::string& serviceName,
117                                                                   const std::string& domain) {
118     assert(dbusConnection_->isConnected());
119
120     std::string commonApiAddress = domain + ":" + serviceName + ":" + participantId;
121
122     std::string interfaceName;
123     std::string connectionName;
124     std::string objectPath;
125
126     DBusAddressTranslator::getInstance().searchForDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
127
128     if(acquiredConnectionName_ == "") {
129         bool isServiceNameAcquired = dbusConnection_->requestServiceNameAndBlock(connectionName);
130         if(!isServiceNameAcquired) {
131             return false;
132         }
133         acquiredConnectionName_ = connectionName;
134     } else if (acquiredConnectionName_ != connectionName) {
135         return false;
136     }
137
138     if(!registeredAdapterFactoryFunctions_) {
139         registeredAdapterFactoryFunctions_ = new std::unordered_map<std::string, DBusAdapterFactoryFunction> {};
140     }
141
142     auto foundFunction = registeredAdapterFactoryFunctions_->find(interfaceId);
143     if(foundFunction != registeredAdapterFactoryFunctions_->end()) {
144         std::shared_ptr<DBusStubAdapter> dbusStubAdapter =  (foundFunction->second)(commonApiAddress, interfaceName, connectionName, objectPath, dbusConnection_, stubBase);
145         if(!dbusStubAdapter) {
146             return false;
147         }
148         if(registeredServices_.insert( {std::move(commonApiAddress), dbusStubAdapter} ).second) {
149             dbusStubAdapter->init();
150             return true;
151         }
152     }
153
154         return false;
155 }
156
157 bool DBusFactory::unregisterService(const std::string& participantId, const std::string& serviceName, const std::string& domain) {
158     std::string commonApiAddress = domain + ":" + serviceName + ":" + participantId;
159         auto foundStubAdapter = registeredServices_.find(commonApiAddress);
160         if(foundStubAdapter != registeredServices_.end()) {
161                 std::shared_ptr<DBusStubAdapter> stubAdapter = foundStubAdapter->second;
162                 stubAdapter->deinit();
163                 return registeredServices_.erase(commonApiAddress);
164         }
165         return false;
166 }
167
168
169 } // namespace DBus
170 } // namespace CommonAPI