Merge pull request #495 from nicolas-raoul/fix-for-issue2907-with-no-formatting-changes
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel / ClientBase.cs
1 //
2 // generic ClientBase.cs
3 //
4 // Author:
5 //      Atsushi Enomoto <atsushi@ximian.com>
6 //
7 // Copyright (C) 2005-2006 Novell, Inc.  http://www.novell.com
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28 using System;
29 using System.Collections.Generic;
30 using System.ComponentModel;
31 using System.Reflection;
32 using System.ServiceModel.Channels;
33 using System.ServiceModel.Description;
34 using System.ServiceModel.Dispatcher;
35 using System.Threading;
36 using System.ServiceModel.MonoInternal;
37
38 namespace System.ServiceModel
39 {
40         [MonoTODO ("It somehow rejects classes, but dunno how we can do that besides our code wise.")]
41         public abstract class ClientBase<TChannel> :
42 #if !MOONLIGHT
43                 IDisposable,
44 #endif
45                 ICommunicationObject where TChannel : class
46         {
47                 static InstanceContext initialContxt = new InstanceContext (null);
48
49                 ChannelFactory<TChannel> factory;
50                 IClientChannel inner_channel;
51
52                 protected delegate IAsyncResult BeginOperationDelegate (object[] inValues, AsyncCallback asyncCallback, object state);
53                 protected delegate object[] EndOperationDelegate (IAsyncResult result);
54
55                 protected ClientBase ()
56                         : this (initialContxt)
57                 {
58                 }
59
60                 protected ClientBase (string endpointConfigurationName)
61                         : this (initialContxt, endpointConfigurationName)
62                 {
63                 }
64
65                 protected ClientBase (Binding binding, EndpointAddress remoteAddress)
66                         : this (initialContxt, binding, remoteAddress)
67                 {
68                 }
69
70                 protected ClientBase (string endpointConfigurationName, EndpointAddress remoteAddress)
71                         : this (initialContxt, endpointConfigurationName, remoteAddress)
72                 {
73                 }
74
75                 protected ClientBase (string endpointConfigurationName, string remoteAddress)
76                         : this (initialContxt, endpointConfigurationName, remoteAddress)
77                 {
78                 }
79
80                 protected ClientBase (InstanceContext instance)
81                         : this (instance, "*")
82                 {
83                 }
84
85                 protected ClientBase (InstanceContext instance, string endpointConfigurationName)
86                 {
87                         if (instance == null)
88                                 throw new ArgumentNullException ("instanceContext");
89                         if (endpointConfigurationName == null)
90                                 throw new ArgumentNullException ("endpointConfigurationName");
91
92                         Initialize (instance, endpointConfigurationName, null);
93                 }
94
95                 protected ClientBase (InstanceContext instance,
96                         string endpointConfigurationName, EndpointAddress remoteAddress)
97                 {
98                         if (instance == null)
99                                 throw new ArgumentNullException ("instanceContext");
100                         if (endpointConfigurationName == null)
101                                 throw new ArgumentNullException ("endpointConfigurationName");
102                         if (remoteAddress == null)
103                                 throw new ArgumentNullException ("remoteAddress");
104
105                         Initialize (instance, endpointConfigurationName, remoteAddress);
106                 }
107
108                 protected ClientBase (InstanceContext instance,
109                         string endpointConfigurationName, string remoteAddress)
110                 {
111                         if (instance == null)
112                                 throw new ArgumentNullException ("instanceContext");
113                         if (remoteAddress == null)
114                                 throw new ArgumentNullException ("endpointAddress");
115                         if (endpointConfigurationName == null)
116                                 throw new ArgumentNullException ("endpointConfigurationName");
117
118                         Initialize (instance, endpointConfigurationName, new EndpointAddress (remoteAddress));
119                 }
120
121                 protected ClientBase (InstanceContext instance,
122                         Binding binding, EndpointAddress remoteAddress)
123                 {
124                         if (instance == null)
125                                 throw new ArgumentNullException ("instanceContext");
126                         if (binding == null)
127                                 throw new ArgumentNullException ("binding");
128                         if (remoteAddress == null)
129                                 throw new ArgumentNullException ("remoteAddress");
130
131                         Initialize (instance, binding, remoteAddress);
132                 }
133
134 #if NET_4_0
135                 protected ClientBase (ServiceEndpoint endpoint)
136                         : this (null, endpoint)
137                 {
138                 }
139
140                 protected ClientBase (InstanceContext instance, ServiceEndpoint endpoint)
141                         : this (instance, new ChannelFactory<TChannel> (endpoint))
142                 {
143                 }
144 #endif
145
146                 internal ClientBase (ChannelFactory<TChannel> factory)
147                         : this (null, factory)
148                 {
149                 }
150
151                 internal ClientBase (InstanceContext instance, ChannelFactory<TChannel> factory)
152                 {
153                         // FIXME: use instance
154                         ChannelFactory = factory;
155                 }
156
157                 internal virtual void Initialize (InstanceContext instance,
158                         string endpointConfigurationName, EndpointAddress remoteAddress)
159                 {
160                         // FIXME: use instance
161                         ChannelFactory = new ChannelFactory<TChannel> (endpointConfigurationName, remoteAddress);
162                 }
163
164                 internal virtual void Initialize (InstanceContext instance,
165                         Binding binding, EndpointAddress remoteAddress)
166                 {
167                         // FIXME: use instance
168                         ChannelFactory = new ChannelFactory<TChannel> (binding, remoteAddress);
169                 }
170
171                 public ChannelFactory<TChannel> ChannelFactory {
172                         get { return factory; }
173                         internal set {
174                                 factory = value;
175                                 factory.OwnerClientBase = this;
176                         }
177                 }
178
179                 public ClientCredentials ClientCredentials {
180                         get { return ChannelFactory.Credentials; }
181                 }
182
183                 public ServiceEndpoint Endpoint {
184                         get { return factory.Endpoint; }
185                 }
186
187                 public IClientChannel InnerChannel {
188                         get {
189                                 if (inner_channel == null)
190                                         inner_channel = (IClientChannel) (object) CreateChannel ();
191                                 return inner_channel;
192                         }
193                 }
194
195                 protected TChannel Channel {
196                         get { return (TChannel) (object) InnerChannel; }
197                 }
198
199                 public CommunicationState State {
200                         get { return inner_channel != null ? inner_channel.State : CommunicationState.Created; }
201                 }
202
203                 public void Abort ()
204                 {
205                         InnerChannel.Abort ();
206                 }
207
208                 public void Close ()
209                 {
210                         InnerChannel.Close ();
211                 }
212
213                 public void DisplayInitializationUI ()
214                 {
215                         InnerChannel.DisplayInitializationUI ();
216                 }
217
218                 protected T GetDefaultValueForInitialization<T> ()
219                 {
220                         return default (T);
221                 }
222
223                 //IAsyncResult delegate_async;
224
225                 void RunCompletedCallback (SendOrPostCallback callback, InvokeAsyncCompletedEventArgs args)
226                 {
227 #if !MOONLIGHT
228                         callback (args);
229 #else
230                         // this ensure the "dirty" work is done in mscorlib and "frees" this assembly from any [SC] or [SSC] code
231                         Mono.MoonlightHelper.RunOnMainThread (callback, args);
232 #endif
233                 }
234
235                 protected void InvokeAsync (BeginOperationDelegate beginOperationDelegate,
236                         object [] inValues, EndOperationDelegate endOperationDelegate,
237                         SendOrPostCallback operationCompletedCallback, object userState)
238                 {
239                         if (beginOperationDelegate == null)
240                                 throw new ArgumentNullException ("beginOperationDelegate");
241                         if (endOperationDelegate == null)
242                                 throw new ArgumentNullException ("endOperationDelegate");
243                         //if (delegate_async != null)
244                         //      throw new InvalidOperationException ("Another async operation is in progress");
245
246                         AsyncCallback cb = delegate (IAsyncResult ar) {
247                                 object [] results = null;
248                                 Exception error = null;
249                                 bool cancelled = false; // FIXME: fill it in case it is cancelled
250                                 try {
251                                         results = endOperationDelegate (ar);
252                                 } catch (Exception ex) {
253                                         error = ex;
254                                 }
255                                 try {
256                                         if (operationCompletedCallback != null)
257                                                 RunCompletedCallback (operationCompletedCallback, new InvokeAsyncCompletedEventArgs (results, error, cancelled, userState));
258                                 } catch (Exception ex) {
259                                         //Console.WriteLine ("Exception during operationCompletedCallback" + ex);
260                                         throw;
261                                 }
262                                 //Console.WriteLine ("System.ServiceModel.ClientBase<TChannel>: web service invocation is successfully done (operationCompletedCallback may not be).");
263                         };
264                         begin_async_result = beginOperationDelegate (inValues, cb, userState);
265                 }
266                 IAsyncResult begin_async_result;
267
268 #if !MOONLIGHT
269                 void IDisposable.Dispose ()
270                 {
271                         Close ();
272                 }
273 #endif
274                 protected virtual TChannel CreateChannel ()
275                 {
276                         return ChannelFactory.CreateChannel ();
277                 }
278
279                 public void Open ()
280                 {
281                         InnerChannel.Open ();
282                 }
283
284                 #region ICommunicationObject implementation
285
286                 IAsyncResult ICommunicationObject.BeginOpen (
287                         AsyncCallback callback, object state)
288                 {
289                         return InnerChannel.BeginOpen (callback, state);
290                 }
291
292                 IAsyncResult ICommunicationObject.BeginOpen (
293                         TimeSpan timeout, AsyncCallback callback, object state)
294                 {
295                         return InnerChannel.BeginOpen (timeout, callback, state);
296                 }
297
298                 void ICommunicationObject.EndOpen (IAsyncResult result)
299                 {
300                         InnerChannel.EndOpen (result);
301                 }
302
303                 IAsyncResult ICommunicationObject.BeginClose (
304                         AsyncCallback callback, object state)
305                 {
306                         return InnerChannel.BeginClose (callback, state);
307                 }
308
309                 IAsyncResult ICommunicationObject.BeginClose (
310                         TimeSpan timeout, AsyncCallback callback, object state)
311                 {
312                         return InnerChannel.BeginClose (timeout, callback, state);
313                 }
314
315                 void ICommunicationObject.EndClose (IAsyncResult result)
316                 {
317                         InnerChannel.EndClose (result);
318                 }
319
320                 void ICommunicationObject.Close (TimeSpan timeout)
321                 {
322                         InnerChannel.Close (timeout);
323                 }
324
325                 void ICommunicationObject.Open (TimeSpan timeout)
326                 {
327                         InnerChannel.Open (timeout);
328                 }
329
330                 event EventHandler ICommunicationObject.Opening {
331                         add { InnerChannel.Opening += value; }
332                         remove { InnerChannel.Opening -= value; }
333                 }
334                 event EventHandler ICommunicationObject.Opened {
335                         add { InnerChannel.Opened += value; }
336                         remove { InnerChannel.Opened -= value; }
337                 }
338                 event EventHandler ICommunicationObject.Closing {
339                         add { InnerChannel.Closing += value; }
340                         remove { InnerChannel.Closing -= value; }
341                 }
342                 event EventHandler ICommunicationObject.Closed {
343                         add { InnerChannel.Closed += value; }
344                         remove { InnerChannel.Closed -= value; }
345                 }
346                 event EventHandler ICommunicationObject.Faulted {
347                         add { InnerChannel.Faulted += value; }
348                         remove { InnerChannel.Faulted -= value; }
349                 }
350
351                 #endregion
352
353                 protected class InvokeAsyncCompletedEventArgs : AsyncCompletedEventArgs
354                 {
355                         internal InvokeAsyncCompletedEventArgs (object [] results, Exception error, bool cancelled, object userState)
356                                 : base (error, cancelled, userState)
357                         {
358                                 Results = results;
359                         }
360
361                         public object [] Results { get; private set; }
362                 }
363
364 #if NET_2_1 || NET_4_0
365                 protected internal
366 #else
367                 internal
368 #endif
369                 class ChannelBase<T> : IClientChannel, IOutputChannel, IRequestChannel where T : class
370                 {
371                         ServiceEndpoint endpoint;
372                         ChannelFactory factory;
373                         ClientRuntimeChannel inner_channel;
374
375                         protected ChannelBase (ClientBase<T> client)
376                                 : this (client.Endpoint, client.ChannelFactory)
377                         {
378                         }
379
380                         internal ChannelBase (ServiceEndpoint endpoint, ChannelFactory factory)
381                         {
382                                 this.endpoint = endpoint;
383                                 this.factory = factory;
384                         }
385
386                         internal ClientRuntimeChannel Inner {
387                                 get {
388                                         if (inner_channel == null)
389                                                 inner_channel = new ClientRuntimeChannel (endpoint, factory, endpoint.Address, null);
390                                         return inner_channel;
391                                 }
392                         }
393
394 #if !MOONLIGHT
395                         protected object Invoke (string methodName, object [] args)
396                         {
397                                 var cd = endpoint.Contract;
398                                 var od = cd.Operations.Find (methodName);
399                                 if (od == null)
400                                         throw new ArgumentException (String.Format ("Operation '{0}' not found in the service contract '{1}' in namespace '{2}'", methodName, cd.Name, cd.Namespace));
401                                 return Inner.Process (od.SyncMethod, methodName, args);
402                         }
403 #endif
404
405                         protected IAsyncResult BeginInvoke (string methodName, object [] args, AsyncCallback callback, object state)
406                         {
407                                 var cd = endpoint.Contract;
408                                 var od = cd.Operations.Find (methodName);
409                                 if (od == null)
410                                         throw new ArgumentException (String.Format ("Operation '{0}' not found in the service contract '{1}' in namespace '{2}'", methodName, cd.Name, cd.Namespace));
411                                 return Inner.BeginProcess (od.BeginMethod, methodName, args, callback, state);
412                         }
413
414                         protected object EndInvoke (string methodName, object [] args, IAsyncResult result)
415                         {
416                                 var cd = endpoint.Contract;
417                                 var od = cd.Operations.Find (methodName);
418                                 if (od == null)
419                                         throw new ArgumentException (String.Format ("Operation '{0}' not found in the service contract '{1}' in namespace '{2}'", methodName, cd.Name, cd.Namespace));
420                                 return Inner.EndProcess (od.EndMethod, methodName, args, result);
421                         }
422
423                         #region ICommunicationObject
424
425                         IAsyncResult ICommunicationObject.BeginClose (AsyncCallback callback, object state)
426                         {
427                                 return Inner.BeginClose (callback, state);
428                         }
429
430                         IAsyncResult ICommunicationObject.BeginClose (TimeSpan timeout, AsyncCallback callback, object state)
431                         {
432                                 return Inner.BeginClose (timeout, callback, state);
433                         }
434
435                         void ICommunicationObject.Close ()
436                         {
437                                 Inner.Close ();
438                         }
439
440                         void ICommunicationObject.Close (TimeSpan timeout)
441                         {
442                                 Inner.Close (timeout);
443                         }
444
445                         IAsyncResult ICommunicationObject.BeginOpen (AsyncCallback callback, object state)
446                         {
447                                 return Inner.BeginOpen (callback, state);
448                         }
449
450                         IAsyncResult ICommunicationObject.BeginOpen (TimeSpan timeout, AsyncCallback callback, object state)
451                         {
452                                 return Inner.BeginOpen (timeout, callback, state);
453                         }
454
455                         void ICommunicationObject.Open ()
456                         {
457                                 Inner.Open ();
458                         }
459
460                         void ICommunicationObject.Open (TimeSpan timeout)
461                         {
462                                 Inner.Open (timeout);
463                         }
464
465                         void ICommunicationObject.Abort ()
466                         {
467                                 Inner.Abort ();
468                         }
469
470                         void ICommunicationObject.EndClose (IAsyncResult result)
471                         {
472                                 Inner.EndClose (result);
473                         }
474
475                         void ICommunicationObject.EndOpen (IAsyncResult result)
476                         {
477                                 Inner.EndOpen (result);
478                         }
479
480                         CommunicationState ICommunicationObject.State {
481                                 get { return Inner.State; }
482                         }
483
484                         event EventHandler ICommunicationObject.Opened {
485                                 add { Inner.Opened += value; }
486                                 remove { Inner.Opened -= value; }
487                         }
488
489                         event EventHandler ICommunicationObject.Opening {
490                                 add { Inner.Opening += value; }
491                                 remove { Inner.Opening -= value; }
492                         }
493
494                         event EventHandler ICommunicationObject.Closed {
495                                 add { Inner.Closed += value; }
496                                 remove { Inner.Closed -= value; }
497                         }
498
499                         event EventHandler ICommunicationObject.Closing {
500                                 add { Inner.Closing += value; }
501                                 remove { Inner.Closing -= value; }
502                         }
503
504                         event EventHandler ICommunicationObject.Faulted {
505                                 add { Inner.Faulted += value; }
506                                 remove { Inner.Faulted -= value; }
507                         }
508
509                         #endregion
510
511                         #region IClientChannel
512
513                         public bool AllowInitializationUI {
514                                 get { return Inner.AllowInitializationUI; }
515                                 set { Inner.AllowInitializationUI = value; }
516                         }
517
518                         public bool DidInteractiveInitialization {
519                                 get { return Inner.DidInteractiveInitialization; }
520                         }
521
522                         public Uri Via {
523                                 get { return Inner.Via; }
524                         }
525
526                         public IAsyncResult BeginDisplayInitializationUI (
527                                 AsyncCallback callback, object state)
528                         {
529                                 return Inner.BeginDisplayInitializationUI (callback, state);
530                         }
531
532                         public void EndDisplayInitializationUI (
533                                 IAsyncResult result)
534                         {
535                                 Inner.EndDisplayInitializationUI (result);
536                         }
537
538                         public void DisplayInitializationUI ()
539                         {
540                                 Inner.DisplayInitializationUI ();
541                         }
542
543                         public void Dispose ()
544                         {
545                                 Inner.Dispose ();
546                         }
547
548                         public event EventHandler<UnknownMessageReceivedEventArgs> UnknownMessageReceived {
549                                 add { Inner.UnknownMessageReceived += value; }
550                                 remove { Inner.UnknownMessageReceived -= value; }
551                         }
552
553                         #endregion
554
555                         #region IContextChannel
556
557                         [MonoTODO]
558                         public bool AllowOutputBatching {
559                                 get { return Inner.AllowOutputBatching; }
560
561                                 set { Inner.AllowOutputBatching = value; }
562                         }
563
564                         [MonoTODO]
565                         public IInputSession InputSession {
566                                 get { return Inner.InputSession; }
567                         }
568
569                         public EndpointAddress LocalAddress {
570                                 get { return Inner.LocalAddress; }
571                         }
572
573                         [MonoTODO]
574                         public TimeSpan OperationTimeout {
575                                 get { return Inner.OperationTimeout; }
576                                 set { Inner.OperationTimeout = value; }
577                         }
578
579                         [MonoTODO]
580                         public IOutputSession OutputSession {
581                                 get { return Inner.OutputSession; }
582                         }
583
584                         public EndpointAddress RemoteAddress {
585                                 get { return Inner.RemoteAddress; }
586                         }
587
588                         [MonoTODO]
589                         public string SessionId {
590                                 get { return Inner.SessionId; }
591                         }
592
593                         #endregion
594
595                         #region IRequestChannel
596
597                         IAsyncResult IRequestChannel.BeginRequest (Message message, AsyncCallback callback, object state)
598                         {
599                                 return ((IRequestChannel) this).BeginRequest (message, endpoint.Binding.SendTimeout, callback, state);
600                         }
601
602                         IAsyncResult IRequestChannel.BeginRequest (Message message, TimeSpan timeout, AsyncCallback callback, object state)
603                         {
604                                 return Inner.BeginRequest (message, timeout, callback, state);
605                         }
606
607                         Message IRequestChannel.EndRequest (IAsyncResult result)
608                         {
609                                 return Inner.EndRequest (result);
610                         }
611
612                         Message IRequestChannel.Request (Message message)
613                         {
614                                 return ((IRequestChannel) this).Request (message, endpoint.Binding.SendTimeout);
615                         }
616
617                         Message IRequestChannel.Request (Message message, TimeSpan timeout)
618                         {
619                                 return Inner.Request (message, timeout);
620                         }
621
622                         EndpointAddress IRequestChannel.RemoteAddress {
623                                 get { return endpoint.Address; }
624                         }
625
626                         Uri IRequestChannel.Via {
627                                 get { return Via; }
628                         }
629
630                         #endregion
631
632                         #region IOutputChannel
633
634                         IAsyncResult IOutputChannel.BeginSend (Message message, AsyncCallback callback, object state)
635                         {
636                                 return ((IOutputChannel) this).BeginSend (message, endpoint.Binding.SendTimeout, callback, state);
637                         }
638
639                         IAsyncResult IOutputChannel.BeginSend (Message message, TimeSpan timeout, AsyncCallback callback, object state)
640                         {
641                                 return Inner.BeginSend (message, timeout, callback, state);
642                         }
643
644                         void IOutputChannel.EndSend (IAsyncResult result)
645                         {
646                                 Inner.EndSend (result);
647                         }
648
649                         void IOutputChannel.Send (Message message)
650                         {
651                                 ((IOutputChannel) this).Send (message, endpoint.Binding.SendTimeout);
652                         }
653
654                         void IOutputChannel.Send (Message message, TimeSpan timeout)
655                         {
656                                 Inner.Send (message, timeout);
657                         }
658
659                         #endregion
660
661                         IExtensionCollection<IContextChannel> IExtensibleObject<IContextChannel>.Extensions {
662                                 get { return Inner.Extensions; }
663                         }
664
665                         TProperty IChannel.GetProperty<TProperty> ()
666                         {
667                                 return Inner.GetProperty<TProperty> ();
668                         }
669                 }
670         }
671 }