Exemple #1
0
        /// <summary>
        /// Creates an instance of this class for the specified task.
        /// </summary>
        public TaskEngine
        (
            XmlElement taskNodeXmlElement,
            ITaskHost hostObject,
            string projectFileOfTaskNode,
            string parentProjectFullFileName,
            EngineLoggingServices loggingServices,
            int handleId,
            TaskExecutionModule parentModule,
            BuildEventContext targetBuildEventContext
        )
        {
            ErrorUtilities.VerifyThrow(taskNodeXmlElement != null, "Need to specify the task node.");
            ErrorUtilities.VerifyThrow(projectFileOfTaskNode != null, "Need to specify path of project.");
            ErrorUtilities.VerifyThrow(parentProjectFullFileName != null, "Need to specify name of project.");
            ErrorUtilities.VerifyThrow(loggingServices != null, "Need to specify the node logger.");

            this.taskNode = taskNodeXmlElement;
            this.taskClass = null;
            this.hostObject = hostObject;
            this.projectFileOfTaskNode = projectFileOfTaskNode;
            this.parentProjectFullFileName = parentProjectFullFileName;
            this.loggingServices = loggingServices;
            this.handleId = handleId;
            this.parentModule = parentModule;
            this.continueOnError = false;
            this.conditionAttribute = taskNode.Attributes[XMakeAttributes.condition];
            this.buildEventContext = targetBuildEventContext;
        }
Exemple #2
0
        /// <summary>
        /// Indicates to the EngineProxy that it is no longer needed.
        /// Called by TaskEngine when the task using the EngineProxy is done.
        /// </summary>
        internal void MarkAsInActive()
        {
            activeProxy = false;

            // Since the task has a pointer to this class it may store it in a static field. Null out
            // internal data so the leak of this object doesn't lead to a major memory leak.
            loggingServices   = null;
            parentModule      = null;
            buildEventContext = null;

            // Clear out the sponsor (who is responsible for keeping the EngineProxy remoting lease alive until the task is done)
            // this will be null if the engineproxy was never sent accross an appdomain boundry.
            if (sponsor != null)
            {
                ILease lease = (ILease)RemotingServices.GetLifetimeService(this);

                if (lease != null)
                {
                    lease.Unregister(sponsor);
                }

                sponsor.Close();
                sponsor = null;
            }
        }
Exemple #3
0
        /// <summary>
        /// Evaluates a string representing a condition from a "condition" attribute.
        /// If the condition is a malformed string, it throws an InvalidProjectFileException.
        /// This method uses cached expression trees to avoid generating them from scratch every time it's called.
        /// This method is thread safe and is called from engine and task execution module threads
        /// </summary>
        /// <param name="condition">Can be null</param>
        /// <param name="conditionAttribute">XML attribute on which the condition is evaluated</param>
        /// <param name="expander">All the data available for expanding embedded properties, metadata, and items</param>
        /// <param name="conditionedPropertiesTable">Can be null</param>
        /// <param name="itemListOptions"></param>
        /// <param name="loggingServices">Can be null</param>
        /// <param name="buildEventContext"> contains contextual information for logging events</param>
        /// <returns>true, if the expression evaluates to true, otherwise false</returns>
        internal static bool EvaluateCondition
        (
            string condition,
            XmlAttribute conditionAttribute,
            Expander expander,
            Hashtable conditionedPropertiesTable,
            ParserOptions itemListOptions,
            EngineLoggingServices loggingServices,
            BuildEventContext buildEventContext
        )
        {
            ErrorUtilities.VerifyThrow((conditionAttribute != null) || (condition.Length == 0),
                                       "If condition is non-empty, you must provide the XML node representing the condition.");

            // An empty condition is equivalent to a "true" condition.
            if ((null == condition) || (condition.Length == 0))
            {
                return(true);
            }

            Hashtable cachedExpressionTreesForCurrentOptions = cachedExpressionTrees[(int)itemListOptions];

            // Try and see if we have an expression tree for this condition already
            GenericExpressionNode parsedExpression = (GenericExpressionNode)cachedExpressionTreesForCurrentOptions[condition];

            if (parsedExpression == null)
            {
                Parser conditionParser = new Parser();

                #region REMOVE_COMPAT_WARNING
                conditionParser.LoggingServices      = loggingServices;
                conditionParser.LogBuildEventContext = buildEventContext;
                #endregion

                parsedExpression = conditionParser.Parse(condition, conditionAttribute, itemListOptions);

                // It's possible two threads will add a different tree to the same entry in the hashtable,
                // but it should be rare and it's not a problem - the previous entry will be thrown away.
                // We could ensure no dupes with double check locking but it's not really necessary here.
                // Also, we don't want to lock on every read.
                lock (cachedExpressionTreesForCurrentOptions)
                {
                    cachedExpressionTreesForCurrentOptions[condition] = parsedExpression;
                }
            }

            ConditionEvaluationState state = new ConditionEvaluationState(conditionAttribute, expander, conditionedPropertiesTable, condition);
            bool result;

            // We are evaluating this expression now and it can cache some state for the duration,
            // so we don't want multiple threads working on the same expression
            lock (parsedExpression)
            {
                result = parsedExpression.Evaluate(state);
                parsedExpression.ResetState();
            }

            return(result);
        }
Exemple #4
0
        /// <summary>
        /// Given a task name and a list of assemblies, this helper method checks if the task exists in any of the assemblies.
        /// </summary>
        /// <remarks>
        /// If the task name is fully qualified, then a match (if any) is unambiguous; otherwise, if there are multiple tasks with
        /// the same name in different namespaces/assemblies, the first task found will be returned.
        /// </remarks>
        /// <param name="taskName"></param>
        /// <param name="taskAssemblies"></param>
        /// <param name="taskProjectFile"></param>
        /// <param name="taskNode"></param>
        /// <param name="loggingServices"></param>
        /// <param name="buildEventContext"></param>
        /// <param name="taskClass"></param>
        /// <returns>true, if task is successfully loaded</returns>
        private bool GetTaskFromAssembly
        (
            string taskName,
            ArrayList taskAssemblies,
            string taskProjectFile,
            XmlNode taskNode,
            EngineLoggingServices loggingServices,
            BuildEventContext buildEventContext,
            out LoadedType taskClass
        )
        {
            taskClass = null;

            foreach (AssemblyLoadInfo assembly in taskAssemblies)
            {
                try
                {
                    taskClass = typeLoader.Load(taskName, assembly);
                }
                catch (TargetInvocationException e)
                {
                    // Exception thrown by the called code itself
                    // Log the stack, so the task vendor can fix their code
                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, taskNode, "TaskLoadFailure", taskName, assembly.ToString(), Environment.NewLine + e.InnerException.ToString());
                }
                catch (ReflectionTypeLoadException e)
                {
                    // ReflectionTypeLoadException.LoaderExceptions may contain nulls
                    foreach (Exception exception in e.LoaderExceptions)
                    {
                        if (exception != null)
                        {
                            loggingServices.LogError(buildEventContext, new BuildEventFileInfo(taskProjectFile), "TaskLoadFailure", taskName, assembly.ToString(), exception.Message);
                        }
                    }

                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, taskNode, "TaskLoadFailure", taskName, assembly.ToString(), e.Message);
                }
                catch (Exception e) // Catching Exception, but rethrowing unless it's a well-known exception.
                {
                    if (ExceptionHandling.NotExpectedReflectionException(e))
                    {
                        throw;
                    }

                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, taskNode, "TaskLoadFailure", taskName, assembly.ToString(), e.Message);
                }

                if (taskClass != null)
                {
                    return(true);
                }
            }

            return(false);
        }
        internal TargetCycleDetector(EngineLoggingServices engineLoggingService, EngineCallback engineCallback)
        {
            this.engineLoggingService = engineLoggingService;
            this.engineCallback = engineCallback;

            dependencyGraph = new Hashtable();
            outstandingExternalRequests = new Hashtable();
            cycleParent = null;
            cycleChild  = null;
        }
        internal TargetCycleDetector(EngineLoggingServices engineLoggingService, EngineCallback engineCallback)
        {
            this.engineLoggingService = engineLoggingService;
            this.engineCallback       = engineCallback;

            dependencyGraph             = new Hashtable();
            outstandingExternalRequests = new Hashtable();
            cycleParent = null;
            cycleChild  = null;
        }
        /// <summary>
        /// Creates an instance of this class for the given target.
        /// </summary>
        /// <owner>SumedhK</owner>
        internal TargetDependencyAnalyzer(string projectDirectory, Target targetToAnalyze, EngineLoggingServices loggingServices, BuildEventContext buildEventContext)
        {
            ErrorUtilities.VerifyThrow(projectDirectory != null, "Need a project directory.");
            ErrorUtilities.VerifyThrow(targetToAnalyze != null, "Need a target to analyze.");
            ErrorUtilities.VerifyThrow(targetToAnalyze.TargetElement != null, "Need a target element.");

            this.projectDirectory = projectDirectory;
            this.targetToAnalyze = targetToAnalyze;
            this.targetInputsAttribute = targetToAnalyze.TargetElement.Attributes[XMakeAttributes.inputs];
            this.targetOutputsAttribute = targetToAnalyze.TargetElement.Attributes[XMakeAttributes.outputs];
            this.loggingService = loggingServices;
            this.buildEventContext = buildEventContext;
        }
Exemple #8
0
 /// <summary>
 /// Override to BuildProject file to return true so we can test that
 /// </summary>
 override internal bool BuildProjectFile
 (
     int nodeProxyId,
     string[] projectFileNames,
     string[] targetNames,
     IDictionary[] globalProperties,
     IDictionary[] targetOutputsPerProject,
     EngineLoggingServices loggingServices,
     string[] toolsVersions,
     bool useResultsCache,
     bool unloadProjectsOnCompletion,
     BuildEventContext taskContext
 )
 {
     return true;
 }
Exemple #9
0
 /// <summary>
 /// Evaluates a string representing a condition from a "condition" attribute.
 /// If the condition is a malformed string, it throws an InvalidProjectFileException.
 /// This method uses cached expression trees to avoid generating them from scratch every time it's called.
 /// This method is thread safe and is called from engine and task execution module threads
 /// </summary>
 /// <param name="condition">Can be null</param>
 /// <param name="conditionAttribute">XML attribute on which the condition is evaluated</param>
 /// <param name="expander">All the data available for expanding embedded properties, metadata, and items</param>
 /// <param name="itemListOptions"></param>
 /// <param name="loggingServices">Can be null</param>
 /// <param name="eventContext"> contains contextual information for logging events</param>
 /// <returns>true, if the expression evaluates to true, otherwise false</returns>
 internal static bool EvaluateCondition
 (
     string condition,
     XmlAttribute conditionAttribute,
     Expander expander,
     ParserOptions itemListOptions,
     EngineLoggingServices loggingServices,
     BuildEventContext buildEventContext
 )
 {
     return(EvaluateCondition(condition,
                              conditionAttribute,
                              expander,
                              null,
                              itemListOptions,
                              loggingServices,
                              buildEventContext));
 }
Exemple #10
0
        /// <summary>
        /// Creates an IntrinsicTask object around a "task" node
        /// </summary>
        internal IntrinsicTask(XmlElement taskNodeXmlElement, EngineLoggingServices loggingServices, BuildEventContext eventContext, string executionDirectory, ItemDefinitionLibrary itemDefinitionLibrary)
        {
            this.taskNodeXmlElement    = taskNodeXmlElement;
            this.conditionAttribute    = taskNodeXmlElement.Attributes[XMakeAttributes.condition];
            this.loggingServices       = loggingServices;
            this.buildEventContext     = eventContext;
            this.executionDirectory    = executionDirectory;
            this.itemDefinitionLibrary = itemDefinitionLibrary;

            ErrorUtilities.VerifyThrow(IsIntrinsicTaskName(taskNodeXmlElement.Name), "Only PropertyGroup and ItemGroup are known intrinsic tasks");

            switch (taskNodeXmlElement.Name)
            {
            case XMakeElements.propertyGroup:
                backingType = BackingType.PropertyGroup;
                // If the backing type is a property group, we can just use a property group object; its semantics aren't
                // tangled up with the project object. Put another way, we only really need the code that understands the XML
                // format of a property group, and we can get that without the rest of BuildPropertyGroup getting in the way.
                // Specify that these properties are output properties, so they get reverted when the project is reset.
                backingPropertyGroup = new BuildPropertyGroup(null /* no parent project */, taskNodeXmlElement, PropertyType.OutputProperty);
                break;

            case XMakeElements.itemGroup:
                backingType = BackingType.ItemGroup;
                // If the backing type is an item group, we just re-use the code that understands the XML format of an item group;
                // the semantics of BuildItemGroup are too coupled to its current use in the Project object for us to re-use it.
                backingItemGroupXml = new BuildItemGroupXml(taskNodeXmlElement);
                List <XmlElement> children = backingItemGroupXml.GetChildren();
                backingBuildItemGroupChildren = new List <BuildItemGroupChildXml>(children.Count);

                foreach (XmlElement child in children)
                {
                    BuildItemGroupChildXml childXml = new BuildItemGroupChildXml(child, ChildType.Any);
                    backingBuildItemGroupChildren.Add(childXml);
                }
                break;
            }
        }
Exemple #11
0
        /// <summary>
        /// Creates an IntrinsicTask object around a "task" node
        /// </summary>
        internal IntrinsicTask(XmlElement taskNodeXmlElement, EngineLoggingServices loggingServices, BuildEventContext eventContext, string executionDirectory, ItemDefinitionLibrary itemDefinitionLibrary)
        {
            this.taskNodeXmlElement = taskNodeXmlElement;
            this.conditionAttribute = taskNodeXmlElement.Attributes[XMakeAttributes.condition];
            this.loggingServices = loggingServices;
            this.buildEventContext = eventContext;
            this.executionDirectory = executionDirectory;
            this.itemDefinitionLibrary = itemDefinitionLibrary;
            
            ErrorUtilities.VerifyThrow(IsIntrinsicTaskName(taskNodeXmlElement.Name), "Only PropertyGroup and ItemGroup are known intrinsic tasks");

            switch (taskNodeXmlElement.Name)
            {
                case XMakeElements.propertyGroup:
                    backingType = BackingType.PropertyGroup;
                    // If the backing type is a property group, we can just use a property group object; its semantics aren't
                    // tangled up with the project object. Put another way, we only really need the code that understands the XML
                    // format of a property group, and we can get that without the rest of BuildPropertyGroup getting in the way.
                    // Specify that these properties are output properties, so they get reverted when the project is reset.
                    backingPropertyGroup = new BuildPropertyGroup(null /* no parent project */, taskNodeXmlElement, PropertyType.OutputProperty);
                    break;
                case XMakeElements.itemGroup:
                    backingType = BackingType.ItemGroup;
                    // If the backing type is an item group, we just re-use the code that understands the XML format of an item group;
                    // the semantics of BuildItemGroup are too coupled to its current use in the Project object for us to re-use it.
                    backingItemGroupXml = new BuildItemGroupXml(taskNodeXmlElement);
                    List<XmlElement> children = backingItemGroupXml.GetChildren();
                    backingBuildItemGroupChildren = new List<BuildItemGroupChildXml>(children.Count);

                    foreach (XmlElement child in children)
                    {
                        BuildItemGroupChildXml childXml = new BuildItemGroupChildXml(child, ChildType.Any);
                        backingBuildItemGroupChildren.Add(childXml);
                    }
                    break;
            }
        }
Exemple #12
0
        /// <summary>
        /// Create an instance of this class to represent the IBuildEngine2 interface to the task
        /// including the event location where the log messages are raised
        /// </summary>
        /// <param name="parentModule">Parent Task Execution Module</param>
        /// <param name="handleId"></param>
        /// <param name="parentProjectFullFileName">the full path to the currently building project</param>
        /// <param name="projectFileOfTaskNode">the path to the actual file (project or targets) where the task invocation is located</param>
        /// <param name="loggingServices"></param>
        /// <param name="buildEventContext">Event Context where events will be seen to be raised from. Task messages will get this as their event context</param>
        internal EngineProxy
        (
            TaskExecutionModule parentModule,
            int handleId,
            string parentProjectFullFileName,
            string projectFileOfTaskNode,
            EngineLoggingServices loggingServices,
            BuildEventContext buildEventContext
        )
        {
            ErrorUtilities.VerifyThrow(parentModule != null, "No parent module.");
            ErrorUtilities.VerifyThrow(loggingServices != null, "No logging services.");
            ErrorUtilities.VerifyThrow(projectFileOfTaskNode != null, "Need project file path string");

            this.parentModule = parentModule;
            this.handleId     = handleId;
            this.parentProjectFullFileName = parentProjectFullFileName;
            this.projectFileOfTaskNode     = projectFileOfTaskNode;
            this.loggingServices           = loggingServices;
            this.buildEventContext         = buildEventContext;
            this.callbackMonitor           = new object();

            activeProxy = true;
        }
Exemple #13
0
 /// <summary>
 /// Initalize this class with a central logger id identifying the central logger to which
 /// these events should be forwarded and a logging service that will do the forwarding
 /// </summary>
 /// <param name="loggerId">central logger id</param>
 /// <param name="loggingService">engine logging service</param>
 internal EventRedirector(int loggerId, EngineLoggingServices loggingService)
 {
     this.loggerId = loggerId;
     this.loggingService = loggingService;
 }
Exemple #14
0
        /// <summary>
        /// Indicates to the EngineProxy that it is no longer needed.
        /// Called by TaskEngine when the task using the EngineProxy is done.
        /// </summary>
        internal void MarkAsInActive()
        {
            activeProxy = false;

            // Since the task has a pointer to this class it may store it in a static field. Null out
            // internal data so the leak of this object doesn't lead to a major memory leak.
            loggingServices = null;
            parentModule = null;
            buildEventContext = null;
            
            // Clear out the sponsor (who is responsible for keeping the EngineProxy remoting lease alive until the task is done)
            // this will be null if the engineproxy was never sent accross an appdomain boundry.
            if (sponsor != null)
            {
                ILease lease = (ILease)RemotingServices.GetLifetimeService(this);
             
                if (lease != null)
                {
                    lease.Unregister(sponsor);
                }
                
                sponsor.Close();
                sponsor = null;
            }
        }
Exemple #15
0
        /// <summary>
        /// Given a task name, this method retrieves the task class. If the task has been requested before, it will be found in
        /// the class cache; otherwise, &lt;UsingTask&gt; declarations will be used to search the appropriate assemblies.
        /// </summary>
        /// <param name="taskName"></param>
        /// <param name="taskProjectFile"></param>
        /// <param name="taskNode"></param>
        /// <param name="exactMatchRequired"></param>
        /// <param name="loggingServices"></param>
        /// <param name="buildEventContext"></param>
        /// <param name="taskClass"></param>
        /// <returns>true, if task is found</returns>
        public bool GetRegisteredTask
        (
            string taskName,
            string taskProjectFile,
            XmlNode taskNode,
            bool exactMatchRequired,
            EngineLoggingServices loggingServices,
            BuildEventContext buildEventContext,
            out LoadedType taskClass
        )
        {
            taskClass = null;

            // If there are no using tags in the project don't bother caching or looking for tasks
            if (registeredTasks == null)
            {
                return(false);
            }

            Hashtable cachedTaskClasses = exactMatchRequired ? this.cachedTaskClassesWithExactMatch : this.cachedTaskClassesWithFuzzyMatch;

            if (cachedTaskClasses.Contains(taskName))
            {
                // Caller has asked us before for this same task name, and for the same value of "bool exactMatchRequired".
                // Return whatever the previous result was, even if it was null.   Why would the result be different than
                // it was before?  NOTE:  Hash tables CAN have "null" as their value, and this still returns "true" for Contains(...).
                taskClass = (LoadedType)cachedTaskClasses[taskName];
            }
            else
            {
                Hashtable registeredTasksFound;

                // look for the given task name in the registry; if not found, gather all registered task names that partially
                // match the given name
                if (FindRegisteredTasks(taskName, exactMatchRequired, out registeredTasksFound))
                {
                    foreach (DictionaryEntry registeredTaskFound in registeredTasksFound)
                    {
                        string mostSpecificTaskName = (string)registeredTaskFound.Key;

                        // if the given task name is longer than the registered task name
                        if (taskName.Length > ((string)registeredTaskFound.Key).Length)
                        {
                            // we will use the longer name to help disambiguate between multiple matches
                            mostSpecificTaskName = taskName;
                        }

                        if (GetTaskFromAssembly(mostSpecificTaskName, (ArrayList)registeredTaskFound.Value, taskProjectFile, taskNode, loggingServices, buildEventContext, out taskClass))
                        {
                            // Whilst we are within the processing of the task, we haven't actually started executing it, so
                            // our using task message needs to be in the context of the target. However any errors should be reported
                            // at the point where the task appears in the project.
                            BuildEventContext usingTaskContext = new BuildEventContext(buildEventContext.NodeId, buildEventContext.TargetId, buildEventContext.ProjectContextId, BuildEventContext.InvalidTaskId);
                            loggingServices.LogComment(usingTaskContext, "TaskFound", taskName, taskClass.Assembly.ToString());
                            break;
                        }
                    }
                }

                // Cache the result, even if it is null.  We should never again do the work we just did, for this task name.
                cachedTaskClasses[taskName] = taskClass;
            }

            return(taskClass != null);
        }
Exemple #16
0
        /// <summary>
        /// Given a task name, this method retrieves the task class. If the task has been requested before, it will be found in
        /// the class cache; otherwise, &lt;UsingTask&gt; declarations will be used to search the appropriate assemblies.
        /// </summary>
        /// <param name="taskName"></param>
        /// <param name="taskProjectFile"></param>
        /// <param name="taskNode"></param>
        /// <param name="exactMatchRequired"></param>
        /// <param name="loggingServices"></param>
        /// <param name="buildEventContext"></param>
        /// <param name="taskClass"></param>
        /// <returns>true, if task is found</returns>
        public bool GetRegisteredTask
        (
            string taskName,
            string taskProjectFile,
            XmlNode taskNode,
            bool exactMatchRequired,
            EngineLoggingServices loggingServices,
            BuildEventContext buildEventContext,
            out LoadedType taskClass
        )
        {
            taskClass = null;

            // If there are no using tags in the project don't bother caching or looking for tasks
            if (registeredTasks == null)
            {
                return false;
            }

            Hashtable cachedTaskClasses = exactMatchRequired ? this.cachedTaskClassesWithExactMatch : this.cachedTaskClassesWithFuzzyMatch;
            
            if (cachedTaskClasses.Contains(taskName))
            {
                // Caller has asked us before for this same task name, and for the same value of "bool exactMatchRequired".
                // Return whatever the previous result was, even if it was null.   Why would the result be different than
                // it was before?  NOTE:  Hash tables CAN have "null" as their value, and this still returns "true" for Contains(...).
                taskClass = (LoadedType) cachedTaskClasses[taskName];
            }
            else
            {
                Hashtable registeredTasksFound;

                // look for the given task name in the registry; if not found, gather all registered task names that partially
                // match the given name
                if (FindRegisteredTasks(taskName, exactMatchRequired, out registeredTasksFound))
                {
                    foreach (DictionaryEntry registeredTaskFound in registeredTasksFound)
                    {
                        string mostSpecificTaskName = (string)registeredTaskFound.Key;

                        // if the given task name is longer than the registered task name
                        if (taskName.Length > ((string)registeredTaskFound.Key).Length)
                        {
                            // we will use the longer name to help disambiguate between multiple matches
                            mostSpecificTaskName = taskName;
                        }

                        if (GetTaskFromAssembly(mostSpecificTaskName, (ArrayList)registeredTaskFound.Value, taskProjectFile, taskNode, loggingServices, buildEventContext, out taskClass))
                        {
                            // Whilst we are within the processing of the task, we haven't actually started executing it, so
                            // our using task message needs to be in the context of the target. However any errors should be reported
                            // at the point where the task appears in the project.
                            BuildEventContext usingTaskContext = new BuildEventContext(buildEventContext.NodeId, buildEventContext.TargetId, buildEventContext.ProjectContextId, BuildEventContext.InvalidTaskId);
                            loggingServices.LogComment(usingTaskContext, "TaskFound", taskName, taskClass.Assembly.ToString());
                            break;
                        }
                    }
                }

                // Cache the result, even if it is null.  We should never again do the work we just did, for this task name.
                cachedTaskClasses[taskName] = taskClass;
            }

            return (taskClass != null);
        }
Exemple #17
0
        /// <summary>
        /// Reads the given &lt;UsingTask&gt; tag and saves the task information specified in it.
        /// </summary>
        /// <param name="usingTask"></param>
        /// <param name="expander"></param>
        /// <param name="loggingServices"></param>
        /// <param name="buildEventContext"></param>
        public void RegisterTask(UsingTask usingTask, Expander expander, EngineLoggingServices loggingServices, BuildEventContext buildEventContext)
        {
            if (
                // if the <UsingTask> tag doesn't have a condition on it
                    (usingTask.Condition == null)
                    ||
                // or if the condition holds
                    Utilities.EvaluateCondition(usingTask.Condition, usingTask.ConditionAttribute, expander,
                        null, ParserOptions.AllowProperties | ParserOptions.AllowItemLists, loggingServices, buildEventContext)
                )
            {
                // Lazily allocate the hashtables if they are needed
                if (registeredTasks == null)
                {
                    cachedTaskClassesWithExactMatch = new Hashtable(StringComparer.OrdinalIgnoreCase);
                    cachedTaskClassesWithFuzzyMatch = new Hashtable(StringComparer.OrdinalIgnoreCase);
                    registeredTasks = new Hashtable(StringComparer.OrdinalIgnoreCase);
                }

                string assemblyName = null;
                string assemblyFile = null;

                if (usingTask.AssemblyName != null)
                {
                    // expand out all embedded properties and items in the assembly name
                    assemblyName = expander.ExpandAllIntoString(usingTask.AssemblyName, usingTask.AssemblyNameAttribute);

                    ProjectErrorUtilities.VerifyThrowInvalidProject(assemblyName.Length > 0,
                        usingTask.AssemblyNameAttribute, "InvalidEvaluatedAttributeValue", assemblyName, usingTask.AssemblyName, XMakeAttributes.assemblyName, XMakeElements.usingTask);
                }
                else
                {
                    // expand out all embedded properties and items in the assembly file/path
                    assemblyFile = expander.ExpandAllIntoString(usingTask.AssemblyFile, usingTask.AssemblyFileAttribute);

                    ProjectErrorUtilities.VerifyThrowInvalidProject(assemblyFile.Length > 0,
                        usingTask.AssemblyFileAttribute, "InvalidEvaluatedAttributeValue", assemblyFile, usingTask.AssemblyFile, XMakeAttributes.assemblyFile, XMakeElements.usingTask);

                    // figure out the directory of the project in which this <UsingTask> node was defined
                    string projectFile = XmlUtilities.GetXmlNodeFile(usingTask.TaskNameAttribute.OwnerElement, String.Empty);
                    string projectDir = (projectFile.Length > 0)
                        ? Path.GetDirectoryName(projectFile)
                        : String.Empty;

                    // ensure the assembly file/path is relative to the project in which this <UsingTask> node was defined -- we
                    // don't want paths from imported projects being interpreted relative to the main project file
                    try
                    {
                        assemblyFile = Path.Combine(projectDir, assemblyFile);
                    }
                    catch (ArgumentException ex)
                    {
                        // Invalid chars in AssemblyFile path
                        ProjectErrorUtilities.VerifyThrowInvalidProject(false, usingTask.AssemblyFileAttribute,
                            "InvalidAttributeValueWithException", assemblyFile,
                            XMakeAttributes.assemblyFile, XMakeElements.usingTask, ex.Message);
                    }

                }

                AssemblyLoadInfo taskAssembly = new AssemblyLoadInfo(assemblyName, assemblyFile);

                // expand out all embedded properties and items
                string taskName = expander.ExpandAllIntoString(usingTask.TaskName, usingTask.TaskNameAttribute);

                ProjectErrorUtilities.VerifyThrowInvalidProject(taskName.Length > 0,
                    usingTask.TaskNameAttribute, "InvalidEvaluatedAttributeValue", taskName, usingTask.TaskName, XMakeAttributes.taskName, XMakeElements.usingTask);

                // since more than one task can have the same name, we want to keep track of all assemblies that are declared to
                // contain tasks with a given name...
                ArrayList taskAssemblies = (ArrayList)registeredTasks[taskName];

                if (taskAssemblies == null)
                {
                    taskAssemblies = new ArrayList();
                    registeredTasks[taskName] = taskAssemblies;
                }

                taskAssemblies.Add(taskAssembly);
            }
        }
Exemple #18
0
        /// <summary>
        /// This function implements the callback via the IBuildEngine interface
        /// </summary>
        /// <returns>result of call to engine</returns>
        virtual internal bool BuildProjectFile
        (
            int handleId,
            string[] projectFileNames,
            string[] targetNames,
            IDictionary[] globalPropertiesPerProject,
            IDictionary[] targetOutputsPerProject,
            EngineLoggingServices loggingServices,
            string [] toolsVersions,
            bool useResultsCache,
            bool unloadProjectsOnCompletion,
            BuildEventContext taskContext
        )
        {
            if (projectFileNames.Length == 0)
            {
                // Nothing to do, just return success
                return(true);
            }

            string currentDir = FileUtilities.GetCurrentDirectoryStaticBuffer(currentDirectoryBuffer);

            if (Engine.debugMode)
            {
                string targetName = targetNames == null ? "null" : targetNames[0];

                bool remoteNode = false;
                for (int r = 0; r < projectFileNames.Length; r++)
                {
                    string fullProjectName = projectFileNames[r] ?? "null";
                    Console.WriteLine("RemoteNode: " + remoteNode + " Project " + fullProjectName + " T:" + targetName + " NodeProdyId# " + handleId + " Time " + DateTime.Now.ToLongTimeString());
                    if (globalPropertiesPerProject[r] != null)
                    {
                        foreach (DictionaryEntry entry in globalPropertiesPerProject[r])
                        {
                            Console.WriteLine(currentDir + " :GLOBAL " + entry.Key + "=" + entry.Value.ToString());
                        }
                    }
                }
            }

            BuildRequest[] buildRequests = new BuildRequest[projectFileNames.Length];
            for (int i = 0; i < buildRequests.Length; i++)
            {
                // We need to get the full path to the project before we call back
                // into the engine which has no control over current path
                string fullProjectName = projectFileNames[i] != null?
                                         Path.GetFullPath(projectFileNames[i]) : null;

                buildRequests[i] = new BuildRequest(handleId, fullProjectName, targetNames, globalPropertiesPerProject[i],
                                                    toolsVersions[i], i, useResultsCache, unloadProjectsOnCompletion);
                ErrorUtilities.VerifyThrow(buildRequests[i].IsGeneratedRequest, "Should not be sending non generated requests from TEM to engine");
                buildRequests[i].ParentBuildEventContext = taskContext;
            }

            BuildResult[] buildResultsLocal = new BuildResult[projectFileNames.Length];

            if (moduleMode == TaskExecutionModuleMode.SingleProcMode)
            {
                for (int i = 0; i < projectFileNames.Length; i++)
                {
                    // If we are running in a single threaded mode we need to
                    // re-enter the main build loop on the current thread in order
                    // to build the requested project, because the main build is below
                    // us on the stack
                    engineCallback.PostBuildRequestsToHost(new BuildRequest[] { buildRequests[i] });
                    buildResultsLocal[i] = engineCallback.GetParentEngine().EngineBuildLoop(buildRequests[i]);
                    buildResultsLocal[i].ConvertToTaskItems();
                }
            }
            else
            {
                WaitForBuildResults(handleId, buildResultsLocal, buildRequests);
            }

            // Store the outputs in the hashtables provided by the caller
            bool overallResult = true;

            for (int i = 0; i < buildResultsLocal.Length; i++)
            {
                // Users of the Object Model can pass in null targetOutputs for projects they do not want outputs for
                // therefore we need to make sure that there are targetoutputs and the users want the results
                if (buildResultsLocal[i] != null)
                {
                    if (buildResultsLocal[i].OutputsByTarget != null && targetOutputsPerProject[i] != null)
                    {
                        foreach (DictionaryEntry entry in buildResultsLocal[i].OutputsByTarget)
                        {
                            targetOutputsPerProject[i].Add(entry.Key, entry.Value);
                        }
                        overallResult = overallResult && buildResultsLocal[i].EvaluationResult;
                    }
                }
                else
                {
                    // The calculation was terminated prior to receiving the result
                    overallResult = false;
                }
            }

            // We're now returning from an IBuildEngine callback;
            // set the current directory back to what the tasks expect
            if (Directory.GetCurrentDirectory() != currentDir)
            {
                Directory.SetCurrentDirectory(currentDir);
            }

            if (Engine.debugMode)
            {
                bool   remoteNode = false;
                string targetName = targetNames == null ? "null" : targetNames[0];
                Console.WriteLine("RemoteNode: " + remoteNode + " T:" + targetName + " HandleId# " + handleId + " Result " + overallResult);
            }

            return(overallResult);
        }
Exemple #19
0
        /// <summary>
        /// This function implements the callback via the IBuildEngine interface
        /// </summary>
        /// <returns>result of call to engine</returns>
        virtual internal bool BuildProjectFile
        (
            int handleId, 
            string[] projectFileNames, 
            string[] targetNames, 
            IDictionary[] globalPropertiesPerProject,
            IDictionary[] targetOutputsPerProject,
            EngineLoggingServices loggingServices,
            string [] toolsVersions,
            bool useResultsCache,
            bool unloadProjectsOnCompletion, 
            BuildEventContext taskContext
        )
        {
            if (projectFileNames.Length == 0)
            {
                // Nothing to do, just return success
                return true;
            }

            string currentDir = FileUtilities.GetCurrentDirectoryStaticBuffer(currentDirectoryBuffer);

            if (Engine.debugMode)
            {
                string targetName = targetNames == null ? "null" : targetNames[0];

                bool remoteNode = false;
                for (int r = 0; r < projectFileNames.Length; r++)
                {
                    string fullProjectName = projectFileNames[r] != null ?
                       projectFileNames[r] : "null";
                    Console.WriteLine("RemoteNode: " + remoteNode + " Project " + fullProjectName + " T:" + targetName + " NodeProdyId# " + handleId + " Time " + DateTime.Now.ToLongTimeString());
                    if (globalPropertiesPerProject[r] != null)
                    {
                        foreach (DictionaryEntry entry in globalPropertiesPerProject[r])
                        {
                            Console.WriteLine(currentDir + " :GLOBAL " + entry.Key + "=" + entry.Value.ToString());
                        }
                    }
                }
            }

            BuildRequest[] buildRequests = new BuildRequest[projectFileNames.Length];
            for (int i = 0; i < buildRequests.Length; i++)
            {
                // We need to get the full path to the project before we call back
                // into the engine which has no control over current path
                string fullProjectName = projectFileNames[i] != null ?
                    Path.GetFullPath(projectFileNames[i]) : null;

                buildRequests[i] = new BuildRequest(handleId, fullProjectName, targetNames, globalPropertiesPerProject[i],
                                                    toolsVersions[i], i, useResultsCache, unloadProjectsOnCompletion);
                ErrorUtilities.VerifyThrow(buildRequests[i].IsGeneratedRequest == true, "Should not be sending non generated requests from TEM to engine");
                buildRequests[i].ParentBuildEventContext = taskContext;
            }

            BuildResult[] buildResultsLocal = new BuildResult[projectFileNames.Length];

            if (moduleMode == TaskExecutionModuleMode.SingleProcMode)
            {
                for (int i = 0; i < projectFileNames.Length; i++)
                {
                    // If we are running in a single threaded mode we need to
                    // re-enter the main build loop on the current thread in order
                    // to build the requested project, because the main build is below
                    // us on the stack
                    engineCallback.PostBuildRequestsToHost(new BuildRequest[] { buildRequests[i] });
                    buildResultsLocal[i] = engineCallback.GetParentEngine().EngineBuildLoop(buildRequests[i]);
                    buildResultsLocal[i].ConvertToTaskItems();
                }
            }
            else
            {
                WaitForBuildResults(handleId, buildResultsLocal, buildRequests);
            }

            // Store the outputs in the hashtables provided by the caller
            bool overallResult = true;
            for (int i = 0; i < buildResultsLocal.Length; i++)
            {
                // Users of the Object Model can pass in null targetOutputs for projects they do not want outputs for
                // therefore we need to make sure that there are targetoutputs and the users want the results
                if (buildResultsLocal[i] != null)
                {
                    if (buildResultsLocal[i].OutputsByTarget != null && targetOutputsPerProject[i] != null)
                    {
                        foreach (DictionaryEntry entry in buildResultsLocal[i].OutputsByTarget)
                        {
                            targetOutputsPerProject[i].Add(entry.Key, entry.Value);
                        }
                        overallResult = overallResult && buildResultsLocal[i].EvaluationResult;
                    }
                }
                else
                {
                    // The calculation was terminated prior to receiving the result
                    overallResult = false;
                }
            }

            // We're now returning from an IBuildEngine callback;
            // set the current directory back to what the tasks expect
            if (Directory.GetCurrentDirectory() != currentDir)
            {
                Directory.SetCurrentDirectory(currentDir);
            }

            if (Engine.debugMode)
            {
                bool remoteNode = false;
                string targetName = targetNames == null ? "null" : targetNames[0];
                Console.WriteLine("RemoteNode: " + remoteNode + " T:" + targetName + " HandleId# " + handleId + " Result " + overallResult);
            }

            return overallResult;
        }
Exemple #20
0
        /// <summary>
        /// Constructor to init all data except for BinPath which is initialized separately because 
        /// a parameterless constructor is needed for COM interop
        /// </summary>
        internal Engine
        (
            int numberOfCpus, 
            bool isChildNode, 
            int parentNodeId, 
            string localNodeProviderParameters,
            BuildPropertyGroup globalProperties, 
            ToolsetDefinitionLocations locations
        )
        {
            // No need to check whether locations parameter 
            // is null, because it is a value type

            this.startupDirectory = Environment.CurrentDirectory;
            this.engineGlobalProperties = globalProperties == null ? new BuildPropertyGroup() : globalProperties;
            this.environmentProperties = new BuildPropertyGroup();
            this.toolsetStateMap = new Dictionary<string, ToolsetState>(StringComparer.OrdinalIgnoreCase);
            this.toolsets = new ToolsetCollection(this);

            // Every environment variable can be referenced just like a property
            // from the project file.  Here, we go ahead and add all the environment
            // variables to the property bag, so they can be treated just like any
            // other property later on.
            this.environmentProperties.GatherEnvironmentVariables();

            this.projectsLoadedByHost = new Hashtable(StringComparer.OrdinalIgnoreCase);

            this.cacheOfBuildingProjects = new ProjectManager();

            this.eventSource = new EventSource();

            this.buildEnabled = true;

            this.flushRequestEvent = new ManualResetEvent(false);

            this.primaryLoggingServices = new EngineLoggingServicesInProc(eventSource, false, flushRequestEvent);

            // Read any toolsets from the registry and config file
            PopulateToolsetStateMap(locations);

            this.nodeId = parentNodeId;
            this.localNodeProviderParameters = localNodeProviderParameters;
            this.numberOfCpus = numberOfCpus;

            if (this.numberOfCpus == 1 && !isChildNode)
            {
                this.primaryLoggingServices.FlushBuildEventsImmediatly = true;
            }

            this.buildRequests = new DualQueue<BuildRequest>();

            this.taskOutputUpdates = new DualQueue<TaskExecutionContext>();

            this.engineCommands = new DualQueue<EngineCommand>();

            this.engineCallback = new EngineCallback(this);
            this.nodeManager = new NodeManager(this.numberOfCpus, isChildNode, this);
            this.scheduler = new Scheduler(this.nodeId, this);
            this.router = new Router(this, scheduler);
            this.cacheManager = new CacheManager(this.DefaultToolsVersion);

            this.lastUsedLoggerId = EngineLoggingServicesInProc.FIRST_AVAILABLE_LOGGERID;

            this.enabledCentralLogging = false;

            this.introspector = new Introspector(this, cacheOfBuildingProjects, nodeManager);

            // Initialize the node provider
            InitializeLocalNodeProvider(locations);
        }
Exemple #21
0
 /// <summary>
 /// Initalize this class with a central logger id identifying the central logger to which
 /// these events should be forwarded and a logging service that will do the forwarding
 /// </summary>
 /// <param name="loggerId">central logger id</param>
 /// <param name="loggingService">engine logging service</param>
 internal EventRedirector(int loggerId, EngineLoggingServices loggingService)
 {
     this.loggerId       = loggerId;
     this.loggingService = loggingService;
 }
 /// <summary>
 /// This constructor initializes all required data.
 /// </summary>
 /// <owner>JomoF</owner>
 /// <param name="loggingServices"></param>
 /// <param name="binPath"></param>
 internal ProjectSchemaValidationHandler(BuildEventContext buildEventContext, EngineLoggingServices loggingServices, string binPath)
 {
     this.engineLoggingServices = loggingServices;
     this.binPath           = binPath;
     this.buildEventContext = buildEventContext;
 }
 /// <summary>
 /// This constructor initializes all required data.
 /// </summary>
 /// <owner>JomoF</owner>
 /// <param name="loggingServices"></param>
 /// <param name="binPath"></param>
 internal ProjectSchemaValidationHandler(BuildEventContext buildEventContext, EngineLoggingServices loggingServices, string binPath)
 {
     this.engineLoggingServices = loggingServices;
     this.binPath = binPath;
     this.buildEventContext = buildEventContext;
 }
Exemple #24
0
        /// <summary>
        /// Evaluates the item and returns a virtual group containing any resulting items.
        /// This allows an item to be evaluated without it belonging to an item group.
        /// </summary>
        internal BuildItemGroup Evaluate(Expander expander, 
                                        string baseDirectory, 
                                        bool expandMetadata,
                                        ParserOptions parserOptions,
                                        EngineLoggingServices loggingServices, 
                                        BuildEventContext buildEventContext)
        {
            BuildItemGroup result = new BuildItemGroup();
            bool itemCondition = Utilities.EvaluateCondition(Condition,
                                                             ConditionAttribute,
                                                             expander,
                                                             parserOptions,
                                                             loggingServices,
                                                             buildEventContext);
            if (!itemCondition)
            {
                return result;
            }

            EvaluateAllItemMetadata(expander, parserOptions, loggingServices, buildEventContext);
            BuildItemGroup items = BuildItemGroup.ExpandItemIntoItems(baseDirectory, this, expander, expandMetadata);

            for (int i = 0; i < items.Count; i++)
            {
                BuildItem newItem = CreateClonedParentedItem(items[i], this);
                result.AddExistingItem(newItem);
            }

            return result;
        }
Exemple #25
0
        /// <summary>
        /// Reads the given &lt;UsingTask&gt; tag and saves the task information specified in it.
        /// </summary>
        /// <param name="usingTask"></param>
        /// <param name="expander"></param>
        /// <param name="loggingServices"></param>
        /// <param name="buildEventContext"></param>
        public void RegisterTask(UsingTask usingTask, Expander expander, EngineLoggingServices loggingServices, BuildEventContext buildEventContext)
        {
            if (
                // if the <UsingTask> tag doesn't have a condition on it
                (usingTask.Condition == null)
                ||
                // or if the condition holds
                Utilities.EvaluateCondition(usingTask.Condition, usingTask.ConditionAttribute, expander,
                                            null, ParserOptions.AllowProperties | ParserOptions.AllowItemLists, loggingServices, buildEventContext)
                )
            {
                // Lazily allocate the hashtables if they are needed
                if (registeredTasks == null)
                {
                    cachedTaskClassesWithExactMatch = new Hashtable(StringComparer.OrdinalIgnoreCase);
                    cachedTaskClassesWithFuzzyMatch = new Hashtable(StringComparer.OrdinalIgnoreCase);
                    registeredTasks = new Hashtable(StringComparer.OrdinalIgnoreCase);
                }

                string assemblyName = null;
                string assemblyFile = null;

                if (usingTask.AssemblyName != null)
                {
                    // expand out all embedded properties and items in the assembly name
                    assemblyName = expander.ExpandAllIntoString(usingTask.AssemblyName, usingTask.AssemblyNameAttribute);

                    ProjectErrorUtilities.VerifyThrowInvalidProject(assemblyName.Length > 0,
                                                                    usingTask.AssemblyNameAttribute, "InvalidEvaluatedAttributeValue", assemblyName, usingTask.AssemblyName, XMakeAttributes.assemblyName, XMakeElements.usingTask);
                }
                else
                {
                    // expand out all embedded properties and items in the assembly file/path
                    assemblyFile = expander.ExpandAllIntoString(usingTask.AssemblyFile, usingTask.AssemblyFileAttribute);

                    ProjectErrorUtilities.VerifyThrowInvalidProject(assemblyFile.Length > 0,
                                                                    usingTask.AssemblyFileAttribute, "InvalidEvaluatedAttributeValue", assemblyFile, usingTask.AssemblyFile, XMakeAttributes.assemblyFile, XMakeElements.usingTask);

                    // figure out the directory of the project in which this <UsingTask> node was defined
                    string projectFile = XmlUtilities.GetXmlNodeFile(usingTask.TaskNameAttribute.OwnerElement, String.Empty);
                    string projectDir  = (projectFile.Length > 0)
                        ? Path.GetDirectoryName(projectFile)
                        : String.Empty;

                    // ensure the assembly file/path is relative to the project in which this <UsingTask> node was defined -- we
                    // don't want paths from imported projects being interpreted relative to the main project file
                    try
                    {
                        assemblyFile = Path.Combine(projectDir, assemblyFile);
                    }
                    catch (ArgumentException ex)
                    {
                        // Invalid chars in AssemblyFile path
                        ProjectErrorUtilities.VerifyThrowInvalidProject(false, usingTask.AssemblyFileAttribute,
                                                                        "InvalidAttributeValueWithException", assemblyFile,
                                                                        XMakeAttributes.assemblyFile, XMakeElements.usingTask, ex.Message);
                    }
                }

                AssemblyLoadInfo taskAssembly = new AssemblyLoadInfo(assemblyName, assemblyFile);

                // expand out all embedded properties and items
                string taskName = expander.ExpandAllIntoString(usingTask.TaskName, usingTask.TaskNameAttribute);

                ProjectErrorUtilities.VerifyThrowInvalidProject(taskName.Length > 0,
                                                                usingTask.TaskNameAttribute, "InvalidEvaluatedAttributeValue", taskName, usingTask.TaskName, XMakeAttributes.taskName, XMakeElements.usingTask);

                // since more than one task can have the same name, we want to keep track of all assemblies that are declared to
                // contain tasks with a given name...
                ArrayList taskAssemblies = (ArrayList)registeredTasks[taskName];

                if (taskAssemblies == null)
                {
                    taskAssemblies            = new ArrayList();
                    registeredTasks[taskName] = taskAssemblies;
                }

                taskAssemblies.Add(taskAssembly);
            }
        }
Exemple #26
0
        /// <summary>
        /// Populate the lists of evaluated and unevaluated metadata with all metadata that have true conditions.
        /// </summary>
        /// <remarks>
        /// FUTURE: Currently this isn't done when the item is constructed; so for example HasMetadata will always return
        /// false until EvaluatedAllItemMetadata is explicitly called. The reason for this is that Metadata are
        /// not first class objects, they are merely string pairs produced by running over the child XML with a particular expander.
        /// When Metadata are first class objects this method can be changed to merely evaluate them, 
        /// just as BuildItemGroup.Evaluate does for BuildItem, then methods like HasMetadata behave more sanely. Of course this
        /// could be a breaking change.
        /// </remarks>
        internal void EvaluateAllItemMetadata
        (
            Expander expander,
            ParserOptions parserOptions,
            EngineLoggingServices loggingServices,
            BuildEventContext buildEventContext
        )
        {
            ErrorUtilities.VerifyThrow(expander != null, "Null expander passed in.");

            // Cache all custom attributes on the item. For a persisted item, this will walk the item's child nodes, and
            // cache the custom attributes using a "last one wins" policy. For a virtual item, this method does nothing.

            // We only evaluate metadata by reading XML
            if (IsBackedByXml)
            {
                ErrorUtilities.VerifyThrow((this.evaluatedCustomMetadata != null) && (this.unevaluatedCustomMetadata != null),
                    "Item is not initialized properly.");

                // We're evaluating from scratch, so clear out any old cached attributes.
                this.evaluatedCustomMetadata.Clear();
                this.unevaluatedCustomMetadata.Clear();

                // Let the expander know about our own item type, so it can
                // expand unqualified metadata expressions
                SpecificItemDefinitionLibrary specificItemDefinitionLibrary = new SpecificItemDefinitionLibrary(name, itemDefinitionLibrary);
                expander = new Expander(expander, specificItemDefinitionLibrary);

                List<XmlElement> metadataElements = xml.GetChildren();

                // look at all the item's child nodes
                foreach (XmlElement metadataElement in metadataElements)
                {
                    // confirm that the child node is not conditionally disabled
                    bool condition = true;
                    XmlAttribute conditionAttribute = ProjectXmlUtilities.GetConditionAttribute(metadataElement, true /*no other attributes allowed*/);

                    if (conditionAttribute != null)
                    {
                        condition = Utilities.EvaluateCondition(conditionAttribute.Value,
                            conditionAttribute, expander, null, parserOptions,
                            loggingServices, buildEventContext);
                    }

                    if (condition)
                    {
                        // cache its value, both the evaluated and unevaluated.
                        string unevaluatedMetadataValue = Utilities.GetXmlNodeInnerContents(metadataElement);
                        unevaluatedCustomMetadata[metadataElement.Name] = unevaluatedMetadataValue;
                        string evaluatedMetadataValue = expander.ExpandAllIntoStringLeaveEscaped(unevaluatedMetadataValue, metadataElement);
                        evaluatedCustomMetadata[metadataElement.Name] = evaluatedMetadataValue;

                        // Add this metadata to the running table we're using, so that one piece of metadata can refer to another one above
                        expander.SetMetadataInMetadataTable(name, metadataElement.Name, evaluatedMetadataValue);

                    }
                }
            }
        }
Exemple #27
0
        /// <summary>
        /// Given a task name and a list of assemblies, this helper method checks if the task exists in any of the assemblies.
        /// </summary>
        /// <remarks>
        /// If the task name is fully qualified, then a match (if any) is unambiguous; otherwise, if there are multiple tasks with
        /// the same name in different namespaces/assemblies, the first task found will be returned.
        /// </remarks>
        /// <param name="taskName"></param>
        /// <param name="taskAssemblies"></param>
        /// <param name="taskProjectFile"></param>
        /// <param name="taskNode"></param>
        /// <param name="loggingServices"></param>
        /// <param name="buildEventContext"></param>
        /// <param name="taskClass"></param>
        /// <returns>true, if task is successfully loaded</returns>
        private bool GetTaskFromAssembly
        (
            string taskName,
            ArrayList taskAssemblies,
            string taskProjectFile,
            XmlNode taskNode,
            EngineLoggingServices loggingServices,
            BuildEventContext buildEventContext,
            out LoadedType taskClass
        )
        {
            taskClass = null;

            foreach (AssemblyLoadInfo assembly in taskAssemblies)
            {
                try
                {
                    taskClass = typeLoader.Load(taskName, assembly);
                }
                catch (TargetInvocationException e)
                {
                    // Exception thrown by the called code itself
                    // Log the stack, so the task vendor can fix their code
                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, taskNode, "TaskLoadFailure", taskName, assembly.ToString(), Environment.NewLine + e.InnerException.ToString());
                }
                catch (ReflectionTypeLoadException e)
                {
                    // ReflectionTypeLoadException.LoaderExceptions may contain nulls
                    foreach (Exception exception in e.LoaderExceptions)
                    {
                        if (exception != null)
                        {
                            loggingServices.LogError(buildEventContext, new BuildEventFileInfo(taskProjectFile), "TaskLoadFailure", taskName, assembly.ToString(), exception.Message);
                        }
                    }

                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, taskNode, "TaskLoadFailure", taskName, assembly.ToString(), e.Message);
                }
                catch (Exception e) // Catching Exception, but rethrowing unless it's a well-known exception.
                {
                    if (ExceptionHandling.NotExpectedReflectionException(e))
                        throw;

                    ProjectErrorUtilities.VerifyThrowInvalidProject(false, taskNode, "TaskLoadFailure", taskName, assembly.ToString(), e.Message);
                }
                
                if (taskClass != null)
                {
                    return true;
                }
            }

            return false;
        }
Exemple #28
0
        /// <summary>
        /// Create an instance of this class to represent the IBuildEngine2 interface to the task
        /// including the event location where the log messages are raised
        /// </summary>
        /// <param name="parentModule">Parent Task Execution Module</param>
        /// <param name="handleId"></param>
        /// <param name="parentProjectFullFileName">the full path to the currently building project</param>
        /// <param name="projectFileOfTaskNode">the path to the actual file (project or targets) where the task invocation is located</param>
        /// <param name="loggingServices"></param>
        /// <param name="buildEventContext">Event Context where events will be seen to be raised from. Task messages will get this as their event context</param>
        internal EngineProxy
        (
            TaskExecutionModule parentModule, 
            int handleId, 
            string parentProjectFullFileName,
            string projectFileOfTaskNode, 
            EngineLoggingServices loggingServices,
            BuildEventContext buildEventContext
        )
        {
            ErrorUtilities.VerifyThrow(parentModule != null, "No parent module.");
            ErrorUtilities.VerifyThrow(loggingServices != null, "No logging services.");
            ErrorUtilities.VerifyThrow(projectFileOfTaskNode != null, "Need project file path string");

            this.parentModule = parentModule;
            this.handleId = handleId;
            this.parentProjectFullFileName = parentProjectFullFileName;
            this.projectFileOfTaskNode = projectFileOfTaskNode;
            this.loggingServices = loggingServices;
            this.buildEventContext = buildEventContext;
            this.callbackMonitor = new object();

            activeProxy = true;
        }