a set of cosmetic part of 2.0 remoting API fixes.
[mono.git] / mcs / class / corlib / System.Runtime.Remoting / ServerIdentity.cs
1 //
2 // System.Runtime.Remoting.Identity.cs
3 //
4 // Author: Lluis Sanchez Gual (lluis@ideary.com)
5 //
6 // (C) 2002, Lluis Sanchez Gual
7 //
8
9 //
10 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
11 //
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
19 // 
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
22 // 
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
30 //
31
32 using System;
33 using System.Runtime.Remoting.Messaging;
34 using System.Runtime.Remoting.Contexts;
35 using System.Runtime.Remoting.Lifetime;
36 using System.Runtime.Remoting.Proxies;
37
38 namespace System.Runtime.Remoting
39 {
40         internal abstract class ServerIdentity : Identity
41         {
42                 protected Type _objectType;
43
44                 protected MarshalByRefObject _serverObject;
45
46                 // Message sink used in the server to dispatch a message
47                 // to the server object
48                 protected IMessageSink _serverSink = null;
49
50                 protected Context _context;
51                 protected Lease _lease;
52
53                 public ServerIdentity (string objectUri, Context context, Type objectType): base (objectUri)
54                 {
55                         _objectType = objectType;
56                         _context = context;
57                 }
58
59                 public Type ObjectType
60                 {
61                         get { return _objectType; }
62                 }
63
64                 public void StartTrackingLifetime (ILease lease)
65                 {
66                         // Adds this identity to the LeaseManager. 
67                         // _serverObject must be set.
68
69                         if (lease != null && lease.CurrentState == LeaseState.Null) lease = null;
70
71                         if (lease != null) 
72                         {
73                                 if (! (lease is Lease)) lease = new Lease();  // This seems to be MS behavior
74                                 _lease = (Lease) lease;
75                                 LifetimeServices.TrackLifetime (this);
76                         }
77                 }
78
79                 public virtual void OnLifetimeExpired()
80                 {
81                         DisposeServerObject();
82                 }
83
84                 public override ObjRef CreateObjRef (Type requestedType)
85                 {
86                         if (_objRef != null)
87                         {
88                                 // Just update channel info. It may have changed.
89                                 _objRef.UpdateChannelInfo();
90                                 return _objRef;
91                         }
92
93                         if (requestedType == null) requestedType = _objectType;
94                         _objRef = new ObjRef ();
95                         _objRef.TypeInfo = new TypeInfo(requestedType);
96                         _objRef.URI = _objectUri;
97
98                         if (_envoySink != null && !(_envoySink is EnvoyTerminatorSink))
99                                 _objRef.EnvoyInfo = new EnvoyInfo (_envoySink);
100
101                         return _objRef;
102                 }
103
104                 public void AttachServerObject (MarshalByRefObject serverObject, Context context)
105                 {
106                         DisposeServerObject();
107
108                         _context = context;
109                         _serverObject = serverObject;
110                         
111                         if (RemotingServices.IsTransparentProxy (serverObject))
112                         {
113                                 RealProxy rp = RemotingServices.GetRealProxy (serverObject);
114                                 if (rp.ObjectIdentity == null)
115                                         rp.ObjectIdentity = this;
116                         }
117                         else
118                         {
119                                 if (_objectType.IsContextful)
120                                         _envoySink = context.CreateEnvoySink (serverObject);
121         
122                                 _serverObject.ObjectIdentity = this;
123                         }
124                 }
125
126                 public Lease Lease
127                 {
128                         get { return _lease; }
129                 }
130
131                 public Context Context
132                 {
133                         get { return _context; }
134                         set { _context = value; }
135                 }
136
137                 public abstract IMessage SyncObjectProcessMessage (IMessage msg);
138                 public abstract IMessageCtrl AsyncObjectProcessMessage (IMessage msg, IMessageSink replySink);
139
140                 protected void DisposeServerObject()
141                 {
142                         // Detach identity from server object to avoid problems if the
143                         // object is marshalled again.
144                         
145                         if (_serverObject != null) {
146                                 _serverObject.ObjectIdentity = null;
147                                 _serverObject = null;
148                                 _serverSink = null;
149                         }
150                 }
151         }
152
153         internal class ClientActivatedIdentity : ServerIdentity
154         {
155                 MarshalByRefObject _targetThis;
156                 
157                 public ClientActivatedIdentity (string objectUri, Type objectType): base (objectUri, null, objectType)
158                 {
159                 }
160         
161                 public MarshalByRefObject GetServerObject ()
162                 {
163                         return _serverObject;
164                 }
165
166                 public MarshalByRefObject GetClientProxy ()
167                 {
168                         return _targetThis;
169                 }
170                 
171                 public void SetClientProxy (MarshalByRefObject obj)
172                 {
173                         _targetThis = obj;
174                 }
175
176                 public override void OnLifetimeExpired()
177                 {
178                         base.OnLifetimeExpired();
179                         RemotingServices.DisposeIdentity (this);
180                 }
181
182                 public override IMessage SyncObjectProcessMessage (IMessage msg)
183                 {
184                         if (_serverSink == null) {
185                                 bool useProxy = _targetThis != null;
186                                 _serverSink = _context.CreateServerObjectSinkChain ((useProxy ? _targetThis : _serverObject), useProxy);
187                         }
188                         return _serverSink.SyncProcessMessage (msg);
189                 }
190
191                 public override IMessageCtrl AsyncObjectProcessMessage (IMessage msg, IMessageSink replySink)
192                 {
193                         if (_serverSink == null) {
194                                 bool useProxy = _targetThis != null;
195                                 _serverSink = _context.CreateServerObjectSinkChain ((useProxy ? _targetThis : _serverObject), useProxy);
196                         }
197                         return _serverSink.AsyncProcessMessage (msg, replySink);
198                 }       
199         }
200
201         internal class SingletonIdentity : ServerIdentity
202         {
203                 public SingletonIdentity (string objectUri, Context context, Type objectType): base (objectUri, context, objectType)
204                 {
205                 }
206
207                 public MarshalByRefObject GetServerObject ()
208                 {
209                         if (_serverObject != null) return _serverObject;
210
211                         lock (this) 
212                         {
213                                 if (_serverObject == null) {
214                                         MarshalByRefObject server = (MarshalByRefObject) Activator.CreateInstance (_objectType, true);
215                                         AttachServerObject (server, Context.DefaultContext);
216                                         StartTrackingLifetime ((ILease)server.InitializeLifetimeService ());
217                                 }
218                         }
219                         return _serverObject;
220                 }
221
222                 public override IMessage SyncObjectProcessMessage (IMessage msg)
223                 {
224                         MarshalByRefObject obj = GetServerObject ();
225                         if (_serverSink == null) _serverSink = _context.CreateServerObjectSinkChain (obj, false);
226                         return _serverSink.SyncProcessMessage (msg);
227                 }
228
229                 public override IMessageCtrl AsyncObjectProcessMessage (IMessage msg, IMessageSink replySink)
230                 {
231                         MarshalByRefObject obj = GetServerObject ();
232                         if (_serverSink == null) _serverSink = _context.CreateServerObjectSinkChain (obj, false);
233                         return _serverSink.AsyncProcessMessage (msg, replySink);
234                 }       
235         }
236
237         internal class SingleCallIdentity : ServerIdentity
238         {
239                 public SingleCallIdentity (string objectUri, Context context, Type objectType): base (objectUri, context, objectType)
240                 {
241                 }
242
243                 public override IMessage SyncObjectProcessMessage (IMessage msg)
244                 {
245                         // SingleCallIdentity creates and disposes an instance in each call
246
247                         MarshalByRefObject obj = (MarshalByRefObject)Activator.CreateInstance (_objectType, true);
248                         if (obj.ObjectIdentity == null) obj.ObjectIdentity = this;
249                         IMessageSink serverSink = _context.CreateServerObjectSinkChain (obj, false);
250                         IMessage result = serverSink.SyncProcessMessage (msg);
251                         if (obj is IDisposable) ((IDisposable)obj).Dispose();
252                         return result;
253                 }
254
255                 public override IMessageCtrl AsyncObjectProcessMessage (IMessage msg, IMessageSink replySink)
256                 {
257                         MarshalByRefObject obj = (MarshalByRefObject)Activator.CreateInstance (_objectType, true);
258                         IMessageSink serverSink = _context.CreateServerObjectSinkChain (obj, false);
259                         if (obj is IDisposable) replySink = new DisposerReplySink(replySink, ((IDisposable)obj));
260                         return serverSink.AsyncProcessMessage (msg, replySink);
261                 }       
262         }
263
264         internal class DisposerReplySink : IMessageSink
265         {
266                 IMessageSink _next;
267                 IDisposable _disposable;
268
269                 public DisposerReplySink (IMessageSink next, IDisposable disposable)
270                 {
271                         _next = next;
272                         _disposable = disposable;
273                 }
274
275                 public IMessage SyncProcessMessage (IMessage msg)
276                 {
277                         _disposable.Dispose();
278                         return _next.SyncProcessMessage (msg);
279                 }
280
281                 public IMessageCtrl AsyncProcessMessage (IMessage msg, IMessageSink replySink)
282                 {
283                         throw new NotSupportedException();
284                 }
285
286                 public IMessageSink NextSink
287                 {
288                         get { return _next; }
289                 }
290         }
291 }