Browse Source

Jupiter::Plugin:

* Added per-plugin configuration files
* Reworked initializataion
* Plugin management functions moved into Jupiter::Plugin as static functions.
release/0.19
Jessica James 9 years ago
parent
commit
b990d5d27f
  1. 182
      Jupiter/Plugin.cpp
  2. 189
      Jupiter/Plugin.h
  3. BIN
      Release/Jupiter.lib

182
Jupiter/Plugin.cpp

@ -1,5 +1,5 @@
/** /**
* Copyright (C) 2014-2015 Jessica James. * Copyright (C) 2014-2016 Jessica James.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -21,12 +21,8 @@
#if defined _WIN32 #if defined _WIN32
#include <Windows.h> #include <Windows.h>
#define DIR_CHR '\\'
#define DEFAULT_PLUGINS_DIRECTORY "Plugins\\"
#else // _WIN32 #else // _WIN32
#include <dlfcn.h> #include <dlfcn.h>
#define DIR_CHR '/'
#define DEFAULT_PLUGINS_DIRECTORY "Plugins/"
#endif // _WIN32 #endif // _WIN32
#include "Plugin.h" #include "Plugin.h"
@ -35,24 +31,13 @@
#include "CString.h" #include "CString.h"
#include "String.h" #include "String.h"
Jupiter::StringS pluginDir = DEFAULT_PLUGINS_DIRECTORY; using namespace Jupiter::literals;
Jupiter::ArrayList<Jupiter::Plugin> _plugins; #if defined _WIN32
Jupiter::ArrayList<Jupiter::Plugin> *Jupiter::plugins = &_plugins; constexpr char directory_character = '\\';
struct dlib; #else
Jupiter::ArrayList<dlib> _libList; constexpr char directory_character = '/';
#endif // _WIN32
Jupiter::Plugin::~Plugin()
{
for (size_t i = 0; i != _plugins.size(); i++)
{
if (_plugins.get(i) == this)
{
_plugins.remove(i);
break;
}
}
}
struct dlib struct dlib
{ {
@ -77,40 +62,100 @@ dlib::~dlib()
} }
} }
void Jupiter::setPluginDirectory(const Jupiter::ReadableString &dir) #if defined _WIN32
const Jupiter::ReferenceString module_file_extension = ".dll"_jrs;
#else // _WIN32
const Jupiter::ReferenceString module_file_extension = ".so"_jrs;
#endif // _WIN32
const Jupiter::ReferenceString config_file_extension = ".ini"_jrs;
Jupiter::StringS plugins_directory = "Plugins"_jrs + directory_character;
Jupiter::StringS plugin_configs_directory = "Configs"_jrs + directory_character;
Jupiter::ArrayList<Jupiter::Plugin> _plugins;
Jupiter::ArrayList<Jupiter::Plugin> *Jupiter::plugins = &_plugins;
Jupiter::ArrayList<dlib> _libList;
/** Jupiter::Plugin Implementation */
Jupiter::Plugin::Plugin()
{ {
if (pluginDir.set(dir) != 0 && pluginDir.get(pluginDir.size() - 1) != DIR_CHR) pluginDir += DIR_CHR; Jupiter::Plugin::config.readFile(Jupiter::Plugin::name);
} }
const Jupiter::ReadableString &Jupiter::getPluginDirectory() Jupiter::Plugin::~Plugin()
{ {
return pluginDir; for (size_t index = 0; index != _plugins.size(); ++index)
{
if (_plugins.get(index) == this)
{
_plugins.remove(index);
break;
}
}
} }
#if defined _WIN32 // Instance Functions
#define MODULE_FILE_EXTENSION ".dll"
#else // _WIN32 bool Jupiter::Plugin::shouldRemove() const
#define MODULE_FILE_EXTENSION ".so" {
#endif // _WIN32 return Jupiter::Plugin::_shouldRemove;
}
const Jupiter::ReadableString &Jupiter::Plugin::getName() const
{
return Jupiter::Plugin::name;
}
const Jupiter::INIFile &Jupiter::Plugin::getConfig() const
{
return Jupiter::Plugin::config;
}
Jupiter::Plugin *Jupiter::loadPlugin(const Jupiter::ReadableString &pluginName) bool Jupiter::Plugin::initialize()
{ {
return Jupiter::loadPluginFile(Jupiter::CStringS::Format("%.*s%.*s" MODULE_FILE_EXTENSION, pluginDir.size(), pluginDir.ptr(), pluginName.size(), pluginName.ptr()).c_str()); return true;
} }
Jupiter::Plugin *Jupiter::loadPluginFile(const char *file) // Static Functions
void Jupiter::Plugin::setDirectory(const Jupiter::ReadableString &dir)
{ {
if (plugins_directory.set(dir) != 0 && plugins_directory.get(plugins_directory.size() - 1) != directory_character)
plugins_directory += directory_character;
}
const Jupiter::ReadableString &Jupiter::Plugin::getDirectory()
{
return plugins_directory;
}
void Jupiter::Plugin::setConfigDirectory(const Jupiter::ReadableString &dir)
{
if (plugin_configs_directory.set(dir) != 0 && plugin_configs_directory.get(plugin_configs_directory.size() - 1) != directory_character)
plugin_configs_directory += directory_character;
}
const Jupiter::ReadableString &Jupiter::Plugin::getConfigDirectory()
{
return plugin_configs_directory;
}
Jupiter::Plugin *Jupiter::Plugin::load(const Jupiter::ReadableString &pluginName)
{
Jupiter::CStringS file = plugins_directory + pluginName + module_file_extension;
dlib *dPlug = new dlib(); dlib *dPlug = new dlib();
// Load the library // Load the library
#if defined _WIN32 #if defined _WIN32
dPlug->lib = LoadLibraryA(file); dPlug->lib = LoadLibraryA(file.c_str());
#else // _WIN32 #else // _WIN32
dPlug->lib = dlopen(file, RTLD_LAZY); dPlug->lib = dlopen(file.c_str(), RTLD_LAZY);
#endif // _WIN32 #endif // _WIN32
if (dPlug->lib == nullptr) if (dPlug->lib == nullptr)
{ {
fprintf(stderr, "Error: Unable to load plugin file \"%s\" (File failed to load)" ENDL, file); fprintf(stderr, "Error: Unable to load plugin file \"%s\" (File failed to load)" ENDL, file.c_str());
goto fail; goto fail;
} }
@ -124,16 +169,22 @@ Jupiter::Plugin *Jupiter::loadPluginFile(const char *file)
#endif // _WIN32 #endif // _WIN32
if (func == nullptr) if (func == nullptr)
{ {
fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Invalid plugin)" ENDL, file); fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Invalid plugin)" ENDL, file.c_str());
goto fail; goto fail;
} }
// Get the plugin
dPlug->plugin = func(); dPlug->plugin = func();
if (dPlug->plugin == nullptr) if (dPlug->plugin == nullptr)
{ {
fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Plugin failed to initialize)" ENDL, file); fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Plugin failed to initialize)" ENDL, file.c_str());
goto fail; goto fail;
} }
// Initialize the plugin
dPlug->plugin->name.set(pluginName);
dPlug->plugin->config.readFile(plugin_configs_directory + pluginName + config_file_extension);
dPlug->plugin->initialize();
} }
{ {
// Get and execute the "load" function if it exists // Get and execute the "load" function if it exists
@ -145,7 +196,7 @@ Jupiter::Plugin *Jupiter::loadPluginFile(const char *file)
#endif // _WIN32 #endif // _WIN32
if (func != nullptr && func() == false) if (func != nullptr && func() == false)
{ {
fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Plugin failed to load)" ENDL, file); fprintf(stderr, "Error: Unable to load plugin file \"%s\" (Plugin failed to load)" ENDL, file.c_str());
goto fail; goto fail;
} }
} }
@ -160,7 +211,7 @@ fail:
return nullptr; return nullptr;
} }
bool Jupiter::freePlugin(size_t index) bool Jupiter::Plugin::free(size_t index)
{ {
if (index < _plugins.size()) if (index < _plugins.size())
{ {
@ -168,7 +219,7 @@ bool Jupiter::freePlugin(size_t index)
_plugins.remove(index); _plugins.remove(index);
dlib *dPlug = _libList.remove(index); dlib *dPlug = _libList.remove(index);
typedef void (*func_type)(void); typedef void(*func_type)(void);
#if defined _WIN32 #if defined _WIN32
func_type func = (func_type)GetProcAddress(dPlug->lib, "unload"); func_type func = (func_type)GetProcAddress(dPlug->lib, "unload");
#else // _WIN32 #else // _WIN32
@ -182,38 +233,52 @@ bool Jupiter::freePlugin(size_t index)
return false; return false;
} }
bool Jupiter::freePlugin(Jupiter::Plugin *plugin) bool Jupiter::Plugin::free(Jupiter::Plugin *plugin)
{ {
if (plugin == nullptr) return false; if (plugin == nullptr)
for (size_t i = 0; i != _plugins.size(); i++) if (_plugins.get(i) == plugin) return Jupiter::freePlugin(i); return false;
for (size_t index = 0; index != _plugins.size(); ++index)
if (_plugins.get(index) == plugin)
return Jupiter::Plugin::free(index);
return false; return false;
} }
bool Jupiter::freePlugin(const Jupiter::ReadableString &pluginName) bool Jupiter::Plugin::free(const Jupiter::ReadableString &pluginName)
{ {
if (pluginName == nullptr) return false; if (pluginName == nullptr)
for (size_t i = 0; i != _plugins.size(); i++) if (pluginName.matchi(_plugins.get(i)->getName())) return Jupiter::freePlugin(i); return false;
for (size_t index = 0; index != _plugins.size(); ++index)
if (pluginName.matchi(_plugins.get(index)->getName()))
return Jupiter::Plugin::free(index);
return false; return false;
} }
Jupiter::Plugin *Jupiter::getPlugin(size_t index) Jupiter::Plugin *Jupiter::Plugin::get(size_t index)
{ {
if (index < _plugins.size()) return _plugins.get(index); if (index < _plugins.size())
return _plugins.get(index);
return nullptr; return nullptr;
} }
Jupiter::Plugin *Jupiter::getPlugin(const Jupiter::ReadableString &pluginName) Jupiter::Plugin *Jupiter::Plugin::get(const Jupiter::ReadableString &pluginName)
{ {
Jupiter::Plugin *p; Jupiter::Plugin *plugin;
for (size_t i = 0; i != _plugins.size(); i++) for (size_t index = 0; index != _plugins.size(); ++index)
{ {
p = _plugins.get(i); plugin = _plugins.get(index);
if (pluginName.matchi(p->getName())) return p; if (pluginName.matchi(plugin->getName()))
return plugin;
} }
return nullptr; return nullptr;
} }
// Event Placeholders // Event Implementations
int Jupiter::Plugin::think() int Jupiter::Plugin::think()
{ {
@ -231,10 +296,7 @@ bool Jupiter::Plugin::OnBadRehash(bool removed)
return false; return false;
} }
bool Jupiter::Plugin::shouldRemove() // Event Placeholders
{
return Jupiter::Plugin::_shouldRemove;
}
void Jupiter::Plugin::OnConnect(Jupiter::IRC::Client *) void Jupiter::Plugin::OnConnect(Jupiter::IRC::Client *)
{ {

189
Jupiter/Plugin.h

@ -1,5 +1,5 @@
/** /**
* Copyright (C) 2014-2015 Jessica James. * Copyright (C) 2014-2016 Jessica James.
* *
* Permission to use, copy, modify, and/or distribute this software for any * Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above * purpose with or without fee is hereby granted, provided that the above
@ -26,8 +26,15 @@
#include "ArrayList.h" #include "ArrayList.h"
#include "Thinker.h" #include "Thinker.h"
#include "Readable_String.h"
#include "Rehash.h" #include "Rehash.h"
#include "INIFile.h"
#include "String.h"
/** DLL Linkage Nagging */
#if defined _MSC_VER
#pragma warning(push)
#pragma warning(disable: 4251)
#endif // _MSC_VER
namespace Jupiter namespace Jupiter
{ {
@ -74,7 +81,29 @@ namespace Jupiter
* *
* @returns True if this plugin should be unloaded, false otherwise. * @returns True if this plugin should be unloaded, false otherwise.
*/ */
bool shouldRemove(); bool shouldRemove() const;
/**
* @brief Returns the name of the plugin.
*
* @return String containing the name of the plugin.
*/
const Jupiter::ReadableString &getName() const;
/**
* @brief Returns the plugin's configuration file.
*
* @return Plugin's configuration file.
*/
const Jupiter::INIFile &getConfig() const;
/**
* @brief Initializes the plugin.
* Note: This function is executed immediately AFTER 'name' is assigned and 'config' is loaded.
*
* @return True on success, false otherwise.
*/
virtual bool initialize();
/** /**
* @brief This is called when a connection has been successfully established. * @brief This is called when a connection has been successfully established.
@ -234,96 +263,106 @@ namespace Jupiter
virtual void OnThink(Jupiter::IRC::Client *server); virtual void OnThink(Jupiter::IRC::Client *server);
/** /**
* @brief Returns the name of the plugin. * @brief Constructor for the Plugin class.
*
* @return String containing the name of the plugin.
*/ */
virtual const Jupiter::ReadableString &getName() = 0; Plugin();
/** /**
* @brief Destructor for Plugin class. * @brief Destructor for Plugin class.
*/ */
virtual ~Plugin(); virtual ~Plugin();
protected: public: // Plugin management functions
bool _shouldRemove = false; /**
}; * @brief Sets the directory to look in for plugins.
*
* @param dir Directory to look for plugins in.
*/
static void setDirectory(const Jupiter::ReadableString &dir);
/** Plugin management functions */ /**
* @brief Returns the current plugin directory.
*
* @return String containing the directory which is prepended to module load attempts.
*/
static const Jupiter::ReadableString &getDirectory();
/** The list containing pointers to plugins */ /**
JUPITER_API extern Jupiter::ArrayList<Jupiter::Plugin> *plugins; * @brief Sets the directory to look in for plugin configuration files.
*
* @param dir Directory to look for configuration files in.
*/
static void setConfigDirectory(const Jupiter::ReadableString &dir);
/** /**
* @brief Sets the directory to look in for plugins. * @brief Returns the current plugin configuration directory
* *
* @param dir Directory to look for plugins in. * @return String containing the directory which is prepended to configuration load attempts.
*/ */
JUPITER_API void setPluginDirectory(const Jupiter::ReadableString &dir); static const Jupiter::ReadableString &getConfigDirectory();
/** /**
* @brief Returns the current plugin directory. * @brief Loads a module, appending .so or .dll as appropriate for the operating system.
* *
* @return String containing the directory which is prepended to module load attempts. * @param pluginName The name of the plugin to load.
*/ * @return A pointer to the plugin that was loaded on success, nullptr otherwise.
JUPITER_API const Jupiter::ReadableString &getPluginDirectory(); */
static Jupiter::Plugin *load(const Jupiter::ReadableString &pluginName);
/** /**
* @brief Loads a module, appending .so or .dll as appropriate for the operating system. * @brief Unloads a module and removes it from the module list, based on its index.
* *
* @param pluginName The name of the plugin to load. * @param index Index of the module.
* @return A pointer to the plugin that was loaded on success, nullptr otherwise. * @return True if a module was unloaded, false otherwise.
*/ */
JUPITER_API Jupiter::Plugin *loadPlugin(const Jupiter::ReadableString &pluginName); static bool free(size_t index);
/** /**
* @brief Loads a module based on a true file name. * @brief Unloads a module and removes it from the module list, based on its data.
* *
* @param file File to attempt to load as a plugin. * @param plugin Pointer to the plugin to unload.
* @return A pointer to the plugin that was loaded on success, nullptr otherwise. * @return True if a module was unloaded, false otherwise.
*/ */
JUPITER_API Jupiter::Plugin *loadPluginFile(const char *file); static bool free(Jupiter::Plugin *plugin);
/** /**
* @brief Unloads a module and removes it from the module list, based on its index. * @brief Unloads a module and removes it from the module list, based on its name.
* * Note: This function accepts wildcard strings.
* @param index Index of the module. *
* @return True if a module was unloaded, false otherwise. * @param pluginName Name of the module to unload.
*/ * @return True if a module was unloaded, false otherwise.
JUPITER_API bool freePlugin(size_t index); */
static bool free(const Jupiter::ReadableString &pluginName);
/** /**
* @brief Unloads a module and removes it from the module list, based on its data. * @brief Fetches a plugin from the list and returns it, based on its index.
* *
* @param plugin Pointer to the plugin to unload. * @param index Index of the module to return.
* @return True if a module was unloaded, false otherwise. * @return A module on success, nullptr otherwise.
*/ */
JUPITER_API bool freePlugin(Jupiter::Plugin *plugin); static Jupiter::Plugin *get(size_t index);
/** /**
* @brief Unloads a module and removes it from the module list, based on its name. * @brief Fetches a plugin from the list and returns it, based on its name.
* Note: This function accepts wildcard strings. *
* * @param pluginName String containing the name of the plugin.
* @param pluginName Name of the module to unload. * @return A module on success, nullptr otherwise.
* @return True if a module was unloaded, false otherwise. */
*/ static Jupiter::Plugin *get(const Jupiter::ReadableString &pluginName);
JUPITER_API bool freePlugin(const Jupiter::ReadableString &pluginName);
/** protected:
* @brief Fetches a plugin from the list and returns it, based on its index. bool _shouldRemove = false;
* Jupiter::StringS name;
* @param index Index of the module to return. Jupiter::INIFile config;
* @return A module on success, nullptr otherwise. };
*/
JUPITER_API Jupiter::Plugin *getPlugin(size_t index);
/** /** The list containing pointers to plugins */
* @brief Fetches a plugin from the list and returns it, based on its name. JUPITER_API extern Jupiter::ArrayList<Jupiter::Plugin> *plugins;
*
* @param pluginName String containing the name of the plugin.
* @return A module on success, nullptr otherwise.
*/
JUPITER_API Jupiter::Plugin *getPlugin(const Jupiter::ReadableString &pluginName);
} }
/** Re-enable warnings */
#if defined _MSC_VER
#pragma warning(pop)
#endif // _MSC_VER
#endif // _PLUGIN_H_HEADER #endif // _PLUGIN_H_HEADER

BIN
Release/Jupiter.lib

Binary file not shown.
Loading…
Cancel
Save