00001 #include <dlfcn.h>
00002 #include "register.hh"
00003 #include <list>
00004
00005 namespace anoid {
00006 namespace loader {
00007
00008 using namespace std;
00009 using namespace config;
00010
00011 Loader loader;
00012
00013 Loader::Loader() {
00014 }
00015
00016 Loader::~Loader() {
00017 }
00018
00019 void Loader::includeInformation(Configuration &c) {
00020 cout << "Loading class information" << endl;
00021 if (c.getName() == "classes") {
00022 list<Configuration *> classes = c.getChildren();
00023
00024 list<DynamicLoadableModuleInfo *> unprocessed;
00025 list<DynamicLoadableModuleInfo *> nextstep;
00026
00027 for (list<Configuration *>::iterator i = classes.begin(); i != classes.end(); ++i) {
00028 if ((*i)->getName() == "class") {
00029 DynamicLoadableModuleInfo *dlmi = new DynamicLoadableModuleInfo((*i)->getString("name"), (*i)->getString("url"));
00030 list<Configuration *> depends = (*i)->getChildren();
00031 for (list<Configuration *>::iterator j = depends.begin(); j != depends.end(); ++j) {
00032 if ((*j)->getName() == "requires")
00033 dlmi->requires.push_back((*j)->getString("ref"));
00034 delete (*j);
00035 }
00036 nextstep.push_back(dlmi);
00037 }
00038
00039 delete (*i);
00040 }
00041
00042 while (unprocessed.size() != nextstep.size()) {
00043 unprocessed = nextstep;
00044 nextstep.clear();
00045 for (list<DynamicLoadableModuleInfo *>::iterator i = unprocessed.begin(); i != unprocessed.end(); ++i) {
00046 bool clean = true;
00047 for (list<string>::iterator j = (*i)->requires.begin(); j != (*i)->requires.end(); ++j) {
00048 if (modules.count(*j) == 0)
00049 clean = false;
00050 }
00051 if (clean) {
00052 cout << "Registering " << (*i)->name << endl;
00053 modules[(*i)->name] = (*i);
00054 } else
00055 nextstep.push_back(*i);
00056 }
00057 }
00058
00059 if (!unprocessed.empty()) {
00060 for (list<DynamicLoadableModuleInfo *>::iterator i = unprocessed.begin(); i != unprocessed.end(); ++i) {
00061 cerr << "Module `" << (*i)->name << "' has unsatisfied dependencies." << endl;
00062 }
00063 }
00064 }
00065 }
00066
00067 void Loader::associate(const string &name, RegisterBase *factory) {
00068 cout << "Associating " << name << endl;
00069 if (factoryMap[name] == NULL) {
00070 factoryMap[name] = factory;
00071 }
00072 }
00073
00074 void Loader::disassociate(const string &name) {
00075 factoryMap.erase(name);
00076 }
00077
00078 void Loader::load(const std::string &name) {
00079 if (DLLMap[name] == NULL) {
00080 DynamicLoadableModuleInfo *d = modules[name];
00081 if (d) {
00082 cout << "Loading " << name << endl;
00083 for (list<string>::iterator i = d->requires.begin(); i != d->requires.end(); ++i) {
00084 load(*i);
00085 }
00086 void *tmp = dlopen(d->location.c_str(), RTLD_NOW);
00087 if (tmp) {
00088 DLLMap[name] = tmp;
00089 } else {
00090 cerr << "Could not load library `" << name << "'." << endl
00091 << "Loading failed with `" << dlerror() << "'." << endl;
00092 }
00093 cout << "Done loading " << name << endl;
00094 return;
00095 } else {
00096 cerr << "Could not find module `" << name << "'." << endl;
00097 }
00098 }
00099
00100 }
00101
00102 void Loader::unload(const std::string &library) {
00103 void *tmp = DLLMap[library];
00104 if (tmp != NULL) {
00105 dlclose(tmp);
00106 }
00107 DLLMap.erase(library);
00108 }
00109
00110 Base *Loader::getInstance(const std::string &name) {
00111 RegisterBase *factory = factoryMap[name];
00112 if (factory == NULL) {
00113 load(name);
00114 factory = factoryMap[name];
00115 }
00116 if (factory != NULL) {
00117 return factory->instantiate();
00118 }
00119 return NULL;
00120 }
00121 };
00122 };