// Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. namespace WixToolset.Harvesters { using System; using System.Collections; using System.Collections.Specialized; using System.IO; using WixToolset.Harvesters.Extensibility; using IIs = Serialize.IIs; using Wix = WixToolset.Harvesters.Serialize; /// /// The harvester mutator for the WiX Toolset Internet Information Services Extension. /// public sealed class IIsHarvesterMutator : BaseMutatorExtension { private ArrayList components; private DirectoryHarvester directoryHarvester; private Hashtable directoryPaths; private FileHarvester fileHarvester; private Wix.IParentElement rootElement; private bool setUniqueIdentifiers; private ArrayList webAddresses; private ArrayList webDirs; private ArrayList webDirProperties; private ArrayList webFilters; private ArrayList webSites; private ArrayList webVirtualDirs; /// /// Instantiate a new IIsHarvesterMutator. /// public IIsHarvesterMutator() { this.components = new ArrayList(); this.directoryHarvester = new DirectoryHarvester(); this.directoryPaths = CollectionsUtil.CreateCaseInsensitiveHashtable(); this.fileHarvester = new FileHarvester(); this.webAddresses = new ArrayList(); this.webDirs = new ArrayList(); this.webDirProperties = new ArrayList(); this.webFilters = new ArrayList(); this.webSites = new ArrayList(); this.webVirtualDirs = new ArrayList(); } /// /// Gets the sequence of this mutator extension. /// /// The sequence of this mutator extension. public override int Sequence { get { return 100; } } /// /// Gets of sets the option to set unique identifiers. /// /// The option to set unique identifiers. public bool SetUniqueIdentifiers { get { return this.setUniqueIdentifiers; } set { this.setUniqueIdentifiers = value; } } /// /// Mutate a WiX document. /// /// The Wix document element. public override void Mutate(Wix.Wix wix) { this.components.Clear(); this.directoryPaths.Clear(); this.webAddresses.Clear(); this.webDirs.Clear(); this.webDirProperties.Clear(); this.webFilters.Clear(); this.webSites.Clear(); this.webVirtualDirs.Clear(); this.rootElement = null; this.IndexElement(wix); this.MutateWebAddresses(); this.MutateWebDirs(); this.MutateWebDirProperties(); this.MutateWebSites(); this.MutateWebVirtualDirs(); // this must come after the web virtual dirs in case they harvest a directory containing a web filter file this.MutateWebFilters(); // this must come after the web site identifiers are created this.MutateComponents(); } /// /// Harvest a new directory or return one that was previously harvested. /// /// The path of the directory. /// The option to harvest the children of the directory. /// The harvested directory. private Wix.Directory HarvestUniqueDirectory(string path, bool harvestChildren) { if (this.directoryPaths.Contains(path)) { return (Wix.Directory)this.directoryPaths[path]; } else { Wix.Directory directory = this.directoryHarvester.HarvestDirectory(path, harvestChildren); this.rootElement.AddChild(directory); // index this new directory and all of its children this.IndexElement(directory); return directory; } } /// /// Index an element. /// /// The element to index. private void IndexElement(Wix.ISchemaElement element) { if (element is IIs.WebAddress) { this.webAddresses.Add(element); } else if (element is IIs.WebDir) { this.webDirs.Add(element); } else if (element is IIs.WebDirProperties) { this.webDirProperties.Add(element); } else if (element is IIs.WebFilter) { this.webFilters.Add(element); } else if (element is IIs.WebSite) { this.webSites.Add(element); } else if (element is IIs.WebVirtualDir) { this.webVirtualDirs.Add(element); } else if (element is Wix.Component) { this.components.Add(element); } else if (element is Wix.Directory) { Wix.Directory directory = (Wix.Directory)element; if (null != directory.FileSource) { this.directoryPaths.Add(directory.FileSource, directory); } } else if (element is Wix.Fragment || element is Wix.Module || element is Wix.PatchCreation || element is Wix.Package) { this.rootElement = (Wix.IParentElement)element; } // index the child elements if (element is Wix.IParentElement) { foreach (Wix.ISchemaElement childElement in ((Wix.IParentElement)element).Children) { this.IndexElement(childElement); } } } /// /// Mutate the Component elements. /// private void MutateComponents() { if (this.setUniqueIdentifiers) { IdentifierGenerator identifierGenerator = new IdentifierGenerator("Component", this.Core); // index all the existing identifiers foreach (Wix.Component component in this.components) { if (null != component.Id) { identifierGenerator.IndexExistingIdentifier(component.Id); } } // index all the web site identifiers foreach (IIs.WebSite webSite in this.webSites) { if (webSite.ParentElement is Wix.Component) { identifierGenerator.IndexName(webSite.Id); } } // create an identifier for each component based on its child web site identifier foreach (IIs.WebSite webSite in this.webSites) { Wix.Component component = webSite.ParentElement as Wix.Component; if (null != component) { component.Id = identifierGenerator.GetIdentifier(webSite.Id); } } } } /// /// Mutate the WebAddress elements. /// private void MutateWebAddresses() { if (this.setUniqueIdentifiers) { IdentifierGenerator identifierGenerator = new IdentifierGenerator("WebAddress", this.Core); // index all the existing identifiers and names foreach (IIs.WebAddress webAddress in this.webAddresses) { if (null != webAddress.Id) { identifierGenerator.IndexExistingIdentifier(webAddress.Id); } else { identifierGenerator.IndexName(String.Concat(webAddress.IP, "_", webAddress.Port)); } } foreach (IIs.WebAddress webAddress in this.webAddresses) { if (null == webAddress.Id) { webAddress.Id = identifierGenerator.GetIdentifier(String.Concat(webAddress.IP, "_", webAddress.Port)); } } } } /// /// Mutate the WebDir elements. /// private void MutateWebDirs() { if (this.setUniqueIdentifiers) { IdentifierGenerator identifierGenerator = new IdentifierGenerator("WebDir", this.Core); // index all the existing identifiers and names foreach (IIs.WebDir webDir in this.webDirs) { if (null != webDir.Id) { identifierGenerator.IndexExistingIdentifier(webDir.Id); } else { identifierGenerator.IndexName(webDir.Path); } } foreach (IIs.WebDir webDir in this.webDirs) { if (null == webDir.Id) { webDir.Id = identifierGenerator.GetIdentifier(webDir.Path); } } } } /// /// Mutate the WebDirProperties elements. /// private void MutateWebDirProperties() { if (this.setUniqueIdentifiers) { IdentifierGenerator identifierGenerator = new IdentifierGenerator("WebDirProperties", this.Core); // index all the existing identifiers and names foreach (IIs.WebDirProperties webDirProperties in this.webDirProperties) { if (null != webDirProperties.Id) { identifierGenerator.IndexExistingIdentifier(webDirProperties.Id); } } foreach (IIs.WebDirProperties webDirProperties in this.webDirProperties) { if (null == webDirProperties.Id) { webDirProperties.Id = identifierGenerator.GetIdentifier(String.Empty); } } } } /// /// Mutate the WebFilter elements. /// private void MutateWebFilters() { IdentifierGenerator identifierGenerator = null; if (this.setUniqueIdentifiers) { identifierGenerator = new IdentifierGenerator("WebFilter", this.Core); // index all the existing identifiers and names foreach (IIs.WebFilter webFilter in this.webFilters) { if (null != webFilter.Id) { identifierGenerator.IndexExistingIdentifier(webFilter.Id); } else { identifierGenerator.IndexName(webFilter.Name); } } } foreach (IIs.WebFilter webFilter in this.webFilters) { if (this.setUniqueIdentifiers && null == webFilter.Id) { webFilter.Id = identifierGenerator.GetIdentifier(webFilter.Name); } // harvest the file for this WebFilter Wix.Directory directory = this.HarvestUniqueDirectory(Path.GetDirectoryName(webFilter.Path), false); Wix.Component component = new Wix.Component(); directory.AddChild(component); Wix.File file = this.fileHarvester.HarvestFile(webFilter.Path); component.AddChild(file); } } /// /// Mutate the WebSite elements. /// private void MutateWebSites() { if (this.setUniqueIdentifiers) { IdentifierGenerator identifierGenerator = new IdentifierGenerator("WebSite", this.Core); // index all the existing identifiers and names foreach (IIs.WebSite webSite in this.webSites) { if (null != webSite.Id) { identifierGenerator.IndexExistingIdentifier(webSite.Id); } else { identifierGenerator.IndexName(webSite.Description); } } foreach (IIs.WebSite webSite in this.webSites) { if (null == webSite.Id) { webSite.Id = identifierGenerator.GetIdentifier(webSite.Description); } } } } /// /// Mutate the WebVirtualDir elements. /// private void MutateWebVirtualDirs() { IdentifierGenerator identifierGenerator = null; if (this.setUniqueIdentifiers) { identifierGenerator = new IdentifierGenerator("WebVirtualDir", this.Core); // index all the existing identifiers and names foreach (IIs.WebVirtualDir webVirtualDir in this.webVirtualDirs) { if (null != webVirtualDir.Id) { identifierGenerator.IndexExistingIdentifier(webVirtualDir.Id); } else { identifierGenerator.IndexName(webVirtualDir.Alias); } } } foreach (IIs.WebVirtualDir webVirtualDir in this.webVirtualDirs) { if (this.setUniqueIdentifiers && null == webVirtualDir.Id) { webVirtualDir.Id = identifierGenerator.GetIdentifier(webVirtualDir.Alias); } // harvest the directory for this WebVirtualDir this.HarvestUniqueDirectory(webVirtualDir.Directory, true); } } } }