diff --git a/.travis.yml b/.travis.yml index 6e9dfbbbe..bd005d5de 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ install: - sudo apt-get build-dep smuxi > /dev/null - sudo apt-get install devscripts equivs > /dev/null - sudo mk-build-deps --install debian/control > /dev/null - - sudo apt-get install mono-devel nunit-console moreutils gtk-sharp2-gapi libgtkspell-dev > /dev/null + - sudo apt-get install mono-devel nunit-console moreutils gtk-sharp2-gapi libgtkspell-dev libmono-addins-cil-dev > /dev/null - sudo apt-get install libnunit-cil-dev > /dev/null script: diff --git a/configure.ac b/configure.ac index c8b60427c..711fbc55f 100644 --- a/configure.ac +++ b/configure.ac @@ -242,11 +242,15 @@ fi AC_SUBST(XBUILD_FLAGS) # Required Libraries - if test "x$(uname)" != "xDarwin"; then + PKG_CHECK_MODULES(MONO_ADDINS, mono-addins >= 1.0) + AC_SUBST(MONO_ADDINS_LIBS) + AM_CONDITIONAL([BUNDLE_MONO_ADDINS], false) + PKG_CHECK_MODULES([LOG4NET], [log4net]) AM_CONDITIONAL([BUNDLE_LOG4NET], false) else + AM_CONDITIONAL([BUNDLE_MONO_ADDINS], true) AM_CONDITIONAL([BUNDLE_LOG4NET], true) fi diff --git a/lib/Mono.Addins.dll b/lib/Mono.Addins.dll new file mode 100644 index 000000000..07eeda1ef Binary files /dev/null and b/lib/Mono.Addins.dll differ diff --git a/src/Engine-Campfire/Engine-Campfire.addin.xml b/src/Engine-Campfire/Engine-Campfire.addin.xml new file mode 100644 index 000000000..4dc6f952a --- /dev/null +++ b/src/Engine-Campfire/Engine-Campfire.addin.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/src/Engine-Campfire/Engine-Campfire.csproj b/src/Engine-Campfire/Engine-Campfire.csproj index 4311eb553..cfcff9d22 100644 --- a/src/Engine-Campfire/Engine-Campfire.csproj +++ b/src/Engine-Campfire/Engine-Campfire.csproj @@ -69,4 +69,9 @@ ServiceStack.Interfaces + + + Enging-Campfire.addin.xml + + \ No newline at end of file diff --git a/src/Engine-Campfire/Makefile.am b/src/Engine-Campfire/Makefile.am index 7c89dfd14..cebdb3b77 100644 --- a/src/Engine-Campfire/Makefile.am +++ b/src/Engine-Campfire/Makefile.am @@ -11,6 +11,9 @@ SOURCES = \ Protocols/Campfire/CampfireEventStream.cs \ Protocols/Campfire/DTO.cs +RESOURCES = \ + Engine-Campfire.addin.xml + REFERENCES = \ System \ System.Web \ @@ -36,5 +39,5 @@ include $(top_srcdir)/Makefile.include all: $(ASSEMBLY_TARGET) -$(ASSEMBLY_TARGET) $(ASSEMBLY_TARGET).mdb: $(SOURCES) $(DLL_REFERENCES) - $(CSC) $(CSC_FLAGS) $(build_references_ref) -target:library -out:$(ASSEMBLY_TARGET) $(SOURCES_BUILD) +$(ASSEMBLY_TARGET) $(ASSEMBLY_TARGET).mdb: $(SOURCES) $(DLL_REFERENCES) $(build_resources) + $(CSC) $(CSC_FLAGS) $(build_references_ref) -target:library -out:$(ASSEMBLY_TARGET) $(SOURCES_BUILD) $(build_resources_embed) diff --git a/src/Engine-IRC/Engine-IRC.addin.xml b/src/Engine-IRC/Engine-IRC.addin.xml new file mode 100644 index 000000000..9253c2670 --- /dev/null +++ b/src/Engine-IRC/Engine-IRC.addin.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/src/Engine-IRC/Engine-IRC.csproj b/src/Engine-IRC/Engine-IRC.csproj index fba339f53..675ed2432 100644 --- a/src/Engine-IRC/Engine-IRC.csproj +++ b/src/Engine-IRC/Engine-IRC.csproj @@ -79,4 +79,9 @@ + + + Engine-IRC.addin.xml + + \ No newline at end of file diff --git a/src/Engine-IRC/Makefile.am b/src/Engine-IRC/Makefile.am index b4fbc3cad..ae6dc0f24 100644 --- a/src/Engine-IRC/Makefile.am +++ b/src/Engine-IRC/Makefile.am @@ -76,7 +76,8 @@ FILES = \ DATA_FILES = -RESOURCES = +RESOURCES = \ + Engine-IRC.addin.xml EXTRAS = \ smuxi-engine-irc.pc.in diff --git a/src/Engine-JabbR/Engine-JabbR.addin.xml b/src/Engine-JabbR/Engine-JabbR.addin.xml new file mode 100644 index 000000000..e094fb9ce --- /dev/null +++ b/src/Engine-JabbR/Engine-JabbR.addin.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/src/Engine-JabbR/Engine-JabbR.csproj b/src/Engine-JabbR/Engine-JabbR.csproj index 9129518ea..2b381bf35 100644 --- a/src/Engine-JabbR/Engine-JabbR.csproj +++ b/src/Engine-JabbR/Engine-JabbR.csproj @@ -63,4 +63,9 @@ + + + Engine-JabbR.addin.xml + + \ No newline at end of file diff --git a/src/Engine-JabbR/Makefile.am b/src/Engine-JabbR/Makefile.am index 7fd4b4381..b76c43616 100644 --- a/src/Engine-JabbR/Makefile.am +++ b/src/Engine-JabbR/Makefile.am @@ -16,6 +16,9 @@ SOURCES = \ JabbrMessageBuilder.cs \ JabbrProtocolManager.cs +RESOURCES = \ + Engine-JabbR.addin.xml + REFERENCES = \ System \ System.Web \ @@ -40,5 +43,5 @@ include $(top_srcdir)/Makefile.include all: $(ASSEMBLY_TARGET) -$(ASSEMBLY_TARGET) $(ASSEMBLY_TARGET).mdb: $(SOURCES) $(DLL_REFERENCES) - $(CSC) $(CSC_FLAGS) $(build_references_ref) -target:library -out:$(ASSEMBLY_TARGET) $(SOURCES_BUILD) +$(ASSEMBLY_TARGET) $(ASSEMBLY_TARGET).mdb: $(SOURCES) $(DLL_REFERENCES) $(build_resources) + $(CSC) $(CSC_FLAGS) $(build_references_ref) -target:library -out:$(ASSEMBLY_TARGET) $(SOURCES_BUILD) $(build_resources_embed) diff --git a/src/Engine-Twitter/Engine-Twitter.addin.xml b/src/Engine-Twitter/Engine-Twitter.addin.xml new file mode 100644 index 000000000..4942b9e8e --- /dev/null +++ b/src/Engine-Twitter/Engine-Twitter.addin.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + diff --git a/src/Engine-Twitter/Engine-Twitter.csproj b/src/Engine-Twitter/Engine-Twitter.csproj index b1266fdf1..59b776950 100644 --- a/src/Engine-Twitter/Engine-Twitter.csproj +++ b/src/Engine-Twitter/Engine-Twitter.csproj @@ -69,4 +69,9 @@ + + + Engine-Twitter.addin.xml + + \ No newline at end of file diff --git a/src/Engine-Twitter/Makefile.am b/src/Engine-Twitter/Makefile.am index 37a0231fa..f06f91e13 100644 --- a/src/Engine-Twitter/Makefile.am +++ b/src/Engine-Twitter/Makefile.am @@ -18,6 +18,9 @@ SOURCES = \ Protocols/Twitter/TwitterMessageBuilder.cs \ Protocols/Twitter/TwitterSearchStream.cs +RESOURCES = \ + Engine-Twitter.addin.xml + REFERENCES = $(LOG4NET_REF_LIBS) \ $(SMARTIRC4NET_LIBS) \ System.Web \ @@ -44,5 +47,5 @@ include $(top_srcdir)/Makefile.include all: $(ASSEMBLY_TARGET) -$(ASSEMBLY_TARGET): $(SOURCES) $(DLL_REFERENCES) - $(MCS) $(CSC_FLAGS) $(build_references_ref) -target:library -out:$(ASSEMBLY_TARGET) $(SOURCES_BUILD) +$(ASSEMBLY_TARGET): $(SOURCES) $(DLL_REFERENCES) $(build_resources) + $(MCS) $(CSC_FLAGS) $(build_references_ref) -target:library -out:$(ASSEMBLY_TARGET) $(SOURCES_BUILD) $(build_resources_embed) diff --git a/src/Engine-XMPP/Engine-XMPP.addin.xml b/src/Engine-XMPP/Engine-XMPP.addin.xml new file mode 100644 index 000000000..4cbd51819 --- /dev/null +++ b/src/Engine-XMPP/Engine-XMPP.addin.xml @@ -0,0 +1,23 @@ + + + + + + + + + + + + + diff --git a/src/Engine-XMPP/Engine-XMPP.csproj b/src/Engine-XMPP/Engine-XMPP.csproj index 0e8121077..7ce13f4cb 100644 --- a/src/Engine-XMPP/Engine-XMPP.csproj +++ b/src/Engine-XMPP/Engine-XMPP.csproj @@ -74,4 +74,9 @@ + + + Engine-XMPP.addin.xml + + diff --git a/src/Engine-XMPP/Makefile.am b/src/Engine-XMPP/Makefile.am index 3eb062c8d..43770252c 100644 --- a/src/Engine-XMPP/Makefile.am +++ b/src/Engine-XMPP/Makefile.am @@ -18,6 +18,9 @@ SOURCES = \ Protocols/Xmpp/XmppProtocolManager.cs \ Config/XmppPersonModel.cs +RESOURCES = \ + Engine-XMPP.addin.xml + REFERENCES = \ System \ System.Core \ @@ -42,5 +45,6 @@ include $(top_srcdir)/Makefile.include all: $(ASSEMBLY_TARGET) -$(ASSEMBLY_TARGET) $(ASSEMBLY_TARGET).mdb: $(SOURCES) $(DLL_REFERENCES) - $(CSC) $(CSC_FLAGS) $(build_references_ref) -target:library -out:$(ASSEMBLY_TARGET) $(SOURCES_BUILD) +$(ASSEMBLY_TARGET) $(ASSEMBLY_TARGET).mdb: $(SOURCES) $(DLL_REFERENCES) $(build_resources) + $(CSC) $(CSC_FLAGS) $(build_references_ref) -target:library -out:$(ASSEMBLY_TARGET) $(SOURCES_BUILD) $(build_resources_embed) + diff --git a/src/Engine/AddinHost.cs b/src/Engine/AddinHost.cs new file mode 100644 index 000000000..405112cf0 --- /dev/null +++ b/src/Engine/AddinHost.cs @@ -0,0 +1,25 @@ +// Smuxi - Smart MUltipleXed Irc +// +// Copyright (c) 2016 Andrés G. Aragoneses +// +// Full GPL License: +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +using Mono.Addins; + +[assembly:AddinRoot("smuxi-engine", "1.1")] +[assembly:AddinDescription("This add-in root provides the engine extension point for add-in protocols to hook")] +[assembly:ExtensionPoint("/Smuxi/Server/Engine", NodeName="Engine")] diff --git a/src/Engine/Engine.csproj b/src/Engine/Engine.csproj index 717332e9a..2cbe7fe67 100644 --- a/src/Engine/Engine.csproj +++ b/src/Engine/Engine.csproj @@ -44,6 +44,7 @@ + @@ -150,6 +151,9 @@ + + mono-addins + diff --git a/src/Engine/Makefile.am b/src/Engine/Makefile.am index 2972c4406..6c670c79c 100644 --- a/src/Engine/Makefile.am +++ b/src/Engine/Makefile.am @@ -33,6 +33,13 @@ SMUXI_COMMON_DLL_SOURCE=../../bin/debug/smuxi-common.dll endif +if BUNDLE_MONO_ADDINS +MONO_ADDINS_DLL_SOURCE=../../lib/Mono.Addins.dll +MONO_ADDINS_REF_LIBS=-r:$(MONO_ADDINS_DLL_SOURCE) +else +MONO_ADDINS_REF_LIBS=$(MONO_ADDINS_LIBS) +endif + if BUNDLE_LOG4NET LOG4NET_DLL_SOURCE=../../lib/log4net.dll LOG4NET_REF_LIBS=-r:$(LOG4NET_DLL_SOURCE) @@ -61,6 +68,7 @@ all: $(ASSEMBLY) $(PROGRAMFILES) $(LINUX_PKGCONFIG) FILES = \ ../AssemblyVersion.cs \ AssemblyInfo.cs \ + AddinHost.cs \ CertificateValidator.cs \ CommandModel.cs \ Engine.cs \ @@ -146,6 +154,7 @@ REFERENCES = \ System.Xml \ Mono.Posix \ Mono.Data.Sqlite \ + $(MONO_ADDINS_REF_LIBS) \ $(NINI_REF_LIBS) \ $(LOG4NET_REF_LIBS) \ $(DB4O_LIBS) \ diff --git a/src/Engine/Protocols/ProtocolManagerFactory.cs b/src/Engine/Protocols/ProtocolManagerFactory.cs index c0140ea0e..cda82e71e 100644 --- a/src/Engine/Protocols/ProtocolManagerFactory.cs +++ b/src/Engine/Protocols/ProtocolManagerFactory.cs @@ -8,6 +8,7 @@ * Smuxi - Smart MUltipleXed Irc * * Copyright (c) 2005-2006 Mirco Bauer + * Copyright (c) 2016 Andrés G. Aragoneses * * Full GPL License: * @@ -30,6 +31,9 @@ using System.IO; using System.Reflection; using System.Collections.Generic; + +using Mono.Addins; + using Smuxi.Common; namespace Smuxi.Engine @@ -50,80 +54,41 @@ public IList ProtocolManagerInfos { public ProtocolManagerFactory() { } - - public void LoadProtocolManager(string filename) + + public void LoadAllProtocolManagers(string path) { - Trace.Call(filename); - - Assembly asm = Assembly.LoadFile(filename); - Type[] types; - try { - types = asm.GetTypes(); - } catch (ReflectionTypeLoadException ex) { -#if LOG4NET - _Logger.WarnFormat( - "LoadProtocolManager(): GetTypes() on {0} threw exceptions", - filename - ); - foreach (var loaderEx in ex.LoaderExceptions) { - _Logger.Warn( - "LoadProtocolManager(): LoaderException: ", - loaderEx - ); - _Logger.Warn( - "LoadProtocolManager(): LoaderException.InnerException: ", - loaderEx.InnerException - ); - } -#endif - types = ex.Types; - } - - foreach (Type type in types) { - if (type.IsAbstract) { - continue; - } - - Type foundType = null; - Type[] interfaceTypes = type.GetInterfaces(); - foreach (Type interfaceType in interfaceTypes) { - if (interfaceType == typeof(IProtocolManager)) { + Trace.Call(path); + + AddinManager.AddinLoadError += (o, a) => { + //try { + // AddinManager.Registry.DisableAddin (a.AddinId); + //} catch {} + throw new Exception(a.Message, a.Exception); + }; + + AddinManager.Initialize(path); + + var engineAddinNodes = AddinManager.GetExtensionNodes("/Smuxi/Server/Engine"); + + foreach(TypeExtensionNode protocolManagerNode in engineAddinNodes) { + Type foundType = protocolManagerNode.Type; #if LOG4NET - _Logger.Debug("LoadProtocolManager(): found " + type); + _Logger.Debug("LoadAllProtocolManagers(): found " + foundType); #endif - foundType = type; - break; - } - } - - if (foundType == null) { - continue; - } - // let's get the info attribute object[] attrs = foundType.GetCustomAttributes(typeof(ProtocolManagerInfoAttribute), true); if (attrs == null || attrs.Length == 0) { throw new ArgumentException("Assembly contains IProtocolManager but misses ProtocolManagerInfoAttribute", "filename"); //continue; } - + ProtocolManagerInfoAttribute attr = (ProtocolManagerInfoAttribute) attrs[0]; ProtocolManagerInfoModel info = new ProtocolManagerInfoModel(attr.Name, attr.Description, attr.Alias); - + _ProtocolManagerTypes.Add(info, foundType); } } - public void LoadAllProtocolManagers(string path) - { - Trace.Call(path); - - string[] filenames = Directory.GetFiles(path, "smuxi-engine*.dll"); - foreach (string filename in filenames) { - LoadProtocolManager(filename); - } - } - public ProtocolManagerInfoModel GetProtocolManagerInfoByAlias(string alias) { foreach (ProtocolManagerInfoModel info in _ProtocolManagerTypes.Keys) { @@ -155,7 +120,7 @@ public IProtocolManager CreateProtocolManager(ProtocolManagerInfoModel info, Ses if (session == null) { throw new ArgumentNullException("session"); } - + Type type = _ProtocolManagerTypes[info]; return (IProtocolManager) Activator.CreateInstance(type, session); }