Scripts.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Win7_3.5.1 / Dotnetfx_Win7_3.5.1 / 3.5.1 / DEVDIV / depot / DevDiv / releases / whidbey / NetFXspW7 / ndp / fx / src / XmlUtils / System / Xml / Xsl / Xslt / Scripts.cs / 1 / Scripts.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
// http://devdiv/Documents/Whidbey/CLR/CurrentSpecs/BCL/CodeDom%20Activation.doc
//----------------------------------------------------------------------------- 
 
using System.CodeDom;
using System.CodeDom.Compiler; 
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Configuration;
using System.Diagnostics; 
using System.Globalization;
using System.IO; 
using System.Reflection; 
using System.Runtime.InteropServices;
using System.Text.RegularExpressions; 
using System.Threading;
using System.Xml.Xsl.IlGen;
using System.Xml.Xsl.Runtime;
using System.Security.Permissions; 

namespace System.Xml.Xsl.Xslt { 
    using Res = System.Xml.Utils.Res; 

    internal class ScriptClass { 
        public string               ns;
        public CompilerInfo         compilerInfo;
        public StringCollection     refAssemblies = new StringCollection();
        public StringCollection     nsImports     = new StringCollection(); 
        public StringCollection     scriptFiles   = new StringCollection();
        public CodeTypeDeclaration  typeDecl; 
        public bool                 refAssembliesByHref = false; 

        // These three fields are used to report a compile error when its position is outside 
        // of all user code snippets in the generated temporary file
        public string               endFileName;
        public int                  endLine;
        public int                  endPos; 

        public ScriptClass(string ns, CompilerInfo compilerInfo) { 
            this.ns           = ns; 
            this.compilerInfo = compilerInfo;
            this.typeDecl     = new CodeTypeDeclaration(GenerateUniqueClassName()); 
        }

        private static long scriptClassCounter = 0;
 
        private static string GenerateUniqueClassName() {
            return "Script" + Interlocked.Increment(ref scriptClassCounter); 
        } 

        public void AddScriptBlock(string source, string uriString, int lineNumber, int endLine, int endPos) { 
            CodeSnippetTypeMember scriptSnippet = new CodeSnippetTypeMember(source);
            string fileName = SourceLineInfo.GetFileName(uriString);
            if (lineNumber > 0) {
                scriptSnippet.LinePragma = new CodeLinePragma(fileName, lineNumber); 
                scriptFiles.Add(fileName);
            } 
            typeDecl.Members.Add(scriptSnippet); 

            this.endFileName  = fileName; 
            this.endLine      = endLine;
            this.endPos       = endPos;
        }
 
        public CompilerError CreateCompileExceptionError(Exception e) {
            string errorText = XslTransformException.CreateMessage(/*[XT_041]*/Res.Xslt_ScriptCompileException, e.Message); 
            return new CompilerError(this.endFileName, this.endLine, this.endPos, /*errorNumber:*/string.Empty, errorText); 
        }
    } 

    internal class Scripts {
        private const string ScriptClassesNamespace = "System.Xml.Xsl.CompiledQuery";
 
        private Compiler                  compiler;
        private List         scriptClasses = new List(); 
        private Dictionary  nsToType      = new Dictionary(); 
        private XmlExtensionFunctionTable extFuncs      = new XmlExtensionFunctionTable();
 
        public Scripts(Compiler compiler) {
            this.compiler = compiler;
        }
 
        public Dictionary ScriptClasses {
            get { return nsToType; } 
        } 

        public XmlExtensionFunction ResolveFunction(string name, string ns, int numArgs, IErrorHelper errorHelper) { 
            Type type;
            if (nsToType.TryGetValue(ns, out type)) {
                try {
                    return extFuncs.Bind(name, ns, numArgs, type, XmlQueryRuntime.EarlyBoundFlags); 
                }
                catch (XslTransformException e) { 
                    errorHelper.ReportError(e.Message); 
                }
            } 
            return null;
        }

        public ScriptClass GetScriptClass(string ns, string language, IErrorHelper errorHelper) { 
            CompilerInfo compilerInfo;
            try { 
                compilerInfo = CodeDomProvider.GetCompilerInfo(language); 
                Debug.Assert(compilerInfo != null);
            } 
            catch (ConfigurationException) {
                // There is no CodeDom provider defined for this language
                errorHelper.ReportError(/*[XT_010]*/Res.Xslt_ScriptInvalidLanguage, language);
                return null; 
            }
 
            foreach (ScriptClass scriptClass in scriptClasses) { 
                if (ns == scriptClass.ns) {
                    // Use object comparison because CompilerInfo.Equals may throw 
                    if (compilerInfo != scriptClass.compilerInfo) {
                        errorHelper.ReportError(/*[XT_011]*/Res.Xslt_ScriptMixedLanguages, ns);
                        return null;
                    } 
                    return scriptClass;
                } 
            } 

            ScriptClass newScriptClass = new ScriptClass(ns, compilerInfo); 
            newScriptClass.typeDecl.TypeAttributes = TypeAttributes.Public;
            scriptClasses.Add(newScriptClass);
            return newScriptClass;
        } 

        //------------------------------------------------ 
        // Compilation 
        //------------------------------------------------
 
        public void CompileScripts() {
            List scriptsForLang = new List();

            for (int i = 0; i < scriptClasses.Count; i++) { 
                // If the script is already compiled, skip it
                if (scriptClasses[i] == null) 
                    continue; 

                // Group together scripts with the same CompilerInfo 
                CompilerInfo compilerInfo = scriptClasses[i].compilerInfo;
                scriptsForLang.Clear();

                for (int j = i; j < scriptClasses.Count; j++) { 
                    // Use object comparison because CompilerInfo.Equals may throw
                    if (scriptClasses[j] != null && scriptClasses[j].compilerInfo == compilerInfo) { 
                        scriptsForLang.Add(scriptClasses[j]); 
                        scriptClasses[j] = null;
                    } 
                }

                Assembly assembly = CompileAssembly(scriptsForLang);
 
                if (assembly != null) {
                    foreach (ScriptClass script in scriptsForLang) { 
                        Type clrType = assembly.GetType(ScriptClassesNamespace + Type.Delimiter + script.typeDecl.Name); 
                        if (clrType != null) {
                            nsToType.Add(script.ns, clrType); 
                        }
                    }
                }
            } 
        }
 
        // Namespaces we always import when compiling 
        private static readonly string[] defaultNamespaces = new string[] {
            "System", 
            "System.Collections",
            "System.Text",
            "System.Text.RegularExpressions",
            "System.Xml", 
            "System.Xml.Xsl",
            "System.Xml.XPath", 
        }; 

        [PermissionSet(SecurityAction.Demand, Name = "FullTrust")] 
        private Assembly CompileAssembly(List scriptsForLang) {
            TempFileCollection      allTempFiles  = compiler.CompilerResults.TempFiles;
            CompilerErrorCollection allErrors     = compiler.CompilerResults.Errors;
            ScriptClass             lastScript    = scriptsForLang[scriptsForLang.Count - 1]; 
            CodeDomProvider         provider;
            bool                    isVB          = false; 
 
            try {
                provider = lastScript.compilerInfo.CreateProvider(); 
            }
            catch (ConfigurationException e) {
                // The CodeDom provider type could not be located, or some error in machine.config
                allErrors.Add(lastScript.CreateCompileExceptionError(e)); 
                return null;
            } 
 
#if !FEATURE_PAL // visualbasic
            isVB = provider is Microsoft.VisualBasic.VBCodeProvider; 
#endif // !FEATURE_PAL

            CodeCompileUnit[] codeUnits = new CodeCompileUnit[scriptsForLang.Count];
            CompilerParameters compilParams = lastScript.compilerInfo.CreateDefaultCompilerParameters(); 

            // 
 

            compilParams.ReferencedAssemblies.Add(typeof(System.Xml.Res).Assembly.Location); 
            compilParams.ReferencedAssemblies.Add("System.dll");
            if (isVB) {
                compilParams.ReferencedAssemblies.Add("Microsoft.VisualBasic.dll");
            } 

            bool refAssembliesByHref = false; 
 
            for (int idx = 0; idx < scriptsForLang.Count; idx++) {
                ScriptClass script = scriptsForLang[idx]; 
                CodeNamespace scriptNs = new CodeNamespace(ScriptClassesNamespace);

                // Add imported namespaces
                foreach (string ns in defaultNamespaces) { 
                    scriptNs.Imports.Add(new CodeNamespaceImport(ns));
                } 
                if (isVB) { 
                    scriptNs.Imports.Add(new CodeNamespaceImport("Microsoft.VisualBasic"));
                } 
                foreach (string ns in script.nsImports) {
                    scriptNs.Imports.Add(new CodeNamespaceImport(ns));
                }
 
                scriptNs.Types.Add(script.typeDecl);
 
                CodeCompileUnit unit = new CodeCompileUnit(); { 
                    unit.Namespaces.Add(scriptNs);
 
                    if (isVB) {
                        // This settings have sense for Visual Basic only. In future releases we may allow to specify
                        // them explicitly in the msxsl:script element.
                        unit.UserData["AllowLateBound"]             = true;   // Allow variables to be declared untyped 
                        unit.UserData["RequireVariableDeclaration"] = false;  // Allow variables to be undeclared
                    } 
 
                    // Put SecurityTransparentAttribute on the first CodeCompileUnit only
                    if (idx == 0) { 
                        unit.AssemblyCustomAttributes.Add(new CodeAttributeDeclaration("System.Security.SecurityTransparentAttribute"));
                    }
                }
 
                codeUnits[idx] = unit;
                foreach (string name in script.refAssemblies) { 
                    compilParams.ReferencedAssemblies.Add(name); 
                }
 
                refAssembliesByHref |= script.refAssembliesByHref;
            }

            XsltSettings settings                 = compiler.Settings; 
            compilParams.WarningLevel             = settings.WarningLevel >= 0 ? settings.WarningLevel : compilParams.WarningLevel;
            compilParams.TreatWarningsAsErrors    = settings.TreatWarningsAsErrors; 
            compilParams.IncludeDebugInformation  = compiler.IsDebug; 

            string asmPath = compiler.ScriptAssemblyPath; 
            if (asmPath != null && scriptsForLang.Count < scriptClasses.Count) {
                asmPath = Path.ChangeExtension(asmPath, "." + GetLanguageName(lastScript.compilerInfo) + Path.GetExtension(asmPath));
            }
 
            compilParams.OutputAssembly           = asmPath;
 
            string tempDir = (settings.TempFiles != null) ? settings.TempFiles.TempDir : null; 
            compilParams.TempFiles                = new TempFileCollection(tempDir);
 
            // We need only .dll and .pdb, but there is no way to specify that
            bool keepFiles = ((compiler.IsDebug && asmPath == null) || XmlILTrace.IsEnabled) && !settings.CheckOnly;
            compilParams.TempFiles.KeepFiles = keepFiles;
 
            // If GenerateInMemory == true, then CodeDom loads the compiled assembly using Assembly.Load(byte[])
            // instead of Assembly.Load(AssemblyName).  That means the assembly will be loaded in the anonymous 
            // context (http://blogs.msdn.com/[....]/archive/2003/05/29/57143.aspx), and its dependencies can only 
            // be loaded from the Load context or using AssemblyResolve event.  However we want to use the LoadFrom
            // context to preload all dependencies specified by , so we turn off 
            // GenerateInMemory here.
            compilParams.GenerateInMemory = (asmPath == null && !compiler.IsDebug && !refAssembliesByHref) || settings.CheckOnly;

            CompilerResults results; 

            try { 
                results = provider.CompileAssemblyFromDom(compilParams, codeUnits); 
            }
            catch (ExternalException e) { 
                // Compiler might have created temporary files
                results = new CompilerResults(compilParams.TempFiles);
                results.Errors.Add(lastScript.CreateCompileExceptionError(e));
            } 

            if (!settings.CheckOnly) { 
                foreach (string fileName in results.TempFiles) { 
                    allTempFiles.AddFile(fileName, allTempFiles.KeepFiles);
                } 
            }

            foreach (CompilerError error in results.Errors) {
                FixErrorPosition(error, scriptsForLang); 
            }
 
            allErrors.AddRange(results.Errors); 
            return results.Errors.HasErrors ? null : results.CompiledAssembly;
        } 

        private int assemblyCounter = 0;

        private string GetLanguageName(CompilerInfo compilerInfo) { 
            Regex alphaNumeric = new Regex("^[0-9a-zA-Z]+$");
            foreach (string name in compilerInfo.GetLanguages()) { 
                if (alphaNumeric.IsMatch(name)) 
                    return name;
            } 
            return "script" + (++assemblyCounter).ToString(CultureInfo.InvariantCulture);
        }

#if !FEATURE_CASE_SENSITIVE_FILESYSTEM 
        private static readonly StringComparison fileNameComparison = StringComparison.OrdinalIgnoreCase;
#else 
        private static readonly StringComparison fileNameComparison = StringComparison.Ordinal; 
#endif
 
        // The position of a compile error may be outside of all user code snippets (for example, in case of
        // unclosed '{'). In that case filename would be the name of the temporary file, and not the name
        // of the stylesheet file. Exposing the path of the temporary file is considered to be a security issue,
        // so here we check that filename is amongst user files. 
        private static void FixErrorPosition(CompilerError error, List scriptsForLang) {
            string fileName = error.FileName; 
            foreach (ScriptClass script in scriptsForLang) { 
                foreach (string scriptFile in script.scriptFiles) {
                    // We assume that CodeDom provider returns absolute paths (VSWhidbey 289665). 
                    // Note that casing may be different.
                    if (fileName.Equals(scriptFile, fileNameComparison)) {
                        // The error position is within one of user stylesheets, its filename may be reported
                        error.FileName = scriptFile; 
                        return;
                    } 
                } 
            }
 
            // Error is outside user code snippeets, we should hide filename for security reasons.
            // Return filename and position of the end of the last script block for the given class.
            int idx, scriptNumber;
            ScriptClass errScript = scriptsForLang[scriptsForLang.Count - 1]; 

            // Normally temporary source files are named according to the scheme ".
                        

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