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