From 881051c8ccef7b49031d0f9a087390336ecc53b5 Mon Sep 17 00:00:00 2001
From: Justin Clark-Casey (justincc)
Date: Sun, 6 Sep 2009 21:14:42 +0100
Subject: Convert iar write request to use inventory service requests rather
 than cache

---
 .../Inventory/Archiver/InventoryArchiveUtils.cs    | 146 +++++++++++++++++++++
 .../Archiver/InventoryArchiveWriteRequest.cs       |  30 +++--
 .../Tests/Common/Mock/TestInventoryDataPlugin.cs   |  12 +-
 3 files changed, 175 insertions(+), 13 deletions(-)
 create mode 100644 OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs

diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs
new file mode 100644
index 0000000..6d598d1
--- /dev/null
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above copyright
+ *       notice, this list of conditions and the following disclaimer in the
+ *       documentation and/or other materials provided with the distribution.
+ *     * Neither the name of the OpenSimulator Project nor the
+ *       names of its contributors may be used to endorse or promote products
+ *       derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Collections.Generic;
+using OpenSim.Framework;
+using OpenSim.Services.Interfaces;
+
+namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
+{
+    /// <summary>
+    /// Utility methods for inventory archiving
+    /// </summary>
+    public static class InventoryArchiveUtils
+    {
+        public static readonly string PATH_DELIMITER = "/";
+        
+        /// <summary>
+        /// Find a folder given a PATH_DELIMITER delimited path starting from this folder
+        /// </summary>        
+        ///
+        /// This method does not handle paths that contain multiple delimitors
+        ///
+        /// FIXME: We do not yet handle situations where folders have the same name.  We could handle this by some
+        /// XPath like expression
+        ///
+        /// FIXME: Delimitors which occur in names themselves are not currently escapable.
+        ///
+        /// <param name="inventoryService">
+        /// Inventory service to query
+        /// </param>
+        /// <param name="startFolder">
+        /// The folder from which the path starts
+        /// </param>
+        /// <param name="path">
+        /// The path to the required folder.  
+        /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned.
+        /// </param>
+        /// <returns>null if the folder is not found</returns>
+        public static InventoryFolderBase FindFolderByPath(
+            IInventoryService inventoryService, InventoryFolderBase startFolder, string path)
+        {
+            if (path == string.Empty)
+                return startFolder;
+
+            path = path.Trim();
+
+            if (path == PATH_DELIMITER)
+                return startFolder;
+
+            InventoryFolderBase foundFolder = null;
+
+            string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None);
+            InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID);
+
+            foreach (InventoryFolderBase folder in contents.Folders)
+            {
+                if (folder.Name == components[0])
+                {
+                    if (components.Length > 1)
+                        return FindFolderByPath(inventoryService, foundFolder, components[1]);
+                    else
+                        return folder;
+                }
+            }
+
+            // We didn't find a folder with the right name
+            return null;
+        }
+        
+        /// <summary>
+        /// Find an item given a PATH_DELIMITOR delimited path starting from this folder.
+        ///
+        /// This method does not handle paths that contain multiple delimitors
+        ///
+        /// FIXME: We do not yet handle situations where folders or items have the same name.  We could handle this by some
+        /// XPath like expression
+        ///
+        /// FIXME: Delimitors which occur in names themselves are not currently escapable.
+        /// </summary>
+        /// 
+        /// <param name="inventoryService">
+        /// Inventory service to query
+        /// </param>
+        /// <param name="startFolder">
+        /// The folder from which the path starts
+        /// </param>
+        /// <param name="path">
+        /// <param name="path">
+        /// The path to the required item.
+        /// </param>
+        /// <returns>null if the item is not found</returns>
+        public static InventoryItemBase FindItemByPath(
+            IInventoryService inventoryService, InventoryFolderBase startFolder, string path)
+        {
+            string[] components = path.Split(new string[] { PATH_DELIMITER }, 2, StringSplitOptions.None);
+
+            if (components.Length == 1)
+            {
+                List<InventoryItemBase> items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID);
+                foreach (InventoryItemBase item in items)
+                {
+                    if (item.Name == components[0])
+                        return item;
+                }
+            }
+            else
+            {
+                InventoryCollection contents = inventoryService.GetFolderContent(startFolder.Owner, startFolder.ID);                
+                
+                foreach (InventoryFolderBase folder in contents.Folders)
+                {
+                    if (folder.Name == components[0])
+                        return FindItemByPath(inventoryService, folder, components[1]);
+                }
+            }
+
+            // We didn't find an item or intermediate folder with the given name
+            return null;
+        }        
+    }
+}
\ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
index badabe0..dee4a5d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs
@@ -158,7 +158,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
         /// <param name="inventoryFolder">The inventory folder to save</param>
         /// <param name="path">The path to which the folder should be saved</param>
         /// <param name="saveThisFolderItself">If true, save this folder itself.  If false, only saves contents</param>
-        protected void SaveInvFolder(InventoryFolderImpl inventoryFolder, string path, bool saveThisFolderItself)
+        protected void SaveInvFolder(InventoryFolderBase inventoryFolder, string path, bool saveThisFolderItself)
         {
             if (saveThisFolderItself)
             {
@@ -173,15 +173,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
                 m_archiveWriter.WriteDir(path);
             }
 
-            List<InventoryFolderImpl> childFolders = inventoryFolder.RequestListOfFolderImpls();
-            List<InventoryItemBase> items = inventoryFolder.RequestListOfItems();
+            InventoryCollection contents 
+                = m_scene.InventoryService.GetFolderContent(inventoryFolder.Owner, inventoryFolder.ID);
+            //List<InventoryFolderImpl> childFolders = inventoryFolder.RequestListOfFolderImpls();
+            //List<InventoryItemBase> items = inventoryFolder.RequestListOfItems();
 
             /*
             Dictionary identicalFolderNames = new Dictionary<string, int>();
 
             foreach (InventoryFolderImpl folder in inventories)
             {
-
                 if (!identicalFolderNames.ContainsKey(folder.Name))
                     identicalFolderNames[folder.Name] = 0;
                 else
@@ -197,12 +198,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
             }
             */
 
-            foreach (InventoryFolderImpl childFolder in childFolders)
+            foreach (InventoryFolderBase childFolder in contents.Folders)
             {
                 SaveInvFolder(childFolder, path, true);
             }
 
-            foreach (InventoryItemBase item in items)
+            foreach (InventoryItemBase item in contents.Items)
             {
                 SaveInvItem(item, path);
             }
@@ -213,8 +214,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
         /// </summary>
         public void Execute()
         {
-            InventoryFolderImpl inventoryFolder = null;
+            InventoryFolderBase inventoryFolder = null;
             InventoryItemBase inventoryItem = null;
+            InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.UserProfile.ID);
 
             // XXX: Very temporarily, drop and refetch inventory to make sure we have any newly created items in cache
             // This will disappear very soon once we stop using the old cached inventory.
@@ -223,6 +225,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
             m_userInfo.FetchInventory();
             */
 
+            /*
             if (!m_userInfo.HasReceivedInventory)
             {
                 // If the region server has access to the user admin service (by which users are created),
@@ -244,11 +247,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
                     m_userInfo.FetchInventory();
                 }
             }
+            */
 
             bool foundStar = false;
 
-            // Eliminate double slashes and any leading / on the path.  This might be better done within InventoryFolderImpl
-            // itself (possibly at a small loss in efficiency).
+            // Eliminate double slashes and any leading / on the path.
             string[] components
                 = m_invPath.Split(
                     new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries);
@@ -273,18 +276,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver
             // Therefore if we still start with a / after the split, then we need the root folder
             if (m_invPath.Length == 0)
             {
-                inventoryFolder = m_userInfo.RootFolder;
+                inventoryFolder = rootFolder;
             }
             else
             {
                 m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER));
-                inventoryFolder = m_userInfo.RootFolder.FindFolderByPath(m_invPath);
+                inventoryFolder 
+                    = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath);
+                //inventoryFolder = m_userInfo.RootFolder.FindFolderByPath(m_invPath);
             }
 
             // The path may point to an item instead
             if (inventoryFolder == null)
             {
-                inventoryItem = m_userInfo.RootFolder.FindItemByPath(m_invPath);
+                inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath);
+                //inventoryItem = m_userInfo.RootFolder.FindItemByPath(m_invPath);
             }
 
             m_archiveWriter = new TarArchiveWriter(m_saveStream);
diff --git a/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs
index a444d91..daef38b 100644
--- a/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs
+++ b/OpenSim/Tests/Common/Mock/TestInventoryDataPlugin.cs
@@ -84,7 +84,17 @@ namespace OpenSim.Tests.Common.Mock
 
         public List<InventoryItemBase> getInventoryInFolder(UUID folderID)
         {
-            return new List<InventoryItemBase>();
+            m_log.DebugFormat("[MOCK INV DB]: Getting items in folder {0}", folderID);
+            
+            List<InventoryItemBase> items = new List<InventoryItemBase>();
+
+            foreach (InventoryItemBase item in m_items.Values)
+            {
+                if (item.Folder == folderID)
+                    items.Add(item);
+            }
+            
+            return items;
         }
 
         public List<InventoryFolderBase> getUserRootFolders(UUID user) { return null; }
-- 
cgit v1.1