main
cs 244 lines 11.7 KB
Raw
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.Bind
4 {
5 using System;
6 using System.Collections.Generic;
7 using System.Linq;
8 using System.Text;
9 using System.Xml;
10 using WixToolset.Core.Burn.Bundles;
11 using WixToolset.Core.Burn.ExtensibilityServices;
12 using WixToolset.Data;
13 using WixToolset.Data.Burn;
14 using WixToolset.Data.Symbols;
15 using WixToolset.Extensibility;
16 using WixToolset.Extensibility.Services;
17
18 internal class GenerateManifestDataFromIRCommand
19 {
20 public GenerateManifestDataFromIRCommand(IMessaging messaging, IntermediateSection section, IEnumerable<IBurnBackendBinderExtension> backendExtensions, IBurnBackendHelper backendHelper, IDictionary<string, IEnumerable<IntermediateSymbol>> extensionSearchSymbolsById)
21 {
22 this.Messaging = messaging;
23 this.Section = section;
24 this.BackendExtensions = backendExtensions;
25 this.BackendHelper = backendHelper;
26 this.ExtensionSearchSymbolsById = extensionSearchSymbolsById;
27 }
28
29 private IEnumerable<IBurnBackendBinderExtension> BackendExtensions { get; }
30
31 private IBurnBackendHelper BackendHelper { get; }
32
33 private IDictionary<string, IEnumerable<IntermediateSymbol>> ExtensionSearchSymbolsById { get; }
34
35 private IMessaging Messaging { get; }
36
37 private IntermediateSection Section { get; }
38
39 public void Execute()
40 {
41 var symbols = this.Section.Symbols.ToList();
42 var cellsByCustomDataAndElementId = new Dictionary<string, List<WixBundleCustomDataCellSymbol>>();
43 var customDataById = new Dictionary<string, WixBundleCustomDataSymbol>();
44
45 foreach (var kvp in this.ExtensionSearchSymbolsById)
46 {
47 var extensionId = kvp.Key;
48 var extensionSearchSymbols = kvp.Value;
49 foreach (var extensionSearchSymbol in extensionSearchSymbols)
50 {
51 this.BackendHelper.AddBootstrapperExtensionData(extensionId, extensionSearchSymbol, symbolIdIsIdAttribute: true);
52 symbols.Remove(extensionSearchSymbol);
53 }
54 }
55
56 foreach (var symbol in symbols)
57 {
58 var unknownSymbol = false;
59 switch (symbol.Definition.Type)
60 {
61 // Symbols used internally and are not added to a data manifest.
62 case SymbolDefinitionType.ProvidesDependency:
63 case SymbolDefinitionType.WixApprovedExeForElevation:
64 case SymbolDefinitionType.WixBootstrapperApplication:
65 case SymbolDefinitionType.WixBootstrapperApplicationDll:
66 case SymbolDefinitionType.WixBundle:
67 case SymbolDefinitionType.WixBundleContainer:
68 case SymbolDefinitionType.WixBundleCustomDataAttribute:
69 case SymbolDefinitionType.WixBundleBundlePackage:
70 case SymbolDefinitionType.WixBundleBundlePackagePayload:
71 case SymbolDefinitionType.WixBundleExePackage:
72 case SymbolDefinitionType.WixBundleExePackagePayload:
73 case SymbolDefinitionType.WixBootstrapperExtension:
74 case SymbolDefinitionType.WixBundleHarvestedBundlePackage:
75 case SymbolDefinitionType.WixBundleHarvestedDependencyProvider:
76 case SymbolDefinitionType.WixBundleHarvestedMsiPackage:
77 case SymbolDefinitionType.WixBundleHarvestedMspPackage:
78 case SymbolDefinitionType.WixBundleMsiFeature:
79 case SymbolDefinitionType.WixBundleMsiPackage:
80 case SymbolDefinitionType.WixBundleMsiPackagePayload:
81 case SymbolDefinitionType.WixBundleMsiProperty:
82 case SymbolDefinitionType.WixBundleMspPackage:
83 case SymbolDefinitionType.WixBundleMspPackagePayload:
84 case SymbolDefinitionType.WixBundleMsuPackage:
85 case SymbolDefinitionType.WixBundleMsuPackagePayload:
86 case SymbolDefinitionType.WixBundlePackage:
87 case SymbolDefinitionType.WixBundlePackageCommandLine:
88 case SymbolDefinitionType.WixBundlePackageExitCode:
89 case SymbolDefinitionType.WixBundlePackageGroup:
90 case SymbolDefinitionType.WixBundlePackageRelatedBundle:
91 case SymbolDefinitionType.WixBundlePatchTargetCode:
92 case SymbolDefinitionType.WixBundlePayload:
93 case SymbolDefinitionType.WixBundlePayloadGroup:
94 case SymbolDefinitionType.WixBundleRelatedPackage:
95 case SymbolDefinitionType.WixBundleRollbackBoundary:
96 case SymbolDefinitionType.WixBundleSlipstreamMsp:
97 case SymbolDefinitionType.WixBundleTag:
98 case SymbolDefinitionType.WixBundleUpdate:
99 case SymbolDefinitionType.WixBundleVariable:
100 case SymbolDefinitionType.WixBuildInfo:
101 case SymbolDefinitionType.WixChain:
102 case SymbolDefinitionType.WixChainItem:
103 case SymbolDefinitionType.WixComponentSearch:
104 case SymbolDefinitionType.WixDependencyProvider:
105 case SymbolDefinitionType.WixFileSearch:
106 case SymbolDefinitionType.WixGroup:
107 case SymbolDefinitionType.WixProductSearch:
108 case SymbolDefinitionType.WixRegistrySearch:
109 case SymbolDefinitionType.WixRelatedBundle:
110 case SymbolDefinitionType.WixSearch:
111 case SymbolDefinitionType.WixSearchRelation:
112 case SymbolDefinitionType.WixSetVariable:
113 case SymbolDefinitionType.WixUpdateRegistration:
114 break;
115
116 // Symbols used before binding.
117 case SymbolDefinitionType.WixComplexReference:
118 case SymbolDefinitionType.WixFragment:
119 case SymbolDefinitionType.WixOrdering:
120 case SymbolDefinitionType.WixSimpleReference:
121 case SymbolDefinitionType.WixVariable:
122 break;
123
124 // All other symbols need to be processed.
125 case SymbolDefinitionType.WixBundleCustomData:
126 unknownSymbol = !this.IndexBundleCustomDataSymbol((WixBundleCustomDataSymbol)symbol, customDataById);
127 break;
128
129 case SymbolDefinitionType.WixBundleCustomDataCell:
130 this.IndexBundleCustomDataCellSymbol((WixBundleCustomDataCellSymbol)symbol, cellsByCustomDataAndElementId);
131 break;
132
133 case SymbolDefinitionType.MustBeFromAnExtension:
134 unknownSymbol = !this.AddSymbolFromExtension(symbol);
135 break;
136
137 default:
138 unknownSymbol = true;
139 break;
140 }
141
142 if (unknownSymbol)
143 {
144 this.Messaging.Write(WarningMessages.SymbolNotTranslatedToOutput(symbol));
145 }
146 }
147
148 this.AddIndexedCellSymbols(customDataById, cellsByCustomDataAndElementId);
149 }
150
151 private bool IndexBundleCustomDataSymbol(WixBundleCustomDataSymbol wixBundleCustomDataSymbol, Dictionary<string, WixBundleCustomDataSymbol> customDataById)
152 {
153 switch (wixBundleCustomDataSymbol.Type)
154 {
155 case WixBundleCustomDataType.BootstrapperApplication:
156 case WixBundleCustomDataType.BootstrapperExtension:
157 break;
158 default:
159 return false;
160 }
161
162 var customDataId = wixBundleCustomDataSymbol.Id.Id;
163 customDataById.Add(customDataId, wixBundleCustomDataSymbol);
164 return true;
165 }
166
167 private void IndexBundleCustomDataCellSymbol(WixBundleCustomDataCellSymbol wixBundleCustomDataCellSymbol, Dictionary<string, List<WixBundleCustomDataCellSymbol>> cellsByCustomDataAndElementId)
168 {
169 var tableAndRowId = wixBundleCustomDataCellSymbol.CustomDataRef + "/" + wixBundleCustomDataCellSymbol.ElementId;
170 if (!cellsByCustomDataAndElementId.TryGetValue(tableAndRowId, out var cells))
171 {
172 cells = new List<WixBundleCustomDataCellSymbol>();
173 cellsByCustomDataAndElementId.Add(tableAndRowId, cells);
174 }
175
176 cells.Add(wixBundleCustomDataCellSymbol);
177 }
178
179 private void AddIndexedCellSymbols(Dictionary<string, WixBundleCustomDataSymbol> customDataById, Dictionary<string, List<WixBundleCustomDataCellSymbol>> cellsByCustomDataAndElementId)
180 {
181 foreach (var elementValues in cellsByCustomDataAndElementId.Values)
182 {
183 var elementName = elementValues[0].CustomDataRef;
184 var customDataSymbol = customDataById[elementName];
185
186 var attributeNames = customDataSymbol.AttributeNamesSeparated;
187
188 var elementValuesByAttribute = elementValues.ToDictionary(t => t.AttributeRef, t => t.Value);
189
190 var sb = new StringBuilder();
191 using (var writer = XmlWriter.Create(sb, BurnBackendHelper.WriterSettings))
192 {
193 switch (customDataSymbol.Type)
194 {
195 case WixBundleCustomDataType.BootstrapperApplication:
196 writer.WriteStartElement(elementName, BurnConstants.BootstrapperApplicationDataNamespace);
197 break;
198 case WixBundleCustomDataType.BootstrapperExtension:
199 writer.WriteStartElement(elementName, BurnConstants.BootstrapperExtensionDataNamespace);
200 break;
201 default:
202 throw new NotImplementedException();
203 }
204
205 // Write all row data as attributes in table column order.
206 foreach (var attributeName in attributeNames)
207 {
208 if (elementValuesByAttribute.TryGetValue(attributeName, out var value))
209 {
210 writer.WriteAttributeString(attributeName, value);
211 }
212 }
213
214 writer.WriteEndElement();
215 }
216
217 switch (customDataSymbol.Type)
218 {
219 case WixBundleCustomDataType.BootstrapperApplication:
220 this.BackendHelper.AddBootstrapperApplicationData(sb.ToString());
221 break;
222 case WixBundleCustomDataType.BootstrapperExtension:
223 this.BackendHelper.AddBootstrapperExtensionData(customDataSymbol.BootstrapperExtensionRef, sb.ToString());
224 break;
225 default:
226 throw new NotImplementedException();
227 }
228 }
229 }
230
231 private bool AddSymbolFromExtension(IntermediateSymbol symbol)
232 {
233 foreach (var extension in this.BackendExtensions)
234 {
235 if (extension.TryProcessSymbol(this.Section, symbol))
236 {
237 return true;
238 }
239 }
240
241 return false;
242 }
243 }
244 }