From 50f6044a2f5d06b6987f5f367fc153b16fa88d01 Mon Sep 17 00:00:00 2001 From: qianlifeng Date: Fri, 26 Dec 2014 19:36:43 +0800 Subject: [PATCH] Refactoring [WIP] --- Wox.Core/Plugin/CSharpPluginLoader.cs | 61 ++++++++ Wox.Core/Plugin/IPluginLoader.cs | 10 ++ .../Plugin}/JsonPRCModel.cs | 2 +- .../Plugin/JsonRPCPlugin.cs | 23 ++- Wox.Core/Plugin/JsonRPCPluginLoader.cs | 21 +++ Wox.Core/Plugin/PluginConfig.cs | 141 ++++++++++++++++++ Wox.Core/Plugin/PluginManager.cs | 99 ++++++++++++ .../Plugin}/PythonPlugin.cs | 15 +- Wox.Core/Properties/AssemblyInfo.cs | 36 +++++ Wox.Core/README.txt | 4 + Wox.Core/Wox.Core.csproj | 86 +++++++++++ Wox.Core/packages.config | 4 + Wox.sln | 8 +- Wox/ActionKeyword.xaml.cs | 6 +- Wox/CommandArgs/PluginDebuggerCommandArg.cs | 3 +- Wox/CommandArgs/ReloadPluginCommandArg.cs | 4 +- Wox/Commands/CommandFactory.cs | 4 +- Wox/Commands/PluginCommand.cs | 4 +- Wox/Commands/SystemCommand.cs | 4 +- Wox/Helper/PluginInstaller.cs | 4 +- Wox/MainWindow.xaml.cs | 11 +- Wox/PluginLoader/BasePluginLoader.cs | 23 --- Wox/PluginLoader/CSharpPluginLoader.cs | 55 ------- Wox/PluginLoader/IPluginLoader.cs | 13 -- Wox/PluginLoader/PluginConfigLoader.cs | 121 --------------- Wox/PluginLoader/Plugins.cs | 58 ------- Wox/SettingWindow.xaml.cs | 8 +- Wox/Wox.csproj | 12 +- 28 files changed, 515 insertions(+), 325 deletions(-) create mode 100644 Wox.Core/Plugin/CSharpPluginLoader.cs create mode 100644 Wox.Core/Plugin/IPluginLoader.cs rename {Wox/JsonRPC => Wox.Core/Plugin}/JsonPRCModel.cs (99%) rename Wox/PluginLoader/BasePlugin.cs => Wox.Core/Plugin/JsonRPCPlugin.cs (93%) create mode 100644 Wox.Core/Plugin/JsonRPCPluginLoader.cs create mode 100644 Wox.Core/Plugin/PluginConfig.cs create mode 100644 Wox.Core/Plugin/PluginManager.cs rename {Wox/PluginLoader => Wox.Core/Plugin}/PythonPlugin.cs (87%) create mode 100644 Wox.Core/Properties/AssemblyInfo.cs create mode 100644 Wox.Core/README.txt create mode 100644 Wox.Core/Wox.Core.csproj create mode 100644 Wox.Core/packages.config delete mode 100644 Wox/PluginLoader/BasePluginLoader.cs delete mode 100644 Wox/PluginLoader/CSharpPluginLoader.cs delete mode 100644 Wox/PluginLoader/IPluginLoader.cs delete mode 100644 Wox/PluginLoader/PluginConfigLoader.cs delete mode 100644 Wox/PluginLoader/Plugins.cs diff --git a/Wox.Core/Plugin/CSharpPluginLoader.cs b/Wox.Core/Plugin/CSharpPluginLoader.cs new file mode 100644 index 0000000000..9cfdc56734 --- /dev/null +++ b/Wox.Core/Plugin/CSharpPluginLoader.cs @@ -0,0 +1,61 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using Wox.Infrastructure.Logger; +using Wox.Plugin; +using Wox.Plugin.SystemPlugins; + +namespace Wox.Core.Plugin +{ + internal class CSharpPluginLoader : IPluginLoader + { + public IEnumerable LoadPlugin(List pluginMetadatas) + { + var plugins = new List(); + List CSharpPluginMetadatas = pluginMetadatas.Where(o => o.Language.ToUpper() == AllowedLanguage.CSharp.ToUpper()).ToList(); + + foreach (PluginMetadata metadata in CSharpPluginMetadatas) + { + try + { + Assembly asm = Assembly.Load(AssemblyName.GetAssemblyName(metadata.ExecuteFilePath)); + List types = asm.GetTypes().Where(o => o.IsClass && !o.IsAbstract && (o.BaseType == typeof(BaseSystemPlugin) || o.GetInterfaces().Contains(typeof(IPlugin)))).ToList(); + if (types.Count == 0) + { + Log.Warn(string.Format("Couldn't load plugin {0}: didn't find the class that implement IPlugin", metadata.Name)); + continue; + } + + foreach (Type type in types) + { + PluginPair pair = new PluginPair() + { + Plugin = Activator.CreateInstance(type) as IPlugin, + Metadata = metadata + }; + + var sys = pair.Plugin as BaseSystemPlugin; + if (sys != null) + { + sys.PluginDirectory = metadata.PluginDirectory; + } + + plugins.Add(pair); + } + } + catch (Exception e) + { + Log.Error(string.Format("Couldn't load plugin {0}: {1}", metadata.Name, e.Message)); +#if (DEBUG) + { + throw; + } +#endif + } + } + + return plugins; + } + } +} \ No newline at end of file diff --git a/Wox.Core/Plugin/IPluginLoader.cs b/Wox.Core/Plugin/IPluginLoader.cs new file mode 100644 index 0000000000..a85e7e361e --- /dev/null +++ b/Wox.Core/Plugin/IPluginLoader.cs @@ -0,0 +1,10 @@ +using System.Collections.Generic; +using Wox.Plugin; + +namespace Wox.Core.Plugin +{ + internal interface IPluginLoader + { + IEnumerable LoadPlugin(List pluginMetadatas); + } +} diff --git a/Wox/JsonRPC/JsonPRCModel.cs b/Wox.Core/Plugin/JsonPRCModel.cs similarity index 99% rename from Wox/JsonRPC/JsonPRCModel.cs rename to Wox.Core/Plugin/JsonPRCModel.cs index 84ecc35180..480d1e386d 100644 --- a/Wox/JsonRPC/JsonPRCModel.cs +++ b/Wox.Core/Plugin/JsonPRCModel.cs @@ -17,7 +17,7 @@ using System.Collections.Generic; using System.Linq; using Wox.Plugin; -namespace Wox.JsonRPC +namespace Wox.Core.Plugin { public class JsonRPCErrorModel { diff --git a/Wox/PluginLoader/BasePlugin.cs b/Wox.Core/Plugin/JsonRPCPlugin.cs similarity index 93% rename from Wox/PluginLoader/BasePlugin.cs rename to Wox.Core/Plugin/JsonRPCPlugin.cs index da6f653de4..1b878dfce3 100644 --- a/Wox/PluginLoader/BasePlugin.cs +++ b/Wox.Core/Plugin/JsonRPCPlugin.cs @@ -2,30 +2,29 @@ using System.Collections.Generic; using System.Diagnostics; using System.IO; -using System.Linq; using System.Reflection; -using System.Text; using System.Threading; -using System.Windows.Forms; using Newtonsoft.Json; -using Wox.Helper; -using Wox.Helper.ErrorReporting; using Wox.Infrastructure.Exceptions; using Wox.Infrastructure.Logger; -using Wox.JsonRPC; using Wox.Plugin; -using MessageBox = System.Windows.MessageBox; -namespace Wox.PluginLoader +namespace Wox.Core.Plugin { - public abstract class BasePlugin : IPlugin + /// + /// Represent the plugin that using JsonPRC + /// + internal abstract class JsonRPCPlugin : IPlugin { protected PluginInitContext context; + /// + /// The language this JsonRPCPlugin support + /// public abstract string SupportedLanguage { get; } protected abstract string ExecuteQuery(Query query); - protected abstract string ExecuteAction(JsonRPCRequestModel rpcRequest); + protected abstract string ExecuteCallback(JsonRPCRequestModel rpcRequest); public List Query(Query query) { @@ -56,7 +55,7 @@ namespace Wox.PluginLoader { ThreadPool.QueueUserWorkItem(state => { - string actionReponse = ExecuteAction(result1.JsonRPCAction); + string actionReponse = ExecuteCallback(result1.JsonRPCAction); JsonRPCRequestModel jsonRpcRequestModel = JsonConvert.DeserializeObject(actionReponse); if (jsonRpcRequestModel != null && !string.IsNullOrEmpty(jsonRpcRequestModel.Method) @@ -161,7 +160,7 @@ namespace Wox.PluginLoader public void Init(PluginInitContext ctx) { - this.context = ctx; + context = ctx; } } } diff --git a/Wox.Core/Plugin/JsonRPCPluginLoader.cs b/Wox.Core/Plugin/JsonRPCPluginLoader.cs new file mode 100644 index 0000000000..234da6a25d --- /dev/null +++ b/Wox.Core/Plugin/JsonRPCPluginLoader.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.Linq; +using Wox.Plugin; + +namespace Wox.Core.Plugin +{ + internal class JsonRPCPluginLoader : IPluginLoader where T : JsonRPCPlugin, new() + { + public virtual IEnumerable LoadPlugin(List pluginMetadatas) + { + T jsonRPCPlugin = new T(); + List jsonRPCPluginMetadatas = pluginMetadatas.Where(o => o.Language.ToUpper() == jsonRPCPlugin.SupportedLanguage.ToUpper()).ToList(); + + return jsonRPCPluginMetadatas.Select(metadata => new PluginPair() + { + Plugin = jsonRPCPlugin, + Metadata = metadata + }).ToList(); + } + } +} diff --git a/Wox.Core/Plugin/PluginConfig.cs b/Wox.Core/Plugin/PluginConfig.cs new file mode 100644 index 0000000000..0359ef6483 --- /dev/null +++ b/Wox.Core/Plugin/PluginConfig.cs @@ -0,0 +1,141 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using Newtonsoft.Json; +using Wox.Infrastructure.Exceptions; +using Wox.Infrastructure.Logger; +using Wox.Infrastructure.Storage.UserSettings; +using Wox.Plugin; + +namespace Wox.Core.Plugin +{ + + internal abstract class PluginConfig + { + private const string pluginConfigName = "plugin.json"; + private static List pluginMetadatas = new List(); + + /// + /// Parse plugin metadata in giving directories + /// + /// + /// + public static List Parse(List pluginDirectories) + { + pluginMetadatas.Clear(); + ParseSystemPlugins(); + foreach (string pluginDirectory in pluginDirectories) + { + ParseThirdPartyPlugins(pluginDirectory); + } + + if (PluginManager.DebuggerMode != null) + { + PluginMetadata metadata = GetPluginMetadata(PluginManager.DebuggerMode); + if (metadata != null) pluginMetadatas.Add(metadata); + } + return pluginMetadatas; + } + + private static void ParseSystemPlugins() + { + pluginMetadatas.Add(new PluginMetadata() + { + Name = "System Plugins", + Author = "System", + Description = "system plugins collection", + Website = "http://www.getwox.com", + Language = AllowedLanguage.CSharp, + Version = "1.0.0", + PluginType = PluginType.System, + ActionKeyword = "*", + ExecuteFileName = "Wox.Plugin.SystemPlugins.dll", + PluginDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + }); + } + + private static void ParseThirdPartyPlugins(string pluginDirectory) + { + + string[] directories = Directory.GetDirectories(pluginDirectory); + foreach (string directory in directories) + { + if (File.Exists((Path.Combine(directory, "NeedDelete.txt")))) + { + Directory.Delete(directory, true); + continue; + } + PluginMetadata metadata = GetPluginMetadata(directory); + if (metadata != null) + { + pluginMetadatas.Add(metadata); + } + } + } + + private static PluginMetadata GetPluginMetadata(string pluginDirectory) + { + string configPath = Path.Combine(pluginDirectory, pluginConfigName); + if (!File.Exists(configPath)) + { + Log.Warn(string.Format("parse plugin {0} failed: didn't find config file.", configPath)); + return null; + } + + PluginMetadata metadata; + try + { + metadata = JsonConvert.DeserializeObject(File.ReadAllText(configPath)); + metadata.PluginType = PluginType.ThirdParty; + metadata.PluginDirectory = pluginDirectory; + } + catch (Exception) + { + string error = string.Format("Parse plugin config {0} failed: json format is not valid", configPath); + Log.Warn(error); +#if (DEBUG) + { + throw new WoxException(error); + } +#endif + return null; + } + + + if (!AllowedLanguage.IsAllowed(metadata.Language)) + { + string error = string.Format("Parse plugin config {0} failed: invalid language {1}", configPath, metadata.Language); + Log.Warn(error); +#if (DEBUG) + { + throw new WoxException(error); + } +#endif + return null; + } + + if (!File.Exists(metadata.ExecuteFilePath)) + { + string error = string.Format("Parse plugin config {0} failed: ExecuteFile {1} didn't exist", configPath, metadata.ExecuteFilePath); + Log.Warn(error); +#if (DEBUG) + { + throw new WoxException(error); + } +#endif + return null; + } + + //replace action keyword if user customized it. + var customizedPluginConfig = UserSettingStorage.Instance.CustomizedPluginConfigs.FirstOrDefault(o => o.ID == metadata.ID); + if (customizedPluginConfig != null && !string.IsNullOrEmpty(customizedPluginConfig.Actionword)) + { + metadata.ActionKeyword = customizedPluginConfig.Actionword; + } + + return metadata; + } + } +} diff --git a/Wox.Core/Plugin/PluginManager.cs b/Wox.Core/Plugin/PluginManager.cs new file mode 100644 index 0000000000..91af115ba8 --- /dev/null +++ b/Wox.Core/Plugin/PluginManager.cs @@ -0,0 +1,99 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Reflection; +using System.Threading; +using Wox.Infrastructure.Http; +using Wox.Plugin; + +namespace Wox.Core.Plugin +{ + /// + /// The entry for managing Wox plugins + /// + public static class PluginManager + { + public static String DebuggerMode { get; private set; } + private static List plugins = new List(); + + /// + /// Directories that will hold Wox plugin directory + /// + private static List pluginDirectories = new List(); + + static PluginManager() + { + pluginDirectories.Add( + Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "Plugins")); + pluginDirectories.Add( + Path.Combine(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), ".Wox"),"Plugins")); + + MakesurePluginDirectoriesExist(); + } + + private static void MakesurePluginDirectoriesExist() + { + foreach (string pluginDirectory in pluginDirectories) + { + if (!Directory.Exists(pluginDirectory)) + { + Directory.CreateDirectory(pluginDirectory); + } + } + } + + /// + /// Load and init all Wox plugins + /// + public static void Init() + { + plugins.Clear(); + + List pluginMetadatas = PluginConfig.Parse(pluginDirectories); + plugins.AddRange(new CSharpPluginLoader().LoadPlugin(pluginMetadatas)); + plugins.AddRange(new JsonRPCPluginLoader().LoadPlugin(pluginMetadatas)); + + foreach (PluginPair pluginPair in plugins) + { + PluginPair pair = pluginPair; + ThreadPool.QueueUserWorkItem(o => pair.Plugin.Init(new PluginInitContext() + { + CurrentPluginMetadata = pair.Metadata, + Proxy = HttpProxy.Instance, + API = App.Window + })); + } + } + + public static List AllPlugins + { + get + { + return plugins; + } + } + + public static bool HitThirdpartyKeyword(Query query) + { + if (string.IsNullOrEmpty(query.ActionName)) return false; + + return plugins.Any(o => o.Metadata.PluginType == PluginType.ThirdParty && o.Metadata.ActionKeyword == query.ActionName); + } + + public static void ActivatePluginDebugger(string path) + { + DebuggerMode = path; + } + + /// + /// get specified plugin, return null if not found + /// + /// + /// + public static PluginPair GetPlugin(string id) + { + return AllPlugins.FirstOrDefault(o => o.Metadata.ID == id); + } + } +} diff --git a/Wox/PluginLoader/PythonPlugin.cs b/Wox.Core/Plugin/PythonPlugin.cs similarity index 87% rename from Wox/PluginLoader/PythonPlugin.cs rename to Wox.Core/Plugin/PythonPlugin.cs index b62bd32182..7704ea7a3d 100644 --- a/Wox/PluginLoader/PythonPlugin.cs +++ b/Wox.Core/Plugin/PythonPlugin.cs @@ -1,17 +1,14 @@ -using System.Collections.Generic; -using System.Diagnostics; +using System.Diagnostics; using System.IO; -using Wox.Helper; -using Wox.Infrastructure; +using System.Reflection; using Wox.Infrastructure.Http; -using Wox.JsonRPC; using Wox.Plugin; -namespace Wox.PluginLoader +namespace Wox.Core.Plugin { - public class PythonPlugin : BasePlugin + internal class PythonPlugin : JsonRPCPlugin { - private static string woxDirectory = Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath); + private static string woxDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); private ProcessStartInfo startInfo; public override string SupportedLanguage @@ -57,7 +54,7 @@ namespace Wox.PluginLoader return Execute(startInfo); } - protected override string ExecuteAction(JsonRPCRequestModel rpcRequest) + protected override string ExecuteCallback(JsonRPCRequestModel rpcRequest) { startInfo.FileName = Path.Combine(woxDirectory, "PythonHome\\pythonw.exe"); startInfo.Arguments = string.Format("-B \"{0}\" \"{1}\"", context.CurrentPluginMetadata.ExecuteFilePath, rpcRequest); diff --git a/Wox.Core/Properties/AssemblyInfo.cs b/Wox.Core/Properties/AssemblyInfo.cs new file mode 100644 index 0000000000..dd5baa0e63 --- /dev/null +++ b/Wox.Core/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Wox.Core")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("Oracle Corporation")] +[assembly: AssemblyProduct("Wox.Core")] +[assembly: AssemblyCopyright("Copyright © Oracle Corporation 2014")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("693aa0e5-741b-4759-b740-fdbb011a3280")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/Wox.Core/README.txt b/Wox.Core/README.txt new file mode 100644 index 0000000000..3cd91680db --- /dev/null +++ b/Wox.Core/README.txt @@ -0,0 +1,4 @@ +What does Wox.Core do? + +* Handle Query +* Loading Plugins \ No newline at end of file diff --git a/Wox.Core/Wox.Core.csproj b/Wox.Core/Wox.Core.csproj new file mode 100644 index 0000000000..34f0938d78 --- /dev/null +++ b/Wox.Core/Wox.Core.csproj @@ -0,0 +1,86 @@ + + + + + Debug + AnyCPU + {B749F0DB-8E75-47DB-9E5E-265D16D0C0D2} + Library + Properties + Wox.Core + Wox.Core + v3.5 + 512 + ..\ + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + False + ..\packages\Newtonsoft.Json.6.0.7\lib\net35\Newtonsoft.Json.dll + + + + + + + + + + + + + + + + + + + + + + + + + {4fd29318-a8ab-4d8f-aa47-60bc241b8da3} + Wox.Infrastructure + + + {69ce0206-cb41-453d-88af-df86092ef9b8} + Wox.Plugin.SystemPlugins + + + {8451ecdd-2ea4-4966-bb0a-7bbc40138e80} + Wox.Plugin + + + + + + + + + \ No newline at end of file diff --git a/Wox.Core/packages.config b/Wox.Core/packages.config new file mode 100644 index 0000000000..4185726464 --- /dev/null +++ b/Wox.Core/packages.config @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/Wox.sln b/Wox.sln index 120076914c..7ef3724a6f 100644 --- a/Wox.sln +++ b/Wox.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 2013 -VisualStudioVersion = 12.0.30723.0 +VisualStudioVersion = 12.0.21005.1 MinimumVisualStudioVersion = 10.0.40219.1 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Test", "Wox.Test\Wox.Test.csproj", "{FF742965-9A80-41A5-B042-D6C7D3A21708}" EndProject @@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Infrastructure", "Wox.I EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Plugin.PluginManagement", "Plugins\Wox.Plugin.PluginManagement\Wox.Plugin.PluginManagement.csproj", "{049490F0-ECD2-4148-9B39-2135EC346EBE}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Core", "Wox.Core\Wox.Core.csproj", "{B749F0DB-8E75-47DB-9E5E-265D16D0C0D2}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -47,6 +49,10 @@ Global {049490F0-ECD2-4148-9B39-2135EC346EBE}.Debug|Any CPU.Build.0 = Debug|Any CPU {049490F0-ECD2-4148-9B39-2135EC346EBE}.Release|Any CPU.ActiveCfg = Release|Any CPU {049490F0-ECD2-4148-9B39-2135EC346EBE}.Release|Any CPU.Build.0 = Release|Any CPU + {B749F0DB-8E75-47DB-9E5E-265D16D0C0D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B749F0DB-8E75-47DB-9E5E-265D16D0C0D2}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B749F0DB-8E75-47DB-9E5E-265D16D0C0D2}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B749F0DB-8E75-47DB-9E5E-265D16D0C0D2}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Wox/ActionKeyword.xaml.cs b/Wox/ActionKeyword.xaml.cs index a2a1037434..4851a979b6 100644 --- a/Wox/ActionKeyword.xaml.cs +++ b/Wox/ActionKeyword.xaml.cs @@ -11,9 +11,9 @@ using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Shapes; +using Wox.Core.Plugin; using Wox.Infrastructure.Storage.UserSettings; using Wox.Plugin; -using Wox.PluginLoader; using MessageBox = System.Windows.MessageBox; namespace Wox @@ -25,7 +25,7 @@ namespace Wox public ActionKeyword(string pluginId) { InitializeComponent(); - PluginPair plugin = Plugins.AllPlugins.FirstOrDefault(o => o.Metadata.ID == pluginId); + PluginPair plugin = PluginManager.GetPlugin(pluginId); if (plugin == null) { MessageBox.Show("Can't find specific plugin"); @@ -56,7 +56,7 @@ namespace Wox } //check new action keyword didn't used by other plugin - if (Plugins.AllPlugins.Exists(o => o.Metadata.ActionKeyword == tbAction.Text.Trim())) + if (PluginManager.AllPlugins.Exists(o => o.Metadata.ActionKeyword == tbAction.Text.Trim())) { MessageBox.Show("New ActionKeyword has been assigned to other plugin, please assign another new action keyword"); return; diff --git a/Wox/CommandArgs/PluginDebuggerCommandArg.cs b/Wox/CommandArgs/PluginDebuggerCommandArg.cs index dadf639f9f..dab93500f8 100644 --- a/Wox/CommandArgs/PluginDebuggerCommandArg.cs +++ b/Wox/CommandArgs/PluginDebuggerCommandArg.cs @@ -3,6 +3,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Windows.Input; +using Wox.Core.Plugin; namespace Wox.CommandArgs { @@ -18,7 +19,7 @@ namespace Wox.CommandArgs if (args.Count > 0) { var pluginFolderPath = args[0]; - PluginLoader.Plugins.ActivatePluginDebugger(pluginFolderPath); + PluginManager.ActivatePluginDebugger(pluginFolderPath); } } } diff --git a/Wox/CommandArgs/ReloadPluginCommandArg.cs b/Wox/CommandArgs/ReloadPluginCommandArg.cs index ccc1a25db5..825f4439f6 100644 --- a/Wox/CommandArgs/ReloadPluginCommandArg.cs +++ b/Wox/CommandArgs/ReloadPluginCommandArg.cs @@ -2,7 +2,7 @@ using System.Collections.Generic; using System.Linq; using System.Text; -using Wox.PluginLoader; +using Wox.Core.Plugin; namespace Wox.CommandArgs { @@ -15,7 +15,7 @@ namespace Wox.CommandArgs public void Execute(IList args) { - Plugins.Init(); + PluginManager.Init(); } } } diff --git a/Wox/Commands/CommandFactory.cs b/Wox/Commands/CommandFactory.cs index fc18439b46..b7b2eb9c20 100644 --- a/Wox/Commands/CommandFactory.cs +++ b/Wox/Commands/CommandFactory.cs @@ -2,9 +2,9 @@ using System.Collections.Generic; using System.Linq; using System.Text; +using Wox.Core.Plugin; using Wox.Helper; using Wox.Plugin; -using Wox.PluginLoader; namespace Wox.Commands { @@ -15,7 +15,7 @@ namespace Wox.Commands public static void DispatchCommand(Query query) { - if (Plugins.HitThirdpartyKeyword(query)) + if (PluginManager.HitThirdpartyKeyword(query)) { pluginCmd.Dispatch(query); } diff --git a/Wox/Commands/PluginCommand.cs b/Wox/Commands/PluginCommand.cs index 34707e9daa..d233f766b9 100644 --- a/Wox/Commands/PluginCommand.cs +++ b/Wox/Commands/PluginCommand.cs @@ -2,11 +2,11 @@ using System.Collections.Generic; using System.Linq; using System.Threading; +using Wox.Core.Plugin; using Wox.Helper; using Wox.Infrastructure.Logger; using Wox.Infrastructure.Storage.UserSettings; using Wox.Plugin; -using Wox.PluginLoader; namespace Wox.Commands { @@ -14,7 +14,7 @@ namespace Wox.Commands { public override void Dispatch(Query query) { - PluginPair thirdPlugin = Plugins.AllPlugins.FirstOrDefault(o => o.Metadata.ActionKeyword == query.ActionName); + PluginPair thirdPlugin = PluginManager.AllPlugins.FirstOrDefault(o => o.Metadata.ActionKeyword == query.ActionName); if (thirdPlugin != null && !string.IsNullOrEmpty(thirdPlugin.Metadata.ActionKeyword)) { var customizedPluginConfig = UserSettingStorage.Instance.CustomizedPluginConfigs.FirstOrDefault(o => o.ID == thirdPlugin.Metadata.ID); diff --git a/Wox/Commands/SystemCommand.cs b/Wox/Commands/SystemCommand.cs index a1fc477a82..d1ca9eb4fc 100644 --- a/Wox/Commands/SystemCommand.cs +++ b/Wox/Commands/SystemCommand.cs @@ -3,16 +3,16 @@ using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; +using Wox.Core.Plugin; using Wox.Infrastructure.Storage.UserSettings; using Wox.Plugin; using Wox.Plugin.SystemPlugins; -using Wox.PluginLoader; namespace Wox.Commands { public class SystemCommand : BaseCommand { - private IEnumerable allSytemPlugins = Plugins.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.System); + private IEnumerable allSytemPlugins = PluginManager.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.System); public override void Dispatch(Query query) { diff --git a/Wox/Helper/PluginInstaller.cs b/Wox/Helper/PluginInstaller.cs index 15c6e55129..ed66f5eb24 100644 --- a/Wox/Helper/PluginInstaller.cs +++ b/Wox/Helper/PluginInstaller.cs @@ -5,8 +5,8 @@ using System.Linq; using System.Windows; using ICSharpCode.SharpZipLib.Zip; using Newtonsoft.Json; +using Wox.Core.Plugin; using Wox.Plugin; -using Wox.PluginLoader; namespace Wox.Helper { @@ -57,7 +57,7 @@ namespace Wox.Helper string content = string.Format( "Do you want to install following plugin?\r\n\r\nName: {0}\r\nVersion: {1}\r\nAuthor: {2}", plugin.Name, plugin.Version, plugin.Author); - PluginPair existingPlugin = Plugins.AllPlugins.FirstOrDefault(o => o.Metadata.ID == plugin.ID); + PluginPair existingPlugin = PluginManager.GetPlugin(plugin.ID); if (existingPlugin != null) { diff --git a/Wox/MainWindow.xaml.cs b/Wox/MainWindow.xaml.cs index 27b395354d..3fe95171dc 100644 --- a/Wox/MainWindow.xaml.cs +++ b/Wox/MainWindow.xaml.cs @@ -15,14 +15,13 @@ using WindowsInput.Native; using NHotkey; using NHotkey.Wpf; using Wox.Commands; +using Wox.Core.Plugin; using Wox.Helper; -using Wox.ImageLoader; using Wox.Infrastructure; using Wox.Infrastructure.Hotkey; using Wox.Infrastructure.Storage; using Wox.Infrastructure.Storage.UserSettings; using Wox.Plugin; -using Wox.PluginLoader; using Wox.Update; using Application = System.Windows.Application; using Brushes = System.Windows.Media.Brushes; @@ -128,12 +127,12 @@ namespace Wox public void ReloadPlugins() { - Dispatcher.Invoke(new Action(Plugins.Init)); + Dispatcher.Invoke(new Action(PluginManager.Init)); } public List GetAllPlugins() { - return Plugins.AllPlugins; + return PluginManager.AllPlugins; } public event WoxKeyDownEventHandler BackKeyDownEvent; @@ -193,7 +192,7 @@ namespace Wox ThreadPool.QueueUserWorkItem(o => { Thread.Sleep(50); - Plugins.Init(); + PluginManager.Init(); }); ThreadPool.QueueUserWorkItem(o => { @@ -360,7 +359,7 @@ namespace Wox var q = new Query(lastQuery); CommandFactory.DispatchCommand(q); BackToResultMode(); - if (Plugins.HitThirdpartyKeyword(q)) + if (PluginManager.HitThirdpartyKeyword(q)) { Dispatcher.DelayInvoke("ShowProgressbar", originQuery => { diff --git a/Wox/PluginLoader/BasePluginLoader.cs b/Wox/PluginLoader/BasePluginLoader.cs deleted file mode 100644 index ea2ad4f5df..0000000000 --- a/Wox/PluginLoader/BasePluginLoader.cs +++ /dev/null @@ -1,23 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Wox.Plugin; - -namespace Wox.PluginLoader -{ - public class BasePluginLoader : IPluginLoader where T : BasePlugin, new() - { - public virtual List LoadPlugin(List pluginMetadatas) - { - string supportedLanguage = new T().SupportedLanguage; - List metadatas = pluginMetadatas.Where(o => supportedLanguage.ToUpper() == o.Language.ToUpper()).ToList(); - - return metadatas.Select(metadata => new PluginPair() - { - Plugin = new T(), - Metadata = metadata - }).ToList(); - } - } -} diff --git a/Wox/PluginLoader/CSharpPluginLoader.cs b/Wox/PluginLoader/CSharpPluginLoader.cs deleted file mode 100644 index 8fa07c5801..0000000000 --- a/Wox/PluginLoader/CSharpPluginLoader.cs +++ /dev/null @@ -1,55 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Reflection; -using Wox.Helper; -using Wox.Infrastructure.Logger; -using Wox.Plugin; -using Wox.Plugin.SystemPlugins; - -namespace Wox.PluginLoader { - - public class CSharpPluginLoader : IPluginLoader - { - public List LoadPlugin(List pluginMetadatas) - { - var plugins = new List(); - - List metadatas = pluginMetadatas.Where(o => o.Language.ToUpper() == AllowedLanguage.CSharp.ToUpper()).ToList(); - foreach (PluginMetadata metadata in metadatas) { - try { - Assembly asm = Assembly.Load(AssemblyName.GetAssemblyName(metadata.ExecuteFilePath)); - List types = asm.GetTypes().Where(o => o.IsClass && !o.IsAbstract && (o.BaseType == typeof(BaseSystemPlugin) || o.GetInterfaces().Contains(typeof(IPlugin)))).ToList(); - if (types.Count == 0) { - Log.Warn(string.Format("Couldn't load plugin {0}: didn't find the class who implement IPlugin", metadata.Name)); - continue; - } - - foreach (Type type in types) { - PluginPair pair = new PluginPair() { - Plugin = Activator.CreateInstance(type) as IPlugin, - Metadata = metadata - }; - - var sys = pair.Plugin as BaseSystemPlugin; - if (sys != null) { - sys.PluginDirectory = metadata.PluginDirectory; - } - - plugins.Add(pair); - } - } - catch (Exception e) { - Log.Error(string.Format("Couldn't load plugin {0}: {1}", metadata.Name, e.Message)); -#if (DEBUG) - { - throw; - } -#endif - } - } - - return plugins; - } - } -} \ No newline at end of file diff --git a/Wox/PluginLoader/IPluginLoader.cs b/Wox/PluginLoader/IPluginLoader.cs deleted file mode 100644 index 6eecec4d8c..0000000000 --- a/Wox/PluginLoader/IPluginLoader.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using Wox.Plugin; - -namespace Wox.PluginLoader -{ - public interface IPluginLoader - { - List LoadPlugin(List pluginMetadatas); - } -} diff --git a/Wox/PluginLoader/PluginConfigLoader.cs b/Wox/PluginLoader/PluginConfigLoader.cs deleted file mode 100644 index 0953b902cf..0000000000 --- a/Wox/PluginLoader/PluginConfigLoader.cs +++ /dev/null @@ -1,121 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Reflection; -using System.Windows.Forms; -using Newtonsoft.Json; -using Wox.Helper; -using Wox.Infrastructure.Exceptions; -using Wox.Infrastructure.Logger; -using Wox.Infrastructure.Storage.UserSettings; -using Wox.Plugin; -using Wox.Plugin.SystemPlugins; - -namespace Wox.PluginLoader { - public abstract class PluginConfigLoader { - private static string PluginPath = Path.Combine(Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath), "Plugins"); - private static string PluginConfigName = "plugin.json"; - private static List pluginMetadatas = new List(); - - public static List ParsePluginsConfig() - { - pluginMetadatas.Clear(); - ParseSystemPlugins(); - ParseThirdPartyPlugins(); - - if (Plugins.DebuggerMode != null) { - PluginMetadata metadata = GetMetadataFromJson(Plugins.DebuggerMode); - if (metadata != null) pluginMetadatas.Add(metadata); - } - return pluginMetadatas; - } - - private static void ParseSystemPlugins() { - pluginMetadatas.Add(new PluginMetadata() { - Name = "System Plugins", - Author = "System", - Description = "system plugins collection", - Website = "http://www.getwox.com", - Language = AllowedLanguage.CSharp, - Version = "1.0", - PluginType = PluginType.System, - ActionKeyword = "*", - ExecuteFileName = "Wox.Plugin.SystemPlugins.dll", - PluginDirectory = Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath) - }); - } - - private static void ParseThirdPartyPlugins() { - if (!Directory.Exists(PluginPath)) - Directory.CreateDirectory(PluginPath); - - string[] directories = Directory.GetDirectories(PluginPath); - foreach (string directory in directories) { - if (File.Exists((Path.Combine(directory, "NeedDelete.txt")))) { - Directory.Delete(directory, true); - continue; - } - PluginMetadata metadata = GetMetadataFromJson(directory); - if (metadata != null) pluginMetadatas.Add(metadata); - } - } - - private static PluginMetadata GetMetadataFromJson(string pluginDirectory) { - string configPath = Path.Combine(pluginDirectory, PluginConfigName); - PluginMetadata metadata; - - if (!File.Exists(configPath)) { - Log.Warn(string.Format("parse plugin {0} failed: didn't find config file.", configPath)); - return null; - } - - try { - metadata = JsonConvert.DeserializeObject(File.ReadAllText(configPath)); - metadata.PluginType = PluginType.ThirdParty; - metadata.PluginDirectory = pluginDirectory; - } - catch (Exception) { - string error = string.Format("Parse plugin config {0} failed: json format is not valid", configPath); - Log.Warn(error); -#if (DEBUG) - { - throw new WoxException(error); - } -#endif - return null; - } - - - if (!AllowedLanguage.IsAllowed(metadata.Language)) { - string error = string.Format("Parse plugin config {0} failed: invalid language {1}", configPath, metadata.Language); - Log.Warn(error); -#if (DEBUG) - { - throw new WoxException(error); - } -#endif - return null; - } - if (!File.Exists(metadata.ExecuteFilePath)) { - string error = string.Format("Parse plugin config {0} failed: ExecuteFile {1} didn't exist", configPath, metadata.ExecuteFilePath); - Log.Warn(error); -#if (DEBUG) - { - throw new WoxException(error); - } -#endif - return null; - } - - var customizedPluginConfig = - UserSettingStorage.Instance.CustomizedPluginConfigs.FirstOrDefault(o => o.ID == metadata.ID); - if (customizedPluginConfig != null && !string.IsNullOrEmpty(customizedPluginConfig.Actionword)) - { - metadata.ActionKeyword = customizedPluginConfig.Actionword; - } - - return metadata; - } - } -} diff --git a/Wox/PluginLoader/Plugins.cs b/Wox/PluginLoader/Plugins.cs deleted file mode 100644 index f4c7eedbfb..0000000000 --- a/Wox/PluginLoader/Plugins.cs +++ /dev/null @@ -1,58 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading; -using Wox.Helper; -using Wox.Infrastructure; -using Wox.Infrastructure.Http; -using Wox.Infrastructure.Storage.UserSettings; -using Wox.Plugin; - -namespace Wox.PluginLoader -{ - public static class Plugins - { - public static String DebuggerMode { get; private set; } - private static List plugins = new List(); - - public static void Init() - { - plugins.Clear(); - List pluginMetadatas = PluginConfigLoader.ParsePluginsConfig(); - - plugins.AddRange(new CSharpPluginLoader().LoadPlugin(pluginMetadatas)); - plugins.AddRange(new BasePluginLoader().LoadPlugin(pluginMetadatas)); - - foreach (PluginPair pluginPair in plugins) - { - PluginPair pair = pluginPair; - ThreadPool.QueueUserWorkItem(o => pair.Plugin.Init(new PluginInitContext() - { - CurrentPluginMetadata = pair.Metadata, - Proxy = HttpProxy.Instance, - API = App.Window - })); - } - } - - public static List AllPlugins - { - get - { - return plugins; - } - } - - public static bool HitThirdpartyKeyword(Query query) - { - if (string.IsNullOrEmpty(query.ActionName)) return false; - - return plugins.Any(o => o.Metadata.PluginType == PluginType.ThirdParty && o.Metadata.ActionKeyword == query.ActionName); - } - - public static void ActivatePluginDebugger(string path) - { - DebuggerMode = path; - } - } -} diff --git a/Wox/SettingWindow.xaml.cs b/Wox/SettingWindow.xaml.cs index 4c752ad13c..a356bdec9c 100644 --- a/Wox/SettingWindow.xaml.cs +++ b/Wox/SettingWindow.xaml.cs @@ -11,11 +11,11 @@ using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using IWshRuntimeLibrary; +using Wox.Core.Plugin; using Wox.Infrastructure.Storage.UserSettings; using Wox.Plugin; using Wox.Helper; using Wox.Plugin.SystemPlugins; -using Wox.PluginLoader; using Wox.Update; using Application = System.Windows.Forms.Application; using File = System.IO.File; @@ -187,7 +187,7 @@ namespace Wox new CollectionContainer { Collection = - PluginLoader.Plugins.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.System) + PluginManager.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.System) .Select(o => o.Plugin) .Cast() }, @@ -195,7 +195,7 @@ namespace Wox new CollectionContainer { Collection = - PluginLoader.Plugins.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.ThirdParty) + PluginManager.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.ThirdParty) } }; lbPlugins.ItemsSource = plugins; @@ -576,7 +576,7 @@ namespace Wox string id = pair.Metadata.ID; ActionKeyword changeKeywordWindow = new ActionKeyword(id); changeKeywordWindow.ShowDialog(); - PluginPair plugin = Plugins.AllPlugins.FirstOrDefault(o => o.Metadata.ID == id); + PluginPair plugin = PluginManager.GetPlugin(id); if (plugin != null) pluginActionKeyword.Text = plugin.Metadata.ActionKeyword; } } diff --git a/Wox/Wox.csproj b/Wox/Wox.csproj index cca06f9642..66bb922123 100644 --- a/Wox/Wox.csproj +++ b/Wox/Wox.csproj @@ -153,17 +153,9 @@ HotkeyControl.xaml - Msg.xaml - - - - - - - ResultPanel.xaml @@ -272,6 +264,10 @@ + + {B749F0DB-8E75-47DB-9E5E-265D16D0C0D2} + Wox.Core + {4fd29318-a8ab-4d8f-aa47-60bc241b8da3} Wox.Infrastructure