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/. */
9 #include "DBusAddressTranslator.h"
10 #include "DBusUtils.h"
12 #include <unordered_set>
24 DBUS_CONNECTION, DBUS_OBJECT, DBUS_INTERFACE, DBUS_PREDEFINED
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}
35 DBusAddressTranslator::DBusAddressTranslator() {}
38 void DBusAddressTranslator::init() {
39 std::string fqnOfConfigFile = getCurrentBinaryFileFQN();
40 fqnOfConfigFile += DBUS_CONFIG_SUFFIX;
42 std::ifstream addressConfigFile;
43 addressConfigFile.open(fqnOfConfigFile.c_str());
45 if(addressConfigFile.is_open()) {
46 readConfigFile(addressConfigFile);
47 addressConfigFile.close();
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();
59 addressConfigFile.clear();
60 addressConfigFile.open(DBUS_GLOBAL_CONFIG_FQN);
61 if(addressConfigFile.is_open()) {
62 readConfigFile(addressConfigFile);
63 addressConfigFile.close();
68 inline void readValue(std::string& readLine, CommonApiServiceDetails& serviceDetails) {
69 std::stringstream readStream(readLine);
71 std::string paramName;
72 std::string paramValue;
74 getline(readStream, paramName, '=');
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>(std::get<0>(serviceDetails)) = paramValue;
83 case TypeEnum::DBUS_OBJECT:
84 std::get<1>(std::get<0>(serviceDetails)) = paramValue;
86 case TypeEnum::DBUS_INTERFACE:
87 std::get<2>(std::get<0>(serviceDetails)) = paramValue;
89 case TypeEnum::DBUS_PREDEFINED:
90 std::get<1>(serviceDetails) = paramValue == "true" ? true : false;
97 inline void reset(DBusServiceAddress& dbusServiceAddress) {
98 std::get<0>(dbusServiceAddress) = "";
99 std::get<1>(dbusServiceAddress) = "";
100 std::get<2>(dbusServiceAddress) = "";
103 inline void reset(CommonApiServiceDetails& serviceDetails) {
104 reset(std::get<0>(serviceDetails));
105 std::get<1>(serviceDetails) = false;
109 void DBusAddressTranslator::readConfigFile(std::ifstream& addressConfigFile) {
110 std::string currentlyParsedCommonApiAddress;
111 CommonApiServiceDetails serviceDetails;
112 reset(serviceDetails);
114 bool newAddressFound = false;
116 while (addressConfigFile.good()) {
117 std::string readLine;
118 getline(addressConfigFile, readLine);
119 const size_t readLineLength = readLine.length();
121 if (readLine[0] == '[' && readLine[readLineLength - 1] == ']') {
122 if (newAddressFound) {
123 fillUndefinedValues(serviceDetails, currentlyParsedCommonApiAddress);
124 commonApiAddressDetails.insert( {currentlyParsedCommonApiAddress, serviceDetails});
125 dbusToCommonApiAddress.insert( {std::get<0>(serviceDetails), currentlyParsedCommonApiAddress});
127 reset(serviceDetails);
128 currentlyParsedCommonApiAddress = readLine.substr(1, readLineLength - 2);
129 newAddressFound = commonApiAddressDetails.find(currentlyParsedCommonApiAddress) == commonApiAddressDetails.end();
131 } else if (newAddressFound) {
132 readValue(readLine, serviceDetails);
135 if(newAddressFound) {
136 fillUndefinedValues(serviceDetails, currentlyParsedCommonApiAddress);
137 commonApiAddressDetails.insert( {currentlyParsedCommonApiAddress, serviceDetails});
138 dbusToCommonApiAddress.insert( {std::get<0>(serviceDetails), currentlyParsedCommonApiAddress});
143 void DBusAddressTranslator::fillUndefinedValues(CommonApiServiceDetails& serviceDetails, const std::string& commonApiAddress) const {
144 std::string connectionName;
145 std::string objectPath;
146 std::string interfaceName;
148 findFallbackDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
150 std::get<0>(std::get<0>(serviceDetails)) = std::get<0>(std::get<0>(serviceDetails)) == "" ? connectionName : std::get<0>(std::get<0>(serviceDetails));
151 std::get<1>(std::get<0>(serviceDetails)) = std::get<1>(std::get<0>(serviceDetails)) == "" ? objectPath : std::get<1>(std::get<0>(serviceDetails));
152 std::get<2>(std::get<0>(serviceDetails)) = std::get<2>(std::get<0>(serviceDetails)) == "" ? interfaceName : std::get<2>(std::get<0>(serviceDetails));
156 DBusAddressTranslator& DBusAddressTranslator::getInstance() {
157 static DBusAddressTranslator* dbusNameService_;
158 if(!dbusNameService_) {
159 dbusNameService_ = new DBusAddressTranslator();
160 dbusNameService_->init();
162 return *dbusNameService_;
166 void DBusAddressTranslator::searchForDBusAddress(const std::string& commonApiAddress,
167 std::string& interfaceName,
168 std::string& connectionName,
169 std::string& objectPath) {
171 const auto& foundAddressMapping = commonApiAddressDetails.find(commonApiAddress);
173 if(foundAddressMapping != commonApiAddressDetails.end()) {
174 connectionName = std::get<0>(std::get<0>(foundAddressMapping->second));
175 objectPath = std::get<1>(std::get<0>(foundAddressMapping->second));
176 interfaceName = std::get<2>(std::get<0>(foundAddressMapping->second));
178 findFallbackDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
179 commonApiAddressDetails.insert( {commonApiAddress, std::make_tuple(std::make_tuple(connectionName, objectPath, interfaceName), false) } );
183 void DBusAddressTranslator::searchForCommonAddress(const std::string& interfaceName,
184 const std::string& connectionName,
185 const std::string& objectPath,
186 std::string& commonApiAddress) {
188 DBusServiceAddress dbusAddress(connectionName, objectPath, interfaceName);
190 const auto& foundAddressMapping = dbusToCommonApiAddress.find(dbusAddress);
191 if (foundAddressMapping != dbusToCommonApiAddress.end()) {
192 commonApiAddress = foundAddressMapping->second;
194 findFallbackCommonAddress(commonApiAddress, interfaceName, connectionName, objectPath);
195 dbusToCommonApiAddress.insert( {std::move(dbusAddress), commonApiAddress} );
199 void DBusAddressTranslator::getPredefinedInstances(const std::string& connectionName,
200 std::vector<DBusServiceAddress>& instances) {
202 auto dbusAddress = commonApiAddressDetails.begin();
203 while (dbusAddress != commonApiAddressDetails.end()) {
204 CommonApiServiceDetails serviceDetails = dbusAddress->second;
205 if (connectionName == std::get<0>(std::get<0>(serviceDetails))
206 && true == std::get<1>(serviceDetails)) {
207 instances.push_back(std::get<0>(serviceDetails));
213 void DBusAddressTranslator::findFallbackDBusAddress(const std::string& commonApiAddress,
214 std::string& interfaceName,
215 std::string& connectionName,
216 std::string& objectPath) const {
217 std::vector<std::string> parts = split(commonApiAddress, ':');
218 interfaceName = parts[1];
219 connectionName = parts[2];
220 objectPath = '/' + parts[2];
221 std::replace(objectPath.begin(), objectPath.end(), '.', '/');
224 void DBusAddressTranslator::findFallbackCommonAddress(std::string& commonApiAddress,
225 const std::string& interfaceName,
226 const std::string& connectionName,
227 const std::string& objectPath) const {
228 commonApiAddress = "local:" + interfaceName + ":" + connectionName;
233 }// namespace CommonAPI