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