--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javacommons/javastorage/src/server/storagedbhandler.cpp Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,439 @@
+/*
+* Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of "Eclipse Public License v1.0"
+* which accompanies this distribution, and is available
+* at the URL "http://www.eclipse.org/legal/epl-v10.html".
+*
+* Initial Contributors:
+* Nokia Corporation - initial contribution.
+*
+* Contributors:
+*
+* Description: StorageDBHandler
+*
+*/
+
+
+#include <sstream>
+#include <sqlite3.h>
+#include <stdlib.h>
+#include <vector>
+
+#include "javacommonutils.h"
+#include "javastoragenames.h"
+#include "javastoragetables.h"
+#include "logger.h"
+#include "storagedbhandler.h"
+
+using namespace java::storage;
+using namespace java::util;
+using namespace std;
+
+StorageDBHandler::StorageDBHandler()
+{
+ JELOG2(EJavaStorage);
+ iDb = 0;
+ iResultString = L"";
+ mHavingTransaction = false;
+}
+
+StorageDBHandler::~StorageDBHandler()
+{
+ JELOG2(EJavaStorage);
+
+ // close and and remove all open sessions from DB list
+ for (iDbListIter = iDbList.begin();
+ iDbListIter != iDbList.end();
+ iDbListIter++)
+ {
+ if ((*iDbListIter).second != 0)
+ {
+ sqlite3_close((*iDbListIter).second);
+ }
+ }
+ iDbList.clear();
+}
+
+int StorageDBHandler::open(const wstring& aDbName)
+{
+ JELOG2(EJavaStorage);
+ mHavingTransaction = false;
+ char* dbnameAsChar = 0;
+
+ try
+ {
+ dbnameAsChar = JavaCommonUtils::wstringToUtf8(aDbName);
+ }
+ catch (ExceptionBase& eb)
+ {
+ ELOG1(EJavaStorage, "UTF8 conversion error: %s", eb.toString().c_str());
+ return -1;
+ }
+
+ // Create a random session id number for the connection
+ wstring sessionID = JavaCommonUtils::intToWstring(rand());
+ sessionID += JavaCommonUtils::intToWstring(rand());
+ int rc = sqlite3_open(dbnameAsChar, &iDb);
+
+ if (rc)
+ {
+ ELOG1(EJavaStorage, "Cannot open database: %s",
+ sqlite3_errmsg(iDb));
+ sqlite3_close(iDb);
+ delete[] dbnameAsChar;
+ return rc;
+ }
+ else
+ {
+ iCurrentSession.first = sessionID;
+ iCurrentSession.second = iDb;
+ iDbList.push_back(iCurrentSession);
+ }
+
+ if (!isDBInitialized(dbnameAsChar))
+ {
+ LOG(EJavaStorage, EInfo, "Initializing DB.");
+ try
+ {
+ initializeDatabase(dbnameAsChar);
+ LOG(EJavaStorage, EInfo, "DB initialized OK.");
+ }
+ catch (JavaStorageException& jse)
+ {
+ ELOG1(EJavaStorage,
+ "Init failed: %s",
+ jse.toString().c_str());
+ rc = EInternalError;
+ }
+ }
+
+ delete[] dbnameAsChar;
+ return rc;
+}
+
+int StorageDBHandler::close()
+{
+ JELOG2(EJavaStorage);
+
+ // If active transaction while closing connection. Rollback is done
+ // to maintain DB consistency.
+ if (mHavingTransaction)
+ {
+ WLOG(EJavaStorage,
+ "Close while active session. Doing rollback");
+ int err = rollback();
+ if (err < 0)
+ {
+ WLOG1(EJavaStorage, "Rollback failed: %d", err);
+ }
+ }
+
+ int rc = sqlite3_close(iDb);
+
+ // remove the session connection object from the connections list
+ for (iDbListIter = iDbList.begin();
+ iDbListIter != iDbList.end();
+ ++iDbListIter)
+ {
+ if (iCurrentSession.first == (*iDbListIter).first)
+ {
+ iDbList.erase(iDbListIter++);
+ break;
+ }
+ }
+ return rc;
+}
+
+int StorageDBHandler::startTransaction()
+{
+ JELOG2(EJavaStorage);
+ int rc = 0;
+ string statement = "BEGIN;";
+ try
+ {
+ executeStandalone(statement);
+ mHavingTransaction = true;
+ }
+ catch (JavaStorageException& jse)
+ {
+ rc = jse.mStatus;
+ mHavingTransaction = false;
+ ELOG1(EJavaStorage,
+ "Transaction start failed: %s",
+ jse.toString().c_str());
+ }
+
+ return rc;
+}
+
+int StorageDBHandler::prepare(const std::wstring& aMessage)
+{
+ JELOG2(EJavaStorage);
+ int rc;
+ const char *tail = 0;
+ int statementBytes = aMessage.length() * 4;
+ char *zErrMsg = 0;
+ char* stmAsChar = 0;
+
+ try
+ {
+ stmAsChar = JavaCommonUtils::wstringToUtf8(aMessage);
+ }
+ catch (ExceptionBase& eb)
+ {
+ ELOG1(EJavaStorage, "UTF8 conversion error: %s", eb.toString().c_str());
+ return -1;
+ }
+
+ rc = sqlite3_prepare_v2(
+ iDb, stmAsChar, statementBytes , &iStatement, &tail);
+
+
+ if (SQLITE_OK != rc)
+ {
+ ELOG1(EJavaStorage, "SQL error on prepare: %d", rc);
+ sqlite3_free(zErrMsg);
+ delete [] stmAsChar;
+ return rc;
+ }
+
+ delete [] stmAsChar;
+
+ return rc;
+}
+
+std::wstring& StorageDBHandler::executeStmt()
+{
+ JELOG2(EJavaStorage);
+ int rc;
+ iResultString.clear();
+ std::wostringstream oss;
+
+ rc = sqlite3_step(iStatement);
+
+ while (SQLITE_ROW == rc)
+ {
+ const char *columnName(0);
+ const unsigned char *column(0);
+ oss << L";#\n;";
+
+ for (int i = 0; i < sqlite3_column_count(iStatement); i++)
+ {
+ column = sqlite3_column_text(iStatement, i);
+
+ if (column)
+ {
+ wstring columnValue = JavaCommonUtils::utf8ToWstring(
+ reinterpret_cast<const char*>(column));
+
+ columnName = sqlite3_column_name(iStatement, i);
+ oss << JavaCommonUtils::utf8ToWstring(columnName);
+ oss << L"=" + columnValue + L";\n;";
+ }
+ }
+ rc = sqlite3_step(iStatement);
+ }
+
+ iResultString = oss.str();
+
+ // Return affected rowCount if no other content to be returned.
+ // This is to return e.g. how many rows removed from DB using DELETE
+ // statement.
+ if (L"" == iResultString)
+ {
+ int changes = sqlite3_changes(iDb);
+ iResultString = JavaCommonUtils::intToWstring(changes);
+ }
+
+ // Same statement is not reused.
+ int fc = sqlite3_finalize(iStatement);
+ if (0 != fc)
+ {
+ WLOG1(EJavaStorage, "Finalize failed: %d", fc);
+ }
+
+ return iResultString;
+}
+
+int StorageDBHandler::commit()
+{
+ JELOG2(EJavaStorage);
+ int rc = 0;
+ string statement = "COMMIT;";
+ try
+ {
+ executeStandalone(statement);
+ mHavingTransaction = false;
+ }
+ catch (JavaStorageException& jse)
+ {
+ rc = jse.mStatus;
+ ELOG1(EJavaStorage,
+ "Transaction commit failed: %s",
+ jse.toString().c_str());
+ }
+
+ return rc;
+}
+
+int StorageDBHandler::rollback()
+{
+ JELOG2(EJavaStorage);
+ int rc = 0;
+ string statement = "ROLLBACK;";
+ try
+ {
+ executeStandalone(statement);
+ mHavingTransaction = false;
+ }
+ catch (JavaStorageException& jse)
+ {
+ rc = jse.mStatus;
+ ELOG1(EJavaStorage,
+ "Transaction rollback failed: %s",
+ jse.toString().c_str());
+ }
+
+ return rc;
+}
+
+bool StorageDBHandler::selectConnection(const wstring& aSessionID)
+{
+ JELOG2(EJavaStorage);
+ for (iDbListIter = iDbList.begin();
+ iDbListIter != iDbList.end();
+ iDbListIter++)
+ {
+ iCurrentSession = *iDbListIter;
+ if (iCurrentSession.first == aSessionID)
+ {
+ iDb = iCurrentSession.second;
+ return true;
+ }
+ }
+ return false;
+}
+
+wstring StorageDBHandler::returnSessionID()
+{
+ return iCurrentSession.first;
+}
+
+bool StorageDBHandler::isDBInitialized(const string& aDbName)
+{
+ JELOG2(EJavaStorage);
+ bool result = false;
+
+ string sqlCommand = "SELECT ID FROM ";
+
+ if (JAVA_DATABASE_NAME == aDbName)
+ {
+ sqlCommand.append(APPLICATION_PACKAGE_TABLE);
+ }
+ else if (JAVA_OTA_DATABASE_NAME == aDbName)
+ {
+ sqlCommand.append(OTA_STATUS_TABLE);
+ }
+ else
+ {
+ // Only predefined databases are supported.
+ return result;
+ }
+
+ sqlCommand.append(";");
+
+ try
+ {
+ executeStandalone(sqlCommand);
+ result = true;
+ }
+ catch (JavaStorageException& jse)
+ {
+ WLOG1(EJavaStorage, "DB not init: %s", jse.toString().c_str());
+ }
+ return result;
+}
+
+void StorageDBHandler::initializeDatabase(const string& aDbName)
+throw(JavaStorageException)
+{
+ JELOG2(EJavaStorage);
+
+ if (JAVA_DATABASE_NAME == aDbName)
+ {
+ // Create java database tables.
+ executeStandalone(APPLICATION_PACKAGE);
+ executeStandalone(APPLICATION);
+ executeStandalone(APPLICATION_PACKAGE_ATTRIBUTES);
+ executeStandalone(MIDP_PACKAGE);
+ executeStandalone(MIDP_PERMISSIONS);
+ executeStandalone(MIDP_FUNC_GRP_SETTINGS);
+ executeStandalone(PUSH_REGISTRATIONS);
+ executeStandalone(ALARM_REGISTRATIONS);
+ executeStandalone(RUNTIME_SETTINGS);
+ executeStandalone(PREINSTALL);
+ }
+ else if (JAVA_OTA_DATABASE_NAME == aDbName)
+ {
+ // Create OTA database table.
+ executeStandalone(OTA_STATUS);
+ }
+ else
+ {
+ // Only predefined database init is supported. No error thrown as
+ // db open is still success.
+ }
+}
+
+void StorageDBHandler::executeStandalone(const string& aStatement)
+throw(JavaStorageException)
+{
+ JELOG2(EJavaStorage);
+
+ char *zErrMsg = 0;
+ int rc = -1;
+
+ rc = sqlite3_exec(iDb, aStatement.c_str(), dBCallback, 0, &zErrMsg);
+
+ if (SQLITE_OK != rc)
+ {
+ ELOG2(EJavaStorage, "Db error code: %d msg: %s", rc, zErrMsg);
+ string errString(zErrMsg);
+
+ sqlite3_free(zErrMsg);
+
+ throw JavaStorageException(rc,
+ errString.c_str(),
+ __FILE__,
+ __FUNCTION__,
+ __LINE__);
+ }
+}
+
+int StorageDBHandler::dBCallback(void */*NotUsed*/,
+ int argc,
+ char **argv,
+ char **azColName)
+{
+ JELOG2(EJavaStorage);
+ for (int i = 0; i < argc; i++)
+ {
+ ELOG2(EJavaStorage, " %s = %s",
+ azColName[i], argv[i] ? argv[i] : "NULL");
+ }
+ return 0;
+}
+
+const char* StorageDBHandler::getErrorMessage()
+{
+ JELOG2(EJavaStorage);
+ return sqlite3_errmsg(iDb);
+}
+
+int StorageDBHandler::getErrorCode()
+{
+ JELOG2(EJavaStorage);
+ return sqlite3_errcode(iDb);
+}