* qt/Makfile.am:
[platform/upstream/dbus.git] / mono / Handler.cs
1 namespace DBus
2 {
3   using System;
4   using System.Runtime.InteropServices;
5   using System.Diagnostics;
6   using System.Reflection;
7   using System.Collections;
8
9   internal enum Result 
10   {
11     Handled = 0,
12     NotYetHandled = 1,
13     NeedMemory = 2
14   }
15
16   internal class Handler
17   {
18     private string path = null;
19     private Introspector introspector = null;
20     private object handledObject = null;
21     private DBusObjectPathVTable vTable;
22     private Connection connection;
23     private Service service;
24
25     // We need to hold extra references to these callbacks so that they don't
26     // get garbage collected before they are called back into from unmanaged
27     // code.
28     private DBusObjectPathUnregisterFunction unregister_func;
29     private DBusObjectPathMessageFunction message_func;
30
31     public Handler(object handledObject, 
32                    string path, 
33                    Service service)
34     {
35       Service = service;
36       Connection = service.Connection;
37       HandledObject = handledObject;
38       this.path = path;
39       
40       // Create the vTable and register the path
41       this.unregister_func = new DBusObjectPathUnregisterFunction (Unregister_Called);
42       this.message_func = new DBusObjectPathMessageFunction (Message_Called);
43
44       vTable = new DBusObjectPathVTable (this.unregister_func, this.message_func);
45       Connection.RegisterObjectPath (Path, vTable);
46       RegisterSignalHandlers();
47     }
48
49     private void RegisterSignalHandlers()
50     {
51       ProxyBuilder proxyBuilder = new ProxyBuilder(Service, HandledObject.GetType(), Path);
52
53       foreach (DictionaryEntry interfaceEntry in this.introspector.InterfaceProxies) {
54         InterfaceProxy interfaceProxy = (InterfaceProxy) interfaceEntry.Value;
55         foreach (DictionaryEntry signalEntry in interfaceProxy.Signals) {
56           EventInfo eventE = (EventInfo) signalEntry.Value;
57           Delegate del = Delegate.CreateDelegate(eventE.EventHandlerType, proxyBuilder.GetSignalProxy(), "Proxy_" + eventE.Name);
58           eventE.AddEventHandler(HandledObject, del);
59         }
60       }
61     }
62
63     public object HandledObject 
64     {
65       get {
66         return this.handledObject;
67       }
68       
69       set {
70         this.handledObject = value;
71         
72         // Register the methods
73         this.introspector = Introspector.GetIntrospector(value.GetType());        
74       }
75     }
76
77     public void Unregister_Called(IntPtr rawConnection, 
78                                   IntPtr userData)
79     {
80       if (service != null) {
81         service.UnregisterObject(HandledObject);
82       }
83
84       path = null;
85     }
86
87     private int Message_Called(IntPtr rawConnection, 
88                                IntPtr rawMessage, 
89                                IntPtr userData) 
90     {
91       Message message = Message.Wrap(rawMessage, Service);
92       Result res = Result.NotYetHandled;
93
94       switch (message.Type) {
95       case Message.MessageType.MethodCall:
96         res = HandleMethod ((MethodCall) message);
97         break;
98
99       case Message.MessageType.Signal:
100         // We're not interested in signals here because we're the ones
101         // that generate them!
102         break;
103       }
104
105       message.Dispose ();
106
107       return (int) res;
108     }
109     
110     private Result HandleMethod(MethodCall methodCall)
111     {
112       methodCall.Service = service;
113       
114       InterfaceProxy interfaceProxy = this.introspector.GetInterface(methodCall.InterfaceName);
115       if (interfaceProxy == null || !interfaceProxy.HasMethod(methodCall.Key)) {
116         // No such interface here.
117         return Result.NotYetHandled;
118       }
119       
120       MethodInfo method = interfaceProxy.GetMethod(methodCall.Key);
121       
122       Message.Push (methodCall);
123
124       // Now call the method. FIXME: Error handling
125       object [] args = methodCall.Arguments.GetParameters(method);
126       object retVal = method.Invoke(this.handledObject, args);
127
128       Message.Pop ();
129
130       // Create the reply and send it
131       MethodReturn methodReturn = new MethodReturn(methodCall);
132       methodReturn.Arguments.AppendResults(method, retVal, args);
133       methodReturn.Send();
134
135       return Result.Handled;
136     }
137
138     internal string Path 
139     {
140       get 
141         {
142           return path;
143         }
144     }
145
146     internal Connection Connection 
147     {
148       get
149         {
150           return connection;
151         }
152       
153       set 
154         {
155           this.connection = value;
156         }
157     }
158
159     public Service Service
160     {
161       get
162         {
163           return service;
164         }
165       
166       set 
167         {
168           this.service = value;
169         }
170     }
171   }
172 }