diff --git a/OpenSim/Framework/LandData.cs b/OpenSim/Framework/LandData.cs index 58a80efe75..f6271ef3fd 100644 --- a/OpenSim/Framework/LandData.cs +++ b/OpenSim/Framework/LandData.cs @@ -34,7 +34,7 @@ using OpenMetaverse; namespace OpenSim.Framework { - public struct LandAccessEntry + public class LandAccessEntry { public UUID AgentID; public int Expires; diff --git a/OpenSim/Framework/Serialization/External/LandDataSerializer.cs b/OpenSim/Framework/Serialization/External/LandDataSerializer.cs index 3ae9a8ee9a..bf6c4e5d82 100644 --- a/OpenSim/Framework/Serialization/External/LandDataSerializer.cs +++ b/OpenSim/Framework/Serialization/External/LandDataSerializer.cs @@ -28,8 +28,10 @@ using System; using System.Collections.Generic; using System.IO; +using System.Reflection; using System.Text; using System.Xml; +using log4net; using OpenMetaverse; using OpenSim.Framework; @@ -40,8 +42,152 @@ namespace OpenSim.Framework.Serialization.External /// public class LandDataSerializer { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + protected static UTF8Encoding m_utf8Encoding = new UTF8Encoding(); + private delegate void LandDataProcessor(LandData landData, XmlTextReader reader); + private static Dictionary m_ldProcessors + = new Dictionary(); + + private delegate void LandAccessEntryProcessor(LandAccessEntry lae, XmlTextReader reader); + private static Dictionary m_laeProcessors + = new Dictionary(); + + static LandDataSerializer() + { + // LandData processors + m_ldProcessors.Add( + "Area", (ld, xtr) => ld.Area = Convert.ToInt32(xtr.ReadElementString("Area"))); + m_ldProcessors.Add( + "AuctionID", (ld, xtr) => ld.AuctionID = Convert.ToUInt32(xtr.ReadElementString("AuctionID"))); + m_ldProcessors.Add( + "AuthBuyerID", (ld, xtr) => ld.AuthBuyerID = UUID.Parse(xtr.ReadElementString("AuthBuyerID"))); + m_ldProcessors.Add( + "Category", (ld, xtr) => ld.Category = (ParcelCategory)Convert.ToSByte(xtr.ReadElementString("Category"))); + m_ldProcessors.Add( + "ClaimDate", (ld, xtr) => ld.ClaimDate = Convert.ToInt32(xtr.ReadElementString("ClaimDate"))); + m_ldProcessors.Add( + "ClaimPrice", (ld, xtr) => ld.ClaimPrice = Convert.ToInt32(xtr.ReadElementString("ClaimPrice"))); + m_ldProcessors.Add( + "GlobalID", (ld, xtr) => ld.GlobalID = UUID.Parse(xtr.ReadElementString("GlobalID"))); + m_ldProcessors.Add( + "GroupID", (ld, xtr) => ld.GroupID = UUID.Parse(xtr.ReadElementString("GroupID"))); + m_ldProcessors.Add( + "IsGroupOwned", (ld, xtr) => ld.IsGroupOwned = Convert.ToBoolean(xtr.ReadElementString("IsGroupOwned"))); + m_ldProcessors.Add( + "Bitmap", (ld, xtr) => ld.Bitmap = Convert.FromBase64String(xtr.ReadElementString("Bitmap"))); + m_ldProcessors.Add( + "Description", (ld, xtr) => ld.Description = xtr.ReadElementString("Description")); + m_ldProcessors.Add( + "Flags", (ld, xtr) => ld.Flags = Convert.ToUInt32(xtr.ReadElementString("Flags"))); + m_ldProcessors.Add( + "LandingType", (ld, xtr) => ld.LandingType = Convert.ToByte(xtr.ReadElementString("LandingType"))); + m_ldProcessors.Add( + "Name", (ld, xtr) => ld.Name = xtr.ReadElementString("Name")); + m_ldProcessors.Add( + "Status", (ld, xtr) => ld.Status = (ParcelStatus)Convert.ToSByte(xtr.ReadElementString("Status"))); + m_ldProcessors.Add( + "LocalID", (ld, xtr) => ld.LocalID = Convert.ToInt32(xtr.ReadElementString("LocalID"))); + m_ldProcessors.Add( + "MediaAutoScale", (ld, xtr) => ld.MediaAutoScale = Convert.ToByte(xtr.ReadElementString("MediaAutoScale"))); + m_ldProcessors.Add( + "MediaID", (ld, xtr) => ld.MediaID = UUID.Parse(xtr.ReadElementString("MediaID"))); + m_ldProcessors.Add( + "MediaURL", (ld, xtr) => ld.MediaURL = xtr.ReadElementString("MediaURL")); + m_ldProcessors.Add( + "MusicURL", (ld, xtr) => ld.MusicURL = xtr.ReadElementString("MusicURL")); + + m_ldProcessors.Add( + "ParcelAccessList", ProcessParcelAccessList); + + m_ldProcessors.Add( + "PassHours", (ld, xtr) => ld.PassHours = Convert.ToSingle(xtr.ReadElementString("PassHours"))); + m_ldProcessors.Add( + "PassPrice", (ld, xtr) => ld.PassPrice = Convert.ToInt32(xtr.ReadElementString("PassPrice"))); + m_ldProcessors.Add( + "SalePrice", (ld, xtr) => ld.SalePrice = Convert.ToInt32(xtr.ReadElementString("SalePrice"))); + m_ldProcessors.Add( + "SnapshotID", (ld, xtr) => ld.SnapshotID = UUID.Parse(xtr.ReadElementString("SnapshotID"))); + m_ldProcessors.Add( + "UserLocation", (ld, xtr) => ld.UserLocation = Vector3.Parse(xtr.ReadElementString("UserLocation"))); + m_ldProcessors.Add( + "UserLookAt", (ld, xtr) => ld.UserLookAt = Vector3.Parse(xtr.ReadElementString("UserLookAt"))); + + // No longer used here // + // m_ldProcessors.Add("Dwell", (landData, xtr) => return); + + m_ldProcessors.Add( + "OtherCleanTime", (ld, xtr) => ld.OtherCleanTime = Convert.ToInt32(xtr.ReadElementString("OtherCleanTime"))); + + // LandAccessEntryProcessors + m_laeProcessors.Add( + "AgentID", (lae, xtr) => lae.AgentID = UUID.Parse(xtr.ReadElementString("AgentID"))); + m_laeProcessors.Add( + "Time", (lae, xtr) => + { + // We really don't care about temp vs perm here and this + // would break on old oars. Assume all bans are perm + xtr.ReadElementString("Time"); + lae.Expires = 0; // Convert.ToUint( xtr.ReadElementString("Time")); + } + ); + m_laeProcessors.Add( + "AccessList", (lae, xtr) => lae.Flags = (AccessList)Convert.ToUInt32(xtr.ReadElementString("AccessList"))); + } + + public static void ProcessParcelAccessList(LandData ld, XmlTextReader xtr) + { + if (!xtr.IsEmptyElement) + { + while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement) + { + LandAccessEntry lae = new LandAccessEntry(); + + xtr.ReadStartElement("ParcelAccessEntry"); + + string nodeName = string.Empty; + while (xtr.NodeType != XmlNodeType.EndElement) + { + nodeName = xtr.Name; + +// m_log.DebugFormat("[LandDataSerializer]: Processing: {0} in ParcelAccessEntry", nodeName); + + LandAccessEntryProcessor p = null; + if (m_laeProcessors.TryGetValue(xtr.Name, out p)) + { +// m_log.DebugFormat("[LandDataSerializer]: Found {0} processor in ParcelAccessEntry", nodeName); + + try + { + p(lae, xtr); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[LandDataSerializer]: Exception while parsing element {0} in ParcelAccessEntry, continuing. Exception {1}{2}", + nodeName, e.Message, e.StackTrace); + + if (xtr.NodeType == XmlNodeType.EndElement) + xtr.Read(); + } + } + else + { + // m_log.DebugFormat("[LandDataSerializer]: caught unknown element {0}", nodeName); + xtr.ReadOuterXml(); // ignore + } + } + + xtr.ReadEndElement(); + + ld.ParcelAccessList.Add(lae); + } + } + + xtr.Read(); + } + /// /// Reify/deserialize landData /// @@ -63,72 +209,43 @@ namespace OpenSim.Framework.Serialization.External { LandData landData = new LandData(); - StringReader sr = new StringReader(serializedLandData); - XmlTextReader xtr = new XmlTextReader(sr); - - xtr.ReadStartElement("LandData"); - - landData.Area = Convert.ToInt32( xtr.ReadElementString("Area")); - landData.AuctionID = Convert.ToUInt32( xtr.ReadElementString("AuctionID")); - landData.AuthBuyerID = UUID.Parse( xtr.ReadElementString("AuthBuyerID")); - landData.Category = (ParcelCategory)Convert.ToSByte( xtr.ReadElementString("Category")); - landData.ClaimDate = Convert.ToInt32( xtr.ReadElementString("ClaimDate")); - landData.ClaimPrice = Convert.ToInt32( xtr.ReadElementString("ClaimPrice")); - landData.GlobalID = UUID.Parse( xtr.ReadElementString("GlobalID")); - landData.GroupID = UUID.Parse( xtr.ReadElementString("GroupID")); - landData.IsGroupOwned = Convert.ToBoolean( xtr.ReadElementString("IsGroupOwned")); - landData.Bitmap = Convert.FromBase64String( xtr.ReadElementString("Bitmap")); - landData.Description = xtr.ReadElementString("Description"); - landData.Flags = Convert.ToUInt32( xtr.ReadElementString("Flags")); - landData.LandingType = Convert.ToByte( xtr.ReadElementString("LandingType")); - landData.Name = xtr.ReadElementString("Name"); - landData.Status = (ParcelStatus)Convert.ToSByte( xtr.ReadElementString("Status")); - landData.LocalID = Convert.ToInt32( xtr.ReadElementString("LocalID")); - landData.MediaAutoScale = Convert.ToByte( xtr.ReadElementString("MediaAutoScale")); - landData.MediaID = UUID.Parse( xtr.ReadElementString("MediaID")); - landData.MediaURL = xtr.ReadElementString("MediaURL"); - landData.MusicURL = xtr.ReadElementString("MusicURL"); - landData.OwnerID = UUID.Parse( xtr.ReadElementString("OwnerID")); - - landData.ParcelAccessList = new List(); - xtr.Read(); - if (xtr.Name != "ParcelAccessList") - throw new XmlException(String.Format("Expected \"ParcelAccessList\" element but got \"{0}\"", xtr.Name)); - - if (!xtr.IsEmptyElement) + using (XmlTextReader reader = new XmlTextReader(new StringReader(serializedLandData))) { - while (xtr.Read() && xtr.NodeType != XmlNodeType.EndElement) + reader.ReadStartElement("LandData"); + + string nodeName = string.Empty; + while (reader.NodeType != XmlNodeType.EndElement) { - LandAccessEntry pae = new LandAccessEntry(); + nodeName = reader.Name; - xtr.ReadStartElement("ParcelAccessEntry"); - pae.AgentID = UUID.Parse( xtr.ReadElementString("AgentID")); - // We really don't care about temp vs perm here and this - // would break on old oars. Assume all bans are perm - xtr.ReadElementString("Time"); - pae.Expires = 0; // Convert.ToUint( xtr.ReadElementString("Time")); - pae.Flags = (AccessList)Convert.ToUInt32( xtr.ReadElementString("AccessList")); - xtr.ReadEndElement(); +// m_log.DebugFormat("[LandDataSerializer]: Processing: {0}", nodeName); - landData.ParcelAccessList.Add(pae); + LandDataProcessor p = null; + if (m_ldProcessors.TryGetValue(reader.Name, out p)) + { + try + { + p(landData, reader); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[LandDataSerializer]: exception while parsing element {0}, continuing. Exception {1}{2}", + nodeName, e.Message, e.StackTrace); + + if (reader.NodeType == XmlNodeType.EndElement) + reader.Read(); + } + } + else + { + // m_log.DebugFormat("[LandDataSerializer]: caught unknown element {0}", nodeName); + reader.ReadOuterXml(); // ignore + } } + + reader.ReadEndElement(); } - xtr.Read(); - - landData.PassHours = Convert.ToSingle( xtr.ReadElementString("PassHours")); - landData.PassPrice = Convert.ToInt32( xtr.ReadElementString("PassPrice")); - landData.SalePrice = Convert.ToInt32( xtr.ReadElementString("SalePrice")); - landData.SnapshotID = UUID.Parse( xtr.ReadElementString("SnapshotID")); - landData.UserLocation = Vector3.Parse( xtr.ReadElementString("UserLocation")); - landData.UserLookAt = Vector3.Parse( xtr.ReadElementString("UserLookAt")); - // No longer used here - xtr.ReadElementString("Dwell"); - landData.OtherCleanTime = Convert.ToInt32( xtr.ReadElementString("OtherCleanTime")); - - xtr.ReadEndElement(); - - xtr.Close(); - sr.Close(); return landData; } diff --git a/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs b/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs index f138437ad5..5d986d55a2 100644 --- a/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs +++ b/OpenSim/Framework/Serialization/External/UserInventoryItemSerializer.cs @@ -41,8 +41,7 @@ namespace OpenSim.Framework.Serialization.External { /// /// Serialize and deserialize user inventory items as an external format. - /// - /// XXX: Please do not use yet. + /// public class UserInventoryItemSerializer { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); diff --git a/OpenSim/Framework/Serialization/External/UserProfileSerializer.cs b/OpenSim/Framework/Serialization/External/UserProfileSerializer.cs index f50b49a342..c685a157e1 100644 --- a/OpenSim/Framework/Serialization/External/UserProfileSerializer.cs +++ b/OpenSim/Framework/Serialization/External/UserProfileSerializer.cs @@ -33,8 +33,11 @@ using OpenSim.Framework; namespace OpenSim.Framework.Serialization.External { /// - /// Serialize and deserialize region settings as an external format. + /// Serialize and deserialize user profiles as an external format. /// + /// + /// Currently UNUSED. + /// public class UserProfileSerializer { public const int MAJOR_VERSION = 0; diff --git a/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs b/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs index 3607ce8e42..11a3a0ac4d 100644 --- a/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs +++ b/OpenSim/Framework/Serialization/Tests/LandDataSerializerTests.cs @@ -27,11 +27,12 @@ using System; using System.Collections.Generic; -using OpenSim.Framework; -using OpenSim.Framework.Serialization.External; using OpenMetaverse; using OpenMetaverse.StructuredData; using NUnit.Framework; +using OpenSim.Framework; +using OpenSim.Framework.Serialization.External; +using OpenSim.Tests.Common; namespace OpenSim.Framework.Serialization.Tests { @@ -92,6 +93,8 @@ namespace OpenSim.Framework.Serialization.Tests [Test] public void LandDataSerializerSerializeTest() { + TestHelpers.InMethod(); + string serialized = LandDataSerializer.Serialize(this.land).Replace("\r\n", "\n"); Assert.That(serialized.Length > 0, "Serialize(LandData) returned empty string"); @@ -112,20 +115,32 @@ namespace OpenSim.Framework.Serialization.Tests /// Test the LandDataSerializer.Deserialize() method /// [Test] - public void TestLandDataSerializerDeserializeFromStringTest() + public void TestLandDataDeserializeNoAccessLists() { - LandData reifiedLandData = LandDataSerializer.Deserialize(LandDataSerializerTest.preSerialized); - Assert.That(reifiedLandData != null, "Deserialize(string) returned null"); - Assert.That(reifiedLandData.GlobalID == this.land.GlobalID, "Reified LandData.GlobalID != original LandData.GlobalID"); - Assert.That(reifiedLandData.Name == this.land.Name, "Reified LandData.Name != original LandData.Name"); + TestHelpers.InMethod(); + log4net.Config.XmlConfigurator.Configure(); - LandData reifiedLandDataWithParcelAccessList = LandDataSerializer.Deserialize(LandDataSerializerTest.preSerializedWithParcelAccessList); - Assert.That(reifiedLandDataWithParcelAccessList != null, + LandData ld = LandDataSerializer.Deserialize(LandDataSerializerTest.preSerialized); + Assert.That(ld != null, "Deserialize(string) returned null"); + Assert.That(ld.GlobalID == this.land.GlobalID, "Reified LandData.GlobalID != original LandData.GlobalID"); + Assert.That(ld.Name == this.land.Name, "Reified LandData.Name != original LandData.Name"); + } + + [Test] + public void TestLandDataDeserializeWithAccessLists() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + LandData ld = LandDataSerializer.Deserialize(LandDataSerializerTest.preSerializedWithParcelAccessList); + Assert.That(ld != null, "Deserialize(string) returned null (pre-serialized with parcel access list)"); - Assert.That(reifiedLandDataWithParcelAccessList.GlobalID == this.landWithParcelAccessList.GlobalID, + Assert.That(ld.GlobalID == this.landWithParcelAccessList.GlobalID, "Reified LandData.GlobalID != original LandData.GlobalID (pre-serialized with parcel access list)"); - Assert.That(reifiedLandDataWithParcelAccessList.Name == this.landWithParcelAccessList.Name, + Assert.That(ld.Name == this.landWithParcelAccessList.Name, "Reified LandData.Name != original LandData.Name (pre-serialized with parcel access list)"); + Assert.That(ld.ParcelAccessList.Count, Is.EqualTo(2)); + Assert.That(ld.ParcelAccessList[0].AgentID, Is.EqualTo(UUID.Parse("62d65d45-c91a-4f77-862c-46557d978b6c"))); } } } diff --git a/bin/OpenSim.Framework.Serialization.Tests.dll.config b/bin/OpenSim.Framework.Serialization.Tests.dll.config new file mode 100644 index 0000000000..a3f681d89e --- /dev/null +++ b/bin/OpenSim.Framework.Serialization.Tests.dll.config @@ -0,0 +1,33 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + +