initial fix for: https://issues.apache.org/activemq/browse/AMQNET-276

Adds MessageTransformation abstract class to NMS util and implements for Stomp and ActiveMQ clients.


diff --git a/src/main/csharp/IMessage.cs b/src/main/csharp/IMessage.cs
index de36f47..2255178 100644
--- a/src/main/csharp/IMessage.cs
+++ b/src/main/csharp/IMessage.cs
@@ -58,7 +58,7 @@
 		/// <summary>
 		/// The destination of the message.  This property is set by the IMessageProducer.
 		/// </summary>
-		IDestination NMSDestination { get; }
+		IDestination NMSDestination { get; set; }
 
 		/// <summary>
 		/// The amount of time for which this message is valid.  Zero if this message does not expire.
@@ -68,7 +68,7 @@
 		/// <summary>
 		/// The message ID which is set by the provider.
 		/// </summary>
-		string NMSMessageId { get; }
+		string NMSMessageId { get; set; }
 
 		/// <summary>
 		/// Whether or not this message is persistent.
@@ -83,7 +83,7 @@
 		/// <summary>
 		/// Returns true if this message has been redelivered to this or another consumer before being acknowledged successfully.
 		/// </summary>
-		bool NMSRedelivered { get; }
+		bool NMSRedelivered { get; set; }
 
 		/// <summary>
 		/// The destination that the consumer of this message should send replies to
@@ -94,7 +94,7 @@
 		/// The timestamp of when the message was pubished in UTC time.  If the publisher disables setting
 		/// the timestamp on the message, the time will be set to the start of the UNIX epoc (1970-01-01 00:00:00).
 		/// </summary>
-		DateTime NMSTimestamp { get; }
+		DateTime NMSTimestamp { get; set; }
 
 		/// <summary>
 		/// The type name of this message.
diff --git a/src/main/csharp/IObjectMessage.cs b/src/main/csharp/IObjectMessage.cs
index 09ca0d1..f7a439f 100644
--- a/src/main/csharp/IObjectMessage.cs
+++ b/src/main/csharp/IObjectMessage.cs
@@ -21,6 +21,6 @@
 	/// </summary>
 	public interface IObjectMessage : IMessage
 	{
-		object Body { get; }
+		object Body { get; set; }
 	}
 }
diff --git a/src/main/csharp/Util/MessageTransformation.cs b/src/main/csharp/Util/MessageTransformation.cs
new file mode 100644
index 0000000..1141367
--- /dev/null
+++ b/src/main/csharp/Util/MessageTransformation.cs
@@ -0,0 +1,168 @@
+/*
+ * 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;
+
+namespace Apache.NMS.Util
+{
+    /// <summary>
+    /// Base Utility class for conversion between IMessage type objects for different
+    /// NMS providers.
+    /// </summary>
+	public abstract class MessageTransformation
+	{
+		public MessageTransformation()
+		{
+		}
+
+        public T TransformMessage<T>(IMessage message)
+        {
+            if(message is T)
+            {
+                return (T) message;
+            }
+            else
+            {
+                IMessage result = null;
+    
+                if(message is IBytesMessage)
+                {
+                    IBytesMessage bytesMsg = message as IBytesMessage;
+                    bytesMsg.Reset();
+                    IBytesMessage msg = DoCreateBytesMessage();
+
+                    try
+                    {
+                        for(;;)
+                        {
+                            // Reads a byte from the message stream until the stream is empty
+                            msg.WriteByte(bytesMsg.ReadByte());
+                        }
+                    }
+                    catch
+                    {
+                    }
+
+                    result = msg;
+                }
+                else if(message is IMapMessage)
+                {
+                    IMapMessage mapMsg = message as IMapMessage;
+                    IMapMessage msg = DoCreateMapMessage();
+
+                    foreach(string key in mapMsg.Body.Keys)
+                    {
+                        msg.Body[key] = mapMsg.Body[key];
+                    }
+
+                    result = msg;
+                }
+                else if(message is IObjectMessage)
+                {
+                    IObjectMessage objMsg = message as IObjectMessage;
+                    IObjectMessage msg = DoCreateObjectMessage();
+                    msg.Body = objMsg.Body;
+
+                    result = msg;
+                }
+                else if(message is IStreamMessage)
+                {
+                    IStreamMessage streamMessage = message as IStreamMessage;
+                    streamMessage.Reset();
+                    IStreamMessage msg = DoCreateStreamMessage();
+
+                    object obj = null;
+
+                    try
+                    {
+                        while((obj = streamMessage.ReadObject()) != null)
+                        {
+                            msg.WriteObject(obj);
+                        }
+                    }
+                    catch
+                    {
+                    }
+
+                    result = msg;
+                }
+                else if(message is ITextMessage)
+                {
+                    ITextMessage textMsg = message as ITextMessage;
+                    ITextMessage msg = DoCreateTextMessage();
+                    msg.Text = textMsg.Text;
+                    result = msg;
+                }
+                else
+                {
+                    result = DoCreateMessage();
+                }
+
+                CopyProperties(message, result);
+
+                // Let the subclass have a chance to do any last minute configurations
+                // on the newly converted message.
+                DoPostProcessMessage(result);
+
+                return (T) result;
+            }
+        }
+
+        /**
+         * Copies the standard JMS and user defined properties from the givem
+         * message to the specified message
+         *
+         * @param fromMessage the message to take the properties from
+         * @param toMessage the message to add the properties to
+         * @throws JMSException
+         */
+        public virtual void CopyProperties(IMessage fromMessage, IMessage toMessage)
+        {
+            toMessage.NMSMessageId = fromMessage.NMSMessageId;
+            toMessage.NMSCorrelationID = fromMessage.NMSCorrelationID;
+            toMessage.NMSReplyTo = DoTransformDestination(fromMessage.NMSReplyTo);
+            toMessage.NMSDestination = DoTransformDestination(fromMessage.NMSDestination);
+            toMessage.NMSDeliveryMode = fromMessage.NMSDeliveryMode;
+            toMessage.NMSRedelivered = fromMessage.NMSRedelivered;
+            toMessage.NMSType = fromMessage.NMSType;
+            toMessage.NMSPriority = fromMessage.NMSPriority;
+            toMessage.NMSTimestamp = fromMessage.NMSTimestamp;
+            toMessage.NMSTimeToLive = fromMessage.NMSTimeToLive;
+
+            foreach(string key in fromMessage.Properties.Keys)
+            {
+                toMessage.Properties[key] = fromMessage.Properties[key];
+            }
+        }
+
+        #region Creation Methods and Conversion Support Methods
+
+        protected abstract IMessage DoCreateMessage();
+        protected abstract IBytesMessage DoCreateBytesMessage();
+        protected abstract ITextMessage DoCreateTextMessage();
+        protected abstract IStreamMessage DoCreateStreamMessage();
+        protected abstract IMapMessage DoCreateMapMessage();
+        protected abstract IObjectMessage DoCreateObjectMessage();
+
+        protected abstract IDestination DoTransformDestination(IDestination destination);
+        protected abstract void DoPostProcessMessage(IMessage message);
+
+        #endregion
+
+	}
+}
+