Implemented UI plugin downloading
This commit is contained in:
parent
4500f1d11b
commit
26aef6b082
31
MediaBrowser.Api/HttpHandlers/PluginAssemblyHandler.cs
Normal file
31
MediaBrowser.Api/HttpHandlers/PluginAssemblyHandler.cs
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using MediaBrowser.Common.Net.Handlers;
|
||||||
|
using MediaBrowser.Controller;
|
||||||
|
|
||||||
|
namespace MediaBrowser.Api.HttpHandlers
|
||||||
|
{
|
||||||
|
class PluginAssemblyHandler : BaseHandler
|
||||||
|
{
|
||||||
|
public override Task<string> GetContentType()
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override Task WriteResponseToOutputStream(Stream stream)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
|
public override Task ProcessRequest(HttpListenerContext ctx)
|
||||||
|
{
|
||||||
|
string filename = ctx.Request.QueryString["assemblyfilename"];
|
||||||
|
|
||||||
|
string path = Path.Combine(Kernel.Instance.ApplicationPaths.PluginsPath, filename);
|
||||||
|
|
||||||
|
return new StaticFileHandler() { Path = path }.ProcessRequest(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -21,7 +21,8 @@ namespace MediaBrowser.Api.HttpHandlers
|
||||||
Name = p.Name,
|
Name = p.Name,
|
||||||
Enabled = p.Enabled,
|
Enabled = p.Enabled,
|
||||||
DownloadToUI = p.DownloadToUI,
|
DownloadToUI = p.DownloadToUI,
|
||||||
Version = p.Version.ToString()
|
Version = p.Version.ToString(),
|
||||||
|
AssemblyFileName = p.AssemblyFileName
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -67,6 +67,7 @@
|
||||||
<Compile Include="HttpHandlers\ItemHandler.cs" />
|
<Compile Include="HttpHandlers\ItemHandler.cs" />
|
||||||
<Compile Include="HttpHandlers\ItemListHandler.cs" />
|
<Compile Include="HttpHandlers\ItemListHandler.cs" />
|
||||||
<Compile Include="HttpHandlers\PersonHandler.cs" />
|
<Compile Include="HttpHandlers\PersonHandler.cs" />
|
||||||
|
<Compile Include="HttpHandlers\PluginAssemblyHandler.cs" />
|
||||||
<Compile Include="HttpHandlers\PluginConfigurationHandler.cs" />
|
<Compile Include="HttpHandlers\PluginConfigurationHandler.cs" />
|
||||||
<Compile Include="HttpHandlers\PluginsHandler.cs" />
|
<Compile Include="HttpHandlers\PluginsHandler.cs" />
|
||||||
<Compile Include="HttpHandlers\ServerConfigurationHandler.cs" />
|
<Compile Include="HttpHandlers\ServerConfigurationHandler.cs" />
|
||||||
|
|
|
@ -113,6 +113,10 @@ namespace MediaBrowser.Api
|
||||||
{
|
{
|
||||||
return new DefaultUserHandler();
|
return new DefaultUserHandler();
|
||||||
}
|
}
|
||||||
|
else if (localPath.EndsWith("/api/pluginassembly", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return new PluginAssemblyHandler();
|
||||||
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -569,7 +569,7 @@ namespace MediaBrowser.ApiInteraction
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a list of plugins installed on the server
|
/// Gets a list of plugins installed on the server
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public async Task<PluginInfo[]> GetInstalledPlugins()
|
public async Task<PluginInfo[]> GetInstalledPluginsAsync()
|
||||||
{
|
{
|
||||||
string url = ApiUrl + "/plugins";
|
string url = ApiUrl + "/plugins";
|
||||||
|
|
||||||
|
@ -578,7 +578,17 @@ namespace MediaBrowser.ApiInteraction
|
||||||
return DeserializeFromStream<PluginInfo[]>(stream);
|
return DeserializeFromStream<PluginInfo[]>(stream);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets a list of plugins installed on the server
|
||||||
|
/// </summary>
|
||||||
|
public Task<Stream> GetPluginAssemblyAsync(PluginInfo plugin)
|
||||||
|
{
|
||||||
|
string url = ApiUrl + "/pluginassembly?assemblyfilename=" + plugin.AssemblyFileName;
|
||||||
|
|
||||||
|
return GetStreamAsync(url);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets weather information for the default location as set in configuration
|
/// Gets weather information for the default location as set in configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -655,7 +665,7 @@ namespace MediaBrowser.ApiInteraction
|
||||||
|
|
||||||
return GetStreamAsync(url);
|
return GetStreamAsync(url);
|
||||||
}
|
}
|
||||||
|
|
||||||
private T DeserializeFromStream<T>(Stream stream)
|
private T DeserializeFromStream<T>(Stream stream)
|
||||||
{
|
{
|
||||||
return DeserializeFromStream<T>(stream, SerializationFormat);
|
return DeserializeFromStream<T>(stream, SerializationFormat);
|
||||||
|
|
|
@ -59,21 +59,18 @@ namespace MediaBrowser.Common.Kernel
|
||||||
ApplicationPaths = new TApplicationPathsType();
|
ApplicationPaths = new TApplicationPathsType();
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual Task Init(IProgress<TaskProgress> progress)
|
public virtual async Task Init(IProgress<TaskProgress> progress)
|
||||||
{
|
{
|
||||||
return Task.Run(() =>
|
ReloadLogger();
|
||||||
{
|
|
||||||
ReloadLogger();
|
|
||||||
|
|
||||||
progress.Report(new TaskProgress() { Description = "Loading configuration", PercentComplete = 0 });
|
progress.Report(new TaskProgress() { Description = "Loading configuration", PercentComplete = 0 });
|
||||||
ReloadConfiguration();
|
ReloadConfiguration();
|
||||||
|
|
||||||
progress.Report(new TaskProgress() { Description = "Starting Http server", PercentComplete = 5 });
|
progress.Report(new TaskProgress() { Description = "Starting Http server", PercentComplete = 5 });
|
||||||
ReloadHttpServer();
|
ReloadHttpServer();
|
||||||
|
|
||||||
progress.Report(new TaskProgress() { Description = "Loading Plugins", PercentComplete = 10 });
|
progress.Report(new TaskProgress() { Description = "Loading Plugins", PercentComplete = 10 });
|
||||||
ReloadComposableParts();
|
await ReloadComposableParts().ConfigureAwait(false);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -98,10 +95,25 @@ namespace MediaBrowser.Common.Kernel
|
||||||
/// Uses MEF to locate plugins
|
/// Uses MEF to locate plugins
|
||||||
/// Subclasses can use this to locate types within plugins
|
/// Subclasses can use this to locate types within plugins
|
||||||
/// </summary>
|
/// </summary>
|
||||||
protected void ReloadComposableParts()
|
protected virtual Task ReloadComposableParts()
|
||||||
{
|
{
|
||||||
DisposeComposableParts();
|
return Task.Run(() =>
|
||||||
|
{
|
||||||
|
DisposeComposableParts();
|
||||||
|
|
||||||
|
var container = GetCompositionContainer(includeCurrentAssembly: true);
|
||||||
|
|
||||||
|
container.ComposeParts(this);
|
||||||
|
|
||||||
|
OnComposablePartsLoaded();
|
||||||
|
|
||||||
|
container.Catalog.Dispose();
|
||||||
|
container.Dispose();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompositionContainer GetCompositionContainer(bool includeCurrentAssembly = false)
|
||||||
|
{
|
||||||
// Gets all plugin assemblies by first reading all bytes of the .dll and calling Assembly.Load against that
|
// Gets all plugin assemblies by first reading all bytes of the .dll and calling Assembly.Load against that
|
||||||
// This will prevent the .dll file from getting locked, and allow us to replace it when needed
|
// This will prevent the .dll file from getting locked, and allow us to replace it when needed
|
||||||
IEnumerable<Assembly> pluginAssemblies = Directory.GetFiles(ApplicationPaths.PluginsPath, "*.dll", SearchOption.TopDirectoryOnly).Select(f => Assembly.Load(File.ReadAllBytes((f))));
|
IEnumerable<Assembly> pluginAssemblies = Directory.GetFiles(ApplicationPaths.PluginsPath, "*.dll", SearchOption.TopDirectoryOnly).Select(f => Assembly.Load(File.ReadAllBytes((f))));
|
||||||
|
@ -112,17 +124,13 @@ namespace MediaBrowser.Common.Kernel
|
||||||
// Uncomment this if it's ever needed
|
// Uncomment this if it's ever needed
|
||||||
//catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
|
//catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
|
||||||
|
|
||||||
// Include composable parts in the subclass assembly
|
if (includeCurrentAssembly)
|
||||||
catalog.Catalogs.Add(new AssemblyCatalog(GetType().Assembly));
|
{
|
||||||
|
// Include composable parts in the subclass assembly
|
||||||
|
catalog.Catalogs.Add(new AssemblyCatalog(GetType().Assembly));
|
||||||
|
}
|
||||||
|
|
||||||
var container = new CompositionContainer(catalog);
|
return new CompositionContainer(catalog);
|
||||||
|
|
||||||
container.ComposeParts(this);
|
|
||||||
|
|
||||||
OnComposablePartsLoaded();
|
|
||||||
|
|
||||||
catalog.Dispose();
|
|
||||||
container.Dispose();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -65,6 +65,7 @@
|
||||||
<HintPath>..\packages\Rx-Linq.2.0.20823\lib\Net45\System.Reactive.Linq.dll</HintPath>
|
<HintPath>..\packages\Rx-Linq.2.0.20823\lib\Net45\System.Reactive.Linq.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="System.Runtime.Remoting" />
|
<Reference Include="System.Runtime.Remoting" />
|
||||||
|
<Reference Include="System.Runtime.Serialization" />
|
||||||
<Reference Include="System.Windows.Interactivity">
|
<Reference Include="System.Windows.Interactivity">
|
||||||
<HintPath>..\packages\MahApps.Metro.0.9.0.0\lib\net40\System.Windows.Interactivity.dll</HintPath>
|
<HintPath>..\packages\MahApps.Metro.0.9.0.0\lib\net40\System.Windows.Interactivity.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
|
|
@ -148,6 +148,12 @@ namespace MediaBrowser.Common.Net
|
||||||
return "application/x-mpegURL";
|
return "application/x-mpegURL";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Misc
|
||||||
|
else if (ext.EndsWith("dll", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
return "application/x-msdownload";
|
||||||
|
}
|
||||||
|
|
||||||
throw new InvalidOperationException("Argument not supported: " + path);
|
throw new InvalidOperationException("Argument not supported: " + path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -63,6 +63,28 @@ namespace MediaBrowser.Common.Plugins
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the name the assembly file
|
||||||
|
/// </summary>
|
||||||
|
public string AssemblyFileName
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return GetType().Assembly.GetName().Name + ".dll";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the path to the assembly file
|
||||||
|
/// </summary>
|
||||||
|
public string AssemblyFilePath
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return Path.Combine(Kernel.ApplicationPaths.PluginsPath, AssemblyFileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the current plugin configuration
|
/// Gets or sets the current plugin configuration
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -23,5 +23,11 @@ namespace MediaBrowser.Model.DTO
|
||||||
|
|
||||||
[ProtoMember(5)]
|
[ProtoMember(5)]
|
||||||
public string Version { get; set; }
|
public string Version { get; set; }
|
||||||
|
|
||||||
|
[ProtoMember(6)]
|
||||||
|
public string AssemblyFileName { get; set; }
|
||||||
|
|
||||||
|
[ProtoMember(7)]
|
||||||
|
public string ConfigurationFileName { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,5 +32,5 @@ using System.Runtime.InteropServices;
|
||||||
// You can specify all the values or you can default the Build and Revision Numbers
|
// You can specify all the values or you can default the Build and Revision Numbers
|
||||||
// by using the '*' as shown below:
|
// by using the '*' as shown below:
|
||||||
// [assembly: AssemblyVersion("1.0.*")]
|
// [assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyVersion("1.0.0.0")]
|
[assembly: AssemblyVersion("1.0.*")]
|
||||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user