kexi

migratemanager.cpp

00001 /* This file is part of the KDE project
00002    Daniel Molkentin <molkentin@kde.org>
00003    Joseph Wenninger <jowenn@kde.org>
00004    Copyright (C) 2003-2004 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 "migratemanager.h"
00023 #include "migratemanager_p.h"
00024 #include "keximigrate.h"
00025 
00026 #include <klibloader.h>
00027 #include <kparts/componentfactory.h>
00028 #include <ktrader.h>
00029 #include <kdebug.h>
00030 #include <klocale.h>
00031 #include <kservice.h>
00032 
00033 #include <assert.h>
00034 
00035 #include <qapplication.h>
00036 
00037 //remove debug
00038 #undef KexiDBDbg
00039 #define KexiDBDbg if (0) kdDebug()
00040 
00041 using namespace KexiMigration;
00042 
00043 MigrateManagerInternal* MigrateManagerInternal::s_self = 0L;
00044 
00050 MigrateManager __manager;
00051 
00052 MigrateManagerInternal::MigrateManagerInternal() /* protected */
00053     : QObject( 0, "KexiMigrate::MigrateManagerInternal" )
00054     , Object()
00055     , m_drivers(17, false)
00056     , m_refCount(0)
00057     , lookupDriversNeeded(true)
00058 {
00059     m_drivers.setAutoDelete(true);
00060     m_serverResultNum=0;
00061 
00062 }
00063 
00064 MigrateManagerInternal::~MigrateManagerInternal()
00065 {
00066     KexiDBDbg << "MigrateManagerInternal::~MigrateManagerInternal()" << endl;
00067     m_drivers.clear();
00068     if ( s_self == this )
00069         s_self = 0;
00070     KexiDBDbg << "MigrateManagerInternal::~MigrateManagerInternal() ok" << endl;
00071 }
00072 
00073 void MigrateManagerInternal::slotAppQuits()
00074 {
00075     if (qApp->mainWidget() && qApp->mainWidget()->isVisible())
00076         return; //what a hack! - we give up when app is still there
00077     KexiDBDbg << "MigrateManagerInternal::slotAppQuits(): let's clear drivers..." << endl;
00078     m_drivers.clear();
00079 }
00080 
00081 MigrateManagerInternal *MigrateManagerInternal::self()
00082 {
00083     if (!s_self)
00084         s_self = new MigrateManagerInternal();
00085 
00086     return s_self;
00087 }
00088 
00089 bool MigrateManagerInternal::lookupDrivers()
00090 {
00091     if (!lookupDriversNeeded)
00092         return true;
00093 
00094     if (qApp) {
00095         connect(qApp,SIGNAL(aboutToQuit()),this,SLOT(slotAppQuits()));
00096     }
00097 //TODO: for QT-only version check for KInstance wrapper
00098 //      KexiDBWarn << "DriverManagerInternal::lookupDrivers(): cannot work without KInstance (KGlobal::instance()==0)!" << endl;
00099 //      setError("Driver Manager cannot work without KInstance (KGlobal::instance()==0)!");
00100 
00101     lookupDriversNeeded = false;
00102     clearError();
00103     KTrader::OfferList tlist = KTrader::self()->query("Kexi/MigrationDriver");
00104     KTrader::OfferList::ConstIterator it(tlist.constBegin());
00105     for(; it != tlist.constEnd(); ++it)
00106     {
00107         KService::Ptr ptr = (*it);
00108         QString srv_name = ptr->property("X-Kexi-MigrationDriverName").toString();
00109         if (srv_name.isEmpty()) {
00110             KexiDBWarn << "MigrateManagerInternal::lookupDrivers(): "
00111                 "X-Kexi-MigrationDriverName must be set for migration driver \"" 
00112                 << ptr->property("Name").toString() << "\" service!\n -- skipped!" << endl;
00113             continue;
00114         }
00115         if (m_services_lcase.contains(srv_name.lower())) {
00116             continue;
00117         }
00118 
00120 //<COPIED>
00121         QString srv_ver_str = ptr->property("X-Kexi-KexiMigrationVersion").toString();
00122         QStringList lst( QStringList::split(".", srv_ver_str) );
00123         int minor_ver, major_ver;
00124         bool ok = (lst.count() == 2);
00125         if (ok)
00126             major_ver = lst[0].toUInt(&ok);
00127         if (ok)
00128             minor_ver = lst[1].toUInt(&ok);
00129         if (!ok) {
00130             KexiDBWarn << "MigrateManagerInternal::lookupDrivers(): problem with detecting '"
00131             << srv_name.lower() << "' driver's version -- skipping it!" << endl;
00132             possibleProblems += QString("\"%1\" migration driver has unrecognized version; "
00133                 "required driver version is \"%2.%3\"")
00134                 .arg(srv_name.lower())
00135                 .arg(KexiMigration::versionMajor()).arg(KexiMigration::versionMinor());
00136             continue;
00137         }
00138         if (major_ver != KexiMigration::versionMajor() || minor_ver != KexiMigration::versionMinor()) {
00139             KexiDBWarn << QString("MigrateManagerInternal::lookupDrivers(): '%1' driver" 
00140                 " has version '%2' but required migration driver version is '%3.%4'\n"
00141                 " -- skipping this driver!").arg(srv_name.lower()).arg(srv_ver_str)
00142                 .arg(KexiMigration::versionMajor()).arg(KexiMigration::versionMinor()) << endl;
00143             possibleProblems += QString("\"%1\" migration driver has version \"%2\" "
00144                 "but required driver version is \"%3.%4\"")
00145                 .arg(srv_name.lower()).arg(srv_ver_str)
00146                 .arg(KexiMigration::versionMajor()).arg(KexiMigration::versionMinor());
00147             continue;
00148         }
00149 //</COPIED>
00150 
00151         QString mime = ptr->property("X-Kexi-FileDBDriverMime").toString().lower();
00152         QString drvType = ptr->property("X-Kexi-MigrationDriverType").toString().lower();
00153         if (drvType=="file") {
00154             if (!mime.isEmpty()) {
00155                 if (!m_services_by_mimetype.contains(mime)) {
00156                     m_services_by_mimetype.insert(mime, ptr);
00157                 }
00158                 else {
00159                     KexiDBWarn << "MigrateManagerInternal::lookupDrivers(): more than one driver for '" 
00160                         << mime << "' mime type!" << endl;
00161                 }
00162             }
00163         }
00164         else {
00165 #ifndef KEXI_SERVER_SUPPORT
00166             //no support for this driver
00167             continue;
00168 #endif
00169         }
00170 
00171         m_services.insert(srv_name, ptr);
00172         m_services_lcase.insert(srv_name.lower(), ptr);
00173         KexiDBDbg << "MigrateManager::lookupDrivers(): registered driver: " << ptr->name() 
00174             << "(" << ptr->library() << ")" << endl;
00175     }
00176 
00177     if (tlist.isEmpty())
00178     {
00179         setError(ERR_DRIVERMANAGER, i18n("Could not find any import/export database drivers.") );
00180         return false;
00181     }
00182     return true;
00183 }
00184 
00185 KexiMigrate* MigrateManagerInternal::driver(const QString& name)
00186 {
00187     if (!lookupDrivers())
00188         return 0;
00189     
00190     clearError();
00191     KexiDBDbg << "MigrationrManagerInternal::migrationDriver(): loading " << name << endl;
00192 
00193     KexiMigrate *drv = name.isEmpty() ? 0 : m_drivers.find(name.latin1());
00194     if (drv)
00195         return drv; //cached
00196 
00197     if (!m_services_lcase.contains(name.lower())) {
00198         setError(ERR_DRIVERMANAGER, i18n("Could not find import/export database driver \"%1\".").arg(name) );
00199         return 0;
00200     }
00201 
00202     KService::Ptr ptr= *(m_services_lcase.find(name.lower()));
00203     QString srv_name = ptr->property("X-Kexi-MigrationDriverName").toString();
00204 
00205     KexiDBDbg << "MigrateManagerInternal::driver(): library: "<<ptr->library()<<endl;
00206     drv = KParts::ComponentFactory::createInstanceFromService<KexiMigrate>(ptr,
00207         this, srv_name.latin1(), QStringList(),&m_serverResultNum);
00208 
00209     if (!drv) {
00210         setError(ERR_DRIVERMANAGER, i18n("Could not load import/export database driver \"%1\".")
00211                 .arg(name) );
00212         if (m_componentLoadingErrors.isEmpty()) {//fill errtable on demand
00213             m_componentLoadingErrors[KParts::ComponentFactory::ErrNoServiceFound]="ErrNoServiceFound";
00214             m_componentLoadingErrors[KParts::ComponentFactory::ErrServiceProvidesNoLibrary]="ErrServiceProvidesNoLibrary";
00215             m_componentLoadingErrors[KParts::ComponentFactory::ErrNoLibrary]="ErrNoLibrary";
00216             m_componentLoadingErrors[KParts::ComponentFactory::ErrNoFactory]="ErrNoFactory";
00217             m_componentLoadingErrors[KParts::ComponentFactory::ErrNoComponent]="ErrNoComponent";
00218         }
00219         m_serverResultName=m_componentLoadingErrors[m_serverResultNum];
00220         return 0;
00221     }
00222     KexiDBDbg << "MigrateManagerInternal::driver(): loading succeed: " << name <<endl;
00223     KexiDBDbg << "drv="<<(long)drv <<endl;
00224 
00225 //  drv->setName(srv_name.latin1());
00226 //  drv->d->service = ptr; //store info
00227 //  drv->d->fileDBDriverMimeType = ptr->property("X-Kexi-FileDBDriverMime").toString();
00228 //  drv->d->initInternalProperties();
00229 
00230     if (!drv->isValid()) {
00231         setError(drv);
00232         delete drv;
00233         return 0;
00234     }
00235 
00236     m_drivers.insert(name.latin1(), drv); //cache it
00237     return drv;
00238 }
00239 
00240 void MigrateManagerInternal::incRefCount()
00241 {
00242     m_refCount++;
00243     KexiDBDbg << "MigrateManagerInternal::incRefCount(): " << m_refCount << endl;
00244 }
00245 
00246 void MigrateManagerInternal::decRefCount()
00247 {
00248     m_refCount--;
00249     KexiDBDbg << "MigrateManagerInternal::decRefCount(): " << m_refCount << endl;
00250 //  if (m_refCount<1) {
00251 //      KexiDBDbg<<"KexiDB::DriverManagerInternal::decRefCount(): reached m_refCount<1 -->deletelater()"<<endl;
00252 //      s_self=0;
00253 //      deleteLater();
00254 //  }
00255 }
00256 
00257 // ---------------------------
00258 // --- DriverManager impl. ---
00259 // ---------------------------
00260 
00261 MigrateManager::MigrateManager()
00262     : QObject( 0, "KexiMigrate::MigrateManager" )
00263     , Object()
00264     , d_int( MigrateManagerInternal::self() )
00265 {
00266     d_int->incRefCount();
00267 //  if ( !s_self )
00268 //      s_self = this;
00269 //  lookupDrivers();
00270 }
00271 
00272 MigrateManager::~MigrateManager()
00273 {
00274     KexiDBDbg << "MigrateManager::~MigrateManager()" << endl;
00275 /*  Connection *conn;
00276     for ( conn = m_connections.first(); conn ; conn = m_connections.next() ) {
00277         conn->disconnect();
00278         conn->m_driver = 0; //don't let the connection touch our driver now
00279         m_connections.remove();
00280         delete conn;
00281     }*/
00282 
00283     d_int->decRefCount();
00284     if (d_int->m_refCount==0) {
00285         //delete internal drv manager!
00286         delete d_int;
00287     }
00288 //  if ( s_self == this )
00289         //s_self = 0;
00290     KexiDBDbg << "MigrateManager::~MigrateManager() ok" << endl;
00291 }
00292 
00293 
00294 const QStringList MigrateManager::driverNames()
00295 {
00296     if (!d_int->lookupDrivers()) {
00297         kdDebug() << "MigrateManager::driverNames() lookupDrivers failed" << endl;
00298         return QStringList();
00299     }
00300     
00301     if (d_int->m_services.isEmpty()) {
00302         kdDebug() << "MigrateManager::driverNames() MigrateManager::ServicesMap is empty" << endl;
00303         return QStringList();
00304     }
00305 
00306     if (d_int->error()) {
00307         kdDebug() << "MigrateManager::driverNames() Error: " << d_int->errorMsg() << endl;
00308         return QStringList();
00309     }
00310 
00311     return d_int->m_services.keys();
00312 }
00313 
00314 QString MigrateManager::driverForMimeType(const QString &mimeType)
00315 {
00316     if (!d_int->lookupDrivers()) {
00317         kdDebug() << "MigrateManager::driverForMimeType() lookupDrivers() failed" << endl;
00318         setError(d_int);
00319         return 0;
00320     }
00321     
00322     KService::Ptr ptr = d_int->m_services_by_mimetype[mimeType.lower()];
00323     if (!ptr) {
00324         kdDebug() << QString("MigrateManager::driverForMimeType(%1) No such mimetype").arg(mimeType) << endl;
00325         return QString::null;
00326     }
00327 
00328     return ptr->property("X-Kexi-MigrationDriverName").toString();
00329 }
00330 
00331 KexiMigrate* MigrateManager::driver(const QString& name)
00332 {
00333     KexiMigrate *drv = d_int->driver(name);
00334     if (d_int->error()) {
00335         kdDebug() << QString("MigrateManager::driver(%1) Error: %2").arg(name).arg(d_int->errorMsg()) << endl;
00336         setError(d_int);
00337     }
00338     return drv;
00339 }
00340 
00341 QString MigrateManager::serverErrorMsg()
00342 {
00343     return d_int->m_serverErrMsg;
00344 }
00345 
00346 int MigrateManager::serverResult()
00347 {
00348     return d_int->m_serverResultNum;
00349 }
00350 
00351 QString MigrateManager::serverResultName()
00352 {
00353     return d_int->m_serverResultName;
00354 }
00355 
00356 void MigrateManager::drv_clearServerResult()
00357 {
00358     d_int->m_serverErrMsg=QString::null;
00359     d_int->m_serverResultNum=0;
00360     d_int->m_serverResultName=QString::null;
00361 }
00362 
00363 QString MigrateManager::possibleProblemsInfoMsg() const
00364 {
00365     if (d_int->possibleProblems.isEmpty())
00366         return QString::null;
00367     QString str;
00368     str.reserve(1024);
00369     str = "<ul>";
00370     for (QStringList::ConstIterator it = d_int->possibleProblems.constBegin();
00371         it!=d_int->possibleProblems.constEnd(); ++it)
00372     {
00373         str += (QString::fromLatin1("<li>") + *it + QString::fromLatin1("</li>"));
00374     }
00375     str += "</ul>";
00376     return str;
00377 }
00378 
00379 //------------------------
00380 
00381 int KexiMigration::versionMajor()
00382 {
00383     return KEXI_MIGRATION_VERSION_MAJOR;
00384 }
00385 
00386 int KexiMigration::versionMinor()
00387 {
00388     return KEXI_MIGRATION_VERSION_MINOR;
00389 }
00390 
00391 #include "migratemanager_p.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys