CommunicationObject.cs 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. //
  2. // CommunicationObject.cs
  3. //
  4. // Author:
  5. // Atsushi Enomoto <[email protected]>
  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. using System;
  29. using System.ServiceModel;
  30. using System.Threading;
  31. namespace System.ServiceModel.Channels
  32. {
  33. public abstract class CommunicationObject : ICommunicationObject
  34. {
  35. object mutex;
  36. CommunicationState state = CommunicationState.Created;
  37. TimeSpan default_open_timeout = TimeSpan.FromMinutes (1), default_close_timeout = TimeSpan.FromMinutes (1);
  38. bool aborted, on_closed_called;
  39. protected CommunicationObject ()
  40. : this (new object ())
  41. {
  42. }
  43. protected CommunicationObject (object mutex)
  44. {
  45. this.mutex = mutex;
  46. }
  47. #region Events
  48. public event EventHandler Closed;
  49. public event EventHandler Closing;
  50. public event EventHandler Faulted;
  51. public event EventHandler Opened;
  52. public event EventHandler Opening;
  53. #endregion
  54. #region Properties
  55. public CommunicationState State {
  56. get { return state; }
  57. }
  58. protected bool IsDisposed {
  59. get { return state == CommunicationState.Closed; }
  60. }
  61. protected object ThisLock {
  62. get { return mutex; }
  63. }
  64. protected internal abstract TimeSpan DefaultCloseTimeout { get; }
  65. protected internal abstract TimeSpan DefaultOpenTimeout { get; }
  66. #endregion
  67. #region Methods
  68. public void Abort ()
  69. {
  70. if (State != CommunicationState.Closed) {
  71. OnAbort ();
  72. ProcessClosed ();
  73. }
  74. }
  75. [MonoTODO]
  76. protected void Fault ()
  77. {
  78. state = CommunicationState.Faulted;
  79. OnFaulted ();
  80. }
  81. public IAsyncResult BeginClose (AsyncCallback callback,
  82. object state)
  83. {
  84. return BeginClose (default_close_timeout, callback, state);
  85. }
  86. public IAsyncResult BeginClose (TimeSpan timeout,
  87. AsyncCallback callback, object state)
  88. {
  89. if (State == CommunicationState.Created)
  90. return new EventHandler (delegate { Abort (); }).BeginInvoke (null, null, callback, state);
  91. ProcessClosing ();
  92. return OnBeginClose (timeout, callback, state);
  93. }
  94. public IAsyncResult BeginOpen (AsyncCallback callback,
  95. object state)
  96. {
  97. return BeginOpen (default_open_timeout, callback, state);
  98. }
  99. public IAsyncResult BeginOpen (TimeSpan timeout,
  100. AsyncCallback callback, object state)
  101. {
  102. ProcessOpening ();
  103. return OnBeginOpen (timeout, callback, state);
  104. }
  105. public void Close ()
  106. {
  107. Close (default_close_timeout);
  108. }
  109. public void Close (TimeSpan timeout)
  110. {
  111. if (State == CommunicationState.Created)
  112. Abort ();
  113. else {
  114. ProcessClosing ();
  115. OnClose (timeout);
  116. ProcessClosed ();
  117. }
  118. }
  119. public void EndClose (IAsyncResult result)
  120. {
  121. if (State == CommunicationState.Created || State == CommunicationState.Closed) {
  122. if (!result.IsCompleted)
  123. result.AsyncWaitHandle.WaitOne ();
  124. } else {
  125. OnEndClose (result);
  126. ProcessClosed ();
  127. }
  128. }
  129. public void EndOpen (IAsyncResult result)
  130. {
  131. OnEndOpen (result);
  132. ProcessOpened ();
  133. }
  134. public void Open ()
  135. {
  136. Open (default_open_timeout);
  137. }
  138. public void Open (TimeSpan timeout)
  139. {
  140. ProcessOpening ();
  141. OnOpen (timeout);
  142. ProcessOpened ();
  143. }
  144. protected abstract void OnAbort ();
  145. protected abstract IAsyncResult OnBeginClose (TimeSpan timeout,
  146. AsyncCallback callback, object state);
  147. protected abstract IAsyncResult OnBeginOpen (TimeSpan timeout,
  148. AsyncCallback callback, object state);
  149. protected abstract void OnClose (TimeSpan timeout);
  150. void ProcessClosing ()
  151. {
  152. if (State == CommunicationState.Faulted)
  153. throw new CommunicationObjectFaultedException ();
  154. state = CommunicationState.Closing;
  155. OnClosing ();
  156. }
  157. protected virtual void OnClosing ()
  158. {
  159. // This means, if this method is overriden, then
  160. // Opening event is surpressed.
  161. if (Closing != null)
  162. Closing (this, new EventArgs ());
  163. }
  164. void ProcessClosed ()
  165. {
  166. state = CommunicationState.Closed;
  167. on_closed_called = false;
  168. OnClosed ();
  169. if (!on_closed_called)
  170. throw new InvalidOperationException ("OnClosed method is implemented but it did not call its base OnClosed method");
  171. }
  172. protected virtual void OnClosed ()
  173. {
  174. // This means, if this method is overriden, then
  175. // Closed event is surpressed.
  176. if (Closed != null)
  177. Closed (this, new EventArgs ());
  178. on_closed_called = true;
  179. }
  180. protected abstract void OnEndClose (IAsyncResult result);
  181. protected abstract void OnEndOpen (IAsyncResult result);
  182. [MonoTODO]
  183. protected virtual void OnFaulted ()
  184. {
  185. // This means, if this method is overriden, then
  186. // Opened event is surpressed.
  187. if (Faulted != null)
  188. Faulted (this, new EventArgs ());
  189. }
  190. protected abstract void OnOpen (TimeSpan timeout);
  191. void ProcessOpened ()
  192. {
  193. OnOpened ();
  194. if (state != CommunicationState.Opened) {
  195. throw new InvalidOperationException (String.Format ("Communication object {0} has an overriden OnOpened method that does not call base OnOpened method.", this.GetType ()));
  196. state = CommunicationState.Faulted;
  197. }
  198. }
  199. protected virtual void OnOpened ()
  200. {
  201. state = CommunicationState.Opened;
  202. if (Opened != null)
  203. Opened (this, new EventArgs ());
  204. }
  205. void ProcessOpening ()
  206. {
  207. ThrowIfDisposedOrImmutable ();
  208. OnOpening ();
  209. if (state != CommunicationState.Opening) {
  210. throw new InvalidOperationException (String.Format ("Communication object {0} has an overriden OnOpening method that does not call base OnOpening method.", this.GetType ()));
  211. state = CommunicationState.Faulted;
  212. }
  213. }
  214. protected virtual void OnOpening ()
  215. {
  216. state = CommunicationState.Opening;
  217. // This means, if this method is overriden, then
  218. // Opening event is surpressed.
  219. if (Opening != null)
  220. Opening (this, new EventArgs ());
  221. }
  222. protected void ThrowIfDisposed ()
  223. {
  224. if (IsDisposed)
  225. throw new ObjectDisposedException (String.Format ("This communication object {0} is already disposed.", GetCommunicationObjectType ()));
  226. }
  227. protected void ThrowIfDisposedOrNotOpen ()
  228. {
  229. ThrowIfDisposed ();
  230. if (State == CommunicationState.Faulted)
  231. throw new CommunicationObjectFaultedException ();
  232. if (State != CommunicationState.Opened)
  233. throw new InvalidOperationException (String.Format ("The communication object {0} must be at opened state.", GetCommunicationObjectType ()));
  234. }
  235. protected void ThrowIfDisposedOrImmutable ()
  236. {
  237. ThrowIfDisposed ();
  238. // hmm, according to msdn, Closing is OK here.
  239. switch (State) {
  240. case CommunicationState.Faulted:
  241. throw new CommunicationObjectFaultedException ();
  242. case CommunicationState.Opening:
  243. case CommunicationState.Opened:
  244. throw new InvalidOperationException (String.Format ("The communication object {0} is not at created state.", GetType ()));
  245. }
  246. }
  247. protected virtual Type GetCommunicationObjectType ()
  248. {
  249. return GetType ();
  250. }
  251. #endregion
  252. class SimpleAsyncResult : IAsyncResult
  253. {
  254. CommunicationState comm_state;
  255. object async_state;
  256. public SimpleAsyncResult (
  257. CommunicationState communicationState,
  258. TimeSpan timeout, AsyncCallback callback,
  259. object asyncState)
  260. {
  261. comm_state = communicationState;
  262. async_state = asyncState;
  263. }
  264. public object AsyncState {
  265. get { return async_state; }
  266. }
  267. // FIXME: implement
  268. public WaitHandle AsyncWaitHandle {
  269. get { throw new NotImplementedException (); }
  270. }
  271. // FIXME: implement
  272. public bool CompletedSynchronously {
  273. get { throw new NotImplementedException (); }
  274. }
  275. // FIXME: implement
  276. public bool IsCompleted {
  277. get { throw new NotImplementedException (); }
  278. }
  279. }
  280. }
  281. }