1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 namespace Ice
6 {
7     using System.Collections.Generic;
8     using System.Threading;
9 
10     //
11     // The base class for all ImplicitContext implementations
12     //
13     public abstract class ImplicitContextI : ImplicitContext
14     {
create(string kind)15         public static ImplicitContextI create(string kind)
16         {
17             if(kind.Equals("None") || kind.Length == 0)
18             {
19                 return null;
20             }
21             else if(kind.Equals("Shared"))
22             {
23                 return new SharedImplicitContext();
24             }
25             else if(kind.Equals("PerThread"))
26             {
27                 return new PerThreadImplicitContext();
28             }
29             else
30             {
31                 throw new InitializationException("'" + kind + "' is not a valid value for Ice.ImplicitContext");
32             }
33         }
34 
getContext()35         public abstract Dictionary<string, string> getContext();
setContext(Dictionary<string, string> newContext)36         public abstract void setContext(Dictionary<string, string> newContext);
containsKey(string key)37         public abstract bool containsKey(string key);
get(string key)38         public abstract string get(string key);
put(string key, string value)39         public abstract string put(string key, string value);
remove(string key)40         public abstract string remove(string key);
41 
write(Dictionary<string, string> prxContext, OutputStream os)42         abstract public void write(Dictionary<string, string> prxContext, OutputStream os);
combine(Dictionary<string, string> prxContext)43         abstract internal Dictionary<string, string> combine(Dictionary<string, string> prxContext);
44     }
45 
46     internal class SharedImplicitContext : ImplicitContextI
47     {
getContext()48         public override Dictionary<string, string> getContext()
49         {
50             lock(this)
51             {
52                 return new Dictionary<string, string>(_context);
53             }
54         }
55 
setContext(Dictionary<string, string> context)56         public override void setContext(Dictionary<string, string> context)
57         {
58             lock(this)
59             {
60                 if(context != null && context.Count != 0)
61                 {
62                     _context = new Dictionary<string, string>(context);
63                 }
64                 else
65                 {
66                     _context.Clear();
67                 }
68             }
69         }
70 
containsKey(string key)71         public override bool containsKey(string key)
72         {
73             lock(this)
74             {
75                 if(key == null)
76                 {
77                     key = "";
78                 }
79 
80                 return _context.ContainsKey(key);
81             }
82         }
83 
get(string key)84         public override string get(string key)
85         {
86             lock(this)
87             {
88                 if(key == null)
89                 {
90                     key = "";
91                 }
92 
93                 string val = _context[key];
94                 if(val == null)
95                 {
96                     val = "";
97                 }
98                 return val;
99             }
100         }
101 
put(string key, string value)102         public override string put(string key, string value)
103         {
104             lock(this)
105             {
106                 if(key == null)
107                 {
108                     key = "";
109                 }
110                 if(value == null)
111                 {
112                     value = "";
113                 }
114 
115                 string oldVal;
116                 _context.TryGetValue(key, out oldVal);
117                 if(oldVal == null)
118                 {
119                     oldVal = "";
120                 }
121                 _context[key] = value;
122 
123                 return oldVal;
124             }
125         }
126 
remove(string key)127         public override string remove(string key)
128         {
129             lock(this)
130             {
131                 if(key == null)
132                 {
133                     key = "";
134                 }
135 
136                 string val = _context[key];
137 
138                 if(val == null)
139                 {
140                     val = "";
141                 }
142                 else
143                 {
144                     _context.Remove(key);
145                 }
146 
147                 return val;
148             }
149         }
150 
write(Dictionary<string, string> prxContext, OutputStream os)151         public override void write(Dictionary<string, string> prxContext, OutputStream os)
152         {
153             if(prxContext.Count == 0)
154             {
155                 lock(this)
156                 {
157                     ContextHelper.write(os, _context);
158                 }
159             }
160             else
161             {
162                 Dictionary<string, string> ctx = null;
163                 lock(this)
164                 {
165                     ctx = _context.Count == 0 ? prxContext : combine(prxContext);
166                 }
167                 ContextHelper.write(os, ctx);
168             }
169         }
170 
combine(Dictionary<string, string> prxContext)171         internal override Dictionary<string, string> combine(Dictionary<string, string> prxContext)
172         {
173             lock(this)
174             {
175                 Dictionary<string, string> combined = new Dictionary<string, string>(prxContext);
176                 foreach(KeyValuePair<string, string> e in _context)
177                 {
178                     try
179                     {
180                         combined.Add(e.Key, e.Value);
181                     }
182                     catch(System.ArgumentException)
183                     {
184                         // Ignore.
185                     }
186                 }
187                 return combined;
188             }
189         }
190 
191         private Dictionary<string, string> _context = new Dictionary<string, string>();
192     }
193 
194     internal class PerThreadImplicitContext : ImplicitContextI
195     {
getContext()196         public override Dictionary<string, string> getContext()
197         {
198             Dictionary<string, string> threadContext = null;
199             Thread currentThread = Thread.CurrentThread;
200             lock(this)
201             {
202                 if(_map.ContainsKey(currentThread))
203                 {
204                     threadContext = _map[currentThread];
205                 }
206             }
207 
208             if(threadContext == null)
209             {
210                 threadContext = new Dictionary<string, string>();
211             }
212             return threadContext;
213         }
214 
setContext(Dictionary<string, string> context)215         public override void setContext(Dictionary<string, string> context)
216         {
217             if(context == null || context.Count == 0)
218             {
219                 lock(this)
220                 {
221                     _map.Remove(Thread.CurrentThread);
222                 }
223             }
224             else
225             {
226                 Dictionary<string, string> threadContext = new Dictionary<string, string>(context);
227 
228                 lock(this)
229                 {
230                     _map.Add(Thread.CurrentThread, threadContext);
231                 }
232             }
233         }
234 
containsKey(string key)235         public override bool containsKey(string key)
236         {
237             if(key == null)
238             {
239                 key = "";
240             }
241 
242             Dictionary<string, string> threadContext = null;
243             lock(this)
244             {
245                 if(!_map.TryGetValue(Thread.CurrentThread, out threadContext))
246                 {
247                     return false;
248                 }
249             }
250 
251             return threadContext.ContainsKey(key);
252         }
253 
get(string key)254         public override string get(string key)
255         {
256             if(key == null)
257             {
258                 key = "";
259             }
260 
261             Dictionary<string, string> threadContext = null;
262             lock(this)
263             {
264                 if(!_map.TryGetValue(Thread.CurrentThread, out threadContext))
265                 {
266                     return "";
267                 }
268             }
269 
270             string val = threadContext[key];
271             if(val == null)
272             {
273                 val = "";
274             }
275             return val;
276         }
277 
put(string key, string value)278         public override string put(string key, string value)
279         {
280             if(key == null)
281             {
282                 key = "";
283             }
284             if(value == null)
285             {
286                 value = "";
287             }
288 
289             Dictionary<string, string> threadContext = null;
290             lock(this)
291             {
292                 if(!_map.TryGetValue(Thread.CurrentThread, out threadContext))
293                 {
294                     threadContext = new Dictionary<string, string>();
295                     _map.Add(Thread.CurrentThread, threadContext);
296                 }
297             }
298 
299             string oldVal;
300             if(!threadContext.TryGetValue(key, out oldVal))
301             {
302                 oldVal = "";
303             }
304 
305             threadContext[key] = value;
306             return oldVal;
307         }
308 
remove(string key)309         public override string remove(string key)
310         {
311             if(key == null)
312             {
313                 key = "";
314             }
315 
316             Dictionary<string, string> threadContext = null;
317             lock(this)
318             {
319                 if(!_map.TryGetValue(Thread.CurrentThread, out threadContext))
320                 {
321                     return "";
322                 }
323             }
324 
325             string val = null;
326             if(!threadContext.TryGetValue(key, out val))
327             {
328                 val = "";
329             }
330             else
331             {
332                 threadContext.Remove(key);
333             }
334             return val;
335         }
336 
write(Dictionary<string, string> prxContext, OutputStream os)337         public override void write(Dictionary<string, string> prxContext, OutputStream os)
338         {
339             Dictionary<string, string> threadContext = null;
340             lock(this)
341             {
342                 _map.TryGetValue(Thread.CurrentThread, out threadContext);
343             }
344 
345             if(threadContext == null || threadContext.Count == 0)
346             {
347                 ContextHelper.write(os, prxContext);
348             }
349             else if(prxContext.Count == 0)
350             {
351                 ContextHelper.write(os, threadContext);
352             }
353             else
354             {
355                 Dictionary<string, string> combined = new Dictionary<string, string>(prxContext);
356                 foreach(KeyValuePair<string, string> e in threadContext)
357                 {
358                     try
359                     {
360                         combined.Add(e.Key, e.Value);
361                     }
362                     catch(System.ArgumentException)
363                     {
364                         // Ignore.
365                     }
366                 }
367                 ContextHelper.write(os, combined);
368             }
369         }
370 
combine(Dictionary<string, string> prxContext)371         internal override Dictionary<string, string> combine(Dictionary<string, string> prxContext)
372         {
373             Dictionary<string, string> threadContext = null;
374             lock(this)
375             {
376                 if(!_map.TryGetValue(Thread.CurrentThread, out threadContext))
377                 {
378                     return new Dictionary<string, string>(prxContext);
379                 }
380             }
381 
382             Dictionary<string, string> combined = new Dictionary<string, string>(prxContext);
383             foreach(KeyValuePair<string, string> e in threadContext)
384             {
385                 combined.Add(e.Key, e.Value);
386             }
387             return combined;
388         }
389 
390         //
391         //  map Thread -> Context
392         //
393         private Dictionary<Thread, Dictionary<string, string> > _map =
394             new Dictionary<Thread, Dictionary<string, string> >();
395     }
396 }
397