/*
* 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 Affero General Public License as
* published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see https://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(),
Region = s3conf.GetPropString("region"),
};
}
}
}