2010-04-06 Jb Evain <jbevain@novell.com>
[mcs.git] / class / corlib / System.Runtime.Remoting / ServerIdentity.cs
blob1e075d88b3647f9f3941970a7d57ed6dbc415d87
1 //
2 // System.Runtime.Remoting.Identity.cs
3 //
4 // Author: Lluis Sanchez Gual (lluis@ideary.com)
5 //
6 // (C) 2002, Lluis Sanchez Gual
7 //
9 //
10 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
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.
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 using System.Runtime.Remoting.Services;
39 namespace System.Runtime.Remoting
41 internal abstract class ServerIdentity : Identity
43 protected Type _objectType;
45 protected MarshalByRefObject _serverObject;
47 // Message sink used in the server to dispatch a message
48 // to the server object
49 protected IMessageSink _serverSink = null;
51 protected Context _context;
52 protected Lease _lease;
54 public ServerIdentity (string objectUri, Context context, Type objectType): base (objectUri)
56 _objectType = objectType;
57 _context = context;
60 public Type ObjectType
62 get { return _objectType; }
65 public void StartTrackingLifetime (ILease lease)
67 // Adds this identity to the LeaseManager.
68 // _serverObject must be set.
70 if (lease != null && lease.CurrentState == LeaseState.Null) lease = null;
72 if (lease != null)
74 if (! (lease is Lease)) lease = new Lease(); // This seems to be MS behavior
75 _lease = (Lease) lease;
76 LifetimeServices.TrackLifetime (this);
80 public virtual void OnLifetimeExpired()
82 DisposeServerObject();
85 public override ObjRef CreateObjRef (Type requestedType)
87 if (_objRef != null)
89 // Just update channel info. It may have changed.
90 _objRef.UpdateChannelInfo();
91 return _objRef;
94 if (requestedType == null) requestedType = _objectType;
95 _objRef = new ObjRef ();
96 _objRef.TypeInfo = new TypeInfo(requestedType);
97 _objRef.URI = _objectUri;
99 if (_envoySink != null && !(_envoySink is EnvoyTerminatorSink))
100 _objRef.EnvoyInfo = new EnvoyInfo (_envoySink);
102 return _objRef;
105 public void AttachServerObject (MarshalByRefObject serverObject, Context context)
107 DisposeServerObject();
109 _context = context;
110 _serverObject = serverObject;
112 if (RemotingServices.IsTransparentProxy (serverObject))
114 RealProxy rp = RemotingServices.GetRealProxy (serverObject);
115 if (rp.ObjectIdentity == null)
116 rp.ObjectIdentity = this;
118 else
120 if (_objectType.IsContextful)
121 _envoySink = context.CreateEnvoySink (serverObject);
123 _serverObject.ObjectIdentity = this;
127 public Lease Lease
129 get { return _lease; }
132 public Context Context
134 get { return _context; }
135 set { _context = value; }
138 public abstract IMessage SyncObjectProcessMessage (IMessage msg);
139 public abstract IMessageCtrl AsyncObjectProcessMessage (IMessage msg, IMessageSink replySink);
141 protected void DisposeServerObject()
143 // Detach identity from server object to avoid problems if the
144 // object is marshalled again.
146 if (_serverObject != null) {
147 MarshalByRefObject obj = _serverObject;
148 _serverObject.ObjectIdentity = null;
149 _serverObject = null;
150 _serverSink = null;
151 TrackingServices.NotifyDisconnectedObject (obj);
156 internal class ClientActivatedIdentity : ServerIdentity
158 MarshalByRefObject _targetThis;
160 public ClientActivatedIdentity (string objectUri, Type objectType): base (objectUri, null, objectType)
164 public MarshalByRefObject GetServerObject ()
166 return _serverObject;
169 public MarshalByRefObject GetClientProxy ()
171 return _targetThis;
174 public void SetClientProxy (MarshalByRefObject obj)
176 _targetThis = obj;
179 public override void OnLifetimeExpired()
181 base.OnLifetimeExpired();
182 RemotingServices.DisposeIdentity (this);
185 public override IMessage SyncObjectProcessMessage (IMessage msg)
187 if (_serverSink == null) {
188 bool useProxy = _targetThis != null;
189 _serverSink = _context.CreateServerObjectSinkChain ((useProxy ? _targetThis : _serverObject), useProxy);
191 return _serverSink.SyncProcessMessage (msg);
194 public override IMessageCtrl AsyncObjectProcessMessage (IMessage msg, IMessageSink replySink)
196 if (_serverSink == null) {
197 bool useProxy = _targetThis != null;
198 _serverSink = _context.CreateServerObjectSinkChain ((useProxy ? _targetThis : _serverObject), useProxy);
200 return _serverSink.AsyncProcessMessage (msg, replySink);
204 internal class SingletonIdentity : ServerIdentity
206 public SingletonIdentity (string objectUri, Context context, Type objectType): base (objectUri, context, objectType)
210 public MarshalByRefObject GetServerObject ()
212 if (_serverObject != null) return _serverObject;
214 lock (this)
216 if (_serverObject == null) {
217 MarshalByRefObject server = (MarshalByRefObject) Activator.CreateInstance (_objectType, true);
218 AttachServerObject (server, Context.DefaultContext);
219 StartTrackingLifetime ((ILease)server.InitializeLifetimeService ());
222 return _serverObject;
225 public override IMessage SyncObjectProcessMessage (IMessage msg)
227 MarshalByRefObject obj = GetServerObject ();
228 if (_serverSink == null) _serverSink = _context.CreateServerObjectSinkChain (obj, false);
229 return _serverSink.SyncProcessMessage (msg);
232 public override IMessageCtrl AsyncObjectProcessMessage (IMessage msg, IMessageSink replySink)
234 MarshalByRefObject obj = GetServerObject ();
235 if (_serverSink == null) _serverSink = _context.CreateServerObjectSinkChain (obj, false);
236 return _serverSink.AsyncProcessMessage (msg, replySink);
240 internal class SingleCallIdentity : ServerIdentity
242 public SingleCallIdentity (string objectUri, Context context, Type objectType): base (objectUri, context, objectType)
246 public override IMessage SyncObjectProcessMessage (IMessage msg)
248 // SingleCallIdentity creates and disposes an instance in each call
250 MarshalByRefObject obj = (MarshalByRefObject)Activator.CreateInstance (_objectType, true);
251 if (obj.ObjectIdentity == null) obj.ObjectIdentity = this;
252 IMessageSink serverSink = _context.CreateServerObjectSinkChain (obj, false);
253 IMessage result = serverSink.SyncProcessMessage (msg);
254 if (obj is IDisposable) ((IDisposable)obj).Dispose();
255 return result;
258 public override IMessageCtrl AsyncObjectProcessMessage (IMessage msg, IMessageSink replySink)
260 MarshalByRefObject obj = (MarshalByRefObject)Activator.CreateInstance (_objectType, true);
261 IMessageSink serverSink = _context.CreateServerObjectSinkChain (obj, false);
262 if (obj is IDisposable) replySink = new DisposerReplySink(replySink, ((IDisposable)obj));
263 return serverSink.AsyncProcessMessage (msg, replySink);
267 internal class DisposerReplySink : IMessageSink
269 IMessageSink _next;
270 IDisposable _disposable;
272 public DisposerReplySink (IMessageSink next, IDisposable disposable)
274 _next = next;
275 _disposable = disposable;
278 public IMessage SyncProcessMessage (IMessage msg)
280 _disposable.Dispose();
281 return _next.SyncProcessMessage (msg);
284 public IMessageCtrl AsyncProcessMessage (IMessage msg, IMessageSink replySink)
286 throw new NotSupportedException();
289 public IMessageSink NextSink
291 get { return _next; }