kexi

drivermanager.cpp

00001 /* This file is part of the KDE project
00002    Copyright (C) 2003 Daniel Molkentin <molkentin@kde.org>
00003    Copyright (C) 2003 Joseph Wenninger <jowenn@kde.org>
00004    Copyright (C) 2003-2006 Jaroslaw Staniek <js@iidea.pl>
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 
00011    This program is distributed in the hope that it will be useful,
00012    but WITHOUT ANY WARRANTY; without even the implied warranty of
00013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014    Library General Public License for more details.
00015 
00016    You should have received a copy of the GNU Library General Public License
00017    along with this program; see the file COPYING.  If not, write to
00018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00019  * Boston, MA 02110-1301, USA.
00020 */
00021 
00022 #include <kexidb/drivermanager.h>
00023 #include <kexidb/drivermanager_p.h>
00024 
00025 #include <kexidb/driver.h>
00026 #include <kexidb/driver_p.h>
00027 #include <kexidb/error.h>
00028 
00029 #include <klibloader.h>
00030 #include <kparts/componentfactory.h>
00031 #include <ktrader.h>
00032 #include <kdebug.h>
00033 #include <klocale.h>
00034 #include <kservice.h>
00035 
00036 #include <assert.h>
00037 
00038 #include <qapplication.h>
00039 
00040 //remove debug
00041 #undef KexiDBDbg
00042 #define KexiDBDbg if (0) kdDebug()
00043 
00044 using namespace KexiDB;
00045 
00046 DriverManagerInternal* DriverManagerInternal::s_self = 0L;
00047 
00048 
00049 DriverManagerInternal::DriverManagerInternal() /* protected */
00050     : QObject( 0, "KexiDB::DriverManager" )
00051     , Object()
00052     , m_drivers(17, false)
00053     , m_refCount(0)
00054     , lookupDriversNeeded(true)
00055 {
00056     m_drivers.setAutoDelete(true);
00057     m_serverResultNum=0;
00058 
00059 }
00060 
00061 DriverManagerInternal::~DriverManagerInternal()
00062 {
00063     KexiDBDbg << "DriverManagerInternal::~DriverManagerInternal()" << endl;
00064     m_drivers.clear();
00065     if ( s_self == this )
00066         s_self = 0;
00067     KexiDBDbg << "DriverManagerInternal::~DriverManagerInternal() ok" << endl;
00068 }
00069 
00070 void DriverManagerInternal::slotAppQuits()
00071 {
00072     if (qApp->mainWidget() && qApp->mainWidget()->isVisible())
00073         return; //what a hack! - we give up when app is still there
00074     KexiDBDbg << "DriverManagerInternal::slotAppQuits(): let's clear drivers..." << endl;
00075     m_drivers.clear();
00076 }
00077 
00078 DriverManagerInternal *DriverManagerInternal::self()
00079 {
00080     if (!s_self)
00081         s_self = new DriverManagerInternal();
00082 
00083     return s_self;
00084 }
00085 
00086 bool DriverManagerInternal::lookupDrivers()
00087 {
00088     if (!lookupDriversNeeded)
00089         return true;
00090 
00091     if (qApp) {
00092         connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(slotAppQuits()));
00093     }
00094 //TODO: for QT-only version check for KInstance wrapper
00095 //      KexiDBWarn << "DriverManagerInternal::lookupDrivers(): cannot work without KInstance (KGlobal::instance()==0)!" << endl;
00096 //      setError("Driver Manager cannot work without KInstance (KGlobal::instance()==0)!");
00097 
00098     lookupDriversNeeded = false;
00099     clearError();
00100     KTrader::OfferList tlist = KTrader::self()->query("Kexi/DBDriver");
00101     KTrader::OfferList::ConstIterator it(tlist.constBegin());
00102     for(; it != tlist.constEnd(); ++it)
00103     {
00104         KService::Ptr ptr = (*it);
00105         if (!ptr->property("Library").toString().startsWith("kexidb_")) {
00106             KexiDBWarn << "DriverManagerInternal::lookupDrivers():"
00107                 " X-KDE-Library == " << ptr->property("Library").toString()
00108                 << ": no \"kexidb_\" prefix -- skipped to avoid potential conflicts!" << endl;
00109             continue;
00110         }
00111         QString srv_name = ptr->property("X-Kexi-DriverName").toString();
00112         if (srv_name.isEmpty()) {
00113             KexiDBWarn << "DriverManagerInternal::lookupDrivers():"
00114                 " X-Kexi-DriverName must be set for KexiDB driver \"" 
00115                 << ptr->property("Name").toString() << "\" service!\n -- skipped!" << endl;
00116             continue;
00117         }
00118         if (m_services_lcase.contains(srv_name.lower())) {
00119             KexiDBWarn << "DriverManagerInternal::lookupDrivers(): more than one driver named '" 
00120                 << srv_name.lower() << "'\n -- skipping this one!" << endl;
00121             continue;
00122         }
00123 
00124         QString srv_ver_str = ptr->property("X-Kexi-KexiDBVersion").toString();
00125         QStringList lst( QStringList::split(".", srv_ver_str) );
00126         uint minor_ver, major_ver;
00127         bool ok = (lst.count() == 2);
00128         if (ok)
00129             major_ver = lst[0].toUInt(&ok);
00130         if (ok)
00131             minor_ver = lst[1].toUInt(&ok);
00132         if (!ok) {
00133             KexiDBWarn << "DriverManagerInternal::lookupDrivers(): problem with detecting '"
00134             << srv_name.lower() << "' driver's version -- skipping it!" << endl;
00135             continue;
00136         }
00137         if (major_ver != KexiDB::version().major || minor_ver != KexiDB::version().minor) {
00138             KexiDBWarn << QString("DriverManagerInternal::lookupDrivers(): '%1' driver" 
00139                 " has version '%2' but required KexiDB driver version is '%3.%4'\n"
00140                 " -- skipping this driver!").arg(srv_name.lower()).arg(srv_ver_str)
00141                 .arg(KexiDB::version().major).arg(KexiDB::version().minor) << endl;
00142             possibleProblems += QString("\"%1\" database driver has version \"%2\" "
00143                 "but required driver version is \"%3.%4\"")
00144                 .arg(srv_name.lower()).arg(srv_ver_str)
00145                 .arg(KexiDB::version().major).arg(KexiDB::version().minor);
00146             continue;
00147         }
00148 
00149         QString drvType = ptr->property("X-Kexi-DriverType").toString().lower();
00150         if (drvType=="file") {
00151             //new property: a list of supported mime types
00152             QStringList mimes( ptr->property("X-Kexi-FileDBDriverMimeList").toStringList() );
00153             //single mime is obsolete, but we're handling it:
00154             {
00155                 QString mime( ptr->property("X-Kexi-FileDBDriverMime").toString().lower() );
00156                 if (!mime.isEmpty())
00157                     mimes.append( mime );
00158             }
00159 
00160             //store association of this driver with all listed mime types
00161             for (QStringList::ConstIterator mime_it = mimes.constBegin(); mime_it!=mimes.constEnd(); ++mime_it) {
00162                 QString mime( (*mime_it).lower() );
00163                 if (!m_services_by_mimetype.contains(mime)) {
00164                     m_services_by_mimetype.insert(mime, ptr);
00165                 }
00166                 else {
00167                     KexiDBWarn << "DriverManagerInternal::lookupDrivers(): more than one driver for '" 
00168                     << mime << "' mime type!" << endl;
00169                 }
00170             }
00171         }
00172         else {
00173 #ifndef KEXI_SERVER_SUPPORT
00174             //no support for this driver
00175             continue;
00176 #endif
00177         }
00178 
00179         m_services.insert(srv_name, ptr);
00180         m_services_lcase.insert(srv_name.lower(), ptr);
00181         KexiDBDbg << "KexiDB::DriverManager::lookupDrivers(): registered driver: " << ptr->name() << "(" << ptr->library() << ")" << endl;
00182     }
00183 
00184     if (tlist.isEmpty())
00185     {
00186         setError(ERR_DRIVERMANAGER, i18n("Could not find any database drivers.") );
00187         return false;
00188     }
00189     return true;
00190 }
00191 
00192 KexiDB::Driver::Info DriverManagerInternal::driverInfo(const QString &name)
00193 {
00194     KexiDB::Driver::Info i = m_driversInfo[name.lower()];
00195     if (!error() && i.name.isEmpty())
00196         setError(ERR_DRIVERMANAGER, i18n("Could not find database driver \"%1\".").arg(name) );
00197     return i;
00198 }
00199 
00200 Driver* DriverManagerInternal::driver(const QString& name)
00201 {
00202     if (!lookupDrivers())
00203         return 0;
00204     
00205     clearError();
00206     KexiDBDbg << "DriverManager::driver(): loading " << name << endl;
00207 
00208     Driver *drv = name.isEmpty() ? 0 : m_drivers.find(name.latin1());
00209     if (drv)
00210         return drv; //cached
00211 
00212     if (!m_services_lcase.contains(name.lower())) {
00213         setError(ERR_DRIVERMANAGER, i18n("Could not find database driver \"%1\".").arg(name) );
00214         return 0;
00215     }
00216 
00217     KService::Ptr ptr= *(m_services_lcase.find(name.lower()));
00218     QString srv_name = ptr->property("X-Kexi-DriverName").toString();
00219 
00220     KexiDBDbg << "KexiDBInterfaceManager::load(): library: "<<ptr->library()<<endl;
00221     drv = KParts::ComponentFactory::createInstanceFromService<KexiDB::Driver>(ptr,
00222         this, srv_name.latin1(), QStringList(),&m_serverResultNum);
00223 
00224     if (!drv) {
00225         setError(ERR_DRIVERMANAGER, i18n("Could not load database driver \"%1\".")
00226                 .arg(name) );
00227         if (m_componentLoadingErrors.isEmpty()) {//fill errtable on demand
00228             m_componentLoadingErrors[KParts::ComponentFactory::ErrNoServiceFound]="ErrNoServiceFound";
00229             m_componentLoadingErrors[KParts::ComponentFactory::ErrServiceProvidesNoLibrary]="ErrServiceProvidesNoLibrary";
00230             m_componentLoadingErrors[KParts::ComponentFactory::ErrNoLibrary]="ErrNoLibrary";
00231             m_componentLoadingErrors[KParts::ComponentFactory::ErrNoFactory]="ErrNoFactory";
00232             m_componentLoadingErrors[KParts::ComponentFactory::ErrNoComponent]="ErrNoComponent";
00233         }
00234         m_serverResultName=m_componentLoadingErrors[m_serverResultNum];
00235         return 0;
00236     }
00237     KexiDBDbg << "KexiDBInterfaceManager::load(): loading succeed: " << name <<endl;
00238 //  KexiDBDbg << "drv="<<(long)drv <<endl;
00239 
00240 //  drv->setName(srv_name.latin1());
00241     drv->d->service = ptr.data(); //store info
00242     drv->d->fileDBDriverMimeType = ptr->property("X-Kexi-FileDBDriverMime").toString();
00243     drv->d->initInternalProperties();
00244 
00245     if (!drv->isValid()) {
00246         setError(drv);
00247         delete drv;
00248         return 0;
00249     }
00250     m_drivers.insert(name.latin1(), drv); //cache it
00251     return drv;
00252 }
00253 
00254 void DriverManagerInternal::incRefCount()
00255 {
00256     m_refCount++;
00257     KexiDBDbg << "DriverManagerInternal::incRefCount(): " << m_refCount << endl;
00258 }
00259 
00260 void DriverManagerInternal::decRefCount()
00261 {
00262     m_refCount--;
00263     KexiDBDbg << "DriverManagerInternal::decRefCount(): " << m_refCount << endl;
00264 //  if (m_refCount<1) {
00265 //      KexiDBDbg<<"KexiDB::DriverManagerInternal::decRefCount(): reached m_refCount<1 -->deletelater()"<<endl;
00266 //      s_self=0;
00267 //      deleteLater();
00268 //  }
00269 }
00270 
00271 void DriverManagerInternal::aboutDelete( Driver* drv )
00272 {
00273     m_drivers.take(drv->name());
00274 }
00275 
00276 
00277 
00278 // ---------------------------
00279 // --- DriverManager impl. ---
00280 // ---------------------------
00281 
00282 DriverManager::DriverManager()
00283     : QObject( 0, "KexiDB::DriverManager" )
00284     , Object()
00285     , d_int( DriverManagerInternal::self() )
00286 {
00287     d_int->incRefCount();
00288 //  if ( !s_self )
00289 //      s_self = this;
00290 //  lookupDrivers();
00291 }
00292 
00293 DriverManager::~DriverManager()
00294 {
00295     KexiDBDbg << "DriverManager::~DriverManager()" << endl;
00296 /*  Connection *conn;
00297     for ( conn = m_connections.first(); conn ; conn = m_connections.next() ) {
00298         conn->disconnect();
00299         conn->m_driver = 0; //don't let the connection touch our driver now
00300         m_connections.remove();
00301         delete conn;
00302     }*/
00303 
00304     d_int->decRefCount();
00305     if (d_int->m_refCount==0) {
00306         //delete internal drv manager!
00307         delete d_int;
00308     }
00309 //  if ( s_self == this )
00310         //s_self = 0;
00311     KexiDBDbg << "DriverManager::~DriverManager() ok" << endl;
00312 }
00313 
00314 const KexiDB::Driver::InfoMap DriverManager::driversInfo()
00315 {
00316     if (!d_int->lookupDrivers())
00317         return KexiDB::Driver::InfoMap();
00318     
00319     if (!d_int->m_driversInfo.isEmpty())
00320         return d_int->m_driversInfo;
00321     ServicesMap::ConstIterator it;
00322     for ( it=d_int->m_services.constBegin() ; it != d_int->m_services.constEnd(); ++it ) {
00323         Driver::Info info;
00324         KService::Ptr ptr = it.data();
00325         info.name = ptr->property("X-Kexi-DriverName").toString();
00326         info.caption = ptr->property("Name").toString();
00327         info.comment = ptr->property("Comment").toString();
00328         if (info.caption.isEmpty())
00329             info.caption = info.name;
00330         info.fileBased = (ptr->property("X-Kexi-DriverType").toString().lower()=="file");
00331         if (info.fileBased)
00332             info.fileDBMimeType = ptr->property("X-Kexi-FileDBDriverMime").toString().lower();
00333         QVariant v = ptr->property("X-Kexi-DoNotAllowProjectImportingTo");
00334         info.allowImportingTo = v.isNull() ? true : !v.toBool();
00335         d_int->m_driversInfo.insert(info.name.lower(), info);
00336     }
00337     return d_int->m_driversInfo;
00338 }
00339 
00340 const QStringList DriverManager::driverNames()
00341 {
00342     if (!d_int->lookupDrivers())
00343         return QStringList();
00344     
00345     if (d_int->m_services.isEmpty() && d_int->error())
00346         return QStringList();
00347     return d_int->m_services.keys();
00348 }
00349 
00350 KexiDB::Driver::Info DriverManager::driverInfo(const QString &name)
00351 {
00352     driversInfo();
00353     KexiDB::Driver::Info i = d_int->driverInfo(name);
00354     if (d_int->error())
00355         setError(d_int);
00356     return i;
00357 }
00358 
00359 KService::Ptr DriverManager::serviceInfo(const QString &name)
00360 {
00361     if (!d_int->lookupDrivers()) {
00362         setError(d_int);
00363         return KService::Ptr();
00364     }
00365     
00366     clearError();
00367     if (d_int->m_services_lcase.contains(name.lower())) {
00368         return *d_int->m_services_lcase.find(name.lower());
00369     } else {
00370         setError(ERR_DRIVERMANAGER, i18n("No such driver service: \"%1\".").arg(name) );
00371         return KService::Ptr();
00372     }
00373 }
00374 
00375 const DriverManager::ServicesMap& DriverManager::services()
00376 {
00377     d_int->lookupDrivers();
00378     
00379     return d_int->m_services;
00380 }
00381 
00382 QString DriverManager::lookupByMime(const QString &mimeType)
00383 {
00384     if (!d_int->lookupDrivers()) {
00385         setError(d_int);
00386         return 0;
00387     }
00388     
00389     KService::Ptr ptr = d_int->m_services_by_mimetype[mimeType.lower()];
00390     if (!ptr)
00391         return QString::null;
00392     return ptr->property("X-Kexi-DriverName").toString();
00393 }
00394 
00395 Driver* DriverManager::driver(const QString& name)
00396 {
00397     Driver *drv = d_int->driver(name);
00398     if (d_int->error())
00399         setError(d_int);
00400     return drv;
00401 }
00402 
00403 QString DriverManager::serverErrorMsg()
00404 {
00405     return d_int->m_serverErrMsg;
00406 }
00407 
00408 int DriverManager::serverResult()
00409 {
00410     return d_int->m_serverResultNum;
00411 }
00412 
00413 QString DriverManager::serverResultName()
00414 {
00415     return d_int->m_serverResultName;
00416 }
00417 
00418 void DriverManager::drv_clearServerResult()
00419 {
00420     d_int->m_serverErrMsg=QString::null;
00421     d_int->m_serverResultNum=0;
00422     d_int->m_serverResultName=QString::null;
00423 }
00424 
00425 QString DriverManager::possibleProblemsInfoMsg() const
00426 {
00427     if (d_int->possibleProblems.isEmpty())
00428         return QString::null;
00429     QString str;
00430     str.reserve(1024);
00431     str = "<ul>";
00432     for (QStringList::ConstIterator it = d_int->possibleProblems.constBegin();
00433         it!=d_int->possibleProblems.constEnd(); ++it)
00434     {
00435         str += (QString::fromLatin1("<li>") + *it + QString::fromLatin1("</li>"));
00436     }
00437     str += "</ul>";
00438     return str;
00439 }
00440 
00441 #include "drivermanager_p.moc"
00442 
KDE Home | KDE Accessibility Home | Description of Access Keys