xenadmin/XenAdmin/Plugins/PluginManager.cs

244 lines
8.3 KiB
C#
Raw Normal View History

/* Copyright (c) Citrix Systems, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms,
* with or without modification, are permitted provided
* that the following conditions are met:
*
* * Redistributions of source code must retain the above
* copyright notice, this list of conditions and the
* following disclaimer.
* * Redistributions in binary form must reproduce the above
* copyright notice, this list of conditions and the
* following disclaimer in the documentation and/or other
* materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
* CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Xml;
using XenAPI;
using XenCenterLib;
using XenAdmin.Core;
namespace XenAdmin.Plugins
{
public class PluginManager : IDisposable
{
private static readonly log4net.ILog log = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
private readonly List<PluginDescriptor> _plugins = new List<PluginDescriptor>();
private static readonly string PLUGIN_FOLDER = Path.Combine(Program.AssemblyDir, "Plugins");
private const string ROOT_ELEMENT_NAME = "XenCenterPlugin";
public event Action PluginsChanged;
/// <summary>
/// Gets the plugins loaded from the Plugin directory.
/// </summary>
/// <value>The plugins.</value>
public ReadOnlyCollection<PluginDescriptor> Plugins
{
get
{
return new ReadOnlyCollection<PluginDescriptor>(_plugins);
}
}
/// <summary>
/// Gets all features from all plugins of the specified type that match the specified predicate.
/// </summary>
/// <typeparam name="T">The type of the features required.</typeparam>
/// <param name="match">The predicate that the features must match.</param>
/// <returns>The features.</returns>
public IEnumerable<T> GetAllFeatures<T>(Predicate<T> match) where T: Feature
{
Util.ThrowIfParameterNull(match, "match");
foreach (PluginDescriptor plugin in Plugins)
{
foreach (Feature feature in plugin.Features)
{
T f = feature as T;
if (f != null && match(f))
{
yield return f;
}
}
}
}
/// <summary>
/// Gets a value indicating whether plugins functionality is enabled. This is driven by whether the Plugins folder exists.
/// </summary>
/// <value><c>true</c> if enabled; otherwise, <c>false</c>.</value>
public bool Enabled
{
get { return !Registry.DisablePlugins; }
}
/// <summary>
/// Gets a value indicating the number of plugins the user has enabled (ticked on the GUI)
/// </summary>
public int EnabledPluginsCount
{
get { return (from PluginDescriptor plugin in _plugins where plugin.Enabled select plugin).Count(); }
}
public void OnPluginsChanged()
{
if (PluginsChanged != null)
PluginsChanged();
}
/// <summary>
/// Loads the plugins from the default Plugins folder.
/// </summary>
public void LoadPlugins()
{
LoadPlugins(PLUGIN_FOLDER);
}
/// <summary>
/// Loads the plugins from the specified folder.
/// </summary>
/// <param name="folder">The folder.</param>
public void LoadPlugins(string folder)
{
if (Enabled)
{
// catch all exceptions, the most likely cause of errors is user mistakes with plugin creation.
// we must not let this kill XenCenter
try
{
//CA-71469: check whether the plugins folder exists
if (!Directory.Exists(folder))
{
log.InfoFormat("Plugin directory {0} was not found.", folder);
return;
}
// Look for plugins in {Application Working Dir}\Plugins
foreach (string vendor in Directory.GetDirectories(folder))
{
foreach (string pluginDir in Directory.GetDirectories(vendor))
{
try
{
string plugin = Path.GetFileName(pluginDir);
string org = Path.GetFileName(vendor);
ProcessPlugin(Path.Combine(pluginDir, string.Format("{0}.xcplugin.xml", plugin)), plugin, org);
}
catch (Exception e)
{
log.Error(string.Format("Failed to load plugin xml for file {0}.xcplugin.xml", Path.GetFileName(pluginDir)), e);
}
}
}
}
catch (Exception ex)
{
log.Error("Error loading plugins.", ex);
}
OnPluginsChanged();
}
}
private void ProcessPlugin(string file, string plugin, string org)
{
XmlDocument pluginXml = new XmlDocument();
pluginXml.XmlResolver = new BasicXMLResolver();
using (StreamReader sr = new StreamReader(file))
{
pluginXml.LoadXml(sr.ReadToEnd());
}
foreach (XmlNode node in pluginXml.GetElementsByTagName(ROOT_ELEMENT_NAME))
{
_plugins.Add(new PluginDescriptor(node, plugin, org));
}
}
private void ClearPlugins()
{
foreach (PluginDescriptor plugin in _plugins)
{
plugin.Dispose();
}
_plugins.Clear();
OnPluginsChanged();
}
public void ReloadPlugins()
{
ClearPlugins();
LoadPlugins();
}
public void DisposeURLs(IXenObject xenObject)
{
foreach (PluginDescriptor plugin in _plugins)
{
plugin.DisposeURLs(xenObject);
}
}
public void SetSelectedXenObject(IXenObject xenObject)
{
foreach (PluginDescriptor plugin in Plugins)
{
foreach (Feature feature in plugin.Features)
{
TabPageFeature tabPageFeature = feature as TabPageFeature;
if (tabPageFeature != null)
{
tabPageFeature.SelectedXenObject = xenObject;
}
}
}
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
ClearPlugins();
}
}
#region IDisposable Members
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
#endregion
}
}