lib

manager.cpp

00001 /***************************************************************************
00002  * manager.cpp
00003  * This file is part of the KDE project
00004  * copyright (C)2004-2005 by Sebastian Sauer (mail@dipe.org)
00005  *
00006  * This program is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Library General Public
00008  * License as published by the Free Software Foundation; either
00009  * version 2 of the License, or (at your option) any later version.
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Library General Public License for more details.
00014  * You should have received a copy of the GNU Library General Public License
00015  * along with this program; see the file COPYING.  If not, write to
00016  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  * Boston, MA 02110-1301, USA.
00018  ***************************************************************************/
00019 
00020 #include "manager.h"
00021 
00022 #include "../api/interpreter.h"
00023 //#include "../api/qtobject.h"
00024 #include "../api/eventslot.h"
00025 #include "../api/eventsignal.h"
00026 //#include "../api/script.h"
00027 
00028 #include "krossconfig.h"
00029 #include "scriptcontainer.h"
00030 
00031 #include <qobject.h>
00032 #include <qfile.h>
00033 #include <qregexp.h>
00034 
00035 #include <kdebug.h>
00036 #include <klibloader.h>
00037 #include <klocale.h>
00038 #include <kstaticdeleter.h>
00039 
00040 extern "C"
00041 {
00042     typedef Kross::Api::Object* (*def_module_func)(Kross::Api::Manager*);
00043 }
00044 
00045 using namespace Kross::Api;
00046 
00047 namespace Kross { namespace Api {
00048 
00050     class ManagerPrivate
00051     {
00052         public:
00054             QMap<QString, InterpreterInfo*> interpreterinfos;
00055 
00057             QMap<QString, Module::Ptr> modules;
00058     };
00059 
00064     static KStaticDeleter<Manager> m_managerdeleter;
00065 
00070     static Manager* m_manager = 0;
00071 
00072 }}
00073 
00074 Manager* Manager::scriptManager()
00075 {
00076     if(! m_manager) {
00077         // Create the Manager-singleton on demand and let the
00078         // KStaticDeleter take care of freeing it if not needed
00079         // any longer.
00080         m_managerdeleter.setObject(m_manager, new Manager());
00081     }
00082 
00083     // and finally return the singleton.
00084     return m_manager;
00085 }
00086 
00087 Manager::Manager()
00088     : MainModule("Kross") // the manager has the name "Kross"
00089     , d( new ManagerPrivate() )
00090 {
00091 #ifdef KROSS_PYTHON_LIBRARY
00092     QString pythonlib = QFile::encodeName( KLibLoader::self()->findLibrary(KROSS_PYTHON_LIBRARY) );
00093     if(! pythonlib.isEmpty()) { // If the Kross Python plugin exists we offer it as supported scripting language.
00094         InterpreterInfo::Option::Map pythonoptions;
00095         pythonoptions.replace("restricted",
00096             new InterpreterInfo::Option("Restricted", "Restricted Python interpreter", QVariant(false,0))
00097         );
00098         d->interpreterinfos.replace("python",
00099             new InterpreterInfo("python",
00100                 pythonlib, // library
00101                 "*.py", // file filter-wildcard
00102                 QStringList() << /* "text/x-python" << */ "application/x-python", // mimetypes
00103                 pythonoptions // options
00104             )
00105         );
00106     }
00107 #endif
00108 #ifdef KROSS_RUBY_LIBRARY
00109     QString rubylib = QFile::encodeName( KLibLoader::self()->findLibrary(KROSS_RUBY_LIBRARY) );
00110     if(! rubylib.isEmpty()) { // If the Kross Ruby plugin exists we offer it as supported scripting language.
00111       InterpreterInfo::Option::Map rubyoptions;
00112       rubyoptions.replace("safelevel",
00113                           new InterpreterInfo::Option("safelevel", "Level of safety of the Ruby interpreter", QVariant(0)) // 0 -> unsafe, 4 -> very safe
00114                            );
00115       d->interpreterinfos.replace("ruby",
00116                                   new InterpreterInfo("ruby",
00117                                       rubylib, // library
00118                                       "*.rb", // file filter-wildcard
00119                                       QStringList() << /* "text/x-ruby" << */ "application/x-ruby", // mimetypes
00120                                       rubyoptions // options
00121                                                      )
00122                                  );
00123     } else {
00124         kdDebug() << "Ruby interpreter for kross in unavailable" << endl;
00125     }
00126 #endif
00127 }
00128 
00129 Manager::~Manager()
00130 {
00131     for(QMap<QString, InterpreterInfo*>::Iterator it = d->interpreterinfos.begin(); it != d->interpreterinfos.end(); ++it)
00132         delete it.data();
00133     delete d;
00134 }
00135 
00136 QMap<QString, InterpreterInfo*> Manager::getInterpreterInfos()
00137 {
00138     return d->interpreterinfos;
00139 }
00140 
00141 bool Manager::hasInterpreterInfo(const QString& interpretername) const
00142 {
00143     return d->interpreterinfos.contains(interpretername);
00144 }
00145 
00146 InterpreterInfo* Manager::getInterpreterInfo(const QString& interpretername)
00147 {
00148     return d->interpreterinfos[interpretername];
00149 }
00150 
00151 const QString Manager::getInterpreternameForFile(const QString& file)
00152 {
00153     QRegExp rx;
00154     rx.setWildcard(true);
00155     for(QMap<QString, InterpreterInfo*>::Iterator it = d->interpreterinfos.begin(); it != d->interpreterinfos.end(); ++it) {
00156         rx.setPattern((*it)->getWildcard());
00157         if( file.find(rx) >= 0 )
00158             return (*it)->getInterpretername();
00159     }
00160     return QString::null;
00161 }
00162 
00163 ScriptContainer::Ptr Manager::getScriptContainer(const QString& scriptname)
00164 {
00165     //TODO at the moment we don't share ScriptContainer instances.
00166 
00167     //if(d->m_scriptcontainers.contains(scriptname))
00168     //    return d->m_scriptcontainers[scriptname];
00169     ScriptContainer* scriptcontainer = new ScriptContainer(scriptname);
00170     //ScriptContainer script(this, scriptname);
00171     //d->m_scriptcontainers.replace(scriptname, scriptcontainer);
00172 
00173     return scriptcontainer;
00174 }
00175 
00176 Interpreter* Manager::getInterpreter(const QString& interpretername)
00177 {
00178     setException(0); // clear previous exceptions
00179 
00180     if(! d->interpreterinfos.contains(interpretername)) {
00181         setException( new Exception(QString(i18n("No such interpreter '%1'")).arg(interpretername)) );
00182         return 0;
00183     }
00184 
00185     return d->interpreterinfos[interpretername]->getInterpreter();
00186 }
00187 
00188 const QStringList Manager::getInterpreters()
00189 {
00190     QStringList list;
00191 
00192     QMap<QString, InterpreterInfo*>::Iterator it( d->interpreterinfos.begin() );
00193     for(; it != d->interpreterinfos.end(); ++it)
00194         list << it.key();
00195 
00196 //list << "TestCase";
00197 
00198     return  list;
00199 }
00200 
00201 bool Manager::addModule(Module::Ptr module)
00202 {
00203     QString name = module->getName();
00204     //if( d->modules.contains(name) ) return false;
00205     d->modules.replace(name, module);
00206     return true;
00207 }
00208 
00209 Module::Ptr Manager::loadModule(const QString& modulename)
00210 {
00211     Module::Ptr module = 0;
00212 
00213     if(d->modules.contains(modulename)) {
00214         module = d->modules[modulename];
00215         if(module)
00216             return module;
00217         else
00218             kdDebug() << QString("Manager::loadModule(%1) =======> Modulename registered, but module is invalid!").arg(modulename) << endl;
00219     }
00220 
00221     KLibLoader* loader = KLibLoader::self();
00222     KLibrary* lib = loader->globalLibrary( modulename.latin1() );
00223     if(! lib) {
00224         kdWarning() << QString("Failed to load module '%1': %2").arg(modulename).arg(loader->lastErrorMessage()) << endl;
00225         return 0;
00226     }
00227     kdDebug() << QString("Successfully loaded module '%1'").arg(modulename) << endl;
00228 
00229     def_module_func func;
00230     func = (def_module_func) lib->symbol("init_module");
00231 
00232     if(! func) {
00233         kdWarning() << QString("Failed to determinate init function in module '%1'").arg(modulename) << endl;
00234         return 0;
00235     }
00236 
00237     try {
00238         module = (Kross::Api::Module*) (func)(this);
00239     }
00240     catch(Kross::Api::Exception::Ptr e) {
00241         kdWarning() << e->toString() << endl;
00242         module = 0;
00243     }
00244     lib->unload();
00245 
00246     if(! module) {
00247         kdWarning() << QString("Failed to load module '%1'").arg(modulename) << endl;
00248         return 0;
00249     }
00250 
00251     // Don't remember module cause we like to have freeing it handled by the caller.
00252     //d->modules.replace(modulename, module);
00253 
00254     //kdDebug() << QString("Kross::Api::Manager::loadModule modulename='%1' module='%2'").arg(modulename).arg(module->toString()) << endl;
00255     return module;
00256 }
00257 
KDE Home | KDE Accessibility Home | Description of Access Keys