Click here to Skip to main content
15,891,976 members
Articles / Hosted Services / Azure

Azure Service Bus Tester

Rate me:
Please Sign up or sign in to vote.
4.96/5 (16 votes)
27 Dec 2014CPOL28 min read 90K   2.9K   24  
This article describes the design and implementation of the small tool, tester for Windows Azure Service Bus Messaging.
//*****************************************************************************
//    Description.....Service Bus Tester
//                                
//    Author..........Roman Kiss, rkiss@pathcom.com
//    Copyright © 2011 ATZ Consulting Inc. (see included license.rtf file)         
//                        
//    Date Created:    11/11/11
//
//    Date        Modified By     Description
//-----------------------------------------------------------------------------
//    11/11/11   Roman Kiss     Initial Revision
//
//*****************************************************************************
//
#region Namespaces
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Runtime.Remoting.Messaging;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using System.Text;
using System.Threading;
using Microsoft.ServiceBus;
using Microsoft.ServiceBus.Messaging;
#endregion

namespace RKiss.Tools.ServiceBusTester
{
    #region Service activator
    // this is a service activator acrross the appDomains
    public sealed class ServiceHostActivator : MarshalByRefObject, IDisposable
    {
        DateTime _created = DateTime.Now;
        string _name = string.Empty;
        ServiceHostBase _host = null;

        #region Dispose
        void IDisposable.Dispose()
        {
            Close();
        }
        public override object InitializeLifetimeService()
        {
            // infinite lifetime
            return null;
        }
        #endregion

        #region Create
        public static ServiceHostActivator Create(AppDomain appDomain, ConsumerConfigData config)
        {
            string _assemblyName = Assembly.GetAssembly(typeof(ServiceHostActivator)).FullName;
            ServiceHostActivator activator = appDomain.CreateInstanceAndUnwrap(_assemblyName, typeof(ServiceHostActivator).ToString()) as ServiceHostActivator;
            activator.SetHost(config);
            return activator;
        }

        private void SetHost(ConsumerConfigData config)
        {
            try
            {
                if (_host == null)
                {
                    //var binding = new NetMessagingBinding();

                    // version 1.2
                    var binding = new CustomBinding();
                    if (config.ContentType.StartsWith("application/soap+xml"))
                        binding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.Soap12WSAddressing10, Encoding.UTF8));
                    else if (config.ContentType.StartsWith("text/plain"))
                        binding.Elements.Add(new TextMessageEncodingBindingElement(MessageVersion.None, Encoding.UTF8));
                    else if (config.ContentType.StartsWith("application/xml") || config.ContentType.StartsWith("application/json"))
                        binding.Elements.Add(new WebMessageEncodingBindingElement(System.Text.Encoding.UTF8));
                    
                    binding.Elements.Add(new NetMessagingTransportBindingElement());

                    var securityBehavior = new TransportClientEndpointBehavior()
                    {
                        TokenProvider = TokenProvider.CreateSharedSecretTokenProvider(config.IssuerName, config.IssuerSecret),
                    };

                    EndpointAddress ea = new EndpointAddress(config.TopicAddress);
                    var se = new ServiceEndpoint(ContractDescription.GetContract(typeof(IGenericOneWayContract)), binding, ea);
                    if(string.IsNullOrEmpty(config.SubscriptionAddress) == false)
                        se.ListenUri = new Uri(config.SubscriptionAddress);
                    if (config.RequiresSession)
                        se.Contract.SessionMode = SessionMode.Required;
                    se.Behaviors.Add(securityBehavior);

                    _host = new ServiceHost(typeof(VirtualService));
                    _host.AddServiceEndpoint(se);
                    _host.Extensions.Add(config);
                    
                    _host.Faulted += new EventHandler(_host_Faulted);
                    _host.Closed += new EventHandler(_host_Closed);
                    _host.Opened += new EventHandler(_host_Opened);
                    _name = config.Name;

                    this.AddToStorage(this);

                    Trace.WriteLine(string.Format("ServiceHostActivator: host '{0}' has been created in the appDomain '{1}, contentType={2}'", config.Name, AppDomain.CurrentDomain.FriendlyName, config.ContentType));
                }
                else
                {
                    throw new InvalidOperationException("The ServiceHost has been already setup");
                }
            }
            finally
            {
                CallContext.FreeNamedDataSlot("_config");
            }
        }
        void _host_Faulted(object sender, EventArgs e)
        {
            Trace.Write(string.Format("ServiceHostActivator.Faulted: {0}", (sender as ServiceHost).Description.Endpoints[0].Address));
        }
        void _host_Closed(object sender, EventArgs e)
        {
            Trace.Write(string.Format("ServiceHostActivator.Closed: {0}", (sender as ServiceHost).Description.Endpoints[0].Address));
        }
        void _host_Opened(object sender, EventArgs e)
        {
            Trace.Write(string.Format("ServiceHostActivator.Opened: {0}", (sender as ServiceHost).Description.Endpoints[0].Address));
        }
        private void AddToStorage(ServiceHostActivator activator)
        {
            List<ServiceHostActivator> activators = this.GetStorage();
            if (activators.Exists(delegate(ServiceHostActivator host) { return host._host.Description.ConfigurationName == activator._host.Description.ConfigurationName; }))
            {
                throw new InvalidOperationException(string.Format("The service '{0}' is already hosted in the appDomain '{1}'", activator._host.Description.ConfigurationName, AppDomain.CurrentDomain.FriendlyName));
            }
            activators.Add(this);
        }
        private void RemoveFromStorage(ServiceHostActivator activator)
        {
            List<ServiceHostActivator> activators = this.GetStorage();
            if (activators.Exists(delegate(ServiceHostActivator host) { return host._host.Description.ConfigurationName == activator._host.Description.ConfigurationName; }))
            {
                activators.Remove(activator);
            }
        }
        private List<ServiceHostActivator> GetStorage()
        {
            string key = typeof(ServiceHostActivator).FullName;
            List<ServiceHostActivator> activators = AppDomain.CurrentDomain.GetData(key) as List<ServiceHostActivator>;
            if (activators == null)
            {
                lock (AppDomain.CurrentDomain.FriendlyName)
                {
                    activators = AppDomain.CurrentDomain.GetData(key) as List<ServiceHostActivator>;
                    if (activators == null)
                    {
                        activators = new List<ServiceHostActivator>();
                        AppDomain.CurrentDomain.SetData(key, activators);
                    }
                }
            }
            return activators;
        }
        #endregion

        #region Remoting
        public void Open()
        {
            if (_host != null)
            {
                try
                {
                    if (_host.State == CommunicationState.Created)
                    {
                        _host.Open();
                        Trace.WriteLine(string.Format("ServiceHostActivator '{0}' opened", this.Name));
                    }
                }
                catch (Exception ex)
                {
                    RemoveFromStorage(this);
                    Trace.WriteLine(string.Format("Opening ServiceHostActivator '{0}' failed: '{1}'", this.Name, ex.Message));
                    throw ex;
                }
            }

        }
        public void Close()
        {
            if (_host != null)
            {
                try
                {
                    if (_host.State == CommunicationState.Opened || _host.State == CommunicationState.Created)
                    {
                        _host.Close();
                        Trace.WriteLine(string.Format("ServiceHostActivator '{0}' closed", this.Name));
                    }
                    else if (_host.State == CommunicationState.Faulted)
                    {
                        Trace.WriteLine(string.Format("ServiceHostActivator '{0}' faulted", this.Name));
                        _host.Abort();
                    }
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("Closing ServiceHostActivator '{0}' failed: '{1}'", this.Name, ex.Message));
                    throw ex;
                }
            }
        }
        public void Abort()
        {
            if (_host != null)
            {
                try
                {
                    _host.Abort();
                    Trace.WriteLine(string.Format("ServiceHostActivator '{0}' aborted", this.Name));
                }
                catch (Exception ex)
                {
                    Trace.WriteLine(string.Format("Aborting ServiceHostActivator '{0}' failed: '{1}'", this.Name, ex.Message));
                    throw ex;
                }
            }
        }
        public ServiceHostBase Host { get { return _host; } } // valid only for default domain! 
        public AppDomain AppDomainHost { get { return AppDomain.CurrentDomain; } }
        public string Name { get { return _name; } }
        public DateTime Created { get { return _created; } }
        public CommunicationState State { get { return _host.State; } }
        #endregion
    }
    #endregion

    #region HostServices
    public sealed class HostServices : IDisposable
    {
        #region Private Members
        ReaderWriterLock _rwl = new ReaderWriterLock();
        string _hostName = string.Empty;
        List<AppDomain> _appDomains = new List<AppDomain>();
        static string _key = typeof(ServiceHostActivator).FullName;
        bool _selfHosted = false;
        #endregion

        #region Constructors
        public HostServices()
            : this(false)
        {
        }
        public HostServices(bool selfHosted)
        {
            _selfHosted = selfHosted;
            Trace.WriteLine(string.Format("The HostServices '{0}' runtime has been created, selfHosted={1}", _hostName, selfHosted));
        }
        #endregion

        #region IDisposable Members
        public void Dispose()
        {
            try
            {
                _rwl.AcquireWriterLock(TimeSpan.FromSeconds(60));
                _appDomains.Clear();
            }
            finally
            {
                _rwl.ReleaseWriterLock();
            }
        }
        #endregion

        #region HostName
        public string HostName
        {
            get { return _hostName; }
        }
        #endregion

        #region Add
        public void Add(string appDomainName, ConsumerConfigData config)
        {
            try
            {
                _rwl.AcquireWriterLock(TimeSpan.FromSeconds(60));
                appDomainName = ValidateAppDomainName(appDomainName);
                AppDomain appDomain = this.CreateDomainHost(appDomainName);
                ServiceHostActivator.Create(appDomain, config);
            }
            finally
            {
                _rwl.ReleaseWriterLock();
            }
        }
     
        private AppDomain CreateDomainHost(string appDomainName)
        {
            AppDomain appDomain = _appDomains.Find(delegate(AppDomain ad) { return ad.FriendlyName == appDomainName; });
            if (appDomain == null)
            {
                appDomain = AppDomain.CurrentDomain.FriendlyName == appDomainName ? AppDomain.CurrentDomain : AppDomain.CreateDomain(appDomainName);
                _appDomains.Add(appDomain);
                Trace.WriteLine(string.Format("The AppDomain '{0}' has been created", appDomainName));

                appDomain.UnhandledException += delegate(object sender, UnhandledExceptionEventArgs e)
                {
                    Trace.WriteLine(string.Format("[{0}] UnhandledException = {1}", (sender as AppDomain).FriendlyName, e.ExceptionObject));
                };
                appDomain.DomainUnload += delegate(object sender, EventArgs e)
                {
                    Trace.WriteLine(string.Format("[{0}] DomainUnload", (sender as AppDomain).FriendlyName));
                };
                appDomain.ProcessExit += delegate(object sender, EventArgs e)
                {
                    Trace.WriteLine(string.Format("[{0}] ProcessExit", (sender as AppDomain).FriendlyName ));
                };
            }
            return appDomain;
        }
        private string ValidateAppDomainName(string appDomainName)
        {
            if (string.IsNullOrEmpty(appDomainName) || appDomainName == "*" || appDomainName.ToLower() == "default")
            {
                appDomainName = AppDomain.CurrentDomain.FriendlyName;
            }
            return appDomainName;
        }
        #endregion

        public bool IsDomainExists(string appDomainName)
        {
            try
            {
                _rwl.AcquireWriterLock(TimeSpan.FromSeconds(60));
                appDomainName = ValidateAppDomainName(appDomainName);
                AppDomain appDomain = _appDomains.Find(delegate(AppDomain ad) { return ad.FriendlyName == appDomainName; });
                return appDomain != null;
            }
            finally
            {
                _rwl.ReleaseWriterLock();
            }

        }

        #region GetAppDomainHost
        public AppDomain this[string appDomainName]
        {
            get
            {
                try
                {
                    _rwl.AcquireWriterLock(TimeSpan.FromSeconds(60));
                    appDomainName = ValidateAppDomainName(appDomainName);
                    AppDomain appDomain = _appDomains.Find(delegate(AppDomain ad) { return ad.FriendlyName == appDomainName; });
                    if (appDomain != null)
                    {
                        return appDomain;
                    }
                    else
                    {
                        throw new InvalidOperationException(string.Format("Requested appDomain '{0}' doesn't exist in the catalog", appDomainName));
                    }
                }
                finally
                {
                    _rwl.ReleaseWriterLock();
                }
            }
        }
        #endregion

        #region GetHostedServices
        public List<ServiceHostActivatorStatus> GetHostedServices
        {
            get
            {
                List<ServiceHostActivatorStatus> lists = new List<ServiceHostActivatorStatus>();
                try
                {
                    _rwl.AcquireReaderLock(TimeSpan.FromSeconds(60));
                    foreach (AppDomain appDomain in _appDomains)
                    {
                        List<ServiceHostActivator> activators = appDomain.GetData(_key) as List<ServiceHostActivator>;
                        if (activators != null)
                        {
                            foreach (ServiceHostActivator activator in activators)
                            {
                                lists.Add(new ServiceHostActivatorStatus 
                                { 
                                    Created=activator.Created,
                                    AppDomainHostName = activator.AppDomainHost.FriendlyName, 
                                    State=activator.State,
                                    Name=activator.Name,
                                    //SubscriptionAddress = activator.
                                     
                                });
                            }
                        }
                    }
                }
                finally
                {
                    _rwl.ReleaseReaderLock();
                }
                return lists;
            }
        }
        #endregion

        #region GetHostedService
        public ServiceHostBase GetHostedService(string name, bool flagRemove)
        {
            ServiceHostBase service = null;
            if (string.IsNullOrEmpty(name))
                throw new ArgumentException("Not valid service name");

            try
            {
                _rwl.AcquireReaderLock(TimeSpan.FromSeconds(60));
                foreach (AppDomain appDomain in _appDomains)
                {
                    List<ServiceHostActivator> activators = appDomain.GetData(_key) as List<ServiceHostActivator>;
                    if (activators != null)
                    {
                        ServiceHostActivator activator = activators.Find(delegate(ServiceHostActivator a) { return a.Name == name; });
                        if (activator != null)
                        {
                            service = activator.Host;
                            if (flagRemove)
                            {
                                activators.Remove(activator);
                            }
                        }
                    }
                }
            }
            finally
            {
                _rwl.ReleaseReaderLock();
            }
            return service;

        }
        #endregion

        #region Open
        public int Open()
        {
            int count = 0;
            try
            {
                _rwl.AcquireWriterLock(TimeSpan.FromSeconds(60));
                foreach (AppDomain ad in _appDomains)
                {
                    List<ServiceHostActivator> activators = ad.GetData(_key) as List<ServiceHostActivator>;
                    if (activators != null)
                    {
                        activators.ForEach(delegate(ServiceHostActivator activator)
                        {
                            activator.Open();
                        });
                    }
                }
            }
            catch (Exception ex)
            {
                throw ex;
            }
            finally
            {
                count = _appDomains.Count;
                _rwl.ReleaseWriterLock();
            }
            return count;
        }
        public void Open(string appDomainName)
        {
            try
            {
                _rwl.AcquireWriterLock(TimeSpan.FromSeconds(60));
                appDomainName = ValidateAppDomainName(appDomainName);
                AppDomain appDomain = _appDomains.Find(delegate(AppDomain ad) { return ad.FriendlyName == appDomainName; });
                if (appDomain != null)
                {
                    if (appDomain.IsDefaultAppDomain() == false)
                    {
                        List<ServiceHostActivator> activators = appDomain.GetData(_key) as List<ServiceHostActivator>;
                        if (activators != null)
                        {
                            activators.ForEach(delegate(ServiceHostActivator activator)
                            {
                                Trace.WriteLine(string.Format("Open service '{0}'",  activator.Name));
                                activator.Open();
                            });
                        }
                        Trace.WriteLine(string.Format("Open services in the AppDomain '{0}'", appDomainName));
                    }
                }
                else
                {
                    throw new InvalidOperationException(string.Format("Open '{0}' appDomain host failed - doesn't exist", appDomainName));
                }
            }
            finally
            {
                _rwl.ReleaseWriterLock();
            }
        }
        #endregion

        #region Close
        public void Close()
        {
            try
            {
                _rwl.AcquireWriterLock(TimeSpan.FromSeconds(60));
                _appDomains.Reverse();
                foreach (AppDomain ad in _appDomains)
                {
                    List<ServiceHostActivator> activators = ad.GetData(_key) as List<ServiceHostActivator>;
                    if (activators != null)
                    {
                        activators.Reverse();
                        activators.ForEach(delegate(ServiceHostActivator activator)
                        {
                            activator.Close();
                        });
                        activators.Clear();
                    }
                }

                int count = _appDomains.RemoveAll(delegate(AppDomain ad)
                {
                    if (!ad.IsDefaultAppDomain())
                    {
                        AppDomain.Unload(ad);
                    }
                    return true;
                });
                _appDomains.Clear();
            }
            finally
            {
                _rwl.ReleaseWriterLock();
            }
        }
        public void Close(string appDomainName)
        {
            this.Close(appDomainName, true);
        }
        public bool Close(string appDomainName, bool bThrow)
        {
            bool bHasBeenClosed = false;
            try
            {
                _rwl.AcquireWriterLock(TimeSpan.FromSeconds(60));

                appDomainName = ValidateAppDomainName(appDomainName);
                AppDomain appDomain = _appDomains.Find(delegate(AppDomain ad) { return ad.FriendlyName == appDomainName; });
                if (appDomain != null)
                {
                    if (appDomain.IsDefaultAppDomain() == false)
                    {

                        List<ServiceHostActivator> activators = appDomain.GetData(_key) as List<ServiceHostActivator>;
                        activators.Reverse();
                        if (activators != null)
                        {
                            activators.ForEach(delegate(ServiceHostActivator activator)
                            {
                                activator.Close();
                            });
                        }

                        // clean-up
                        activators.Clear();
                        _appDomains.Remove(appDomain);
                        AppDomain.Unload(appDomain);
                        bHasBeenClosed = true;
                    }
                    else if (bThrow)
                    {
                        throw new InvalidOperationException("The Close operation can't be processed on the default appDomain");
                    }
                }
            }
            finally
            {
                _rwl.ReleaseWriterLock();
            }
            return bHasBeenClosed;
        }
        #endregion

        #region Abort
        public bool Abort(string appDomainName, bool bThrow)
        {
            bool bHasBeenAborted = false;
            try
            {
                _rwl.AcquireWriterLock(TimeSpan.FromSeconds(60));

                appDomainName = ValidateAppDomainName(appDomainName);
                AppDomain appDomain = _appDomains.Find(delegate(AppDomain ad) { return ad.FriendlyName == appDomainName; });

                if (appDomain != null)
                {
                    if (appDomain.IsDefaultAppDomain() == false)
                    {
                        List<ServiceHostActivator> activators = appDomain.GetData(_key) as List<ServiceHostActivator>;
                        activators.Reverse();
                        if (activators != null)
                        {
                            activators.ForEach(delegate(ServiceHostActivator activator)
                            {
                                activator.Abort();
                            });
                        }

                        // clean-up
                        activators.Clear();
                        _appDomains.Remove(appDomain);
                        AppDomain.Unload(appDomain);
                        bHasBeenAborted = true;
                    }
                    else if (bThrow)
                    {
                        throw new InvalidOperationException("The Abort operation can't be processed on the default appDomain");
                    }
                }
            }
            finally
            {
                _rwl.ReleaseWriterLock();
            }
            return bHasBeenAborted;
        }
        #endregion

        #region Current
        public static HostServices Current
        {
            get
            {
                string key = typeof(HostServices).FullName;
                HostServices hostservices = AppDomain.CurrentDomain.GetData(key) as HostServices;
                if (hostservices == null)
                {
                    lock (AppDomain.CurrentDomain.FriendlyName)
                    {
                        hostservices = AppDomain.CurrentDomain.GetData(key) as HostServices;
                        if (hostservices == null)
                        {
                            hostservices = new HostServices(true);
                            AppDomain.CurrentDomain.SetData(key, hostservices);
                        }
                    }
                }
                return hostservices;
            }
        }
        #endregion
    }
    #endregion
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions