// -------------------------------------------------------------------------------------------------------------------- // // Copyright (c) James South. // Licensed under the Apache License, Version 2.0. // // // Encapsulates methods to allow the retrieval of ImageProcessor settings. // // // -------------------------------------------------------------------------------------------------------------------- namespace ImageProcessor.Web.Configuration { using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Web.Compilation; using ImageProcessor.Common.Extensions; using ImageProcessor.Processors; using ImageProcessor.Web.Processors; using ImageProcessor.Web.Services; /// /// Encapsulates methods to allow the retrieval of ImageProcessor settings. /// /// public sealed class ImageProcessorConfiguration { #region Fields /// /// A new instance Initializes a new instance of the class. /// with lazy initialization. /// private static readonly Lazy Lazy = new Lazy(() => new ImageProcessorConfiguration()); /// /// A collection of the processing presets defined in the configuration. /// for available plugins. /// private static readonly ConcurrentDictionary PresetSettings = new ConcurrentDictionary(); /// /// The processing configuration section from the current application configuration. /// private static ImageProcessingSection imageProcessingSection; /// /// The cache configuration section from the current application configuration. /// private static ImageCacheSection imageCacheSection; /// /// The security configuration section from the current application configuration. /// private static ImageSecuritySection imageSecuritySection; #endregion #region Constructors /// /// Prevents a default instance of the class from being created. /// private ImageProcessorConfiguration() { this.LoadGraphicsProcessors(); this.LoadImageServices(); } #endregion #region Properties /// /// Gets the current instance of the class. /// public static ImageProcessorConfiguration Instance { get { return Lazy.Value; } } /// /// Gets the list of available GraphicsProcessors. /// public IList GraphicsProcessors { get; private set; } /// /// Gets the list of available ImageServices. /// public IList ImageServices { get; private set; } /// /// Gets a value indicating whether to preserve exif meta data. /// public bool PreserveExifMetaData { get { return GetImageProcessingSection().PreserveExifMetaData; } } #region Caching /// /// Gets the maximum number of days to store images in the cache. /// public int MaxCacheDays { get { return GetImageCacheSection().MaxDays; } } /// /// Gets or the virtual path of the cache folder. /// /// The virtual path of the cache folder. public string VirtualCachePath { get { return GetImageCacheSection().VirtualPath; } } #endregion #endregion #region Methods /// /// Returns the processing instructions matching the preset defined in the configuration. /// /// /// The name of the plugin to get the settings for. /// /// /// The the processing instructions. /// public string GetPresetSettings(string name) { return PresetSettings.GetOrAdd( name, n => { ImageProcessingSection.PresetElement presetElement = GetImageProcessingSection() .Presets .Cast() .FirstOrDefault(x => x.Name == n); return presetElement != null ? presetElement.Value : null; }); } /// /// Retrieves the processing configuration section from the current application configuration. /// /// The processing configuration section from the current application configuration. private static ImageProcessingSection GetImageProcessingSection() { return imageProcessingSection ?? (imageProcessingSection = ImageProcessingSection.GetConfiguration()); } /// /// Retrieves the caching configuration section from the current application configuration. /// /// The caching configuration section from the current application configuration. private static ImageCacheSection GetImageCacheSection() { return imageCacheSection ?? (imageCacheSection = ImageCacheSection.GetConfiguration()); } /// /// Retrieves the security configuration section from the current application configuration. /// /// The security configuration section from the current application configuration. private static ImageSecuritySection GetImageSecuritySection() { return imageSecuritySection ?? (imageSecuritySection = ImageSecuritySection.GetConfiguration()); } #region GraphicesProcessors /// /// Gets the list of available GraphicsProcessors. /// private void LoadGraphicsProcessors() { if (this.GraphicsProcessors == null) { if (GetImageProcessingSection().Plugins.AutoLoadPlugins) { Type type = typeof(IWebGraphicsProcessor); try { // Build a list of native IGraphicsProcessor instances. List availableTypes = BuildManager.GetReferencedAssemblies() .Cast() .SelectMany(s => s.GetLoadableTypes()) .Where(t => type.IsAssignableFrom(t) && t.IsClass && !t.IsAbstract) .ToList(); // Create them and add. this.GraphicsProcessors = availableTypes.Select(x => (Activator.CreateInstance(x) as IWebGraphicsProcessor)).ToList(); // Add the available settings. foreach (IWebGraphicsProcessor webProcessor in this.GraphicsProcessors) { webProcessor.Processor.Settings = this.GetPluginSettings(webProcessor.GetType().Name); } } catch (ReflectionTypeLoadException) { this.LoadGraphicsProcessorsFromConfiguration(); } } else { this.LoadGraphicsProcessorsFromConfiguration(); } } } /// /// Loads graphics processors from configuration. /// /// /// Thrown when an cannot be loaded. /// private void LoadGraphicsProcessorsFromConfiguration() { ImageProcessingSection.PluginElementCollection pluginConfigs = imageProcessingSection.Plugins; this.GraphicsProcessors = new List(); foreach (ImageProcessingSection.PluginElement pluginConfig in pluginConfigs) { Type type = Type.GetType(pluginConfig.Type); if (type == null) { throw new TypeLoadException("Couldn't load IWebGraphicsProcessor: " + pluginConfig.Type); } this.GraphicsProcessors.Add(Activator.CreateInstance(type) as IWebGraphicsProcessor); } // Add the available settings. foreach (IWebGraphicsProcessor webProcessor in this.GraphicsProcessors) { webProcessor.Processor.Settings = this.GetPluginSettings(webProcessor.GetType().Name); } } /// /// Returns the for the given plugin. /// /// /// The name of the plugin to get the settings for. /// /// /// The for the given plugin. /// private Dictionary GetPluginSettings(string name) { ImageProcessingSection.PluginElement pluginElement = GetImageProcessingSection() .Plugins .Cast() .FirstOrDefault(x => x.Name == name); Dictionary settings; if (pluginElement != null) { settings = pluginElement.Settings .Cast() .ToDictionary(setting => setting.Key, setting => setting.Value); } else { settings = new Dictionary(); } return settings; } #endregion #region ImageServices /// /// Gets the list of available ImageServices. /// private void LoadImageServices() { if (this.ImageServices == null) { if (GetImageSecuritySection().ImageServices.AutoLoadServices) { Type type = typeof(IImageService); try { // Build a list of native IGraphicsProcessor instances. List availableTypes = BuildManager.GetReferencedAssemblies() .Cast() .SelectMany(s => s.GetLoadableTypes()) .Where(t => type.IsAssignableFrom(t) && t.IsClass && !t.IsAbstract) .ToList(); // Create them and add. this.ImageServices = availableTypes.Select(x => (Activator.CreateInstance(x) as IImageService)).ToList(); // Add the available settings. foreach (IImageService service in this.ImageServices) { string name = service.GetType().Name; service.Settings = this.GetServiceSettings(name); service.WhiteList = this.GetServiceWhitelist(name); } } catch (ReflectionTypeLoadException) { this.LoadImageServicesFromConfiguration(); } } else { this.LoadImageServicesFromConfiguration(); } } } /// /// Loads image services from configuration. /// /// /// Thrown when an cannot be loaded. /// private void LoadImageServicesFromConfiguration() { ImageSecuritySection.ServiceElementCollection services = imageSecuritySection.ImageServices; this.ImageServices = new List(); foreach (ImageSecuritySection.ServiceElement config in services) { Type type = Type.GetType(config.Type); if (type == null) { throw new TypeLoadException("Couldn't load IImageService: " + config.Type); } IImageService imageService = Activator.CreateInstance(type) as IImageService; if (!string.IsNullOrWhiteSpace(config.Prefix)) { if (!string.IsNullOrWhiteSpace(config.Prefix)) { if (imageService != null) { imageService.Prefix = config.Prefix; } } } this.ImageServices.Add(imageService); } // Add the available settings. foreach (IImageService service in this.ImageServices) { string name = service.GetType().Name; service.Settings = this.GetServiceSettings(name); service.WhiteList = this.GetServiceWhitelist(name); } } /// /// Returns the for the given plugin. /// /// /// The name of the plugin to get the settings for. /// /// /// The for the given plugin. /// private Dictionary GetServiceSettings(string name) { ImageSecuritySection.ServiceElement serviceElement = GetImageSecuritySection() .ImageServices .Cast() .FirstOrDefault(x => x.Name == name); Dictionary settings; if (serviceElement != null) { settings = serviceElement.Settings .Cast() .ToDictionary(setting => setting.Key, setting => setting.Value); } else { settings = new Dictionary(); } return settings; } /// /// Gets the whitelist of for the given service. /// /// /// The name of the service to return the whitelist for. /// /// /// The array containing the whitelist. /// private Uri[] GetServiceWhitelist(string name) { ImageSecuritySection.ServiceElement serviceElement = GetImageSecuritySection() .ImageServices .Cast() .FirstOrDefault(x => x.Name == name); Uri[] whitelist = { }; if (serviceElement != null) { whitelist = serviceElement.WhiteList.Cast() .Select(s => s.Url).ToArray(); } return whitelist; } #endregion #endregion } }