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 2018/08/27 21:15:44 UTC
[07/15] activemq-nms-amqp git commit: AMQNET-575: NMS AMQP Client
Rework Add an NMS API implementation that wraps the AMQPnetLite .NET API.
http://git-wip-us.apache.org/repos/asf/activemq-nms-amqp/blob/432c9613/src/main/csharp/Util/IdGenerator.cs
----------------------------------------------------------------------
diff --git a/src/main/csharp/Util/IdGenerator.cs b/src/main/csharp/Util/IdGenerator.cs
new file mode 100644
index 0000000..965c748
--- /dev/null
+++ b/src/main/csharp/Util/IdGenerator.cs
@@ -0,0 +1,674 @@
+/*
+ * 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.Net;
+using System.Security.Permissions;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Apache.NMS.Util;
+using Apache.NMS;
+
+namespace Apache.NMS.AMQP.Util
+{
+ #region Id Class
+
+ class Id : IComparable
+ {
+ public static readonly Id EMPTY = new Id();
+ protected const int DEFAULT_MAX_CAPACITY = 1;
+ protected static readonly int[] HashTable = new int[] { 2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97};
+ protected static readonly int HashTableSize = HashTable.Length;
+ protected delegate ComponentId InstanceFactory(object o);
+ protected static readonly Dictionary<Type, InstanceFactory> buildMap;
+
+ #region Class Initializer
+
+ static Id()
+ {
+ buildMap = new Dictionary<Type, InstanceFactory>();
+ buildMap.Add(typeof(String), (o) => { return new ComponentId<string>(o as string); });
+ buildMap.Add(typeof(UInt16), (o) => { return new ComponentId<UInt16>(Convert.ToUInt16(o)); });
+ buildMap.Add(typeof(UInt32), (o) => { return new ComponentId<UInt32>(Convert.ToUInt32(o)); });
+ buildMap.Add(typeof(UInt64), (o) => { return new ComponentId<UInt64>(Convert.ToUInt64(o)); });
+ buildMap.Add(typeof(Int16), (o) => { return new ComponentId<UInt16>(Convert.ToUInt16(o)); });
+ buildMap.Add(typeof(Int32), (o) => { return new ComponentId<UInt32>(Convert.ToUInt32(o)); });
+ buildMap.Add(typeof(Int64), (o) => { return new ComponentId<UInt64>(Convert.ToUInt64(o)); });
+ buildMap.Add(typeof(AtomicSequence), (o) =>
+ {
+ ulong val = 0;
+ AtomicSequence seq = o as AtomicSequence;
+ if (o != null && seq != null)
+ {
+ val = seq.getAndIncrement();
+ }
+ return new ComponentId<UInt64>(val);
+ });
+ buildMap.Add(typeof(Guid), (o) =>
+ {
+ Guid id;
+ if (o == null)
+ {
+ id = Guid.Empty;
+ }
+ else
+ {
+ id = (Guid)o;
+ }
+ return new ComponentId<Guid>(id);
+ });
+ buildMap.Add(typeof(Id), (o) => { return new ComponentId<Id>(o as Id); });
+ }
+
+ #endregion
+
+ ComponentId[] components;
+ private bool isReadOnly = false;
+ private int length;
+ private int maxCapacity;
+ private int current;
+ private string componentDelimeter;
+ private int hashcode = 0;
+
+ #region Constructors
+
+ public Id(string delimeter, int size, int maxSize)
+ {
+ maxCapacity = Math.Max(maxSize, DEFAULT_MAX_CAPACITY);
+ length = size;
+ components = new ComponentId[length];
+ current = 0;
+ componentDelimeter = delimeter;
+ }
+
+ public Id(int size, int maxSize) : this(IdGenerator.ID_COMPONENT_DELIMETER, size, maxSize) { }
+
+ public Id(int size) : this(IdGenerator.ID_COMPONENT_DELIMETER, size, size) { }
+
+ public Id(params object[] args) : this(args.Length)
+ {
+ int added = this.AddAll(args);
+ if(added > maxCapacity)
+ {
+ Tracer.ErrorFormat("Id Format error.");
+ }
+ Generate();
+ }
+
+ #endregion
+
+ #region Public Properties
+
+ public int Size
+ {
+ get { return length; }
+ }
+
+ #endregion
+
+ #region Public Methods
+
+ public void Add(object component)
+ {
+ Tracer.DebugFormat("Adding Component To Id, component {0}, current index: {1}", component, current);
+ if (isReadOnly)
+ {
+ throw new NMSException("Invalid Operation when generating Component Id. Can not change id once generated.");
+ }
+ if (current >= maxCapacity)
+ {
+ throw new NMSException("Invalid Operation when generating Component Id. Can not add component. Adding Compoenent at full capacity " + maxCapacity);
+ }
+ if (current >= length)
+ {
+ grow(length * 2);
+ }
+ Type type = component.GetType();
+ InstanceFactory instf = null;
+ buildMap.TryGetValue(type, out instf);
+ if (instf == null)
+ {
+ throw new NMSException(string.Format("Invalid Id component type {0} for component {1}", type.ToString(), component.ToString()));
+ }
+ components[current] = instf(component);
+ current++;
+
+ }
+
+ public object[] GetComponents(int startIndex=0)
+ {
+ return GetComponents(startIndex, length);
+ }
+
+ public object[] GetComponents(int startIndex, int endIndex)
+ {
+ int eIndex = Math.Max(0,Math.Min(endIndex, length));
+ int sIndex = Math.Max(0, startIndex);
+ int resultLen = eIndex - sIndex;
+ if (resultLen<0)
+ {
+ return null;
+ }
+ object[] comps = new object[resultLen];
+ int index = 0;
+ for(int i=sIndex; i< eIndex; i++)
+ {
+ comps[index] = components[i].IdValue;
+ index++;
+ }
+ return comps;
+ }
+
+ public object GetComponent(int index)
+ {
+ if (isReadOnly)
+ {
+ if (index >= 0 && index < length)
+ {
+ return components[index].IdValue;
+ }
+ }
+ return null;
+ }
+
+ public object GetFirstComponent(Type type)
+ {
+ if (isReadOnly)
+ {
+ for (int i = 0; i < length; i++)
+ {
+ ComponentId cid = components[i];
+ if (cid.ValueType.Equals(type))
+ {
+ return cid.IdValue;
+ }
+ }
+ }
+ return null;
+ }
+
+ public object GetLastComponent(Type type)
+ {
+ if (isReadOnly)
+ {
+ for (int i = length; i > 0; i--)
+ {
+ ComponentId cid = components[i - 1];
+ if (cid.ValueType.Equals(type))
+ {
+ return cid.IdValue;
+ }
+ }
+ }
+ return null;
+ }
+
+ public void Generate()
+ {
+ if (!isReadOnly)
+ {
+ isReadOnly = true;
+ this.GetHashCode();
+ }
+ }
+
+ #endregion
+
+ #region Object Override Methods
+
+ public override bool Equals(object obj)
+ {
+ if(GetHashCode() == obj.GetHashCode())
+ {
+ return true;
+ }
+ else
+ {
+ return CompareTo(obj) == 0;
+ }
+ }
+
+ public override int GetHashCode()
+ {
+ if(hashcode == 0 && isReadOnly && length > 0)
+ {
+ int hashIndex = 0;
+ ComponentId cid = components[0];
+ hashcode = HashTable[hashIndex] * cid.GetHashCode();
+ for (int i=1; i<length; i++)
+ {
+ cid = components[i];
+ hashIndex = i % HashTableSize;
+ hashcode = hashcode ^ HashTable[hashIndex] * cid.GetHashCode();
+ }
+ }
+ return hashcode;
+ }
+
+ public override string ToString()
+ {
+ if (maxCapacity == 0)
+ {
+ return "0";
+ }
+ if (isReadOnly)
+ {
+ if (length == 0)
+ {
+ return EMPTY.ToString();
+ }
+ StringBuilder sb = new StringBuilder();
+ ComponentId cid = this.components[0];
+ sb.Append(cid.ToString());
+ for (int i = 1; i < length; i++)
+ {
+ cid = this.components[i];
+ sb.Append(componentDelimeter);
+ sb.Append(cid.ToString());
+
+ }
+ return sb.ToString();
+ }
+ else
+ {
+ return base.ToString();
+ }
+ }
+
+ #endregion
+
+ #region IComparable Methods
+
+ public int CompareTo(object obj)
+ {
+
+ if(obj!=null && obj is Id)
+ {
+ return CompareTo(obj as Id);
+ }
+ else if(obj == null)
+ {
+ return 1;
+ }
+ else
+ {
+ return -1;
+ }
+
+ }
+
+ public int CompareTo(Id that)
+ {
+ if(this.length > that.length)
+ {
+ return 1;
+ }
+ else if (this.length < that.length)
+ {
+ return -1;
+ }
+ else
+ {
+ int compare = 0;
+ for(int i=0; i<length; i++)
+ {
+ ComponentId thisCid = this.components[i];
+ ComponentId thatCid = that.components[i];
+ compare = thisCid.CompareTo(thatCid);
+ if ( compare > 0)
+ {
+ return 1;
+ }
+ else if ( compare < 0 )
+ {
+ return -1;
+ }
+
+ }
+ return compare;
+ }
+ }
+
+ #endregion
+
+ #region Protected Methods
+
+ protected void grow(int newCapacity)
+ {
+ int size = Math.Min(newCapacity, maxCapacity);
+ ComponentId[] buffer = new ComponentId[size];
+ Array.Copy(this.components, buffer, this.length);
+ length = size;
+ this.components = buffer;
+ }
+
+ protected int AddAll(params object[] args)
+ {
+#if NET46
+ if(Tracer.IsDebugEnabled)
+ {
+ Tracer.DebugFormat("Adding Id components: {0} MaxCapacity: {1}", string.Join(",",
+ args.Select(x => x.ToString()).ToArray()), maxCapacity);
+
+ }
+#else
+#endif
+ int added = 0;
+ foreach (object o in args)
+ {
+ Type type = o.GetType();
+
+ if (type.IsArray && type.Equals(typeof(object[])))
+ {
+ object[] moreArgs = o as object[];
+ int addlen = (moreArgs).Length;
+
+ maxCapacity = maxCapacity + addlen - 1;
+ added += this.AddAll(moreArgs);
+
+ }
+ else
+ {
+ this.Add(o);
+ added++;
+ }
+ }
+ return added;
+ }
+
+#endregion
+
+#region Inner ComponentId Classes
+
+ protected abstract class ComponentId : IComparable
+ {
+ protected object value;
+
+ protected ComponentId(object idvalue)
+ {
+ value = idvalue;
+ }
+
+ public object IdValue { get { return value; } }
+
+ public abstract Type ValueType { get; }
+
+ public virtual int CompareTo(object obj)
+ {
+ if(obj == null)
+ {
+ return 1;
+ }
+ else if(obj is ComponentId)
+ {
+ return CompareTo(obj as ComponentId);
+ }
+ else if (obj is IComparable)
+ {
+ return -1 * (obj as IComparable).CompareTo(this.IdValue);
+ }
+ else
+ {
+ return -1;
+ }
+ }
+
+ public virtual int CompareTo(ComponentId that)
+ {
+ if (this.ValueType.Equals(that.ValueType) || this.ValueType.IsEquivalentTo(that.ValueType))
+ {
+ if (this.IdValue.Equals(that.IdValue))
+ {
+ return 0;
+ }
+ else
+ {
+ return this.GetHashCode() - that.GetHashCode();
+ }
+ }
+ else if (this.IdValue is IComparable)
+ {
+ return (this.IdValue as IComparable).CompareTo(that.IdValue);
+ }
+ else if (that.IdValue is IComparable)
+ {
+ return -1 * (that.IdValue as IComparable).CompareTo(this.IdValue);
+ }
+ else
+ {
+ return this.ValueType.GetHashCode() - that.ValueType.GetHashCode();
+ }
+
+ }
+
+ public override bool Equals(object obj)
+ {
+ return CompareTo(obj) == 0;
+ }
+
+
+ public override int GetHashCode()
+ {
+ return this.IdValue.GetHashCode();
+ }
+
+ public override string ToString()
+ {
+ return value.ToString();
+ }
+ }
+
+ protected class ComponentId<T> : ComponentId
+ {
+ public ComponentId(T val) : base(val)
+ {
+ }
+
+ public T Value
+ {
+ get { return (T)this.value; }
+ }
+
+ public override Type ValueType
+ {
+ get
+ {
+ if (value != null)
+ {
+ return value.GetType();
+ }
+ return default(T).GetType();
+ }
+ }
+ }
+
+#endregion
+
+ }
+
+#endregion
+
+#region IdGenerator Class
+
+ class IdGenerator
+ {
+ public const string ID_COMPONENT_DELIMETER = ":";
+ protected static readonly string DEFAULT_PREFIX = "ID";
+ protected static string hostname = null;
+
+ protected readonly string prefix;
+ protected readonly AtomicSequence sequence = new AtomicSequence(1);
+
+#region Class Initializer
+
+ static IdGenerator()
+ {
+#if NETSTANDARD2_0
+ hostname = Dns.GetHostName();
+#else
+ DnsPermission permissions = null;
+ try
+ {
+ permissions = new DnsPermission(PermissionState.Unrestricted);
+ }
+ catch (Exception e)
+ {
+ Tracer.InfoFormat("{0}", e.StackTrace);
+ }
+ if (permissions != null)
+ {
+ hostname = Dns.GetHostName();
+ }
+#endif
+
+ }
+
+#endregion
+
+#region Constructors
+
+ public IdGenerator(string prefix)
+ {
+ this.prefix = RemoveEnd(prefix, ID_COMPONENT_DELIMETER)
+ + ((hostname == null)
+ ?
+ ""
+ :
+ ID_COMPONENT_DELIMETER + hostname)
+ ;
+ }
+
+ public IdGenerator() : this(DEFAULT_PREFIX)
+ {
+ }
+
+#endregion
+
+ public virtual Id GenerateId()
+ {
+ Id id = new Id(this.prefix, Guid.NewGuid(), sequence);
+ return id;
+ }
+
+ public virtual string generateID()
+ {
+ Id id = GenerateId();
+ return id.ToString();
+ //return string.Format("{0}{1}" + ID_COMPONENT_DELIMETER + "{2}", this.prefix, Guid.NewGuid().ToString(), sequence.getAndIncrement());
+ }
+
+ protected static string RemoveEnd(string s, string end)
+ {
+ string result = s;
+
+ if (s != null && end != null && s.EndsWith(end))
+ {
+ int sLen = s.Length;
+ int endLen = end.Length;
+ int newLen = sLen - endLen;
+ if (endLen > 0 && newLen > 0)
+ {
+ StringBuilder sb = new StringBuilder(s, 0, newLen, newLen);
+ result = sb.ToString();
+ }
+ }
+ return result;
+ }
+ }
+
+#endregion
+
+#region Derivative IdGenerator Classes
+
+ class NestedIdGenerator : IdGenerator
+ {
+ protected Id parentId;
+ protected bool removeParentPrefix;
+
+ public NestedIdGenerator(string prefix, Id pId, bool remove) : base(prefix)
+ {
+ parentId = pId;
+ removeParentPrefix = remove;
+ }
+
+ public NestedIdGenerator(string prefix, Id pId) : this(prefix, pId, false) { }
+
+ public NestedIdGenerator(Id pId):this(DEFAULT_PREFIX, pId) { }
+
+ public override Id GenerateId()
+ {
+ Id id;
+ if (removeParentPrefix)
+ {
+ int componentIndex = (parentId.Size == 1) ? 0 : 1;
+ id = new Id(prefix, parentId.GetComponents(componentIndex), sequence);
+ }
+ else
+ {
+ id = new Id(prefix, parentId, sequence);
+ }
+
+ return id;
+ }
+
+ public override string generateID()
+ {
+ return GenerateId().ToString();
+ }
+ }
+
+ class CustomIdGenerator : IdGenerator
+ {
+ protected object[] parts;
+ protected bool isOnlyParts;
+
+
+ public CustomIdGenerator(string prefix, params object[] args) : base(prefix)
+ {
+ parts = args;
+ }
+
+ public CustomIdGenerator(bool onlyParts, params object[] args) : this(DEFAULT_PREFIX, args)
+ {
+ isOnlyParts = onlyParts;
+ }
+
+ public CustomIdGenerator(Id pId) : this(DEFAULT_PREFIX, pId) { }
+
+ public override Id GenerateId()
+ {
+ Id id;
+ if (isOnlyParts)
+ {
+ id = new Id(parts);
+ }
+ else
+ {
+ id = new Id(prefix, parts, sequence);
+ }
+ return id;
+ }
+
+ public override string generateID()
+ {
+ return GenerateId().ToString();
+ }
+ }
+
+#endregion
+}
http://git-wip-us.apache.org/repos/asf/activemq-nms-amqp/blob/432c9613/src/main/csharp/Util/LinkCache.cs
----------------------------------------------------------------------
diff --git a/src/main/csharp/Util/LinkCache.cs b/src/main/csharp/Util/LinkCache.cs
new file mode 100644
index 0000000..985f9e4
--- /dev/null
+++ b/src/main/csharp/Util/LinkCache.cs
@@ -0,0 +1,190 @@
+/*
+ * 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.Collections.Generic;
+using Apache.NMS;
+
+namespace Apache.NMS.AMQP.Util
+{
+
+ #region Abstract Link Cache
+
+ internal abstract class LinkCache<TKey, TLink> : ICollection, IDisposable where TKey : class where TLink : MessageLink
+ {
+ protected readonly IDictionary<TKey, TLink> cachedLinks;
+
+ public LinkCache()
+ {
+ cachedLinks = CreateCache();
+ }
+
+ #region ICollection Properties
+
+ public int Count { get => cachedLinks.Count; }
+
+ public object SyncRoot { get => cachedLinks; }
+
+ public bool IsSynchronized { get => false; }
+
+ #endregion
+
+ #region ICollection Methods
+
+ public abstract void CopyTo(Array array, int index);
+
+ public IEnumerator GetEnumerator()
+ {
+ return (cachedLinks as IEnumerable).GetEnumerator();
+ }
+
+ #endregion
+
+ #region Link Cache Properties
+
+ internal ICollection<TKey> Keys { get => cachedLinks.Keys; }
+
+ internal ICollection<TLink> Links { get => cachedLinks.Values; }
+
+ #endregion
+
+ #region Link Cache Methods
+
+ public TLink GetLink(TKey cacheId)
+ {
+ TLink link = null;
+ if (!IsValidKey(cacheId)) return link;
+ if(!cachedLinks.TryGetValue(cacheId, out link))
+ {
+ Tracer.InfoFormat("Failed to get Link for cache request id {0}", cacheId);
+ }
+ return link;
+ }
+
+ public void AddLink(TKey cacheId, TLink link)
+ {
+ if (HasLink(cacheId))
+ {
+ throw new NMSException("Cannot add link to cache with Id {0} which is already in use.");
+ }
+ cachedLinks.Add(cacheId, link);
+ }
+
+ public TLink RemoveLink(TKey cacheId)
+ {
+ TLink linkToRemove = null;
+ cachedLinks.TryGetValue(cacheId, out linkToRemove);
+ cachedLinks.Remove(cacheId);
+ return linkToRemove;
+ }
+
+ public bool HasLink(TKey cacheId)
+ {
+ return IsValidKey(cacheId) && cachedLinks.ContainsKey(cacheId);
+ }
+
+ public virtual void Close() { }
+
+ public virtual void Dispose()
+ {
+ Close();
+ }
+
+ #endregion
+
+ #region Abstract Link Cache Methods
+
+ protected abstract IDictionary<TKey, TLink> CreateCache();
+ protected abstract bool IsValidKey(TKey cacheId);
+
+ #endregion
+ }
+
+ #endregion
+
+ #region Temporary Link Cache
+
+ internal class TemporaryLinkCache : LinkCache<TemporaryDestination, TemporaryLink>
+ {
+ private Connection connection;
+ private Session tempSession;
+ internal TemporaryLinkCache(Connection connection) : base()
+ {
+ this.connection = connection;
+
+ }
+
+ internal Session Session
+ {
+ get
+ {
+ if(tempSession == null)
+ {
+ tempSession = connection.CreateSession() as Session;
+ }
+ return tempSession;
+ }
+ }
+
+ protected override bool IsValidKey(TemporaryDestination cacheId)
+ {
+ return cacheId != null && cacheId.DestinationId != null && cacheId.DestinationId.Size > 0;
+ }
+
+ protected override IDictionary<TemporaryDestination, TemporaryLink> CreateCache()
+ {
+ return new Dictionary<TemporaryDestination, TemporaryLink>(new TemporaryDestinationComparer());
+ }
+
+ protected sealed class TemporaryDestinationComparer : IEqualityComparer<TemporaryDestination>
+ {
+ public bool Equals(TemporaryDestination x, TemporaryDestination y)
+ {
+ return x.Equals(y);
+ }
+
+ public int GetHashCode(TemporaryDestination obj)
+ {
+ return obj.GetHashCode();
+ }
+ }
+
+ public override void CopyTo(Array array, int index)
+ {
+ (this.cachedLinks as Dictionary<TemporaryDestination, TemporaryLink> as IDictionary).CopyTo(array, index);
+ }
+
+ public override void Close()
+ {
+ base.Close();
+ this.cachedLinks.Clear();
+ if(tempSession != null)
+ {
+ tempSession.Close();
+ tempSession = null;
+ }
+ }
+ }
+
+ #endregion
+
+ #region Anonymous Link Cache
+
+ //TODO implement for Anonymous Fallback producer.
+
+ #endregion
+}
http://git-wip-us.apache.org/repos/asf/activemq-nms-amqp/blob/432c9613/src/main/csharp/Util/MessageSupport.cs
----------------------------------------------------------------------
diff --git a/src/main/csharp/Util/MessageSupport.cs b/src/main/csharp/Util/MessageSupport.cs
new file mode 100644
index 0000000..2941103
--- /dev/null
+++ b/src/main/csharp/Util/MessageSupport.cs
@@ -0,0 +1,397 @@
+/*
+ * 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.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Apache.NMS;
+using Amqp.Framing;
+using Amqp.Types;
+using Apache.NMS.AMQP.Message;
+
+namespace Apache.NMS.AMQP.Util
+{
+ /// <summary>
+ /// Utility class containing constant values for NMS message fields, and values.
+ /// Also contains Utility methods for NMS messagId/correlationId and Destinations.
+ /// </summary>
+ class MessageSupport
+ {
+ // "x-opt-jms-msg-type" values
+ public const byte JMS_TYPE_MSG = 0x00;
+ public const byte JMS_TYPE_OBJ = 0x01;
+ public const byte JMS_TYPE_MAP = 0x02;
+ public const byte JMS_TYPE_BYTE = 0x03;
+ public const byte JMS_TYPE_STRM = 0x04;
+ public const byte JMS_TYPE_TXT = 0x05;
+
+ // "x-opt-jms-dest" and "x-opt-jms-reply-to" values
+ public const byte JMS_DEST_TYPE_QUEUE = 0x00;
+ public const byte JMS_DEST_TYPE_TOPIC = 0x01;
+ public const byte JMS_DEST_TYPE_TEMP_QUEUE = 0x02;
+ public const byte JMS_DEST_TYPE_TEMP_TOPIC = 0x03;
+
+ // Message Serialization ENCODING Annotation keys
+ public const string JMS_AMQP_TYPE_ENCODING = "JMS_AMQP_TYPE_ENCODING";
+ public const string JMS_JAVA_ENCODING = "JMS_JAVA_ENCODING";
+ public const string JMS_DONET_ENCODING = "JMS_DOTNET_ENCODING";
+
+ // Message Content-type values
+ public const string OCTET_STREAM_CONTENT_TYPE = "application/octet-stream";
+ public const string SERIALIZED_JAVA_OBJECT_CONTENT_TYPE = "application/x-java-serialized-object";
+
+ // Amqp.Message priority default value
+ public static readonly byte DEFAULT_PRIORITY_BYTE = Convert.ToByte((int)NMSConstants.defaultPriority);
+
+ public static readonly Data EMPTY_DATA = new Data() { Binary = new byte[] { } };
+ public static readonly AmqpValue NULL_AMQP_VALUE_BODY = new AmqpValue() { Value = null };
+
+ // Amqp Message Outcome instances
+ public static readonly Amqp.Framing.Accepted ACCEPTED_INSTANCE = new Amqp.Framing.Accepted();
+ public static readonly Amqp.Framing.Released RELEASED_INSTANCE = new Amqp.Framing.Released();
+ public static readonly Amqp.Framing.Rejected REJECTED_INSTANCE = new Amqp.Framing.Rejected();
+ public static readonly Amqp.Framing.Modified MODIFIED_INSTANCE = new Amqp.Framing.Modified();
+ public static readonly Amqp.Framing.Modified MODIFIED_FAILED_INSTANCE = new Amqp.Framing.Modified() { DeliveryFailed = true };
+ public static readonly AckType DEFAULT_ACK_TYPE = AckType.ACCEPTED;
+
+ // Message Id constants
+ public const string NMS_ID_PREFIX = "ID:";
+ public const string AMQP_STRING_PREFIX = "AMQP_STRING:";
+ public const string AMQP_ULONG_PREFIX = "AMQP_ULONG:";
+ public const string AMQP_BINARY_PREFIX = "AMQP_BINARY:";
+ public const string AMQP_UUID_PREFIX = "AMQP_UUID:";
+ public const string AMQP_NO_PREFIX = "AMQP_NO_PREFIX:";
+
+ private const string AMQP_TYPE = "AMQP_";
+ private static readonly int NMS_ID_PREFIX_LENGTH = NMS_ID_PREFIX.Length;
+ private static readonly int AMQP_TYPE_LENGTH = AMQP_TYPE.Length;
+ private static readonly int AMQP_STRING_PREFIX_LENGTH = AMQP_STRING_PREFIX.Length;
+ private static readonly int AMQP_BINARY_PREFIX_LENGTH = AMQP_BINARY_PREFIX.Length;
+ private static readonly int AMQP_ULONG_PREFIX_LENGTH = AMQP_ULONG_PREFIX.Length;
+ private static readonly int AMQP_UUID_PREFIX_LENGTH = AMQP_UUID_PREFIX.Length;
+ private static readonly int AMQP_NO_PREFIX_LENGTH = AMQP_NO_PREFIX.Length;
+ private static readonly char[] HEX_CHARS = "0123456789ABCDEF".ToCharArray();
+
+ public static IDestination CreateDestinationFromMessage(Connection source, Properties properties, byte type, bool replyTo = false)
+ {
+ IDestination dest = null;
+ if(properties==null || source == null) { return dest; }
+ bool isPropertyNull = (!replyTo) ? properties.To != null : properties.ReplyTo != null;
+ if (isPropertyNull)
+ {
+ string destname = (!replyTo) ? properties.To : properties.ReplyTo;
+ destname = UriUtil.GetDestinationName(destname, source);
+ switch (type)
+ {
+ case JMS_DEST_TYPE_TEMP_QUEUE:
+ dest = new TemporaryQueue(source, destname);
+ break;
+ case JMS_DEST_TYPE_QUEUE:
+ dest = new Queue(source, destname);
+ break;
+ case JMS_DEST_TYPE_TEMP_TOPIC:
+ dest = new TemporaryTopic(source, destname);
+ break;
+ case JMS_DEST_TYPE_TOPIC:
+ dest = new Topic(source, destname);
+ break;
+ }
+ }
+ return dest;
+ }
+
+ public static sbyte GetValueForDestination(IDestination destination)
+ {
+ sbyte b = 0x00; // same as queue.
+ if (destination != null)
+ {
+ if (destination.IsTopic)
+ {
+ if (destination.IsTemporary)
+ {
+ return (sbyte)JMS_DEST_TYPE_TEMP_TOPIC;
+ }
+ else
+ {
+ return (sbyte)JMS_DEST_TYPE_TOPIC;
+ }
+ }
+ else if (destination.IsQueue)
+ {
+ if (destination.IsTemporary)
+ {
+ return (sbyte)JMS_DEST_TYPE_TEMP_QUEUE;
+ }
+ else
+ {
+ return (sbyte)JMS_DEST_TYPE_QUEUE;
+ }
+ }
+ }
+ return b;
+ }
+
+ public static byte GetValueForPriority(MsgPriority mp)
+ {
+ return Convert.ToByte((int)mp);
+ }
+
+ public static MsgPriority GetPriorityFromValue(byte value)
+ {
+ MsgPriority result = NMSConstants.defaultPriority;
+
+ switch (value)
+ {
+ case 0x00:
+ result = MsgPriority.Lowest;
+ break;
+ case 0x01:
+ result = MsgPriority.VeryLow;
+ break;
+ case 0x02:
+ result = MsgPriority.Low;
+ break;
+ case 0x03:
+ result = MsgPriority.AboveLow;
+ break;
+ case 0x04:
+ result = MsgPriority.BelowNormal;
+ break;
+ case 0x05:
+ result = MsgPriority.Normal;
+ break;
+ case 0x06:
+ result = MsgPriority.AboveNormal;
+ break;
+ case 0x07:
+ result = MsgPriority.High;
+ break;
+ case 0x08:
+ result = MsgPriority.VeryHigh;
+ break;
+ case 0x09:
+ result = MsgPriority.Highest;
+ break;
+ default:
+ break;
+ }
+
+ return result;
+ }
+
+ public static object CreateAMQPMessageId(string nmsId)
+ {
+ if(nmsId == null)
+ {
+ return null;
+ }
+ if (!HasNMSIdPrefix(nmsId))
+ {
+ // application specific msg id return as is.
+ return nmsId;
+ }
+
+ try
+ {
+ if (HasAMQPNoPrefix(nmsId, NMS_ID_PREFIX_LENGTH))
+ {
+ return nmsId.Substring(NMS_ID_PREFIX_LENGTH + AMQP_NO_PREFIX_LENGTH);
+ }
+ else if (HasAMQPStringPrefix(nmsId, NMS_ID_PREFIX_LENGTH))
+ {
+ return nmsId.Substring(NMS_ID_PREFIX_LENGTH + AMQP_STRING_PREFIX_LENGTH);
+ }
+ else if (HasAMQPBinaryPrefix(nmsId, NMS_ID_PREFIX_LENGTH))
+ {
+ string hexString = nmsId.Substring(NMS_ID_PREFIX_LENGTH + AMQP_BINARY_PREFIX_LENGTH).ToUpper();
+ return ToByteArray(hexString, nmsId);
+ }
+ else if (HasAMQPULongPrefix(nmsId, NMS_ID_PREFIX_LENGTH))
+ {
+ string ulongString = nmsId.Substring(NMS_ID_PREFIX_LENGTH + AMQP_ULONG_PREFIX_LENGTH);
+ return Convert.ToUInt64(ulongString);
+ }
+ else if (HasAMQPUuidPrefix(nmsId, NMS_ID_PREFIX_LENGTH))
+ {
+ string guidString = nmsId.Substring(NMS_ID_PREFIX_LENGTH + AMQP_UUID_PREFIX_LENGTH);
+ return Guid.Parse(guidString);
+ }
+ else
+ {
+ return nmsId;
+ }
+
+ }
+ catch (Exception e)
+ {
+ throw new NMSException("Id Conversion Failure. Provided Id: " + nmsId, e);
+ }
+ }
+
+ public static string CreateNMSMessageId(object amqpId)
+ {
+ if(null == amqpId)
+ {
+ return null;
+ }
+ if(amqpId is string)
+ {
+ string id = amqpId as string;
+ if (!HasNMSIdPrefix(id))
+ {
+ return NMS_ID_PREFIX + AMQP_NO_PREFIX + id;
+ }
+ else if (HasEncodingTypePrefix(id, NMS_ID_PREFIX_LENGTH))
+ {
+ return NMS_ID_PREFIX + AMQP_STRING_PREFIX + id;
+ }
+ else
+ {
+ return id;
+ }
+ }
+ else if (amqpId is Guid)
+ {
+ return NMS_ID_PREFIX + AMQP_UUID_PREFIX + amqpId.ToString();
+ }
+ else if (amqpId is ulong)
+ {
+ return NMS_ID_PREFIX + AMQP_ULONG_PREFIX + amqpId.ToString();
+ }
+ else if (amqpId is byte[])
+ {
+ return NMS_ID_PREFIX + AMQP_BINARY_PREFIX + ToHexString(amqpId as byte[]);
+ }
+ else
+ {
+ throw new NMSException("Unsupported Id Type provided: ", amqpId.GetType().FullName);
+ }
+ }
+
+ private static bool HasNMSIdPrefix(string id)
+ {
+ if(id == null)
+ {
+ return false;
+ }
+ return id.StartsWith(NMS_ID_PREFIX);
+ }
+
+ private static bool HasAMQPNoPrefix(string id, int offset)
+ {
+ if (id.Length - offset < AMQP_NO_PREFIX_LENGTH)
+ {
+ return false;
+ }
+ return id.IndexOf(AMQP_NO_PREFIX, offset, AMQP_NO_PREFIX_LENGTH) - offset == 0;
+ }
+
+ private static bool HasAMQPBinaryPrefix(string id, int offset)
+ {
+ if (id.Length - offset < AMQP_BINARY_PREFIX_LENGTH)
+ {
+ return false;
+ }
+ return id.IndexOf(AMQP_BINARY_PREFIX, offset, AMQP_BINARY_PREFIX_LENGTH) - offset == 0;
+ }
+
+ private static bool HasAMQPStringPrefix(string id, int offset)
+ {
+ if (id.Length - offset < AMQP_STRING_PREFIX_LENGTH)
+ {
+ return false;
+ }
+ return id.IndexOf(AMQP_STRING_PREFIX, offset, AMQP_STRING_PREFIX_LENGTH) - offset == 0;
+ }
+
+ private static bool HasAMQPULongPrefix(string id, int offset)
+ {
+ if (id.Length - offset < AMQP_ULONG_PREFIX_LENGTH)
+ {
+ return false;
+ }
+ return id.IndexOf(AMQP_ULONG_PREFIX, offset, AMQP_ULONG_PREFIX_LENGTH) - offset == 0;
+ }
+
+ private static bool HasAMQPUuidPrefix(string id, int offset)
+ {
+ if (id.Length - offset < AMQP_UUID_PREFIX_LENGTH)
+ {
+ return false;
+ }
+ return id.IndexOf(AMQP_UUID_PREFIX, offset, AMQP_UUID_PREFIX_LENGTH) - offset == 0;
+ }
+
+ private static bool HasEncodingTypePrefix(string id, int offset)
+ {
+ if (id.Length - offset < AMQP_NO_PREFIX_LENGTH)
+ {
+ return false;
+ }
+ if (id.IndexOf(AMQP_TYPE,offset, AMQP_TYPE_LENGTH) != 0)
+ {
+ return false;
+ }
+ return HasAMQPBinaryPrefix(id, offset) ||
+ HasAMQPNoPrefix(id, offset) ||
+ HasAMQPStringPrefix(id, offset) ||
+ HasAMQPULongPrefix(id, offset) ||
+ HasAMQPUuidPrefix(id, offset);
+ }
+
+ private static string ToHexString(byte[] bytes)
+ {
+ if(bytes == null)
+ {
+ return null;
+ }
+ StringBuilder sb = new StringBuilder(bytes.Length);
+ foreach(byte b in bytes)
+ {
+ int upper = (b >> 4) & 0x0F;
+ int lower = b & 0x0F;
+ sb.Append(HEX_CHARS[upper]);
+ sb.Append(HEX_CHARS[lower]);
+ }
+ return sb.ToString();
+ }
+
+ private static byte[] ToByteArray(string hex, string originalId)
+ {
+ if (hex == null || hex.Length % 2 != 0)
+ {
+ throw new NMSException("Invalid Binary MessageId " + originalId);
+ }
+ int size = hex.Length / 2;
+ int index = 0;
+ byte[] result = new byte[size];
+ for (int i=0; i<result.Length; i++)
+ {
+ char upper = hex[index];
+ index++;
+ char lower = hex[index];
+ index++;
+ char[] subchars = { upper, lower };
+ string substring = new string(subchars);
+ result[i] = Convert.ToByte(substring, 16);
+ }
+ return result;
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/activemq-nms-amqp/blob/432c9613/src/main/csharp/Util/PropertyUtil.cs
----------------------------------------------------------------------
diff --git a/src/main/csharp/Util/PropertyUtil.cs b/src/main/csharp/Util/PropertyUtil.cs
new file mode 100644
index 0000000..7b68bd5
--- /dev/null
+++ b/src/main/csharp/Util/PropertyUtil.cs
@@ -0,0 +1,1294 @@
+/*
+ * 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 Apache.NMS;
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Collections.Specialized;
+using System.Linq;
+using System.Reflection;
+using System.Text;
+using System.Threading.Tasks;
+using System.Security.Authentication;
+
+using Apache.NMS.AMQP.Transport.Secure;
+using Apache.NMS.AMQP.Transport;
+
+namespace Apache.NMS.AMQP.Util
+{
+ class PropertyUtil
+ {
+ private const string PROPERTY_TERM_SEPARATOR = ".";
+ public const string PROPERTY_PREFIX = "NMS" + PROPERTY_TERM_SEPARATOR;
+
+ public static string CreateProperty(string name, string subprefix = "", string prefix = PROPERTY_PREFIX)
+ {
+ string propertyPrefix = prefix +
+ (prefix.Length > 0 && !prefix.EndsWith(PROPERTY_TERM_SEPARATOR)
+ ?
+ PROPERTY_TERM_SEPARATOR
+ :
+ ""
+ );
+
+ string subPropertyTerm = subprefix +
+ (subprefix.Length > 0 && !subprefix.EndsWith(PROPERTY_TERM_SEPARATOR)
+ ?
+ PROPERTY_TERM_SEPARATOR
+ :
+ ""
+ );
+ return propertyPrefix + subPropertyTerm + name;
+ }
+
+ public static void SetProperties(object obj, StringDictionary properties, string propertyPrefix = PROPERTY_PREFIX)
+ {
+ Dictionary<string, PropertyInfo> props = GetPropertiesForClass(obj);
+ foreach (string rawkey in properties.Keys)
+ {
+ string key = removePrefix(propertyPrefix, rawkey);
+ Tracer.DebugFormat("Searching for Property: \"{0}\"", key);
+ if (props.ContainsKey(key))
+ {
+ Tracer.DebugFormat(
+ "Assigning Property {0} to {1}.{2} with value {3}",
+ key, obj.GetType().Namespace, obj.GetType().Name, properties[rawkey]
+ );
+#if NET40
+ if (props[key].GetSetMethod() != null)
+#else
+ if(props[key].SetMethod!=null)
+#endif
+ props[key].SetValue(obj, ConvertType(props[key].PropertyType, properties[rawkey]), null);
+ }
+
+ }
+ }
+
+ public static StringDictionary GetProperties(object obj, string propertyPrefix = PROPERTY_PREFIX)
+ {
+ StringDictionary result = new StringDictionary();
+ Dictionary<string, PropertyInfo> props = GetPropertiesForClass(obj);
+ string propsPrefix = propertyPrefix +
+ (
+ propertyPrefix.Length > 0 && !propertyPrefix.EndsWith(PROPERTY_TERM_SEPARATOR)
+ ?
+ PROPERTY_TERM_SEPARATOR
+ :
+ ""
+ );
+ foreach (string key in props.Keys)
+ {
+ object value = props[key].GetValue(obj, null);
+ if (value != null)
+ {
+ result[propertyPrefix + key] = value.ToString();
+ }
+ }
+ return result;
+ }
+
+ public static object ConvertType(Type targetType, string value)
+ {
+ if (targetType.IsPrimitive)
+ {
+ return Convert.ChangeType(value, targetType);
+ }
+ else if (targetType.Equals(typeof(string)))
+ {
+ return value;
+ }
+ return null;
+ }
+
+ private static string removePrefix(string prefix, string propertyName)
+ {
+ if (propertyName.StartsWith(prefix, StringComparison.CurrentCultureIgnoreCase) && prefix.Length > 0)
+ {
+ return propertyName.Remove(0, prefix.Length);
+ }
+ else
+ {
+ return propertyName;
+ }
+ }
+
+ public static Dictionary<string, PropertyInfo> GetPropertiesForClass(object obj)
+ {
+ MemberInfo[] members = obj.GetType().GetMembers();
+ Dictionary<string, PropertyInfo> properties = new Dictionary<string, PropertyInfo>();
+ foreach (MemberInfo member in members)
+ {
+ string memberName = member.Name;
+ if (member != null && member is PropertyInfo)
+ {
+ PropertyInfo prop = member as PropertyInfo;
+ properties.Add(memberName.ToLower(), prop);
+ }
+ }
+ return properties;
+ }
+
+ public static StringDictionary Clone(StringDictionary original)
+ {
+ StringDictionary clone = new StringDictionary();
+ foreach (string key in original.Keys)
+ {
+ clone.Add(key?.Clone() as string, original[key]?.Clone() as string);
+ }
+ return clone;
+ }
+
+ /// <summary>
+ /// See <see cref="Merge(StringDictionary, StringDictionary, out StringDictionary, string, string, string)"/>
+ /// </summary>
+ /// <param name="one"></param>
+ /// <param name="other"></param>
+ /// <param name="onePrefix"></param>
+ /// <param name="otherPrefix"></param>
+ /// <param name="mergePrefix"></param>
+ /// <returns></returns>
+ public static StringDictionary Merge(
+ StringDictionary one,
+ StringDictionary other,
+ string onePrefix = PROPERTY_PREFIX,
+ string otherPrefix = PROPERTY_PREFIX,
+ string mergePrefix = PROPERTY_PREFIX
+ )
+ {
+ StringDictionary d;
+ return Merge(one, other, out d, onePrefix, otherPrefix, mergePrefix);
+ }
+
+
+ /// <summary>
+ /// Takes all properties from one StringDictionary and merges them with the other StringDictionary.
+ /// The properties in "one" are prefered over the "other".
+ ///
+ /// </summary>
+ /// <param name="one">StringDictionary containing properties.</param>
+ /// <param name="other">Another StringDictionary containing properties.</param>
+ /// <param name="cross">Holds all the properties from the "other" StringDictionary that are not used because one has the properties.</param>
+ /// <param name="onePrefix">Optional string prefix for the properties in "one".</param>
+ /// <param name="otherPrefix">Optional string prefix for the properties in "other".</param>
+ /// <param name="mergePrefix">Optional string prefix for the properties in result.</param>
+ /// <returns>Merged StringDictionary with properties from both "one" and "other".</returns>
+ public static StringDictionary Merge(
+ StringDictionary one,
+ StringDictionary other,
+ out StringDictionary cross,
+ string onePrefix = PROPERTY_PREFIX,
+ string otherPrefix = PROPERTY_PREFIX,
+ string mergePrefix = PROPERTY_PREFIX
+ )
+ {
+ if (one == null && other != null)
+ {
+ cross = null;
+ return Clone(other);
+ }
+ else if (one!=null && other == null)
+ {
+ cross = null;
+ return Clone(one);
+ }
+ else if (one == null && other == null)
+ {
+ cross = null;
+ return new StringDictionary();
+ }
+ StringDictionary result = new StringDictionary();
+ StringDictionary dups = new StringDictionary();
+
+ Array arr = new string[other.Keys.Count];
+ other.Keys.CopyTo(arr, 0);
+ ArrayList otherKeys = new ArrayList(arr);
+
+ string mPre = mergePrefix +
+ (
+ mergePrefix.Length > 0 && !mergePrefix.EndsWith(PROPERTY_TERM_SEPARATOR)
+ ?
+ PROPERTY_TERM_SEPARATOR
+ :
+ ""
+ );
+ mergePrefix.ToLower();
+
+ string onePre = onePrefix +
+ (
+ onePrefix.Length > 0 && !onePrefix.EndsWith(PROPERTY_TERM_SEPARATOR)
+ ?
+ PROPERTY_TERM_SEPARATOR
+ :
+ ""
+ );
+ onePre.ToLower();
+
+ string otherPre = otherPrefix +
+ (
+ otherPrefix.Length > 0 && !otherPrefix.EndsWith(PROPERTY_TERM_SEPARATOR)
+ ?
+ PROPERTY_TERM_SEPARATOR
+ :
+ ""
+ );
+ otherPre.ToLower();
+
+ foreach (string rawkey in one.Keys)
+ {
+ string key = removePrefix(onePre, rawkey);
+ string otherkey = (otherPre + key).ToLower();
+ string mergekey = (mPre + key).ToLower();
+ if (!result.ContainsKey(mergekey))
+ {
+ result.Add(mergekey, one[rawkey]);
+ }
+ if (other.ContainsKey(otherkey))
+ {
+ otherKeys.Remove(otherkey);
+ dups.Add(mergekey, other[otherkey]);
+ }
+ }
+
+ foreach (string rawkey in otherKeys)
+ {
+ string key = removePrefix(otherPre, rawkey);
+ result.Add(mPre + key, other[rawkey]);
+ }
+
+ cross = dups.Count == 0 ? null : dups;
+ return result;
+ }
+
+ public static string ToString(IList set)
+ {
+ if (set == null)
+ {
+ return "null";
+ }
+ if (set.Count == 0)
+ {
+ return "[]";
+ }
+ string result = "[";
+ foreach (object o in set)
+ {
+ result += o.ToString() + ",";
+ }
+ return result.Substring(0, result.Length - 1) + "]";
+ }
+
+ private static string ToString(ArrayList set)
+ {
+ if(set == null)
+ {
+ return "null";
+ }
+ if(set.Count == 0)
+ {
+ return "[]";
+ }
+ string result = "[";
+ foreach(object o in set)
+ {
+ result += o.ToString() + ",";
+ }
+ return result.Substring(0,result.Length - 1) + "]";
+ }
+
+ public static string ToString(StringDictionary properties)
+ {
+ if(properties == null)
+ {
+ return "null";
+ }
+ if (properties.Count == 0)
+ {
+ return "[]";
+ }
+ string result = "[\n";
+ foreach(string s in properties.Keys)
+ {
+ result += string.Format("{0} : {1},\n", s, properties[s]);
+ }
+ return result.Substring(0,result.Length-2) + "\n]";
+ }
+
+ public static IDictionary<K,V> Clone<K,V>(IDictionary<K,V> dict)
+ {
+ if (dict == null) return null;
+ Dictionary<K, V> clone = new Dictionary<K, V>(dict.Count);
+ dict.CopyTo(clone.ToArray(), 0);
+ return clone;
+ }
+ }
+
+#region NMS Resource Property Interceptor classes StringDictionary based
+
+#region abstract Property Interceptor classes
+
+ internal abstract class PropertyInterceptor<T> : StringDictionary where T : class
+ {
+ protected delegate void ApplyProperty(T instance, string key, string value);
+ protected delegate string GetProperty(T instance, string key);
+ protected delegate void ClearProperty(T instance);
+ protected delegate bool CheckProperty(T instance);
+
+ protected struct Interceptor
+ {
+ public ApplyProperty Setter;
+ public GetProperty Getter;
+ public ClearProperty Reset;
+ public CheckProperty Exists;
+ }
+
+
+ private readonly StringDictionary properties;
+ private readonly IDictionary<string, Interceptor> interceptors;
+ private readonly T instance;
+ protected PropertyInterceptor(T instance, StringDictionary properties, IDictionary<string, Interceptor> interceptors) : base()
+ {
+ this.properties = properties;
+ this.instance = instance;
+
+ // initialize interceptor map
+ this.interceptors = new Dictionary<string, Interceptor>();
+ foreach (string key in interceptors.Keys)
+ {
+ AddInterceptor(key, interceptors[key]);
+ }
+
+ }
+
+ protected T Instance { get { return instance; } }
+
+ protected StringDictionary Properties { get { return properties; } }
+
+ protected void AddInterceptor(string key, Interceptor interceptor)
+ {
+ bool updated = false;
+ // add new interceptor
+ if (!interceptors.ContainsKey(key))
+ {
+ this.interceptors.Add(key, interceptor);
+ }
+ else
+ {
+ // update interceptor
+ // this allows subs classes to override base classes.
+ this.interceptors[key] = interceptor;
+ updated = true;
+ }
+ // Remove intercepted properties from base string dictionary
+ if (properties.ContainsKey(key) || updated)
+ {
+ SetProperty(key, properties[key]);
+ properties.Remove(key);
+ }
+ }
+
+ protected void AddProperty(string key, string value)
+ {
+ if (interceptors.ContainsKey(key))
+ {
+ interceptors[key].Setter(instance, key, value);
+ }
+ else
+ {
+ properties.Add(key, value);
+ }
+ }
+
+ protected void SetProperty(string key, string value)
+ {
+ if (interceptors.ContainsKey(key))
+ {
+ interceptors[key].Setter(instance, key, value);
+ }
+ else
+ {
+ properties[key] = value;
+ }
+ }
+
+ protected string GetValue(string key)
+ {
+ string value = null;
+ if (interceptors.ContainsKey(key))
+ {
+ if (interceptors[key].Exists(instance))
+ {
+ value = interceptors[key].Getter(instance, key);
+ }
+ }
+ else
+ {
+ value = properties[key];
+ }
+ return value;
+ }
+
+ protected int InterceptorCount
+ {
+ get
+ {
+ int count = 0;
+ foreach (string key in interceptors.Keys)
+ {
+ Interceptor i = interceptors[key];
+ if (i.Exists(instance))
+ {
+ count++;
+ }
+ }
+ return count;
+ }
+ }
+
+ #region IDictionary<> Methods
+
+ public override int Count => this.properties.Count + InterceptorCount;
+
+ public override void Add(string key, string value)
+ {
+ AddProperty(key, value);
+ }
+
+ public override string this[string key]
+ {
+ get
+ {
+ return GetValue(key);
+ }
+ set
+ {
+ SetProperty(key, value);
+ }
+ }
+
+ public override void Clear()
+ {
+ this.properties.Clear();
+ Interceptor[] set = interceptors.Values.ToArray();
+ foreach (Interceptor i in set)
+ {
+ i.Reset?.Invoke(Instance);
+ }
+ }
+
+ public override void Remove(string key)
+ {
+ if (this.properties.ContainsKey(key))
+ {
+ this.properties.Remove(key);
+ }
+ else if (this.interceptors.ContainsKey(key))
+ {
+ if (this.interceptors[key].Exists(Instance))
+ {
+ this.interceptors[key].Reset(Instance);
+ }
+ }
+ }
+
+ public override bool ContainsKey(string key)
+ {
+ if (this.properties.ContainsKey(key))
+ {
+ return true;
+ }
+ else if (this.interceptors.ContainsKey(key))
+ {
+ return this.interceptors[key].Exists(Instance);
+ }
+ return false;
+ }
+
+ public override ICollection Keys
+ {
+ get
+ {
+ ISet<string> keys = new HashSet<string>();
+ foreach (string key in interceptors.Keys)
+ {
+ Interceptor i = interceptors[key];
+ if (i.Exists(instance))
+ {
+ keys.Add(key);
+ }
+ }
+ foreach (string key in properties.Keys)
+ {
+ keys.Add(key);
+ }
+
+ return keys.ToList();
+ }
+ }
+
+ public override ICollection Values
+ {
+ get
+ {
+ ISet<object> values = new HashSet<object>();
+ foreach (string key in interceptors.Keys)
+ {
+ Interceptor i = interceptors[key];
+ if (i.Exists(instance))
+ {
+ values.Add(i.Getter(instance, key));
+ }
+ }
+ foreach (object value in properties.Values)
+ {
+ values.Add(value);
+ }
+
+ return values.ToList();
+ }
+ }
+
+ #endregion
+ public override string ToString()
+ {
+ string result = base.ToString();
+ foreach (string key in Keys)
+ {
+ result += "\n" + key.ToString() + ": " + GetValue(key).ToString();
+ }
+ return result;
+ }
+
+ }
+
+ internal abstract class NMSResourcePropertyInterceptor<T, I> : PropertyInterceptor<T> where I : ResourceInfo where T : NMSResource<I>
+ {
+ protected NMSResourcePropertyInterceptor(T instance, StringDictionary properties, IDictionary<string, Interceptor> interceptors) : base(instance, properties, interceptors)
+ {
+
+ }
+ }
+
+ #region RelfectionPropertyInterceptor
+
+ internal abstract class ReflectionPropertyInterceptor<T> : PropertyInterceptor<T> where T : class
+ {
+ #region static methods
+
+ private static bool DefaultExists(T instance)
+ {
+ return true;
+ }
+
+ private static void SetReflectedValue(PropertyInfo info, object instance, string value)
+ {
+ if (info.GetSetMethod() != null)
+ {
+ object objValue = ParseReflectedValue(info, value);
+ info.SetValue(instance, objValue, null);
+ }
+ }
+
+ private static object GetReflectedValue(PropertyInfo info, object instance)
+ {
+ object value = null;
+ if (info.GetGetMethod() != null)
+ {
+ value = info.GetValue(instance);
+ }
+ return value;
+ }
+
+ private static object ParseReflectedValue(PropertyInfo info, string value)
+ {
+ Type targetType = info.PropertyType;
+ return PropertyUtil.ConvertType(targetType, value);
+ }
+
+ #endregion
+
+ protected struct ReflectedInteceptor
+ {
+ public PropertyInfo ReflectedProperty;
+ public Interceptor BaseInterceptor;
+ }
+
+
+ private Dictionary<string, ReflectedInteceptor> autoInterceptors = null;
+
+ #region Contructor
+
+ protected ReflectionPropertyInterceptor(T instance, StringDictionary properties, IDictionary<string, Interceptor> interceptors ) : base(instance, properties, interceptors)
+ {
+ this.autoInterceptors = CreateReflectionInterceptors(instance);
+ if (this.autoInterceptors != null)
+ {
+ foreach (string propertyName in this.autoInterceptors.Keys)
+ {
+ this.AddInterceptor(propertyName, this.autoInterceptors[propertyName].BaseInterceptor);
+ }
+
+ if (Tracer.IsDebugEnabled)
+ {
+ StringBuilder sb = new StringBuilder();
+#if TRACE
+ sb.AppendFormat("Generated {0} reflection properties, Properties = [", this.autoInterceptors.Keys.Count);
+ foreach (string propertyName in this.autoInterceptors.Keys)
+ {
+ sb.AppendFormat("\n\t{0},\n", propertyName);
+ }
+ sb.AppendFormat("]");
+#else
+ sb.AppendFormat("Generated {0} reflection properties", this.autoInterceptors.Keys.Count);
+#endif
+ Tracer.DebugFormat(sb.ToString());
+ }
+
+ }
+ }
+
+ #endregion
+
+ #region abstract Properties
+
+ protected abstract string PropertyPrefix { get; }
+
+ #endregion
+
+ protected abstract bool CanReflect(PropertyInfo reflectedProperty);
+
+ #region Private Methods
+
+ private Interceptor? CreateReflectedInterceptor(PropertyInfo reflectedProperty)
+ {
+ Interceptor? result = null;
+
+ if (reflectedProperty.GetSetMethod() == null)
+ {
+
+ }
+ else
+ {
+
+
+ ApplyProperty reflectedSetter = (inst, key, value) =>
+ {
+ SetReflectedValue(reflectedProperty, inst, value);
+ };
+
+ GetProperty reflectedGetter = (inst, key) =>
+ {
+ return GetReflectedValue(reflectedProperty, inst)?.ToString();
+ };
+
+ ClearProperty reflectedClear = (inst) =>
+ {
+ SetReflectedValue(reflectedProperty, inst, null);
+ };
+
+ CheckProperty reflectedExists = DefaultExists;
+
+ result = new Interceptor()
+ {
+ Getter = reflectedGetter,
+ Setter = reflectedSetter,
+ Reset = reflectedClear,
+ Exists = reflectedExists
+ };
+ }
+
+ return result;
+ }
+
+ private Dictionary<string, ReflectedInteceptor> CreateReflectionInterceptors(T instance)
+ {
+ Dictionary<string, PropertyInfo> objProperties = PropertyUtil.GetPropertiesForClass(instance);
+
+ Dictionary<string, ReflectedInteceptor> result = new Dictionary<string, ReflectedInteceptor>();
+
+ if (Tracer.IsDebugEnabled)
+ {
+
+ List<string> stringPropertyNames = new List<string>(objProperties.Keys.Count);
+ foreach (string pName in objProperties.Keys)
+ {
+ string propertyName = this.PropertyPrefix + pName;
+ stringPropertyNames.Add(propertyName);
+ }
+
+ Tracer.DebugFormat("Creating reflection interceptors for Class instance {0}, Generating Properties = {1}", instance.GetType().Name, PropertyUtil.ToString(stringPropertyNames));
+ }
+
+ foreach (string key in objProperties.Keys)
+ {
+ string propertyName = this.PropertyPrefix + key;
+ PropertyInfo info = objProperties[key];
+ if (!CanReflect(info)) continue;
+ //MethodInfo propGetter = info.GetGetMethod();
+ Interceptor? reflectedInterceptor = CreateReflectedInterceptor(info);
+ if (reflectedInterceptor != null)
+ {
+ Interceptor i = (Interceptor)reflectedInterceptor;
+ ReflectedInteceptor ri = new ReflectedInteceptor()
+ {
+ ReflectedProperty = info,
+ BaseInterceptor = i,
+ };
+ result.Add(propertyName, ri);
+ }
+
+ }
+
+ return result;
+ }
+
+ #endregion
+
+ }
+
+ #endregion // end abstract reflection interception
+
+ #endregion
+
+#region Transport Property Interceptor class
+
+ internal class SecureTransportPropertyInterceptor : TransportPropertyInterceptor
+ {
+ internal const string SSL_PROTOCOLS_PROPERTY = ConnectionFactory.TransportPropertyPrefix + "SSLProtocol";
+
+ private static bool ValidateProtocolString(string protocolString, out string cleanProtocols)
+ {
+ const string COMMA = ",";
+ cleanProtocols = protocolString;
+ if (protocolString != null)
+ {
+ string trim = protocolString.Trim();
+ if(trim.StartsWith(COMMA) || trim.EndsWith(COMMA))
+ {
+ return false;
+ }
+ cleanProtocols = trim;
+ }
+ return true;
+ }
+
+ protected static Dictionary<string, Interceptor> secureTransportConextInterceptors = new Dictionary<string, Interceptor>()
+ {
+ {
+ SSL_PROTOCOLS_PROPERTY,
+ new Interceptor()
+ {
+ Getter = (context, key) =>
+ {
+ return (context as IProviderSecureTransportContext).SSLProtocol;
+ },
+ Setter = (context, key, value) =>
+ {
+ string cleanValue;
+ if(!ValidateProtocolString(value, out cleanValue))
+ {
+ throw new InvalidPropertyException(key, "Protocol string can not start or end with ','");
+ }
+ else
+ {
+ (context as IProviderSecureTransportContext).SSLProtocol = cleanValue;
+ }
+ },
+ Exists = (context) =>
+ {
+ return true;
+ },
+ Reset = (context) =>
+ {
+ (context as IProviderSecureTransportContext).SSLProtocol = null;
+ }
+ }
+
+ }
+ };
+
+
+ public SecureTransportPropertyInterceptor(IProviderSecureTransportContext context, StringDictionary props ) : base(context, props)
+ {
+
+
+ foreach(string key in secureTransportConextInterceptors.Keys)
+ {
+ this.AddInterceptor(key, secureTransportConextInterceptors[key]);
+ }
+ }
+
+ protected override bool CanReflect(PropertyInfo reflectedProperty)
+ {
+ Type TargetType = reflectedProperty.PropertyType;
+ return TargetType.IsPrimitive || TargetType.Equals(typeof(string));
+ }
+
+ }
+
+ internal class TransportPropertyInterceptor : ReflectionPropertyInterceptor<IProviderTransportContext>
+ {
+ protected static Dictionary<string, Interceptor> transportContextInterceptors = new Dictionary<string, Interceptor>()
+ {
+
+ };
+
+ public TransportPropertyInterceptor(IProviderTransportContext c, StringDictionary transportProperties) : base(c, transportProperties, transportContextInterceptors)
+ {
+
+ }
+
+ protected override string PropertyPrefix => ConnectionFactory.TransportPropertyPrefix;
+
+ protected override bool CanReflect(PropertyInfo reflectedProperty)
+ {
+ return true;
+ }
+
+ }
+
+#endregion
+
+#region ConnectionFactory Property Interceptor Class
+
+ internal class ConnectionFactoryPropertyInterceptor : PropertyInterceptor<ConnectionFactory>
+ {
+
+#region Ignore Case Comparer
+ private class IgnoreCaseComparer : IEqualityComparer
+ {
+ public new bool Equals(object x, object y)
+ {
+ if(x==null || y == null)
+ {
+ return x == null && y == null;
+ }
+ else if(!(x is string) || !(y is string))
+ {
+ return false;
+ }
+ else
+ {
+ string a = x as string;
+ string b = y as string;
+ return a.Equals(b, StringComparison.InvariantCultureIgnoreCase);
+ }
+
+ }
+
+ public int GetHashCode(object obj)
+ {
+ return obj.GetHashCode();
+ }
+ }
+
+#endregion
+
+ private readonly static IgnoreCaseComparer ComparerInstance = new IgnoreCaseComparer();
+
+ private static Amqp.ConnectionFactory.SslSettings GetSSLSettings(Amqp.IConnectionFactory cf)
+ {
+ // TODO Create Provider AMQP Implementation hook to access Amqp.IConnectionFactory implementation.
+ return ((Amqp.ConnectionFactory)cf).SSL;
+ }
+
+ private static bool IsSecureConfiguration(ConnectionFactory cf)
+ {
+ return cf.Context != null && cf.Context is IProviderSecureTransportContext;
+ }
+
+#region Interceptors
+
+ protected static Dictionary<string, Interceptor> connFactoryInterceptors = new Dictionary<string, Interceptor>()
+ {
+ // TODO Add connection porperty interceptors. eg for username, password, requesttimeout, etc.
+ {
+ ConnectionFactory.CLIENT_ID_PROP,
+ new Interceptor()
+ {
+ Getter = (cf, key) =>
+ {
+ return cf.ClientId;
+ },
+ Setter = (cf, key, value) =>
+ {
+ cf.ClientId = value;
+ },
+ Exists = (cf) =>
+ {
+ return !cf.IsClientIdSet;
+ },
+ Reset = (cf) =>
+ {
+ cf.ClientId = null;
+ }
+ }
+ }
+ };
+
+#endregion
+
+ public ConnectionFactoryPropertyInterceptor(ConnectionFactory factory, StringDictionary properties) : base(factory, properties, connFactoryInterceptors)
+ {
+
+ }
+ }
+
+#endregion
+
+#region Connnection Property Interceptor Class
+
+ public class ConnectionPropertyConstants
+ {
+ public static readonly string REQUEST_TIMEOUT = PropertyUtil.CreateProperty("RequestTimeout", "Connection");
+
+ }
+
+ internal class ConnectionPropertyInterceptor : NMSResourcePropertyInterceptor<Connection, ConnectionInfo>
+ {
+ // TODO add more properties.
+ protected static Dictionary<string, Interceptor> connInterceptors = new Dictionary<string, Interceptor>()
+ {
+ {
+ ConnectionPropertyConstants.REQUEST_TIMEOUT,
+ new Interceptor
+ {
+ Setter = (c, key, value)=>
+ {
+ c.RequestTimeout = TimeSpan.FromMilliseconds(Convert.ToInt64(value));
+ },
+ Getter = (c, key) => { return Convert.ToInt64(c.RequestTimeout.TotalMilliseconds).ToString(); }
+ }
+ },
+ };
+
+ public ConnectionPropertyInterceptor(Connection connection, StringDictionary properties) : base(connection, properties, connInterceptors)
+ {
+
+ }
+ }
+
+#endregion
+
+#region Session Property Interceptor Class
+ //TODO Implement
+#endregion
+
+#region Producer Property Interceptor Class
+ //TODO Implement
+#endregion
+
+#region Consumer Property Interceptor Class
+ //TODO Implement
+#endregion
+
+#endregion
+
+#region NMS object Property Interceptor classes IPrimitiveMap based
+
+#region Abstract Property Interceptor Class
+ internal abstract class NMSPropertyInterceptor<T> : Types.Map.PrimitiveMapBase, IPrimitiveMap
+ {
+
+#region Generic delegates and Interceptor struct
+
+ protected delegate void ApplyProperty(T instance, object value);
+ protected delegate object GetProperty(T instance);
+ protected delegate void ClearProperty(T instance);
+ protected delegate bool CheckProperty(T instance);
+
+ // The Interceptor struct is a container of operation delegates
+ // to be used on a specific property of instance T.
+ protected struct Interceptor
+ {
+ public ApplyProperty Setter;
+ public GetProperty Getter;
+ public ClearProperty Reset;
+ public CheckProperty Exists;
+ }
+
+#endregion
+
+ private readonly object SyncLock;
+ private readonly IPrimitiveMap properties;
+ private readonly IDictionary<string, Interceptor> interceptors;
+ private readonly T instance;
+ protected NMSPropertyInterceptor(T instance, IPrimitiveMap properties, IDictionary<string, Interceptor> interceptors) : base()
+ {
+ this.properties = properties ?? new Apache.NMS.Util.PrimitiveMap();
+
+ this.instance = instance;
+ if (this.properties is Types.Map.PrimitiveMapBase)
+ {
+ SyncLock = (this.properties as Types.Map.PrimitiveMapBase).SyncRoot;
+ }
+ else
+ {
+ SyncLock = new object();
+ }
+
+ this.interceptors = new Dictionary<string, Interceptor>();
+ foreach(string key in interceptors.Keys)
+ {
+ AddInterceptor(key, interceptors[key]);
+ }
+ }
+
+#region Property Interceptor Methods
+
+ protected T Instance { get { return instance; } }
+
+ protected void AddInterceptor(string key, Interceptor interceptor)
+ {
+ bool updated = false;
+ if(!interceptors.ContainsKey(key))
+ this.interceptors.Add(key, interceptor);
+ else
+ {
+ // this allows subs classes to override base classes.
+ this.interceptors[key] = interceptor;
+ updated = true;
+ }
+ if (properties.Contains(key) || updated)
+ {
+ SetProperty(key, properties[key]);
+ properties.Remove(key);
+ }
+
+ }
+
+ protected void SetProperty(string key, object value)
+ {
+ if (interceptors.ContainsKey(key))
+ {
+ interceptors[key].Setter(instance, value);
+ }
+ else
+ {
+ properties[key] = value;
+ }
+ }
+
+ protected object GetValue(string key)
+ {
+ object value = null;
+ if (interceptors.ContainsKey(key))
+ {
+ if(interceptors[key].Exists(instance))
+ value = interceptors[key].Getter(instance);
+ }
+ else
+ {
+ value = properties[key];
+ }
+ return value;
+ }
+
+#endregion
+
+#region PrimitiveMapBase abstract override methods
+
+ internal override object SyncRoot { get { return SyncLock; } }
+
+ public override bool Contains(object key)
+ {
+ bool found = properties.Contains(key);
+ if (!found && interceptors.ContainsKey(key.ToString()))
+ {
+ string keystring = key.ToString();
+ found = interceptors[keystring].Exists(instance);
+ }
+ return found;
+ }
+
+ public override void Clear()
+ {
+ properties.Clear();
+ foreach(string key in interceptors.Keys)
+ {
+ interceptors[key].Reset(instance);
+ }
+ }
+
+ protected int InterceptorCount
+ {
+ get
+ {
+ int count = 0;
+ foreach(string key in interceptors.Keys)
+ {
+ Interceptor i = interceptors[key];
+ if(i.Exists(instance))
+ {
+ count++;
+ }
+ }
+ return count;
+ }
+ }
+
+ public override int Count => this.properties.Count + InterceptorCount;
+
+ public override void Remove(object key)
+ {
+ if(properties.Contains(key))
+ properties.Remove(key);
+ else if(interceptors.ContainsKey(key.ToString()))
+ {
+ interceptors[key.ToString()].Reset(instance);
+ }
+ }
+
+ public override ICollection Keys
+ {
+ get
+ {
+ ISet<string> keys = new HashSet<string>();
+ foreach (string key in interceptors.Keys)
+ {
+ Interceptor i = interceptors[key];
+ if (i.Exists(instance))
+ {
+ keys.Add(key);
+ }
+ }
+ foreach(string key in properties.Keys)
+ {
+ keys.Add(key);
+ }
+
+ return keys.ToList();
+ }
+ }
+
+ public override ICollection Values
+ {
+ get
+ {
+ ISet<object> values = new HashSet<object>();
+ foreach (string key in interceptors.Keys)
+ {
+ Interceptor i = interceptors[key];
+ if (i.Exists(instance))
+ {
+ values.Add(i.Getter(instance));
+ }
+ }
+ foreach (object value in properties.Values)
+ {
+ values.Add(value);
+ }
+
+ return values.ToList();
+ }
+ }
+
+ protected override void SetObjectProperty(string key, object value)
+ {
+ SetProperty(key, value);
+ }
+
+ protected override object GetObjectProperty(string key)
+ {
+ return GetValue(key);
+ }
+#endregion
+
+ }
+#endregion
+
+#region Message Property Interceptor Class
+ internal class NMSMessagePropertyInterceptor : NMSPropertyInterceptor<Message.Message>
+ {
+ protected static readonly Dictionary<string, Interceptor> messageInterceptors = new Dictionary<string, Interceptor>()
+ {
+ {
+ Message.Message.MESSAGE_VENDOR_ACK_PROP,
+ new Interceptor
+ {
+ Setter = (m, value) =>
+ {
+ if(m.GetMessageCloak().AckHandler == null && m.GetMessageCloak().IsReceived)
+ {
+ throw new NMSException("Session Acknowledgement mode does not allow setting " + Message.Message.MESSAGE_VENDOR_ACK_PROP);
+ }
+ int ackType = -1;
+ try
+ {
+ ackType = Types.ConversionSupport.ConvertNMSType<int>(value);
+ }
+ catch (Types.ConversionSupport.NMSTypeConversionException ce)
+ {
+ throw ExceptionSupport.Wrap(ce, "Property {0} cannot be set from a {1}", Message.Message.MESSAGE_VENDOR_ACK_PROP, value?.GetType()?.Name);
+ }
+ if (ackType != -1)
+ m.GetMessageCloak().AckHandler.AcknowledgementType = (Message.AckType)ackType;
+
+ },
+ Getter = (m) =>
+ {
+ object acktype = null;
+ if(m.GetMessageCloak().AckHandler != null)
+ {
+ acktype = m.GetMessageCloak().AckHandler.AcknowledgementType;
+ }
+ return acktype;
+ },
+ Exists = (m) =>
+ {
+ Message.Cloak.IMessageCloak cloak = m.GetMessageCloak();
+ if (cloak.AckHandler != null)
+ {
+ return cloak.AckHandler.IsAckTypeSet;
+ }
+ return false;
+ },
+ Reset = (m) =>
+ {
+ Message.Cloak.IMessageCloak cloak = m.GetMessageCloak();
+ if (cloak.AckHandler != null)
+ {
+ cloak.AckHandler.ClearAckType();
+ }
+ }
+
+ }
+ },
+ };
+
+
+ public NMSMessagePropertyInterceptor(Message.Message instance, IPrimitiveMap properties) : base (instance, properties, messageInterceptors)
+ {
+
+ }
+ public override string ToString()
+ {
+ string result = base.ToString();
+ foreach (string key in Keys)
+ {
+ result += "\n" + key.ToString() + ": " + GetObjectProperty(key).ToString();
+ }
+ return result;
+ }
+
+ }//*/
+
+#endregion
+
+#endregion
+
+}