XInventoryServicesConnector.cs 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  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. using log4net;
  28. using System;
  29. using System.Collections.Generic;
  30. using System.IO;
  31. using System.Reflection;
  32. using Nini.Config;
  33. using OpenSim.Framework;
  34. using OpenSim.Framework.Console;
  35. using OpenSim.Framework.Monitoring;
  36. using OpenSim.Services.Interfaces;
  37. using OpenSim.Server.Base;
  38. using OpenMetaverse;
  39. namespace OpenSim.Services.Connectors
  40. {
  41. public class XInventoryServicesConnector : BaseServiceConnector, IInventoryService
  42. {
  43. private static readonly ILog m_log =
  44. LogManager.GetLogger(
  45. MethodBase.GetCurrentMethod().DeclaringType);
  46. /// <summary>
  47. /// Number of requests made to the remote inventory service.
  48. /// </summary>
  49. public int RequestsMade { get; private set; }
  50. private string m_ServerURI = String.Empty;
  51. /// <summary>
  52. /// Timeout for remote requests.
  53. /// </summary>
  54. /// <remarks>
  55. /// In this case, -1 is default timeout (100 seconds), not infinite.
  56. /// </remarks>
  57. private int m_requestTimeoutSecs = -1;
  58. private const double CACHE_EXPIRATION_SECONDS = 20.0;
  59. private static ExpiringCache<UUID, InventoryItemBase> m_ItemCache = new ExpiringCache<UUID,InventoryItemBase>();
  60. public XInventoryServicesConnector()
  61. {
  62. }
  63. public XInventoryServicesConnector(string serverURI)
  64. {
  65. m_ServerURI = serverURI.TrimEnd('/');
  66. }
  67. public XInventoryServicesConnector(IConfigSource source)
  68. : base(source, "InventoryService")
  69. {
  70. Initialise(source);
  71. }
  72. public virtual void Initialise(IConfigSource source)
  73. {
  74. IConfig config = source.Configs["InventoryService"];
  75. if (config == null)
  76. {
  77. m_log.Error("[INVENTORY CONNECTOR]: InventoryService missing from OpenSim.ini");
  78. throw new Exception("Inventory connector init error");
  79. }
  80. string serviceURI = config.GetString("InventoryServerURI",
  81. String.Empty);
  82. if (serviceURI == String.Empty)
  83. {
  84. m_log.Error("[INVENTORY CONNECTOR]: No Server URI named in section InventoryService");
  85. throw new Exception("Inventory connector init error");
  86. }
  87. m_ServerURI = serviceURI;
  88. m_requestTimeoutSecs = config.GetInt("RemoteRequestTimeout", m_requestTimeoutSecs);
  89. StatsManager.RegisterStat(
  90. new Stat(
  91. "RequestsMade",
  92. "Requests made",
  93. "Number of requests made to the remove inventory service",
  94. "requests",
  95. "inventory",
  96. serviceURI,
  97. StatType.Pull,
  98. MeasuresOfInterest.AverageChangeOverTime,
  99. s => s.Value = RequestsMade,
  100. StatVerbosity.Debug));
  101. }
  102. private bool CheckReturn(Dictionary<string, object> ret)
  103. {
  104. if (ret == null)
  105. return false;
  106. if (ret.Count == 0)
  107. return false;
  108. if (ret.ContainsKey("RESULT"))
  109. {
  110. if (ret["RESULT"] is string)
  111. {
  112. bool result;
  113. if (bool.TryParse((string)ret["RESULT"], out result))
  114. return result;
  115. return false;
  116. }
  117. }
  118. return true;
  119. }
  120. public bool CreateUserInventory(UUID principalID)
  121. {
  122. Dictionary<string,object> ret = MakeRequest("CREATEUSERINVENTORY",
  123. new Dictionary<string,object> {
  124. { "PRINCIPAL", principalID.ToString() }
  125. });
  126. return CheckReturn(ret);
  127. }
  128. public List<InventoryFolderBase> GetInventorySkeleton(UUID principalID)
  129. {
  130. Dictionary<string,object> ret = MakeRequest("GETINVENTORYSKELETON",
  131. new Dictionary<string,object> {
  132. { "PRINCIPAL", principalID.ToString() }
  133. });
  134. if (!CheckReturn(ret))
  135. return null;
  136. Dictionary<string, object> folders = (Dictionary<string, object>)ret["FOLDERS"];
  137. List<InventoryFolderBase> fldrs = new List<InventoryFolderBase>();
  138. try
  139. {
  140. foreach (Object o in folders.Values)
  141. fldrs.Add(BuildFolder((Dictionary<string, object>)o));
  142. }
  143. catch (Exception e)
  144. {
  145. m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception unwrapping folder list: ", e);
  146. }
  147. return fldrs;
  148. }
  149. public InventoryFolderBase GetRootFolder(UUID principalID)
  150. {
  151. Dictionary<string,object> ret = MakeRequest("GETROOTFOLDER",
  152. new Dictionary<string,object> {
  153. { "PRINCIPAL", principalID.ToString() }
  154. });
  155. if (!CheckReturn(ret))
  156. return null;
  157. return BuildFolder((Dictionary<string, object>)ret["folder"]);
  158. }
  159. public InventoryFolderBase GetFolderForType(UUID principalID, FolderType type)
  160. {
  161. Dictionary<string,object> ret = MakeRequest("GETFOLDERFORTYPE",
  162. new Dictionary<string,object> {
  163. { "PRINCIPAL", principalID.ToString() },
  164. { "TYPE", ((int)type).ToString() }
  165. });
  166. if (!CheckReturn(ret))
  167. return null;
  168. return BuildFolder((Dictionary<string, object>)ret["folder"]);
  169. }
  170. public InventoryCollection GetFolderContent(UUID principalID, UUID folderID)
  171. {
  172. InventoryCollection inventory = new InventoryCollection();
  173. inventory.Folders = new List<InventoryFolderBase>();
  174. inventory.Items = new List<InventoryItemBase>();
  175. inventory.OwnerID = principalID;
  176. try
  177. {
  178. Dictionary<string,object> ret = MakeRequest("GETFOLDERCONTENT",
  179. new Dictionary<string,object> {
  180. { "PRINCIPAL", principalID.ToString() },
  181. { "FOLDER", folderID.ToString() }
  182. });
  183. if (!CheckReturn(ret))
  184. return null;
  185. Dictionary<string,object> folders = ret.ContainsKey("FOLDERS") ?
  186. (Dictionary<string,object>)ret["FOLDERS"] : null;
  187. Dictionary<string,object> items = ret.ContainsKey("ITEMS") ?
  188. (Dictionary<string, object>)ret["ITEMS"] : null;
  189. if (folders != null)
  190. foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i
  191. inventory.Folders.Add(BuildFolder((Dictionary<string, object>)o));
  192. if (items != null)
  193. foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
  194. inventory.Items.Add(BuildItem((Dictionary<string, object>)o));
  195. }
  196. catch (Exception e)
  197. {
  198. m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetFolderContent: {0}", e.Message);
  199. }
  200. return inventory;
  201. }
  202. public virtual InventoryCollection[] GetMultipleFoldersContent(UUID principalID, UUID[] folderIDs)
  203. {
  204. InventoryCollection[] inventoryArr = new InventoryCollection[folderIDs.Length];
  205. // m_log.DebugFormat("[XXX]: In GetMultipleFoldersContent {0}", String.Join(",", folderIDs));
  206. try
  207. {
  208. Dictionary<string, object> resultSet = MakeRequest("GETMULTIPLEFOLDERSCONTENT",
  209. new Dictionary<string, object> {
  210. { "PRINCIPAL", principalID.ToString() },
  211. { "FOLDERS", String.Join(",", folderIDs) },
  212. { "COUNT", folderIDs.Length.ToString() }
  213. });
  214. if (!CheckReturn(resultSet))
  215. return null;
  216. int i = 0;
  217. foreach (KeyValuePair<string, object> kvp in resultSet)
  218. {
  219. InventoryCollection inventory = new InventoryCollection();
  220. if (kvp.Key.StartsWith("F_"))
  221. {
  222. UUID fid = UUID.Zero;
  223. if (UUID.TryParse(kvp.Key.Substring(2), out fid) && fid == folderIDs[i])
  224. {
  225. inventory.Folders = new List<InventoryFolderBase>();
  226. inventory.Items = new List<InventoryItemBase>();
  227. Dictionary<string, object> ret = (Dictionary<string, object>)kvp.Value;
  228. if (ret.ContainsKey("FID"))
  229. {
  230. if (!UUID.TryParse(ret["FID"].ToString(), out inventory.FolderID))
  231. m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Could not parse folder id {0}", ret["FID"].ToString());
  232. }
  233. else
  234. m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: FID key not present in response");
  235. inventory.Version = -1;
  236. if (ret.ContainsKey("VERSION"))
  237. Int32.TryParse(ret["VERSION"].ToString(), out inventory.Version);
  238. if (ret.ContainsKey("OWNER"))
  239. UUID.TryParse(ret["OWNER"].ToString(), out inventory.OwnerID);
  240. //m_log.DebugFormat("[XXX]: Received {0} ({1}) {2} {3}", inventory.FolderID, fid, inventory.Version, inventory.OwnerID);
  241. Dictionary<string, object> folders =
  242. (Dictionary<string, object>)ret["FOLDERS"];
  243. Dictionary<string, object> items =
  244. (Dictionary<string, object>)ret["ITEMS"];
  245. foreach (Object o in folders.Values) // getting the values directly, we don't care about the keys folder_i
  246. {
  247. inventory.Folders.Add(BuildFolder((Dictionary<string, object>)o));
  248. }
  249. foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
  250. {
  251. inventory.Items.Add(BuildItem((Dictionary<string, object>)o));
  252. }
  253. inventoryArr[i] = inventory;
  254. }
  255. else
  256. {
  257. m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Folder id does not match. Expected {0} got {1}",
  258. folderIDs[i], fid);
  259. m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: {0} {1}", String.Join(",", folderIDs), String.Join(",", resultSet.Keys));
  260. }
  261. i += 1;
  262. }
  263. }
  264. }
  265. catch (Exception e)
  266. {
  267. m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetMultipleFoldersContent: {0}", e.Message);
  268. }
  269. return inventoryArr;
  270. }
  271. public List<InventoryItemBase> GetFolderItems(UUID principalID, UUID folderID)
  272. {
  273. Dictionary<string,object> ret = MakeRequest("GETFOLDERITEMS",
  274. new Dictionary<string,object> {
  275. { "PRINCIPAL", principalID.ToString() },
  276. { "FOLDER", folderID.ToString() }
  277. });
  278. if (!CheckReturn(ret))
  279. return null;
  280. Dictionary<string, object> items = (Dictionary<string, object>)ret["ITEMS"];
  281. List<InventoryItemBase> fitems = new List<InventoryItemBase>();
  282. foreach (Object o in items.Values) // getting the values directly, we don't care about the keys item_i
  283. fitems.Add(BuildItem((Dictionary<string, object>)o));
  284. return fitems;
  285. }
  286. public bool AddFolder(InventoryFolderBase folder)
  287. {
  288. Dictionary<string,object> ret = MakeRequest("ADDFOLDER",
  289. new Dictionary<string,object> {
  290. { "ParentID", folder.ParentID.ToString() },
  291. { "Type", folder.Type.ToString() },
  292. { "Version", folder.Version.ToString() },
  293. { "Name", folder.Name.ToString() },
  294. { "Owner", folder.Owner.ToString() },
  295. { "ID", folder.ID.ToString() }
  296. });
  297. return CheckReturn(ret);
  298. }
  299. public bool UpdateFolder(InventoryFolderBase folder)
  300. {
  301. Dictionary<string,object> ret = MakeRequest("UPDATEFOLDER",
  302. new Dictionary<string,object> {
  303. { "ParentID", folder.ParentID.ToString() },
  304. { "Type", folder.Type.ToString() },
  305. { "Version", folder.Version.ToString() },
  306. { "Name", folder.Name.ToString() },
  307. { "Owner", folder.Owner.ToString() },
  308. { "ID", folder.ID.ToString() }
  309. });
  310. return CheckReturn(ret);
  311. }
  312. public bool MoveFolder(InventoryFolderBase folder)
  313. {
  314. Dictionary<string,object> ret = MakeRequest("MOVEFOLDER",
  315. new Dictionary<string,object> {
  316. { "ParentID", folder.ParentID.ToString() },
  317. { "ID", folder.ID.ToString() },
  318. { "PRINCIPAL", folder.Owner.ToString() }
  319. });
  320. return CheckReturn(ret);
  321. }
  322. public bool DeleteFolders(UUID principalID, List<UUID> folderIDs)
  323. {
  324. List<string> slist = new List<string>();
  325. foreach (UUID f in folderIDs)
  326. slist.Add(f.ToString());
  327. Dictionary<string,object> ret = MakeRequest("DELETEFOLDERS",
  328. new Dictionary<string,object> {
  329. { "PRINCIPAL", principalID.ToString() },
  330. { "FOLDERS", slist }
  331. });
  332. return CheckReturn(ret);
  333. }
  334. public bool PurgeFolder(InventoryFolderBase folder)
  335. {
  336. Dictionary<string,object> ret = MakeRequest("PURGEFOLDER",
  337. new Dictionary<string,object> {
  338. { "ID", folder.ID.ToString() }
  339. });
  340. return CheckReturn(ret);
  341. }
  342. public bool AddItem(InventoryItemBase item)
  343. {
  344. if (item.Description == null)
  345. item.Description = String.Empty;
  346. if (item.CreatorData == null)
  347. item.CreatorData = String.Empty;
  348. if (item.CreatorId == null)
  349. item.CreatorId = String.Empty;
  350. Dictionary<string, object> ret = MakeRequest("ADDITEM",
  351. new Dictionary<string,object> {
  352. { "AssetID", item.AssetID.ToString() },
  353. { "AssetType", item.AssetType.ToString() },
  354. { "Name", item.Name.ToString() },
  355. { "Owner", item.Owner.ToString() },
  356. { "ID", item.ID.ToString() },
  357. { "InvType", item.InvType.ToString() },
  358. { "Folder", item.Folder.ToString() },
  359. { "CreatorId", item.CreatorId.ToString() },
  360. { "CreatorData", item.CreatorData.ToString() },
  361. { "Description", item.Description.ToString() },
  362. { "NextPermissions", item.NextPermissions.ToString() },
  363. { "CurrentPermissions", item.CurrentPermissions.ToString() },
  364. { "BasePermissions", item.BasePermissions.ToString() },
  365. { "EveryOnePermissions", item.EveryOnePermissions.ToString() },
  366. { "GroupPermissions", item.GroupPermissions.ToString() },
  367. { "GroupID", item.GroupID.ToString() },
  368. { "GroupOwned", item.GroupOwned.ToString() },
  369. { "SalePrice", item.SalePrice.ToString() },
  370. { "SaleType", item.SaleType.ToString() },
  371. { "Flags", item.Flags.ToString() },
  372. { "CreationDate", item.CreationDate.ToString() }
  373. });
  374. return CheckReturn(ret);
  375. }
  376. public bool UpdateItem(InventoryItemBase item)
  377. {
  378. if (item.CreatorData == null)
  379. item.CreatorData = String.Empty;
  380. Dictionary<string,object> ret = MakeRequest("UPDATEITEM",
  381. new Dictionary<string,object> {
  382. { "AssetID", item.AssetID.ToString() },
  383. { "AssetType", item.AssetType.ToString() },
  384. { "Name", item.Name.ToString() },
  385. { "Owner", item.Owner.ToString() },
  386. { "ID", item.ID.ToString() },
  387. { "InvType", item.InvType.ToString() },
  388. { "Folder", item.Folder.ToString() },
  389. { "CreatorId", item.CreatorId.ToString() },
  390. { "CreatorData", item.CreatorData.ToString() },
  391. { "Description", item.Description.ToString() },
  392. { "NextPermissions", item.NextPermissions.ToString() },
  393. { "CurrentPermissions", item.CurrentPermissions.ToString() },
  394. { "BasePermissions", item.BasePermissions.ToString() },
  395. { "EveryOnePermissions", item.EveryOnePermissions.ToString() },
  396. { "GroupPermissions", item.GroupPermissions.ToString() },
  397. { "GroupID", item.GroupID.ToString() },
  398. { "GroupOwned", item.GroupOwned.ToString() },
  399. { "SalePrice", item.SalePrice.ToString() },
  400. { "SaleType", item.SaleType.ToString() },
  401. { "Flags", item.Flags.ToString() },
  402. { "CreationDate", item.CreationDate.ToString() }
  403. });
  404. bool result = CheckReturn(ret);
  405. if (result)
  406. {
  407. m_ItemCache.AddOrUpdate(item.ID, item, CACHE_EXPIRATION_SECONDS);
  408. }
  409. return result;
  410. }
  411. public bool MoveItems(UUID principalID, List<InventoryItemBase> items)
  412. {
  413. List<string> idlist = new List<string>();
  414. List<string> destlist = new List<string>();
  415. foreach (InventoryItemBase item in items)
  416. {
  417. idlist.Add(item.ID.ToString());
  418. destlist.Add(item.Folder.ToString());
  419. }
  420. Dictionary<string,object> ret = MakeRequest("MOVEITEMS",
  421. new Dictionary<string,object> {
  422. { "PRINCIPAL", principalID.ToString() },
  423. { "IDLIST", idlist },
  424. { "DESTLIST", destlist }
  425. });
  426. return CheckReturn(ret);
  427. }
  428. public bool DeleteItems(UUID principalID, List<UUID> itemIDs)
  429. {
  430. List<string> slist = new List<string>();
  431. foreach (UUID f in itemIDs)
  432. slist.Add(f.ToString());
  433. Dictionary<string,object> ret = MakeRequest("DELETEITEMS",
  434. new Dictionary<string,object> {
  435. { "PRINCIPAL", principalID.ToString() },
  436. { "ITEMS", slist }
  437. });
  438. return CheckReturn(ret);
  439. }
  440. public InventoryItemBase GetItem(InventoryItemBase item)
  441. {
  442. InventoryItemBase retrieved = null;
  443. if (m_ItemCache.TryGetValue(item.ID, out retrieved))
  444. return retrieved;
  445. try
  446. {
  447. Dictionary<string, object> ret = MakeRequest("GETITEM",
  448. new Dictionary<string, object> {
  449. { "ID", item.ID.ToString() }
  450. });
  451. if (!CheckReturn(ret))
  452. return null;
  453. retrieved = BuildItem((Dictionary<string, object>)ret["item"]);
  454. }
  455. catch (Exception e)
  456. {
  457. m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetItem: ", e);
  458. }
  459. m_ItemCache.AddOrUpdate(item.ID, retrieved, CACHE_EXPIRATION_SECONDS);
  460. return retrieved;
  461. }
  462. public virtual InventoryItemBase[] GetMultipleItems(UUID principalID, UUID[] itemIDs)
  463. {
  464. //m_log.DebugFormat("[XXX]: In GetMultipleItems {0}", String.Join(",", itemIDs));
  465. InventoryItemBase[] itemArr = new InventoryItemBase[itemIDs.Length];
  466. // Try to get them from the cache
  467. List<UUID> pending = new List<UUID>();
  468. InventoryItemBase item = null;
  469. int i = 0;
  470. foreach (UUID id in itemIDs)
  471. {
  472. if (m_ItemCache.TryGetValue(id, out item))
  473. itemArr[i++] = item;
  474. else
  475. pending.Add(id);
  476. }
  477. if (pending.Count == 0) // we're done, everything was in the cache
  478. return itemArr;
  479. try
  480. {
  481. Dictionary<string, object> resultSet = MakeRequest("GETMULTIPLEITEMS",
  482. new Dictionary<string, object> {
  483. { "PRINCIPAL", principalID.ToString() },
  484. { "ITEMS", String.Join(",", pending.ToArray()) },
  485. { "COUNT", pending.Count.ToString() }
  486. });
  487. if (!CheckReturn(resultSet))
  488. {
  489. if (i == 0)
  490. return null;
  491. else
  492. return itemArr;
  493. }
  494. // carry over index i where we left above
  495. foreach (KeyValuePair<string, object> kvp in resultSet)
  496. {
  497. InventoryCollection inventory = new InventoryCollection();
  498. if (kvp.Key.StartsWith("item_"))
  499. {
  500. if (kvp.Value is Dictionary<string, object>)
  501. {
  502. item = BuildItem((Dictionary<string, object>)kvp.Value);
  503. m_ItemCache.AddOrUpdate(item.ID, item, CACHE_EXPIRATION_SECONDS);
  504. itemArr[i++] = item;
  505. }
  506. else
  507. itemArr[i++] = null;
  508. }
  509. }
  510. }
  511. catch (Exception e)
  512. {
  513. m_log.WarnFormat("[XINVENTORY SERVICES CONNECTOR]: Exception in GetMultipleItems: {0}", e.Message);
  514. }
  515. return itemArr;
  516. }
  517. public InventoryFolderBase GetFolder(InventoryFolderBase folder)
  518. {
  519. try
  520. {
  521. Dictionary<string, object> ret = MakeRequest("GETFOLDER",
  522. new Dictionary<string, object> {
  523. { "ID", folder.ID.ToString() }
  524. });
  525. if (!CheckReturn(ret))
  526. return null;
  527. return BuildFolder((Dictionary<string, object>)ret["folder"]);
  528. }
  529. catch (Exception e)
  530. {
  531. m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception in GetFolder: ", e);
  532. }
  533. return null;
  534. }
  535. public List<InventoryItemBase> GetActiveGestures(UUID principalID)
  536. {
  537. Dictionary<string,object> ret = MakeRequest("GETACTIVEGESTURES",
  538. new Dictionary<string,object> {
  539. { "PRINCIPAL", principalID.ToString() }
  540. });
  541. if (!CheckReturn(ret))
  542. return null;
  543. List<InventoryItemBase> items = new List<InventoryItemBase>();
  544. foreach (Object o in ((Dictionary<string,object>)ret["ITEMS"]).Values)
  545. items.Add(BuildItem((Dictionary<string, object>)o));
  546. return items;
  547. }
  548. public int GetAssetPermissions(UUID principalID, UUID assetID)
  549. {
  550. Dictionary<string,object> ret = MakeRequest("GETASSETPERMISSIONS",
  551. new Dictionary<string,object> {
  552. { "PRINCIPAL", principalID.ToString() },
  553. { "ASSET", assetID.ToString() }
  554. });
  555. // We cannot use CheckReturn() here because valid values for RESULT are "false" (in the case of request failure) or an int
  556. if (ret == null)
  557. return 0;
  558. if (ret.ContainsKey("RESULT"))
  559. {
  560. if (ret["RESULT"] is string)
  561. {
  562. int intResult;
  563. if (int.TryParse ((string)ret["RESULT"], out intResult))
  564. return intResult;
  565. }
  566. }
  567. return 0;
  568. }
  569. public bool HasInventoryForUser(UUID principalID)
  570. {
  571. return false;
  572. }
  573. // Helpers
  574. //
  575. private Dictionary<string,object> MakeRequest(string method,
  576. Dictionary<string,object> sendData)
  577. {
  578. // Add "METHOD" as the first key in the dictionary. This ensures that it will be
  579. // visible even when using partial logging ("debug http all 5").
  580. Dictionary<string, object> temp = sendData;
  581. sendData = new Dictionary<string,object>{ { "METHOD", method } };
  582. foreach (KeyValuePair<string, object> kvp in temp)
  583. sendData.Add(kvp.Key, kvp.Value);
  584. RequestsMade++;
  585. string reply
  586. = SynchronousRestFormsRequester.MakeRequest(
  587. "POST", m_ServerURI + "/xinventory",
  588. ServerUtils.BuildQueryString(sendData), m_requestTimeoutSecs, m_Auth);
  589. Dictionary<string, object> replyData = ServerUtils.ParseXmlResponse(
  590. reply);
  591. return replyData;
  592. }
  593. private InventoryFolderBase BuildFolder(Dictionary<string,object> data)
  594. {
  595. InventoryFolderBase folder = new InventoryFolderBase();
  596. try
  597. {
  598. folder.ParentID = new UUID(data["ParentID"].ToString());
  599. folder.Type = short.Parse(data["Type"].ToString());
  600. folder.Version = ushort.Parse(data["Version"].ToString());
  601. folder.Name = data["Name"].ToString();
  602. folder.Owner = new UUID(data["Owner"].ToString());
  603. folder.ID = new UUID(data["ID"].ToString());
  604. }
  605. catch (Exception e)
  606. {
  607. m_log.Error("[XINVENTORY SERVICES CONNECTOR]: Exception building folder: ", e);
  608. }
  609. return folder;
  610. }
  611. private InventoryItemBase BuildItem(Dictionary<string,object> data)
  612. {
  613. InventoryItemBase item = new InventoryItemBase();
  614. try
  615. {
  616. item.AssetID = new UUID(data["AssetID"].ToString());
  617. item.AssetType = int.Parse(data["AssetType"].ToString());
  618. item.Name = data["Name"].ToString();
  619. item.Owner = new UUID(data["Owner"].ToString());
  620. item.ID = new UUID(data["ID"].ToString());
  621. item.InvType = int.Parse(data["InvType"].ToString());
  622. item.Folder = new UUID(data["Folder"].ToString());
  623. item.CreatorId = data["CreatorId"].ToString();
  624. if (data.ContainsKey("CreatorData"))
  625. item.CreatorData = data["CreatorData"].ToString();
  626. else
  627. item.CreatorData = String.Empty;
  628. item.Description = data["Description"].ToString();
  629. item.NextPermissions = uint.Parse(data["NextPermissions"].ToString());
  630. item.CurrentPermissions = uint.Parse(data["CurrentPermissions"].ToString());
  631. item.BasePermissions = uint.Parse(data["BasePermissions"].ToString());
  632. item.EveryOnePermissions = uint.Parse(data["EveryOnePermissions"].ToString());
  633. item.GroupPermissions = uint.Parse(data["GroupPermissions"].ToString());
  634. item.GroupID = new UUID(data["GroupID"].ToString());
  635. item.GroupOwned = bool.Parse(data["GroupOwned"].ToString());
  636. item.SalePrice = int.Parse(data["SalePrice"].ToString());
  637. item.SaleType = byte.Parse(data["SaleType"].ToString());
  638. item.Flags = uint.Parse(data["Flags"].ToString());
  639. item.CreationDate = int.Parse(data["CreationDate"].ToString());
  640. }
  641. catch (Exception e)
  642. {
  643. m_log.Error("[XINVENTORY CONNECTOR]: Exception building item: ", e);
  644. }
  645. return item;
  646. }
  647. }
  648. }