/* * Copyright (c) 2022 Vaughn Nugent * * Library: VNLib * Package: VNLib.Plugins.Extensions.Loading * File: ConfigurationExtensions.cs * * ConfigurationExtensions.cs is part of VNLib.Plugins.Extensions.Loading which is part of the larger * VNLib collection of libraries and utilities. * * VNLib.Plugins.Extensions.Loading is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published * by the Free Software Foundation, either version 2 of the License, * or (at your option) any later version. * * VNLib.Plugins.Extensions.Loading is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * General Public License for more details. * * You should have received a copy of the GNU General Public License * along with VNLib.Plugins.Extensions.Loading. If not, see http://www.gnu.org/licenses/. */ using System; using System.Linq; using System.Text.Json; using System.Reflection; using System.Collections.Generic; using VNLib.Utils.Extensions; namespace VNLib.Plugins.Extensions.Loading { /// /// Specifies a configuration variable name in the plugin's configuration /// containing data specific to the type /// [AttributeUsage(AttributeTargets.Class)] public sealed class ConfigurationNameAttribute : Attribute { /// /// /// public string ConfigVarName { get; } /// /// Initializes a new /// /// The name of the configuration variable for the class public ConfigurationNameAttribute(string configVarName) { ConfigVarName = configVarName; } } /// /// Contains extensions for plugin configuration specifc extensions /// public static class ConfigurationExtensions { public const string S3_CONFIG = "s3_config"; public const string S3_SECRET_KEY = "s3_secret"; /// /// Retrieves a top level configuration dictionary of elements for the specified type. /// The type must contain a /// /// The type to get the configuration of /// /// A of top level configuration elements for the type /// public static IReadOnlyDictionary GetConfigForType(this PluginBase plugin) { Type t = typeof(T); return plugin.GetConfigForType(t); } /// /// Retrieves a top level configuration dictionary of elements with the specified property name, /// from the plugin config first, or falls back to the host config file /// /// /// The config property name to retrieve /// A of top level configuration elements for the type /// /// public static IReadOnlyDictionary GetConfig(this PluginBase plugin, string propName) { plugin.ThrowIfUnloaded(); try { //Try to get the element from the plugin config first if (!plugin.PluginConfig.TryGetProperty(propName, out JsonElement el)) { //Fallback to the host config el = plugin.HostConfig.GetProperty(propName); } //Get the top level config as a dictionary return el.EnumerateObject().ToDictionary(static k => k.Name, static k => k.Value); } catch(KeyNotFoundException) { throw new KeyNotFoundException($"Missing required top level configuration object '{propName}', in host/plugin configuration files"); } } /// /// Retrieves a top level configuration dictionary of elements with the specified property name, /// from the plugin config first, or falls back to the host config file /// /// /// The config property name to retrieve /// A of top level configuration elements for the type /// public static IReadOnlyDictionary? TryGetConfig(this PluginBase plugin, string propName) { plugin.ThrowIfUnloaded(); //Try to get the element from the plugin config first, or fallback to host if (plugin.PluginConfig.TryGetProperty(propName, out JsonElement el) || plugin.HostConfig.TryGetProperty(propName, out el)) { //Get the top level config as a dictionary return el.EnumerateObject().ToDictionary(static k => k.Name, static k => k.Value); } //No config found return null; } /// /// Retrieves a top level configuration dictionary of elements for the specified type. /// The type must contain a /// /// /// The type to get configuration data for /// A of top level configuration elements for the type /// public static IReadOnlyDictionary GetConfigForType(this PluginBase plugin, Type type) { //Get config name attribute from plugin type ConfigurationNameAttribute? configName = type.GetCustomAttribute(); return configName?.ConfigVarName == null ? throw new KeyNotFoundException("No configuration attribute set") : plugin.GetConfig(configName.ConfigVarName); } /// /// Shortcut extension for to get /// config of current class /// /// The object that a configuration can be retrieved for /// The plugin containing configuration variables /// A of top level configuration elements for the type /// public static IReadOnlyDictionary GetConfig(this PluginBase plugin, object obj) { Type t = obj.GetType(); return plugin.GetConfigForType(t); } /// /// Determines if the current plugin configuration contains the require properties to initialize /// the type /// /// /// /// True if the plugin config contains the require configuration property public static bool HasConfigForType(this PluginBase plugin) { Type type = typeof(T); ConfigurationNameAttribute? configName = type.GetCustomAttribute(); //See if the plugin contains a configuration varables return configName != null && plugin.PluginConfig.TryGetProperty(configName.ConfigVarName, out _); } /// /// Attempts to load the basic S3 configuration variables required /// for S3 client access /// /// /// The S3 configuration object found in the plugin/host configuration public static S3Config? TryGetS3Config(this PluginBase plugin) { //Try get the config IReadOnlyDictionary? s3conf = plugin.TryGetConfig(S3_CONFIG); if(s3conf == null) { return null; } //Try get the elements return new() { BaseBucket = s3conf.GetPropString("bucket"), ClientId = s3conf.GetPropString("access_key"), ServerAddress = s3conf.GetPropString("server_address"), UseSsl = s3conf.TryGetValue("use_ssl", out JsonElement el) && el.GetBoolean(), ClientSecret = plugin.TryGetSecretAsync(S3_SECRET_KEY).Result, Region = s3conf.GetPropString("region"), }; } } }