Files
autodesk/Plant3D2026/P_Rec_Annot/src/PRecAnnot.Plant3D2026/CompositeModuleManifest.cs
T

28 lines
1.8 KiB
C#

using System.Security.Cryptography;
using System.Text.Json;
namespace PRecAnnot.Plant3D2026;
internal sealed record CompositeAssemblyManifest(string Name, string Sha256, bool Required);
internal sealed record CompositeManifest(int SchemaVersion, string Package, string Version, IReadOnlyList<string> Modules, IReadOnlyList<CompositeAssemblyManifest> Assemblies);
internal static class CompositeModuleManifest
{
public static CompositeManifest Validate()
{
var assemblyPath = typeof(EntryPoint).Assembly.Location;
var path = Path.GetFullPath(Path.Combine(Path.GetDirectoryName(assemblyPath)!, "..", "module-manifest.json"));
if (!File.Exists(path)) throw new InvalidOperationException("COMPOSITE_MODULE_MANIFEST_MISSING");
var manifest = JsonSerializer.Deserialize<CompositeManifest>(File.ReadAllText(path), new JsonSerializerOptions { PropertyNameCaseInsensitive = true }) ?? throw new InvalidOperationException("COMPOSITE_MODULE_MANIFEST_INVALID");
if (manifest.SchemaVersion != 1 || !string.Equals(manifest.Package, "P_Rec_Annot", StringComparison.Ordinal) || manifest.Modules.Count == 0) throw new InvalidOperationException("COMPOSITE_MODULE_MANIFEST_INVALID");
foreach (var item in manifest.Assemblies.Where(value => value.Required))
{
var file = Path.Combine(Path.GetDirectoryName(assemblyPath)!, item.Name);
if (!File.Exists(file)) throw new InvalidOperationException($"COMPOSITE_MODULE_ASSEMBLY_MISSING:{item.Name}");
var hash = Convert.ToHexString(SHA256.HashData(File.ReadAllBytes(file))).ToLowerInvariant();
if (!string.Equals(hash, item.Sha256, StringComparison.OrdinalIgnoreCase)) throw new InvalidOperationException($"COMPOSITE_MODULE_HASH_MISMATCH:{item.Name}");
}
return manifest;
}
}