tizen 2.4 release
[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/wrt_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  * DBus::Client class is intended to act as simple DBus client. To call a method
37  * on remote service "Service", on remote object "Object", interface
38  * "Interface",use it like this:
39  *
40  *
41  *  DBus::Client client("Object", "Service", "Interface");
42  *  (...) // variables declarations
43  *  client.call("Method name", arg1, arg2, arg2, ... argN,
44  *                             &outArg1, &outArg2, &outArg3, ..., &outArgN);
45  *
46  *
47  * As You can see, input parameters of the call are passed with reference,
48  * output ones are passed as pointers - parameters MUST be passed this way.
49  *
50  * To call a void function (no out params), just pass in arguments to Call().
51  *
52  * Currently client supports serialization and deserialization of simple types
53  * (int, char, float, unsigned), strings (std::string and char*) and
54  * some STL containers (std::vector, std::list, std::map, std::set, std::pair).
55  * Structures and classes are not (yet) supported.
56  */
57
58 class Client
59 {
60   public:
61     class Exception
62     {
63       public:
64         DECLARE_EXCEPTION_TYPE(DPL::Exception, Base)
65         DECLARE_EXCEPTION_TYPE(Base, DBusClientException)
66     };
67
68     Client(std::string serverPath,
69            std::string serviceName,
70            std::string interfaceName) :
71         m_serviceName(serviceName),
72         m_serverPath(serverPath),
73         m_interfaceName(interfaceName)
74     {
75         DBusError error;
76
77         dbus_error_init(&error);
78         m_connection = dbus_bus_get(DBUS_BUS_SYSTEM, &error);
79         if (NULL == m_connection) {
80             WrtLogD("Couldn't get DBUS connection. Error: %s",
81                         error.message);
82             dbus_error_free(&error);
83             ThrowMsg(Exception::DBusClientException,
84                      "Couldn't get DBUS connection.");
85         }
86     }
87
88     template<typename ... Args>
89     void call(const char* methodName, const Args& ... args)
90     {
91         DBusMessage* message = dbus_message_new_method_call(
92                 m_serviceName.c_str(),
93                 m_serverPath.c_str(),
94                 m_interfaceName.c_str(),
95                 methodName);
96         DBusMessageIter argsIterator;
97         dbus_message_iter_init_append(message, &argsIterator);
98         call(message, &argsIterator, args ...);
99         dbus_message_unref(message);
100     }
101
102     template<typename ... Args>
103     void call(std::string methodName, const Args& ... args)
104     {
105         call(methodName.c_str(), args ...);
106     }
107
108     ~Client()
109     {
110         dbus_connection_unref(m_connection);
111     }
112
113   private:
114
115     DBusMessage* makeCall(
116         DBusMessage* message)
117     {
118         DBusError error;
119         dbus_error_init(&error);
120         DBusMessage* ret = dbus_connection_send_with_reply_and_block(
121                 m_connection,
122                 message,
123                 -1,
124                 &error);
125         if (NULL == ret) {
126             WrtLogD("Error sending DBUS message: %s",
127                         error.message);
128             dbus_error_free(&error);
129             ThrowMsg(Exception::DBusClientException,
130                      "Error sending DBUS message.");
131         }
132         return ret;
133     }
134
135     void call(DBusMessage* message, DBusMessageIter* /*argsIterator*/)
136     {
137         DBusMessage* ret = makeCall(message);
138         if (ret != NULL) {
139             dbus_message_unref(ret);
140         } else {
141             WrtLogD("Error getting DBUS response.");
142             ThrowMsg(Exception::DBusClientException,
143                      "Error getting DBUS response.");
144         }
145     }
146
147     template<typename T, typename ... Args>
148     void call(
149         DBusMessage* message,
150         DBusMessageIter* argsIterator,
151         const T& invalue,
152         const Args& ... args)
153     {
154         if (!Serialization::serialize(argsIterator, invalue)) {
155             WrtLogD("Error in serialization.");
156             ThrowMsg(Exception::DBusClientException,
157                      "Error in serialization.");
158         }
159         call(message, argsIterator, args ...);
160     }
161
162     template<typename T, typename ... Args>
163     void call(
164         DBusMessage* message,
165         DBusMessageIter* argsIterator,
166         const T* invalue,
167         const Args& ... args)
168     {
169         if (!Serialization::serialize(argsIterator, invalue)) {
170             WrtLogD("Error in serialization.");
171             ThrowMsg(Exception::DBusClientException,
172                      "Error in serialization.");
173         }
174         call(message, argsIterator, args ...);
175     }
176
177     template<typename T, typename ... Args>
178     void call(
179         DBusMessage* message,
180         DBusMessageIter* argsIterator,
181         const T* invalue)
182     {
183         if (!Serialization::serialize(argsIterator, invalue)) {
184             WrtLogD("Error in serialization.");
185             ThrowMsg(Exception::DBusClientException,
186                      "Error in serialization.");
187         }
188         call(message, argsIterator);
189     }
190
191     template<typename T, typename ... Args>
192     void call(
193         DBusMessage* message,
194         DBusMessageIter* /*argsIterator*/,
195         T* out,
196         const Args& ... args)
197     {
198         DBusMessage* ret = makeCall(message);
199         if (ret != NULL) {
200             DBusMessageIter responseIterator;
201             dbus_message_iter_init(ret, &responseIterator);
202             returnFromCall(&responseIterator, out, args ...);
203             dbus_message_unref(ret);
204         }
205     }
206
207     template<typename T, typename ... Args>
208     void returnFromCall(
209         DBusMessageIter* responseIterator,
210         T* out,
211         const Args& ... args)
212     {
213         if (!Deserialization::deserialize(responseIterator, out)) {
214             WrtLogD("Error in deserialization.");
215             ThrowMsg(Exception::DBusClientException,
216                      "Error in deserialization.");
217         }
218         returnFromCall(responseIterator, args ...);
219     }
220
221     template<typename T>
222     void returnFromCall(DBusMessageIter* responseIterator, T* out)
223     {
224         if (!Deserialization::deserialize(responseIterator, out)) {
225             WrtLogD("Error in deserialization.");
226             ThrowMsg(Exception::DBusClientException,
227                      "Error in deserialization.");
228         }
229     }
230
231     std::string m_serviceName, m_serverPath, m_interfaceName;
232     DBusConnection* m_connection;
233 };
234 } // namespace DBus
235 } // namespace DPL
236
237 #endif // DPL_DBUS_DBUS_CLIENT_H_