diff options
Diffstat (limited to 'lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs')
-rw-r--r-- | lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs | 199 |
1 files changed, 199 insertions, 0 deletions
diff --git a/lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs b/lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs new file mode 100644 index 0000000..18df8e0 --- /dev/null +++ b/lib/VNLib.Plugins.Extensions.Loading/src/ConfigurationExtensions.cs @@ -0,0 +1,199 @@ +/* +* 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 +{ + /// <summary> + /// Specifies a configuration variable name in the plugin's configuration + /// containing data specific to the type + /// </summary> + [AttributeUsage(AttributeTargets.Class)] + public sealed class ConfigurationNameAttribute : Attribute + { + /// <summary> + /// + /// </summary> + public string ConfigVarName { get; } + + /// <summary> + /// Initializes a new <see cref="ConfigurationNameAttribute"/> + /// </summary> + /// <param name="configVarName">The name of the configuration variable for the class</param> + public ConfigurationNameAttribute(string configVarName) + { + ConfigVarName = configVarName; + } + } + + /// <summary> + /// Contains extensions for plugin configuration specifc extensions + /// </summary> + public static class ConfigurationExtensions + { + public const string S3_CONFIG = "s3_config"; + public const string S3_SECRET_KEY = "s3_secret"; + + /// <summary> + /// Retrieves a top level configuration dictionary of elements for the specified type. + /// The type must contain a <see cref="ConfigurationNameAttribute"/> + /// </summary> + /// <typeparam name="T">The type to get the configuration of</typeparam> + /// <param name="plugin"></param> + /// <returns>A <see cref="Dictionary{TKey, TValue}"/> of top level configuration elements for the type</returns> + /// <exception cref="ObjectDisposedException"></exception> + public static IReadOnlyDictionary<string, JsonElement> GetConfigForType<T>(this PluginBase plugin) + { + Type t = typeof(T); + return plugin.GetConfigForType(t); + } + /// <summary> + /// 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 + /// </summary> + /// <param name="plugin"></param> + /// <param name="propName">The config property name to retrieve</param> + /// <returns>A <see cref="Dictionary{TKey, TValue}"/> of top level configuration elements for the type</returns> + /// <exception cref="KeyNotFoundException"></exception> + /// <exception cref="ObjectDisposedException"></exception> + public static IReadOnlyDictionary<string, JsonElement> 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"); + } + } + /// <summary> + /// 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 + /// </summary> + /// <param name="plugin"></param> + /// <param name="propName">The config property name to retrieve</param> + /// <returns>A <see cref="Dictionary{TKey, TValue}"/> of top level configuration elements for the type</returns> + /// <exception cref="ObjectDisposedException"></exception> + public static IReadOnlyDictionary<string, JsonElement>? 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; + } + + /// <summary> + /// Retrieves a top level configuration dictionary of elements for the specified type. + /// The type must contain a <see cref="ConfigurationNameAttribute"/> + /// </summary> + /// <param name="plugin"></param> + /// <param name="type">The type to get configuration data for</param> + /// <returns>A <see cref="Dictionary{TKey, TValue}"/> of top level configuration elements for the type</returns> + /// <exception cref="ObjectDisposedException"></exception> + public static IReadOnlyDictionary<string, JsonElement> GetConfigForType(this PluginBase plugin, Type type) + { + //Get config name attribute from plugin type + ConfigurationNameAttribute? configName = type.GetCustomAttribute<ConfigurationNameAttribute>(); + return configName?.ConfigVarName == null + ? throw new KeyNotFoundException("No configuration attribute set") + : plugin.GetConfig(configName.ConfigVarName); + } + + /// <summary> + /// Shortcut extension for <see cref="GetConfigForType{T}(PluginBase)"/> to get + /// config of current class + /// </summary> + /// <param name="obj">The object that a configuration can be retrieved for</param> + /// <param name="plugin">The plugin containing configuration variables</param> + /// <returns>A <see cref="Dictionary{TKey, TValue}"/> of top level configuration elements for the type</returns> + /// <exception cref="ObjectDisposedException"></exception> + public static IReadOnlyDictionary<string, JsonElement> GetConfig(this PluginBase plugin, object obj) + { + Type t = obj.GetType(); + return plugin.GetConfigForType(t); + } + + /// <summary> + /// Determines if the current plugin configuration contains the require properties to initialize + /// the type + /// </summary> + /// <typeparam name="T"></typeparam> + /// <param name="plugin"></param> + /// <returns>True if the plugin config contains the require configuration property</returns> + public static bool HasConfigForType<T>(this PluginBase plugin) + { + Type type = typeof(T); + ConfigurationNameAttribute? configName = type.GetCustomAttribute<ConfigurationNameAttribute>(); + //See if the plugin contains a configuration varables + return configName != null && plugin.PluginConfig.TryGetProperty(configName.ConfigVarName, out _); + } + + /// <summary> + /// Attempts to load the basic S3 configuration variables required + /// for S3 client access + /// </summary> + /// <param name="plugin"></param> + /// <returns>The S3 configuration object found in the plugin/host configuration</returns> + public static S3Config? TryGetS3Config(this PluginBase plugin) + { + //Try get the config + IReadOnlyDictionary<string, JsonElement>? 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(), + Region = s3conf.GetPropString("region"), + }; + } + } +} |