Improving the dynamic factory loading routine.
Fixes [AMQNET-333]. (See https://issues.apache.org/jira/browse/AMQNET-333)
diff --git a/src/main/csharp/CommonConnectionFactory.cs b/src/main/csharp/CommonConnectionFactory.cs
index c7adbf8..c19537d 100644
--- a/src/main/csharp/CommonConnectionFactory.cs
+++ b/src/main/csharp/CommonConnectionFactory.cs
@@ -17,6 +17,8 @@
using System;
using System.Reflection;
+using System.Collections;
+using System.IO;
namespace Apache.NMS.ZMQ
{
@@ -34,50 +36,14 @@
// 64-bit runtimes' ItrPtr size is 8.
static private bool is32bit = (IntPtr.Size == 4);
+ private static Assembly factoryAssembly = null;
private static Type factoryType = null;
private IConnectionFactory connFactory = null;
+ private object connectionFactoryLock = new object();
private const string DEFAULT_BROKER_URL = "tcp://localhost:5556";
private const string ENV_BROKER_URL = "ZMQ_BROKER_URL";
- /// <summary>
- /// Static class constructor that is executed only once before any normal object constructors.
- /// This is the type constructor.
- /// </summary>
- static ConnectionFactory()
- {
- // Load the assembly and get the type.
- string assemblyFileName = (is32bit ? "Apache.NMS.ZMQ32.dll" : "Apache.NMS.ZMQ64.dll");
- Assembly assembly;
-
- try
- {
- assembly = Assembly.Load(assemblyFileName);
- if(null != assembly)
- {
- Tracer.DebugFormat("Succesfully loaded provider: {0}", assemblyFileName);
- factoryType = assembly.GetType("Apache.NMS.ZMQ.ConnectionFactory", true, true);
- }
- }
- catch(Exception ex)
- {
- Tracer.ErrorFormat("Exception loading assembly {0} failed: {1}", assemblyFileName, ex.Message);
- factoryType = null;
- }
- }
-
- private static string GetDefaultBrokerUrl()
- {
- string brokerUrl = Environment.GetEnvironmentVariable(ENV_BROKER_URL);
-
- if(string.IsNullOrEmpty(brokerUrl))
- {
- brokerUrl = DEFAULT_BROKER_URL;
- }
-
- return brokerUrl;
- }
-
public ConnectionFactory()
: this(GetDefaultBrokerUrl())
{
@@ -100,12 +66,100 @@
public ConnectionFactory(Uri brokerUri, string clientID)
{
- if(null == factoryType)
+ LoadConnectionFactory();
+ connFactory = (IConnectionFactory) Activator.CreateInstance(factoryType, new object[] { brokerUri, clientID });
+ }
+
+ /// <summary>
+ /// Static class constructor that is executed only once before any normal object constructors.
+ /// This is the type constructor.
+ /// </summary>
+ private void LoadConnectionFactory()
+ {
+ lock(connectionFactoryLock)
{
- throw new ApplicationException("Could not load the ZMQ connection factory assembly.");
+ if(null == factoryType)
+ {
+ // Load the assembly and get the type.
+ string assemblyFileName = (is32bit ? "Apache.NMS.ZMQ32.dll" : "Apache.NMS.ZMQ64.dll");
+ string[] searchPaths = GetAssemblySearchPaths();
+
+ foreach(string path in searchPaths)
+ {
+ string fullFileName = Path.Combine(path, assemblyFileName);
+
+ try
+ {
+ factoryAssembly = Assembly.Load(fullFileName);
+ if(null != factoryAssembly)
+ {
+ Tracer.DebugFormat("Succesfully loaded provider: {0}", fullFileName);
+ factoryType = factoryAssembly.GetType("Apache.NMS.ZMQ.ConnectionFactory", true, true);
+ if(null != factoryType)
+ {
+ break;
+ }
+ }
+ }
+ catch(Exception ex)
+ {
+ Tracer.DebugFormat("Exception loading assembly {0} failed: {1}", fullFileName, ex.Message);
+ factoryType = null;
+ }
+ }
+
+ if(null == factoryType)
+ {
+ Tracer.ErrorFormat("Failed to load assembly {0}", assemblyFileName);
+ throw new ApplicationException(string.Format("Could not load the ZMQ connection factory assembly {0}.", assemblyFileName));
+ }
+ }
+ }
+ }
+
+ /// <summary>
+ /// Get the paths to search for the assembly file.
+ /// </summary>
+ /// <returns></returns>
+ private static string[] GetAssemblySearchPaths()
+ {
+ ArrayList pathList = new ArrayList();
+
+ // Check the current folder first.
+ pathList.Add("");
+
+ // Check the folder the assembly is located in.
+ AppDomain currentDomain = AppDomain.CurrentDomain;
+
+ pathList.Add(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
+ if(null != currentDomain.BaseDirectory)
+ {
+ pathList.Add(currentDomain.BaseDirectory);
}
- connFactory = (IConnectionFactory) Activator.CreateInstance(factoryType, new object[] { brokerUri, clientID });
+ if(null != currentDomain.RelativeSearchPath)
+ {
+ pathList.Add(currentDomain.RelativeSearchPath);
+ }
+
+ return (string[]) pathList.ToArray(typeof(string));
+ }
+
+ /// <summary>
+ /// Get the default connection Uri if none is specified.
+ /// The environment variable is checked first.
+ /// </summary>
+ /// <returns></returns>
+ private static string GetDefaultBrokerUrl()
+ {
+ string brokerUrl = Environment.GetEnvironmentVariable(ENV_BROKER_URL);
+
+ if(string.IsNullOrEmpty(brokerUrl))
+ {
+ brokerUrl = DEFAULT_BROKER_URL;
+ }
+
+ return brokerUrl;
}
#region IConnectionFactory Members
diff --git a/src/test/csharp/ZMQTest.cs b/src/test/csharp/ZMQTest.cs
index 189e248..957850d 100644
--- a/src/test/csharp/ZMQTest.cs
+++ b/src/test/csharp/ZMQTest.cs
@@ -19,6 +19,7 @@
using System.Messaging;
using NUnit.Framework;
using System.Threading;
+using System.IO;
namespace Apache.NMS.ZMQ
{
@@ -48,23 +49,17 @@
////////////////////////////
// Dependencies check
////////////////////////////
- string TmpPath;
- string TmpFilename;
- //TmpPath = System.Reflection.Assembly.GetExecutingAssembly().Location;
- TmpPath = System.Environment.CurrentDirectory;
- if(!TmpPath.EndsWith("\\"))
- {
- TmpPath += "\\";
- }
+ string libFolder = System.Environment.CurrentDirectory;
+ string libFileName;
- TmpFilename = TmpPath + "libzmq.dll";
- Assert.IsTrue(System.IO.File.Exists(TmpFilename), "Missing zmq library file: {0}", TmpFilename);
- TmpFilename = TmpPath + "clrzmq.dll";
- Assert.IsTrue(System.IO.File.Exists(TmpFilename), "Missing zmq wrapper file: {0}", TmpFilename);
- TmpFilename = TmpPath + "Apache.NMS.dll";
- Assert.IsTrue(System.IO.File.Exists(TmpFilename), "Missing Apache.NMS library file: {0}", TmpFilename);
- TmpFilename = TmpPath + "Apache.NMS.ZMQ.dll";
- Assert.IsTrue(System.IO.File.Exists(TmpFilename), "Missing Apache.NMS.ZMQ library file: {0}", TmpFilename);
+ libFileName = Path.Combine(libFolder, "libzmq.dll");
+ Assert.IsTrue(File.Exists(libFileName), "Missing zmq library file: {0}", libFileName);
+ libFileName = Path.Combine(libFolder, "clrzmq.dll");
+ Assert.IsTrue(File.Exists(libFileName), "Missing zmq wrapper file: {0}", libFileName);
+ libFileName = Path.Combine(libFolder, "Apache.NMS.dll");
+ Assert.IsTrue(File.Exists(libFileName), "Missing Apache.NMS library file: {0}", libFileName);
+ libFileName = Path.Combine(libFolder, "Apache.NMS.ZMQ.dll");
+ Assert.IsTrue(File.Exists(libFileName), "Missing Apache.NMS.ZMQ library file: {0}", libFileName);
////////////////////////////
// Factory check