You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by df...@apache.org on 2021/04/09 20:12:36 UTC
[activemq-nms-ems] 02/06: Add calls to TIBCO API to turn on
failover mode. Add support for URL parameters:
connection.ExceptionOnFTEvents connection.ExceptionOnFTSwitch
connection.ConnAttemptCount connection.ConnAttemptDelay
connection.ConnAttemptTimeout connection.ReconnAttemptCount
connection.ReconnAttemptDelay connection.ReconnAttemptTimeout
This is an automated email from the ASF dual-hosted git repository.
dfoulks pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/activemq-nms-ems.git
commit ccdf3177fa6919060d5f87d0e6def360c2731ea8
Author: Jim Gomes <jg...@apache.org>
AuthorDate: Fri Sep 25 23:18:10 2015 +0000
Add calls to TIBCO API to turn on failover mode.
Add support for URL parameters:
connection.ExceptionOnFTEvents
connection.ExceptionOnFTSwitch
connection.ConnAttemptCount
connection.ConnAttemptDelay
connection.ConnAttemptTimeout
connection.ReconnAttemptCount
connection.ReconnAttemptDelay
connection.ReconnAttemptTimeout
Fixes [AMQNET-511]. (See https://issues.apache.org/jira/browse/AMQNET-511)
---
src/main/csharp/ConnectionFactory.cs | 145 ++++++++++++++++++++++---
src/main/csharp/IntrospectionSupport.cs | 182 ++++++++++++++++++++++++++++++++
vs2008-ems.csproj | 1 +
3 files changed, 311 insertions(+), 17 deletions(-)
diff --git a/src/main/csharp/ConnectionFactory.cs b/src/main/csharp/ConnectionFactory.cs
index 7cd3c1d..ba5959c 100644
--- a/src/main/csharp/ConnectionFactory.cs
+++ b/src/main/csharp/ConnectionFactory.cs
@@ -17,7 +17,10 @@
using System;
using System.Collections;
+using System.Collections.Specialized;
+using Apache.NMS.EMS.Util;
using Apache.NMS.Policies;
+using Apache.NMS.Util;
namespace Apache.NMS.EMS
{
@@ -30,6 +33,14 @@ namespace Apache.NMS.EMS
private Uri brokerUri;
private string clientId;
private Hashtable properties;
+ private bool exceptionOnFTEvents = true;
+ private bool exceptionOnFTSwitch = true;
+ private int connAttemptCount = Int32.MaxValue; // Infinite
+ private int connAttemptDelay = 30000; // 30 seconds
+ private int connAttemptTimeout = 5000; // 5 seconds
+ private int reconnAttemptCount = Int32.MaxValue; // Infinite
+ private int reconnAttemptDelay = 30000; // 30 seconds
+ private int reconnAttemptTimeout = 5000; // 5 seconds
private IRedeliveryPolicy redeliveryPolicy = new RedeliveryPolicy();
@@ -38,6 +49,7 @@ namespace Apache.NMS.EMS
try
{
this.tibcoConnectionFactory = new TIBCO.EMS.ConnectionFactory();
+ ConfigureConnectionFactory();
}
catch(Exception ex)
{
@@ -77,10 +89,11 @@ namespace Apache.NMS.EMS
{
try
{
- this.tibcoConnectionFactory = new TIBCO.EMS.ConnectionFactory(serverUrl.AbsolutePath, clientId, properties);
- this.brokerUri = serverUrl;
+ this.brokerUri = ParseUriProperties(serverUrl);
+ this.tibcoConnectionFactory = new TIBCO.EMS.ConnectionFactory(TrimParens(this.brokerUri.AbsolutePath), clientId, properties);
this.clientId = clientId;
this.properties = properties;
+ ConfigureConnectionFactory();
}
catch(Exception ex)
{
@@ -91,6 +104,22 @@ namespace Apache.NMS.EMS
VerifyConnectionFactory();
}
+ private void ConfigureConnectionFactory()
+ {
+ TIBCO.EMS.Tibems.SetExceptionOnFTEvents(this.ExceptionOnFTEvents);
+ TIBCO.EMS.Tibems.SetExceptionOnFTSwitch(this.ExceptionOnFTSwitch);
+
+ // Set the initial connection retry settings.
+ this.tibcoConnectionFactory.SetConnAttemptCount(this.ConnAttemptCount);
+ this.tibcoConnectionFactory.SetConnAttemptDelay(this.ConnAttemptDelay);
+ this.tibcoConnectionFactory.SetConnAttemptTimeout(this.ConnAttemptTimeout);
+
+ // Set the failover reconnect retry settings
+ this.tibcoConnectionFactory.SetReconnAttemptCount(this.ReconnAttemptCount);
+ this.tibcoConnectionFactory.SetReconnAttemptDelay(this.ReconnAttemptDelay);
+ this.tibcoConnectionFactory.SetReconnAttemptTimeout(this.ReconnAttemptTimeout);
+ }
+
private void VerifyConnectionFactory()
{
if(null == this.tibcoConnectionFactory)
@@ -99,6 +128,58 @@ namespace Apache.NMS.EMS
}
}
+ #region Connection Factory Properties (configure via URL parameters)
+
+ public bool ExceptionOnFTEvents
+ {
+ get { return this.exceptionOnFTEvents; }
+ set { this.exceptionOnFTEvents = value; }
+ }
+
+ public bool ExceptionOnFTSwitch
+ {
+ get { return this.exceptionOnFTSwitch; }
+ set { this.exceptionOnFTSwitch = value; }
+ }
+
+ public int ConnAttemptCount
+ {
+ get { return this.connAttemptCount; }
+ set { this.connAttemptCount = value; }
+ }
+
+ public int ConnAttemptDelay
+ {
+ get { return this.connAttemptDelay; }
+ set { this.connAttemptDelay = value; }
+ }
+
+ public int ConnAttemptTimeout
+ {
+ get { return this.connAttemptTimeout; }
+ set { this.connAttemptTimeout = value; }
+ }
+
+ public int ReconnAttemptCount
+ {
+ get { return this.reconnAttemptCount; }
+ set { this.reconnAttemptCount = value; }
+ }
+
+ public int ReconnAttemptDelay
+ {
+ get { return this.reconnAttemptDelay; }
+ set { this.reconnAttemptDelay = value; }
+ }
+
+ public int ReconnAttemptTimeout
+ {
+ get { return this.reconnAttemptTimeout; }
+ set { this.reconnAttemptTimeout = value; }
+ }
+
+ #endregion
+
#region IConnectionFactory Members
/// <summary>
@@ -162,33 +243,32 @@ namespace Apache.NMS.EMS
{
try
{
- if(null == this.brokerUri || !this.brokerUri.Equals(value))
+ // Create or Re-create the TIBCO connection factory.
+ this.brokerUri = ParseUriProperties(value);
+ if(null == this.brokerUri)
+ {
+ this.tibcoConnectionFactory = new TIBCO.EMS.ConnectionFactory();
+ }
+ else
{
- // Re-create the TIBCO connection factory.
- this.brokerUri = value;
- if(null == this.brokerUri)
+ if(null == this.clientId)
{
- this.tibcoConnectionFactory = new TIBCO.EMS.ConnectionFactory();
+ this.tibcoConnectionFactory = new TIBCO.EMS.ConnectionFactory(TrimParens(this.brokerUri.AbsolutePath));
}
else
{
- if(null == this.clientId)
+ if(null == this.properties)
{
- this.tibcoConnectionFactory = new TIBCO.EMS.ConnectionFactory(this.brokerUri.OriginalString);
+ this.tibcoConnectionFactory = new TIBCO.EMS.ConnectionFactory(TrimParens(this.brokerUri.AbsolutePath), this.clientId);
}
else
{
- if(null == this.properties)
- {
- this.tibcoConnectionFactory = new TIBCO.EMS.ConnectionFactory(this.brokerUri.OriginalString, this.clientId);
- }
- else
- {
- this.tibcoConnectionFactory = new TIBCO.EMS.ConnectionFactory(this.brokerUri.OriginalString, this.clientId, this.properties);
- }
+ this.tibcoConnectionFactory = new TIBCO.EMS.ConnectionFactory(TrimParens(this.brokerUri.AbsolutePath), this.clientId, this.properties);
}
}
}
+
+ ConfigureConnectionFactory();
}
catch(Exception ex)
{
@@ -197,6 +277,37 @@ namespace Apache.NMS.EMS
}
}
+ private Uri ParseUriProperties(Uri rawUri)
+ {
+ Tracer.InfoFormat("BrokerUri set = {0}", rawUri.OriginalString);
+ Uri parsedUri = rawUri;
+
+ if(!String.IsNullOrEmpty(rawUri.Query) && !rawUri.OriginalString.EndsWith(")"))
+ {
+ parsedUri = new Uri(rawUri.OriginalString);
+ // Since the Uri class will return the end of a Query string found in a Composite
+ // URI we must ensure that we trim that off before we proceed.
+ string query = parsedUri.Query.Substring(parsedUri.Query.LastIndexOf(")") + 1);
+
+ StringDictionary properties = URISupport.ParseQuery(query);
+
+ StringDictionary connection = URISupport.ExtractProperties(properties, "connection.");
+ StringDictionary nms = URISupport.ExtractProperties(properties, "nms.");
+
+ IntrospectionSupport.SetProperties(this, connection, "connection.");
+ IntrospectionSupport.SetProperties(this, nms, "nms.");
+
+ parsedUri = URISupport.CreateRemainingUri(parsedUri, properties);
+ }
+
+ return parsedUri;
+ }
+
+ private string TrimParens(string stringWithParens)
+ {
+ return stringWithParens.TrimStart('(').TrimEnd(')');
+ }
+
/// <summary>
/// Get/or set the redelivery policy that new IConnection objects are
/// assigned upon creation.
diff --git a/src/main/csharp/IntrospectionSupport.cs b/src/main/csharp/IntrospectionSupport.cs
new file mode 100644
index 0000000..2077901
--- /dev/null
+++ b/src/main/csharp/IntrospectionSupport.cs
@@ -0,0 +1,182 @@
+/*
+ * 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.EMS.Util
+{
+ /// <summary>
+ /// Utility class used to provide conveince methods that apply named property
+ /// settings to objects.
+ /// </summary>
+ public class IntrospectionSupport
+ {
+ /// <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">The object whose properties will be set.</param>
+ /// <param name="map">Map of key/value pairs.</param>
+ public static void SetProperties(object target, StringDictionary map)
+ {
+ SetProperties(target, map, "");
+ }
+
+ /// <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">The object whose properties will be set.</param>
+ /// <param name="map">Map of key/value pairs.</param>
+ /// <param name="prefix">Key value prefix. This is prepended to the property name
+ /// before searching for a matching key value.</param>
+ public static void SetProperties(object target, StringDictionary map, string prefix)
+ {
+ Tracer.DebugFormat("SetProperties called with target: {0}, and prefix: {1}",
+ target.GetType().Name, prefix);
+
+ foreach(string key in map.Keys)
+ {
+ if(key.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase))
+ {
+ string propertyName = key.Substring(prefix.Length);
+
+ // Process all member assignments at this level before processing
+ // any deeper member assignments.
+ if(!propertyName.Contains("."))
+ {
+ MemberInfo member = FindPropertyInfo(target, propertyName);
+
+ if(member == null)
+ {
+ throw new NMSException(string.Format("No such property or field: {0} on class: {1}", propertyName, target.GetType().Name));
+ }
+
+ try
+ {
+ if(member.MemberType == MemberTypes.Property)
+ {
+ PropertyInfo property = member as PropertyInfo;
+ property.SetValue(target, Convert.ChangeType(map[key], property.PropertyType, CultureInfo.InvariantCulture), null);
+ }
+ else
+ {
+ FieldInfo field = member as FieldInfo;
+ field.SetValue(target, Convert.ChangeType(map[key], field.FieldType, CultureInfo.InvariantCulture));
+ }
+ }
+ catch(Exception ex)
+ {
+ throw NMSExceptionSupport.Create("Error while attempting to apply option.", ex);
+ }
+ }
+ }
+ }
+
+ IList<string> propertiesSet = new List<string>();
+
+ // Now process any compound assignments, ensuring that once we recurse into an
+ // object we don't do it again as there could be multiple compunds element assignments
+ // and they'd have already been processed recursively.
+ foreach(string key in map.Keys)
+ {
+ if(key.StartsWith(prefix, StringComparison.InvariantCultureIgnoreCase))
+ {
+ string propertyName = key.Substring(prefix.Length);
+
+ if(propertyName.Contains("."))
+ {
+ string newTargetName = propertyName.Substring(0, propertyName.IndexOf('.'));
+ string newPrefix = prefix + newTargetName + ".";
+
+ if(!propertiesSet.Contains(newPrefix))
+ {
+ MemberInfo member = FindPropertyInfo(target, newTargetName);
+ object newTarget = GetUnderlyingObject(member, target);
+ SetProperties(newTarget, map, newPrefix);
+ propertiesSet.Add(newPrefix);
+ }
+ }
+ }
+ }
+ }
+
+ 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("The field given is a priomitive type: " + member.Name);
+ }
+
+ result = field.GetValue(target);
+ }
+ else
+ {
+ PropertyInfo property = member as PropertyInfo;
+ MethodInfo getter = property.GetGetMethod();
+
+ if(getter == null)
+ {
+ throw new NMSException("Cannot access member: " + 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;
+ }
+
+ private static MemberInfo FindPropertyInfo(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;
+ }
+
+ }
+}
diff --git a/vs2008-ems.csproj b/vs2008-ems.csproj
index c21fa3f..baebf54 100644
--- a/vs2008-ems.csproj
+++ b/vs2008-ems.csproj
@@ -74,6 +74,7 @@
<Compile Include="src\main\csharp\ConnectionFactory.cs" />
<Compile Include="src\main\csharp\ConnectionMetaData.cs" />
<Compile Include="src\main\csharp\ExceptionUtil.cs" />
+ <Compile Include="src\main\csharp\IntrospectionSupport.cs" />
<Compile Include="src\main\csharp\StreamMessage.cs" />
<Compile Include="src\main\csharp\QueueBrowser.cs" />
<Compile Include="src\main\csharp\Destination.cs" />