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 #include <kdebug.h>
00035 #include <kstaticdeleter.h>
00036 #include <klibloader.h>
00037 
00038 extern "C"
00039 {
00040     typedef Kross::Api::Object* (*def_module_func)(Kross::Api::Manager*);
00041 }
00042 
00043 using namespace Kross::Api;
00044 
00045 namespace Kross { namespace Api {
00046 
00047     /// @internal
00048     class ManagerPrivate
00049     {
00050         public:
00051             /// List of \a InterpreterInfo instances.
00052             QMap<QString, InterpreterInfo*> interpreterinfos;
00053 
00054             /// Loaded modules.
00055             QMap<QString, Module::Ptr> modules;
00056     };
00057 
00058     /**
00059      * Free the static Manager instance if the lib is unloaded or
00060      * the app terminates by using the KStaticDeleter template.
00061      */
00062     static KStaticDeleter<Manager> m_managerdeleter;
00063 
00064     /**
00065      * The Manager-singleton instance is NULL by default till the
00066      * Manager::scriptManager() method got called first time.
00067      */
00068     static Manager* m_manager = 0;
00069 
00070 }}
00071 
00072 Manager* Manager::scriptManager()
00073 {
00074     if(! m_manager) {
00075         // Create the Manager-singleton on demand and let the
00076         // KStaticDeleter take care of freeing it if not needed
00077         // any longer.
00078         m_managerdeleter.setObject(m_manager, new Manager());
00079     }
00080 
00081     // and finally return the singleton.
00082     return m_manager;
00083 }
00084 
00085 Manager::Manager()
00086     : MainModule("Kross") // the manager has the name "Kross"
00087     , d( new ManagerPrivate() )
00088 {
00089 #ifdef KROSS_PYTHON_LIBRARY
00090     QString pythonlib = QFile::encodeName( KLibLoader::self()->findLibrary(KROSS_PYTHON_LIBRARY) );
00091     if(! pythonlib.isEmpty()) { // If the Kross Python plugin exists we offer it as supported scripting language.
00092         InterpreterInfo::Option::Map pythonoptions;
00093         pythonoptions.replace("restricted",
00094             new InterpreterInfo::Option("Restricted", "Restricted Python interpreter", QVariant(false,0))
00095         );
00096         d->interpreterinfos.replace("python",
00097             new InterpreterInfo("python",
00098                 pythonlib, // library
00099                 "*.py", // file filter-wildcard
00100                 QStringList() << /* "text/x-python" << */ "application/x-python", // mimetypes
00101                 pythonoptions // options
00102             )
00103         );
00104     }
00105 #endif
00106 #ifdef KROSS_RUBY_LIBRARY
00107     QString rubylib = QFile::encodeName( KLibLoader::self()->findLibrary(KROSS_RUBY_LIBRARY) );
00108     if(! rubylib.isEmpty()) { // If the Kross Ruby plugin exists we offer it as supported scripting language.
00109       InterpreterInfo::Option::Map rubyoptions;
00110       rubyoptions.replace("safelevel",
00111                           new InterpreterInfo::Option("safelevel", "Level of safety of the Ruby interpreter", QVariant(0)) // 0 -> unsafe, 4 -> very safe
00112                            );
00113       d->interpreterinfos.replace("ruby",
00114                                   new InterpreterInfo("ruby",
00115                                       rubylib, // library
00116                                       "*.rb", // file filter-wildcard
00117                                       QStringList() << /* "text/x-ruby" << */ "application/x-ruby", // mimetypes
00118                                       rubyoptions // options
00119                                                      )
00120                                  );
00121     } else {
00122         kdDebug() << "Ruby interpreter for kross in unavailable" << endl;
00123     }
00124 #endif
00125 }
00126 
00127 Manager::~Manager()
00128 {
00129     for(QMap<QString, InterpreterInfo*>::Iterator it = d->interpreterinfos.begin(); it != d->interpreterinfos.end(); ++it)
00130         delete it.data();
00131     delete d;
00132 }
00133 
00134 QMap<QString, InterpreterInfo*> Manager::getInterpreterInfos()
00135 {
00136     return d->interpreterinfos;
00137 }
00138 
00139 bool Manager::hasInterpreterInfo(const QString& interpretername) const
00140 {
00141     return d->interpreterinfos.contains(interpretername);
00142 }
00143 
00144 InterpreterInfo* Manager::getInterpreterInfo(const QString& interpretername)
00145 {
00146     return d->interpreterinfos[interpretername];
00147 }
00148 
00149 const QString& Manager::getInterpreternameForFile(const QString& file)
00150 {
00151     QRegExp rx;
00152     rx.setWildcard(true);
00153     for(QMap<QString, InterpreterInfo*>::Iterator it = d->interpreterinfos.begin(); it != d->interpreterinfos.end(); ++it) {
00154         rx.setPattern((*it)->getWildcard());
00155         if( file.find(rx) >= 0 )
00156             return (*it)->getInterpretername();
00157     }
00158     return QString::null;
00159 }
00160 
00161 ScriptContainer::Ptr Manager::getScriptContainer(const QString& scriptname)
00162 {
00163     //TODO at the moment we don't share ScriptContainer instances.
00164 
00165     //if(d->m_scriptcontainers.contains(scriptname))
00166     //    return d->m_scriptcontainers[scriptname];
00167     ScriptContainer* scriptcontainer = new ScriptContainer(scriptname);
00168     //ScriptContainer script(this, scriptname);
00169     //d->m_scriptcontainers.replace(scriptname, scriptcontainer);
00170 
00171     return scriptcontainer;
00172 }
00173 
00174 Interpreter* Manager::getInterpreter(const QString& interpretername)
00175 {
00176     setException(0); // clear previous exceptions
00177 
00178     if(! d->interpreterinfos.contains(interpretername)) {
00179         setException( new Exception(QString("No such interpreter '%1'").arg(interpretername)) );
00180         return 0;
00181     }
00182 
00183     return d->interpreterinfos[interpretername]->getInterpreter();
00184 }
00185 
00186 const QStringList Manager::getInterpreters()
00187 {
00188     QStringList list;
00189 
00190     QMap<QString, InterpreterInfo*>::Iterator it( d->interpreterinfos.begin() );
00191     for(; it != d->interpreterinfos.end(); ++it)
00192         list << it.key();
00193 
00194 //list << "TestCase";
00195 
00196     return  list;
00197 }
00198 
00199 bool Manager::addModule(Module::Ptr module)
00200 {
00201     QString name = module->getName();
00202     //if( d->modules.contains(name) ) return false;
00203     d->modules.replace(name, module);
00204     return true;
00205 }
00206 
00207 Module::Ptr Manager::loadModule(const QString& modulename)
00208 {
00209     Module::Ptr module = 0;
00210 
00211     if(d->modules.contains(modulename)) {
00212         module = d->modules[modulename];
00213         if(module)
00214             return module;
00215         else
00216             kdDebug() << QString("Manager::loadModule(%1) =======> Modulename registered, but module is invalid!").arg(modulename) << endl;
00217     }
00218 
00219     KLibLoader* loader = KLibLoader::self();
00220     KLibrary* lib = loader->globalLibrary( modulename.latin1() );
00221     if(! lib) {
00222         kdWarning() << QString("Failed to load module '%1': %2").arg(modulename).arg(loader->lastErrorMessage()) << endl;
00223         return 0;
00224     }
00225     kdDebug() << QString("Successfully loaded module '%1'").arg(modulename) << endl;
00226 
00227     def_module_func func;
00228     func = (def_module_func) lib->symbol("init_module");
00229 
00230     if(! func) {
00231         kdWarning() << QString("Failed to determinate init function in module '%1'").arg(modulename) << endl;
00232         return 0;
00233     }
00234 
00235     module = (Kross::Api::Module*) (func)(this);
00236     lib->unload();
00237 
00238     if(! module) {
00239         kdWarning() << QString("Failed to load module '%1'").arg(modulename) << endl;
00240         return 0;
00241     }
00242 
00243     // Don't remember module cause we like to have freeing it handled by the caller.
00244     //d->modules.replace(modulename, module);
00245 
00246     //kdDebug() << QString("Kross::Api::Manager::loadModule modulename='%1' module='%2'").arg(modulename).arg(module->toString()) << endl;
00247     return module;
00248 }
00249 

Generated on Thu Feb 9 17:59:10 2006 for Kross by  doxygen 1.4.6