Improved coding in DBusAddressTranslator, moved statics from DBusUtils
[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
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 };
32
33
34 DBusAddressTranslator::DBusAddressTranslator() {}
35
36
37 void DBusAddressTranslator::init() {
38     std::string fqnOfConfigFile = getCurrentBinaryFileFQN();
39     fqnOfConfigFile += DBUS_CONFIG_SUFFIX;
40
41     std::ifstream addressConfigFile;
42     addressConfigFile.open(fqnOfConfigFile.c_str());
43
44     if(addressConfigFile.is_open()) {
45         readConfigFile(addressConfigFile);
46         addressConfigFile.close();
47     }
48
49     addressConfigFile.clear();
50     std::vector<std::string> splittedConfigFQN = split(fqnOfConfigFile, '/');
51     std::string globalConfigFQN = DBUS_GLOBAL_CONFIG_ROOT + splittedConfigFQN.at(splittedConfigFQN.size() - 1);
52     addressConfigFile.open(globalConfigFQN);
53     if(addressConfigFile.is_open()) {
54         readConfigFile(addressConfigFile);
55         addressConfigFile.close();
56     }
57
58     addressConfigFile.clear();
59     addressConfigFile.open(DBUS_GLOBAL_CONFIG_FQN);
60     if(addressConfigFile.is_open()) {
61         readConfigFile(addressConfigFile);
62         addressConfigFile.close();
63     }
64 }
65
66
67 inline void readValue(std::string& readLine, DBusServiceAddress& dbusServiceAddress) {
68     std::stringstream readStream(readLine);
69
70     std::string paramName;
71     std::string paramValue;
72
73     getline(readStream, paramName, '=');
74
75     auto typeEntry = allowedValueTypes.find(paramName);
76     if(typeEntry != allowedValueTypes.end()) {
77         getline(readStream, paramValue);
78         switch(typeEntry->second) {
79             case TypeEnum::DBUS_CONNECTION:
80                 std::get<0>(dbusServiceAddress) = paramValue;
81                 break;
82             case TypeEnum::DBUS_OBJECT:
83                 std::get<1>(dbusServiceAddress) = paramValue;
84                 break;
85             case TypeEnum::DBUS_INTERFACE:
86                 std::get<2>(dbusServiceAddress) = paramValue;
87                 break;
88         }
89     }
90 }
91
92
93 inline void reset(DBusServiceAddress& dbusServiceAddress) {
94     std::get<0>(dbusServiceAddress) = "";
95     std::get<1>(dbusServiceAddress) = "";
96     std::get<2>(dbusServiceAddress) = "";
97 }
98
99
100 void DBusAddressTranslator::readConfigFile(std::ifstream& addressConfigFile) {
101     std::string currentlyParsedCommonApiAddress;
102     DBusServiceAddress dbusServiceAddress;
103     reset(dbusServiceAddress);
104
105     bool newAddressFound = false;
106
107     while (addressConfigFile.good()) {
108         std::string readLine;
109         getline(addressConfigFile, readLine);
110         const size_t readLineLength = readLine.length();
111
112         if (readLine[0] == '[' && readLine[readLineLength - 1] == ']') {
113             if (newAddressFound) {
114                 fillUndefinedValues(dbusServiceAddress, currentlyParsedCommonApiAddress);
115                 knownDBusAddresses.insert( {currentlyParsedCommonApiAddress, dbusServiceAddress});
116                 knownCommonAddresses.insert( {dbusServiceAddress, currentlyParsedCommonApiAddress});
117             }
118             reset(dbusServiceAddress);
119             currentlyParsedCommonApiAddress = readLine.substr(1, readLineLength - 2);
120             newAddressFound = knownDBusAddresses.find(currentlyParsedCommonApiAddress) == knownDBusAddresses.end();
121
122         } else if (newAddressFound) {
123             readValue(readLine, dbusServiceAddress);
124         }
125     }
126     if(newAddressFound) {
127         fillUndefinedValues(dbusServiceAddress, currentlyParsedCommonApiAddress);
128         knownDBusAddresses.insert( {currentlyParsedCommonApiAddress, dbusServiceAddress});
129         knownCommonAddresses.insert( {dbusServiceAddress, currentlyParsedCommonApiAddress});
130     }
131 }
132
133
134 void DBusAddressTranslator::fillUndefinedValues(DBusServiceAddress& dbusServiceAddress, const std::string& commonApiAddress) const {
135     std::string connectionName;
136     std::string objectPath;
137     std::string interfaceName;
138
139     findFallbackDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
140
141     std::get<0>(dbusServiceAddress) = std::get<0>(dbusServiceAddress) == "" ? connectionName : std::get<0>(dbusServiceAddress);
142     std::get<1>(dbusServiceAddress) = std::get<1>(dbusServiceAddress) == "" ? objectPath : std::get<1>(dbusServiceAddress);
143     std::get<2>(dbusServiceAddress) = std::get<2>(dbusServiceAddress) == "" ? interfaceName : std::get<2>(dbusServiceAddress);
144 }
145
146
147 DBusAddressTranslator& DBusAddressTranslator::getInstance() {
148     static DBusAddressTranslator* dbusNameService_;
149     if(!dbusNameService_) {
150         dbusNameService_ = new DBusAddressTranslator();
151         dbusNameService_->init();
152     }
153     return *dbusNameService_;
154 }
155
156
157 void DBusAddressTranslator::searchForDBusAddress(const std::string& commonApiAddress,
158                                                  std::string& interfaceName,
159                                                  std::string& connectionName,
160                                                  std::string& objectPath) {
161
162     const auto& foundAddressMapping = knownDBusAddresses.find(commonApiAddress);
163
164     if(foundAddressMapping != knownDBusAddresses.end()) {
165         connectionName = std::get<0>(foundAddressMapping->second);
166         objectPath = std::get<1>(foundAddressMapping->second);
167         interfaceName = std::get<2>(foundAddressMapping->second);
168     } else {
169         findFallbackDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
170         knownDBusAddresses.insert( {commonApiAddress, std::make_tuple(connectionName, objectPath, interfaceName) } );
171     }
172 }
173
174 void DBusAddressTranslator::searchForCommonAddress(const std::string& interfaceName,
175                                                    const std::string& connectionName,
176                                                    const std::string& objectPath,
177                                                    std::string& commonApiAddress) {
178
179     DBusServiceAddress dbusAddress(connectionName, objectPath, interfaceName);
180
181     const auto& foundAddressMapping = knownCommonAddresses.find(dbusAddress);
182     if (foundAddressMapping != knownCommonAddresses.end()) {
183         commonApiAddress = foundAddressMapping->second;
184     } else {
185         findFallbackCommonAddress(commonApiAddress, interfaceName, connectionName, objectPath);
186         knownCommonAddresses.insert( {std::move(dbusAddress), commonApiAddress} );
187     }
188 }
189
190
191 void DBusAddressTranslator::findFallbackDBusAddress(const std::string& commonApiAddress,
192                                                     std::string& interfaceName,
193                                                     std::string& connectionName,
194                                                     std::string& objectPath) const {
195     std::vector<std::string> parts = split(commonApiAddress, ':');
196     interfaceName = parts[1];
197     connectionName = parts[2];
198     objectPath = '/' + parts[2];
199     std::replace(objectPath.begin(), objectPath.end(), '.', '/');
200 }
201
202 void DBusAddressTranslator::findFallbackCommonAddress(std::string& commonApiAddress,
203                                                       const std::string& interfaceName,
204                                                       const std::string& connectionName,
205                                                       const std::string& objectPath) const {
206     commonApiAddress = "local:" + interfaceName + ":" + connectionName;
207 }
208
209
210 }// namespace DBus
211 }// namespace CommonAPI