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, DBusServiceAddress& dbusServiceAddress) {
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>(dbusServiceAddress) = paramValue;
83 case TypeEnum::DBUS_OBJECT:
84 std::get<1>(dbusServiceAddress) = paramValue;
86 case TypeEnum::DBUS_INTERFACE:
87 std::get<2>(dbusServiceAddress) = paramValue;
89 case TypeEnum::DBUS_PREDEFINED:
90 std::get<3>(dbusServiceAddress) = 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) = "";
101 std::get<3>(dbusServiceAddress) = false;
105 void DBusAddressTranslator::readConfigFile(std::ifstream& addressConfigFile) {
106 std::string currentlyParsedCommonApiAddress;
107 DBusServiceAddress dbusServiceAddress;
108 reset(dbusServiceAddress);
110 bool newAddressFound = false;
112 while (addressConfigFile.good()) {
113 std::string readLine;
114 getline(addressConfigFile, readLine);
115 const size_t readLineLength = readLine.length();
117 if (readLine[0] == '[' && readLine[readLineLength - 1] == ']') {
118 if (newAddressFound) {
119 fillUndefinedValues(dbusServiceAddress, currentlyParsedCommonApiAddress);
120 knownDBusAddresses.insert( {currentlyParsedCommonApiAddress, dbusServiceAddress});
121 knownCommonAddresses.insert( {dbusServiceAddress, currentlyParsedCommonApiAddress});
123 reset(dbusServiceAddress);
124 currentlyParsedCommonApiAddress = readLine.substr(1, readLineLength - 2);
125 newAddressFound = knownDBusAddresses.find(currentlyParsedCommonApiAddress) == knownDBusAddresses.end();
127 } else if (newAddressFound) {
128 readValue(readLine, dbusServiceAddress);
131 if(newAddressFound) {
132 fillUndefinedValues(dbusServiceAddress, currentlyParsedCommonApiAddress);
133 knownDBusAddresses.insert( {currentlyParsedCommonApiAddress, dbusServiceAddress});
134 knownCommonAddresses.insert( {dbusServiceAddress, currentlyParsedCommonApiAddress});
139 void DBusAddressTranslator::fillUndefinedValues(DBusServiceAddress& dbusServiceAddress, const std::string& commonApiAddress) const {
140 std::string connectionName;
141 std::string objectPath;
142 std::string interfaceName;
144 findFallbackDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
146 std::get<0>(dbusServiceAddress) = std::get<0>(dbusServiceAddress) == "" ? connectionName : std::get<0>(dbusServiceAddress);
147 std::get<1>(dbusServiceAddress) = std::get<1>(dbusServiceAddress) == "" ? objectPath : std::get<1>(dbusServiceAddress);
148 std::get<2>(dbusServiceAddress) = std::get<2>(dbusServiceAddress) == "" ? interfaceName : std::get<2>(dbusServiceAddress);
152 DBusAddressTranslator& DBusAddressTranslator::getInstance() {
153 static DBusAddressTranslator* dbusNameService_;
154 if(!dbusNameService_) {
155 dbusNameService_ = new DBusAddressTranslator();
156 dbusNameService_->init();
158 return *dbusNameService_;
162 void DBusAddressTranslator::searchForDBusAddress(const std::string& commonApiAddress,
163 std::string& interfaceName,
164 std::string& connectionName,
165 std::string& objectPath) {
167 const auto& foundAddressMapping = knownDBusAddresses.find(commonApiAddress);
169 if(foundAddressMapping != knownDBusAddresses.end()) {
170 connectionName = std::get<0>(foundAddressMapping->second);
171 objectPath = std::get<1>(foundAddressMapping->second);
172 interfaceName = std::get<2>(foundAddressMapping->second);
174 findFallbackDBusAddress(commonApiAddress, interfaceName, connectionName, objectPath);
175 knownDBusAddresses.insert( {commonApiAddress, std::make_tuple(connectionName, objectPath, interfaceName, false) } );
179 void DBusAddressTranslator::searchForCommonAddress(const std::string& interfaceName,
180 const std::string& connectionName,
181 const std::string& objectPath,
182 std::string& commonApiAddress) {
184 DBusServiceAddress dbusAddress(connectionName, objectPath, interfaceName, false);
186 const auto& foundAddressMapping = knownCommonAddresses.find(dbusAddress);
187 if (foundAddressMapping != knownCommonAddresses.end()) {
188 commonApiAddress = foundAddressMapping->second;
190 findFallbackCommonAddress(commonApiAddress, interfaceName, connectionName, objectPath);
191 knownCommonAddresses.insert( {std::move(dbusAddress), commonApiAddress} );
195 void DBusAddressTranslator::getPredefinedInstances(const std::string& connectionName,
196 std::vector<DBusServiceAddress>& instances) {
198 auto dbusAddress = knownDBusAddresses.begin();
199 while (dbusAddress != knownDBusAddresses.end()) {
200 if (connectionName == std::get<0>(dbusAddress->second) && true == std::get<3>(dbusAddress->second)) {
201 instances.push_back(dbusAddress->second);
207 void DBusAddressTranslator::findFallbackDBusAddress(const std::string& commonApiAddress,
208 std::string& interfaceName,
209 std::string& connectionName,
210 std::string& objectPath) const {
211 std::vector<std::string> parts = split(commonApiAddress, ':');
212 interfaceName = parts[1];
213 connectionName = parts[2];
214 objectPath = '/' + parts[2];
215 std::replace(objectPath.begin(), objectPath.end(), '.', '/');
218 void DBusAddressTranslator::findFallbackCommonAddress(std::string& commonApiAddress,
219 const std::string& interfaceName,
220 const std::string& connectionName,
221 const std::string& objectPath) const {
222 commonApiAddress = "local:" + interfaceName + ":" + connectionName;
227 }// namespace CommonAPI