コード例 #1
0
        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;
        }
コード例 #2
0
ファイル: Plugins.cs プロジェクト: garysharp/Disco
        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;
        }
コード例 #3
0
ファイル: PluginExtensions.cs プロジェクト: garysharp/Disco
        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);
        }
コード例 #4
0
 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
 }
コード例 #5
0
ファイル: Plugins.cs プロジェクト: garysharp/Disco
        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();
            }
        }
コード例 #6
0
        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);
        }
コード例 #7
0
ファイル: PluginsLog.cs プロジェクト: garysharp/Disco
 public static void LogPluginMessage(PluginManifest Manifest, string Message, params object[] ExportData)
 {
     LogPluginWarningOrMessage(EventTypeIds.PluginMessage, Manifest, Message, ExportData);
 }
コード例 #8
0
ファイル: PluginsLog.cs プロジェクト: garysharp/Disco
 public static void LogUninstalled(PluginManifest Manifest, bool UninstalledData)
 {
     Current.Log((int)EventTypeIds.Uninstalled, Manifest.Id, Manifest.Name, Manifest.PluginLocation, Manifest.Version.ToString(4), UninstalledData);
 }
コード例 #9
0
ファイル: PluginsLog.cs プロジェクト: garysharp/Disco
 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));
 }
コード例 #10
0
        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;
        }
コード例 #11
0
ファイル: PluginManifest.cs プロジェクト: garysharp/Disco
        internal bool AfterPluginUpdate(DiscoDataContext Database, PluginManifest PreviousManifest)
        {
            // Initialize Plugin
            InitializePluginEnvironment(Database);

            using (var pluginInstance = this.CreateInstance())
            {
                pluginInstance.AfterUpdate(Database, PreviousManifest);
            }

            return true;
        }
コード例 #12
0
ファイル: PluginManifest.cs プロジェクト: garysharp/Disco
        /// <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;
        }
コード例 #13
0
ファイル: PluginsLog.cs プロジェクト: garysharp/Disco
 public static void LogInitializedPluginFeature(PluginManifest PluginMenifest, PluginFeatureManifest FeatureManifest)
 {
     Current.Log((int)EventTypeIds.InitializedPluginFeature, PluginMenifest.Id, FeatureManifest.Type.Name);
 }
コード例 #14
0
ファイル: PluginsLog.cs プロジェクト: garysharp/Disco
        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);
        }
コード例 #15
0
ファイル: Plugins.cs プロジェクト: garysharp/Disco
        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;
        }
コード例 #16
0
ファイル: Plugins.cs プロジェクト: garysharp/Disco
        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;
                }
            }
        }
コード例 #17
0
ファイル: Plugins.cs プロジェクト: garysharp/Disco
        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;
        }
コード例 #18
0
ファイル: Plugins.cs プロジェクト: garysharp/Disco
        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;
            }
        }
コード例 #19
0
ファイル: Plugins.cs プロジェクト: garysharp/Disco
 public static bool TryGetPlugin(string PluginId, out PluginManifest PluginManifest)
 {
     return TryGetPlugin(PluginId, null, out PluginManifest);
 }
コード例 #20
0
ファイル: PluginsLog.cs プロジェクト: garysharp/Disco
 public static void LogInitializedPlugin(PluginManifest Menifest)
 {
     Current.Log((int)EventTypeIds.InitializedPlugin, Menifest.Id, Menifest.Version.ToString(3), Menifest.Type.Name, Menifest.Type.Assembly.Location);
 }
コード例 #21
0
ファイル: Plugin.cs プロジェクト: garysharp/Disco
 public virtual void AfterUpdate(DiscoDataContext Database, PluginManifest PreviousManifest) { return; }
コード例 #22
0
ファイル: PluginsLog.cs プロジェクト: garysharp/Disco
 public static void LogInstalling(PluginManifest Manifest)
 {
     Current.Log((int)EventTypeIds.Installing, Manifest.Id, Manifest.Version.ToString(4), Manifest.Name);
 }
コード例 #23
0
ファイル: WebHelper.cs プロジェクト: garysharp/Disco
 public WebHelper(HttpContextBase Context, PluginManifest Manifest)
 {
     this.Context = Context;
     this.Manifest = Manifest;
 }