FileWebRequest.cs 8.7 KB

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