File: Tasks\MsDeploy\ImportParameterFile.cs
Web Access
Project: ..\..\..\src\WebSdk\Publish\Tasks\Microsoft.NET.Sdk.Publish.Tasks.csproj (Microsoft.NET.Sdk.Publish.Tasks)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Diagnostics;
using Microsoft.Build.Utilities;
using Microsoft.NET.Sdk.Publish.Tasks.MsDeploy;
using Microsoft.NET.Sdk.Publish.Tasks.Properties;
using Microsoft.NET.Sdk.Publish.Tasks.Xdt;
using Microsoft.Web.XmlTransform;
using Framework = Microsoft.Build.Framework;
using Xml = System.Xml;
 
namespace Microsoft.NET.Sdk.Publish.Tasks.Tasks.MsDeploy
{
    public class ImportParameterFile : Task
    {
        private Framework.ITaskItem[]? m_sourceFiles = null;
        private List<Framework.ITaskItem> m_parametersList = new(8);
 
        [Framework.Required]
        public Framework.ITaskItem[]? Files
        {
            get { return m_sourceFiles; }
            set { m_sourceFiles = value; }
        }
 
        [Framework.Output]
        public Framework.ITaskItem[] Result
        {
            get { return m_parametersList.ToArray(); }
        }
 
        public bool DisableEscapeMSBuildVariable
        {
            get;
            set;
        }
 
        /// <summary>
        /// Utility function to pare the top level of the element
        /// </summary>
        /// <param name="element"></param>
        private void ReadParametersElement(Xml.XmlElement element)
        {
            Debug.Assert(element != null);
            if (element is not null && string.Compare(element.Name, "parameters", StringComparison.OrdinalIgnoreCase) == 0)
            {
                foreach (Xml.XmlNode childNode in element.ChildNodes)
                {
                    Xml.XmlElement? childElement = childNode as Xml.XmlElement;
                    if (childElement != null)
                    {
                        ReadParameterElement(childElement);
                    }
                }
            }
        }
 
        /// <summary>
        /// Parse the Parameter element
        /// </summary>
        /// <param name="element"></param>
        private void ReadParameterElement(Xml.XmlElement element)
        {
            Debug.Assert(element != null);
            if (element is not null && string.Compare(element.Name, "parameter", StringComparison.OrdinalIgnoreCase) == 0)
            {
                Xml.XmlAttribute? nameAttribute = element.Attributes.GetNamedItem("name") as Xml.XmlAttribute;
                if (nameAttribute != null)
                {
                    TaskItem taskItem = new(nameAttribute.Value);
                    foreach (Xml.XmlNode attribute in element.Attributes)
                    {
                        string attributeName = attribute.Name.ToLower(System.Globalization.CultureInfo.InvariantCulture);
                        if (string.CompareOrdinal(attributeName, "xmlns") == 0
                            || attribute.Name.StartsWith("xmlns:", StringComparison.Ordinal)
                            || string.CompareOrdinal(attributeName, "name") == 0
                            )
                        {
                            continue;
                        }
                        string? value = DisableEscapeMSBuildVariable ? attribute.Value : Utility.EscapeTextForMSBuildVariable(attribute.Value);
                        taskItem.SetMetadata(attribute.Name, value);
                    }
                    // work around the MSDeploy.exe limitation of the Parameter must have the ParameterEntry.
                    // m_parametersList.Add(taskItem);
                    bool fAddNoParameterEntryParameter = true;
 
                    foreach (Xml.XmlNode childNode in element.ChildNodes)
                    {
                        Xml.XmlElement? childElement = childNode as Xml.XmlElement;
                        if (childElement != null)
                        {
                            TaskItem? childEntry = ReadParameterEntryElement(childElement, taskItem);
                            if (childEntry != null)
                            {
                                fAddNoParameterEntryParameter = false; // we have Parameter entry, suppress adding the Parameter with no entry
                                m_parametersList.Add(childEntry);
                            }
                        }
                    }
 
                    if (fAddNoParameterEntryParameter)
                    {
                        // finally add a parameter without any entry
                        m_parametersList.Add(taskItem);
                    }
                }
            }
        }
 
        /// <summary>
        /// Helper function to parse the ParameterEntryElement
        /// </summary>
        /// <param name="element"></param>
        /// <param name="parentItem"></param>
        /// <returns></returns>
        private TaskItem? ReadParameterEntryElement(Xml.XmlElement element, TaskItem parentItem)
        {
            Debug.Assert(element != null && parentItem != null);
            TaskItem? taskItem = null;
            if (element is not null && string.Compare(element.Name, "parameterEntry", StringComparison.OrdinalIgnoreCase) == 0)
            {
                taskItem = new TaskItem(parentItem);
                taskItem.RemoveMetadata("OriginalItemSpec");
                foreach (Xml.XmlNode attribute in element.Attributes)
                {
                    if (attribute != null && attribute.Name != null && attribute.Value != null)
                    {
                        string? value = DisableEscapeMSBuildVariable ? attribute.Value : Utility.EscapeTextForMSBuildVariable(attribute.Value);
                        taskItem.SetMetadata(attribute.Name, value);
                    }
                }
            }
            else if (element is not null && string.Compare(element.Name, "parameterValidation", StringComparison.OrdinalIgnoreCase) == 0)
            {
                taskItem = new TaskItem(parentItem);
                taskItem.RemoveMetadata("OriginalItemSpec");
                taskItem.SetMetadata("Element", "parameterValidation");
                foreach (Xml.XmlNode attribute in element.Attributes)
                {
                    if (attribute != null && attribute.Name != null && attribute.Value != null)
                    {
                        string? value = DisableEscapeMSBuildVariable ? attribute.Value : Utility.EscapeTextForMSBuildVariable(attribute.Value);
                        taskItem.SetMetadata(attribute.Name, value);
                    }
                }
            }
            return taskItem;
        }
 
        /// <summary>
        /// The task execute function
        /// </summary>
        /// <returns></returns>
        public override bool Execute()
        {
            bool succeeded = true;
            IXmlTransformationLogger logger = new TaskTransformationLogger(Log);
 
            if (m_sourceFiles != null)
            {
                try
                {
                    foreach (Framework.ITaskItem item in m_sourceFiles)
                    {
                        string filePath = item.GetMetadata("FullPath");
                        if (!File.Exists(filePath))
                        {
                            Log.LogError(Resources.BUILDTASK_TransformXml_SourceLoadFailed, new object[] { filePath });
                            succeeded = false;
                            break;
                        }
                        Xml.XmlDocument document = new();
                        document.Load(filePath);
                        foreach (Xml.XmlNode node in document.ChildNodes)
                        {
                            Xml.XmlElement? element = node as Xml.XmlElement;
                            if (element != null)
                            {
                                ReadParametersElement(element);
                            }
                        }
                    }
                }
                catch (Xml.XmlException ex)
                {
                    if (ex.SourceUri is not null)
                    {
                        Uri sourceUri = new(ex.SourceUri);
                        logger.LogError(sourceUri.LocalPath, ex.LineNumber, ex.LinePosition, ex.Message);
                    }
                    succeeded = false;
                }
                catch (Exception ex)
                {
                    logger.LogErrorFromException(ex);
                    succeeded = false;
                }
            }
            return succeeded;
        }
    }
}