6b86c57c7f385c0491c73963a5a2ef8ce4aa2510
[framework/web/wrt-commons.git] / modules / dbus / include / dpl / dbus / dbus_client.h
1 /*
2  * Copyright (c) 2011 Samsung Electronics Co., Ltd All Rights Reserved
3  *
4  *    Licensed under the Apache License, Version 2.0 (the "License");
5  *    you may not use this file except in compliance with the License.
6  *    You may obtain a copy of the License at
7  *
8  *        http://www.apache.org/licenses/LICENSE-2.0
9  *
10  *    Unless required by applicable law or agreed to in writing, software
11  *    distributed under the License is distributed on an "AS IS" BASIS,
12  *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  *    See the License for the specific language governing permissions and
14  *    limitations under the License.
15  */
16 /*
17  * @file        dbus_client.h
18  * @author      Tomasz Swierczek (t.swierczek@samsung.com)
19  * @version     1.0
20  * @brief       Header file for DBus generic client support
21  */
22
23 #ifndef DPL_DBUS_DBUS_CLIENT_H_
24 #define DPL_DBUS_DBUS_CLIENT_H_
25
26 #include <string>
27 #include <dbus/dbus.h>
28 #include <dpl/exception.h>
29 #include <dpl/log/log.h>
30 #include <dpl/dbus/dbus_serialization.h>
31 #include <dpl/dbus/dbus_deserialization.h>
32
33 namespace DPL {
34 namespace DBus {
35
36 /*
37  * DBus::Client class is intended to act as simple DBus client. To call a method
38  * on remote service "Service", on remote object "Object", interface
39  * "Interface",use it like this:
40  *
41  *
42  *  DBus::Client client("Object", "Service", "Interface");
43  *  (...) // variables declarations
44  *  client.call("Method name", arg1, arg2, arg2, ... argN,
45  *                             &outArg1, &outArg2, &outArg3, ..., &outArgN);
46  *
47  *
48  * As You can see, input parameters of the call are passed with reference,
49  * output ones are passed as pointers - parameters MUST be passed this way.
50  *
51  * To call a void function (no out params), just pass in arguments to Call().
52  *
53  * Currently client supports serialization and deserialization of simple types
54  * (int, char, float, unsigned), strings (std::string and char*) and
55  * some STL containers (std::vector, std::list, std::map, std::set, std::pair).
56  * Structures and classes are not (yet) supported.
57  */
58
59 class Client
60 {
61
62   public:
63     class Exception
64     {
65       public:
66         DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
67         DECLARE_EXCEPTION_TYPE(Base, DBusClientException)
68     };
69
70     Client(std::string serverPath,
71            std::string serviceName,
72            std::string interfaceName) :
73             m_serviceName(serviceName),
74             m_serverPath(serverPath),
75             m_interfaceName(interfaceName)
76     {
77         DBusError error;
78
79         dbus_error_init(&error);
80         m_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
81         if (NULL == m_connection) {
82             LogPedantic("Couldn't get DBUS connection. Error: " <<
83                     error.message);
84             dbus_error_free(&error);
85             ThrowMsg(Exception::DBusClientException,
86                     "Couldn't get DBUS connection." );
87         }
88     }
89
90     template<typename ...Args>
91     void call(const char* methodName, const Args&... args)
92     {
93         DBusMessage* message = dbus_message_new_method_call(
94                 m_serviceName.c_str(),
95                 m_serverPath.c_str(),
96                 m_interfaceName.c_str(),
97                 methodName);
98         DBusMessageIter argsIterator;
99         dbus_message_iter_init_append(message, &argsIterator);
100         call(message, &argsIterator, args...);
101         dbus_message_unref(message);
102     }
103
104     template<typename ...Args>
105     void call(std::string methodName, const Args&... args)
106     {
107         call(methodName.c_str(), args...);
108     }
109
110     ~Client()
111     {
112         dbus_connection_unref(m_connection);
113     }
114
115   private:
116
117     DBusMessage* makeCall(
118             DBusMessage* message)
119     {
120         DBusError error;
121         dbus_error_init(&error);
122         DBusMessage* ret = dbus_connection_send_with_reply_and_block(
123                 m_connection,
124                 message,
125                 -1,
126                 &error);
127         if (NULL == ret) {
128             LogPedantic("Error sending DBUS message: " <<
129                     error.message);
130             dbus_error_free(&error);
131             ThrowMsg(Exception::DBusClientException,
132                     "Error sending DBUS message." );
133         }
134         return ret;
135     }
136
137     void call(DBusMessage* message, DBusMessageIter* /*argsIterator*/)
138     {
139         DBusMessage* ret = makeCall(message);
140         if (ret != NULL) {
141             dbus_message_unref(ret);
142         } else {
143             LogPedantic("Error getting DBUS response.");
144             ThrowMsg(Exception::DBusClientException,
145                     "Error getting DBUS response." );
146         }
147     }
148
149     template<typename T, typename ... Args>
150     void call(
151             DBusMessage* message,
152             DBusMessageIter* argsIterator,
153             const T& invalue,
154             const Args&... args)
155     {
156         if (!Serialization::serialize(argsIterator, invalue)){
157             LogPedantic("Error in serialization.");
158             ThrowMsg(Exception::DBusClientException,
159                     "Error in serialization." );
160         }
161         call(message, argsIterator, args...);
162     }
163
164     template<typename T, typename ... Args>
165     void call(
166             DBusMessage* message,
167             DBusMessageIter* argsIterator,
168             const T* invalue,
169             const Args&... args)
170     {
171         if (!Serialization::serialize(argsIterator, invalue)){
172             LogPedantic("Error in serialization.");
173             ThrowMsg(Exception::DBusClientException,
174                     "Error in serialization." );
175         }
176         call(message, argsIterator, args...);
177     }
178
179     template<typename T, typename ... Args>
180     void call(
181             DBusMessage* message,
182             DBusMessageIter* argsIterator,
183             const T* invalue)
184     {
185         if (!Serialization::serialize(argsIterator, invalue)){
186             LogPedantic("Error in serialization.");
187             ThrowMsg(Exception::DBusClientException,
188                     "Error in serialization." );
189         }
190         call(message, argsIterator);
191     }
192
193     template<typename T, typename ... Args>
194     void call(
195             DBusMessage* message,
196             DBusMessageIter* /*argsIterator*/,
197             T* out,
198             const Args&... args)
199     {
200         DBusMessage* ret = makeCall(message);
201         if (ret != NULL) {
202             DBusMessageIter responseIterator;
203             dbus_message_iter_init(ret, &responseIterator);
204             returnFromCall(&responseIterator, out, args...);
205             dbus_message_unref(ret);
206         }
207     }
208
209     template<typename T, typename ... Args>
210     void returnFromCall(
211             DBusMessageIter* responseIterator,
212             T* out,
213             const Args&... args)
214     {
215         if (!Deserialization::deserialize(responseIterator, out)){
216             LogPedantic("Error in deserialization.");
217             ThrowMsg(Exception::DBusClientException,
218                     "Error in deserialization." );
219         }
220         returnFromCall(responseIterator, args...);
221     }
222
223     template<typename T>
224     void returnFromCall(DBusMessageIter* responseIterator, T* out)
225     {
226         if (!Deserialization::deserialize(responseIterator, out)){
227             LogPedantic("Error in deserialization.");
228             ThrowMsg(Exception::DBusClientException,
229                     "Error in deserialization." );
230         }
231     }
232
233     std::string m_serviceName, m_serverPath, m_interfaceName;
234     DBusConnection* m_connection;
235 };
236
237 } // namespace DBus
238 } // namespace DPL
239
240 #endif // DPL_DBUS_DBUS_CLIENT_H_