You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by ta...@apache.org on 2017/03/08 13:45:14 UTC
[08/13] activemq-nms-xms git commit: Initial check-in of new Apache.NMS.XMS provider implementation. Big thanks to Stéphane Ramet for the implementation! Fixes [AMQNET-185]. (See https://issues.apache.org/jira/browse/AMQNET-185)
http://git-wip-us.apache.org/repos/asf/activemq-nms-xms/blob/653d676d/src/main/csharp/StreamMessage.cs
----------------------------------------------------------------------
diff --git a/src/main/csharp/StreamMessage.cs b/src/main/csharp/StreamMessage.cs
new file mode 100644
index 0000000..b25579b
--- /dev/null
+++ b/src/main/csharp/StreamMessage.cs
@@ -0,0 +1,480 @@
+/*
+ * 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 Apache.NMS;
+using Apache.NMS.Util;
+using Apache.NMS.XMS.Util;
+using IBM.XMS;
+
+namespace Apache.NMS.XMS
+{
+ /// <summary>
+ /// A StreamMessage object is used to send a stream of primitive types in the
+ /// .NET programming language. It is filled and read sequentially. It inherits
+ /// from the Message interface and adds a stream message body.
+ /// </summary>
+ class StreamMessage : Apache.NMS.XMS.Message, Apache.NMS.IStreamMessage
+ {
+ #region Constructors and access to internal stream message
+
+ /// <summary>
+ /// Internal IBM XMS stream message.
+ /// </summary>
+ public IBM.XMS.IStreamMessage xmsStreamMessage
+ {
+ get { return (IBM.XMS.IStreamMessage)this.xmsMessage; }
+ set { this.xmsMessage = value; }
+ }
+
+ /// <summary>
+ /// Constructs a <c>StreamMessage</c> object.
+ /// </summary>
+ /// <param name="message">XMS stream message.</param>
+ public StreamMessage(IBM.XMS.IStreamMessage message)
+ : base(message)
+ {
+ }
+
+ #endregion
+
+ #region IStreamMessage Members
+
+ #region Reset method
+
+ /// <summary>
+ /// Resets the contents of the stream message body.
+ /// </summary>
+ public void Reset()
+ {
+ try
+ {
+ this.xmsStreamMessage.Reset();
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ }
+ }
+
+ #endregion
+
+ #region Read methods
+
+ /// <summary>
+ /// Reads a boolean from the stream message.
+ /// </summary>
+ /// <returns>A <see cref="System.Boolean"/></returns>
+ public bool ReadBoolean()
+ {
+ try
+ {
+ return this.xmsStreamMessage.ReadBoolean();
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ return false;
+ }
+ }
+
+ /// <summary>
+ /// Reads a byte from the stream message.
+ /// </summary>
+ /// <returns>A <see cref="System.Byte"/></returns>
+ public byte ReadByte()
+ {
+ try
+ {
+ return this.xmsStreamMessage.ReadByte();
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ return 0;
+ }
+ }
+
+ /// <summary>
+ /// Reads a byte array from the stream message.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Byte"/> array</param>
+ /// <returns>The total number of bytes read into the buffer, or -1 if
+ /// there is no more data because the end of the byte field has been
+ /// reached</returns>
+ public int ReadBytes(byte[] value)
+ {
+ try
+ {
+ return this.xmsStreamMessage.ReadBytes(value);
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ return 0;
+ }
+ }
+
+ /// <summary>
+ /// Reads a character from the stream message.
+ /// </summary>
+ /// <returns>A <see cref="System.Char"/></returns>
+ public char ReadChar()
+ {
+ try
+ {
+ return this.xmsStreamMessage.ReadChar();
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ return (char) 0;
+ }
+ }
+
+ /// <summary>
+ /// Reads a 16 bits (short) integer number from the stream message.
+ /// </summary>
+ /// <returns>A <see cref="System.Int16"/></returns>
+ public short ReadInt16()
+ {
+ try
+ {
+ return this.xmsStreamMessage.ReadShort();
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ return 0;
+ }
+ }
+
+ /// <summary>
+ /// Reads a 32 bits (int) integer number from the stream message.
+ /// </summary>
+ /// <returns>A <see cref="System.Int32"/></returns>
+ public int ReadInt32()
+ {
+ try
+ {
+ return this.xmsStreamMessage.ReadInt();
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ return 0;
+ }
+ }
+
+ /// <summary>
+ /// Reads a 64 bits (long) integer number from the stream message.
+ /// </summary>
+ /// <returns>A <see cref="System.Int64"/></returns>
+ public long ReadInt64()
+ {
+ try
+ {
+ return this.xmsStreamMessage.ReadLong();
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ return 0;
+ }
+ }
+
+ /// <summary>
+ /// Reads a single precision floating point number from the stream
+ /// message.
+ /// </summary>
+ /// <returns>A <see cref="System.Single"/></returns>
+ public float ReadSingle()
+ {
+ try
+ {
+ return this.xmsStreamMessage.ReadFloat();
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ return 0;
+ }
+ }
+
+ /// <summary>
+ /// Reads a double precision floating point number from the stream
+ /// message.
+ /// </summary>
+ /// <returns>A <see cref="System.Double"/></returns>
+ public double ReadDouble()
+ {
+ try
+ {
+ return this.xmsStreamMessage.ReadDouble();
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ return 0;
+ }
+ }
+
+ /// <summary>
+ /// Reads a character string from the stream message.
+ /// </summary>
+ /// <returns>A <see cref="System.String"/></returns>
+ public string ReadString()
+ {
+ try
+ {
+ return this.xmsStreamMessage.ReadString();
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ return null;
+ }
+ }
+
+ /// <summary>
+ /// Reads an object from the stream message.
+ /// </summary>
+ /// <returns>A <see cref="System.Object"/></returns>
+ public object ReadObject()
+ {
+ try
+ {
+ return this.xmsStreamMessage.ReadObject();
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ return 0;
+ }
+ }
+
+ #endregion
+
+ #region Write methods
+
+ /// <summary>
+ /// Writes a boolean to the stream message.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Boolean"/></param>
+ public void WriteBoolean(bool value)
+ {
+ try
+ {
+ this.xmsStreamMessage.WriteBoolean(value);
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ }
+ }
+
+ /// <summary>
+ /// Writes a byte to the stream message.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Byte"/></param>
+ public void WriteByte(byte value)
+ {
+ try
+ {
+ this.xmsStreamMessage.WriteByte(value);
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ }
+ }
+
+ /// <summary>
+ /// Writes a byte array to the stream message.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Byte"/> array</param>
+ public void WriteBytes(byte[] value)
+ {
+ try
+ {
+ this.xmsStreamMessage.WriteBytes(value);
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ }
+ }
+
+ /// <summary>
+ /// Writes a portion of a byte array as a byte array field to the
+ /// stream message.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Byte"/> array</param>
+ /// <param name="offset">A <see cref="System.Int32"/> value that
+ /// indicates the point in the buffer to begin writing to the stream
+ /// message.</param>
+ /// <param name="length">A <see cref="System.Int32"/> value that
+ /// indicates how many bytes in the buffer to write to the stream
+ /// message.</param>
+ public void WriteBytes(byte[] value, int offset, int length)
+ {
+ try
+ {
+ this.xmsStreamMessage.WriteBytes(value, offset, length);
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ }
+ }
+
+ /// <summary>
+ /// Writes a character to the stream message.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Char"/></param>
+ public void WriteChar(char value)
+ {
+ try
+ {
+ this.xmsStreamMessage.WriteChar(value);
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ }
+ }
+
+ /// <summary>
+ /// Writes a 16 bts (short) integer to the stream message.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Int16"/></param>
+ public void WriteInt16(short value)
+ {
+ try
+ {
+ this.xmsStreamMessage.WriteShort(value);
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ }
+ }
+
+ /// <summary>
+ /// Writes a 32 bts (int) integer to the stream message.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Int32"/></param>
+ public void WriteInt32(int value)
+ {
+ try
+ {
+ this.xmsStreamMessage.WriteInt(value);
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ }
+ }
+
+ /// <summary>
+ /// Writes a 64 bts (long) integer to the stream message.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Int64"/></param>
+ public void WriteInt64(long value)
+ {
+ try
+ {
+ this.xmsStreamMessage.WriteLong(value);
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ }
+ }
+
+ /// <summary>
+ /// Writes a single precision floating point number to the stream
+ /// message.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Single"/></param>
+ public void WriteSingle(float value)
+ {
+ try
+ {
+ this.xmsStreamMessage.WriteFloat(value);
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ }
+ }
+
+ /// <summary>
+ /// Writes a double precision floating point number to the stream
+ /// message.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Double"/></param>
+ public void WriteDouble(double value)
+ {
+ try
+ {
+ this.xmsStreamMessage.WriteDouble(value);
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ }
+ }
+
+ /// <summary>
+ /// Writes a character string to the stream
+ /// message.
+ /// </summary>
+ /// <param name="value">A <see cref="System.String"/></param>
+ public void WriteString(string value)
+ {
+ try
+ {
+ this.xmsStreamMessage.WriteString(value);
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ }
+ }
+
+ /// <summary>
+ /// Writes an object to the stream
+ /// message.
+ /// </summary>
+ /// <param name="value">A <see cref="System.Object"/></param>
+ public void WriteObject(object value)
+ {
+ try
+ {
+ this.xmsStreamMessage.WriteObject(value);
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ }
+ }
+
+ #endregion
+
+ #endregion
+ }
+}
http://git-wip-us.apache.org/repos/asf/activemq-nms-xms/blob/653d676d/src/main/csharp/TemporaryQueue.cs
----------------------------------------------------------------------
diff --git a/src/main/csharp/TemporaryQueue.cs b/src/main/csharp/TemporaryQueue.cs
new file mode 100644
index 0000000..4d896c5
--- /dev/null
+++ b/src/main/csharp/TemporaryQueue.cs
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+namespace Apache.NMS.XMS
+{
+ class TemporaryQueue : Apache.NMS.XMS.Queue, Apache.NMS.ITemporaryQueue
+ {
+ #region Constructors and destructors
+
+ /// <summary>
+ /// Constructs a <c>TemporaryQueue</c> object.
+ /// </summary>
+ /// <param name="temporaryQueue">IBM XMS queue</param>
+ public TemporaryQueue(IBM.XMS.IDestination temporaryQueue)
+ : base(temporaryQueue, true)
+ {
+ }
+
+ #endregion
+
+ #region ITemporaryQueue Members
+
+ /// <summary>
+ /// Deletes the temporary queue.
+ /// </summary>
+ public void Delete()
+ {
+ // IBM.XMS does not provide a method for deleting a destination.
+ // Should we throw an exception or ignore the request ?
+ //this.xmsDestination.Delete();
+ }
+
+ #endregion
+
+ #region ToString
+
+ /// <summary>
+ /// Returns a string representation of this instance.
+ /// </summary>
+ /// <returns>String representation of this instance</returns>
+ public override System.String ToString()
+ {
+ return "temp-queue://" + QueueName;
+ }
+
+ #endregion
+ }
+}
http://git-wip-us.apache.org/repos/asf/activemq-nms-xms/blob/653d676d/src/main/csharp/TemporaryTopic.cs
----------------------------------------------------------------------
diff --git a/src/main/csharp/TemporaryTopic.cs b/src/main/csharp/TemporaryTopic.cs
new file mode 100644
index 0000000..374b528
--- /dev/null
+++ b/src/main/csharp/TemporaryTopic.cs
@@ -0,0 +1,62 @@
+/*
+ * 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.
+ */
+
+namespace Apache.NMS.XMS
+{
+ class TemporaryTopic : Apache.NMS.XMS.Topic, Apache.NMS.ITemporaryTopic
+ {
+ #region Constructors and destructors
+
+ /// <summary>
+ /// Constructs a <c>TemporaryTopic</c> object.
+ /// </summary>
+ /// <param name="temporaryTopic">IBM XMS queue</param>
+ public TemporaryTopic(IBM.XMS.IDestination temporaryTopic)
+ : base(temporaryTopic, true)
+ {
+ }
+
+ #endregion
+
+ #region ITemporaryTopic Members
+
+ /// <summary>
+ /// Deletes the temporary topic.
+ /// </summary>
+ public void Delete()
+ {
+ // IBM.XMS does not provide a method for deleting a destination.
+ // Should we throw an exception or ignore the request ?
+ //this.xmsDestination.Delete();
+ }
+
+ #endregion
+
+ #region ToString
+
+ /// <summary>
+ /// Returns a string representation of this instance.
+ /// </summary>
+ /// <returns>string representation of this instance</returns>
+ public override System.String ToString()
+ {
+ return "temp-topic://" + TopicName;
+ }
+
+ #endregion
+ }
+}
http://git-wip-us.apache.org/repos/asf/activemq-nms-xms/blob/653d676d/src/main/csharp/TextMessage.cs
----------------------------------------------------------------------
diff --git a/src/main/csharp/TextMessage.cs b/src/main/csharp/TextMessage.cs
new file mode 100644
index 0000000..d98cd03
--- /dev/null
+++ b/src/main/csharp/TextMessage.cs
@@ -0,0 +1,86 @@
+/*
+ * 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 Apache.NMS;
+using Apache.NMS.Util;
+using Apache.NMS.XMS.Util;
+using IBM.XMS;
+
+namespace Apache.NMS.XMS
+{
+ /// <summary>
+ /// Represents a text based message.
+ /// </summary>
+ class TextMessage : Apache.NMS.XMS.Message, Apache.NMS.ITextMessage
+ {
+ #region Constructors and access to internal stream message
+
+ /// <summary>
+ /// Internal IBM XMS text message.
+ /// </summary>
+ public IBM.XMS.ITextMessage xmsTextMessage
+ {
+ get { return (IBM.XMS.ITextMessage)this.xmsMessage; }
+ set { this.xmsMessage = value; }
+ }
+
+ /// <summary>
+ /// Constructs a <c>TextMessage</c> object.
+ /// </summary>
+ /// <param name="message">XMS text message.</param>
+ public TextMessage(IBM.XMS.ITextMessage message)
+ : base(message)
+ {
+ }
+
+ #endregion
+
+ #region ITextMessage Members
+
+ /// <summary>
+ /// The text contents of the message body.
+ /// </summary>
+ public string Text
+ {
+ get
+ {
+ try
+ {
+ return this.xmsTextMessage.Text;
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ return null;
+ }
+ }
+ set
+ {
+ try
+ {
+ this.xmsTextMessage.Text = value;
+ }
+ catch(Exception ex)
+ {
+ ExceptionUtil.WrapAndThrowNMSException(ex);
+ }
+ }
+ }
+
+ #endregion
+ }
+}
http://git-wip-us.apache.org/repos/asf/activemq-nms-xms/blob/653d676d/src/main/csharp/Topic.cs
----------------------------------------------------------------------
diff --git a/src/main/csharp/Topic.cs b/src/main/csharp/Topic.cs
new file mode 100644
index 0000000..c4cc4c2
--- /dev/null
+++ b/src/main/csharp/Topic.cs
@@ -0,0 +1,72 @@
+/*
+ * 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 Apache.NMS;
+using Apache.NMS.Util;
+using Apache.NMS.XMS.Util;
+using IBM.XMS;
+
+namespace Apache.NMS.XMS
+{
+ public class Topic : Apache.NMS.XMS.Destination, Apache.NMS.ITopic
+ {
+ #region Constructors and destructors
+
+ /// <summary>
+ /// Constructs a <c>Topic</c> object.
+ /// </summary>
+ /// <param name="topic">IBM XMS topic</param>
+ public Topic(IBM.XMS.IDestination topic)
+ : base(topic)
+ {
+ }
+
+ /// <summary>
+ /// Constructs a <c>Topic</c> object.
+ /// </summary>
+ /// <param name="topic">IBM XMS topic</param>
+ /// <param name="isTemporary">Whether the topic is temporary</param>
+ public Topic(IBM.XMS.IDestination topic, bool isTemporary)
+ : base(topic, isTemporary)
+ {
+ }
+
+ #endregion
+
+ #region ITopic Members
+
+ public string TopicName
+ {
+ get { return this.xmsDestination.Name; }
+ }
+
+ #endregion
+
+ #region ToString
+
+ /// <summary>
+ /// Returns a String representation of this instance.
+ /// </summary>
+ /// <returns>String representation of this instance</returns>
+ public override System.String ToString()
+ {
+ return "topic://" + TopicName;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/activemq-nms-xms/blob/653d676d/src/main/csharp/Util/Dispatcher.cs
----------------------------------------------------------------------
diff --git a/src/main/csharp/Util/Dispatcher.cs b/src/main/csharp/Util/Dispatcher.cs
new file mode 100644
index 0000000..d036cb3
--- /dev/null
+++ b/src/main/csharp/Util/Dispatcher.cs
@@ -0,0 +1,173 @@
+/*
+ * 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.Threading;
+
+namespace Apache.NMS.XMS.Util
+{
+ /// <summary>
+ /// Handles the multi-threaded dispatching between the transport and the consumers
+ /// </summary>
+ public class Dispatcher
+ {
+ System.Collections.Queue queue = new System.Collections.Queue();
+ readonly Object semaphore = new Object();
+ readonly ArrayList messagesToRedeliver = new ArrayList();
+
+ // TODO can't use EventWaitHandle on MONO 1.0
+ AutoResetEvent messageReceivedEventHandle = new AutoResetEvent(false);
+ bool m_bAsyncDelivery = false;
+ bool m_bClosed = false;
+
+ public void SetAsyncDelivery(AutoResetEvent eventHandle)
+ {
+ lock (semaphore)
+ {
+ messageReceivedEventHandle = eventHandle;
+ m_bAsyncDelivery = true;
+ if (queue.Count > 0)
+ {
+ messageReceivedEventHandle.Set();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Whem we start a transaction we must redeliver any rolled back messages
+ /// </summary>
+ public void RedeliverRolledBackMessages()
+ {
+ lock (semaphore)
+ {
+ System.Collections.Queue replacement = new System.Collections.Queue(queue.Count + messagesToRedeliver.Count);
+ foreach (Apache.NMS.IMessage element in messagesToRedeliver)
+ {
+ replacement.Enqueue(element);
+ }
+ messagesToRedeliver.Clear();
+
+ while (queue.Count > 0)
+ {
+ Apache.NMS.IMessage element = (Apache.NMS.IMessage) queue.Dequeue();
+ replacement.Enqueue(element);
+ }
+
+ queue = replacement;
+ if (queue.Count > 0)
+ {
+ messageReceivedEventHandle.Set();
+ }
+ }
+ }
+
+ /// <summary>
+ /// Redeliver the given message, putting it at the head of the queue
+ /// </summary>
+ public void Redeliver(Apache.NMS.IMessage message)
+ {
+ lock (semaphore)
+ {
+ messagesToRedeliver.Add(message);
+ }
+ }
+
+ /// <summary>
+ /// Method Enqueue
+ /// </summary>
+ public void Enqueue(Apache.NMS.IMessage message)
+ {
+ lock (semaphore)
+ {
+ queue.Enqueue(message);
+ messageReceivedEventHandle.Set();
+ }
+ }
+
+ /// <summary>
+ /// Method DequeueNoWait
+ /// </summary>
+ public Apache.NMS.IMessage DequeueNoWait()
+ {
+ Apache.NMS.XMS.Message rc = null;
+ lock (semaphore)
+ {
+ if (!m_bClosed && queue.Count > 0)
+ {
+ rc = (Apache.NMS.XMS.Message) queue.Dequeue();
+ if(null != rc)
+ {
+ rc.ReadOnlyBody = true;
+ rc.ReadOnlyProperties = true;
+ }
+ }
+ }
+ return rc;
+ }
+
+ /// <summary>
+ /// Method Dequeue
+ /// </summary>
+ public Apache.NMS.IMessage Dequeue(TimeSpan timeout)
+ {
+ Apache.NMS.IMessage rc;
+ bool bClosed = false;
+ lock (semaphore)
+ {
+ bClosed = m_bClosed;
+ rc = DequeueNoWait();
+ }
+
+ while (!bClosed && rc == null)
+ {
+ if( !messageReceivedEventHandle.WaitOne(timeout, false))
+ {
+ break;
+ }
+
+ lock (semaphore)
+ {
+ rc = DequeueNoWait();
+ bClosed = m_bClosed;
+ }
+ }
+ return rc;
+ }
+
+ /// <summary>
+ /// Method Dequeue
+ /// </summary>
+ public Apache.NMS.IMessage Dequeue()
+ {
+ TimeSpan indefiniteWait = TimeSpan.FromMilliseconds(Timeout.Infinite);
+ return Dequeue(indefiniteWait);
+ }
+
+ public void Close()
+ {
+ lock (semaphore)
+ {
+ m_bClosed = true;
+ queue.Clear();
+ if(m_bAsyncDelivery)
+ {
+ messageReceivedEventHandle.Set();
+ }
+ }
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/activemq-nms-xms/blob/653d676d/src/main/csharp/Util/ExceptionUtil.cs
----------------------------------------------------------------------
diff --git a/src/main/csharp/Util/ExceptionUtil.cs b/src/main/csharp/Util/ExceptionUtil.cs
new file mode 100644
index 0000000..14ee5d1
--- /dev/null
+++ b/src/main/csharp/Util/ExceptionUtil.cs
@@ -0,0 +1,147 @@
+\ufeff/*
+ * 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.Text;
+using System.Collections.Generic;
+using IBM.XMS;
+
+namespace Apache.NMS.XMS.Util
+{
+ class ExceptionUtil
+ {
+ /// <summary>
+ /// Wrap the provider specific exception inside an NMS exception to
+ /// more tightly integrate the provider extensions into the NMS API.
+ /// </summary>
+ /// <param name="ex">Original exception.</param>
+ public static void WrapAndThrowNMSException(Exception ex)
+ {
+ if(ex is Apache.NMS.NMSException)
+ {
+ // Already derived from NMSException
+ throw ex;
+ }
+
+ if(ex is IBM.XMS.IllegalStateException)
+ {
+ IBM.XMS.IllegalStateException xmsEx =
+ (IBM.XMS.IllegalStateException)ex;
+ throw new Apache.NMS.IllegalStateException(
+ xmsEx.Message, xmsEx.ErrorCode, xmsEx);
+ }
+
+ if(ex is IBM.XMS.InvalidClientIDException)
+ {
+ IBM.XMS.InvalidClientIDException xmsEx =
+ (IBM.XMS.InvalidClientIDException)ex;
+ throw new Apache.NMS.InvalidClientIDException(
+ xmsEx.Message, xmsEx.ErrorCode, xmsEx);
+ }
+
+ if(ex is IBM.XMS.InvalidDestinationException)
+ {
+ IBM.XMS.InvalidDestinationException xmsEx =
+ (IBM.XMS.InvalidDestinationException)ex;
+ throw new Apache.NMS.InvalidDestinationException(
+ xmsEx.Message, xmsEx.ErrorCode, xmsEx);
+ }
+
+ if(ex is IBM.XMS.InvalidSelectorException)
+ {
+ IBM.XMS.InvalidSelectorException xmsEx =
+ (IBM.XMS.InvalidSelectorException)ex;
+ throw new Apache.NMS.InvalidSelectorException(
+ xmsEx.Message, xmsEx.ErrorCode, xmsEx);
+ }
+
+ if(ex is IBM.XMS.MessageEOFException)
+ {
+ IBM.XMS.MessageEOFException xmsEx =
+ (IBM.XMS.MessageEOFException)ex;
+ throw new Apache.NMS.MessageEOFException(
+ xmsEx.Message, xmsEx.ErrorCode, xmsEx);
+ }
+
+ if(ex is IBM.XMS.MessageFormatException)
+ {
+ IBM.XMS.MessageFormatException xmsEx =
+ (IBM.XMS.MessageFormatException)ex;
+ throw new Apache.NMS.MessageFormatException(
+ xmsEx.Message, xmsEx.ErrorCode, xmsEx);
+ }
+
+ if(ex is IBM.XMS.MessageNotReadableException)
+ {
+ IBM.XMS.MessageNotReadableException xmsEx =
+ (IBM.XMS.MessageNotReadableException)ex;
+ throw new Apache.NMS.MessageNotReadableException(
+ xmsEx.Message, xmsEx.ErrorCode, xmsEx);
+ }
+
+ if(ex is IBM.XMS.MessageNotWriteableException)
+ {
+ IBM.XMS.MessageNotWriteableException xmsEx =
+ (IBM.XMS.MessageNotWriteableException)ex;
+ throw new Apache.NMS.MessageNotWriteableException(
+ xmsEx.Message, xmsEx.ErrorCode, xmsEx);
+ }
+
+ if(ex is IBM.XMS.ResourceAllocationException)
+ {
+ IBM.XMS.ResourceAllocationException xmsEx =
+ (IBM.XMS.ResourceAllocationException)ex;
+ throw new Apache.NMS.ResourceAllocationException(
+ xmsEx.Message, xmsEx.ErrorCode, xmsEx);
+ }
+
+ if(ex is IBM.XMS.SecurityException)
+ {
+ IBM.XMS.SecurityException xmsEx =
+ (IBM.XMS.SecurityException)ex;
+ throw new Apache.NMS.NMSSecurityException(
+ xmsEx.Message, xmsEx.ErrorCode, xmsEx);
+ }
+
+ if(ex is IBM.XMS.TransactionInProgressException)
+ {
+ IBM.XMS.TransactionInProgressException xmsEx =
+ (IBM.XMS.TransactionInProgressException)ex;
+ throw new Apache.NMS.TransactionInProgressException(
+ xmsEx.Message, xmsEx.ErrorCode, xmsEx);
+ }
+
+ if(ex is IBM.XMS.TransactionRolledBackException)
+ {
+ IBM.XMS.TransactionRolledBackException xmsEx =
+ (IBM.XMS.TransactionRolledBackException)ex;
+ throw new Apache.NMS.TransactionRolledBackException(
+ xmsEx.Message, xmsEx.ErrorCode, xmsEx);
+ }
+
+ if(ex is IBM.XMS.XMSException)
+ {
+ IBM.XMS.XMSException xmsEx =
+ (IBM.XMS.XMSException)ex;
+ throw new Apache.NMS.NMSException(
+ xmsEx.Message, xmsEx.ErrorCode, xmsEx);
+ }
+
+ // Not an EMS exception that should be wrapped.
+ throw ex;
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/activemq-nms-xms/blob/653d676d/src/main/csharp/Util/IntrospectionSupport.cs
----------------------------------------------------------------------
diff --git a/src/main/csharp/Util/IntrospectionSupport.cs b/src/main/csharp/Util/IntrospectionSupport.cs
new file mode 100644
index 0000000..175135f
--- /dev/null
+++ b/src/main/csharp/Util/IntrospectionSupport.cs
@@ -0,0 +1,434 @@
+\ufeff/*
+ * 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;
+using System.Globalization;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using Apache.NMS;
+using Apache.NMS.Util;
+
+namespace Apache.NMS.XMS.Util
+{
+ /// <summary>
+ /// Utility class used to provide convenience methods that apply named
+ /// property settings to objects.
+ /// </summary>
+ public class IntrospectionSupport
+ {
+ #region Manage maps of member names and URI aliases
+
+ private static Dictionary<Type, StringDictionary> nameMaps =
+ new Dictionary<Type, StringDictionary>();
+ private static readonly object nameMapsLock = new object();
+
+ /// <summary>
+ /// Gets the member names map for the specified type.
+ /// </summary>
+ /// <param name="type">Type whose names map is requested.</param>
+ /// <returns>Names map for the specified type.</returns>
+ /// <remarks>
+ /// The map is created and registered if it is not found in the
+ /// <c>nameMaps</c> registry.
+ /// </remarks>
+ public static StringDictionary GetNameMap(Type type)
+ {
+ StringDictionary nameMap;
+ lock(IntrospectionSupport.nameMapsLock)
+ {
+ if(!IntrospectionSupport.nameMaps.TryGetValue(
+ type, out nameMap))
+ {
+ nameMap = CreateNameMap(type);
+ IntrospectionSupport.nameMaps.Add(type, nameMap);
+ }
+ }
+ return nameMap;
+ }
+
+ /// <summary>
+ /// Creates a dictionary of public property and attribute names,
+ /// indexed by themselves plus all URI attribute keys associated
+ /// to them.
+ /// </summary>
+ /// <param name="type">Type whose names map is requested.</param>
+ /// <returns>Names map for the specified type.</returns>
+ /// <remarks>
+ /// Applied to this property:
+ /// <code>
+ /// [UriAttribute("My.Test", "MyTest")]
+ /// public string Test
+ /// { get { return(_test); }
+ /// set { _test = value; }
+ /// }
+ /// </code>
+ /// the method returns a dictionary containing
+ /// ("test" -> "Test"), ("my.test" -> "Test"), ("mytest" -> "Test").
+ /// Note that <c>StringDictionary</c> converts keys to lowercase but
+ /// keeps values untouched.
+ /// </remarks>
+ public static StringDictionary CreateNameMap(Type type)
+ {
+ StringDictionary nameMap = new StringDictionary();
+ BindingFlags flags = BindingFlags.FlattenHierarchy
+ | BindingFlags.Public
+ | BindingFlags.Instance;
+
+ // Process public instance self or inherited property
+ foreach(PropertyInfo propertyInfo in type.GetProperties(flags))
+ {
+ AddToNameMap(nameMap, propertyInfo);
+ }
+
+ // Process public instance self or inherited fields
+ foreach(FieldInfo fieldInfo in type.GetFields(flags))
+ {
+ AddToNameMap(nameMap, fieldInfo);
+ }
+
+ return(nameMap);
+ }
+
+ /// <summary>
+ /// Adds a property or field name and URI attribute keys to the
+ /// specified name map.
+ /// </summary>
+ /// <param name="nameMap">Name map.</param>
+ /// <param name="memberInfo">Member information for the property
+ /// or field.</param>
+ private static void AddToNameMap(StringDictionary nameMap,
+ MemberInfo memberInfo)
+ {
+ // Add member name mapped to itself
+ nameMap.Add(memberInfo.Name, memberInfo.Name);
+
+ // For each UriAttribute custom attribute
+ foreach(Attribute attr in memberInfo.GetCustomAttributes(
+ typeof(UriAttributeAttribute), true))
+ {
+ // For each URI attribute key
+ foreach(string key in
+ ((UriAttributeAttribute)attr).AttributeKeys)
+ {
+ // Index property name by URI attribute key
+ if(!nameMap.ContainsKey(key))
+ {
+ nameMap.Add(key, memberInfo.Name);
+ }
+ }
+ }
+
+ return;
+ }
+
+ #endregion
+
+ #region Set properties
+
+ /// <summary>
+ /// Sets the public properties of a target object using a string map.
+ /// This method uses .Net reflection to identify public properties of
+ /// the target object matching the keys from the passed map.
+ /// </summary>
+ /// <param name="target">Object whose properties will be set.</param>
+ /// <param name="valueMap">Map of key/value pairs.</param>
+ public static void SetProperties(object target,
+ StringDictionary valueMap)
+ {
+ SetProperties(target, valueMap, GetNameMap(target.GetType()));
+ }
+
+ /// <summary>
+ /// Sets the public properties of a target object using a string map.
+ /// This method uses .Net reflection to access public properties of
+ /// the target object matching the keys from the passed map.
+ /// </summary>
+ /// <param name="target">The object whose properties will be set.</param>
+ /// <param name="valueMap">Map of key/value pairs.</param>
+ /// <param name="nameMap">Map of key/property name pairs.</param>
+ public static void SetProperties(object target,
+ StringDictionary valueMap,
+ StringDictionary nameMap)
+ {
+ Tracer.DebugFormat("SetProperties called with target: {0}",
+ target.GetType().Name);
+
+ // Application of specified values is recursive. If a key does not
+ // correspond to a member of the current target object, it is
+ // supposed to refer to a sub-member of such a member. Since member
+ // keys can contain dot characters, an attempt is made to find the
+ // "longest" key corresponding to a member of the current object
+ // (this identifies the "sub-target"), and extract the remaining
+ // key characters as a sub-key to sub-members.
+ // The following dictionary indexes keys to "sub-targets", and
+ // "sub-key"/value pairs to assign to "sub-targets".
+ Dictionary<string, StringDictionary> subTargetMap = null;
+
+ foreach(string key in valueMap.Keys)
+ {
+ if(nameMap.ContainsKey(key))
+ {
+ // Key refers to a member of the current target
+ string memberName = nameMap[key];
+ MemberInfo member = FindMemberInfo(target, memberName);
+ if(member == null)
+ {
+ // Should not happen if the nameMap was indeed created
+ // for the current target object...
+ throw new NMSException(string.Format(
+ "No such property or field: {0} on class: {1}",
+ memberName, target.GetType().Name));
+ }
+
+ // Set value
+ try
+ {
+ if(member.MemberType == MemberTypes.Property)
+ {
+ PropertyInfo property = (PropertyInfo)member;
+ object value = ConvertValue(valueMap[key],
+ property.PropertyType);
+ property.SetValue(target, value, null);
+ }
+ else
+ {
+ FieldInfo field = (FieldInfo)member;
+ object value = ConvertValue(valueMap[key],
+ field.FieldType);
+ field.SetValue(target, value);
+ }
+ }
+ catch(Exception ex)
+ {
+ throw NMSExceptionSupport.Create(
+ "Error while attempting to apply option.", ex);
+ }
+ }
+ else
+ {
+ // Key does NOT refers to a member of the current target
+ // Extract maximal member key + subkeys
+ string memberKey = key;
+ int dotPos = memberKey.LastIndexOf('.');
+ bool memberFound = false;
+ while(!memberFound && dotPos > 0)
+ {
+ memberKey = memberKey.Substring(0, dotPos);
+ if(nameMap.ContainsKey(memberKey))
+ {
+ memberKey = nameMap[memberKey];
+ memberFound = true;
+ }
+ else
+ {
+ dotPos = memberKey.LastIndexOf('.');
+ }
+ }
+
+ if(!memberFound)
+ {
+ throw new NMSException(string.Format(
+ "Unknown property or field: {0} on class: {1}",
+ key, target.GetType().Name));
+ }
+
+ // Register memberKey, subKey and value for further processing
+ string subKey = key.Substring(dotPos + 1);
+ StringDictionary subValueMap;
+
+ if(subTargetMap == null)
+ {
+ subTargetMap = new Dictionary<string, StringDictionary>();
+ }
+
+ if(!subTargetMap.TryGetValue(memberKey, out subValueMap))
+ {
+ subValueMap = new StringDictionary();
+ subTargetMap.Add(memberKey, subValueMap);
+ }
+
+ // In theory, we can't have the same subkey twice, since
+ // they were unique subkeys from another dictionary.
+ // Therefore, no need to check for subValueMap.ContainsKey.
+ subValueMap.Add(subKey, valueMap[key]);
+ }
+ }
+
+ // Now process any compound assignments.
+ if(subTargetMap != null)
+ {
+ foreach(string subTargetKey in subTargetMap.Keys)
+ {
+ MemberInfo member = FindMemberInfo(target, subTargetKey);
+ object subTarget = GetUnderlyingObject(member, target);
+ SetProperties(subTarget, subTargetMap[subTargetKey]);
+ }
+ }
+ }
+
+ /// <summary>
+ /// Converts the specified string value to the type of the target
+ /// member.
+ /// </summary>
+ private static object ConvertValue(string inputString, Type targetType)
+ {
+ // If the target member is an enumeration, get the enumeration
+ // value or combined (or-ed) values
+ object value;
+ if(targetType.IsEnum)
+ {
+ if(inputString.Contains("+"))
+ {
+ string[] inputValues = inputString.Split('+');
+
+ FieldInfo fieldInfo = targetType.GetField(inputValues[0],
+ BindingFlags.Public
+ | BindingFlags.Static
+ | BindingFlags.IgnoreCase);
+ if(fieldInfo == null)
+ {
+ throw new NMSException(string.Format(
+ "Invalid {0} value \"{1}\"", targetType.Name,
+ inputValues[0]));
+ }
+ dynamic val = fieldInfo.GetValue(null);
+
+ for(int v = 1; v < inputValues.Length; v++)
+ {
+ fieldInfo = targetType.GetField(inputValues[v],
+ BindingFlags.Public
+ | BindingFlags.Static
+ | BindingFlags.IgnoreCase);
+ if(fieldInfo == null)
+ {
+ throw new NMSException(string.Format(
+ "Invalid {0} value \"{1}\"", targetType.Name,
+ inputValues[v]));
+ }
+ val = (dynamic)val | (dynamic)fieldInfo.GetValue(null);
+ }
+
+ value = Convert.ChangeType(val, targetType);
+ }
+ else
+ {
+ FieldInfo fieldInfo = targetType.GetField(inputString,
+ BindingFlags.Public
+ | BindingFlags.Static
+ | BindingFlags.IgnoreCase);
+ if(fieldInfo == null)
+ {
+ throw new NMSException(string.Format(
+ "Invalid {0} value \"{1}\"", targetType.Name,
+ inputString));
+ }
+ value = fieldInfo.GetValue(null);
+ }
+ }
+ else
+ {
+ // Not an enumeration
+ value = Convert.ChangeType(inputString,
+ targetType, CultureInfo.InvariantCulture);
+ }
+ return value;
+ }
+
+ #endregion
+
+ #region Get member information and objects
+
+ /// <summary>
+ /// Gets member information for a property or field of the target
+ /// object.
+ /// </summary>
+ /// <param name="target">Target object.</param>
+ /// <param name="name">Property or field name.</param>
+ /// <returns>Retrieved member information.</returns>
+ private static MemberInfo FindMemberInfo(object target, string name)
+ {
+ BindingFlags flags = BindingFlags.FlattenHierarchy
+ | BindingFlags.Public
+ | BindingFlags.Instance
+ | BindingFlags.IgnoreCase;
+
+ Type type = target.GetType();
+
+ MemberInfo member = type.GetProperty(name, flags);
+
+ if(member == null)
+ {
+ member = type.GetField(name, flags);
+ }
+
+ return member;
+ }
+
+ /// <summary>
+ /// Gets object assigned to the specified property or field member of
+ /// the target object.
+ /// </summary>
+ /// <param name="member">Member information.</param>
+ /// <param name="target">Target object.</param>
+ /// <returns>Retrieved object.</returns>
+ private static object GetUnderlyingObject(
+ MemberInfo member, object target)
+ {
+ object result = null;
+
+ if(member.MemberType == MemberTypes.Field)
+ {
+ FieldInfo field = member as FieldInfo;
+
+ if(field.FieldType.IsPrimitive)
+ {
+ throw new NMSException(string.Format(
+ "The field given is a primitive type: {0}",
+ member.Name));
+ }
+
+ result = field.GetValue(target);
+ }
+ else
+ {
+ PropertyInfo property = member as PropertyInfo;
+ MethodInfo getter = property.GetGetMethod();
+
+ if(getter == null)
+ {
+ throw new NMSException(string.Format(
+ "Cannot access member: {0}",
+ member.Name));
+ }
+
+ result = getter.Invoke(target, null);
+ }
+
+ if(result == null)
+ {
+ throw new NMSException(string.Format(
+ "Could not retrieve the value of member {0}.",
+ member.Name));
+ }
+
+ return result;
+ }
+
+ #endregion
+ }
+}
http://git-wip-us.apache.org/repos/asf/activemq-nms-xms/blob/653d676d/src/main/csharp/Util/UriAttributeAttribute.cs
----------------------------------------------------------------------
diff --git a/src/main/csharp/Util/UriAttributeAttribute.cs b/src/main/csharp/Util/UriAttributeAttribute.cs
new file mode 100644
index 0000000..f7278d8
--- /dev/null
+++ b/src/main/csharp/Util/UriAttributeAttribute.cs
@@ -0,0 +1,51 @@
+\ufeff/*
+ * 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.XMS.Util
+{
+ /// <summary>
+ /// Attribute for mapping a URI attribute key to an object's property.
+ /// </summary>
+ public class UriAttributeAttribute : System.Attribute
+ {
+ private readonly string[] attributeKeys;
+
+ /// <summary>
+ /// Constructs an <c>UriAttributeAttribute</c> specifying a list
+ /// of attribute keys.
+ /// </summary>
+ /// <param name="keys">URI attribute keys.</param>
+ public UriAttributeAttribute(params string[] keys)
+ {
+ this.attributeKeys = new string[keys.Length];
+ for(int k = 0; k < keys.Length; k++)
+ {
+ this.attributeKeys[k] = keys[k];
+ }
+ }
+
+ /// <summary>
+ /// URI attribute keys.
+ /// </summary>
+ public string[] AttributeKeys
+ {
+ get { return this.attributeKeys; }
+ }
+ }
+}