1
/* This file is part of Strigi Desktop Search
3
* Copyright (C) 2007 Jos van den Oever <jos@vandenoever.info>
5
* This library is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU Library General Public
7
* License as published by the Free Software Foundation; either
8
* version 2 of the License, or (at your option) any later version.
10
* This library is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13
* Library General Public License for more details.
15
* You should have received a copy of the GNU Library General Public License
16
* along with this library; see the file COPYING.LIB. If not, write to
17
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18
* Boston, MA 02110-1301, USA.
20
#include "indexpluginloader.h"
21
#include "indexmanager.h"
26
#include <stgdirent.h>
29
using namespace Strigi;
34
#define DLCLOSE dlclose
36
#define DLSYM GetProcAddress
37
#define DLCLOSE FreeLibrary
41
typedef void* StgModuleType;
44
typedef HMODULE StgModuleType;
47
vector<string> getdirs(const string& direnv) {
49
string::size_type lastp = 0;
50
string::size_type p = direnv.find(PATH_SEPARATOR);
51
while (p != string::npos) {
52
dirs.push_back(direnv.substr(lastp, p-lastp));
54
p = direnv.find(PATH_SEPARATOR, lastp);
56
dirs.push_back(direnv.substr(lastp));
60
// anonymous namespace for static variables
64
const StgModuleType mod;
65
Module(const Module&);
66
void operator=(const Module&);
68
Strigi::IndexManager* (*create)(const char*);
69
void (*destroy)(Strigi::IndexManager*);
70
Module(StgModuleType m)
73
// TODO: figure out why we get segfaults when cleaning up nicely
79
map<std::string, Module*> modules;
81
map<std::string, Module*>& mods() {
82
if (!initialized) initialize();
85
map<void*, Module*> indexmanagers;
93
// load the plugins from the environment setting
94
string strigipluginpath;
95
if (getenv("STRIGI_PLUGIN_PATH")) {
96
strigipluginpath = getenv("STRIGI_PLUGIN_PATH");
98
vector<string> strigipluginpaths = getdirs(strigipluginpath);
99
if (strigipluginpath.size()) {
100
for (uint i=0; i<strigipluginpaths.size(); ++i) {
101
IndexPluginLoader::loadPlugins(strigipluginpaths[i].c_str());
104
IndexPluginLoader::loadPlugins( LIBINSTALLDIR "/strigi");
108
// delete all leftover indexmanagers
109
// if code deletes the indexmanager on it's own, the error will
111
map<void*, Module*>::iterator j;
112
for (j = indexmanagers.begin(); j != indexmanagers.end(); ++j) {
113
j->second->destroy(static_cast<IndexManager*>(j->first));
115
// unload all the modules
116
map<string, Module*>::iterator i;
117
for (i = modules.begin(); i != modules.end(); ++i) {
121
void loadModule(const string& name, const string& dir);
124
ModuleList::loadModule(const string& name, const string& lib) {
125
// check if this module was already loaded
126
map<string, Module*>::iterator i = modules.find(name);
127
if (i != modules.end()) {
130
StgModuleType handle;
132
// do not use RTLD_GLOBAL here
133
// note: If neither RTLD_GLOBAL nor RTLD_LOCAL are specified,
134
// the default is RTLD_LOCAL.
135
handle = dlopen(lib.c_str(), RTLD_LOCAL | RTLD_NOW);
137
handle = LoadLibrary(lib.c_str());
141
cerr << "Could not load '" << lib << "':" << dlerror() << endl;
143
cerr << "Could not load '" << lib << "': GetLastError(): "
144
<< GetLastError() << endl;
148
IndexManager*(*create)(const char*) = (IndexManager*(*)(const char*))
149
DLSYM(handle, "createIndexManager");
152
fprintf(stderr, "%s\n", dlerror());
154
fprintf(stderr, "GetLastError: %d\n", GetLastError());
159
void(*destroy)(IndexManager*) = (void(*)(IndexManager*))
160
DLSYM(handle, "deleteIndexManager");
163
fprintf(stderr, "%s\n", dlerror());
165
fprintf(stderr, "GetLastError: %d\n", GetLastError());
170
Module* module = new Module(handle);
171
module->create = create;
172
module->destroy = destroy;
173
modules[name] = module;
175
static ModuleList modules;
178
IndexPluginLoader::loadPlugins(const char* d) {
179
DIR *dir = opendir(d);
183
struct dirent* ent = readdir(dir);
184
string prefix("strigiindex_");
186
string suffix(".dll");
188
string suffix(".so");
191
size_t len = strlen(ent->d_name);
192
const char* prepos = strstr(ent->d_name, prefix.c_str());
193
const char* sufpos = strstr(ent->d_name, suffix.c_str());
194
if (prepos && sufpos + suffix.length() == ent->d_name + len) {
195
len -= (prepos - ent->d_name) + prefix.length() + suffix.length();
196
string name(prepos + prefix.length(), len);
197
string pluginpath = d;
198
if (pluginpath[pluginpath.length()-1] != '/') {
199
pluginpath.append("/");
201
pluginpath.append(ent->d_name);
202
// check that the file is a regular file
204
if (stat(pluginpath.c_str(), &s) == 0 && (S_IFREG & s.st_mode)) {
205
modules.loadModule(name, pluginpath);
213
IndexPluginLoader::indexNames() {
214
vector<string> names;
215
map<string, Module*>::const_iterator i = modules.mods().begin();
216
for (; i != modules.mods().end(); ++i) {
217
names.push_back(i->first);
222
IndexPluginLoader::createIndexManager(const char* name, const char* dir) {
223
// find the right plugin
224
map<string, Module*>::iterator i = modules.mods().find(name);
225
if (i == modules.mods().end()) {
228
// create the indexmanager
229
IndexManager* im = i->second->create(dir);
231
// map the indexmanager to the module that created it, so we can delete
233
modules.indexmanagers[im] = i->second;
238
IndexPluginLoader::deleteIndexManager(IndexManager* im) {
239
// find the right module
240
map<void*, Module*>::iterator i = modules.indexmanagers.find(im);
241
if (i == modules.indexmanagers.end()) {
244
// let the module delete the indexmanager
245
i->second->destroy(im);
246
// remove the mapping from the map
247
modules.indexmanagers.erase(i);