using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Net.Http; using System.Threading.Tasks; namespace AWSPowerShellGenerator.Utils { /// /// This class provides helper methods to download libraries from NuGet. /// class SdkVersionsUtils { private const string SdkLibraryPrefix = "AWSSDK."; private static HashSet DownloadedSdkPlatforms = new HashSet(); internal static IEnumerable GetDependencies(string sdkAssembliesFolder, string packageName) { if (!packageName.StartsWith(SdkLibraryPrefix)) { throw new ArgumentException($"{packageName} is not an AWS SDK library"); } try { var root = ReadSdkVersionFile(sdkAssembliesFolder); if (packageName == "AWSSDK.Core") { return new string[0]; } else { var package = root["ServiceVersions"][packageName.Substring(SdkLibraryPrefix.Length)]; if (package != null) { var sdkDependencies = package["Dependencies"].Children() .OfType() .Select(dep => dep.Name) .Except(new string[] { "Core" }) .ToArray(); return sdkDependencies; } else { return new string[0]; } } } catch (Exception e) { throw new Exception($"Error while reading {packageName} entry from version file", e); } } internal static Version GetSDKVersion(string sdkAssembliesFolder) { try { var root = ReadSdkVersionFile(sdkAssembliesFolder); return Version.Parse((string)root["ProductVersion"]); } catch (Exception e) { throw new Exception($"Error while reading ProductVersion from version file", e); } } /// /// Downloads the latest version of a library. /// /// Name of the NuGet package /// Path where the library should be extracted /// Name of the platorm, for example "net45" or "netstandard2.0' /// A list of other SDK libraries this library depends on internal static void EnsureSdkLibraryIsAvailable(string packageName, string sdkAssembliesFolder, IEnumerable platformNames) { Directory.CreateDirectory(sdkAssembliesFolder); foreach (string platformName in platformNames) { var platformPath = Path.Combine(sdkAssembliesFolder, platformName); Directory.CreateDirectory(platformPath); foreach (var fileName in new string[] { $"{packageName}.dll", $"{packageName}.xml" }) { string filePath = Path.Combine(platformPath, fileName); if (!File.Exists(filePath)) { var version = SdkVersionsUtils.GetSDKVersion(sdkAssembliesFolder); DownloadSDKAssembliesAsync(platformPath, platformName, version).Wait(); } } } } /// /// Downloads the required version/platform of the SDK assemblies /// private static async Task DownloadSDKAssembliesAsync(string platformPath, string platformName, Version sdkVersion) { if (DownloadedSdkPlatforms.Add(platformPath)) { var sdkUri = $"https://sdk-for-net.amazonwebservices.com/releases/aws-sdk-{platformName}-{sdkVersion}.zip"; Console.WriteLine($"Downloading SDK at {sdkUri}"); try { var tempFile = Path.GetTempFileName(); try { using (var client = new HttpClient()) using (var fileStream = File.Create(tempFile)) using (var packageStream = await client.GetStreamAsync(sdkUri)) { packageStream.CopyTo(fileStream); } using (var archive = ZipFile.OpenRead(tempFile)) { foreach (var entry in archive.Entries) { var filePath = Path.Combine(platformPath, entry.Name); //Existing files in the folder are not overwritten! if (!File.Exists(filePath)) { entry.ExtractToFile(filePath, false); } } } } finally { File.Delete(tempFile); } } catch (Exception e) { throw new Exception($"Error while downloading {sdkUri}", e); } } } internal static JObject ReadSdkVersionFile(string sdkAssembliesFolder) { var versionsFilePath = Path.Combine(sdkAssembliesFolder, "..", "_sdk-versions.json"); try { using (var jsonReader = new JsonTextReader(File.OpenText(versionsFilePath))) { return JObject.Load(jsonReader); } } catch (Exception e) { throw new Exception($"Error while reading from {versionsFilePath}", e); } } } }