predefined service support in config file
[profile/ivi/common-api-dbus-runtime.git] / src / CommonAPI / DBus / DBusAddressTranslator.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
9 #include "DBusAddressTranslator.h"
10 #include "DBusUtils.h"
11
12 #include <unordered_set>
13 #include <string.h>
14 #include <iostream>
15 #include <fstream>
16 #include <cassert>
17
18
19 namespace CommonAPI {
20 namespace DBus {
21
22
23 enum class TypeEnum {
24     DBUS_CONNECTION, DBUS_OBJECT, DBUS_INTERFACE, DBUS_PREDEFINED
25 };
26
27 static const std::unordered_map<std::string, TypeEnum> allowedValueTypes = {
28                 {"dbus_connection", TypeEnum::DBUS_CONNECTION},
29                 {"dbus_object", TypeEnum::DBUS_OBJECT},
30                 {"dbus_interface", TypeEnum::DBUS_INTERFACE},
31                 {"dbus_predefined", TypeEnum::DBUS_PREDEFINED}
32 };
33
34
35 DBusAddressTranslator::DBusAddressTranslator() {}
36
37
38 void DBusAddressTranslator::init() {
39     std::string fqnOfConfigFile = getCurrentBinaryFileFQN();
40     fqnOfConfigFile += DBUS_CONFIG_SUFFIX;
41
42     std::ifstream addressConfigFile;
43     addressConfigFile.open(fqnOfConfigFile.c_str());
44
45     if(addressConfigFile.is_open()) {
46         readConfigFile(addressConfigFile);
47         addressConfigFile.close();
48     }
49
50     addressConfigFile.clear();
51     std::vector<std::string> splittedConfigFQN = split(fqnOfConfigFile, '/');
52     std::string globalConfigFQN = DBUS_GLOBAL_CONFIG_ROOT + splittedConfigFQN.at(splittedConfigFQN.size() - 1);
53     addressConfigFile.open(globalConfigFQN);
54     if(addressConfigFile.is_open()) {
55         readConfigFile(addressConfigFile);
56         addressConfigFile.close();
57     }
58
59     addressConfigFile.clear();
60     addressConfigFile.open(DBUS_GLOBAL_CONFIG_FQN);
61     if(addressConfigFile.is_open()) {
62         readConfigFile(addressConfigFile);
63         addressConfigFile.close();
64     }
65 }
66
67
68 inline void readValue(std::string& readLine, DBusServiceAddress& dbusServiceAddress) {
69     std::stringstream readStream(readLine);
70
71     std::string paramName;
72     std::string paramValue;
73
74     getline(readStream, paramName, '=');
75
76     auto typeEntry = allowedValueTypes.find(paramName);
77     if(typeEntry != allowedValueTypes.end()) {
78         getline(readStream, paramValue);
79         switch(typeEntry->second) {
80             case TypeEnum::DBUS_CONNECTION:
81                 std::get<0>(dbusServiceAddress) = paramValue;
82                 break;
83             case TypeEnum::DBUS_OBJECT:
84                 std::get<1>(dbusServiceAddress) = paramValue;
85                 break;
86             case TypeEnum::DBUS_INTERFACE:
87                 std::get<2>(dbusServiceAddress) = paramValue;
88                 break;
89             case TypeEnum::DBUS_PREDEFINED:
90                 std::get<3>(dbusServiceAddress) = paramValue == "true" ? true : false;
91                 break;
92         }
93     }
94 }
95
96
97 inline void reset(DBusServiceAddress& dbusServiceAddress) {
98     std::get<0>(dbusServiceAddress) = "";
99     std::get<1>(dbusServiceAddress) = "";
100     std::get<2>(dbusServiceAddress) = "";
101     std::get<3>(dbusServiceAddress) = false;
102 }
103
104
105 void DBusAddressTranslator::readConfigFile(std::ifstream& addressConfigFile) {
106     std::string currentlyParsedCommonApiAddress;
107     DBusServiceAddress dbusServiceAddress;
108     reset(dbusServiceAddress);
109
110     bool newAddressFound = false;
111
112     while (addressConfigFile.good()) {
113         std::string readLine;
114         getline(addressConfigFile, readLine);
115         const size_t readLineLength = readLine.length();
116
117         if (readLine[0] == '[' && readLine[readLineLength - 1] == ']') {
118             if (newAddressFound) {
119                 fillUndefinedValues(dbusServiceAddress, currentlyParsedCommonApiAddress);
120                 knownDBusAddresses.insert( {currentlyParsedCommonApiAddress, dbusServiceAddress});
121                 knownCommonAddresses.insert( {dbusServiceAddress, currentlyParsedCommonApiAddress});
122             }
123             reset(dbusServiceAddress);
124             currentlyParsedCommonApiAddress = readLine.substr(1, readLineLength - 2);
125             newAddressFound = knownDBusAddresses.find(currentlyParsedCommonApiAddress) == knownDBusAddresses.end();
126
127         } else if (newAddressFound) {
128             readValue(readLine, dbusServiceAddress);
129         }
130     }
131     if(newAddressFound) {
132         fillUndefinedValues(dbusServiceAddress, currentlyParsedCommonApiAddress);
133         knownDBusAddresses.insert( {currentlyParsedCommonApiAddress, dbusServiceAddress});
134         knownCommonAddresses.insert( {dbusServiceAddress, currentlyParsedCommonApiAddress});
135     }
136 }
137
138
139 void DBusAddressTranslator::fillUndefinedValues(DBusServiceAddress& dbusServiceAddress, const std::string& commonApiAddress) const {
140     std::string connectionName;
141     std::string objectPath;
142     std::string interfaceName;
143
144     findFallbackDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
145
146     std::get<0>(dbusServiceAddress) = std::get<0>(dbusServiceAddress) == "" ? connectionName : std::get<0>(dbusServiceAddress);
147     std::get<1>(dbusServiceAddress) = std::get<1>(dbusServiceAddress) == "" ? objectPath : std::get<1>(dbusServiceAddress);
148     std::get<2>(dbusServiceAddress) = std::get<2>(dbusServiceAddress) == "" ? interfaceName : std::get<2>(dbusServiceAddress);
149 }
150
151
152 DBusAddressTranslator& DBusAddressTranslator::getInstance() {
153     static DBusAddressTranslator* dbusNameService_;
154     if(!dbusNameService_) {
155         dbusNameService_ = new DBusAddressTranslator();
156         dbusNameService_->init();
157     }
158     return *dbusNameService_;
159 }
160
161
162 void DBusAddressTranslator::searchForDBusAddress(const std::string& commonApiAddress,
163                                                  std::string& interfaceName,
164                                                  std::string& connectionName,
165                                                  std::string& objectPath) {
166
167     const auto& foundAddressMapping = knownDBusAddresses.find(commonApiAddress);
168
169     if(foundAddressMapping != knownDBusAddresses.end()) {
170         connectionName = std::get<0>(foundAddressMapping->second);
171         objectPath = std::get<1>(foundAddressMapping->second);
172         interfaceName = std::get<2>(foundAddressMapping->second);
173     } else {
174         findFallbackDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
175         knownDBusAddresses.insert( {commonApiAddress, std::make_tuple(connectionName, objectPath, interfaceName, false) } );
176     }
177 }
178
179 void DBusAddressTranslator::searchForCommonAddress(const std::string& interfaceName,
180                                                    const std::string& connectionName,
181                                                    const std::string& objectPath,
182                                                    std::string& commonApiAddress) {
183
184     DBusServiceAddress dbusAddress(connectionName, objectPath, interfaceName, false);
185
186     const auto& foundAddressMapping = knownCommonAddresses.find(dbusAddress);
187     if (foundAddressMapping != knownCommonAddresses.end()) {
188         commonApiAddress = foundAddressMapping->second;
189     } else {
190         findFallbackCommonAddress(commonApiAddress, interfaceName, connectionName, objectPath);
191         knownCommonAddresses.insert( {std::move(dbusAddress), commonApiAddress} );
192     }
193 }
194
195 void DBusAddressTranslator::getPredefinedInstances(const std::string& connectionName,
196                                    std::vector<DBusServiceAddress>& instances) {
197     instances.clear();
198     auto dbusAddress = knownDBusAddresses.begin();
199     while (dbusAddress != knownDBusAddresses.end()) {
200         if (connectionName == std::get<0>(dbusAddress->second) && true == std::get<3>(dbusAddress->second)) {
201             instances.push_back(dbusAddress->second);
202         }
203         dbusAddress++;
204     }
205 }
206
207 void DBusAddressTranslator::findFallbackDBusAddress(const std::string& commonApiAddress,
208                                                     std::string& interfaceName,
209                                                     std::string& connectionName,
210                                                     std::string& objectPath) const {
211     std::vector<std::string> parts = split(commonApiAddress, ':');
212     interfaceName = parts[1];
213     connectionName = parts[2];
214     objectPath = '/' + parts[2];
215     std::replace(objectPath.begin(), objectPath.end(), '.', '/');
216 }
217
218 void DBusAddressTranslator::findFallbackCommonAddress(std::string& commonApiAddress,
219                                                       const std::string& interfaceName,
220                                                       const std::string& connectionName,
221                                                       const std::string& objectPath) const {
222     commonApiAddress = "local:" + interfaceName + ":" + connectionName;
223 }
224
225
226 }// namespace DBus
227 }// namespace CommonAPI