1 // 2 // TransactionFlowBindingElement.cs 3 // 4 // Author: 5 // Atsushi Enomoto <atsushi@ximian.com> 6 // 7 // Copyright (C) 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.ServiceModel.Description; 31 using System.ServiceModel.Security; 32 using System.ServiceModel.Channels; 33 using System.Transactions; 34 35 namespace System.ServiceModel.Channels 36 { 37 public class TransactionFlowBindingElement : BindingElement 38 { 39 TransactionProtocol protocol; 40 41 // Funny, but since it uses OLE TX, Mono will never support this constructor. 42 [MonoTODO] TransactionFlowBindingElement()43 public TransactionFlowBindingElement () 44 : this (TransactionProtocol.Default) 45 { 46 } 47 TransactionFlowBindingElement(TransactionProtocol transactionProtocol)48 public TransactionFlowBindingElement (TransactionProtocol transactionProtocol) 49 { 50 this.protocol = transactionProtocol; 51 } 52 53 public TransactionProtocol TransactionProtocol { 54 get { return protocol; } 55 } 56 Clone()57 public override BindingElement Clone () 58 { 59 return new TransactionFlowBindingElement (protocol); 60 } 61 62 [MonoTODO] GetProperty(BindingContext context)63 public override T GetProperty<T> (BindingContext context) 64 { 65 return context.GetInnerProperty<T> (); 66 } 67 CanBuildChannelFactory(BindingContext context)68 public override bool CanBuildChannelFactory<TChannel> (BindingContext context) 69 { 70 return context.CanBuildInnerChannelFactory<TChannel> (); 71 } 72 73 [MonoTODO] CanBuildChannelListener(BindingContext context)74 public override bool CanBuildChannelListener<TChannel> (BindingContext context) 75 { 76 return context.CanBuildInnerChannelListener<TChannel> (); 77 } 78 BuildChannelFactory(BindingContext context)79 public override IChannelFactory<TChannel> BuildChannelFactory<TChannel> (BindingContext context) 80 { 81 if (protocol == null) 82 throw new InvalidOperationException ("Set transaction protocol in prior to build a channel factory."); 83 if (protocol == TransactionProtocol.Default) 84 throw new NotSupportedException ("Mono does not support DTC."); 85 if (!CanBuildChannelFactory<TChannel> (context.Clone ())) 86 throw new ArgumentException (String.Format ("The channel type '{0}' is not supported", typeof (TChannel))); 87 return new TransactionChannelFactory<TChannel> (context.BuildInnerChannelFactory<TChannel> (), protocol); 88 } 89 BuildChannelListener(BindingContext context)90 public override IChannelListener<TChannel> BuildChannelListener<TChannel> (BindingContext context) 91 { 92 if (protocol == null) 93 throw new InvalidOperationException ("Set transaction protocol in prior to build a channel listener."); 94 if (protocol == TransactionProtocol.Default) 95 throw new NotSupportedException ("Mono does not support DTC."); 96 if (!CanBuildChannelListener<TChannel> (context.Clone ())) 97 throw new ArgumentException (String.Format ("The channel type '{0}' is not supported", typeof (TChannel))); 98 return new TransactionChannelListener<TChannel> ( 99 context.BuildInnerChannelListener<TChannel> (), 100 protocol); 101 } 102 } 103 104 internal class TransactionChannelFactory<TChannel> : ChannelFactoryBase<TChannel> 105 { 106 IChannelFactory<TChannel> inner_factory; 107 TransactionScope txscope; 108 TransactionProtocol protocol; 109 TransactionChannelFactory(IChannelFactory<TChannel> innerFactory, TransactionProtocol protocol)110 public TransactionChannelFactory (IChannelFactory<TChannel> innerFactory, TransactionProtocol protocol) 111 { 112 this.inner_factory = innerFactory; 113 this.protocol = protocol; 114 } 115 ProcessOpen()116 void ProcessOpen () 117 { 118 CommittableTransaction tx = new CommittableTransaction (); 119 txscope = new TransactionScope (tx); 120 } 121 OnOpen(TimeSpan timeout)122 protected override void OnOpen (TimeSpan timeout) 123 { 124 ProcessOpen (); 125 inner_factory.Open (timeout); 126 } 127 OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)128 protected override IAsyncResult OnBeginOpen (TimeSpan timeout, AsyncCallback callback, object state) 129 { 130 ProcessOpen (); 131 return inner_factory.BeginOpen (timeout, callback, state); 132 } 133 OnEndOpen(IAsyncResult result)134 protected override void OnEndOpen (IAsyncResult result) 135 { 136 inner_factory.EndOpen (result); 137 } 138 OnCreateChannel( EndpointAddress remoteAddress, Uri via)139 protected override TChannel OnCreateChannel ( 140 EndpointAddress remoteAddress, Uri via) 141 { 142 return inner_factory.CreateChannel (remoteAddress, via); 143 } 144 OnClose(TimeSpan timeout)145 protected override void OnClose (TimeSpan timeout) 146 { 147 inner_factory.Close (timeout); 148 txscope.Complete (); 149 } 150 } 151 152 internal class TransactionChannelListener<TChannel> : ChannelListenerBase<TChannel> where TChannel : class, IChannel 153 { 154 IChannelListener<TChannel> inner_listener; 155 TransactionScope txscope; 156 TransactionProtocol protocol; 157 TransactionChannelListener(IChannelListener<TChannel> innerListener, TransactionProtocol protocol)158 public TransactionChannelListener (IChannelListener<TChannel> innerListener, TransactionProtocol protocol) 159 { 160 this.inner_listener = innerListener; 161 this.protocol = protocol; 162 } 163 GetProperty()164 public override T GetProperty<T> () 165 { 166 return inner_listener.GetProperty<T> () ?? base.GetProperty<T> (); 167 } 168 169 public override Uri Uri { 170 get { return inner_listener.Uri; } 171 } 172 OnAbort()173 protected override void OnAbort () 174 { 175 inner_listener.Abort (); 176 } 177 OnOpen(TimeSpan timeout)178 protected override void OnOpen (TimeSpan timeout) 179 { 180 CommittableTransaction tx = new CommittableTransaction (); 181 txscope = new TransactionScope (tx); 182 inner_listener.Open (timeout); 183 } 184 OnBeginOpen(TimeSpan timeout, AsyncCallback callback, object state)185 protected override IAsyncResult OnBeginOpen (TimeSpan timeout, AsyncCallback callback, object state) 186 { 187 return inner_listener.BeginOpen (timeout, callback, state); 188 } 189 OnEndOpen(IAsyncResult result)190 protected override void OnEndOpen (IAsyncResult result) 191 { 192 inner_listener.EndOpen (result); 193 } 194 OnClose(TimeSpan timeout)195 protected override void OnClose (TimeSpan timeout) 196 { 197 inner_listener.Close (timeout); 198 txscope.Complete (); 199 } 200 OnBeginClose(TimeSpan timeout, AsyncCallback callback, object state)201 protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state) 202 { 203 return inner_listener.BeginClose (timeout, callback, state); 204 } 205 OnEndClose(IAsyncResult result)206 protected override void OnEndClose (IAsyncResult result) 207 { 208 inner_listener.EndClose (result); 209 } 210 OnWaitForChannel(TimeSpan timeout)211 protected override bool OnWaitForChannel (TimeSpan timeout) 212 { 213 return inner_listener.WaitForChannel (timeout); 214 } 215 OnBeginWaitForChannel(TimeSpan timeout, AsyncCallback callback, object state)216 protected override IAsyncResult OnBeginWaitForChannel (TimeSpan timeout, AsyncCallback callback, object state) 217 { 218 return inner_listener.BeginWaitForChannel (timeout, callback, state); 219 } 220 OnEndWaitForChannel(IAsyncResult result)221 protected override bool OnEndWaitForChannel (IAsyncResult result) 222 { 223 return inner_listener.EndWaitForChannel (result); 224 } 225 OnAcceptChannel(TimeSpan timeout)226 protected override TChannel OnAcceptChannel (TimeSpan timeout) 227 { 228 return inner_listener.AcceptChannel (timeout); 229 } 230 OnBeginAcceptChannel(TimeSpan timeout, AsyncCallback callback, object asyncState)231 protected override IAsyncResult OnBeginAcceptChannel (TimeSpan timeout, 232 AsyncCallback callback, object asyncState) 233 { 234 return inner_listener.BeginAcceptChannel (timeout, callback, asyncState); 235 } 236 OnEndAcceptChannel(IAsyncResult result)237 protected override TChannel OnEndAcceptChannel (IAsyncResult result) 238 { 239 return inner_listener.EndAcceptChannel (result); 240 } 241 } 242 } 243