clockwerk-opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 1 /*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27  
28 using log4net;
29 using System;
30 using System.Collections.Generic;
31 using System.IO;
32 using System.Reflection;
33 using Nini.Config;
34 using OpenSim.Framework;
35 using OpenSim.Framework.Console;
36 using OpenSim.Framework.Communications;
37 using OpenSim.Framework.Monitoring;
38 using OpenSim.Services.Interfaces;
39 using OpenSim.Server.Base;
40 using OpenMetaverse;
41  
42 namespace OpenSim.Services.Connectors
43 {
44 public class XInventoryServicesConnector : BaseServiceConnector, IInventoryService
45 {
46 private static readonly ILog m_log =
47 LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType);
49  
50 /// <summary>
51 /// Number of requests made to the remote inventory service.
52 /// </summary>
53 public int RequestsMade { get; private set; }
54  
55 private string m_ServerURI = String.Empty;
56  
57 /// <summary>
58 /// Timeout for remote requests.
59 /// </summary>
60 /// <remarks>
61 /// In this case, -1 is default timeout (100 seconds), not infinite.
62 /// </remarks>
63 private int m_requestTimeoutSecs = -1;
64  
65 public XInventoryServicesConnector()
66 {
67 }
68  
69 public XInventoryServicesConnector(string serverURI)
70 {
71 m_ServerURI = serverURI.TrimEnd('/');
72 }
73  
74 public XInventoryServicesConnector(IConfigSource source)
75 : base(source, "InventoryService")
76 {
77 Initialise(source);
78 }
79  
80 public virtual void Initialise(IConfigSource source)
81 {
82 IConfig config = source.Configs["InventoryService"];
83 if (config == null)
84 {
85 m_log.Error("[INVENTORY CONNECTOR]: InventoryService missing from OpenSim.ini");
86 throw new Exception("Inventory connector init error");
87 }
88  
89 string serviceURI = config.GetString("InventoryServerURI",
90 String.Empty);
91  
92 if (serviceURI == String.Empty)
93 {
94 m_log.Error("[INVENTORY CONNECTOR]: No Server URI named in section InventoryService");
95 throw new Exception("Inventory connector init error");
96 }
97 m_ServerURI = serviceURI;
98  
99 m_requestTimeoutSecs = config.GetInt("RemoteRequestTimeout", m_requestTimeoutSecs);
100  
101 StatsManager.RegisterStat(
102 new Stat(
103 "RequestsMade",
104 "Requests made",
105 "Number of requests made to the remove inventory service",
106 "requests",
107 "inventory",
108 serviceURI,
109 StatType.Pull,
110 MeasuresOfInterest.AverageChangeOverTime,
111 s => s.Value = RequestsMade,
112 StatVerbosity.Debug));
113 }
114  
115 private bool CheckReturn(Dictionary<string, object> ret)
116 {
117 if (ret == null)
118 return false;
119  
120 if (ret.Count == 0)
121 return false;
122  
123 if (ret.ContainsKey("RESULT"))
124 {
125 if (ret["RESULT"] is string)
126 {
127 bool result;
128  
129 if (bool.TryParse((string)ret["RESULT"], out result))
130 return result;
131  
132 return false;
133 }
134 }
135  
136 return true;
137 }
138  
139 public bool CreateUserInventory(UUID principalID)
140 {
141 Dictionary<string,object> ret = MakeRequest("CREATEUSERINVENTORY",
142 new Dictionary<string,object> {
143 { "PRINCIPAL", principalID.ToString() }
144 });
145  
146 return CheckReturn(ret);
147 }
148  
149 public List<InventoryFolderBase> GetInventorySkeleton(UUID principalID)
150 {
151 Dictionary<string,object> ret = MakeRequest("GETINVENTORYSKELETON",
152 new Dictionary<string,object> {
153 { "PRINCIPAL", principalID.ToString() }
154 });
155  
156 if (!CheckReturn(ret))
157 return null;
158  
159 Dictionary<string, object> folders = (Dictionary<string, object>)ret["FOLDERS"];
160  
161 List<InventoryFolderBase> fldrs = new List<InventoryFolderBase>();
162  
163 try
164 {
165 foreach (Object o in folders.Values)
166 fldrs.Add(BuildFolder((Dictionary<string, object>)o));
167 }
168 catch (Exception e)
169 {
170 m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception unwrapping folder list: ", e);
171 }
172  
173 return fldrs;
174 }
175  
176 public InventoryFolderBase GetRootFolder(UUID principalID)
177 {
178 Dictionary<string,object> ret = MakeRequest("GETROOTFOLDER",
179 new Dictionary<string,object> {
180 { "PRINCIPAL", principalID.ToString() }
181 });
182  
183 if (!CheckReturn(ret))
184 return null;
185  
186 return BuildFolder((Dictionary<string, object>)ret["folder"]);
187 }
188  
189 public InventoryFolderBase GetFolderForType(UUID principalID, AssetType type)
190 {
191 Dictionary<string,object> ret = MakeRequest("GETFOLDERFORTYPE",
192 new Dictionary<string,object> {
193 { "PRINCIPAL", principalID.ToString() },
194 { "TYPE", ((int)type).ToString() }
195 });
196  
197 if (!CheckReturn(ret))
198 return null;
199  
200 return BuildFolder((Dictionary<string, object>)ret["folder"]);
201 }
202  
203 public InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
204 {
205 InventoryCollection inventory = new InventoryCollection();
206 inventory.Folders = new List<InventoryFolderBase>();
207 inventory.Items = new List<InventoryItemBase>();
208 inventory.UserID = principalID;
209  
210 try
211 {
212 Dictionary<string,object> ret = MakeRequest("GETFOLDERCONTENT",
213 new Dictionary<string,object> {
214 { "PRINCIPAL", principalID.ToString() },
215 { "FOLDER", folderID.ToString() }
216 });
217  
218 if (!CheckReturn(ret))
219 return null;
220  
221 Dictionary<string,object> folders =
222 (Dictionary<string,object>)ret["FOLDERS"];
223 Dictionary<string,object> items =
224 (Dictionary<string,object>)ret["ITEMS"];
225  
226 foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i
227 inventory.Folders.Add(BuildFolder((Dictionary<string, object>)o));
228 foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
229 inventory.Items.Add(BuildItem((Dictionary<string, object>)o));
230 }
231 catch (Exception e)
232 {
233 m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetFolderContent: {0}", e.Message);
234 }
235  
236 return inventory;
237 }
238  
239 public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
240 {
241 Dictionary<string,object> ret = MakeRequest("GETFOLDERITEMS",
242 new Dictionary<string,object> {
243 { "PRINCIPAL", principalID.ToString() },
244 { "FOLDER", folderID.ToString() }
245 });
246  
247 if (!CheckReturn(ret))
248 return null;
249  
250 Dictionary<string, object> items = (Dictionary<string, object>)ret["ITEMS"];
251 List<InventoryItemBase> fitems = new List<InventoryItemBase>();
252 foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
253 fitems.Add(BuildItem((Dictionary<string, object>)o));
254  
255 return fitems;
256 }
257  
258 public bool AddFolder(InventoryFolderBase folder)
259 {
260 Dictionary<string,object> ret = MakeRequest("ADDFOLDER",
261 new Dictionary<string,object> {
262 { "ParentID", folder.ParentID.ToString() },
263 { "Type", folder.Type.ToString() },
264 { "Version", folder.Version.ToString() },
265 { "Name", folder.Name.ToString() },
266 { "Owner", folder.Owner.ToString() },
267 { "ID", folder.ID.ToString() }
268 });
269  
270 return CheckReturn(ret);
271 }
272  
273 public bool UpdateFolder(InventoryFolderBase folder)
274 {
275 Dictionary<string,object> ret = MakeRequest("UPDATEFOLDER",
276 new Dictionary<string,object> {
277 { "ParentID", folder.ParentID.ToString() },
278 { "Type", folder.Type.ToString() },
279 { "Version", folder.Version.ToString() },
280 { "Name", folder.Name.ToString() },
281 { "Owner", folder.Owner.ToString() },
282 { "ID", folder.ID.ToString() }
283 });
284  
285 return CheckReturn(ret);
286 }
287  
288 public bool MoveFolder(InventoryFolderBase folder)
289 {
290 Dictionary<string,object> ret = MakeRequest("MOVEFOLDER",
291 new Dictionary<string,object> {
292 { "ParentID", folder.ParentID.ToString() },
293 { "ID", folder.ID.ToString() },
294 { "PRINCIPAL", folder.Owner.ToString() }
295 });
296  
297 return CheckReturn(ret);
298 }
299  
300 public bool DeleteFolders(UUID principalID, List<UUID> folderIDs)
301 {
302 List<string> slist = new List<string>();
303  
304 foreach (UUID f in folderIDs)
305 slist.Add(f.ToString());
306  
307 Dictionary<string,object> ret = MakeRequest("DELETEFOLDERS",
308 new Dictionary<string,object> {
309 { "PRINCIPAL", principalID.ToString() },
310 { "FOLDERS", slist }
311 });
312  
313 return CheckReturn(ret);
314 }
315  
316 public bool PurgeFolder(InventoryFolderBase folder)
317 {
318 Dictionary<string,object> ret = MakeRequest("PURGEFOLDER",
319 new Dictionary<string,object> {
320 { "ID", folder.ID.ToString() }
321 });
322  
323 return CheckReturn(ret);
324 }
325  
326 public bool AddItem(InventoryItemBase item)
327 {
328 if (item.CreatorData == null)
329 item.CreatorData = String.Empty;
330 Dictionary<string,object> ret = MakeRequest("ADDITEM",
331 new Dictionary<string,object> {
332 { "AssetID", item.AssetID.ToString() },
333 { "AssetType", item.AssetType.ToString() },
334 { "Name", item.Name.ToString() },
335 { "Owner", item.Owner.ToString() },
336 { "ID", item.ID.ToString() },
337 { "InvType", item.InvType.ToString() },
338 { "Folder", item.Folder.ToString() },
339 { "CreatorId", item.CreatorId.ToString() },
340 { "CreatorData", item.CreatorData.ToString() },
341 { "Description", item.Description.ToString() },
342 { "NextPermissions", item.NextPermissions.ToString() },
343 { "CurrentPermissions", item.CurrentPermissions.ToString() },
344 { "BasePermissions", item.BasePermissions.ToString() },
345 { "EveryOnePermissions", item.EveryOnePermissions.ToString() },
346 { "GroupPermissions", item.GroupPermissions.ToString() },
347 { "GroupID", item.GroupID.ToString() },
348 { "GroupOwned", item.GroupOwned.ToString() },
349 { "SalePrice", item.SalePrice.ToString() },
350 { "SaleType", item.SaleType.ToString() },
351 { "Flags", item.Flags.ToString() },
352 { "CreationDate", item.CreationDate.ToString() }
353 });
354  
355 return CheckReturn(ret);
356 }
357  
358 public bool UpdateItem(InventoryItemBase item)
359 {
360 if (item.CreatorData == null)
361 item.CreatorData = String.Empty;
362 Dictionary<string,object> ret = MakeRequest("UPDATEITEM",
363 new Dictionary<string,object> {
364 { "AssetID", item.AssetID.ToString() },
365 { "AssetType", item.AssetType.ToString() },
366 { "Name", item.Name.ToString() },
367 { "Owner", item.Owner.ToString() },
368 { "ID", item.ID.ToString() },
369 { "InvType", item.InvType.ToString() },
370 { "Folder", item.Folder.ToString() },
371 { "CreatorId", item.CreatorId.ToString() },
372 { "CreatorData", item.CreatorData.ToString() },
373 { "Description", item.Description.ToString() },
374 { "NextPermissions", item.NextPermissions.ToString() },
375 { "CurrentPermissions", item.CurrentPermissions.ToString() },
376 { "BasePermissions", item.BasePermissions.ToString() },
377 { "EveryOnePermissions", item.EveryOnePermissions.ToString() },
378 { "GroupPermissions", item.GroupPermissions.ToString() },
379 { "GroupID", item.GroupID.ToString() },
380 { "GroupOwned", item.GroupOwned.ToString() },
381 { "SalePrice", item.SalePrice.ToString() },
382 { "SaleType", item.SaleType.ToString() },
383 { "Flags", item.Flags.ToString() },
384 { "CreationDate", item.CreationDate.ToString() }
385 });
386  
387 return CheckReturn(ret);
388 }
389  
390 public bool MoveItems(UUID principalID, List<InventoryItemBase> items)
391 {
392 List<string> idlist = new List<string>();
393 List<string> destlist = new List<string>();
394  
395 foreach (InventoryItemBase item in items)
396 {
397 idlist.Add(item.ID.ToString());
398 destlist.Add(item.Folder.ToString());
399 }
400  
401 Dictionary<string,object> ret = MakeRequest("MOVEITEMS",
402 new Dictionary<string,object> {
403 { "PRINCIPAL", principalID.ToString() },
404 { "IDLIST", idlist },
405 { "DESTLIST", destlist }
406 });
407  
408 return CheckReturn(ret);
409 }
410  
411 public bool DeleteItems(UUID principalID, List<UUID> itemIDs)
412 {
413 List<string> slist = new List<string>();
414  
415 foreach (UUID f in itemIDs)
416 slist.Add(f.ToString());
417  
418 Dictionary<string,object> ret = MakeRequest("DELETEITEMS",
419 new Dictionary<string,object> {
420 { "PRINCIPAL", principalID.ToString() },
421 { "ITEMS", slist }
422 });
423  
424 return CheckReturn(ret);
425 }
426  
427 public InventoryItemBase GetItem(InventoryItemBase item)
428 {
429 try
430 {
431 Dictionary<string, object> ret = MakeRequest("GETITEM",
432 new Dictionary<string, object> {
433 { "ID", item.ID.ToString() }
434 });
435  
436 if (!CheckReturn(ret))
437 return null;
438  
439 return BuildItem((Dictionary<string, object>)ret["item"]);
440 }
441 catch (Exception e)
442 {
443 m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetItem: ", e);
444 }
445  
446 return null;
447 }
448  
449 public InventoryFolderBase GetFolder(InventoryFolderBase folder)
450 {
451 try
452 {
453 Dictionary<string, object> ret = MakeRequest("GETFOLDER",
454 new Dictionary<string, object> {
455 { "ID", folder.ID.ToString() }
456 });
457  
458 if (!CheckReturn(ret))
459 return null;
460  
461 return BuildFolder((Dictionary<string, object>)ret["folder"]);
462 }
463 catch (Exception e)
464 {
465 m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetFolder: ", e);
466 }
467  
468 return null;
469 }
470  
471 public List<InventoryItemBase> GetActiveGestures(UUID principalID)
472 {
473 Dictionary<string,object> ret = MakeRequest("GETACTIVEGESTURES",
474 new Dictionary<string,object> {
475 { "PRINCIPAL", principalID.ToString() }
476 });
477  
478 if (!CheckReturn(ret))
479 return null;
480  
481 List<InventoryItemBase> items = new List<InventoryItemBase>();
482  
483 foreach (Object o in ((Dictionary<string,object>)ret["ITEMS"]).Values)
484 items.Add(BuildItem((Dictionary<string, object>)o));
485  
486 return items;
487 }
488  
489 public int GetAssetPermissions(UUID principalID, UUID assetID)
490 {
491 Dictionary<string,object> ret = MakeRequest("GETASSETPERMISSIONS",
492 new Dictionary<string,object> {
493 { "PRINCIPAL", principalID.ToString() },
494 { "ASSET", assetID.ToString() }
495 });
496  
497 // We cannot use CheckReturn() here because valid values for RESULT are "false" (in the case of request failure) or an int
498 if (ret == null)
499 return 0;
500  
501 if (ret.ContainsKey("RESULT"))
502 {
503 if (ret["RESULT"] is string)
504 {
505 int intResult;
506  
507 if (int.TryParse ((string)ret["RESULT"], out intResult))
508 return intResult;
509 }
510 }
511  
512 return 0;
513 }
514  
515 public bool HasInventoryForUser(UUID principalID)
516 {
517 return false;
518 }
519  
520 // Helpers
521 //
522 private Dictionary<string,object> MakeRequest(string method,
523 Dictionary<string,object> sendData)
524 {
525 // Add "METHOD" as the first key in the dictionary. This ensures that it will be
526 // visible even when using partial logging ("debug http all 5").
527 Dictionary<string, object> temp = sendData;
528 sendData = new Dictionary<string,object>{ { "METHOD", method } };
529 foreach (KeyValuePair<string, object> kvp in temp)
530 sendData.Add(kvp.Key, kvp.Value);
531  
532 RequestsMade++;
533  
534 string reply
535 = SynchronousRestFormsRequester.MakeRequest(
536 "POST", m_ServerURI + "/xinventory",
537 ServerUtils.BuildQueryString(sendData), m_requestTimeoutSecs, m_Auth);
538  
539 Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
540 reply);
541  
542 return replyData;
543 }
544  
545 private InventoryFolderBase BuildFolder(Dictionary<string,object> data)
546 {
547 InventoryFolderBase folder = new InventoryFolderBase();
548  
549 try
550 {
551 folder.ParentID = new UUID(data["ParentID"].ToString());
552 folder.Type = short.Parse(data["Type"].ToString());
553 folder.Version = ushort.Parse(data["Version"].ToString());
554 folder.Name = data["Name"].ToString();
555 folder.Owner = new UUID(data["Owner"].ToString());
556 folder.ID = new UUID(data["ID"].ToString());
557 }
558 catch (Exception e)
559 {
560 m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception building folder: ", e);
561 }
562  
563 return folder;
564 }
565  
566 private InventoryItemBase BuildItem(Dictionary<string,object> data)
567 {
568 InventoryItemBase item = new InventoryItemBase();
569  
570 try
571 {
572 item.AssetID = new UUID(data["AssetID"].ToString());
573 item.AssetType = int.Parse(data["AssetType"].ToString());
574 item.Name = data["Name"].ToString();
575 item.Owner = new UUID(data["Owner"].ToString());
576 item.ID = new UUID(data["ID"].ToString());
577 item.InvType = int.Parse(data["InvType"].ToString());
578 item.Folder = new UUID(data["Folder"].ToString());
579 item.CreatorId = data["CreatorId"].ToString();
580 if (data.ContainsKey("CreatorData"))
581 item.CreatorData = data["CreatorData"].ToString();
582 else
583 item.CreatorData = String.Empty;
584 item.Description = data["Description"].ToString();
585 item.NextPermissions = uint.Parse(data["NextPermissions"].ToString());
586 item.CurrentPermissions = uint.Parse(data["CurrentPermissions"].ToString());
587 item.BasePermissions = uint.Parse(data["BasePermissions"].ToString());
588 item.EveryOnePermissions = uint.Parse(data["EveryOnePermissions"].ToString());
589 item.GroupPermissions = uint.Parse(data["GroupPermissions"].ToString());
590 item.GroupID = new UUID(data["GroupID"].ToString());
591 item.GroupOwned = bool.Parse(data["GroupOwned"].ToString());
592 item.SalePrice = int.Parse(data["SalePrice"].ToString());
593 item.SaleType = byte.Parse(data["SaleType"].ToString());
594 item.Flags = uint.Parse(data["Flags"].ToString());
595 item.CreationDate = int.Parse(data["CreationDate"].ToString());
596 }
597 catch (Exception e)
598 {
599 m_log.Error("[XINVENTORY CONNECTOR]: Exception building item: ", e);
600 }
601  
602 return item;
603 }
604 }
605 }