2 // System.Net.FileWebRequest
5 // Lawrence Pit (loz@cable.a2000.nl)
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:
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
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.
30 using System
.Collections
;
32 using System
.Runtime
.Serialization
;
33 using System
.Runtime
.Remoting
.Messaging
;
34 using System
.Threading
;
39 public class FileWebRequest
: WebRequest
, ISerializable
42 private WebHeaderCollection webHeaders
;
44 private ICredentials credentials
;
45 private string connectionGroup
;
46 private string method
= "GET";
47 private int timeout
= 100000;
49 private Stream requestStream
;
50 private FileWebResponse webResponse
;
51 private AutoResetEvent requestEndEvent
;
52 private bool requesting
;
53 private bool asyncResponding
;
57 internal FileWebRequest (Uri uri
)
60 this.webHeaders
= new WebHeaderCollection ();
63 protected FileWebRequest (SerializationInfo serializationInfo
, StreamingContext streamingContext
)
65 SerializationInfo info
= serializationInfo
;
67 method
= info
.GetString ("method");
68 uri
= (Uri
) info
.GetValue ("uri", typeof (Uri
));
69 timeout
= info
.GetInt32 ("timeout");
70 connectionGroup
= info
.GetString ("connectionGroup");
71 webHeaders
= (WebHeaderCollection
) info
.GetValue ("webHeaders", typeof (WebHeaderCollection
));
76 // currently not used according to spec
77 public override string ConnectionGroupName
{
78 get { return connectionGroup; }
79 set { connectionGroup = value; }
82 public override long ContentLength
{
85 return Int64
.Parse (webHeaders
["Content-Length"]);
92 throw new ArgumentException ("value");
93 webHeaders
["Content-Length"] = Convert
.ToString (value);
97 public override string ContentType
{
98 get { return webHeaders ["Content-Type"]; }
99 set { webHeaders ["Content-Type"] = value; }
102 public override ICredentials Credentials
{
103 get { return credentials; }
104 set { credentials = value; }
107 public override WebHeaderCollection Headers
{
108 get { return webHeaders; }
111 // currently not used according to spec
112 public override string Method
{
113 get { return this.method; }
114 set { this.method = value; }
117 // currently not used according to spec
118 public override bool PreAuthenticate
{
119 get { throw new NotSupportedException (); }
120 set { throw new NotSupportedException (); }
123 // currently not used according to spec
124 public override IWebProxy Proxy
{
125 get { throw new NotSupportedException (); }
126 set { throw new NotSupportedException (); }
129 public override Uri RequestUri
{
130 get { return this.uri; }
133 public override int Timeout
{
134 get { return timeout; }
137 throw new ArgumentException ("value");
144 private delegate Stream
GetRequestStreamCallback ();
145 private delegate WebResponse
GetResponseCallback ();
147 public override IAsyncResult
BeginGetRequestStream (AsyncCallback callback
, object state
)
149 if (method
== null || (!method
.Equals ("PUT") && !method
.Equals ("POST")))
150 throw new ProtocolViolationException ("Cannot send file when method is: " + this.method
+ ". Method must be PUT.");
151 // workaround for bug 24943
154 if (asyncResponding
|| webResponse
!= null)
155 e
= new InvalidOperationException ("This operation cannot be performed after the request has been submitted.");
157 e
= new InvalidOperationException ("Cannot re-call start of asynchronous method while a previous call is still in progress.");
165 if (asyncResponding || webResponse != null)
166 throw new InvalidOperationException ("This operation cannot be performed after the request has been submitted.");
168 throw new InvalidOperationException ("Cannot re-call start of asynchronous method while a previous call is still in progress.");
172 GetRequestStreamCallback c
= new GetRequestStreamCallback (this.GetRequestStreamInternal
);
173 return c
.BeginInvoke (callback
, state
);
176 public override Stream
EndGetRequestStream (IAsyncResult asyncResult
)
178 if (asyncResult
== null)
179 throw new ArgumentNullException ("asyncResult");
180 if (!asyncResult
.IsCompleted
)
181 asyncResult
.AsyncWaitHandle
.WaitOne ();
182 AsyncResult
async = (AsyncResult
) asyncResult
;
183 GetRequestStreamCallback cb
= (GetRequestStreamCallback
) async.AsyncDelegate
;
184 return cb
.EndInvoke (asyncResult
);
187 public override Stream
GetRequestStream()
189 IAsyncResult asyncResult
= BeginGetRequestStream (null, null);
190 if (!(asyncResult
.AsyncWaitHandle
.WaitOne (timeout
, false))) {
191 throw new WebException("The request timed out", WebExceptionStatus
.Timeout
);
193 return EndGetRequestStream (asyncResult
);
196 internal Stream
GetRequestStreamInternal ()
198 this.requestStream
= new FileWebStream (
203 return this.requestStream
;
206 public override IAsyncResult
BeginGetResponse (AsyncCallback callback
, object state
)
208 // workaround for bug 24943
212 e
= new InvalidOperationException ("Cannot re-call start of asynchronous method while a previous call is still in progress.");
214 asyncResponding
= true;
221 throw new InvalidOperationException ("Cannot re-call start of asynchronous method while a previous call is still in progress.");
222 asyncResponding = true;
225 GetResponseCallback c
= new GetResponseCallback (this.GetResponseInternal
);
226 return c
.BeginInvoke (callback
, state
);
229 public override WebResponse
EndGetResponse (IAsyncResult asyncResult
)
231 if (asyncResult
== null)
232 throw new ArgumentNullException ("asyncResult");
233 if (!asyncResult
.IsCompleted
)
234 asyncResult
.AsyncWaitHandle
.WaitOne ();
235 AsyncResult
async = (AsyncResult
) asyncResult
;
236 GetResponseCallback cb
= (GetResponseCallback
) async.AsyncDelegate
;
237 WebResponse webResponse
= cb
.EndInvoke(asyncResult
);
238 asyncResponding
= false;
242 public override WebResponse
GetResponse ()
244 IAsyncResult asyncResult
= BeginGetResponse (null, null);
245 if (!(asyncResult
.AsyncWaitHandle
.WaitOne (timeout
, false))) {
246 throw new WebException("The request timed out", WebExceptionStatus
.Timeout
);
248 return EndGetResponse (asyncResult
);
251 WebResponse
GetResponseInternal ()
253 if (webResponse
!= null)
257 requestEndEvent
= new AutoResetEvent (false);
260 if (requestEndEvent
!= null) {
261 requestEndEvent
.WaitOne ();
263 FileStream fileStream
= new FileWebStream (
268 this.webResponse
= new FileWebResponse (this.uri
, fileStream
);
269 return (WebResponse
) this.webResponse
;
272 void ISerializable
.GetObjectData (SerializationInfo serializationInfo
, StreamingContext streamingContext
)
274 SerializationInfo info
= serializationInfo
;
276 info
.AddValue ("method", method
);
277 info
.AddValue ("uri", uri
, typeof (Uri
));
278 info
.AddValue ("timeout", timeout
);
279 info
.AddValue ("connectionGroup", connectionGroup
);
280 info
.AddValue ("webHeaders", webHeaders
, typeof (WebHeaderCollection
));
283 internal void Close ()
285 // already done in class below
286 // if (requestStream != null) {
287 // requestStream.Close ();
292 if (requestEndEvent
!= null)
293 requestEndEvent
.Set ();
294 // requestEndEvent = null;
298 // to catch the Close called on the FileStream
299 internal class FileWebStream
: FileStream
301 FileWebRequest webRequest
;
303 internal FileWebStream (FileWebRequest webRequest
,
307 : base (webRequest
.RequestUri
.LocalPath
,
310 this.webRequest
= webRequest
;
313 public override void Close()
316 FileWebRequest req
= webRequest
;