1 // Copyright (c) Microsoft. All rights reserved.
2 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3 
4 using System;
5 using System.Collections;
6 using System.Collections.Generic;
7 using System.Diagnostics;
8 using System.Globalization;
9 using System.Xml;
10 using System.Runtime.InteropServices;
11 
12 namespace Microsoft.Build.Tasks.Deployment.Bootstrapper
13 {
14     internal enum CopyAllFilesType
15     {
16         CopyAllFilesFalse, CopyAllFilesTrue, CopyAllFilesIfNotHomeSite
17     };
18 
19     /// <summary>
20     /// This class represents a product in the found by the BootstrapperBuilder in the Path property.
21     /// </summary>
22     [ComVisible(true), GuidAttribute("532BF563-A85D-4088-8048-41F51AC5239F"), ClassInterface(ClassInterfaceType.None)]
23     public class Product : IProduct
24     {
25         private XmlNode _node;
26         private string _productCode;
27         private PackageCollection _packages;
28         private ProductCollection _includes;
29         private List<List<Product>> _dependencies;
30         private ArrayList _missingDependencies;
31         private Hashtable _cultures;
32         private CopyAllFilesType _copyAllPackageFiles;
33         private ProductValidationResults _validationResults;
34 
Product()35         public Product()
36         {
37             Debug.Fail("Products are not to be created in this fashion.  Please use IBootstrapperBuilder.Products instead.");
38             throw new InvalidOperationException();
39         }
40 
Product(XmlNode node, string code, ProductValidationResults validationResults, string copyAll)41         internal Product(XmlNode node, string code, ProductValidationResults validationResults, string copyAll)
42         {
43             _node = node;
44             _packages = new PackageCollection();
45             _includes = new ProductCollection();
46             _dependencies = new List<List<Product>>();
47             _missingDependencies = new ArrayList();
48             _productCode = code;
49             _validationResults = validationResults;
50             _cultures = new Hashtable();
51             if (copyAll == "IfNotHomeSite")
52                 _copyAllPackageFiles = CopyAllFilesType.CopyAllFilesIfNotHomeSite;
53             else if (copyAll == "false")
54                 _copyAllPackageFiles = CopyAllFilesType.CopyAllFilesFalse;
55             else
56                 _copyAllPackageFiles = CopyAllFilesType.CopyAllFilesTrue;
57         }
58 
59         internal XmlNode Node
60         {
61             get { return _node; }
62         }
63 
64         internal CopyAllFilesType CopyAllPackageFiles
65         {
66             get { return _copyAllPackageFiles; }
67         }
68 
69         /// <summary>
70         /// The ProductBuilder representation of this Product
71         /// </summary>
72         public ProductBuilder ProductBuilder
73         {
74             get { return new ProductBuilder(this); }
75         }
76 
77         /// <summary>
78         /// A string specifying the unique identifier of this product
79         /// </summary>
80         public string ProductCode
81         {
82             get { return _productCode; }
83         }
84 
85         /// <summary>
86         /// A human-readable name for this product
87         /// </summary>
88         public string Name
89         {
90             get
91             {
92                 CultureInfo culture = Util.DefaultCultureInfo;
93                 Package p = _packages.Package(culture.Name);
94 
95                 if (p != null)
96                 {
97                     return p.Name;
98                 }
99 
100                 while (culture != null && culture != CultureInfo.InvariantCulture)
101                 {
102                     p = _packages.Package(culture.Parent.Name);
103 
104                     if (p != null)
105                     {
106                         return p.Name;
107                     }
108 
109                     culture = culture.Parent;
110                 }
111 
112                 if (_packages.Count > 0)
113                 {
114                     return _packages.Item(0).Name;
115                 }
116 
117                 return _productCode.ToString();
118             }
119         }
120 
121         /// <summary>
122         /// All products which this product also installs
123         /// </summary>
124         public ProductCollection Includes
125         {
126             get { return _includes; }
127         }
128 
129         internal List<List<Product>> Dependencies
130         {
131             get { return _dependencies; }
132         }
133 
ContainsCulture(string culture)134         internal bool ContainsCulture(string culture)
135         {
136             return _cultures.Contains(culture.ToLowerInvariant());
137         }
138 
ContainsDependencies(List<Product> dependenciesToCheck)139         internal bool ContainsDependencies(List<Product> dependenciesToCheck)
140         {
141             foreach (List<Product> d in _dependencies)
142             {
143                 bool found = true;
144                 foreach (Product p in d)
145                 {
146                     bool containedInDependencies = false;
147                     foreach (Product pd in dependenciesToCheck)
148                     {
149                         if (p._productCode == pd._productCode)
150                         {
151                             containedInDependencies = true;
152                             break;
153                         }
154                     }
155                     if (!containedInDependencies)
156                     {
157                         found = false;
158                         break;
159                     }
160                 }
161 
162                 if (found)
163                 {
164                     return true;
165                 }
166             }
167 
168             return false;
169         }
170 
171         internal ArrayList MissingDependencies
172         {
173             get
174             {
175                 return _missingDependencies;
176             }
177         }
178 
AddPackage(Package package)179         internal void AddPackage(Package package)
180         {
181             if (package == null || String.IsNullOrEmpty(package.Culture))
182                 throw new ArgumentNullException("package");
183 
184             if (!_cultures.Contains(package.Culture.ToLowerInvariant()))
185             {
186                 _packages.Add(package);
187                 _cultures.Add(package.Culture.ToLowerInvariant(), package);
188             }
189             else
190             {
191                 Debug.WriteLine(String.Format(CultureInfo.CurrentCulture, "A package with culture '{0}' has already been added to product '{1}'", package.Culture.ToLowerInvariant(), ProductCode));
192             }
193         }
194 
AddIncludedProduct(Product product)195         internal void AddIncludedProduct(Product product)
196         {
197             _includes.Add(product);
198         }
199 
AddDependentProduct(Product product)200         internal void AddDependentProduct(Product product)
201         {
202             List<Product> newDependency = new List<Product>();
203             newDependency.Add(product);
204             _dependencies.Add(newDependency);
205         }
206 
AddMissingDependency(ArrayList productCodes)207         internal void AddMissingDependency(ArrayList productCodes)
208         {
209             bool found = false;
210             foreach (ArrayList md in _missingDependencies)
211             {
212                 bool hasAll = true;
213                 foreach (string dep in md)
214                 {
215                     if (!productCodes.Contains(dep))
216                     {
217                         hasAll = false;
218                         break;
219                     }
220                 }
221 
222                 if (hasAll)
223                 {
224                     found = true;
225                     break;
226                 }
227             }
228 
229             if (!found)
230             {
231                 _missingDependencies.Add(productCodes);
232             }
233         }
234 
235         internal PackageCollection Packages
236         {
237             get { return _packages; }
238         }
239 
GetPackageValidationResults(string culture)240         internal XmlValidationResults GetPackageValidationResults(string culture)
241         {
242             if (_validationResults == null)
243                 return null;
244             return _validationResults.PackageResults(culture);
245         }
246 
247         internal bool ValidationPassed
248         {
249             get
250             {
251                 if (_validationResults == null)
252                     return true;
253                 return _validationResults.ValidationPassed;
254             }
255         }
256 
257         internal ProductValidationResults ValidationResults
258         {
259             get { return _validationResults; }
260         }
261     }
262 }
263