File: AuthoringOM\Compiler\XomlCompilerParameters.cs
Project: ndp\cdf\src\WF\Common\System.Workflow.ComponentModel.csproj (System.Workflow.ComponentModel)
namespace System.Workflow.ComponentModel.Compiler
{
    #region Imports
 
    using System;
    using System.Text;
    using System.Collections;
    using System.Collections.Specialized;
    using System.Collections.Generic;
    using System.CodeDom;
    using System.Reflection;
    using System.CodeDom.Compiler;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.Runtime.Serialization;
    using System.Diagnostics;
    using System.Text.RegularExpressions;
    using System.Runtime.Versioning;
    using System.Security;
    using Microsoft.Build.Utilities;
    using System.IO;
    using System.Runtime.InteropServices;
 
    #endregion
 
    [Serializable]
    class MultiTargetingInfo : ISerializable
    {
        internal static readonly Version DefaultTargetFramework = new Version("4.0");
 
        static readonly Version TargetFramework30 = new Version("3.0");
        internal const string TargetFramework30CompilerVersion = "v2.0";
        static readonly Version TargetFramework35 = new Version("3.5");
        internal const string TargetFramework35CompilerVersion = "v3.5";
        static readonly Version TargetFramework40 = new Version("4.0");
        internal const string TargetFramework40CompilerVersion = "v4.0";
        const string TargetFramework40CompatiblePrefix = "v4.";
 
        const string SerializationItem_TargetFramework = "TargetFramework";
 
        static IDictionary<Version, string> KnownSupportedTargetFrameworksAndRelatedCompilerVersions =
            new Dictionary<Version, string>()
            { { TargetFramework30, TargetFramework30CompilerVersion }, { TargetFramework35, TargetFramework35CompilerVersion }, 
              { TargetFramework40, TargetFramework40CompilerVersion } };
 
        FrameworkName targetFramework;
        string compilerVersion;
 
        public MultiTargetingInfo(string targetFramework)
        {
            this.targetFramework = new FrameworkName(targetFramework);
        }
 
        protected MultiTargetingInfo(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
            {
                throw new ArgumentNullException("info");
            }
 
            this.targetFramework = new FrameworkName(info.GetString(MultiTargetingInfo.SerializationItem_TargetFramework));
        }
 
        public FrameworkName TargetFramework
        {
            get
            {
                return this.targetFramework;
            }
        }
        public string CompilerVersion
        {
            get
            {
                if (this.compilerVersion == null)
                {
                    this.compilerVersion = MultiTargetingInfo.GetCompilerVersion(this.targetFramework.Version);
                }
                return this.compilerVersion;
            }
        }
 
        [SecurityCritical]
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            if (info == null)
            {
                throw new ArgumentNullException("info");
            }
 
            info.AddValue(MultiTargetingInfo.SerializationItem_TargetFramework, this.targetFramework.FullName, typeof(string));
        }
 
        static string GetCompilerVersion(Version targetFrameworkVersion)
        {
            // As part of the future fx support - every 4.X framework is colided to 4.0
            Version versionKey;
            if (targetFrameworkVersion.Major == 4)
            {
                versionKey = TargetFramework40;
            }
            else
            {
                versionKey = new Version(targetFrameworkVersion.Major, targetFrameworkVersion.Minor);
            }
 
            string compilerVersion;
            if (!MultiTargetingInfo.KnownSupportedTargetFrameworksAndRelatedCompilerVersions.TryGetValue(versionKey, out compilerVersion))
            {
                compilerVersion = string.Empty;
            }
            return compilerVersion;
        }
 
        public static class MultiTargetingUtilities
        {
            const string RuntimeReferencePrefix = "<RUNTIME>";
            const string FrameworkReferencePrefix = "<FRAMEWORK>";
 
            static RuntimeManager runtimeManager;
            static ReferenceManager refManager;
 
            public static bool IsFrameworkReferenceAssembly(string path)
            {
                EnsureReferenceManager();
                return refManager.IsFrameworkReferenceAssembly(path);
            }
 
            public static WorkflowCompilerParameters NormalizeReferencedAssemblies(WorkflowCompilerParameters parameters)
            {
                EnsureRuntimeManager();
                EnsureReferenceManager();
                string[] normalizedAssemblies = new string[parameters.ReferencedAssemblies.Count];
                bool wasNormelized = false;
                for (int i = 0; i < parameters.ReferencedAssemblies.Count; i++)
                {
                    normalizedAssemblies[i] = NormalizePath(parameters.ReferencedAssemblies[i], ref wasNormelized);
                }
                if (wasNormelized)
                {
                    return new WorkflowCompilerParameters(parameters, normalizedAssemblies);
                }
                else
                {
                    return parameters;
                }
            }
            public static WorkflowCompilerParameters RenormalizeReferencedAssemblies(WorkflowCompilerParameters parameters)
            {
                EnsureRuntimeManager();
                EnsureReferenceManager();
                string[] renormalizedAssemblies = new string[parameters.ReferencedAssemblies.Count];
                bool wasRenormelized = false;
                for (int i = 0; i < parameters.ReferencedAssemblies.Count; i++)
                {
                    renormalizedAssemblies[i] = RenormalizePath(parameters.ReferencedAssemblies[i], ref wasRenormelized);
                }
                if (wasRenormelized)
                {
                    return new WorkflowCompilerParameters(parameters, renormalizedAssemblies);
                }
                else
                {
                    return parameters;
                }
            }
 
            static void EnsureRuntimeManager()
            {
                if (runtimeManager == null)
                {
                    runtimeManager = new RuntimeManager();
                }
            }
            static void EnsureReferenceManager()
            {
                if (refManager == null)
                {
                    refManager = new ReferenceManager();
                }
            }
 
            static string NormalizePath(string path, ref bool wasNormelized)
            {
                path = Path.GetFullPath(path);
                if (IsPathUnderDirectory(path, runtimeManager.NetFxRuntimeRoot))
                {
                    wasNormelized = true;
                    return path.Replace(runtimeManager.NetFxRuntimeRoot, RuntimeReferencePrefix);
                }
                else if (IsPathUnderDirectory(path, refManager.FrameworkReferenceAssemblyRoot))
                {
                    wasNormelized = true;
                    return path.Replace(refManager.FrameworkReferenceAssemblyRoot, FrameworkReferencePrefix);
                }
                else
                {
                    return path;
                }
            }
            static string RenormalizePath(string path, ref bool wasRenormelized)
            {
                if (path.StartsWith(RuntimeReferencePrefix, StringComparison.Ordinal))
                {
                    wasRenormelized = true;
                    return path.Replace(RuntimeReferencePrefix, runtimeManager.NetFxRuntimeRoot);
                }
                else if (path.StartsWith(FrameworkReferencePrefix, StringComparison.Ordinal))
                {
                    wasRenormelized = true;
                    return path.Replace(FrameworkReferencePrefix, refManager.FrameworkReferenceAssemblyRoot);
                }
                else
                {
                    return path;
                }
            }
            static bool IsPathUnderDirectory(string path, string parentDirectory)
            {
                if (!path.StartsWith(parentDirectory, StringComparison.CurrentCultureIgnoreCase))
                {
                    return false;
                }
                int parentLength = parentDirectory.Length;
                if (path.Length == parentLength)
                {
                    return false;
                }
                if ((path[parentLength] != Path.DirectorySeparatorChar) && (path[parentLength] != Path.AltDirectorySeparatorChar))
                {
                    return false;
                }
 
                return true;
            }
 
            class RuntimeManager
            {
                const string NDPSetupRegistryBranch = "SOFTWARE\\Microsoft\\NET Framework Setup\\NDP";
 
                string netFxRuntimeRoot;
 
                public RuntimeManager()
                {
                    string runtimePath = XomlCompilerHelper.TrimDirectorySeparatorChar(RuntimeEnvironment.GetRuntimeDirectory());
                    this.netFxRuntimeRoot = XomlCompilerHelper.TrimDirectorySeparatorChar(Path.GetDirectoryName(runtimePath));
                }
 
                public string NetFxRuntimeRoot
                {
                    get
                    {
                        return this.netFxRuntimeRoot;
                    }
                }
            }
            class ReferenceManager
            {
                string frameworkReferenceAssemblyRoot;
                HashSet<string> frameworkReferenceDirectories;
 
                public ReferenceManager()
                {
                    this.frameworkReferenceAssemblyRoot = ToolLocationHelper.GetProgramFilesReferenceAssemblyRoot();
                    this.frameworkReferenceDirectories = new HashSet<string>(StringComparer.CurrentCultureIgnoreCase);
 
                    IList<string> supportedTargetFrameworks = ToolLocationHelper.GetSupportedTargetFrameworks();
                    for (int i = 0; i < supportedTargetFrameworks.Count; i++)
                    {
                        FrameworkName fxName = new FrameworkName(supportedTargetFrameworks[i]);
                        IList<string> refDirectories = ToolLocationHelper.GetPathToReferenceAssemblies(fxName);
                        for (int j = 0; j < refDirectories.Count; j++)
                        {
                            string refDir = XomlCompilerHelper.TrimDirectorySeparatorChar(refDirectories[j]);
                            if (!this.frameworkReferenceDirectories.Contains(refDir))
                            {
                                this.frameworkReferenceDirectories.Add(refDir);
                            }
                        }
                    }
                }
 
                public string FrameworkReferenceAssemblyRoot
                {
                    get
                    {
                        return this.frameworkReferenceAssemblyRoot;
                    }
                }
 
                public bool IsFrameworkReferenceAssembly(string path)
                {
                    string dir = XomlCompilerHelper.TrimDirectorySeparatorChar(Path.GetDirectoryName(Path.GetFullPath(path)));
                    return this.frameworkReferenceDirectories.Contains(dir);
                }
            }
        }
    }
 
    [Serializable]
    [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
    public sealed class WorkflowCompilerParameters : CompilerParameters
    {
        #region Private members
 
        internal const string NoCodeSwitch = "/nocode";
        internal const string CheckTypesSwitch = "/checktypes";
 
        private bool generateCCU = false;
        private string languageToUse = "CSharp";
        private IList<CodeCompileUnit> userCodeCCUs = null;
        private StringCollection libraryPaths = null;
        private Assembly localAssembly = null;
        private bool compileWithNoCode = false;
        private bool checkTypes = false;
        private string compilerOptions = null;
        [OptionalField(VersionAdded = 2)]
        MultiTargetingInfo mtInfo = null;
 
        #endregion
 
        #region Constructors
 
        public WorkflowCompilerParameters()
        {
        }
 
        public WorkflowCompilerParameters(string[] assemblyNames)
            : base(assemblyNames)
        {
        }
 
        public WorkflowCompilerParameters(string[] assemblyNames, string outputName)
            : base(assemblyNames, outputName)
        {
        }
 
        public WorkflowCompilerParameters(string[] assemblyNames, string outputName, bool includeDebugInformation)
            : base(assemblyNames, outputName, includeDebugInformation)
        {
        }
 
        public WorkflowCompilerParameters(WorkflowCompilerParameters parameters)
            : this(parameters, null)
        {
        }
 
        internal WorkflowCompilerParameters(WorkflowCompilerParameters parameters, string[] newReferencedAssemblies)
            : this()
        {
            if (parameters == null)
            {
                throw new ArgumentNullException("parameters");
            }
 
            this.CompilerOptions = parameters.CompilerOptions;
            foreach (string embeddedResource in parameters.EmbeddedResources)
            {
                this.EmbeddedResources.Add(embeddedResource);
            }
            this.GenerateExecutable = parameters.GenerateExecutable;
            this.GenerateInMemory = parameters.GenerateInMemory;
            this.IncludeDebugInformation = parameters.IncludeDebugInformation;
            foreach (string linkedResource in parameters.LinkedResources)
            {
                this.LinkedResources.Add(linkedResource);
            }
            this.MainClass = parameters.MainClass;
            this.OutputAssembly = parameters.OutputAssembly;
            if (newReferencedAssemblies != null)
            {
                this.ReferencedAssemblies.AddRange(newReferencedAssemblies);
            }
            else
            {
                foreach (string referenceAssembly in parameters.ReferencedAssemblies)
                {
                    this.ReferencedAssemblies.Add(referenceAssembly);
                }
            }
            this.TreatWarningsAsErrors = parameters.TreatWarningsAsErrors;
            this.UserToken = parameters.UserToken;
            this.WarningLevel = parameters.WarningLevel;
            this.Win32Resource = parameters.Win32Resource;
 
            this.generateCCU = parameters.generateCCU;
            this.languageToUse = parameters.languageToUse;
            if (parameters.libraryPaths != null)
            {
                this.libraryPaths = new StringCollection();
                foreach (string libraryPath in parameters.libraryPaths)
                {
                    this.libraryPaths.Add(libraryPath);
                }
            }
            if (parameters.userCodeCCUs != null)
            {
                this.userCodeCCUs = new List<CodeCompileUnit>(parameters.userCodeCCUs);
            }
            this.localAssembly = parameters.localAssembly;
        }
 
        #endregion
 
        #region Properties
 
        public new string CompilerOptions
        {
            get
            {
                return this.compilerOptions;
            }
 
            set
            {
                this.compilerOptions = value;
                base.CompilerOptions =
                    XomlCompilerHelper.ProcessCompilerOptions(value, out this.compileWithNoCode, out this.checkTypes);
            }
        }
 
        public bool GenerateCodeCompileUnitOnly
        {
            get
            {
                return this.generateCCU;
            }
            set
            {
                this.generateCCU = value;
            }
        }
 
        public string LanguageToUse
        {
            get
            {
                return this.languageToUse;
            }
            set
            {
                if (String.IsNullOrEmpty(value))
                    throw new ArgumentNullException("value");
 
                if (String.Compare(value, SupportedLanguages.CSharp.ToString(), StringComparison.OrdinalIgnoreCase) != 0 &&
                    String.Compare(value, SupportedLanguages.VB.ToString(), StringComparison.OrdinalIgnoreCase) != 0)
                    throw new NotSupportedException(SR.GetString(SR.Error_LanguageNeedsToBeVBCSharp, value));
 
                this.languageToUse = value;
            }
        }
 
        public StringCollection LibraryPaths
        {
            get
            {
                if (this.libraryPaths == null)
                    this.libraryPaths = new StringCollection();
 
                return this.libraryPaths;
            }
        }
 
        public IList<CodeCompileUnit> UserCodeCompileUnits
        {
            get
            {
                if (this.userCodeCCUs == null)
                    this.userCodeCCUs = new List<CodeCompileUnit>();
                return this.userCodeCCUs;
            }
        }
 
        internal Assembly LocalAssembly
        {
            get
            {
                return this.localAssembly;
            }
            set
            {
                this.localAssembly = value;
            }
        }
 
        internal bool CompileWithNoCode
        {
            get
            {
                return this.compileWithNoCode;
            }
        }
 
        internal bool CheckTypes
        {
            get
            {
                return this.checkTypes;
            }
        }
 
        internal string CompilerVersion
        {
            get
            {
                if (this.mtInfo == null)
                {
                    return string.Empty;
                }
                else
                {
                    return this.mtInfo.CompilerVersion;
                }
            }
        }
 
        internal MultiTargetingInfo MultiTargetingInformation
        {
            get
            {
                return this.mtInfo;
            }
            set
            {
                this.mtInfo = value;
            }
        }
 
        #endregion
 
        internal static string ExtractRootNamespace(WorkflowCompilerParameters parameters)
        {
            string rootNamespace = string.Empty;
 
            // extract the namespace from the compiler options
            if (parameters.CompilerOptions != null && (CompilerHelpers.GetSupportedLanguage(parameters.LanguageToUse) == SupportedLanguages.VB))
            {
                Regex options = new Regex(@"\s*[/-]rootnamespace[:=]\s*(?<RootNamespace>[^\s]*)");
                Match match = options.Match(parameters.CompilerOptions);
 
                if (match.Success)
                    rootNamespace = match.Groups["RootNamespace"].Value;
            }
            return rootNamespace;
        }
    }
}