2010-07-14 Atsushi Enomoto <atsushi@ximian.com>
[mono.git] / mcs / class / System.ServiceModel / System.ServiceModel.Channels / MsmqOutputChannel.cs
1 //
2 // MsmqOutputChannel.cs
3 //
4 // Author: Atsushi Enomoto (atsushi@ximian.com)
5 //
6 // Copyright (C) 2007 Novell, Inc (http://www.novell.com)
7 //
8 // Permission is hereby granted, free of charge, to any person obtaining
9 // a copy of this software and associated documentation files (the
10 // "Software"), to deal in the Software without restriction, including
11 // without limitation the rights to use, copy, modify, merge, publish,
12 // distribute, sublicense, and/or sell copies of the Software, and to
13 // permit persons to whom the Software is furnished to do so, subject to
14 // the following conditions:
15 // 
16 // The above copyright notice and this permission notice shall be
17 // included in all copies or substantial portions of the Software.
18 // 
19 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
20 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
21 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
22 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
23 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
24 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
25 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
26 //
27 using System;
28 using System.IO;
29 using System.Messaging;
30 using System.ServiceModel;
31 using System.Threading;
32
33 namespace System.ServiceModel.Channels
34 {
35         internal class MsmqOutputChannel : OutputChannelBase
36         {
37                 MsmqChannelFactory<IOutputChannel> source;
38                 MessageQueue queue;
39
40                 public MsmqOutputChannel (MsmqChannelFactory<IOutputChannel> factory,
41                         EndpointAddress address, Uri via)
42                         : base (factory, address, via)
43                 {
44                         this.source = factory;
45                 }
46
47                 // Send
48
49                 public override IAsyncResult BeginSend (Message message, TimeSpan timeout, AsyncCallback callback, object state)
50                 {
51                         ThrowIfDisposedOrNotOpen ();
52
53                         return new MsmqChannelOutputAsyncResult (this, message, timeout, callback, state);
54                 }
55
56                 public override void EndSend (IAsyncResult result)
57                 {
58                         if (result == null)
59                                 throw new ArgumentNullException ("result");
60                         MsmqChannelOutputAsyncResult r = result as MsmqChannelOutputAsyncResult;
61                         if (r == null)
62                                 throw new InvalidOperationException ("Wrong IAsyncResult");
63                         r.WaitEnd ();
64                 }
65
66                 public override void Send (Message message, TimeSpan timeout)
67                 {
68                         ThrowIfDisposedOrNotOpen ();
69
70                         MemoryStream ms = new MemoryStream ();
71                         source.MessageEncoder.WriteMessage (message, ms);
72
73                         queue.Send (ms);
74
75                         //throw new NotImplementedException ();
76                 }
77
78                 // Abort
79
80                 protected override void OnAbort ()
81                 {
82                         throw new NotImplementedException ();
83                 }
84
85                 // Close
86
87                 protected override void OnClose (TimeSpan timeout)
88                 {
89                         if (queue != null)
90                                 queue.Close ();
91                         queue = null;
92                 }
93
94                 protected override IAsyncResult OnBeginClose (TimeSpan timeout, AsyncCallback callback, object state)
95                 {
96                         throw new NotImplementedException ();
97                 }
98
99                 protected override void OnEndClose (IAsyncResult result)
100                 {
101                         throw new NotImplementedException ();
102                 }
103
104                 // Open
105
106                 protected override void OnOpen (TimeSpan timeout)
107                 {
108                         // FIXME: is distination really like this?
109                         Uri destination = Via != null ? Via : RemoteAddress.Uri;
110
111                         queue = new MessageQueue (destination.GetLeftPart (UriPartial.Scheme));
112                         // FIXME: setup queue
113                 }
114
115                 protected override IAsyncResult OnBeginOpen (TimeSpan timeout, AsyncCallback callback, object state)
116                 {
117                         throw new NotImplementedException ();
118                 }
119
120                 protected override void OnEndOpen (IAsyncResult result)
121                 {
122                         throw new NotImplementedException ();
123                 }
124
125                 class MsmqChannelOutputAsyncResult : IAsyncResult
126                 {
127                         MsmqOutputChannel channel;
128                         Message message;
129                         TimeSpan timeout;
130                         AsyncCallback callback;
131                         object state;
132                         AutoResetEvent wait;
133                         bool done, waiting;
134                         Exception error;
135
136                         public MsmqChannelOutputAsyncResult (MsmqOutputChannel channel, Message message, TimeSpan timeout, AsyncCallback callback, object state)
137                         {
138                                 this.channel = channel;
139                                 this.message = message;
140                                 this.timeout = timeout;
141                                 this.callback = callback;
142                                 this.state = state;
143
144                                 wait = new AutoResetEvent (false);
145                                 Thread t = new Thread (delegate () {
146                                         try {
147                                                 channel.Send (message, timeout);
148                                                 if (callback != null)
149                                                         callback (this);
150                                         } catch (Exception ex) {
151                                                 error = ex;
152                                         } finally {
153                                                 done = true;
154                                                 wait.Set ();
155                                         }
156                                 });
157                                 t.Start ();
158                         }
159
160                         public WaitHandle AsyncWaitHandle {
161                                 get { return wait; }
162                         }
163
164                         public object AsyncState {
165                                 get { return state; }
166                         }
167
168                         public bool CompletedSynchronously {
169                                 get { return done && !waiting; }
170                         }
171
172                         public bool IsCompleted {
173                                 get { return done; }
174                         }
175
176                         public void WaitEnd ()
177                         {
178                                 if (!done) {
179                                         waiting = true;
180                                         wait.WaitOne (timeout, true);
181                                 }
182                                 if (error != null)
183                                         throw error;
184                         }
185                 }
186         }
187 }