ServiceParser.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / System.ServiceModel.Activation / System / ServiceModel / Activation / ServiceParser.cs / 1305376 / ServiceParser.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.ServiceModel.Activation 
{
    using System.CodeDom; 
    using System.CodeDom.Compiler; 
    using System.Collections;
    using System.Collections.Specialized; 
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Globalization;
    using System.IO; 
    using System.Reflection;
    using System.Text.RegularExpressions; 
    using System.Web; 
    using System.Web.Hosting;
    using System.Web.Compilation; 
    using System.Web.RegularExpressions;
    using System.ServiceModel.Activation.Diagnostics;
    using System.Security;
    using System.Runtime.Diagnostics; 

    ///  
    /// This class will parse the .svc file and maintains a list of useful information that the build 
    /// provider needs in order to compile the file. The parser creates a list of dependent assemblies,
    /// understands the compiler that we need to use, fully parses all the supported directives etc. 
    /// 
    /// 
    /// The class is not thread-safe.
    ///  
#pragma warning disable 618 // have not moved to the v4 security model yet
    [SecurityCritical(SecurityCriticalScope.Everything)] 
#pragma warning restore 618 
    class ServiceParser
    { 
        // the delimiter for the compiled custom string
        const string Delimiter = ServiceHostingEnvironment.ServiceParserDelimiter;

        // attribute names 
        const string DefaultDirectiveName = "ServiceHost";
        const string FactoryAttributeName = "Factory"; 
        const string ServiceAttributeName = "Service"; 

        // regular exression for the directive 
        readonly static SimpleDirectiveRegex directiveRegex = new SimpleDirectiveRegex();

        // the build provider we will work with
        ServiceBuildProvider buildProvider; 

        // text for the file 
        string serviceText; 

        // the class attribute value 
        string factoryAttributeValue = string.Empty;

        // the constructorstring
        string serviceAttributeValue = string.Empty; 

        // the line number in file currently being parsed 
        int lineNumber; 

        // the column number in file currently being parsed 
        int startColumn;

        // the main directive was found or not
        bool foundMainDirective; 

        // the type of the compiler (i.e C#) 
        CompilerType compilerType; 

        // the string containing the code to be compiled, 
        // it will be null when all the code is "behind"
        string sourceString;

        // assemblies to be linked with, we need a unique list 
        // of them and we maintain a Dictionary for it.
        HybridDictionary linkedAssemblies; 
 
        // the set of assemblies that the build system is
        // telling us we will be linked with. There is no unique 
        // requirement for them.
        ICollection referencedAssemblies;

        // used to figure out where the new lines start 
        static char[] newlineChars = new char[] { '\r', '\n' };
 
        // source file dependencies 
        HybridDictionary sourceDependencies;
 
        // virtual path for the file that we are parsing
        string virtualPath;

        ///  
        /// The Contructor needs the path to the file that it will parse and a reference to
        /// the build provider that we are using. This is necessary because there are things that 
        /// need to be set on the build provider directly as we are parsing... 
        /// 
        internal ServiceParser(string virtualPath, ServiceBuildProvider buildProvider) 
        {
            if (DiagnosticUtility.ShouldTraceInformation)
            {
                TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.WebHostCompilation, SR.TraceCodeWebHostCompilation, 
                    new StringTraceRecord("VirtualPath", virtualPath), this, (Exception)null);
            } 
 
            this.virtualPath = virtualPath;
            this.buildProvider = buildProvider; 
        }

        /// 
        /// Constructor that is used when the whole svc file content is provided. This is the case 
        /// when the COM+ Admin tool calls into it.
        ///  
        ServiceParser(string serviceText) 
        {
            this.serviceText = serviceText; 
            this.buildProvider = new ServiceBuildProvider();
        }

        ///  
        /// Parsing the content of the service file and retrieve the serviceAttributeValue attribute for ComPlus.
        ///  
        /// The content of the service file. 
        /// The "serviceAttributeValue" attribute of the Service directive. 
        ///  
        internal static IDictionary ParseServiceDirective(string serviceText)
        {
            ServiceParser parser = new ServiceParser(serviceText);
            parser.ParseString(); 

            // the list of valid attributes for ComPlus for Service Directive 
            IDictionary attributeTable = new Dictionary( 
                StringComparer.OrdinalIgnoreCase);
 
            if (!string.IsNullOrEmpty(parser.factoryAttributeValue))
                attributeTable.Add(FactoryAttributeName, parser.factoryAttributeValue);

            if (!string.IsNullOrEmpty(parser.serviceAttributeValue)) 
                attributeTable.Add(ServiceAttributeName, parser.serviceAttributeValue);
 
            return attributeTable; 
        }
 
        /// 
        /// 

        // various getters for private objects that the build 
        // provider will need
        // 
        internal CompilerType CompilerType 
        {
            get 
            {
                return compilerType;
            }
        } 

        internal ICollection AssemblyDependencies 
        { 
            get
            { 
                if (linkedAssemblies == null)
                {
                    return null;
                } 

                return linkedAssemblies.Keys; 
            } 
        }
 
        internal ICollection SourceDependencies
        {
            get
            { 
                if (sourceDependencies == null)
                { 
                    return null; 
                }
 
                return sourceDependencies.Keys;
            }
        }
 
        internal bool HasInlineCode
        { 
            get 
            {
                return (sourceString != null); 
            }
        }

        ///  
        /// Parses the code file appropriately. This method is used by the
        /// build provider. 
        ///  
        internal void Parse(ICollection referencedAssemblies)
        { 
            if (referencedAssemblies == null)
            {
                throw FxTrace.Exception.ArgumentNull("referencedAssemblies");
            } 

            this.referencedAssemblies = referencedAssemblies; 
            AddSourceDependency(virtualPath); 

            using (TextReader reader = buildProvider.OpenReaderInternal()) 
            {
                this.serviceText = reader.ReadToEnd();
                ParseString();
            } 
        }
 
        ///  
        /// This method returns a code compile unit that will be added
        /// to the other depdnecies in order to compile 
        /// 
        internal CodeCompileUnit GetCodeModel()
        {
            // Do we have something to compile? 
            //
            if (sourceString == null || sourceString.Length == 0) 
                return null; 

            CodeSnippetCompileUnit snippetCompileUnit = new CodeSnippetCompileUnit(sourceString); 

            // Put in some context so that the file can be debugged.
            //
            string pragmaFile = HostingEnvironmentWrapper.MapPath(virtualPath); 
            snippetCompileUnit.LinePragma = new CodeLinePragma(pragmaFile, lineNumber);
 
            return snippetCompileUnit; 
        }
 
        Exception CreateParseException(string message, string sourceCode)
        {
            return CreateParseException(message, null, sourceCode);
        } 

        Exception CreateParseException(Exception innerException, string sourceCode) 
        { 
            return CreateParseException(innerException.Message, innerException, sourceCode);
        } 

        Exception CreateParseException(string message, Exception innerException, string sourceCode)
        {
            return new HttpParseException(message, innerException, this.virtualPath, sourceCode, this.lineNumber); 
        }
 
        ///  
        /// This method returns the custom string that is to be passed to ServiceHostingEnvironment from BuildManager.
        ///  
        /// The full name of the built assembly for inline code.
        internal string CreateParseString(Assembly compiledAssembly)
        {
            Type typeToPreserve = this.GetCompiledType(compiledAssembly); 
            string typeToPreserveName = string.Empty;
            if (typeToPreserve != null) 
                typeToPreserveName = typeToPreserve.AssemblyQualifiedName; 

            System.Text.StringBuilder builder = new System.Text.StringBuilder(); 
            if (compiledAssembly != null)
            {
                builder.Append(Delimiter);
                builder.Append(compiledAssembly.FullName); 
            }
 
            if (this.referencedAssemblies != null) 
            {
                foreach (Assembly assembly in this.referencedAssemblies) 
                {
                    builder.Append(Delimiter);
                    builder.Append(assembly.FullName);
                } 
            }
 
            if (this.AssemblyDependencies != null) 
            {
                foreach (Assembly assembly in this.AssemblyDependencies) 
                {
                    builder.Append(Delimiter);
                    builder.Append(assembly.FullName);
                } 
            }
            // use application relative virtualpath instead of the absolute path 
            // so that the compliedcustomstring is applicationame independent 
            return string.Concat(VirtualPathUtility.ToAppRelative(virtualPath), Delimiter,
                typeToPreserveName, Delimiter, 
                serviceAttributeValue, builder.ToString());
        }

        void AddSourceDependency(string fileName) 
        {
            if (sourceDependencies == null) 
                sourceDependencies = new HybridDictionary(true); 

            sourceDependencies.Add(fileName, fileName); 
        }

        Type GetCompiledType(Assembly compiledAssembly)
        { 
            if (string.IsNullOrEmpty(factoryAttributeValue))
            { 
                return null; 
            }
 
            Type type = null;

            // First, try to get the type from the assembly that has been built (if any)
            if (this.HasInlineCode && (compiledAssembly != null)) 
            {
                type = compiledAssembly.GetType(factoryAttributeValue); 
            } 

            // If not, try to get it from other assemblies 
            if (type == null)
            {
                type = GetType(factoryAttributeValue);
            } 

            return type; 
        } 

        internal IDictionary GetLinePragmasTable() 
        {
            LinePragmaCodeInfo info = new LinePragmaCodeInfo(this.lineNumber, this.startColumn, 1, -1, false);
            IDictionary dictionary = new Hashtable();
            dictionary[this.lineNumber] = info; 
            return dictionary;
        } 
 
        /// 
        /// Parses the content of the svc file for each directive line 
        /// 
        void ParseString()
        {
            try 
            {
                int textPos = 0; 
                Match match; 
                lineNumber = 1;
 
                // Check for ending bracket first, MB 45013.
                if(this.serviceText.IndexOf('>') == -1)
                {
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderDirectiveEndBracketMissing(ServiceParser.DefaultDirectiveName))); 
                }
 
                // First, parse all the <%@ ... %> directives 
                //
                for (; ; ) 
                {
                    match = directiveRegex.Match(this.serviceText, textPos);

                    // Done with the directives? 
                    //
                    if (!match.Success) 
                        break; 

                    lineNumber += ServiceParserUtilities.LineCount(this.serviceText, textPos, match.Index); 
                    textPos = match.Index;

                    // Get all the directives into a bag
                    // 
                    IDictionary directive = CollectionsUtil.CreateCaseInsensitiveSortedList();
                    string directiveName = ProcessAttributes(match, directive); 
 
                    // Understand the directive
                    // 
                    ProcessDirective(directiveName, directive);
                    lineNumber += ServiceParserUtilities.LineCount(this.serviceText, textPos, match.Index + match.Length);
                    textPos = match.Index + match.Length;
 
                    // Fixup line and column numbers to have meaninglful errors
                    // 
                    int newlineIndex = this.serviceText.LastIndexOfAny(newlineChars, textPos - 1); 
                    startColumn = textPos - newlineIndex;
                } 

                if (!foundMainDirective)
                {
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderDirectiveMissing(ServiceParser.DefaultDirectiveName))); 
                }
 
                // skip the directives chunk 
                //
                string remainingText = this.serviceText.Substring(textPos); 

                // If there is something else in the file, it needs to be compiled
                //
                if (!ServiceParserUtilities.IsWhiteSpaceString(remainingText)) 
                {
                    sourceString = remainingText; 
                } 
            }
            catch (HttpException e) 
            {
                // the string is set in the internal exception, no need to set it again.
                //
                Exception parseException = CreateParseException(e, this.serviceText); 
                throw FxTrace.Exception.AsError(
                    new HttpCompileException(parseException.Message, parseException)); 
            } 
        }
 
        /// 
        /// Return the directive if it exists or an empty string
        /// 
        string ProcessAttributes(Match match, IDictionary attribs) 
        {
            // creates 3 parallel capture collections 
            // for the attribute names, the attribute values and the 
            // equal signs
            // 
            string ret = String.Empty;

            CaptureCollection attrnames = match.Groups["attrname"].Captures;
            CaptureCollection attrvalues = match.Groups["attrval"].Captures; 
            CaptureCollection equalsign = match.Groups["equal"].Captures;
 
            // Iterate through all of them and add then to 
            // the dictionary of attributes
            // 
            for (int i = 0; i < attrnames.Count; i++)
            {
                string attribName = attrnames[i].ToString();
                string attribValue = attrvalues[i].ToString(); 

                // Check if there is an equal sign. 
                // 
                bool fHasEqual = (equalsign[i].ToString().Length > 0);
 
                if (attribName != null)
                {
                    // A <%@ %> block can have two formats:
                    // <%@ directive foo=1 bar=hello %> 
                    // <%@ foo=1 bar=hello %>
                    // Check if we have the first format 
                    // 
                    if (!fHasEqual && i == 0)
                    { 
                        // return the main directive
                        //
                        ret = attribName;
                        continue; 
                    }
 
                    try 
                    {
                        if (attribs != null) 
                            attribs.Add(attribName, attribValue);
                    }
                    catch (ArgumentException)
                    { 
                        throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderDuplicateAttribute(attribName)));
                    } 
                } 
            }
            return ret; 
        }

        /// 
        /// This method understands the compilation parameters if any ... 
        /// 
        void ProcessCompilationParams(IDictionary directive, CompilerParameters compilParams) 
        { 
            bool debug = false;
            if (ServiceParserUtilities.GetAndRemoveBooleanAttribute(directive, "debug", ref debug)) 
            {
                compilParams.IncludeDebugInformation = debug;
            }
 
            int warningLevel = 0;
            if (ServiceParserUtilities.GetAndRemoveNonNegativeIntegerAttribute(directive, "warninglevel", ref warningLevel)) 
            { 
                compilParams.WarningLevel = warningLevel;
                if (warningLevel > 0) 
                    compilParams.TreatWarningsAsErrors = true;
            }

            string compilerOptions = ServiceParserUtilities.GetAndRemoveNonEmptyAttribute(directive, "compileroptions"); 
            if (compilerOptions != null)
            { 
                compilParams.CompilerOptions = compilerOptions; 
            }
        } 


        /// 
        /// Processes a directive block 
        /// 
        void ProcessDirective(string directiveName, IDictionary directive) 
        { 
            // Throw on empy, no directive specified
            // 
            if (directiveName.Length == 0)
            {
                throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderDirectiveNameMissing));
            } 

            // Check for the main directive 
            // 
            if (string.Compare(directiveName, ServiceParser.DefaultDirectiveName, StringComparison.OrdinalIgnoreCase) == 0)
            { 
                // Make sure the main directive was not already specified
                //
                if (foundMainDirective)
                { 
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderDuplicateDirective(ServiceParser.DefaultDirectiveName)));
                } 
 
                foundMainDirective = true;
 
                // Ignore 'codebehind' attribute (ASURT 4591)
                //
                directive.Remove("codebehind");
 
                string language = ServiceParserUtilities.GetAndRemoveNonEmptyAttribute(directive, "language");
 
                // Get the compiler for the specified language (if any) 
                // or get the one from config
                // 
                if (language != null)
                {
                    compilerType = buildProvider.GetDefaultCompilerTypeForLanguageInternal(language);
                } 
                else
                { 
                    compilerType = buildProvider.GetDefaultCompilerTypeInternal(); 
                }
 

                if (directive.Contains(FactoryAttributeName))
                {
                    factoryAttributeValue = ServiceParserUtilities.GetAndRemoveNonEmptyAttribute(directive, FactoryAttributeName); 
                    serviceAttributeValue = ServiceParserUtilities.GetAndRemoveNonEmptyAttribute(directive, ServiceAttributeName);
                } 
                else if (directive.Contains(ServiceAttributeName)) 
                {
                    serviceAttributeValue = ServiceParserUtilities.GetAndRemoveNonEmptyAttribute(directive, ServiceAttributeName); 
                }
                else
                {
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderMainAttributeMissing)); 
                }
                // parse the parameters that are related to the compiler 
                // 
                ProcessCompilationParams(directive, compilerType.CompilerParameters);
            } 
            else if (string.Compare(directiveName, "assembly", StringComparison.OrdinalIgnoreCase) == 0)
            {
                if (directive.Contains("name") && directive.Contains("src"))
                { 
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderMutualExclusiveAttributes("src", "name")));
                } 
                else if (directive.Contains("name")) 
                {
                    string assemblyName = ServiceParserUtilities.GetAndRemoveNonEmptyAttribute(directive, "name"); 
                    if (assemblyName != null)
                    {
                        AddAssemblyDependency(assemblyName);
                    } 
                    else
                        throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderAttributeEmpty("name"))); 
                } 
                else if (directive.Contains("src"))
                { 
                    string srcPath = ServiceParserUtilities.GetAndRemoveNonEmptyAttribute(directive, "src");
                    if (srcPath != null)
                    {
                        ImportSourceFile(srcPath); 
                    }
                    else 
                        throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderAttributeEmpty("src"))); 
                }
                else 
                { // if (!directive.Contains("name") && !directive.Contains("src"))
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderRequiredAttributesMissing("src", "name")));
                }
            } 
            else
            { 
                throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderUnknownDirective(directiveName))); 
            }
 
            // check if there are any directives that you did not process
            //
            if (directive.Count > 0)
                throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderUnknownAttribute(ServiceParserUtilities.FirstDictionaryKey(directive)))); 
        }
 
        void ImportSourceFile(string path) 
        {
            // Get a full path to the source file, compile it to an assembly 
            // add the depedency to the assembly
            //
            string baseVirtualDir = VirtualPathUtility.GetDirectory(virtualPath);
            string fullVirtualPath = VirtualPathUtility.Combine(baseVirtualDir, path); 

            AddSourceDependency(fullVirtualPath); 
            Assembly a = BuildManager.GetCompiledAssembly(fullVirtualPath); 
            AddAssemblyDependency(a);
        } 

        void AddAssemblyDependency(string assemblyName)
        {
            // Load and keep track of the assembly 
            //
            Assembly a = Assembly.Load(assemblyName); 
            AddAssemblyDependency(a); 
        }
 
        void AddAssemblyDependency(Assembly assembly)
        {
            if (linkedAssemblies == null)
                linkedAssemblies = new HybridDictionary(false); 

            linkedAssemblies.Add(assembly, null); 
        } 

        ///  
        /// Look for a type by name in the assemblies available to this page
        /// 
        Type GetType(string typeName)
        { 
            Type type;
 
            // If it contains an assembly name, just call Type.GetType (ASURT 53589) 
            //
            if (ServiceParserUtilities.TypeNameIncludesAssembly(typeName)) 
            {
                try
                {
                    type = Type.GetType(typeName, true); 
                }
                catch (ArgumentException e) 
                { 
                    Exception parseException = CreateParseException(e, this.sourceString);
                    throw FxTrace.Exception.AsError( 
                        new HttpCompileException(parseException.Message, parseException));
                }
                catch (TargetInvocationException e)
                { 
                    Exception parseException = CreateParseException(e, this.sourceString);
                    throw FxTrace.Exception.AsError( 
                        new HttpCompileException(parseException.Message, parseException)); 
                }
                catch (TypeLoadException e) 
                {
                    Exception parseException = CreateParseException(SR.Hosting_BuildProviderCouldNotCreateType(typeName), e, this.sourceString);
                    throw FxTrace.Exception.AsError(
                        new HttpCompileException(parseException.Message, parseException)); 
                }
 
                return type; 
            }
 
            try
            {
                type = ServiceParserUtilities.GetTypeFromAssemblies(referencedAssemblies, typeName, false /*ignoreCase*/);
                if (type != null) 
                    return type;
 
                type = ServiceParserUtilities.GetTypeFromAssemblies(AssemblyDependencies, typeName, false /*ignoreCase*/); 
                if (type != null)
                    return type; 
            }
            catch (HttpException e)
            {
                Exception parseException = CreateParseException(SR.Hosting_BuildProviderCouldNotCreateType(typeName), e, this.sourceString); 
                throw FxTrace.Exception.AsError(
                        new HttpCompileException(parseException.Message, parseException)); 
            } 

            Exception exception = CreateParseException(SR.Hosting_BuildProviderCouldNotCreateType(typeName), this.sourceString); 
            throw FxTrace.Exception.AsError(
                        new HttpCompileException(exception.Message, exception));
        }
 
        /// 
        /// This class contains static methods that are necessary to manipulate the 
        /// structures that contain the directives. The logic assumes that the parser will 
        /// create a dictionary that contains all the directives and we can pull certain directives as
        /// necessary while processing/compiling the page. The directives are strings. 
        ///
        /// 
        static class ServiceParserUtilities
        { 
            /// 
            /// Return the first key of the dictionary as a string.  Throws if it's 
            /// empty or if the key is not a string. 
            /// 
            internal static string FirstDictionaryKey(IDictionary dictionary) 
            {
                // assume that the caller has checked the dictionary before calling
                //
                IDictionaryEnumerator e = dictionary.GetEnumerator(); 
                e.MoveNext();
                return (string)e.Key; 
            } 

            ///  
            /// Get a string value from a dictionary, and remove
            /// it from the dictionary of attributes if it exists.
            /// 
            /// Returns null if the value was not there ... 
            static string GetAndRemove(IDictionary dictionary, string key)
            { 
                string val = (string)dictionary[key]; 

                if (val != null) 
                {
                    dictionary.Remove(key);
                    val = val.Trim();
                } 
                else
                    return string.Empty; 
 
                return val;
            } 

            /// 
            /// Get a value from a dictionary, and remove it from the dictionary if
            /// it exists.  Throw an exception if the value is a whitespace string. 
            /// However, don't complain about null, which simply means the value is not
            /// in the dictionary. 
            ///  
            internal static string GetAndRemoveNonEmptyAttribute(IDictionary directives, string key, bool required)
            { 
                string val = ServiceParserUtilities.GetAndRemove(directives, key);

                if (val.Length == 0)
                { 
                    if (required)
                    { 
                        throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderAttributeMissing(key))); 
                    }
                    return null; 
                }

                return val;
            } 

 
            internal static string GetAndRemoveNonEmptyAttribute(IDictionary directives, string key) 
            {
                return GetAndRemoveNonEmptyAttribute(directives, key, false /*required*/); 
            }

            /// 
            /// Get a string value from a dictionary, and convert it to bool.  Throw an 
            /// exception if it's not a valid bool string.
            /// However, don't complain about null, which simply means the value is not 
            /// in the dictionary. 
            /// The value is returned through a REF param (unchanged if null)
            ///  
            /// True if attrib exists, false otherwise
            internal static bool GetAndRemoveBooleanAttribute(IDictionary directives, string key, ref bool val)
            {
                string s = ServiceParserUtilities.GetAndRemove(directives, key); 

                if (s.Length == 0) 
                    return false; 

                try 
                {
                    val = bool.Parse(s);
                }
                catch (FormatException) 
                {
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderInvalidValueForBooleanAttribute(s, key))); 
                } 

                return true; 
            }

            /// 
            /// Get a string value from a dictionary, and convert it to integer.  Throw an 
            /// exception if it's not a valid positive integer string.
            /// However, don't complain about null, which simply means the value is not 
            /// in the dictionary. 
            /// The value is returned through a REF param (unchanged if null)
            ///  
            /// True if attrib exists, false otherwise
            internal static bool GetAndRemoveNonNegativeIntegerAttribute(IDictionary directives, string key, ref int val)
            {
                string s = ServiceParserUtilities.GetAndRemove(directives, key); 

                if (s.Length == 0) 
                    return false; 

                val = GetNonNegativeIntegerAttribute(key, s); 
                return true;
            }

            ///  
            /// Parse a string attribute into a non-negative integer
            ///  
            /// Name of the attribute, used only for the error messages 
            /// Value to convert to int
            static int GetNonNegativeIntegerAttribute(string name, string value) 
            {
                int ret;

                try 
                {
                    ret = int.Parse(value, CultureInfo.InvariantCulture); 
                } 
                catch (FormatException)
                { 
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderInvalidValueForNonNegativeIntegerAttribute(value, name)));
                }

                // Make sure it's not negative 
                //
                if (ret < 0) 
                { 
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderInvalidValueForNonNegativeIntegerAttribute(value, name)));
                } 

                return ret;
            }
 
            internal static bool IsWhiteSpaceString(string s)
            { 
                return (s.Trim().Length == 0); 
            }
 
            /// 
            /// This method takes the code that will be compiled as a string and it
            /// will count how many lines exist between the given offset and the final
            /// offset. 
            /// 
            /// The text that contains the source code 
            /// Starting offset for lookup 
            /// Ending offset
            /// The number of lines 
            internal static int LineCount(string text, int offset, int newoffset)
            {
                int linecount = 0;
 
                while (offset < newoffset)
                { 
                    if (text[offset] == '\r' || (text[offset] == '\n' && (offset == 0 || text[offset - 1] != '\r'))) 
                        linecount++;
 
                    offset++;
                }

                return linecount; 
            }
 
            ///  
            /// Parses a string that contains a type trying to figure out if the assembly info is there.
            ///  
            /// The string to search
            internal static bool TypeNameIncludesAssembly(string typeName)
            {
                return (typeName.IndexOf(",", StringComparison.Ordinal) >= 0); 
            }
 
            ///  
            /// Loops through a list of assemblies that are already collected by the parser/provider and
            /// looks for the specified type. 
            /// 
            /// The collection of assemblies
            /// The type name
            /// Case sensitivity knob 
            /// 
            internal static Type GetTypeFromAssemblies(ICollection assemblies, string typeName, bool ignoreCase) 
            { 
                if (assemblies == null)
                    return null; 

                Type type = null;

                foreach (Assembly assembly in assemblies) 
                {
                    Type t = assembly.GetType(typeName, false /*throwOnError*/, ignoreCase); 
 
                    if (t == null)
                        continue; 

                    // If we had already found a different one, it's an ambiguous type reference
                    //
                    if (type != null && t != type) 
                    {
                        throw FxTrace.Exception.AsError(new HttpException( 
                            SR.Hosting_BuildProviderAmbiguousType(typeName, type.Assembly.FullName, t.Assembly.FullName))); 
                    }
 
                    // Keep track of it
                    //
                    type = t;
                } 

                return type; 
            } 
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

namespace System.ServiceModel.Activation 
{
    using System.CodeDom; 
    using System.CodeDom.Compiler; 
    using System.Collections;
    using System.Collections.Specialized; 
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.Globalization;
    using System.IO; 
    using System.Reflection;
    using System.Text.RegularExpressions; 
    using System.Web; 
    using System.Web.Hosting;
    using System.Web.Compilation; 
    using System.Web.RegularExpressions;
    using System.ServiceModel.Activation.Diagnostics;
    using System.Security;
    using System.Runtime.Diagnostics; 

    ///  
    /// This class will parse the .svc file and maintains a list of useful information that the build 
    /// provider needs in order to compile the file. The parser creates a list of dependent assemblies,
    /// understands the compiler that we need to use, fully parses all the supported directives etc. 
    /// 
    /// 
    /// The class is not thread-safe.
    ///  
#pragma warning disable 618 // have not moved to the v4 security model yet
    [SecurityCritical(SecurityCriticalScope.Everything)] 
#pragma warning restore 618 
    class ServiceParser
    { 
        // the delimiter for the compiled custom string
        const string Delimiter = ServiceHostingEnvironment.ServiceParserDelimiter;

        // attribute names 
        const string DefaultDirectiveName = "ServiceHost";
        const string FactoryAttributeName = "Factory"; 
        const string ServiceAttributeName = "Service"; 

        // regular exression for the directive 
        readonly static SimpleDirectiveRegex directiveRegex = new SimpleDirectiveRegex();

        // the build provider we will work with
        ServiceBuildProvider buildProvider; 

        // text for the file 
        string serviceText; 

        // the class attribute value 
        string factoryAttributeValue = string.Empty;

        // the constructorstring
        string serviceAttributeValue = string.Empty; 

        // the line number in file currently being parsed 
        int lineNumber; 

        // the column number in file currently being parsed 
        int startColumn;

        // the main directive was found or not
        bool foundMainDirective; 

        // the type of the compiler (i.e C#) 
        CompilerType compilerType; 

        // the string containing the code to be compiled, 
        // it will be null when all the code is "behind"
        string sourceString;

        // assemblies to be linked with, we need a unique list 
        // of them and we maintain a Dictionary for it.
        HybridDictionary linkedAssemblies; 
 
        // the set of assemblies that the build system is
        // telling us we will be linked with. There is no unique 
        // requirement for them.
        ICollection referencedAssemblies;

        // used to figure out where the new lines start 
        static char[] newlineChars = new char[] { '\r', '\n' };
 
        // source file dependencies 
        HybridDictionary sourceDependencies;
 
        // virtual path for the file that we are parsing
        string virtualPath;

        ///  
        /// The Contructor needs the path to the file that it will parse and a reference to
        /// the build provider that we are using. This is necessary because there are things that 
        /// need to be set on the build provider directly as we are parsing... 
        /// 
        internal ServiceParser(string virtualPath, ServiceBuildProvider buildProvider) 
        {
            if (DiagnosticUtility.ShouldTraceInformation)
            {
                TraceUtility.TraceEvent(TraceEventType.Information, TraceCode.WebHostCompilation, SR.TraceCodeWebHostCompilation, 
                    new StringTraceRecord("VirtualPath", virtualPath), this, (Exception)null);
            } 
 
            this.virtualPath = virtualPath;
            this.buildProvider = buildProvider; 
        }

        /// 
        /// Constructor that is used when the whole svc file content is provided. This is the case 
        /// when the COM+ Admin tool calls into it.
        ///  
        ServiceParser(string serviceText) 
        {
            this.serviceText = serviceText; 
            this.buildProvider = new ServiceBuildProvider();
        }

        ///  
        /// Parsing the content of the service file and retrieve the serviceAttributeValue attribute for ComPlus.
        ///  
        /// The content of the service file. 
        /// The "serviceAttributeValue" attribute of the Service directive. 
        ///  
        internal static IDictionary ParseServiceDirective(string serviceText)
        {
            ServiceParser parser = new ServiceParser(serviceText);
            parser.ParseString(); 

            // the list of valid attributes for ComPlus for Service Directive 
            IDictionary attributeTable = new Dictionary( 
                StringComparer.OrdinalIgnoreCase);
 
            if (!string.IsNullOrEmpty(parser.factoryAttributeValue))
                attributeTable.Add(FactoryAttributeName, parser.factoryAttributeValue);

            if (!string.IsNullOrEmpty(parser.serviceAttributeValue)) 
                attributeTable.Add(ServiceAttributeName, parser.serviceAttributeValue);
 
            return attributeTable; 
        }
 
        /// 
        /// 

        // various getters for private objects that the build 
        // provider will need
        // 
        internal CompilerType CompilerType 
        {
            get 
            {
                return compilerType;
            }
        } 

        internal ICollection AssemblyDependencies 
        { 
            get
            { 
                if (linkedAssemblies == null)
                {
                    return null;
                } 

                return linkedAssemblies.Keys; 
            } 
        }
 
        internal ICollection SourceDependencies
        {
            get
            { 
                if (sourceDependencies == null)
                { 
                    return null; 
                }
 
                return sourceDependencies.Keys;
            }
        }
 
        internal bool HasInlineCode
        { 
            get 
            {
                return (sourceString != null); 
            }
        }

        ///  
        /// Parses the code file appropriately. This method is used by the
        /// build provider. 
        ///  
        internal void Parse(ICollection referencedAssemblies)
        { 
            if (referencedAssemblies == null)
            {
                throw FxTrace.Exception.ArgumentNull("referencedAssemblies");
            } 

            this.referencedAssemblies = referencedAssemblies; 
            AddSourceDependency(virtualPath); 

            using (TextReader reader = buildProvider.OpenReaderInternal()) 
            {
                this.serviceText = reader.ReadToEnd();
                ParseString();
            } 
        }
 
        ///  
        /// This method returns a code compile unit that will be added
        /// to the other depdnecies in order to compile 
        /// 
        internal CodeCompileUnit GetCodeModel()
        {
            // Do we have something to compile? 
            //
            if (sourceString == null || sourceString.Length == 0) 
                return null; 

            CodeSnippetCompileUnit snippetCompileUnit = new CodeSnippetCompileUnit(sourceString); 

            // Put in some context so that the file can be debugged.
            //
            string pragmaFile = HostingEnvironmentWrapper.MapPath(virtualPath); 
            snippetCompileUnit.LinePragma = new CodeLinePragma(pragmaFile, lineNumber);
 
            return snippetCompileUnit; 
        }
 
        Exception CreateParseException(string message, string sourceCode)
        {
            return CreateParseException(message, null, sourceCode);
        } 

        Exception CreateParseException(Exception innerException, string sourceCode) 
        { 
            return CreateParseException(innerException.Message, innerException, sourceCode);
        } 

        Exception CreateParseException(string message, Exception innerException, string sourceCode)
        {
            return new HttpParseException(message, innerException, this.virtualPath, sourceCode, this.lineNumber); 
        }
 
        ///  
        /// This method returns the custom string that is to be passed to ServiceHostingEnvironment from BuildManager.
        ///  
        /// The full name of the built assembly for inline code.
        internal string CreateParseString(Assembly compiledAssembly)
        {
            Type typeToPreserve = this.GetCompiledType(compiledAssembly); 
            string typeToPreserveName = string.Empty;
            if (typeToPreserve != null) 
                typeToPreserveName = typeToPreserve.AssemblyQualifiedName; 

            System.Text.StringBuilder builder = new System.Text.StringBuilder(); 
            if (compiledAssembly != null)
            {
                builder.Append(Delimiter);
                builder.Append(compiledAssembly.FullName); 
            }
 
            if (this.referencedAssemblies != null) 
            {
                foreach (Assembly assembly in this.referencedAssemblies) 
                {
                    builder.Append(Delimiter);
                    builder.Append(assembly.FullName);
                } 
            }
 
            if (this.AssemblyDependencies != null) 
            {
                foreach (Assembly assembly in this.AssemblyDependencies) 
                {
                    builder.Append(Delimiter);
                    builder.Append(assembly.FullName);
                } 
            }
            // use application relative virtualpath instead of the absolute path 
            // so that the compliedcustomstring is applicationame independent 
            return string.Concat(VirtualPathUtility.ToAppRelative(virtualPath), Delimiter,
                typeToPreserveName, Delimiter, 
                serviceAttributeValue, builder.ToString());
        }

        void AddSourceDependency(string fileName) 
        {
            if (sourceDependencies == null) 
                sourceDependencies = new HybridDictionary(true); 

            sourceDependencies.Add(fileName, fileName); 
        }

        Type GetCompiledType(Assembly compiledAssembly)
        { 
            if (string.IsNullOrEmpty(factoryAttributeValue))
            { 
                return null; 
            }
 
            Type type = null;

            // First, try to get the type from the assembly that has been built (if any)
            if (this.HasInlineCode && (compiledAssembly != null)) 
            {
                type = compiledAssembly.GetType(factoryAttributeValue); 
            } 

            // If not, try to get it from other assemblies 
            if (type == null)
            {
                type = GetType(factoryAttributeValue);
            } 

            return type; 
        } 

        internal IDictionary GetLinePragmasTable() 
        {
            LinePragmaCodeInfo info = new LinePragmaCodeInfo(this.lineNumber, this.startColumn, 1, -1, false);
            IDictionary dictionary = new Hashtable();
            dictionary[this.lineNumber] = info; 
            return dictionary;
        } 
 
        /// 
        /// Parses the content of the svc file for each directive line 
        /// 
        void ParseString()
        {
            try 
            {
                int textPos = 0; 
                Match match; 
                lineNumber = 1;
 
                // Check for ending bracket first, MB 45013.
                if(this.serviceText.IndexOf('>') == -1)
                {
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderDirectiveEndBracketMissing(ServiceParser.DefaultDirectiveName))); 
                }
 
                // First, parse all the <%@ ... %> directives 
                //
                for (; ; ) 
                {
                    match = directiveRegex.Match(this.serviceText, textPos);

                    // Done with the directives? 
                    //
                    if (!match.Success) 
                        break; 

                    lineNumber += ServiceParserUtilities.LineCount(this.serviceText, textPos, match.Index); 
                    textPos = match.Index;

                    // Get all the directives into a bag
                    // 
                    IDictionary directive = CollectionsUtil.CreateCaseInsensitiveSortedList();
                    string directiveName = ProcessAttributes(match, directive); 
 
                    // Understand the directive
                    // 
                    ProcessDirective(directiveName, directive);
                    lineNumber += ServiceParserUtilities.LineCount(this.serviceText, textPos, match.Index + match.Length);
                    textPos = match.Index + match.Length;
 
                    // Fixup line and column numbers to have meaninglful errors
                    // 
                    int newlineIndex = this.serviceText.LastIndexOfAny(newlineChars, textPos - 1); 
                    startColumn = textPos - newlineIndex;
                } 

                if (!foundMainDirective)
                {
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderDirectiveMissing(ServiceParser.DefaultDirectiveName))); 
                }
 
                // skip the directives chunk 
                //
                string remainingText = this.serviceText.Substring(textPos); 

                // If there is something else in the file, it needs to be compiled
                //
                if (!ServiceParserUtilities.IsWhiteSpaceString(remainingText)) 
                {
                    sourceString = remainingText; 
                } 
            }
            catch (HttpException e) 
            {
                // the string is set in the internal exception, no need to set it again.
                //
                Exception parseException = CreateParseException(e, this.serviceText); 
                throw FxTrace.Exception.AsError(
                    new HttpCompileException(parseException.Message, parseException)); 
            } 
        }
 
        /// 
        /// Return the directive if it exists or an empty string
        /// 
        string ProcessAttributes(Match match, IDictionary attribs) 
        {
            // creates 3 parallel capture collections 
            // for the attribute names, the attribute values and the 
            // equal signs
            // 
            string ret = String.Empty;

            CaptureCollection attrnames = match.Groups["attrname"].Captures;
            CaptureCollection attrvalues = match.Groups["attrval"].Captures; 
            CaptureCollection equalsign = match.Groups["equal"].Captures;
 
            // Iterate through all of them and add then to 
            // the dictionary of attributes
            // 
            for (int i = 0; i < attrnames.Count; i++)
            {
                string attribName = attrnames[i].ToString();
                string attribValue = attrvalues[i].ToString(); 

                // Check if there is an equal sign. 
                // 
                bool fHasEqual = (equalsign[i].ToString().Length > 0);
 
                if (attribName != null)
                {
                    // A <%@ %> block can have two formats:
                    // <%@ directive foo=1 bar=hello %> 
                    // <%@ foo=1 bar=hello %>
                    // Check if we have the first format 
                    // 
                    if (!fHasEqual && i == 0)
                    { 
                        // return the main directive
                        //
                        ret = attribName;
                        continue; 
                    }
 
                    try 
                    {
                        if (attribs != null) 
                            attribs.Add(attribName, attribValue);
                    }
                    catch (ArgumentException)
                    { 
                        throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderDuplicateAttribute(attribName)));
                    } 
                } 
            }
            return ret; 
        }

        /// 
        /// This method understands the compilation parameters if any ... 
        /// 
        void ProcessCompilationParams(IDictionary directive, CompilerParameters compilParams) 
        { 
            bool debug = false;
            if (ServiceParserUtilities.GetAndRemoveBooleanAttribute(directive, "debug", ref debug)) 
            {
                compilParams.IncludeDebugInformation = debug;
            }
 
            int warningLevel = 0;
            if (ServiceParserUtilities.GetAndRemoveNonNegativeIntegerAttribute(directive, "warninglevel", ref warningLevel)) 
            { 
                compilParams.WarningLevel = warningLevel;
                if (warningLevel > 0) 
                    compilParams.TreatWarningsAsErrors = true;
            }

            string compilerOptions = ServiceParserUtilities.GetAndRemoveNonEmptyAttribute(directive, "compileroptions"); 
            if (compilerOptions != null)
            { 
                compilParams.CompilerOptions = compilerOptions; 
            }
        } 


        /// 
        /// Processes a directive block 
        /// 
        void ProcessDirective(string directiveName, IDictionary directive) 
        { 
            // Throw on empy, no directive specified
            // 
            if (directiveName.Length == 0)
            {
                throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderDirectiveNameMissing));
            } 

            // Check for the main directive 
            // 
            if (string.Compare(directiveName, ServiceParser.DefaultDirectiveName, StringComparison.OrdinalIgnoreCase) == 0)
            { 
                // Make sure the main directive was not already specified
                //
                if (foundMainDirective)
                { 
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderDuplicateDirective(ServiceParser.DefaultDirectiveName)));
                } 
 
                foundMainDirective = true;
 
                // Ignore 'codebehind' attribute (ASURT 4591)
                //
                directive.Remove("codebehind");
 
                string language = ServiceParserUtilities.GetAndRemoveNonEmptyAttribute(directive, "language");
 
                // Get the compiler for the specified language (if any) 
                // or get the one from config
                // 
                if (language != null)
                {
                    compilerType = buildProvider.GetDefaultCompilerTypeForLanguageInternal(language);
                } 
                else
                { 
                    compilerType = buildProvider.GetDefaultCompilerTypeInternal(); 
                }
 

                if (directive.Contains(FactoryAttributeName))
                {
                    factoryAttributeValue = ServiceParserUtilities.GetAndRemoveNonEmptyAttribute(directive, FactoryAttributeName); 
                    serviceAttributeValue = ServiceParserUtilities.GetAndRemoveNonEmptyAttribute(directive, ServiceAttributeName);
                } 
                else if (directive.Contains(ServiceAttributeName)) 
                {
                    serviceAttributeValue = ServiceParserUtilities.GetAndRemoveNonEmptyAttribute(directive, ServiceAttributeName); 
                }
                else
                {
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderMainAttributeMissing)); 
                }
                // parse the parameters that are related to the compiler 
                // 
                ProcessCompilationParams(directive, compilerType.CompilerParameters);
            } 
            else if (string.Compare(directiveName, "assembly", StringComparison.OrdinalIgnoreCase) == 0)
            {
                if (directive.Contains("name") && directive.Contains("src"))
                { 
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderMutualExclusiveAttributes("src", "name")));
                } 
                else if (directive.Contains("name")) 
                {
                    string assemblyName = ServiceParserUtilities.GetAndRemoveNonEmptyAttribute(directive, "name"); 
                    if (assemblyName != null)
                    {
                        AddAssemblyDependency(assemblyName);
                    } 
                    else
                        throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderAttributeEmpty("name"))); 
                } 
                else if (directive.Contains("src"))
                { 
                    string srcPath = ServiceParserUtilities.GetAndRemoveNonEmptyAttribute(directive, "src");
                    if (srcPath != null)
                    {
                        ImportSourceFile(srcPath); 
                    }
                    else 
                        throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderAttributeEmpty("src"))); 
                }
                else 
                { // if (!directive.Contains("name") && !directive.Contains("src"))
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderRequiredAttributesMissing("src", "name")));
                }
            } 
            else
            { 
                throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderUnknownDirective(directiveName))); 
            }
 
            // check if there are any directives that you did not process
            //
            if (directive.Count > 0)
                throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderUnknownAttribute(ServiceParserUtilities.FirstDictionaryKey(directive)))); 
        }
 
        void ImportSourceFile(string path) 
        {
            // Get a full path to the source file, compile it to an assembly 
            // add the depedency to the assembly
            //
            string baseVirtualDir = VirtualPathUtility.GetDirectory(virtualPath);
            string fullVirtualPath = VirtualPathUtility.Combine(baseVirtualDir, path); 

            AddSourceDependency(fullVirtualPath); 
            Assembly a = BuildManager.GetCompiledAssembly(fullVirtualPath); 
            AddAssemblyDependency(a);
        } 

        void AddAssemblyDependency(string assemblyName)
        {
            // Load and keep track of the assembly 
            //
            Assembly a = Assembly.Load(assemblyName); 
            AddAssemblyDependency(a); 
        }
 
        void AddAssemblyDependency(Assembly assembly)
        {
            if (linkedAssemblies == null)
                linkedAssemblies = new HybridDictionary(false); 

            linkedAssemblies.Add(assembly, null); 
        } 

        ///  
        /// Look for a type by name in the assemblies available to this page
        /// 
        Type GetType(string typeName)
        { 
            Type type;
 
            // If it contains an assembly name, just call Type.GetType (ASURT 53589) 
            //
            if (ServiceParserUtilities.TypeNameIncludesAssembly(typeName)) 
            {
                try
                {
                    type = Type.GetType(typeName, true); 
                }
                catch (ArgumentException e) 
                { 
                    Exception parseException = CreateParseException(e, this.sourceString);
                    throw FxTrace.Exception.AsError( 
                        new HttpCompileException(parseException.Message, parseException));
                }
                catch (TargetInvocationException e)
                { 
                    Exception parseException = CreateParseException(e, this.sourceString);
                    throw FxTrace.Exception.AsError( 
                        new HttpCompileException(parseException.Message, parseException)); 
                }
                catch (TypeLoadException e) 
                {
                    Exception parseException = CreateParseException(SR.Hosting_BuildProviderCouldNotCreateType(typeName), e, this.sourceString);
                    throw FxTrace.Exception.AsError(
                        new HttpCompileException(parseException.Message, parseException)); 
                }
 
                return type; 
            }
 
            try
            {
                type = ServiceParserUtilities.GetTypeFromAssemblies(referencedAssemblies, typeName, false /*ignoreCase*/);
                if (type != null) 
                    return type;
 
                type = ServiceParserUtilities.GetTypeFromAssemblies(AssemblyDependencies, typeName, false /*ignoreCase*/); 
                if (type != null)
                    return type; 
            }
            catch (HttpException e)
            {
                Exception parseException = CreateParseException(SR.Hosting_BuildProviderCouldNotCreateType(typeName), e, this.sourceString); 
                throw FxTrace.Exception.AsError(
                        new HttpCompileException(parseException.Message, parseException)); 
            } 

            Exception exception = CreateParseException(SR.Hosting_BuildProviderCouldNotCreateType(typeName), this.sourceString); 
            throw FxTrace.Exception.AsError(
                        new HttpCompileException(exception.Message, exception));
        }
 
        /// 
        /// This class contains static methods that are necessary to manipulate the 
        /// structures that contain the directives. The logic assumes that the parser will 
        /// create a dictionary that contains all the directives and we can pull certain directives as
        /// necessary while processing/compiling the page. The directives are strings. 
        ///
        /// 
        static class ServiceParserUtilities
        { 
            /// 
            /// Return the first key of the dictionary as a string.  Throws if it's 
            /// empty or if the key is not a string. 
            /// 
            internal static string FirstDictionaryKey(IDictionary dictionary) 
            {
                // assume that the caller has checked the dictionary before calling
                //
                IDictionaryEnumerator e = dictionary.GetEnumerator(); 
                e.MoveNext();
                return (string)e.Key; 
            } 

            ///  
            /// Get a string value from a dictionary, and remove
            /// it from the dictionary of attributes if it exists.
            /// 
            /// Returns null if the value was not there ... 
            static string GetAndRemove(IDictionary dictionary, string key)
            { 
                string val = (string)dictionary[key]; 

                if (val != null) 
                {
                    dictionary.Remove(key);
                    val = val.Trim();
                } 
                else
                    return string.Empty; 
 
                return val;
            } 

            /// 
            /// Get a value from a dictionary, and remove it from the dictionary if
            /// it exists.  Throw an exception if the value is a whitespace string. 
            /// However, don't complain about null, which simply means the value is not
            /// in the dictionary. 
            ///  
            internal static string GetAndRemoveNonEmptyAttribute(IDictionary directives, string key, bool required)
            { 
                string val = ServiceParserUtilities.GetAndRemove(directives, key);

                if (val.Length == 0)
                { 
                    if (required)
                    { 
                        throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderAttributeMissing(key))); 
                    }
                    return null; 
                }

                return val;
            } 

 
            internal static string GetAndRemoveNonEmptyAttribute(IDictionary directives, string key) 
            {
                return GetAndRemoveNonEmptyAttribute(directives, key, false /*required*/); 
            }

            /// 
            /// Get a string value from a dictionary, and convert it to bool.  Throw an 
            /// exception if it's not a valid bool string.
            /// However, don't complain about null, which simply means the value is not 
            /// in the dictionary. 
            /// The value is returned through a REF param (unchanged if null)
            ///  
            /// True if attrib exists, false otherwise
            internal static bool GetAndRemoveBooleanAttribute(IDictionary directives, string key, ref bool val)
            {
                string s = ServiceParserUtilities.GetAndRemove(directives, key); 

                if (s.Length == 0) 
                    return false; 

                try 
                {
                    val = bool.Parse(s);
                }
                catch (FormatException) 
                {
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderInvalidValueForBooleanAttribute(s, key))); 
                } 

                return true; 
            }

            /// 
            /// Get a string value from a dictionary, and convert it to integer.  Throw an 
            /// exception if it's not a valid positive integer string.
            /// However, don't complain about null, which simply means the value is not 
            /// in the dictionary. 
            /// The value is returned through a REF param (unchanged if null)
            ///  
            /// True if attrib exists, false otherwise
            internal static bool GetAndRemoveNonNegativeIntegerAttribute(IDictionary directives, string key, ref int val)
            {
                string s = ServiceParserUtilities.GetAndRemove(directives, key); 

                if (s.Length == 0) 
                    return false; 

                val = GetNonNegativeIntegerAttribute(key, s); 
                return true;
            }

            ///  
            /// Parse a string attribute into a non-negative integer
            ///  
            /// Name of the attribute, used only for the error messages 
            /// Value to convert to int
            static int GetNonNegativeIntegerAttribute(string name, string value) 
            {
                int ret;

                try 
                {
                    ret = int.Parse(value, CultureInfo.InvariantCulture); 
                } 
                catch (FormatException)
                { 
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderInvalidValueForNonNegativeIntegerAttribute(value, name)));
                }

                // Make sure it's not negative 
                //
                if (ret < 0) 
                { 
                    throw FxTrace.Exception.AsError(new HttpException(SR.Hosting_BuildProviderInvalidValueForNonNegativeIntegerAttribute(value, name)));
                } 

                return ret;
            }
 
            internal static bool IsWhiteSpaceString(string s)
            { 
                return (s.Trim().Length == 0); 
            }
 
            /// 
            /// This method takes the code that will be compiled as a string and it
            /// will count how many lines exist between the given offset and the final
            /// offset. 
            /// 
            /// The text that contains the source code 
            /// Starting offset for lookup 
            /// Ending offset
            /// The number of lines 
            internal static int LineCount(string text, int offset, int newoffset)
            {
                int linecount = 0;
 
                while (offset < newoffset)
                { 
                    if (text[offset] == '\r' || (text[offset] == '\n' && (offset == 0 || text[offset - 1] != '\r'))) 
                        linecount++;
 
                    offset++;
                }

                return linecount; 
            }
 
            ///  
            /// Parses a string that contains a type trying to figure out if the assembly info is there.
            ///  
            /// The string to search
            internal static bool TypeNameIncludesAssembly(string typeName)
            {
                return (typeName.IndexOf(",", StringComparison.Ordinal) >= 0); 
            }
 
            ///  
            /// Loops through a list of assemblies that are already collected by the parser/provider and
            /// looks for the specified type. 
            /// 
            /// The collection of assemblies
            /// The type name
            /// Case sensitivity knob 
            /// 
            internal static Type GetTypeFromAssemblies(ICollection assemblies, string typeName, bool ignoreCase) 
            { 
                if (assemblies == null)
                    return null; 

                Type type = null;

                foreach (Assembly assembly in assemblies) 
                {
                    Type t = assembly.GetType(typeName, false /*throwOnError*/, ignoreCase); 
 
                    if (t == null)
                        continue; 

                    // If we had already found a different one, it's an ambiguous type reference
                    //
                    if (type != null && t != type) 
                    {
                        throw FxTrace.Exception.AsError(new HttpException( 
                            SR.Hosting_BuildProviderAmbiguousType(typeName, type.Assembly.FullName, t.Assembly.FullName))); 
                    }
 
                    // Keep track of it
                    //
                    type = t;
                } 

                return type; 
            } 
        }
    } 
}

// 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