diff options
author | Diva Canto | 2015-05-05 20:59:09 -0700 |
---|---|---|
committer | Diva Canto | 2015-05-05 20:59:09 -0700 |
commit | 1abbad71b4603245e5481c11e3ce55f57b64935f (patch) | |
tree | 694b750495216edbb16a2822a546e7617eff2c66 /OpenSim/Region | |
parent | Revert "Patch llCastRay fully-simplified to V2." for further review. (diff) | |
download | opensim-SC-1abbad71b4603245e5481c11e3ce55f57b64935f.zip opensim-SC-1abbad71b4603245e5481c11e3ce55f57b64935f.tar.gz opensim-SC-1abbad71b4603245e5481c11e3ce55f57b64935f.tar.bz2 opensim-SC-1abbad71b4603245e5481c11e3ce55f57b64935f.tar.xz |
Refactored some code that is used in two different dlls related to SOP rewriting. Also added some unit tests that relate to mantis #7514
Diffstat (limited to 'OpenSim/Region')
3 files changed, 139 insertions, 208 deletions
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index c2010b1..f54298c 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs | |||
@@ -35,6 +35,7 @@ using System.Xml; | |||
35 | using log4net; | 35 | using log4net; |
36 | using OpenMetaverse; | 36 | using OpenMetaverse; |
37 | using OpenSim.Framework; | 37 | using OpenSim.Framework; |
38 | using OpenSim.Framework.Serialization.External; | ||
38 | 39 | ||
39 | using OpenSim.Region.Framework.Scenes; | 40 | using OpenSim.Region.Framework.Scenes; |
40 | using OpenSim.Region.Framework.Scenes.Serialization; | 41 | using OpenSim.Region.Framework.Scenes.Serialization; |
@@ -189,217 +190,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess | |||
189 | return Utils.StringToBytes(RewriteSOP(xml)); | 190 | return Utils.StringToBytes(RewriteSOP(xml)); |
190 | } | 191 | } |
191 | 192 | ||
192 | protected void TransformXml(XmlReader reader, XmlWriter writer) | ||
193 | { | ||
194 | // m_log.DebugFormat("[HG ASSET MAPPER]: Transforming XML"); | ||
195 | |||
196 | int sopDepth = -1; | ||
197 | UserAccount creator = null; | ||
198 | bool hasCreatorData = false; | ||
199 | |||
200 | while (reader.Read()) | ||
201 | { | ||
202 | // Console.WriteLine("Depth: {0}, name {1}", reader.Depth, reader.Name); | ||
203 | |||
204 | switch (reader.NodeType) | ||
205 | { | ||
206 | case XmlNodeType.Attribute: | ||
207 | // Console.WriteLine("FOUND ATTRIBUTE {0}", reader.Name); | ||
208 | writer.WriteAttributeString(reader.Name, reader.Value); | ||
209 | break; | ||
210 | |||
211 | case XmlNodeType.CDATA: | ||
212 | writer.WriteCData(reader.Value); | ||
213 | break; | ||
214 | |||
215 | case XmlNodeType.Comment: | ||
216 | writer.WriteComment(reader.Value); | ||
217 | break; | ||
218 | |||
219 | case XmlNodeType.DocumentType: | ||
220 | writer.WriteDocType(reader.Name, reader.Value, null, null); | ||
221 | break; | ||
222 | |||
223 | case XmlNodeType.Element: | ||
224 | // m_log.DebugFormat("Depth {0} at element {1}", reader.Depth, reader.Name); | ||
225 | |||
226 | writer.WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI); | ||
227 | |||
228 | if (reader.HasAttributes) | ||
229 | { | ||
230 | while (reader.MoveToNextAttribute()) | ||
231 | writer.WriteAttributeString(reader.Name, reader.Value); | ||
232 | |||
233 | reader.MoveToElement(); | ||
234 | } | ||
235 | |||
236 | if (reader.LocalName == "SceneObjectPart") | ||
237 | { | ||
238 | if (sopDepth < 0) | ||
239 | { | ||
240 | sopDepth = reader.Depth; | ||
241 | // m_log.DebugFormat("[HG ASSET MAPPER]: Set sopDepth to {0}", sopDepth); | ||
242 | } | ||
243 | } | ||
244 | else | ||
245 | { | ||
246 | if (sopDepth >= 0 && reader.Depth == sopDepth + 1) | ||
247 | { | ||
248 | if (reader.Name == "CreatorID") | ||
249 | { | ||
250 | reader.Read(); | ||
251 | if (reader.NodeType == XmlNodeType.Element && reader.Name == "Guid" || reader.Name == "UUID") | ||
252 | { | ||
253 | reader.Read(); | ||
254 | |||
255 | if (reader.NodeType == XmlNodeType.Text) | ||
256 | { | ||
257 | UUID uuid = UUID.Zero; | ||
258 | UUID.TryParse(reader.Value, out uuid); | ||
259 | creator = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid); | ||
260 | writer.WriteElementString("UUID", reader.Value); | ||
261 | reader.Read(); | ||
262 | } | ||
263 | else | ||
264 | { | ||
265 | // If we unexpected run across mixed content in this node, still carry on | ||
266 | // transforming the subtree (this replicates earlier behaviour). | ||
267 | TransformXml(reader, writer); | ||
268 | } | ||
269 | } | ||
270 | else | ||
271 | { | ||
272 | // If we unexpected run across mixed content in this node, still carry on | ||
273 | // transforming the subtree (this replicates earlier behaviour). | ||
274 | TransformXml(reader, writer); | ||
275 | } | ||
276 | } | ||
277 | else if (reader.Name == "CreatorData") | ||
278 | { | ||
279 | reader.Read(); | ||
280 | if (reader.NodeType == XmlNodeType.Text) | ||
281 | { | ||
282 | hasCreatorData = true; | ||
283 | writer.WriteString(reader.Value); | ||
284 | } | ||
285 | else | ||
286 | { | ||
287 | // If we unexpected run across mixed content in this node, still carry on | ||
288 | // transforming the subtree (this replicates earlier behaviour). | ||
289 | TransformXml(reader, writer); | ||
290 | } | ||
291 | } | ||
292 | } | ||
293 | } | ||
294 | |||
295 | if (reader.IsEmptyElement) | ||
296 | { | ||
297 | // m_log.DebugFormat("[HG ASSET MAPPER]: Writing end for empty element {0}", reader.Name); | ||
298 | writer.WriteEndElement(); | ||
299 | } | ||
300 | |||
301 | break; | ||
302 | |||
303 | case XmlNodeType.EndElement: | ||
304 | // m_log.DebugFormat("Depth {0} at EndElement", reader.Depth); | ||
305 | if (sopDepth == reader.Depth) | ||
306 | { | ||
307 | if (!hasCreatorData && creator != null) | ||
308 | writer.WriteElementString(reader.Prefix, "CreatorData", reader.NamespaceURI, string.Format("{0};{1} {2}", m_HomeURI, creator.FirstName, creator.LastName)); | ||
309 | |||
310 | // m_log.DebugFormat("[HG ASSET MAPPER]: Reset sopDepth"); | ||
311 | sopDepth = -1; | ||
312 | creator = null; | ||
313 | hasCreatorData = false; | ||
314 | } | ||
315 | writer.WriteEndElement(); | ||
316 | break; | ||
317 | |||
318 | case XmlNodeType.EntityReference: | ||
319 | writer.WriteEntityRef(reader.Name); | ||
320 | break; | ||
321 | |||
322 | case XmlNodeType.ProcessingInstruction: | ||
323 | writer.WriteProcessingInstruction(reader.Name, reader.Value); | ||
324 | break; | ||
325 | |||
326 | case XmlNodeType.Text: | ||
327 | writer.WriteString(reader.Value); | ||
328 | break; | ||
329 | |||
330 | case XmlNodeType.XmlDeclaration: | ||
331 | // For various reasons, not all serializations have xml declarations (or consistent ones) | ||
332 | // and as it's embedded inside a byte stream we don't need it anyway, so ignore. | ||
333 | break; | ||
334 | |||
335 | default: | ||
336 | m_log.WarnFormat( | ||
337 | "[HG ASSET MAPPER]: Unrecognized node {0} in asset XML transform in {1}", | ||
338 | reader.NodeType, m_scene.Name); | ||
339 | break; | ||
340 | } | ||
341 | } | ||
342 | } | ||
343 | |||
344 | protected string RewriteSOP(string xmlData) | 193 | protected string RewriteSOP(string xmlData) |
345 | { | 194 | { |
346 | // Console.WriteLine("Input XML [{0}]", xmlData); | 195 | // Console.WriteLine("Input XML [{0}]", xmlData); |
196 | return ExternalRepresentationUtils.RewriteSOP(xmlData, m_scene.Name, m_HomeURI, m_scene.UserAccountService, m_scene.RegionInfo.ScopeID); | ||
347 | 197 | ||
348 | using (StringWriter sw = new StringWriter()) | ||
349 | using (XmlTextWriter writer = new XmlTextWriter(sw)) | ||
350 | using (XmlTextReader wrappedReader = new XmlTextReader(xmlData, XmlNodeType.Element, null)) | ||
351 | using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment })) | ||
352 | { | ||
353 | TransformXml(reader, writer); | ||
354 | |||
355 | // Console.WriteLine("Output: [{0}]", sw.ToString()); | ||
356 | |||
357 | return sw.ToString(); | ||
358 | } | ||
359 | |||
360 | // We are now taking the more complex streaming approach above because some assets can be very large | ||
361 | // and can trigger higher CPU use or possibly memory problems. | ||
362 | // XmlDocument doc = new XmlDocument(); | ||
363 | // doc.LoadXml(xml); | ||
364 | // XmlNodeList sops = doc.GetElementsByTagName("SceneObjectPart"); | ||
365 | // | ||
366 | // foreach (XmlNode sop in sops) | ||
367 | // { | ||
368 | // UserAccount creator = null; | ||
369 | // bool hasCreatorData = false; | ||
370 | // XmlNodeList nodes = sop.ChildNodes; | ||
371 | // foreach (XmlNode node in nodes) | ||
372 | // { | ||
373 | // if (node.Name == "CreatorID") | ||
374 | // { | ||
375 | // UUID uuid = UUID.Zero; | ||
376 | // UUID.TryParse(node.InnerText, out uuid); | ||
377 | // creator = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid); | ||
378 | // } | ||
379 | // if (node.Name == "CreatorData" && node.InnerText != null && node.InnerText != string.Empty) | ||
380 | // hasCreatorData = true; | ||
381 | // | ||
382 | // //if (node.Name == "OwnerID") | ||
383 | // //{ | ||
384 | // // UserAccount owner = GetUser(node.InnerText); | ||
385 | // // if (owner != null) | ||
386 | // // node.InnerText = m_ProfileServiceURL + "/" + node.InnerText + "/" + owner.FirstName + " " + owner.LastName; | ||
387 | // //} | ||
388 | // } | ||
389 | // | ||
390 | // if (!hasCreatorData && creator != null) | ||
391 | // { | ||
392 | // XmlElement creatorData = doc.CreateElement("CreatorData"); | ||
393 | // creatorData.InnerText = m_HomeURI + ";" + creator.FirstName + " " + creator.LastName; | ||
394 | // sop.AppendChild(creatorData); | ||
395 | // } | ||
396 | // } | ||
397 | // | ||
398 | // using (StringWriter wr = new StringWriter()) | ||
399 | // { | ||
400 | // doc.Save(wr); | ||
401 | // return wr.ToString(); | ||
402 | // } | ||
403 | } | 198 | } |
404 | 199 | ||
405 | // TODO: unused | 200 | // TODO: unused |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index 4d99a6e..db66c83 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs | |||
@@ -335,7 +335,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
335 | if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home")) | 335 | if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home")) |
336 | { | 336 | { |
337 | //m_log.DebugFormat("[ARCHIVER]: Rewriting object data for {0}", asset.ID); | 337 | //m_log.DebugFormat("[ARCHIVER]: Rewriting object data for {0}", asset.ID); |
338 | string xml = ExternalRepresentationUtils.RewriteSOP(Utils.BytesToString(asset.Data), m_options["home"].ToString(), m_userAccountService, m_scopeID); | 338 | string xml = ExternalRepresentationUtils.RewriteSOP(Utils.BytesToString(asset.Data), string.Empty, m_options["home"].ToString(), m_userAccountService, m_scopeID); |
339 | asset.Data = Utils.StringToBytes(xml); | 339 | asset.Data = Utils.StringToBytes(xml); |
340 | } | 340 | } |
341 | return asset; | 341 | return asset; |
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSerializationTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSerializationTests.cs new file mode 100644 index 0000000..927d8e8 --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectSerializationTests.cs | |||
@@ -0,0 +1,136 @@ | |||
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.Reflection; | ||
31 | using System.Threading; | ||
32 | using System.Xml; | ||
33 | using System.Linq; | ||
34 | using Nini.Config; | ||
35 | using NUnit.Framework; | ||
36 | using OpenMetaverse; | ||
37 | using OpenSim.Framework; | ||
38 | using OpenSim.Framework.Serialization.External; | ||
39 | using OpenSim.Framework.Communications; | ||
40 | using OpenSim.Region.Framework.Scenes; | ||
41 | using OpenSim.Region.Framework.Scenes.Serialization; | ||
42 | using OpenSim.Services.Interfaces; | ||
43 | using OpenSim.Tests.Common; | ||
44 | |||
45 | namespace OpenSim.Region.Framework.Scenes.Tests | ||
46 | { | ||
47 | /// <summary> | ||
48 | /// Basic scene object serialization tests. | ||
49 | /// </summary> | ||
50 | [TestFixture] | ||
51 | public class SceneObjectSerializationTests : OpenSimTestCase | ||
52 | { | ||
53 | |||
54 | /// <summary> | ||
55 | /// Serialize and deserialize. | ||
56 | /// </summary> | ||
57 | [Test] | ||
58 | public void TestSerialDeserial() | ||
59 | { | ||
60 | TestHelpers.InMethod(); | ||
61 | |||
62 | Scene scene = new SceneHelpers().SetupScene(); | ||
63 | int partsToTestCount = 3; | ||
64 | |||
65 | SceneObjectGroup so | ||
66 | = SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10); | ||
67 | SceneObjectPart[] parts = so.Parts; | ||
68 | so.Name = "obj1"; | ||
69 | so.Description = "xpto"; | ||
70 | |||
71 | string xml = SceneObjectSerializer.ToXml2Format(so); | ||
72 | Assert.That(!string.IsNullOrEmpty(xml), "SOG serialization resulted in empty or null string"); | ||
73 | |||
74 | XmlDocument doc = new XmlDocument(); | ||
75 | doc.LoadXml(xml); | ||
76 | XmlNodeList nodes = doc.GetElementsByTagName("SceneObjectPart"); | ||
77 | Assert.That(nodes.Count, Is.EqualTo(3), "SOG serialization resulted in wrong number of SOPs"); | ||
78 | |||
79 | SceneObjectGroup so2 = SceneObjectSerializer.FromXml2Format(xml); | ||
80 | Assert.IsNotNull(so2, "SOG deserialization resulted in null object"); | ||
81 | Assert.That(so2.Name == so.Name, "Name of deserialized object does not match original name"); | ||
82 | Assert.That(so2.Description == so.Description, "Description of deserialized object does not match original name"); | ||
83 | } | ||
84 | |||
85 | /// <summary> | ||
86 | /// This checks for a bug reported in mantis #7514 | ||
87 | /// </summary> | ||
88 | [Test] | ||
89 | public void TestNamespaceAttribute() | ||
90 | { | ||
91 | TestHelpers.InMethod(); | ||
92 | |||
93 | Scene scene = new SceneHelpers().SetupScene(); | ||
94 | UserAccount account = new UserAccount(UUID.Zero, UUID.Random(), "Test", "User", string.Empty); | ||
95 | scene.UserAccountService.StoreUserAccount(account); | ||
96 | int partsToTestCount = 1; | ||
97 | |||
98 | SceneObjectGroup so | ||
99 | = SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10); | ||
100 | SceneObjectPart[] parts = so.Parts; | ||
101 | so.Name = "obj1"; | ||
102 | so.Description = "xpto"; | ||
103 | so.OwnerID = account.PrincipalID; | ||
104 | so.RootPart.CreatorID = so.OwnerID; | ||
105 | |||
106 | string xml = SceneObjectSerializer.ToXml2Format(so); | ||
107 | Assert.That(!string.IsNullOrEmpty(xml), "SOG serialization resulted in empty or null string"); | ||
108 | |||
109 | xml = ExternalRepresentationUtils.RewriteSOP(xml, "Test Scene", "http://localhost", scene.UserAccountService, UUID.Zero); | ||
110 | //Console.WriteLine(xml); | ||
111 | |||
112 | XmlDocument doc = new XmlDocument(); | ||
113 | doc.LoadXml(xml); | ||
114 | |||
115 | XmlNodeList nodes = doc.GetElementsByTagName("SceneObjectPart"); | ||
116 | Assert.That(nodes.Count, Is.GreaterThan(0), "SOG serialization resulted in no SOPs"); | ||
117 | foreach (XmlAttribute a in nodes[0].Attributes) | ||
118 | { | ||
119 | int count = a.Name.Count(c => c == ':'); | ||
120 | Assert.That(count, Is.EqualTo(1), "Cannot have multiple ':' in attribute name in SOP"); | ||
121 | } | ||
122 | nodes = doc.GetElementsByTagName("CreatorData"); | ||
123 | Assert.That(nodes.Count, Is.GreaterThan(0), "SOG serialization resulted in no CreatorData"); | ||
124 | foreach (XmlAttribute a in nodes[0].Attributes) | ||
125 | { | ||
126 | int count = a.Name.Count(c => c == ':'); | ||
127 | Assert.That(count, Is.EqualTo(1), "Cannot have multiple ':' in attribute name in CreatorData"); | ||
128 | } | ||
129 | |||
130 | SceneObjectGroup so2 = SceneObjectSerializer.FromXml2Format(xml); | ||
131 | Assert.IsNotNull(so2, "SOG deserialization resulted in null object"); | ||
132 | Assert.AreNotEqual(so.RootPart.CreatorIdentification, so2.RootPart.CreatorIdentification, "RewriteSOP failed to transform CreatorData."); | ||
133 | Assert.That(so2.RootPart.CreatorIdentification.Contains("http://"), "RewriteSOP failed to add the homeURL to CreatorData"); | ||
134 | } | ||
135 | } | ||
136 | } \ No newline at end of file | ||