2004-04-12 David Sheldon <dave-mono@earth.li>
[mono.git] / mcs / class / corlib / System.Runtime.Remoting.Activation / ActivationServices.cs
index e4ae53e7bc705e36811546eee9188680296ab58b..09772a67fa8711c0a0529fa8fbcc5998d9a68ce3 100644 (file)
 //
 // (C) 2002, Lluis Sanchez Gual
 //
-\r
-using System;\r
-using System.Runtime.Remoting.Messaging;\r
-using System.Reflection;\r
+
+using System;
+using System.Threading;
+using System.Runtime.Remoting.Messaging;
+using System.Runtime.Remoting.Activation;
+using System.Runtime.Remoting.Contexts;
+using System.Runtime.Remoting.Proxies;
+using System.Reflection;
 using System.Runtime.CompilerServices;
-\r
-namespace System.Runtime.Remoting.Activation\r
-{\r
-       internal class ActivationServices\r
-       {\r
-               public static IMessage CreateInstanceFromMessage (IConstructionCallMessage ctorCall)\r
-               {\r
-                       object obj = AllocateUninitializedClassInstance (ctorCall.ActivationType);\r
-                       ctorCall.MethodBase.Invoke (obj, ctorCall.Args);\r
-\r
+using System.Collections;
+using System.Runtime.Remoting.Channels;
+
+namespace System.Runtime.Remoting.Activation
+{
+       internal class ActivationServices
+       {
+               static IActivator _constructionActivator = new ConstructionLevelActivator ();
+
+               public static IMessage Activate (RemotingProxy proxy, ConstructionCall ctorCall)
+               {
+                       IMessage response;
+
+                       if (Thread.CurrentContext.HasExitSinks && !ctorCall.IsContextOk)
+                               response = Thread.CurrentContext.GetClientContextSinkChain ().SyncProcessMessage (ctorCall);
+                       else
+                               response = RemoteActivate (ctorCall);
+
+                       if (response is IConstructionReturnMessage && ((IConstructionReturnMessage)response).Exception == null)
+                       {
+                               Identity identity = RemotingServices.GetMessageTargetIdentity (ctorCall);
+                               proxy.AttachIdentity (identity);
+                       }
+
+                       return response;
+               }
+
+               public static IMessage RemoteActivate (IConstructionCallMessage ctorCall)
+               {
+                       try \r
+                       {
+                               return ctorCall.Activator.Activate (ctorCall);
+                       }
+                       catch (Exception ex) \r
+                       {
+                               return new ReturnMessage (ex, ctorCall);
+                       }               \r
+               }
+
+               public static object CreateProxyFromAttributes (Type type, object[] activationAttributes)
+               {
+                       string activationUrl = null;
+                       foreach (object attr in activationAttributes)
+                       {
+                               if (!(attr is IContextAttribute)) throw new RemotingException ("Activation attribute does not implement the IContextAttribute interface");
+                               if (attr is UrlAttribute) activationUrl = ((UrlAttribute)attr).UrlValue;
+                       }
+
+                       if (activationUrl != null)
+                               return RemotingServices.CreateClientProxy (type, activationUrl, activationAttributes);
+
+                       ActivatedClientTypeEntry activatedEntry = RemotingConfiguration.IsRemotelyActivatedClientType (type);
+                       if (activatedEntry != null)
+                               return RemotingServices.CreateClientProxy (activatedEntry, activationAttributes);
+
+                       if (type.IsContextful)
+                               return RemotingServices.CreateClientProxyForContextBound (type, activationAttributes);
+                       
+                       return null;
+               }
+
+               public static ConstructionCall CreateConstructionCall (Type type, string activationUrl, object[] activationAttributes)
+               {
+                       ConstructionCall ctorCall = new ConstructionCall (type);
+
+                       if (!type.IsContextful) 
+                       {
+                               // Must be a remote activated object
+                               ctorCall.Activator = new AppDomainLevelActivator (activationUrl, _constructionActivator);
+                               ctorCall.IsContextOk = false;   // It'll be activated in a remote context
+                               return ctorCall;
+                       }
+
+                       // It is a CBO. Need collect context properties and
+                       // check if a new context is needed.
+
+                       IActivator activatorChain = _constructionActivator;
+                       activatorChain = new ContextLevelActivator (activatorChain);
+
+                       ArrayList attributes = new ArrayList ();
+                       if (activationAttributes != null) attributes.AddRange (activationAttributes);
+
+                       bool isContextOk = (activationUrl == ChannelServices.CrossContextUrl);  // Remote CBOs are always created in a new context
+                       Context currentContext = Threading.Thread.CurrentContext;
+
+                       if (isContextOk) 
+                       {
+                               foreach (IContextAttribute attr in attributes) 
+                               {
+                                       if (!attr.IsContextOK (currentContext, ctorCall)) 
+                                       {
+                                               isContextOk = false;
+                                               break;
+                                       }
+                               }
+                       }
+
+                       object[] typeAttributes = type.GetCustomAttributes (true);
+                       foreach (object attr in typeAttributes) 
+                       {
+                               if (attr is IContextAttribute) 
+                               {
+                                       isContextOk = isContextOk && ((IContextAttribute)attr).IsContextOK (currentContext, ctorCall);
+                                       attributes.Add (attr);
+                               }
+                       }
+
+                       if (!isContextOk)
+                       {
+                               // A new context is needed. Collect the context properties and chain
+                               // the context level activator.
+
+                               ctorCall.SetActivationAttributes (attributes.ToArray());
+
+                               foreach (IContextAttribute attr in attributes)
+                                       attr.GetPropertiesForNewContext (ctorCall);
+                       }
+
+                       if (activationUrl != ChannelServices.CrossContextUrl)
+                               activatorChain = new AppDomainLevelActivator (activationUrl, activatorChain);
+                       
+                       ctorCall.Activator = activatorChain;
+                       ctorCall.IsContextOk = isContextOk;
+
+                       return ctorCall;
+               }
+
+               public static IMessage CreateInstanceFromMessage (IConstructionCallMessage ctorCall)
+               {
+                       object obj = AllocateUninitializedClassInstance (ctorCall.ActivationType);
+                       ctorCall.MethodBase.Invoke (obj, ctorCall.Args);
+
                        ServerIdentity identity = (ServerIdentity) RemotingServices.GetMessageTargetIdentity (ctorCall);
 
-//                     FIXME: restore when Thread.CurrentContext workds
-//                     identity.AttachServerObject ((MarshalByRefObject) obj, Threading.Thread.CurrentContext);
-                       identity.AttachServerObject ((MarshalByRefObject) obj, System.Runtime.Remoting.Contexts.Context.DefaultContext);
+                       identity.AttachServerObject ((MarshalByRefObject) obj, Threading.Thread.CurrentContext);
 
                        return new ConstructionResponse (obj, null, ctorCall);
-               }\r
-\r
-               internal static object CreateProxyForType (Type type)
+               }
+
+               public static object CreateProxyForType (Type type)
                {
                        // Called by the runtime when creating an instance of a type
                        // that has been registered as remotely activated.
@@ -39,23 +163,23 @@ namespace System.Runtime.Remoting.Activation
 
                        ActivatedClientTypeEntry activatedEntry = RemotingConfiguration.IsRemotelyActivatedClientType (type);
                        if (activatedEntry != null)
-                               return RemotingServices.CreateClientProxy (activatedEntry);
+                               return RemotingServices.CreateClientProxy (activatedEntry, null);
 
                        WellKnownClientTypeEntry wellknownEntry = RemotingConfiguration.IsWellKnownClientType (type);
                        if (wellknownEntry != null)
                                return RemotingServices.CreateClientProxy (wellknownEntry);
 
                        if (type.IsContextful)
-                               return RemotingServices.CreateClientProxyForContextBound (type);
+                               return RemotingServices.CreateClientProxyForContextBound (type, null);
 
                        return null;
-               }\r
-\r
-               // Allocates an uninitialized instance. It never creates proxies.\r
+               }
+
+               // Allocates an uninitialized instance. It never creates proxies.
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
-               private static extern object AllocateUninitializedClassInstance (Type type);
-\r
+               public static extern object AllocateUninitializedClassInstance (Type type);
+
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                public extern static void EnableProxyActivation (Type type, bool enable);
-       }\r
-}\r
+       }
+}