diff options
Diffstat (limited to 'src/WixToolset.Core/Extensibility/HeatExtension.cs')
-rw-r--r-- | src/WixToolset.Core/Extensibility/HeatExtension.cs | 204 |
1 files changed, 204 insertions, 0 deletions
diff --git a/src/WixToolset.Core/Extensibility/HeatExtension.cs b/src/WixToolset.Core/Extensibility/HeatExtension.cs new file mode 100644 index 00000000..5e292220 --- /dev/null +++ b/src/WixToolset.Core/Extensibility/HeatExtension.cs | |||
@@ -0,0 +1,204 @@ | |||
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.Extensibility | ||
4 | { | ||
5 | using System; | ||
6 | using System.Collections.Generic; | ||
7 | using System.IO; | ||
8 | using System.Reflection; | ||
9 | using WixToolset; | ||
10 | using WixToolset.Data; | ||
11 | using WixToolset.Extensibilty; | ||
12 | using WixToolset.Tools; | ||
13 | using Wix = WixToolset.Data.Serialize; | ||
14 | |||
15 | /// <summary> | ||
16 | /// A command line option. | ||
17 | /// </summary> | ||
18 | public struct HeatCommandLineOption | ||
19 | { | ||
20 | public string Option; | ||
21 | |||
22 | public string Description; | ||
23 | |||
24 | /// <summary> | ||
25 | /// Instantiates a new CommandLineOption. | ||
26 | /// </summary> | ||
27 | /// <param name="option">The option name.</param> | ||
28 | /// <param name="description">The description of the option.</param> | ||
29 | public HeatCommandLineOption(string option, string description) | ||
30 | { | ||
31 | this.Option = option; | ||
32 | this.Description = description; | ||
33 | } | ||
34 | } | ||
35 | |||
36 | /// <summary> | ||
37 | /// An extension for the WiX Toolset Harvester application. | ||
38 | /// </summary> | ||
39 | public abstract class HeatExtension | ||
40 | { | ||
41 | /// <summary> | ||
42 | /// Gets or sets the heat core for the extension. | ||
43 | /// </summary> | ||
44 | /// <value>The heat core for the extension.</value> | ||
45 | public IHeatCore Core { get; set; } | ||
46 | |||
47 | /// <summary> | ||
48 | /// Gets the supported command line types for this extension. | ||
49 | /// </summary> | ||
50 | /// <value>The supported command line types for this extension.</value> | ||
51 | public virtual HeatCommandLineOption[] CommandLineTypes | ||
52 | { | ||
53 | get { return null; } | ||
54 | } | ||
55 | |||
56 | /// <summary> | ||
57 | /// Loads a HeatExtension from a type description string. | ||
58 | /// </summary> | ||
59 | /// <param name="extension">The extension type description string.</param> | ||
60 | /// <returns>The loaded HeatExtension.</returns> | ||
61 | /// <remarks> | ||
62 | /// <paramref name="extension"/> can be in several different forms: | ||
63 | /// <list type="number"> | ||
64 | /// <item><term>AssemblyQualifiedName (TopNamespace.SubNameSpace.ContainingClass+NestedClass, MyAssembly, Version=1.3.0.0, Culture=neutral, PublicKeyToken=b17a5c561934e089)</term></item> | ||
65 | /// <item><term>AssemblyName (MyAssembly, Version=1.3.0.0, Culture=neutral, PublicKeyToken=b17a5c561934e089)</term></item> | ||
66 | /// <item><term>Absolute path to an assembly (C:\MyExtensions\ExtensionAssembly.dll)</term></item> | ||
67 | /// <item><term>Filename of an assembly in the application directory (ExtensionAssembly.dll)</term></item> | ||
68 | /// <item><term>Relative path to an assembly (..\..\MyExtensions\ExtensionAssembly.dll)</term></item> | ||
69 | /// </list> | ||
70 | /// To specify a particular class to use, prefix the fully qualified class name to the assembly and separate them with a comma. | ||
71 | /// For example: "TopNamespace.SubNameSpace.ContainingClass+NestedClass, C:\MyExtensions\ExtensionAssembly.dll" | ||
72 | /// </remarks> | ||
73 | public static HeatExtension Load(string extension) | ||
74 | { | ||
75 | Type extensionType = null; | ||
76 | int commaIndex = extension.IndexOf(','); | ||
77 | string className = String.Empty; | ||
78 | string assemblyName = extension; | ||
79 | |||
80 | if (0 <= commaIndex) | ||
81 | { | ||
82 | className = extension.Substring(0, commaIndex); | ||
83 | assemblyName = (extension.Length <= commaIndex + 1 ? String.Empty : extension.Substring(commaIndex + 1)); | ||
84 | } | ||
85 | |||
86 | className = className.Trim(); | ||
87 | assemblyName = assemblyName.Trim(); | ||
88 | |||
89 | if (null == extensionType && 0 < assemblyName.Length) | ||
90 | { | ||
91 | |||
92 | Assembly extensionAssembly; | ||
93 | |||
94 | // case 3: Absolute path to an assembly | ||
95 | if (Path.IsPathRooted(assemblyName)) | ||
96 | { | ||
97 | extensionAssembly = ExtensionLoadFrom(assemblyName); | ||
98 | } | ||
99 | else | ||
100 | { | ||
101 | try | ||
102 | { | ||
103 | // case 2: AssemblyName | ||
104 | extensionAssembly = Assembly.Load(assemblyName); | ||
105 | } | ||
106 | catch (IOException e) | ||
107 | { | ||
108 | if (e is FileLoadException || e is FileNotFoundException) | ||
109 | { | ||
110 | try | ||
111 | { | ||
112 | // case 4: Filename of an assembly in the application directory | ||
113 | extensionAssembly = Assembly.Load(Path.GetFileNameWithoutExtension(assemblyName)); | ||
114 | } | ||
115 | catch (IOException innerE) | ||
116 | { | ||
117 | if (innerE is FileLoadException || innerE is FileNotFoundException) | ||
118 | { | ||
119 | // case 5: Relative path to an assembly | ||
120 | |||
121 | // we want to use Assembly.Load when we can because it has some benefits over Assembly.LoadFrom | ||
122 | // (see the documentation for Assembly.LoadFrom). However, it may fail when the path is a relative | ||
123 | // path, so we should try Assembly.LoadFrom one last time. We could have detected a directory | ||
124 | // separator character and used Assembly.LoadFrom directly, but dealing with path canonicalization | ||
125 | // issues is something we don't want to deal with if we don't have to. | ||
126 | extensionAssembly = ExtensionLoadFrom(assemblyName); | ||
127 | } | ||
128 | else | ||
129 | { | ||
130 | throw new WixException(WixErrors.InvalidExtension(assemblyName, innerE.Message)); | ||
131 | } | ||
132 | } | ||
133 | } | ||
134 | else | ||
135 | { | ||
136 | throw new WixException(WixErrors.InvalidExtension(assemblyName, e.Message)); | ||
137 | } | ||
138 | } | ||
139 | } | ||
140 | |||
141 | if (0 < className.Length) | ||
142 | { | ||
143 | try | ||
144 | { | ||
145 | // case 1: AssemblyQualifiedName | ||
146 | extensionType = extensionAssembly.GetType(className, true /* throwOnError */, true /* ignoreCase */); | ||
147 | } | ||
148 | catch (Exception e) | ||
149 | { | ||
150 | throw new WixException(WixErrors.InvalidExtensionType(assemblyName, className, e.GetType().ToString(), e.Message)); | ||
151 | } | ||
152 | } | ||
153 | else | ||
154 | { | ||
155 | // if no class name was specified, then let's hope the assembly defined a default WixExtension | ||
156 | AssemblyDefaultHeatExtensionAttribute extensionAttribute = (AssemblyDefaultHeatExtensionAttribute)Attribute.GetCustomAttribute(extensionAssembly, typeof(AssemblyDefaultHeatExtensionAttribute)); | ||
157 | |||
158 | if (null != extensionAttribute) | ||
159 | { | ||
160 | extensionType = extensionAttribute.ExtensionType; | ||
161 | } | ||
162 | else | ||
163 | { | ||
164 | throw new WixException(WixErrors.InvalidExtensionType(assemblyName, typeof(AssemblyDefaultHeatExtensionAttribute).ToString())); | ||
165 | } | ||
166 | } | ||
167 | } | ||
168 | |||
169 | if (extensionType.IsSubclassOf(typeof(HeatExtension))) | ||
170 | { | ||
171 | return Activator.CreateInstance(extensionType) as HeatExtension; | ||
172 | } | ||
173 | else | ||
174 | { | ||
175 | throw new WixException(WixErrors.InvalidExtensionType(extension, extensionType.ToString(), typeof(HeatExtension).ToString())); | ||
176 | } | ||
177 | } | ||
178 | |||
179 | /// <summary> | ||
180 | /// Parse the command line options for this extension. | ||
181 | /// </summary> | ||
182 | /// <param name="type">The active harvester type.</param> | ||
183 | /// <param name="args">The option arguments.</param> | ||
184 | public virtual void ParseOptions(string type, string[] args) | ||
185 | { | ||
186 | } | ||
187 | |||
188 | private static Assembly ExtensionLoadFrom(string assemblyName) | ||
189 | { | ||
190 | Assembly extensionAssembly = null; | ||
191 | |||
192 | try | ||
193 | { | ||
194 | extensionAssembly = Assembly.LoadFrom(assemblyName); | ||
195 | } | ||
196 | catch (Exception e) | ||
197 | { | ||
198 | throw new WixException(WixErrors.InvalidExtension(assemblyName, e.Message)); | ||
199 | } | ||
200 | |||
201 | return extensionAssembly; | ||
202 | } | ||
203 | } | ||
204 | } | ||