From ca8d1d57e1bbf49cb52abe81b3a7246dacbe9b03 Mon Sep 17 00:00:00 2001 From: Charles Krinke Date: Fri, 27 Jun 2008 02:15:57 +0000 Subject: [PATCH] Mantis#1591. Thank you graciously, Sempuki for a patch that: Currently module loading is done ad-hoc. I propose creating a simple loader class that leverages Mono.Addins (and perhaps the new .NET addins when they become available in mono). Attached is a basic patch for review that compiles into HEAD, but doesn't yet replace any existing ad-hoc loaders. --- .../LoadRegions/LoadRegionsPlugin.cs | 17 ++- .../RemoteController/RemoteAdminPlugin.cs | 17 ++- OpenSim/ApplicationPlugins/Rest/RestPlugin.cs | 16 +++ OpenSim/Data/AssetDataBase.cs | 1 + OpenSim/Data/MSSQL/MSSQLAssetData.cs | 2 + OpenSim/Data/MySQL/MySQLAssetData.cs | 4 +- .../Data/NHibernate/NHibernateAssetData.cs | 8 +- OpenSim/Data/SQLite/SQLiteAssetData.cs | 2 + OpenSim/Framework/IAssetProvider.cs | 2 +- OpenSim/Framework/IPlugin.cs | 18 ++- OpenSim/Framework/PluginLoader.cs | 115 ++++++++++++++++++ .../Framework/Servers/OSHttpRequestPump.cs | 2 +- OpenSim/Grid/GridServer/GridServerBase.cs | 27 ++-- OpenSim/Grid/GridServer/IGridPlugin.cs | 3 +- .../Region/Application/IApplicationPlugin.cs | 4 +- OpenSim/Region/Application/OpenSimBase.cs | 41 +++---- .../3Di/LoadBalancer/LoadBalancerPlugin.cs | 14 ++- .../3Di/RegionProxy/RegionProxyPlugin.cs | 14 ++- prebuild.xml | 1 + 19 files changed, 244 insertions(+), 64 deletions(-) create mode 100644 OpenSim/Framework/PluginLoader.cs diff --git a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs index 4b11fd473f..6743fb4e95 100644 --- a/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs +++ b/OpenSim/ApplicationPlugins/LoadRegions/LoadRegionsPlugin.cs @@ -46,6 +46,19 @@ namespace OpenSim.ApplicationPlugins.LoadRegions #region IApplicationPlugin Members + // TODO: required by IPlugin, but likely not at all right + string m_name = "LoadRegionsPlugin"; + string m_version = "0.0"; + + public string Version { get { return m_version; } } + public string Name { get { return m_name; } } + + public void Initialise() + { + m_log.Info("[LOADREGIONS]: " + Name + " cannot be default-initialized!"); + throw new PluginNotInitialisedException (Name); + } + public void Initialise(OpenSimBase openSim) { m_log.Info("[LOADREGIONS]: Load Regions addin being initialised"); @@ -78,7 +91,7 @@ namespace OpenSim.ApplicationPlugins.LoadRegions openSim.ModuleLoader.ClearCache(); } - public void Close() + public void Dispose() { } @@ -113,4 +126,4 @@ namespace OpenSim.ApplicationPlugins.LoadRegions } } } -} \ No newline at end of file +} diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 50633757c0..d3fe0e0cdc 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -54,6 +54,19 @@ namespace OpenSim.ApplicationPlugins.RemoteController private BaseHttpServer m_httpd; private string requiredPassword = String.Empty; + // TODO: required by IPlugin, but likely not at all right + string m_name = "RemoteAdminPlugin"; + string m_version = "0.0"; + + public string Version { get { return m_version; } } + public string Name { get { return m_name; } } + + public void Initialise() + { + m_log.Info("[RADMIN]: " + Name + " cannot be default-initialized!"); + throw new PluginNotInitialisedException (Name); + } + public void Initialise(OpenSimBase openSim) { try @@ -607,8 +620,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController return response; } - public void Close() + public void Dispose() { } } -} \ No newline at end of file +} diff --git a/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs b/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs index 4558d4d415..78e0e6697e 100644 --- a/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs +++ b/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs @@ -188,6 +188,17 @@ namespace OpenSim.ApplicationPlugins.Rest #region methods + // TODO: required by IPlugin, but likely not at all right + string m_version = "0.0"; + + public string Version { get { return m_version; } } + + public void Initialise() + { + m_log.Info("[RESTPLUGIN]: " + Name + " cannot be default-initialized!"); + throw new PluginNotInitialisedException (Name); + } + /// /// This method is called by OpenSimMain immediately after loading the /// plugin and after basic server setup, but before running any server commands. @@ -357,6 +368,11 @@ namespace OpenSim.ApplicationPlugins.Rest _agents = null; } + public virtual void Dispose() + { + Close(); + } + /// /// Return a failure message. /// diff --git a/OpenSim/Data/AssetDataBase.cs b/OpenSim/Data/AssetDataBase.cs index e3b5c253bc..ca1de5a839 100644 --- a/OpenSim/Data/AssetDataBase.cs +++ b/OpenSim/Data/AssetDataBase.cs @@ -42,5 +42,6 @@ namespace OpenSim.Data public abstract string Name { get; } public abstract void Initialise(string connect); public abstract void Initialise(); + public abstract void Dispose(); } } diff --git a/OpenSim/Data/MSSQL/MSSQLAssetData.cs b/OpenSim/Data/MSSQL/MSSQLAssetData.cs index 50e2e3aa8d..44d78ed17c 100644 --- a/OpenSim/Data/MSSQL/MSSQLAssetData.cs +++ b/OpenSim/Data/MSSQL/MSSQLAssetData.cs @@ -218,6 +218,8 @@ namespace OpenSim.Data.MSSQL #region IPlugin Members + override public void Dispose() { } + /// /// Initialises asset interface /// diff --git a/OpenSim/Data/MySQL/MySQLAssetData.cs b/OpenSim/Data/MySQL/MySQLAssetData.cs index a64a2568a0..ac7fa1d177 100644 --- a/OpenSim/Data/MySQL/MySQLAssetData.cs +++ b/OpenSim/Data/MySQL/MySQLAssetData.cs @@ -39,7 +39,7 @@ namespace OpenSim.Data.MySQL /// /// A MySQL Interface for the Asset Server /// - internal class MySQLAssetData : AssetDataBase, IPlugin + internal class MySQLAssetData : AssetDataBase { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -109,6 +109,8 @@ namespace OpenSim.Data.MySQL } + override public void Dispose() { } + #region IAssetProvider Members /// diff --git a/OpenSim/Data/NHibernate/NHibernateAssetData.cs b/OpenSim/Data/NHibernate/NHibernateAssetData.cs index 89f907f5a0..a339ee3037 100644 --- a/OpenSim/Data/NHibernate/NHibernateAssetData.cs +++ b/OpenSim/Data/NHibernate/NHibernateAssetData.cs @@ -43,7 +43,7 @@ namespace OpenSim.Data.NHibernate /// /// A User storage interface for the DB4o database system /// - public class NHibernateAssetData : AssetDataBase, IDisposable + public class NHibernateAssetData : AssetDataBase { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -51,6 +51,8 @@ namespace OpenSim.Data.NHibernate private ISessionFactory factory; private ISession session; + override public void Dispose() { } + public override void Initialise() { Initialise("SQLiteDialect;SqliteClientDriver;URI=file:Asset.db,version=3"); @@ -173,9 +175,5 @@ namespace OpenSim.Data.NHibernate get { return "0.1"; } } - public void Dispose() - { - - } } } diff --git a/OpenSim/Data/SQLite/SQLiteAssetData.cs b/OpenSim/Data/SQLite/SQLiteAssetData.cs index f560b9e3d8..018501fe6a 100644 --- a/OpenSim/Data/SQLite/SQLiteAssetData.cs +++ b/OpenSim/Data/SQLite/SQLiteAssetData.cs @@ -56,6 +56,8 @@ namespace OpenSim.Data.SQLite private SqliteConnection m_conn; + override public void Dispose() { } + /// /// /// Initialises AssetData interface diff --git a/OpenSim/Framework/IAssetProvider.cs b/OpenSim/Framework/IAssetProvider.cs index 5c02ff138a..dcb79ea6f1 100644 --- a/OpenSim/Framework/IAssetProvider.cs +++ b/OpenSim/Framework/IAssetProvider.cs @@ -38,4 +38,4 @@ namespace OpenSim.Framework void CommitAssets(); // force a sync to the database void Initialise(string connect); } -} \ No newline at end of file +} diff --git a/OpenSim/Framework/IPlugin.cs b/OpenSim/Framework/IPlugin.cs index 8a0b2b1ab0..342918cec1 100644 --- a/OpenSim/Framework/IPlugin.cs +++ b/OpenSim/Framework/IPlugin.cs @@ -25,12 +25,24 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; + namespace OpenSim.Framework { + /// + /// Exception thrown if Initialise has been called, but failed. + /// + public class PluginNotInitialisedException : Exception + { + public PluginNotInitialisedException () : base() {} + public PluginNotInitialisedException (string msg) : base(msg) {} + public PluginNotInitialisedException (string msg, Exception e) : base(msg, e) {} + } + /// /// This interface, describes a generic plugin /// - public interface IPlugin + public interface IPlugin : System.IDisposable { /// /// Returns the plugin version @@ -45,8 +57,8 @@ namespace OpenSim.Framework string Name { get; } /// - /// Initialises the plugin (artificial constructor) + /// Default-initialises the plugin /// void Initialise(); } -} \ No newline at end of file +} diff --git a/OpenSim/Framework/PluginLoader.cs b/OpenSim/Framework/PluginLoader.cs new file mode 100644 index 0000000000..26df3d1810 --- /dev/null +++ b/OpenSim/Framework/PluginLoader.cs @@ -0,0 +1,115 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * 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. + * * Neither the name of the OpenSim Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``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 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.IO; +using System.Collections.Generic; +using System.Reflection; +using log4net; +using Mono.Addins; + +namespace OpenSim.Framework +{ + public class PluginLoader : IDisposable where T : IPlugin + { + private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private List loaded = new List(); + + public PluginLoader (string dir) + { + AddPluginDir (dir); + } + + public void AddPluginDir (string dir) + { + suppress_console_output_ (true); + AddinManager.Initialize (dir); + suppress_console_output_ (false); + } + + public delegate void Initialiser (IPlugin p); + private void default_initialiser_ (IPlugin p) { p.Initialise(); } + + public void Load (string extpoint) + { + Load (extpoint, default_initialiser_); + } + + public void Load (string extpoint, Initialiser initialize) + { + AddinManager.Registry.Update (null); + + ExtensionNodeList ns = AddinManager.GetExtensionNodes(extpoint); + foreach (TypeExtensionNode n in ns) + { + T p = (T) n.CreateInstance(); + initialize (p); + Plugins.Add (p); + + log.Info("[PLUGINS]: Loading plugin " + n.Path + "/" + p.Name); + } + } + + public List Plugins + { + get { return loaded; } + } + + public void Dispose () + { + foreach (T p in Plugins) + p.Dispose (); + } + + public void ClearCache() + { + // The Mono addin manager (in Mono.Addins.dll version 0.2.0.0) occasionally seems to corrupt its addin cache + // Hence, as a temporary solution we'll remove it before each startup + if (Directory.Exists("addin-db-000")) + Directory.Delete("addin-db-000", true); + + if (Directory.Exists("addin-db-001")) + Directory.Delete("addin-db-001", true); + } + + private static TextWriter prev_console_; + public void suppress_console_output_ (bool save) + { + if (save) + { + prev_console_ = System.Console.Out; + System.Console.SetOut(new StreamWriter(Stream.Null)); + } + else + { + if (prev_console_ != null) + System.Console.SetOut(prev_console_); + } + } + + } +} diff --git a/OpenSim/Framework/Servers/OSHttpRequestPump.cs b/OpenSim/Framework/Servers/OSHttpRequestPump.cs index 06e41e468c..6214ab0502 100644 --- a/OpenSim/Framework/Servers/OSHttpRequestPump.cs +++ b/OpenSim/Framework/Servers/OSHttpRequestPump.cs @@ -58,4 +58,4 @@ namespace OpenSim.Framework.Servers return pumps; } } -} \ No newline at end of file +} diff --git a/OpenSim/Grid/GridServer/GridServerBase.cs b/OpenSim/Grid/GridServer/GridServerBase.cs index 7891c29cae..010c250286 100644 --- a/OpenSim/Grid/GridServer/GridServerBase.cs +++ b/OpenSim/Grid/GridServer/GridServerBase.cs @@ -116,26 +116,17 @@ namespace OpenSim.Grid.GridServer m_httpServer.AddStreamHandler(new RestStreamHandler("POST", "/regions/", m_gridManager.RestSetRegionMethod)); } + protected void grid_plugin_initialiser_ (IPlugin plugin) + { + IGridPlugin p = plugin as IGridPlugin; + p.Initialise (this); + } + protected void LoadGridPlugins() { - // Temporary hack to stop mono-addins scanning warnings from coming out on the console - TextWriter oldOutput = Console.Out; - Console.SetOut(new StreamWriter(Stream.Null)); - - AddinManager.Initialize("."); - AddinManager.Registry.Update(null); - - // Returns the console.writelines back to the console's stream - Console.SetOut(oldOutput); - - ExtensionNodeList nodes = AddinManager.GetExtensionNodes("/OpenSim/GridServer"); - foreach (TypeExtensionNode node in nodes) - { - m_log.Info("[GRID PLUGINS]: Loading OpenSim plugin " + node.Path); - IGridPlugin plugin = (IGridPlugin)node.CreateInstance(); - plugin.Initialise(this); - m_plugins.Add(plugin); - } + PluginLoader loader = new PluginLoader ("."); + loader.Load ("/OpenSim/GridServer", grid_plugin_initialiser_); + m_plugins = loader.Plugins; } protected virtual void SetupGridManager() diff --git a/OpenSim/Grid/GridServer/IGridPlugin.cs b/OpenSim/Grid/GridServer/IGridPlugin.cs index 47273a2dfe..d51deb3fc6 100644 --- a/OpenSim/Grid/GridServer/IGridPlugin.cs +++ b/OpenSim/Grid/GridServer/IGridPlugin.cs @@ -27,13 +27,14 @@ */ using Mono.Addins; +using OpenSim.Framework; [assembly : AddinRoot("OpenSim", "0.5")] namespace OpenSim.Grid.GridServer { [TypeExtensionPoint("/OpenSim/GridServer")] - public interface IGridPlugin + public interface IGridPlugin : IPlugin { void Initialise(GridServerBase gridServer); void Close(); diff --git a/OpenSim/Region/Application/IApplicationPlugin.cs b/OpenSim/Region/Application/IApplicationPlugin.cs index 7ca4383b9a..e1187ae2dc 100644 --- a/OpenSim/Region/Application/IApplicationPlugin.cs +++ b/OpenSim/Region/Application/IApplicationPlugin.cs @@ -26,15 +26,15 @@ */ using Mono.Addins; +using OpenSim.Framework; [assembly : AddinRoot("OpenSim", "0.5")] namespace OpenSim { [TypeExtensionPoint("/OpenSim/Startup")] - public interface IApplicationPlugin + public interface IApplicationPlugin : IPlugin { void Initialise(OpenSimBase openSim); - void Close(); } } diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 49e1da32cb..d0d5378c1b 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -149,24 +149,6 @@ namespace OpenSim { IConfig startupConfig = configSource.Configs["Startup"]; - // The Mono addin manager (in Mono.Addins.dll version 0.2.0.0) occasionally seems to corrupt its addin cache - // Hence, as a temporary solution we'll remove it before each startup - if (Directory.Exists("addin-db-000")) - Directory.Delete("addin-db-000", true); - - if (Directory.Exists("addin-db-001")) - Directory.Delete("addin-db-001", true); - - // This blocks the scanning warnings from outputing to the console. - TextWriter oldOutput = Console.Out; - Console.SetOut(new StreamWriter(Stream.Null)); - - AddinManager.Initialize("."); - AddinManager.Registry.Update(null); - - // Returns the console.writelines back to the console's stream - Console.SetOut(oldOutput); - Application.iniFilePath = startupConfig.GetString("inifile", "OpenSim.ini"); m_config = new OpenSimConfigSource(); @@ -347,6 +329,19 @@ namespace OpenSim m_networkServersInfo.loadFromConfiguration(m_config.Source); } + protected void plugin_initialiser_ (IPlugin plugin) + { + IApplicationPlugin p = plugin as IApplicationPlugin; + p.Initialise (this); + } + + protected void LoadPlugins() + { + PluginLoader loader = new PluginLoader ("."); + loader.Load ("/OpenSim/Startup", plugin_initialiser_); + m_plugins = loader.Plugins; + } + /// /// Performs initialisation of the scene, such as loading configuration from disk. /// @@ -403,14 +398,7 @@ namespace OpenSim // Create a ModuleLoader instance m_moduleLoader = new ModuleLoader(m_config.Source); - ExtensionNodeList nodes = AddinManager.GetExtensionNodes("/OpenSim/Startup"); - foreach (TypeExtensionNode node in nodes) - { - m_log.InfoFormat("[PLUGINS]: Loading OpenSim application plugin {0}", node.Path); - IApplicationPlugin plugin = (IApplicationPlugin)node.CreateInstance(); - plugin.Initialise(this); - m_plugins.Add(plugin); - } + LoadPlugins(); } protected override void Initialize() @@ -740,3 +728,4 @@ namespace OpenSim } } + diff --git a/ThirdParty/3Di/LoadBalancer/LoadBalancerPlugin.cs b/ThirdParty/3Di/LoadBalancer/LoadBalancerPlugin.cs index 2aa2398c57..625e3c5733 100644 --- a/ThirdParty/3Di/LoadBalancer/LoadBalancerPlugin.cs +++ b/ThirdParty/3Di/LoadBalancer/LoadBalancerPlugin.cs @@ -74,6 +74,18 @@ namespace OpenSim.ApplicationPlugins.LoadBalancer private List m_clientServers; #region IApplicationPlugin Members + // TODO: required by IPlugin, but likely not at all right + string m_name = "LoadBalancerPlugin"; + string m_version = "0.0"; + + public string Version { get { return m_version; } } + public string Name { get { return m_name; } } + + public void Initialise() + { + m_log.Info("[BALANCER]: " + Name + " cannot be default-initialized!"); + throw new PluginNotInitialisedException (Name); + } public void Initialise(OpenSimBase openSim) { @@ -109,7 +121,7 @@ namespace OpenSim.ApplicationPlugins.LoadBalancer m_log.Info("[BALANCER] " + "Exiting Initialize()"); } - public void Close() + public void Dispose() { } diff --git a/ThirdParty/3Di/RegionProxy/RegionProxyPlugin.cs b/ThirdParty/3Di/RegionProxy/RegionProxyPlugin.cs index 9bb883ecd5..a3108f69f1 100644 --- a/ThirdParty/3Di/RegionProxy/RegionProxyPlugin.cs +++ b/ThirdParty/3Di/RegionProxy/RegionProxyPlugin.cs @@ -68,6 +68,18 @@ namespace OpenSim.ApplicationPlugins.RegionProxy private ProxyServer proxy; #region IApplicationPlugin Members + // TODO: required by IPlugin, but likely not at all right + string m_name = "RegionProxyPlugin"; + string m_version = "0.0"; + + public string Version { get { return m_version; } } + public string Name { get { return m_name; } } + + public void Initialise() + { + m_log.Info("[PROXY]: " + Name + " cannot be default-initialized!"); + throw new PluginNotInitialisedException (Name); + } public void Initialise(OpenSimBase openSim) { @@ -89,7 +101,7 @@ namespace OpenSim.ApplicationPlugins.RegionProxy proxy = new ProxyServer(m_log); } - public void Close() + public void Dispose() { } diff --git a/prebuild.xml b/prebuild.xml index 2c2dc01512..fdc9eeec3e 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -95,6 +95,7 @@ +