Utility methods for inventory archiving
        /// <summary>
        /// Execute the request
        /// </summary>
        /// <remarks>
        /// Only call this once.  To load another IAR, construct another request object.
        /// </remarks>
        /// <returns>
        /// A list of the inventory nodes loaded.  If folders were loaded then only the root folders are
        /// returned
        /// </returns>
        /// <exception cref="System.Exception">Thrown if load fails.</exception>
        public HashSet <InventoryNodeBase> Execute()
        {
            try
            {
                string filePath = "ERROR";

                List <InventoryFolderBase> folderCandidates
                    = InventoryArchiveUtils.FindFoldersByPath(
                          m_InventoryService, m_userInfo.PrincipalID, m_invPath);

                if (folderCandidates.Count == 0)
                {
                    // Possibly provide an option later on to automatically create this folder if it does not exist
                    m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath);

                    return(m_loadedNodes);
                }

                m_rootDestinationFolder = folderCandidates[0];
                TarArchiveReader archive = null;
                try
                {
                    archive = new TarArchiveReader(m_loadStream);
                    byte[] data;
                    TarArchiveReader.TarEntryType entryType;

                    while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
                    {
                        if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
                        {
                            LoadControlFile(filePath, data);
                        }
                        else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
                        {
                            LoadAssetFile(filePath, data);
                        }
                        else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH))
                        {
                            LoadInventoryFile(filePath, entryType, data);
                        }
                    }
                }
                finally
                {
                    archive.Close();
                }
                FixupInventoryLinks();

                m_log.DebugFormat(
                    "[INVENTORY ARCHIVER]: Successfully loaded {0} assets and {1} failures",
                    m_successfulAssetRestores, m_failedAssetRestores);
                m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items and {1} failures", m_successfulItemRestores, m_failedItemRestores);

                return(m_loadedNodes);
            }
            finally
            {
                m_loadStream.Close();
            }
        }
 /// <summary>
 /// Create an archive item name given its constituent components
 /// </summary>
 /// <param name="name"></param>
 /// <param name="id"></param>
 /// <returns></returns>
 public static string CreateArchiveItemName(string name, UUID id)
 {
     return(string.Format(
                "{0}{1}{2}.xml",
                InventoryArchiveUtils.EscapeArchivePath(name),
                ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR,
                id));
 }
        /// <summary>
        /// Resolve a destination folder
        /// </summary>
        ///
        /// We require here a root destination folder (usually the root of the user's inventory) and the archive
        /// path.  We also pass in a list of previously resolved folders in case we've found this one previously.
        ///
        /// <param name="archivePath">
        /// The item archive path to resolve.  The portion of the path passed back is that
        /// which corresponds to the resolved desintation folder.
        /// <param name="rootDestinationFolder">
        /// The root folder for the inventory load
        /// </param>
        /// <param name="resolvedFolders">
        /// The folders that we have resolved so far for a given archive path.
        /// </param>
        /// <returns>
        /// The folder in the user's inventory that matches best the archive path given.  If no such folder was found
        /// then the passed in root destination folder is returned.
        /// </returns>
        protected InventoryFolderBase ResolveDestinationFolder(
            InventoryFolderBase rootDestFolder,
            ref string archivePath,
            Dictionary <string, InventoryFolderBase> resolvedFolders)
        {
            //            string originalArchivePath = archivePath;

            while (archivePath.Length > 0)
            {
                //                m_log.DebugFormat("[INVENTORY ARCHIVER]: Trying to resolve destination folder {0}", archivePath);

                if (resolvedFolders.ContainsKey(archivePath))
                {
                    //                    m_log.DebugFormat(
                    //                        "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath);
                    return(resolvedFolders[archivePath]);
                }
                else
                {
                    if (m_merge)
                    {
                        // TODO: Using m_invPath is totally wrong - what we need to do is strip the uuid from the
                        // iar name and try to find that instead.
                        string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath);
                        List <InventoryFolderBase> folderCandidates
                            = InventoryArchiveUtils.FindFoldersByPath(
                                  m_InventoryService, m_userInfo.PrincipalID, plainPath);

                        if (folderCandidates.Count != 0)
                        {
                            InventoryFolderBase destFolder = folderCandidates[0];
                            resolvedFolders[archivePath] = destFolder;
                            return(destFolder);
                        }
                    }

                    // Don't include the last slash so find the penultimate one
                    int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2);

                    if (penultimateSlashIndex >= 0)
                    {
                        // Remove the last section of path so that we can see if we've already resolved the parent
                        archivePath = archivePath.Remove(penultimateSlashIndex + 1);
                    }
                    else
                    {
                        //                        m_log.DebugFormat(
                        //                            "[INVENTORY ARCHIVER]: Found no previously created folder for archive path {0}",
                        //                            originalArchivePath);
                        archivePath = string.Empty;
                        return(rootDestFolder);
                    }
                }
            }

            return(rootDestFolder);
        }
        /// <summary>
        /// Create a set of folders for the given path.
        /// </summary>
        /// <param name="destFolder">
        /// The root folder from which the creation will take place.
        /// </param>
        /// <param name="iarPathExisting">
        /// the part of the iar path that already exists
        /// </param>
        /// <param name="iarPathToReplicate">
        /// The path to replicate in the user's inventory from iar
        /// </param>
        /// <param name="resolvedFolders">
        /// The folders that we have resolved so far for a given archive path.
        /// </param>
        /// <param name="loadedNodes">
        /// Track the inventory nodes created.
        /// </param>
        private void CreateFoldersForPath(
            InventoryFolderBase destFolder,
            string iarPathExisting,
            string iarPathToReplicate,
            Dictionary <string, InventoryFolderBase> resolvedFolders,
            HashSet <InventoryNodeBase> loadedNodes)
        {
            string[] rawDirsToCreate = iarPathToReplicate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);

            for (int i = 0; i < rawDirsToCreate.Length; i++)
            {
//                m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0} from IAR", rawDirsToCreate[i]);

                if (!rawDirsToCreate[i].Contains(ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR))
                {
                    continue;
                }

                int identicalNameIdentifierIndex
                    = rawDirsToCreate[i].LastIndexOf(
                          ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR);

                UUID   oldFolderId   = UUID.Zero;
                string newFolderName = rawDirsToCreate[i].Remove(identicalNameIdentifierIndex);

                newFolderName = InventoryArchiveUtils.UnescapeArchivePath(newFolderName);
                UUID newFolderId = UUID.Random();
                if (UUID.TryParse(rawDirsToCreate[i].Substring(identicalNameIdentifierIndex + 2), out oldFolderId))
                {
                    m_MapIarFolders[oldFolderId] = newFolderId;
                }

                // Asset type has to be Unknown here rather than Folder, otherwise the created folder can't be
                // deleted once the client has relogged.
                // The root folder appears to be labelled AssetType.Folder (shows up as "Category" in the client)
                // even though there is a AssetType.RootCategory
                destFolder
                    = new InventoryFolderBase(
                          newFolderId, newFolderName, m_userInfo.PrincipalID,
                          (short)AssetType.Unknown, destFolder.ID, 1);
                m_InventoryService.AddFolder(destFolder);

                // Record that we have now created this folder
                iarPathExisting += rawDirsToCreate[i] + "/";
                m_log.DebugFormat("[INVENTORY ARCHIVER]: Created folder {0} from IAR", iarPathExisting);
                resolvedFolders[iarPathExisting] = destFolder;

                if (0 == i)
                {
                    loadedNodes.Add(destFolder);
                }
            }
        }
        /// <summary>
        /// Create a set of folders for the given path.
        /// </summary>
        /// <param name="destFolder">
        /// The root folder from which the creation will take place.
        /// </param>
        /// <param name="iarPathExisting">
        /// the part of the iar path that already exists
        /// </param>
        /// <param name="iarPathToReplicate">
        /// The path to replicate in the user's inventory from iar
        /// </param>
        /// <param name="resolvedFolders">
        /// The folders that we have resolved so far for a given archive path.
        /// </param>
        /// <param name="loadedNodes">
        /// Track the inventory nodes created.
        /// </param>
        protected void CreateFoldersForPath(
            InventoryFolderBase destFolder,
            string iarPathExisting,
            string iarPathToReplicate,
            Dictionary <string, InventoryFolderBase> resolvedFolders,
            Dictionary <UUID, InventoryNodeBase> loadedNodes)
        {
            string[] rawDirsToCreate = iarPathToReplicate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries);

            for (int i = 0; i < rawDirsToCreate.Length; i++)
            {
                //                m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0} from IAR", rawDirsToCreate[i]);

                if (!rawDirsToCreate[i].Contains(ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR))
                {
                    continue;
                }

                int identicalNameIdentifierIndex
                    = rawDirsToCreate[i].LastIndexOf(
                          ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR);

                string newFolderName = rawDirsToCreate[i].Remove(identicalNameIdentifierIndex);

                newFolderName = InventoryArchiveUtils.UnescapeArchivePath(newFolderName);
                UUID newFolderId = UUID.Random();

                destFolder
                    = new InventoryFolderBase(
                          newFolderId, newFolderName, m_userInfo.PrincipalID,
                          (short)FolderType.None, destFolder.ID, 1);
                m_InventoryService.AddFolder(destFolder);

                // Record that we have now created this folder
                iarPathExisting += rawDirsToCreate[i] + "/";
                m_log.DebugFormat("[INVENTORY ARCHIVER]: Created folder {0} from IAR", iarPathExisting);
                resolvedFolders[iarPathExisting] = destFolder;

                if (0 == i)
                {
                    loadedNodes[destFolder.ID] = destFolder;
                }
            }
        }
        /// <summary>
        /// Execute the request
        /// </summary>
        /// <remarks>
        /// Only call this once.  To load another IAR, construct another request object.
        /// </remarks>
        /// <returns>
        /// A list of the inventory nodes loaded.  If folders were loaded then only the root folders are
        /// returned
        /// </returns>
        /// <exception cref="System.Exception">Thrown if load fails.</exception>
        public Dictionary <UUID, InventoryNodeBase> Execute()
        {
            try
            {
                Exception reportedException = null;

                string filePath = "ERROR";

                List <InventoryFolderBase> folderCandidates
                    = InventoryArchiveUtils.FindFoldersByPath(
                          m_InventoryService, m_userInfo.PrincipalID, m_invPath);

                if (folderCandidates.Count == 0)
                {
                    // Possibly provide an option later on to automatically create this folder if it does not exist
                    m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath);

                    return(m_loadedNodes);
                }

                m_rootDestinationFolder = folderCandidates[0];
                archive = new TarArchiveReader(m_loadStream);
                byte[] data;
                TarArchiveReader.TarEntryType entryType;

                while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
                {
                    if (filePath == ArchiveConstants.CONTROL_FILE_PATH)
                    {
                        LoadControlFile(filePath, data);
                    }
                    else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
                    {
                        LoadAssetFile(filePath, data);
                    }
                    else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH))
                    {
                        LoadInventoryFile(filePath, entryType, data);
                    }
                }

                archive.Close();
                LoadInventoryLinks();

                m_log.DebugFormat(
                    "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures",
                    m_successfulAssetRestores, m_failedAssetRestores);

                //Alicia: When this is called by LibraryModule or Tests, m_module will be null as event is not required
                if (m_module != null)
                {
                    m_module.TriggerInventoryArchiveLoaded(m_id, true, m_userInfo, m_invPath, m_loadStream, reportedException, m_successfulItemRestores);
                }

                return(m_loadedNodes);
            }
            catch (Exception Ex)
            {
                // Trigger saved event with failed result and exception data
                if (m_module != null)
                {
                    m_module.TriggerInventoryArchiveLoaded(m_id, false, m_userInfo, m_invPath, m_loadStream, Ex, 0);
                }

                return(m_loadedNodes);
            }
            finally
            {
                m_loadStream.Close();
            }
        }
        /// <summary>
        /// Execute the inventory write request
        /// </summary>
        public void Execute()
        {
            InventoryFolderBase inventoryFolder = null;
            InventoryItemBase   inventoryItem   = null;
            InventoryFolderBase rootFolder      = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID);

            bool foundStar = false;

            // Eliminate double slashes and any leading / on the path.
            string[] components
                = m_invPath.Split(
                      new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries);

            int maxComponentIndex = components.Length - 1;

            // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the
            // folder itself.  This may get more sophisicated later on
            if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD)
            {
                foundStar = true;
                maxComponentIndex--;
            }

            m_invPath = String.Empty;
            for (int i = 0; i <= maxComponentIndex; i++)
            {
                m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER;
            }

            // Annoyingly Split actually returns the original string if the input string consists only of delimiters
            // Therefore if we still start with a / after the split, then we need the root folder
            if (m_invPath.Length == 0)
            {
                inventoryFolder = rootFolder;
            }
            else
            {
                m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER));
                List <InventoryFolderBase> candidateFolders
                    = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath);
                if (candidateFolders.Count > 0)
                {
                    inventoryFolder = candidateFolders[0];
                }
            }

            // The path may point to an item instead
            if (inventoryFolder == null)
            {
                inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath);
                //inventoryItem = m_userInfo.RootFolder.FindItemByPath(m_invPath);
            }

            if (null == inventoryFolder && null == inventoryItem)
            {
                // We couldn't find the path indicated
                string errorMessage = string.Format("Aborted save.  Could not find inventory path {0}", m_invPath);
                m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", errorMessage);
                m_module.TriggerInventoryArchiveSaved(
                    m_id, false, m_userInfo, m_invPath, m_saveStream,
                    new Exception(errorMessage));
                return;
            }

            m_archiveWriter = new TarArchiveWriter(m_saveStream);

            try
            {
                if (inventoryFolder != null)
                {
                    m_log.DebugFormat(
                        "[INVENTORY ARCHIVER]: Found folder {0} {1} at {2}",
                        inventoryFolder.Name, inventoryFolder.ID, m_invPath);

                    //recurse through all dirs getting dirs and files
                    SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !foundStar);
                }
                else if (inventoryItem != null)
                {
                    m_log.DebugFormat(
                        "[INVENTORY ARCHIVER]: Found item {0} {1} at {2}",
                        inventoryItem.Name, inventoryItem.ID, m_invPath);

                    SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH);
                }

                // Don't put all this profile information into the archive right now.
                //SaveUsers();
            }
            catch (Exception)
            {
                m_archiveWriter.Close();
                throw;
            }

            new AssetsRequest(
                new AssetsArchiver(m_archiveWriter), m_assetUuids,
                m_scene.AssetService, ReceivedAllAssets).Execute();
        }
Ejemplo n.º 8
0
        /// <summary>
        /// Execute the inventory write request
        /// </summary>
        public void Execute(Dictionary <string, object> options, IUserAccountService userAccountService)
        {
            if (options.ContainsKey("noassets") && (bool)options["noassets"])
            {
                SaveAssets = false;
            }

            // Set Permission filter if flag is set
            if (options.ContainsKey("checkPermissions"))
            {
                Object temp;
                if (options.TryGetValue("checkPermissions", out temp))
                {
                    FilterContent = temp.ToString().ToUpper();
                }
            }

            try
            {
                InventoryFolderBase inventoryFolder = null;
                InventoryItemBase   inventoryItem   = null;
                InventoryFolderBase rootFolder      = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID);

                bool saveFolderContentsOnly = false;

                // Eliminate double slashes and any leading / on the path.
                string[] components
                    = m_invPath.Split(
                          new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries);

                int maxComponentIndex = components.Length - 1;

                // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the
                // folder itself.  This may get more sophisicated later on
                if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD)
                {
                    saveFolderContentsOnly = true;
                    maxComponentIndex--;
                }
                else if (maxComponentIndex == -1)
                {
                    // If the user has just specified "/", then don't save the root "My Inventory" folder.  This is
                    // more intuitive then requiring the user to specify "/*" for this.
                    saveFolderContentsOnly = true;
                }

                m_invPath = String.Empty;
                for (int i = 0; i <= maxComponentIndex; i++)
                {
                    m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER;
                }

                // Annoyingly Split actually returns the original string if the input string consists only of delimiters
                // Therefore if we still start with a / after the split, then we need the root folder
                if (m_invPath.Length == 0)
                {
                    inventoryFolder = rootFolder;
                }
                else
                {
                    m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER));
                    List <InventoryFolderBase> candidateFolders
                        = InventoryArchiveUtils.FindFoldersByPath(m_scene.InventoryService, rootFolder, m_invPath);
                    if (candidateFolders.Count > 0)
                    {
                        inventoryFolder = candidateFolders[0];
                    }
                }

                // The path may point to an item instead
                if (inventoryFolder == null)
                {
                    inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath);
                }

                if (null == inventoryFolder && null == inventoryItem)
                {
                    // We couldn't find the path indicated
                    string    errorMessage = string.Format("Aborted save.  Could not find inventory path {0}", m_invPath);
                    Exception e            = new InventoryArchiverException(errorMessage);
                    m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e, 0, 0);
                    if (m_saveStream != null && m_saveStream.CanWrite)
                    {
                        m_saveStream.Close();
                    }
                    throw e;
                }

                m_archiveWriter = new TarArchiveWriter(m_saveStream);

                m_log.InfoFormat("[INVENTORY ARCHIVER]: Adding control file to archive.");

                // Write out control file.  This has to be done first so that subsequent loaders will see this file first
                // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this
                // not sure how to fix this though, short of going with a completely different file format.
                m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options));

                if (inventoryFolder != null)
                {
                    m_log.DebugFormat(
                        "[INVENTORY ARCHIVER]: Found folder {0} {1} at {2}",
                        inventoryFolder.Name,
                        inventoryFolder.ID,
                        m_invPath == String.Empty ? InventoryFolderImpl.PATH_DELIMITER : m_invPath);

                    //recurse through all dirs getting dirs and files
                    SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !saveFolderContentsOnly, options, userAccountService);
                }
                else if (inventoryItem != null)
                {
                    m_log.DebugFormat(
                        "[INVENTORY ARCHIVER]: Found item {0} {1} at {2}",
                        inventoryItem.Name, inventoryItem.ID, m_invPath);

                    SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH, options, userAccountService);
                }

                // Don't put all this profile information into the archive right now.
                //SaveUsers();

                if (SaveAssets)
                {
                    m_assetGatherer.GatherAll();

                    int errors = m_assetGatherer.FailedUUIDs.Count;

                    m_log.DebugFormat(
                        "[INVENTORY ARCHIVER]: The items to save reference {0} possible assets", m_assetGatherer.GatheredUuids.Count + errors);
                    if (errors > 0)
                    {
                        m_log.DebugFormat("[INVENTORY ARCHIVER]: {0} of these have problems or are not assets and will be ignored", errors);
                    }

                    AssetsRequest ar = new AssetsRequest(
                        new AssetsArchiver(m_archiveWriter),
                        m_assetGatherer.GatheredUuids, m_assetGatherer.FailedUUIDs.Count,
                        m_scene.AssetService,
                        m_scene.UserAccountService, m_scene.RegionInfo.ScopeID,
                        options, ReceivedAllAssets);
                    ar.Execute();
                }
                else
                {
                    m_log.DebugFormat("[INVENTORY ARCHIVER]: Not saving assets since --noassets was specified");

                    ReceivedAllAssets(new List <UUID>(), new List <UUID>(), false);
                }
            }
            catch (Exception)
            {
                m_saveStream.Close();
                throw;
            }
        }
        /// <summary>
        /// Execute the request
        /// </summary>
        /// <returns>
        /// A list of the inventory nodes loaded.  If folders were loaded then only the root folders are
        /// returned
        /// </returns>
        public HashSet <InventoryNodeBase> Execute(bool loadAll)
        {
            try
            {
                string filePath = "ERROR";
                int    successfulAssetRestores = 0;
                int    failedAssetRestores     = 0;
                int    successfulItemRestores  = 0;

                HashSet <InventoryNodeBase> loadedNodes = new HashSet <InventoryNodeBase>();

                List <InventoryFolderBase> folderCandidates
                    = InventoryArchiveUtils.FindFolderByPath(
                          m_registry.RequestModuleInterface <IInventoryService>(), m_userInfo.PrincipalID, m_invPath);

                if (folderCandidates.Count == 0)
                {
                    // Possibly provide an option later on to automatically create this folder if it does not exist
                    m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath);

                    return(loadedNodes);
                }

                InventoryFolderBase rootDestinationFolder = folderCandidates[0];
                archive = new TarArchiveReader(m_loadStream);

                // In order to load identically named folders, we need to keep track of the folders that we have already
                // resolved
                Dictionary <string, InventoryFolderBase> resolvedFolders = new Dictionary <string, InventoryFolderBase>();

                byte[] data;
                TarArchiveReader.TarEntryType entryType;

                while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
                {
                    if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH))
                    {
                        if (LoadAsset(filePath, data))
                        {
                            successfulAssetRestores++;
                        }
                        else
                        {
                            failedAssetRestores++;
                        }

                        if ((successfulAssetRestores) % 50 == 0)
                        {
                            m_log.DebugFormat(
                                "[INVENTORY ARCHIVER]: Loaded {0} assets...",
                                successfulAssetRestores);
                        }
                    }
                    else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH))
                    {
                        filePath = filePath.Substring(ArchiveConstants.INVENTORY_PATH.Length);

                        // Trim off the file portion if we aren't already dealing with a directory path
                        if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
                        {
                            filePath = filePath.Remove(filePath.LastIndexOf("/") + 1);
                        }

                        InventoryFolderBase foundFolder
                            = ReplicateArchivePathToUserInventory(
                                  filePath, rootDestinationFolder, resolvedFolders, loadedNodes);

                        if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType)
                        {
                            InventoryItemBase item = LoadItem(data, foundFolder);

                            if (item != null)
                            {
                                successfulItemRestores++;

                                // If we aren't loading the folder containing the item then well need to update the
                                // viewer separately for that item.
                                if (!loadedNodes.Contains(foundFolder))
                                {
                                    if (loadAll)
                                    {
                                        loadedNodes.Add(item);
                                    }
                                }
                            }
                        }
                    }
                }

                archive.Close();

                m_log.DebugFormat(
                    "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures",
                    successfulAssetRestores, failedAssetRestores);
                m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores);

                return(loadedNodes);
            }
            finally
            {
                m_loadStream.Close();
            }
        }
Ejemplo n.º 10
0
        /// <summary>
        /// Execute the inventory write request
        /// </summary>
        public void Execute(Dictionary <string, object> options, IUserAccountService userAccountService)
        {
            try
            {
                InventoryFolderBase inventoryFolder = null;
                InventoryItemBase   inventoryItem   = null;
                InventoryFolderBase rootFolder      = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID);

                bool saveFolderContentsOnly = false;

                // Eliminate double slashes and any leading / on the path.
                string[] components
                    = m_invPath.Split(
                          new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries);

                int maxComponentIndex = components.Length - 1;

                // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the
                // folder itself.  This may get more sophisicated later on
                if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD)
                {
                    saveFolderContentsOnly = true;
                    maxComponentIndex--;
                }

                m_invPath = String.Empty;
                for (int i = 0; i <= maxComponentIndex; i++)
                {
                    m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER;
                }

                // Annoyingly Split actually returns the original string if the input string consists only of delimiters
                // Therefore if we still start with a / after the split, then we need the root folder
                if (m_invPath.Length == 0)
                {
                    inventoryFolder = rootFolder;
                }
                else
                {
                    m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER));
                    List <InventoryFolderBase> candidateFolders
                        = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath);
                    if (candidateFolders.Count > 0)
                    {
                        inventoryFolder = candidateFolders[0];
                    }
                }

                // The path may point to an item instead
                if (inventoryFolder == null)
                {
                    inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath);
                    //inventoryItem = m_userInfo.RootFolder.FindItemByPath(m_invPath);
                }

                if (null == inventoryFolder && null == inventoryItem)
                {
                    // We couldn't find the path indicated
                    string    errorMessage = string.Format("Aborted save.  Could not find inventory path {0}", m_invPath);
                    Exception e            = new InventoryArchiverException(errorMessage);
                    m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e);
                    throw e;
                }

                m_archiveWriter = new TarArchiveWriter(m_saveStream);

                // Write out control file.  This has to be done first so that subsequent loaders will see this file first
                // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this
                // not sure how to fix this though, short of going with a completely different file format.
                m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options));
                m_log.InfoFormat("[INVENTORY ARCHIVER]: Added control file to archive.");

                if (inventoryFolder != null)
                {
                    m_log.DebugFormat(
                        "[INVENTORY ARCHIVER]: Found folder {0} {1} at {2}",
                        inventoryFolder.Name,
                        inventoryFolder.ID,
                        m_invPath == String.Empty ? InventoryFolderImpl.PATH_DELIMITER : m_invPath);

                    //recurse through all dirs getting dirs and files
                    SaveInvFolder(inventoryFolder, ArchiveConstants.INVENTORY_PATH, !saveFolderContentsOnly, options, userAccountService);
                }
                else if (inventoryItem != null)
                {
                    m_log.DebugFormat(
                        "[INVENTORY ARCHIVER]: Found item {0} {1} at {2}",
                        inventoryItem.Name, inventoryItem.ID, m_invPath);

                    SaveInvItem(inventoryItem, ArchiveConstants.INVENTORY_PATH, options, userAccountService);
                }

                // Don't put all this profile information into the archive right now.
                //SaveUsers();

                new AssetsRequest(
                    new AssetsArchiver(m_archiveWriter),
                    m_assetUuids, m_scene.AssetService,
                    m_scene.UserAccountService, m_scene.RegionInfo.ScopeID,
                    options, ReceivedAllAssets).Execute();
            }
            catch (Exception)
            {
                m_saveStream.Close();
                throw;
            }
        }