1 //
2 // System.Runtime.Remoting.ActivationServices.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.Threading;
34 using System.Runtime.Remoting.Messaging;
35 using System.Runtime.Remoting.Activation;
36 using System.Runtime.Remoting.Contexts;
37 using System.Runtime.Remoting.Proxies;
38 using System.Reflection;
39 using System.Runtime.CompilerServices;
40 using System.Collections;
41 using System.Runtime.Remoting.Channels;
42 
43 namespace System.Runtime.Remoting.Activation
44 {
45 	internal class ActivationServices
46 	{
47 		static IActivator _constructionActivator;
48 
49 		static IActivator ConstructionActivator {
50 			get {
51 				if (_constructionActivator == null)
52 					_constructionActivator = new ConstructionLevelActivator ();
53 
54 				return _constructionActivator;
55 			}
56 		}
57 
Activate(RemotingProxy proxy, ConstructionCall ctorCall)58 		public static IMessage Activate (RemotingProxy proxy, ConstructionCall ctorCall)
59 		{
60 			IMessage response;
61 			ctorCall.SourceProxy = proxy;
62 
63 			if (Thread.CurrentContext.HasExitSinks && !ctorCall.IsContextOk)
64 				response = Thread.CurrentContext.GetClientContextSinkChain ().SyncProcessMessage (ctorCall);
65 			else
66 				response = RemoteActivate (ctorCall);
67 
68 			if (response is IConstructionReturnMessage && ((IConstructionReturnMessage)response).Exception == null && proxy.ObjectIdentity == null)
69 			{
70 				Identity identity = RemotingServices.GetMessageTargetIdentity (ctorCall);
71 				proxy.AttachIdentity (identity);
72 			}
73 
74 			return response;
75 		}
76 
RemoteActivate(IConstructionCallMessage ctorCall)77 		public static IMessage RemoteActivate (IConstructionCallMessage ctorCall)
78 		{
79 			try
80 			{
81 				return ctorCall.Activator.Activate (ctorCall);
82 			}
83 			catch (Exception ex)
84 			{
85 				return new ReturnMessage (ex, ctorCall);
86 			}
87 		}
88 
CreateProxyFromAttributes(Type type, object[] activationAttributes)89 		public static object CreateProxyFromAttributes (Type type, object[] activationAttributes)
90 		{
91 			string activationUrl = null;
92 			foreach (object attr in activationAttributes)
93 			{
94 				if (!(attr is IContextAttribute)) throw new RemotingException ("Activation attribute does not implement the IContextAttribute interface");
95 				if (attr is UrlAttribute) activationUrl = ((UrlAttribute)attr).UrlValue;
96 			}
97 
98 			if (activationUrl != null)
99 				return RemotingServices.CreateClientProxy (type, activationUrl, activationAttributes);
100 
101 			ActivatedClientTypeEntry activatedEntry = RemotingConfiguration.IsRemotelyActivatedClientType (type);
102 			if (activatedEntry != null)
103 				return RemotingServices.CreateClientProxy (activatedEntry, activationAttributes);
104 
105 			if (type.IsContextful)
106 				return RemotingServices.CreateClientProxyForContextBound (type, activationAttributes);
107 
108 			return null;
109 		}
110 
CreateConstructionCall(Type type, string activationUrl, object[] activationAttributes)111 		public static ConstructionCall CreateConstructionCall (Type type, string activationUrl, object[] activationAttributes)
112 		{
113 			ConstructionCall ctorCall = new ConstructionCall (type);
114 
115 			if (!type.IsContextful)
116 			{
117 				// Must be a remote activated object
118 				ctorCall.Activator = new AppDomainLevelActivator (activationUrl, ConstructionActivator);
119 				ctorCall.IsContextOk = false;	// It'll be activated in a remote context
120 				return ctorCall;
121 			}
122 
123 			// It is a CBO. Need collect context properties and
124 			// check if a new context is needed.
125 
126 			IActivator activatorChain = ConstructionActivator;
127 			activatorChain = new ContextLevelActivator (activatorChain);
128 
129 			ArrayList attributes = new ArrayList ();
130 			if (activationAttributes != null) attributes.AddRange (activationAttributes);
131 
132 			bool isContextOk = (activationUrl == ChannelServices.CrossContextUrl);	// Remote CBOs are always created in a new context
133 			Context currentContext = Threading.Thread.CurrentContext;
134 
135 			if (isContextOk)
136 			{
137 				foreach (IContextAttribute attr in attributes)
138 				{
139 					if (!attr.IsContextOK (currentContext, ctorCall))
140 					{
141 						isContextOk = false;
142 						break;
143 					}
144 				}
145 			}
146 
147 			object[] typeAttributes = type.GetCustomAttributes (true);
148 			foreach (object attr in typeAttributes)
149 			{
150 				if (attr is IContextAttribute)
151 				{
152 					isContextOk = isContextOk && ((IContextAttribute)attr).IsContextOK (currentContext, ctorCall);
153 					attributes.Add (attr);
154 				}
155 			}
156 
157 			if (!isContextOk)
158 			{
159 				// A new context is needed. Collect the context properties and chain
160 				// the context level activator.
161 
162 				ctorCall.SetActivationAttributes (attributes.ToArray());
163 
164 				foreach (IContextAttribute attr in attributes)
165 					attr.GetPropertiesForNewContext (ctorCall);
166 			}
167 
168 			if (activationUrl != ChannelServices.CrossContextUrl)
169 				activatorChain = new AppDomainLevelActivator (activationUrl, activatorChain);
170 
171 			ctorCall.Activator = activatorChain;
172 			ctorCall.IsContextOk = isContextOk;
173 
174 			return ctorCall;
175 		}
176 
CreateInstanceFromMessage(IConstructionCallMessage ctorCall)177 		public static IMessage CreateInstanceFromMessage (IConstructionCallMessage ctorCall)
178 		{
179 			object obj = AllocateUninitializedClassInstance (ctorCall.ActivationType);
180 
181 			ServerIdentity identity = (ServerIdentity) RemotingServices.GetMessageTargetIdentity (ctorCall);
182 			identity.AttachServerObject ((MarshalByRefObject) obj, Threading.Thread.CurrentContext);
183 
184 			ConstructionCall call = ctorCall as ConstructionCall;
185 
186 			if (ctorCall.ActivationType.IsContextful && call != null && call.SourceProxy != null)
187 			{
188 				call.SourceProxy.AttachIdentity (identity);
189 				MarshalByRefObject target = (MarshalByRefObject) call.SourceProxy.GetTransparentProxy ();
190 				RemotingServices.InternalExecuteMessage (target, ctorCall);
191 			}
192 			else
193 				ctorCall.MethodBase.Invoke (obj, ctorCall.Args);
194 
195 			return new ConstructionResponse (obj, null, ctorCall);
196 		}
197 
CreateProxyForType(Type type)198 		public static object CreateProxyForType (Type type)
199 		{
200 			// Called by the runtime when creating an instance of a type
201 			// that has been registered as remotely activated.
202 
203 			// First of all check for remote activation. If the object is not remote, then
204 			// it may be contextbound.
205 
206 			ActivatedClientTypeEntry activatedEntry = RemotingConfiguration.IsRemotelyActivatedClientType (type);
207 			if (activatedEntry != null)
208 				return RemotingServices.CreateClientProxy (activatedEntry, null);
209 
210 			WellKnownClientTypeEntry wellknownEntry = RemotingConfiguration.IsWellKnownClientType (type);
211 			if (wellknownEntry != null)
212 				return RemotingServices.CreateClientProxy (wellknownEntry);
213 
214 			if (type.IsContextful)
215 				return RemotingServices.CreateClientProxyForContextBound (type, null);
216 #if !MOBILE
217 			if (type.IsCOMObject) {
218 				return RemotingServices.CreateClientProxyForComInterop (type);
219 			}
220 #endif
221 			return null;
222 		}
223 
PushActivationAttributes(Type serverType, Object[] attributes)224 		internal static void PushActivationAttributes (Type serverType, Object[] attributes)
225 		{
226 			// TODO:
227 		}
228 
PopActivationAttributes(Type serverType)229 		internal static void PopActivationAttributes (Type serverType)
230 		{
231 			// TODO:
232 		}
233 
234 		// Allocates an uninitialized instance. It never creates proxies.
235 		[MethodImplAttribute(MethodImplOptions.InternalCall)]
AllocateUninitializedClassInstance(Type type)236 		public static extern object AllocateUninitializedClassInstance (Type type);
237 
238 		[MethodImplAttribute(MethodImplOptions.InternalCall)]
EnableProxyActivation(Type type, bool enable)239 		public extern static void EnableProxyActivation (Type type, bool enable);
240 	}
241 }
242