| 1 | /**************************************************************************** | 
| 2 | ** | 
| 3 | ** Copyright (C) 2015 The Qt Company Ltd and/or its subsidiary(-ies). | 
| 4 | ** Contact: http://www.qt-project.org/legal | 
| 5 | ** | 
| 6 | ** This file is part of the QtSystems module of the Qt Toolkit. | 
| 7 | ** | 
| 8 | ** $QT_BEGIN_LICENSE:LGPL21$ | 
| 9 | ** Commercial License Usage | 
| 10 | ** Licensees holding valid commercial Qt licenses may use this file in | 
| 11 | ** accordance with the commercial license agreement provided with the | 
| 12 | ** Software or, alternatively, in accordance with the terms contained in | 
| 13 | ** a written agreement between you and The Qt Company. For licensing terms | 
| 14 | ** and conditions see http://www.qt.io/terms-conditions. For further | 
| 15 | ** information use the contact form at http://www.qt.io/contact-us. | 
| 16 | ** | 
| 17 | ** GNU Lesser General Public License Usage | 
| 18 | ** Alternatively, this file may be used under the terms of the GNU Lesser | 
| 19 | ** General Public License version 2.1 or version 3 as published by the Free | 
| 20 | ** Software Foundation and appearing in the file LICENSE.LGPLv21 and | 
| 21 | ** LICENSE.LGPLv3 included in the packaging of this file. Please review the | 
| 22 | ** following information to ensure the GNU Lesser General Public License | 
| 23 | ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and | 
| 24 | ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | 
| 25 | ** | 
| 26 | ** As a special exception, The Qt Company gives you certain additional | 
| 27 | ** rights. These rights are described in The Qt Company LGPL Exception | 
| 28 | ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | 
| 29 | ** | 
| 30 | ** $QT_END_LICENSE$ | 
| 31 | ** | 
| 32 | ****************************************************************************/ | 
| 33 |  | 
| 34 | // #define QT_SFW_SERVICEDATABASE_DEBUG | 
| 35 |  | 
| 36 | #include "servicedatabase_p.h" | 
| 37 | #include <QDir> | 
| 38 | #include <QSet> | 
| 39 | #include "qserviceinterfacedescriptor.h" | 
| 40 | #include "qserviceinterfacedescriptor_p.h" | 
| 41 | #include <QUuid> | 
| 42 | #include "dberror_p.h" | 
| 43 |  | 
| 44 | //database name | 
| 45 | #define RESOLVERDATABASE "services.db" | 
| 46 |  | 
| 47 | //database table names | 
| 48 | #define SERVICE_TABLE "Service" | 
| 49 | #define INTERFACE_TABLE "Interface" | 
| 50 | #define DEFAULTS_TABLE "Defaults" | 
| 51 | #define SERVICE_PROPERTY_TABLE "ServiceProperty" | 
| 52 | #define INTERFACE_PROPERTY_TABLE "InterfaceProperty" | 
| 53 |  | 
| 54 | //separator | 
| 55 | #define RESOLVERDATABASE_PATH_SEPARATOR "//" | 
| 56 |  | 
| 57 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 58 | #include <QDebug> | 
| 59 | #endif | 
| 60 |  | 
| 61 | #define SERVICE_DESCRIPTION_KEY "DESCRIPTION" | 
| 62 | #ifdef QT_SFW_SERVICEDATABASE_USE_SECURITY_TOKEN | 
| 63 | #define SECURITY_TOKEN_KEY "SECURITYTOKEN" | 
| 64 | #endif | 
| 65 | #define INTERFACE_DESCRIPTION_KEY "DESCRIPTION" | 
| 66 | #define SERVICE_INITIALIZED_KEY SERVICE_INITIALIZED_ATTR | 
| 67 | #define INTERFACE_CAPABILITY_KEY "CAPABILITIES" | 
| 68 | #define INTERFACE_SERVICETYPE_KEY "SERVICETYPE" | 
| 69 |  | 
| 70 | //service prefixes | 
| 71 | #define SERVICE_IPC_PREFIX "_q_ipc_addr:" | 
| 72 |  | 
| 73 | QT_BEGIN_NAMESPACE | 
| 74 |  | 
| 75 | enum TBindIndexes | 
| 76 |     { | 
| 77 |         EBindIndex=0, | 
| 78 |         EBindIndex1, | 
| 79 |         EBindIndex2, | 
| 80 |         EBindIndex3, | 
| 81 |         EBindIndex4, | 
| 82 |         EBindIndex5, | 
| 83 |         EBindIndex6, | 
| 84 |         EBindIndex7 | 
| 85 |     }; | 
| 86 |  | 
| 87 |  | 
| 88 | /* | 
| 89 |    \class ServiceDatabase | 
| 90 |    The ServiceDatabase is responsible for the management of a single | 
| 91 |    service database.  It provides operations for: | 
| 92 |    - opening and closing a connection with the database, | 
| 93 |    - registering and unregistering services | 
| 94 |    - querying for services and interfaces | 
| 95 |    - setting and getting default interface implementations. | 
| 96 | */ | 
| 97 |  | 
| 98 | /* | 
| 99 |     Constructor | 
| 100 | */ | 
| 101 | ServiceDatabase::ServiceDatabase(void) | 
| 102 | :m_isDatabaseOpen(false),m_inTransaction(false) | 
| 103 | { | 
| 104 | } | 
| 105 |  | 
| 106 | /* | 
| 107 |     Destructor | 
| 108 | */ | 
| 109 | ServiceDatabase::~ServiceDatabase() | 
| 110 | { | 
| 111 |     close(); | 
| 112 | } | 
| 113 |  | 
| 114 | /* | 
| 115 |     Opens the service database | 
| 116 |     The method creates or opens database and creates tables if they are not present | 
| 117 |     Returns true if the operation was successful, false if not. | 
| 118 | */ | 
| 119 | bool ServiceDatabase::open() | 
| 120 | { | 
| 121 |     if (m_isDatabaseOpen) | 
| 122 |         return true; | 
| 123 |  | 
| 124 |     QString path; | 
| 125 |  | 
| 126 |     //Create full path to database | 
| 127 |     if (m_databasePath.isEmpty ()) | 
| 128 |         m_databasePath = databasePath(); | 
| 129 |  | 
| 130 |     path = m_databasePath; | 
| 131 |     QFileInfo dbFileInfo(path); | 
| 132 |     if (!dbFileInfo.dir().exists()) { | 
| 133 |        QDir::root().mkpath(dirPath: dbFileInfo.path()); | 
| 134 |        QFile file(path); | 
| 135 |        if (!file.open(flags: QIODevice::ReadWrite)) { | 
| 136 |            QString errorText(QLatin1String("Could not create database directory: %1" )); | 
| 137 |            m_lastError.setError(error: DBError::CannotCreateDbDir, errorText: errorText.arg(a: dbFileInfo.path())); | 
| 138 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 139 |            qWarning() << "ServiceDatabase::open():-"  | 
| 140 |                         << "Problem:"  << qPrintable(m_lastError.text()); | 
| 141 | #endif | 
| 142 |            close(); | 
| 143 |            return false; | 
| 144 |         } | 
| 145 |         file.close(); | 
| 146 |     } | 
| 147 |  | 
| 148 |     m_connectionName = dbFileInfo.completeBaseName() + QStringLiteral("--" ) + QString::number(reinterpret_cast<quintptr>(QThread::currentThreadId())); | 
| 149 |     QSqlDatabase  database; | 
| 150 |     if (QSqlDatabase::contains(connectionName: m_connectionName)) { | 
| 151 |         database = QSqlDatabase::database(connectionName: m_connectionName); | 
| 152 |     } else { | 
| 153 |         database = QSqlDatabase::addDatabase(type: QLatin1String("QSQLITE" ), connectionName: m_connectionName); | 
| 154 |         database.setDatabaseName(path); | 
| 155 |     } | 
| 156 |  | 
| 157 |     if (!database.isValid()){ | 
| 158 |         m_lastError.setError(error: DBError::InvalidDatabaseConnection); | 
| 159 |         close(); | 
| 160 |         return false; | 
| 161 |     } | 
| 162 |  | 
| 163 |     //Create or open database | 
| 164 |     if (!database.isOpen()) { | 
| 165 |         if (!database.open()) { | 
| 166 |             m_lastError.setError(error: DBError::SqlError, errorText: database.lastError().text()); | 
| 167 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 168 |             qWarning() << "ServiceDatabase::open():-"  | 
| 169 |                         << "Problem:"  << "Could not open database. "  | 
| 170 |                         << "Reason:"  << m_lastError.text(); | 
| 171 | #endif | 
| 172 |             close(); | 
| 173 |             return false; | 
| 174 |         } | 
| 175 |     } | 
| 176 |     m_isDatabaseOpen = true; | 
| 177 |  | 
| 178 |     //Check database structure (tables) and recreate tables if neccessary | 
| 179 |     //If one of tables is missing remove all tables and recreate them | 
| 180 |     //This operation is required in order to avoid data coruption | 
| 181 |     if (!checkTables()) { | 
| 182 |         if (dropTables()) { | 
| 183 |             if (createTables()) { | 
| 184 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 185 |                 qDebug() << "ServiceDatabase::open():-"  | 
| 186 |                     << "Database tables recreated" ; | 
| 187 | #endif | 
| 188 |             } else { | 
| 189 |                 //createTable() should've handled error message | 
| 190 |                 //and warning | 
| 191 |                 close(); | 
| 192 |                 return false; | 
| 193 |             } | 
| 194 |         } | 
| 195 |         else { | 
| 196 |             //dropTables() should've handled error message | 
| 197 |             //and warning | 
| 198 |             close(); | 
| 199 |             return false; | 
| 200 |         } | 
| 201 |     } | 
| 202 |     return true; | 
| 203 | } | 
| 204 |  | 
| 205 | /* | 
| 206 |    Adds a \a service into the database. | 
| 207 |  | 
| 208 |    May set the following error codes | 
| 209 |    DBError::NoError | 
| 210 |    DBError::LocationAlreadyRegistered | 
| 211 |    DBError::IfaceImplAlreadyRegistered | 
| 212 |    DBError::SqlError | 
| 213 |    DBError::DatabaseNotOpen | 
| 214 |    DBError::InvalidDatabaseConnection | 
| 215 |    DBError::NoWritePermissions | 
| 216 |    DBError::InvalidDatabaseFile | 
| 217 | */ | 
| 218 | //bool ServiceDatabase::registerService(ServiceMetaData &service) | 
| 219 | bool ServiceDatabase::registerService(const ServiceMetaDataResults &service, const QString &securityToken) | 
| 220 | { | 
| 221 |     // Derive the location name with the service type prefix to be stored | 
| 222 |     QString locationPrefix = service.location; | 
| 223 |     int type = service.interfaces[0].d->attributes[QServiceInterfaceDescriptor::ServiceType].toInt(); | 
| 224 |     if (type == QService::InterProcess) | 
| 225 |         locationPrefix = QLatin1String(SERVICE_IPC_PREFIX) + service.location; | 
| 226 |  | 
| 227 | #ifndef QT_SFW_SERVICEDATABASE_USE_SECURITY_TOKEN | 
| 228 |     Q_UNUSED(securityToken); | 
| 229 | #else | 
| 230 |     if (securityToken.isEmpty()) { | 
| 231 |         QString errorText("Access denied, no security token provided (for registering service: \"%1\")" ); | 
| 232 |         m_lastError.setError(DBError::NoWritePermissions, errorText.arg(service.name)); | 
| 233 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 234 |         qWarning() << "ServiceDatabase::registerService():-"  | 
| 235 |                 << "Problem: Unable to register service,"  | 
| 236 |                 << "reason:"  << qPrintable(m_lastError.text()); | 
| 237 | #endif | 
| 238 |         return false; | 
| 239 |     } | 
| 240 | #endif | 
| 241 |  | 
| 242 |     if (!checkConnection()) { | 
| 243 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 244 |         qWarning() << "ServiceDatabase::registerService():-"  | 
| 245 |                     << "Problem:"  << qPrintable(m_lastError.text()); | 
| 246 | #endif | 
| 247 |         return false; | 
| 248 |     } | 
| 249 |  | 
| 250 |     QSqlDatabase database = QSqlDatabase::database(connectionName: m_connectionName); | 
| 251 |     QSqlQuery query(database); | 
| 252 |  | 
| 253 |     if (!beginTransaction(query: &query, Write)) { | 
| 254 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 255 |         qWarning() << "ServiceDatabase::registerService():-"  | 
| 256 |                     << "Unable to begin transaction,"  | 
| 257 |                     << "reason:"  << qPrintable(m_lastError.text()); | 
| 258 | #endif | 
| 259 |         return false; | 
| 260 |     } | 
| 261 |     //See if the service's location has already been previously registered | 
| 262 |     QString statement(QLatin1String("SELECT Name from Service WHERE Location=? COLLATE NOCASE" )); | 
| 263 |     QList<QVariant> bindValues; | 
| 264 |     bindValues.append(t: locationPrefix); | 
| 265 |     if (!executeQuery(query: &query, statement, bindValues)) { | 
| 266 |         rollbackTransaction(query: &query); | 
| 267 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 268 |         qWarning() << "ServiceDatabase::registerService():-"  | 
| 269 |                     << qPrintable(m_lastError.text()); | 
| 270 | #endif | 
| 271 |         return false; | 
| 272 |     } | 
| 273 |  | 
| 274 |     if (query.next()) { | 
| 275 |         QString alreadyRegisteredService = query.value(i: EBindIndex).toString(); | 
| 276 |         const QString errorText = QLatin1String("Cannot register service \"%1\". Service location \"%2\" is already "  | 
| 277 |                     "registered to service \"%3\".  \"%3\" must first be deregistered "  | 
| 278 |                     "for new registration to take place." ); | 
| 279 |  | 
| 280 |         m_lastError.setError(error: DBError::LocationAlreadyRegistered, | 
| 281 |                 errorText: errorText.arg(a: service.name) | 
| 282 |                         .arg(a: service.location) | 
| 283 |                         .arg(a: alreadyRegisteredService)); | 
| 284 |  | 
| 285 |         rollbackTransaction(query: &query); | 
| 286 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 287 |         qWarning() << "ServiceDatabase::registerService():-"  | 
| 288 |                     << "Problem:"  << qPrintable(m_lastError.text()); | 
| 289 | #endif | 
| 290 |         return false; | 
| 291 |     } | 
| 292 |  | 
| 293 | #ifdef QT_SFW_SERVICEDATABASE_USE_SECURITY_TOKEN | 
| 294 |     // If service(s) have already been registered with same name, they must all come from | 
| 295 |     // same application. Fetch a service with given name and if such exists, check that its | 
| 296 |     // security ID equals to the security ID of the current registrar. | 
| 297 |     // One application may register multiple services with same name (different location), | 
| 298 |     // hence the keyword DISTINCT. | 
| 299 |     statement = "SELECT DISTINCT ServiceProperty.Value FROM Service, ServiceProperty "  | 
| 300 |                 "WHERE Service.ID = ServiceProperty.ServiceID "  | 
| 301 |                 "AND ServiceProperty.Key = ? "  | 
| 302 |                 "AND Service.Name = ?" ; | 
| 303 |     bindValues.clear(); | 
| 304 |     bindValues.append(SECURITY_TOKEN_KEY); | 
| 305 |     bindValues.append(service.name); | 
| 306 |     if (!executeQuery(&query, statement, bindValues)) { | 
| 307 |         rollbackTransaction(&query); | 
| 308 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 309 |         qWarning() << "ServiceDatabase::registerService():-"  | 
| 310 |                    << qPrintable(m_lastError.text()); | 
| 311 | #endif | 
| 312 |         return false; | 
| 313 |     } | 
| 314 |     QString existingSecurityToken; | 
| 315 |     if (query.next()) { | 
| 316 |         existingSecurityToken = query.value(EBindIndex).toString(); | 
| 317 |     } | 
| 318 |     if (!existingSecurityToken.isEmpty() && (existingSecurityToken != securityToken)) { | 
| 319 |         QString errorText("Access denied: \"%1\"" ); | 
| 320 |         m_lastError.setError(DBError::NoWritePermissions, errorText.arg(service.name)); | 
| 321 |         rollbackTransaction(&query); | 
| 322 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 323 |         qWarning() << "ServiceDatabase::registerService():-"  | 
| 324 |                 << "Problem: Unable to register service,"  | 
| 325 |                 << "reason:"  << qPrintable(m_lastError.text()); | 
| 326 | #endif | 
| 327 |         return false; | 
| 328 |     } | 
| 329 | #endif // QT_SFW_SERVICEDATABASE_USE_SECURITY_TOKEN | 
| 330 |  | 
| 331 |     // Checks done, create new rows into tables. | 
| 332 |     statement = QLatin1String("INSERT INTO Service(ID,Name,Location) VALUES(?,?,?)" ); | 
| 333 |  | 
| 334 |     qsrand(seed: QTime::currentTime().msec()); | 
| 335 |     QString serviceID = QUuid::createUuid().toString(); | 
| 336 |  | 
| 337 |     bindValues.clear(); | 
| 338 |     bindValues.append(t: serviceID); | 
| 339 |     bindValues.append(t: service.name); | 
| 340 |     bindValues.append(t: locationPrefix); | 
| 341 |  | 
| 342 |     if (!executeQuery(query: &query, statement, bindValues)) { | 
| 343 |         rollbackTransaction(query: &query); | 
| 344 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 345 |         qWarning() << "ServiceDatabase::registerService():-"  | 
| 346 |                     << qPrintable(m_lastError.text()); | 
| 347 | #endif | 
| 348 |         return false; | 
| 349 |     } | 
| 350 |  | 
| 351 |     statement = QLatin1String("INSERT INTO ServiceProperty(ServiceID,Key,Value) VALUES(?,?,?)" ); | 
| 352 |     bindValues.clear(); | 
| 353 |     bindValues.append(t: serviceID); | 
| 354 |     bindValues.append(t: QLatin1String(SERVICE_DESCRIPTION_KEY)); | 
| 355 |     if (service.description.isNull()) | 
| 356 |         bindValues.append(t: QLatin1String("" )); // This relies on !QString::isNull(). | 
| 357 |     else | 
| 358 |         bindValues.append(t: service.description); | 
| 359 |  | 
| 360 |     if (!executeQuery(query: &query, statement, bindValues)) { | 
| 361 |         rollbackTransaction(query: &query); | 
| 362 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 363 |         qWarning() << "ServiceDatabase::registerService():-"  | 
| 364 |                     << qPrintable(m_lastError.text()); | 
| 365 | #endif | 
| 366 |         return false; | 
| 367 |     } | 
| 368 |  | 
| 369 | #ifdef QT_SFW_SERVICEDATABASE_GENERATE | 
| 370 |     statement = "INSERT INTO ServiceProperty(ServiceId,Key,Value) VALUES(?,?,?)" ; | 
| 371 |     bindValues.clear(); | 
| 372 |     bindValues.append(serviceID); | 
| 373 |     bindValues.append(SERVICE_INITIALIZED_KEY); | 
| 374 |     bindValues.append(QString("NO" )); | 
| 375 |     if (!executeQuery(&query, statement, bindValues)) { | 
| 376 |         rollbackTransaction(&query); | 
| 377 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 378 |         qWarning() << "ServiceDatabase::registerService():-"  | 
| 379 |                     << qPrintable(m_lastError.text()); | 
| 380 | #endif | 
| 381 |         return false; | 
| 382 |     } | 
| 383 | #endif | 
| 384 |  | 
| 385 | #ifdef QT_SFW_SERVICEDATABASE_USE_SECURITY_TOKEN | 
| 386 |     // Insert a security token for the particular service | 
| 387 |     statement = "INSERT INTO ServiceProperty(ServiceID,Key,Value) VALUES(?,?,?)" ; | 
| 388 |     bindValues.clear(); | 
| 389 |     bindValues.append(serviceID); | 
| 390 |     bindValues.append(SECURITY_TOKEN_KEY); | 
| 391 |     bindValues.append(securityToken); | 
| 392 |  | 
| 393 |     if (!executeQuery(&query, statement, bindValues)) { | 
| 394 |         rollbackTransaction(&query); | 
| 395 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 396 |         qWarning() << "ServiceDatabase::registerService():-"  | 
| 397 |                 << qPrintable(m_lastError.text()); | 
| 398 | #endif | 
| 399 |         return false; | 
| 400 |     } | 
| 401 | #endif // QT_SFW_SERVICEDATABASE_USE_SECURITY_TOKEN | 
| 402 |  | 
| 403 |     QList <QServiceInterfaceDescriptor> interfaces = service.interfaces; | 
| 404 |     QString interfaceID;; | 
| 405 |     foreach (const QServiceInterfaceDescriptor &serviceInterface, interfaces) { | 
| 406 |         interfaceID = getInterfaceID(query: &query, serviceInterface); | 
| 407 |         if (m_lastError.code() == DBError::NoError) { | 
| 408 |             QString errorText; | 
| 409 |             errorText = QLatin1String("Cannot register service \"%1\". \"%1\" is already registered "  | 
| 410 |                         "and implements interface \"%2\", Version \"%3.%4.\"  \"%1\" must "  | 
| 411 |                         "first be deregistered for new registration to take place." ); | 
| 412 |             m_lastError.setError(error: DBError::IfaceImplAlreadyRegistered, | 
| 413 |                                 errorText: errorText.arg(a: serviceInterface.serviceName()) | 
| 414 |                                             .arg(a: serviceInterface.interfaceName()) | 
| 415 |                                             .arg(a: serviceInterface.majorVersion()) | 
| 416 |                                             .arg(a: serviceInterface.minorVersion())); | 
| 417 |  | 
| 418 |             rollbackTransaction(query: &query); | 
| 419 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 420 |             qWarning() << "ServiceDatabase::registerService():-"  | 
| 421 |                         << "Problem:"  << qPrintable(m_lastError.text()); | 
| 422 | #endif | 
| 423 |             return false; | 
| 424 |         } else if (m_lastError.code() == DBError::NotFound){ | 
| 425 |             //No interface implementation already exists for the service | 
| 426 |             //so add it | 
| 427 |             if (!insertInterfaceData(query: &query, anInterface: serviceInterface, serviceID)) { | 
| 428 |                 rollbackTransaction(query: &query); | 
| 429 |                 return false; | 
| 430 |             } else { | 
| 431 |                 continue; | 
| 432 |             } | 
| 433 |         } else { | 
| 434 |             rollbackTransaction(query: &query); | 
| 435 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 436 |             qWarning() << "ServiceDatabase::registerService():-"  | 
| 437 |                         << "Unable to confirm if implementation version"  | 
| 438 |                         << (QString::number(serviceInterface.majorVersion()) + "."  | 
| 439 |                            + QString::number(serviceInterface.minorVersion())).toLatin1() | 
| 440 |                         << "for interface"  << serviceInterface.interfaceName() | 
| 441 |                         << "is already registered for service "  | 
| 442 |                         << serviceInterface.serviceName() | 
| 443 |                         << "\n"  << m_lastError.text(); | 
| 444 | #endif | 
| 445 |             return false; | 
| 446 |         } | 
| 447 |     } | 
| 448 |  | 
| 449 |     interfaces = service.latestInterfaces; | 
| 450 |     QServiceInterfaceDescriptor defaultInterface; | 
| 451 |     foreach (const QServiceInterfaceDescriptor &serviceInterface, interfaces) { | 
| 452 |         defaultInterface = interfaceDefault(interfaceName: serviceInterface.interfaceName(), NULL, inTransaction: true); | 
| 453 |         if (m_lastError.code() == DBError::NoError | 
| 454 |                 || m_lastError.code() == DBError::ExternalIfaceIDFound) { | 
| 455 |             continue; //default already exists so don't do anything | 
| 456 |         } else if (m_lastError.code() == DBError::NotFound) { | 
| 457 |             //default does not already exist so create one | 
| 458 |             interfaceID = getInterfaceID(query: &query, serviceInterface); | 
| 459 |             if (m_lastError.code() != DBError::NoError) { | 
| 460 |                 rollbackTransaction(query: &query); | 
| 461 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 462 |                 qWarning() << "ServiceDatabase::registerService():-"  | 
| 463 |                            << "Unable to retrieve interfaceID for "  | 
| 464 |                               "interface"  << serviceInterface.interfaceName() | 
| 465 |                            << "\n"  << m_lastError.text(); | 
| 466 | #endif | 
| 467 |                 return false; | 
| 468 |             } | 
| 469 |  | 
| 470 |             statement = QLatin1String("INSERT INTO Defaults(InterfaceName, InterfaceID) VALUES(?,?)" ); | 
| 471 |             bindValues.clear(); | 
| 472 |             bindValues.append(t: serviceInterface.interfaceName()); | 
| 473 |             bindValues.append(t: interfaceID); | 
| 474 |             if (!executeQuery(query: &query, statement, bindValues)) { | 
| 475 |                 rollbackTransaction(query: &query); | 
| 476 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 477 |                 qWarning() << "ServiceDatabase::registerService():-"  | 
| 478 |                     << qPrintable(m_lastError.text()); | 
| 479 | #endif | 
| 480 |                 return false; | 
| 481 |             } | 
| 482 |         } else { | 
| 483 |             rollbackTransaction(query: &query); | 
| 484 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 485 |             qWarning() << "ServiceDatabase::registerService()"  | 
| 486 |                         << "Problem: Unable to confirm if interface"  | 
| 487 |                         << serviceInterface.interfaceName() | 
| 488 |                         << "already has a default implementation" ; | 
| 489 | #endif | 
| 490 |             return false; | 
| 491 |         } | 
| 492 |     } | 
| 493 |  | 
| 494 |     if (!commitTransaction(query: &query)) { | 
| 495 |         rollbackTransaction(query: &query); | 
| 496 |         return false; | 
| 497 |     } | 
| 498 |     m_lastError.setError(error: DBError::NoError); | 
| 499 |     return true; | 
| 500 | } | 
| 501 |  | 
| 502 | /* | 
| 503 |     Obtains an interface ID corresponding to a given interface \a descriptor | 
| 504 |  | 
| 505 |     May set the following error codes: | 
| 506 |     DBError::NoError | 
| 507 |     DBError::NotFound | 
| 508 |     DBError::SqlError | 
| 509 |     DBError::DatabaseNotOpen | 
| 510 |     DBError::InvalidDatabaseConnection | 
| 511 | */ | 
| 512 | QString ServiceDatabase::getInterfaceID(const QServiceInterfaceDescriptor &serviceInterface) { | 
| 513 |     QString interfaceID; | 
| 514 |     if (!checkConnection()) { | 
| 515 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 516 |         qWarning() << "ServiceDatabase::getInterfaceID():-"  | 
| 517 |                     << "Problem:"  << qPrintable(m_lastError.text()); | 
| 518 | #endif | 
| 519 |         return interfaceID; | 
| 520 |     } | 
| 521 |  | 
| 522 |     QSqlDatabase database = QSqlDatabase::database(connectionName: m_connectionName); | 
| 523 |     QSqlQuery query(database); | 
| 524 |  | 
| 525 |     return getInterfaceID(query: &query, serviceInterface); | 
| 526 | } | 
| 527 |  | 
| 528 | /* | 
| 529 |     This function should only ever be called on a user scope database. | 
| 530 |     It returns a list of Interface Name and Interface ID pairs, where | 
| 531 |     the Interface ID refers to an external interface implementation | 
| 532 |     in the system scope database. | 
| 533 |  | 
| 534 |     May set the last error to: | 
| 535 |     DBError::NoError | 
| 536 |     DBError::SqlError | 
| 537 |     DBError::DatabaseNotOpen | 
| 538 |     DBError::InvalidDatabaseConnection | 
| 539 |  | 
| 540 |     Aside:  There is only one query which implicitly gets | 
| 541 |     wrapped in it's own transaction. | 
| 542 | */ | 
| 543 | QList<QPair<QString,QString> > ServiceDatabase::externalDefaultsInfo() | 
| 544 | { | 
| 545 |     QList<QPair<QString,QString> > ret; | 
| 546 |     if (!checkConnection()) { | 
| 547 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 548 |         qWarning() << "ServiceDatabase::externalDefaultsInfo():-"  | 
| 549 |                     << "Problem:"  << qPrintable(m_lastError.text()); | 
| 550 | #endif | 
| 551 |         return ret; | 
| 552 |     } | 
| 553 |  | 
| 554 |     QSqlDatabase database = QSqlDatabase::database(connectionName: m_connectionName); | 
| 555 |     QSqlQuery query(database); | 
| 556 |  | 
| 557 |     //Prepare search query, bind criteria values and execute search | 
| 558 |     QString selectComponent = QLatin1String("SELECT InterfaceName, InterfaceID " ); | 
| 559 |     QString fromComponent = QLatin1String("FROM Defaults " ); | 
| 560 |     QString whereComponent = QLatin1String("WHERE InterfaceID NOT IN (SELECT Interface.ID FROM Interface) " ); | 
| 561 |  | 
| 562 |     //Aside: this individual query is implicitly wrapped in a transaction | 
| 563 |     if (!executeQuery(query: &query, statement: selectComponent + fromComponent + whereComponent)) { | 
| 564 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 565 |         qWarning() << "ServiceDatabase::externalDefaultsInfo():-"  | 
| 566 |                     << "Problem:"  << qPrintable(m_lastError.text()); | 
| 567 | #endif | 
| 568 |         return ret; | 
| 569 |     } | 
| 570 |  | 
| 571 |     while (query.next()) { | 
| 572 |         ret.append(t: qMakePair(x: query.value(i: EBindIndex).toString(), | 
| 573 |                     y: query.value(i: EBindIndex1).toString())); | 
| 574 |     } | 
| 575 |  | 
| 576 |     m_lastError.setError(error: DBError::NoError); | 
| 577 |     return ret; | 
| 578 | } | 
| 579 |  | 
| 580 | /* | 
| 581 |     Helper function that obtains an interfaceID for a given \a descriptor. | 
| 582 |  | 
| 583 |     May set last error to one of the following error codes: | 
| 584 |     DBError::NoError | 
| 585 |     DBError::NotFound | 
| 586 |     DBError::SqlError | 
| 587 |  | 
| 588 |     Aside: This function may be safely called standalone or within an explicit | 
| 589 |     transaction.  If called standalone, it's single query is implicitly | 
| 590 |     wrapped in it's own transaction. | 
| 591 | */ | 
| 592 | QString ServiceDatabase::getInterfaceID(QSqlQuery *query, const QServiceInterfaceDescriptor &serviceInterface) | 
| 593 | { | 
| 594 |     QString statement = QLatin1String("SELECT Interface.ID "  | 
| 595 |                         "FROM Interface, Service "  | 
| 596 |                         "WHERE Service.ID = Interface.ServiceID "  | 
| 597 |                         "AND Service.Name = ? COLLATE NOCASE "  | 
| 598 |                         "AND Interface.Name = ? COLLATE NOCASE "  | 
| 599 |                         "AND Interface.VerMaj = ? AND Interface.VerMin = ?" ); | 
| 600 |     QList<QVariant> bindValues; | 
| 601 |     bindValues.append(t: serviceInterface.serviceName()); | 
| 602 |     bindValues.append(t: serviceInterface.interfaceName()); | 
| 603 |     bindValues.append(t: serviceInterface.majorVersion()); | 
| 604 |     bindValues.append(t: serviceInterface.minorVersion()); | 
| 605 |  | 
| 606 |     if (!executeQuery(query, statement, bindValues)) { | 
| 607 |         return QString(); | 
| 608 |     } | 
| 609 |  | 
| 610 |     if (!query->next()) { | 
| 611 |          QString errorText(QLatin1String("No Interface Descriptor found with "  | 
| 612 |                             "Service name: %1 "  | 
| 613 |                             "Interface name: %2 "  | 
| 614 |                             "Version: %3.%4" )); | 
| 615 |         m_lastError.setError(error: DBError::NotFound, errorText: errorText.arg(a: serviceInterface.serviceName()) | 
| 616 |                                                         .arg(a: serviceInterface.interfaceName()) | 
| 617 |                                                         .arg(a: serviceInterface.majorVersion()) | 
| 618 |                                                         .arg(a: serviceInterface.minorVersion())); | 
| 619 |         return QString(); | 
| 620 |     } | 
| 621 |  | 
| 622 |     m_lastError.setError(error: DBError::NoError); | 
| 623 |     return query->value(i: EBindIndex).toString(); | 
| 624 | } | 
| 625 |  | 
| 626 | /* | 
| 627 |     Helper functions that saves \a interface related data in the Interface table | 
| 628 |     The \a interface data is recorded as belonging to the service assocciated | 
| 629 |     with \a serviceID. | 
| 630 |  | 
| 631 |     May set the last error to one of the following error codes: | 
| 632 |     DBError::NoError | 
| 633 |     DBError::SqlError | 
| 634 |  | 
| 635 |     Aside: It is already assumed that a write transaction has been started by the | 
| 636 |     time this function is called; and this function will not rollback/commit | 
| 637 |     the transaction. | 
| 638 | */ | 
| 639 | bool ServiceDatabase::insertInterfaceData(QSqlQuery *query,const QServiceInterfaceDescriptor &serviceInterface, const QString &serviceID) | 
| 640 | { | 
| 641 |     QString statement = QLatin1String("INSERT INTO Interface(ID, ServiceID,Name,VerMaj, VerMin) "  | 
| 642 |                         "VALUES(?,?,?,?,?)" ); | 
| 643 |     QString interfaceID = QUuid::createUuid().toString(); | 
| 644 |  | 
| 645 |     QList<QVariant> bindValues; | 
| 646 |     bindValues.append(t: interfaceID); | 
| 647 |     bindValues.append(t: serviceID); | 
| 648 |     bindValues.append(t: serviceInterface.interfaceName()); | 
| 649 |     bindValues.append(t: serviceInterface.majorVersion()); | 
| 650 |     bindValues.append(t: serviceInterface.minorVersion()); | 
| 651 |  | 
| 652 |     if (!executeQuery(query, statement, bindValues)) { | 
| 653 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 654 |         qWarning() << "ServiceDatabase::insertInterfaceData():-"  | 
| 655 |                     << qPrintable(m_lastError.text()); | 
| 656 | #endif | 
| 657 |         return false; | 
| 658 |     } | 
| 659 |  | 
| 660 |     statement = QLatin1String("INSERT INTO InterfaceProperty(InterfaceID, Key, Value) VALUES(?,?,?)" ); | 
| 661 |     QHash<QServiceInterfaceDescriptor::Attribute, QVariant>::const_iterator iter = serviceInterface.d->attributes.constBegin(); | 
| 662 |     bool isValidInterfaceProperty; | 
| 663 |     QString capabilities; | 
| 664 |     QString interfaceDescription; | 
| 665 |     while (iter != serviceInterface.d->attributes.constEnd()) { | 
| 666 |         isValidInterfaceProperty = true; | 
| 667 |  | 
| 668 |         bindValues.clear(); | 
| 669 |         bindValues.append(t: interfaceID); | 
| 670 |         switch (iter.key()) { | 
| 671 |             case (QServiceInterfaceDescriptor::Capabilities): | 
| 672 |                 bindValues.append(t: QLatin1String(INTERFACE_CAPABILITY_KEY)); | 
| 673 |                 capabilities = serviceInterface.attribute(which: QServiceInterfaceDescriptor::Capabilities).toStringList().join(sep: QLatin1String("," )); | 
| 674 |                 if (capabilities.isNull()) | 
| 675 |                     capabilities = QLatin1String("" ); | 
| 676 |                 bindValues.append(t: capabilities); | 
| 677 |                 break; | 
| 678 |             case(QServiceInterfaceDescriptor::Location): | 
| 679 |                 isValidInterfaceProperty = false; | 
| 680 |                 break; | 
| 681 |             case(QServiceInterfaceDescriptor::ServiceDescription): | 
| 682 |                 isValidInterfaceProperty = false; | 
| 683 |                 break; | 
| 684 |             case(QServiceInterfaceDescriptor::InterfaceDescription): | 
| 685 |                 bindValues.append(t: QLatin1String(INTERFACE_DESCRIPTION_KEY)); | 
| 686 |                 interfaceDescription = serviceInterface.attribute(which: QServiceInterfaceDescriptor::InterfaceDescription).toString(); | 
| 687 |                 if (interfaceDescription.isNull()) | 
| 688 |                     interfaceDescription = QLatin1String("" ); | 
| 689 |                 bindValues.append(t: interfaceDescription); | 
| 690 |                 break; | 
| 691 |             default: | 
| 692 |                 isValidInterfaceProperty = false; | 
| 693 |                 break; | 
| 694 |         } | 
| 695 |  | 
| 696 |         if (isValidInterfaceProperty) { | 
| 697 |               if (!executeQuery(query, statement, bindValues)) { | 
| 698 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 699 |                   qWarning() << "ServiceDatabase::insertInterfaceData():-"  | 
| 700 |                                 << qPrintable(m_lastError.text()); | 
| 701 | #endif | 
| 702 |                   return false; | 
| 703 |               } | 
| 704 |         } | 
| 705 |         ++iter; | 
| 706 |     } | 
| 707 |  | 
| 708 |     // add custom attributes | 
| 709 |     QHash<QString, QString>::const_iterator customIter = serviceInterface.d->customAttributes.constBegin(); | 
| 710 |     while (customIter!=serviceInterface.d->customAttributes.constEnd()) { | 
| 711 |         bindValues.clear(); | 
| 712 |         bindValues.append(t: interfaceID); | 
| 713 |         // to avoid key clashes use separate c_ namespace ->is this sufficient? | 
| 714 |         bindValues.append(t: QVariant(QStringLiteral("c_" ) + customIter.key())); | 
| 715 |         bindValues.append(t: customIter.value()); | 
| 716 |         if (!executeQuery(query, statement, bindValues)) { | 
| 717 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 718 |             qWarning() << "ServiceDatabase::insertInterfaceData(customProps):-"  | 
| 719 |                             << qPrintable(m_lastError.text()); | 
| 720 | #endif | 
| 721 |             return false; | 
| 722 |         } | 
| 723 |         ++customIter; | 
| 724 |     } | 
| 725 |     m_lastError.setError(error: DBError::NoError); | 
| 726 |  | 
| 727 |     return true; | 
| 728 | } | 
| 729 |  | 
| 730 | /* | 
| 731 |     Helper function that executes the sql query specified in \a statement. | 
| 732 |     It is assumed that the \a statement uses positional placeholders and | 
| 733 |     corresponding parameters are placed in the list of \a bindValues. | 
| 734 |  | 
| 735 |     Aside: This function may be safely called standalone or within an explicit | 
| 736 |     transaction.  If called standalone, it's single query is implicitly | 
| 737 |     wrapped in it's own transaction. | 
| 738 |  | 
| 739 |     May set the last error to one of the following error codes: | 
| 740 |     DBError::NoError | 
| 741 |     DBError::SqlError | 
| 742 |     DBError::NoWritePermissions | 
| 743 |     DBError::InvalidDatabaseFile | 
| 744 | */ | 
| 745 | bool ServiceDatabase::executeQuery(QSqlQuery *query, const QString &statement, const QList<QVariant> &bindValues) | 
| 746 | { | 
| 747 |     Q_ASSERT(query != NULL); | 
| 748 |  | 
| 749 |     bool success = false; | 
| 750 |     enum {Prepare =0 , Execute=1}; | 
| 751 |     for (int stage=Prepare; stage <= Execute; ++stage) { | 
| 752 |         if ( stage == Prepare) | 
| 753 |             success = query->prepare(query: statement); | 
| 754 |         else // stage == Execute | 
| 755 |             success = query->exec(); | 
| 756 |  | 
| 757 |         if (!success) { | 
| 758 |             QString errorText; | 
| 759 |             errorText = QLatin1String("Problem: Could not %1 statement: %2"  | 
| 760 |                 "Reason: %3"  | 
| 761 |                 "Parameters: %4\n" ); | 
| 762 |             QString parameters; | 
| 763 |             if (bindValues.count() > 0) { | 
| 764 |                 for (int i = 0; i < bindValues.count(); ++i) { | 
| 765 |                     parameters.append(QStringLiteral("\n\t[" ) + QString::number(i) + QStringLiteral("]: " ) + bindValues.at(i).toString()); | 
| 766 |                 } | 
| 767 |             } else { | 
| 768 |                 parameters = QLatin1String("None" ); | 
| 769 |             } | 
| 770 |  | 
| 771 |             DBError::ErrorCode errorType; | 
| 772 |             int result = query->lastError().number(); | 
| 773 |             if (result == 26 || result == 11) {//SQLILTE_NOTADB || SQLITE_CORRUPT | 
| 774 |                 qWarning() << "Service Framework:- Database file is corrupt or invalid:"  << databasePath(); | 
| 775 |                 errorType = DBError::InvalidDatabaseFile; | 
| 776 |             } | 
| 777 |             else if ( result == 8) //SQLITE_READONLY | 
| 778 |                 errorType = DBError::NoWritePermissions; | 
| 779 |             else | 
| 780 |                 errorType = DBError::SqlError; | 
| 781 |  | 
| 782 |             m_lastError.setError(error: errorType, | 
| 783 |                     errorText: errorText | 
| 784 |                     .arg(a: stage == Prepare ?QLatin1String("prepare" ):QLatin1String("execute" )) | 
| 785 |                     .arg(a: statement) | 
| 786 |                     .arg(a: query->lastError().text()) | 
| 787 |                     .arg(a: parameters)); | 
| 788 |  | 
| 789 |             query->finish(); | 
| 790 |             query->clear(); | 
| 791 |             return false; | 
| 792 |         } | 
| 793 |  | 
| 794 |         if (stage == Prepare) { | 
| 795 |             foreach (const QVariant &bindValue, bindValues) | 
| 796 |             query->addBindValue(val: bindValue); | 
| 797 |         } | 
| 798 |     } | 
| 799 |  | 
| 800 |     m_lastError.setError(error: DBError::NoError); | 
| 801 |     return true; | 
| 802 | } | 
| 803 |  | 
| 804 | /* | 
| 805 |    Obtains a list of QServiceInterfaceDescriptors that match the constraints supplied | 
| 806 |    by \a filter. | 
| 807 |  | 
| 808 |    May set last error to one of the following error codes: | 
| 809 |    DBError::NoError | 
| 810 |    DBError::SqlError | 
| 811 |    DBError::DatabaseNotOpen | 
| 812 |    DBError::InvalidDatabaseConnection | 
| 813 |    DBError::NoWritePermissions | 
| 814 |    DBError::InvalidDatabaseFile | 
| 815 | */ | 
| 816 | QList<QServiceInterfaceDescriptor> ServiceDatabase::getInterfaces(const QServiceFilter &filter) | 
| 817 | { | 
| 818 |     QList<QServiceInterfaceDescriptor> interfaces; | 
| 819 |     if (!checkConnection()) { | 
| 820 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 821 |         qWarning() << "ServiceDatabase::getInterfaces():-"  | 
| 822 |                     << "Problem:"  << qPrintable(m_lastError.text()); | 
| 823 | #endif | 
| 824 |         return interfaces; | 
| 825 |     } | 
| 826 |  | 
| 827 |     QSqlDatabase database = QSqlDatabase::database(connectionName: m_connectionName); | 
| 828 |     QSqlQuery query(database); | 
| 829 |  | 
| 830 |     //multiple read queries are performed so wrap them | 
| 831 |     //in a read only transaction | 
| 832 |     if (!beginTransaction(query: &query, Read)) { | 
| 833 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 834 |         qWarning() << "ServiceDatabase::getInterfaces():-"  | 
| 835 |                     << "Unable to begin transaction. "  | 
| 836 |                     << "Reason:"  << qPrintable(m_lastError.text()); | 
| 837 | #endif | 
| 838 |         return interfaces; | 
| 839 |     } | 
| 840 |  | 
| 841 |     //Prepare search query, bind criteria values | 
| 842 |     QString selectComponent = QLatin1String("SELECT Interface.Name, "  | 
| 843 |                                 "Service.Name, Interface.VerMaj, "  | 
| 844 |                                 "Interface.VerMin, "  | 
| 845 |                                 "Service.Location, "  | 
| 846 |                                 "Service.ID, "  | 
| 847 |                                 "Interface.ID " ); | 
| 848 |     QString fromComponent = QLatin1String("FROM Interface, Service " ); | 
| 849 |     QString whereComponent = QLatin1String("WHERE Service.ID = Interface.ServiceID " ); | 
| 850 |     QList<QVariant> bindValues; | 
| 851 |  | 
| 852 |     if (filter.serviceName().isEmpty() && filter.interfaceName().isEmpty()) { | 
| 853 |         //do nothing, (don't add any extra constraints to the query | 
| 854 |     } else { | 
| 855 |  | 
| 856 |         if (!filter.serviceName().isEmpty()) { | 
| 857 |             whereComponent.append(s: QLatin1String("AND Service.Name = ?" )).append(s: QLatin1String(" COLLATE NOCASE " )); | 
| 858 |             bindValues.append(t: filter.serviceName()); | 
| 859 |         } | 
| 860 |         if (!filter.interfaceName().isEmpty()) { | 
| 861 |             whereComponent.append(s: QLatin1String("AND Interface.Name = ?" )).append(s: QLatin1String(" COLLATE NOCASE " )); | 
| 862 |             bindValues.append(t: filter.interfaceName()); | 
| 863 |             if (filter.majorVersion() >=0 && filter.minorVersion() >=0) { | 
| 864 |                 if (filter.versionMatchRule() == QServiceFilter::ExactVersionMatch) { | 
| 865 |                     whereComponent.append(s: QLatin1String("AND Interface.VerMaj = ?" )).append(s: QLatin1String(" AND Interface.VerMin = ? " )); | 
| 866 |                     bindValues.append(t: QString::number(filter.majorVersion())); | 
| 867 |                     bindValues.append(t: QString::number(filter.minorVersion())); | 
| 868 |                 } | 
| 869 |                 else if (filter.versionMatchRule() == QServiceFilter::MinimumVersionMatch) { | 
| 870 |                     whereComponent.append(s: QLatin1String("AND ((Interface.VerMaj > ?" )) | 
| 871 |                         .append(s: QLatin1String(") OR Interface.VerMaj = ?" )).append(s: QLatin1String(" AND Interface.VerMin >= ?" )).append(s: QLatin1String(") " )); | 
| 872 |                     bindValues.append(t: QString::number(filter.majorVersion())); | 
| 873 |                     bindValues.append(t: QString::number(filter.majorVersion())); | 
| 874 |                     bindValues.append(t: QString::number(filter.minorVersion())); | 
| 875 |                 } | 
| 876 |             } | 
| 877 |         } | 
| 878 |     } | 
| 879 |  | 
| 880 |     if (!executeQuery(query: &query, statement: selectComponent + fromComponent + whereComponent, bindValues)) { | 
| 881 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 882 |         qWarning() << "ServiceDatabase::getInterfaces():-"  | 
| 883 |                     << "Problem:"  << qPrintable(m_lastError.text()); | 
| 884 | #endif | 
| 885 |         rollbackTransaction(query: &query); | 
| 886 |         return interfaces; | 
| 887 |     } | 
| 888 |  | 
| 889 |     QServiceInterfaceDescriptor serviceInterface; | 
| 890 |     serviceInterface.d = new QServiceInterfaceDescriptorPrivate; | 
| 891 |     QStringList capabilities; | 
| 892 |     QString serviceID; | 
| 893 |     QString interfaceID; | 
| 894 |     const QSet<QString> filterCaps = filter.capabilities().toSet(); | 
| 895 |     QSet<QString> difference; | 
| 896 |  | 
| 897 |     while (query.next()){ | 
| 898 |         difference.clear(); | 
| 899 |         serviceInterface.d->customAttributes.clear(); | 
| 900 |         serviceInterface.d->attributes.clear(); | 
| 901 |         serviceInterface.d->interfaceName = query.value(i: EBindIndex).toString(); | 
| 902 |         serviceInterface.d->serviceName = query.value(i: EBindIndex1).toString(); | 
| 903 |         serviceInterface.d->major = query.value(i: EBindIndex2).toInt(); | 
| 904 |         serviceInterface.d->minor = query.value(i: EBindIndex3).toInt(); | 
| 905 |  | 
| 906 |         QString location = query.value(i: EBindIndex4).toString(); | 
| 907 |         if (location.startsWith(s: QLatin1String(SERVICE_IPC_PREFIX))) { | 
| 908 |             serviceInterface.d->attributes[QServiceInterfaceDescriptor::ServiceType] = QService::InterProcess; | 
| 909 |             serviceInterface.d->attributes[QServiceInterfaceDescriptor::Location] | 
| 910 |                 = location.remove(i: 0,len: QString(QLatin1String(SERVICE_IPC_PREFIX)).size()); | 
| 911 |         } else { | 
| 912 |             serviceInterface.d->attributes[QServiceInterfaceDescriptor::ServiceType] = QService::Plugin; | 
| 913 |             serviceInterface.d->attributes[QServiceInterfaceDescriptor::Location] = location; | 
| 914 |         } | 
| 915 |  | 
| 916 |         serviceID = query.value(i: EBindIndex5).toString(); | 
| 917 |         if (!populateServiceProperties(descriptor: &serviceInterface, serviceID)) { | 
| 918 |             //populateServiceProperties should already give a warning message | 
| 919 |             //and set the last error | 
| 920 |             interfaces.clear(); | 
| 921 |             rollbackTransaction(query: &query); | 
| 922 |             return interfaces; | 
| 923 |         } | 
| 924 |  | 
| 925 |         interfaceID = query.value(i: EBindIndex6).toString(); | 
| 926 |         if (!populateInterfaceProperties(descriptor: &serviceInterface, interfaceID)) { | 
| 927 |             //populateInterfaceProperties should already give a warning message | 
| 928 |             //and set the last error | 
| 929 |             interfaces.clear(); | 
| 930 |             rollbackTransaction(query: &query); | 
| 931 |             return interfaces; | 
| 932 |         } | 
| 933 |  | 
| 934 |         const QSet<QString> ifaceCaps = serviceInterface.d->attributes.value(akey: QServiceInterfaceDescriptor::Capabilities).toStringList().toSet(); | 
| 935 |         difference = ((filter.capabilityMatchRule() == QServiceFilter::MatchMinimum) ? (filterCaps-ifaceCaps) : (ifaceCaps-filterCaps)); | 
| 936 |         if (!difference.isEmpty()) | 
| 937 |             continue; | 
| 938 |  | 
| 939 |         //only return those interfaces that comply with set custom filters | 
| 940 |         if (filter.customAttributes().size() > 0) { | 
| 941 |             QSet<QString> keyDiff = filter.customAttributes().toSet(); | 
| 942 |             keyDiff.subtract(other: serviceInterface.d->customAttributes.uniqueKeys().toSet()); | 
| 943 |             if (keyDiff.isEmpty()) { //target descriptor has same custom keys as filter | 
| 944 |                 bool isMatch = true; | 
| 945 |                 const QStringList keys = filter.customAttributes(); | 
| 946 |                 for (int i = 0; i<keys.count(); i++) { | 
| 947 |                     if (serviceInterface.d->customAttributes.value(akey: keys[i]) != | 
| 948 |                             filter.customAttribute(which: keys[i])) { | 
| 949 |                         isMatch = false; | 
| 950 |                         break; | 
| 951 |                     } | 
| 952 |                 } | 
| 953 |                 if (isMatch) | 
| 954 |                     interfaces.append(t: serviceInterface); | 
| 955 |             } | 
| 956 |         } else { //no custom keys -> SQL statement ensures proper selection already | 
| 957 |             interfaces.append(t: serviceInterface); | 
| 958 |         } | 
| 959 |     } | 
| 960 |  | 
| 961 |     rollbackTransaction(query: &query);//read-only operation so just rollback | 
| 962 |     m_lastError.setError(error: DBError::NoError); | 
| 963 |     return interfaces; | 
| 964 | } | 
| 965 |  | 
| 966 | /* | 
| 967 |    Obtains a QServiceInterfaceDescriptor that | 
| 968 |    corresponds to a given \a interfaceID | 
| 969 |  | 
| 970 |    May set last error to one of the following error codes: | 
| 971 |    DBError::NoError | 
| 972 |    DBError::NotFound | 
| 973 |    DBError::SqlError | 
| 974 |    DBError::DatabaseNotOpen | 
| 975 |    DBError::InvalidDatabaseConnection | 
| 976 |    DBError::NoWritePermissions | 
| 977 |    DBError::InvalidDatabaseFile | 
| 978 | */ | 
| 979 | QServiceInterfaceDescriptor ServiceDatabase::getInterface(const QString &interfaceID) | 
| 980 | { | 
| 981 |     QServiceInterfaceDescriptor serviceInterface; | 
| 982 |     if (!checkConnection()) { | 
| 983 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 984 |         qWarning() << "ServiceDatabase::getInterface():-"  | 
| 985 |                     << "Problem:"  << qPrintable(m_lastError.text()); | 
| 986 | #endif | 
| 987 |         return serviceInterface; | 
| 988 |     } | 
| 989 |  | 
| 990 |     QSqlDatabase database = QSqlDatabase::database(connectionName: m_connectionName); | 
| 991 |     QSqlQuery query(database); | 
| 992 |  | 
| 993 |     if (!beginTransaction(query: &query, Read)) { | 
| 994 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 995 |         qWarning() << "ServiceDatabase::getInterface():-"  | 
| 996 |                     << "Unable to begin transaction. "  | 
| 997 |                     << "Reason:"  << qPrintable(m_lastError.text()); | 
| 998 | #endif | 
| 999 |         return serviceInterface; | 
| 1000 |     } | 
| 1001 |  | 
| 1002 |     QString selectComponent = QLatin1String("SELECT Interface.Name, "  | 
| 1003 |                                 "Service.Name, Interface.VerMaj, "  | 
| 1004 |                                 "Interface.VerMin, "  | 
| 1005 |                                 "Service.Location, "  | 
| 1006 |                                 "Service.ID " ); | 
| 1007 |     QString fromComponent = QLatin1String("FROM Interface, Service " ); | 
| 1008 |     QString whereComponent = QLatin1String("WHERE Service.ID = Interface.ServiceID "  | 
| 1009 |                                     "AND Interface.ID = ? " ); | 
| 1010 |     QList<QVariant> bindValues; | 
| 1011 |     bindValues.append(t: interfaceID); | 
| 1012 |  | 
| 1013 |     if (!executeQuery(query: &query, statement: selectComponent + fromComponent + whereComponent, bindValues)) { | 
| 1014 |         rollbackTransaction(query: &query); | 
| 1015 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1016 |         qWarning() << "ServiceDatabase::getInterfaces():-"  | 
| 1017 |                     << "Problem:"  << qPrintable(m_lastError.text()); | 
| 1018 | #endif | 
| 1019 |         return serviceInterface; | 
| 1020 |     } | 
| 1021 |  | 
| 1022 |     if (!query.next()) { | 
| 1023 |         rollbackTransaction(query: &query); | 
| 1024 |         QString errorText(QLatin1String("Interface implementation not found for Interface ID: %1" )); | 
| 1025 |         m_lastError.setError(error: DBError::NotFound, errorText: errorText.arg(a: interfaceID)); | 
| 1026 |         return serviceInterface; | 
| 1027 |     } | 
| 1028 |  | 
| 1029 |     serviceInterface.d = new QServiceInterfaceDescriptorPrivate; | 
| 1030 |     serviceInterface.d->interfaceName =query.value(i: EBindIndex).toString(); | 
| 1031 |     serviceInterface.d->serviceName = query.value(i: EBindIndex1).toString(); | 
| 1032 |     serviceInterface.d->major = query.value(i: EBindIndex2).toInt(); | 
| 1033 |     serviceInterface.d->minor = query.value(i: EBindIndex3).toInt(); | 
| 1034 |  | 
| 1035 |     QString location = query.value(i: EBindIndex4).toString(); | 
| 1036 |     if (location.startsWith(s: QLatin1String(SERVICE_IPC_PREFIX))) { | 
| 1037 |         serviceInterface.d->attributes[QServiceInterfaceDescriptor::ServiceType] = QService::InterProcess; | 
| 1038 |         serviceInterface.d->attributes[QServiceInterfaceDescriptor::Location] | 
| 1039 |             = location.remove(i: 0,len: QString(QLatin1String(SERVICE_IPC_PREFIX)).size()); | 
| 1040 |     } else { | 
| 1041 |         serviceInterface.d->attributes[QServiceInterfaceDescriptor::ServiceType] = QService::Plugin; | 
| 1042 |         serviceInterface.d->attributes[QServiceInterfaceDescriptor::Location] = location; | 
| 1043 |     } | 
| 1044 |  | 
| 1045 |     QString serviceID = query.value(i: EBindIndex5).toString(); | 
| 1046 |     if (!populateServiceProperties(descriptor: &serviceInterface, serviceID)) { | 
| 1047 |         //populateServiceProperties should already give a warning message | 
| 1048 |         //and set the last error | 
| 1049 |         rollbackTransaction(query: &query); | 
| 1050 |         return QServiceInterfaceDescriptor(); | 
| 1051 |     } | 
| 1052 |  | 
| 1053 |     if (!populateInterfaceProperties(descriptor: &serviceInterface, interfaceID)) { | 
| 1054 |         //populateInterfaceProperties should already give a warning message | 
| 1055 |         //and set the last error | 
| 1056 |         rollbackTransaction(query: &query); | 
| 1057 |         return QServiceInterfaceDescriptor(); | 
| 1058 |     } | 
| 1059 |  | 
| 1060 |     rollbackTransaction(query: &query);//read only operation so just rollback | 
| 1061 |     m_lastError.setError(error: DBError::NoError); | 
| 1062 |     return serviceInterface; | 
| 1063 | } | 
| 1064 |  | 
| 1065 | /* | 
| 1066 |     Obtains a list of services names.  If \a interfaceName is empty, | 
| 1067 |     then all service names are returned.  If \a interfaceName specifies | 
| 1068 |     an interface then the names of all services implementing that interface | 
| 1069 |     are returned | 
| 1070 |  | 
| 1071 |     May set last error to one of the following error codes: | 
| 1072 |     DBError::NoError | 
| 1073 |     DBError::SqlError | 
| 1074 |     DBError::DatabaseNotOpen | 
| 1075 |     DBError::InvalidDatabaseConnection | 
| 1076 |     DBError::NoWritePermissions | 
| 1077 |     DBError::InvalidDatabaseFile | 
| 1078 |  | 
| 1079 |     Aside:  There is only one query which implicitly gets | 
| 1080 |     wrapped in it's own transaction. | 
| 1081 | */ | 
| 1082 | QStringList ServiceDatabase::getServiceNames(const QString &interfaceName) | 
| 1083 | { | 
| 1084 |     QStringList services; | 
| 1085 |     if (!checkConnection()) { | 
| 1086 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1087 |         qWarning() << "ServiceDatabase::getServiceNames():-"  | 
| 1088 |                     << "Problem:"  << qPrintable(m_lastError.text()); | 
| 1089 | #endif | 
| 1090 |         return services; | 
| 1091 |     } | 
| 1092 |     QSqlDatabase database = QSqlDatabase::database(connectionName: m_connectionName); | 
| 1093 |     QSqlQuery query(database); | 
| 1094 |     QString selectComponent(QLatin1String("SELECT DISTINCT Service.Name COLLATE NOCASE " )); | 
| 1095 |     QString fromComponent; | 
| 1096 |     QString whereComponent; | 
| 1097 |     QList<QVariant> bindValues; | 
| 1098 |     if (interfaceName.isEmpty()) { | 
| 1099 |         fromComponent = QLatin1String("FROM Service " ); | 
| 1100 |     } else { | 
| 1101 |         fromComponent = QLatin1String("FROM Interface,Service " ); | 
| 1102 |         whereComponent = QLatin1String("WHERE Service.ID = Interface.ServiceID AND Interface.Name = ? COLLATE NOCASE " ); | 
| 1103 |         bindValues.append(t: interfaceName); | 
| 1104 |     } | 
| 1105 |  | 
| 1106 |     if (!executeQuery(query: &query, statement: selectComponent + fromComponent + whereComponent, bindValues)) { | 
| 1107 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1108 |         qWarning() << "ServiceDatabase::getServiceNames():-"  | 
| 1109 |                     << qPrintable(m_lastError.text()); | 
| 1110 | #endif | 
| 1111 |         return services; | 
| 1112 |     } | 
| 1113 |  | 
| 1114 |     while ( query.next()) { | 
| 1115 |         services.append(t: query.value(i: EBindIndex).toString()); | 
| 1116 |     } | 
| 1117 |     query.finish(); | 
| 1118 |     query.clear(); | 
| 1119 |     m_lastError.setError(error: DBError::NoError); | 
| 1120 |     return services; | 
| 1121 | } | 
| 1122 |  | 
| 1123 | /* | 
| 1124 |     Returns a descriptor for the default interface implementation of | 
| 1125 |     \a interfaceName. | 
| 1126 |  | 
| 1127 |     For user scope databases only, \a defaultInterfaceID is set if the default | 
| 1128 |     in the user scope database refers to a interface implementation in the | 
| 1129 |     system scope database.  In this case the descriptor will be invalid and | 
| 1130 |     the \a defaultInterfaceID must be used to query the system scope database, | 
| 1131 |     The last error set to DBError::ExternalIfaceIDFound | 
| 1132 |  | 
| 1133 |     If this function is called within a transaction, \a inTransaction | 
| 1134 |     must be set to true.  If \a inTransaction is false, this fuction | 
| 1135 |     will begin and end its own transaction. | 
| 1136 |  | 
| 1137 |     The last error may be set to one of the following error codes: | 
| 1138 |     DBError::NoError | 
| 1139 |     DBError::ExternalIfaceIDFound | 
| 1140 |     DBError::SqlError | 
| 1141 |     DBError::DatabaseNotOpen | 
| 1142 |     DBError::InvalidDatabaseConnection | 
| 1143 |     DBError::NoWritePermissions | 
| 1144 |     DBError::InvalidDatabaseFile | 
| 1145 | */ | 
| 1146 | QServiceInterfaceDescriptor ServiceDatabase::interfaceDefault(const QString &interfaceName, QString *defaultInterfaceID, | 
| 1147 |                                                                     bool inTransaction) | 
| 1148 | { | 
| 1149 |     QServiceInterfaceDescriptor serviceInterface; | 
| 1150 |     if (!checkConnection()) | 
| 1151 |     { | 
| 1152 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1153 |         qWarning() << "ServiceDatabase::interfaceDefault():-"  | 
| 1154 |                     << "Problem:"  << qPrintable(m_lastError.text()); | 
| 1155 | #endif | 
| 1156 |         return serviceInterface; | 
| 1157 |     } | 
| 1158 |  | 
| 1159 |     QSqlDatabase database = QSqlDatabase::database(connectionName: m_connectionName); | 
| 1160 |     QSqlQuery query(database); | 
| 1161 |  | 
| 1162 |     if (!inTransaction && !beginTransaction(query: &query, Read)) { | 
| 1163 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1164 |         qWarning() << "ServiceDatabase::interfaceDefault(QString, QString):-"  | 
| 1165 |                     << "Unable to begin transaction. "  | 
| 1166 |                     << "Reason:"  << qPrintable(m_lastError.text()); | 
| 1167 | #endif | 
| 1168 |         return serviceInterface; | 
| 1169 |     } | 
| 1170 |  | 
| 1171 |     QString statement(QLatin1String("SELECT InterfaceID FROM Defaults WHERE InterfaceName = ? COLLATE NOCASE" )); | 
| 1172 |     QList<QVariant> bindValues; | 
| 1173 |     bindValues.append(t: interfaceName); | 
| 1174 |     if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1175 |         if (!inTransaction) | 
| 1176 |             rollbackTransaction(query: &query); | 
| 1177 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1178 |         qWarning() << "ServiceDatabase::interfaceDefault():-"  | 
| 1179 |                     << qPrintable(m_lastError.text()); | 
| 1180 | #endif | 
| 1181 |         return serviceInterface; | 
| 1182 |     } | 
| 1183 |  | 
| 1184 |     QString interfaceID; | 
| 1185 |     if (!query.next()) | 
| 1186 |     { | 
| 1187 |         if (!inTransaction) | 
| 1188 |             rollbackTransaction(query: &query); | 
| 1189 |         QString errorText(QLatin1String("No default service found for interface: \"%1\"" )); | 
| 1190 |         m_lastError.setError(error: DBError::NotFound, errorText: errorText.arg(a: interfaceName)); | 
| 1191 |         return serviceInterface; | 
| 1192 |     } | 
| 1193 |     else | 
| 1194 |         interfaceID = query.value(i: EBindIndex).toString(); | 
| 1195 |     Q_ASSERT(!interfaceID.isEmpty()); | 
| 1196 |  | 
| 1197 |     statement = QLatin1String("SELECT Interface.Name, "  | 
| 1198 |                         "Service.Name, Interface.VerMaj, "  | 
| 1199 |                         "Interface.VerMin, "  | 
| 1200 |                         "Service.Location, "  | 
| 1201 |                         "Service.ID "  | 
| 1202 |                     "FROM Service, Interface "  | 
| 1203 |                     "WHERE Service.ID = Interface.ServiceID AND Interface.ID = ?" ); | 
| 1204 |     bindValues.clear(); | 
| 1205 |     bindValues.append(t: interfaceID); | 
| 1206 |     if (!executeQuery(query: &query, statement, bindValues)) | 
| 1207 |     { | 
| 1208 |         if (!inTransaction) | 
| 1209 |             rollbackTransaction(query: &query); | 
| 1210 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1211 |         qWarning() << "ServiceDatabase::interfaceDefault():-"  | 
| 1212 |                     << qPrintable(m_lastError.text()); | 
| 1213 | #endif | 
| 1214 |         return serviceInterface; | 
| 1215 |     } | 
| 1216 |  | 
| 1217 |     if (!query.next()) { | 
| 1218 |         if (!inTransaction) | 
| 1219 |             rollbackTransaction(query: &query); | 
| 1220 |         if (defaultInterfaceID != NULL ) | 
| 1221 |             *defaultInterfaceID = interfaceID; | 
| 1222 |         m_lastError.setError(error: DBError::ExternalIfaceIDFound); | 
| 1223 |         return serviceInterface; | 
| 1224 |     } | 
| 1225 |  | 
| 1226 |     serviceInterface.d = new QServiceInterfaceDescriptorPrivate; | 
| 1227 |     serviceInterface.d->interfaceName =query.value(i: EBindIndex).toString(); | 
| 1228 |     serviceInterface.d->serviceName = query.value(i: EBindIndex1).toString(); | 
| 1229 |     serviceInterface.d->major = query.value(i: EBindIndex2).toInt(); | 
| 1230 |     serviceInterface.d->minor = query.value(i: EBindIndex3).toInt(); | 
| 1231 |  | 
| 1232 |     QString location = query.value(i: EBindIndex4).toString(); | 
| 1233 |     if (location.startsWith(s: QLatin1String(SERVICE_IPC_PREFIX))) { | 
| 1234 |         serviceInterface.d->attributes[QServiceInterfaceDescriptor::ServiceType] = QService::InterProcess; | 
| 1235 |         serviceInterface.d->attributes[QServiceInterfaceDescriptor::Location] | 
| 1236 |             = location.remove(i: 0,len: QString(QLatin1String(SERVICE_IPC_PREFIX)).size()); | 
| 1237 |     } else { | 
| 1238 |         serviceInterface.d->attributes[QServiceInterfaceDescriptor::ServiceType] = QService::Plugin; | 
| 1239 |         serviceInterface.d->attributes[QServiceInterfaceDescriptor::Location] = location; | 
| 1240 |     } | 
| 1241 |  | 
| 1242 |     QString serviceID = query.value(i: EBindIndex5).toString(); | 
| 1243 |     if (!populateServiceProperties(descriptor: &serviceInterface, serviceID)) { | 
| 1244 |         //populateServiceProperties should already give a warning | 
| 1245 |         //and set the last error | 
| 1246 |         if (!inTransaction) | 
| 1247 |             rollbackTransaction(query: &query); | 
| 1248 |         return QServiceInterfaceDescriptor(); | 
| 1249 |     } | 
| 1250 |  | 
| 1251 |     if (!populateInterfaceProperties(descriptor: &serviceInterface, interfaceID)) { | 
| 1252 |         //populateInterfaceProperties should already give a warning | 
| 1253 |         //and set the last error | 
| 1254 |         if (!inTransaction) | 
| 1255 |             rollbackTransaction(query: &query); | 
| 1256 |         return QServiceInterfaceDescriptor(); | 
| 1257 |     } | 
| 1258 |  | 
| 1259 |     if (!inTransaction) | 
| 1260 |         rollbackTransaction(query: &query); //Read only operation so just rollback | 
| 1261 |     m_lastError.setError(error: DBError::NoError); | 
| 1262 |     return serviceInterface; | 
| 1263 | } | 
| 1264 |  | 
| 1265 | /* | 
| 1266 |    Sets a particular service's \a interface implementation as a the default | 
| 1267 |    implementation to look up when using the interface's name in | 
| 1268 |    interfaceDefault(). | 
| 1269 |  | 
| 1270 |    For a user scope database an \a externalInterfaceID can be provided | 
| 1271 |    so that the Defaults table will contain a "link" to an interface | 
| 1272 |    implmentation provided in the system scope database. | 
| 1273 |  | 
| 1274 |    May set the last error to one of the following error codes: | 
| 1275 |    DBError::NoError | 
| 1276 |    DBerror::NotFound | 
| 1277 |    DBError::SqlError | 
| 1278 |    DBError::DatabaseNotOpen | 
| 1279 |    DBError::InvalidDatabaseConnection | 
| 1280 |    DBError::NoWritePermissions | 
| 1281 |    DBError::InvalidDatabaseFile | 
| 1282 | */ | 
| 1283 | bool ServiceDatabase::setInterfaceDefault(const QServiceInterfaceDescriptor &serviceInterface, const QString &externalInterfaceID) | 
| 1284 | { | 
| 1285 |     if (!checkConnection()) { | 
| 1286 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1287 |         qWarning() << "ServiceDatabase::setInterfaceDefault(QServiceInterfaceDescriptor):-"  | 
| 1288 |             << "Problem:"  << qPrintable(m_lastError.text()); | 
| 1289 | #endif | 
| 1290 |         return false; | 
| 1291 |     } | 
| 1292 |  | 
| 1293 |     QSqlDatabase database = QSqlDatabase::database(connectionName: m_connectionName); | 
| 1294 |     QSqlQuery query(database); | 
| 1295 |  | 
| 1296 |     //Begin Transaction | 
| 1297 |     if (!beginTransaction(query: &query, Write)) { | 
| 1298 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1299 |         qWarning() << "ServiceDatabase::setInterfaceDefault(QServiceInterfaceDescriptor):-"  | 
| 1300 |             << "Problem: Unable to begin transaction."  | 
| 1301 |             << "Reason:"  << qPrintable(m_lastError.text()); | 
| 1302 | #endif | 
| 1303 |         return false; | 
| 1304 |     } | 
| 1305 |  | 
| 1306 |     QString statement; | 
| 1307 |     QList<QVariant> bindValues; | 
| 1308 |     QString interfaceID = externalInterfaceID; | 
| 1309 |     if (interfaceID.isEmpty()) { | 
| 1310 |         statement = QLatin1String("SELECT Interface.ID from Interface, Service "  | 
| 1311 |                 "WHERE Service.ID = Interface.ServiceID "  | 
| 1312 |                 "AND Service.Name = ? COLLATE NOCASE "  | 
| 1313 |                 "AND Interface.Name = ? COLLATE NOCASE "  | 
| 1314 |                 "AND Interface.VerMaj = ? "  | 
| 1315 |                 "AND Interface.VerMin = ? " ); | 
| 1316 |         bindValues.append(t: serviceInterface.serviceName()); | 
| 1317 |         bindValues.append(t: serviceInterface.interfaceName()); | 
| 1318 |         bindValues.append(t: serviceInterface.majorVersion()); | 
| 1319 |         bindValues.append(t: serviceInterface.minorVersion()); | 
| 1320 |  | 
| 1321 |         if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1322 |             rollbackTransaction(query: &query); | 
| 1323 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1324 |             qWarning() << "ServiceDatabase::setInterfaceDefault(QServiceInterfaceDescriptor):-"  | 
| 1325 |                 << qPrintable(m_lastError.text()); | 
| 1326 | #endif | 
| 1327 |             return false; | 
| 1328 |         } | 
| 1329 |  | 
| 1330 |         if (!query.next()) { | 
| 1331 |             QString errorText; | 
| 1332 |             errorText = QLatin1String("No implementation for interface: %1, Version: %2.%3 found "  | 
| 1333 |                 "for service: %4" ); | 
| 1334 |             m_lastError.setNotFoundError(errorText.arg(a: serviceInterface.interfaceName()) | 
| 1335 |                     .arg(a: serviceInterface.majorVersion()) | 
| 1336 |                     .arg(a: serviceInterface.minorVersion()) | 
| 1337 |                     .arg(a: serviceInterface.serviceName())); | 
| 1338 |  | 
| 1339 |             rollbackTransaction(query: &query); | 
| 1340 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1341 |             qWarning() << "ServiceDatbase::setInterfaceDefault(QServiceInterfaceDescriptor):-"  | 
| 1342 |                 << "Problem: Unable to set default service. "  | 
| 1343 |                 << "Reason:"  << qPrintable(m_lastError.text()); | 
| 1344 | #endif | 
| 1345 |             return false; | 
| 1346 |         } | 
| 1347 |  | 
| 1348 |         interfaceID = query.value(i: EBindIndex).toString(); | 
| 1349 |         Q_ASSERT(!interfaceID.isEmpty()); | 
| 1350 |     } | 
| 1351 |  | 
| 1352 |     statement = QLatin1String("SELECT InterfaceName FROM Defaults WHERE InterfaceName = ? COLLATE NOCASE" ); | 
| 1353 |     bindValues.clear(); | 
| 1354 |     bindValues.append(t: serviceInterface.interfaceName()); | 
| 1355 |     if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1356 |         rollbackTransaction(query: &query); | 
| 1357 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1358 |         qWarning() << "ServiceDatabase::setInterfaceDefault(QServiceInterfaceDescriptor):-"  | 
| 1359 |                     << qPrintable(m_lastError.text()); | 
| 1360 | #endif | 
| 1361 |         return false; | 
| 1362 |     } | 
| 1363 |  | 
| 1364 |     if (query.next()) { | 
| 1365 |         statement = QLatin1String("UPDATE Defaults "  | 
| 1366 |             "SET InterfaceID = ? "  | 
| 1367 |             "WHERE InterfaceName = ? COLLATE NOCASE" ); | 
| 1368 |         bindValues.clear(); | 
| 1369 |         bindValues.append(t: interfaceID); | 
| 1370 |         bindValues.append(t: serviceInterface.interfaceName()); | 
| 1371 |  | 
| 1372 |         if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1373 |             rollbackTransaction(query: &query); | 
| 1374 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1375 |             qWarning() << "ServiceDatabase::setInterfaceDefault(QServiceInterfaceDescriptor):-"  | 
| 1376 |                 << qPrintable(m_lastError.text()); | 
| 1377 | #endif | 
| 1378 |             return false; | 
| 1379 |         } | 
| 1380 |     } else { | 
| 1381 |         statement = QLatin1String("INSERT INTO Defaults(InterfaceName,InterfaceID) VALUES(?,?)" ); | 
| 1382 |         bindValues.clear(); | 
| 1383 |         bindValues.append(t: serviceInterface.interfaceName()); | 
| 1384 |         bindValues.append(t: interfaceID); | 
| 1385 |  | 
| 1386 |         if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1387 |             rollbackTransaction(query: &query); | 
| 1388 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1389 |             qWarning() << "ServiceDatabase::setInterfaceDefault(QServiceInterfaceDescriptor):-"  | 
| 1390 |                 << qPrintable(m_lastError.text()); | 
| 1391 | #endif | 
| 1392 |             return false; | 
| 1393 |         } | 
| 1394 |     } | 
| 1395 |  | 
| 1396 |     //End Transaction | 
| 1397 |     if (!commitTransaction(query: &query)) { | 
| 1398 |         rollbackTransaction(query: &query); | 
| 1399 |         return false; | 
| 1400 |     } | 
| 1401 |     m_lastError.setError(error: DBError::NoError); | 
| 1402 |     return true; | 
| 1403 | } | 
| 1404 |  | 
| 1405 | /* | 
| 1406 |    Removes the service with name \a serviceName. | 
| 1407 |    If the service provides a default interface implementation, then | 
| 1408 |    another service implementing the highest interface implementation | 
| 1409 |    version becomes the new default(if any).  If more than one service | 
| 1410 |    provides same the highest version number, an arbitrary choice is made | 
| 1411 |    between them. | 
| 1412 |  | 
| 1413 |    May set the last error to the folowing error codes: | 
| 1414 |    DBError::NoError | 
| 1415 |    DBError::NotFound | 
| 1416 |    DBError::SqlError | 
| 1417 |    DBError::DatabaseNotOpen | 
| 1418 |    DBError::InvalidDatabaseConnection | 
| 1419 |    DBError::NoWritePermissions | 
| 1420 |    DBError::InvalidDatabaseFile | 
| 1421 | */ | 
| 1422 | bool ServiceDatabase::unregisterService(const QString &serviceName, const QString &securityToken) | 
| 1423 | { | 
| 1424 | #ifndef QT_SFW_SERVICEDATABASE_USE_SECURITY_TOKEN | 
| 1425 |     Q_UNUSED(securityToken); | 
| 1426 | #else | 
| 1427 |     if (securityToken.isEmpty()) { | 
| 1428 |         QString errorText(QLatin1String("Access denied, no security token provided (for unregistering service: \"%1\")" )); | 
| 1429 |         m_lastError.setError(DBError::NoWritePermissions, errorText.arg(serviceName)); | 
| 1430 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1431 |         qWarning() << "ServiceDatabase::unregisterService():-"  | 
| 1432 |                 << "Problem: Unable to unregister service. "  | 
| 1433 |                 << "Reason:"  << qPrintable(m_lastError.text()); | 
| 1434 | #endif | 
| 1435 |         return false; | 
| 1436 |     } | 
| 1437 | #endif | 
| 1438 |  | 
| 1439 |  | 
| 1440 |     if (!checkConnection()) { | 
| 1441 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1442 |         qWarning() << "ServiceDatabase::unregisterService():-"  | 
| 1443 |                     << "Problem:"  << qPrintable(m_lastError.text()); | 
| 1444 | #endif | 
| 1445 |         return false; | 
| 1446 |     } | 
| 1447 |  | 
| 1448 |     QSqlDatabase database = QSqlDatabase::database(connectionName: m_connectionName); | 
| 1449 |     QSqlQuery query(database); | 
| 1450 |  | 
| 1451 |     if (!beginTransaction(query: &query, Write)) { | 
| 1452 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1453 |         qWarning() << "ServiceDatabase::unregisterService():-"  | 
| 1454 |                     << "Problem: Unable to begin transaction. "  | 
| 1455 |                     << "Reason:"  << qPrintable(m_lastError.text()); | 
| 1456 | #endif | 
| 1457 |         return false; | 
| 1458 |     } | 
| 1459 |  | 
| 1460 |     QString statement(QLatin1String("SELECT Service.ID from Service WHERE Service.Name = ? COLLATE NOCASE" )); | 
| 1461 |     QList<QVariant> bindValues; | 
| 1462 |     bindValues.append(t: serviceName); | 
| 1463 |     if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1464 |         rollbackTransaction(query: &query); | 
| 1465 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1466 |         qWarning() << "ServiceDatabase::unregisterService():-"  | 
| 1467 |                     << qPrintable(m_lastError.text()); | 
| 1468 | #endif | 
| 1469 |         return false; | 
| 1470 |     } | 
| 1471 |  | 
| 1472 |     QStringList serviceIDs; | 
| 1473 |     while (query.next()) { | 
| 1474 |         serviceIDs << query.value(i: EBindIndex).toString(); | 
| 1475 |     } | 
| 1476 |  | 
| 1477 | #ifdef QT_SFW_SERVICEDATABASE_USE_SECURITY_TOKEN | 
| 1478 |     // Only the application that registered the service is allowed to unregister that | 
| 1479 |     // service. Fetch a security ID of a service (with given name) and verify that it matches | 
| 1480 |     // with current apps security id. Only one application is allowed to register services with | 
| 1481 |     // same name, hence a distinct (just any of the) security token will do because they are identical. | 
| 1482 |     if (!serviceIDs.isEmpty()) { | 
| 1483 |         statement = QLatin1String("SELECT DISTINCT Value FROM ServiceProperty WHERE ServiceID = ? AND Key = ?" ); | 
| 1484 |         bindValues.clear(); | 
| 1485 |         bindValues.append(serviceIDs.first()); | 
| 1486 |         bindValues.append(SECURITY_TOKEN_KEY); | 
| 1487 |  | 
| 1488 |         if (!executeQuery(&query, statement, bindValues)) { | 
| 1489 |             rollbackTransaction(&query); | 
| 1490 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1491 |             qWarning() << "ServiceDatabase::unregisterService():-"  | 
| 1492 |                     << qPrintable(m_lastError.text()); | 
| 1493 | #endif | 
| 1494 |             return false; | 
| 1495 |         } | 
| 1496 |         QString existingSecurityToken; | 
| 1497 |         if (query.next()) { | 
| 1498 |             existingSecurityToken = query.value(EBindIndex).toString(); | 
| 1499 |         } | 
| 1500 |         if (existingSecurityToken != securityToken) { | 
| 1501 |             QString errorText(QLatin1String("Access denied: \"%1\"" )); | 
| 1502 |             m_lastError.setError(DBError::NoWritePermissions, errorText.arg(serviceName)); | 
| 1503 |             rollbackTransaction(&query); | 
| 1504 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1505 |             qWarning() << "ServiceDatabase::unregisterService():-"  | 
| 1506 |                     << "Problem: Unable to unregister service"  | 
| 1507 |                     << "Reason:"  << qPrintable(m_lastError.text()); | 
| 1508 | #endif | 
| 1509 |             return false; | 
| 1510 |         } | 
| 1511 |     } | 
| 1512 | #endif // QT_SFW_SERVICEDATABASE_USE_SECURITY_TOKEN | 
| 1513 |  | 
| 1514 |     statement = QLatin1String("SELECT Interface.ID from Interface, Service "  | 
| 1515 |                 "WHERE Interface.ServiceID = Service.ID "  | 
| 1516 |                     "AND Service.Name =? COLLATE NOCASE" ); | 
| 1517 |     bindValues.clear(); | 
| 1518 |     bindValues.append(t: serviceName); | 
| 1519 |     if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1520 |         rollbackTransaction(query: &query); | 
| 1521 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1522 |         qWarning() << "ServiceDatabase::unregisterService():-"  | 
| 1523 |                     << qPrintable(m_lastError.text()); | 
| 1524 | #endif | 
| 1525 |         return false; | 
| 1526 |     } | 
| 1527 |  | 
| 1528 |     QStringList interfaceIDs; | 
| 1529 |     while (query.next()) { | 
| 1530 |         interfaceIDs << query.value(i: EBindIndex).toString(); | 
| 1531 |     } | 
| 1532 |  | 
| 1533 |     if (serviceIDs.count() == 0) { | 
| 1534 |         QString errorText(QLatin1String("Service not found: \"%1\"" )); | 
| 1535 |         m_lastError.setError(error: DBError::NotFound, errorText: errorText.arg(a: serviceName)); | 
| 1536 |         rollbackTransaction(query: &query); | 
| 1537 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1538 |         qWarning() << "ServiceDatabase::unregisterService():-"  | 
| 1539 |                     << "Problem: Unable to unregister service"  | 
| 1540 |                     << "Reason:"  << qPrintable(m_lastError.text()); | 
| 1541 | #endif | 
| 1542 |         return false; | 
| 1543 |     } | 
| 1544 |  | 
| 1545 |     statement = QLatin1String("SELECT Defaults.InterfaceName "  | 
| 1546 |                 "FROM Defaults, Interface, Service "  | 
| 1547 |                 "WHERE Defaults.InterfaceID = Interface.ID "  | 
| 1548 |                     "AND Interface.ServiceID = Service.ID "  | 
| 1549 |                     "AND Service.Name = ? COLLATE NOCASE" ); | 
| 1550 |     bindValues.clear(); | 
| 1551 |     bindValues.append(t: serviceName); | 
| 1552 |     if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1553 |         rollbackTransaction(query: &query); | 
| 1554 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1555 |         qWarning() << "ServiceDatabase:unregisterService():-"  | 
| 1556 |                     << qPrintable(m_lastError.text()); | 
| 1557 | #endif | 
| 1558 |         return false; | 
| 1559 |     } | 
| 1560 |  | 
| 1561 |     QStringList serviceDefaultInterfaces; | 
| 1562 |     while (query.next()) { | 
| 1563 |         serviceDefaultInterfaces << query.value(i: EBindIndex).toString(); | 
| 1564 |     } | 
| 1565 |  | 
| 1566 |  | 
| 1567 |     statement = QLatin1String("DELETE FROM Service WHERE Service.Name = ? COLLATE NOCASE" ); | 
| 1568 |     bindValues.clear(); | 
| 1569 |     bindValues.append(t: serviceName); | 
| 1570 |     if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1571 |         rollbackTransaction(query: &query); | 
| 1572 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1573 |         qWarning() << "ServiceDatabase::unregisterService():-"  | 
| 1574 |                     << qPrintable(m_lastError.text()); | 
| 1575 | #endif | 
| 1576 |         return false; | 
| 1577 |     } | 
| 1578 |  | 
| 1579 |     statement = QLatin1String("DELETE FROM Interface WHERE Interface.ServiceID = ?" ); | 
| 1580 |     foreach (const QString &serviceID, serviceIDs) { | 
| 1581 |         bindValues.clear(); | 
| 1582 |         bindValues.append(t: serviceID); | 
| 1583 |         if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1584 |             rollbackTransaction(query: &query); | 
| 1585 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1586 |             qWarning() << "ServiceDatabase::unregisterService():-"  | 
| 1587 |                         << qPrintable(m_lastError.text()); | 
| 1588 | #endif | 
| 1589 |             return false; | 
| 1590 |         } | 
| 1591 |     } | 
| 1592 |  | 
| 1593 |     statement = QLatin1String("DELETE FROM ServiceProperty WHERE ServiceID = ?" ); | 
| 1594 |  | 
| 1595 |     foreach (const QString &serviceID, serviceIDs) { | 
| 1596 |         bindValues.clear(); | 
| 1597 |         bindValues.append(t: serviceID); | 
| 1598 |         if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1599 |             rollbackTransaction(query: &query); | 
| 1600 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1601 |             qWarning() << "ServiceDatabase::unregisterService():-"  | 
| 1602 |                         << qPrintable(m_lastError.text()); | 
| 1603 | #endif | 
| 1604 |             return false; | 
| 1605 |         } | 
| 1606 |     } | 
| 1607 |  | 
| 1608 |     statement = QLatin1String("DELETE FROM InterfaceProperty WHERE InterfaceID = ?" ); | 
| 1609 |     foreach (const QString &interfaceID,  interfaceIDs) { | 
| 1610 |         bindValues.clear(); | 
| 1611 |         bindValues.append(t: interfaceID); | 
| 1612 |         if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1613 |             rollbackTransaction(query: &query); | 
| 1614 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1615 |             qWarning() << "ServiceDatabase::unregisterService():-"  | 
| 1616 |                         << qPrintable(m_lastError.text()); | 
| 1617 | #endif | 
| 1618 |             return false; | 
| 1619 |         } | 
| 1620 |     } | 
| 1621 |  | 
| 1622 |     foreach (const QString &interfaceName, serviceDefaultInterfaces) { | 
| 1623 |         statement = QLatin1String("SELECT ID FROM Interface WHERE Interface.Name = ? COLLATE NOCASE "  | 
| 1624 |                     "ORDER BY Interface.VerMaj DESC, Interface.VerMin DESC" ); | 
| 1625 |         bindValues.clear(); | 
| 1626 |         bindValues.append(t: interfaceName); | 
| 1627 |         if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1628 |             rollbackTransaction(query: &query); | 
| 1629 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1630 |             qWarning() << "ServiceDatabase::unregisterService():-"  | 
| 1631 |                         << qPrintable(m_lastError.text()); | 
| 1632 | #endif | 
| 1633 |             return false; | 
| 1634 |         } | 
| 1635 |  | 
| 1636 |         if (query.next()) { | 
| 1637 |             QString newDefaultID = query.value(i: EBindIndex).toString(); | 
| 1638 |             statement = QLatin1String("UPDATE Defaults SET InterfaceID = ? WHERE InterfaceName = ? COLLATE NOCASE " ); | 
| 1639 |             bindValues.clear(); | 
| 1640 |             bindValues.append(t: newDefaultID); | 
| 1641 |             bindValues.append(t: interfaceName); | 
| 1642 |             if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1643 |                 rollbackTransaction(query: &query); | 
| 1644 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1645 |                 qWarning() << "ServiceDatabase::unregisterService():-"  | 
| 1646 |                             << qPrintable(m_lastError.text()); | 
| 1647 | #endif | 
| 1648 |                 return false; | 
| 1649 |             } | 
| 1650 |         } else { | 
| 1651 |             statement = QLatin1String("DELETE FROM Defaults WHERE InterfaceName = ? COLLATE NOCASE " ); | 
| 1652 |             bindValues.clear(); | 
| 1653 |             bindValues.append(t: interfaceName); | 
| 1654 |             if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1655 |                 rollbackTransaction(query: &query); | 
| 1656 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1657 |                 qWarning() << "ServiceDatabase::unregisterService():-"  | 
| 1658 |                             << qPrintable(m_lastError.text()); | 
| 1659 | #endif | 
| 1660 |                 return false; | 
| 1661 |             } | 
| 1662 |         } | 
| 1663 |     } | 
| 1664 |  | 
| 1665 |     //databaseCommit | 
| 1666 |     if (!commitTransaction(query: &query)) { | 
| 1667 |         rollbackTransaction(query: &query); | 
| 1668 |         return false; | 
| 1669 |     } | 
| 1670 |     m_lastError.setError(error: DBError::NoError); | 
| 1671 |     return true; | 
| 1672 | } | 
| 1673 |  | 
| 1674 | /* | 
| 1675 |     Registers the service initialization into the database. | 
| 1676 | */ | 
| 1677 | bool ServiceDatabase::serviceInitialized(const QString &serviceName, const QString &securityToken) | 
| 1678 | { | 
| 1679 | #ifndef QT_SFW_SERVICEDATABASE_USE_SECURITY_TOKEN | 
| 1680 |     Q_UNUSED(securityToken); | 
| 1681 | #endif | 
| 1682 |  | 
| 1683 |     if (!checkConnection()) { | 
| 1684 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1685 |         qWarning() << "ServiceDatabase::unregisterService():-"  | 
| 1686 |                     << "Problem:"  << qPrintable(m_lastError.text()); | 
| 1687 | #endif | 
| 1688 |         return false; | 
| 1689 |     } | 
| 1690 |  | 
| 1691 |     QSqlDatabase database = QSqlDatabase::database(connectionName: m_connectionName); | 
| 1692 |     QSqlQuery query(database); | 
| 1693 |  | 
| 1694 |     if (!beginTransaction(query: &query, Write)) { | 
| 1695 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1696 |         qWarning() << "ServiceDatabase::serviceInitialized():-"  | 
| 1697 |                     << "Problem: Unable to begin transaction"  | 
| 1698 |                     << "\nReason:"  << qPrintable(m_lastError.text()); | 
| 1699 | #endif | 
| 1700 |         return false; | 
| 1701 |     } | 
| 1702 |  | 
| 1703 |     QString statement(QLatin1String("SELECT Service.ID from Service WHERE Service.Name = ? COLLATE NOCASE" )); | 
| 1704 |     QList<QVariant> bindValues; | 
| 1705 |     bindValues.append(t: serviceName); | 
| 1706 |     if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1707 |         rollbackTransaction(query: &query); | 
| 1708 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1709 |         qWarning() << "ServiceDatabase::serviceInitialized():-"  | 
| 1710 |                     << qPrintable(m_lastError.text()); | 
| 1711 | #endif | 
| 1712 |         return false; | 
| 1713 |     } | 
| 1714 |  | 
| 1715 |     QStringList serviceIDs; | 
| 1716 |     while (query.next()) { | 
| 1717 |         serviceIDs << query.value(i: EBindIndex).toString(); | 
| 1718 |     } | 
| 1719 |  | 
| 1720 |  | 
| 1721 | #ifdef QT_SFW_SERVICEDATABASE_USE_SECURITY_TOKEN | 
| 1722 |     statement = QLatin1String("SELECT Value FROM ServiceProperty WHERE ServiceID = ? AND Key = ?" ); | 
| 1723 |     bindValues.clear(); | 
| 1724 |     bindValues.append(serviceName); | 
| 1725 |     bindValues.append(SECURITY_TOKEN_KEY); | 
| 1726 |     if (!executeQuery(&query, statement, bindValues)) { | 
| 1727 |         rollbackTransaction(&query); | 
| 1728 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1729 |         qWarning() << "ServiceDatabase::unregisterService():-"  | 
| 1730 |                     << qPrintable(m_lastError.text()); | 
| 1731 | #endif | 
| 1732 |         return false; | 
| 1733 |     } | 
| 1734 |  | 
| 1735 |     QStringList securityTokens; | 
| 1736 |     while (query.next()) { | 
| 1737 |         securityTokens << query.value(EBindIndex).toString(); | 
| 1738 |     } | 
| 1739 |  | 
| 1740 |     if (!securityTokens.isEmpty() && (securityTokens.first() != securityToken)) { | 
| 1741 |         QString errorText(QLatin1String("Access denied: \"%1\"" )); | 
| 1742 |              m_lastError.setError(DBError::NoWritePermissions, errorText.arg(serviceName)); | 
| 1743 |              rollbackTransaction(&query); | 
| 1744 |      #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1745 |              qWarning() << "ServiceDatabase::serviceInitialized():-"  | 
| 1746 |                          << "Problem: Unable to update service initialization"  | 
| 1747 |                          << "\nReason:"  << qPrintable(m_lastError.text()); | 
| 1748 |      #endif | 
| 1749 |     } | 
| 1750 | #endif | 
| 1751 |  | 
| 1752 |     statement = QLatin1String("DELETE FROM ServiceProperty WHERE ServiceID = ? AND Key = ?" ); | 
| 1753 |     foreach (const QString &serviceID, serviceIDs) { | 
| 1754 |         bindValues.clear(); | 
| 1755 |         bindValues.append(t: serviceID); | 
| 1756 |         bindValues.append(t: QLatin1String(SERVICE_INITIALIZED_KEY)); | 
| 1757 |         if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1758 |             rollbackTransaction(query: &query); | 
| 1759 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1760 |             qWarning() << "ServiceDatabase::serviceInitialized():-"  | 
| 1761 |                         << qPrintable(m_lastError.text()); | 
| 1762 | #endif | 
| 1763 |             return false; | 
| 1764 |         } | 
| 1765 |     } | 
| 1766 |  | 
| 1767 |     //databaseCommit | 
| 1768 |     if (!commitTransaction(query: &query)) { | 
| 1769 |         rollbackTransaction(query: &query); | 
| 1770 |         return false; | 
| 1771 |     } | 
| 1772 |     m_lastError.setError(error: DBError::NoError); | 
| 1773 |     return true; | 
| 1774 | } | 
| 1775 |  | 
| 1776 | /* | 
| 1777 |     Closes the database | 
| 1778 |  | 
| 1779 |     May set the following error codes: | 
| 1780 |     DBError::NoError | 
| 1781 |     DBError::InvalidDatabaseConnection | 
| 1782 | */ | 
| 1783 | bool ServiceDatabase::close() | 
| 1784 | { | 
| 1785 |     if (m_isDatabaseOpen) { | 
| 1786 |         QSqlDatabase database = QSqlDatabase::database(connectionName: m_connectionName, open: false); | 
| 1787 |         if (database.isValid()) { | 
| 1788 |             if (database.isOpen()) { | 
| 1789 |                 database.close(); | 
| 1790 |                 m_isDatabaseOpen = false; | 
| 1791 |                 return true; | 
| 1792 |             } | 
| 1793 |         } else { | 
| 1794 |             m_lastError.setError(error: DBError::InvalidDatabaseConnection); | 
| 1795 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1796 |             qWarning() << "ServiceDatabase::close():-"  | 
| 1797 |                         << "Problem: "  << qPrintable(m_lastError.text()); | 
| 1798 | #endif | 
| 1799 |             return false; | 
| 1800 |         } | 
| 1801 |     } | 
| 1802 |     m_lastError.setError(error: DBError::NoError); | 
| 1803 |     return true; | 
| 1804 | } | 
| 1805 |  | 
| 1806 | /* | 
| 1807 |     Sets the path of the service database to \a databasePath | 
| 1808 | */ | 
| 1809 | void ServiceDatabase::setDatabasePath(const QString &databasePath) | 
| 1810 | { | 
| 1811 |     m_databasePath = QDir::toNativeSeparators(pathName: databasePath); | 
| 1812 | } | 
| 1813 |  | 
| 1814 | /* | 
| 1815 |     Returns the path of the service database | 
| 1816 | */ | 
| 1817 | QString ServiceDatabase::databasePath() const | 
| 1818 | { | 
| 1819 |     QString path; | 
| 1820 |     if (m_databasePath.isEmpty()) { | 
| 1821 |         QSettings settings(QSettings::SystemScope, QLatin1String("Nokia" ), QLatin1String("Services" )); | 
| 1822 |         path = settings.value(key: QLatin1String("ServicesDB/Path" )).toString(); | 
| 1823 |         if (path.isEmpty()) { | 
| 1824 |             path = QDir::currentPath(); | 
| 1825 |             if (path.lastIndexOf(s: QLatin1String(RESOLVERDATABASE_PATH_SEPARATOR)) != path.length() -1) { | 
| 1826 |                 path.append(s: QLatin1String(RESOLVERDATABASE_PATH_SEPARATOR)); | 
| 1827 |             } | 
| 1828 |             path.append(s: QLatin1String(RESOLVERDATABASE)); | 
| 1829 |         } | 
| 1830 |         path = QDir::toNativeSeparators(pathName: path); | 
| 1831 |     } else { | 
| 1832 |         path = m_databasePath; | 
| 1833 |     } | 
| 1834 |  | 
| 1835 |     return path; | 
| 1836 | } | 
| 1837 |  | 
| 1838 | /* | 
| 1839 |     Helper method that creates the database tables: Service, Interface, | 
| 1840 |     Defaults, ServiceProperty and InterfaceProperty | 
| 1841 |  | 
| 1842 |     May set the last error to one of the following error codes: | 
| 1843 |     DBError::NoError | 
| 1844 |     DBError::SqlError | 
| 1845 |     DBError::NoWritePermissions | 
| 1846 |     DBError::InvalidDatabaseFile | 
| 1847 | */ | 
| 1848 | bool ServiceDatabase::createTables() | 
| 1849 | { | 
| 1850 |     QSqlDatabase database = QSqlDatabase::database(connectionName: m_connectionName); | 
| 1851 |     QSqlQuery query(database); | 
| 1852 |  | 
| 1853 |     //Begin Transaction | 
| 1854 |     if (!beginTransaction(query: &query, Write)) { | 
| 1855 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1856 |         qWarning() << "ServiceDatabase::createTables():-"  | 
| 1857 |                     << "Unable to begin transaction. "  | 
| 1858 |                     << "Reason:"  << qPrintable(m_lastError.text()); | 
| 1859 | #endif | 
| 1860 |         return false; | 
| 1861 |     } | 
| 1862 |  | 
| 1863 |     QString statement(QLatin1String("CREATE TABLE Service("  | 
| 1864 |                         "ID TEXT NOT NULL PRIMARY KEY UNIQUE,"  | 
| 1865 |                         "Name TEXT NOT NULL, "  | 
| 1866 |                         "Location TEXT NOT NULL)" )); | 
| 1867 |     if (!executeQuery(query: &query, statement)) { | 
| 1868 |         rollbackTransaction(query: &query); | 
| 1869 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1870 |         qWarning() << "ServiceDatabase::createTables():-"  | 
| 1871 |                     << qPrintable(m_lastError.text()); | 
| 1872 | #endif | 
| 1873 |         return false; | 
| 1874 |     } | 
| 1875 |  | 
| 1876 |     statement = QLatin1String("CREATE TABLE Interface("  | 
| 1877 |                 "ID TEXT NOT NULL PRIMARY KEY UNIQUE,"  | 
| 1878 |                 "ServiceID TEXT NOT NULL, "  | 
| 1879 |                 "Name TEXT NOT NULL, "  | 
| 1880 |                 "VerMaj INTEGER NOT NULL, "  | 
| 1881 |                 "VerMin INTEGER NOT NULL)" ); | 
| 1882 |     if (!executeQuery(query: &query, statement)) { | 
| 1883 |         rollbackTransaction(query: &query); | 
| 1884 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1885 |         qWarning() << "ServiceDatabase::createTables():-"  | 
| 1886 |                     << qPrintable(m_lastError.text()); | 
| 1887 | #endif | 
| 1888 |         return false; | 
| 1889 |     } | 
| 1890 |  | 
| 1891 |     statement = QLatin1String("CREATE TABLE Defaults("  | 
| 1892 |                 "InterfaceName TEXT PRIMARY KEY UNIQUE NOT NULL,"  | 
| 1893 |                 "InterfaceID TEXT NOT NULL)" ); | 
| 1894 |     if (!executeQuery(query: &query, statement)) { | 
| 1895 |         rollbackTransaction(query: &query); | 
| 1896 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1897 |         qWarning() << "ServiceDatabase::createTables():-"  | 
| 1898 |                     << qPrintable(m_lastError.text()); | 
| 1899 | #endif | 
| 1900 |         return false; | 
| 1901 |     } | 
| 1902 |  | 
| 1903 |     statement = QLatin1String("CREATE TABLE ServiceProperty("  | 
| 1904 |                 "ServiceID TEXT NOT NULL,"  | 
| 1905 |                 "Key TEXT NOT NULL,"  | 
| 1906 |                 "Value TEXT NOT NULL)" ); | 
| 1907 |     if (!executeQuery(query: &query, statement)) { | 
| 1908 |         rollbackTransaction(query: &query); | 
| 1909 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1910 |         qWarning() << "ServiceDatabase::createTables():-"  | 
| 1911 |                     << qPrintable(m_lastError.text()); | 
| 1912 | #endif | 
| 1913 |         return false; | 
| 1914 |     } | 
| 1915 |  | 
| 1916 |     statement = QLatin1String("CREATE TABLE InterfaceProperty("  | 
| 1917 |                 "InterfaceID TEXT NOT NULL,"  | 
| 1918 |                 "Key TEXT NOT NULL,"  | 
| 1919 |                 "Value TEXT NOT NULL)" ); | 
| 1920 |  | 
| 1921 |     if (!executeQuery(query: &query, statement)) { | 
| 1922 |         rollbackTransaction(query: &query); | 
| 1923 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1924 |         qWarning() << "ServiceDatabase::createTables():-"  | 
| 1925 |                     << qPrintable(m_lastError.text()); | 
| 1926 | #endif | 
| 1927 |         return false; | 
| 1928 |     } | 
| 1929 |  | 
| 1930 |     if (!commitTransaction(query: &query)) { | 
| 1931 |         rollbackTransaction(query: &query); | 
| 1932 |         return false; | 
| 1933 |     } | 
| 1934 |     m_lastError.setError(error: DBError::NoError); | 
| 1935 |     return true; | 
| 1936 | } | 
| 1937 |  | 
| 1938 | /*! | 
| 1939 |     Helper method that checks if the all expected tables exist in the database | 
| 1940 |     Returns true if they all exist and false if any of them don't | 
| 1941 | */ | 
| 1942 | bool ServiceDatabase::checkTables() | 
| 1943 | { | 
| 1944 |     bool bTables(false); | 
| 1945 |     QStringList tables = QSqlDatabase::database(connectionName: m_connectionName).tables(); | 
| 1946 |     if (tables.contains(str: QLatin1String(SERVICE_TABLE)) | 
| 1947 |         && tables.contains(str: QLatin1String(INTERFACE_TABLE)) | 
| 1948 |         && tables.contains(str: QLatin1String(DEFAULTS_TABLE)) | 
| 1949 |         && tables.contains(str: QLatin1String(SERVICE_PROPERTY_TABLE)) | 
| 1950 |         && tables.contains(str: QLatin1String(INTERFACE_PROPERTY_TABLE))){ | 
| 1951 |             bTables = true; | 
| 1952 |     } | 
| 1953 |     return bTables; | 
| 1954 | } | 
| 1955 |  | 
| 1956 | /* | 
| 1957 |    This function should only ever be used on a user scope database | 
| 1958 |    It removes an entry from the Defaults table where the default | 
| 1959 |    refers to an interface implementation in the system scope database. | 
| 1960 |    The particular default that is removed is specified by | 
| 1961 |    \a interfaceID. | 
| 1962 |  | 
| 1963 |    May set the last error to one of the following error codes: | 
| 1964 |    DBError::NoError | 
| 1965 |    DBError::IfaceIDNotExternal | 
| 1966 |    DBError::SqlError | 
| 1967 |    DBError::NoWritePermissions | 
| 1968 |    DBError::InvalidDatabaseFile | 
| 1969 | */ | 
| 1970 | bool ServiceDatabase::removeExternalDefaultServiceInterface(const QString &interfaceID) | 
| 1971 | { | 
| 1972 |     QSqlDatabase database = QSqlDatabase::database(connectionName: m_connectionName); | 
| 1973 |     QSqlQuery query(database); | 
| 1974 |  | 
| 1975 |     //begin transaction | 
| 1976 |     if (!beginTransaction(query: &query, Write)) { | 
| 1977 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1978 |         qWarning() << "ServiceDatabase::removeExternalDefaultServiceInterface():-"  | 
| 1979 |                     << "Problem: Unable to begin transaction. "  | 
| 1980 |                     << "Reason:"  << qPrintable(m_lastError.text()); | 
| 1981 | #endif | 
| 1982 |         return false; | 
| 1983 |     } | 
| 1984 |  | 
| 1985 |     QString statement(QLatin1String("SELECT Name FROM Interface WHERE Interface.ID = ?" )); | 
| 1986 |     QList<QVariant> bindValues; | 
| 1987 |     bindValues.append(t: interfaceID); | 
| 1988 |     if (!executeQuery(query: &query, statement, bindValues)) { | 
| 1989 |         rollbackTransaction(query: &query); | 
| 1990 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 1991 |         qWarning() << "ServiceDatabase::removeDefaultServiceInterface():-"  | 
| 1992 |                     << qPrintable(m_lastError.text()); | 
| 1993 | #endif | 
| 1994 |         return false; | 
| 1995 |     } | 
| 1996 |     if (query.next()) { | 
| 1997 |         QString interfaceName = query.value(i: EBindIndex).toString(); | 
| 1998 |         QString errorText(QLatin1String("Local interface implementation exists for interface \"%1\" "  | 
| 1999 |                            "with interfaceID: \"%2\"" )); | 
| 2000 |         m_lastError.setError(error: DBError::IfaceIDNotExternal, | 
| 2001 |                 errorText: errorText.arg(a: interfaceName).arg(a: interfaceID)); | 
| 2002 |         rollbackTransaction(query: &query); | 
| 2003 |         return false; | 
| 2004 |     } | 
| 2005 |  | 
| 2006 |     statement = QLatin1String("DELETE FROM Defaults WHERE InterfaceID = ? COLLATE NOCASE" ); | 
| 2007 |     bindValues.clear(); | 
| 2008 |     bindValues.append(t: interfaceID); | 
| 2009 |     if (!executeQuery(query: &query, statement, bindValues)) { | 
| 2010 |         rollbackTransaction(query: &query); | 
| 2011 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 2012 |         qWarning() << "ServiceDatabase::removeDefaultServiceInterface():-"  | 
| 2013 |                     << qPrintable(m_lastError.text()); | 
| 2014 | #endif | 
| 2015 |         return false; | 
| 2016 |     } | 
| 2017 |  | 
| 2018 |     //end transaction | 
| 2019 |     if (!commitTransaction(query: &query)){ | 
| 2020 |         rollbackTransaction(query: &query); | 
| 2021 |         return false; | 
| 2022 |     } | 
| 2023 |     m_lastError.setError(error: DBError::NoError); | 
| 2024 |     return true; | 
| 2025 | } | 
| 2026 |  | 
| 2027 | /* | 
| 2028 |     Removes all tables from the database | 
| 2029 |  | 
| 2030 |     In future this function may be deprecated or removed. | 
| 2031 |  | 
| 2032 |     May set the last error to one of the following error codes: | 
| 2033 |     DBError::NoError | 
| 2034 |     DBError::SqlError | 
| 2035 |     DBError::NoWritePermissions | 
| 2036 |     DBError::InvalidDatabaseFile | 
| 2037 | */ | 
| 2038 | bool ServiceDatabase::dropTables() | 
| 2039 | { | 
| 2040 |     //Execute transaction for deleting the database tables | 
| 2041 |     QSqlDatabase database = QSqlDatabase::database(connectionName: m_connectionName); | 
| 2042 |     QSqlQuery query(database); | 
| 2043 |     QStringList expectedTables; | 
| 2044 |     expectedTables << QLatin1String(SERVICE_TABLE) | 
| 2045 |                 << QLatin1String(INTERFACE_TABLE) | 
| 2046 |                 << QLatin1String(DEFAULTS_TABLE) | 
| 2047 |                 << QLatin1String(SERVICE_PROPERTY_TABLE) | 
| 2048 |                 << QLatin1String(INTERFACE_PROPERTY_TABLE); | 
| 2049 |  | 
| 2050 |     if (database.tables().count() > 0) { | 
| 2051 |         if (!beginTransaction(query: &query, Write)) { | 
| 2052 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 2053 |             qWarning() << "ServiceDatabase::dropTables():-"  | 
| 2054 |                         << "Unable to begin transaction. "  | 
| 2055 |                         << "Reason:"  << qPrintable(m_lastError.text()); | 
| 2056 | #endif | 
| 2057 |             return false; | 
| 2058 |         } | 
| 2059 |         QStringList actualTables = database.tables(); | 
| 2060 |  | 
| 2061 |         foreach (const QString expectedTable, expectedTables) { | 
| 2062 |             if ((actualTables.contains(str: expectedTable)) | 
| 2063 |                 && (!executeQuery(query: &query, statement: QLatin1String("DROP TABLE " ) + expectedTable))) { | 
| 2064 |                 rollbackTransaction(query: &query); | 
| 2065 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 2066 |                 qWarning() << "ServiceDatabase::dropTables():-"  | 
| 2067 |                            << qPrintable(m_lastError.text()); | 
| 2068 | #endif | 
| 2069 |                 return false; | 
| 2070 |             } | 
| 2071 |         } | 
| 2072 |         if (!commitTransaction(query: &query)) { | 
| 2073 |             rollbackTransaction(query: &query); | 
| 2074 |             return false; | 
| 2075 |         } | 
| 2076 |     } | 
| 2077 |     m_lastError.setError(error: DBError::NoError); | 
| 2078 |     return true; | 
| 2079 | } | 
| 2080 |  | 
| 2081 | /* | 
| 2082 |     Checks if the database is open | 
| 2083 | */ | 
| 2084 | bool ServiceDatabase::isOpen() const | 
| 2085 | { | 
| 2086 |   return m_isDatabaseOpen; | 
| 2087 | } | 
| 2088 |  | 
| 2089 | /* | 
| 2090 |    Checks the database connection. | 
| 2091 |  | 
| 2092 |    May set the last error to one of the following error codes: | 
| 2093 |    DBError::DatabaseNotOpen | 
| 2094 |    DBError::InvalidDatabaseConnection | 
| 2095 | */ | 
| 2096 | bool ServiceDatabase::checkConnection() | 
| 2097 | { | 
| 2098 |     if (!m_isDatabaseOpen) | 
| 2099 |     { | 
| 2100 |         m_lastError.setError(error: DBError::DatabaseNotOpen); | 
| 2101 |         return false; | 
| 2102 |     } | 
| 2103 |  | 
| 2104 |     if (!QSqlDatabase::database(connectionName: m_connectionName).isValid()) | 
| 2105 |     { | 
| 2106 |         m_lastError.setError(error: DBError::InvalidDatabaseConnection); | 
| 2107 |         return false; | 
| 2108 |     } | 
| 2109 |  | 
| 2110 |     return true; | 
| 2111 | } | 
| 2112 |  | 
| 2113 | /* | 
| 2114 |    Begins a transcaction based on the \a type which can be Read or Write. | 
| 2115 |  | 
| 2116 |    May set the last error to one of the following error codes: | 
| 2117 |    DBError::NoError | 
| 2118 |    DBError::SqlError | 
| 2119 |    DBError::NoWritePermissions | 
| 2120 |    DBError::InvalidDatabaseFile | 
| 2121 | */ | 
| 2122 | bool ServiceDatabase::beginTransaction(QSqlQuery *query, TransactionType type) | 
| 2123 | { | 
| 2124 |     bool success; | 
| 2125 |     if (type == Read) | 
| 2126 |         success = query->exec(query: QLatin1String("BEGIN" )); | 
| 2127 |     else | 
| 2128 |         success = query->exec(query: QLatin1String("BEGIN IMMEDIATE" )); | 
| 2129 |  | 
| 2130 |     if (!success) { | 
| 2131 |         int result = query->lastError().number(); | 
| 2132 |         if (result == 26 || result == 11) {//SQLITE_NOTADB || SQLITE_CORRUPT | 
| 2133 |             qWarning() << "Service Framework:- Database file is corrupt or invalid:"  << databasePath(); | 
| 2134 |             m_lastError.setError(error: DBError::InvalidDatabaseFile, errorText: query->lastError().text()); | 
| 2135 |         } | 
| 2136 |         else if (result == 8) { //SQLITE_READONLY | 
| 2137 |             qWarning() << "Service Framework:-  Insufficient permissions to write to database:"  << databasePath(); | 
| 2138 |             m_lastError.setError(error: DBError::NoWritePermissions, errorText: query->lastError().text()); | 
| 2139 |         } | 
| 2140 |         else | 
| 2141 |             m_lastError.setError(error: DBError::SqlError, errorText: query->lastError().text()); | 
| 2142 |         return false; | 
| 2143 |     } | 
| 2144 |  | 
| 2145 |     m_lastError.setError(error: DBError::NoError); | 
| 2146 |     return true; | 
| 2147 | } | 
| 2148 |  | 
| 2149 | /* | 
| 2150 |     Commits a transaction | 
| 2151 |  | 
| 2152 |     May set the last error to one of the following error codes: | 
| 2153 |     DBError::NoError | 
| 2154 |     DBError::SqlError | 
| 2155 | */ | 
| 2156 | bool ServiceDatabase::commitTransaction(QSqlQuery *query) | 
| 2157 | { | 
| 2158 |     Q_ASSERT(query != NULL); | 
| 2159 |     query->finish(); | 
| 2160 |     query->clear(); | 
| 2161 |     if (!query->exec(query: QLatin1String("COMMIT" ))) { | 
| 2162 |         m_lastError.setError(error: DBError::SqlError, errorText: query->lastError().text()); | 
| 2163 |         return false; | 
| 2164 |     } | 
| 2165 |     m_lastError.setError(error: DBError::NoError); | 
| 2166 |     return true; | 
| 2167 | } | 
| 2168 |  | 
| 2169 | /* | 
| 2170 |     Rolls back a transaction | 
| 2171 |  | 
| 2172 |     May set the last error to one of the following error codes: | 
| 2173 |     DBError::NoError | 
| 2174 |     DBError::SqlError | 
| 2175 | */ | 
| 2176 | bool ServiceDatabase::rollbackTransaction(QSqlQuery *query) | 
| 2177 | { | 
| 2178 |     Q_ASSERT(query !=NULL); | 
| 2179 |     query->finish(); | 
| 2180 |     query->clear(); | 
| 2181 |  | 
| 2182 |     if (!query->exec(query: QLatin1String("ROLLBACK" ))) { | 
| 2183 |         m_lastError.setError(error: DBError::SqlError, errorText: query->lastError().text()); | 
| 2184 |         return false; | 
| 2185 |     } | 
| 2186 |     return true; | 
| 2187 | } | 
| 2188 |  | 
| 2189 | /* | 
| 2190 |     Helper function that populates a service \a interface descriptor | 
| 2191 |     with interface related attributes corresponding to the interface | 
| 2192 |     represented by \a interfaceID | 
| 2193 |  | 
| 2194 |     It is already assumed that a transaction has been started by the time | 
| 2195 |     this function is called.  This function will not rollback/commit the | 
| 2196 |     transaction. | 
| 2197 |  | 
| 2198 |     May set the last error to one of the following error codes: | 
| 2199 |     DBError::NoError | 
| 2200 |     DBError::SqlError | 
| 2201 | */ | 
| 2202 | bool ServiceDatabase::populateInterfaceProperties(QServiceInterfaceDescriptor *serviceInterface, const QString &interfaceID) | 
| 2203 | { | 
| 2204 |     QSqlQuery query(QSqlDatabase::database(connectionName: m_connectionName)); | 
| 2205 |     QString statement(QLatin1String("SELECT Key, Value FROM InterfaceProperty WHERE InterfaceID = ?" )); | 
| 2206 |     QList<QVariant> bindValues; | 
| 2207 |     bindValues.append(t: interfaceID); | 
| 2208 |     if (!executeQuery(query: &query, statement, bindValues)) { | 
| 2209 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 2210 |         qWarning() << "ServiceDatabase::populateInterfaceProperties():-"  | 
| 2211 |                     << qPrintable(m_lastError.text()); | 
| 2212 | #endif | 
| 2213 |         return false; | 
| 2214 |     } | 
| 2215 |  | 
| 2216 |     bool isFound = false; | 
| 2217 |     QString attribute; | 
| 2218 |     while (query.next()) { | 
| 2219 |         isFound = true; | 
| 2220 |         attribute = query.value(i: EBindIndex).toString(); | 
| 2221 |         if (attribute == QLatin1String(INTERFACE_CAPABILITY_KEY)) { | 
| 2222 |             const QStringList capabilities = query.value(i: EBindIndex1).toString().split(sep: QLatin1String("," )); | 
| 2223 |             if (capabilities.count() == 1 && capabilities[0].isEmpty()) { | 
| 2224 |                 serviceInterface->d->attributes[QServiceInterfaceDescriptor::Capabilities] | 
| 2225 |                     = QStringList(); | 
| 2226 |             } else { | 
| 2227 |                 serviceInterface->d->attributes[QServiceInterfaceDescriptor::Capabilities] | 
| 2228 |                 = capabilities; | 
| 2229 |             } | 
| 2230 |         } else if (attribute == QLatin1String(INTERFACE_DESCRIPTION_KEY)) { | 
| 2231 |             serviceInterface->d->attributes[QServiceInterfaceDescriptor::InterfaceDescription] | 
| 2232 |                = query.value(i: EBindIndex1).toString(); | 
| 2233 |         } else if (attribute.startsWith(s: QLatin1String("c_" ))) { | 
| 2234 |             serviceInterface->d->customAttributes[attribute.mid(position: 2)] | 
| 2235 |                = query.value(i: EBindIndex1).toString(); | 
| 2236 |         } | 
| 2237 |     } | 
| 2238 |  | 
| 2239 |     if (!isFound) { | 
| 2240 |         QString errorText(QLatin1String("Database integrity corrupted, Properties for InterfaceID: %1 does not exist in the InterfaceProperty table for interface \"%2\"" )); | 
| 2241 |         m_lastError.setError(error: DBError::SqlError, errorText: errorText.arg(a: interfaceID).arg(a: serviceInterface->interfaceName())); | 
| 2242 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 2243 |         qWarning() << "ServiceDatabase::populateInterfaceProperties():-"  | 
| 2244 |                     << "Problem:"  << qPrintable(m_lastError.text()); | 
| 2245 | #endif | 
| 2246 |         return false; | 
| 2247 |     } | 
| 2248 |     m_lastError.setError(error: DBError::NoError); | 
| 2249 |     return true; | 
| 2250 | } | 
| 2251 |  | 
| 2252 | /* | 
| 2253 |     Helper function that populates a service \a interface descriptor | 
| 2254 |     with service related attributes corresponding to the service | 
| 2255 |     represented by \a serviceID | 
| 2256 |  | 
| 2257 |     It is already assumed that a transaction has been started by the time | 
| 2258 |     this function is called.  This function will not rollback/commit the | 
| 2259 |     transaction. | 
| 2260 |  | 
| 2261 |     May set the last error to one of the following error codes: | 
| 2262 |     DBError::NoError | 
| 2263 |     DBError::SqlError | 
| 2264 | */ | 
| 2265 | bool ServiceDatabase::populateServiceProperties(QServiceInterfaceDescriptor *serviceInterface, const QString &serviceID) | 
| 2266 | { | 
| 2267 |     QSqlQuery query(QSqlDatabase::database(connectionName: m_connectionName)); | 
| 2268 |     QString statement(QLatin1String("SELECT Key, Value FROM ServiceProperty WHERE ServiceID = ?" )); | 
| 2269 |     QList<QVariant> bindValues; | 
| 2270 |     bindValues.append(t: serviceID); | 
| 2271 |     if (!executeQuery(query: &query, statement, bindValues)) { | 
| 2272 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 2273 |         qWarning() << "ServiceDatabase::populateServiceProperties():-"  | 
| 2274 |                     << qPrintable(m_lastError.text()); | 
| 2275 | #endif | 
| 2276 |         return false; | 
| 2277 |     } | 
| 2278 |  | 
| 2279 |     bool isFound = false; | 
| 2280 |     QString attribute; | 
| 2281 |     while (query.next()) { | 
| 2282 |         isFound = true; | 
| 2283 |         attribute = query.value(i: EBindIndex).toString(); | 
| 2284 |         if (attribute == QLatin1String(SERVICE_DESCRIPTION_KEY)) { | 
| 2285 |                 serviceInterface->d->attributes[QServiceInterfaceDescriptor::ServiceDescription] | 
| 2286 |                     = query.value(i: EBindIndex1).toString(); | 
| 2287 |         } | 
| 2288 |         // fetch initialized and put it as a custom attribute | 
| 2289 |         if (attribute == QLatin1String(SERVICE_INITIALIZED_KEY)) { | 
| 2290 |             serviceInterface->d->customAttributes[attribute] = query.value(i: EBindIndex1).toString(); | 
| 2291 |         } | 
| 2292 |     } | 
| 2293 |  | 
| 2294 |     if (!isFound) { | 
| 2295 |         QString errorText(QLatin1String("Database integrity corrupted, Service Properties for ServiceID: \"%1\" does not exist in the ServiceProperty table for service \"%2\"" )); | 
| 2296 |         m_lastError.setError(error: DBError::SqlError, errorText: errorText.arg(a: serviceID).arg(a: serviceInterface->serviceName())); | 
| 2297 | #ifdef QT_SFW_SERVICEDATABASE_DEBUG | 
| 2298 |         qWarning() << "ServiceDatabase::populateServiceProperties():-"  | 
| 2299 |                     << "Problem:"  << qPrintable(m_lastError.text()); | 
| 2300 | #endif | 
| 2301 |         return false; | 
| 2302 |     } | 
| 2303 |     m_lastError.setError(error: DBError::NoError); | 
| 2304 |     return true; | 
| 2305 | } | 
| 2306 |  | 
| 2307 | #include "moc_servicedatabase_p.cpp" | 
| 2308 |  | 
| 2309 | QT_END_NAMESPACE | 
| 2310 |  |