/*
* 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.Collections;
using System.IO;
namespace Apache.NMS.ZMQ
{
///
/// A Factory that will instantiate a 32-bit or 64-bit version of the provider
/// as determined by the runtime environment. This factory delegates instantiation responsibilities
/// to the real factory. This is only in place so that the correct bit-version can be loaded.
/// This factory indirection is necessary due to the low-level dependency on a 32-bit or 64-bit native DLL.
/// To avoid a DLL load failure, we have to ensure we dynamically link to the correct version.
///
public class ConnectionFactory : IConnectionFactory
{
// Checking the runtime size of an IntPtr will tell us our runtime environment.
// 32-bit runtime's IntPtr size is 4.
// 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";
public ConnectionFactory()
: this(GetDefaultBrokerUrl())
{
}
public ConnectionFactory(string brokerUri)
: this(brokerUri, null)
{
}
public ConnectionFactory(string brokerUri, string clientID)
: this(new Uri(brokerUri), clientID)
{
}
public ConnectionFactory(Uri brokerUri)
: this(brokerUri, null)
{
}
public ConnectionFactory(Uri brokerUri, string clientID)
{
LoadConnectionFactory();
connFactory = (IConnectionFactory) Activator.CreateInstance(factoryType, new object[] { brokerUri, clientID });
}
///
/// Static class constructor that is executed only once before any normal object constructors.
/// This is the type constructor.
///
private void LoadConnectionFactory()
{
lock(connectionFactoryLock)
{
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.LoadFile(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));
}
}
}
}
///
/// Get the paths to search for the assembly file.
///
///
private static string[] GetAssemblySearchPaths()
{
ArrayList pathList = new ArrayList();
// Check the current folder first.
pathList.Add(Environment.CurrentDirectory);
AppDomain currentDomain = AppDomain.CurrentDomain;
// Check the folder the assembly is located in.
pathList.Add(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location));
// Check the domain's base directory
if(!string.IsNullOrEmpty(currentDomain.BaseDirectory))
{
pathList.Add(currentDomain.BaseDirectory);
}
// Search the domain's relative paths.
if(!string.IsNullOrEmpty(currentDomain.RelativeSearchPath))
{
pathList.Add(currentDomain.RelativeSearchPath);
}
return (string[]) pathList.ToArray(typeof(string));
}
///
/// Get the default connection Uri if none is specified.
/// The environment variable is checked first.
///
///
private static string GetDefaultBrokerUrl()
{
string brokerUrl = Environment.GetEnvironmentVariable(ENV_BROKER_URL);
if(string.IsNullOrEmpty(brokerUrl))
{
brokerUrl = DEFAULT_BROKER_URL;
}
return brokerUrl;
}
#region IConnectionFactory Members
public Uri BrokerUri
{
get { return connFactory.BrokerUri; }
set { connFactory.BrokerUri = value; }
}
public ConsumerTransformerDelegate ConsumerTransformer
{
get { return connFactory.ConsumerTransformer; }
set { connFactory.ConsumerTransformer = value; }
}
public IConnection CreateConnection(string userName, string password)
{
return connFactory.CreateConnection(userName, password);
}
public IConnection CreateConnection()
{
return connFactory.CreateConnection();
}
public ProducerTransformerDelegate ProducerTransformer
{
get { return connFactory.ProducerTransformer; }
set { connFactory.ProducerTransformer = value; }
}
public IRedeliveryPolicy RedeliveryPolicy
{
get { return connFactory.RedeliveryPolicy; }
set { connFactory.RedeliveryPolicy = value; }
}
#endregion
}
}