aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Framework/Communications/RestClient/RestClient.cs
diff options
context:
space:
mode:
authorSean Dague2007-10-25 15:43:48 +0000
committerSean Dague2007-10-25 15:43:48 +0000
commit461eaf188e953096360abfa8baf9cbe8bdef3a8a (patch)
tree8990758c26a44e82fecccf7f515a56827c289d51 /OpenSim/Framework/Communications/RestClient/RestClient.cs
parentapply http://bug.opensecondlife.org/view.php?id=512 from chillken (diff)
downloadopensim-SC-461eaf188e953096360abfa8baf9cbe8bdef3a8a.zip
opensim-SC-461eaf188e953096360abfa8baf9cbe8bdef3a8a.tar.gz
opensim-SC-461eaf188e953096360abfa8baf9cbe8bdef3a8a.tar.bz2
opensim-SC-461eaf188e953096360abfa8baf9cbe8bdef3a8a.tar.xz
fix line endings
Diffstat (limited to 'OpenSim/Framework/Communications/RestClient/RestClient.cs')
-rw-r--r--OpenSim/Framework/Communications/RestClient/RestClient.cs656
1 files changed, 328 insertions, 328 deletions
diff --git a/OpenSim/Framework/Communications/RestClient/RestClient.cs b/OpenSim/Framework/Communications/RestClient/RestClient.cs
index ccf8376..25fc61a 100644
--- a/OpenSim/Framework/Communications/RestClient/RestClient.cs
+++ b/OpenSim/Framework/Communications/RestClient/RestClient.cs
@@ -1,328 +1,328 @@
1using System; 1using System;
2using System.IO; 2using System.IO;
3using System.Net; 3using System.Net;
4using System.Web; 4using System.Web;
5using System.Text; 5using System.Text;
6using System.Collections.Generic; 6using System.Collections.Generic;
7using System.Threading; 7using System.Threading;
8 8
9namespace OpenSim.Framework.RestClient 9namespace OpenSim.Framework.RestClient
10{ 10{
11 /// <summary> 11 /// <summary>
12 /// Implementation of a generic REST client 12 /// Implementation of a generic REST client
13 /// </summary> 13 /// </summary>
14 /// <remarks> 14 /// <remarks>
15 /// This class is a generic implementation of a REST (Representational State Transfer) web service. This 15 /// This class is a generic implementation of a REST (Representational State Transfer) web service. This
16 /// class is designed to execute both synchroneously and asynchroneously. 16 /// class is designed to execute both synchroneously and asynchroneously.
17 /// 17 ///
18 /// Internally the implementation works as a two stage asynchroneous web-client. 18 /// Internally the implementation works as a two stage asynchroneous web-client.
19 /// When the request is initiated, RestClient will query asynchroneously for for a web-response, 19 /// When the request is initiated, RestClient will query asynchroneously for for a web-response,
20 /// sleeping until the initial response is returned by the server. Once the initial response is retrieved 20 /// sleeping until the initial response is returned by the server. Once the initial response is retrieved
21 /// the second stage of asynchroneous requests will be triggered, in an attempt to read of the response 21 /// the second stage of asynchroneous requests will be triggered, in an attempt to read of the response
22 /// object into a memorystream as a sequence of asynchroneous reads. 22 /// object into a memorystream as a sequence of asynchroneous reads.
23 /// 23 ///
24 /// The asynchronisity of RestClient is designed to move as much processing into the back-ground, allowing 24 /// The asynchronisity of RestClient is designed to move as much processing into the back-ground, allowing
25 /// other threads to execute, while it waits for a response from the web-service. RestClient it self, can be 25 /// other threads to execute, while it waits for a response from the web-service. RestClient it self, can be
26 /// invoked by the caller in either synchroneous mode or asynchroneous mode. 26 /// invoked by the caller in either synchroneous mode or asynchroneous mode.
27 /// </remarks> 27 /// </remarks>
28 public class RestClient 28 public class RestClient
29 { 29 {
30 /// <summary> 30 /// <summary>
31 /// The base Uri of the web-service e.g. http://www.google.com 31 /// The base Uri of the web-service e.g. http://www.google.com
32 /// </summary> 32 /// </summary>
33 private string _url; 33 private string _url;
34 34
35 /// <summary> 35 /// <summary>
36 /// Path elements of the query 36 /// Path elements of the query
37 /// </summary> 37 /// </summary>
38 private List<string> _pathElements = new List<string>(); 38 private List<string> _pathElements = new List<string>();
39 39
40 /// <summary> 40 /// <summary>
41 /// Parameter elements of the query, e.g. min=34 41 /// Parameter elements of the query, e.g. min=34
42 /// </summary> 42 /// </summary>
43 private Dictionary<string, string> _parameterElements = new Dictionary<string, string>(); 43 private Dictionary<string, string> _parameterElements = new Dictionary<string, string>();
44 44
45 /// <summary> 45 /// <summary>
46 /// Request method. E.g. GET, POST, PUT or DELETE 46 /// Request method. E.g. GET, POST, PUT or DELETE
47 /// </summary> 47 /// </summary>
48 private string _method; 48 private string _method;
49 49
50 /// <summary> 50 /// <summary>
51 /// Temporary buffer used to store bytes temporarily as they come in from the server 51 /// Temporary buffer used to store bytes temporarily as they come in from the server
52 /// </summary> 52 /// </summary>
53 private byte[] _readbuf; 53 private byte[] _readbuf;
54 54
55 /// <summary> 55 /// <summary>
56 /// MemoryStream representing the resultiong resource 56 /// MemoryStream representing the resultiong resource
57 /// </summary> 57 /// </summary>
58 MemoryStream _resource; 58 MemoryStream _resource;
59 59
60 /// <summary> 60 /// <summary>
61 /// WebRequest object, held as a member variable 61 /// WebRequest object, held as a member variable
62 /// </summary> 62 /// </summary>
63 private HttpWebRequest _request; 63 private HttpWebRequest _request;
64 64
65 /// <summary> 65 /// <summary>
66 /// WebResponse object, held as a member variable, so we can close it 66 /// WebResponse object, held as a member variable, so we can close it
67 /// </summary> 67 /// </summary>
68 private HttpWebResponse _response; 68 private HttpWebResponse _response;
69 69
70 /// <summary> 70 /// <summary>
71 /// This flag will help block the main synchroneous method, in case we run in synchroneous mode 71 /// This flag will help block the main synchroneous method, in case we run in synchroneous mode
72 /// </summary> 72 /// </summary>
73 public static ManualResetEvent _allDone = new ManualResetEvent(false); 73 public static ManualResetEvent _allDone = new ManualResetEvent(false);
74 74
75 /// <summary> 75 /// <summary>
76 /// Default time out period 76 /// Default time out period
77 /// </summary> 77 /// </summary>
78 const int DefaultTimeout = 10 * 1000; // 10 seconds timeout 78 const int DefaultTimeout = 10 * 1000; // 10 seconds timeout
79 79
80 /// <summary> 80 /// <summary>
81 /// Default Buffer size of a block requested from the web-server 81 /// Default Buffer size of a block requested from the web-server
82 /// </summary> 82 /// </summary>
83 const int BufferSize = 4096; // Read blocks of 4 KB. 83 const int BufferSize = 4096; // Read blocks of 4 KB.
84 84
85 85
86 /// <summary> 86 /// <summary>
87 /// if an exception occours during async processing, we need to save it, so it can be 87 /// if an exception occours during async processing, we need to save it, so it can be
88 /// rethrown on the primary thread; 88 /// rethrown on the primary thread;
89 /// </summary> 89 /// </summary>
90 private Exception _asyncException; 90 private Exception _asyncException;
91 91
92 /// <summary> 92 /// <summary>
93 /// Instantiate a new RestClient 93 /// Instantiate a new RestClient
94 /// </summary> 94 /// </summary>
95 /// <param name="url">Web-service to query, e.g. http://osgrid.org:8003</param> 95 /// <param name="url">Web-service to query, e.g. http://osgrid.org:8003</param>
96 public RestClient(string url) 96 public RestClient(string url)
97 { 97 {
98 _url = url; 98 _url = url;
99 _readbuf = new byte[BufferSize]; 99 _readbuf = new byte[BufferSize];
100 _resource = new MemoryStream(); 100 _resource = new MemoryStream();
101 _request = null; 101 _request = null;
102 _response = null; 102 _response = null;
103 } 103 }
104 104
105 /// <summary> 105 /// <summary>
106 /// Add a path element to the query, e.g. assets 106 /// Add a path element to the query, e.g. assets
107 /// </summary> 107 /// </summary>
108 /// <param name="element">path entry</param> 108 /// <param name="element">path entry</param>
109 public void AddResourcePath(string element) 109 public void AddResourcePath(string element)
110 { 110 {
111 if(isSlashed(element)) 111 if(isSlashed(element))
112 _pathElements.Add(element.Substring(0, element.Length-1)); 112 _pathElements.Add(element.Substring(0, element.Length-1));
113 else 113 else
114 _pathElements.Add(element); 114 _pathElements.Add(element);
115 } 115 }
116 116
117 /// <summary> 117 /// <summary>
118 /// Add a query parameter to the Url 118 /// Add a query parameter to the Url
119 /// </summary> 119 /// </summary>
120 /// <param name="name">Name of the parameter, e.g. min</param> 120 /// <param name="name">Name of the parameter, e.g. min</param>
121 /// <param name="value">Value of the parameter, e.g. 42</param> 121 /// <param name="value">Value of the parameter, e.g. 42</param>
122 public void AddQueryParameter(string name, string value) 122 public void AddQueryParameter(string name, string value)
123 { 123 {
124 _parameterElements.Add(HttpUtility.UrlEncode(name), HttpUtility.UrlEncode(value)); 124 _parameterElements.Add(HttpUtility.UrlEncode(name), HttpUtility.UrlEncode(value));
125 } 125 }
126 126
127 /// <summary> 127 /// <summary>
128 /// Web-Request method, e.g. GET, PUT, POST, DELETE 128 /// Web-Request method, e.g. GET, PUT, POST, DELETE
129 /// </summary> 129 /// </summary>
130 public string RequestMethod 130 public string RequestMethod
131 { 131 {
132 get { return _method; } 132 get { return _method; }
133 set { _method = value; } 133 set { _method = value; }
134 } 134 }
135 135
136 /// <summary> 136 /// <summary>
137 /// True if string contains a trailing slash '/' 137 /// True if string contains a trailing slash '/'
138 /// </summary> 138 /// </summary>
139 /// <param name="s">string to be examined</param> 139 /// <param name="s">string to be examined</param>
140 /// <returns>true if slash is present</returns> 140 /// <returns>true if slash is present</returns>
141 private bool isSlashed(string s) 141 private bool isSlashed(string s)
142 { 142 {
143 return s.Substring(s.Length - 1, 1) == "/"; 143 return s.Substring(s.Length - 1, 1) == "/";
144 } 144 }
145 145
146 /// <summary> 146 /// <summary>
147 /// return a slash or blank. A slash will be returned if the string does not contain one 147 /// return a slash or blank. A slash will be returned if the string does not contain one
148 /// </summary> 148 /// </summary>
149 /// <param name="s">stromg to be examined</param> 149 /// <param name="s">stromg to be examined</param>
150 /// <returns>slash '/' if not already present</returns> 150 /// <returns>slash '/' if not already present</returns>
151 private string slash(string s) 151 private string slash(string s)
152 { 152 {
153 return isSlashed(s) ? "" : "/"; 153 return isSlashed(s) ? "" : "/";
154 } 154 }
155 155
156 /// <summary> 156 /// <summary>
157 /// Build a Uri based on the intial Url, path elements and parameters 157 /// Build a Uri based on the intial Url, path elements and parameters
158 /// </summary> 158 /// </summary>
159 /// <returns>fully constructed Uri</returns> 159 /// <returns>fully constructed Uri</returns>
160 Uri buildUri() 160 Uri buildUri()
161 { 161 {
162 StringBuilder sb = new StringBuilder(); 162 StringBuilder sb = new StringBuilder();
163 sb.Append(_url); 163 sb.Append(_url);
164 164
165 foreach (string e in _pathElements) 165 foreach (string e in _pathElements)
166 { 166 {
167 sb.Append("/"); 167 sb.Append("/");
168 sb.Append(e); 168 sb.Append(e);
169 } 169 }
170 170
171 bool firstElement = true; 171 bool firstElement = true;
172 foreach (KeyValuePair<string, string> kv in _parameterElements) 172 foreach (KeyValuePair<string, string> kv in _parameterElements)
173 { 173 {
174 if (firstElement) 174 if (firstElement)
175 { 175 {
176 sb.Append("?"); 176 sb.Append("?");
177 firstElement = false; 177 firstElement = false;
178 } else 178 } else
179 sb.Append("&"); 179 sb.Append("&");
180 180
181 sb.Append(kv.Key); 181 sb.Append(kv.Key);
182 if (kv.Value != null && kv.Value.Length != 0) 182 if (kv.Value != null && kv.Value.Length != 0)
183 { 183 {
184 sb.Append("="); 184 sb.Append("=");
185 sb.Append(kv.Value); 185 sb.Append(kv.Value);
186 } 186 }
187 } 187 }
188 return new Uri(sb.ToString()); 188 return new Uri(sb.ToString());
189 } 189 }
190 190
191 /// <summary> 191 /// <summary>
192 /// Async method, invoked when a block of data has been received from the service 192 /// Async method, invoked when a block of data has been received from the service
193 /// </summary> 193 /// </summary>
194 /// <param name="ar"></param> 194 /// <param name="ar"></param>
195 private void StreamIsReadyDelegate(IAsyncResult ar) 195 private void StreamIsReadyDelegate(IAsyncResult ar)
196 { 196 {
197 try 197 try
198 { 198 {
199 Stream s = (Stream)ar.AsyncState; 199 Stream s = (Stream)ar.AsyncState;
200 int read = s.EndRead(ar); 200 int read = s.EndRead(ar);
201 201
202 // Read the HTML page and then print it to the console. 202 // Read the HTML page and then print it to the console.
203 if (read > 0) 203 if (read > 0)
204 { 204 {
205 _resource.Write(_readbuf, 0, read); 205 _resource.Write(_readbuf, 0, read);
206 IAsyncResult asynchronousResult = s.BeginRead(_readbuf, 0, BufferSize, new AsyncCallback(StreamIsReadyDelegate), s); 206 IAsyncResult asynchronousResult = s.BeginRead(_readbuf, 0, BufferSize, new AsyncCallback(StreamIsReadyDelegate), s);
207 207
208 // TODO! Implement timeout, without killing the server 208 // TODO! Implement timeout, without killing the server
209 //ThreadPool.RegisterWaitForSingleObject(asynchronousResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); 209 //ThreadPool.RegisterWaitForSingleObject(asynchronousResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true);
210 return; 210 return;
211 } 211 }
212 else 212 else
213 { 213 {
214 s.Close(); 214 s.Close();
215 _allDone.Set(); 215 _allDone.Set();
216 } 216 }
217 } 217 }
218 catch (Exception e) 218 catch (Exception e)
219 { 219 {
220 _allDone.Set(); 220 _allDone.Set();
221 _asyncException = e; 221 _asyncException = e;
222 } 222 }
223 } 223 }
224 224
225 /// <summary> 225 /// <summary>
226 /// Async method, invoked when the intial response if received from the server 226 /// Async method, invoked when the intial response if received from the server
227 /// </summary> 227 /// </summary>
228 /// <param name="ar"></param> 228 /// <param name="ar"></param>
229 private void ResponseIsReadyDelegate(IAsyncResult ar) 229 private void ResponseIsReadyDelegate(IAsyncResult ar)
230 { 230 {
231 try 231 try
232 { 232 {
233 // grab response 233 // grab response
234 WebRequest wr = (WebRequest)ar.AsyncState; 234 WebRequest wr = (WebRequest)ar.AsyncState;
235 _response = (HttpWebResponse)wr.EndGetResponse(ar); 235 _response = (HttpWebResponse)wr.EndGetResponse(ar);
236 236
237 // get response stream, and setup async reading 237 // get response stream, and setup async reading
238 Stream s = _response.GetResponseStream(); 238 Stream s = _response.GetResponseStream();
239 IAsyncResult asynchronousResult = s.BeginRead(_readbuf, 0, BufferSize, new AsyncCallback(StreamIsReadyDelegate), s); 239 IAsyncResult asynchronousResult = s.BeginRead(_readbuf, 0, BufferSize, new AsyncCallback(StreamIsReadyDelegate), s);
240 240
241 // TODO! Implement timeout, without killing the server 241 // TODO! Implement timeout, without killing the server
242 // wait until completed, or we timed out 242 // wait until completed, or we timed out
243 // ThreadPool.RegisterWaitForSingleObject(asynchronousResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); 243 // ThreadPool.RegisterWaitForSingleObject(asynchronousResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true);
244 } 244 }
245 catch (Exception e) 245 catch (Exception e)
246 { 246 {
247 _allDone.Set(); 247 _allDone.Set();
248 _asyncException = e; 248 _asyncException = e;
249 } 249 }
250 } 250 }
251 251
252 // Abort the request if the timer fires. 252 // Abort the request if the timer fires.
253 private static void TimeoutCallback(object state, bool timedOut) 253 private static void TimeoutCallback(object state, bool timedOut)
254 { 254 {
255 if (timedOut) 255 if (timedOut)
256 { 256 {
257 HttpWebRequest request = state as HttpWebRequest; 257 HttpWebRequest request = state as HttpWebRequest;
258 if (request != null) 258 if (request != null)
259 { 259 {
260 request.Abort(); 260 request.Abort();
261 } 261 }
262 } 262 }
263 } 263 }
264 264
265 /// <summary> 265 /// <summary>
266 /// Perform synchroneous request 266 /// Perform synchroneous request
267 /// </summary> 267 /// </summary>
268 public Stream Request() 268 public Stream Request()
269 { 269 {
270 _request = (HttpWebRequest)WebRequest.Create(buildUri()); 270 _request = (HttpWebRequest)WebRequest.Create(buildUri());
271 _request.KeepAlive = false; 271 _request.KeepAlive = false;
272 _request.ContentType = "text/html"; 272 _request.ContentType = "text/html";
273 _request.Timeout = 200; 273 _request.Timeout = 200;
274 _asyncException = null; 274 _asyncException = null;
275 275
276 IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request); 276 IAsyncResult responseAsyncResult = _request.BeginGetResponse(new AsyncCallback(ResponseIsReadyDelegate), _request);
277 277
278 // TODO! Implement timeout, without killing the server 278 // TODO! Implement timeout, without killing the server
279 // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted 279 // this line implements the timeout, if there is a timeout, the callback fires and the request becomes aborted
280 //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true); 280 //ThreadPool.RegisterWaitForSingleObject(responseAsyncResult.AsyncWaitHandle, new WaitOrTimerCallback(TimeoutCallback), _request, DefaultTimeout, true);
281 281
282 _allDone.WaitOne(); 282 _allDone.WaitOne();
283 if(_response != null) 283 if(_response != null)
284 _response.Close(); 284 _response.Close();
285 if (_asyncException != null) 285 if (_asyncException != null)
286 throw _asyncException; 286 throw _asyncException;
287 return _resource; 287 return _resource;
288 } 288 }
289 289
290 #region Async Invocation 290 #region Async Invocation
291 public IAsyncResult BeginRequest(AsyncCallback callback, object state) 291 public IAsyncResult BeginRequest(AsyncCallback callback, object state)
292 { 292 {
293 /// <summary> 293 /// <summary>
294 /// In case, we are invoked asynchroneously this object will keep track of the state 294 /// In case, we are invoked asynchroneously this object will keep track of the state
295 /// </summary> 295 /// </summary>
296 AsyncResult<Stream> ar = new AsyncResult<Stream>(callback, state); 296 AsyncResult<Stream> ar = new AsyncResult<Stream>(callback, state);
297 ThreadPool.QueueUserWorkItem(RequestHelper, ar); 297 ThreadPool.QueueUserWorkItem(RequestHelper, ar);
298 return ar; 298 return ar;
299 } 299 }
300 300
301 public Stream EndRequest(IAsyncResult asyncResult) 301 public Stream EndRequest(IAsyncResult asyncResult)
302 { 302 {
303 AsyncResult<Stream> ar = (AsyncResult<Stream>)asyncResult; 303 AsyncResult<Stream> ar = (AsyncResult<Stream>)asyncResult;
304 304
305 // Wait for operation to complete, then return result or 305 // Wait for operation to complete, then return result or
306 // throw exception 306 // throw exception
307 return ar.EndInvoke(); 307 return ar.EndInvoke();
308 } 308 }
309 309
310 private void RequestHelper(Object asyncResult) 310 private void RequestHelper(Object asyncResult)
311 { 311 {
312 // We know that it's really an AsyncResult<DateTime> object 312 // We know that it's really an AsyncResult<DateTime> object
313 AsyncResult<Stream> ar = (AsyncResult<Stream>)asyncResult; 313 AsyncResult<Stream> ar = (AsyncResult<Stream>)asyncResult;
314 try 314 try
315 { 315 {
316 // Perform the operation; if sucessful set the result 316 // Perform the operation; if sucessful set the result
317 Stream s = Request(); 317 Stream s = Request();
318 ar.SetAsCompleted(s, false); 318 ar.SetAsCompleted(s, false);
319 } 319 }
320 catch (Exception e) 320 catch (Exception e)
321 { 321 {
322 // If operation fails, set the exception 322 // If operation fails, set the exception
323 ar.HandleException(e, false); 323 ar.HandleException(e, false);
324 } 324 }
325 } 325 }
326 #endregion Async Invocation 326 #endregion Async Invocation
327 } 327 }
328} 328}