no message
[mono.git] / mcs / class / corlib / System.Runtime.Remoting / RemotingServices.cs
1 //
2 // System.Runtime.Remoting.RemotingServices.cs
3 //
4 // Authors:
5 //   Dietmar Maurer (dietmar@ximian.com)
6 //   Lluis Sanchez Gual (lsg@ctv.es)
7 //
8 // (C) 2001 Ximian, Inc.  http://www.ximian.com
9 //
10
11 using System;
12 using System.Reflection;
13 using System.Threading;
14 using System.Collections;
15 using System.Runtime.Remoting.Messaging;
16 using System.Runtime.Remoting.Proxies;
17 using System.Runtime.Remoting.Channels;
18 using System.Runtime.Remoting.Contexts;
19 using System.Runtime.CompilerServices;
20 using System.Runtime.Serialization;
21
22 namespace System.Runtime.Remoting
23 {
24         public sealed class RemotingServices 
25         {
26                 // Holds the identities of the objects, using uri as index
27                 static Hashtable uri_hash = new Hashtable ();           
28
29                 internal static string app_id;
30                 static int next_id = 1;
31                 
32                 static RemotingServices ()
33                 {
34                          app_id = "/" + Guid.NewGuid().ToString().Replace('-', '_') + "/";
35                 }
36         
37                 private RemotingServices () {}
38
39                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
40                 internal extern static object InternalExecute (MonoMethod method, Object obj,
41                                                                Object[] parameters, out object [] out_args);
42
43                 [MethodImplAttribute(MethodImplOptions.InternalCall)]
44                 public extern static bool IsTransparentProxy (object proxy);
45                 
46                 internal static IMethodReturnMessage InternalExecuteMessage (
47                         MarshalByRefObject target, IMethodCallMessage reqMsg)
48                 {
49                         ReturnMessage result;
50                         
51                         MonoMethod method = (MonoMethod)reqMsg.MethodBase;
52
53                         try {
54                                 object [] out_args;
55                                 object rval = InternalExecute (method, target, reqMsg.Args, out out_args);
56                                 result = new ReturnMessage (rval, out_args, out_args.Length,
57                                                             reqMsg.LogicalCallContext, reqMsg);
58                         
59                         } catch (Exception e) {
60                                 result = new ReturnMessage (e, reqMsg);
61                         }
62
63                         return result;
64                 }
65
66                 public static IMethodReturnMessage ExecuteMessage (
67                         MarshalByRefObject target, IMethodCallMessage reqMsg)
68                 {
69                         if (IsTransparentProxy(target))
70                         {
71                                 // Message must go through all chain of sinks
72                                 RealProxy rp = GetRealProxy (target);
73                                 return (IMethodReturnMessage) rp.Invoke (reqMsg);
74                         }
75                         else    // Direct call
76                                 return InternalExecuteMessage (target, reqMsg);
77                 }
78
79                 public static object Connect (Type classToProxy, string url)
80                 {
81                         return GetRemoteObject(classToProxy, url, null);
82                 }
83
84                 public static object Connect (Type classToProxy, string url, object data)
85                 {
86                         return GetRemoteObject (classToProxy, url, data);
87                 }
88
89                 public static Type GetServerTypeForUri (string uri)
90                 {
91                         object svr = GetServerForUri (uri);
92
93                         if (svr == null)
94                                 return null;
95                         
96                         return svr.GetType ();
97                 }
98
99                 public static string GetObjectUri (MarshalByRefObject obj)
100                 {
101                         if (IsTransparentProxy(obj))
102                         {
103                                 return GetRealProxy (obj).ObjectIdentity.ObjectUri;
104                         }
105                         else
106                                 return obj.ObjectIdentity.ObjectUri;
107                 }
108                 
109                 internal static MarshalByRefObject GetServerForUri (string uri)
110                 {
111                         lock (uri_hash)
112                         {
113                                 return (MarshalByRefObject)((Identity)uri_hash [uri]).RealObject;
114                         }
115                 }
116
117                 internal static Identity GetIdentityForUri (string uri)
118                 {
119                         lock (uri_hash)
120                         {
121                                 return (Identity)uri_hash [uri];
122                         }
123                 }
124
125                 private static Identity GetClientIdentity(Type requiredType, string url, object channelData)
126                 {
127                         // This method looks for an identity for the given url. 
128                         // If an identity is not found, it creates the identity and 
129                         // assigns it a proxy to the remote object.
130
131                         // Creates the client sink chain for the given url or channelData.
132                         // It will also get the object uri from the url.
133
134                         string objectUri;
135                         IMessageSink sink = ChannelServices.CreateClientChannelSinkChain (url, channelData, out objectUri);
136                         if (sink == null) 
137                         {
138                                 string msg = String.Format ("Cannot create channel sink to connect to URL {0}.", url); 
139                                 throw new RemotingException (msg);
140                         }
141
142                         lock (uri_hash)
143                         {
144                                 Identity identity = (Identity)uri_hash [objectUri];
145                                 if (identity != null) 
146                                         return identity;        // Object already registered
147
148                                 // Creates an identity and a proxy for the remote object
149
150                                 identity = new Identity(objectUri, null, requiredType);
151                                 identity.ClientSink = sink;
152
153                                 RemotingProxy proxy = new RemotingProxy (requiredType, identity);
154                                 identity.RealObject = proxy.GetTransparentProxy();
155
156                                 // Registers the identity
157                                 uri_hash [objectUri] = identity;
158                                 return identity;
159                         }
160                 }
161
162                 private static Identity GetServerIdentity(MarshalByRefObject realObject, string objectUri)
163                 {
164                         // This method looks for an identity for the given object. 
165                         // If an identity is not found, it creates the identity and 
166                         // assigns it to the given object
167
168                         lock (uri_hash)
169                         {
170                                 Identity identity = (Identity)uri_hash [objectUri];
171                                 if (identity != null) 
172                                         return identity;        // Object already registered
173
174                                 identity = new Identity (objectUri, Context.DefaultContext, realObject.GetType());
175                                 identity.RealObject = realObject;
176
177                                 // Registers the identity
178                                 uri_hash[objectUri] = identity;
179                                 realObject.ObjectIdentity = identity;
180
181                                 return identity;
182                         }
183                 }
184
185                 internal static object GetRemoteObject(Type requiredType, string url, object channelData)
186                 {
187                         Identity id = GetClientIdentity(requiredType, url, channelData);
188                         return id.RealObject;
189                 }
190                 
191                 public static object Unmarshal (ObjRef objref)
192                 {
193                         return Unmarshal(objref, false);
194                 }
195
196                 public static object Unmarshal (ObjRef objref, bool fRefine)
197                 {
198                         // FIXME: use type name when fRefine==true
199                         Type requiredType = Type.GetType(objref.TypeInfo.TypeName);
200                         return GetRemoteObject(requiredType, null, objref.ChannelInfo.ChannelData);
201                 }
202
203                 public static ObjRef Marshal (MarshalByRefObject obj)
204                 {
205                         return Marshal (obj, null, null);
206                 }
207                 
208                 public static ObjRef Marshal (MarshalByRefObject obj, string uri)
209                 {
210                         return Marshal (obj, uri, null);
211                 }
212                 
213                 public static ObjRef Marshal (MarshalByRefObject obj, string uri, Type requested_type)
214                 {
215                         if (IsTransparentProxy (obj))
216                         {
217                                 RealProxy proxy = RemotingServices.GetRealProxy(obj);
218                                 if (proxy != null && proxy.ObjectIdentity != null)
219                                 {
220                                         if (uri != null)
221                                                 throw new RemotingException ("It is not possible marshal a proxy of a remote object");
222
223                                         return proxy.ObjectIdentity.CreateObjRef(requested_type);
224                                 }
225                         }
226
227                         if (uri == null) uri = app_id + Environment.TickCount + "_" + next_id++;
228
229                         // It creates the identity if not found
230                         Identity identity = GetServerIdentity (obj, uri);
231
232                         if (obj != identity.RealObject)
233                                 throw new RemotingException ("uri already in use, " + uri);
234                                         // already registered
235
236                         return identity.CreateObjRef(requested_type);
237                 }
238
239                 public static RealProxy GetRealProxy (object proxy)
240                 {
241                         if (!IsTransparentProxy(proxy)) throw new RemotingException("Cannot get the real proxy from an object that is not a transparent proxy");
242                         return (RealProxy)((TransparentProxy)proxy)._rp;
243                 }
244         }
245
246 }