Integrated the DBusServicePublisher to manage services and added an
[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 #include "DBusServicePublisher.h"
15
16 #include <algorithm>
17 #include <cassert>
18 #include <sstream>
19 #include <unordered_map>
20 #include <vector>
21
22 namespace CommonAPI {
23 namespace DBus {
24
25
26 std::unordered_map<std::string, DBusProxyFactoryFunction>* registeredProxyFactoryFunctions_;
27 std::unordered_map<std::string, DBusAdapterFactoryFunction>* registeredAdapterFactoryFunctions_;
28
29
30 void DBusFactory::registerProxyFactoryMethod(std::string interfaceName, DBusProxyFactoryFunction proxyFactoryMethod) {
31     if(!registeredProxyFactoryFunctions_) {
32         registeredProxyFactoryFunctions_ = new std::unordered_map<std::string, DBusProxyFactoryFunction>();
33     }
34     registeredProxyFactoryFunctions_->insert({interfaceName, proxyFactoryMethod});
35 }
36
37 void DBusFactory::registerAdapterFactoryMethod(std::string interfaceName, DBusAdapterFactoryFunction adapterFactoryMethod) {
38     if(!registeredAdapterFactoryFunctions_) {
39         registeredAdapterFactoryFunctions_ = new std::unordered_map<std::string, DBusAdapterFactoryFunction>();
40     }
41     registeredAdapterFactoryFunctions_->insert({interfaceName, adapterFactoryMethod});
42 }
43
44
45 DBusFactory::DBusFactory(std::shared_ptr<Runtime> runtime, const MiddlewareInfo* middlewareInfo, std::shared_ptr<MainLoopContext> mainLoopContext) :
46                 CommonAPI::Factory(runtime, middlewareInfo),
47                 dbusConnection_(CommonAPI::DBus::DBusConnection::getSessionBus()),
48                 acquiredConnectionName_(""),
49                 mainLoopContext_(mainLoopContext) {
50     bool startDispatchThread = !mainLoopContext_;
51     dbusConnection_->connect(startDispatchThread);
52     if(mainLoopContext_) {
53         dbusConnection_->attachMainLoopContext(mainLoopContext);
54     }
55 }
56
57
58 DBusFactory::~DBusFactory() {
59 }
60
61
62 std::vector<std::string> DBusFactory::getAvailableServiceInstances(const std::string& serviceName,
63                                                                    const std::string& domainName) {
64     return dbusConnection_->getDBusServiceRegistry()->getAvailableServiceInstances(serviceName, domainName);
65 }
66
67
68 void DBusFactory::getAvailableServiceInstancesAsync(Factory::GetAvailableServiceInstancesCallback callback, const std::string& serviceName, const std::string& serviceDomainName) {
69     dbusConnection_->getDBusServiceRegistry()->getAvailableServiceInstancesAsync(callback, serviceName, serviceDomainName);
70 }
71
72
73 bool DBusFactory::isServiceInstanceAlive(const std::string& serviceAddress) {
74     std::vector<std::string> parts = split(serviceAddress, ':');
75     assert(parts[0] == "local");
76
77     std::string interfaceName;
78     std::string connectionName;
79     std::string objectPath;
80     DBusAddressTranslator::getInstance().searchForDBusAddress(serviceAddress, interfaceName, connectionName, objectPath);
81
82     return dbusConnection_->getDBusServiceRegistry()->isServiceInstanceAlive(interfaceName, connectionName, objectPath);
83 }
84
85
86 bool DBusFactory::isServiceInstanceAlive(const std::string& participantId,
87                                          const std::string& serviceName,
88                                          const std::string& domainName) {
89     std::string serviceAddress = domainName + ":" + serviceName + ":" + participantId;
90     return isServiceInstanceAlive(serviceAddress);
91 }
92
93
94 SubscriptionStatus DBusFactory::isServiceInstanceAliveCallbackThunk(Factory::IsServiceInstanceAliveCallback callback, const AvailabilityStatus& status) {
95     callback(status == AvailabilityStatus::AVAILABLE);
96     return SubscriptionStatus::CANCEL;
97 }
98
99 void DBusFactory::isServiceInstanceAliveAsync(Factory::IsServiceInstanceAliveCallback callback, const std::string& serviceAddress) {
100     std::string interfaceName;
101     std::string connectionName;
102     std::string objectPath;
103
104     DBusAddressTranslator::getInstance().searchForDBusAddress(serviceAddress, interfaceName, connectionName, objectPath);
105
106     dbusConnection_->getDBusServiceRegistry()->subscribeAvailabilityListener(
107                     serviceAddress,
108                     std::bind(&DBusFactory::isServiceInstanceAliveCallbackThunk,
109                               this,
110                               callback,
111                               std::placeholders::_1)
112     );
113 }
114
115 void DBusFactory::isServiceInstanceAliveAsync(Factory::IsServiceInstanceAliveCallback callback, const std::string& serviceInstanceID, const std::string& serviceName, const std::string& serviceDomainName) {
116     std::string commonApiAddress = serviceDomainName + ":" + serviceName + ":" + serviceInstanceID;
117     isServiceInstanceAliveAsync(callback, commonApiAddress);
118 }
119
120
121 std::shared_ptr<Proxy> DBusFactory::createProxy(const char* interfaceId,
122                                                 const std::string& participantId,
123                                                 const std::string& serviceName,
124                                                 const std::string& domain) {
125     std::string commonApiAddress = domain + ":" + serviceName + ":" + participantId;
126
127     std::string interfaceName;
128     std::string connectionName;
129     std::string objectPath;
130
131     DBusAddressTranslator::getInstance().searchForDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
132
133     if(!registeredProxyFactoryFunctions_) {
134         registeredProxyFactoryFunctions_ = new std::unordered_map<std::string, DBusProxyFactoryFunction> {};
135     }
136
137     for (auto it = registeredProxyFactoryFunctions_->begin(); it != registeredProxyFactoryFunctions_->end(); ++it) {
138         if(it->first == interfaceId) {
139             return (it->second)(commonApiAddress, interfaceName, connectionName, objectPath, dbusConnection_);
140         }
141     }
142
143     return NULL;
144 }
145
146 bool DBusFactory::registerAdapter(std::shared_ptr<StubBase> stubBase,
147                                                                   const char* interfaceId,
148                                                                   const std::string& participantId,
149                                                                   const std::string& serviceName,
150                                                                   const std::string& domain) {
151     assert(dbusConnection_->isConnected());
152
153     std::string commonApiAddress = domain + ":" + serviceName + ":" + participantId;
154
155     std::string interfaceName;
156     std::string connectionName;
157     std::string objectPath;
158
159     DBusAddressTranslator::getInstance().searchForDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
160
161     if(acquiredConnectionName_ == "") {
162         bool isServiceNameAcquired = dbusConnection_->requestServiceNameAndBlock(connectionName);
163         if(!isServiceNameAcquired) {
164             return false;
165         }
166         acquiredConnectionName_ = connectionName;
167     } else if (acquiredConnectionName_ != connectionName) {
168         return false;
169     }
170
171     if(!registeredAdapterFactoryFunctions_) {
172         registeredAdapterFactoryFunctions_ = new std::unordered_map<std::string, DBusAdapterFactoryFunction> {};
173     }
174
175     auto foundFunction = registeredAdapterFactoryFunctions_->find(interfaceId);
176     if(foundFunction != registeredAdapterFactoryFunctions_->end()) {
177         std::shared_ptr<DBusStubAdapter> dbusStubAdapter = (foundFunction->second)(commonApiAddress, interfaceName, connectionName, objectPath, dbusConnection_, stubBase);
178         if(!dbusStubAdapter) {
179             return false;
180         }
181         if(DBusServicePublisher::getInstance()->registerService(commonApiAddress, dbusStubAdapter)) {
182             dbusStubAdapter->init();
183             return true;
184         }
185     }
186
187         return false;
188 }
189
190 bool DBusFactory::unregisterService(const std::string& participantId, const std::string& serviceName, const std::string& domain) {
191     std::string serviceAddress(domain + ":" + serviceName + ":" + participantId);
192     return DBusServicePublisher::getInstance()->unregisterService(serviceAddress);
193 }
194
195
196 } // namespace DBus
197 } // namespace CommonAPI