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 std::ifstream addressConfigFile;
42 if (fqnOfConfigFile != "") {
43 fqnOfConfigFile += DBUS_CONFIG_SUFFIX;
45 addressConfigFile.open(fqnOfConfigFile.c_str());
47 if (addressConfigFile.is_open()) {
48 readConfigFile(addressConfigFile);
49 addressConfigFile.close();
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();
60 addressConfigFile.clear();
63 addressConfigFile.open(DBUS_GLOBAL_CONFIG_FQN);
64 if(addressConfigFile.is_open()) {
65 readConfigFile(addressConfigFile);
66 addressConfigFile.close();
71 inline void readValue(std::string& readLine, CommonApiServiceDetails& serviceDetails) {
72 std::stringstream readStream(readLine);
74 std::string paramName;
75 std::string paramValue;
77 getline(readStream, paramName, '=');
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;
86 case TypeEnum::DBUS_OBJECT:
87 std::get<1>(std::get<0>(serviceDetails)) = paramValue;
89 case TypeEnum::DBUS_INTERFACE:
90 std::get<2>(std::get<0>(serviceDetails)) = paramValue;
92 case TypeEnum::DBUS_PREDEFINED:
93 std::get<1>(serviceDetails) = paramValue == "true" ? true : false;
100 inline void reset(DBusServiceAddress& dbusServiceAddress) {
101 std::get<0>(dbusServiceAddress) = "";
102 std::get<1>(dbusServiceAddress) = "";
103 std::get<2>(dbusServiceAddress) = "";
106 inline void reset(CommonApiServiceDetails& serviceDetails) {
107 reset(std::get<0>(serviceDetails));
108 std::get<1>(serviceDetails) = false;
112 void DBusAddressTranslator::readConfigFile(std::ifstream& addressConfigFile) {
113 std::string currentlyParsedCommonApiAddress;
114 CommonApiServiceDetails serviceDetails;
115 reset(serviceDetails);
117 bool newAddressFound = false;
119 while (addressConfigFile.good()) {
120 std::string readLine;
121 getline(addressConfigFile, readLine);
122 const size_t readLineLength = readLine.length();
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});
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();
137 } else if (newAddressFound) {
138 readValue(readLine, serviceDetails);
141 if(newAddressFound) {
142 fillUndefinedValues(serviceDetails, currentlyParsedCommonApiAddress);
143 commonApiAddressDetails.insert( {currentlyParsedCommonApiAddress, serviceDetails});
144 dbusToCommonApiAddress.insert( {std::get<0>(serviceDetails), currentlyParsedCommonApiAddress});
149 void DBusAddressTranslator::fillUndefinedValues(CommonApiServiceDetails& serviceDetails, const std::string& commonApiAddress) const {
150 std::string connectionName;
151 std::string objectPath;
152 std::string interfaceName;
154 findFallbackDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
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));
162 DBusAddressTranslator& DBusAddressTranslator::getInstance() {
163 static DBusAddressTranslator* dbusNameService_;
164 if(!dbusNameService_) {
165 dbusNameService_ = new DBusAddressTranslator();
166 dbusNameService_->init();
168 return *dbusNameService_;
172 void DBusAddressTranslator::searchForDBusAddress(const std::string& commonApiAddress,
173 std::string& interfaceName,
174 std::string& connectionName,
175 std::string& objectPath) {
177 const auto& foundAddressMapping = commonApiAddressDetails.find(commonApiAddress);
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));
184 findFallbackDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
185 commonApiAddressDetails.insert( {commonApiAddress, std::make_tuple(std::make_tuple(connectionName, objectPath, interfaceName), false) } );
189 void DBusAddressTranslator::searchForCommonAddress(const std::string& interfaceName,
190 const std::string& connectionName,
191 const std::string& objectPath,
192 std::string& commonApiAddress) {
194 DBusServiceAddress dbusAddress(connectionName, objectPath, interfaceName);
196 const auto& foundAddressMapping = dbusToCommonApiAddress.find(dbusAddress);
197 if (foundAddressMapping != dbusToCommonApiAddress.end()) {
198 commonApiAddress = foundAddressMapping->second;
200 findFallbackCommonAddress(commonApiAddress, interfaceName, connectionName, objectPath);
201 dbusToCommonApiAddress.insert( {std::move(dbusAddress), commonApiAddress} );
205 void DBusAddressTranslator::getPredefinedInstances(const std::string& connectionName,
206 std::vector<DBusServiceAddress>& instances) {
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));
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(), '.', '/');
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;
239 }// namespace CommonAPI