// Copyright Epic Games, Inc. All Rights Reserved. using System; using System.Collections.Concurrent; using EpicGames.Core; using HordeServer.Plugins; namespace HordeServer.Utilities { /// /// Cache for Json schemas /// public class JsonSchemaCache { readonly JsonSchemaFactory _factory; readonly ConcurrentDictionary _cachedSchemas = new ConcurrentDictionary(); /// /// Constructor /// public JsonSchemaCache(IPluginCollection pluginCollection) { _factory = new JsonSchemaFactory(new XmlDocReader()); // Create a dummy class for the global plugin configuration, which has named properties for each plugin JsonSchemaObject globalPluginsObj = new JsonSchemaObject(); globalPluginsObj.Name = "GlobalPluginsConfig"; foreach (ILoadedPlugin plugin in pluginCollection.LoadedPlugins) { if (plugin.GlobalConfigType != null) { JsonSchemaType pluginSchemaType = _factory.CreateSchemaType(plugin.GlobalConfigType); globalPluginsObj.Properties.Add(new JsonSchemaProperty(plugin.Name.ToString(), $"Configuration for the {plugin.Name} plugin", pluginSchemaType)); } } _factory.TypeCache.Add(typeof(PluginConfigCollection), globalPluginsObj); // Same thing for the server config. This is handled by adding a custom property, since config binding for app settings is different to the global config parser. JsonSchemaObject serverPluginsObj = new JsonSchemaObject(); serverPluginsObj.Name = "ServerPluginsConfig"; foreach (ILoadedPlugin plugin in pluginCollection.LoadedPlugins) { if (plugin.ServerConfigType != null && plugin.ServerConfigType != typeof(object)) { JsonSchemaType pluginSchemaType = _factory.CreateSchemaType(plugin.ServerConfigType); serverPluginsObj.Properties.Add(new JsonSchemaProperty(plugin.Name.ToString(), $"Configuration for the {plugin.Name} plugin", pluginSchemaType)); } } JsonSchemaObject serverObj = (JsonSchemaObject)_factory.CreateSchemaType(typeof(ServerSettings)); serverObj.Properties.Add(new JsonSchemaProperty("Plugins", "Configuration for plugins", serverPluginsObj)); } /// /// Create a Json schema (or retrieve a cached schema) /// public JsonSchema CreateSchema(Type type) { JsonSchema? schema; if (!_cachedSchemas.TryGetValue(type, out schema)) { lock (_factory) { schema = _cachedSchemas.GetOrAdd(type, x => _factory.CreateSchema(x)); } } return schema; } } }