PluginManager.cpp
1 //
3 // Pluma - Plug-in Management Framework
4 // Copyright (C) 2010-2012 Gil Costa (gsaurus@gmail.com)
5 //
6 // This software is provided 'as-is', without any express or implied warranty.
7 // In no event will the authors be held liable for any damages arising from the use of this software.
8 //
9 // Permission is granted to anyone to use this software for any purpose,
10 // including commercial applications, and to alter it and redistribute it freely,
11 // subject to the following restrictions:
12 //
13 // 1. The origin of this software must not be misrepresented;
14 // you must not claim that you wrote the original software.
15 // If you use this software in a product, an acknowledgment
16 // in the product documentation would be appreciated but is not required.
17 //
18 // 2. Altered source versions must be plainly marked as such,
19 // and must not be misrepresented as being the original software.
20 //
21 // 3. This notice may not be removed or altered from any source distribution.
22 //
24 
25 
27 // Headers
29 #include <Pluma/PluginManager.hpp>
30 #include <Pluma/DLibrary.hpp>
31 #include <Pluma/Dir.hpp>
32 #include <cstdio>
33 
34 namespace pluma{
35 
38  // Nothing to do
39 }
40 
41 
44  unloadAll();
45 }
46 
47 
49 bool PluginManager::load(const std::string& path){
50  std::string plugName = getPluginName(path);
51  std::string realPath = resolvePathExtension(path);
52  DLibrary* lib = DLibrary::load(realPath);
53  if (!lib) return false;
54 
55  fnRegisterPlugin* registerFunction;
56  registerFunction = reinterpret_cast<fnRegisterPlugin*>(lib->getSymbol("connect"));
57 
58  if(!registerFunction){
59  fprintf(stderr, "Failed to initialize plugin \"%s\": connect function not found\n", plugName.c_str());
60  delete lib;
61  return false;
62  }
63  // try to initialize plugin:
64  if (!registerFunction(host)){
65  // plugin decided to fail
66  fprintf(stderr, "Self registry failed on plugin \"%s\".\n", plugName.c_str());
67  host.cancelAddictions();
68  delete lib;
69  return false;
70  }
71  // Store the library if addictions are confirmed
72  if (host.confirmAddictions())
73  libraries[plugName] = lib;
74  else{
75  // otherwise nothing was registered
76  fprintf(stderr, "Nothing registered by plugin \"%s\".\n", plugName.c_str());
77  delete lib;
78  return false;
79  }
80  return true;
81 }
82 
83 
85 bool PluginManager::load(const std::string& folder, const std::string& pluginName){
86  if (folder.empty())
87  return load(pluginName);
88  else if (folder[folder.size()-1] == '/' || folder[folder.size()-1] == '\\')
89  return load(folder + pluginName);
90  return load(folder + '/' + pluginName);
91 }
92 
93 
95 int PluginManager::loadFromFolder(const std::string& folder, bool recursive){
96  std::list<std::string> files;
97  dir::listFiles(files, folder, PLUMA_LIB_EXTENSION, recursive);
98  // try to load every library
99  int res = 0;
100  std::list<std::string>::const_iterator it;
101  for (it = files.begin() ; it != files.end() ; ++it){
102  if ( load(*it) ) ++res;
103  }
104  return res;
105 }
106 
107 
109 bool PluginManager::unload(const std::string& pluginName){
110  std::string plugName = getPluginName(pluginName);
111  LibMap::iterator it = libraries.find(plugName);
112  if( it != libraries.end() ) {
113  delete it->second;
114  libraries.erase(it);
115  return true;
116  }
117  return false;
118 }
119 
120 
123 
124  host.clearProviders();
125  LibMap::iterator it;
126  for (it = libraries.begin() ; it != libraries.end() ; ++it){
127  delete it->second;
128  }
129  libraries.clear();
130 }
131 
132 
134 std::string PluginManager::getPluginName(const std::string& path){
135  size_t lastDash = path.find_last_of("/\\");
136  size_t lastDot = path.find_last_of('.');
137  if (lastDash == std::string::npos) lastDash = 0;
138  else ++lastDash;
139  if (lastDot < lastDash || lastDot == std::string::npos){
140  // path without extension
141  lastDot = path.length();
142  }
143  return path.substr(lastDash, lastDot-lastDash);
144 }
145 
146 
148 std::string PluginManager::resolvePathExtension(const std::string& path){
149  size_t lastDash = path.find_last_of("/\\");
150  size_t lastDot = path.find_last_of('.');
151  if (lastDash == std::string::npos) lastDash = 0;
152  else ++lastDash;
153  if (lastDot < lastDash || lastDot == std::string::npos){
154  // path without extension, add it
155  return path + "." + PLUMA_LIB_EXTENSION;
156  }
157  return path;
158 }
159 
160 
162 void PluginManager::registerType(const std::string& type, unsigned int version, unsigned int lowestVersion){
163  host.registerType(type, version, lowestVersion);
164 }
165 
166 
169  if (provider == NULL){
170  fprintf(stderr, "Trying to add null provider\n");
171  return false;
172  }
173  return host.registerProvider(provider);
174 }
175 
176 
178 void PluginManager::getLoadedPlugins(std::vector<const std::string*>& pluginNames) const{
179  pluginNames.reserve(pluginNames.size()+libraries.size());
180  LibMap::const_iterator it;
181  for(it = libraries.begin() ; it != libraries.end() ; ++it){
182  pluginNames.push_back(&(it->first));
183  }
184 }
185 
186 
188 bool PluginManager::isLoaded(const std::string& pluginName) const{
189  return libraries.find(getPluginName(pluginName)) != libraries.end();
190 }
191 
192 
194 const std::list<Provider*>* PluginManager::getProviders(const std::string& type) const{
195  return host.getProviders(type);
196 }
197 
198 
199 
200 } // namespace pluma
201 
bool unload(const std::string &pluginName)
Unload a plugin.
void registerType(const std::string &type, unsigned int version, unsigned int lowestVersion)
Register a provider type.
void unloadAll()
Unload all loaded plugins.
PluginManager()
Default constructor.
Interface to provide applications with objects from plugins.
Definition: Provider.hpp:42
const std::list< Provider * > * getProviders(const std::string &type) const
Get providers of a certain type.
static DLibrary * load(const std::string &path)
Load a library.
Definition: DLibrary.cpp:37
Manages a Dynamic Linking Library.
Definition: DLibrary.hpp:49
int loadFromFolder(const std::string &folder, bool recursive=false)
Load all plugins from a given folder.
void * getSymbol(const std::string &symbol)
Get a symbol from the library.
Definition: DLibrary.cpp:79
bool load(const std::string &path)
Load a plugin given it's path.
~PluginManager()
Destructor.
bool isLoaded(const std::string &pluginName) const
Check if a plug-in is loaded.
void getLoadedPlugins(std::vector< const std::string * > &pluginNames) const
Get the name of all loaded plugins.
bool addProvider(Provider *provider)
Directly add a new provider.