FileWebRequest.cs 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. //
  2. // System.Net.FileWebRequest
  3. //
  4. // Author:
  5. // Lawrence Pit ([email protected])
  6. //
  7. using System;
  8. using System.Collections;
  9. using System.IO;
  10. using System.Runtime.Serialization;
  11. using System.Runtime.Remoting.Messaging;
  12. using System.Threading;
  13. namespace System.Net
  14. {
  15. [Serializable]
  16. public class FileWebRequest : WebRequest, ISerializable
  17. {
  18. private Uri uri;
  19. private WebHeaderCollection webHeaders;
  20. private ICredentials credentials;
  21. private string connectionGroup;
  22. private string method;
  23. private int timeout;
  24. private Stream requestStream = null;
  25. private FileWebResponse webResponse = null;
  26. private AutoResetEvent requestEndEvent = null;
  27. private bool requesting = false;
  28. private bool asyncResponding = false;
  29. // Constructors
  30. internal FileWebRequest (Uri uri)
  31. {
  32. this.uri = uri;
  33. this.webHeaders = new WebHeaderCollection ();
  34. this.method = "GET";
  35. this.timeout = System.Threading.Timeout.Infinite;
  36. }
  37. [MonoTODO]
  38. protected FileWebRequest (SerializationInfo serializationInfo, StreamingContext streamingContext)
  39. {
  40. throw new NotImplementedException ();
  41. }
  42. // Properties
  43. // currently not used according to spec
  44. public override string ConnectionGroupName {
  45. get { return connectionGroup; }
  46. set { connectionGroup = value; }
  47. }
  48. public override long ContentLength {
  49. get {
  50. try {
  51. return Int64.Parse (webHeaders ["Content-Length"]);
  52. } catch (Exception) {
  53. return 0;
  54. }
  55. }
  56. set {
  57. if (value < 0)
  58. throw new ArgumentException ("value");
  59. webHeaders ["Content-Length"] = Convert.ToString (value);
  60. }
  61. }
  62. public override string ContentType {
  63. get { return webHeaders ["Content-Type"]; }
  64. set { webHeaders ["Content-Type"] = value; }
  65. }
  66. public override ICredentials Credentials {
  67. get { return credentials; }
  68. set { credentials = value; }
  69. }
  70. public override WebHeaderCollection Headers {
  71. get { return webHeaders; }
  72. }
  73. // currently not used according to spec
  74. public override string Method {
  75. get { return this.method; }
  76. set { this.method = value; }
  77. }
  78. // currently not used according to spec
  79. public override bool PreAuthenticate {
  80. get { throw new NotSupportedException (); }
  81. set { throw new NotSupportedException (); }
  82. }
  83. // currently not used according to spec
  84. public override IWebProxy Proxy {
  85. get { throw new NotSupportedException (); }
  86. set { throw new NotSupportedException (); }
  87. }
  88. public override Uri RequestUri {
  89. get { return this.uri; }
  90. }
  91. public override int Timeout {
  92. get { return timeout; }
  93. set {
  94. if (value < 0)
  95. throw new ArgumentException ("value");
  96. timeout = value;
  97. }
  98. }
  99. // Methods
  100. private delegate Stream GetRequestStreamCallback ();
  101. private delegate WebResponse GetResponseCallback ();
  102. public override IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state)
  103. {
  104. if (method == null || (!method.Equals ("PUT") && !method.Equals ("POST")))
  105. throw new ProtocolViolationException ("Cannot send file when method is: " + this.method + ". Method must be PUT.");
  106. // workaround for bug 24943
  107. Exception e = null;
  108. lock (this) {
  109. if (asyncResponding || webResponse != null)
  110. e = new InvalidOperationException ("This operation cannot be performed after the request has been submitted.");
  111. else if (requesting)
  112. e = new InvalidOperationException ("Cannot re-call start of asynchronous method while a previous call is still in progress.");
  113. else
  114. requesting = true;
  115. }
  116. if (e != null)
  117. throw e;
  118. /*
  119. lock (this) {
  120. if (asyncResponding || webResponse != null)
  121. throw new InvalidOperationException ("This operation cannot be performed after the request has been submitted.");
  122. if (requesting)
  123. throw new InvalidOperationException ("Cannot re-call start of asynchronous method while a previous call is still in progress.");
  124. requesting = true;
  125. }
  126. */
  127. GetRequestStreamCallback c = new GetRequestStreamCallback (this.GetRequestStreamInternal);
  128. return c.BeginInvoke (callback, state);
  129. }
  130. public override Stream EndGetRequestStream (IAsyncResult asyncResult)
  131. {
  132. if (asyncResult == null)
  133. throw new ArgumentNullException ("asyncResult");
  134. if (!asyncResult.IsCompleted)
  135. asyncResult.AsyncWaitHandle.WaitOne ();
  136. AsyncResult async = (AsyncResult) asyncResult;
  137. GetRequestStreamCallback cb = (GetRequestStreamCallback) async.AsyncDelegate;
  138. return cb.EndInvoke (asyncResult);
  139. }
  140. public override Stream GetRequestStream()
  141. {
  142. IAsyncResult asyncResult = BeginGetRequestStream (null, null);
  143. if (!(asyncResult.AsyncWaitHandle.WaitOne (timeout, false))) {
  144. throw new WebException("The request timed out", WebExceptionStatus.Timeout);
  145. }
  146. return EndGetRequestStream (asyncResult);
  147. }
  148. internal Stream GetRequestStreamInternal ()
  149. {
  150. this.requestStream = new FileWebStream (
  151. this,
  152. FileMode.CreateNew,
  153. FileAccess.Write,
  154. FileShare.Read);
  155. return this.requestStream;
  156. }
  157. public override IAsyncResult BeginGetResponse (AsyncCallback callback, object state)
  158. {
  159. // workaround for bug 24943
  160. Exception e = null;
  161. lock (this) {
  162. if (asyncResponding)
  163. e = new InvalidOperationException ("Cannot re-call start of asynchronous method while a previous call is still in progress.");
  164. else
  165. asyncResponding = true;
  166. }
  167. if (e != null)
  168. throw e;
  169. /*
  170. lock (this) {
  171. if (asyncResponding)
  172. throw new InvalidOperationException ("Cannot re-call start of asynchronous method while a previous call is still in progress.");
  173. asyncResponding = true;
  174. }
  175. */
  176. GetResponseCallback c = new GetResponseCallback (this.GetResponseInternal);
  177. return c.BeginInvoke (callback, state);
  178. }
  179. public override WebResponse EndGetResponse (IAsyncResult asyncResult)
  180. {
  181. if (asyncResult == null)
  182. throw new ArgumentNullException ("asyncResult");
  183. if (!asyncResult.IsCompleted)
  184. asyncResult.AsyncWaitHandle.WaitOne ();
  185. AsyncResult async = (AsyncResult) asyncResult;
  186. GetResponseCallback cb = (GetResponseCallback) async.AsyncDelegate;
  187. WebResponse webResponse = cb.EndInvoke(asyncResult);
  188. asyncResponding = false;
  189. return webResponse;
  190. }
  191. public override WebResponse GetResponse ()
  192. {
  193. IAsyncResult asyncResult = BeginGetResponse (null, null);
  194. if (!(asyncResult.AsyncWaitHandle.WaitOne (timeout, false))) {
  195. throw new WebException("The request timed out", WebExceptionStatus.Timeout);
  196. }
  197. return EndGetResponse (asyncResult);
  198. }
  199. public WebResponse GetResponseInternal ()
  200. {
  201. if (webResponse != null)
  202. return webResponse;
  203. lock (this) {
  204. if (requesting) {
  205. requestEndEvent = new AutoResetEvent (false);
  206. }
  207. }
  208. if (requestEndEvent != null) {
  209. requestEndEvent.WaitOne ();
  210. }
  211. FileStream fileStream = new FileWebStream (
  212. this,
  213. FileMode.Open,
  214. FileAccess.Read,
  215. FileShare.Read);
  216. this.webResponse = new FileWebResponse (this.uri, fileStream);
  217. return (WebResponse) this.webResponse;
  218. }
  219. [MonoTODO]
  220. void ISerializable.GetObjectData (SerializationInfo serializationInfo,
  221. StreamingContext streamingContext)
  222. {
  223. throw new NotImplementedException ();
  224. }
  225. internal void Close ()
  226. {
  227. // already done in class below
  228. // if (requestStream != null) {
  229. // requestStream.Close ();
  230. // }
  231. lock (this) {
  232. requesting = false;
  233. if (requestEndEvent != null)
  234. requestEndEvent.Set ();
  235. // requestEndEvent = null;
  236. }
  237. }
  238. // to catch the Close called on the FileStream
  239. internal class FileWebStream : FileStream
  240. {
  241. FileWebRequest webRequest;
  242. internal FileWebStream (FileWebRequest webRequest,
  243. FileMode mode,
  244. FileAccess access,
  245. FileShare share)
  246. : base (webRequest.RequestUri.LocalPath,
  247. mode, access, share)
  248. {
  249. this.webRequest = webRequest;
  250. }
  251. public override void Close()
  252. {
  253. base.Close ();
  254. FileWebRequest req = webRequest;
  255. webRequest = null;
  256. if (req != null)
  257. req.Close ();
  258. }
  259. }
  260. }
  261. }