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