~ubuntu-branches/ubuntu/gutsy/tomboy/gutsy-updates

« back to all changes in this revision

Viewing changes to Tomboy/dbus-sharp/dbus-sharp/src/BusObject.cs

  • Committer: Bazaar Package Importer
  • Author(s): Sebastian Dröge
  • Date: 2006-11-22 19:22:17 UTC
  • mfrom: (1.1.8 upstream)
  • Revision ID: james.westby@ubuntu.com-20061122192217-odnb17d1ib22okof
Tags: 0.5.1-0ubuntu1
* New upstream release:
  + New Managed D-Bus/DBusSharp (Sebastian Dröge)
  + Additional search interface improvements
  + More secure wrapper script to launch Tomboy.exe
  + Fix panel and TrayIcon resizing
  + Fix 1x1 pixel TrayIcon
  + Removed old tintin image
* debian/control:
  + Update build dependencies
* debian/patches/01-dbus0.9.patch,
  debian/patches/50_tintin.patch,
  debian/patches/51_tomboy-dllmap.patch,
  debian/patches/52_external-dbus-sharp.patch,
  debian/patches/53_tomboy-tray-icon.patch:
  + Dropped, merged upstream
* debian/rules,
  debian/tomboy.desktop:
  + Use upstream's desktop file again after it was fixed now
* debian/rules:
  + DBus service file path workaround removed, it's fixed upstream

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Copyright 2006 Alp Toker <alp@atoker.com>
 
2
// This software is made available under the MIT License
 
3
// See COPYING for details
 
4
 
 
5
using System;
 
6
using System.Reflection;
 
7
using System.Reflection.Emit;
 
8
 
 
9
namespace NDesk.DBus
 
10
{
 
11
        //marked internal because this isn't ready for public use yet
 
12
        //it probably needs to be made into a base and import/export subclasses
 
13
        internal class BusObject
 
14
        {
 
15
                Connection conn;
 
16
                string bus_name;
 
17
                ObjectPath object_path;
 
18
 
 
19
                //protected BusObject ()
 
20
                public BusObject ()
 
21
                {
 
22
                }
 
23
 
 
24
                public BusObject (Connection conn, string bus_name, ObjectPath object_path)
 
25
                {
 
26
                        this.conn = conn;
 
27
                        this.bus_name = bus_name;
 
28
                        this.object_path = object_path;
 
29
                }
 
30
 
 
31
                public Connection Connection
 
32
                {
 
33
                        get {
 
34
                                return conn;
 
35
                        }
 
36
                }
 
37
 
 
38
                public string BusName
 
39
                {
 
40
                        get {
 
41
                                return bus_name;
 
42
                        }
 
43
                }
 
44
 
 
45
                public ObjectPath Path
 
46
                {
 
47
                        get {
 
48
                                return object_path;
 
49
                        }
 
50
                }
 
51
 
 
52
                //convenience method
 
53
                public object InvokeMethod (MethodInfo methodInfo, params object[] inArgs)
 
54
                {
 
55
                        //TODO: this ignores outArgs, doesn't wrap the exception etc.
 
56
 
 
57
                        object[] outArgs;
 
58
                        object retVal;
 
59
                        Exception exception;
 
60
 
 
61
                        Invoke (methodInfo, methodInfo.Name, inArgs, out outArgs, out retVal, out exception);
 
62
 
 
63
                        if (exception != null)
 
64
                                throw exception;
 
65
 
 
66
                        return retVal;
 
67
                }
 
68
 
 
69
                //this method is kept simple while IL generation support is worked on
 
70
                public object SendMethodCall (MethodInfo methodInfo, string @interface, string member, object[] inArgs)
 
71
                {
 
72
                        //TODO: don't ignore retVal, exception etc.
 
73
 
 
74
                        object[] outArgs;
 
75
                        object retVal;
 
76
                        Exception exception;
 
77
                        Invoke (methodInfo, methodInfo.Name, inArgs, out outArgs, out retVal, out exception);
 
78
 
 
79
                        if (exception != null)
 
80
                                throw exception;
 
81
 
 
82
                        return retVal;
 
83
                }
 
84
 
 
85
                public void Invoke (MethodBase methodBase, string methodName, object[] inArgs, out object[] outArgs, out object retVal, out Exception exception)
 
86
                {
 
87
                        outArgs = new object[0];
 
88
                        retVal = null;
 
89
                        exception = null;
 
90
 
 
91
                        MethodInfo mi = methodBase as MethodInfo;
 
92
 
 
93
                        if (mi != null && mi.IsSpecialName && (methodName.StartsWith ("add_") || methodName.StartsWith ("remove_"))) {
 
94
                                string[] parts = methodName.Split (new char[]{'_'}, 2);
 
95
                                string ename = parts[1];
 
96
                                Delegate dlg = (Delegate)inArgs[0];
 
97
                                string matchRule = MessageFilter.CreateMatchRule (MessageType.Signal, object_path, Mapper.GetInterfaceName (mi), ename);
 
98
 
 
99
                                if (parts[0] == "add") {
 
100
                                        if (conn.Handlers.ContainsKey (matchRule))
 
101
                                                conn.Handlers[matchRule] = Delegate.Combine (conn.Handlers[matchRule], dlg);
 
102
                                        else {
 
103
                                                conn.Handlers[matchRule] = dlg;
 
104
                                                conn.AddMatch (matchRule);
 
105
                                        }
 
106
                                } else if (parts[0] == "remove") {
 
107
                                        conn.Handlers[matchRule] = Delegate.Remove (conn.Handlers[matchRule], dlg);
 
108
                                        if (conn.Handlers[matchRule] == null) {
 
109
                                                conn.RemoveMatch (matchRule);
 
110
                                                conn.Handlers.Remove (matchRule);
 
111
                                        }
 
112
                                }
 
113
                                return;
 
114
                        }
 
115
 
 
116
                        Type[] inTypes = Mapper.GetTypes (ArgDirection.In, mi.GetParameters ());
 
117
                        Signature inSig = Signature.GetSig (inTypes);
 
118
 
 
119
                        MethodCall method_call;
 
120
                        Message callMsg;
 
121
 
 
122
                        //build the outbound method call message
 
123
                        {
 
124
                                //this bit is error-prone (no null checking) and will need rewriting when DProxy is replaced
 
125
                                string iface = null;
 
126
                                if (mi != null)
 
127
                                        iface = Mapper.GetInterfaceName (mi);
 
128
 
 
129
                                //map property accessors
 
130
                                //TODO: this needs to be done properly, not with simple String.Replace
 
131
                                //note that IsSpecialName is also for event accessors, but we already handled those and returned
 
132
                                if (mi != null && mi.IsSpecialName) {
 
133
                                        methodName = methodName.Replace ("get_", "Get");
 
134
                                        methodName = methodName.Replace ("set_", "Set");
 
135
                                }
 
136
 
 
137
                                method_call = new MethodCall (object_path, iface, methodName, bus_name, inSig);
 
138
 
 
139
                                callMsg = method_call.message;
 
140
 
 
141
                                if (inArgs != null && inArgs.Length != 0) {
 
142
                                        MessageWriter writer = new MessageWriter ();
 
143
 
 
144
                                        for (int i = 0 ; i != inTypes.Length ; i++)
 
145
                                                writer.Write (inTypes[i], inArgs[i]);
 
146
 
 
147
                                        callMsg.Body = writer.ToArray ();
 
148
                                }
 
149
                        }
 
150
 
 
151
                        //TODO: complete out parameter support
 
152
                        Type[] outParmTypes = Mapper.GetTypes (ArgDirection.Out, mi.GetParameters ());
 
153
                        Signature outParmSig = Signature.GetSig (outParmTypes);
 
154
 
 
155
                        if (outParmSig != Signature.Empty)
 
156
                                throw new Exception ("Out parameters not yet supported: out_signature='" + outParmSig.Value + "'");
 
157
 
 
158
                        Type[] outTypes = new Type[1];
 
159
                        outTypes[0] = mi.ReturnType;
 
160
 
 
161
                        //we default to always requiring replies for now, even though unnecessary
 
162
                        //this is to make sure errors are handled synchronously
 
163
                        //TODO: don't hard code this
 
164
                        bool needsReply = true;
 
165
 
 
166
                        //if (mi.ReturnType == typeof (void))
 
167
                        //      needsReply = false;
 
168
 
 
169
                        callMsg.ReplyExpected = needsReply;
 
170
                        callMsg.Signature = inSig;
 
171
 
 
172
                        if (!needsReply) {
 
173
                                conn.Send (callMsg);
 
174
                                return;
 
175
                        }
 
176
 
 
177
#if PROTO_REPLY_SIGNATURE
 
178
                        if (needsReply) {
 
179
                                Signature outSig = Signature.GetSig (outTypes);
 
180
                                callMsg.Header.Fields[FieldCode.ReplySignature] = outSig;
 
181
                        }
 
182
#endif
 
183
 
 
184
                        Message retMsg = conn.SendWithReplyAndBlock (callMsg);
 
185
 
 
186
                        //handle the reply message
 
187
                        switch (retMsg.Header.MessageType) {
 
188
                                case MessageType.MethodReturn:
 
189
                                object[] retVals = MessageHelper.GetDynamicValues (retMsg, outTypes);
 
190
                                if (retVals.Length != 0)
 
191
                                        retVal = retVals[retVals.Length - 1];
 
192
                                break;
 
193
                                case MessageType.Error:
 
194
                                //TODO: typed exceptions
 
195
                                Error error = new Error (retMsg);
 
196
                                string errMsg = "";
 
197
                                if (retMsg.Signature.Value.StartsWith ("s")) {
 
198
                                        MessageReader reader = new MessageReader (retMsg);
 
199
                                        reader.GetValue (out errMsg);
 
200
                                }
 
201
                                exception = new Exception (error.ErrorName + ": " + errMsg);
 
202
                                break;
 
203
                                default:
 
204
                                throw new Exception ("Got unexpected message of type " + retMsg.Header.MessageType + " while waiting for a MethodReturn or Error");
 
205
                        }
 
206
 
 
207
                        return;
 
208
                }
 
209
 
 
210
                static AssemblyBuilder asmB;
 
211
                static ModuleBuilder modB;
 
212
 
 
213
                static void InitHack ()
 
214
                {
 
215
                        if (asmB != null)
 
216
                                return;
 
217
 
 
218
                        asmB = AppDomain.CurrentDomain.DefineDynamicAssembly (new AssemblyName ("ProxyAssembly"), AssemblyBuilderAccess.Run);
 
219
                        modB = asmB.DefineDynamicModule ("ProxyModule");
 
220
                }
 
221
 
 
222
                static System.Collections.Generic.Dictionary<Type,Type> map = new System.Collections.Generic.Dictionary<Type,Type> ();
 
223
 
 
224
                public static Type DefineType (Type declType)
 
225
                {
 
226
                        if (map.ContainsKey (declType))
 
227
                                return map[declType];
 
228
 
 
229
                        InitHack ();
 
230
 
 
231
                        TypeBuilder typeB = modB.DefineType (declType.Name, TypeAttributes.Class | TypeAttributes.Public, typeof (BusObject));
 
232
 
 
233
                        Implement (typeB, declType);
 
234
 
 
235
                        foreach (Type iface in declType.GetInterfaces ()) {
 
236
                                Implement (typeB, iface);
 
237
                                //typeB.DefineMethodOverride (body, declMethod);
 
238
                        }
 
239
 
 
240
                        Type retT = typeB.CreateType ();
 
241
 
 
242
                        map[declType] = retT;
 
243
                        //return typeB.CreateType ();
 
244
                        return retT;
 
245
                }
 
246
 
 
247
                public static void Implement (TypeBuilder typeB, Type iface)
 
248
                {
 
249
                        typeB.AddInterfaceImplementation (iface);
 
250
 
 
251
                        foreach (MethodInfo declMethod in iface.GetMethods ()) {
 
252
 
 
253
                                MethodBuilder method_builder = typeB.DefineMethod (declMethod.Name, MethodAttributes.Public | MethodAttributes.Virtual, declMethod.ReturnType, Mapper.GetTypes (ArgDirection.In, declMethod.GetParameters ()));
 
254
                                ILGenerator ilg = method_builder.GetILGenerator ();
 
255
 
 
256
                        //Mapper.GetTypes (ArgDirection.In, declMethod.GetParameters ())
 
257
 
 
258
                        ParameterInfo[] delegateParms = declMethod.GetParameters ();
 
259
                        Type[] hookupParms = new Type[delegateParms.Length+1];
 
260
                        hookupParms[0] = typeof (BusObject);
 
261
                        for (int i = 0; i < delegateParms.Length ; i++)
 
262
                                hookupParms[i+1] = delegateParms[i].ParameterType;
 
263
 
 
264
                                GenHookupMethod (ilg, declMethod, sendMethodCallMethod, Mapper.GetInterfaceName (iface), declMethod.Name, hookupParms);
 
265
                        }
 
266
                }
 
267
 
 
268
                public static object GetObject (Connection conn, string bus_name, ObjectPath object_path, Type declType)
 
269
                {
 
270
                        Type proxyType = DefineType (declType);
 
271
 
 
272
                        BusObject inst = (BusObject)Activator.CreateInstance (proxyType);
 
273
                        inst.conn = conn;
 
274
                        inst.bus_name = bus_name;
 
275
                        inst.object_path = object_path;
 
276
 
 
277
                        return inst;
 
278
                }
 
279
 
 
280
                static MethodInfo sendMethodCallMethod = typeof (BusObject).GetMethod ("SendMethodCall");
 
281
                static MethodInfo sendSignalMethod = typeof (BusObject).GetMethod ("SendSignal");
 
282
 
 
283
                public Delegate GetHookupDelegate (EventInfo ei)
 
284
                {
 
285
                        if (ei.EventHandlerType.IsAssignableFrom (typeof (System.EventHandler)))
 
286
                                Console.Error.WriteLine ("Warning: Cannot yet fully marshal EventHandler and its subclasses: " + ei.EventHandlerType);
 
287
 
 
288
                        MethodInfo declMethod = ei.EventHandlerType.GetMethod ("Invoke");
 
289
 
 
290
                        DynamicMethod hookupMethod = GetHookupMethod (declMethod, sendSignalMethod, Mapper.GetInterfaceName (ei), ei.Name);
 
291
 
 
292
                        Delegate d = hookupMethod.CreateDelegate (ei.EventHandlerType, this);
 
293
 
 
294
                        return d;
 
295
                }
 
296
 
 
297
                public static DynamicMethod GetHookupMethod (MethodInfo declMethod, MethodInfo invokeMethod, string @interface, string member)
 
298
                {
 
299
                        ParameterInfo[] delegateParms = declMethod.GetParameters ();
 
300
                        Type[] hookupParms = new Type[delegateParms.Length+1];
 
301
                        hookupParms[0] = typeof (BusObject);
 
302
                        for (int i = 0; i < delegateParms.Length ; i++)
 
303
                                hookupParms[i+1] = delegateParms[i].ParameterType;
 
304
 
 
305
                        DynamicMethod hookupMethod = new DynamicMethod ("Handle" + member, declMethod.ReturnType, hookupParms, typeof (object));
 
306
 
 
307
                        ILGenerator ilg = hookupMethod.GetILGenerator ();
 
308
 
 
309
                        GenHookupMethod (ilg, declMethod, invokeMethod, @interface, member, hookupParms);
 
310
 
 
311
                        return hookupMethod;
 
312
                }
 
313
 
 
314
                public static void GenHookupMethod (ILGenerator ilg, MethodInfo declMethod, MethodInfo invokeMethod, string @interface, string member, Type[] hookupParms)
 
315
                {
 
316
                        Type retType = declMethod.ReturnType;
 
317
 
 
318
                        //the BusObject instance
 
319
                        ilg.Emit (OpCodes.Ldarg_0);
 
320
 
 
321
                        //MethodInfo
 
322
                        ilg.Emit (OpCodes.Ldtoken, declMethod);
 
323
                        ilg.Emit (OpCodes.Call, typeof (MethodBase).GetMethod ("GetMethodFromHandle"));
 
324
 
 
325
                        //interface
 
326
                        ilg.Emit (OpCodes.Ldstr, @interface);
 
327
 
 
328
                        //member
 
329
                        ilg.Emit (OpCodes.Ldstr, member);
 
330
 
 
331
                        LocalBuilder local = ilg.DeclareLocal (typeof (object[]));
 
332
                        ilg.Emit (OpCodes.Ldc_I4, hookupParms.Length - 1);
 
333
                        ilg.Emit (OpCodes.Newarr, typeof (object));
 
334
                        ilg.Emit (OpCodes.Stloc, local);
 
335
 
 
336
                        //offset by one because arg0 is the instance of the delegate
 
337
                        for (int i = 1 ; i < hookupParms.Length ; i++)
 
338
                        {
 
339
                                Type t = hookupParms[i];
 
340
 
 
341
                                ilg.Emit (OpCodes.Ldloc, local);
 
342
                                //the instance parameter requires the -1 offset here
 
343
                                ilg.Emit (OpCodes.Ldc_I4, i-1);
 
344
                                ilg.Emit (OpCodes.Ldarg, i);
 
345
 
 
346
                                if (t.IsValueType)
 
347
                                        ilg.Emit (OpCodes.Box, t);
 
348
 
 
349
                                ilg.Emit (OpCodes.Stelem_Ref);
 
350
                        }
 
351
 
 
352
                        ilg.Emit (OpCodes.Ldloc, local);
 
353
                        ilg.Emit (OpCodes.Call, invokeMethod);
 
354
 
 
355
                        if (retType == typeof (void)) {
 
356
                                //we aren't expecting a return value, so throw away the (hopefully) null return
 
357
                                if (invokeMethod.ReturnType != typeof (void))
 
358
                                        ilg.Emit (OpCodes.Pop);
 
359
                        } else {
 
360
                                if (retType.IsValueType)
 
361
                                        ilg.Emit (OpCodes.Unbox_Any, retType);
 
362
                                else
 
363
                                        ilg.Emit (OpCodes.Castclass, retType);
 
364
                        }
 
365
 
 
366
                        ilg.Emit (OpCodes.Ret);
 
367
                }
 
368
 
 
369
                public void SendSignal (MethodInfo mi, string @interface, string member, object[] outValues)
 
370
                {
 
371
                        //TODO: make use of bus_name?
 
372
 
 
373
                        Type[] outTypes = Mapper.GetTypes (ArgDirection.In, mi.GetParameters ());
 
374
                        Signature outSig = Signature.GetSig (outTypes);
 
375
 
 
376
                        Signal signal = new Signal (object_path, @interface, member);
 
377
                        signal.message.Signature = outSig;
 
378
 
 
379
                        if (outValues != null && outValues.Length != 0) {
 
380
                                MessageWriter writer = new MessageWriter ();
 
381
 
 
382
                                for (int i = 0 ; i != outTypes.Length ; i++)
 
383
                                        writer.Write (outTypes[i], outValues[i]);
 
384
 
 
385
                                signal.message.Body = writer.ToArray ();
 
386
                        }
 
387
 
 
388
                        conn.Send (signal.message);
 
389
                }
 
390
        }
 
391
}