Line data Source code
1 : /*
2 : * Copyright (c) 2013-2015: G-CSC, Goethe University Frankfurt
3 : * Author: Sebastian Reiter
4 : *
5 : * This file is part of UG4.
6 : *
7 : * UG4 is free software: you can redistribute it and/or modify it under the
8 : * terms of the GNU Lesser General Public License version 3 (as published by the
9 : * Free Software Foundation) with the following additional attribution
10 : * requirements (according to LGPL/GPL v3 §7):
11 : *
12 : * (1) The following notice must be displayed in the Appropriate Legal Notices
13 : * of covered and combined works: "Based on UG4 (www.ug4.org/license)".
14 : *
15 : * (2) The following notice must be displayed at a prominent place in the
16 : * terminal output of covered works: "Based on UG4 (www.ug4.org/license)".
17 : *
18 : * (3) The following bibliography is recommended for citation and must be
19 : * preserved in all covered files:
20 : * "Reiter, S., Vogel, A., Heppner, I., Rupp, M., and Wittum, G. A massively
21 : * parallel geometric multigrid solver on hierarchically distributed grids.
22 : * Computing and visualization in science 16, 4 (2013), 151-164"
23 : * "Vogel, A., Reiter, S., Rupp, M., Nägel, A., and Wittum, G. UG4 -- a novel
24 : * flexible software system for simulating pde based models on high performance
25 : * computers. Computing and visualization in science 16, 4 (2013), 165-179"
26 : *
27 : * This program is distributed in the hope that it will be useful,
28 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 : * GNU Lesser General Public License for more details.
31 : */
32 :
33 : #include <string>
34 : #include "common/log.h"
35 : #include "bridge/bridge.h"
36 : #include "common/profiler/profiler.h"
37 : #include "path_provider.h"
38 : #include "file_util.h"
39 : #include "os_info.h"
40 : #include "dynamic_library_util.h"
41 :
42 : #include "plugin_util.h"
43 :
44 : using namespace std;
45 :
46 :
47 :
48 : namespace ug{
49 :
50 : namespace {
51 : vector<DynLibHandle> loadedPlugins;
52 : vector<string> loadedPluginNames;
53 : }
54 :
55 0 : bool PluginLoaded(const string &name)
56 : {
57 0 : return find(loadedPluginNames.begin(), loadedPluginNames.end(), name) != loadedPluginNames.end();
58 : }
59 :
60 1 : bool LoadPlugins(const char* pluginPath, string parentGroup, bridge::Registry& reg, bool bPrefixGroup)
61 : {
62 : PROFILE_FUNC();
63 : typedef void (*FctInitPlugin)(ug::bridge::Registry*, string);
64 :
65 : bool bSuccess = true;
66 :
67 : // first we'll try to find all plugins in the given path
68 : vector<string> files;
69 :
70 1 : GetFilesInDirectory(files, pluginPath);
71 :
72 1 : string prefixStr = GetDynamicLibraryPrefix();
73 2 : string suffixStr = string(".").append(GetDynamicLibrarySuffix());
74 :
75 1 : int prefixLen = prefixStr.size();
76 1 : int suffixLen = suffixStr.size(); // includes '.'
77 :
78 2 : for(size_t i = 0; i < files.size(); ++i){
79 :
80 : // extract the plugins name from the file-name
81 : int nameStart = prefixLen;
82 1 : int nameLength = (int)files[i].size() - suffixLen - nameStart;
83 :
84 : // exclude MAC OS X hidden folder custom file ".DS_Store" from plugin consideration
85 : #ifdef __APPLE__
86 : if(files[i].compare(".DS_Store") == 0) continue;
87 : #endif
88 :
89 : // check that plugin name can exist
90 1 : if(nameLength <= 0)
91 : {
92 0 : UG_ERR_LOG("Plugin-filename '" << files[i] <<
93 : "' too short. Ignoring plugin.\n");
94 : bSuccess = false;
95 0 : continue;
96 : }
97 :
98 : // check for prefix
99 1 : if(files[i].compare(0,prefixLen,prefixStr) != 0)
100 : {
101 0 : UG_ERR_LOG("Plugin-filename '" << files[i] << "' does not "
102 : "start with Plugin prefix '"<<prefixStr<<"'. Ignoring plugin.\n");
103 : bSuccess = false;
104 0 : continue;
105 : }
106 :
107 : // check for suffix
108 1 : if(files[i].compare(files[i].size()-suffixLen,suffixLen,suffixStr) != 0)
109 : {
110 0 : UG_ERR_LOG("Plugin-filename '" << files[i] << "' does not "
111 : "end with Plugin suffix '"<<suffixStr<<"'. Ignoring plugin.\n");
112 : bSuccess = false;
113 0 : continue;
114 : }
115 :
116 : // load the library
117 1 : string fullPluginName(pluginPath);
118 1 : fullPluginName.append("/").append(files[i]);
119 :
120 :
121 : DynLibHandle libHandle;
122 : try{
123 1 : libHandle = OpenLibrary(fullPluginName.c_str());
124 : }
125 0 : catch(std::string errMsg)
126 : {
127 : UG_ERR_LOG("PLUGIN-ERROR: Couldn't open plugin " << files[i] << endl);
128 0 : UG_ERR_LOG("Error Message: " << errMsg << "\n");
129 0 : UG_ERR_LOG("NOTE: This could be due to incompatible build settings in ugshell and the plugin.\n");
130 : bSuccess = false;
131 : continue;
132 0 : }
133 :
134 :
135 : // find the plugins init function
136 1 : string pluginName = files[i].substr(nameStart, nameLength);
137 1 : string fctName("InitUGPlugin_");
138 : fctName.append(pluginName);
139 :
140 : FctInitPlugin fctInitPlugin =
141 1 : (FctInitPlugin) GetLibraryProcedure(libHandle, fctName.c_str());
142 :
143 1 : if(!fctInitPlugin){
144 : UG_ERR_LOG("PLUGIN-ERROR: Couldn't find entry point " << fctName
145 : << " in plugin " << files[i] << endl);
146 0 : CloseLibrary(libHandle);
147 : bSuccess = false;
148 : continue;
149 : }
150 :
151 : //#define DEBUG_PLUGINS
152 : #ifdef DEBUG_PLUGINS
153 : UG_LOG("Loaded plugin " << pluginName << " from " << fullPluginName << "\n");
154 : size_t numClassesPre = reg.num_classes();
155 : size_t numFunctionsPre = reg.num_functions();
156 : UG_LOG("Call " << fctName << "... ");
157 : #endif
158 :
159 : // added this for better docu generation
160 : // this way, we can distinguish what plugin did what classes/functions etc.
161 : std::string group;
162 1 : if(bPrefixGroup)
163 0 : group = std::string("(Plugin) ") + pluginName + std::string(" ") + parentGroup;
164 : else
165 : group = parentGroup;
166 :
167 : // call the init method
168 1 : fctInitPlugin(®, group);
169 : #ifdef DEBUG_PLUGINS
170 : UG_LOG("added " << reg.num_classes() - numClassesPre << " classes, " << reg.num_functions()-numFunctionsPre << " functions, "
171 : << "group = " << group << "\n")
172 : #endif
173 :
174 1 : loadedPlugins.push_back(libHandle);
175 1 : loadedPluginNames.push_back(pluginName);
176 : }
177 :
178 : // make sure that the registry is updated
179 1 : reg.registry_changed();
180 :
181 1 : return bSuccess;
182 1 : }
183 :
184 0 : bool UnloadPlugins()
185 : {
186 : typedef void (*FctFinalizePlugin)();
187 0 : for(size_t i=0; i<loadedPlugins.size(); ++i)
188 : {
189 0 : string fctName("FinalizeUGPlugin");
190 0 : DynLibHandle libHandle = loadedPlugins[i];
191 :
192 : FctFinalizePlugin fctFinalizePlugin =
193 0 : (FctFinalizePlugin) GetLibraryProcedure(libHandle, fctName.c_str());
194 :
195 0 : if(fctFinalizePlugin) fctFinalizePlugin();
196 :
197 0 : CloseLibrary(libHandle);
198 : }
199 : loadedPlugins.clear();
200 0 : return true;
201 : }
202 :
203 0 : vector<string> GetLoadedPlugins()
204 : {
205 0 : return loadedPluginNames;
206 : }
207 :
208 : }// end of namespace
|