Refactoring [WIP]

This commit is contained in:
qianlifeng
2014-12-26 19:36:43 +08:00
parent 31281c7faa
commit 50f6044a2f
28 changed files with 515 additions and 325 deletions

View File

@@ -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<PluginPair> LoadPlugin(List<PluginMetadata> pluginMetadatas)
{
var plugins = new List<PluginPair>();
List<PluginMetadata> 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<Type> 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;
}
}
}

View File

@@ -0,0 +1,10 @@
using System.Collections.Generic;
using Wox.Plugin;
namespace Wox.Core.Plugin
{
internal interface IPluginLoader
{
IEnumerable<PluginPair> LoadPlugin(List<PluginMetadata> pluginMetadatas);
}
}

View File

@@ -17,7 +17,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using Wox.Plugin; using Wox.Plugin;
namespace Wox.JsonRPC namespace Wox.Core.Plugin
{ {
public class JsonRPCErrorModel public class JsonRPCErrorModel
{ {

View File

@@ -2,30 +2,29 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Diagnostics; using System.Diagnostics;
using System.IO; using System.IO;
using System.Linq;
using System.Reflection; using System.Reflection;
using System.Text;
using System.Threading; using System.Threading;
using System.Windows.Forms;
using Newtonsoft.Json; using Newtonsoft.Json;
using Wox.Helper;
using Wox.Helper.ErrorReporting;
using Wox.Infrastructure.Exceptions; using Wox.Infrastructure.Exceptions;
using Wox.Infrastructure.Logger; using Wox.Infrastructure.Logger;
using Wox.JsonRPC;
using Wox.Plugin; using Wox.Plugin;
using MessageBox = System.Windows.MessageBox;
namespace Wox.PluginLoader namespace Wox.Core.Plugin
{ {
public abstract class BasePlugin : IPlugin /// <summary>
/// Represent the plugin that using JsonPRC
/// </summary>
internal abstract class JsonRPCPlugin : IPlugin
{ {
protected PluginInitContext context; protected PluginInitContext context;
/// <summary>
/// The language this JsonRPCPlugin support
/// </summary>
public abstract string SupportedLanguage { get; } public abstract string SupportedLanguage { get; }
protected abstract string ExecuteQuery(Query query); protected abstract string ExecuteQuery(Query query);
protected abstract string ExecuteAction(JsonRPCRequestModel rpcRequest); protected abstract string ExecuteCallback(JsonRPCRequestModel rpcRequest);
public List<Result> Query(Query query) public List<Result> Query(Query query)
{ {
@@ -56,7 +55,7 @@ namespace Wox.PluginLoader
{ {
ThreadPool.QueueUserWorkItem(state => ThreadPool.QueueUserWorkItem(state =>
{ {
string actionReponse = ExecuteAction(result1.JsonRPCAction); string actionReponse = ExecuteCallback(result1.JsonRPCAction);
JsonRPCRequestModel jsonRpcRequestModel = JsonConvert.DeserializeObject<JsonRPCRequestModel>(actionReponse); JsonRPCRequestModel jsonRpcRequestModel = JsonConvert.DeserializeObject<JsonRPCRequestModel>(actionReponse);
if (jsonRpcRequestModel != null if (jsonRpcRequestModel != null
&& !string.IsNullOrEmpty(jsonRpcRequestModel.Method) && !string.IsNullOrEmpty(jsonRpcRequestModel.Method)
@@ -161,7 +160,7 @@ namespace Wox.PluginLoader
public void Init(PluginInitContext ctx) public void Init(PluginInitContext ctx)
{ {
this.context = ctx; context = ctx;
} }
} }
} }

View File

@@ -0,0 +1,21 @@
using System.Collections.Generic;
using System.Linq;
using Wox.Plugin;
namespace Wox.Core.Plugin
{
internal class JsonRPCPluginLoader<T> : IPluginLoader where T : JsonRPCPlugin, new()
{
public virtual IEnumerable<PluginPair> LoadPlugin(List<PluginMetadata> pluginMetadatas)
{
T jsonRPCPlugin = new T();
List<PluginMetadata> jsonRPCPluginMetadatas = pluginMetadatas.Where(o => o.Language.ToUpper() == jsonRPCPlugin.SupportedLanguage.ToUpper()).ToList();
return jsonRPCPluginMetadatas.Select(metadata => new PluginPair()
{
Plugin = jsonRPCPlugin,
Metadata = metadata
}).ToList();
}
}
}

View File

@@ -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<PluginMetadata> pluginMetadatas = new List<PluginMetadata>();
/// <summary>
/// Parse plugin metadata in giving directories
/// </summary>
/// <param name="pluginDirectories"></param>
/// <returns></returns>
public static List<PluginMetadata> Parse(List<string> 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<PluginMetadata>(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;
}
}
}

View File

@@ -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
{
/// <summary>
/// The entry for managing Wox plugins
/// </summary>
public static class PluginManager
{
public static String DebuggerMode { get; private set; }
private static List<PluginPair> plugins = new List<PluginPair>();
/// <summary>
/// Directories that will hold Wox plugin directory
/// </summary>
private static List<string> pluginDirectories = new List<string>();
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);
}
}
}
/// <summary>
/// Load and init all Wox plugins
/// </summary>
public static void Init()
{
plugins.Clear();
List<PluginMetadata> pluginMetadatas = PluginConfig.Parse(pluginDirectories);
plugins.AddRange(new CSharpPluginLoader().LoadPlugin(pluginMetadatas));
plugins.AddRange(new JsonRPCPluginLoader<PythonPlugin>().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<PluginPair> 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;
}
/// <summary>
/// get specified plugin, return null if not found
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public static PluginPair GetPlugin(string id)
{
return AllPlugins.FirstOrDefault(o => o.Metadata.ID == id);
}
}
}

View File

@@ -1,17 +1,14 @@
using System.Collections.Generic; using System.Diagnostics;
using System.Diagnostics;
using System.IO; using System.IO;
using Wox.Helper; using System.Reflection;
using Wox.Infrastructure;
using Wox.Infrastructure.Http; using Wox.Infrastructure.Http;
using Wox.JsonRPC;
using Wox.Plugin; 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; private ProcessStartInfo startInfo;
public override string SupportedLanguage public override string SupportedLanguage
@@ -57,7 +54,7 @@ namespace Wox.PluginLoader
return Execute(startInfo); return Execute(startInfo);
} }
protected override string ExecuteAction(JsonRPCRequestModel rpcRequest) protected override string ExecuteCallback(JsonRPCRequestModel rpcRequest)
{ {
startInfo.FileName = Path.Combine(woxDirectory, "PythonHome\\pythonw.exe"); startInfo.FileName = Path.Combine(woxDirectory, "PythonHome\\pythonw.exe");
startInfo.Arguments = string.Format("-B \"{0}\" \"{1}\"", context.CurrentPluginMetadata.ExecuteFilePath, rpcRequest); startInfo.Arguments = string.Format("-B \"{0}\" \"{1}\"", context.CurrentPluginMetadata.ExecuteFilePath, rpcRequest);

View File

@@ -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")]

4
Wox.Core/README.txt Normal file
View File

@@ -0,0 +1,4 @@
What does Wox.Core do?
* Handle Query
* Loading Plugins

86
Wox.Core/Wox.Core.csproj Normal file
View File

@@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{B749F0DB-8E75-47DB-9E5E-265D16D0C0D2}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Wox.Core</RootNamespace>
<AssemblyName>Wox.Core</AssemblyName>
<TargetFrameworkVersion>v3.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Newtonsoft.Json, Version=6.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<SpecificVersion>False</SpecificVersion>
<HintPath>..\packages\Newtonsoft.Json.6.0.7\lib\net35\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Plugin\JsonRPCPlugin.cs" />
<Compile Include="Plugin\JsonRPCPluginLoader.cs" />
<Compile Include="Plugin\CSharpPluginLoader.cs" />
<Compile Include="Plugin\IPluginLoader.cs" />
<Compile Include="Plugin\JsonPRCModel.cs" />
<Compile Include="Plugin\PluginConfig.cs" />
<Compile Include="Plugin\PluginManager.cs" />
<Compile Include="Plugin\PythonPlugin.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="README.txt" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Wox.Infrastructure\Wox.Infrastructure.csproj">
<Project>{4fd29318-a8ab-4d8f-aa47-60bc241b8da3}</Project>
<Name>Wox.Infrastructure</Name>
</ProjectReference>
<ProjectReference Include="..\Wox.Plugin.SystemPlugins\Wox.Plugin.SystemPlugins.csproj">
<Project>{69ce0206-cb41-453d-88af-df86092ef9b8}</Project>
<Name>Wox.Plugin.SystemPlugins</Name>
</ProjectReference>
<ProjectReference Include="..\Wox.Plugin\Wox.Plugin.csproj">
<Project>{8451ecdd-2ea4-4966-bb0a-7bbc40138e80}</Project>
<Name>Wox.Plugin</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\NuGet.targets" Condition="Exists('$(SolutionDir)\.nuget\NuGet.targets')" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

4
Wox.Core/packages.config Normal file
View File

@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Newtonsoft.Json" version="6.0.7" targetFramework="net35" />
</packages>

View File

@@ -1,7 +1,7 @@
 
Microsoft Visual Studio Solution File, Format Version 12.00 Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 2013 # Visual Studio 2013
VisualStudioVersion = 12.0.30723.0 VisualStudioVersion = 12.0.21005.1
MinimumVisualStudioVersion = 10.0.40219.1 MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Test", "Wox.Test\Wox.Test.csproj", "{FF742965-9A80-41A5-B042-D6C7D3A21708}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Test", "Wox.Test\Wox.Test.csproj", "{FF742965-9A80-41A5-B042-D6C7D3A21708}"
EndProject EndProject
@@ -17,6 +17,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Infrastructure", "Wox.I
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Plugin.PluginManagement", "Plugins\Wox.Plugin.PluginManagement\Wox.Plugin.PluginManagement.csproj", "{049490F0-ECD2-4148-9B39-2135EC346EBE}" Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Plugin.PluginManagement", "Plugins\Wox.Plugin.PluginManagement\Wox.Plugin.PluginManagement.csproj", "{049490F0-ECD2-4148-9B39-2135EC346EBE}"
EndProject EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Wox.Core", "Wox.Core\Wox.Core.csproj", "{B749F0DB-8E75-47DB-9E5E-265D16D0C0D2}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU 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}.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.ActiveCfg = Release|Any CPU
{049490F0-ECD2-4148-9B39-2135EC346EBE}.Release|Any CPU.Build.0 = 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 EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE

View File

@@ -11,9 +11,9 @@ using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using System.Windows.Shapes; using System.Windows.Shapes;
using Wox.Core.Plugin;
using Wox.Infrastructure.Storage.UserSettings; using Wox.Infrastructure.Storage.UserSettings;
using Wox.Plugin; using Wox.Plugin;
using Wox.PluginLoader;
using MessageBox = System.Windows.MessageBox; using MessageBox = System.Windows.MessageBox;
namespace Wox namespace Wox
@@ -25,7 +25,7 @@ namespace Wox
public ActionKeyword(string pluginId) public ActionKeyword(string pluginId)
{ {
InitializeComponent(); InitializeComponent();
PluginPair plugin = Plugins.AllPlugins.FirstOrDefault(o => o.Metadata.ID == pluginId); PluginPair plugin = PluginManager.GetPlugin(pluginId);
if (plugin == null) if (plugin == null)
{ {
MessageBox.Show("Can't find specific plugin"); MessageBox.Show("Can't find specific plugin");
@@ -56,7 +56,7 @@ namespace Wox
} }
//check new action keyword didn't used by other plugin //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"); MessageBox.Show("New ActionKeyword has been assigned to other plugin, please assign another new action keyword");
return; return;

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Windows.Input; using System.Windows.Input;
using Wox.Core.Plugin;
namespace Wox.CommandArgs namespace Wox.CommandArgs
{ {
@@ -18,7 +19,7 @@ namespace Wox.CommandArgs
if (args.Count > 0) if (args.Count > 0)
{ {
var pluginFolderPath = args[0]; var pluginFolderPath = args[0];
PluginLoader.Plugins.ActivatePluginDebugger(pluginFolderPath); PluginManager.ActivatePluginDebugger(pluginFolderPath);
} }
} }
} }

View File

@@ -2,7 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Wox.PluginLoader; using Wox.Core.Plugin;
namespace Wox.CommandArgs namespace Wox.CommandArgs
{ {
@@ -15,7 +15,7 @@ namespace Wox.CommandArgs
public void Execute(IList<string> args) public void Execute(IList<string> args)
{ {
Plugins.Init(); PluginManager.Init();
} }
} }
} }

View File

@@ -2,9 +2,9 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using Wox.Core.Plugin;
using Wox.Helper; using Wox.Helper;
using Wox.Plugin; using Wox.Plugin;
using Wox.PluginLoader;
namespace Wox.Commands namespace Wox.Commands
{ {
@@ -15,7 +15,7 @@ namespace Wox.Commands
public static void DispatchCommand(Query query) public static void DispatchCommand(Query query)
{ {
if (Plugins.HitThirdpartyKeyword(query)) if (PluginManager.HitThirdpartyKeyword(query))
{ {
pluginCmd.Dispatch(query); pluginCmd.Dispatch(query);
} }

View File

@@ -2,11 +2,11 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using Wox.Core.Plugin;
using Wox.Helper; using Wox.Helper;
using Wox.Infrastructure.Logger; using Wox.Infrastructure.Logger;
using Wox.Infrastructure.Storage.UserSettings; using Wox.Infrastructure.Storage.UserSettings;
using Wox.Plugin; using Wox.Plugin;
using Wox.PluginLoader;
namespace Wox.Commands namespace Wox.Commands
{ {
@@ -14,7 +14,7 @@ namespace Wox.Commands
{ {
public override void Dispatch(Query query) 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)) if (thirdPlugin != null && !string.IsNullOrEmpty(thirdPlugin.Metadata.ActionKeyword))
{ {
var customizedPluginConfig = UserSettingStorage.Instance.CustomizedPluginConfigs.FirstOrDefault(o => o.ID == thirdPlugin.Metadata.ID); var customizedPluginConfig = UserSettingStorage.Instance.CustomizedPluginConfigs.FirstOrDefault(o => o.ID == thirdPlugin.Metadata.ID);

View File

@@ -3,16 +3,16 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using Wox.Core.Plugin;
using Wox.Infrastructure.Storage.UserSettings; using Wox.Infrastructure.Storage.UserSettings;
using Wox.Plugin; using Wox.Plugin;
using Wox.Plugin.SystemPlugins; using Wox.Plugin.SystemPlugins;
using Wox.PluginLoader;
namespace Wox.Commands namespace Wox.Commands
{ {
public class SystemCommand : BaseCommand public class SystemCommand : BaseCommand
{ {
private IEnumerable<PluginPair> allSytemPlugins = Plugins.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.System); private IEnumerable<PluginPair> allSytemPlugins = PluginManager.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.System);
public override void Dispatch(Query query) public override void Dispatch(Query query)
{ {

View File

@@ -5,8 +5,8 @@ using System.Linq;
using System.Windows; using System.Windows;
using ICSharpCode.SharpZipLib.Zip; using ICSharpCode.SharpZipLib.Zip;
using Newtonsoft.Json; using Newtonsoft.Json;
using Wox.Core.Plugin;
using Wox.Plugin; using Wox.Plugin;
using Wox.PluginLoader;
namespace Wox.Helper namespace Wox.Helper
{ {
@@ -57,7 +57,7 @@ namespace Wox.Helper
string content = string.Format( string content = string.Format(
"Do you want to install following plugin?\r\n\r\nName: {0}\r\nVersion: {1}\r\nAuthor: {2}", "Do you want to install following plugin?\r\n\r\nName: {0}\r\nVersion: {1}\r\nAuthor: {2}",
plugin.Name, plugin.Version, plugin.Author); 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) if (existingPlugin != null)
{ {

View File

@@ -15,14 +15,13 @@ using WindowsInput.Native;
using NHotkey; using NHotkey;
using NHotkey.Wpf; using NHotkey.Wpf;
using Wox.Commands; using Wox.Commands;
using Wox.Core.Plugin;
using Wox.Helper; using Wox.Helper;
using Wox.ImageLoader;
using Wox.Infrastructure; using Wox.Infrastructure;
using Wox.Infrastructure.Hotkey; using Wox.Infrastructure.Hotkey;
using Wox.Infrastructure.Storage; using Wox.Infrastructure.Storage;
using Wox.Infrastructure.Storage.UserSettings; using Wox.Infrastructure.Storage.UserSettings;
using Wox.Plugin; using Wox.Plugin;
using Wox.PluginLoader;
using Wox.Update; using Wox.Update;
using Application = System.Windows.Application; using Application = System.Windows.Application;
using Brushes = System.Windows.Media.Brushes; using Brushes = System.Windows.Media.Brushes;
@@ -128,12 +127,12 @@ namespace Wox
public void ReloadPlugins() public void ReloadPlugins()
{ {
Dispatcher.Invoke(new Action(Plugins.Init)); Dispatcher.Invoke(new Action(PluginManager.Init));
} }
public List<PluginPair> GetAllPlugins() public List<PluginPair> GetAllPlugins()
{ {
return Plugins.AllPlugins; return PluginManager.AllPlugins;
} }
public event WoxKeyDownEventHandler BackKeyDownEvent; public event WoxKeyDownEventHandler BackKeyDownEvent;
@@ -193,7 +192,7 @@ namespace Wox
ThreadPool.QueueUserWorkItem(o => ThreadPool.QueueUserWorkItem(o =>
{ {
Thread.Sleep(50); Thread.Sleep(50);
Plugins.Init(); PluginManager.Init();
}); });
ThreadPool.QueueUserWorkItem(o => ThreadPool.QueueUserWorkItem(o =>
{ {
@@ -360,7 +359,7 @@ namespace Wox
var q = new Query(lastQuery); var q = new Query(lastQuery);
CommandFactory.DispatchCommand(q); CommandFactory.DispatchCommand(q);
BackToResultMode(); BackToResultMode();
if (Plugins.HitThirdpartyKeyword(q)) if (PluginManager.HitThirdpartyKeyword(q))
{ {
Dispatcher.DelayInvoke("ShowProgressbar", originQuery => Dispatcher.DelayInvoke("ShowProgressbar", originQuery =>
{ {

View File

@@ -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<T> : IPluginLoader where T : BasePlugin, new()
{
public virtual List<PluginPair> LoadPlugin(List<PluginMetadata> pluginMetadatas)
{
string supportedLanguage = new T().SupportedLanguage;
List<PluginMetadata> metadatas = pluginMetadatas.Where(o => supportedLanguage.ToUpper() == o.Language.ToUpper()).ToList();
return metadatas.Select(metadata => new PluginPair()
{
Plugin = new T(),
Metadata = metadata
}).ToList();
}
}
}

View File

@@ -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<PluginPair> LoadPlugin(List<PluginMetadata> pluginMetadatas)
{
var plugins = new List<PluginPair>();
List<PluginMetadata> 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<Type> 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;
}
}
}

View File

@@ -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<PluginPair> LoadPlugin(List<PluginMetadata> pluginMetadatas);
}
}

View File

@@ -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<PluginMetadata> pluginMetadatas = new List<PluginMetadata>();
public static List<PluginMetadata> 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<PluginMetadata>(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;
}
}
}

View File

@@ -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<PluginPair> plugins = new List<PluginPair>();
public static void Init()
{
plugins.Clear();
List<PluginMetadata> pluginMetadatas = PluginConfigLoader.ParsePluginsConfig();
plugins.AddRange(new CSharpPluginLoader().LoadPlugin(pluginMetadatas));
plugins.AddRange(new BasePluginLoader<PythonPlugin>().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<PluginPair> 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;
}
}
}

View File

@@ -11,11 +11,11 @@ using System.Windows.Input;
using System.Windows.Media; using System.Windows.Media;
using System.Windows.Media.Imaging; using System.Windows.Media.Imaging;
using IWshRuntimeLibrary; using IWshRuntimeLibrary;
using Wox.Core.Plugin;
using Wox.Infrastructure.Storage.UserSettings; using Wox.Infrastructure.Storage.UserSettings;
using Wox.Plugin; using Wox.Plugin;
using Wox.Helper; using Wox.Helper;
using Wox.Plugin.SystemPlugins; using Wox.Plugin.SystemPlugins;
using Wox.PluginLoader;
using Wox.Update; using Wox.Update;
using Application = System.Windows.Forms.Application; using Application = System.Windows.Forms.Application;
using File = System.IO.File; using File = System.IO.File;
@@ -187,7 +187,7 @@ namespace Wox
new CollectionContainer new CollectionContainer
{ {
Collection = Collection =
PluginLoader.Plugins.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.System) PluginManager.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.System)
.Select(o => o.Plugin) .Select(o => o.Plugin)
.Cast<ISystemPlugin>() .Cast<ISystemPlugin>()
}, },
@@ -195,7 +195,7 @@ namespace Wox
new CollectionContainer new CollectionContainer
{ {
Collection = Collection =
PluginLoader.Plugins.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.ThirdParty) PluginManager.AllPlugins.Where(o => o.Metadata.PluginType == PluginType.ThirdParty)
} }
}; };
lbPlugins.ItemsSource = plugins; lbPlugins.ItemsSource = plugins;
@@ -576,7 +576,7 @@ namespace Wox
string id = pair.Metadata.ID; string id = pair.Metadata.ID;
ActionKeyword changeKeywordWindow = new ActionKeyword(id); ActionKeyword changeKeywordWindow = new ActionKeyword(id);
changeKeywordWindow.ShowDialog(); 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; if (plugin != null) pluginActionKeyword.Text = plugin.Metadata.ActionKeyword;
} }
} }

View File

@@ -153,17 +153,9 @@
<DependentUpon>HotkeyControl.xaml</DependentUpon> <DependentUpon>HotkeyControl.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="Converters\ImagePathConverter.cs" /> <Compile Include="Converters\ImagePathConverter.cs" />
<Compile Include="PluginLoader\IPluginLoader.cs" />
<Compile Include="Msg.xaml.cs"> <Compile Include="Msg.xaml.cs">
<DependentUpon>Msg.xaml</DependentUpon> <DependentUpon>Msg.xaml</DependentUpon>
</Compile> </Compile>
<Compile Include="PluginLoader\PluginConfigLoader.cs" />
<Compile Include="PluginLoader\CSharpPluginLoader.cs" />
<Compile Include="PluginLoader\BasePluginLoader.cs" />
<Compile Include="PluginLoader\BasePlugin.cs" />
<Compile Include="JsonRPC\JsonPRCModel.cs" />
<Compile Include="PluginLoader\Plugins.cs" />
<Compile Include="PluginLoader\PythonPlugin.cs" />
<Compile Include="Properties\Annotations.cs" /> <Compile Include="Properties\Annotations.cs" />
<Compile Include="ResultPanel.xaml.cs"> <Compile Include="ResultPanel.xaml.cs">
<DependentUpon>ResultPanel.xaml</DependentUpon> <DependentUpon>ResultPanel.xaml</DependentUpon>
@@ -272,6 +264,10 @@
<AppDesigner Include="Properties\" /> <AppDesigner Include="Properties\" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Wox.Core\Wox.Core.csproj">
<Project>{B749F0DB-8E75-47DB-9E5E-265D16D0C0D2}</Project>
<Name>Wox.Core</Name>
</ProjectReference>
<ProjectReference Include="..\Wox.Infrastructure\Wox.Infrastructure.csproj"> <ProjectReference Include="..\Wox.Infrastructure\Wox.Infrastructure.csproj">
<Project>{4fd29318-a8ab-4d8f-aa47-60bc241b8da3}</Project> <Project>{4fd29318-a8ab-4d8f-aa47-60bc241b8da3}</Project>
<Name>Wox.Infrastructure</Name> <Name>Wox.Infrastructure</Name>