private static object[] BuildMethodParameters(PluginManifest Manifest, Type Handler, MethodInfo methodInfo, string ActionName, Controller HostController) { var methodParams = methodInfo.GetParameters(); var result = new object[methodParams.Length]; for (int i = 0; i < methodParams.Length; i++) { var methodParam = methodParams[i]; Type parameterType = methodParam.ParameterType; IModelBinder modelBinder = ModelBinders.Binders.GetBinder(parameterType); IValueProvider valueProvider = HostController.ValueProvider; string parameterName = methodParam.Name; ModelBindingContext bindingContext = new ModelBindingContext() { FallbackToEmptyPrefix = true, ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(null, parameterType), ModelName = parameterName, ModelState = HostController.ViewData.ModelState, PropertyFilter = (p) => true, ValueProvider = valueProvider }; var parameterValue = modelBinder.BindModel(HostController.ControllerContext, bindingContext); if (parameterValue == null && methodParam.HasDefaultValue) parameterValue = methodParam.DefaultValue; result[i] = parameterValue; } return result; }
public static bool TryGetPlugin(string PluginId, Type ContainsCategoryType, out PluginManifest PluginManifest) { PluginManifest = null; if (_PluginManifests == null) return false; PluginManifest manifest; if (_PluginManifests.TryGetValue(PluginId, out manifest)) { if (ContainsCategoryType == null) { PluginManifest = manifest; return true; } else { foreach (var featureManifest in manifest.Features) { if (ContainsCategoryType.IsAssignableFrom(featureManifest.CategoryType)) { PluginManifest = manifest; return true; } } } } return false; }
public static List<SelectListItem> ToSelectListItems(this IEnumerable<PluginManifest> PluginFeatureDefinitions, PluginManifest SelectedItem) { string selectedId = default(string); if (SelectedItem != null) selectedId = SelectedItem.Id; return PluginFeatureDefinitions.ToSelectListItems(selectedId); }
private static WebHandlerCachedItem FindControllerMethod(PluginManifest Manifest, Type Handler, string ActionName) { var descriptors = CacheWebHandler(Manifest, Handler); WebHandlerCachedItem method; if (descriptors.TryGetValue(ActionName.ToLower(), out method)) return method; // Not Found else return null; // Not Found }
internal static void AddPlugin(PluginManifest Manifest) { lock (_PluginLock) { if (_PluginManifests.ContainsKey(Manifest.Id)) throw new InvalidOperationException(string.Format("The '{0} [{1}]' Plugin is already installed, please uninstall any existing versions before trying again", Manifest.Name, Manifest.Id)); // Add Plugin Manifest to Environment _PluginManifests[Manifest.Id] = Manifest; // Reinitialize Plugin Host Environment Plugins.ReinitializePluginHostEnvironment(); } }
public static ScheduledTaskStatus UninstallPlugin(PluginManifest Manifest, bool UninstallData) { if (ScheduledTasks.GetTaskStatuses(typeof(InstallPluginTask)).Where(s => s.IsRunning).Count() > 0) throw new InvalidOperationException("A plugin is already being Uninstalled"); if (ScheduledTasks.GetTaskStatuses(typeof(UpdatePluginTask)).Where(s => s.IsRunning).Count() > 0) throw new InvalidOperationException("A plugin is being Updated"); if (ScheduledTasks.GetTaskStatuses(typeof(InstallPluginTask)).Where(s => s.IsRunning).Count() > 0) throw new InvalidOperationException("A plugin is being Installed"); var taskData = new JobDataMap() { { "PluginManifest", Manifest }, { "UninstallData", UninstallData } }; var instance = new UninstallPluginTask(); return instance.ScheduleTask(taskData); }
public static void LogPluginMessage(PluginManifest Manifest, string Message, params object[] ExportData) { LogPluginWarningOrMessage(EventTypeIds.PluginMessage, Manifest, Message, ExportData); }
public static void LogUninstalled(PluginManifest Manifest, bool UninstalledData) { Current.Log((int)EventTypeIds.Uninstalled, Manifest.Id, Manifest.Name, Manifest.PluginLocation, Manifest.Version.ToString(4), UninstalledData); }
public static void LogAfterUpdate(PluginManifest ExistingManifest, PluginManifest UpdateManifest) { Current.Log((int)EventTypeIds.AfterUpdate, UpdateManifest.Id, UpdateManifest.Name, UpdateManifest.PluginLocation, ExistingManifest.Version.ToString(4), UpdateManifest.Version.ToString(4)); }
private static Dictionary<string, WebHandlerCachedItem> CacheWebHandler(PluginManifest Manifest, Type Handler) { Dictionary<string, WebHandlerCachedItem> result; if (!WebHandlerCachedItems.TryGetValue(Handler, out result)) { // Cache Miss result = new Dictionary<string, WebHandlerCachedItem>(); var methods = Array.FindAll<MethodInfo>(Handler.GetMethods(BindingFlags.InvokeMethod | BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly), mi => { return !mi.IsSpecialName && typeof(ActionResult).IsAssignableFrom(mi.ReturnType); }); foreach (var method in methods) { var authorizers = method.GetCustomAttributes<DiscoAuthorizeBaseAttribute>().ToArray(); foreach (var authorizer in authorizers) authorizer.AuthorizeResource = string.Format("[Plugin]::{0}::{1}", Manifest.Id, method.Name); var item = new WebHandlerCachedItem() { Method = method.Name, MethodInfo = method, Authorizers = authorizers }; result.Add(item.Method.ToLower(), item); } WebHandlerCachedItems[Handler] = result; } return result; }
internal bool AfterPluginUpdate(DiscoDataContext Database, PluginManifest PreviousManifest) { // Initialize Plugin InitializePluginEnvironment(Database); using (var pluginInstance = this.CreateInstance()) { pluginInstance.AfterUpdate(Database, PreviousManifest); } return true; }
/// <summary> /// Uses reflection to build a Plugin Manifest /// </summary> /// <param name="pluginAssembly">Assembly containing a plugin</param> /// <returns>A plugin manifest for the first encountered plugin within the assembly</returns> public static PluginManifest FromPluginAssembly(Assembly assembly) { // Determine Plugin Properties var pluginType = (from type in assembly.GetTypes() where typeof(Plugin).IsAssignableFrom(type) && !type.IsAbstract select type).FirstOrDefault(); if (pluginType == null) throw new ArgumentException("No Plugin was found in this Assembly", "pluginAssembly"); var assemblyName = assembly.GetName(); var pluginAttributes = pluginType.GetCustomAttribute<PluginAttribute>(false); if (pluginAttributes == null) throw new ArgumentException(string.Format("Plugin found [{0}], but no PluginAttribute found", pluginType.Name), "pluginAssembly"); var pluginId = pluginAttributes.Id; var pluginName = pluginAttributes.Name; var pluginAuthor = pluginAttributes.Author; var pluginUrl = pluginAttributes.Url; var pluginHostVersionMin = pluginAttributes.HostVersionMin == null ? null : Version.Parse(pluginAttributes.HostVersionMin); var pluginHostVersionMax = pluginAttributes.HostVersionMax == null ? null : Version.Parse(pluginAttributes.HostVersionMax); var pluginVersion = assemblyName.Version; var pluginAssemblyPath = Path.GetFileName(assembly.Location); var pluginTypeName = pluginType.FullName; var pluginLocation = Path.GetDirectoryName(assembly.Location); // Find Configuration Handler var pluginConfigurationHandlerType = (from type in assembly.GetTypes() where typeof(PluginConfigurationHandler).IsAssignableFrom(type) && !type.IsAbstract select type).FirstOrDefault(); if (pluginConfigurationHandlerType == null) throw new ArgumentException("A Plugin was found, but no Configuration Handler was found in this Assembly - this is required", "pluginAssembly"); // Find Web Handler var pluginWebHandlerType = (from type in assembly.GetTypes() where typeof(PluginWebHandler).IsAssignableFrom(type) && !type.IsAbstract select type).FirstOrDefault(); Dictionary<string, string> pluginAssemblyReferences = new Dictionary<string, string>(); foreach (string referenceFilename in Directory.EnumerateFiles(pluginLocation, "*.dll", SearchOption.TopDirectoryOnly)) { if (!referenceFilename.Equals(assembly.Location, StringComparison.OrdinalIgnoreCase)) { // Ignore Excluded Assemblies if (!PluginExcludedAssemblies.Contains(Path.GetFileNameWithoutExtension(referenceFilename))) { try { Assembly pluginRefAssembly = Assembly.ReflectionOnlyLoadFrom(referenceFilename); pluginAssemblyReferences[pluginRefAssembly.FullName] = referenceFilename.Substring(pluginLocation.Length + 1); } catch (Exception) { } // Ignore Load Exceptions } } } PluginManifest pluginManifest = new PluginManifest() { Id = pluginId, Name = pluginName, Author = pluginAuthor, Version = pluginVersion, Url = pluginUrl, HostVersionMin = pluginHostVersionMin, HostVersionMax = pluginHostVersionMax, AssemblyPath = pluginAssemblyPath, TypeName = pluginTypeName, AssemblyReferences = pluginAssemblyReferences, PluginAssembly = assembly, Type = pluginType, PluginLocation = pluginLocation, ConfigurationHandlerType = pluginConfigurationHandlerType, ConfigurationHandlerTypeName = pluginConfigurationHandlerType.FullName, WebHandlerType = pluginWebHandlerType, WebHandlerTypeName = (pluginWebHandlerType == null ? null : pluginWebHandlerType.FullName) }; pluginManifest.Features = (from type in assembly.GetTypes() where typeof(PluginFeature).IsAssignableFrom(type) && !type.IsAbstract select PluginFeatureManifest.FromPluginFeatureType(type, pluginManifest)).ToList(); return pluginManifest; }
public static void LogInitializedPluginFeature(PluginManifest PluginMenifest, PluginFeatureManifest FeatureManifest) { Current.Log((int)EventTypeIds.InitializedPluginFeature, PluginMenifest.Id, FeatureManifest.Type.Name); }
private static void LogPluginWarningOrMessage(EventTypeIds WarningOrMessage, PluginManifest Manifest, string Message, object[] ExportData) { if (WarningOrMessage != EventTypeIds.PluginMessage && WarningOrMessage != EventTypeIds.PluginWarning) throw new ArgumentException("Only PluginMessage/PluginWarning is allowed", "WarningOrMessage"); object[] LogData; if (ExportData == null || ExportData.Length == 0) { LogData = new object[3]; } else { LogData = new object[4 + ExportData.Length]; for (int i = 0; i < ExportData.Length; i++) LogData[4 + i] = ExportData[i]; } LogData[0] = Manifest.Name; LogData[1] = Manifest.Id; LogData[2] = Manifest.VersionFormatted; LogData[3] = Message; Log(WarningOrMessage, LogData); }
private static Assembly CurrentDomain_AssemblyResolve_ByPlugin(PluginManifest pluginManifest, ResolveEventArgs args) { if (pluginManifest.AssemblyReferences != null) { string assemblyPath; if (pluginManifest.AssemblyReferences.TryGetValue(args.Name, out assemblyPath)) { var resolvedAssemblyPath = Path.Combine(pluginManifest.PluginLocation, assemblyPath); try { Assembly loadedAssembly = Assembly.LoadFile(resolvedAssemblyPath); PluginsLog.LogPluginReferenceAssemblyLoaded(args.Name, resolvedAssemblyPath, args.RequestingAssembly.FullName); return loadedAssembly; } catch (Exception ex) { PluginsLog.LogPluginException(string.Format("Resolving Plugin Reference Assembly: '{0}' [{1}]; Requested by: '{2}' [{3}]; Disco.Plugins.DiscoPlugins.CurrentDomain_AssemblyResolve()", args.Name, resolvedAssemblyPath, args.RequestingAssembly.FullName, args.RequestingAssembly.Location), ex); } } } return null; }
public static PluginManifest UpdatePlugin(DiscoDataContext Database, PluginManifest ExistingManifest, Stream UpdatePluginPackage, PluginLibraryIncompatibility PluginLibraryIncompatibility = null) { using (MemoryStream packageStream = new MemoryStream()) { if (UpdatePluginPackage.Position != 0) UpdatePluginPackage.Position = 0; UpdatePluginPackage.CopyTo(packageStream); packageStream.Position = 0; using (ZipArchive packageArchive = new ZipArchive(packageStream, ZipArchiveMode.Read, false)) { ZipArchiveEntry packageManifestEntry = packageArchive.GetEntry("manifest.json"); if (packageManifestEntry == null) throw new InvalidDataException("The plugin package does not contain the 'manifest.json' entry"); PluginManifest packageManifest; using (Stream packageManifestStream = packageManifestEntry.Open()) { packageManifest = PluginManifest.FromPluginManifestFile(packageManifestStream); } if (ExistingManifest.Version > packageManifest.Version) { throw new InvalidDataException("A newer version of this plugin is already installed"); } // Check Compatibility if (PluginLibraryIncompatibility == null) PluginLibraryIncompatibility = PluginLibrary.LoadManifest(Database).LoadIncompatibilityData(); var pluginIncompatibility = PluginLibraryIncompatibility.IncompatiblePlugins.FirstOrDefault(i => i.PluginId.Equals(packageManifest.Id, StringComparison.OrdinalIgnoreCase) && packageManifest.Version == i.Version); if (pluginIncompatibility != null) throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", packageManifest.Id, packageManifest.VersionFormatted, pluginIncompatibility.Reason)); string packagePath = Path.Combine(Database.DiscoConfiguration.PluginsLocation, packageManifest.Id); // Force Delete of Existing Folder if (Directory.Exists(packagePath)) Directory.Delete(packagePath, true); Directory.CreateDirectory(packagePath); // Extract Package Contents foreach (var packageEntry in packageArchive.Entries) { // Determine Extraction Path var packageEntryTarget = Path.Combine(packagePath, packageEntry.FullName); // Create Sub Directories Directory.CreateDirectory(Path.GetDirectoryName(packageEntryTarget)); using (var packageEntryStream = packageEntry.Open()) { using (var packageTargetStream = File.Open(packageEntryTarget, FileMode.Create, FileAccess.Write, FileShare.None)) { packageEntryStream.CopyTo(packageTargetStream); } } } // Reload Manifest packageManifest = PluginManifest.FromPluginManifestFile(Path.Combine(packagePath, "manifest.json")); // Trigger AfterPluginUpdate packageManifest.AfterPluginUpdate(Database, ExistingManifest); PluginsLog.LogAfterUpdate(ExistingManifest, packageManifest); // Return Updated Manifest return packageManifest; } } }
public static PluginManifest UpdatePlugin(DiscoDataContext Database, PluginManifest ExistingManifest, String UpdatePluginPackageFilePath, PluginLibraryIncompatibility PluginLibraryIncompatibility = null) { PluginManifest updatedManifest; using (var packageStream = File.OpenRead(UpdatePluginPackageFilePath)) { updatedManifest = UpdatePlugin(Database, ExistingManifest, packageStream, PluginLibraryIncompatibility); } // Remove Update after processing File.Delete(UpdatePluginPackageFilePath); return updatedManifest; }
public static bool TryGetPlugin(Assembly PluginAssembly, out PluginManifest PluginManifest) { PluginManifest = null; if (_PluginAssemblyManifests == null) return false; PluginManifest manifest; if (_PluginAssemblyManifests.TryGetValue(PluginAssembly, out manifest)) { PluginManifest = manifest; return true; } else { return false; } }
public static bool TryGetPlugin(string PluginId, out PluginManifest PluginManifest) { return TryGetPlugin(PluginId, null, out PluginManifest); }
public static void LogInitializedPlugin(PluginManifest Menifest) { Current.Log((int)EventTypeIds.InitializedPlugin, Menifest.Id, Menifest.Version.ToString(3), Menifest.Type.Name, Menifest.Type.Assembly.Location); }
public virtual void AfterUpdate(DiscoDataContext Database, PluginManifest PreviousManifest) { return; }
public static void LogInstalling(PluginManifest Manifest) { Current.Log((int)EventTypeIds.Installing, Manifest.Id, Manifest.Version.ToString(4), Manifest.Name); }
public WebHelper(HttpContextBase Context, PluginManifest Manifest) { this.Context = Context; this.Manifest = Manifest; }