aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Services/InventoryService
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Services/InventoryService')
-rw-r--r--OpenSim/Services/InventoryService/InventoryService.cs700
-rw-r--r--OpenSim/Services/InventoryService/InventoryServiceBase.cs82
-rw-r--r--OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs33
-rw-r--r--OpenSim/Services/InventoryService/Tests/XInventoryServiceTests.cs177
-rw-r--r--OpenSim/Services/InventoryService/XInventoryService.cs116
5 files changed, 301 insertions, 807 deletions
diff --git a/OpenSim/Services/InventoryService/InventoryService.cs b/OpenSim/Services/InventoryService/InventoryService.cs
deleted file mode 100644
index 73dd06a..0000000
--- a/OpenSim/Services/InventoryService/InventoryService.cs
+++ /dev/null
@@ -1,700 +0,0 @@
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
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using log4net;
32using Nini.Config;
33using OpenMetaverse;
34using OpenSim.Data;
35using OpenSim.Framework;
36using OpenSim.Services.Interfaces;
37
38namespace OpenSim.Services.InventoryService
39{
40 /// <summary>
41 /// The Inventory service reference implementation
42 /// </summary>
43 public class InventoryService : InventoryServiceBase, IInventoryService
44 {
45 private static readonly ILog m_log
46 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47
48 public InventoryService(IConfigSource config) : base(config)
49 {
50 m_log.Debug("[INVENTORY SERVICE]: Initialized.");
51 }
52
53 #region IInventoryServices methods
54
55 public string Host
56 {
57 get { return "default"; }
58 }
59
60 public List<InventoryFolderBase> GetInventorySkeleton(UUID userId)
61 {
62 m_log.DebugFormat("[INVENTORY SERVICE]: Getting inventory skeleton for {0}", userId);
63
64 InventoryFolderBase rootFolder = GetRootFolder(userId);
65
66 // Agent has no inventory structure yet.
67 if (null == rootFolder)
68 {
69 m_log.DebugFormat("[INVENTORY SERVICE]: No root folder");
70 return null;
71 }
72
73 List<InventoryFolderBase> userFolders = new List<InventoryFolderBase>();
74
75 userFolders.Add(rootFolder);
76
77 IList<InventoryFolderBase> folders = m_Database.getFolderHierarchy(rootFolder.ID);
78 userFolders.AddRange(folders);
79
80// m_log.DebugFormat("[INVENTORY SERVICE]: Got folder {0} {1}", folder.name, folder.folderID);
81
82 return userFolders;
83 }
84
85 public virtual bool HasInventoryForUser(UUID userID)
86 {
87 return false;
88 }
89
90 // See IInventoryServices
91 public virtual InventoryFolderBase GetRootFolder(UUID userID)
92 {
93 //m_log.DebugFormat("[INVENTORY SERVICE]: Getting root folder for {0}", userID);
94
95 // Retrieve the first root folder we get from the DB.
96 InventoryFolderBase rootFolder = m_Database.getUserRootFolder(userID);
97 if (rootFolder != null)
98 return rootFolder;
99
100 // Return nothing if the plugin was unable to supply a root folder
101 return null;
102 }
103
104 // See IInventoryServices
105 public bool CreateUserInventory(UUID user)
106 {
107 InventoryFolderBase existingRootFolder;
108 try
109 {
110 existingRootFolder = GetRootFolder(user);
111 }
112 catch /*(Exception e)*/
113 {
114 // Munch the exception, it has already been reported
115 //
116 return false;
117 }
118
119 if (null != existingRootFolder)
120 {
121 m_log.WarnFormat(
122 "[INVENTORY SERVICE]: Did not create a new inventory for user {0} since they already have "
123 + "a root inventory folder with id {1}",
124 user, existingRootFolder.ID);
125 }
126 else
127 {
128 UsersInventory inven = new UsersInventory();
129 inven.CreateNewInventorySet(user);
130 AddNewInventorySet(inven);
131
132 return true;
133 }
134
135 return false;
136 }
137
138 // See IInventoryServices
139
140 /// <summary>
141 /// Return a user's entire inventory synchronously
142 /// </summary>
143 /// <param name="rawUserID"></param>
144 /// <returns>The user's inventory. If an inventory cannot be found then an empty collection is returned.</returns>
145 public InventoryCollection GetUserInventory(UUID userID)
146 {
147 m_log.InfoFormat("[INVENTORY SERVICE]: Processing request for inventory of {0}", userID);
148
149 // Uncomment me to simulate a slow responding inventory server
150 //Thread.Sleep(16000);
151
152 InventoryCollection invCollection = new InventoryCollection();
153
154 List<InventoryFolderBase> allFolders = GetInventorySkeleton(userID);
155
156 if (null == allFolders)
157 {
158 m_log.WarnFormat("[INVENTORY SERVICE]: No inventory found for user {0}", userID);
159
160 return invCollection;
161 }
162
163 List<InventoryItemBase> allItems = new List<InventoryItemBase>();
164
165 foreach (InventoryFolderBase folder in allFolders)
166 {
167 List<InventoryItemBase> items = GetFolderItems(userID, folder.ID);
168
169 if (items != null)
170 {
171 allItems.InsertRange(0, items);
172 }
173 }
174
175 invCollection.UserID = userID;
176 invCollection.Folders = allFolders;
177 invCollection.Items = allItems;
178
179 // foreach (InventoryFolderBase folder in invCollection.Folders)
180 // {
181 // m_log.DebugFormat("[GRID INVENTORY SERVICE]: Sending back folder {0} {1}", folder.Name, folder.ID);
182 // }
183 //
184 // foreach (InventoryItemBase item in invCollection.Items)
185 // {
186 // m_log.DebugFormat("[GRID INVENTORY SERVICE]: Sending back item {0} {1}, folder {2}", item.Name, item.ID, item.Folder);
187 // }
188
189 m_log.InfoFormat(
190 "[INVENTORY SERVICE]: Sending back inventory response to user {0} containing {1} folders and {2} items",
191 invCollection.UserID, invCollection.Folders.Count, invCollection.Items.Count);
192
193 return invCollection;
194 }
195
196 /// <summary>
197 /// Asynchronous inventory fetch.
198 /// </summary>
199 /// <param name="userID"></param>
200 /// <param name="callback"></param>
201 public void GetUserInventory(UUID userID, InventoryReceiptCallback callback)
202 {
203 m_log.InfoFormat("[INVENTORY SERVICE]: Requesting inventory for user {0}", userID);
204
205 List<InventoryFolderImpl> folders = new List<InventoryFolderImpl>();
206 List<InventoryItemBase> items = new List<InventoryItemBase>();
207
208 List<InventoryFolderBase> skeletonFolders = GetInventorySkeleton(userID);
209
210 if (skeletonFolders != null)
211 {
212 InventoryFolderImpl rootFolder = null;
213
214 // Need to retrieve the root folder on the first pass
215 foreach (InventoryFolderBase folder in skeletonFolders)
216 {
217 if (folder.ParentID == UUID.Zero)
218 {
219 rootFolder = new InventoryFolderImpl(folder);
220 folders.Add(rootFolder);
221 items.AddRange(GetFolderItems(userID, rootFolder.ID));
222 break; // Only 1 root folder per user
223 }
224 }
225
226 if (rootFolder != null)
227 {
228 foreach (InventoryFolderBase folder in skeletonFolders)
229 {
230 if (folder.ID != rootFolder.ID)
231 {
232 folders.Add(new InventoryFolderImpl(folder));
233 items.AddRange(GetFolderItems(userID, folder.ID));
234 }
235 }
236 }
237
238 m_log.InfoFormat(
239 "[INVENTORY SERVICE]: Received inventory response for user {0} containing {1} folders and {2} items",
240 userID, folders.Count, items.Count);
241 }
242 else
243 {
244 m_log.WarnFormat("[INVENTORY SERVICE]: User {0} inventory not available", userID);
245 }
246
247 Util.FireAndForget(delegate { callback(folders, items); });
248 }
249
250 public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
251 {
252 // Uncomment me to simulate a slow responding inventory server
253 //Thread.Sleep(16000);
254
255 InventoryCollection invCollection = new InventoryCollection();
256
257 List<InventoryItemBase> items = GetFolderItems(userID, folderID);
258 List<InventoryFolderBase> folders = RequestSubFolders(folderID);
259
260 invCollection.UserID = userID;
261 invCollection.Folders = folders;
262 invCollection.Items = items;
263
264 m_log.DebugFormat("[INVENTORY SERVICE]: Found {0} items and {1} folders in folder {2}", items.Count, folders.Count, folderID);
265
266 return invCollection;
267 }
268
269 public InventoryFolderBase GetFolderForType(UUID userID, AssetType type)
270 {
271// m_log.DebugFormat("[INVENTORY SERVICE]: Looking for folder type {0} for user {1}", type, userID);
272
273 InventoryFolderBase root = m_Database.getUserRootFolder(userID);
274 if (root != null)
275 {
276 List<InventoryFolderBase> folders = RequestSubFolders(root.ID);
277
278 foreach (InventoryFolderBase folder in folders)
279 {
280 if (folder.Type == (short)type)
281 {
282// m_log.DebugFormat(
283// "[INVENTORY SERVICE]: Found folder {0} type {1}", folder.Name, (AssetType)folder.Type);
284
285 return folder;
286 }
287 }
288 }
289
290 // we didn't find any folder of that type. Return the root folder
291 // hopefully the root folder is not null. If it is, too bad
292 return root;
293 }
294
295 public Dictionary<AssetType, InventoryFolderBase> GetSystemFolders(UUID userID)
296 {
297 InventoryFolderBase root = GetRootFolder(userID);
298 if (root != null)
299 {
300 InventoryCollection content = GetFolderContent(userID, root.ID);
301 if (content != null)
302 {
303 Dictionary<AssetType, InventoryFolderBase> folders = new Dictionary<AssetType, InventoryFolderBase>();
304 foreach (InventoryFolderBase folder in content.Folders)
305 {
306 if ((folder.Type != (short)AssetType.Folder) && (folder.Type != (short)AssetType.Unknown))
307 folders[(AssetType)folder.Type] = folder;
308 }
309 m_log.DebugFormat("[INVENTORY SERVICE]: Got {0} system folders for {1}", folders.Count, userID);
310 return folders;
311 }
312 }
313 m_log.WarnFormat("[INVENTORY SERVICE]: System folders for {0} not found", userID);
314 return new Dictionary<AssetType, InventoryFolderBase>();
315 }
316
317 public List<InventoryItemBase> GetActiveGestures(UUID userId)
318 {
319 List<InventoryItemBase> activeGestures = new List<InventoryItemBase>();
320 activeGestures.AddRange(m_Database.fetchActiveGestures(userId));
321
322 return activeGestures;
323 }
324
325 #endregion
326
327 #region Methods used by GridInventoryService
328
329 public List<InventoryFolderBase> RequestSubFolders(UUID parentFolderID)
330 {
331 List<InventoryFolderBase> inventoryList = new List<InventoryFolderBase>();
332
333 inventoryList.AddRange(m_Database.getInventoryFolders(parentFolderID));
334
335 return inventoryList;
336 }
337
338 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
339 {
340 List<InventoryItemBase> itemsList = new List<InventoryItemBase>();
341
342 itemsList.AddRange(m_Database.getInventoryInFolder(folderID));
343
344// m_log.DebugFormat(
345// "[INVENTORY SERVICE]: Found {0} items in folder {1} for {2}", itemsList.Count, folderID, userID);
346
347 return itemsList;
348 }
349
350 #endregion
351
352 // See IInventoryServices
353 public virtual bool AddFolder(InventoryFolderBase folder)
354 {
355 m_log.DebugFormat(
356 "[INVENTORY SERVICE]: Adding folder {0} {1} to folder {2}", folder.Name, folder.ID, folder.ParentID);
357
358 m_Database.addInventoryFolder(folder);
359
360 // FIXME: Should return false on failure
361 return true;
362 }
363
364 // See IInventoryServices
365 public virtual bool UpdateFolder(InventoryFolderBase folder)
366 {
367 m_log.DebugFormat(
368 "[INVENTORY SERVICE]: Updating folder {0} {1} to folder {2}", folder.Name, folder.ID, folder.ParentID);
369
370 m_Database.updateInventoryFolder(folder);
371
372 // FIXME: Should return false on failure
373 return true;
374 }
375
376 // See IInventoryServices
377 public virtual bool MoveFolder(InventoryFolderBase folder)
378 {
379 m_log.DebugFormat(
380 "[INVENTORY SERVICE]: Moving folder {0} {1} to folder {2}", folder.Name, folder.ID, folder.ParentID);
381
382 m_Database.moveInventoryFolder(folder);
383
384 // FIXME: Should return false on failure
385 return true;
386 }
387
388 // See IInventoryServices
389 public virtual bool AddItem(InventoryItemBase item)
390 {
391// m_log.DebugFormat(
392// "[INVENTORY SERVICE]: Adding item {0} {1} to folder {2} for {3}",
393// item.Name, item.ID, item.Folder, item.Owner);
394
395 m_Database.addInventoryItem(item);
396
397 // FIXME: Should return false on failure
398 return true;
399 }
400
401 // See IInventoryServices
402 public virtual bool UpdateItem(InventoryItemBase item)
403 {
404 m_log.InfoFormat(
405 "[INVENTORY SERVICE]: Updating item {0} {1} in folder {2}", item.Name, item.ID, item.Folder);
406
407 m_Database.updateInventoryItem(item);
408
409 // FIXME: Should return false on failure
410 return true;
411 }
412
413 public virtual bool MoveItems(UUID ownerID, List<InventoryItemBase> items)
414 {
415 m_log.InfoFormat(
416 "[INVENTORY SERVICE]: Moving {0} items from user {1}", items.Count, ownerID);
417
418 InventoryItemBase itm = null;
419 foreach (InventoryItemBase item in items)
420 {
421 itm = GetInventoryItem(item.ID);
422 itm.Folder = item.Folder;
423 if ((item.Name != null) && !item.Name.Equals(string.Empty))
424 itm.Name = item.Name;
425 m_Database.updateInventoryItem(itm);
426 }
427
428 return true;
429 }
430
431 // See IInventoryServices
432 public virtual bool DeleteItems(UUID owner, List<UUID> itemIDs)
433 {
434 m_log.InfoFormat(
435 "[INVENTORY SERVICE]: Deleting {0} items from user {1}", itemIDs.Count, owner);
436
437 // uhh.....
438 foreach (UUID uuid in itemIDs)
439 m_Database.deleteInventoryItem(uuid);
440
441 // FIXME: Should return false on failure
442 return true;
443 }
444
445 public virtual InventoryItemBase GetItem(InventoryItemBase item)
446 {
447 InventoryItemBase result = m_Database.getInventoryItem(item.ID);
448 if (result != null)
449 return result;
450 m_log.DebugFormat("[INVENTORY SERVICE]: GetItem failed to find item {0}", item.ID);
451 return null;
452 }
453
454 public virtual InventoryFolderBase GetFolder(InventoryFolderBase folder)
455 {
456 InventoryFolderBase result = m_Database.getInventoryFolder(folder.ID);
457 if (result != null)
458 return result;
459
460 m_log.DebugFormat("[INVENTORY SERVICE]: GetFolder failed to find folder {0}", folder.ID);
461 return null;
462 }
463
464 public virtual bool DeleteFolders(UUID ownerID, List<UUID> folderIDs)
465 {
466 m_log.InfoFormat("[INVENTORY SERVICE]: Deleting {0} folders from user {1}", folderIDs.Count, ownerID);
467 foreach (UUID id in folderIDs)
468 {
469 InventoryFolderBase folder = new InventoryFolderBase(id, ownerID);
470 PurgeFolder(folder);
471 m_Database.deleteInventoryFolder(id);
472 }
473 return true;
474 }
475
476 /// <summary>
477 /// Purge a folder of all items items and subfolders.
478 ///
479 /// FIXME: Really nasty in a sense, because we have to query the database to get information we may
480 /// already know... Needs heavy refactoring.
481 /// </summary>
482 /// <param name="folder"></param>
483 public virtual bool PurgeFolder(InventoryFolderBase folder)
484 {
485 m_log.DebugFormat(
486 "[INVENTORY SERVICE]: Purging folder {0} {1} of its contents", folder.Name, folder.ID);
487
488 List<InventoryFolderBase> subFolders = RequestSubFolders(folder.ID);
489
490 foreach (InventoryFolderBase subFolder in subFolders)
491 {
492// m_log.DebugFormat("[INVENTORY SERVICE]: Deleting folder {0} {1}", subFolder.Name, subFolder.ID);
493
494 m_Database.deleteInventoryFolder(subFolder.ID);
495 }
496
497 List<InventoryItemBase> items = GetFolderItems(folder.Owner, folder.ID);
498
499 List<UUID> uuids = new List<UUID>();
500 foreach (InventoryItemBase item in items)
501 {
502 uuids.Add(item.ID);
503 }
504 DeleteItems(folder.Owner, uuids);
505
506 // FIXME: Should return false on failure
507 return true;
508 }
509
510 private void AddNewInventorySet(UsersInventory inventory)
511 {
512 foreach (InventoryFolderBase folder in inventory.Folders.Values)
513 {
514 AddFolder(folder);
515 }
516 }
517
518 public InventoryItemBase GetInventoryItem(UUID itemID)
519 {
520 InventoryItemBase item = m_Database.getInventoryItem(itemID);
521 if (item != null)
522 return item;
523
524 return null;
525 }
526
527 public int GetAssetPermissions(UUID userID, UUID assetID)
528 {
529 InventoryFolderBase parent = GetRootFolder(userID);
530 return FindAssetPerms(parent, assetID);
531 }
532
533 private int FindAssetPerms(InventoryFolderBase folder, UUID assetID)
534 {
535 InventoryCollection contents = GetFolderContent(folder.Owner, folder.ID);
536
537 int perms = 0;
538 foreach (InventoryItemBase item in contents.Items)
539 {
540 if (item.AssetID == assetID)
541 perms = (int)item.CurrentPermissions | perms;
542 }
543
544 foreach (InventoryFolderBase subfolder in contents.Folders)
545 perms = perms | FindAssetPerms(subfolder, assetID);
546
547 return perms;
548 }
549
550 /// <summary>
551 /// Used to create a new user inventory.
552 /// </summary>
553 private class UsersInventory
554 {
555 public Dictionary<UUID, InventoryFolderBase> Folders = new Dictionary<UUID, InventoryFolderBase>();
556 public Dictionary<UUID, InventoryItemBase> Items = new Dictionary<UUID, InventoryItemBase>();
557
558 public virtual void CreateNewInventorySet(UUID user)
559 {
560 InventoryFolderBase folder = new InventoryFolderBase();
561
562 folder.ParentID = UUID.Zero;
563 folder.Owner = user;
564 folder.ID = UUID.Random();
565 folder.Name = "My Inventory";
566 folder.Type = (short)AssetType.Folder;
567 folder.Version = 1;
568 Folders.Add(folder.ID, folder);
569
570 UUID rootFolder = folder.ID;
571
572 folder = new InventoryFolderBase();
573 folder.ParentID = rootFolder;
574 folder.Owner = user;
575 folder.ID = UUID.Random();
576 folder.Name = "Animations";
577 folder.Type = (short)AssetType.Animation;
578 folder.Version = 1;
579 Folders.Add(folder.ID, folder);
580
581 folder = new InventoryFolderBase();
582 folder.ParentID = rootFolder;
583 folder.Owner = user;
584 folder.ID = UUID.Random();
585 folder.Name = "Body Parts";
586 folder.Type = (short)AssetType.Bodypart;
587 folder.Version = 1;
588 Folders.Add(folder.ID, folder);
589
590 folder = new InventoryFolderBase();
591 folder.ParentID = rootFolder;
592 folder.Owner = user;
593 folder.ID = UUID.Random();
594 folder.Name = "Calling Cards";
595 folder.Type = (short)AssetType.CallingCard;
596 folder.Version = 1;
597 Folders.Add(folder.ID, folder);
598
599 folder = new InventoryFolderBase();
600 folder.ParentID = rootFolder;
601 folder.Owner = user;
602 folder.ID = UUID.Random();
603 folder.Name = "Clothing";
604 folder.Type = (short)AssetType.Clothing;
605 folder.Version = 1;
606 Folders.Add(folder.ID, folder);
607
608 folder = new InventoryFolderBase();
609 folder.ParentID = rootFolder;
610 folder.Owner = user;
611 folder.ID = UUID.Random();
612 folder.Name = "Gestures";
613 folder.Type = (short)AssetType.Gesture;
614 folder.Version = 1;
615 Folders.Add(folder.ID, folder);
616
617 folder = new InventoryFolderBase();
618 folder.ParentID = rootFolder;
619 folder.Owner = user;
620 folder.ID = UUID.Random();
621 folder.Name = "Landmarks";
622 folder.Type = (short)AssetType.Landmark;
623 folder.Version = 1;
624 Folders.Add(folder.ID, folder);
625
626 folder = new InventoryFolderBase();
627 folder.ParentID = rootFolder;
628 folder.Owner = user;
629 folder.ID = UUID.Random();
630 folder.Name = "Lost And Found";
631 folder.Type = (short)AssetType.LostAndFoundFolder;
632 folder.Version = 1;
633 Folders.Add(folder.ID, folder);
634
635 folder = new InventoryFolderBase();
636 folder.ParentID = rootFolder;
637 folder.Owner = user;
638 folder.ID = UUID.Random();
639 folder.Name = "Notecards";
640 folder.Type = (short)AssetType.Notecard;
641 folder.Version = 1;
642 Folders.Add(folder.ID, folder);
643
644 folder = new InventoryFolderBase();
645 folder.ParentID = rootFolder;
646 folder.Owner = user;
647 folder.ID = UUID.Random();
648 folder.Name = "Objects";
649 folder.Type = (short)AssetType.Object;
650 folder.Version = 1;
651 Folders.Add(folder.ID, folder);
652
653 folder = new InventoryFolderBase();
654 folder.ParentID = rootFolder;
655 folder.Owner = user;
656 folder.ID = UUID.Random();
657 folder.Name = "Photo Album";
658 folder.Type = (short)AssetType.SnapshotFolder;
659 folder.Version = 1;
660 Folders.Add(folder.ID, folder);
661
662 folder = new InventoryFolderBase();
663 folder.ParentID = rootFolder;
664 folder.Owner = user;
665 folder.ID = UUID.Random();
666 folder.Name = "Scripts";
667 folder.Type = (short)AssetType.LSLText;
668 folder.Version = 1;
669 Folders.Add(folder.ID, folder);
670
671 folder = new InventoryFolderBase();
672 folder.ParentID = rootFolder;
673 folder.Owner = user;
674 folder.ID = UUID.Random();
675 folder.Name = "Sounds";
676 folder.Type = (short)AssetType.Sound;
677 folder.Version = 1;
678 Folders.Add(folder.ID, folder);
679
680 folder = new InventoryFolderBase();
681 folder.ParentID = rootFolder;
682 folder.Owner = user;
683 folder.ID = UUID.Random();
684 folder.Name = "Textures";
685 folder.Type = (short)AssetType.Texture;
686 folder.Version = 1;
687 Folders.Add(folder.ID, folder);
688
689 folder = new InventoryFolderBase();
690 folder.ParentID = rootFolder;
691 folder.Owner = user;
692 folder.ID = UUID.Random();
693 folder.Name = "Trash";
694 folder.Type = (short)AssetType.TrashFolder;
695 folder.Version = 1;
696 Folders.Add(folder.ID, folder);
697 }
698 }
699 }
700}
diff --git a/OpenSim/Services/InventoryService/InventoryServiceBase.cs b/OpenSim/Services/InventoryService/InventoryServiceBase.cs
deleted file mode 100644
index 456e455..0000000
--- a/OpenSim/Services/InventoryService/InventoryServiceBase.cs
+++ /dev/null
@@ -1,82 +0,0 @@
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
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using Nini.Config;
32using OpenSim.Framework;
33using OpenSim.Data;
34using OpenSim.Services.Interfaces;
35using OpenSim.Services.Base;
36
37namespace OpenSim.Services.InventoryService
38{
39 public class InventoryServiceBase : ServiceBase
40 {
41 protected IInventoryDataPlugin m_Database = null;
42
43 public InventoryServiceBase(IConfigSource config) : base(config)
44 {
45 string dllName = String.Empty;
46 string connString = String.Empty;
47
48 //
49 // Try reading the [DatabaseService] section first, if it exists
50 //
51 IConfig dbConfig = config.Configs["DatabaseService"];
52 if (dbConfig != null)
53 {
54 dllName = dbConfig.GetString("StorageProvider", String.Empty);
55 connString = dbConfig.GetString("ConnectionString", String.Empty);
56 }
57
58 //
59 // Try reading the more specific [InventoryService] section, if it exists
60 //
61 IConfig inventoryConfig = config.Configs["InventoryService"];
62 if (inventoryConfig != null)
63 {
64 dllName = inventoryConfig.GetString("StorageProvider", dllName);
65 connString = inventoryConfig.GetString("ConnectionString", connString);
66 }
67
68 //
69 // We tried, but this doesn't exist. We can't proceed.
70 //
71 if (dllName.Equals(String.Empty))
72 throw new Exception("No InventoryService configuration");
73
74 m_Database = LoadPlugin<IInventoryDataPlugin>(dllName);
75 if (m_Database == null)
76 throw new Exception("Could not find a storage interface in the given module");
77
78 m_Database.Initialise(connString);
79 }
80
81 }
82}
diff --git a/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs b/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs
new file mode 100644
index 0000000..41ad9f8
--- /dev/null
+++ b/OpenSim/Services/InventoryService/Properties/AssemblyInfo.cs
@@ -0,0 +1,33 @@
1using System.Reflection;
2using System.Runtime.CompilerServices;
3using System.Runtime.InteropServices;
4
5// General Information about an assembly is controlled through the following
6// set of attributes. Change these attribute values to modify the information
7// associated with an assembly.
8[assembly: AssemblyTitle("OpenSim.Services.InventoryService")]
9[assembly: AssemblyDescription("")]
10[assembly: AssemblyConfiguration("")]
11[assembly: AssemblyCompany("http://opensimulator.org")]
12[assembly: AssemblyProduct("OpenSim")]
13[assembly: AssemblyCopyright("OpenSimulator developers")]
14[assembly: AssemblyTrademark("")]
15[assembly: AssemblyCulture("")]
16
17// Setting ComVisible to false makes the types in this assembly not visible
18// to COM components. If you need to access a type in this assembly from
19// COM, set the ComVisible attribute to true on that type.
20[assembly: ComVisible(false)]
21
22// The following GUID is for the ID of the typelib if this project is exposed to COM
23[assembly: Guid("d96d6d8c-9769-47e7-88dc-dbeb8fe7105a")]
24
25// Version information for an assembly consists of the following four values:
26//
27// Major Version
28// Minor Version
29// Build Number
30// Revision
31//
32[assembly: AssemblyVersion("0.7.5.*")]
33[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/OpenSim/Services/InventoryService/Tests/XInventoryServiceTests.cs b/OpenSim/Services/InventoryService/Tests/XInventoryServiceTests.cs
new file mode 100644
index 0000000..9e3fa69
--- /dev/null
+++ b/OpenSim/Services/InventoryService/Tests/XInventoryServiceTests.cs
@@ -0,0 +1,177 @@
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
28using System;
29using Nini.Config;
30using NUnit.Framework;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Server.Base;
34using OpenSim.Services.Interfaces;
35using OpenSim.Tests.Common;
36
37namespace OpenSim.Services.InventoryService.Tests
38{
39 /// <summary>
40 /// Tests for the XInventoryService
41 /// </summary>
42 /// <remarks>
43 /// TODO: Fill out more tests.
44 /// </remarks>
45 [TestFixture]
46 public class XInventoryServiceTests : OpenSimTestCase
47 {
48 private IInventoryService CreateXInventoryService()
49 {
50 IConfigSource config = new IniConfigSource();
51 config.AddConfig("InventoryService");
52 config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll");
53
54 return ServerUtils.LoadPlugin<IInventoryService>(
55 "OpenSim.Services.InventoryService.dll:XInventoryService", new Object[] { config });
56 }
57
58 /// <summary>
59 /// Tests add item operation.
60 /// </summary>
61 /// <remarks>
62 /// TODO: Test all operations.
63 /// </remarks>
64 [Test]
65 public void TestAddItem()
66 {
67 TestHelpers.InMethod();
68
69 string creatorId = TestHelpers.ParseTail(0x1).ToString();
70 UUID ownerId = TestHelpers.ParseTail(0x2);
71 UUID itemId = TestHelpers.ParseTail(0x10);
72 UUID assetId = TestHelpers.ParseTail(0x20);
73 UUID folderId = TestHelpers.ParseTail(0x30);
74 int invType = (int)InventoryType.Animation;
75 int assetType = (int)AssetType.Animation;
76 string itemName = "item1";
77
78 IInventoryService xis = CreateXInventoryService();
79
80 InventoryItemBase itemToStore
81 = new InventoryItemBase(itemId, ownerId)
82 {
83 CreatorIdentification = creatorId.ToString(),
84 AssetID = assetId,
85 Name = itemName,
86 Folder = folderId,
87 InvType = invType,
88 AssetType = assetType
89 };
90
91 Assert.That(xis.AddItem(itemToStore), Is.True);
92
93 InventoryItemBase itemRetrieved = new InventoryItemBase(itemId);
94 itemRetrieved = xis.GetItem(itemRetrieved);
95
96 Assert.That(itemRetrieved, Is.Not.Null);
97 Assert.That(itemRetrieved.CreatorId, Is.EqualTo(creatorId));
98 Assert.That(itemRetrieved.Owner, Is.EqualTo(ownerId));
99 Assert.That(itemRetrieved.AssetID, Is.EqualTo(assetId));
100 Assert.That(itemRetrieved.Folder, Is.EqualTo(folderId));
101 Assert.That(itemRetrieved.InvType, Is.EqualTo(invType));
102 Assert.That(itemRetrieved.AssetType, Is.EqualTo(assetType));
103 Assert.That(itemRetrieved.Name, Is.EqualTo(itemName));
104 }
105
106 [Test]
107 public void TestUpdateItem()
108 {
109 TestHelpers.InMethod();
110// TestHelpers.EnableLogging();
111
112 string creatorId = TestHelpers.ParseTail(0x1).ToString();
113 UUID ownerId = TestHelpers.ParseTail(0x2);
114 UUID itemId = TestHelpers.ParseTail(0x10);
115 UUID assetId = TestHelpers.ParseTail(0x20);
116 UUID folderId = TestHelpers.ParseTail(0x30);
117 int invType = (int)InventoryType.Animation;
118 int assetType = (int)AssetType.Animation;
119 string itemName = "item1";
120 string itemName2 = "item2";
121
122 IInventoryService xis = CreateXInventoryService();
123
124 InventoryItemBase itemToStore
125 = new InventoryItemBase(itemId, ownerId)
126 {
127 CreatorIdentification = creatorId.ToString(),
128 AssetID = assetId,
129 Name = itemName,
130 Folder = folderId,
131 InvType = invType,
132 AssetType = assetType
133 };
134
135 Assert.That(xis.AddItem(itemToStore), Is.True);
136
137 // Normal update
138 itemToStore.Name = itemName2;
139
140 Assert.That(xis.UpdateItem(itemToStore), Is.True);
141
142 InventoryItemBase itemRetrieved = new InventoryItemBase(itemId);
143 itemRetrieved = xis.GetItem(itemRetrieved);
144
145 Assert.That(itemRetrieved, Is.Not.Null);
146 Assert.That(itemRetrieved.Name, Is.EqualTo(itemName2));
147
148 // Attempt to update properties that should never change
149 string creatorId2 = TestHelpers.ParseTail(0x7).ToString();
150 UUID ownerId2 = TestHelpers.ParseTail(0x8);
151 UUID folderId2 = TestHelpers.ParseTail(0x70);
152 int invType2 = (int)InventoryType.CallingCard;
153 int assetType2 = (int)AssetType.CallingCard;
154 string itemName3 = "item3";
155
156 itemToStore.CreatorIdentification = creatorId2.ToString();
157 itemToStore.Owner = ownerId2;
158 itemToStore.Folder = folderId2;
159 itemToStore.InvType = invType2;
160 itemToStore.AssetType = assetType2;
161 itemToStore.Name = itemName3;
162
163 Assert.That(xis.UpdateItem(itemToStore), Is.True);
164
165 itemRetrieved = xis.GetItem(itemRetrieved);
166
167 Assert.That(itemRetrieved, Is.Not.Null);
168 Assert.That(itemRetrieved.CreatorId, Is.EqualTo(creatorId));
169 Assert.That(itemRetrieved.Owner, Is.EqualTo(ownerId));
170 Assert.That(itemRetrieved.AssetID, Is.EqualTo(assetId));
171 Assert.That(itemRetrieved.Folder, Is.EqualTo(folderId));
172 Assert.That(itemRetrieved.InvType, Is.EqualTo(invType));
173 Assert.That(itemRetrieved.AssetType, Is.EqualTo(assetType));
174 Assert.That(itemRetrieved.Name, Is.EqualTo(itemName3));
175 }
176 }
177} \ No newline at end of file
diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs
index 7518b86..00faa44 100644
--- a/OpenSim/Services/InventoryService/XInventoryService.cs
+++ b/OpenSim/Services/InventoryService/XInventoryService.cs
@@ -94,6 +94,7 @@ namespace OpenSim.Services.InventoryService
94 94
95 m_Database = LoadPlugin<IXInventoryData>(dllName, 95 m_Database = LoadPlugin<IXInventoryData>(dllName,
96 new Object[] {connString, String.Empty}); 96 new Object[] {connString, String.Empty});
97
97 if (m_Database == null) 98 if (m_Database == null)
98 throw new Exception("Could not find a storage interface in the given module"); 99 throw new Exception("Could not find a storage interface in the given module");
99 } 100 }
@@ -229,10 +230,28 @@ namespace OpenSim.Services.InventoryService
229 public virtual InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) 230 public virtual InventoryFolderBase GetFolderForType(UUID principalID, AssetType type)
230 { 231 {
231// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID); 232// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID);
233
234 InventoryFolderBase rootFolder = GetRootFolder(principalID);
235
236 if (rootFolder == null)
237 {
238 m_log.WarnFormat(
239 "[XINVENTORY]: Found no root folder for {0} in GetFolderForType() when looking for {1}",
240 principalID, type);
241
242 return null;
243 }
244
245 return GetSystemFolderForType(rootFolder, type);
246 }
247
248 private InventoryFolderBase GetSystemFolderForType(InventoryFolderBase rootFolder, AssetType type)
249 {
250// m_log.DebugFormat("[XINVENTORY SERVICE]: Getting folder type {0} for user {1}", type, principalID);
232 251
233 XInventoryFolder[] folders = m_Database.GetFolders( 252 XInventoryFolder[] folders = m_Database.GetFolders(
234 new string[] { "agentID", "type"}, 253 new string[] { "agentID", "parentFolderID", "type"},
235 new string[] { principalID.ToString(), ((int)type).ToString() }); 254 new string[] { rootFolder.Owner.ToString(), rootFolder.ID.ToString(), ((int)type).ToString() });
236 255
237 if (folders.Length == 0) 256 if (folders.Length == 0)
238 { 257 {
@@ -308,22 +327,38 @@ namespace OpenSim.Services.InventoryService
308 if (check != null) 327 if (check != null)
309 return false; 328 return false;
310 329
311 if (folder.Type == (short)AssetType.Folder 330 if (folder.Type != (short)AssetType.Folder && folder.Type != (short)AssetType.Unknown)
312 || folder.Type == (short)AssetType.Unknown
313 || folder.Type == (short)AssetType.OutfitFolder
314 || GetFolderForType(folder.Owner, (AssetType)(folder.Type)) == null)
315 { 331 {
316 XInventoryFolder xFolder = ConvertFromOpenSim(folder); 332 InventoryFolderBase rootFolder = GetRootFolder(folder.Owner);
317 return m_Database.StoreFolder(xFolder); 333
318 } 334 if (rootFolder == null)
319 else 335 {
320 { 336 m_log.WarnFormat(
321 m_log.WarnFormat( 337 "[XINVENTORY]: Found no root folder for {0} in AddFolder() when looking for {1}",
322 "[XINVENTORY]: Folder of type {0} already exists when tried to add {1} to {2} for {3}", 338 folder.Owner, folder.Type);
323 folder.Type, folder.Name, folder.ParentID, folder.Owner); 339
340 return false;
341 }
342
343 // Check we're not trying to add this as a system folder.
344 if (folder.ParentID == rootFolder.ID)
345 {
346 InventoryFolderBase existingSystemFolder
347 = GetSystemFolderForType(rootFolder, (AssetType)folder.Type);
348
349 if (existingSystemFolder != null)
350 {
351 m_log.WarnFormat(
352 "[XINVENTORY]: System folder of type {0} already exists when tried to add {1} to {2} for {3}",
353 folder.Type, folder.Name, folder.ParentID, folder.Owner);
354
355 return false;
356 }
357 }
324 } 358 }
325 359
326 return false; 360 XInventoryFolder xFolder = ConvertFromOpenSim(folder);
361 return m_Database.StoreFolder(xFolder);
327 } 362 }
328 363
329 public virtual bool UpdateFolder(InventoryFolderBase folder) 364 public virtual bool UpdateFolder(InventoryFolderBase folder)
@@ -365,16 +400,7 @@ namespace OpenSim.Services.InventoryService
365 400
366 public virtual bool MoveFolder(InventoryFolderBase folder) 401 public virtual bool MoveFolder(InventoryFolderBase folder)
367 { 402 {
368 XInventoryFolder[] x = m_Database.GetFolders( 403 return m_Database.MoveFolder(folder.ID.ToString(), folder.ParentID.ToString());
369 new string[] { "folderID" },
370 new string[] { folder.ID.ToString() });
371
372 if (x.Length == 0)
373 return false;
374
375 x[0].parentFolderID = folder.ParentID;
376
377 return m_Database.StoreFolder(x[0]);
378 } 404 }
379 405
380 // We don't check the principal's ID here 406 // We don't check the principal's ID here
@@ -450,6 +476,46 @@ namespace OpenSim.Services.InventoryService
450// m_log.InfoFormat( 476// m_log.InfoFormat(
451// "[XINVENTORY SERVICE]: Updating item {0} {1} in folder {2}", item.Name, item.ID, item.Folder); 477// "[XINVENTORY SERVICE]: Updating item {0} {1} in folder {2}", item.Name, item.ID, item.Folder);
452 478
479 InventoryItemBase retrievedItem = GetItem(item);
480
481 if (retrievedItem == null)
482 {
483 m_log.WarnFormat(
484 "[XINVENTORY SERVICE]: Tried to update item {0} {1}, owner {2} but no existing item found.",
485 item.Name, item.ID, item.Owner);
486
487 return false;
488 }
489
490 // Do not allow invariants to change. Changes to folder ID occur in MoveItems()
491 if (retrievedItem.InvType != item.InvType
492 || retrievedItem.AssetType != item.AssetType
493 || retrievedItem.Folder != item.Folder
494 || retrievedItem.CreatorIdentification != item.CreatorIdentification
495 || retrievedItem.Owner != item.Owner)
496 {
497 m_log.WarnFormat(
498 "[XINVENTORY SERVICE]: Caller to UpdateItem() for {0} {1} tried to alter property(s) that should be invariant, (InvType, AssetType, Folder, CreatorIdentification, Owner), existing ({2}, {3}, {4}, {5}, {6}), update ({7}, {8}, {9}, {10}, {11})",
499 retrievedItem.Name,
500 retrievedItem.ID,
501 retrievedItem.InvType,
502 retrievedItem.AssetType,
503 retrievedItem.Folder,
504 retrievedItem.CreatorIdentification,
505 retrievedItem.Owner,
506 item.InvType,
507 item.AssetType,
508 item.Folder,
509 item.CreatorIdentification,
510 item.Owner);
511
512 item.InvType = retrievedItem.InvType;
513 item.AssetType = retrievedItem.AssetType;
514 item.Folder = retrievedItem.Folder;
515 item.CreatorIdentification = retrievedItem.CreatorIdentification;
516 item.Owner = retrievedItem.Owner;
517 }
518
453 return m_Database.StoreItem(ConvertFromOpenSim(item)); 519 return m_Database.StoreItem(ConvertFromOpenSim(item));
454 } 520 }
455 521