clockwerk-opensim – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 vero 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  
28 using System;
29 using System.Collections.Generic;
30 using System.IO;
31 using System.Reflection;
32 using System.Threading;
33 using System.Xml;
34  
35 using log4net;
36 using OpenMetaverse;
37 using OpenSim.Framework;
38  
39 using OpenSim.Region.Framework.Scenes;
40 using OpenSim.Region.Framework.Scenes.Serialization;
41 using OpenSim.Region.Framework.Interfaces;
42 using OpenSim.Services.Interfaces;
43  
44 //using HyperGrid.Framework;
45 //using OpenSim.Region.Communications.Hypergrid;
46  
47 namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
48 {
49 public class HGAssetMapper
50 {
51 #region Fields
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53  
54 // This maps between inventory server urls and inventory server clients
55 // private Dictionary<string, InventoryClient> m_inventoryServers = new Dictionary<string, InventoryClient>();
56  
57 private Scene m_scene;
58 private string m_HomeURI;
59  
60 #endregion
61  
62 #region Constructor
63  
64 public HGAssetMapper(Scene scene, string homeURL)
65 {
66 m_scene = scene;
67 m_HomeURI = homeURL;
68 }
69  
70 #endregion
71  
72 #region Internal functions
73  
74 private AssetMetadata FetchMetadata(string url, UUID assetID)
75 {
76 if (string.IsNullOrEmpty(url))
77 return null;
78  
79 if (!url.EndsWith("/") && !url.EndsWith("="))
80 url = url + "/";
81  
82 AssetMetadata meta = m_scene.AssetService.GetMetadata(url + assetID.ToString());
83  
84 if (meta != null)
85 m_log.DebugFormat("[HG ASSET MAPPER]: Fetched metadata for asset {0} of type {1} from {2} ", assetID, meta.Type, url);
86 else
87 m_log.DebugFormat("[HG ASSET MAPPER]: Unable to fetched metadata for asset {0} from {1} ", assetID, url);
88  
89 return meta;
90 }
91  
92 private AssetBase FetchAsset(string url, UUID assetID)
93 {
94 // Test if it's already here
95 AssetBase asset = m_scene.AssetService.Get(assetID.ToString());
96 if (asset == null)
97 {
98 if (string.IsNullOrEmpty(url))
99 return null;
100  
101 if (!url.EndsWith("/") && !url.EndsWith("="))
102 url = url + "/";
103  
104 asset = m_scene.AssetService.Get(url + assetID.ToString());
105  
106 //if (asset != null)
107 // m_log.DebugFormat("[HG ASSET MAPPER]: Fetched asset {0} of type {1} from {2} ", assetID, asset.Metadata.Type, url);
108 //else
109 // m_log.DebugFormat("[HG ASSET MAPPER]: Unable to fetch asset {0} from {1} ", assetID, url);
110  
111 }
112  
113 return asset;
114 }
115  
116 public bool PostAsset(string url, AssetBase asset)
117 {
118 if (string.IsNullOrEmpty(url))
119 return false;
120  
121 if (!url.EndsWith("/") && !url.EndsWith("="))
122 url = url + "/";
123  
124 if (asset == null)
125 {
126 m_log.Warn("[HG ASSET MAPPER]: Tried to post asset to remote server, but asset not in local cache.");
127 return false;
128 }
129  
130 // See long comment in AssetCache.AddAsset
131 if (asset.Temporary || asset.Local)
132 return true;
133  
134 // We need to copy the asset into a new asset, because
135 // we need to set its ID to be URL+UUID, so that the
136 // HGAssetService dispatches it to the remote grid.
137 // It's not pretty, but the best that can be done while
138 // not having a global naming infrastructure
139 AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID);
140 Copy(asset, asset1);
141 asset1.ID = url + asset.ID;
142  
143 AdjustIdentifiers(asset1.Metadata);
144 if (asset1.Metadata.Type == (sbyte)AssetType.Object)
145 asset1.Data = AdjustIdentifiers(asset.Data);
146 else
147 asset1.Data = asset.Data;
148  
149 string id = m_scene.AssetService.Store(asset1);
150 if (String.IsNullOrEmpty(id))
151 {
152 m_log.DebugFormat("[HG ASSET MAPPER]: Asset server {0} did not accept {1}", url, asset.ID);
153 return false;
154 }
155 else {
156 m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url);
157 return true;
158 }
159 }
160  
161 private void Copy(AssetBase from, AssetBase to)
162 {
163 //to.Data = from.Data; // don't copy this, it's copied elsewhere
164 to.Description = from.Description;
165 to.FullID = from.FullID;
166 to.ID = from.ID;
167 to.Local = from.Local;
168 to.Name = from.Name;
169 to.Temporary = from.Temporary;
170 to.Type = from.Type;
171  
172 }
173  
174 private void AdjustIdentifiers(AssetMetadata meta)
175 {
176 if (!string.IsNullOrEmpty(meta.CreatorID))
177 {
178 UUID uuid = UUID.Zero;
179 UUID.TryParse(meta.CreatorID, out uuid);
180 UserAccount creator = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid);
181 if (creator != null)
182 meta.CreatorID = m_HomeURI + ";" + creator.FirstName + " " + creator.LastName;
183 }
184 }
185  
186 protected byte[] AdjustIdentifiers(byte[] data)
187 {
188 string xml = Utils.BytesToString(data);
189 return Utils.StringToBytes(RewriteSOP(xml));
190 }
191  
192 protected string RewriteSOP(string xml)
193 {
194 XmlDocument doc = new XmlDocument();
195 doc.LoadXml(xml);
196 XmlNodeList sops = doc.GetElementsByTagName("SceneObjectPart");
197  
198 foreach (XmlNode sop in sops)
199 {
200 UserAccount creator = null;
201 bool hasCreatorData = false;
202 XmlNodeList nodes = sop.ChildNodes;
203 foreach (XmlNode node in nodes)
204 {
205 if (node.Name == "CreatorID")
206 {
207 UUID uuid = UUID.Zero;
208 UUID.TryParse(node.InnerText, out uuid);
209 creator = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid);
210 }
211 if (node.Name == "CreatorData" && node.InnerText != null && node.InnerText != string.Empty)
212 hasCreatorData = true;
213  
214 //if (node.Name == "OwnerID")
215 //{
216 // UserAccount owner = GetUser(node.InnerText);
217 // if (owner != null)
218 // node.InnerText = m_ProfileServiceURL + "/" + node.InnerText + "/" + owner.FirstName + " " + owner.LastName;
219 //}
220 }
221  
222 if (!hasCreatorData && creator != null)
223 {
224 XmlElement creatorData = doc.CreateElement("CreatorData");
225 creatorData.InnerText = m_HomeURI + ";" + creator.FirstName + " " + creator.LastName;
226 sop.AppendChild(creatorData);
227 }
228 }
229  
230 using (StringWriter wr = new StringWriter())
231 {
232 doc.Save(wr);
233 return wr.ToString();
234 }
235  
236 }
237  
238 // TODO: unused
239 // private void Dump(Dictionary<UUID, bool> lst)
240 // {
241 // m_log.Debug("XXX -------- UUID DUMP ------- XXX");
242 // foreach (KeyValuePair<UUID, bool> kvp in lst)
243 // m_log.Debug(" >> " + kvp.Key + " (texture? " + kvp.Value + ")");
244 // m_log.Debug("XXX -------- UUID DUMP ------- XXX");
245 // }
246  
247 #endregion
248  
249  
250 #region Public interface
251  
252 public void Get(UUID assetID, UUID ownerID, string userAssetURL)
253 {
254 // Get the item from the remote asset server onto the local AssetService
255  
256 AssetMetadata meta = FetchMetadata(userAssetURL, assetID);
257 if (meta == null)
258 return;
259  
260 // The act of gathering UUIDs downloads some assets from the remote server
261 // but not all...
262 Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
263 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL);
264 uuidGatherer.GatherAssetUuids(assetID, meta.Type, ids);
265 m_log.DebugFormat("[HG ASSET MAPPER]: Preparing to get {0} assets", ids.Count);
266 bool success = true;
267 foreach (UUID uuid in ids.Keys)
268 if (FetchAsset(userAssetURL, uuid) == null)
269 success = false;
270  
271 // maybe all pieces got here...
272 if (!success)
273 m_log.DebugFormat("[HG ASSET MAPPER]: Problems getting item {0} from asset server {1}", assetID, userAssetURL);
274 else
275 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully got item {0} from asset server {1}", assetID, userAssetURL);
276 }
277  
278  
279 public void Post(UUID assetID, UUID ownerID, string userAssetURL)
280 {
281 m_log.DebugFormat("[HG ASSET MAPPER]: Starting to send asset {0} with children to asset server {1}", assetID, userAssetURL);
282  
283 // Find all the embedded assets
284  
285 AssetBase asset = m_scene.AssetService.Get(assetID.ToString());
286 if (asset == null)
287 {
288 m_log.DebugFormat("[HG ASSET MAPPER]: Something wrong with asset {0}, it could not be found", assetID);
289 return;
290 }
291  
292 Dictionary<UUID, sbyte> ids = new Dictionary<UUID, sbyte>();
293 HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty);
294 uuidGatherer.GatherAssetUuids(asset.FullID, asset.Type, ids);
295  
296 // Check which assets already exist in the destination server
297  
298 string url = userAssetURL;
299 if (!url.EndsWith("/") && !url.EndsWith("="))
300 url = url + "/";
301  
302 string[] remoteAssetIDs = new string[ids.Count];
303 int i = 0;
304 foreach (UUID id in ids.Keys)
305 remoteAssetIDs[i++] = url + id.ToString();
306  
307 bool[] exist = m_scene.AssetService.AssetsExist(remoteAssetIDs);
308  
309 var existSet = new HashSet<string>();
310 i = 0;
311 foreach (UUID id in ids.Keys)
312 {
313 if (exist[i])
314 existSet.Add(id.ToString());
315 ++i;
316 }
317  
318 // Send only those assets which don't already exist in the destination server
319  
320 bool success = true;
321  
322 foreach (UUID uuid in ids.Keys)
323 {
324 if (!existSet.Contains(uuid.ToString()))
325 {
326 asset = m_scene.AssetService.Get(uuid.ToString());
327 if (asset == null)
328 m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid);
329 else
330 success &= PostAsset(userAssetURL, asset);
331 }
332 else
333 m_log.DebugFormat("[HG ASSET MAPPER]: Didn't post asset {0} because it already exists in asset server {1}", uuid, userAssetURL);
334 }
335  
336 if (!success)
337 m_log.DebugFormat("[HG ASSET MAPPER]: Problems sending asset {0} with children to asset server {1}", assetID, userAssetURL);
338 else
339 m_log.DebugFormat("[HG ASSET MAPPER]: Successfully sent asset {0} with children to asset server {1}", assetID, userAssetURL);
340 }
341  
342 #endregion
343  
344 }
345 }