File: System\ServiceModel\Channels\MsmqUri.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------
namespace System.ServiceModel.Channels
{
    using System.Globalization;
    using System.Net;
    using System.ServiceModel;
    using System.Text;
 
    static class MsmqUri
    {
        static IAddressTranslator netMsmqAddressTranslator;
        static IAddressTranslator activeDirectoryAddressTranslator;
        static IAddressTranslator deadLetterQueueAddressTranslator;
        static IAddressTranslator srmpAddressTranslator;
        static IAddressTranslator srmpsAddressTranslator;
        static IAddressTranslator formatnameAddressTranslator;
 
        public static IAddressTranslator NetMsmqAddressTranslator
        {
            get
            {
                if (null == netMsmqAddressTranslator)
                    netMsmqAddressTranslator = new MsmqUri.NetMsmq();
                return netMsmqAddressTranslator;
            }
        }
 
        public static IAddressTranslator ActiveDirectoryAddressTranslator
        {
            get
            {
                if (null == activeDirectoryAddressTranslator)
                    activeDirectoryAddressTranslator = new MsmqUri.ActiveDirectory();
                return activeDirectoryAddressTranslator;
            }
        }
 
        public static IAddressTranslator DeadLetterQueueAddressTranslator
        {
            get
            {
                if (null == deadLetterQueueAddressTranslator)
                    deadLetterQueueAddressTranslator = new MsmqUri.Dlq();
                return deadLetterQueueAddressTranslator;
            }
        }
 
        public static IAddressTranslator SrmpAddressTranslator
        {
            get
            {
                if (null == srmpAddressTranslator)
                    srmpAddressTranslator = new MsmqUri.Srmp();
                return srmpAddressTranslator;
            }
        }
 
        public static IAddressTranslator SrmpsAddressTranslator
        {
            get
            {
                if (null == srmpsAddressTranslator)
                    srmpsAddressTranslator = new MsmqUri.SrmpSecure();
                return srmpsAddressTranslator;
            }
        }
 
        public static IAddressTranslator FormatNameAddressTranslator
        {
            get
            {
                if (null == formatnameAddressTranslator)
                    formatnameAddressTranslator = new MsmqUri.FormatName();
                return formatnameAddressTranslator;
            }
        }
 
        public static string UriToFormatNameByScheme(Uri uri)
        {
            if (uri.Scheme == NetMsmqAddressTranslator.Scheme)
            {
                return NetMsmqAddressTranslator.UriToFormatName(uri);
            }
            else if (uri.Scheme == FormatNameAddressTranslator.Scheme)
            {
                return FormatNameAddressTranslator.UriToFormatName(uri);
            }
            else
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument("uri");
            }
        }
 
        static void AppendQueueName(StringBuilder builder, string relativePath, string slash)
        {
            const string privatePart = "/private";
 
            if (relativePath.StartsWith("/private$", StringComparison.OrdinalIgnoreCase))
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new InvalidOperationException(SR.GetString(SR.MsmqWrongPrivateQueueSyntax)));
 
            if (relativePath.StartsWith(privatePart, StringComparison.OrdinalIgnoreCase))
            {
                if (privatePart.Length == relativePath.Length)
                {
                    builder.Append("private$");
                    builder.Append(slash);
                    relativePath = "/";
                }
                else if ('/' == relativePath[privatePart.Length])
                {
                    builder.Append("private$");
                    builder.Append(slash);
                    relativePath = relativePath.Substring(privatePart.Length);
                }
            }
            builder.Append(relativePath.Substring(1));
        }
 
        internal interface IAddressTranslator
        {
            string Scheme { get; }
            string UriToFormatName(Uri uri);
            Uri CreateUri(string host, string name, bool isPrivate);
        }
 
        class NetMsmq : IAddressTranslator
        {
            public string Scheme
            {
                get { return "net.msmq"; }
            }
 
            public string UriToFormatName(Uri uri)
            {
                if (null == uri)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("uri"));
                if (uri.Scheme != this.Scheme)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.MsmqInvalidScheme), "uri"));
                if (String.IsNullOrEmpty(uri.Host))
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.MsmqWrongUri));
                if (-1 != uri.Port)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.MsmqUnexpectedPort));
 
                StringBuilder builder = new StringBuilder();
                builder.Append("DIRECT=");
                if (0 == String.Compare(uri.Host, "localhost", StringComparison.OrdinalIgnoreCase))
                    builder.Append("OS:.");
                else
                {
                    IPAddress address = null;
                    if (IPAddress.TryParse(uri.Host, out address))
                        builder.Append("TCP:");
                    else
                        builder.Append("OS:");
 
                    builder.Append(uri.Host);
                }
                builder.Append("\\");
                MsmqUri.AppendQueueName(builder, Uri.UnescapeDataString(uri.PathAndQuery), "\\");
 
                return builder.ToString();
            }
 
            public Uri CreateUri(string host, string name, bool isPrivate)
            {
                string path = "/" + name;
                if (isPrivate)
                {
                    path = "/private" + path;
                }
 
                return (new UriBuilder(Scheme, host, -1, path)).Uri;
            }
        }
 
        class PathName : IAddressTranslator
        {
            public string Scheme
            {
                get { return "net.msmq"; }
            }
 
            public virtual string UriToFormatName(Uri uri)
            {
                if (null == uri)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("uri"));
                if (uri.Scheme != this.Scheme)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.MsmqInvalidScheme), "uri"));
                if (String.IsNullOrEmpty(uri.Host))
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.MsmqWrongUri));
                if (-1 != uri.Port)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.MsmqUnexpectedPort));
 
                uri = PostVerify(uri);
 
                StringBuilder builder = new StringBuilder();
                if (0 == String.Compare(uri.Host, "localhost", StringComparison.OrdinalIgnoreCase))
                    builder.Append(".");
                else
                    builder.Append(uri.Host);
 
                builder.Append("\\");
                MsmqUri.AppendQueueName(builder, Uri.UnescapeDataString(uri.PathAndQuery), "\\");
 
                return builder.ToString();
            }
 
            public Uri CreateUri(string host, string name, bool isPrivate)
            {
                string path = "/" + name;
                if (isPrivate)
                {
                    path = "/private" + path;
                }
 
                return (new UriBuilder(Scheme, host, -1, path)).Uri;
            }
 
            protected virtual Uri PostVerify(Uri uri)
            {
                return uri;
            }
        }
 
        class ActiveDirectory : PathName
        {
            public override string UriToFormatName(Uri uri)
            {
                return MsmqFormatName.FromQueuePath(base.UriToFormatName(uri));
            }
        }
 
        class Dlq : PathName
        {
            protected override Uri PostVerify(Uri uri)
            {
                if (0 == String.Compare(uri.Host, "localhost", StringComparison.OrdinalIgnoreCase))
                    return uri;
                try
                {
                    if (0 == String.Compare(DnsCache.MachineName, DnsCache.Resolve(uri).HostName, StringComparison.OrdinalIgnoreCase))
                    {
                        return new UriBuilder(Scheme, "localhost", -1, uri.PathAndQuery).Uri;
                    }
                }
                catch (EndpointNotFoundException ex)
                {
                    MsmqDiagnostics.ExpectedException(ex);
                }
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.MsmqDLQNotLocal), "uri"));
            }
        }
 
        abstract class SrmpBase : IAddressTranslator
        {
            const string msmqPart = "/msmq/";
 
            public string Scheme
            {
                get { return "net.msmq"; }
            }
 
            public string UriToFormatName(Uri uri)
            {
                if (null == uri)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("uri"));
                if (uri.Scheme != this.Scheme)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.MsmqInvalidScheme), "uri"));
                if (String.IsNullOrEmpty(uri.Host))
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgument(SR.GetString(SR.MsmqWrongUri));
 
                StringBuilder builder = new StringBuilder();
                builder.Append("DIRECT=");
                builder.Append(this.DirectScheme);
                builder.Append(uri.Host);
                if (-1 != uri.Port)
                {
                    builder.Append(":");
                    builder.Append(uri.Port.ToString(CultureInfo.InvariantCulture));
                }
 
                string relativePath = Uri.UnescapeDataString(uri.PathAndQuery);
                builder.Append(msmqPart);
                MsmqUri.AppendQueueName(builder, relativePath, "/");
 
                return builder.ToString();
            }
 
            abstract protected string DirectScheme { get; }
 
            public Uri CreateUri(string host, string name, bool isPrivate)
            {
                string path = "/" + name;
                if (isPrivate)
                {
                    path = "/private" + path;
                }
 
                return (new UriBuilder(Scheme, host, -1, path)).Uri;
            }
        }
 
        class Srmp : SrmpBase
        {
            protected override string DirectScheme
            {
                get { return "http://"; }
            }
        }
 
        class SrmpSecure : SrmpBase
        {
            protected override string DirectScheme
            {
                get { return "https://"; }
            }
        }
 
        class FormatName : IAddressTranslator
        {
            public string Scheme
            {
                get { return "msmq.formatname"; }
            }
 
            public string UriToFormatName(Uri uri)
            {
                if (null == uri)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("uri"));
                if (uri.Scheme != this.Scheme)
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.MsmqInvalidScheme), "uri"));
                return Uri.UnescapeDataString(uri.AbsoluteUri.Substring(this.Scheme.Length + 1));
            }
 
            public Uri CreateUri(string host, string name, bool isPrivate)
            {
                string path;
                if (isPrivate)
                {
                    path = "PRIVATE$\\" + name;
                }
                else
                {
                    path = name;
                }
 
                path = "DIRECT=OS:" + host + "\\" + path;
 
                return new Uri(Scheme + ":" + path);
            }
        }
    }
}