diff options
Diffstat (limited to 'src/WixToolset.Core.Burn')
| -rw-r--r-- | src/WixToolset.Core.Burn/Bind/BaseSearchFacade.cs | 27 | ||||
| -rw-r--r-- | src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs | 41 | ||||
| -rw-r--r-- | src/WixToolset.Core.Burn/Bind/ExtensionSearchFacade.cs | 24 | ||||
| -rw-r--r-- | src/WixToolset.Core.Burn/Bind/LegacySearchFacade.cs (renamed from src/WixToolset.Core.Burn/Bind/SearchFacade.cs) | 74 | ||||
| -rw-r--r-- | src/WixToolset.Core.Burn/Bundles/BurnCommon.cs | 8 | ||||
| -rw-r--r-- | src/WixToolset.Core.Burn/Bundles/CreateBootstrapperApplicationManifestCommand.cs | 6 | ||||
| -rw-r--r-- | src/WixToolset.Core.Burn/Bundles/CreateBundleExtensionManifestCommand.cs | 149 | ||||
| -rw-r--r-- | src/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs | 4 | ||||
| -rw-r--r-- | src/WixToolset.Core.Burn/Bundles/OrderSearchesCommand.cs | 71 | ||||
| -rw-r--r-- | src/WixToolset.Core.Burn/ISearchFacade.cs | 15 |
10 files changed, 344 insertions, 75 deletions
diff --git a/src/WixToolset.Core.Burn/Bind/BaseSearchFacade.cs b/src/WixToolset.Core.Burn/Bind/BaseSearchFacade.cs new file mode 100644 index 00000000..d00c5778 --- /dev/null +++ b/src/WixToolset.Core.Burn/Bind/BaseSearchFacade.cs | |||
| @@ -0,0 +1,27 @@ | |||
| 1 | // 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. | ||
| 2 | |||
| 3 | namespace WixToolset.Core.Burn | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Xml; | ||
| 7 | using WixToolset.Data.Tuples; | ||
| 8 | |||
| 9 | internal abstract class BaseSearchFacade : ISearchFacade | ||
| 10 | { | ||
| 11 | protected WixSearchTuple SearchTuple { get; set; } | ||
| 12 | |||
| 13 | public virtual void WriteXml(XmlTextWriter writer) | ||
| 14 | { | ||
| 15 | writer.WriteAttributeString("Id", this.SearchTuple.Id.Id); | ||
| 16 | writer.WriteAttributeString("Variable", this.SearchTuple.Variable); | ||
| 17 | if (!String.IsNullOrEmpty(this.SearchTuple.Condition)) | ||
| 18 | { | ||
| 19 | writer.WriteAttributeString("Condition", this.SearchTuple.Condition); | ||
| 20 | } | ||
| 21 | if (!String.IsNullOrEmpty(this.SearchTuple.BundleExtensionRef)) | ||
| 22 | { | ||
| 23 | writer.WriteAttributeString("ExtensionId", this.SearchTuple.BundleExtensionRef); | ||
| 24 | } | ||
| 25 | } | ||
| 26 | } | ||
| 27 | } | ||
diff --git a/src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs b/src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs index 9f98483f..2cb5ed64 100644 --- a/src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs +++ b/src/WixToolset.Core.Burn/Bind/BindBundleCommand.cs | |||
| @@ -117,10 +117,10 @@ namespace WixToolset.Core.Burn | |||
| 117 | // If there are any fields to resolve later, create the cache to populate during bind. | 117 | // If there are any fields to resolve later, create the cache to populate during bind. |
| 118 | var variableCache = this.DelayedFields.Any() ? new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) : null; | 118 | var variableCache = this.DelayedFields.Any() ? new Dictionary<string, string>(StringComparer.InvariantCultureIgnoreCase) : null; |
| 119 | 119 | ||
| 120 | // TODO: Although the WixSearch tables are defined in the Util extension, | 120 | var orderSearchesCommand = new OrderSearchesCommand(this.Messaging, section); |
| 121 | // the Bundle Binder has to know all about them. We hope to revisit all | 121 | orderSearchesCommand.Execute(); |
| 122 | // of this in the 4.0 timeframe. | 122 | var orderedSearches = orderSearchesCommand.OrderedSearchFacades; |
| 123 | var orderedSearches = this.OrderSearches(section); | 123 | var extensionSearchTuplesById = orderSearchesCommand.ExtensionSearchTuplesByExtensionId; |
| 124 | 124 | ||
| 125 | // Extract files that come from binary .wixlibs and WixExtensions (this does not extract files from merge modules). | 125 | // Extract files that come from binary .wixlibs and WixExtensions (this does not extract files from merge modules). |
| 126 | { | 126 | { |
| @@ -387,6 +387,17 @@ namespace WixToolset.Core.Burn | |||
| 387 | 387 | ||
| 388 | var baManifestPayload = command.BootstrapperApplicationManifestPayloadRow; | 388 | var baManifestPayload = command.BootstrapperApplicationManifestPayloadRow; |
| 389 | payloadTuples.Add(baManifestPayload.Id.Id, baManifestPayload); | 389 | payloadTuples.Add(baManifestPayload.Id.Id, baManifestPayload); |
| 390 | ++uxPayloadIndex; | ||
| 391 | } | ||
| 392 | |||
| 393 | // Generate the bundle extension manifest... | ||
| 394 | { | ||
| 395 | var command = new CreateBundleExtensionManifestCommand(section, bundleTuple, extensionSearchTuplesById, uxPayloadIndex, this.IntermediateFolder); | ||
| 396 | command.Execute(); | ||
| 397 | |||
| 398 | var bextManifestPayload = command.BundleExtensionManifestPayloadRow; | ||
| 399 | payloadTuples.Add(bextManifestPayload.Id.Id, bextManifestPayload); | ||
| 400 | ++uxPayloadIndex; | ||
| 390 | } | 401 | } |
| 391 | 402 | ||
| 392 | #if TODO | 403 | #if TODO |
| @@ -464,28 +475,6 @@ namespace WixToolset.Core.Burn | |||
| 464 | trackedFiles.Add(trackIntermediate); | 475 | trackedFiles.Add(trackIntermediate); |
| 465 | } | 476 | } |
| 466 | 477 | ||
| 467 | private IEnumerable<SearchFacade> OrderSearches(IntermediateSection section) | ||
| 468 | { | ||
| 469 | var searchesById = section.Tuples | ||
| 470 | .Where(t => t.Definition.Type == TupleDefinitionType.WixComponentSearch || | ||
| 471 | t.Definition.Type == TupleDefinitionType.WixFileSearch || | ||
| 472 | t.Definition.Type == TupleDefinitionType.WixProductSearch || | ||
| 473 | t.Definition.Type == TupleDefinitionType.WixRegistrySearch) | ||
| 474 | .ToDictionary(t => t.Id.Id); | ||
| 475 | |||
| 476 | var orderedSearches = new List<SearchFacade>(searchesById.Keys.Count); | ||
| 477 | |||
| 478 | foreach (var searchTuple in section.Tuples.OfType<WixSearchTuple>()) | ||
| 479 | { | ||
| 480 | if (searchesById.TryGetValue(searchTuple.Id.Id, out var specificSearchTuple)) | ||
| 481 | { | ||
| 482 | orderedSearches.Add(new SearchFacade(searchTuple, specificSearchTuple)); | ||
| 483 | } | ||
| 484 | } | ||
| 485 | |||
| 486 | return orderedSearches; | ||
| 487 | } | ||
| 488 | |||
| 489 | /// <summary> | 478 | /// <summary> |
| 490 | /// Populates the variable cache with specific package properties. | 479 | /// Populates the variable cache with specific package properties. |
| 491 | /// </summary> | 480 | /// </summary> |
diff --git a/src/WixToolset.Core.Burn/Bind/ExtensionSearchFacade.cs b/src/WixToolset.Core.Burn/Bind/ExtensionSearchFacade.cs new file mode 100644 index 00000000..6a830a28 --- /dev/null +++ b/src/WixToolset.Core.Burn/Bind/ExtensionSearchFacade.cs | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // 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. | ||
| 2 | |||
| 3 | namespace WixToolset.Core.Burn | ||
| 4 | { | ||
| 5 | using System.Xml; | ||
| 6 | using WixToolset.Data.Tuples; | ||
| 7 | |||
| 8 | internal class ExtensionSearchFacade : BaseSearchFacade | ||
| 9 | { | ||
| 10 | public ExtensionSearchFacade(WixSearchTuple searchTuple) | ||
| 11 | { | ||
| 12 | this.SearchTuple = searchTuple; | ||
| 13 | } | ||
| 14 | |||
| 15 | public override void WriteXml(XmlTextWriter writer) | ||
| 16 | { | ||
| 17 | writer.WriteStartElement("ExtensionSearch"); | ||
| 18 | |||
| 19 | base.WriteXml(writer); | ||
| 20 | |||
| 21 | writer.WriteEndElement(); | ||
| 22 | } | ||
| 23 | } | ||
| 24 | } | ||
diff --git a/src/WixToolset.Core.Burn/Bind/SearchFacade.cs b/src/WixToolset.Core.Burn/Bind/LegacySearchFacade.cs index 65f3cb5b..0a80760d 100644 --- a/src/WixToolset.Core.Burn/Bind/SearchFacade.cs +++ b/src/WixToolset.Core.Burn/Bind/LegacySearchFacade.cs | |||
| @@ -7,48 +7,36 @@ namespace WixToolset.Core.Burn | |||
| 7 | using WixToolset.Data; | 7 | using WixToolset.Data; |
| 8 | using WixToolset.Data.Tuples; | 8 | using WixToolset.Data.Tuples; |
| 9 | 9 | ||
| 10 | internal class SearchFacade | 10 | internal class LegacySearchFacade : BaseSearchFacade |
| 11 | { | 11 | { |
| 12 | public SearchFacade(WixSearchTuple searchTuple, IntermediateTuple searchSpecificTuple) | 12 | public LegacySearchFacade(WixSearchTuple searchTuple, IntermediateTuple searchSpecificTuple) |
| 13 | { | 13 | { |
| 14 | this.SearchTuple = searchTuple; | 14 | this.SearchTuple = searchTuple; |
| 15 | this.SearchSpecificTuple = searchSpecificTuple; | 15 | this.SearchSpecificTuple = searchSpecificTuple; |
| 16 | } | 16 | } |
| 17 | 17 | ||
| 18 | public WixSearchTuple SearchTuple { get; } | ||
| 19 | |||
| 20 | public IntermediateTuple SearchSpecificTuple { get; } | 18 | public IntermediateTuple SearchSpecificTuple { get; } |
| 21 | 19 | ||
| 22 | /// <summary> | 20 | /// <summary> |
| 23 | /// Generates Burn manifest and ParameterInfo-style markup a search. | 21 | /// Generates Burn manifest and ParameterInfo-style markup a search. |
| 24 | /// </summary> | 22 | /// </summary> |
| 25 | /// <param name="writer"></param> | 23 | /// <param name="writer"></param> |
| 26 | public void WriteXml(XmlTextWriter writer) | 24 | public override void WriteXml(XmlTextWriter writer) |
| 27 | { | 25 | { |
| 28 | switch (this.SearchSpecificTuple) | 26 | switch (this.SearchSpecificTuple) |
| 29 | { | 27 | { |
| 30 | case WixComponentSearchTuple tuple: | 28 | case WixComponentSearchTuple tuple: |
| 31 | this.WriteComponentSearchXml(writer, tuple); | 29 | this.WriteComponentSearchXml(writer, tuple); |
| 32 | break; | 30 | break; |
| 33 | case WixFileSearchTuple tuple: | 31 | case WixFileSearchTuple tuple: |
| 34 | this.WriteFileSearchXml(writer, tuple); | 32 | this.WriteFileSearchXml(writer, tuple); |
| 35 | break; | 33 | break; |
| 36 | case WixProductSearchTuple tuple: | 34 | case WixProductSearchTuple tuple: |
| 37 | this.WriteProductSearchXml(writer, tuple); | 35 | this.WriteProductSearchXml(writer, tuple); |
| 38 | break; | 36 | break; |
| 39 | case WixRegistrySearchTuple tuple: | 37 | case WixRegistrySearchTuple tuple: |
| 40 | this.WriteRegistrySearchXml(writer, tuple); | 38 | this.WriteRegistrySearchXml(writer, tuple); |
| 41 | break; | 39 | break; |
| 42 | } | ||
| 43 | } | ||
| 44 | |||
| 45 | private void WriteCommonAttributes(XmlTextWriter writer) | ||
| 46 | { | ||
| 47 | writer.WriteAttributeString("Id", this.SearchTuple.Id.Id); | ||
| 48 | writer.WriteAttributeString("Variable", this.SearchTuple.Variable); | ||
| 49 | if (!String.IsNullOrEmpty(this.SearchTuple.Condition)) | ||
| 50 | { | ||
| 51 | writer.WriteAttributeString("Condition", this.SearchTuple.Condition); | ||
| 52 | } | 40 | } |
| 53 | } | 41 | } |
| 54 | 42 | ||
| @@ -56,7 +44,7 @@ namespace WixToolset.Core.Burn | |||
| 56 | { | 44 | { |
| 57 | writer.WriteStartElement("MsiComponentSearch"); | 45 | writer.WriteStartElement("MsiComponentSearch"); |
| 58 | 46 | ||
| 59 | this.WriteCommonAttributes(writer); | 47 | base.WriteXml(writer); |
| 60 | 48 | ||
| 61 | writer.WriteAttributeString("ComponentId", searchTuple.Guid); | 49 | writer.WriteAttributeString("ComponentId", searchTuple.Guid); |
| 62 | 50 | ||
| @@ -85,7 +73,7 @@ namespace WixToolset.Core.Burn | |||
| 85 | { | 73 | { |
| 86 | writer.WriteStartElement((0 == (searchTuple.Attributes & WixFileSearchAttributes.IsDirectory)) ? "FileSearch" : "DirectorySearch"); | 74 | writer.WriteStartElement((0 == (searchTuple.Attributes & WixFileSearchAttributes.IsDirectory)) ? "FileSearch" : "DirectorySearch"); |
| 87 | 75 | ||
| 88 | this.WriteCommonAttributes(writer); | 76 | base.WriteXml(writer); |
| 89 | 77 | ||
| 90 | writer.WriteAttributeString("Path", searchTuple.Path); | 78 | writer.WriteAttributeString("Path", searchTuple.Path); |
| 91 | if (WixFileSearchAttributes.WantExists == (searchTuple.Attributes & WixFileSearchAttributes.WantExists)) | 79 | if (WixFileSearchAttributes.WantExists == (searchTuple.Attributes & WixFileSearchAttributes.WantExists)) |
| @@ -108,7 +96,7 @@ namespace WixToolset.Core.Burn | |||
| 108 | { | 96 | { |
| 109 | writer.WriteStartElement("MsiProductSearch"); | 97 | writer.WriteStartElement("MsiProductSearch"); |
| 110 | 98 | ||
| 111 | this.WriteCommonAttributes(writer); | 99 | base.WriteXml(writer); |
| 112 | 100 | ||
| 113 | if (0 != (tuple.Attributes & WixProductSearchAttributes.UpgradeCode)) | 101 | if (0 != (tuple.Attributes & WixProductSearchAttributes.UpgradeCode)) |
| 114 | { | 102 | { |
| @@ -143,22 +131,22 @@ namespace WixToolset.Core.Burn | |||
| 143 | { | 131 | { |
| 144 | writer.WriteStartElement("RegistrySearch"); | 132 | writer.WriteStartElement("RegistrySearch"); |
| 145 | 133 | ||
| 146 | this.WriteCommonAttributes(writer); | 134 | base.WriteXml(writer); |
| 147 | 135 | ||
| 148 | switch (tuple.Root) | 136 | switch (tuple.Root) |
| 149 | { | 137 | { |
| 150 | case RegistryRootType.ClassesRoot: | 138 | case RegistryRootType.ClassesRoot: |
| 151 | writer.WriteAttributeString("Root", "HKCR"); | 139 | writer.WriteAttributeString("Root", "HKCR"); |
| 152 | break; | 140 | break; |
| 153 | case RegistryRootType.CurrentUser: | 141 | case RegistryRootType.CurrentUser: |
| 154 | writer.WriteAttributeString("Root", "HKCU"); | 142 | writer.WriteAttributeString("Root", "HKCU"); |
| 155 | break; | 143 | break; |
| 156 | case RegistryRootType.LocalMachine: | 144 | case RegistryRootType.LocalMachine: |
| 157 | writer.WriteAttributeString("Root", "HKLM"); | 145 | writer.WriteAttributeString("Root", "HKLM"); |
| 158 | break; | 146 | break; |
| 159 | case RegistryRootType.Users: | 147 | case RegistryRootType.Users: |
| 160 | writer.WriteAttributeString("Root", "HKU"); | 148 | writer.WriteAttributeString("Root", "HKU"); |
| 161 | break; | 149 | break; |
| 162 | } | 150 | } |
| 163 | 151 | ||
| 164 | writer.WriteAttributeString("Key", tuple.Key); | 152 | writer.WriteAttributeString("Key", tuple.Key); |
diff --git a/src/WixToolset.Core.Burn/Bundles/BurnCommon.cs b/src/WixToolset.Core.Burn/Bundles/BurnCommon.cs index 78b95bf4..5cff0b5a 100644 --- a/src/WixToolset.Core.Burn/Bundles/BurnCommon.cs +++ b/src/WixToolset.Core.Burn/Bundles/BurnCommon.cs | |||
| @@ -22,6 +22,12 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 22 | public const string BurnUXContainerPayloadIdFormat = "p{0}"; | 22 | public const string BurnUXContainerPayloadIdFormat = "p{0}"; |
| 23 | public const string BurnAttachedContainerEmbeddedIdFormat = "a{0}"; | 23 | public const string BurnAttachedContainerEmbeddedIdFormat = "a{0}"; |
| 24 | 24 | ||
| 25 | public const string BADataFileName = "BootstrapperApplicationData.xml"; | ||
| 26 | public const string BADataNamespace = "http://wixtoolset.org/schemas/v4/BootstrapperApplicationData"; | ||
| 27 | |||
| 28 | public const string BundleExtensionDataFileName = "BundleExtensionData.xml"; | ||
| 29 | public const string BundleExtensionDataNamespace = "http://wixtoolset.org/schemas/v4/BundleExtensionData"; | ||
| 30 | |||
| 25 | // See WinNT.h for details about the PE format, including the | 31 | // See WinNT.h for details about the PE format, including the |
| 26 | // structure and offsets for IMAGE_DOS_HEADER, IMAGE_NT_HEADERS32, | 32 | // structure and offsets for IMAGE_DOS_HEADER, IMAGE_NT_HEADERS32, |
| 27 | // IMAGE_FILE_HEADER, etc. | 33 | // IMAGE_FILE_HEADER, etc. |
| @@ -167,7 +173,7 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 167 | /// <returns>True if initialized.</returns> | 173 | /// <returns>True if initialized.</returns> |
| 168 | protected bool Initialize(BinaryReader reader) | 174 | protected bool Initialize(BinaryReader reader) |
| 169 | { | 175 | { |
| 170 | if (!GetWixburnSectionInfo(reader)) | 176 | if (!this.GetWixburnSectionInfo(reader)) |
| 171 | { | 177 | { |
| 172 | return false; | 178 | return false; |
| 173 | } | 179 | } |
diff --git a/src/WixToolset.Core.Burn/Bundles/CreateBootstrapperApplicationManifestCommand.cs b/src/WixToolset.Core.Burn/Bundles/CreateBootstrapperApplicationManifestCommand.cs index 5cd1f7e8..be8227f2 100644 --- a/src/WixToolset.Core.Burn/Bundles/CreateBootstrapperApplicationManifestCommand.cs +++ b/src/WixToolset.Core.Burn/Bundles/CreateBootstrapperApplicationManifestCommand.cs | |||
| @@ -57,7 +57,7 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 57 | { | 57 | { |
| 58 | writer.Formatting = Formatting.Indented; | 58 | writer.Formatting = Formatting.Indented; |
| 59 | writer.WriteStartDocument(); | 59 | writer.WriteStartDocument(); |
| 60 | writer.WriteStartElement("BootstrapperApplicationData", "http://wixtoolset.org/schemas/v4/BootstrapperApplicationData"); | 60 | writer.WriteStartElement("BootstrapperApplicationData", BurnCommon.BADataNamespace); |
| 61 | 61 | ||
| 62 | this.WriteBundleInfo(writer); | 62 | this.WriteBundleInfo(writer); |
| 63 | 63 | ||
| @@ -247,11 +247,11 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 247 | 247 | ||
| 248 | private WixBundlePayloadTuple CreateBootstrapperApplicationManifestPayloadRow(string baManifestPath) | 248 | private WixBundlePayloadTuple CreateBootstrapperApplicationManifestPayloadRow(string baManifestPath) |
| 249 | { | 249 | { |
| 250 | var generatedId = Common.GenerateIdentifier("ux", "BootstrapperApplicationData.xml"); | 250 | var generatedId = Common.GenerateIdentifier("ux", BurnCommon.BADataFileName); |
| 251 | 251 | ||
| 252 | var tuple = new WixBundlePayloadTuple(this.BundleTuple.SourceLineNumbers, new Identifier(AccessModifier.Private, generatedId)) | 252 | var tuple = new WixBundlePayloadTuple(this.BundleTuple.SourceLineNumbers, new Identifier(AccessModifier.Private, generatedId)) |
| 253 | { | 253 | { |
| 254 | Name = "BootstrapperApplicationData.xml", | 254 | Name = BurnCommon.BADataFileName, |
| 255 | SourceFile = new IntermediateFieldPathValue { Path = baManifestPath }, | 255 | SourceFile = new IntermediateFieldPathValue { Path = baManifestPath }, |
| 256 | Compressed = true, | 256 | Compressed = true, |
| 257 | UnresolvedSourceFile = baManifestPath, | 257 | UnresolvedSourceFile = baManifestPath, |
diff --git a/src/WixToolset.Core.Burn/Bundles/CreateBundleExtensionManifestCommand.cs b/src/WixToolset.Core.Burn/Bundles/CreateBundleExtensionManifestCommand.cs new file mode 100644 index 00000000..b608c03d --- /dev/null +++ b/src/WixToolset.Core.Burn/Bundles/CreateBundleExtensionManifestCommand.cs | |||
| @@ -0,0 +1,149 @@ | |||
| 1 | // 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. | ||
| 2 | |||
| 3 | namespace WixToolset.Core.Burn.Bundles | ||
| 4 | { | ||
| 5 | using System; | ||
| 6 | using System.Collections.Generic; | ||
| 7 | using System.Diagnostics; | ||
| 8 | using System.Globalization; | ||
| 9 | using System.IO; | ||
| 10 | using System.Linq; | ||
| 11 | using System.Text; | ||
| 12 | using System.Xml; | ||
| 13 | using WixToolset.Data; | ||
| 14 | using WixToolset.Data.Burn; | ||
| 15 | using WixToolset.Data.Tuples; | ||
| 16 | |||
| 17 | internal class CreateBundleExtensionManifestCommand | ||
| 18 | { | ||
| 19 | public CreateBundleExtensionManifestCommand(IntermediateSection section, WixBundleTuple bundleTuple, IDictionary<string, IList<IntermediateTuple>> extensionSearchTuplesByExtensionId, int lastUXPayloadIndex, string intermediateFolder) | ||
| 20 | { | ||
| 21 | this.Section = section; | ||
| 22 | this.BundleTuple = bundleTuple; | ||
| 23 | this.ExtensionSearchTuplesByExtensionId = extensionSearchTuplesByExtensionId; | ||
| 24 | this.LastUXPayloadIndex = lastUXPayloadIndex; | ||
| 25 | this.IntermediateFolder = intermediateFolder; | ||
| 26 | } | ||
| 27 | |||
| 28 | private IntermediateSection Section { get; } | ||
| 29 | |||
| 30 | private WixBundleTuple BundleTuple { get; } | ||
| 31 | |||
| 32 | private IDictionary<string, IList<IntermediateTuple>> ExtensionSearchTuplesByExtensionId { get; } | ||
| 33 | |||
| 34 | private int LastUXPayloadIndex { get; } | ||
| 35 | |||
| 36 | private string IntermediateFolder { get; } | ||
| 37 | |||
| 38 | public WixBundlePayloadTuple BundleExtensionManifestPayloadRow { get; private set; } | ||
| 39 | |||
| 40 | public void Execute() | ||
| 41 | { | ||
| 42 | var bextManifestPath = this.CreateBundleExtensionManifest(); | ||
| 43 | |||
| 44 | this.BundleExtensionManifestPayloadRow = this.CreateBundleExtensionManifestPayloadRow(bextManifestPath); | ||
| 45 | } | ||
| 46 | |||
| 47 | private string CreateBundleExtensionManifest() | ||
| 48 | { | ||
| 49 | var path = Path.Combine(this.IntermediateFolder, "wix-bextdata.xml"); | ||
| 50 | |||
| 51 | Directory.CreateDirectory(Path.GetDirectoryName(path)); | ||
| 52 | |||
| 53 | using (var writer = new XmlTextWriter(path, Encoding.Unicode)) | ||
| 54 | { | ||
| 55 | writer.Formatting = Formatting.Indented; | ||
| 56 | writer.WriteStartDocument(); | ||
| 57 | writer.WriteStartElement("BundleExtensionData", BurnCommon.BundleExtensionDataNamespace); | ||
| 58 | |||
| 59 | foreach (var kvp in this.ExtensionSearchTuplesByExtensionId) | ||
| 60 | { | ||
| 61 | this.WriteExtension(writer, kvp.Key, kvp.Value); | ||
| 62 | } | ||
| 63 | |||
| 64 | writer.WriteEndElement(); | ||
| 65 | writer.WriteEndDocument(); | ||
| 66 | } | ||
| 67 | |||
| 68 | return path; | ||
| 69 | } | ||
| 70 | |||
| 71 | private void WriteExtension(XmlTextWriter writer, string extensionId, IEnumerable<IntermediateTuple> tuples) | ||
| 72 | { | ||
| 73 | writer.WriteStartElement("BundleExtension"); | ||
| 74 | |||
| 75 | writer.WriteAttributeString("Id", extensionId); | ||
| 76 | |||
| 77 | this.WriteBundleExtensionDataTuples(writer, tuples); | ||
| 78 | |||
| 79 | writer.WriteEndElement(); | ||
| 80 | } | ||
| 81 | |||
| 82 | private void WriteBundleExtensionDataTuples(XmlTextWriter writer, IEnumerable<IntermediateTuple> tuples) | ||
| 83 | { | ||
| 84 | var dataTuplesGroupedByDefinitionName = tuples.GroupBy(t => t.Definition); | ||
| 85 | |||
| 86 | foreach (var group in dataTuplesGroupedByDefinitionName) | ||
| 87 | { | ||
| 88 | var definition = group.Key; | ||
| 89 | |||
| 90 | // We simply assert that the table (and field) name is valid, because | ||
| 91 | // this is up to the extension developer to get right. An author will | ||
| 92 | // only affect the attribute value, and that will get properly escaped. | ||
| 93 | #if DEBUG | ||
| 94 | Debug.Assert(Common.IsIdentifier(definition.Name)); | ||
| 95 | foreach (var fieldDef in definition.FieldDefinitions) | ||
| 96 | { | ||
| 97 | Debug.Assert(Common.IsIdentifier(fieldDef.Name)); | ||
| 98 | } | ||
| 99 | #endif // DEBUG | ||
| 100 | |||
| 101 | foreach (var tuple in group) | ||
| 102 | { | ||
| 103 | writer.WriteStartElement(definition.Name); | ||
| 104 | |||
| 105 | if (tuple.Id != null) | ||
| 106 | { | ||
| 107 | writer.WriteAttributeString("Id", tuple.Id.Id); | ||
| 108 | } | ||
| 109 | |||
| 110 | foreach (var field in tuple.Fields) | ||
| 111 | { | ||
| 112 | if (!field.IsNull()) | ||
| 113 | { | ||
| 114 | writer.WriteAttributeString(field.Definition.Name, field.AsString()); | ||
| 115 | } | ||
| 116 | } | ||
| 117 | |||
| 118 | writer.WriteEndElement(); | ||
| 119 | } | ||
| 120 | } | ||
| 121 | } | ||
| 122 | |||
| 123 | private WixBundlePayloadTuple CreateBundleExtensionManifestPayloadRow(string bextManifestPath) | ||
| 124 | { | ||
| 125 | var generatedId = Common.GenerateIdentifier("ux", BurnCommon.BundleExtensionDataFileName); | ||
| 126 | |||
| 127 | var tuple = new WixBundlePayloadTuple(this.BundleTuple.SourceLineNumbers, new Identifier(AccessModifier.Private, generatedId)) | ||
| 128 | { | ||
| 129 | Name = BurnCommon.BundleExtensionDataFileName, | ||
| 130 | SourceFile = new IntermediateFieldPathValue { Path = bextManifestPath }, | ||
| 131 | Compressed = true, | ||
| 132 | UnresolvedSourceFile = bextManifestPath, | ||
| 133 | ContainerRef = BurnConstants.BurnUXContainerName, | ||
| 134 | EmbeddedId = String.Format(CultureInfo.InvariantCulture, BurnCommon.BurnUXContainerEmbeddedIdFormat, this.LastUXPayloadIndex), | ||
| 135 | Packaging = PackagingType.Embedded, | ||
| 136 | }; | ||
| 137 | |||
| 138 | var fileInfo = new FileInfo(bextManifestPath); | ||
| 139 | |||
| 140 | tuple.FileSize = (int)fileInfo.Length; | ||
| 141 | |||
| 142 | tuple.Hash = BundleHashAlgorithm.Hash(fileInfo); | ||
| 143 | |||
| 144 | this.Section.Tuples.Add(tuple); | ||
| 145 | |||
| 146 | return tuple; | ||
| 147 | } | ||
| 148 | } | ||
| 149 | } | ||
diff --git a/src/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs b/src/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs index 64a01794..58133d38 100644 --- a/src/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs +++ b/src/WixToolset.Core.Burn/Bundles/CreateBurnManifestCommand.cs | |||
| @@ -18,7 +18,7 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 18 | 18 | ||
| 19 | internal class CreateBurnManifestCommand | 19 | internal class CreateBurnManifestCommand |
| 20 | { | 20 | { |
| 21 | public CreateBurnManifestCommand(IMessaging messaging, IEnumerable<IBurnBackendExtension> backendExtensions, string executableName, IntermediateSection section, WixBundleTuple bundleTuple, IEnumerable<WixBundleContainerTuple> containers, WixChainTuple chainTuple, IEnumerable<PackageFacade> orderedPackages, IEnumerable<WixBundleRollbackBoundaryTuple> boundaries, IEnumerable<WixBundlePayloadTuple> uxPayloads, Dictionary<string, WixBundlePayloadTuple> allPayloadsById, IEnumerable<SearchFacade> orderedSearches, IEnumerable<WixBundleCatalogTuple> catalogs, string intermediateFolder) | 21 | public CreateBurnManifestCommand(IMessaging messaging, IEnumerable<IBurnBackendExtension> backendExtensions, string executableName, IntermediateSection section, WixBundleTuple bundleTuple, IEnumerable<WixBundleContainerTuple> containers, WixChainTuple chainTuple, IEnumerable<PackageFacade> orderedPackages, IEnumerable<WixBundleRollbackBoundaryTuple> boundaries, IEnumerable<WixBundlePayloadTuple> uxPayloads, Dictionary<string, WixBundlePayloadTuple> allPayloadsById, IEnumerable<ISearchFacade> orderedSearches, IEnumerable<WixBundleCatalogTuple> catalogs, string intermediateFolder) |
| 22 | { | 22 | { |
| 23 | this.Messaging = messaging; | 23 | this.Messaging = messaging; |
| 24 | this.BackendExtensions = backendExtensions; | 24 | this.BackendExtensions = backendExtensions; |
| @@ -54,7 +54,7 @@ namespace WixToolset.Core.Burn.Bundles | |||
| 54 | 54 | ||
| 55 | private IEnumerable<PackageFacade> OrderedPackages { get; } | 55 | private IEnumerable<PackageFacade> OrderedPackages { get; } |
| 56 | 56 | ||
| 57 | private IEnumerable<SearchFacade> OrderedSearches { get; } | 57 | private IEnumerable<ISearchFacade> OrderedSearches { get; } |
| 58 | 58 | ||
| 59 | private Dictionary<string, WixBundlePayloadTuple> Payloads { get; } | 59 | private Dictionary<string, WixBundlePayloadTuple> Payloads { get; } |
| 60 | 60 | ||
diff --git a/src/WixToolset.Core.Burn/Bundles/OrderSearchesCommand.cs b/src/WixToolset.Core.Burn/Bundles/OrderSearchesCommand.cs new file mode 100644 index 00000000..55b31ed3 --- /dev/null +++ b/src/WixToolset.Core.Burn/Bundles/OrderSearchesCommand.cs | |||
| @@ -0,0 +1,71 @@ | |||
| 1 | // 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. | ||
| 2 | |||
| 3 | namespace WixToolset.Core.Burn.Bundles | ||
| 4 | { | ||
| 5 | using System.Collections.Generic; | ||
| 6 | using System.Linq; | ||
| 7 | using WixToolset.Data; | ||
| 8 | using WixToolset.Data.Burn; | ||
| 9 | using WixToolset.Data.Tuples; | ||
| 10 | using WixToolset.Extensibility.Services; | ||
| 11 | |||
| 12 | internal class OrderSearchesCommand | ||
| 13 | { | ||
| 14 | public OrderSearchesCommand(IMessaging messaging, IntermediateSection section) | ||
| 15 | { | ||
| 16 | this.Messaging = messaging; | ||
| 17 | this.Section = section; | ||
| 18 | } | ||
| 19 | |||
| 20 | private IMessaging Messaging { get; } | ||
| 21 | |||
| 22 | private IntermediateSection Section { get; } | ||
| 23 | |||
| 24 | public IDictionary<string, IList<IntermediateTuple>> ExtensionSearchTuplesByExtensionId { get; private set; } | ||
| 25 | |||
| 26 | public IList<ISearchFacade> OrderedSearchFacades { get; private set; } | ||
| 27 | |||
| 28 | public void Execute() | ||
| 29 | { | ||
| 30 | // TODO: Although the WixSearch tables are defined in the Util extension, | ||
| 31 | // the Bundle Binder has to know all about them. We hope to revisit all | ||
| 32 | // of this in the 4.0 timeframe. | ||
| 33 | var legacySearchesById = this.Section.Tuples | ||
| 34 | .Where(t => t.Definition.Type == TupleDefinitionType.WixComponentSearch || | ||
| 35 | t.Definition.Type == TupleDefinitionType.WixFileSearch || | ||
| 36 | t.Definition.Type == TupleDefinitionType.WixProductSearch || | ||
| 37 | t.Definition.Type == TupleDefinitionType.WixRegistrySearch) | ||
| 38 | .ToDictionary(t => t.Id.Id); | ||
| 39 | var extensionSearchesById = this.Section.Tuples | ||
| 40 | .Where(t => t.Definition.HasTag(BurnConstants.BundleExtensionSearchTupleDefinitionTag)) | ||
| 41 | .ToDictionary(t => t.Id.Id); | ||
| 42 | var searchTuples = this.Section.Tuples.OfType<WixSearchTuple>().ToList(); | ||
| 43 | |||
| 44 | this.ExtensionSearchTuplesByExtensionId = new Dictionary<string, IList<IntermediateTuple>>(); | ||
| 45 | this.OrderedSearchFacades = new List<ISearchFacade>(legacySearchesById.Keys.Count + extensionSearchesById.Keys.Count); | ||
| 46 | |||
| 47 | foreach (var searchTuple in searchTuples) | ||
| 48 | { | ||
| 49 | if (legacySearchesById.TryGetValue(searchTuple.Id.Id, out var specificSearchTuple)) | ||
| 50 | { | ||
| 51 | this.OrderedSearchFacades.Add(new LegacySearchFacade(searchTuple, specificSearchTuple)); | ||
| 52 | } | ||
| 53 | else if (extensionSearchesById.TryGetValue(searchTuple.Id.Id, out var extensionSearchTuple)) | ||
| 54 | { | ||
| 55 | this.OrderedSearchFacades.Add(new ExtensionSearchFacade(searchTuple)); | ||
| 56 | |||
| 57 | if (!this.ExtensionSearchTuplesByExtensionId.TryGetValue(searchTuple.BundleExtensionRef, out var extensionSearchTuples)) | ||
| 58 | { | ||
| 59 | extensionSearchTuples = new List<IntermediateTuple>(); | ||
| 60 | this.ExtensionSearchTuplesByExtensionId[searchTuple.BundleExtensionRef] = extensionSearchTuples; | ||
| 61 | } | ||
| 62 | extensionSearchTuples.Add(extensionSearchTuple); | ||
| 63 | } | ||
| 64 | else | ||
| 65 | { | ||
| 66 | this.Messaging.Write(ErrorMessages.MissingBundleSearch(searchTuple.SourceLineNumbers, searchTuple.Id.Id)); | ||
| 67 | } | ||
| 68 | } | ||
| 69 | } | ||
| 70 | } | ||
| 71 | } | ||
diff --git a/src/WixToolset.Core.Burn/ISearchFacade.cs b/src/WixToolset.Core.Burn/ISearchFacade.cs new file mode 100644 index 00000000..b9ad8649 --- /dev/null +++ b/src/WixToolset.Core.Burn/ISearchFacade.cs | |||
| @@ -0,0 +1,15 @@ | |||
| 1 | // 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. | ||
| 2 | |||
| 3 | namespace WixToolset.Core.Burn | ||
| 4 | { | ||
| 5 | using System.Xml; | ||
| 6 | |||
| 7 | internal interface ISearchFacade | ||
| 8 | { | ||
| 9 | /// <summary> | ||
| 10 | /// Writes the search to the Burn manifest. | ||
| 11 | /// </summary> | ||
| 12 | /// <param name="writer"></param> | ||
| 13 | void WriteXml(XmlTextWriter writer); | ||
| 14 | } | ||
| 15 | } | ||
