migratemanager.cpp
1/* This file is part of the KDE project
2 Daniel Molkentin <molkentin@kde.org>
3 Joseph Wenninger <jowenn@kde.org>
4 Copyright (C) 2003-2004 Jaroslaw Staniek <js@iidea.pl>
5
6 This program is free software; you can redistribute it and/or
7 modify it under the terms of the GNU Library General Public
8 License as published by the Free Software Foundation; either
9 version 2 of the License, or (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 Library General Public License for more details.
15
16 You should have received a copy of the GNU Library General Public License
17 along with this program; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20*/
21
22#include "migratemanager.h"
23#include "migratemanager_p.h"
24#include "keximigrate.h"
25
26#include <klibloader.h>
27#include <tdeparts/componentfactory.h>
28#include <ktrader.h>
29#include <kdebug.h>
30#include <tdelocale.h>
31#include <kservice.h>
32
33#include <assert.h>
34
35#include <tqapplication.h>
36
37//remove debug
38#undef KexiDBDbg
39#define KexiDBDbg if (0) kdDebug()
40
41using namespace KexiMigration;
42
43MigrateManagerInternal* MigrateManagerInternal::s_self = 0L;
44
50MigrateManager __manager;
51
52MigrateManagerInternal::MigrateManagerInternal() /* protected */
53 : TQObject( 0, "KexiMigrate::MigrateManagerInternal" )
54 , Object()
55 , m_drivers(17, false)
56 , m_refCount(0)
57 , lookupDriversNeeded(true)
58{
59 m_drivers.setAutoDelete(true);
60 m_serverResultNum=0;
61
62}
63
64MigrateManagerInternal::~MigrateManagerInternal()
65{
66 KexiDBDbg << "MigrateManagerInternal::~MigrateManagerInternal()" << endl;
67 m_drivers.clear();
68 if ( s_self == this )
69 s_self = 0;
70 KexiDBDbg << "MigrateManagerInternal::~MigrateManagerInternal() ok" << endl;
71}
72
73void MigrateManagerInternal::slotAppQuits()
74{
75 if (tqApp->mainWidget() && tqApp->mainWidget()->isVisible())
76 return; //what a hack! - we give up when app is still there
77 KexiDBDbg << "MigrateManagerInternal::slotAppQuits(): let's clear drivers..." << endl;
78 m_drivers.clear();
79}
80
81MigrateManagerInternal *MigrateManagerInternal::self()
82{
83 if (!s_self)
84 s_self = new MigrateManagerInternal();
85
86 return s_self;
87}
88
89bool MigrateManagerInternal::lookupDrivers()
90{
91 if (!lookupDriversNeeded)
92 return true;
93
94 if (tqApp) {
95 connect(tqApp,TQ_SIGNAL(aboutToQuit()),this,TQ_SLOT(slotAppQuits()));
96 }
97//TODO: for TQt-only version check for TDEInstance wrapper
98// KexiDBWarn << "DriverManagerInternal::lookupDrivers(): cannot work without TDEInstance (TDEGlobal::instance()==0)!" << endl;
99// setError("Driver Manager cannot work without TDEInstance (TDEGlobal::instance()==0)!");
100
101 lookupDriversNeeded = false;
102 clearError();
103 TDETrader::OfferList tlist = TDETrader::self()->query("Kexi/MigrationDriver");
104 TDETrader::OfferList::ConstIterator it(tlist.constBegin());
105 for(; it != tlist.constEnd(); ++it)
106 {
107 KService::Ptr ptr = (*it);
108 TQString srv_name = ptr->property("X-Kexi-MigrationDriverName").toString();
109 if (srv_name.isEmpty()) {
110 KexiDBWarn << "MigrateManagerInternal::lookupDrivers(): "
111 "X-Kexi-MigrationDriverName must be set for migration driver \""
112 << ptr->property("Name").toString() << "\" service!\n -- skipped!" << endl;
113 continue;
114 }
115 if (m_services_lcase.contains(srv_name.lower())) {
116 continue;
117 }
118
120//<COPIED>
121 TQString srv_ver_str = ptr->property("X-Kexi-KexiMigrationVersion").toString();
122 TQStringList lst( TQStringList::split(".", srv_ver_str) );
123 int minor_ver, major_ver;
124 bool ok = (lst.count() == 2);
125 if (ok)
126 major_ver = lst[0].toUInt(&ok);
127 if (ok)
128 minor_ver = lst[1].toUInt(&ok);
129 if (!ok) {
130 KexiDBWarn << "MigrateManagerInternal::lookupDrivers(): problem with detecting '"
131 << srv_name.lower() << "' driver's version -- skipping it!" << endl;
132 possibleProblems += TQString("\"%1\" migration driver has unrecognized version; "
133 "required driver version is \"%2.%3\"")
134 .arg(srv_name.lower())
136 continue;
137 }
138 if (major_ver != KexiMigration::versionMajor() || minor_ver != KexiMigration::versionMinor()) {
139 KexiDBWarn << TQString("MigrateManagerInternal::lookupDrivers(): '%1' driver"
140 " has version '%2' but required migration driver version is '%3.%4'\n"
141 " -- skipping this driver!").arg(srv_name.lower()).arg(srv_ver_str)
143 possibleProblems += TQString("\"%1\" migration driver has version \"%2\" "
144 "but required driver version is \"%3.%4\"")
145 .arg(srv_name.lower()).arg(srv_ver_str)
147 continue;
148 }
149//</COPIED>
150
151 TQString mime = ptr->property("X-Kexi-FileDBDriverMime").toString().lower();
152 TQString drvType = ptr->property("X-Kexi-MigrationDriverType").toString().lower();
153 if (drvType=="file") {
154 if (!mime.isEmpty()) {
155 if (!m_services_by_mimetype.contains(mime)) {
156 m_services_by_mimetype.insert(mime, ptr);
157 }
158 else {
159 KexiDBWarn << "MigrateManagerInternal::lookupDrivers(): more than one driver for '"
160 << mime << "' mime type!" << endl;
161 }
162 }
163 }
164 m_services.insert(srv_name, ptr);
165 m_services_lcase.insert(srv_name.lower(), ptr);
166 KexiDBDbg << "MigrateManager::lookupDrivers(): registered driver: " << ptr->name()
167 << "(" << ptr->library() << ")" << endl;
168 }
169
170 if (tlist.isEmpty())
171 {
172 setError(ERR_DRIVERMANAGER, i18n("Could not find any import/export database drivers.") );
173 return false;
174 }
175 return true;
176}
177
178KexiMigrate* MigrateManagerInternal::driver(const TQString& name)
179{
180 if (!lookupDrivers())
181 return 0;
182
183 clearError();
184 KexiDBDbg << "MigrationrManagerInternal::migrationDriver(): loading " << name << endl;
185
186 KexiMigrate *drv = name.isEmpty() ? 0 : m_drivers.find(name.latin1());
187 if (drv)
188 return drv; //cached
189
190 if (!m_services_lcase.contains(name.lower())) {
191 setError(ERR_DRIVERMANAGER, i18n("Could not find import/export database driver \"%1\".").arg(name) );
192 return 0;
193 }
194
195 KService::Ptr ptr= *(m_services_lcase.find(name.lower()));
196 TQString srv_name = ptr->property("X-Kexi-MigrationDriverName").toString();
197
198 KexiDBDbg << "MigrateManagerInternal::driver(): library: "<<ptr->library()<<endl;
199 drv = KParts::ComponentFactory::createInstanceFromService<KexiMigrate>(ptr,
200 this, srv_name.latin1(), TQStringList(),&m_serverResultNum);
201
202 if (!drv) {
203 setError(ERR_DRIVERMANAGER, i18n("Could not load import/export database driver \"%1\".")
204 .arg(name) );
205 if (m_componentLoadingErrors.isEmpty()) {//fill errtable on demand
206 m_componentLoadingErrors[KParts::ComponentFactory::ErrNoServiceFound]="ErrNoServiceFound";
207 m_componentLoadingErrors[KParts::ComponentFactory::ErrServiceProvidesNoLibrary]="ErrServiceProvidesNoLibrary";
208 m_componentLoadingErrors[KParts::ComponentFactory::ErrNoLibrary]="ErrNoLibrary";
209 m_componentLoadingErrors[KParts::ComponentFactory::ErrNoFactory]="ErrNoFactory";
210 m_componentLoadingErrors[KParts::ComponentFactory::ErrNoComponent]="ErrNoComponent";
211 }
212 m_serverResultName=m_componentLoadingErrors[m_serverResultNum];
213 return 0;
214 }
215 KexiDBDbg << "MigrateManagerInternal::driver(): loading succeed: " << name <<endl;
216 KexiDBDbg << "drv="<<(long)drv <<endl;
217
218// drv->setName(srv_name.latin1());
219// drv->d->service = ptr; //store info
220// drv->d->fileDBDriverMimeType = ptr->property("X-Kexi-FileDBDriverMime").toString();
221// drv->d->initInternalProperties();
222
223 if (!drv->isValid()) {
224 setError(drv);
225 delete drv;
226 return 0;
227 }
228
229 m_drivers.insert(name.latin1(), drv); //cache it
230 return drv;
231}
232
233void MigrateManagerInternal::incRefCount()
234{
235 m_refCount++;
236 KexiDBDbg << "MigrateManagerInternal::incRefCount(): " << m_refCount << endl;
237}
238
239void MigrateManagerInternal::decRefCount()
240{
241 m_refCount--;
242 KexiDBDbg << "MigrateManagerInternal::decRefCount(): " << m_refCount << endl;
243// if (m_refCount<1) {
244// KexiDBDbg<<"KexiDB::DriverManagerInternal::decRefCount(): reached m_refCount<1 -->deletelater()"<<endl;
245// s_self=0;
246// deleteLater();
247// }
248}
249
250// ---------------------------
251// --- DriverManager impl. ---
252// ---------------------------
253
254MigrateManager::MigrateManager()
255 : TQObject( 0, "KexiMigrate::MigrateManager" )
256 , Object()
257 , d_int( MigrateManagerInternal::self() )
258{
259 d_int->incRefCount();
260// if ( !s_self )
261// s_self = this;
262// lookupDrivers();
263}
264
265MigrateManager::~MigrateManager()
266{
267 KexiDBDbg << "MigrateManager::~MigrateManager()" << endl;
268/* Connection *conn;
269 for ( conn = m_connections.first(); conn ; conn = m_connections.next() ) {
270 conn->disconnect();
271 conn->m_driver = 0; //don't let the connection touch our driver now
272 m_connections.remove();
273 delete conn;
274 }*/
275
276 d_int->decRefCount();
277 if (d_int->m_refCount==0) {
278 //delete internal drv manager!
279 delete d_int;
280 }
281// if ( s_self == this )
282 //s_self = 0;
283 KexiDBDbg << "MigrateManager::~MigrateManager() ok" << endl;
284}
285
286
287const TQStringList MigrateManager::driverNames()
288{
289 if (!d_int->lookupDrivers()) {
290 kdDebug() << "MigrateManager::driverNames() lookupDrivers failed" << endl;
291 return TQStringList();
292 }
293
294 if (d_int->m_services.isEmpty()) {
295 kdDebug() << "MigrateManager::driverNames() MigrateManager::ServicesMap is empty" << endl;
296 return TQStringList();
297 }
298
299 if (d_int->error()) {
300 kdDebug() << "MigrateManager::driverNames() Error: " << d_int->errorMsg() << endl;
301 return TQStringList();
302 }
303
304 return d_int->m_services.keys();
305}
306
307TQString MigrateManager::driverForMimeType(const TQString &mimeType)
308{
309 if (!d_int->lookupDrivers()) {
310 kdDebug() << "MigrateManager::driverForMimeType() lookupDrivers() failed" << endl;
311 setError(d_int);
312 return 0;
313 }
314
315 KService::Ptr ptr = d_int->m_services_by_mimetype[mimeType.lower()];
316 if (!ptr) {
317 kdDebug() << TQString("MigrateManager::driverForMimeType(%1) No such mimetype").arg(mimeType) << endl;
318 return TQString();
319 }
320
321 return ptr->property("X-Kexi-MigrationDriverName").toString();
322}
323
325{
326 KexiMigrate *drv = d_int->driver(name);
327 if (d_int->error()) {
328 kdDebug() << TQString("MigrateManager::driver(%1) Error: %2").arg(name).arg(d_int->errorMsg()) << endl;
329 setError(d_int);
330 }
331 return drv;
332}
333
335{
336 return d_int->m_serverErrMsg;
337}
338
340{
341 return d_int->m_serverResultNum;
342}
343
345{
346 return d_int->m_serverResultName;
347}
348
350{
351 d_int->m_serverErrMsg=TQString();
352 d_int->m_serverResultNum=0;
353 d_int->m_serverResultName=TQString();
354}
355
357{
358 if (d_int->possibleProblems.isEmpty())
359 return TQString();
360 TQString str;
361 str.reserve(1024);
362 str = "<ul>";
363 for (TQStringList::ConstIterator it = d_int->possibleProblems.constBegin();
364 it!=d_int->possibleProblems.constEnd(); ++it)
365 {
366 str += (TQString::fromLatin1("<li>") + *it + TQString::fromLatin1("</li>"));
367 }
368 str += "</ul>";
369 return str;
370}
371
372//------------------------
373
375{
376 return KEXI_MIGRATION_VERSION_MAJOR;
377}
378
380{
381 return KEXI_MIGRATION_VERSION_MINOR;
382}
383
384#include "migratemanager_p.moc"
virtual void setError(int code=ERR_OTHER, const TQString &msg=TQString())
Definition object.cpp:53
Imports non-native databases into Kexi projects.
Definition keximigrate.h:79
Migration library management, for finding and loading mogration drivers.
TQString possibleProblemsInfoMsg() const
KexiMigrate * driver(const TQString &name)
virtual TQString serverErrorMsg()
server error is set if there is error at KService level (useful for debugging)
virtual TQString serverResultName()
const TQStringList driverNames()
TQString driverForMimeType(const TQString &mimeType)
Framework for importing databases into native KexiDB databases.
KEXIMIGR_EXPORT int versionMajor()
KEXIMIGR_EXPORT int versionMinor()