// 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);
}
}
}
}