(DISTFILES): Comment out a few missing files.
[mono-project.git] / mcs / class / corlib / System.Runtime.Remoting.Contexts / Context.cs
blob0d72a0fc379af4c8ba6dd7dedc7b7e2f09b4e945
1 //
2 // System.Runtime.Remoting.Contexts.Context..cs
3 //
4 // Author:
5 // Miguel de Icaza (miguel@ximian.com)
6 // Lluis Sanchez Gual (lluis@ideary.com)
7 // Patrik Torstensson
8 //
9 // (C) Ximian, Inc. http://www.ximian.com
13 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 //
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 //
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
35 using System.Collections;
36 using System.Threading;
37 using System.Runtime.Remoting;
38 using System.Runtime.Remoting.Proxies;
39 using System.Runtime.Remoting.Activation;
40 using System.Runtime.Remoting.Messaging;
41 using System.Runtime.Remoting.Lifetime;
43 namespace System.Runtime.Remoting.Contexts {
45 public class Context
47 int domain_id;
48 int context_id;
49 int process_id;
50 IntPtr static_data;
52 // Default server context sink chain
53 static IMessageSink default_server_context_sink;
55 // The sink chain that has to be used by all calls entering the context
56 IMessageSink server_context_sink_chain = null;
58 // The sink chain that has to be used by all calls exiting the context
59 IMessageSink client_context_sink_chain = null;
61 Hashtable datastore;
62 ArrayList context_properties;
63 bool frozen;
65 static int global_count;
66 static Hashtable namedSlots;
68 static DynamicPropertyCollection global_dynamic_properties;
69 DynamicPropertyCollection context_dynamic_properties;
70 ContextCollbackObject callback_object = null;
72 public Context ()
74 domain_id = Thread.GetDomainID();
75 context_id = 1 + global_count++;
78 ~Context ()
82 public static Context DefaultContext {
83 get {
84 return AppDomain.InternalGetDefaultContext ();
88 public virtual int ContextID {
89 get {
90 return context_id;
94 public IContextProperty[] ContextProperties
96 get
98 if (context_properties == null) return new IContextProperty[0];
99 else return (IContextProperty[]) context_properties.ToArray (typeof(IContextProperty[]));
103 internal bool IsDefaultContext
105 get { return context_id == 0; }
108 public static bool RegisterDynamicProperty(IDynamicProperty prop, ContextBoundObject obj, Context ctx)
110 DynamicPropertyCollection col = GetDynamicPropertyCollection (obj, ctx);
111 return col.RegisterDynamicProperty (prop);
114 public static bool UnregisterDynamicProperty(string name, ContextBoundObject obj, Context ctx)
116 DynamicPropertyCollection col = GetDynamicPropertyCollection (obj, ctx);
117 return col.UnregisterDynamicProperty (name);
120 static DynamicPropertyCollection GetDynamicPropertyCollection(ContextBoundObject obj, Context ctx)
122 if (ctx == null && obj != null)
124 if (RemotingServices.IsTransparentProxy(obj))
126 RealProxy rp = RemotingServices.GetRealProxy (obj);
127 return rp.ObjectIdentity.ClientDynamicProperties;
129 else
130 return obj.ObjectIdentity.ServerDynamicProperties;
132 else if (ctx != null && obj == null)
134 if (ctx.context_dynamic_properties == null) ctx.context_dynamic_properties = new DynamicPropertyCollection ();
135 return ctx.context_dynamic_properties;
137 else if (ctx == null && obj == null)
139 if (global_dynamic_properties == null) global_dynamic_properties = new DynamicPropertyCollection ();
140 return global_dynamic_properties;
142 else
143 throw new ArgumentException ("Either obj or ctx must be null");
146 internal static void NotifyGlobalDynamicSinks (bool start, IMessage req_msg, bool client_site, bool async)
148 if (global_dynamic_properties != null && global_dynamic_properties.HasProperties)
149 global_dynamic_properties.NotifyMessage (start, req_msg, client_site, async);
152 internal static bool HasGlobalDynamicSinks
154 get { return (global_dynamic_properties != null && global_dynamic_properties.HasProperties); }
157 internal void NotifyDynamicSinks (bool start, IMessage req_msg, bool client_site, bool async)
159 if (context_dynamic_properties != null && context_dynamic_properties.HasProperties)
160 context_dynamic_properties.NotifyMessage (start, req_msg, client_site, async);
163 internal bool HasDynamicSinks
165 get { return (context_dynamic_properties != null && context_dynamic_properties.HasProperties); }
168 internal bool HasExitSinks
172 // Needs to go through the client context sink if there are custom
173 // client context or dynamic sinks.
175 return ( !(GetClientContextSinkChain() is ClientContextTerminatorSink) || HasDynamicSinks || HasGlobalDynamicSinks);
179 public virtual IContextProperty GetProperty (string name)
181 if (context_properties == null)
182 return null;
184 foreach (IContextProperty p in context_properties)
185 if (p.Name == name)
186 return p;
188 return null;
191 public virtual void SetProperty (IContextProperty prop)
193 if (prop == null)
194 throw new ArgumentNullException ("IContextProperty");
195 if (this == DefaultContext)
196 throw new InvalidOperationException ("Can not add properties to " +
197 "default context");
198 if (frozen)
199 throw new InvalidOperationException ("Context is Frozen");
201 if (context_properties == null)
202 context_properties = new ArrayList ();
204 context_properties.Add (prop);
207 public virtual void Freeze ()
209 if (context_properties != null)
211 foreach (IContextProperty prop in context_properties)
212 prop.Freeze (this);
216 public override string ToString()
218 return "ContextID: " + context_id;
221 internal IMessageSink GetServerContextSinkChain()
223 if (server_context_sink_chain == null)
225 if (default_server_context_sink == null)
226 default_server_context_sink = new ServerContextTerminatorSink();
228 server_context_sink_chain = default_server_context_sink;
230 if (context_properties != null) {
231 // Enumerate in reverse order
232 for (int n = context_properties.Count-1; n>=0; n--) {
233 IContributeServerContextSink contributor = context_properties[n] as IContributeServerContextSink;
234 if (contributor != null)
235 server_context_sink_chain = contributor.GetServerContextSink (server_context_sink_chain);
239 return server_context_sink_chain;
242 internal IMessageSink GetClientContextSinkChain()
244 if (client_context_sink_chain == null)
246 client_context_sink_chain = new ClientContextTerminatorSink (this);
248 if (context_properties != null) {
249 foreach (IContextProperty prop in context_properties) {
250 IContributeClientContextSink contributor = prop as IContributeClientContextSink;
251 if (contributor != null)
252 client_context_sink_chain = contributor.GetClientContextSink (client_context_sink_chain);
256 return client_context_sink_chain;
259 internal IMessageSink CreateServerObjectSinkChain (MarshalByRefObject obj, bool forceInternalExecute)
261 IMessageSink objectSink = new StackBuilderSink (obj, forceInternalExecute);
262 objectSink = new ServerObjectTerminatorSink (objectSink);
263 objectSink = new Lifetime.LeaseSink (objectSink);
265 if (context_properties != null)
267 // Contribute object sinks in reverse order
268 for (int n = context_properties.Count-1; n >= 0; n--)
270 IContextProperty prop = (IContextProperty) context_properties[n];
271 IContributeObjectSink contributor = prop as IContributeObjectSink;
272 if (contributor != null)
273 objectSink = contributor.GetObjectSink (obj, objectSink);
276 return objectSink;
279 internal IMessageSink CreateEnvoySink (MarshalByRefObject serverObject)
281 IMessageSink sink = EnvoyTerminatorSink.Instance;
282 if (context_properties != null)
284 foreach (IContextProperty prop in context_properties)
286 IContributeEnvoySink contributor = prop as IContributeEnvoySink;
287 if (contributor != null)
288 sink = contributor.GetEnvoySink (serverObject, sink);
291 return sink;
294 internal static Context SwitchToContext (Context newContext)
296 return AppDomain.InternalSetContext (newContext);
299 internal static Context CreateNewContext (IConstructionCallMessage msg)
301 // Create the new context
303 Context newContext = new Context();
305 foreach (IContextProperty prop in msg.ContextProperties)
307 if (newContext.GetProperty (prop.Name) == null)
308 newContext.SetProperty (prop);
310 newContext.Freeze();
313 // Ask each context property whether the new context is OK
315 foreach (IContextProperty prop in msg.ContextProperties)
316 if (!prop.IsNewContextOK (newContext))
317 throw new RemotingException("A context property did not approve the candidate context for activating the object");
319 return newContext;
322 public void DoCallBack (CrossContextDelegate deleg)
324 if (callback_object == null)
326 lock (this)
328 if (callback_object == null) {
329 Context oldContext = Context.SwitchToContext (this);
330 callback_object = new ContextCollbackObject ();
331 Context.SwitchToContext (oldContext);
336 callback_object.DoCallBack (deleg);
339 public static LocalDataStoreSlot AllocateDataSlot ()
341 return new LocalDataStoreSlot ();
344 public static LocalDataStoreSlot AllocateNamedDataSlot (string name)
346 if (namedSlots == null)
348 lock (typeof(Context))
350 if (namedSlots == null)
351 namedSlots = new Hashtable ();
355 lock (namedSlots.SyncRoot)
357 LocalDataStoreSlot slot = new LocalDataStoreSlot ();
358 namedSlots.Add (name, slot);
359 return slot;
363 public static void FreeNamedDataSlot (string name)
365 if (namedSlots == null) return;
367 lock (namedSlots.SyncRoot)
369 namedSlots.Remove (name);
373 public static object GetData (LocalDataStoreSlot slot)
375 Context ctx = Thread.CurrentContext;
376 if (ctx.datastore == null) return null;
378 lock (ctx.datastore.SyncRoot)
380 return ctx.datastore [slot];
384 public static LocalDataStoreSlot GetNamedDataSlot (string name)
386 if (namedSlots == null)
387 return AllocateNamedDataSlot (name);
389 lock (namedSlots)
391 LocalDataStoreSlot slot = namedSlots [name] as LocalDataStoreSlot;
392 if (slot == null) return AllocateNamedDataSlot (name);
393 else return slot;
397 public static void SetData (LocalDataStoreSlot slot, object data)
399 Context ctx = Thread.CurrentContext;
400 if (ctx.datastore == null)
402 lock (ctx)
404 if (ctx.datastore == null)
405 ctx.datastore = new Hashtable ();
409 lock (ctx.datastore.SyncRoot)
411 ctx.datastore [slot] = data;
416 class DynamicPropertyCollection
418 ArrayList _properties = new ArrayList();
420 class DynamicPropertyReg
422 public IDynamicProperty Property;
423 public IDynamicMessageSink Sink;
426 public bool HasProperties
428 get { return _properties.Count > 0; }
431 public bool RegisterDynamicProperty(IDynamicProperty prop)
433 lock (this)
435 if (FindProperty (prop.Name) != -1)
436 throw new InvalidOperationException ("Another property by this name already exists");
438 // Make a copy, do not interfere with threads running dynamic sinks
439 ArrayList newProps = new ArrayList (_properties);
441 DynamicPropertyReg reg = new DynamicPropertyReg();
442 reg.Property = prop;
443 IContributeDynamicSink contributor = prop as IContributeDynamicSink;
444 if (contributor != null) reg.Sink = contributor.GetDynamicSink ();
445 newProps.Add (reg);
447 _properties = newProps;
449 return true; // When should be false?
453 public bool UnregisterDynamicProperty(string name)
455 lock (this)
457 int i = FindProperty (name);
458 if (i == -1) throw new RemotingException ("A property with the name " + name + " was not found");
460 _properties.RemoveAt (i);
461 return true; // When should be false?
465 public void NotifyMessage (bool start, IMessage msg, bool client_site, bool async)
467 ArrayList props = _properties;
468 if (start)
470 foreach (DynamicPropertyReg reg in props)
471 if (reg.Sink != null) reg.Sink.ProcessMessageStart (msg, client_site, async);
473 else
475 foreach (DynamicPropertyReg reg in props)
476 if (reg.Sink != null) reg.Sink.ProcessMessageFinish (msg, client_site, async);
480 int FindProperty (string name)
482 for (int n=0; n<_properties.Count; n++)
483 if (((DynamicPropertyReg)_properties[n]).Property.Name == name)
484 return n;
485 return -1;
489 class ContextCollbackObject: ContextBoundObject
491 public void DoCallBack (CrossContextDelegate deleg)