ScopeCompiler.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / NetFx40 / System.ServiceModel.Discovery / System / ServiceModel / Discovery / ScopeCompiler.cs / 1305376 / ScopeCompiler.cs

                            //---------------------------------------------------------------- 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//---------------------------------------------------------------
namespace System.ServiceModel.Discovery
{ 
    using System;
    using System.Collections.Generic; 
    using System.Runtime; 
    using System.Text;
    using SR2 = System.ServiceModel.Discovery.SR; 

    static class ScopeCompiler
    {
        public static string[] Compile(ICollection scopes) 
        {
            if (scopes == null || scopes.Count == 0) 
            { 
                return null;
            } 

            List compiledScopes = new List();
            foreach (Uri scope in scopes)
            { 
                Compile(scope, compiledScopes);
            } 
 
            return compiledScopes.ToArray();
        } 

        public static CompiledScopeCriteria[] CompileMatchCriteria(ICollection scopes, Uri matchBy)
        {
            Fx.Assert(matchBy != null, "The matchBy must be non null."); 

            if (scopes == null || scopes.Count == 0) 
            { 
                return null;
            } 

            List compiledCriterias = new List();
            foreach (Uri scope in scopes)
            { 
                compiledCriterias.Add(CompileCriteria(scope, matchBy));
            } 
 
            return compiledCriterias.ToArray();
        } 

        public static bool IsSupportedMatchingRule(Uri matchBy)
        {
            Fx.Assert(matchBy != null, "The matchBy must be non null."); 

            return (matchBy.Equals(FindCriteria.ScopeMatchByPrefix) || 
                matchBy.Equals(FindCriteria.ScopeMatchByUuid) || 
                matchBy.Equals(FindCriteria.ScopeMatchByLdap) ||
                matchBy.Equals(FindCriteria.ScopeMatchByExact) || 
                matchBy.Equals(FindCriteria.ScopeMatchByNone));
        }

        public static bool IsMatch(CompiledScopeCriteria compiledScopeMatchCriteria, string[] compiledScopes) 
        {
            Fx.Assert(compiledScopeMatchCriteria != null, "The compiledScopeMatchCriteria must be non null."); 
            Fx.Assert(compiledScopes != null, "The compiledScopes must be non null."); 

            if (compiledScopeMatchCriteria.MatchBy == CompiledScopeCriteriaMatchBy.Exact) 
            {
                for (int i = 0; i < compiledScopes.Length; i++)
                {
                    if (string.CompareOrdinal(compiledScopes[i], compiledScopeMatchCriteria.CompiledScope) == 0) 
                    {
                        return true; 
                    } 
                }
            } 
            else if (compiledScopeMatchCriteria.MatchBy == CompiledScopeCriteriaMatchBy.StartsWith)
            {
                for (int i = 0; i < compiledScopes.Length; i++)
                { 
                    if (compiledScopes[i].StartsWith(compiledScopeMatchCriteria.CompiledScope,
                        StringComparison.Ordinal)) 
                    { 
                        return true;
                    } 
                }
            }

            return false; 
        }
 
        static void Compile(Uri scope, List compiledScopes) 
        {
            // MatchByRfc2396 can be applied to any URI 
            compiledScopes.Add(CompileForMatchByRfc2396(scope));

            // MatchByUuid can be applied to only UUIDs we treat urn:uuid:GUID same as uuid:GUID
            Guid guid; 
            if (TryGetUuidGuid(scope, out guid))
            { 
                compiledScopes.Add(CompileForMatchByUuid(guid)); 
            }
 
            // MatchByStrcmp0 can be applied to any URI
            compiledScopes.Add(CompileForMatchByStrcmp0(scope));

            // MatchByLdap can be applied to only LDAP URI 
            if (string.Compare(scope.Scheme, "ldap", StringComparison.OrdinalIgnoreCase) == 0)
            { 
                compiledScopes.Add(CompileForMatchByLdap(scope)); 
            }
        } 

        static CompiledScopeCriteria CompileCriteria(Uri scope, Uri matchBy)
        {
            string compiledScope; 
            CompiledScopeCriteriaMatchBy compiledMatchBy;
 
            if (matchBy.Equals(FindCriteria.ScopeMatchByPrefix)) 
            {
                compiledScope = CompileForMatchByRfc2396(scope); 
                compiledMatchBy = CompiledScopeCriteriaMatchBy.StartsWith;
            }
            else if (matchBy.Equals(FindCriteria.ScopeMatchByUuid))
            { 
                Guid guid;
                if (!TryGetUuidGuid(scope, out guid)) 
                { 
                    throw FxTrace.Exception.AsError(new FormatException(SR2.DiscoveryFormatInvalidScopeUuidUri(scope.ToString())));
                } 
                compiledScope = CompileForMatchByUuid(guid);
                compiledMatchBy = CompiledScopeCriteriaMatchBy.Exact;
            }
            else if (matchBy.Equals(FindCriteria.ScopeMatchByLdap)) 
            {
                if (string.Compare(scope.Scheme, "ldap", StringComparison.OrdinalIgnoreCase) != 0) 
                { 
                    throw FxTrace.Exception.AsError(new FormatException(SR2.DiscoveryFormatInvalidScopeLdapUri(scope.ToString())));
                } 
                compiledScope = CompileForMatchByLdap(scope);
                compiledMatchBy = CompiledScopeCriteriaMatchBy.StartsWith;
            }
            else if (matchBy.Equals(FindCriteria.ScopeMatchByExact)) 
            {
                compiledScope = CompileForMatchByStrcmp0(scope); 
                compiledMatchBy = CompiledScopeCriteriaMatchBy.Exact; 
            }
            else 
            {
                throw FxTrace.Exception.ArgumentOutOfRange("matchBy", matchBy,
                    SR2.DiscoveryMatchingRuleNotSupported(
                    FindCriteria.ScopeMatchByExact, 
                    FindCriteria.ScopeMatchByPrefix,
                    FindCriteria.ScopeMatchByUuid, 
                    FindCriteria.ScopeMatchByLdap)); 
            }
 
            return new CompiledScopeCriteria(compiledScope, compiledMatchBy);
        }

        static string CompileForMatchByRfc2396(Uri scope) 
        {
            StringBuilder compiledScopeBuilder = new StringBuilder(); 
 
            // Append the matching rule name, so this compiled scope can only be
            // matched for that particular matching rule. 
            compiledScopeBuilder.Append("rfc2396match::");

            //
            // Rule: Using a case-insensitive comparison, The scheme [RFC 2396] 
            //       of S1 and S2 is the same and
            // 
            string scheme = scope.GetComponents(UriComponents.Scheme, UriFormat.UriEscaped); 
            if (scheme != null)
            { 
                scheme = scheme.ToUpperInvariant();
            }
            else
            { 
                scheme = string.Empty;
            } 
            compiledScopeBuilder.Append(scheme); 
            compiledScopeBuilder.Append(":");
 
            //
            // Rule: Using a case-insensitive comparison, The authority of S1
            //       and S2 is the same and
            // 
            string authority = scope.GetComponents(UriComponents.StrongAuthority, UriFormat.UriEscaped);
            if (authority != null) 
            { 
                authority = authority.ToUpperInvariant();
            } 
            else
            {
                authority = string.Empty;
            } 
            compiledScopeBuilder.Append(authority);
            compiledScopeBuilder.Append(":"); 
 
            //
            // Rule: The path_segments of S1 is a segment-wise (not string) 
            //       prefix of the path_segments of S2 and Neither S1 nor S2
            //       contain the "." segment or the ".." segment. All other
            //       components (e.g., query and fragment) are explicitly
            //       excluded from comparison. S1 and S2 MUST be canonicalized 
            //       (e.g., unescaping escaped characters) before using this
            //       matching rule. 
            foreach (string segment in scope.Segments) 
            {
                compiledScopeBuilder.Append(ProcessUriSegment(segment)); 
            }

            return compiledScopeBuilder.ToString();
        } 

        static string ProcessUriSegment(string segment) 
        { 
            // ignore the segment parameters, if any
            int index = segment.IndexOf(';'); 
            if (index != -1)
            {
                segment = segment.Substring(0, index);
            } 

            // prevent the comparision of partial segments 
            // Note: this matching rule does NOT test whether the string 
            // representation of S1 is a prefix of the string representation
            // of S2. For example, "http://example.com/abc" matches 
            // "http://example.com/abc/def" using this rule but
            // "http://example.com/a" does not.
            if (!segment.EndsWith("/", StringComparison.Ordinal))
            { 
                segment = segment + "/";
            } 
 
            return segment;
        } 

        static bool TryGetUuidGuid(Uri scope, out Guid guid)
        {
            string guidString = null; 
            if (string.Compare(scope.Scheme, "uuid", StringComparison.OrdinalIgnoreCase) == 0)
            { 
                guidString = scope.GetComponents(UriComponents.Path, UriFormat.UriEscaped); 
            }
            else if (string.Compare(scope.Scheme, "urn", StringComparison.OrdinalIgnoreCase) == 0) 
            {
                string scopeString = scope.ToString();
                if (string.Compare(scopeString, 4, "uuid:", 0, 5, StringComparison.OrdinalIgnoreCase) == 0)
                { 
                    guidString = scopeString.Substring(9);
                } 
            } 

            return Fx.TryCreateGuid(guidString, out guid); 
        }

        static string CompileForMatchByUuid(Guid guid)
        { 
            // Append the matching rule name, so this compiled scope can only be
            // matched for that particular matching rule. 
            // 
            // Rule: Using a case-insensitive comparison, the scheme of S1 and
            //      S2 is "uuid" and each of the unsigned integer fields [UUID] 
            //      in S1 is equal to the corresponding field in S2, or
            //      equivalently, the 128 bits of the in-memory representation
            //      of S1 and S2 are the same 128 bit unsigned integer.
            return "uuidmatch::" + guid.ToString(); 
        }
 
        static string CompileForMatchByStrcmp0(Uri scope) 
        {
            // 
            // Rule: Using a case-sensitive comparison, the string
            //      representation of S1 and S2 is the same.
            //
            return "strcmp0match::" + scope.ToString(); 
        }
 
        static string CompileForMatchByLdap(Uri scope) 
        {
            StringBuilder compiledScopeBuilder = new StringBuilder(); 

            // Append the matching rule name, so this compiled scope can only be
            // matched for that particular matching rule.
            compiledScopeBuilder.Append("ldapmatch::"); 

            // 
            // Rule: Using a case-insensitive comparison, the scheme of S1 
            // and S2 is "ldap" and
            compiledScopeBuilder.Append("ldap:"); 

            //
            // Rule: and the hostport [RFC 2255] of S1 and S2 is the
            //       same and 
            //
            string hostport = scope.GetComponents(UriComponents.HostAndPort, UriFormat.UriEscaped); 
            if (hostport != null) 
            {
                hostport = hostport.ToUpperInvariant(); 
            }
            else
            {
                hostport = string.Empty; 
            }
            compiledScopeBuilder.Append(hostport); 
            compiledScopeBuilder.Append(":"); 

 
            //
            // Rule: and the RDNSequence [RFC 2253] of the dn of S1 is a
            //       prefix of the RDNSequence of the dn of S2, where comparison
            //       does not support the variants in an RDNSequence described 
            //       in Section 4 of RFC 2253 [RFC 2253].
            // 
            // get the ldap DN string. 
            string dn = scope.GetComponents(UriComponents.Path, UriFormat.Unescaped);
 
            // parse the RDNs in order from DN
            compiledScopeBuilder.Append(ParseLdapRDNSequence(dn));

            return compiledScopeBuilder.ToString(); 
        }
 
        static string ParseLdapRDNSequence(string dn) 
        {
            // Assuming the conversion of DN to string as per Section 2 RFC2253 
            // ignoring the variations described in section 4.

            StringBuilder rdnSequenceBuilder = new StringBuilder();
            string[] tokens = dn.Split(','); 
            StringBuilder rdnBuilder = new StringBuilder();
            foreach (string token in tokens) 
            { 
                if (string.IsNullOrEmpty(token.Trim()))
                { 
                    continue;
                }

                if (token.EndsWith("\\", StringComparison.Ordinal)) 
                {
                    // it is part of the RDN 
                    rdnBuilder.Append(token.Substring(0, token.Length - 1)); 
                    rdnBuilder.Append(',');
                } 
                else
                {
                    // RDN ends here.
                    rdnBuilder.Append(token); 
                    rdnSequenceBuilder.Insert(0, "/");
                    rdnSequenceBuilder.Insert(0, ParseAndSortRDNAttributes(rdnBuilder.ToString())); 
                    rdnBuilder = new StringBuilder(); 
                }
            } 

            return rdnSequenceBuilder.ToString();
        }
 
        static string ParseAndSortRDNAttributes(string rdn)
        { 
            // 
            // Rule: RFC2253 Section 2:
            //       When converting from an ASN.1 RelativeDistinguishedName 
            //       to a string, the output consists of the string encodings
            //       of each AttributeTypeAndValue (according to 2.3), in any
            //       order. Where there is a multi-valued RDN, the outputs
            //       from adjoining AttributeTypeAndValues are separated by 
            //       a plus ('+' ASCII 43) character.
            // 
 
            // since the RDN attributes can be converted to string in any order
            // we must make sure that the compiled form of the scope and match 
            // criteria have the same order so that simple string prefix
            // comparision produces the same result of comparing the RDN
            // attribute values individually, we sort the attributes or RDN
            // based on their name. 

            // optimize the case where there is only one attrvalue for RDN 
            if (rdn.IndexOf('+') == -1) 
            {
                return rdn; 
            }

            string[] tokens = rdn.Split('+');
            StringBuilder attrTypeAndValueBuilder = new StringBuilder(); 
            Dictionary attrTypeValueTable = new Dictionary();
            List attrTypeList = new List(); 
 
            foreach (string token in tokens)
            { 
                if (string.IsNullOrEmpty(token.Trim()))
                {
                    continue;
                } 

                if (token.EndsWith("\\", StringComparison.Ordinal)) 
                { 
                    // it is part of the attribute value
                    attrTypeAndValueBuilder.Append(token.Substring(0, token.Length - 1)); 
                    attrTypeAndValueBuilder.Append('+');
                }
                else
                { 
                    // attribute value ends here.
                    attrTypeAndValueBuilder.Append(token); 
 
                    // get attribute and value.
                    string attrTypeAndValue = attrTypeAndValueBuilder.ToString(); 
                    string attrType = attrTypeAndValue;
                    string attrValue = null;

                    int equalIndex = attrTypeAndValue.IndexOf('='); 
                    if (equalIndex != -1)
                    { 
                        attrType = attrTypeAndValue.Substring(0, equalIndex); 
                        attrValue = attrTypeAndValue.Substring(equalIndex + 1);
                    } 

                    attrTypeList.Add(attrType);
                    attrTypeValueTable.Add(attrType, attrValue);
                    attrTypeAndValueBuilder = new StringBuilder(); 
                }
            } 
 
            // sort the list based on the attribute type
            attrTypeList.Sort(); 

            // created the RDN from the sorted attribute values.
            StringBuilder rdnBuilder = new StringBuilder();
            for (int i = 0; i < attrTypeList.Count - 1; i++) 
            {
                rdnBuilder.Append(attrTypeList[i]); 
                if (attrTypeValueTable[attrTypeList[i]] != null) 
                {
                    rdnBuilder.Append("="); 
                    rdnBuilder.Append(attrTypeValueTable[attrTypeList[i]]);
                }
                rdnBuilder.Append("+");
            } 

            if (attrTypeList.Count > 1) 
            { 
                rdnBuilder.Append(attrTypeList[attrTypeList.Count - 1]);
                if (attrTypeValueTable[attrTypeList[attrTypeList.Count - 1]] != null) 
                {
                    rdnBuilder.Append("=");
                    rdnBuilder.Append(attrTypeValueTable[attrTypeList[attrTypeList.Count - 1]]);
                } 
                rdnBuilder.Append("+");
            } 
 
            return rdnBuilder.ToString();
        } 
    }
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK