From 4ebc33174c02e1c9f5693b5ef38ecfe3292c687f Mon Sep 17 00:00:00 2001 From: Rob Mensching Date: Fri, 11 Aug 2017 00:39:04 -0700 Subject: Move to .NET Core 2.0 --- src/WixToolset.Data/Library.cs | 297 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 src/WixToolset.Data/Library.cs (limited to 'src/WixToolset.Data/Library.cs') diff --git a/src/WixToolset.Data/Library.cs b/src/WixToolset.Data/Library.cs new file mode 100644 index 00000000..bb04d216 --- /dev/null +++ b/src/WixToolset.Data/Library.cs @@ -0,0 +1,297 @@ +// 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. + +namespace WixToolset.Data +{ + using System; + using System.Collections.Generic; + using System.IO; + using System.Linq; + using System.Xml; + + /// + /// Object that represents a library file. + /// + public sealed class Library + { + public const string XmlNamespaceUri = "http://wixtoolset.org/schemas/v4/wixlib"; + private static readonly Version CurrentVersion = new Version("4.0.0.0"); + + private string id; + private Dictionary localizations; + private List
sections; + + /// + /// Instantiates a new empty library which is only useful from static creating methods. + /// + private Library() + { + this.localizations = new Dictionary(); + this.sections = new List
(); + } + + /// + /// Instantiate a new library populated with sections. + /// + /// Sections to add to the library. + public Library(IEnumerable
sections) + { + this.localizations = new Dictionary(); + this.sections = new List
(sections); + + this.id = Convert.ToBase64String(Guid.NewGuid().ToByteArray()).TrimEnd('=').Replace('+', '.').Replace('/', '_'); + foreach (Section section in this.sections) + { + section.LibraryId = this.id; + } + } + + /// + /// Get the sections contained in this library. + /// + /// Sections contained in this library. + public IEnumerable
Sections { get { return this.sections; } } + + /// + /// Add a localization file to this library. + /// + /// The localization file to add. + public void AddLocalization(Localization localization) + { + Localization existingCulture; + if (this.localizations.TryGetValue(localization.Culture, out existingCulture)) + { + existingCulture.Merge(localization); + } + else + { + this.localizations.Add(localization.Culture, localization); + } + } + + /// + /// Gets localization files from this library that match the cultures passed in, in the order of the array of cultures. + /// + /// The list of cultures to get localizations for. + /// All localizations contained in this library that match the set of cultures provided, in the same order. + public IEnumerable GetLocalizations(string[] cultures) + { + foreach (string culture in cultures ?? new string[0]) + { + Localization localization; + if (this.localizations.TryGetValue(culture, out localization)) + { + yield return localization; + } + } + } + + /// + /// Loads a library from a path on disk. + /// + /// Path to library file saved on disk. + /// Collection containing TableDefinitions to use when reconstituting the intermediates. + /// Suppresses wix.dll version mismatch check. + /// Returns the loaded library. + public static Library Load(string path, TableDefinitionCollection tableDefinitions, bool suppressVersionCheck) + { + using (FileStream stream = File.OpenRead(path)) + { + return Load(stream, new Uri(Path.GetFullPath(path)), tableDefinitions, suppressVersionCheck); + } + } + + /// + /// Loads a library from a stream. + /// + /// Stream containing the library file. + /// Uri for finding this stream. + /// Collection containing TableDefinitions to use when reconstituting the intermediates. + /// Suppresses wix.dll version mismatch check. + /// Returns the loaded library. + public static Library Load(Stream stream, Uri uri, TableDefinitionCollection tableDefinitions, bool suppressVersionCheck) + { + using (FileStructure fs = FileStructure.Read(stream)) + { + if (FileFormat.Wixlib != fs.FileFormat) + { + throw new WixUnexpectedFileFormatException(uri.LocalPath, FileFormat.Wixlib, fs.FileFormat); + } + + using (XmlReader reader = XmlReader.Create(fs.GetDataStream(), null, uri.AbsoluteUri)) + { + try + { + reader.MoveToContent(); + return Library.Read(reader, tableDefinitions, suppressVersionCheck); + } + catch (XmlException xe) + { + throw new WixCorruptFileException(uri.LocalPath, fs.FileFormat, xe); + } + } + } + } + + /// + /// Saves a library to a path on disk. + /// + /// Path to save library file to on disk. + /// The WiX path resolver. + public void Save(string path, ILibraryBinaryFileResolver resolver) + { + List embedFilePaths = new List(); + + // Resolve paths to files that are to be embedded in the library. + if (null != resolver) + { + foreach (Table table in this.sections.SelectMany(s => s.Tables)) + { + foreach (Row row in table.Rows) + { + foreach (ObjectField objectField in row.Fields.Where(f => f is ObjectField)) + { + if (null != objectField.Data) + { + string file = resolver.Resolve(row.SourceLineNumbers, table.Name, (string)objectField.Data); + if (!String.IsNullOrEmpty(file)) + { + // File was successfully resolved so track the embedded index as the embedded file index. + objectField.EmbeddedFileIndex = embedFilePaths.Count; + embedFilePaths.Add(file); + } + else + { + Messaging.Instance.OnMessage(WixDataErrors.FileNotFound(row.SourceLineNumbers, (string)objectField.Data, table.Name)); + } + } + else // clear out embedded file id in case there was one there before. + { + objectField.EmbeddedFileIndex = null; + } + } + } + } + } + + // Do not save the library if errors were found while resolving object paths. + if (Messaging.Instance.EncounteredError) + { + return; + } + + // Ensure the location to output the library exists and write it out. + Directory.CreateDirectory(Path.GetDirectoryName(Path.GetFullPath(path))); + + using (FileStream stream = File.Create(path)) + using (FileStructure fs = FileStructure.Create(stream, FileFormat.Wixlib, embedFilePaths)) + using (XmlWriter writer = XmlWriter.Create(fs.GetDataStream())) + { + writer.WriteStartDocument(); + + this.Write(writer); + + writer.WriteEndDocument(); + } + } + + /// + /// Parse the root library element. + /// + /// XmlReader with library persisted as Xml. + /// Collection containing TableDefinitions to use when reconstituting the intermediates. + /// Suppresses check for wix.dll version mismatch. + /// The parsed Library. + private static Library Read(XmlReader reader, TableDefinitionCollection tableDefinitions, bool suppressVersionCheck) + { + if (!reader.LocalName.Equals("wixLibrary")) + { + throw new XmlException(); + } + + bool empty = reader.IsEmptyElement; + Library library = new Library(); + Version version = null; + + while (reader.MoveToNextAttribute()) + { + switch (reader.LocalName) + { + case "version": + version = new Version(reader.Value); + break; + case "id": + library.id = reader.Value; + break; + } + } + + if (!suppressVersionCheck && null != version && !Library.CurrentVersion.Equals(version)) + { + throw new WixException(WixDataErrors.VersionMismatch(SourceLineNumber.CreateFromUri(reader.BaseURI), "library", version.ToString(), Library.CurrentVersion.ToString())); + } + + if (!empty) + { + bool done = false; + + while (!done && (XmlNodeType.Element == reader.NodeType || reader.Read())) + { + switch (reader.NodeType) + { + case XmlNodeType.Element: + switch (reader.LocalName) + { + case "localization": + Localization localization = Localization.Read(reader, tableDefinitions); + library.localizations.Add(localization.Culture, localization); + break; + case "section": + Section section = Section.Read(reader, tableDefinitions); + section.LibraryId = library.id; + library.sections.Add(section); + break; + default: + throw new XmlException(); + } + break; + case XmlNodeType.EndElement: + done = true; + break; + } + } + + if (!done) + { + throw new XmlException(); + } + } + + return library; + } + + /// + /// Persists a library in an XML format. + /// + /// XmlWriter where the library should persist itself as XML. + private void Write(XmlWriter writer) + { + writer.WriteStartElement("wixLibrary", XmlNamespaceUri); + + writer.WriteAttributeString("version", CurrentVersion.ToString()); + + writer.WriteAttributeString("id", this.id); + + foreach (Localization localization in this.localizations.Values) + { + localization.Write(writer); + } + + foreach (Section section in this.sections) + { + section.Write(writer); + } + + writer.WriteEndElement(); + } + } +} -- cgit v1.2.3-55-g6feb