[System.Net] Add support for .pac proxy config scripts on mac
[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                 IDisposable,
43                 ICommunicationObject where TChannel : class
44         {
45                 static InstanceContext initialContxt = new InstanceContext (null);
46
47                 ChannelFactory<TChannel> factory;
48                 IClientChannel inner_channel;
49
50                 protected delegate IAsyncResult BeginOperationDelegate (object[] inValues, AsyncCallback asyncCallback, object state);
51                 protected delegate object[] EndOperationDelegate (IAsyncResult result);
52
53                 protected ClientBase ()
54                         : this (initialContxt)
55                 {
56                 }
57
58                 protected ClientBase (string endpointConfigurationName)
59                         : this (initialContxt, endpointConfigurationName)
60                 {
61                 }
62
63                 protected ClientBase (Binding binding, EndpointAddress remoteAddress)
64                         : this (initialContxt, binding, remoteAddress)
65                 {
66                 }
67
68                 protected ClientBase (string endpointConfigurationName, EndpointAddress remoteAddress)
69                         : this (initialContxt, endpointConfigurationName, remoteAddress)
70                 {
71                 }
72
73                 protected ClientBase (string endpointConfigurationName, string remoteAddress)
74                         : this (initialContxt, endpointConfigurationName, remoteAddress)
75                 {
76                 }
77
78                 protected ClientBase (InstanceContext instance)
79                         : this (instance, "*")
80                 {
81                 }
82
83                 protected ClientBase (InstanceContext instance, string endpointConfigurationName)
84                 {
85                         if (instance == null)
86                                 throw new ArgumentNullException ("instanceContext");
87                         if (endpointConfigurationName == null)
88                                 throw new ArgumentNullException ("endpointConfigurationName");
89
90                         Initialize (instance, endpointConfigurationName, null);
91                 }
92
93                 protected ClientBase (InstanceContext instance,
94                         string endpointConfigurationName, EndpointAddress remoteAddress)
95                 {
96                         if (instance == null)
97                                 throw new ArgumentNullException ("instanceContext");
98                         if (endpointConfigurationName == null)
99                                 throw new ArgumentNullException ("endpointConfigurationName");
100                         if (remoteAddress == null)
101                                 throw new ArgumentNullException ("remoteAddress");
102
103                         Initialize (instance, endpointConfigurationName, remoteAddress);
104                 }
105
106                 protected ClientBase (InstanceContext instance,
107                         string endpointConfigurationName, string remoteAddress)
108                 {
109                         if (instance == null)
110                                 throw new ArgumentNullException ("instanceContext");
111                         if (remoteAddress == null)
112                                 throw new ArgumentNullException ("endpointAddress");
113                         if (endpointConfigurationName == null)
114                                 throw new ArgumentNullException ("endpointConfigurationName");
115
116                         Initialize (instance, endpointConfigurationName, new EndpointAddress (remoteAddress));
117                 }
118
119                 protected ClientBase (InstanceContext instance,
120                         Binding binding, EndpointAddress remoteAddress)
121                 {
122                         if (instance == null)
123                                 throw new ArgumentNullException ("instanceContext");
124                         if (binding == null)
125                                 throw new ArgumentNullException ("binding");
126                         if (remoteAddress == null)
127                                 throw new ArgumentNullException ("remoteAddress");
128
129                         Initialize (instance, binding, remoteAddress);
130                 }
131
132 #if NET_4_0
133                 protected ClientBase (ServiceEndpoint endpoint)
134                         : this (null, endpoint)
135                 {
136                 }
137
138                 protected ClientBase (InstanceContext instance, ServiceEndpoint endpoint)
139                         : this (instance, new ChannelFactory<TChannel> (endpoint))
140                 {
141                 }
142 #endif
143
144                 internal ClientBase (ChannelFactory<TChannel> factory)
145                         : this (null, factory)
146                 {
147                 }
148
149                 internal ClientBase (InstanceContext instance, ChannelFactory<TChannel> factory)
150                 {
151                         // FIXME: use instance
152                         ChannelFactory = factory;
153                 }
154
155                 internal virtual void Initialize (InstanceContext instance,
156                         string endpointConfigurationName, EndpointAddress remoteAddress)
157                 {
158                         // FIXME: use instance
159                         ChannelFactory = new ChannelFactory<TChannel> (endpointConfigurationName, remoteAddress);
160                 }
161
162                 internal virtual void Initialize (InstanceContext instance,
163                         Binding binding, EndpointAddress remoteAddress)
164                 {
165                         // FIXME: use instance
166                         ChannelFactory = new ChannelFactory<TChannel> (binding, remoteAddress);
167                 }
168
169                 public ChannelFactory<TChannel> ChannelFactory {
170                         get { return factory; }
171                         internal set {
172                                 factory = value;
173                                 factory.OwnerClientBase = this;
174                         }
175                 }
176
177                 public ClientCredentials ClientCredentials {
178                         get { return ChannelFactory.Credentials; }
179                 }
180
181                 public ServiceEndpoint Endpoint {
182                         get { return factory.Endpoint; }
183                 }
184
185                 public IClientChannel InnerChannel {
186                         get {
187                                 if (inner_channel == null)
188                                         inner_channel = (IClientChannel) (object) CreateChannel ();
189                                 return inner_channel;
190                         }
191                 }
192
193                 protected TChannel Channel {
194                         get { return (TChannel) (object) InnerChannel; }
195                 }
196
197                 public CommunicationState State {
198                         get { return inner_channel != null ? inner_channel.State : CommunicationState.Created; }
199                 }
200
201                 public void Abort ()
202                 {
203                         InnerChannel.Abort ();
204                 }
205
206                 public void Close ()
207                 {
208                         InnerChannel.Close ();
209                 }
210
211                 public void DisplayInitializationUI ()
212                 {
213                         InnerChannel.DisplayInitializationUI ();
214                 }
215
216                 protected T GetDefaultValueForInitialization<T> ()
217                 {
218                         return default (T);
219                 }
220
221                 //IAsyncResult delegate_async;
222
223                 void RunCompletedCallback (SendOrPostCallback callback, InvokeAsyncCompletedEventArgs args)
224                 {
225                         callback (args);
226                 }
227
228                 protected void InvokeAsync (BeginOperationDelegate beginOperationDelegate,
229                         object [] inValues, EndOperationDelegate endOperationDelegate,
230                         SendOrPostCallback operationCompletedCallback, object userState)
231                 {
232                         if (beginOperationDelegate == null)
233                                 throw new ArgumentNullException ("beginOperationDelegate");
234                         if (endOperationDelegate == null)
235                                 throw new ArgumentNullException ("endOperationDelegate");
236                         //if (delegate_async != null)
237                         //      throw new InvalidOperationException ("Another async operation is in progress");
238
239                         AsyncCallback cb = delegate (IAsyncResult ar) {
240                                 object [] results = null;
241                                 Exception error = null;
242                                 bool cancelled = false; // FIXME: fill it in case it is cancelled
243                                 try {
244                                         results = endOperationDelegate (ar);
245                                 } catch (Exception ex) {
246                                         error = ex;
247                                 }
248                                 try {
249                                         if (operationCompletedCallback != null)
250                                                 RunCompletedCallback (operationCompletedCallback, new InvokeAsyncCompletedEventArgs (results, error, cancelled, userState));
251                                 } catch (Exception ex) {
252                                         //Console.WriteLine ("Exception during operationCompletedCallback" + ex);
253                                         throw;
254                                 }
255                                 //Console.WriteLine ("System.ServiceModel.ClientBase<TChannel>: web service invocation is successfully done (operationCompletedCallback may not be).");
256                         };
257                         begin_async_result = beginOperationDelegate (inValues, cb, userState);
258                 }
259                 IAsyncResult begin_async_result;
260
261                 void IDisposable.Dispose ()
262                 {
263                         Close ();
264                 }
265
266                 protected virtual TChannel CreateChannel ()
267                 {
268                         return ChannelFactory.CreateChannel ();
269                 }
270
271                 public void Open ()
272                 {
273                         InnerChannel.Open ();
274                 }
275
276                 #region ICommunicationObject implementation
277
278                 IAsyncResult ICommunicationObject.BeginOpen (
279                         AsyncCallback callback, object state)
280                 {
281                         return InnerChannel.BeginOpen (callback, state);
282                 }
283
284                 IAsyncResult ICommunicationObject.BeginOpen (
285                         TimeSpan timeout, AsyncCallback callback, object state)
286                 {
287                         return InnerChannel.BeginOpen (timeout, callback, state);
288                 }
289
290                 void ICommunicationObject.EndOpen (IAsyncResult result)
291                 {
292                         InnerChannel.EndOpen (result);
293                 }
294
295                 IAsyncResult ICommunicationObject.BeginClose (
296                         AsyncCallback callback, object state)
297                 {
298                         return InnerChannel.BeginClose (callback, state);
299                 }
300
301                 IAsyncResult ICommunicationObject.BeginClose (
302                         TimeSpan timeout, AsyncCallback callback, object state)
303                 {
304                         return InnerChannel.BeginClose (timeout, callback, state);
305                 }
306
307                 void ICommunicationObject.EndClose (IAsyncResult result)
308                 {
309                         InnerChannel.EndClose (result);
310                 }
311
312                 void ICommunicationObject.Close (TimeSpan timeout)
313                 {
314                         InnerChannel.Close (timeout);
315                 }
316
317                 void ICommunicationObject.Open (TimeSpan timeout)
318                 {
319                         InnerChannel.Open (timeout);
320                 }
321
322                 event EventHandler ICommunicationObject.Opening {
323                         add { InnerChannel.Opening += value; }
324                         remove { InnerChannel.Opening -= value; }
325                 }
326                 event EventHandler ICommunicationObject.Opened {
327                         add { InnerChannel.Opened += value; }
328                         remove { InnerChannel.Opened -= value; }
329                 }
330                 event EventHandler ICommunicationObject.Closing {
331                         add { InnerChannel.Closing += value; }
332                         remove { InnerChannel.Closing -= value; }
333                 }
334                 event EventHandler ICommunicationObject.Closed {
335                         add { InnerChannel.Closed += value; }
336                         remove { InnerChannel.Closed -= value; }
337                 }
338                 event EventHandler ICommunicationObject.Faulted {
339                         add { InnerChannel.Faulted += value; }
340                         remove { InnerChannel.Faulted -= value; }
341                 }
342
343                 #endregion
344
345                 protected class InvokeAsyncCompletedEventArgs : AsyncCompletedEventArgs
346                 {
347                         internal InvokeAsyncCompletedEventArgs (object [] results, Exception error, bool cancelled, object userState)
348                                 : base (error, cancelled, userState)
349                         {
350                                 Results = results;
351                         }
352
353                         public object [] Results { get; private set; }
354                 }
355
356 #if NET_4_0
357                 protected internal
358 #else
359                 internal
360 #endif
361                 class ChannelBase<T> : IClientChannel, IOutputChannel, IRequestChannel where T : class
362                 {
363                         ServiceEndpoint endpoint;
364                         ChannelFactory factory;
365                         ClientRuntimeChannel inner_channel;
366
367                         protected ChannelBase (ClientBase<T> client)
368                                 : this (client.Endpoint, client.ChannelFactory)
369                         {
370                         }
371
372                         internal ChannelBase (ServiceEndpoint endpoint, ChannelFactory factory)
373                         {
374                                 this.endpoint = endpoint;
375                                 this.factory = factory;
376                         }
377
378                         internal ClientRuntimeChannel Inner {
379                                 get {
380                                         if (inner_channel == null)
381                                                 inner_channel = new ClientRuntimeChannel (endpoint, factory, endpoint.Address, null);
382                                         return inner_channel;
383                                 }
384                         }
385
386                         protected object Invoke (string methodName, object [] args)
387                         {
388                                 var cd = endpoint.Contract;
389                                 var od = cd.Operations.Find (methodName);
390                                 if (od == null)
391                                         throw new ArgumentException (String.Format ("Operation '{0}' not found in the service contract '{1}' in namespace '{2}'", methodName, cd.Name, cd.Namespace));
392                                 return Inner.Process (od.SyncMethod, methodName, args);
393                         }
394
395                         protected IAsyncResult BeginInvoke (string methodName, object [] args, AsyncCallback callback, object state)
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.BeginProcess (od.BeginMethod, methodName, args, callback, state);
402                         }
403
404                         protected object EndInvoke (string methodName, object [] args, IAsyncResult result)
405                         {
406                                 var cd = endpoint.Contract;
407                                 var od = cd.Operations.Find (methodName);
408                                 if (od == null)
409                                         throw new ArgumentException (String.Format ("Operation '{0}' not found in the service contract '{1}' in namespace '{2}'", methodName, cd.Name, cd.Namespace));
410                                 return Inner.EndProcess (od.EndMethod, methodName, args, result);
411                         }
412
413                         #region ICommunicationObject
414
415                         IAsyncResult ICommunicationObject.BeginClose (AsyncCallback callback, object state)
416                         {
417                                 return Inner.BeginClose (callback, state);
418                         }
419
420                         IAsyncResult ICommunicationObject.BeginClose (TimeSpan timeout, AsyncCallback callback, object state)
421                         {
422                                 return Inner.BeginClose (timeout, callback, state);
423                         }
424
425                         void ICommunicationObject.Close ()
426                         {
427                                 Inner.Close ();
428                         }
429
430                         void ICommunicationObject.Close (TimeSpan timeout)
431                         {
432                                 Inner.Close (timeout);
433                         }
434
435                         IAsyncResult ICommunicationObject.BeginOpen (AsyncCallback callback, object state)
436                         {
437                                 return Inner.BeginOpen (callback, state);
438                         }
439
440                         IAsyncResult ICommunicationObject.BeginOpen (TimeSpan timeout, AsyncCallback callback, object state)
441                         {
442                                 return Inner.BeginOpen (timeout, callback, state);
443                         }
444
445                         void ICommunicationObject.Open ()
446                         {
447                                 Inner.Open ();
448                         }
449
450                         void ICommunicationObject.Open (TimeSpan timeout)
451                         {
452                                 Inner.Open (timeout);
453                         }
454
455                         void ICommunicationObject.Abort ()
456                         {
457                                 Inner.Abort ();
458                         }
459
460                         void ICommunicationObject.EndClose (IAsyncResult result)
461                         {
462                                 Inner.EndClose (result);
463                         }
464
465                         void ICommunicationObject.EndOpen (IAsyncResult result)
466                         {
467                                 Inner.EndOpen (result);
468                         }
469
470                         CommunicationState ICommunicationObject.State {
471                                 get { return Inner.State; }
472                         }
473
474                         event EventHandler ICommunicationObject.Opened {
475                                 add { Inner.Opened += value; }
476                                 remove { Inner.Opened -= value; }
477                         }
478
479                         event EventHandler ICommunicationObject.Opening {
480                                 add { Inner.Opening += value; }
481                                 remove { Inner.Opening -= value; }
482                         }
483
484                         event EventHandler ICommunicationObject.Closed {
485                                 add { Inner.Closed += value; }
486                                 remove { Inner.Closed -= value; }
487                         }
488
489                         event EventHandler ICommunicationObject.Closing {
490                                 add { Inner.Closing += value; }
491                                 remove { Inner.Closing -= value; }
492                         }
493
494                         event EventHandler ICommunicationObject.Faulted {
495                                 add { Inner.Faulted += value; }
496                                 remove { Inner.Faulted -= value; }
497                         }
498
499                         #endregion
500
501                         #region IClientChannel
502
503                         public bool AllowInitializationUI {
504                                 get { return Inner.AllowInitializationUI; }
505                                 set { Inner.AllowInitializationUI = value; }
506                         }
507
508                         public bool DidInteractiveInitialization {
509                                 get { return Inner.DidInteractiveInitialization; }
510                         }
511
512                         public Uri Via {
513                                 get { return Inner.Via; }
514                         }
515
516                         public IAsyncResult BeginDisplayInitializationUI (
517                                 AsyncCallback callback, object state)
518                         {
519                                 return Inner.BeginDisplayInitializationUI (callback, state);
520                         }
521
522                         public void EndDisplayInitializationUI (
523                                 IAsyncResult result)
524                         {
525                                 Inner.EndDisplayInitializationUI (result);
526                         }
527
528                         public void DisplayInitializationUI ()
529                         {
530                                 Inner.DisplayInitializationUI ();
531                         }
532
533                         public void Dispose ()
534                         {
535                                 Inner.Dispose ();
536                         }
537
538                         public event EventHandler<UnknownMessageReceivedEventArgs> UnknownMessageReceived {
539                                 add { Inner.UnknownMessageReceived += value; }
540                                 remove { Inner.UnknownMessageReceived -= value; }
541                         }
542
543                         #endregion
544
545                         #region IContextChannel
546
547                         [MonoTODO]
548                         public bool AllowOutputBatching {
549                                 get { return Inner.AllowOutputBatching; }
550
551                                 set { Inner.AllowOutputBatching = value; }
552                         }
553
554                         [MonoTODO]
555                         public IInputSession InputSession {
556                                 get { return Inner.InputSession; }
557                         }
558
559                         public EndpointAddress LocalAddress {
560                                 get { return Inner.LocalAddress; }
561                         }
562
563                         [MonoTODO]
564                         public TimeSpan OperationTimeout {
565                                 get { return Inner.OperationTimeout; }
566                                 set { Inner.OperationTimeout = value; }
567                         }
568
569                         [MonoTODO]
570                         public IOutputSession OutputSession {
571                                 get { return Inner.OutputSession; }
572                         }
573
574                         public EndpointAddress RemoteAddress {
575                                 get { return Inner.RemoteAddress; }
576                         }
577
578                         [MonoTODO]
579                         public string SessionId {
580                                 get { return Inner.SessionId; }
581                         }
582
583                         #endregion
584
585                         #region IRequestChannel
586
587                         IAsyncResult IRequestChannel.BeginRequest (Message message, AsyncCallback callback, object state)
588                         {
589                                 return ((IRequestChannel) this).BeginRequest (message, endpoint.Binding.SendTimeout, callback, state);
590                         }
591
592                         IAsyncResult IRequestChannel.BeginRequest (Message message, TimeSpan timeout, AsyncCallback callback, object state)
593                         {
594                                 return Inner.BeginRequest (message, timeout, callback, state);
595                         }
596
597                         Message IRequestChannel.EndRequest (IAsyncResult result)
598                         {
599                                 return Inner.EndRequest (result);
600                         }
601
602                         Message IRequestChannel.Request (Message message)
603                         {
604                                 return ((IRequestChannel) this).Request (message, endpoint.Binding.SendTimeout);
605                         }
606
607                         Message IRequestChannel.Request (Message message, TimeSpan timeout)
608                         {
609                                 return Inner.Request (message, timeout);
610                         }
611
612                         EndpointAddress IRequestChannel.RemoteAddress {
613                                 get { return endpoint.Address; }
614                         }
615
616                         Uri IRequestChannel.Via {
617                                 get { return Via; }
618                         }
619
620                         #endregion
621
622                         #region IOutputChannel
623
624                         IAsyncResult IOutputChannel.BeginSend (Message message, AsyncCallback callback, object state)
625                         {
626                                 return ((IOutputChannel) this).BeginSend (message, endpoint.Binding.SendTimeout, callback, state);
627                         }
628
629                         IAsyncResult IOutputChannel.BeginSend (Message message, TimeSpan timeout, AsyncCallback callback, object state)
630                         {
631                                 return Inner.BeginSend (message, timeout, callback, state);
632                         }
633
634                         void IOutputChannel.EndSend (IAsyncResult result)
635                         {
636                                 Inner.EndSend (result);
637                         }
638
639                         void IOutputChannel.Send (Message message)
640                         {
641                                 ((IOutputChannel) this).Send (message, endpoint.Binding.SendTimeout);
642                         }
643
644                         void IOutputChannel.Send (Message message, TimeSpan timeout)
645                         {
646                                 Inner.Send (message, timeout);
647                         }
648
649                         #endregion
650
651                         IExtensionCollection<IContextChannel> IExtensibleObject<IContextChannel>.Extensions {
652                                 get { return Inner.Extensions; }
653                         }
654
655                         TProperty IChannel.GetProperty<TProperty> ()
656                         {
657                                 return Inner.GetProperty<TProperty> ();
658                         }
659                 }
660         }
661 }