/// <summary> /// Creates a <see cref="SmartSignalPackage"/> from a zipped package stream /// </summary> /// <param name="zippedPackageStream">The zipped package stream</param> /// <param name="tracer">The tracer</param> /// <returns>A <see cref="SmartSignalPackage"/></returns> public static SmartSignalPackage CreateFromStream(Stream zippedPackageStream, ITracer tracer) { var packageContent = new Dictionary <string, byte[]>(StringComparer.OrdinalIgnoreCase); using (var archive = new ZipArchive(zippedPackageStream, ZipArchiveMode.Read)) { // for each file in the package get the file name and content and add it to the result dictionary foreach (ZipArchiveEntry entry in archive.Entries) { Stream entryStream = entry.Open(); using (var entryMemoryStream = new MemoryStream()) { entryStream.CopyTo(entryMemoryStream); byte[] entryBytes = entryMemoryStream.ToArray(); packageContent.Add(entry.FullName, entryBytes); } } } bool manifestFileExists = packageContent.TryGetValue(ManifestFileName, out byte[] manifestBytes); if (!manifestFileExists) { throw new InvalidSmartSignalPackageException("No manifest file found in the smart signal package"); } // Deserialize the manifest. We use stream reader to avoid unexpected characters such as BOM. using (var stream = new StreamReader(new MemoryStream(manifestBytes))) { string manifest = stream.ReadToEnd(); tracer.TraceInformation($"Deserializing signal manifest {manifest}"); SmartSignalManifest signalManifest = JsonConvert.DeserializeObject <SmartSignalManifest>(manifest); return(new SmartSignalPackage(signalManifest, packageContent)); } }
/// <summary> /// Creates a <see cref="SmartSignalPackage"/> from a folder /// </summary> /// <param name="sourceFolder">The folder of the package</param> /// <returns>A <see cref="SmartSignalPackage"/></returns> public static SmartSignalPackage CreateFromFolder(string sourceFolder) { string[] fileEntries = Directory.GetFiles(sourceFolder); var packageContent = new Dictionary <string, byte[]>(StringComparer.OrdinalIgnoreCase); // for each file in the package get the file name and content and add it to the result dictionary foreach (string fileNamePath in fileEntries) { packageContent.Add(Path.GetFileName(fileNamePath), File.ReadAllBytes(fileNamePath)); } bool manifestFileExists = packageContent.TryGetValue(ManifestFileName, out byte[] manifestBytes); if (!manifestFileExists) { throw new InvalidSmartSignalPackageException("Failed to create Smart Signal Package - no manifest file found in the smart signal package"); } try { // Validates the manifest. We use stream reader to avoid unexpected characters such as BOM. using (var stream = new StreamReader(new MemoryStream(manifestBytes))) { string manifest = stream.ReadToEnd(); SmartSignalManifest signalManifest = JsonConvert.DeserializeObject <SmartSignalManifest>(manifest); if (!packageContent.ContainsKey(signalManifest.AssemblyName)) { throw new InvalidSmartSignalPackageException("Failed to create Smart Signal Package - the manifest file is invalid: Assembly name must be a file in the smart signal package."); } if (!signalManifest.SupportedResourceTypes.Any()) { throw new InvalidSmartSignalPackageException("Failed to create Smart Signal Package - the manifest file is invalid: Must specify at least one supported resource type."); } if (!signalManifest.SupportedCadencesInMinutes.Any()) { throw new InvalidSmartSignalPackageException("Failed to create Smart Signal Package - the manifest file is invalid: Must specify at least one supported cadence."); } return(new SmartSignalPackage(signalManifest, packageContent)); } } catch (ArgumentException argumentException) { throw new InvalidSmartSignalPackageException($"Failed to create Smart Signal Package - the manifest file is invalid: {argumentException.Message}"); } catch (JsonException jsonException) { throw new InvalidSmartSignalPackageException($"Failed to create Smart Signal Package - the manifest file is invalid: {jsonException.Message}"); } }
/// <summary> /// Initializes a new instance of the <see cref="SmartSignalPackage"/> class. /// </summary> /// <param name="manifest">The signal's manifest</param> /// <param name="content">The signal package content represented by a dictionary mapping a file name to the file content bytes</param> public SmartSignalPackage(SmartSignalManifest manifest, IReadOnlyDictionary <string, byte[]> content) { if (manifest == null) { throw new ArgumentNullException(nameof(manifest)); } if (content == null) { throw new ArgumentNullException(nameof(content)); } else if (content.Count == 0) { throw new ArgumentException("Package content must include at least one item", nameof(content)); } this.Manifest = manifest; this.Content = content; }