diff options
Diffstat (limited to 'OpenSim/Grid/AssetInventoryServer/Extensions/SimpleInventory.cs')
-rw-r--r-- | OpenSim/Grid/AssetInventoryServer/Extensions/SimpleInventory.cs | 602 |
1 files changed, 602 insertions, 0 deletions
diff --git a/OpenSim/Grid/AssetInventoryServer/Extensions/SimpleInventory.cs b/OpenSim/Grid/AssetInventoryServer/Extensions/SimpleInventory.cs new file mode 100644 index 0000000..f8acdea --- /dev/null +++ b/OpenSim/Grid/AssetInventoryServer/Extensions/SimpleInventory.cs | |||
@@ -0,0 +1,602 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008 Intel Corporation | ||
3 | * All rights reserved. | ||
4 | * Redistribution and use in source and binary forms, with or without | ||
5 | * modification, are permitted provided that the following conditions | ||
6 | * are met: | ||
7 | * | ||
8 | * -- Redistributions of source code must retain the above copyright | ||
9 | * notice, this list of conditions and the following disclaimer. | ||
10 | * -- Redistributions in binary form must reproduce the above copyright | ||
11 | * notice, this list of conditions and the following disclaimer in the | ||
12 | * documentation and/or other materials provided with the distribution. | ||
13 | * -- Neither the name of the Intel Corporation nor the names of its | ||
14 | * contributors may be used to endorse or promote products derived from | ||
15 | * this software without specific prior written permission. | ||
16 | * | ||
17 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
18 | * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
19 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A | ||
20 | * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE INTEL OR ITS | ||
21 | * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, | ||
22 | * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, | ||
23 | * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR | ||
24 | * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF | ||
25 | * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING | ||
26 | * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||
27 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
28 | */ | ||
29 | |||
30 | using System; | ||
31 | using System.Collections.Generic; | ||
32 | using System.Net; | ||
33 | using System.IO; | ||
34 | using System.Text; | ||
35 | using ExtensionLoader; | ||
36 | using OpenMetaverse; | ||
37 | using OpenMetaverse.StructuredData; | ||
38 | |||
39 | namespace OpenSim.Grid.AssetInventoryServer.Extensions | ||
40 | { | ||
41 | public class SimpleInventory : IExtension<AssetInventoryServer>, IInventoryProvider | ||
42 | { | ||
43 | const string EXTENSION_NAME = "SimpleInventory"; // Used for metrics reporting | ||
44 | const string DEFAULT_INVENTORY_DIR = "SimpleInventory"; | ||
45 | |||
46 | AssetInventoryServer server; | ||
47 | Dictionary<Uri, InventoryCollection> inventories = new Dictionary<Uri, InventoryCollection>(); | ||
48 | Dictionary<Uri, List<InventoryItem>> activeGestures = new Dictionary<Uri, List<InventoryItem>>(); | ||
49 | Utils.InventoryItemSerializer itemSerializer = new Utils.InventoryItemSerializer(); | ||
50 | Utils.InventoryFolderSerializer folderSerializer = new Utils.InventoryFolderSerializer(); | ||
51 | |||
52 | public SimpleInventory() | ||
53 | { | ||
54 | } | ||
55 | |||
56 | #region Required Interfaces | ||
57 | |||
58 | public void Start(AssetInventoryServer server) | ||
59 | { | ||
60 | this.server = server; | ||
61 | |||
62 | LoadFiles(DEFAULT_INVENTORY_DIR); | ||
63 | |||
64 | Logger.Log.InfoFormat("Initialized the inventory index with data for {0} avatars", | ||
65 | inventories.Count); | ||
66 | } | ||
67 | |||
68 | public void Stop() | ||
69 | { | ||
70 | } | ||
71 | |||
72 | public BackendResponse TryFetchItem(Uri owner, UUID itemID, out InventoryItem item) | ||
73 | { | ||
74 | item = null; | ||
75 | BackendResponse ret; | ||
76 | |||
77 | InventoryCollection collection; | ||
78 | if (inventories.TryGetValue(owner, out collection) && collection.Items.TryGetValue(itemID, out item)) | ||
79 | ret = BackendResponse.Success; | ||
80 | else | ||
81 | ret = BackendResponse.NotFound; | ||
82 | |||
83 | server.MetricsProvider.LogInventoryFetch(EXTENSION_NAME, ret, owner, itemID, false, DateTime.Now); | ||
84 | return ret; | ||
85 | } | ||
86 | |||
87 | public BackendResponse TryFetchFolder(Uri owner, UUID folderID, out InventoryFolder folder) | ||
88 | { | ||
89 | folder = null; | ||
90 | BackendResponse ret; | ||
91 | |||
92 | InventoryCollection collection; | ||
93 | if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder)) | ||
94 | ret = BackendResponse.Success; | ||
95 | else | ||
96 | ret = BackendResponse.NotFound; | ||
97 | |||
98 | server.MetricsProvider.LogInventoryFetch(EXTENSION_NAME, ret, owner, folderID, true, DateTime.Now); | ||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | public BackendResponse TryFetchFolderContents(Uri owner, UUID folderID, out InventoryCollection contents) | ||
103 | { | ||
104 | contents = null; | ||
105 | BackendResponse ret; | ||
106 | |||
107 | InventoryCollection collection; | ||
108 | InventoryFolder folder; | ||
109 | |||
110 | if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder)) | ||
111 | { | ||
112 | contents = new InventoryCollection(); | ||
113 | contents.UserID = collection.UserID; | ||
114 | contents.Folders = new Dictionary<UUID, InventoryFolder>(); | ||
115 | contents.Items = new Dictionary<UUID, InventoryItem>(); | ||
116 | |||
117 | foreach (InventoryBase invBase in folder.Children.Values) | ||
118 | { | ||
119 | if (invBase is InventoryItem) | ||
120 | { | ||
121 | InventoryItem invItem = invBase as InventoryItem; | ||
122 | contents.Items.Add(invItem.ID, invItem); | ||
123 | } | ||
124 | else | ||
125 | { | ||
126 | InventoryFolder invFolder = invBase as InventoryFolder; | ||
127 | contents.Folders.Add(invFolder.ID, invFolder); | ||
128 | } | ||
129 | } | ||
130 | |||
131 | ret = BackendResponse.Success; | ||
132 | } | ||
133 | else | ||
134 | { | ||
135 | ret = BackendResponse.NotFound; | ||
136 | } | ||
137 | |||
138 | server.MetricsProvider.LogInventoryFetchFolderContents(EXTENSION_NAME, ret, owner, folderID, DateTime.Now); | ||
139 | return ret; | ||
140 | } | ||
141 | |||
142 | public BackendResponse TryFetchFolderList(Uri owner, out List<InventoryFolder> folders) | ||
143 | { | ||
144 | folders = null; | ||
145 | BackendResponse ret; | ||
146 | |||
147 | InventoryCollection collection; | ||
148 | if (inventories.TryGetValue(owner, out collection)) | ||
149 | { | ||
150 | folders = new List<InventoryFolder>(collection.Folders.Values); | ||
151 | return BackendResponse.Success; | ||
152 | } | ||
153 | else | ||
154 | { | ||
155 | ret = BackendResponse.NotFound; | ||
156 | } | ||
157 | |||
158 | server.MetricsProvider.LogInventoryFetchFolderList(EXTENSION_NAME, ret, owner, DateTime.Now); | ||
159 | return ret; | ||
160 | } | ||
161 | |||
162 | public BackendResponse TryFetchInventory(Uri owner, out InventoryCollection inventory) | ||
163 | { | ||
164 | inventory = null; | ||
165 | BackendResponse ret; | ||
166 | |||
167 | if (inventories.TryGetValue(owner, out inventory)) | ||
168 | ret = BackendResponse.Success; | ||
169 | else | ||
170 | ret = BackendResponse.NotFound; | ||
171 | |||
172 | server.MetricsProvider.LogInventoryFetchInventory(EXTENSION_NAME, ret, owner, DateTime.Now); | ||
173 | return ret; | ||
174 | } | ||
175 | |||
176 | public BackendResponse TryFetchActiveGestures(Uri owner, out List<InventoryItem> gestures) | ||
177 | { | ||
178 | gestures = null; | ||
179 | BackendResponse ret; | ||
180 | |||
181 | if (activeGestures.TryGetValue(owner, out gestures)) | ||
182 | ret = BackendResponse.Success; | ||
183 | else | ||
184 | ret = BackendResponse.NotFound; | ||
185 | |||
186 | server.MetricsProvider.LogInventoryFetchActiveGestures(EXTENSION_NAME, ret, owner, DateTime.Now); | ||
187 | return ret; | ||
188 | } | ||
189 | |||
190 | public BackendResponse TryCreateItem(Uri owner, InventoryItem item) | ||
191 | { | ||
192 | BackendResponse ret; | ||
193 | |||
194 | InventoryCollection collection; | ||
195 | if (inventories.TryGetValue(owner, out collection)) | ||
196 | { | ||
197 | // Delete this item first if it already exists | ||
198 | InventoryItem oldItem; | ||
199 | if (collection.Items.TryGetValue(item.ID, out oldItem)) | ||
200 | TryDeleteItem(owner, item.ID); | ||
201 | |||
202 | try | ||
203 | { | ||
204 | // Create the file | ||
205 | SaveItem(item); | ||
206 | |||
207 | // Add the item to the collection | ||
208 | lock (collection) collection.Items[item.ID] = item; | ||
209 | |||
210 | // Add the item to its parent folder | ||
211 | InventoryFolder parent; | ||
212 | if (collection.Folders.TryGetValue(item.Folder, out parent)) | ||
213 | lock (parent.Children) parent.Children.Add(item.ID, item); | ||
214 | |||
215 | // Add active gestures to our list | ||
216 | if (item.InvType == (int)InventoryType.Gesture && item.Flags == 1) | ||
217 | { | ||
218 | lock (activeGestures) | ||
219 | activeGestures[owner].Add(item); | ||
220 | } | ||
221 | |||
222 | ret = BackendResponse.Success; | ||
223 | } | ||
224 | catch (Exception ex) | ||
225 | { | ||
226 | Logger.Log.Error(ex.Message); | ||
227 | ret = BackendResponse.Failure; | ||
228 | } | ||
229 | } | ||
230 | else | ||
231 | { | ||
232 | return BackendResponse.NotFound; | ||
233 | } | ||
234 | |||
235 | server.MetricsProvider.LogInventoryCreate(EXTENSION_NAME, ret, owner, false, DateTime.Now); | ||
236 | return ret; | ||
237 | } | ||
238 | |||
239 | public BackendResponse TryCreateFolder(Uri owner, InventoryFolder folder) | ||
240 | { | ||
241 | BackendResponse ret; | ||
242 | |||
243 | InventoryCollection collection; | ||
244 | if (inventories.TryGetValue(owner, out collection)) | ||
245 | { | ||
246 | // Delete this folder first if it already exists | ||
247 | InventoryFolder oldFolder; | ||
248 | if (collection.Folders.TryGetValue(folder.ID, out oldFolder)) | ||
249 | TryDeleteFolder(owner, folder.ID); | ||
250 | |||
251 | try | ||
252 | { | ||
253 | // Create the file | ||
254 | SaveFolder(folder); | ||
255 | |||
256 | // Add the folder to the collection | ||
257 | lock (collection) collection.Folders[folder.ID] = folder; | ||
258 | |||
259 | // Add the folder to its parent folder | ||
260 | InventoryFolder parent; | ||
261 | if (collection.Folders.TryGetValue(folder.ParentID, out parent)) | ||
262 | lock (parent.Children) parent.Children.Add(folder.ID, folder); | ||
263 | |||
264 | ret = BackendResponse.Success; | ||
265 | } | ||
266 | catch (Exception ex) | ||
267 | { | ||
268 | Logger.Log.Error(ex.Message); | ||
269 | ret = BackendResponse.Failure; | ||
270 | } | ||
271 | } | ||
272 | else | ||
273 | { | ||
274 | ret = BackendResponse.NotFound; | ||
275 | } | ||
276 | |||
277 | server.MetricsProvider.LogInventoryCreate(EXTENSION_NAME, ret, owner, true, DateTime.Now); | ||
278 | return ret; | ||
279 | } | ||
280 | |||
281 | public BackendResponse TryCreateInventory(Uri owner, InventoryFolder rootFolder) | ||
282 | { | ||
283 | BackendResponse ret; | ||
284 | |||
285 | lock (inventories) | ||
286 | { | ||
287 | if (!inventories.ContainsKey(owner)) | ||
288 | { | ||
289 | InventoryCollection collection = new InventoryCollection(); | ||
290 | collection.UserID = rootFolder.Owner; | ||
291 | collection.Folders = new Dictionary<UUID, InventoryFolder>(); | ||
292 | collection.Folders.Add(rootFolder.ID, rootFolder); | ||
293 | collection.Items = new Dictionary<UUID, InventoryItem>(); | ||
294 | |||
295 | inventories.Add(owner, collection); | ||
296 | |||
297 | ret = BackendResponse.Success; | ||
298 | } | ||
299 | else | ||
300 | { | ||
301 | ret = BackendResponse.Failure; | ||
302 | } | ||
303 | } | ||
304 | |||
305 | if (ret == BackendResponse.Success) | ||
306 | { | ||
307 | string path = Path.Combine(DEFAULT_INVENTORY_DIR, rootFolder.Owner.ToString()); | ||
308 | try | ||
309 | { | ||
310 | // Create the directory for this agent | ||
311 | Directory.CreateDirectory(path); | ||
312 | |||
313 | // Create an index.txt containing the UUID and URI for this agent | ||
314 | string[] index = new string[] { rootFolder.Owner.ToString(), owner.ToString() }; | ||
315 | File.WriteAllLines(Path.Combine(path, "index.txt"), index); | ||
316 | |||
317 | // Create the root folder file | ||
318 | SaveFolder(rootFolder); | ||
319 | } | ||
320 | catch (Exception ex) | ||
321 | { | ||
322 | Logger.Log.Error(ex.Message); | ||
323 | ret = BackendResponse.Failure; | ||
324 | } | ||
325 | } | ||
326 | |||
327 | server.MetricsProvider.LogInventoryCreateInventory(EXTENSION_NAME, ret, DateTime.Now); | ||
328 | return ret; | ||
329 | } | ||
330 | |||
331 | public BackendResponse TryDeleteItem(Uri owner, UUID itemID) | ||
332 | { | ||
333 | BackendResponse ret; | ||
334 | |||
335 | InventoryCollection collection; | ||
336 | InventoryItem item; | ||
337 | if (inventories.TryGetValue(owner, out collection) && collection.Items.TryGetValue(itemID, out item)) | ||
338 | { | ||
339 | // Remove the item from its parent folder | ||
340 | InventoryFolder parent; | ||
341 | if (collection.Folders.TryGetValue(item.Folder, out parent)) | ||
342 | lock (parent.Children) parent.Children.Remove(itemID); | ||
343 | |||
344 | // Remove the item from the collection | ||
345 | lock (collection) collection.Items.Remove(itemID); | ||
346 | |||
347 | // Remove from the active gestures list if applicable | ||
348 | if (item.InvType == (int)InventoryType.Gesture) | ||
349 | { | ||
350 | lock (activeGestures) | ||
351 | { | ||
352 | for (int i = 0; i < activeGestures[owner].Count; i++) | ||
353 | { | ||
354 | if (activeGestures[owner][i].ID == itemID) | ||
355 | { | ||
356 | activeGestures[owner].RemoveAt(i); | ||
357 | break; | ||
358 | } | ||
359 | } | ||
360 | } | ||
361 | } | ||
362 | |||
363 | // Delete the file. We don't know exactly what the file name is, | ||
364 | // so search for it | ||
365 | string path = PathFromURI(owner); | ||
366 | string[] matches = Directory.GetFiles(path, String.Format("*{0}.item", itemID), SearchOption.TopDirectoryOnly); | ||
367 | foreach (string match in matches) | ||
368 | { | ||
369 | try { File.Delete(match); } | ||
370 | catch (Exception ex) { Logger.Log.ErrorFormat("Failed to delete file {0}: {1}", match, ex.Message); } | ||
371 | } | ||
372 | |||
373 | ret = BackendResponse.Success; | ||
374 | } | ||
375 | else | ||
376 | { | ||
377 | ret = BackendResponse.NotFound; | ||
378 | } | ||
379 | |||
380 | server.MetricsProvider.LogInventoryDelete(EXTENSION_NAME, ret, owner, itemID, false, DateTime.Now); | ||
381 | return ret; | ||
382 | } | ||
383 | |||
384 | public BackendResponse TryDeleteFolder(Uri owner, UUID folderID) | ||
385 | { | ||
386 | BackendResponse ret; | ||
387 | |||
388 | InventoryCollection collection; | ||
389 | InventoryFolder folder; | ||
390 | if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder)) | ||
391 | { | ||
392 | // Remove the folder from its parent folder | ||
393 | InventoryFolder parent; | ||
394 | if (collection.Folders.TryGetValue(folder.ParentID, out parent)) | ||
395 | lock (parent.Children) parent.Children.Remove(folderID); | ||
396 | |||
397 | // Remove the folder from the collection | ||
398 | lock (collection) collection.Items.Remove(folderID); | ||
399 | |||
400 | // Delete the folder file. We don't know exactly what the file name is, | ||
401 | // so search for it | ||
402 | string path = PathFromURI(owner); | ||
403 | string[] matches = Directory.GetFiles(path, String.Format("*{0}.folder", folderID), SearchOption.TopDirectoryOnly); | ||
404 | foreach (string match in matches) | ||
405 | { | ||
406 | try { File.Delete(match); } | ||
407 | catch (Exception ex) { Logger.Log.ErrorFormat("Failed to delete folder file {0}: {1}", match, ex.Message); } | ||
408 | } | ||
409 | |||
410 | ret = BackendResponse.Success; | ||
411 | } | ||
412 | else | ||
413 | { | ||
414 | ret = BackendResponse.NotFound; | ||
415 | } | ||
416 | |||
417 | server.MetricsProvider.LogInventoryDelete(EXTENSION_NAME, ret, owner, folderID, true, DateTime.Now); | ||
418 | return ret; | ||
419 | } | ||
420 | |||
421 | public BackendResponse TryPurgeFolder(Uri owner, UUID folderID) | ||
422 | { | ||
423 | BackendResponse ret; | ||
424 | |||
425 | InventoryCollection collection; | ||
426 | InventoryFolder folder; | ||
427 | if (inventories.TryGetValue(owner, out collection) && collection.Folders.TryGetValue(folderID, out folder)) | ||
428 | { | ||
429 | // Delete all of the folder children | ||
430 | foreach (InventoryBase obj in new List<InventoryBase>(folder.Children.Values)) | ||
431 | { | ||
432 | if (obj is InventoryItem) | ||
433 | { | ||
434 | TryDeleteItem(owner, (obj as InventoryItem).ID); | ||
435 | } | ||
436 | else | ||
437 | { | ||
438 | InventoryFolder childFolder = obj as InventoryFolder; | ||
439 | TryPurgeFolder(owner, childFolder.ID); | ||
440 | TryDeleteFolder(owner, childFolder.ID); | ||
441 | } | ||
442 | } | ||
443 | |||
444 | ret = BackendResponse.Success; | ||
445 | } | ||
446 | else | ||
447 | { | ||
448 | ret = BackendResponse.NotFound; | ||
449 | } | ||
450 | |||
451 | server.MetricsProvider.LogInventoryPurgeFolder(EXTENSION_NAME, ret, owner, folderID, DateTime.Now); | ||
452 | return ret; | ||
453 | } | ||
454 | |||
455 | #endregion Required Interfaces | ||
456 | |||
457 | void SaveItem(InventoryItem item) | ||
458 | { | ||
459 | string filename = String.Format("{0}-{1}.item", SanitizeFilename(item.Name), item.ID); | ||
460 | |||
461 | string path = Path.Combine(DEFAULT_INVENTORY_DIR, item.Owner.ToString()); | ||
462 | path = Path.Combine(path, filename); | ||
463 | |||
464 | using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write)) | ||
465 | { | ||
466 | itemSerializer.Serialize(stream, item); | ||
467 | stream.Flush(); | ||
468 | } | ||
469 | } | ||
470 | |||
471 | void SaveFolder(InventoryFolder folder) | ||
472 | { | ||
473 | string filename = String.Format("{0}-{1}.folder", SanitizeFilename(folder.Name), folder.ID); | ||
474 | |||
475 | string path = Path.Combine(DEFAULT_INVENTORY_DIR, folder.Owner.ToString()); | ||
476 | path = Path.Combine(path, filename); | ||
477 | |||
478 | using (FileStream stream = new FileStream(path, FileMode.Create, FileAccess.Write)) | ||
479 | { | ||
480 | folderSerializer.Serialize(stream, folder); | ||
481 | stream.Flush(); | ||
482 | } | ||
483 | } | ||
484 | |||
485 | string SanitizeFilename(string filename) | ||
486 | { | ||
487 | string output = filename; | ||
488 | |||
489 | if (output.Length > 64) | ||
490 | output = output.Substring(0, 64); | ||
491 | |||
492 | foreach (char i in Path.GetInvalidFileNameChars()) | ||
493 | output = output.Replace(i, '_'); | ||
494 | |||
495 | return output; | ||
496 | } | ||
497 | |||
498 | static string PathFromURI(Uri uri) | ||
499 | { | ||
500 | byte[] hash = OpenMetaverse.Utils.SHA1(Encoding.UTF8.GetBytes(uri.ToString())); | ||
501 | StringBuilder digest = new StringBuilder(40); | ||
502 | |||
503 | // Convert the hash to a hex string | ||
504 | foreach (byte b in hash) | ||
505 | digest.AppendFormat(OpenMetaverse.Utils.EnUsCulture, "{0:x2}", b); | ||
506 | |||
507 | return Path.Combine(DEFAULT_INVENTORY_DIR, digest.ToString()); | ||
508 | } | ||
509 | |||
510 | void LoadFiles(string folder) | ||
511 | { | ||
512 | // Try to create the directory if it doesn't already exist | ||
513 | if (!Directory.Exists(folder)) | ||
514 | { | ||
515 | try { Directory.CreateDirectory(folder); } | ||
516 | catch (Exception ex) | ||
517 | { | ||
518 | Logger.Log.Warn(ex.Message); | ||
519 | return; | ||
520 | } | ||
521 | } | ||
522 | |||
523 | try | ||
524 | { | ||
525 | string[] agentFolders = Directory.GetDirectories(DEFAULT_INVENTORY_DIR); | ||
526 | |||
527 | for (int i = 0; i < agentFolders.Length; i++) | ||
528 | { | ||
529 | string foldername = agentFolders[i]; | ||
530 | string indexPath = Path.Combine(foldername, "index.txt"); | ||
531 | UUID ownerID = UUID.Zero; | ||
532 | Uri owner = null; | ||
533 | |||
534 | try | ||
535 | { | ||
536 | string[] index = File.ReadAllLines(indexPath); | ||
537 | ownerID = UUID.Parse(index[0]); | ||
538 | owner = new Uri(index[1]); | ||
539 | } | ||
540 | catch (Exception ex) | ||
541 | { | ||
542 | Logger.Log.WarnFormat("Failed loading the index file {0}: {1}", indexPath, ex.Message); | ||
543 | } | ||
544 | |||
545 | if (ownerID != UUID.Zero && owner != null) | ||
546 | { | ||
547 | // Initialize the active gestures list for this agent | ||
548 | activeGestures.Add(owner, new List<InventoryItem>()); | ||
549 | |||
550 | InventoryCollection collection = new InventoryCollection(); | ||
551 | collection.UserID = ownerID; | ||
552 | |||
553 | // Load all of the folders for this agent | ||
554 | string[] folders = Directory.GetFiles(foldername, "*.folder", SearchOption.TopDirectoryOnly); | ||
555 | collection.Folders = new Dictionary<UUID,InventoryFolder>(folders.Length); | ||
556 | |||
557 | for (int j = 0; j < folders.Length; j++) | ||
558 | { | ||
559 | InventoryFolder invFolder = (InventoryFolder)folderSerializer.Deserialize( | ||
560 | new FileStream(folders[j], FileMode.Open, FileAccess.Read)); | ||
561 | collection.Folders[invFolder.ID] = invFolder; | ||
562 | } | ||
563 | |||
564 | // Iterate over the folders collection, adding children to their parents | ||
565 | foreach (InventoryFolder invFolder in collection.Folders.Values) | ||
566 | { | ||
567 | InventoryFolder parent; | ||
568 | if (collection.Folders.TryGetValue(invFolder.ParentID, out parent)) | ||
569 | parent.Children[invFolder.ID] = invFolder; | ||
570 | } | ||
571 | |||
572 | // Load all of the items for this agent | ||
573 | string[] files = Directory.GetFiles(foldername, "*.item", SearchOption.TopDirectoryOnly); | ||
574 | collection.Items = new Dictionary<UUID, InventoryItem>(files.Length); | ||
575 | |||
576 | for (int j = 0; j < files.Length; j++) | ||
577 | { | ||
578 | InventoryItem invItem = (InventoryItem)itemSerializer.Deserialize( | ||
579 | new FileStream(files[j], FileMode.Open, FileAccess.Read)); | ||
580 | collection.Items[invItem.ID] = invItem; | ||
581 | |||
582 | // Add items to their parent folders | ||
583 | InventoryFolder parent; | ||
584 | if (collection.Folders.TryGetValue(invItem.Folder, out parent)) | ||
585 | parent.Children[invItem.ID] = invItem; | ||
586 | |||
587 | // Add active gestures to our list | ||
588 | if (invItem.InvType == (int)InventoryType.Gesture && invItem.Flags != 0) | ||
589 | activeGestures[owner].Add(invItem); | ||
590 | } | ||
591 | |||
592 | inventories.Add(owner, collection); | ||
593 | } | ||
594 | } | ||
595 | } | ||
596 | catch (Exception ex) | ||
597 | { | ||
598 | Logger.Log.ErrorFormat("Failed loading inventory from {0}: {1}", folder, ex.Message); | ||
599 | } | ||
600 | } | ||
601 | } | ||
602 | } | ||