main
cs 128 lines 5 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 WixToolset.Data;
8 using WixToolset.Data.Burn;
9 using WixToolset.Data.Symbols;
10 using WixToolset.Extensibility;
11 using WixToolset.Extensibility.Services;
12
13 internal class ResolveDownloadUrlsCommand
14 {
15 public ResolveDownloadUrlsCommand(IMessaging messaging, IEnumerable<IBurnBackendBinderExtension> backendExtensions, IEnumerable<WixBundleContainerSymbol> containers, Dictionary<string, WixBundlePayloadSymbol> payloadsById)
16 {
17 this.Messaging = messaging;
18 this.BackendExtensions = backendExtensions;
19 this.Containers = containers;
20 this.PayloadsById = payloadsById;
21 }
22
23 private IMessaging Messaging { get; }
24
25 private IEnumerable<IBurnBackendBinderExtension> BackendExtensions { get; }
26
27 private IEnumerable<WixBundleContainerSymbol> Containers { get; }
28
29 private Dictionary<string, WixBundlePayloadSymbol> PayloadsById { get; }
30
31 public void Execute()
32 {
33 this.ResolveContainerUrls();
34
35 this.ResolvePayloadUrls();
36 }
37
38 private void ResolveContainerUrls()
39 {
40 foreach (var container in this.Containers)
41 {
42 if (container.Type == ContainerType.Detached)
43 {
44 var resolvedUrl = this.ResolveUrl(container.DownloadUrl, null, null, container.Id.Id, container.Name);
45 if (!String.IsNullOrEmpty(resolvedUrl))
46 {
47 container.DownloadUrl = resolvedUrl;
48 }
49 }
50 else if (container.Type == ContainerType.Attached)
51 {
52 if (!String.IsNullOrEmpty(container.DownloadUrl))
53 {
54 this.Messaging.Write(WarningMessages.DownloadUrlNotSupportedForAttachedContainers(container.SourceLineNumbers, container.Id.Id));
55 }
56 }
57 }
58 }
59
60 private void ResolvePayloadUrls()
61 {
62 foreach (var payload in this.PayloadsById.Values)
63 {
64 if (payload.Packaging == PackagingType.Embedded && payload.ContainerRef == BurnConstants.BurnUXContainerName)
65 {
66 if (!String.IsNullOrEmpty(payload.DownloadUrl))
67 {
68 this.Messaging.Write(WarningMessages.DownloadUrlNotSupportedForBAPayloads(payload.SourceLineNumbers, payload.Id.Id));
69 }
70 }
71 else
72 {
73 var packageId = payload.ParentPackagePayloadRef;
74 var parentUrl = payload.ParentPackagePayloadRef == null ? null : this.PayloadsById[payload.ParentPackagePayloadRef].DownloadUrl;
75 var resolvedUrl = this.ResolveUrl(payload.DownloadUrl, parentUrl, packageId, payload.Id.Id, payload.Name);
76 if (!String.IsNullOrEmpty(resolvedUrl))
77 {
78 payload.DownloadUrl = resolvedUrl;
79 }
80 }
81 }
82 }
83
84 private string ResolveUrl(string url, string fallbackUrl, string packageId, string payloadId, string fileName)
85 {
86 string resolvedUrl = null;
87
88 foreach (var extension in this.BackendExtensions)
89 {
90 resolvedUrl = extension.ResolveUrl(url, fallbackUrl, packageId, payloadId, fileName);
91 if (!String.IsNullOrEmpty(resolvedUrl))
92 {
93 break;
94 }
95 }
96
97 if (String.IsNullOrEmpty(resolvedUrl))
98 {
99 // If a URL was not specified but there is a fallback URL that has a format specifier in it
100 // then use the fallback URL formatter for this URL.
101 if (String.IsNullOrEmpty(url) && !String.IsNullOrEmpty(fallbackUrl))
102 {
103 var formattedFallbackUrl = String.Format(fallbackUrl, packageId, payloadId, fileName);
104 if (!String.Equals(fallbackUrl, formattedFallbackUrl, StringComparison.OrdinalIgnoreCase))
105 {
106 url = fallbackUrl;
107 }
108 }
109
110 if (!String.IsNullOrEmpty(url))
111 {
112 var formattedUrl = String.Format(url, packageId, payloadId, fileName);
113
114 if (Uri.TryCreate(formattedUrl, UriKind.Absolute, out var canonicalUri))
115 {
116 resolvedUrl = canonicalUri.AbsoluteUri;
117 }
118 else
119 {
120 resolvedUrl = null;
121 }
122 }
123 }
124
125 return resolvedUrl;
126 }
127 }
128 }