Update: Plugin Framework Install & UI

This commit is contained in:
Gary Sharp
2013-02-12 17:27:54 +11:00
parent b24253fd64
commit 734b02fa1d
35 changed files with 2792 additions and 1888 deletions
+110 -4
View File
@@ -7,6 +7,9 @@ using System.Text;
using System.Threading.Tasks;
using Disco.Data.Repository;
using System.IO.Compression;
using Disco.Models.BI.Interop.Community;
using System.Web;
using Newtonsoft.Json;
namespace Disco.Services.Plugins
{
@@ -42,6 +45,15 @@ namespace Disco.Services.Plugins
}
}
public static bool PluginInstalled(string PluginId)
{
if (_PluginManifests == null)
throw new InvalidOperationException("Plugins have not been initialized");
PluginManifest manifest;
return _PluginManifests.TryGetValue(PluginId, out manifest);
}
public static PluginManifest GetPlugin(string PluginId, Type ContainsCategoryType)
{
if (_PluginManifests == null)
@@ -145,6 +157,81 @@ namespace Disco.Services.Plugins
throw new InvalidOperationException(string.Format("Unknown Plugin Feature Category Type: [{0}]", FeatureCategoryType.Name));
}
public static string CatalogueFile(DiscoDataContext dbContext)
{
return Path.Combine(dbContext.DiscoConfiguration.PluginPackagesLocation, "Catalogue.json");
}
public static string CompatibilityFile(DiscoDataContext dbContext)
{
return Path.Combine(dbContext.DiscoConfiguration.PluginPackagesLocation, "Compatibility.json");
}
public static PluginLibraryUpdateResponse LoadCatalogue(DiscoDataContext dbContext)
{
var catalogueFile = CatalogueFile(dbContext);
if (!File.Exists(catalogueFile))
return null;
return JsonConvert.DeserializeObject<PluginLibraryUpdateResponse>(File.ReadAllText(catalogueFile));
}
public static PluginLibraryCompatibilityResponse LoadCompatibilityData(DiscoDataContext dbContext)
{
var pluginAssembly = typeof(Plugins).Assembly;
Version hostVersion = pluginAssembly.GetName().Version;
PluginLibraryCompatibilityResponse Data = null;
var localCompatFile = Path.Combine(Path.GetDirectoryName(pluginAssembly.Location), "ReleasePluginCompatibility.json");
var serverCompatFile = CompatibilityFile(dbContext);
if (File.Exists(localCompatFile))
{
Data = JsonConvert.DeserializeObject<PluginLibraryCompatibilityResponse>(File.ReadAllText(localCompatFile));
Data.HostVersion = hostVersion.ToString(4);
}
if (File.Exists(serverCompatFile))
{
var serverData = JsonConvert.DeserializeObject<PluginLibraryCompatibilityResponse>(File.ReadAllText(serverCompatFile));
if (Version.Parse(serverData.HostVersion) == hostVersion)
{
if (Data == null)
{
// No Local Compatibility File
Data = serverData;
}
else
{
// Join Compatibility Files
var localItems = Data.Plugins;
var localItemVersions = localItems.ToDictionary(i => i, i => Version.Parse(i.Version));
var joinedItems = localItems.ToList();
Data.ResponseTimestamp = serverData.ResponseTimestamp;
foreach (var serverItem in serverData.Plugins)
{
var serverItemVersion = Version.Parse(serverItem.Version);
var localItem = localItems.FirstOrDefault(i => i.Id.Equals(serverItem.Id, StringComparison.InvariantCultureIgnoreCase) && serverItemVersion == localItemVersions[i]);
if (localItem != null)
joinedItems.Remove(localItem);
joinedItems.Add(serverItem);
}
Data.Plugins = joinedItems;
}
}
}
if (Data == null)
{
Data = new PluginLibraryCompatibilityResponse()
{
HostVersion = hostVersion.ToString(4),
Plugins = new List<PluginLibraryCompatibilityItem>(),
ResponseTimestamp = new DateTime(2011, 7, 1)
};
}
return Data;
}
public static void InitalizePlugins(DiscoDataContext dbContext)
{
if (_PluginManifests == null)
@@ -153,6 +240,8 @@ namespace Disco.Services.Plugins
{
if (_PluginManifests == null)
{
Version hostVersion = typeof(Plugins).Assembly.GetName().Version;
var compatibilityData = new Lazy<PluginLibraryCompatibilityResponse>(() => LoadCompatibilityData(dbContext));
Dictionary<string, PluginManifest> loadedPlugins = new Dictionary<string, PluginManifest>();
PluginPath = dbContext.DiscoConfiguration.PluginsLocation;
@@ -185,11 +274,21 @@ namespace Disco.Services.Plugins
if (File.Exists(updatePackagePath))
{
// Update Plugin
pluginManifest = UpdatePlugin(dbContext, pluginManifest, updatePackagePath);
pluginManifest = UpdatePlugin(dbContext, pluginManifest, updatePackagePath, compatibilityData.Value);
}
if (pluginManifest != null)
{
// Check Version Compatibility
var pluginCompatibility = compatibilityData.Value.Plugins.FirstOrDefault(i => i.Id.Equals(pluginManifest.Id, StringComparison.InvariantCultureIgnoreCase) && pluginManifest.Version == Version.Parse(i.Version));
if (pluginCompatibility != null && !pluginCompatibility.Compatible)
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", pluginManifest.Id, pluginManifest.VersionFormatted, pluginCompatibility.Reason));
if (pluginManifest.HostVersionMin != null && pluginManifest.HostVersionMin > hostVersion)
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] does not support this version of Disco (Requires v{2} or greater)", pluginManifest.Id, pluginManifest.VersionFormatted, pluginManifest.HostVersionMin.ToString()));
if (pluginManifest.HostVersionMax != null && pluginManifest.HostVersionMax < hostVersion)
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] does not support this version of Disco (Support expired as of v{2})", pluginManifest.Id, pluginManifest.VersionFormatted, pluginManifest.HostVersionMax.ToString()));
pluginManifest.InitializePlugin(dbContext);
loadedPlugins[pluginManifest.Id] = pluginManifest;
}
@@ -251,13 +350,13 @@ namespace Disco.Services.Plugins
_PluginAssemblyManifests = _PluginManifests.Values.ToDictionary(p => p.PluginAssembly, p => p);
}
public static PluginManifest UpdatePlugin(DiscoDataContext dbContext, PluginManifest ExistingManifest, String UpdatePluginPackageFilePath)
public static PluginManifest UpdatePlugin(DiscoDataContext dbContext, PluginManifest ExistingManifest, String UpdatePluginPackageFilePath, PluginLibraryCompatibilityResponse CompatibilityData = null)
{
PluginManifest updatedManifest;
using (var packageStream = File.OpenRead(UpdatePluginPackageFilePath))
{
updatedManifest = UpdatePlugin(dbContext, ExistingManifest, packageStream);
updatedManifest = UpdatePlugin(dbContext, ExistingManifest, packageStream, CompatibilityData);
}
// Remove Update after processing
@@ -266,7 +365,7 @@ namespace Disco.Services.Plugins
return updatedManifest;
}
public static PluginManifest UpdatePlugin(DiscoDataContext dbContext, PluginManifest ExistingManifest, Stream UpdatePluginPackage)
public static PluginManifest UpdatePlugin(DiscoDataContext dbContext, PluginManifest ExistingManifest, Stream UpdatePluginPackage, PluginLibraryCompatibilityResponse CompatibilityData = null)
{
using (MemoryStream packageStream = new MemoryStream())
{
@@ -301,6 +400,13 @@ namespace Disco.Services.Plugins
throw new InvalidDataException("A newer version of this plugin is already installed");
}
// Check Compatibility
if (CompatibilityData == null)
CompatibilityData = LoadCompatibilityData(dbContext);
var pluginCompatibility = CompatibilityData.Plugins.FirstOrDefault(i => i.Id.Equals(packageManifest.Id, StringComparison.InvariantCultureIgnoreCase) && packageManifest.Version == Version.Parse(i.Version));
if (pluginCompatibility != null && !pluginCompatibility.Compatible)
throw new InvalidOperationException(string.Format("The plugin [{0} v{1}] is not compatible: {2}", packageManifest.Id, packageManifest.VersionFormatted, pluginCompatibility.Reason));
string packagePath = Path.Combine(dbContext.DiscoConfiguration.PluginsLocation, packageManifest.Id);
// Force Delete of Existing Folder