// Lawrence Pit (loz@cable.a2000.nl)\r
//\r
\r
+//\r
+// Permission is hereby granted, free of charge, to any person obtaining\r
+// a copy of this software and associated documentation files (the\r
+// "Software"), to deal in the Software without restriction, including\r
+// without limitation the rights to use, copy, modify, merge, publish,\r
+// distribute, sublicense, and/or sell copies of the Software, and to\r
+// permit persons to whom the Software is furnished to do so, subject to\r
+// the following conditions:\r
+// \r
+// The above copyright notice and this permission notice shall be\r
+// included in all copies or substantial portions of the Software.\r
+// \r
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,\r
+// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\r
+// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\r
+// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\r
+// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\r
+// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\r
+// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r
+//\r
+\r
using System;\r
using System.Collections;\r
using System.IO;\r
using System.Runtime.Serialization;\r
+using System.Runtime.Remoting.Messaging;\r
+using System.Threading;\r
\r
namespace System.Net \r
{\r
\r
private ICredentials credentials;\r
private string connectionGroup;\r
- private string method;\r
- private int timeout;\r
- private bool open = false;\r
+ private long contentLength;\r
+ private FileAccess fileAccess = FileAccess.Read;\r
+ private string method = "GET";\r
+ private IWebProxy proxy;\r
+ private bool preAuthenticate;\r
+ private int timeout = 100000;\r
+ \r
+ private Stream requestStream;\r
+ private FileWebResponse webResponse;\r
+ private AutoResetEvent requestEndEvent;\r
+ private bool requesting;\r
+ private bool asyncResponding;\r
\r
// Constructors\r
\r
internal FileWebRequest (Uri uri) \r
{ \r
this.uri = uri;\r
- this.webHeaders = new WebHeaderCollection ();\r
- this.method = "GET";\r
- this.timeout = System.Threading.Timeout.Infinite; \r
- } \r
+ this.webHeaders = new WebHeaderCollection ();\r
+ }\r
\r
- [MonoTODO]\r
+ [Obsolete ("Serialization is obsoleted for this type", false)]\r
protected FileWebRequest (SerializationInfo serializationInfo, StreamingContext streamingContext) \r
{\r
- throw new NotImplementedException ();\r
+ SerializationInfo info = serializationInfo;\r
+ webHeaders = (WebHeaderCollection) info.GetValue ("headers", typeof (WebHeaderCollection));\r
+ proxy = (IWebProxy) info.GetValue ("proxy", typeof (IWebProxy));\r
+ uri = (Uri) info.GetValue ("uri", typeof (Uri));\r
+ connectionGroup = info.GetString ("connectionGroupName");\r
+ method = info.GetString ("method");\r
+ contentLength = info.GetInt64 ("contentLength");\r
+ timeout = info.GetInt32 ("timeout");\r
+ fileAccess = (FileAccess) info.GetValue ("fileAccess", typeof (FileAccess));\r
+ preAuthenticate = info.GetBoolean ("preauthenticate");\r
}\r
\r
// Properties\r
\r
// currently not used according to spec\r
- public override string ConnectionGroupName { \r
+ public override string ConnectionGroupName {\r
get { return connectionGroup; }\r
set { connectionGroup = value; }\r
}\r
\r
- public override long ContentLength { \r
- get { \r
- try {\r
- return Int64.Parse (webHeaders ["Content-Length"]); \r
- } catch (Exception) {\r
- return 0;\r
- }\r
- }\r
- set { \r
+ public override long ContentLength {\r
+ get { return contentLength; }\r
+ set {\r
if (value < 0)\r
- throw new ArgumentException ("value");\r
- webHeaders ["Content-Length"] = Convert.ToString (value);\r
+ throw new ArgumentException ("The Content-Length value must be greater than or equal to zero.", "value");\r
+ contentLength = value;\r
}\r
}\r
\r
// currently not used according to spec\r
public override string Method { \r
get { return this.method; }\r
- set { this.method = value; }\r
+ set {\r
+ if (value == null || value.Length == 0)\r
+ throw new ArgumentException ("Cannot set null or blank "\r
+ + "methods on request.", "value");\r
+ this.method = value;\r
+ }\r
}\r
\r
// currently not used according to spec\r
public override bool PreAuthenticate { \r
- get { throw new NotSupportedException (); }\r
- set { throw new NotSupportedException (); }\r
+ get { return preAuthenticate; }\r
+ set { preAuthenticate = value; }\r
}\r
\r
// currently not used according to spec\r
- public override IWebProxy Proxy { \r
- get { throw new NotSupportedException (); }\r
- set { throw new NotSupportedException (); }\r
+ public override IWebProxy Proxy {\r
+ get { return proxy; }\r
+ set { proxy = value; }\r
}\r
\r
public override Uri RequestUri { \r
public override int Timeout { \r
get { return timeout; }\r
set { \r
- if (value < 0)\r
- throw new ArgumentException ("value");\r
+ if (value < -1)\r
+ throw new ArgumentOutOfRangeException ("Timeout can be "\r
+ + "only set to 'System.Threading.Timeout.Infinite' "\r
+ + "or a value >= 0.");\r
timeout = value;\r
}\r
}\r
- \r
+\r
+ public override bool UseDefaultCredentials\r
+ {\r
+ get {\r
+ throw new NotSupportedException ();\r
+ }\r
+ set {\r
+ throw new NotSupportedException ();\r
+ }\r
+ }\r
// Methods\r
\r
- [MonoTODO]\r
- public override IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state) \r
+ private delegate Stream GetRequestStreamCallback ();\r
+ private delegate WebResponse GetResponseCallback ();\r
+\r
+ static Exception GetMustImplement ()\r
{\r
- throw new NotImplementedException ();\r
+ return new NotImplementedException ();\r
}\r
\r
+ /* LAMESPEC: Docs suggest this was present in 1.1 and\r
+ * 1.0 profiles, but the masterinfos say otherwise\r
+ */\r
[MonoTODO]\r
- public override IAsyncResult BeginGetResponse (AsyncCallback callback, object state)\r
+ public override void Abort ()\r
{\r
- throw new NotImplementedException ();\r
+ throw GetMustImplement ();\r
}\r
\r
- [MonoTODO]\r
+ public override IAsyncResult BeginGetRequestStream (AsyncCallback callback, object state) \r
+ {\r
+ if (string.Compare ("GET", method, true) == 0 ||\r
+ string.Compare ("HEAD", method, true) == 0 ||\r
+ string.Compare ("CONNECT", method, true) == 0)\r
+ throw new ProtocolViolationException ("Cannot send a content-body with this verb-type.");\r
+ lock (this) {\r
+ if (asyncResponding || webResponse != null)\r
+ throw new InvalidOperationException ("This operation cannot be performed after the request has been submitted.");\r
+ if (requesting)\r
+ throw new InvalidOperationException ("Cannot re-call start of asynchronous method while a previous call is still in progress.");\r
+ requesting = true;\r
+ }\r
+ GetRequestStreamCallback c = new GetRequestStreamCallback (this.GetRequestStreamInternal);\r
+ return c.BeginInvoke (callback, state);\r
+ }\r
+ \r
public override Stream EndGetRequestStream (IAsyncResult asyncResult)\r
{\r
- throw new NotImplementedException ();\r
+ if (asyncResult == null)\r
+ throw new ArgumentNullException ("asyncResult");\r
+ if (!asyncResult.IsCompleted)\r
+ asyncResult.AsyncWaitHandle.WaitOne ();\r
+ AsyncResult async = (AsyncResult) asyncResult;\r
+ GetRequestStreamCallback cb = (GetRequestStreamCallback) async.AsyncDelegate;\r
+ return cb.EndInvoke (asyncResult);\r
+ }\r
+\r
+ public override Stream GetRequestStream()\r
+ {\r
+ IAsyncResult asyncResult = BeginGetRequestStream (null, null);\r
+ if (!(asyncResult.AsyncWaitHandle.WaitOne (timeout, false))) {\r
+ throw new WebException("The request timed out", WebExceptionStatus.Timeout);\r
+ }\r
+ return EndGetRequestStream (asyncResult);\r
+ }\r
+ \r
+ internal Stream GetRequestStreamInternal ()\r
+ {\r
+ this.requestStream = new FileWebStream (\r
+ this,\r
+ FileMode.Create,\r
+ FileAccess.Write, \r
+ FileShare.Read);\r
+ return this.requestStream;\r
+ }\r
+ \r
+ public override IAsyncResult BeginGetResponse (AsyncCallback callback, object state)\r
+ {\r
+ lock (this) {\r
+ if (asyncResponding)\r
+ throw new InvalidOperationException ("Cannot re-call start of asynchronous method while a previous call is still in progress.");\r
+ asyncResponding = true;\r
+ }\r
+ GetResponseCallback c = new GetResponseCallback (this.GetResponseInternal);\r
+ return c.BeginInvoke (callback, state);\r
}\r
\r
- [MonoTODO]\r
public override WebResponse EndGetResponse (IAsyncResult asyncResult)\r
{\r
- throw new NotImplementedException ();\r
+ if (asyncResult == null)\r
+ throw new ArgumentNullException ("asyncResult");\r
+ if (!asyncResult.IsCompleted)\r
+ asyncResult.AsyncWaitHandle.WaitOne ();\r
+ AsyncResult async = (AsyncResult) asyncResult;\r
+ GetResponseCallback cb = (GetResponseCallback) async.AsyncDelegate;\r
+ FileWebResponse webResponse = (FileWebResponse) cb.EndInvoke(asyncResult);\r
+ asyncResponding = false;\r
+ if (webResponse.HasError)\r
+ throw webResponse.Error;\r
+ return webResponse;\r
}\r
\r
- public override Stream GetRequestStream()\r
+ public override WebResponse GetResponse ()\r
{\r
- if (method == null || (!method.Equals ("PUT") && !method.Equals ("POST")))\r
- throw new ProtocolViolationException ("Cannot send file when method is: " + this.method + ". Method must be PUT.");\r
- if (open)\r
- throw new WebException ("Stream already open");\r
- open = true;\r
- FileStream fileStream = new FileWebStream (\r
- this,\r
- FileMode.CreateNew, \r
- FileAccess.Write, \r
- FileShare.Read,\r
- 4096,\r
- false);\r
- return fileStream; \r
- }\r
- \r
- public override WebResponse GetResponse()\r
- {\r
- if (method == null || !method.Equals ("GET"))\r
- throw new ProtocolViolationException ("Cannot retrieve file when method is: " + this.method + ". Method must be GET.");\r
- if (open)\r
- throw new WebException ("Stream already open");\r
- FileStream fileStream = new FileWebStream (\r
- this,\r
- FileMode.Open, \r
- FileAccess.Read, \r
- FileShare.Read,\r
- 4096,\r
- false);\r
- return new FileWebResponse (this, fileStream);\r
+ IAsyncResult asyncResult = BeginGetResponse (null, null);\r
+ if (!(asyncResult.AsyncWaitHandle.WaitOne (timeout, false))) {\r
+ throw new WebException("The request timed out", WebExceptionStatus.Timeout);\r
+ }\r
+ return EndGetResponse (asyncResult);\r
}\r
\r
- [MonoTODO]\r
- void ISerializable.GetObjectData (SerializationInfo serializationInfo,\r
- StreamingContext streamingContext)\r
+ WebResponse GetResponseInternal ()\r
{\r
- throw new NotImplementedException ();\r
+ if (webResponse != null)\r
+ return webResponse;\r
+ lock (this) {\r
+ if (requesting) {\r
+ requestEndEvent = new AutoResetEvent (false);\r
+ }\r
+ }\r
+ if (requestEndEvent != null) {\r
+ requestEndEvent.WaitOne ();\r
+ }\r
+ FileStream fileStream = null;\r
+ try {\r
+ fileStream = new FileWebStream (this, FileMode.Open, FileAccess.Read, FileShare.Read);\r
+ this.webResponse = new FileWebResponse (this.uri, fileStream);\r
+ } catch (Exception ex) {\r
+ this.webResponse = new FileWebResponse (this.uri, new WebException (ex.Message, ex));\r
+ }\r
+ return this.webResponse;\r
}\r
\r
- internal void Close ()\r
+ void ISerializable.GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)\r
{\r
- open = false;\r
+ GetObjectData (serializationInfo, streamingContext);\r
+ }\r
+\r
+ protected override void GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)\r
+ {\r
+ SerializationInfo info = serializationInfo;\r
+ info.AddValue ("headers", webHeaders, typeof (WebHeaderCollection));\r
+ info.AddValue ("proxy", proxy, typeof (IWebProxy));\r
+ info.AddValue ("uri", uri, typeof (Uri));\r
+ info.AddValue ("connectionGroupName", connectionGroup);\r
+ info.AddValue ("method", method);\r
+ info.AddValue ("contentLength", contentLength);\r
+ info.AddValue ("timeout", timeout);\r
+ info.AddValue ("fileAccess", fileAccess);\r
+ info.AddValue ("preauthenticate", false);\r
}\r
\r
- internal bool IsClosed ()\r
+ internal void Close ()\r
{\r
- return !open;\r
+ // already done in class below\r
+ // if (requestStream != null) {\r
+ // requestStream.Close ();\r
+ // }\r
+\r
+ lock (this) {\r
+ requesting = false;\r
+ if (requestEndEvent != null) \r
+ requestEndEvent.Set ();\r
+ // requestEndEvent = null;\r
+ }\r
}\r
\r
// to catch the Close called on the FileStream\r
internal FileWebStream (FileWebRequest webRequest, \r
FileMode mode,\r
FileAccess access,\r
- FileShare share,\r
- int bufferSize,\r
- bool useAsync)\r
+ FileShare share)\r
: base (webRequest.RequestUri.LocalPath, \r
- mode, access, share, bufferSize, useAsync) \r
+ mode, access, share)\r
{\r
this.webRequest = webRequest;\r
}\r
- \r
+ \r
public override void Close() \r
{\r
base.Close ();\r
- webRequest.Close ();\r
+ FileWebRequest req = webRequest;\r
+ webRequest = null;\r
+ if (req != null)\r
+ req.Close ();\r
}\r
}\r
}\r
-}
\ No newline at end of file
+}\r