a575963da9
Former-commit-id: da6be194a6b1221998fc28233f2503bd61dd9d14
295 lines
8.2 KiB
C#
295 lines
8.2 KiB
C#
//
|
|
// System.Runtime.Remoting.Identity.cs
|
|
//
|
|
// Author: Lluis Sanchez Gual (lluis@ideary.com)
|
|
//
|
|
// (C) 2002, Lluis Sanchez Gual
|
|
//
|
|
|
|
//
|
|
// Copyright (C) 2004 Novell, Inc (http://www.novell.com)
|
|
//
|
|
// Permission is hereby granted, free of charge, to any person obtaining
|
|
// a copy of this software and associated documentation files (the
|
|
// "Software"), to deal in the Software without restriction, including
|
|
// without limitation the rights to use, copy, modify, merge, publish,
|
|
// distribute, sublicense, and/or sell copies of the Software, and to
|
|
// permit persons to whom the Software is furnished to do so, subject to
|
|
// the following conditions:
|
|
//
|
|
// The above copyright notice and this permission notice shall be
|
|
// included in all copies or substantial portions of the Software.
|
|
//
|
|
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
//
|
|
|
|
using System;
|
|
using System.Runtime.Remoting.Messaging;
|
|
using System.Runtime.Remoting.Contexts;
|
|
using System.Runtime.Remoting.Lifetime;
|
|
using System.Runtime.Remoting.Proxies;
|
|
using System.Runtime.Remoting.Services;
|
|
|
|
namespace System.Runtime.Remoting
|
|
{
|
|
internal abstract class ServerIdentity : Identity
|
|
{
|
|
protected Type _objectType;
|
|
|
|
protected MarshalByRefObject _serverObject;
|
|
|
|
// Message sink used in the server to dispatch a message
|
|
// to the server object
|
|
protected IMessageSink _serverSink = null;
|
|
|
|
protected Context _context;
|
|
protected Lease _lease;
|
|
|
|
public ServerIdentity (string objectUri, Context context, Type objectType): base (objectUri)
|
|
{
|
|
_objectType = objectType;
|
|
_context = context;
|
|
}
|
|
|
|
public Type ObjectType
|
|
{
|
|
get { return _objectType; }
|
|
}
|
|
|
|
public void StartTrackingLifetime (ILease lease)
|
|
{
|
|
// Adds this identity to the LeaseManager.
|
|
// _serverObject must be set.
|
|
|
|
if (lease != null && lease.CurrentState == LeaseState.Null) lease = null;
|
|
|
|
if (lease != null)
|
|
{
|
|
if (! (lease is Lease)) lease = new Lease(); // This seems to be MS behavior
|
|
_lease = (Lease) lease;
|
|
LifetimeServices.TrackLifetime (this);
|
|
}
|
|
}
|
|
|
|
public virtual void OnLifetimeExpired()
|
|
{
|
|
DisposeServerObject();
|
|
}
|
|
|
|
public override ObjRef CreateObjRef (Type requestedType)
|
|
{
|
|
if (_objRef != null)
|
|
{
|
|
// Just update channel info. It may have changed.
|
|
_objRef.UpdateChannelInfo();
|
|
return _objRef;
|
|
}
|
|
|
|
if (requestedType == null) requestedType = _objectType;
|
|
_objRef = new ObjRef ();
|
|
_objRef.TypeInfo = new TypeInfo(requestedType);
|
|
_objRef.URI = _objectUri;
|
|
|
|
if (_envoySink != null && !(_envoySink is EnvoyTerminatorSink))
|
|
_objRef.EnvoyInfo = new EnvoyInfo (_envoySink);
|
|
|
|
return _objRef;
|
|
}
|
|
|
|
public void AttachServerObject (MarshalByRefObject serverObject, Context context)
|
|
{
|
|
DisposeServerObject();
|
|
|
|
_context = context;
|
|
_serverObject = serverObject;
|
|
|
|
if (RemotingServices.IsTransparentProxy (serverObject))
|
|
{
|
|
RealProxy rp = RemotingServices.GetRealProxy (serverObject);
|
|
if (rp.ObjectIdentity == null)
|
|
rp.ObjectIdentity = this;
|
|
}
|
|
else
|
|
{
|
|
if (_objectType.IsContextful)
|
|
_envoySink = context.CreateEnvoySink (serverObject);
|
|
|
|
_serverObject.ObjectIdentity = this;
|
|
}
|
|
}
|
|
|
|
public Lease Lease
|
|
{
|
|
get { return _lease; }
|
|
}
|
|
|
|
public Context Context
|
|
{
|
|
get { return _context; }
|
|
set { _context = value; }
|
|
}
|
|
|
|
public abstract IMessage SyncObjectProcessMessage (IMessage msg);
|
|
public abstract IMessageCtrl AsyncObjectProcessMessage (IMessage msg, IMessageSink replySink);
|
|
|
|
protected void DisposeServerObject()
|
|
{
|
|
// Detach identity from server object to avoid problems if the
|
|
// object is marshalled again.
|
|
|
|
if (_serverObject != null) {
|
|
MarshalByRefObject obj = _serverObject;
|
|
_serverObject.ObjectIdentity = null;
|
|
_serverObject = null;
|
|
_serverSink = null;
|
|
TrackingServices.NotifyDisconnectedObject (obj);
|
|
}
|
|
}
|
|
}
|
|
|
|
internal class ClientActivatedIdentity : ServerIdentity
|
|
{
|
|
MarshalByRefObject _targetThis;
|
|
|
|
public ClientActivatedIdentity (string objectUri, Type objectType): base (objectUri, null, objectType)
|
|
{
|
|
}
|
|
|
|
public MarshalByRefObject GetServerObject ()
|
|
{
|
|
return _serverObject;
|
|
}
|
|
|
|
public MarshalByRefObject GetClientProxy ()
|
|
{
|
|
return _targetThis;
|
|
}
|
|
|
|
public void SetClientProxy (MarshalByRefObject obj)
|
|
{
|
|
_targetThis = obj;
|
|
}
|
|
|
|
public override void OnLifetimeExpired()
|
|
{
|
|
base.OnLifetimeExpired();
|
|
RemotingServices.DisposeIdentity (this);
|
|
}
|
|
|
|
public override IMessage SyncObjectProcessMessage (IMessage msg)
|
|
{
|
|
if (_serverSink == null) {
|
|
bool useProxy = _targetThis != null;
|
|
_serverSink = _context.CreateServerObjectSinkChain ((useProxy ? _targetThis : _serverObject), useProxy);
|
|
}
|
|
return _serverSink.SyncProcessMessage (msg);
|
|
}
|
|
|
|
public override IMessageCtrl AsyncObjectProcessMessage (IMessage msg, IMessageSink replySink)
|
|
{
|
|
if (_serverSink == null) {
|
|
bool useProxy = _targetThis != null;
|
|
_serverSink = _context.CreateServerObjectSinkChain ((useProxy ? _targetThis : _serverObject), useProxy);
|
|
}
|
|
return _serverSink.AsyncProcessMessage (msg, replySink);
|
|
}
|
|
}
|
|
|
|
internal class SingletonIdentity : ServerIdentity
|
|
{
|
|
public SingletonIdentity (string objectUri, Context context, Type objectType): base (objectUri, context, objectType)
|
|
{
|
|
}
|
|
|
|
public MarshalByRefObject GetServerObject ()
|
|
{
|
|
if (_serverObject != null) return _serverObject;
|
|
|
|
lock (this)
|
|
{
|
|
if (_serverObject == null) {
|
|
MarshalByRefObject server = (MarshalByRefObject) Activator.CreateInstance (_objectType, true);
|
|
AttachServerObject (server, Context.DefaultContext);
|
|
StartTrackingLifetime ((ILease)server.InitializeLifetimeService ());
|
|
}
|
|
}
|
|
return _serverObject;
|
|
}
|
|
|
|
public override IMessage SyncObjectProcessMessage (IMessage msg)
|
|
{
|
|
MarshalByRefObject obj = GetServerObject ();
|
|
if (_serverSink == null) _serverSink = _context.CreateServerObjectSinkChain (obj, false);
|
|
return _serverSink.SyncProcessMessage (msg);
|
|
}
|
|
|
|
public override IMessageCtrl AsyncObjectProcessMessage (IMessage msg, IMessageSink replySink)
|
|
{
|
|
MarshalByRefObject obj = GetServerObject ();
|
|
if (_serverSink == null) _serverSink = _context.CreateServerObjectSinkChain (obj, false);
|
|
return _serverSink.AsyncProcessMessage (msg, replySink);
|
|
}
|
|
}
|
|
|
|
internal class SingleCallIdentity : ServerIdentity
|
|
{
|
|
public SingleCallIdentity (string objectUri, Context context, Type objectType): base (objectUri, context, objectType)
|
|
{
|
|
}
|
|
|
|
public override IMessage SyncObjectProcessMessage (IMessage msg)
|
|
{
|
|
// SingleCallIdentity creates and disposes an instance in each call
|
|
|
|
MarshalByRefObject obj = (MarshalByRefObject)Activator.CreateInstance (_objectType, true);
|
|
if (obj.ObjectIdentity == null) obj.ObjectIdentity = this;
|
|
IMessageSink serverSink = _context.CreateServerObjectSinkChain (obj, false);
|
|
IMessage result = serverSink.SyncProcessMessage (msg);
|
|
if (obj is IDisposable) ((IDisposable)obj).Dispose();
|
|
return result;
|
|
}
|
|
|
|
public override IMessageCtrl AsyncObjectProcessMessage (IMessage msg, IMessageSink replySink)
|
|
{
|
|
MarshalByRefObject obj = (MarshalByRefObject)Activator.CreateInstance (_objectType, true);
|
|
IMessageSink serverSink = _context.CreateServerObjectSinkChain (obj, false);
|
|
if (obj is IDisposable) replySink = new DisposerReplySink(replySink, ((IDisposable)obj));
|
|
return serverSink.AsyncProcessMessage (msg, replySink);
|
|
}
|
|
}
|
|
|
|
internal class DisposerReplySink : IMessageSink
|
|
{
|
|
IMessageSink _next;
|
|
IDisposable _disposable;
|
|
|
|
public DisposerReplySink (IMessageSink next, IDisposable disposable)
|
|
{
|
|
_next = next;
|
|
_disposable = disposable;
|
|
}
|
|
|
|
public IMessage SyncProcessMessage (IMessage msg)
|
|
{
|
|
_disposable.Dispose();
|
|
return _next.SyncProcessMessage (msg);
|
|
}
|
|
|
|
public IMessageCtrl AsyncProcessMessage (IMessage msg, IMessageSink replySink)
|
|
{
|
|
throw new NotSupportedException();
|
|
}
|
|
|
|
public IMessageSink NextSink
|
|
{
|
|
get { return _next; }
|
|
}
|
|
}
|
|
}
|