aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs')
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs507
1 files changed, 335 insertions, 172 deletions
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
index 74b980c..6f8d9ed 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Collections.Specialized;
30using System.IO; 31using System.IO;
31using System.Net; 32using System.Net;
32using System.Reflection; 33using System.Reflection;
@@ -122,7 +123,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
122 m_Enabled = true; 123 m_Enabled = true;
123 } 124 }
124 125
125 #region IAssetService 126#region IAssetService
126 127
127 public AssetBase Get(string id) 128 public AssetBase Get(string id)
128 { 129 {
@@ -140,8 +141,9 @@ namespace OpenSim.Services.Connectors.SimianGrid
140 return asset; 141 return asset;
141 } 142 }
142 143
143 return GetRemote(id); 144 return SimianGetOperation(id);
144 } 145 }
146
145 147
146 public AssetBase GetCached(string id) 148 public AssetBase GetCached(string id)
147 { 149 {
@@ -164,8 +166,6 @@ namespace OpenSim.Services.Connectors.SimianGrid
164 throw new InvalidOperationException(); 166 throw new InvalidOperationException();
165 } 167 }
166 168
167 AssetMetadata metadata = null;
168
169 // Cache fetch 169 // Cache fetch
170 if (m_cache != null) 170 if (m_cache != null)
171 { 171 {
@@ -174,50 +174,18 @@ namespace OpenSim.Services.Connectors.SimianGrid
174 return asset.Metadata; 174 return asset.Metadata;
175 } 175 }
176 176
177 Uri url; 177 // return GetRemoteMetadata(id);
178 178 return SimianGetMetadataOperation(id);
179 // Determine if id is an absolute URL or a grid-relative UUID
180 if (!Uri.TryCreate(id, UriKind.Absolute, out url))
181 url = new Uri(m_serverUrl + id);
182
183 try
184 {
185 HttpWebRequest request = UntrustedHttpWebRequest.Create(url);
186 request.Method = "HEAD";
187
188 using (WebResponse response = request.GetResponse())
189 {
190 using (Stream responseStream = response.GetResponseStream())
191 {
192 // Create the metadata object
193 metadata = new AssetMetadata();
194 metadata.ContentType = response.ContentType;
195 metadata.ID = id;
196
197 UUID uuid;
198 if (UUID.TryParse(id, out uuid))
199 metadata.FullID = uuid;
200
201 string lastModifiedStr = response.Headers.Get("Last-Modified");
202 if (!String.IsNullOrEmpty(lastModifiedStr))
203 {
204 DateTime lastModified;
205 if (DateTime.TryParse(lastModifiedStr, out lastModified))
206 metadata.CreationDate = lastModified;
207 }
208 }
209 }
210 }
211 catch (Exception ex)
212 {
213 m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset HEAD from " + url + " failed: " + ex.Message);
214 }
215
216 return metadata;
217 } 179 }
218 180
219 public byte[] GetData(string id) 181 public byte[] GetData(string id)
220 { 182 {
183 if (String.IsNullOrEmpty(m_serverUrl))
184 {
185 m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
186 throw new InvalidOperationException();
187 }
188
221 AssetBase asset = Get(id); 189 AssetBase asset = Get(id);
222 190
223 if (asset != null) 191 if (asset != null)
@@ -255,7 +223,7 @@ namespace OpenSim.Services.Connectors.SimianGrid
255 Util.FireAndForget( 223 Util.FireAndForget(
256 delegate(object o) 224 delegate(object o)
257 { 225 {
258 AssetBase asset = GetRemote(id); 226 AssetBase asset = SimianGetOperation(id);
259 handler(id, sender, asset); 227 handler(id, sender, asset);
260 } 228 }
261 ); 229 );
@@ -278,7 +246,6 @@ namespace OpenSim.Services.Connectors.SimianGrid
278 } 246 }
279 247
280 bool storedInCache = false; 248 bool storedInCache = false;
281 string errorMessage = null;
282 249
283 // AssetID handling 250 // AssetID handling
284 if (String.IsNullOrEmpty(asset.ID) || asset.ID == ZeroID) 251 if (String.IsNullOrEmpty(asset.ID) || asset.ID == ZeroID)
@@ -307,83 +274,9 @@ namespace OpenSim.Services.Connectors.SimianGrid
307 return asset.ID; 274 return asset.ID;
308 } 275 }
309 276
310 // Distinguish public and private assets 277 return SimianStoreOperation(asset);
311 bool isPublic = true;
312 switch ((AssetType)asset.Type)
313 {
314 case AssetType.CallingCard:
315 case AssetType.Gesture:
316 case AssetType.LSLBytecode:
317 case AssetType.LSLText:
318 isPublic = false;
319 break;
320 }
321
322 // Make sure ContentType is set
323 if (String.IsNullOrEmpty(asset.Metadata.ContentType))
324 asset.Metadata.ContentType = SLUtil.SLAssetTypeToContentType(asset.Type);
325
326 // Build the remote storage request
327 List<MultipartForm.Element> postParameters = new List<MultipartForm.Element>()
328 {
329 new MultipartForm.Parameter("AssetID", asset.FullID.ToString()),
330 new MultipartForm.Parameter("CreatorID", asset.Metadata.CreatorID),
331 new MultipartForm.Parameter("Temporary", asset.Temporary ? "1" : "0"),
332 new MultipartForm.Parameter("Public", isPublic ? "1" : "0"),
333 new MultipartForm.File("Asset", asset.Name, asset.Metadata.ContentType, asset.Data)
334 };
335
336 // Make the remote storage request
337 try
338 {
339 // Simian does not require the asset ID to be in the URL because it's in the post data.
340 // By appending it to the URL also, we allow caching proxies (squid) to invalidate asset URLs
341 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl + asset.FullID.ToString());
342
343 using (HttpWebResponse response = MultipartForm.Post(request, postParameters))
344 {
345 using (Stream responseStream = response.GetResponseStream())
346 {
347 string responseStr = null;
348
349 try
350 {
351 responseStr = responseStream.GetStreamString();
352 OSD responseOSD = OSDParser.Deserialize(responseStr);
353 if (responseOSD.Type == OSDType.Map)
354 {
355 OSDMap responseMap = (OSDMap)responseOSD;
356 if (responseMap["Success"].AsBoolean())
357 return asset.ID;
358 else
359 errorMessage = "Upload failed: " + responseMap["Message"].AsString();
360 }
361 else
362 {
363 errorMessage = "Response format was invalid:\n" + responseStr;
364 }
365 }
366 catch (Exception ex)
367 {
368 if (!String.IsNullOrEmpty(responseStr))
369 errorMessage = "Failed to parse the response:\n" + responseStr;
370 else
371 errorMessage = "Failed to retrieve the response: " + ex.Message;
372 }
373 }
374 }
375 }
376 catch (WebException ex)
377 {
378 errorMessage = ex.Message;
379 }
380
381 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: Failed to store asset \"{0}\" ({1}, {2}): {3}",
382 asset.Name, asset.ID, asset.Metadata.ContentType, errorMessage);
383
384 return null;
385 } 278 }
386 279
387 /// <summary> 280 /// <summary>
388 /// Update an asset's content 281 /// Update an asset's content
389 /// </summary> 282 /// </summary>
@@ -393,11 +286,17 @@ namespace OpenSim.Services.Connectors.SimianGrid
393 /// <returns></returns> 286 /// <returns></returns>
394 public bool UpdateContent(string id, byte[] data) 287 public bool UpdateContent(string id, byte[] data)
395 { 288 {
289 if (String.IsNullOrEmpty(m_serverUrl))
290 {
291 m_log.Error("[SIMIAN ASSET CONNECTOR]: No AssetServerURI configured");
292 throw new InvalidOperationException();
293 }
294
396 AssetBase asset = Get(id); 295 AssetBase asset = Get(id);
397 296
398 if (asset == null) 297 if (asset == null)
399 { 298 {
400 m_log.Warn("[SIMIAN ASSET CONNECTOR]: Failed to fetch asset " + id + " for updating"); 299 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: Failed to fetch asset {0} for updating", id);
401 return false; 300 return false;
402 } 301 }
403 302
@@ -420,83 +319,347 @@ namespace OpenSim.Services.Connectors.SimianGrid
420 throw new InvalidOperationException(); 319 throw new InvalidOperationException();
421 } 320 }
422 321
423 //string errorMessage = String.Empty;
424 string url = m_serverUrl + id;
425
426 if (m_cache != null) 322 if (m_cache != null)
427 m_cache.Expire(id); 323 m_cache.Expire(id);
428 324
325 return SimianDeleteOperation(id);
326 }
327
328#endregion IAssetService
329
330#region SimianOperations
331 /// <summary>
332 /// Invokes the xRemoveAsset operation on the simian server to delete an asset
333 /// </summary>
334 /// <param name="id"></param>
335 /// <returns></returns>
336 private bool SimianDeleteOperation(string id)
337 {
429 try 338 try
430 { 339 {
431 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(url); 340 NameValueCollection requestArgs = new NameValueCollection
432 request.Method = "DELETE"; 341 {
342 { "RequestMethod", "xRemoveAsset" },
343 { "AssetID", id }
344 };
433 345
434 using (HttpWebResponse response = (HttpWebResponse)request.GetResponse()) 346 OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs);
347 if (! response["Success"].AsBoolean())
435 { 348 {
436 if (response.StatusCode != HttpStatusCode.NoContent) 349 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: failed to delete asset; {0}",response["Message"].AsString());
437 { 350 return false;
438 m_log.Warn("[SIMIAN ASSET CONNECTOR]: Unexpected response when deleting asset " + url + ": " +
439 response.StatusCode + " (" + response.StatusDescription + ")");
440 }
441 } 351 }
442 352
443 return true; 353 return true;
354
444 } 355 }
445 catch (Exception ex) 356 catch (Exception ex)
446 { 357 {
447 m_log.Warn("[SIMIAN ASSET CONNECTOR]: Failed to delete asset " + id + " from the asset service: " + ex.Message); 358 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: failed to delete asset {0}; {1}", id, ex.Message);
448 return false;
449 } 359 }
450 }
451 360
452 #endregion IAssetService 361 return false;
362 }
453 363
454 private AssetBase GetRemote(string id) 364 /// <summary>
365 /// Invokes the xAddAsset operation on the simian server to create or update an asset
366 /// </summary>
367 /// <param name="id"></param>
368 /// <returns></returns>
369 private string SimianStoreOperation(AssetBase asset)
455 { 370 {
456 AssetBase asset = null; 371 try
457 Uri url; 372 {
373 NameValueCollection requestArgs = new NameValueCollection
374 {
375 { "RequestMethod", "xAddAsset" },
376 { "ContentType", asset.Metadata.ContentType },
377 { "EncodedData", Convert.ToBase64String(asset.Data) },
378 { "AssetID", asset.FullID.ToString() },
379 { "CreatorID", asset.Metadata.CreatorID },
380 { "Temporary", asset.Temporary ? "1" : "0" },
381 { "Name", asset.Name }
382 };
383
384 OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs);
385 if (! response["Success"].AsBoolean())
386 {
387 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR] failed to store asset; {0}",response["Message"].AsString());
388 return null;
389 }
458 390
459 // Determine if id is an absolute URL or a grid-relative UUID 391 // asset.ID is always set before calling this function
460 if (!Uri.TryCreate(id, UriKind.Absolute, out url)) 392 return asset.ID;
461 url = new Uri(m_serverUrl + id); 393
394 }
395 catch (Exception ex)
396 {
397 m_log.ErrorFormat("[SIMIAN ASSET CONNECTOR] failed to store asset; {0}",ex.Message);
398 }
399
400 return null;
401 }
462 402
463 try 403 /// <summary>
404 /// Invokes the xGetAsset operation on the simian server to get data associated with an asset
405 /// </summary>
406 /// <param name="id"></param>
407 /// <returns></returns>
408 private AssetBase SimianGetOperation(string id)
409 {
410 try
464 { 411 {
465 HttpWebRequest request = UntrustedHttpWebRequest.Create(url); 412 NameValueCollection requestArgs = new NameValueCollection
413 {
414 { "RequestMethod", "xGetAsset" },
415 { "ID", id }
416 };
466 417
467 using (WebResponse response = request.GetResponse()) 418 OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs);
419 if (! response["Success"].AsBoolean())
468 { 420 {
469 using (Stream responseStream = response.GetResponseStream()) 421 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR] Failed to get asset; {0}",response["Message"].AsString());
470 { 422 return null;
471 string creatorID = response.Headers.GetOne("X-Asset-Creator-Id") ?? String.Empty;
472
473 // Create the asset object
474 asset = new AssetBase(id, String.Empty, SLUtil.ContentTypeToSLAssetType(response.ContentType), creatorID);
475
476 UUID assetID;
477 if (UUID.TryParse(id, out assetID))
478 asset.FullID = assetID;
479
480 // Grab the asset data from the response stream
481 using (MemoryStream stream = new MemoryStream())
482 {
483 responseStream.CopyStream(stream, Int32.MaxValue);
484 asset.Data = stream.ToArray();
485 }
486 }
487 } 423 }
424
425 AssetBase asset = new AssetBase();
488 426
489 // Cache store 427 asset.ID = id;
490 if (m_cache != null && asset != null) 428 asset.Name = String.Empty;
491 m_cache.Cache(asset); 429 asset.Metadata.ContentType = response["ContentType"].AsString(); // this will also set the asset Type property
430 asset.CreatorID = response["CreatorID"].AsString();
431 asset.Data = System.Convert.FromBase64String(response["EncodedData"].AsString());
432 asset.Local = false;
433 asset.Temporary = response["Temporary"];
492 434
493 return asset; 435 return asset;
494 } 436 }
495 catch (Exception ex) 437 catch (Exception ex)
496 { 438 {
497 m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset GET from " + url + " failed: " + ex.Message); 439 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: failed to retrieve asset {0}; {1}", id, ex.Message);
498 return null;
499 } 440 }
441
442 return null;
443 }
444
445 /// <summary>
446 /// Invokes the xGetAssetMetadata operation on the simian server to retrieve metadata for an asset
447 /// This operation is generally used to determine if an asset exists in the database
448 /// </summary>
449 /// <param name="id"></param>
450 /// <returns></returns>
451 private AssetMetadata SimianGetMetadataOperation(string id)
452 {
453 try
454 {
455 NameValueCollection requestArgs = new NameValueCollection
456 {
457 { "RequestMethod", "xGetAssetMetadata" },
458 { "ID", id }
459 };
460
461 OSDMap response = SimianGrid.PostToService(m_serverUrl,requestArgs);
462 if (! response["Success"].AsBoolean())
463 {
464 // this is not really an error, this call is used to test existence
465 // m_log.DebugFormat("[SIMIAN ASSET CONNECTOR] Failed to get asset metadata; {0}",response["Message"].AsString());
466 return null;
467 }
468
469 AssetMetadata metadata = new AssetMetadata();
470 metadata.ID = id;
471 metadata.ContentType = response["ContentType"].AsString();
472 metadata.CreatorID = response["CreatorID"].AsString();
473 metadata.Local = false;
474 metadata.Temporary = response["Temporary"];
475
476 string lastModifiedStr = response["Last-Modified"].AsString();
477 if (! String.IsNullOrEmpty(lastModifiedStr))
478 {
479 DateTime lastModified;
480 if (DateTime.TryParse(lastModifiedStr, out lastModified))
481 metadata.CreationDate = lastModified;
482 }
483
484 return metadata;
485 }
486 catch (Exception ex)
487 {
488 m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: Failed to get asset metadata; {0}", ex.Message);
489 }
490
491 return null;
500 } 492 }
493#endregion
494
495 // private AssetMetadata GetRemoteMetadata(string id)
496 // {
497 // Uri url;
498 // AssetMetadata metadata = null;
499
500 // // Determine if id is an absolute URL or a grid-relative UUID
501 // if (!Uri.TryCreate(id, UriKind.Absolute, out url))
502 // url = new Uri(m_serverUrl + id);
503
504 // try
505 // {
506 // HttpWebRequest request = UntrustedHttpWebRequest.Create(url);
507 // request.Method = "HEAD";
508
509 // using (WebResponse response = request.GetResponse())
510 // {
511 // using (Stream responseStream = response.GetResponseStream())
512 // {
513 // // Create the metadata object
514 // metadata = new AssetMetadata();
515 // metadata.ContentType = response.ContentType;
516 // metadata.ID = id;
517
518 // UUID uuid;
519 // if (UUID.TryParse(id, out uuid))
520 // metadata.FullID = uuid;
521
522 // string lastModifiedStr = response.Headers.Get("Last-Modified");
523 // if (!String.IsNullOrEmpty(lastModifiedStr))
524 // {
525 // DateTime lastModified;
526 // if (DateTime.TryParse(lastModifiedStr, out lastModified))
527 // metadata.CreationDate = lastModified;
528 // }
529 // }
530 // }
531 // }
532 // catch (Exception ex)
533 // {
534 // m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset HEAD from " + url + " failed: " + ex.Message);
535 // }
536
537 // return metadata;
538 // }
539
540 // private AssetBase GetRemote(string id)
541 // {
542 // AssetBase asset = null;
543 // Uri url;
544
545 // // Determine if id is an absolute URL or a grid-relative UUID
546 // if (!Uri.TryCreate(id, UriKind.Absolute, out url))
547 // url = new Uri(m_serverUrl + id);
548
549 // try
550 // {
551 // HttpWebRequest request = UntrustedHttpWebRequest.Create(url);
552
553 // using (WebResponse response = request.GetResponse())
554 // {
555 // using (Stream responseStream = response.GetResponseStream())
556 // {
557 // string creatorID = response.Headers.GetOne("X-Asset-Creator-Id") ?? String.Empty;
558
559 // // Create the asset object
560 // asset = new AssetBase(id, String.Empty, SLUtil.ContentTypeToSLAssetType(response.ContentType), creatorID);
561
562 // UUID assetID;
563 // if (UUID.TryParse(id, out assetID))
564 // asset.FullID = assetID;
565
566 // // Grab the asset data from the response stream
567 // using (MemoryStream stream = new MemoryStream())
568 // {
569 // responseStream.CopyStream(stream, Int32.MaxValue);
570 // asset.Data = stream.ToArray();
571 // }
572 // }
573 // }
574
575 // // Cache store
576 // if (m_cache != null && asset != null)
577 // m_cache.Cache(asset);
578
579 // return asset;
580 // }
581 // catch (Exception ex)
582 // {
583 // m_log.Warn("[SIMIAN ASSET CONNECTOR]: Asset GET from " + url + " failed: " + ex.Message);
584 // return null;
585 // }
586 // }
587
588 // private string StoreRemote(AssetBase asset)
589 // {
590 // // Distinguish public and private assets
591 // bool isPublic = true;
592 // switch ((AssetType)asset.Type)
593 // {
594 // case AssetType.CallingCard:
595 // case AssetType.Gesture:
596 // case AssetType.LSLBytecode:
597 // case AssetType.LSLText:
598 // isPublic = false;
599 // break;
600 // }
601
602 // string errorMessage = null;
603
604 // // Build the remote storage request
605 // List<MultipartForm.Element> postParameters = new List<MultipartForm.Element>()
606 // {
607 // new MultipartForm.Parameter("AssetID", asset.FullID.ToString()),
608 // new MultipartForm.Parameter("CreatorID", asset.Metadata.CreatorID),
609 // new MultipartForm.Parameter("Temporary", asset.Temporary ? "1" : "0"),
610 // new MultipartForm.Parameter("Public", isPublic ? "1" : "0"),
611 // new MultipartForm.File("Asset", asset.Name, asset.Metadata.ContentType, asset.Data)
612 // };
613
614 // // Make the remote storage request
615 // try
616 // {
617 // // Simian does not require the asset ID to be in the URL because it's in the post data.
618 // // By appending it to the URL also, we allow caching proxies (squid) to invalidate asset URLs
619 // HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl + asset.FullID.ToString());
620
621 // using (HttpWebResponse response = MultipartForm.Post(request, postParameters))
622 // {
623 // using (Stream responseStream = response.GetResponseStream())
624 // {
625 // string responseStr = null;
626
627 // try
628 // {
629 // responseStr = responseStream.GetStreamString();
630 // OSD responseOSD = OSDParser.Deserialize(responseStr);
631 // if (responseOSD.Type == OSDType.Map)
632 // {
633 // OSDMap responseMap = (OSDMap)responseOSD;
634 // if (responseMap["Success"].AsBoolean())
635 // return asset.ID;
636 // else
637 // errorMessage = "Upload failed: " + responseMap["Message"].AsString();
638 // }
639 // else
640 // {
641 // errorMessage = "Response format was invalid:\n" + responseStr;
642 // }
643 // }
644 // catch (Exception ex)
645 // {
646 // if (!String.IsNullOrEmpty(responseStr))
647 // errorMessage = "Failed to parse the response:\n" + responseStr;
648 // else
649 // errorMessage = "Failed to retrieve the response: " + ex.Message;
650 // }
651 // }
652 // }
653 // }
654 // catch (WebException ex)
655 // {
656 // errorMessage = ex.Message;
657 // }
658
659 // m_log.WarnFormat("[SIMIAN ASSET CONNECTOR]: Failed to store asset \"{0}\" ({1}, {2}): {3}",
660 // asset.Name, asset.ID, asset.Metadata.ContentType, errorMessage);
661
662 // return null;
663 // }
501 } 664 }
502} 665}