29 using System.Collections.Generic;
31 using System.IO.Compression;
32 using System.Reflection;
33 using System.Threading;
36 using System.Xml.Linq;
39 using OpenSim.Framework;
40 using OpenSim.Framework.Serialization;
41 using OpenSim.Framework.Serialization.External;
42 using OpenSim.Region.CoreModules.World.Archiver;
43 using OpenSim.Region.Framework.Scenes;
44 using OpenSim.Region.Framework.Scenes.Serialization;
45 using OpenSim.Region.Framework.Interfaces;
46 using OpenSim.Services.Interfaces;
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
58 public static int MAX_MAJOR_VERSION = 1;
63 private string m_invPath;
84 private Stream m_loadStream;
89 public bool ControlFileLoaded {
get;
private set; }
95 public bool EnforceControlFileCheck {
get;
private set; }
112 protected HashSet<InventoryNodeBase> m_loadedNodes =
new HashSet<InventoryNodeBase>();
118 Dictionary <string, InventoryFolderBase> m_resolvedFolders =
new Dictionary<string, InventoryFolderBase>();
124 protected Dictionary<UUID, UUID> m_creatorIdForAssetId =
new Dictionary<UUID, UUID>();
128 : this(
UUID.Zero, null,
158 m_InventoryService = inv;
159 m_AssetService = assets;
160 m_UserAccountService = uacc;
162 m_userInfo = userInfo;
164 m_loadStream = loadStream;
170 ControlFileLoaded =
true;
188 Exception reportedException = null;
190 string filePath =
"ERROR";
192 List<InventoryFolderBase> folderCandidates
193 = InventoryArchiveUtils.FindFoldersByPath(
194 m_InventoryService, m_userInfo.PrincipalID, m_invPath);
196 if (folderCandidates.Count == 0)
199 m_log.ErrorFormat(
"[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath);
201 return m_loadedNodes;
204 m_rootDestinationFolder = folderCandidates[0];
207 TarArchiveReader.TarEntryType entryType;
209 while ((data = archive.ReadEntry(out filePath, out entryType)) != null)
213 LoadControlFile(filePath, data);
217 LoadAssetFile(filePath, data);
221 LoadInventoryFile(filePath, entryType, data);
228 "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures",
229 m_successfulAssetRestores, m_failedAssetRestores);
233 m_module.TriggerInventoryArchiveLoaded(m_id,
true, m_userInfo, m_invPath, m_loadStream, reportedException, m_successfulItemRestores);
235 return m_loadedNodes;
240 if (m_module != null)
241 m_module.TriggerInventoryArchiveLoaded(m_id,
false, m_userInfo, m_invPath, m_loadStream, Ex, 0);
243 return m_loadedNodes;
247 m_loadStream.Close();
253 if (m_loadStream != null)
254 m_loadStream.Close();
273 Dictionary <string, InventoryFolderBase> resolvedFolders,
274 HashSet<InventoryNodeBase> loadedNodes)
276 string iarPathExisting = iarPath;
282 = ResolveDestinationFolder(rootDestFolder, ref iarPathExisting, resolvedFolders);
288 string iarPathToCreate = iarPath.Substring(iarPathExisting.Length);
289 CreateFoldersForPath(destFolder, iarPathExisting, iarPathToCreate, resolvedFolders, loadedNodes);
316 ref
string archivePath,
317 Dictionary <string, InventoryFolderBase> resolvedFolders)
321 while (archivePath.Length > 0)
325 if (resolvedFolders.ContainsKey(archivePath))
329 return resolvedFolders[archivePath];
337 string plainPath = ArchiveConstants.ExtractPlainPathFromIarPath(archivePath);
338 List<InventoryFolderBase> folderCandidates
339 = InventoryArchiveUtils.FindFoldersByPath(
340 m_InventoryService, m_userInfo.PrincipalID, plainPath);
342 if (folderCandidates.Count != 0)
345 resolvedFolders[archivePath] = destFolder;
351 int penultimateSlashIndex = archivePath.LastIndexOf(
"/", archivePath.Length - 2);
353 if (penultimateSlashIndex >= 0)
356 archivePath = archivePath.Remove(penultimateSlashIndex + 1);
363 archivePath = string.Empty;
364 return rootDestFolder;
369 return rootDestFolder;
392 string iarPathExisting,
393 string iarPathToReplicate,
394 Dictionary <string, InventoryFolderBase> resolvedFolders,
395 HashSet<InventoryNodeBase> loadedNodes)
397 string[] rawDirsToCreate = iarPathToReplicate.Split(
new char[] {
'/' }, StringSplitOptions.RemoveEmptyEntries);
399 for (
int i = 0; i < rawDirsToCreate.Length; i++)
406 int identicalNameIdentifierIndex
407 = rawDirsToCreate[i].LastIndexOf(
408 ArchiveConstants.INVENTORY_NODE_NAME_COMPONENT_SEPARATOR);
410 string newFolderName = rawDirsToCreate[i].Remove(identicalNameIdentifierIndex);
412 newFolderName = InventoryArchiveUtils.UnescapeArchivePath(newFolderName);
413 UUID newFolderId = UUID.Random();
417 newFolderId, newFolderName, m_userInfo.PrincipalID,
418 (
short)FolderType.None, destFolder.ID, 1);
419 m_InventoryService.AddFolder(destFolder);
422 iarPathExisting += rawDirsToCreate[i] +
"/";
423 m_log.DebugFormat(
"[INVENTORY ARCHIVER]: Created folder {0} from IAR", iarPathExisting);
424 resolvedFolders[iarPathExisting] = destFolder;
427 loadedNodes.Add(destFolder);
443 item.ID = UUID.Random();
445 UUID ospResolvedId = OspResolver.ResolveOspa(item.CreatorId, m_UserAccountService);
446 if (
UUID.Zero != ospResolvedId)
454 item.CreatorId = ospResolvedId.ToString();
455 item.CreatorData = string.Empty;
459 item.CreatorId = m_userInfo.PrincipalID.ToString();
463 item.Owner = m_userInfo.PrincipalID;
466 item.Folder = loadFolder.ID;
473 m_creatorIdForAssetId[item.AssetID] = item.CreatorIdAsUuid;
475 if (!m_InventoryService.AddItem(item))
476 m_log.WarnFormat(
"[INVENTORY ARCHIVER]: Unable to save item {0} in folder {1}", item.
Name, item.
Folder);
487 private bool LoadAsset(
string assetPath, byte[] data)
491 string filename = assetPath.Remove(0, ArchiveConstants.ASSETS_PATH.Length);
492 int i = filename.LastIndexOf(ArchiveConstants.ASSET_EXTENSION_SEPARATOR);
497 "[INVENTORY ARCHIVER]: Could not find extension information in asset path {0} since it's missing the separator {1}. Skipping",
498 assetPath, ArchiveConstants.ASSET_EXTENSION_SEPARATOR);
503 string extension = filename.Substring(i);
504 string rawUuid = filename.Remove(filename.Length - extension.Length);
509 sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension];
511 if (assetType == (sbyte)AssetType.Unknown)
513 m_log.WarnFormat(
"[INVENTORY ARCHIVER]: Importing {0} byte asset {1} with unknown type", data.Length, assetId);
515 else if (assetType == (sbyte)AssetType.Object)
517 if (m_creatorIdForAssetId.ContainsKey(assetId))
519 data = SceneObjectSerializer.ModifySerializedObject(assetId, data,
521 bool modified =
false;
527 sop.CreatorID = m_creatorIdForAssetId[assetId];
545 m_AssetService.Store(asset);
552 "[INVENTORY ARCHIVER]: Tried to dearchive data with path {0} with an unknown type extension {1}",
553 assetPath, extension);
566 XDocument doc = XDocument.Parse(Encoding.ASCII.GetString(data));
567 XElement archiveElement = doc.Element(
"archive");
568 int majorVersion = int.Parse(archiveElement.Attribute(
"major_version").
Value);
569 int minorVersion = int.Parse(archiveElement.Attribute(
"minor_version").
Value);
570 string version = string.Format(
"{0}.{1}", majorVersion, minorVersion);
572 if (majorVersion > MAX_MAJOR_VERSION)
576 "The IAR you are trying to load has major version number of {0} but this version of OpenSim can only load IARs with major version number {1} and below",
577 majorVersion, MAX_MAJOR_VERSION));
580 ControlFileLoaded =
true;
581 m_log.InfoFormat(
"[INVENTORY ARCHIVER]: Loading IAR with version {0}", version);
592 if (!ControlFileLoaded)
595 "The IAR you are trying to load does not list {0} before {1}. Aborting load",
601 "The IAR you are trying to load does not list all {0} before {1}. Aborting load",
604 path = path.Substring(ArchiveConstants.INVENTORY_PATH.Length);
608 path = path.Remove(path.LastIndexOf(
"/") + 1);
611 = ReplicateArchivePathToUserInventory(
612 path, m_rootDestinationFolder, m_resolvedFolders, m_loadedNodes);
620 m_successfulItemRestores++;
624 if (!m_loadedNodes.Contains(foundFolder))
625 m_loadedNodes.Add(item);
629 m_inventoryNodesLoaded =
true;
639 if (!ControlFileLoaded)
642 "The IAR you are trying to load does not list {0} before {1}. Aborting load",
645 if (!m_inventoryNodesLoaded)
648 "The IAR you are trying to load does not list all {0} before {1}. Aborting load",
651 if (LoadAsset(path, data))
652 m_successfulAssetRestores++;
654 m_failedAssetRestores++;
656 if ((m_successfulAssetRestores) % 50 == 0)
658 "[INVENTORY ARCHIVER]: Loaded {0} assets...",
659 m_successfulAssetRestores);
661 m_assetsLoaded =
true;
InventoryArchiveReadRequest(UUID id, InventoryArchiverModule module, IInventoryService inv, IAssetService assets, IUserAccountService uacc, UserAccount userInfo, string invPath, string loadPath, bool merge)
Temporary code to do the bare minimum required to read a tar archive for our purposes ...
HashSet< InventoryNodeBase > Execute()
Execute the request
InventoryArchiveReadRequest(IInventoryService inv, IAssetService assets, IUserAccountService uacc, UserAccount userInfo, string invPath, string loadPath, bool merge)
Constants for the archiving module
InventoryItemBase LoadItem(byte[] data, InventoryFolderBase loadFolder)
Load an item from the archive
InventoryFolderBase ReplicateArchivePathToUserInventory(string iarPath, InventoryFolderBase rootDestFolder, Dictionary< string, InventoryFolderBase > resolvedFolders, HashSet< InventoryNodeBase > loadedNodes)
Replicate the inventory paths in the archive to the user's inventory as necessary.
int m_successfulItemRestores
InventoryFolderBase ResolveDestinationFolder(InventoryFolderBase rootDestFolder, ref string archivePath, Dictionary< string, InventoryFolderBase > resolvedFolders)
Resolve a destination folder
OpenSim.Framework.Serialization.TarArchiveReader TarArchiveReader
InventoryArchiveReadRequest(UUID id, InventoryArchiverModule module, IInventoryService inv, IAssetService assets, IUserAccountService uacc, UserAccount userInfo, string invPath, Stream loadStream, bool merge)
bool m_merge
Do we want to merge this load with existing inventory?
const string CONTROL_FILE_PATH
bool m_inventoryNodesLoaded
void LoadAssetFile(string path, byte[] data)
Load asset file
static readonly IDictionary< string, sbyte > EXTENSION_TO_ASSET_TYPE
Ionic.Zlib.GZipStream GZipStream
int m_successfulAssetRestores
int m_failedAssetRestores
IAssetService m_AssetService
void LoadControlFile(string path, byte[] data)
Load control file
Asset class. All Assets are reference by this class or a class derived from this class ...
IUserAccountService m_UserAccountService
This module loads and saves OpenSimulator inventory archives
string CreatorData
Data about the creator in the form home_url;name
IInventoryService m_InventoryService
const string INVENTORY_NODE_NAME_COMPONENT_SEPARATOR
InventoryFolderBase m_rootDestinationFolder
Root destination folder for the IAR load.
void CreateFoldersForPath(InventoryFolderBase destFolder, string iarPathExisting, string iarPathToReplicate, Dictionary< string, InventoryFolderBase > resolvedFolders, HashSet< InventoryNodeBase > loadedNodes)
Create a set of folders for the given path.
Inventory Item - contains all the properties associated with an individual inventory piece...
string CreatorData
Extended creator information of the form <profile url>="">;<name>
void LoadInventoryFile(string path, TarArchiveReader.TarEntryType entryType, byte[] data)
Load inventory file
Interactive OpenSim region server
virtual string Name
The name of the node (64 characters or less)
Ionic.Zlib.CompressionMode CompressionMode
const string INVENTORY_PATH