d1f1b9e3ed7c9e73b96e133b80b3b42f9718b26e
[mono.git] / mcs / class / corlib / System.Runtime.Remoting.Messaging / MethodDictionary.cs
1 //
2 // System.Runtime.Remoting.Messaging.MethodDictionary.cs
3 //
4 // Author: Lluis Sanchez Gual (lluis@ideary.com)
5 //
6 // 2003 (C) 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.Collections;
34
35 namespace System.Runtime.Remoting.Messaging
36 {
37         [Serializable]
38         internal class MethodDictionary : IDictionary
39         {
40                 IDictionary _internalProperties = null;
41                 protected IMethodMessage _message;
42                 string[] _methodKeys;
43                 bool _ownProperties = false;
44
45                 public MethodDictionary (IMethodMessage message)
46                 {
47                         _message = message;
48                 }
49
50                 internal bool HasInternalProperties 
51                 {
52                         get 
53                         {
54                                 if (null != _internalProperties)
55                                 {
56                                         // MethodCallMessageWrapper uses a nested MethodDictionary
57                                         if (_internalProperties is MethodDictionary)
58                                                 return ((MethodDictionary)_internalProperties).HasInternalProperties;
59                                         else 
60                                                 return _internalProperties.Count > 0;
61                                 }
62                                 return false;
63                         }
64                 }
65
66                 internal IDictionary InternalProperties
67                 {
68                         get 
69                         {
70                                 if (null != _internalProperties)
71                                 {
72                                         if (_internalProperties is MethodDictionary)
73                                                 return ((MethodDictionary)_internalProperties).InternalProperties;
74                                 }
75                                 return _internalProperties;
76                         }
77                 }
78
79                 public string[] MethodKeys
80                 {
81                         get { return _methodKeys; }
82                         set { _methodKeys = value; }
83                 }
84
85                 protected virtual IDictionary AllocInternalProperties()
86                 {
87                         _ownProperties = true;
88                         return new Hashtable();
89                 }
90
91                 public IDictionary GetInternalProperties()
92                 {
93                         if (_internalProperties == null) _internalProperties = AllocInternalProperties();
94                         return _internalProperties;
95                 }
96
97                 private bool IsOverridenKey (string key)
98                 {
99                         // Small optimization. If the internal properties have been
100                         // created by this dictionary, then it can be assured that it does
101                         // not contain values for overriden keys.
102                         if (_ownProperties) return false;
103
104                         foreach (string mkey in _methodKeys)
105                                 if (key == mkey) return true;
106                         return false;
107                 }
108
109                 public MethodDictionary(string[] keys)
110                 {
111                         _methodKeys = keys;
112                 }
113
114                 public bool IsFixedSize 
115                 { 
116                         get { return false; } 
117                 }
118                 
119                 public bool IsReadOnly 
120                 { 
121                         get { return false; } 
122                 }
123
124                 public object this[object key] 
125                 { 
126                         get
127                         {
128                                 string keyStr = (string)key;
129                                 for (int n=0; n<_methodKeys.Length; n++)
130                                         if (_methodKeys[n] == keyStr) return GetMethodProperty (keyStr);
131
132                                 if (_internalProperties != null) 
133                                         return _internalProperties[key];
134                                 else 
135                                         return null;
136                         }
137
138                         set
139                         {
140                                 Add (key, value);
141                         }
142                 }
143
144                 protected virtual object GetMethodProperty (string key)
145                 {
146                         switch (key)
147                         {
148                                 case "__Uri" : return _message.Uri;
149                                 case "__MethodName" : return _message.MethodName;
150                                 case "__TypeName" : return _message.TypeName;
151                                 case "__MethodSignature" : return _message.MethodSignature;
152                                 case "__CallContext" : return _message.LogicalCallContext;
153                                 case "__Args" : return _message.Args;
154                                 case "__OutArgs": return ((IMethodReturnMessage)_message).OutArgs;
155                                 case "__Return": return ((IMethodReturnMessage)_message).ReturnValue;
156                                 default : return null;
157                         }
158                 }
159
160                 protected virtual void SetMethodProperty (string key, object value)
161                 {
162                         switch (key)
163                         {
164                                 case "__CallContext": // Ignore?
165                                 case "__OutArgs":
166                                 case "__Return": return;
167
168                                 case "__MethodName" : 
169                                 case "__TypeName" : 
170                                 case "__MethodSignature" : 
171                                 case "__Args" : throw new ArgumentException ("key was invalid");
172                                 case "__Uri": ((IInternalMessage)_message).Uri = (string) value; return;
173                         }
174                 }
175
176                 public ICollection Keys 
177                 { 
178                         get 
179                         { 
180                                 ArrayList keys = new ArrayList();
181                                 for (int n=0; n<_methodKeys.Length; n++)
182                                         keys.Add (_methodKeys[n]);
183
184                                 if (_internalProperties != null)
185                                 {
186                                         foreach (string key in _internalProperties.Keys)
187                                                 if (!IsOverridenKey (key)) keys.Add (key);
188                                 }
189
190                                 return keys; 
191                         }
192                 }
193
194                 public ICollection Values 
195                 { 
196                         get 
197                         { 
198                                 ArrayList values = new ArrayList();
199                                 for (int n=0; n<_methodKeys.Length; n++)
200                                         values.Add (GetMethodProperty(_methodKeys[n]));
201
202                                 if (_internalProperties != null)
203                                 {
204                                         foreach (DictionaryEntry entry in _internalProperties)
205                                                 if (!IsOverridenKey((string)entry.Key)) values.Add (entry.Value);
206                                 }
207
208                                 return values; 
209                         }
210                 }
211
212                 public void Add (object key, object value)
213                 {
214                         string keyStr = (string)key;
215                         for (int n=0; n<_methodKeys.Length; n++)
216                                 if (_methodKeys[n] == keyStr) {
217                                         SetMethodProperty (keyStr, value);
218                                         return;
219                                 }
220
221                         if (_internalProperties == null) _internalProperties = AllocInternalProperties();
222                         _internalProperties[key] = value;
223                 }
224
225                 public void Clear ()
226                 {
227                         if (_internalProperties != null) _internalProperties.Clear();
228                 }
229
230                 public bool Contains (object key)
231                 {
232                         string keyStr = (string)key;
233                         for (int n=0; n<_methodKeys.Length; n++)
234                                 if (_methodKeys[n] == keyStr) return true;
235
236                         if (_internalProperties != null) return _internalProperties.Contains (key);
237                         else return false;
238                 }
239
240                 public void Remove (object key)
241                 {
242                         string keyStr = (string)key;
243                         for (int n=0; n<_methodKeys.Length; n++)
244                                 if (_methodKeys[n] == keyStr) throw new ArgumentException ("key was invalid");
245
246                         if (_internalProperties != null) _internalProperties.Remove (key);
247                 }
248
249                 public int Count 
250                 { 
251                         get 
252                         {
253                                 if (_internalProperties != null) return _internalProperties.Count + _methodKeys.Length;
254                                 else return _methodKeys.Length;
255                         }
256                 }
257
258                 public bool IsSynchronized 
259                 { 
260                         get { return false; }
261                 }
262
263                 public object SyncRoot 
264                 { 
265                         get { return this; }
266                 }
267
268                 public void CopyTo (Array array, int index)
269                 {
270                         Values.CopyTo (array, index);
271                 }
272
273                 IEnumerator IEnumerable.GetEnumerator()
274                 {
275                         return new DictionaryEnumerator (this);
276                 }
277
278                 public IDictionaryEnumerator GetEnumerator ()
279                 {
280                         return new DictionaryEnumerator (this);
281                 }
282
283                 // Dictionary enumerator
284
285                 class DictionaryEnumerator : IDictionaryEnumerator
286                 {
287                         MethodDictionary _methodDictionary;
288                         IDictionaryEnumerator _hashtableEnum;
289                         int _posMethod;
290
291                         public DictionaryEnumerator (MethodDictionary methodDictionary)
292                         {
293                                 _methodDictionary = methodDictionary;
294                                 _hashtableEnum = (_methodDictionary._internalProperties != null) ? _methodDictionary._internalProperties.GetEnumerator() : null;
295                                 _posMethod = -1;
296                         }
297
298                         public object Current 
299                         {
300                                 get {return Entry.Value; }
301                         }
302
303                         public bool MoveNext()
304                         {
305                                 if (_posMethod != -2)
306                                 {
307                                         _posMethod++;
308                                         if (_posMethod < _methodDictionary._methodKeys.Length) return true;
309                                         _posMethod = -2;
310                                 }
311
312                                 if (_hashtableEnum == null) return false;
313                                 
314                                 while (_hashtableEnum.MoveNext())
315                                 {
316                                         if (!_methodDictionary.IsOverridenKey((string)_hashtableEnum.Key)) 
317                                                 return true;
318                                 }
319                                 return false;
320                         }
321
322                         public void Reset()
323                         {
324                                 _posMethod = -1;
325                                 _hashtableEnum.Reset();
326                         }
327
328                         public DictionaryEntry Entry 
329                         {
330                                 get
331                                 {
332                                         if (_posMethod >= 0) 
333                                                 return new DictionaryEntry (_methodDictionary._methodKeys[_posMethod], _methodDictionary.GetMethodProperty(_methodDictionary._methodKeys[_posMethod]));
334                                         else if (_posMethod == -1 || _hashtableEnum == null) 
335                                                 throw new InvalidOperationException ("The enumerator is positioned before the first element of the collection or after the last element");
336                                         else
337                                                 return _hashtableEnum.Entry;
338                                 }
339                         }
340
341                         public object Key
342                         {
343                                 get { return Entry.Key; }
344                         }
345
346                         public object Value
347                         {
348                                 get { return Entry.Value; }
349                         }
350                 }
351
352         }
353 }