File: AuthoringOM\Compiler\XomlCompiler.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.Collections;
    using System.Collections.Specialized;
    using System.Collections.Generic;
    using System.CodeDom;
    using System.ComponentModel;
    using System.ComponentModel.Design;
    using System.CodeDom.Compiler;
    using System.Reflection;
    using System.ComponentModel.Design.Serialization;
    using System.Xml;
    using System.Globalization;
    using System.IO;
    using System.Text;
    using System.Diagnostics;
    using System.Text.RegularExpressions;
    using Microsoft.CSharp;
    using Microsoft.VisualBasic;
    using System.Workflow.ComponentModel.Design;
    using System.Workflow.ComponentModel.Serialization;
    using System.Security.Policy;
    using System.Runtime.Versioning;
    using System.Configuration;
    using System.Collections.ObjectModel;
 
    #endregion
 
    #region WorkflowMarkupSourceAttribute Class
    [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
    [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
    public sealed class WorkflowMarkupSourceAttribute : Attribute
    {
        private string fileName;
        private string md5Digest;
 
        public WorkflowMarkupSourceAttribute(string fileName, string md5Digest)
        {
            this.fileName = fileName;
            this.md5Digest = md5Digest;
        }
 
        public string FileName
        {
            get
            {
                return this.fileName;
            }
        }
 
        public string MD5Digest
        {
            get
            {
                return this.md5Digest;
            }
        }
    }
    #endregion
 
    #region Interface IWorkflowCompilerOptionsService
    [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
    public interface IWorkflowCompilerOptionsService
    {
        string RootNamespace { get; }
        string Language { get; }
        bool CheckTypes { get; }
    }
 
    [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
    public class WorkflowCompilerOptionsService : IWorkflowCompilerOptionsService
    {
        internal const string DefaultLanguage = "CSharp";
 
        public virtual string RootNamespace
        {
            get
            {
                return string.Empty;
            }
        }
        public virtual string Language
        {
            get
            {
                return WorkflowCompilerOptionsService.DefaultLanguage;
            }
        }
        public virtual bool CheckTypes
        {
            get
            {
                return false;
            }
        }
        public virtual string TargetFrameworkMoniker
        {
            get
            {
                return string.Empty;
            }
        }
    }
    #endregion
 
    #region WorkflowCompilationContext
 
    [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
    public sealed class WorkflowCompilationContext
    {
        [ThreadStatic]
        static WorkflowCompilationContext current = null;
 
        ContextScope scope;
        ReadOnlyCollection<AuthorizedType> authorizedTypes;
 
        WorkflowCompilationContext(ContextScope scope)
        {
            this.scope = scope;
        }
 
        public static WorkflowCompilationContext Current
        {
            get
            {
                return WorkflowCompilationContext.current;
            }
            private set
            {
                WorkflowCompilationContext.current = value;
            }
        }
 
        public string RootNamespace
        {
            get
            {
                return this.scope.RootNamespace;
            }
        }
        public string Language
        {
            get
            {
                return this.scope.Language;
            }
        }
        public bool CheckTypes
        {
            get
            {
                return this.scope.CheckTypes;
            }
        }
 
        internal FrameworkName TargetFramework
        {
            get
            {
                return this.scope.TargetFramework;
            }
        }
        internal Version TargetFrameworkVersion
        {
            get
            {
                FrameworkName fx = this.scope.TargetFramework;
                if (fx != null)
                {
                    return fx.Version;
                }
                else
                {
                    return MultiTargetingInfo.DefaultTargetFramework;
                }
            }
        }
        internal IServiceProvider ServiceProvider
        {
            get
            {
                return this.scope;
            }
        }
 
        public static IDisposable CreateScope(IServiceProvider serviceProvider)
        {
            if (serviceProvider == null)
            {
                throw new ArgumentNullException("serviceProvider");
            }
 
            IWorkflowCompilerOptionsService optionsService = serviceProvider.GetService(typeof(IWorkflowCompilerOptionsService)) as IWorkflowCompilerOptionsService;
            if (optionsService != null)
            {
                return CreateScope(serviceProvider, optionsService);
            }
            else
            {
                return new DefaultContextScope(serviceProvider);
            }
        }
 
        public IList<AuthorizedType> GetAuthorizedTypes()
        {
            if (this.authorizedTypes == null)
            {
                try
                {
                    IList<AuthorizedType> authorizedTypes;
 
                    IDictionary<string, IList<AuthorizedType>> authorizedTypesDictionary =
                        ConfigurationManager.GetSection("System.Workflow.ComponentModel.WorkflowCompiler/authorizedTypes") as IDictionary<string, IList<AuthorizedType>>;
                    Version targetVersion = null;
                    FrameworkName framework = this.scope.TargetFramework;
                    if (framework != null)
                    {
                        targetVersion = framework.Version;
                    }
                    else
                    {
                        targetVersion = MultiTargetingInfo.DefaultTargetFramework;
                    }
 
                    string normalizedVersionString = string.Format(CultureInfo.InvariantCulture, "v{0}.{1}", targetVersion.Major, targetVersion.Minor);
 
                    if (authorizedTypesDictionary.TryGetValue(normalizedVersionString, out authorizedTypes))
                    {
                        this.authorizedTypes = new ReadOnlyCollection<AuthorizedType>(authorizedTypes);
                    }
                }
                catch
                {
                }
            }
            return this.authorizedTypes;
        }
 
        internal static IDisposable CreateScope(IServiceProvider serviceProvider, WorkflowCompilerParameters parameters)
        {
            return new ParametersContextScope(serviceProvider, parameters);
        }
 
        static IDisposable CreateScope(IServiceProvider serviceProvider, IWorkflowCompilerOptionsService optionsService)
        {
            WorkflowCompilerOptionsService standardService = optionsService as WorkflowCompilerOptionsService;
            if (standardService != null)
            {
                return new StandardContextScope(serviceProvider, standardService);
            }
            else
            {
                return new InterfaceContextScope(serviceProvider, optionsService);
            }
        }
 
        abstract class ContextScope : IDisposable, IServiceProvider
        {
            IServiceProvider serviceProvider;
            WorkflowCompilationContext currentContext;
            bool disposed;
 
            protected ContextScope(IServiceProvider serviceProvider)
            {
                this.serviceProvider = serviceProvider;
                this.currentContext = WorkflowCompilationContext.Current;
                WorkflowCompilationContext.Current = new WorkflowCompilationContext(this);
            }
            ~ContextScope()
            {
                DisposeImpl();
            }
 
            public abstract string RootNamespace { get; }
            public abstract string Language { get; }
            public abstract bool CheckTypes { get; }
            public abstract FrameworkName TargetFramework { get; }
 
            public void Dispose()
            {
                DisposeImpl();
                GC.SuppressFinalize(this);
            }
            public object GetService(Type serviceType)
            {
                return this.serviceProvider.GetService(serviceType);
            }
 
            void DisposeImpl()
            {
                if (!this.disposed)
                {
                    WorkflowCompilationContext.Current = this.currentContext;
                    this.disposed = true;
                }
            }
        }
        class InterfaceContextScope : ContextScope
        {
            IWorkflowCompilerOptionsService service;
 
            public InterfaceContextScope(IServiceProvider serviceProvider, IWorkflowCompilerOptionsService service)
                : base(serviceProvider)
            {
                this.service = service;
            }
 
            public override string RootNamespace
            {
                get
                {
                    return this.service.RootNamespace;
                }
            }
            public override string Language
            {
                get
                {
                    return this.service.Language;
                }
            }
            public override bool CheckTypes
            {
                get
                {
                    return this.service.CheckTypes;
                }
            }
            public override FrameworkName TargetFramework
            {
                get
                {
                    return null;
                }
            }
        }
        class StandardContextScope : ContextScope
        {
            WorkflowCompilerOptionsService service;
            FrameworkName fxName;
 
            public StandardContextScope(IServiceProvider serviceProvider, WorkflowCompilerOptionsService service)
                : base(serviceProvider)
            {
                this.service = service;
            }
 
            public override string RootNamespace
            {
                get
                {
                    return this.service.RootNamespace;
                }
            }
            public override string Language
            {
                get
                {
                    return this.service.Language;
                }
            }
            public override bool CheckTypes
            {
                get
                {
                    return this.service.CheckTypes;
                }
            }
            public override FrameworkName TargetFramework
            {
                get
                {
                    if (this.fxName == null)
                    {
                        string fxName = this.service.TargetFrameworkMoniker;
                        if (!string.IsNullOrEmpty(fxName))
                        {
                            this.fxName = new FrameworkName(fxName);
                        }
                    }
                    return this.fxName;
                }
            }
        }
        class ParametersContextScope : ContextScope
        {
            WorkflowCompilerParameters parameters;
 
            public ParametersContextScope(IServiceProvider serviceProvider, WorkflowCompilerParameters parameters)
                : base(serviceProvider)
            {
                this.parameters = parameters;
            }
 
            public override string RootNamespace
            {
                get
                {
                    return WorkflowCompilerParameters.ExtractRootNamespace(this.parameters);
                }
            }
            public override string Language
            {
                get
                {
                    return this.parameters.LanguageToUse;
                }
            }
 
            public override bool CheckTypes
            {
                get
                {
                    return this.parameters.CheckTypes;
                }
            }
            public override FrameworkName TargetFramework
            {
                get
                {
                    if (this.parameters.MultiTargetingInformation != null)
                    {
                        return this.parameters.MultiTargetingInformation.TargetFramework;
                    }
                    else
                    {
                        return null;
                    }
                }
            }
        }
        class DefaultContextScope : ContextScope
        {
            public DefaultContextScope(IServiceProvider serviceProvider)
                : base(serviceProvider)
            {
            }
 
            public override string RootNamespace
            {
                get
                {
                    return string.Empty;
                }
            }
            public override string Language
            {
                get
                {
                    return WorkflowCompilerOptionsService.DefaultLanguage;
                }
            }
            public override bool CheckTypes
            {
                get
                {
                    return false;
                }
            }
            public override FrameworkName TargetFramework
            {
                get
                {
                    return null;
                }
            }
        }
    }
 
    #endregion
 
    #region Class WorkflowCompiler
 
    [Obsolete("The System.Workflow.* types are deprecated.  Instead, please use the new types from System.Activities.*")]
    public sealed class WorkflowCompiler
    {
        public WorkflowCompilerResults Compile(WorkflowCompilerParameters parameters, params string[] files)
        {
            if (parameters == null)
                throw new ArgumentNullException("parameters");
            if (files == null)
                throw new ArgumentNullException("files");
 
            string createdDirectoryName = null;
            string createdTempFileName = null;
 
            AppDomainSetup setup = AppDomain.CurrentDomain.SetupInformation;
            setup.LoaderOptimization = LoaderOptimization.MultiDomainHost;
            AppDomain compilerDomain = AppDomain.CreateDomain("CompilerDomain", null, setup);
 
            bool generateInMemory = false;
            string originalOutputAssembly = parameters.OutputAssembly;
 
            try
            {
                if (parameters.GenerateInMemory)
                {
                    generateInMemory = true;
                    parameters.GenerateInMemory = false;
 
                    if (string.IsNullOrEmpty(parameters.OutputAssembly))
                    {
                        // We need to remember the filename generated by Path.GetTempFileName so we can clean it up.
                        createdTempFileName = Path.GetTempFileName();
                        parameters.OutputAssembly = createdTempFileName + ".dll";
                    }
                    else
                    {
                        int tries = 0;
                        while (true)
                        {
                            try
                            {
                                tries++;
                                createdDirectoryName = Path.GetTempPath() + "\\" + Guid.NewGuid();
                                DirectoryInfo info = Directory.CreateDirectory(createdDirectoryName);
                                parameters.OutputAssembly = info.FullName + "\\" + parameters.OutputAssembly;
                                break;
                            }
                            catch
                            {
                                // If we have tried 10 times without success, give up. Something must be wrong
                                // with what gets returned by GetTempPath or we have exceeded max_path by appending
                                // the GUID.
                                if (tries >= 10)
                                {
                                    throw;
                                }
                            }
                        }
                    }
                }
 
                WorkflowCompilerInternal compiler = (WorkflowCompilerInternal)compilerDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(WorkflowCompilerInternal).FullName);
                WorkflowCompilerResults results = compiler.Compile(parameters, files);
 
                if (generateInMemory && !results.Errors.HasErrors)
                {
                    results.CompiledAssembly = Assembly.Load(File.ReadAllBytes(results.PathToAssembly));
                    results.PathToAssembly = null;
                }
 
                return results;
            }
            finally
            {
                string outputAssembly = parameters.OutputAssembly;
 
                if (generateInMemory)
                {
                    parameters.GenerateInMemory = true;
                    parameters.OutputAssembly = originalOutputAssembly;
                }
 
                AppDomain.Unload(compilerDomain);
 
                // The temp file must be deleted after the app domain is unloaded, or else it will
                // be "busy", causing the delete to throw an access exception.
                if (generateInMemory)
                {
                    try
                    {
                        // There will always be an outputAssemblyName to delete.
                        File.Delete(outputAssembly);
 
                        // If we created a temp file name with Path.GetTempFileName, we need to delete it here.
                        if (createdTempFileName != null)
                        {
                            File.Delete(createdTempFileName);
                        }
 
                        // If we created a directory, delete it.
                        if (createdDirectoryName != null)
                        {
                            Directory.Delete(createdDirectoryName, true);
                        }
                    }
                    catch
                    { }
                }
            }
        }
    }
 
    #endregion
 
    #region Class TypeAuthorizerClass
    internal sealed class TypeAuthorizerClass : ITypeAuthorizer
    {
        public TypeAuthorizerClass(IList<AuthorizedType> authorizedTypes, WorkflowCompilerResults results, string filename)
        {
            if (results == null)
            {
                throw new ArgumentNullException("results");
            }
            if (string.IsNullOrWhiteSpace(filename))
            {
                throw new ArgumentException("filename");
            }
            // It is okay for authorizedTypes to be null. Nothing may have been specified in the config.
 
            this.AuthorizedTypes = authorizedTypes;
            this.Results = results;
            this.Filename = filename;
        }
 
        public IList<AuthorizedType> AuthorizedTypes
        {
            get;
            private set;
        }
 
        public WorkflowCompilerResults Results
        {
            get;
            private set;
        }
 
        public string Filename
        {
            get;
            private set;
        }
 
        public bool IsTypeAuthorized(Type typeToAuthorize)
        {
            if (typeToAuthorize == null)
            {
                Results.Errors.Add(new WorkflowCompilerError(this.Filename, -1, -1, ErrorNumbers.Error_TypeNotAuthorized.ToString(CultureInfo.InvariantCulture), SR.GetString(SR.Error_TypeNotAuthorized, SR.GetString(SR.NullConditionExpression))));
                return false;
            }
 
            bool authorized = false;
            if (AuthorizedTypes != null)
            {
                foreach (AuthorizedType authorizedType in AuthorizedTypes)
                {
                    if (authorizedType.RegularExpression.IsMatch(typeToAuthorize.AssemblyQualifiedName))
                    {
                        authorized = (String.Compare(bool.TrueString, authorizedType.Authorized, StringComparison.OrdinalIgnoreCase) == 0);
                        if (!authorized)
                            break;
                    }
                }
            }
 
            if (!authorized)
            {
                Results.Errors.Add(new WorkflowCompilerError(this.Filename, -1, -1, ErrorNumbers.Error_TypeNotAuthorized.ToString(CultureInfo.InvariantCulture), SR.GetString(SR.Error_TypeNotAuthorized, typeToAuthorize)));
            }
 
            return authorized;
        }
    }
    #endregion
 
    #region Class WorkflowCompilerInternal
 
    internal sealed class WorkflowCompilerInternal : MarshalByRefObject
    {
        #region Lifetime service
 
        public override object InitializeLifetimeService()
        {
            return null;
        }
 
        #endregion
 
        #region File based compilation
 
        public WorkflowCompilerResults Compile(WorkflowCompilerParameters parameters, string[] allFiles)
        {
            WorkflowCompilerResults results = new WorkflowCompilerResults(parameters.TempFiles);
 
            // Split the xoml files from cs/vb files.
            StringCollection xomlFiles = new StringCollection();
            StringCollection userCodeFiles = new StringCollection();
            foreach (string file in allFiles)
            {
                if (file.EndsWith(".xoml", StringComparison.OrdinalIgnoreCase))
                    xomlFiles.Add(file);
                else
                    userCodeFiles.Add(file);
            }
 
            string[] files = new string[xomlFiles.Count];
            xomlFiles.CopyTo(files, 0);
            string[] codeFiles = new string[userCodeFiles.Count];
            userCodeFiles.CopyTo(codeFiles, 0);
 
            string mscorlibPath = typeof(object).Assembly.Location;
            ServiceContainer serviceContainer = new ServiceContainer();
            MultiTargetingInfo mtInfo = parameters.MultiTargetingInformation;
            if (mtInfo == null)
            {
                XomlCompilerHelper.FixReferencedAssemblies(parameters, results, parameters.LibraryPaths);
            }
            string mscorlibName = Path.GetFileName(mscorlibPath);
 
            // Add assembly resolver.
            ReferencedAssemblyResolver resolver = new ReferencedAssemblyResolver(parameters.ReferencedAssemblies, parameters.LocalAssembly);
            AppDomain.CurrentDomain.AssemblyResolve += resolver.ResolveEventHandler;
 
            // prepare service container
            TypeProvider typeProvider = new TypeProvider(new ServiceContainer());
            int mscorlibIndex = -1;
            if ((parameters.ReferencedAssemblies != null) && (parameters.ReferencedAssemblies.Count > 0))
            {
                for (int i = 0; i < parameters.ReferencedAssemblies.Count; i++)
                {
                    string assemblyPath = parameters.ReferencedAssemblies[i];
                    if ((mscorlibIndex == -1) && (string.Compare(mscorlibName, Path.GetFileName(assemblyPath), StringComparison.OrdinalIgnoreCase) == 0))
                    {
                        mscorlibIndex = i;
                        mscorlibPath = assemblyPath;
                    }
                    typeProvider.AddAssemblyReference(assemblyPath);
                }
            }
            // a note about references to mscorlib:
            //  If we found mscorlib in the list of reference assemblies, we should remove it prior to sending it to the CodeDOM compiler.
            //  The CodeDOM compiler would add the right mscorlib [based on the version of the provider we use] and the duplication would
            //  cause a compilation error.
            //  If we didn't found a reference to mscorlib we need to add it to the type-provider, though, so we will support exposing
            //  those known types.
            if (mscorlibIndex != -1)
            {
                parameters.ReferencedAssemblies.RemoveAt(mscorlibIndex);
                if (string.IsNullOrEmpty(parameters.CoreAssemblyFileName))
                {
                    parameters.CoreAssemblyFileName = mscorlibPath;
                }
            }
            else
            {
                typeProvider.AddAssemblyReference(mscorlibPath);
            }
 
            serviceContainer.AddService(typeof(ITypeProvider), typeProvider);
            
            TempFileCollection intermediateTempFiles = null;
            string localAssemblyPath = string.Empty;
            string createdDirectoryName = null;
 
            try
            {
                using (WorkflowCompilationContext.CreateScope(serviceContainer, parameters))
                {
                    parameters.LocalAssembly = GenerateLocalAssembly(files, codeFiles, parameters, results, out intermediateTempFiles, out localAssemblyPath, out createdDirectoryName);
                    if (parameters.LocalAssembly != null)
                    {
                        // WinOE Bug 17591: we must set the local assembly here,
                        // otherwise, the resolver won't be able to resolve custom types correctly.
                        resolver.SetLocalAssembly(parameters.LocalAssembly);
 
                        // Work around HERE!!!
                        // prepare type provider
                        typeProvider.SetLocalAssembly(parameters.LocalAssembly);
                        typeProvider.AddAssembly(parameters.LocalAssembly);
 
                        results.Errors.Clear();
                        XomlCompilerHelper.InternalCompileFromDomBatch(files, codeFiles, parameters, results, localAssemblyPath);
                    }
                }
            }
            catch (Exception e)
            {
                results.Errors.Add(new WorkflowCompilerError(String.Empty, -1, -1, ErrorNumbers.Error_UnknownCompilerException.ToString(CultureInfo.InvariantCulture), SR.GetString(SR.Error_CompilationFailed, e.Message)));
            }
            finally
            {
                // Delate the temp files.
                if (intermediateTempFiles != null && parameters.TempFiles.KeepFiles == false)
                {
                    foreach (string file in intermediateTempFiles)
                    {
                        try
                        {
                            System.IO.File.Delete(file);
                        }
                        catch
                        {
                        }
                    }
 
                    try
                    {
                        // GenerateLocalAssembly may have created a directory, so let's try to delete it
                        // We can't just delete Path.GetDirectoryName(localAssemblyPath) because it might be the Temp directory.
                        if (createdDirectoryName != null)
                        {
                            Directory.Delete(createdDirectoryName, true);
                        }
                    }
                    catch
                    {
                    }
                }
            }
 
            return results;
        }
 
        #endregion
 
        #region Code for Generating Local Assembly
 
        private static ValidationErrorCollection ValidateIdentifiers(IServiceProvider serviceProvider, Activity activity)
        {
            ValidationErrorCollection validationErrors = new ValidationErrorCollection();
            Dictionary<string, int> names = new Dictionary<string, int>();
 
            Walker walker = new Walker();
            walker.FoundActivity += delegate(Walker walker2, WalkerEventArgs e)
            {
                Activity currentActivity = e.CurrentActivity;
                if (!currentActivity.Enabled)
                {
                    e.Action = WalkerAction.Skip;
                    return;
                }
 
                ValidationError identifierError = null;
 
                if (names.ContainsKey(currentActivity.QualifiedName))
                {
                    if (names[currentActivity.QualifiedName] != 1)
                    {
                        identifierError = new ValidationError(SR.GetString(SR.Error_DuplicatedActivityID, currentActivity.QualifiedName), ErrorNumbers.Error_DuplicatedActivityID, false, "Name");
                        identifierError.UserData[typeof(Activity)] = currentActivity;
                        validationErrors.Add(identifierError);
                        names[currentActivity.QualifiedName] = 1;
                    }
 
                    return;
                }
                // Undone: AkashS - remove this check when we allow root activities to not have a name.
                if (!string.IsNullOrEmpty(currentActivity.Name))
                {
                    names[currentActivity.Name] = 0;
                    identifierError = ValidationHelpers.ValidateIdentifier("Name", serviceProvider, currentActivity.Name);
                    if (identifierError != null)
                    {
                        identifierError.UserData[typeof(Activity)] = currentActivity;
                        validationErrors.Add(identifierError);
                    }
                }
            };
 
            walker.Walk(activity as Activity);
            return validationErrors;
        }
 
        private Assembly GenerateLocalAssembly(string[] files, string[] codeFiles, WorkflowCompilerParameters parameters, WorkflowCompilerResults results, out TempFileCollection tempFiles2, out string localAssemblyPath, out string createdDirectoryName)
        {
            localAssemblyPath = string.Empty;
            createdDirectoryName = null;
            tempFiles2 = null;
 
            // Generate code for the markup files.
            CodeCompileUnit markupCompileUnit = GenerateCodeFromFileBatch(files, parameters, results);
            if (results.Errors.HasErrors)
                return null;
 
            SupportedLanguages language = CompilerHelpers.GetSupportedLanguage(parameters.LanguageToUse);
 
            // Convert all compile units to source files.
            CodeDomProvider codeDomProvider = CompilerHelpers.GetCodeDomProvider(language, parameters.CompilerVersion);
 
            // Clone the parameters.
            CompilerParameters clonedParams = XomlCompilerHelper.CloneCompilerParameters(parameters);
            clonedParams.TempFiles.KeepFiles = true;
            tempFiles2 = clonedParams.TempFiles;
 
            clonedParams.GenerateInMemory = true;
 
            if (string.IsNullOrEmpty(parameters.OutputAssembly))
                localAssemblyPath = clonedParams.OutputAssembly = clonedParams.TempFiles.AddExtension("dll");
            else
            {
                string tempAssemblyDirectory = clonedParams.TempFiles.BasePath;
                int postfix = 0;
                while (true)
                {
                    try
                    {
                        if (Directory.Exists(tempAssemblyDirectory))
                        {
                            break;
                        }
                        Directory.CreateDirectory(tempAssemblyDirectory);
                        createdDirectoryName = tempAssemblyDirectory;
                        break;
                    }
                    catch
                    {
                        // If we have tried 10 times without success, give up. Something must be wrong
                        // with what gets returned by TempFiles.BasePath
                        if (postfix >= 10)
                        {
                            throw;
                        }
                        tempAssemblyDirectory = clonedParams.TempFiles.BasePath + postfix++;
                    }
                    
                }
                localAssemblyPath = clonedParams.OutputAssembly = tempAssemblyDirectory + "\\" + Path.GetFileName(clonedParams.OutputAssembly);
                clonedParams.TempFiles.AddFile(localAssemblyPath, true);
 
                // Working around the fact that when the OutputAssembly is specified, the
                // codeDomProvider.CompileAssemblyFromFile call below does NOT add the pdb file
                // to the clonedParams.TempFiles collection. Instead, it looks as though it
                // does a clonedParams.TempFiles.BasePath.AddExtension("pdb"), which is a file
                // that doesn't actually get created.
                // We need to add the pdb file to the clonedParameters.TempFiles collection so that
                // it gets deleted, even in the case where we didn't end up creating the tempAssemblyDirectory above.
                string pdbFilename = Path.GetFileNameWithoutExtension(localAssemblyPath) + ".pdb";
                clonedParams.TempFiles.AddFile(Path.GetDirectoryName(localAssemblyPath) + "\\" + pdbFilename, true);
            }
 
            // Explictily ignore warnings (in case the user set this property in the project options).
            clonedParams.TreatWarningsAsErrors = false;
 
            if (clonedParams.CompilerOptions != null && clonedParams.CompilerOptions.Length > 0)
            {
                // Need to remove /delaysign option together with the /keyfile or /keycontainer
                // the temp assembly should not be signed or we'll have problems loading it.
 
                // Custom splitting: need to take strings like '"one two"' into account 
                // even though it has a space inside, it should not be split.
 
                string source = clonedParams.CompilerOptions;
                ArrayList optionsList = new ArrayList();
                int begin = 0;
                int end = 0;
                bool insideString = false;
                while (end < source.Length)
                {
                    int currentLength = end - begin;
                    if (source[end] == '"')
                    {
                        insideString = !insideString;
                    }
                    else if (source[end] == ' ' && !insideString)
                    {
                        // Split only if not inside string like in "inside some string".
                        // Split here. Ignore multiple spaces.
                        if (begin == end)
                        {
                            begin++; // end will get incremented in the end of the loop.
                        }
                        else
                        {
                            string substring = source.Substring(begin, end - begin);
                            optionsList.Add(substring);
                            begin = end + 1; // end will get incremented in the end of the loop
                        }
                    }
 
                    end++;
                }
 
                // The remaining sub-string.
                if (begin != end)
                {
                    string substring = source.Substring(begin, end - begin);
                    optionsList.Add(substring);
                }
 
                string[] options = optionsList.ToArray(typeof(string)) as string[];
 
                clonedParams.CompilerOptions = string.Empty;
                foreach (string option in options)
                {
                    if (option.Length > 0 &&
                        !option.StartsWith("/delaysign", StringComparison.OrdinalIgnoreCase) &&
                        !option.StartsWith("/keyfile", StringComparison.OrdinalIgnoreCase) &&
                        !option.StartsWith("/keycontainer", StringComparison.OrdinalIgnoreCase))
                    {
                        clonedParams.CompilerOptions += " " + option;
                    }
                }
            }
 
            // Disable compiler optimizations, but include debug information.
            clonedParams.CompilerOptions = (clonedParams.CompilerOptions == null) ? "/optimize-" : clonedParams.CompilerOptions + " /optimize-";
            clonedParams.IncludeDebugInformation = true;
 
            if (language == SupportedLanguages.CSharp)
                clonedParams.CompilerOptions += " /unsafe";
 
            // Add files.
            ArrayList ccus = new ArrayList((ICollection)parameters.UserCodeCompileUnits);
            ccus.Add(markupCompileUnit);
            ArrayList userCodeFiles = new ArrayList();
            userCodeFiles.AddRange(codeFiles);
            userCodeFiles.AddRange(XomlCompilerHelper.GenerateFiles(codeDomProvider, clonedParams, (CodeCompileUnit[])ccus.ToArray(typeof(CodeCompileUnit))));
 
            // Generate the temporary assembly.
            CompilerResults results2 = codeDomProvider.CompileAssemblyFromFile(clonedParams, (string[])userCodeFiles.ToArray(typeof(string)));
            if (results2.Errors.HasErrors)
            {
                results.AddCompilerErrorsFromCompilerResults(results2);
                return null;
            }
 
 
            return results2.CompiledAssembly;
        }
 
        internal static CodeCompileUnit GenerateCodeFromFileBatch(string[] files, WorkflowCompilerParameters parameters, WorkflowCompilerResults results)
        {
            WorkflowCompilationContext context = WorkflowCompilationContext.Current;
            if (context == null)
                throw new Exception(SR.GetString(SR.Error_MissingCompilationContext));
 
            CodeCompileUnit codeCompileUnit = new CodeCompileUnit();
            foreach (string fileName in files)
            {
                TypeAuthorizerClass typeAuthorizer = null;
                // Only set up a TypeAuthorizerClass if CheckTypes is specified.
                if (parameters.CheckTypes)
                {
                    typeAuthorizer = new TypeAuthorizerClass(context.GetAuthorizedTypes(), results, fileName);
                }
 
                Activity rootActivity = null;
                try
                {
                    DesignerSerializationManager manager = new DesignerSerializationManager(context.ServiceProvider);
                    using (manager.CreateSession())
                    {
                        WorkflowMarkupSerializationManager xomlSerializationManager = new WorkflowMarkupSerializationManager(manager);
                        xomlSerializationManager.WorkflowMarkupStack.Push(parameters);
                        xomlSerializationManager.LocalAssembly = parameters.LocalAssembly;
                        using (XmlReader reader = XmlReader.Create(fileName))
                        {
                            if (typeAuthorizer == null)
                            {
                                rootActivity = WorkflowMarkupSerializationHelpers.LoadXomlDocument(xomlSerializationManager, reader, fileName);
                            }
                            else
                            {
                                rootActivity = WorkflowMarkupSerializationHelpers.LoadXomlDocument(xomlSerializationManager, reader, fileName, typeAuthorizer);
                            }
                        }
 
                        if (parameters.LocalAssembly != null)
                        {
                            foreach (object error in manager.Errors)
                            {
                                if (error is WorkflowMarkupSerializationException)
                                {
                                    results.Errors.Add(new WorkflowCompilerError(fileName, (WorkflowMarkupSerializationException)error));
                                }
                                else
                                {
                                    results.Errors.Add(new WorkflowCompilerError(fileName, -1, -1, ErrorNumbers.Error_SerializationError.ToString(CultureInfo.InvariantCulture), error.ToString()));
                                }
                            }
                        }
 
                    }
                }
                catch (WorkflowMarkupSerializationException xomlSerializationException)
                {
                    results.Errors.Add(new WorkflowCompilerError(fileName, xomlSerializationException));
                    continue;
                }
                catch (Exception e)
                {
                    results.Errors.Add(new WorkflowCompilerError(fileName, -1, -1, ErrorNumbers.Error_SerializationError.ToString(CultureInfo.InvariantCulture), SR.GetString(SR.Error_CompilationFailed, e.Message)));
                    continue;
                }
 
                if (rootActivity == null)
                {
                    results.Errors.Add(new WorkflowCompilerError(fileName, 1, 1, ErrorNumbers.Error_SerializationError.ToString(CultureInfo.InvariantCulture), SR.GetString(SR.Error_RootActivityTypeInvalid)));
                    continue;
                }
 
                bool createNewClass = (!string.IsNullOrEmpty(rootActivity.GetValue(WorkflowMarkupSerializer.XClassProperty) as string));
                if (!createNewClass)
                {
                    results.Errors.Add(new WorkflowCompilerError(fileName, 1, 1, ErrorNumbers.Error_SerializationError.ToString(CultureInfo.InvariantCulture), SR.GetString(SR.Error_CannotCompile_No_XClass)));
                    continue;
                }
 
                //NOTE: CompileWithNoCode is meaningless now. It means no x:Code in a XOML file. It exists until the FP migration is done
                //Ideally FP should just use XOML files w/o X:Class and run them w/o ever compiling them
                if ((parameters.CompileWithNoCode) && XomlCompilerHelper.HasCodeWithin(rootActivity))
                {
                    ValidationError error = new ValidationError(SR.GetString(SR.Error_CodeWithinNotAllowed), ErrorNumbers.Error_CodeWithinNotAllowed);
                    error.UserData[typeof(Activity)] = rootActivity;
                    results.Errors.Add(XomlCompilerHelper.CreateXomlCompilerError(error, parameters));
                }
 
                ValidationErrorCollection errors = new ValidationErrorCollection();
 
                errors = ValidateIdentifiers(context.ServiceProvider, rootActivity);
                foreach (ValidationError error in errors)
                    results.Errors.Add(XomlCompilerHelper.CreateXomlCompilerError(error, parameters));
 
                if (results.Errors.HasErrors)
                    continue;
 
                codeCompileUnit.Namespaces.AddRange(WorkflowMarkupSerializationHelpers.GenerateCodeFromXomlDocument(rootActivity, fileName, context.RootNamespace, CompilerHelpers.GetSupportedLanguage(context.Language), context.ServiceProvider));
            }
 
            WorkflowMarkupSerializationHelpers.FixStandardNamespacesAndRootNamespace(codeCompileUnit.Namespaces, context.RootNamespace, CompilerHelpers.GetSupportedLanguage(context.Language));
            return codeCompileUnit;
        }
        #endregion
    }
 
    #endregion
}