You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
arts/mcop/objectmanager.cc

290 lines
6.4 KiB

/*
Copyright (C) 2000,2001 Stefan Westerfeld
stefan@space.twc.de
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include <config.h>
#include "mcoputils.h"
#include "mcopconfig.h"
#include "objectmanager.h"
#include "dispatcher.h"
#include "extensionloader.h"
#include "debug.h"
#include <stdio.h>
#include <unistd.h>
#include <iostream>
using namespace std;
using namespace Arts;
class Arts::ObjectManagerPrivate {
public:
struct LoaderData {
LoaderData() : init(false) { }
bool init;
Loader loader;
};
list<ExtensionLoader *> extensions;
map<string, long> capabilities;
map<string, LoaderData> loaders;
};
Object_skel *ObjectManager::create(const string& name)
{
list<Factory *>::iterator i;
/* first try: look through all factories we have */
for(i = factories.begin();i != factories.end(); i++)
{
Factory *f = *i;
if(f->interfaceName() == name ) return f->createInstance();
}
/* second try: look if there is a suitable extension we could load */
TraderQuery query;
query.supports("InterfaceName", name);
vector<TraderOffer> *offers = query.query();
vector<TraderOffer>::iterator oi;
for(oi = offers->begin(); oi != offers->end(); oi++)
{
/*
* check whether we provide everything that this
* implementation requires to run
*/
bool requirementsOk = true;
vector<string> *requires = oi->getProperty("Requires");
vector<string>::iterator ri;
for(ri = requires->begin(); ri != requires->end(); ri++)
{
if(d->capabilities[*ri] <= 0)
requirementsOk = false;
}
delete requires;
vector<string> *language = oi->getProperty("Language");
vector<string> *libs = oi->getProperty("Library");
if(language->size() == 0 && libs->size() == 1)
{
arts_warning("ObjectManager: %s - assuming 'Language=C++' because library given",name.c_str());
language->push_back("C++");
}
if(language->size() != 1)
{
arts_warning("ObjectManager: %s - Language missing", name.c_str());
requirementsOk = false;
}
if(requirementsOk && language->front() == "C++" && libs->empty())
{
arts_warning("ObjectManager: %s - Library missing", name.c_str());
requirementsOk = false;
}
/* loading C++ components */
if(requirementsOk && language->front() == "C++")
{
string library = libs->front();
ExtensionLoader *e = new ExtensionLoader(library);
if(e->success())
{
d->extensions.push_back(e);
for(i = factories.begin();i != factories.end(); i++)
{
Factory *f = *i;
if(f->interfaceName() == name)
{
delete language;
delete libs;
delete offers;
return f->createInstance();
}
}
}
else
{
arts_warning("MCOP ObjectManager:"
" Could not load extension %s.", library.c_str());
delete e;
}
}
delete libs;
/* other languages/binary formats */
if(requirementsOk)
{
string lang = language->front();
ObjectManagerPrivate::LoaderData &ld = d->loaders[lang];
if(!ld.init)
{
TraderQuery query;
query.supports("Interface", "Arts::Loader");
query.supports("LoadLanguage", lang);
vector<TraderOffer> *loffers = query.query();
// TODO: error checking for SubClass
if(loffers->size() > 0)
{
ld.loader = SubClass(loffers->front().interfaceName());
}
else
{
ld.loader = Arts::Loader::null();
}
delete loffers;
}
ld.init = true;
if(!ld.loader.isNull())
{
/*
* ### change when breaking BC:
* it's bad that ObjectManager has to return _skel()s, but
* well, can't change it now
*/
Object obj = ld.loader.loadObject(*oi);
delete language;
delete offers;
return obj._base()->_copy()->_skel();
}
}
delete language;
}
arts_warning("MCOP ObjectManager: can't find implementation for %s.",
name.c_str());
delete offers;
return 0;
}
void ObjectManager::registerFactory(Factory *factory)
{
factories.push_back(factory);
}
void ObjectManager::removeFactory(Factory *factory)
{
list<Factory *>::iterator i;
i = factories.begin();
while(i != factories.end())
{
if(*i == factory) {
factories.erase(i);
i = factories.begin();
}
else i++;
}
}
ObjectManager *ObjectManager::_instance = 0;
ObjectManager::ObjectManager()
{
assert(!_instance);
_instance = this;
d = new ObjectManagerPrivate;
}
ObjectManager::~ObjectManager()
{
// they should be unloaded before this object can be deleted
assert(d->extensions.empty());
delete d;
assert(_instance);
_instance = 0;
}
ObjectManager *ObjectManager::the()
{
assert(_instance);
return _instance;
}
void ObjectManager::shutdownExtensions()
{
// give up references to the loaders
d->loaders.clear();
// shuts down all dynamically loaded extensions
list<ExtensionLoader *>::iterator i;
for(i=d->extensions.begin(); i != d->extensions.end(); i++)
(*i)->shutdown();
}
void ObjectManager::removeExtensions()
{
// unloads all dynamically loaded extensions
list<ExtensionLoader *>::iterator i;
for(i=d->extensions.begin(); i != d->extensions.end(); i++)
delete *i;
d->extensions.clear();
}
/*
* global references
*/
bool ObjectManager::addGlobalReference(Object object, const string& name)
{
bool result;
result = Dispatcher::the()->globalComm().put(name,object.toString());
if(result)
referenceNames.push_back(name);
return result;
}
string ObjectManager::getGlobalReference(const string& name)
{
return Dispatcher::the()->globalComm().get(name);
}
void ObjectManager::removeGlobalReferences()
{
list<string>::iterator i;
for(i=referenceNames.begin(); i != referenceNames.end();i++)
Dispatcher::the()->globalComm().erase(*i);
}
void ObjectManager::provideCapability(const string& name)
{
d->capabilities[name]++;
}
void ObjectManager::removeCapability(const string& name)
{
d->capabilities[name]--;
}