2 // System.Runtime.Remoting.Identity.cs
4 // Author: Lluis Sanchez Gual (lluis@ideary.com)
6 // (C) 2002, Lluis Sanchez Gual
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:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
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.
33 using System.Runtime.Remoting.Messaging;
34 using System.Runtime.Remoting.Contexts;
35 using System.Runtime.Remoting.Lifetime;
36 using System.Runtime.Remoting.Proxies;
38 namespace System.Runtime.Remoting
40 internal abstract class ServerIdentity : Identity
42 protected Type _objectType;
44 protected MarshalByRefObject _serverObject;
46 // Message sink used in the server to dispatch a message
47 // to the server object
48 protected IMessageSink _serverSink = null;
50 protected Context _context;
51 protected Lease _lease;
53 public ServerIdentity (string objectUri, Context context, Type objectType): base (objectUri)
55 _objectType = objectType;
59 public Type ObjectType
61 get { return _objectType; }
64 public void StartTrackingLifetime (ILease lease)
66 // Adds this identity to the LeaseManager.
67 // _serverObject must be set.
69 if (lease != null && lease.CurrentState == LeaseState.Null) lease = null;
73 if (! (lease is Lease)) lease = new Lease(); // This seems to be MS behavior
74 _lease = (Lease) lease;
75 LifetimeServices.TrackLifetime (this);
79 public virtual void OnLifetimeExpired()
81 DisposeServerObject();
84 public override ObjRef CreateObjRef (Type requestedType)
88 // Just update channel info. It may have changed.
89 _objRef.UpdateChannelInfo();
93 if (requestedType == null) requestedType = _objectType;
94 _objRef = new ObjRef ();
95 _objRef.TypeInfo = new TypeInfo(requestedType);
96 _objRef.URI = _objectUri;
98 if (_envoySink != null && !(_envoySink is EnvoyTerminatorSink))
99 _objRef.EnvoyInfo = new EnvoyInfo (_envoySink);
104 public void AttachServerObject (MarshalByRefObject serverObject, Context context)
106 DisposeServerObject();
109 _serverObject = serverObject;
111 if (RemotingServices.IsTransparentProxy (serverObject))
113 RealProxy rp = RemotingServices.GetRealProxy (serverObject);
114 if (rp.ObjectIdentity == null)
115 rp.ObjectIdentity = this;
119 if (_objectType.IsContextful)
120 _envoySink = context.CreateEnvoySink (serverObject);
122 _serverObject.ObjectIdentity = this;
128 get { return _lease; }
131 public Context Context
133 get { return _context; }
134 set { _context = value; }
137 public abstract IMessage SyncObjectProcessMessage (IMessage msg);
138 public abstract IMessageCtrl AsyncObjectProcessMessage (IMessage msg, IMessageSink replySink);
140 protected void DisposeServerObject()
142 // Detach identity from server object to avoid problems if the
143 // object is marshalled again.
145 if (_serverObject != null) {
146 _serverObject.ObjectIdentity = null;
147 _serverObject = null;
153 internal class ClientActivatedIdentity : ServerIdentity
155 MarshalByRefObject _targetThis;
157 public ClientActivatedIdentity (string objectUri, Type objectType): base (objectUri, null, objectType)
161 public MarshalByRefObject GetServerObject ()
163 return _serverObject;
166 public MarshalByRefObject GetClientProxy ()
171 public void SetClientProxy (MarshalByRefObject obj)
176 public override void OnLifetimeExpired()
178 base.OnLifetimeExpired();
179 RemotingServices.DisposeIdentity (this);
182 public override IMessage SyncObjectProcessMessage (IMessage msg)
184 if (_serverSink == null) {
185 bool useProxy = _targetThis != null;
186 _serverSink = _context.CreateServerObjectSinkChain ((useProxy ? _targetThis : _serverObject), useProxy);
188 return _serverSink.SyncProcessMessage (msg);
191 public override IMessageCtrl AsyncObjectProcessMessage (IMessage msg, IMessageSink replySink)
193 if (_serverSink == null) {
194 bool useProxy = _targetThis != null;
195 _serverSink = _context.CreateServerObjectSinkChain ((useProxy ? _targetThis : _serverObject), useProxy);
197 return _serverSink.AsyncProcessMessage (msg, replySink);
201 internal class SingletonIdentity : ServerIdentity
203 public SingletonIdentity (string objectUri, Context context, Type objectType): base (objectUri, context, objectType)
207 public MarshalByRefObject GetServerObject ()
209 if (_serverObject != null) return _serverObject;
213 if (_serverObject == null) {
214 MarshalByRefObject server = (MarshalByRefObject) Activator.CreateInstance (_objectType, true);
215 AttachServerObject (server, Context.DefaultContext);
216 StartTrackingLifetime ((ILease)server.InitializeLifetimeService ());
219 return _serverObject;
222 public override IMessage SyncObjectProcessMessage (IMessage msg)
224 MarshalByRefObject obj = GetServerObject ();
225 if (_serverSink == null) _serverSink = _context.CreateServerObjectSinkChain (obj, false);
226 return _serverSink.SyncProcessMessage (msg);
229 public override IMessageCtrl AsyncObjectProcessMessage (IMessage msg, IMessageSink replySink)
231 MarshalByRefObject obj = GetServerObject ();
232 if (_serverSink == null) _serverSink = _context.CreateServerObjectSinkChain (obj, false);
233 return _serverSink.AsyncProcessMessage (msg, replySink);
237 internal class SingleCallIdentity : ServerIdentity
239 public SingleCallIdentity (string objectUri, Context context, Type objectType): base (objectUri, context, objectType)
243 public override IMessage SyncObjectProcessMessage (IMessage msg)
245 // SingleCallIdentity creates and disposes an instance in each call
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();
255 public override IMessageCtrl AsyncObjectProcessMessage (IMessage msg, IMessageSink replySink)
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);
264 internal class DisposerReplySink : IMessageSink
267 IDisposable _disposable;
269 public DisposerReplySink (IMessageSink next, IDisposable disposable)
272 _disposable = disposable;
275 public IMessage SyncProcessMessage (IMessage msg)
277 _disposable.Dispose();
278 return _next.SyncProcessMessage (msg);
281 public IMessageCtrl AsyncProcessMessage (IMessage msg, IMessageSink replySink)
283 throw new NotSupportedException();
286 public IMessageSink NextSink
288 get { return _next; }