Imported Upstream version 1.3.99.3~20130529~SE~b989f69~SYSYNC~3366831
[platform/upstream/syncevolution.git] / src / gdbusxx / test / example.cpp
1 /*
2  *
3  *  Library for simple D-Bus integration with GLib
4  *
5  *  Copyright (C) 2009  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <stdint.h>
30 #include <sys/signal.h>
31
32 #include "gdbus-cxx-bridge.h"
33 #include <memory>
34 #include <iostream>
35
36 #include <boost/noncopyable.hpp>
37
38 namespace GDBusCXX {
39
40 struct args {
41     int a;
42     std::string b;
43     std::map<std::string, std::string> c;
44 };
45
46 static void hello_global() {}
47
48 class Test {
49     typedef boost::shared_ptr< Result1<const std::string&> > string_result;
50     struct async : private boost::noncopyable
51     {
52         async(const boost::shared_ptr<Watch> &watch, Watch *watch2, const string_result &result):
53             m_watch(watch),
54             m_watch2(watch2),
55             m_result(result)
56         {}
57         ~async()
58         {
59             delete m_watch2;
60         }
61
62         boost::shared_ptr<Watch> m_watch;
63         Watch *m_watch2;
64         string_result m_result;
65     };
66
67
68     static gboolean method_idle(gpointer data)
69     {
70         std::auto_ptr<async> mydata(static_cast<async *>(data));
71         std::cout << "replying to method_async" << std::endl;
72         mydata->m_result->done("Hello World, asynchronous and delayed");
73         return false;
74     }
75
76     static void disconnect(const std::string &id, const std::string &peer)
77     {
78         std::cout << id << ": " << peer << " has disconnected." << std::endl;
79     }
80
81 public:
82
83     static void hello_static() {}
84     void hello_const() const {}
85     static void hello_world(const char *msg) { puts(msg); }
86     void hello_base() {}
87
88     void method(std::string &text)
89     {
90         text = "Hello World";
91     }
92
93     void method_async(const Caller_t &caller,
94                       const boost::shared_ptr<Watch> &watch,
95                       int32_t secs,
96                       const string_result &r)
97     {
98         watch->setCallback(boost::bind(disconnect, "watch1", caller));
99         Watch *watch2 = r->createWatch(boost::bind(disconnect, "watch2", caller));
100         std::cout << "method_async called by " << caller << " delay " << secs << std::endl;
101         g_timeout_add_seconds(secs, method_idle, new async(watch, watch2, r));
102     }
103
104     void method2(int32_t arg, int32_t &ret)
105     {
106         ret = arg * 2;
107     }
108
109     int32_t method3(int32_t arg)
110     {
111         return arg * 3;
112     }
113
114     void method8_simple(int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5,
115                         int32_t a6, int32_t a7, int32_t a8)
116     {
117     }
118
119     void method9_async(Result9<int32_t, int32_t, int32_t, int32_t, int32_t,
120                                int32_t, int32_t, int32_t, int32_t> *r)
121     {
122         r->done(1, 2, 3, 4, 5, 6, 7, 8, 9);
123         delete r;
124     }
125
126     int32_t method9(int32_t a1, int32_t a2, int32_t a3, int32_t a4, int32_t a5,
127                     int32_t a6, int32_t a7, int32_t a8, int32_t a9)
128     {
129         return 0;
130     }
131
132
133     void hash(const std::map<int8_t, int32_t> &in, std::map<int16_t, int32_t> &out)
134     {
135         for (std::map<int8_t, int32_t>::const_iterator it = in.begin();
136              it != in.end();
137              ++it) {
138             out.insert(std::make_pair((int16_t)it->first, it->second * it->second));
139         }
140     }
141
142     void array(const std::vector<int32_t> &in, std::vector<int32_t> &out)
143     {
144         for (std::vector<int32_t>::const_iterator it = in.begin();
145              it != in.end();
146              ++it) {
147             out.push_back(*it * *it);
148         }
149     }
150
151     void error()
152     {
153         throw dbus_error("org.example.error.Invalid", "error");
154     }
155
156     void argtest(const args &in, args &out)
157     {
158         out = in;
159         out.a = in.a + 1;
160     }
161 };
162
163 class Test2
164 {
165 public:
166     void test2() {}
167 };
168
169 template<> struct dbus_traits<args> :
170     public dbus_struct_traits<args, dbus_member<args, int, &args::a,
171                                     dbus_member<args, std::string, &args::b,
172                                     dbus_member_single<args, std::map<std::string, std::string>, &args::c> > > >
173 {};
174
175 class DBusTest : public Test, private Test2
176 {
177     DBusObjectHelper m_object;
178     DBusObjectHelper m_secondary;
179
180 public:
181     DBusTest(const DBusConnectionPtr &conn) :
182         m_object(conn, "/test", "org.example.Test"),
183         // same path!
184         m_secondary(conn, m_object.getPath(), "org.example.Secondary"),
185         signal(m_object, "Signal")
186     {
187         m_object.add(this, &Test::method8_simple, "Method8Simple");
188         // m_object.add(this, &Test::method10_async, "Method10Async", G_DBUS_METHOD_FLAG_ASYNC);
189         // m_object.add(this, &Test::method9, "Method9");
190         m_object.add(this, &Test::method2, "Method2");
191         m_object.add(this, &Test::method3, "Method3");
192         m_object.add(this, &Test::method, "Test");
193         m_object.add(this, &Test::method_async, "TestAsync");
194         m_object.add(this, &Test::argtest, "ArgTest");
195         m_object.add(this, &Test::hash, "Hash");
196         m_object.add(this, &Test::array, "Array");
197         m_object.add(this, &Test::error, "Error");
198         m_object.add(&hello_global, "Global");
199         m_object.add(&DBusTest::hello_static, "Static");
200         m_object.add(static_cast<Test2 *>(this), &Test2::test2, "Private");
201         // The hello_const() method cannot be registered
202         // because there is no matching MakeMethodEntry<>
203         // specialization for it or DBusObjectHelper::add()
204         // fails to determine the right function type,
205         // depending how one wants to interpret the problem.
206         // m_object.add2(this, &DBusTest::hello_const, "Const");
207
208         m_object.add(signal);
209
210         m_secondary.add(this, &DBusTest::hello, "Hello");
211     }
212
213     ~DBusTest()
214     {
215     }
216
217     EmitSignal3<int32_t, const std::string &, const std::map<int32_t, int32_t> &>signal;
218
219     void hello() {}
220     static void hello_static() {}
221     void hello_const() const {}
222
223     void activate()
224     {
225         m_secondary.activate();
226         m_object.activate();
227     }
228
229     void deactivate()
230     {
231         m_object.deactivate();
232         m_secondary.deactivate();
233     }
234 };
235
236 static GMainLoop *main_loop = NULL;
237
238 static void sig_term(int sig)
239 {
240     g_main_loop_quit(main_loop);
241 }
242
243 } // namespace GDBusCXX
244
245 using namespace GDBusCXX;
246
247 int main(int argc, char *argv[])
248 {
249     DBusConnectionPtr conn;
250     DBusErrorCXX err;
251     struct sigaction sa;
252
253     memset(&sa, 0, sizeof(sa));
254     sa.sa_handler = sig_term;
255     sigaction(SIGINT, &sa, NULL);
256     sigaction(SIGTERM, &sa, NULL);
257
258     sa.sa_handler = SIG_IGN;
259     sigaction(SIGCHLD, &sa, NULL);
260     sigaction(SIGPIPE, &sa, NULL);
261
262     main_loop = g_main_loop_new(NULL, FALSE);
263
264     conn = dbus_get_bus_connection("SESSION", "org.example", false, &err);
265     if (conn == NULL) {
266         std::string message = err.getMessage();
267         if (!message.empty()) {
268             fprintf(stderr, "%s\n", message.c_str());
269         } else
270             fprintf(stderr, "Can't register with session bus\n");
271         exit(1);
272     }
273
274     std::auto_ptr<DBusTest> test(new DBusTest(conn));
275     test->activate();
276     test->signal(42, "hello world", std::map<int32_t, int32_t>());
277     test->deactivate();
278     test->activate();
279     test->signal(123, "here I am again", std::map<int32_t, int32_t>());
280
281     g_main_loop_run(main_loop);
282
283     test.reset();
284
285     // is this really necessary?
286     // if(!g_dbus_connection_close_sync(conn, NULL, NULL)) {
287     // fprintf(stderr, "Problem closing connection.\n");
288     // }
289
290     g_main_loop_unref(main_loop);
291
292     return 0;
293 }