You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by jg...@apache.org on 2009/04/08 06:11:45 UTC
svn commit: r762903 - in /activemq/activemq-dotnet/Apache.NMS/trunk:
src/main/csharp/Util/Convert.cs src/main/csharp/Util/XmlUtils.cs
src/test/csharp/MessageSelectorTest.cs src/test/csharp/XmlMessage.cs
vs2008-nms-test.csproj vs2008-nms.csproj
Author: jgomes
Date: Tue Apr 7 19:01:00 2009
New Revision: 762903
URL: http://svn.apache.org/viewvc?rev=762903&view=rev
Log:
Added support for serializing/deserializing objects via XML format for easy cross-platform communication.
Fixes [AMQNET-156]. (See https://issues.apache.org/activemq/browse/AMQNET-156)
Added:
activemq/activemq-dotnet/Apache.NMS/trunk/src/main/csharp/Util/XmlUtils.cs
activemq/activemq-dotnet/Apache.NMS/trunk/src/test/csharp/XmlMessage.cs
Modified:
activemq/activemq-dotnet/Apache.NMS/trunk/src/main/csharp/Util/Convert.cs
activemq/activemq-dotnet/Apache.NMS/trunk/src/test/csharp/MessageSelectorTest.cs
activemq/activemq-dotnet/Apache.NMS/trunk/vs2008-nms-test.csproj
activemq/activemq-dotnet/Apache.NMS/trunk/vs2008-nms.csproj
Modified: activemq/activemq-dotnet/Apache.NMS/trunk/src/main/csharp/Util/Convert.cs
URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS/trunk/src/main/csharp/Util/Convert.cs?rev=762903&r1=762902&r2=762903&view=diff
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS/trunk/src/main/csharp/Util/Convert.cs (original)
+++ activemq/activemq-dotnet/Apache.NMS/trunk/src/main/csharp/Util/Convert.cs Tue Apr 7 19:01:00 2009
@@ -14,12 +14,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-using System;
+using System;
+using System.Reflection;
namespace Apache.NMS.Util
{
public class NMSConvert
{
+ /// <summary>
+ /// Convert the acknowledgment mode string into AcknowledgementMode enum.
+ /// </summary>
+ /// <param name="ackText"></param>
+ /// <returns>Equivalent enum value. If unknown string is encounted, it will default to AutoAcknowledge.</returns>
public static AcknowledgementMode ToAcknowledgementMode(string ackText)
{
if(String.Compare(ackText, "AutoAcknowledge", true) == 0)
@@ -43,5 +49,73 @@
return AcknowledgementMode.AutoAcknowledge;
}
}
+
+ /// <summary>
+ /// Convert an object into a text message. The object must be serializable to XML.
+ /// </summary>
+ public static ITextMessage ToXmlMessage(IMessageProducer producer, object obj)
+ {
+ ITextMessage message = producer.CreateTextMessage(XmlUtil.Serialize(obj));
+
+ // Embed the type into the message
+ message.NMSType = obj.GetType().FullName;
+ return message;
+ }
+
+ /// <summary>
+ /// Convert an object into a text message. The object must be serializable to XML.
+ /// </summary>
+ public static ITextMessage ToXmlMessage(ISession session, object obj)
+ {
+ ITextMessage message = session.CreateTextMessage(XmlUtil.Serialize(obj));
+
+ // Embed the type into the message
+ message.NMSType = obj.GetType().FullName;
+ return message;
+ }
+
+ /// <summary>
+ /// Convert a text message into an object. The object must be serializable from XML.
+ /// </summary>
+ public static object FromXmlMessage(IMessage message)
+ {
+ ITextMessage textMessage = message as ITextMessage;
+
+ if(null == textMessage)
+ {
+ return null;
+ }
+
+ Type objType = GetRuntimeType(textMessage.NMSType);
+ if(null == objType)
+ {
+ Tracer.ErrorFormat("Could not load type for {0} while deserializing XML object.", textMessage.NMSType);
+ return null;
+ }
+
+ return XmlUtil.Deserialize(objType, textMessage.Text);
+ }
+
+ /// <summary>
+ /// Get the runtime type for the class name. This routine will search all loaded
+ /// assemblies in the current App Domain to find the type.
+ /// </summary>
+ /// <param name="typeName">Full name of the type.</param>
+ /// <returns>Type object if found, or null if not found.</returns>
+ private static Type GetRuntimeType(string typeName)
+ {
+ Type objType = null;
+
+ foreach(Assembly assembly in AppDomain.CurrentDomain.GetAssemblies())
+ {
+ objType = assembly.GetType(typeName, false, true);
+ if(null != objType)
+ {
+ break;
+ }
+ }
+
+ return objType;
+ }
}
}
Added: activemq/activemq-dotnet/Apache.NMS/trunk/src/main/csharp/Util/XmlUtils.cs
URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS/trunk/src/main/csharp/Util/XmlUtils.cs?rev=762903&view=auto
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS/trunk/src/main/csharp/Util/XmlUtils.cs (added)
+++ activemq/activemq-dotnet/Apache.NMS/trunk/src/main/csharp/Util/XmlUtils.cs Tue Apr 7 19:01:00 2009
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.IO;
+using System.Text;
+using System.Xml.Serialization;
+
+namespace Apache.NMS.Util
+{
+ /// <summary>
+ /// Class to provide support for working with Xml objects.
+ /// </summary>
+ public class XmlUtil
+ {
+ public static string Serialize(object obj)
+ {
+ XmlSerializer serializer = new XmlSerializer(obj.GetType());
+ StringWriter writer = new StringWriter(new StringBuilder(4096));
+
+ /*
+ * If the XML document has been altered with unknown
+ * nodes or attributes, handle them with the
+ * UnknownNode and UnknownAttribute events.
+ */
+ serializer.UnknownNode += new XmlNodeEventHandler(serializer_UnknownNode);
+ serializer.UnknownAttribute += new XmlAttributeEventHandler(serializer_UnknownAttribute);
+ serializer.Serialize(writer, obj);
+ return writer.ToString();
+ }
+
+ public static object Deserialize(Type objType, string text)
+ {
+ if(null == text)
+ {
+ return null;
+ }
+
+ XmlSerializer serializer = new XmlSerializer(objType);
+ /*
+ * If the XML document has been altered with unknown
+ * nodes or attributes, handle them with the
+ * UnknownNode and UnknownAttribute events.
+ */
+ serializer.UnknownNode += new XmlNodeEventHandler(serializer_UnknownNode);
+ serializer.UnknownAttribute += new XmlAttributeEventHandler(serializer_UnknownAttribute);
+ return serializer.Deserialize(new StringReader(text));
+ }
+
+ private static void serializer_UnknownNode(object sender, XmlNodeEventArgs e)
+ {
+ Tracer.ErrorFormat("Unknown Node: {0}\t{1}", e.Name, e.Text);
+ }
+
+ private static void serializer_UnknownAttribute(object sender, XmlAttributeEventArgs e)
+ {
+ Tracer.ErrorFormat("Unknown attribute: {0}='{1}'", e.Attr.Name, e.Attr.Value);
+ }
+
+ }
+}
+
Modified: activemq/activemq-dotnet/Apache.NMS/trunk/src/test/csharp/MessageSelectorTest.cs
URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS/trunk/src/test/csharp/MessageSelectorTest.cs?rev=762903&r1=762902&r2=762903&view=diff
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS/trunk/src/test/csharp/MessageSelectorTest.cs (original)
+++ activemq/activemq-dotnet/Apache.NMS/trunk/src/test/csharp/MessageSelectorTest.cs Tue Apr 7 19:01:00 2009
@@ -58,7 +58,6 @@
{
IDestination destination1 = CreateDestination(session1, destinationName);
IDestination destination2 = SessionUtil.GetDestination(session2, destinationName);
- IDestination destination3 = SessionUtil.GetDestination(session2, destinationName);
using(IMessageProducer producer = session1.CreateProducer(destination1))
using(IMessageConsumer consumer1 = session2.CreateConsumer(destination2, "JMSType NOT LIKE '%IGNORE'"))
Added: activemq/activemq-dotnet/Apache.NMS/trunk/src/test/csharp/XmlMessage.cs
URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS/trunk/src/test/csharp/XmlMessage.cs?rev=762903&view=auto
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS/trunk/src/test/csharp/XmlMessage.cs (added)
+++ activemq/activemq-dotnet/Apache.NMS/trunk/src/test/csharp/XmlMessage.cs Tue Apr 7 19:01:00 2009
@@ -0,0 +1,127 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+using System;
+using System.Xml.Schema;
+using System.Xml.Serialization;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+ // Serializable object. In real life, this type of object would be generated from
+ // an XSD file using XSDObjectGen.
+ [Serializable]
+ public enum CheckType
+ {
+ // [XmlEnum(Name = "message")]
+ message,
+ // [XmlEnum(Name = "command")]
+ command,
+ // [XmlEnum(Name = "response")]
+ response
+ }
+
+ [XmlRoot(ElementName = "NMSTestXmlType1", IsNullable = false), Serializable]
+ public class NMSTestXmlType1
+ {
+ // [XmlElement(ElementName = "crcCheck", IsNullable = false, DataType = "int")]
+ public int crcCheck;
+
+ // [XmlElement(Type = typeof(CheckType), ElementName = "checkType", IsNullable = false)]
+ public CheckType checkType;
+
+ public NMSTestXmlType1()
+ {
+ crcCheck = 0;
+ checkType = CheckType.message;
+ }
+ }
+
+ [XmlRoot(ElementName = "NMSTestXmlType2", IsNullable = false), Serializable]
+ public class NMSTestXmlType2
+ {
+ // [XmlElement(ElementName = "stringCheck", IsNullable = false, DataType = "string")]
+ public string stringCheck;
+
+ public NMSTestXmlType2()
+ {
+ stringCheck = String.Empty;
+ }
+ }
+
+ [TestFixture]
+ public class XmlMessageTest : NMSTestSupport
+ {
+ protected static string DESTINATION_NAME = "XmlMessageDestination";
+ protected static string TEST_CLIENT_ID = "XmlMessageClientId";
+
+ [Test]
+ public void SendReceiveXmlMessage()
+ {
+ using(IConnection connection = CreateConnection(TEST_CLIENT_ID))
+ {
+ connection.Start();
+ using(ISession session = connection.CreateSession(AcknowledgementMode.AutoAcknowledge))
+ {
+ IDestination destination = SessionUtil.GetDestination(session, DESTINATION_NAME);
+ using(IMessageConsumer consumer = session.CreateConsumer(destination))
+ using(IMessageProducer producer = session.CreateProducer(destination))
+ {
+ producer.RequestTimeout = receiveTimeout;
+
+ NMSTestXmlType1 srcIntObject = new NMSTestXmlType1();
+ srcIntObject.crcCheck = 0xbadf00d;
+ srcIntObject.checkType = CheckType.command;
+ producer.Send(NMSConvert.ToXmlMessage(session, srcIntObject));
+
+ NMSTestXmlType2 srcStringObject = new NMSTestXmlType2();
+ srcStringObject.stringCheck = "BadFood";
+ producer.Send(NMSConvert.ToXmlMessage(session, srcStringObject));
+
+ // Demonstrate the ability to generically handle multiple object types
+ // sent to the same consumer. If only one object type is ever sent to
+ // the destination, then a simple inline cast is all that is necessary
+ // when calling the NMSConvert.FromXmlMessage() function.
+
+ for(int index = 0; index < 2; index++)
+ {
+ object receivedObject = NMSConvert.FromXmlMessage(consumer.Receive(receiveTimeout));
+ Assert.IsNotNull(receivedObject, "Failed to retrieve XML message object.");
+
+ if(receivedObject is NMSTestXmlType1)
+ {
+ NMSTestXmlType1 destObject = (NMSTestXmlType1) receivedObject;
+ Assert.AreEqual(srcIntObject.crcCheck, destObject.crcCheck, "CRC integer mis-match.");
+ Assert.AreEqual(srcIntObject.checkType, destObject.checkType, "Check type mis-match.");
+ }
+ else if(receivedObject is NMSTestXmlType2)
+ {
+ NMSTestXmlType2 destObject = (NMSTestXmlType2) receivedObject;
+ Assert.AreEqual(srcStringObject.stringCheck, destObject.stringCheck, "CRC string mis-match.");
+ }
+ else
+ {
+ Assert.Fail("Invalid object type.");
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+}
Modified: activemq/activemq-dotnet/Apache.NMS/trunk/vs2008-nms-test.csproj
URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS/trunk/vs2008-nms-test.csproj?rev=762903&r1=762902&r2=762903&view=diff
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS/trunk/vs2008-nms-test.csproj (original)
+++ activemq/activemq-dotnet/Apache.NMS/trunk/vs2008-nms-test.csproj Tue Apr 7 19:01:00 2009
@@ -103,6 +103,7 @@
<Compile Include="src\test\csharp\TransactionTest.cs">
<SubType>Code</SubType>
</Compile>
+ <Compile Include="src\test\csharp\XmlMessage.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="vs2008-nms.csproj">
Modified: activemq/activemq-dotnet/Apache.NMS/trunk/vs2008-nms.csproj
URL: http://svn.apache.org/viewvc/activemq/activemq-dotnet/Apache.NMS/trunk/vs2008-nms.csproj?rev=762903&r1=762902&r2=762903&view=diff
==============================================================================
--- activemq/activemq-dotnet/Apache.NMS/trunk/vs2008-nms.csproj (original)
+++ activemq/activemq-dotnet/Apache.NMS/trunk/vs2008-nms.csproj Tue Apr 7 19:01:00 2009
@@ -93,6 +93,7 @@
<Compile Include="src\main\csharp\Util\URISupport.cs">
<SubType>Code</SubType>
</Compile>
+ <Compile Include="src\main\csharp\Util\XmlUtils.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="LICENSE.txt">