Moved PrimitiveMap, OpenWireBinaryReader, OpenWireBinaryWriter, EndianSupport, MessagePropertyHelper and associated tests from Apache.NMS.ActiveMQ into Apache.NMS. These are generally useful classes that should be shared among the providers instead of forcing all providers to re-implement these highly useful and complex classes.
Renamed OpenWireBinaryWriter to EndianBinaryWriter.
Renamed OpenWireBinaryReader to EndianBinaryReader.
Implemented MapMessage marshaling in Apache.NMS.MSMQ.
diff --git a/src/main/csharp/Util/EndianBinaryReader.cs b/src/main/csharp/Util/EndianBinaryReader.cs
new file mode 100644
index 0000000..d2231d3
--- /dev/null
+++ b/src/main/csharp/Util/EndianBinaryReader.cs
@@ -0,0 +1,410 @@
+/*
+ * 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;
+
+namespace Apache.NMS.Util
+{
+ /// <summary>
+ /// A BinaryWriter that switches the endian orientation of the read operations so that they
+ /// are compatible across platforms.
+ /// </summary>
+ [CLSCompliant(false)]
+ public class EndianBinaryReader : BinaryReader
+ {
+ public EndianBinaryReader(Stream input)
+ : base(input)
+ {
+ }
+
+ /// <summary>
+ /// Method Read
+ /// </summary>
+ /// <returns>An int</returns>
+ /// <param name="buffer">A char[]</param>
+ /// <param name="index">An int</param>
+ /// <param name="count">An int</param>
+ public override int Read(char[] buffer, int index, int count)
+ {
+ int size = base.Read(buffer, index, count);
+ for(int i = 0; i < size; i++)
+ {
+ buffer[index + i] = EndianSupport.SwitchEndian(buffer[index + i]);
+ }
+ return size;
+ }
+
+ /// <summary>
+ /// Method ReadChars
+ /// </summary>
+ /// <returns>A char[]</returns>
+ /// <param name="count">An int</param>
+ public override char[] ReadChars(int count)
+ {
+ char[] rc = base.ReadChars(count);
+ if(rc != null)
+ {
+ for(int i = 0; i < rc.Length; i++)
+ {
+ rc[i] = EndianSupport.SwitchEndian(rc[i]);
+ }
+ }
+ return rc;
+ }
+
+ /// <summary>
+ /// Method ReadInt16
+ /// </summary>
+ /// <returns>A short</returns>
+ public override short ReadInt16()
+ {
+ return EndianSupport.SwitchEndian(base.ReadInt16());
+ }
+
+ /// <summary>
+ /// Method ReadChar
+ /// </summary>
+ /// <returns>A char</returns>
+ public override char ReadChar()
+ {
+ return (char) (
+ (((char) ((byte) (base.ReadByte()))) << 8) |
+ (((char) ((byte) (base.ReadByte()))))
+ );
+
+ // return EndianSupport.SwitchEndian(base.ReadChar());
+ }
+
+ /// <summary>
+ /// Method ReadInt64
+ /// </summary>
+ /// <returns>A long</returns>
+ public override long ReadInt64()
+ {
+ return EndianSupport.SwitchEndian(base.ReadInt64());
+ }
+
+ /// <summary>
+ /// Method ReadUInt64
+ /// </summary>
+ /// <returns>An ulong</returns>
+ public override ulong ReadUInt64()
+ {
+ return EndianSupport.SwitchEndian(base.ReadUInt64());
+ }
+
+ /// <summary>
+ /// Method ReadUInt32
+ /// </summary>
+ /// <returns>An uint</returns>
+ public override uint ReadUInt32()
+ {
+ return EndianSupport.SwitchEndian(base.ReadUInt32());
+ }
+
+ /// <summary>
+ /// Method ReadUInt16
+ /// </summary>
+ /// <returns>An ushort</returns>
+ public override ushort ReadUInt16()
+ {
+ return EndianSupport.SwitchEndian(base.ReadUInt16());
+ }
+
+ /// <summary>
+ /// Method ReadInt32
+ /// </summary>
+ /// <returns>An int</returns>
+ public override int ReadInt32()
+ {
+ int x = base.ReadInt32();
+ int y = EndianSupport.SwitchEndian(x);
+ return y;
+ }
+
+ /// <summary>
+ /// Method ReadString
+ /// </summary>
+ /// <returns>A string</returns>
+ public override String ReadString()
+ {
+ short utflen = ReadInt16();
+ if(utflen > -1)
+ {
+ StringBuilder str = new StringBuilder(utflen);
+
+ byte[] bytearr = new byte[utflen];
+ int bytesRead = 0;
+ while(bytesRead < utflen)
+ {
+ int rc = Read(bytearr, bytesRead, utflen - bytesRead);
+ if(rc == 0)
+ {
+ throw new IOException("premature end of stream");
+ }
+
+ bytesRead += rc;
+ }
+
+ int c, char2, char3;
+ int count = 0;
+
+ while(count < utflen)
+ {
+ c = bytearr[count] & 0xff;
+ switch(c >> 4)
+ {
+ case 0:
+ case 1:
+ case 2:
+ case 3:
+ case 4:
+ case 5:
+ case 6:
+ case 7:
+ /* 0xxxxxxx */
+ count++;
+ str.Append((char) c);
+ break;
+ case 12:
+ case 13:
+ /* 110x xxxx 10xx xxxx */
+ count += 2;
+ if(count > utflen)
+ {
+ throw CreateDataFormatException();
+ }
+
+ char2 = bytearr[count - 1];
+ if((char2 & 0xC0) != 0x80)
+ {
+ throw CreateDataFormatException();
+ }
+
+ str.Append((char) (((c & 0x1F) << 6) | (char2 & 0x3F)));
+ break;
+ case 14:
+ /* 1110 xxxx 10xx xxxx 10xx xxxx */
+ count += 3;
+ if(count > utflen)
+ {
+ throw CreateDataFormatException();
+ }
+
+ char2 = bytearr[count - 2];
+ char3 = bytearr[count - 1];
+ if(((char2 & 0xC0) != 0x80) || ((char3 & 0xC0) != 0x80))
+ {
+ throw CreateDataFormatException();
+ }
+
+ str.Append((char) (((c & 0x0F) << 12) | ((char2 & 0x3F) << 6) | ((char3 & 0x3F) << 0)));
+ break;
+ default:
+ /* 10xx xxxx, 1111 xxxx */
+ throw CreateDataFormatException();
+ }
+ }
+ // The number of chars produced may be less than utflen
+ return str.ToString();
+ }
+ else
+ {
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Method ReadString16, reads a String value encoded in the Java modified
+ /// UTF-8 format with a length index encoded as a 16bit unsigned short.
+ /// </summary>
+ /// <returns>A string</returns>
+ public String ReadString16()
+ {
+ int utfLength = ReadUInt16();
+
+ if(utfLength <= 0)
+ {
+ return "";
+ }
+
+ char[] result = new char[utfLength];
+ byte[] buffer = new byte[utfLength];
+
+ int bytesRead = 0;
+ while(bytesRead < utfLength)
+ {
+ int rc = Read(buffer, bytesRead, utfLength - bytesRead);
+ if(rc == 0)
+ {
+ throw new IOException("premature end of stream");
+ }
+
+ bytesRead += rc;
+ }
+
+ int count = 0;
+ int index = 0;
+ byte a = 0;
+
+ while(count < utfLength)
+ {
+ if((result[index] = (char) buffer[count++]) < 0x80)
+ {
+ index++;
+ }
+ else if(((a = (byte) result[index]) & 0xE0) == 0xC0)
+ {
+ if(count >= utfLength)
+ {
+ throw new IOException("Invalid UTF-8 encoding found, start of two byte char found at end.");
+ }
+
+ byte b = buffer[count++];
+ if((b & 0xC0) != 0x80)
+ {
+ throw new IOException("Invalid UTF-8 encoding found, byte two does not start with 0x80.");
+ }
+
+ result[index++] = (char) (((a & 0x1F) << 6) | (b & 0x3F));
+ }
+ else if((a & 0xF0) == 0xE0)
+ {
+ if(count + 1 >= utfLength)
+ {
+ throw new IOException("Invalid UTF-8 encoding found, start of three byte char found at end.");
+ }
+
+ byte b = buffer[count++];
+ byte c = buffer[count++];
+ if(((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80))
+ {
+ throw new IOException("Invalid UTF-8 encoding found, byte two does not start with 0x80.");
+ }
+
+ result[index++] = (char) (((a & 0x0F) << 12) |
+ ((b & 0x3F) << 6) | (c & 0x3F));
+ }
+ else
+ {
+ throw new IOException("Invalid UTF-8 encoding found, aborting.");
+ }
+ }
+
+ return new String(result, 0, index);
+ }
+
+ /// <summary>
+ /// Method ReadString32, reads a String value encoded in the Java modified
+ /// UTF-8 format with a length index encoded as a singed integer value.
+ /// </summary>
+ /// <returns>A string</returns>
+ public String ReadString32()
+ {
+ int utfLength = ReadInt32();
+
+ if(utfLength <= 0)
+ {
+ return "";
+ }
+
+ char[] result = new char[utfLength];
+ byte[] buffer = new byte[utfLength];
+
+ int bytesRead = 0;
+ while(bytesRead < utfLength)
+ {
+ int rc = Read(buffer, bytesRead, utfLength - bytesRead);
+ if(rc == 0)
+ {
+ throw new IOException("premature end of stream");
+ }
+
+ bytesRead += rc;
+ }
+
+ int count = 0;
+ int index = 0;
+ byte a = 0;
+
+ while(count < utfLength)
+ {
+ if((result[index] = (char) buffer[count++]) < 0x80)
+ {
+ index++;
+ }
+ else if(((a = (byte) result[index]) & 0xE0) == 0xC0)
+ {
+ if(count >= utfLength)
+ {
+ throw new IOException("Invalid UTF-8 encoding found, start of two byte char found at end.");
+ }
+
+ byte b = buffer[count++];
+ if((b & 0xC0) != 0x80)
+ {
+ throw new IOException("Invalid UTF-8 encoding found, byte two does not start with 0x80.");
+ }
+
+ result[index++] = (char) (((a & 0x1F) << 6) | (b & 0x3F));
+ }
+ else if((a & 0xF0) == 0xE0)
+ {
+
+ if(count + 1 >= utfLength)
+ {
+ throw new IOException("Invalid UTF-8 encoding found, start of three byte char found at end.");
+ }
+
+ byte b = buffer[count++];
+ byte c = buffer[count++];
+ if(((b & 0xC0) != 0x80) || ((c & 0xC0) != 0x80))
+ {
+ throw new IOException("Invalid UTF-8 encoding found, byte two does not start with 0x80.");
+ }
+
+ result[index++] = (char) (((a & 0x0F) << 12) |
+ ((b & 0x3F) << 6) | (c & 0x3F));
+ }
+ else
+ {
+ throw new IOException("Invalid UTF-8 encoding found, aborting.");
+ }
+ }
+
+ return new String(result, 0, index);
+ }
+
+ public override float ReadSingle()
+ {
+ return EndianSupport.SwitchEndian(base.ReadSingle());
+ }
+
+ public override double ReadDouble()
+ {
+ return EndianSupport.SwitchEndian(base.ReadDouble());
+ }
+
+ protected static Exception CreateDataFormatException()
+ {
+ // TODO: implement a better exception
+ return new IOException("Data format error!");
+ }
+ }
+}
diff --git a/src/main/csharp/Util/EndianBinaryWriter.cs b/src/main/csharp/Util/EndianBinaryWriter.cs
new file mode 100644
index 0000000..bcd0bbb
--- /dev/null
+++ b/src/main/csharp/Util/EndianBinaryWriter.cs
@@ -0,0 +1,295 @@
+/*
+ * 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;
+
+namespace Apache.NMS.Util
+{
+ /// <summary>
+ /// A BinaryWriter that switches the endian orientation of the write operations so that they
+ /// are compatible across platforms.
+ /// </summary>
+ [CLSCompliant(false)]
+ public class EndianBinaryWriter : BinaryWriter
+ {
+ public const int MAXSTRINGLEN = short.MaxValue;
+
+ public EndianBinaryWriter(Stream output)
+ : base(output)
+ {
+ }
+
+ /// <summary>
+ /// Method Write
+ /// </summary>
+ /// <param name="value">A long</param>
+ public override void Write(long value)
+ {
+ base.Write(EndianSupport.SwitchEndian(value));
+ }
+
+ /// <summary>
+ /// Method Write
+ /// </summary>
+ /// <param name="value">An ushort</param>
+ public override void Write(ushort value)
+ {
+ base.Write(EndianSupport.SwitchEndian(value));
+ }
+
+ /// <summary>
+ /// Method Write
+ /// </summary>
+ /// <param name="value">An int</param>
+ public override void Write(int value)
+ {
+ int x = EndianSupport.SwitchEndian(value);
+ base.Write(x);
+ }
+
+ /// <summary>
+ /// Method Write
+ /// </summary>
+ /// <param name="chars">A char[]</param>
+ /// <param name="index">An int</param>
+ /// <param name="count">An int</param>
+ public override void Write(char[] chars, int index, int count)
+ {
+ char[] t = new char[count];
+ for(int i = 0; i < count; i++)
+ {
+ t[index + i] = EndianSupport.SwitchEndian(t[index + i]);
+ }
+ base.Write(t);
+ }
+
+ /// <summary>
+ /// Method Write
+ /// </summary>
+ /// <param name="chars">A char[]</param>
+ public override void Write(char[] chars)
+ {
+ Write(chars, 0, chars.Length);
+ }
+
+ /// <summary>
+ /// Method Write
+ /// </summary>
+ /// <param name="value">An uint</param>
+ public override void Write(uint value)
+ {
+ base.Write(EndianSupport.SwitchEndian(value));
+ }
+
+ /// <summary>
+ /// Method Write
+ /// </summary>
+ /// <param name="ch">A char</param>
+ public override void Write(char ch)
+ {
+ base.Write((byte) ((ch >> 8) & 0xFF));
+ base.Write((byte) (ch & 0xFF));
+ }
+
+ /// <summary>
+ /// Method Write
+ /// </summary>
+ /// <param name="value">An ulong</param>
+ public override void Write(ulong value)
+ {
+ base.Write(EndianSupport.SwitchEndian(value));
+ }
+
+ /// <summary>
+ /// Method Write
+ /// </summary>
+ /// <param name="value">A short</param>
+ public override void Write(short value)
+ {
+ base.Write(EndianSupport.SwitchEndian(value));
+ }
+
+ /// <summary>
+ /// Method Write, writes a string to the output using the WriteString16
+ /// method.
+ /// </summary>
+ /// <param name="text">A string</param>
+ public override void Write(String text)
+ {
+ WriteString16(text);
+ }
+
+ /// <summary>
+ /// Method WriteString16, writes a string to the output using the Java
+ /// standard modified UTF-8 encoding with an unsigned short value written first to
+ /// indicate the length of the encoded data, the short is read as an unsigned
+ /// value so the max amount of data this method can write is 65535 encoded bytes.
+ ///
+ /// Unlike the WriteString32 method this method does not encode the length
+ /// value to -1 if the string is null, this is to match the behaviour of
+ /// the Java DataOuputStream class's writeUTF method.
+ ///
+ /// Because modified UTF-8 encding can result in a number of bytes greater that
+ /// the size of the String this method must first check that the encoding proces
+ /// will not result in a value that cannot be written becuase it is greater than
+ /// the max value of an unsigned short.
+ /// </summary>
+ /// <param name="text">A string</param>
+ public void WriteString16(String text)
+ {
+ if(text != null)
+ {
+ if(text.Length > ushort.MaxValue)
+ {
+ throw new IOException(
+ String.Format(
+ "Cannot marshall string longer than: {0} characters, supplied string was: " +
+ "{1} characters", ushort.MaxValue, text.Length));
+ }
+
+ char[] charr = text.ToCharArray();
+ uint utfLength = CountUtf8Bytes(charr);
+
+ if(utfLength > ushort.MaxValue)
+ {
+ throw new IOException(
+ String.Format(
+ "Cannot marshall an encoded string longer than: {0} bytes, supplied" +
+ "string requires: {1} characters to encode", ushort.MaxValue, utfLength));
+ }
+
+ byte[] bytearr = new byte[utfLength];
+ encodeUTF8toBuffer(charr, bytearr);
+
+ Write((ushort) utfLength);
+ Write(bytearr);
+ }
+ }
+
+ /// <summary>
+ /// Method WriteString32, writes a string to the output using the Openwire
+ /// standard modified UTF-8 encoding which an int value written first to
+ /// indicate the length of the encoded data, the int is read as an signed
+ /// value so the max amount of data this method can write is 2^31 encoded bytes.
+ ///
+ /// In the case of a null value being passed this method writes a -1 to the
+ /// stream to indicate that the string is null.
+ ///
+ /// Because modified UTF-8 encding can result in a number of bytes greater that
+ /// the size of the String this method must first check that the encoding proces
+ /// will not result in a value that cannot be written becuase it is greater than
+ /// the max value of an int.
+ /// </summary>
+ /// <param name="text">A string</param>
+ public void WriteString32(String text)
+ {
+ if(text != null)
+ {
+ char[] charr = text.ToCharArray();
+ uint utfLength = CountUtf8Bytes(charr);
+
+ if(utfLength > int.MaxValue)
+ {
+ throw new IOException(
+ String.Format(
+ "Cannot marshall an encoded string longer than: {0} bytes, supplied" +
+ "string requires: {1} characters to encode", int.MaxValue, utfLength));
+ }
+
+ byte[] bytearr = new byte[utfLength];
+ encodeUTF8toBuffer(charr, bytearr);
+
+ Write(utfLength);
+ Write(bytearr);
+ }
+ else
+ {
+ Write((int) -1);
+ }
+ }
+
+ /// <summary>
+ /// Method Write
+ /// </summary>
+ /// <param name="value">A double</param>
+ public override void Write(float value)
+ {
+ base.Write(EndianSupport.SwitchEndian(value));
+ }
+
+ /// <summary>
+ /// Method Write
+ /// </summary>
+ /// <param name="value">A double</param>
+ public override void Write(double value)
+ {
+ base.Write(EndianSupport.SwitchEndian(value));
+ }
+
+ private uint CountUtf8Bytes(char[] chars)
+ {
+ uint utfLength = 0;
+ int c = 0;
+
+ for(int i = 0; i < chars.Length; i++)
+ {
+ c = chars[i];
+ if((c >= 0x0001) && (c <= 0x007F))
+ {
+ utfLength++;
+ }
+ else if(c > 0x07FF)
+ {
+ utfLength += 3;
+ }
+ else
+ {
+ utfLength += 2;
+ }
+ }
+
+ return utfLength;
+ }
+
+ private void encodeUTF8toBuffer(char[] chars, byte[] buffer)
+ {
+ int c = 0;
+ int count = 0;
+
+ for(int i = 0; i < chars.Length; i++)
+ {
+ c = chars[i];
+ if((c >= 0x0001) && (c <= 0x007F))
+ {
+ buffer[count++] = (byte) c;
+ }
+ else if(c > 0x07FF)
+ {
+ buffer[count++] = (byte) (0xE0 | ((c >> 12) & 0x0F));
+ buffer[count++] = (byte) (0x80 | ((c >> 6) & 0x3F));
+ buffer[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
+ }
+ else
+ {
+ buffer[count++] = (byte) (0xC0 | ((c >> 6) & 0x1F));
+ buffer[count++] = (byte) (0x80 | ((c >> 0) & 0x3F));
+ }
+ }
+ }
+ }
+}
diff --git a/src/main/csharp/Util/EndianSupport.cs b/src/main/csharp/Util/EndianSupport.cs
new file mode 100644
index 0000000..2b44795
--- /dev/null
+++ b/src/main/csharp/Util/EndianSupport.cs
@@ -0,0 +1,133 @@
+/*
+ * 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.IO;
+using System;
+
+namespace Apache.NMS.Util
+{
+ /// <summary>
+ /// Support class that switches from one endian to the other.
+ /// </summary>
+ [CLSCompliant(false)]
+ public class EndianSupport
+ {
+
+ public static char SwitchEndian(char x)
+ {
+ return (char) (
+ (((char)( (byte)(x) )) << 8 ) |
+ (((char)( (byte)(x >> 8) )) )
+ );
+ }
+
+ public static short SwitchEndian(short x)
+ {
+ return (short) (
+ (((ushort)( (byte)(x) )) << 8 ) |
+ (((ushort)( (byte)(x >> 8) )) )
+ );
+ }
+
+ public static int SwitchEndian(int x)
+ {
+ return
+ (((int)( (byte)(x) )) << 24 ) |
+ (((int)( (byte)(x >> 8) )) << 16 ) |
+ (((int)( (byte)(x >> 16) )) << 8 ) |
+ (((int)( (byte)(x >> 24) )) );
+ }
+
+ public static long SwitchEndian(long x)
+ {
+ return
+ (((long)( (byte)(x ) )) << 56 ) |
+ (((long)( (byte)(x >> 8) )) << 48 ) |
+ (((long)( (byte)(x >> 16) )) << 40 ) |
+ (((long)( (byte)(x >> 24) )) << 32 ) |
+ (((long)( (byte)(x >> 32) )) << 24 ) |
+ (((long)( (byte)(x >> 40) )) << 16 ) |
+ (((long)( (byte)(x >> 48) )) << 8 ) |
+ (((long)( (byte)(x >> 56) )) );
+ }
+
+ public static ushort SwitchEndian(ushort x)
+ {
+ return (ushort) (
+ (((ushort)( (byte)(x) )) << 8 ) |
+ (((ushort)( (byte)(x >> 8) )) )
+ );
+ }
+
+ public static uint SwitchEndian(uint x)
+ {
+ return
+ (((uint)( (byte)(x ) )) << 24 ) |
+ (((uint)( (byte)(x >> 8) )) << 16 ) |
+ (((uint)( (byte)(x >> 16) )) << 8 ) |
+ (((uint)( (byte)(x >> 24) )) );
+ }
+
+ public static ulong SwitchEndian(ulong x)
+ {
+ return
+ (((ulong)( (byte)(x ) )) << 56 ) |
+ (((ulong)( (byte)(x >> 8) )) << 48 ) |
+ (((ulong)( (byte)(x >> 16) )) << 40 ) |
+ (((ulong)( (byte)(x >> 24) )) << 32 ) |
+ (((ulong)( (byte)(x >> 32) )) << 24 ) |
+ (((ulong)( (byte)(x >> 40) )) << 16 ) |
+ (((ulong)( (byte)(x >> 48) )) << 8 ) |
+ (((ulong)( (byte)(x >> 56) )) );
+ }
+
+ public static double SwitchEndian(double x)
+ {
+ MemoryStream ms = new MemoryStream();
+ BinaryWriter bw = new BinaryWriter(ms);
+ bw.Write(x);
+ bw.Flush();
+ ms = new MemoryStream(SwitchEndian(ms.ToArray()));
+ BinaryReader br = new BinaryReader(ms);
+ return br.ReadDouble();
+ }
+
+
+ public static float SwitchEndian(float x)
+ {
+ MemoryStream ms = new MemoryStream();
+ BinaryWriter bw = new BinaryWriter(ms);
+ bw.Write(x);
+ bw.Flush();
+ ms = new MemoryStream(SwitchEndian(ms.ToArray()));
+ BinaryReader br = new BinaryReader(ms);
+ return br.ReadSingle();
+ }
+
+
+ public static byte[] SwitchEndian(byte[] x)
+ {
+ byte[] rc = new byte[x.Length];
+ int j = x.Length-1;
+ for(int i=0; i < x.Length; i++ ) {
+ rc[i] = x[j];
+ j--;
+ }
+ return rc;
+ }
+ }
+}
+
diff --git a/src/main/csharp/Util/MessagePropertyHelper.cs b/src/main/csharp/Util/MessagePropertyHelper.cs
new file mode 100644
index 0000000..47a0080
--- /dev/null
+++ b/src/main/csharp/Util/MessagePropertyHelper.cs
@@ -0,0 +1,232 @@
+/*
+ * 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.Reflection;
+
+namespace Apache.NMS.Util
+{
+ // Set NMS properties via introspection
+ public class MessagePropertyHelper : IPrimitiveMap
+ {
+ private static BindingFlags publicBinding = BindingFlags.Public | BindingFlags.Instance;
+ private IMessage message;
+ private IPrimitiveMap properties;
+ private Type messageType;
+
+ public MessagePropertyHelper(IMessage _message, IPrimitiveMap _properties)
+ {
+ this.message = _message;
+ this.properties = _properties;
+ this.messageType = _message.GetType();
+ }
+
+ protected object GetObjectProperty(string name)
+ {
+ PropertyInfo propertyInfo = this.messageType.GetProperty(name, publicBinding);
+
+ if(null != propertyInfo && propertyInfo.CanRead)
+ {
+ return propertyInfo.GetValue(this.message, null);
+ }
+ else
+ {
+ FieldInfo fieldInfo = this.messageType.GetField(name, publicBinding);
+
+ if(null != fieldInfo)
+ {
+ return fieldInfo.GetValue(this.message);
+ }
+ }
+
+ return this.properties[name];
+ }
+
+ protected void SetObjectProperty(string name, object value)
+ {
+ PropertyInfo propertyInfo = this.messageType.GetProperty(name, publicBinding);
+
+ if(null != propertyInfo && propertyInfo.CanWrite)
+ {
+ propertyInfo.SetValue(this.message, value, null);
+ }
+ else
+ {
+ FieldInfo fieldInfo = this.messageType.GetField(name, publicBinding);
+
+ if(null != fieldInfo && !fieldInfo.IsLiteral && !fieldInfo.IsInitOnly)
+ {
+ fieldInfo.SetValue(this.message, value);
+ }
+ else
+ {
+ this.properties[name] = value;
+ }
+ }
+ }
+
+ #region IPrimitiveMap Members
+
+ public void Clear()
+ {
+ this.properties.Clear();
+ }
+
+ public bool Contains(object key)
+ {
+ return this.properties.Contains(key);
+ }
+
+ public void Remove(object key)
+ {
+ this.properties.Remove(key);
+ }
+
+ public int Count
+ {
+ get { return this.properties.Count; }
+ }
+
+ public System.Collections.ICollection Keys
+ {
+ get { return this.properties.Keys; }
+ }
+
+ public System.Collections.ICollection Values
+ {
+ get { return this.properties.Values; }
+ }
+
+ public object this[string key]
+ {
+ get { return GetObjectProperty(key); }
+ set { SetObjectProperty(key, value); }
+ }
+
+ public string GetString(string key)
+ {
+ return (string) GetObjectProperty(key);
+ }
+
+ public void SetString(string key, string value)
+ {
+ SetObjectProperty(key, value);
+ }
+
+ public bool GetBool(string key)
+ {
+ return (bool) GetObjectProperty(key);
+ }
+
+ public void SetBool(string key, bool value)
+ {
+ SetObjectProperty(key, value);
+ }
+
+ public byte GetByte(string key)
+ {
+ return (byte) GetObjectProperty(key);
+ }
+
+ public void SetByte(string key, byte value)
+ {
+ SetObjectProperty(key, value);
+ }
+
+ public char GetChar(string key)
+ {
+ return (char) GetObjectProperty(key);
+ }
+
+ public void SetChar(string key, char value)
+ {
+ SetObjectProperty(key, value);
+ }
+
+ public short GetShort(string key)
+ {
+ return (short) GetObjectProperty(key);
+ }
+
+ public void SetShort(string key, short value)
+ {
+ SetObjectProperty(key, value);
+ }
+
+ public int GetInt(string key)
+ {
+ return (int) GetObjectProperty(key);
+ }
+
+ public void SetInt(string key, int value)
+ {
+ SetObjectProperty(key, value);
+ }
+
+ public long GetLong(string key)
+ {
+ return (long) GetObjectProperty(key);
+ }
+
+ public void SetLong(string key, long value)
+ {
+ SetObjectProperty(key, value);
+ }
+
+ public float GetFloat(string key)
+ {
+ return (float) GetObjectProperty(key);
+ }
+
+ public void SetFloat(string key, float value)
+ {
+ SetObjectProperty(key, value);
+ }
+
+ public double GetDouble(string key)
+ {
+ return (double) GetObjectProperty(key);
+ }
+
+ public void SetDouble(string key, double value)
+ {
+ SetObjectProperty(key, value);
+ }
+
+ public System.Collections.IList GetList(string key)
+ {
+ return (System.Collections.IList) GetObjectProperty(key);
+ }
+
+ public void SetList(string key, System.Collections.IList list)
+ {
+ SetObjectProperty(key, list);
+ }
+
+ public System.Collections.IDictionary GetDictionary(string key)
+ {
+ return (System.Collections.IDictionary) GetObjectProperty(key);
+ }
+
+ public void SetDictionary(string key, System.Collections.IDictionary dictionary)
+ {
+ SetObjectProperty(key, dictionary);
+ }
+
+ #endregion
+ }
+}
diff --git a/src/main/csharp/Util/PrimitiveMap.cs b/src/main/csharp/Util/PrimitiveMap.cs
new file mode 100644
index 0000000..522caef
--- /dev/null
+++ b/src/main/csharp/Util/PrimitiveMap.cs
@@ -0,0 +1,540 @@
+/*
+ * 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.Collections;
+using System.IO;
+
+namespace Apache.NMS.Util
+{
+ /// <summary>
+ /// A default implementation of IPrimitiveMap
+ /// </summary>
+ public class PrimitiveMap : IPrimitiveMap
+ {
+ public const byte NULL = 0;
+ public const byte BOOLEAN_TYPE = 1;
+ public const byte BYTE_TYPE = 2;
+ public const byte CHAR_TYPE = 3;
+ public const byte SHORT_TYPE = 4;
+ public const byte INTEGER_TYPE = 5;
+ public const byte LONG_TYPE = 6;
+ public const byte DOUBLE_TYPE = 7;
+ public const byte FLOAT_TYPE = 8;
+ public const byte STRING_TYPE = 9;
+ public const byte BYTE_ARRAY_TYPE = 10;
+ public const byte MAP_TYPE = 11;
+ public const byte LIST_TYPE = 12;
+ public const byte BIG_STRING_TYPE = 13;
+
+ private IDictionary dictionary = Hashtable.Synchronized(new Hashtable());
+
+ public void Clear()
+ {
+ dictionary.Clear();
+ }
+
+ public bool Contains(Object key)
+ {
+ return dictionary.Contains(key);
+ }
+
+ public void Remove(Object key)
+ {
+ dictionary.Remove(key);
+ }
+
+ public int Count
+ {
+ get { return dictionary.Count; }
+ }
+
+ public ICollection Keys
+ {
+ get { lock(dictionary.SyncRoot) return new ArrayList(dictionary.Keys); }
+ }
+
+ public ICollection Values
+ {
+ get { lock(dictionary.SyncRoot) return new ArrayList(dictionary.Values); }
+ }
+
+ public object this[string key]
+ {
+ get { return GetValue(key); }
+ set
+ {
+ CheckValidType(value);
+ SetValue(key, value);
+ }
+ }
+
+ public string GetString(string key)
+ {
+ Object value = GetValue(key);
+ if(value == null)
+ {
+ return null;
+ }
+ CheckValueType(value, typeof(string));
+ return (string) value;
+ }
+
+ public void SetString(string key, string value)
+ {
+ SetValue(key, value);
+ }
+
+ public bool GetBool(String key)
+ {
+ Object value = GetValue(key);
+ CheckValueType(value, typeof(bool));
+ return (bool) value;
+ }
+
+ public void SetBool(String key, bool value)
+ {
+ SetValue(key, value);
+ }
+
+ public byte GetByte(String key)
+ {
+ Object value = GetValue(key);
+ CheckValueType(value, typeof(byte));
+ return (byte) value;
+ }
+
+ public void SetByte(String key, byte value)
+ {
+ SetValue(key, value);
+ }
+
+ public char GetChar(String key)
+ {
+ Object value = GetValue(key);
+ CheckValueType(value, typeof(char));
+ return (char) value;
+ }
+
+ public void SetChar(String key, char value)
+ {
+ SetValue(key, value);
+ }
+
+ public short GetShort(String key)
+ {
+ Object value = GetValue(key);
+ CheckValueType(value, typeof(short));
+ return (short) value;
+ }
+
+ public void SetShort(String key, short value)
+ {
+ SetValue(key, value);
+ }
+
+ public int GetInt(String key)
+ {
+ Object value = GetValue(key);
+ CheckValueType(value, typeof(int));
+ return (int) value;
+ }
+
+ public void SetInt(String key, int value)
+ {
+ SetValue(key, value);
+ }
+
+ public long GetLong(String key)
+ {
+ Object value = GetValue(key);
+ CheckValueType(value, typeof(long));
+ return (long) value;
+ }
+
+ public void SetLong(String key, long value)
+ {
+ SetValue(key, value);
+ }
+
+ public float GetFloat(String key)
+ {
+ Object value = GetValue(key);
+ CheckValueType(value, typeof(float));
+ return (float) value;
+ }
+
+ public void SetFloat(String key, float value)
+ {
+ SetValue(key, value);
+ }
+
+ public double GetDouble(String key)
+ {
+ Object value = GetValue(key);
+ CheckValueType(value, typeof(double));
+ return (double) value;
+ }
+
+ public void SetDouble(String key, double value)
+ {
+ SetValue(key, value);
+ }
+
+ public IList GetList(String key)
+ {
+ Object value = GetValue(key);
+ if(value != null && !(value is IList))
+ {
+ throw new NMSException("Property: " + key + " is not an IList but is: " + value);
+ }
+ return (IList) value;
+ }
+
+ public void SetList(String key, IList value)
+ {
+ SetValue(key, value);
+ }
+
+ public IDictionary GetDictionary(String key)
+ {
+ Object value = GetValue(key);
+ if(value != null && !(value is IDictionary))
+ {
+ throw new NMSException("Property: " + key + " is not an IDictionary but is: " + value);
+ }
+ return (IDictionary) value;
+ }
+
+ public void SetDictionary(String key, IDictionary value)
+ {
+ SetValue(key, value);
+ }
+
+ protected virtual void SetValue(String key, Object value)
+ {
+ dictionary[key] = value;
+ }
+
+ protected virtual Object GetValue(String key)
+ {
+ return dictionary[key];
+ }
+
+ protected virtual void CheckValueType(Object value, Type type)
+ {
+ if(!type.IsInstanceOfType(value))
+ {
+ throw new NMSException("Expected type: " + type.Name + " but was: " + value);
+ }
+ }
+
+ protected virtual void CheckValidType(Object value)
+ {
+ if(value != null && !(value is IList) && !(value is IDictionary))
+ {
+ Type type = value.GetType();
+ if(!type.IsPrimitive && !type.IsValueType && !type.IsAssignableFrom(typeof(string)))
+ {
+ throw new NMSException("Invalid type: " + type.Name + " for value: " + value);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Method ToString
+ /// </summary>
+ /// <returns>A string</returns>
+ public override String ToString()
+ {
+ String s = "{";
+ bool first = true;
+ lock(dictionary.SyncRoot)
+ {
+ foreach(DictionaryEntry entry in dictionary)
+ {
+ if(!first)
+ {
+ s += ", ";
+ }
+ first = false;
+ String name = (String) entry.Key;
+ Object value = entry.Value;
+ s += name + "=" + value;
+ }
+ }
+ s += "}";
+ return s;
+ }
+
+ /// <summary>
+ /// Unmarshalls the map from the given data or if the data is null just
+ /// return an empty map
+ /// </summary>
+ public static PrimitiveMap Unmarshal(byte[] data)
+ {
+ PrimitiveMap answer = new PrimitiveMap();
+ answer.dictionary = UnmarshalPrimitiveMap(data);
+ return answer;
+ }
+
+ public byte[] Marshal()
+ {
+ lock(dictionary.SyncRoot)
+ {
+ return MarshalPrimitiveMap(dictionary);
+ }
+ }
+
+ /// <summary>
+ /// Marshals the primitive type map to a byte array
+ /// </summary>
+ public static byte[] MarshalPrimitiveMap(IDictionary map)
+ {
+ if(map == null)
+ {
+ return null;
+ }
+
+ MemoryStream memoryStream = new MemoryStream();
+ lock(map.SyncRoot)
+ {
+ MarshalPrimitiveMap(map, new EndianBinaryWriter(memoryStream));
+ }
+
+ return memoryStream.GetBuffer();
+ }
+
+ public static void MarshalPrimitiveMap(IDictionary map, BinaryWriter dataOut)
+ {
+ if(map == null)
+ {
+ dataOut.Write((int) -1);
+ }
+ else
+ {
+ lock(map.SyncRoot)
+ {
+ dataOut.Write(map.Count);
+ foreach(DictionaryEntry entry in map)
+ {
+ String name = (String) entry.Key;
+ dataOut.Write(name);
+ Object value = entry.Value;
+ MarshalPrimitive(dataOut, value);
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Unmarshals the primitive type map from the given byte array
+ /// </summary>
+ public static IDictionary UnmarshalPrimitiveMap(byte[] data)
+ {
+ if(data == null)
+ {
+ return new Hashtable();
+ }
+ else
+ {
+ return UnmarshalPrimitiveMap(new EndianBinaryReader(new MemoryStream(data)));
+ }
+ }
+
+ public static IDictionary UnmarshalPrimitiveMap(BinaryReader dataIn)
+ {
+ int size = dataIn.ReadInt32();
+ if(size < 0)
+ {
+ return null;
+ }
+
+ IDictionary answer = new Hashtable(size);
+ for(int i = 0; i < size; i++)
+ {
+ String name = dataIn.ReadString();
+ answer[name] = UnmarshalPrimitive(dataIn);
+ }
+
+ return answer;
+ }
+
+ public static void MarshalPrimitiveList(IList list, BinaryWriter dataOut)
+ {
+ dataOut.Write((int) list.Count);
+ foreach(Object element in list)
+ {
+ MarshalPrimitive(dataOut, element);
+ }
+ }
+
+ public static IList UnmarshalPrimitiveList(BinaryReader dataIn)
+ {
+ int size = dataIn.ReadInt32();
+ IList answer = new ArrayList(size);
+ while(size-- > 0)
+ {
+ answer.Add(UnmarshalPrimitive(dataIn));
+ }
+
+ return answer;
+ }
+
+ public static void MarshalPrimitive(BinaryWriter dataOut, Object value)
+ {
+ if(value == null)
+ {
+ dataOut.Write(NULL);
+ }
+ else if(value is bool)
+ {
+ dataOut.Write(BOOLEAN_TYPE);
+ dataOut.Write((bool) value);
+ }
+ else if(value is byte)
+ {
+ dataOut.Write(BYTE_TYPE);
+ dataOut.Write(((byte) value));
+ }
+ else if(value is char)
+ {
+ dataOut.Write(CHAR_TYPE);
+ dataOut.Write((char) value);
+ }
+ else if(value is short)
+ {
+ dataOut.Write(SHORT_TYPE);
+ dataOut.Write((short) value);
+ }
+ else if(value is int)
+ {
+ dataOut.Write(INTEGER_TYPE);
+ dataOut.Write((int) value);
+ }
+ else if(value is long)
+ {
+ dataOut.Write(LONG_TYPE);
+ dataOut.Write((long) value);
+ }
+ else if(value is float)
+ {
+ dataOut.Write(FLOAT_TYPE);
+ dataOut.Write((float) value);
+ }
+ else if(value is double)
+ {
+ dataOut.Write(DOUBLE_TYPE);
+ dataOut.Write((double) value);
+ }
+ else if(value is byte[])
+ {
+ byte[] data = (byte[]) value;
+ dataOut.Write(BYTE_ARRAY_TYPE);
+ dataOut.Write(data.Length);
+ dataOut.Write(data);
+ }
+ else if(value is string)
+ {
+ string s = (string) value;
+ // is the string big??
+ if(s.Length > 8191)
+ {
+ dataOut.Write(BIG_STRING_TYPE);
+ ((EndianBinaryWriter) dataOut).WriteString32(s);
+ }
+ else
+ {
+ dataOut.Write(STRING_TYPE);
+ ((EndianBinaryWriter) dataOut).WriteString16(s);
+ }
+ }
+ else if(value is IDictionary)
+ {
+ dataOut.Write(MAP_TYPE);
+ MarshalPrimitiveMap((IDictionary) value, dataOut);
+ }
+ else if(value is IList)
+ {
+ dataOut.Write(LIST_TYPE);
+ MarshalPrimitiveList((IList) value, dataOut);
+ }
+ else
+ {
+ throw new IOException("Object is not a primitive: " + value);
+ }
+ }
+
+ public static Object UnmarshalPrimitive(BinaryReader dataIn)
+ {
+ Object value = null;
+ byte type = dataIn.ReadByte();
+ switch(type)
+ {
+ case NULL:
+ value = null;
+ break;
+ case BYTE_TYPE:
+ value = dataIn.ReadByte();
+ break;
+ case BOOLEAN_TYPE:
+ value = dataIn.ReadBoolean();
+ break;
+ case CHAR_TYPE:
+ value = dataIn.ReadChar();
+ break;
+ case SHORT_TYPE:
+ value = dataIn.ReadInt16();
+ break;
+ case INTEGER_TYPE:
+ value = dataIn.ReadInt32();
+ break;
+ case LONG_TYPE:
+ value = dataIn.ReadInt64();
+ break;
+ case FLOAT_TYPE:
+ value = dataIn.ReadSingle();
+ break;
+ case DOUBLE_TYPE:
+ value = dataIn.ReadDouble();
+ break;
+ case BYTE_ARRAY_TYPE:
+ int size = dataIn.ReadInt32();
+ byte[] data = new byte[size];
+ dataIn.Read(data, 0, size);
+ value = data;
+ break;
+ case STRING_TYPE:
+ value = ((EndianBinaryReader) dataIn).ReadString16();
+ break;
+ case BIG_STRING_TYPE:
+ value = ((EndianBinaryReader) dataIn).ReadString32();
+ break;
+ case MAP_TYPE:
+ value = UnmarshalPrimitiveMap(dataIn);
+ break;
+ case LIST_TYPE:
+ value = UnmarshalPrimitiveList(dataIn);
+ break;
+
+ default:
+ throw new Exception("Unsupported data type: " + type);
+ }
+ return value;
+ }
+ }
+}
diff --git a/src/test/csharp/EndianBinaryReaderTest.cs b/src/test/csharp/EndianBinaryReaderTest.cs
new file mode 100644
index 0000000..273645f
--- /dev/null
+++ b/src/test/csharp/EndianBinaryReaderTest.cs
@@ -0,0 +1,163 @@
+/*
+ * 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.IO;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+ [TestFixture]
+ public class EndianBinaryReaderTest
+ {
+ public void readString16Helper(byte[] input, char[] expect)
+ {
+ MemoryStream stream = new MemoryStream(input);
+ EndianBinaryReader reader = new EndianBinaryReader(stream);
+
+ char[] result = reader.ReadString16().ToCharArray();
+
+ for(int i = 0; i < expect.Length; ++i)
+ {
+ Assert.AreEqual(expect[i], result[i]);
+ }
+ }
+
+ [Test]
+ public void testReadString16_1byteUTF8encoding()
+ {
+ // Test data with 1-byte UTF8 encoding.
+ char[] expect = { '\u0000', '\u000B', '\u0048', '\u0065', '\u006C', '\u006C', '\u006F', '\u0020', '\u0057', '\u006F', '\u0072', '\u006C', '\u0064' };
+ byte[] input = { 0x00, 0x0E, 0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 };
+
+ readString16Helper(input, expect);
+ }
+
+ [Test]
+ public void testReadString16_2byteUTF8encoding()
+ {
+ // Test data with 2-byte UT8 encoding.
+ char[] expect = { '\u0000', '\u00C2', '\u00A9', '\u00C3', '\u00A6' };
+ byte[] input = { 0x00, 0x0A, 0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 };
+ readString16Helper(input, expect);
+ }
+
+ [Test]
+ public void testReadString16_1byteAnd2byteEmbeddedNULLs()
+ {
+ // Test data with 1-byte and 2-byte encoding with embedded NULL's.
+ char[] expect = { '\u0000', '\u0004', '\u00C2', '\u00A9', '\u00C3', '\u0000', '\u00A6' };
+ byte[] input = { 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+ readString16Helper(input, expect);
+ }
+
+ [Test]
+ [ExpectedException(typeof(IOException))]
+ public void testReadString16_UTF8Missing2ndByte()
+ {
+ // Test with bad UTF-8 encoding, missing 2nd byte of two byte value
+ byte[] input = { 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xC2, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+ MemoryStream stream = new MemoryStream(input);
+ EndianBinaryReader reader = new EndianBinaryReader(stream);
+
+ reader.ReadString16();
+ }
+
+ [Test]
+ [ExpectedException(typeof(IOException))]
+ public void testReadString16_3byteEncodingMissingLastByte()
+ {
+ // Test with three byte encode that's missing a last byte.
+ byte[] input = { 0x00, 0x02, 0xE8, 0xA8 };
+
+ MemoryStream stream = new MemoryStream(input);
+ EndianBinaryReader reader = new EndianBinaryReader(stream);
+
+ reader.ReadString16();
+ }
+
+ public void readString32Helper(byte[] input, char[] expect)
+ {
+ MemoryStream stream = new MemoryStream(input);
+ EndianBinaryReader reader = new EndianBinaryReader(stream);
+
+ char[] result = reader.ReadString32().ToCharArray();
+
+ for(int i = 0; i < expect.Length; ++i)
+ {
+ Assert.AreEqual(expect[i], result[i]);
+ }
+ }
+
+ [Test]
+ public void testReadString32_1byteUTF8encoding()
+ {
+ // Test data with 1-byte UTF8 encoding.
+ char[] expect = { '\u0000', '\u000B', '\u0048', '\u0065', '\u006C', '\u006C', '\u006F', '\u0020', '\u0057', '\u006F', '\u0072', '\u006C', '\u0064' };
+ byte[] input = { 0x00, 0x00, 0x00, 0x0E, 0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 };
+
+ readString32Helper(input, expect);
+ }
+
+ [Test]
+ public void testReadString32_2byteUTF8encoding()
+ {
+ // Test data with 2-byte UT8 encoding.
+ char[] expect = { '\u0000', '\u00C2', '\u00A9', '\u00C3', '\u00A6' };
+ byte[] input = { 0x00, 0x00, 0x00, 0x0A, 0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 };
+ readString32Helper(input, expect);
+ }
+
+ [Test]
+ public void testReadString32_1byteAnd2byteEmbeddedNULLs()
+ {
+ // Test data with 1-byte and 2-byte encoding with embedded NULL's.
+ char[] expect = { '\u0000', '\u0004', '\u00C2', '\u00A9', '\u00C3', '\u0000', '\u00A6' };
+ byte[] input = { 0x00, 0x00, 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+ readString32Helper(input, expect);
+ }
+
+ [Test]
+ [ExpectedException(typeof(IOException))]
+ public void testReadString32_UTF8Missing2ndByte()
+ {
+ // Test with bad UTF-8 encoding, missing 2nd byte of two byte value
+ byte[] input = { 0x00, 0x00, 0x00, 0x0D, 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xC2, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+ MemoryStream stream = new MemoryStream(input);
+ EndianBinaryReader reader = new EndianBinaryReader(stream);
+
+ reader.ReadString32();
+ }
+
+ [Test]
+ [ExpectedException(typeof(IOException))]
+ public void testReadString32_3byteEncodingMissingLastByte()
+ {
+ // Test with three byte encode that's missing a last byte.
+ byte[] input = { 0x00, 0x00, 0x00, 0x02, 0xE8, 0xA8 };
+
+ MemoryStream stream = new MemoryStream(input);
+ EndianBinaryReader reader = new EndianBinaryReader(stream);
+
+ reader.ReadString32();
+ }
+ }
+}
diff --git a/src/test/csharp/EndianBinaryWriterTest.cs b/src/test/csharp/EndianBinaryWriterTest.cs
new file mode 100644
index 0000000..635b449
--- /dev/null
+++ b/src/test/csharp/EndianBinaryWriterTest.cs
@@ -0,0 +1,202 @@
+/*
+ * 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 Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+ [TestFixture]
+ public class EndianBinaryWriterTest
+ {
+ void writeString16TestHelper(char[] input, byte[] expect)
+ {
+ MemoryStream stream = new MemoryStream();
+ EndianBinaryWriter writer = new EndianBinaryWriter(stream);
+
+ String str = new String(input);
+
+ writer.WriteString16(str);
+
+ byte[] result = stream.GetBuffer();
+
+ Assert.AreEqual(result[0], 0x00);
+ Assert.AreEqual(result[1], expect.Length);
+
+ for(int i = 4; i < expect.Length; ++i)
+ {
+ Assert.AreEqual(result[i], expect[i - 2]);
+ }
+ }
+
+ [Test]
+ public void testWriteString16_1byteUTF8encoding()
+ {
+ // Test data with 1-byte UTF8 encoding.
+ char[] input = { '\u0000', '\u000B', '\u0048', '\u0065', '\u006C', '\u006C', '\u006F', '\u0020', '\u0057', '\u006F', '\u0072', '\u006C', '\u0064' };
+ byte[] expect = { 0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 };
+
+ writeString16TestHelper(input, expect);
+ }
+
+ [Test]
+ public void testWriteString16_2byteUTF8encoding()
+ {
+ // Test data with 2-byte UT8 encoding.
+ char[] input = { '\u0000', '\u00C2', '\u00A9', '\u00C3', '\u00A6' };
+ byte[] expect = { 0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 };
+
+ writeString16TestHelper(input, expect);
+ }
+
+ [Test]
+ public void testWriteString16_1byteAnd2byteEmbeddedNULLs()
+ {
+ // Test data with 1-byte and 2-byte encoding with embedded NULL's.
+ char[] input = { '\u0000', '\u0004', '\u00C2', '\u00A9', '\u00C3', '\u0000', '\u00A6' };
+ byte[] expect = { 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+ writeString16TestHelper(input, expect);
+ }
+
+ [Test]
+ public void testWriteString16_nullstring()
+ {
+ // test that a null string writes no output.
+ MemoryStream stream = new MemoryStream();
+ EndianBinaryWriter writer = new EndianBinaryWriter(stream);
+ writer.WriteString16(null);
+ Assert.AreEqual(0, stream.Length);
+ }
+
+ [Test]
+ public void testWriteString16_emptystring()
+ {
+ // test that a null string writes no output.
+ MemoryStream stream = new MemoryStream();
+ EndianBinaryWriter writer = new EndianBinaryWriter(stream);
+ writer.WriteString16("");
+
+ stream.Seek(0, SeekOrigin.Begin);
+ EndianBinaryReader reader = new EndianBinaryReader(stream);
+ Assert.AreEqual(0, reader.ReadInt16());
+ }
+
+ [Test]
+ [ExpectedException(typeof(IOException))]
+ public void testWriteString16_stringTooLong()
+ {
+ // String of length 65536 of Null Characters.
+ MemoryStream stream = new MemoryStream();
+ EndianBinaryWriter writer = new EndianBinaryWriter(stream);
+ String testStr = new String('a', 65536);
+ writer.Write(testStr);
+ }
+
+ [Test]
+ public void testWriteString16_maxStringLength()
+ {
+ // String of length 65535 of non Null Characters since Null encodes as UTF-8.
+ MemoryStream stream = new MemoryStream();
+ EndianBinaryWriter writer = new EndianBinaryWriter(stream);
+ String testStr = new String('a', 65535);
+ writer.Write(testStr);
+ }
+
+ [Test]
+ [ExpectedException(typeof(IOException))]
+ public void testWriteString16_invalidEncodingHeader()
+ {
+ // Set one of the 65535 bytes to a value that will result in a 2 byte UTF8 encoded sequence.
+ // This will cause the string of length 65535 to have a utf length of 65536.
+ MemoryStream stream = new MemoryStream();
+ EndianBinaryWriter writer = new EndianBinaryWriter(stream);
+ String testStr = new String('a', 65535);
+ char[] array = testStr.ToCharArray();
+ array[0] = '\u0000';
+ testStr = new String(array);
+ writer.Write(testStr);
+ }
+
+ void writeString32TestHelper(char[] input, byte[] expect)
+ {
+ MemoryStream stream = new MemoryStream();
+ EndianBinaryWriter writer = new EndianBinaryWriter(stream);
+
+ String str = new String(input);
+
+ writer.WriteString32(str);
+
+ byte[] result = stream.GetBuffer();
+
+ Assert.AreEqual(result[0], 0x00);
+ Assert.AreEqual(result[1], 0x00);
+ Assert.AreEqual(result[2], 0x00);
+ Assert.AreEqual(result[3], expect.Length);
+
+ for(int i = 4; i < expect.Length; ++i)
+ {
+ Assert.AreEqual(result[i], expect[i - 4]);
+ }
+ }
+
+ [Test]
+ public void testWriteString32_1byteUTF8encoding()
+ {
+ // Test data with 1-byte UTF8 encoding.
+ char[] input = { '\u0000', '\u000B', '\u0048', '\u0065', '\u006C', '\u006C', '\u006F', '\u0020', '\u0057', '\u006F', '\u0072', '\u006C', '\u0064' };
+ byte[] expect = { 0xC0, 0x80, 0x0B, 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0x57, 0x6F, 0x72, 0x6C, 0x64 };
+
+ writeString32TestHelper(input, expect);
+ }
+
+ [Test]
+ public void testWriteString32_2byteUTF8encoding()
+ {
+ // Test data with 2-byte UT8 encoding.
+ char[] input = { '\u0000', '\u00C2', '\u00A9', '\u00C3', '\u00A6' };
+ byte[] expect = { 0xC0, 0x80, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC2, 0xA6 };
+
+ writeString32TestHelper(input, expect);
+ }
+
+ [Test]
+ public void testWriteString32_1byteAnd2byteEmbeddedNULLs()
+ {
+ // Test data with 1-byte and 2-byte encoding with embedded NULL's.
+ char[] input = { '\u0000', '\u0004', '\u00C2', '\u00A9', '\u00C3', '\u0000', '\u00A6' };
+ byte[] expect = { 0xC0, 0x80, 0x04, 0xC3, 0x82, 0xC2, 0xA9, 0xC3, 0x83, 0xC0, 0x80, 0xC2, 0xA6 };
+
+ writeString32TestHelper(input, expect);
+ }
+
+ [Test]
+ public void testWriteString32_nullstring()
+ {
+ // test that a null strings writes a -1
+ MemoryStream stream = new MemoryStream();
+ EndianBinaryWriter writer = new EndianBinaryWriter(stream);
+ writer.WriteString32(null);
+
+ stream.Seek(0, SeekOrigin.Begin);
+ EndianBinaryReader reader = new EndianBinaryReader(stream);
+ Assert.AreEqual(-1, reader.ReadInt32());
+ }
+ }
+}
diff --git a/src/test/csharp/EndianTest.cs b/src/test/csharp/EndianTest.cs
new file mode 100644
index 0000000..ad9ce08
--- /dev/null
+++ b/src/test/csharp/EndianTest.cs
@@ -0,0 +1,131 @@
+/*
+ * 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.IO;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+ [TestFixture]
+ public class EndianTest
+ {
+ [Test]
+ public void TestLongEndian()
+ {
+ long value = 0x0102030405060708L;
+ long newValue = EndianSupport.SwitchEndian(value);
+ Assert.AreEqual(0x0807060504030201L, newValue);
+ long actual = EndianSupport.SwitchEndian(newValue);
+ Assert.AreEqual(value, actual);
+ }
+
+ [Test]
+ public void TestIntEndian()
+ {
+ int value = 0x12345678;
+ int newValue = EndianSupport.SwitchEndian(value);
+ Assert.AreEqual(0x78563412, newValue);
+ int actual = EndianSupport.SwitchEndian(newValue);
+ Assert.AreEqual(value, actual);
+ }
+
+ [Test]
+ public void TestCharEndian()
+ {
+ char value = 'J';
+ char newValue = EndianSupport.SwitchEndian(value);
+ char actual = EndianSupport.SwitchEndian(newValue);
+ Assert.AreEqual(value, actual);
+ }
+
+ [Test]
+ public void TestShortEndian()
+ {
+ short value = 0x1234;
+ short newValue = EndianSupport.SwitchEndian(value);
+ Assert.AreEqual(0x3412, newValue);
+ short actual = EndianSupport.SwitchEndian(newValue);
+ Assert.AreEqual(value, actual);
+ }
+
+ [Test]
+ public void TestNegativeLongEndian()
+ {
+ long value = -0x0102030405060708L;
+ long newValue = EndianSupport.SwitchEndian(value);
+ long actual = EndianSupport.SwitchEndian(newValue);
+ Assert.AreEqual(value, actual);
+ }
+
+ [Test]
+ public void TestNegativeIntEndian()
+ {
+ int value = -0x12345678;
+ int newValue = EndianSupport.SwitchEndian(value);
+ int actual = EndianSupport.SwitchEndian(newValue);
+ Assert.AreEqual(value, actual);
+ }
+
+ [Test]
+ public void TestNegativeShortEndian()
+ {
+ short value = -0x1234;
+ short newValue = EndianSupport.SwitchEndian(value);
+ short actual = EndianSupport.SwitchEndian(newValue);
+ Assert.AreEqual(value, actual);
+ }
+
+ [Test]
+ public void TestFloatDontNeedEndianSwitch()
+ {
+ float value = -1.223F;
+
+ // Convert to int so we can compare to Java version.
+ MemoryStream ms = new MemoryStream(4);
+ BinaryWriter bw = new BinaryWriter(ms);
+ bw.Write(value);
+ bw.Close();
+ ms = new MemoryStream(ms.ToArray());
+ BinaryReader br = new BinaryReader(ms);
+
+ // System.out.println(Integer.toString(Float.floatToIntBits(-1.223F), 16));
+ Assert.AreEqual(-0x406374bc, br.ReadInt32());
+ }
+
+ [Test]
+ public void TestDoublDontNeedEndianSwitch()
+ {
+ double value = -1.223D;
+
+ // Convert to int so we can compare to Java version.
+ MemoryStream ms = new MemoryStream(4);
+ BinaryWriter bw = new BinaryWriter(ms);
+ bw.Write(value);
+ bw.Close();
+ ms = new MemoryStream(ms.ToArray());
+ BinaryReader br = new BinaryReader(ms);
+ long longVersion = br.ReadInt64();
+
+ // System.out.println(Long.toString(Double.doubleToLongBits(-1.223D), 16));
+ Assert.AreEqual(-0x400c6e978d4fdf3b, longVersion);
+ }
+ }
+}
+
+
+
diff --git a/src/test/csharp/NMSTestSupport.cs b/src/test/csharp/NMSTestSupport.cs
index eead3bc..97754db 100644
--- a/src/test/csharp/NMSTestSupport.cs
+++ b/src/test/csharp/NMSTestSupport.cs
@@ -41,7 +41,7 @@
{
Apache.NMS.Tracer.Trace = new NmsTracer();
}
-
+
public NMSTestSupport()
{
}
@@ -121,8 +121,8 @@
configFound = true;
break;
}
- }
-
+ }
+
Assert.IsTrue(configFound, "Connection configuration file does not exist.");
XmlDocument configDoc = new XmlDocument();
@@ -175,7 +175,7 @@
return (string[]) pathList.ToArray(typeof(string));
}
-
+
/// <summary>
/// Get the parameters for the ConnectionFactory from the configuration file.
/// </summary>
@@ -201,11 +201,11 @@
{
case "string":
factoryParams.Add(paramValue);
- break;
+ break;
case "int":
factoryParams.Add(int.Parse(paramValue));
- break;
+ break;
// TODO: Add more parameter types
}
diff --git a/src/test/csharp/PrimitiveMapTest.cs b/src/test/csharp/PrimitiveMapTest.cs
new file mode 100644
index 0000000..3e20892
--- /dev/null
+++ b/src/test/csharp/PrimitiveMapTest.cs
@@ -0,0 +1,170 @@
+/*
+ * 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.Collections;
+using Apache.NMS.Util;
+using NUnit.Framework;
+
+namespace Apache.NMS.Test
+{
+ [TestFixture]
+ public class PrimitiveMapTest
+ {
+
+ bool a = true;
+ byte b = 123;
+ char c = 'c';
+ short d = 0x1234;
+ int e = 0x12345678;
+ long f = 0x1234567812345678;
+ string g = "Hello World!";
+ bool h = false;
+ byte i = 0xFF;
+ short j = -0x1234;
+ int k = -0x12345678;
+ long l = -0x1234567812345678;
+ IList m = CreateList();
+ IDictionary n = CreateDictionary();
+
+ [Test]
+ public void TestNotMarshalled()
+ {
+ PrimitiveMap map = CreatePrimitiveMap();
+ AssertPrimitiveMap(map);
+ }
+
+ [Test]
+ public void TestMarshalled()
+ {
+ PrimitiveMap map = CreatePrimitiveMap();
+ byte[] data = map.Marshal();
+ map = PrimitiveMap.Unmarshal(data);
+ AssertPrimitiveMap(map);
+ }
+
+ [Test]
+ public void TestMarshalledWithBigString()
+ {
+ PrimitiveMap map = CreatePrimitiveMap();
+ String test = new String('a', 65538);
+ map.SetString("BIG_STRING", test);
+ byte[] data = map.Marshal();
+ map = PrimitiveMap.Unmarshal(data);
+ AssertPrimitiveMap(map);
+ Assert.AreEqual(test, map.GetString("BIG_STRING"));
+ }
+
+ protected PrimitiveMap CreatePrimitiveMap()
+ {
+ PrimitiveMap map = new PrimitiveMap();
+
+ map["a"] = a;
+ map["b"] = b;
+ map["c"] = c;
+ map["d"] = d;
+ map["e"] = e;
+ map["f"] = f;
+ map["g"] = g;
+ map["h"] = h;
+ map["i"] = i;
+ map["j"] = j;
+ map["k"] = k;
+ map["l"] = l;
+ map["m"] = m;
+ map["n"] = n;
+
+ return map;
+ }
+
+ protected void AssertPrimitiveMap(PrimitiveMap map)
+ {
+ // use generic API to access entries
+ Assert.AreEqual(a, map["a"], "generic map entry: a");
+ Assert.AreEqual(b, map["b"], "generic map entry: b");
+ Assert.AreEqual(c, map["c"], "generic map entry: c");
+ Assert.AreEqual(d, map["d"], "generic map entry: d");
+ Assert.AreEqual(e, map["e"], "generic map entry: e");
+ Assert.AreEqual(f, map["f"], "generic map entry: f");
+ Assert.AreEqual(g, map["g"], "generic map entry: g");
+ Assert.AreEqual(h, map["h"], "generic map entry: h");
+ Assert.AreEqual(i, map["i"], "generic map entry: i");
+ Assert.AreEqual(j, map["j"], "generic map entry: j");
+ Assert.AreEqual(k, map["k"], "generic map entry: k");
+ Assert.AreEqual(l, map["l"], "generic map entry: l");
+ //Assert.AreEqual(m, map["m"], "generic map entry: m");
+ //Assert.AreEqual(n, map["n"], "generic map entry: n");
+
+ // use type safe APIs
+ Assert.AreEqual(a, map.GetBool("a"), "map entry: a");
+ Assert.AreEqual(b, map.GetByte("b"), "map entry: b");
+ Assert.AreEqual(c, map.GetChar("c"), "map entry: c");
+ Assert.AreEqual(d, map.GetShort("d"), "map entry: d");
+ Assert.AreEqual(e, map.GetInt("e"), "map entry: e");
+ Assert.AreEqual(f, map.GetLong("f"), "map entry: f");
+ Assert.AreEqual(g, map.GetString("g"), "map entry: g");
+ Assert.AreEqual(h, map.GetBool("h"), "map entry: h");
+ Assert.AreEqual(i, map.GetByte("i"), "map entry: i");
+ Assert.AreEqual(j, map.GetShort("j"), "map entry: j");
+ Assert.AreEqual(k, map.GetInt("k"), "map entry: k");
+ Assert.AreEqual(l, map.GetLong("l"), "map entry: l");
+ //Assert.AreEqual(m, map.GetList("m"), "map entry: m");
+ //Assert.AreEqual(n, map.GetDictionary("n"), "map entry: n");
+
+ IList list = map.GetList("m");
+ Assert.AreEqual(2, list.Count, "list size");
+ Assert.IsTrue(list.Contains("Item1"));
+ Assert.IsTrue(list.Contains("Item2"));
+
+ IDictionary dictionary = map.GetDictionary("n");
+ Assert.AreEqual(5, dictionary.Count, "dictionary size");
+
+ IDictionary childMap = (IDictionary) dictionary["childMap"];
+ Assert.IsNotNull(childMap);
+ Assert.AreEqual("childMap", childMap["name"], "childMap[name]");
+
+ IList childList = (IList) dictionary["childList"];
+ Assert.IsNotNull(childList);
+ Assert.IsTrue(childList.Contains("childListElement1"));
+ }
+
+ protected static IList CreateList()
+ {
+ ArrayList answer = new ArrayList();
+ answer.Add("Item1");
+ answer.Add("Item2");
+ return answer;
+ }
+
+ protected static IDictionary CreateDictionary()
+ {
+ Hashtable answer = new Hashtable();
+ answer.Add("Name", "James");
+ answer.Add("Location", "London");
+ answer.Add("Company", "LogicBlaze");
+
+ Hashtable childMap = new Hashtable();
+ childMap.Add("name", "childMap");
+ answer.Add("childMap", childMap);
+
+ ArrayList childList = new ArrayList();
+ childList.Add("childListElement1");
+ answer.Add("childList", childList);
+ return answer;
+ }
+ }
+}
diff --git a/vs2008-nms-test.csproj b/vs2008-nms-test.csproj
index 4d65091..d46ba84 100644
--- a/vs2008-nms-test.csproj
+++ b/vs2008-nms-test.csproj
@@ -84,6 +84,9 @@
<Compile Include="src\test\csharp\DurableTest.cs">
<SubType>Code</SubType>
</Compile>
+ <Compile Include="src\test\csharp\EndianBinaryReaderTest.cs" />
+ <Compile Include="src\test\csharp\EndianBinaryWriterTest.cs" />
+ <Compile Include="src\test\csharp\EndianTest.cs" />
<Compile Include="src\test\csharp\NMSPropertyTest.cs" />
<Compile Include="src\test\csharp\NMSTestSupport.cs">
<SubType>Code</SubType>
@@ -96,6 +99,7 @@
</Compile>
<Compile Include="src\test\csharp\MessageSelectorTest.cs" />
<Compile Include="src\test\csharp\NmsTracer.cs" />
+ <Compile Include="src\test\csharp\PrimitiveMapTest.cs" />
<Compile Include="src\test\csharp\TempDestinationDeletionTest.cs" />
<Compile Include="src\test\csharp\TextMessage.cs">
<SubType>Code</SubType>
diff --git a/vs2008-nms.csproj b/vs2008-nms.csproj
index 11a6155..fbe2536 100644
--- a/vs2008-nms.csproj
+++ b/vs2008-nms.csproj
@@ -89,6 +89,11 @@
<Compile Include="src\main\csharp\Util\Convert.cs" />
<Compile Include="src\main\csharp\Util\CountDownLatch.cs" />
<Compile Include="src\main\csharp\Util\DateUtils.cs" />
+ <Compile Include="src\main\csharp\Util\EndianBinaryReader.cs" />
+ <Compile Include="src\main\csharp\Util\EndianBinaryWriter.cs" />
+ <Compile Include="src\main\csharp\Util\EndianSupport.cs" />
+ <Compile Include="src\main\csharp\Util\MessagePropertyHelper.cs" />
+ <Compile Include="src\main\csharp\Util\PrimitiveMap.cs" />
<Compile Include="src\main\csharp\Util\SessionUtils.cs" />
<Compile Include="src\main\csharp\Util\URISupport.cs">
<SubType>Code</SubType>