[sgen] Make sure we don't sweep a block if we're not supposed to
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel.Channels / ChannelFactoryBase.cs
1 //
2 // ChannelFactoryBase.cs
3 //
4 // Author:
5 //      Atsushi Enomoto  <atsushi@ximian.com>
6 //
7 // Copyright (C) 2005 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
29 using System;
30 using System.Collections.Generic;
31 using System.Collections.ObjectModel;
32 using System.ServiceModel;
33 using System.ServiceModel.Dispatcher;
34
35 namespace System.ServiceModel.Channels
36 {
37         internal interface IHasMessageEncoder
38         {
39                 MessageEncoder MessageEncoder { get; }
40         }
41
42         internal abstract class TransportChannelFactoryBase<TChannel> : ChannelFactoryBase<TChannel>, IHasMessageEncoder
43         {
44                 protected TransportChannelFactoryBase (TransportBindingElement source, BindingContext ctx)
45                 {
46                         Transport = source;
47                 }
48
49                 public TransportBindingElement Transport { get; private set; }
50
51                 public MessageEncoder MessageEncoder { get; internal set; }
52
53                 Action<TimeSpan> open_delegate;
54
55                 protected override IAsyncResult OnBeginOpen (TimeSpan timeout,
56                         AsyncCallback callback, object state)
57                 {
58                         if (open_delegate == null)
59                                 open_delegate = new Action<TimeSpan> (OnOpen);
60                         return open_delegate.BeginInvoke (timeout, callback, state);
61                 }
62
63                 protected override void OnEndOpen (IAsyncResult result)
64                 {
65                         if (open_delegate == null)
66                                 throw new InvalidOperationException ("Async open operation has not started");
67                         open_delegate.EndInvoke (result);
68                 }
69
70                 protected override void OnOpen (TimeSpan timeout)
71                 {
72                 }
73
74                 /* commented out as it is in doubt.
75                 public override T GetProperty<T> ()
76                 {
77                         if (typeof (T) == typeof (MessageVersion))
78                                 return (T) (object) MessageEncoder.MessageVersion;
79                         return base.GetProperty<T> ();
80                 }
81                 */
82         }
83
84         public abstract class ChannelFactoryBase<TChannel>
85                 : ChannelFactoryBase, IChannelFactory<TChannel>
86         {
87                 List<TChannel> channels = new List<TChannel> ();
88
89                 protected ChannelFactoryBase ()
90                         : this (DefaultCommunicationTimeouts.Instance)
91                 {
92                 }
93
94                 protected ChannelFactoryBase (
95                         IDefaultCommunicationTimeouts timeouts)
96                         : base (timeouts)
97                 {
98                 }
99
100                 public TChannel CreateChannel (
101                         EndpointAddress remoteAddress)
102                 {
103                         if (remoteAddress == null)
104                                 throw new ArgumentNullException ("remoteAddress");
105                         return CreateChannel (remoteAddress, remoteAddress.Uri);
106                 }
107
108                 public TChannel CreateChannel (
109                         EndpointAddress remoteAddress, Uri via)
110                 {
111                         if (remoteAddress == null)
112                                 throw new ArgumentNullException ("remoteAddress");
113                         if (via == null)
114                                 throw new ArgumentNullException ("via");
115
116                         ValidateCreateChannel ();
117                         var ch = OnCreateChannel (remoteAddress, via);
118                         channels.Add (ch);
119                         return ch;
120                 }
121
122                 protected abstract TChannel OnCreateChannel (
123                         EndpointAddress remoteAddress, Uri via);
124
125                 protected override void OnAbort ()
126                 {
127                         // this implicitly premises: TChannel is IChannel
128                         foreach (IChannel ch in channels)
129                                 ch.Abort ();
130                         base.OnAbort ();
131                 }
132
133                 protected override void OnClose (TimeSpan timeout)
134                 {
135                         DateTime start = DateTime.Now;
136                         // this implicitly premises: TChannel is IChannel
137                         foreach (IChannel ch in channels)
138                                 ch.Close (timeout - (DateTime.Now - start));
139                         base.OnClose (timeout - (DateTime.Now - start));
140                 }
141
142                 protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state)
143                 {
144                         // base impl. will call this.OnClose()
145                         // FIXME: use async BeginClose/EndClose on the channels.
146                         return base.OnBeginClose (timeout, callback, state);
147                 }
148
149                 protected override void OnEndClose (IAsyncResult result)
150                 {
151                         // base impl. will call this.OnClose()
152                         base.OnEndClose (result);
153                 }
154
155                 protected void ValidateCreateChannel ()
156                 {
157                         ThrowIfDisposedOrNotOpen ();
158                         if (State == CommunicationState.Faulted)
159                                 throw new CommunicationObjectFaultedException ();
160                 }
161         }
162
163         public abstract class ChannelFactoryBase
164                 : ChannelManagerBase, IChannelFactory, ICommunicationObject
165         {
166                 TimeSpan open_timeout, close_timeout, receive_timeout, send_timeout;
167
168                 protected ChannelFactoryBase ()
169                         : this (DefaultCommunicationTimeouts.Instance)
170                 {
171                 }
172
173                 protected ChannelFactoryBase (
174                         IDefaultCommunicationTimeouts timeouts)
175                 {
176                         open_timeout = timeouts.OpenTimeout;
177                         close_timeout = timeouts.CloseTimeout;
178                         send_timeout = timeouts.SendTimeout;
179                         receive_timeout = timeouts.ReceiveTimeout;
180                 }
181
182                 protected internal override TimeSpan DefaultCloseTimeout {
183                         get { return close_timeout; }
184                 }
185
186                 protected internal override TimeSpan DefaultOpenTimeout {
187                         get { return open_timeout; }
188                 }
189
190                 protected internal override TimeSpan DefaultReceiveTimeout {
191                         get { return receive_timeout; }
192                 }
193
194                 protected internal override TimeSpan DefaultSendTimeout {
195                         get { return send_timeout; }
196                 }
197
198                 public virtual T GetProperty<T> () where T : class
199                 {
200                         return null;
201                 }
202
203                 protected override void OnAbort ()
204                 {
205                         // what should we do here?
206                 }
207
208                 Action<TimeSpan> close_delegate;
209
210                 protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state)
211                 {
212                         if (close_delegate == null)
213                                 close_delegate = new Action<TimeSpan> (OnClose);
214                         return close_delegate.BeginInvoke (timeout, callback, state);
215                 }
216
217                 protected override void OnEndClose (IAsyncResult result)
218                 {
219                         if (close_delegate == null)
220                                 throw new InvalidOperationException ("Async close operation has not started");
221                         close_delegate.EndInvoke (result);
222                 }
223
224                 protected override void OnClose (TimeSpan timeout)
225                 {
226                         // what should we do here?
227                 }
228         }
229 }