--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javacommons/javastorage/src.s60/client/javadataaccessimpl.cpp Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,557 @@
+/*
+* 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: JavaDataAccessImpl
+*
+*/
+
+#include <memory>
+
+#include "commsmessage.h"
+#include "javacommonutils.h"
+#include "javadataaccessimpl.h"
+#include "javastorageexception.h"
+#include "javastoragemessage.h"
+#include "javastoragenames.h"
+#include "javastoragetables.h"
+#include "javasymbianoslayer.h"
+#include "javauids.h"
+#include "logger.h"
+
+using namespace java::comms;
+using namespace java::storage;
+using namespace java::util;
+using namespace std;
+
+const int OK = 0;
+_LIT8(KJavaDbTimeoutOption, "QSQLITE_BUSY_TIMEOUT==10000;");
+
+JavaDataAccessImpl::JavaDataAccessImpl()
+ : mConnOpen(false), mHavingTransaction(false)
+{
+}
+
+OS_EXPORT JavaDataAccessImpl::~JavaDataAccessImpl()
+{
+ JELOG2(EJavaStorage);
+
+ if (mHavingTransaction)
+ {
+ WLOG(EJavaStorage,
+ "Active transaction while deleting. Rollback.");
+
+ _LIT(KRollbackStatement, "ROLLBACK;");
+ TInt err = mDatabase.Exec(KRollbackStatement);
+ }
+
+ if (mConnOpen)
+ {
+ mDatabase.Close();
+ }
+}
+
+OS_EXPORT void JavaDataAccessImpl::open(
+ const string& /*aHeaders*/,
+ const string& aStorageName,
+ CommsMessage& aReceivedMessage) throw(JavaStorageException)
+{
+ JELOG2(EJavaStorage);
+
+ int status = OK;
+
+ if (!mConnOpen)
+ {
+ try
+ {
+ openDatabase(aStorageName);
+ }
+ catch (JavaStorageException& aJse)
+ {
+ status = aJse.mStatus;
+ }
+ }
+ else
+ {
+ WLOG(EJavaStorage, "Connection already open");
+ }
+
+ // SessionID is not needed in this platform context.
+ mSessionId = "N/A";
+
+ aReceivedMessage<<status;
+ aReceivedMessage<<mSessionId;
+}
+
+bool JavaDataAccessImpl::isDBInitialized(const string& aStorageName)
+{
+ JELOG2(EJavaStorage);
+ bool result = false;
+ string sqlStatement = "SELECT ";
+
+ if (JAVA_DATABASE_NAME == aStorageName)
+ {
+ sqlStatement.append("NAME FROM ");
+ sqlStatement.append(PREINSTALL_TABLE);
+ }
+ else if (JAVA_OTA_DATABASE_NAME == aStorageName)
+ {
+ sqlStatement.append("ID FROM ");
+ sqlStatement.append(OTA_STATUS_TABLE);
+ }
+ else
+ {
+ // External DB initialisation is not supported.
+ // returning true skips other checks.
+ return true;
+ }
+
+ sqlStatement.append(";");
+
+ auto_ptr<HBufC> sqlDes(stringToDes(sqlStatement.c_str()));
+
+ TInt err = mDatabase.Exec(sqlDes->Des());
+
+ if (err >= 0)
+ {
+ result = true;
+ }
+ else
+ {
+ WLOG1(EJavaStorage, "Database is not initialized: %d", err);
+ }
+
+ return result;
+}
+
+void JavaDataAccessImpl::initializeDatabase(const string& aStorageName)
+throw(JavaStorageException)
+{
+ JELOG2(EJavaStorage);
+
+ if (JAVA_DATABASE_NAME == aStorageName
+ && !isDBInitialized(aStorageName))
+ {
+ auto_ptr<HBufC> sqlDes(stringToDes(APPLICATION_PACKAGE));
+ LOG(EJavaStorage, EInfo, "Creating APPLICATION PACKAGE");
+ createTable(sqlDes->Des());
+
+ sqlDes.reset(stringToDes(APPLICATION));
+ LOG(EJavaStorage, EInfo, "Creating APPLICATION");
+ createTable(sqlDes->Des());
+
+ sqlDes.reset(stringToDes(APPLICATION_PACKAGE_ATTRIBUTES));
+ LOG(EJavaStorage, EInfo, "Creating APPLICATION_PACKAGE_ATTRIBUTES");
+ createTable(sqlDes->Des());
+
+ sqlDes.reset(stringToDes(MIDP_PACKAGE));
+ LOG(EJavaStorage, EInfo, "Creating MIDP_PACKAGE");
+ createTable(sqlDes->Des());
+
+ sqlDes.reset(stringToDes(MIDP_PERMISSIONS));
+ LOG(EJavaStorage, EInfo, "Creating MIDP_PERMISSIONS");
+ createTable(sqlDes->Des());
+
+ sqlDes.reset(stringToDes(MIDP_FUNC_GRP_SETTINGS));
+ LOG(EJavaStorage, EInfo, "Creating MIDP_FUNC_GRP_SETTINGS");
+ createTable(sqlDes->Des());
+
+ sqlDes.reset(stringToDes(PUSH_REGISTRATIONS));
+ LOG(EJavaStorage, EInfo, "Creating PUSH_REGISTRATIONS");
+ createTable(sqlDes->Des());
+
+ sqlDes.reset(stringToDes(ALARM_REGISTRATIONS));
+ LOG(EJavaStorage, EInfo, "Creating ALARM_REGISTRATIONS");
+ createTable(sqlDes->Des());
+
+ sqlDes.reset(stringToDes(RUNTIME_SETTINGS));
+ LOG(EJavaStorage, EInfo, "Creating RUNTIME_SETTINGS");
+ createTable(sqlDes->Des());
+
+ sqlDes.reset(stringToDes(PREINSTALL));
+ LOG(EJavaStorage, EInfo, "Creating PREINSTALL");
+ createTable(sqlDes->Des());
+ }
+ else if (JAVA_OTA_DATABASE_NAME == aStorageName
+ && !isDBInitialized(aStorageName))
+ {
+ auto_ptr<HBufC> sqlDes(stringToDes(OTA_STATUS));
+ LOG(EJavaStorage, EInfo, "Creating OTA_STATUS");
+ createTable(sqlDes->Des());
+ }
+}
+
+OS_EXPORT void JavaDataAccessImpl::close(const string& /*aHeaders*/,
+ CommsMessage& aReceivedMessage)
+throw(JavaStorageException)
+{
+ JELOG2(EJavaStorage);
+ int status = OK;
+
+ // If active transaction while closing connection. Rollback is tried.
+ if (mHavingTransaction)
+ {
+ WLOG(EJavaStorage,
+ "Active transaction while closing connection. Rollback.");
+
+ _LIT(KRollbackStatement, "ROLLBACK;");
+ TInt err = mDatabase.Exec(KRollbackStatement);
+ }
+
+ mDatabase.Close();
+ mConnOpen = false;
+ mHavingTransaction = false;
+
+ aReceivedMessage<<status;
+ aReceivedMessage<<mSessionId;
+}
+
+OS_EXPORT void JavaDataAccessImpl::execute(const string& aHeaders,
+ const wstring& aSqlStatement,
+ CommsMessage& aReceivedMessage)
+throw(JavaStorageException)
+{
+ JELOG2(EJavaStorage);
+
+ int status = OK;
+ wstring resultData;
+
+ // First char contains msgId len
+ int msgIdLen = JavaCommonUtils::stringToInt(aHeaders.substr(0, 1));
+ // Next chars contain msgId
+ int msgId = JavaCommonUtils::stringToInt(aHeaders.substr(1, msgIdLen));
+
+ auto_ptr<HBufC> sqlStatement(HBufC16::New(aSqlStatement.size() + 1));
+
+ if (!sqlStatement.get())
+ {
+ throw JavaStorageException(KErrNoMemory,
+ "Cannot allocate statement Buffer",
+ __FILE__, __FUNCTION__, __LINE__);
+ }
+
+ TPtr16 statementPtr(sqlStatement->Des());
+ statementPtr = (const TUint16*)aSqlStatement.c_str();
+
+ // ###################### TEMP ############################################
+ // LOG1WSTR(EJavaStorage, EInfo, "Sql statement: %s", aSqlStatement);
+ // ####################### END OF TEMP ####################################
+
+ switch (msgId)
+ {
+ case JavaStorageMessage::EStartTransaction:
+ {
+ TInt err = mDatabase.Exec(sqlStatement->Des());
+ status = err;
+ resultData = L"OK";
+
+ if (status < 0)
+ {
+ mHavingTransaction = false;
+ }
+ else
+ {
+ mHavingTransaction = true;
+ }
+ break;
+ }
+ case JavaStorageMessage::ECommit:
+ case JavaStorageMessage::ERollback:
+ {
+ TInt err = mDatabase.Exec(sqlStatement->Des());
+ status = err;
+ resultData = L"OK";
+
+ if (status >= 0)
+ {
+ mHavingTransaction = false;
+ }
+ break;
+ }
+ case JavaStorageMessage::EWrite:
+ case JavaStorageMessage::ECreateTable:
+ case JavaStorageMessage::EUpdate:
+ case JavaStorageMessage::EAppendTable:
+ {
+ TInt err = mDatabase.Exec(sqlStatement->Des());
+ status = err;
+ resultData = L"OK";
+ break;
+ }
+ case JavaStorageMessage::ERemove:
+ {
+ TInt err = mDatabase.Exec(sqlStatement->Des());
+ status = err;
+
+ if (0 <= status)
+ {
+ // Add affected row amount
+ resultData = JavaCommonUtils::intToWstring(status);
+ }
+ break;
+ }
+ case JavaStorageMessage::ERead:
+ case JavaStorageMessage::ESearch:
+ {
+ RSqlStatement statement;
+ TInt err = statement.Prepare(mDatabase, sqlStatement->Des());
+
+ if (err < 0)
+ {
+ ELOG1(EJavaStorage, "Prepare error: %d", err);
+ status = err;
+ statement.Close();
+ break;
+ }
+
+ while ((err = statement.Next()) == KSqlAtRow)
+ {
+ resultData.append(L";#\n;");
+
+ for (int i = 0; i < statement.ColumnCount(); i++)
+ {
+ TSqlColumnType colType = statement.ColumnType(i);
+
+ if (colType != ESqlNull)
+ {
+ wstring colValue = L"";
+ columnValue(i, statement, colType, colValue);
+
+ wstring colName = L"";
+ columnName(i, statement, colName);
+ resultData.append(colName).append(L"=")
+ .append(colValue).append(L";\n;");
+ }
+ }
+ }
+
+ if (err != KSqlAtEnd)
+ {
+ ELOG1(EJavaStorage,
+ "Error during statement execution: %d", err);
+ }
+
+ status = err;
+
+ if (resultData.size() == 0)
+ {
+ resultData = L"OK"; // Indicate no match found.
+ }
+
+ statement.Close();
+ break;
+ }
+ default:
+ {
+ LOG1(EJavaStorage, EInfo, "Unknown command: %d", msgId);
+ break;
+ }
+ }
+
+ if (status < 0)
+ {
+ ELOG1WSTR(EJavaStorage, "ErrorStmt: %s", aSqlStatement);
+ TPtrC errMsg = mDatabase.LastErrorMessage();
+ auto_ptr<HBufC16> tempBuf(HBufC16::New(errMsg.Size() + 1));
+
+ if (!tempBuf.get())
+ {
+ throw JavaStorageException(
+ KErrNoMemory, "Cannot allocate errorMsg buffer",
+ __FILE__, __FUNCTION__, __LINE__);
+ }
+
+ TPtr16 tempBufPtr(tempBuf->Des());
+ tempBufPtr.Append(errMsg);
+ wstring tempStr(desToWstring(tempBufPtr));
+ resultData = tempStr;
+
+ if (resultData.size() == 0)
+ {
+ resultData = L"No error description available";
+ }
+ ELOG1WSTR(EJavaStorage, "EMsg: %s", resultData);
+ }
+
+ aReceivedMessage<<status;
+ aReceivedMessage<<resultData;
+}
+
+void JavaDataAccessImpl::openDatabase(const string& aStorageName)
+throw(JavaStorageException)
+{
+ JELOG2(EJavaStorage);
+
+ auto_ptr<HBufC> dbName(0);
+ bool isDefaultDB = false;
+
+ if (JAVA_DATABASE_NAME == aStorageName
+ || JAVA_OTA_DATABASE_NAME == aStorageName)
+ {
+ TUid tempUid = TUid::Uid(KJavaCaptainUid);
+ java::util::Uid uid;
+ TUidToUid(tempUid, uid);
+ const char* tempStr = JavaCommonUtils::wstringToUtf8(uid.toString());
+ string uidStr(tempStr);
+ delete [] tempStr;
+ string tempName = "c:" + uidStr + aStorageName + ".db";
+
+ dbName.reset(stringToDes(tempName.c_str()));
+ isDefaultDB = true;
+ }
+ else
+ {
+ dbName.reset(stringToDes(aStorageName.c_str()));
+ }
+
+ if (KErrNone != mDatabase.Open(dbName->Des(), &KJavaDbTimeoutOption))
+ {
+ createDatabase(dbName->Des(), isDefaultDB);
+ initializeDatabase(aStorageName);
+ }
+
+ LOG1(EJavaStorage, EInfo, "Database '%s' opened", aStorageName.c_str());
+ mConnOpen = true;
+}
+
+void JavaDataAccessImpl::createDatabase(const TDesC& aDbName, bool aIsDefault)
+throw(JavaStorageException)
+{
+ JELOG2(EJavaStorage);
+ mDatabase.Close();
+
+ TInt err = KErrNone;
+
+ if (aIsDefault)
+ {
+ TSecurityPolicy defaultPolicy;
+ RSqlSecurityPolicy securityPolicy;
+
+ securityPolicy.Create(defaultPolicy);
+
+ // Create similar security policy to all Java platform system databases.
+
+#ifdef RD_JAVA_S60_RELEASE_9_2_ONWARDS
+ TSecurityPolicy schemaPolicy(ECapabilityTrustedUI);
+ TSecurityPolicy writePolicy(ECapabilityTrustedUI);
+#else // RD_JAVA_S60_RELEASE_9_2_ONWARDS
+ // Beta release must be run with lower capability set as
+ // SBE engine capability set cannot anymore be modified.
+ TSecurityPolicy schemaPolicy(ECapabilityWriteDeviceData);
+ TSecurityPolicy writePolicy(ECapabilityWriteDeviceData);
+#endif // RD_JAVA_S60_RELEASE_9_2_ONWARDS
+
+ TSecurityPolicy readPolicy(TSecurityPolicy::EAlwaysPass);
+
+ securityPolicy.SetDbPolicy(RSqlSecurityPolicy::ESchemaPolicy,
+ schemaPolicy);
+ securityPolicy.SetDbPolicy(RSqlSecurityPolicy::EWritePolicy,
+ writePolicy);
+ securityPolicy.SetDbPolicy(RSqlSecurityPolicy::EReadPolicy, readPolicy);
+ err = mDatabase.Create(aDbName, securityPolicy);
+ securityPolicy.Close();
+ }
+ else
+ {
+ err = mDatabase.Create(aDbName);
+ }
+
+ if (KErrNone != err)
+ {
+ ELOG1(EJavaStorage, "Cannot create database: %d", err);
+
+ // LastErrorMessage cannot be called as create or open
+ // didn't succeeded.
+ mSessionId = "Database creation error";
+ mConnOpen = false;
+
+ throw JavaStorageException(err, mSessionId.c_str(),
+ __FILE__, __FUNCTION__, __LINE__);
+ }
+ mConnOpen = true;
+}
+
+void JavaDataAccessImpl::createTable(const TDesC& aStatement)
+throw(JavaStorageException)
+{
+ TInt err = mDatabase.Exec(aStatement);
+
+ if (err < 0)
+ {
+ ELOG1(EJavaStorage, "Table create failed: %d", err);
+ throw JavaStorageException(
+ EInvalidDataStructure,
+ "Table creation failed",
+ __FILE__,
+ __FUNCTION__,
+ __LINE__);
+ }
+}
+
+void JavaDataAccessImpl::columnName(int aIndex,
+ RSqlStatement& aStmt,
+ wstring& aColName)
+{
+ TPtrC16 columnNamePtr;
+ TInt err = aStmt.ColumnName(aIndex, columnNamePtr);
+
+ if (KErrNone != err)
+ {
+ WLOG1(EJavaStorage, "Get ColumnName: %d", err);
+ }
+
+ // Deep copy needed.
+ auto_ptr<HBufC16> colName(HBufC16::New(columnNamePtr.Length() + 1));
+
+ if (!colName.get())
+ {
+ throw JavaStorageException(KErrNoMemory,
+ "Cannot allocate column name buffer",
+ __FILE__, __FUNCTION__, __LINE__);
+ }
+
+ TPtr16 colName2Ptr(colName->Des());
+ colName2Ptr.Append(columnNamePtr);
+ wstring temp(desToWstring(colName2Ptr));
+ aColName = temp;
+}
+
+void JavaDataAccessImpl::columnValue(const int aIndex,
+ RSqlStatement& aStmt,
+ const TSqlColumnType aColumnType,
+ wstring& aColValue)
+{
+ // Only INT and STRING currently supported
+ if (ESqlInt == aColumnType)
+ {
+ TInt value = aStmt.ColumnInt(aIndex);
+ aColValue = JavaCommonUtils::intToWstring(value);
+ }
+ else
+ {
+ // Deep copy needed.
+ auto_ptr<HBufC16> column(HBufC16::New(aStmt.ColumnSize(aIndex) + 1));
+
+ if (!column.get())
+ {
+ throw JavaStorageException(KErrNoMemory,
+ "Cannot allocate column value buffer",
+ __FILE__, __FUNCTION__, __LINE__);
+ }
+
+ TPtr16 columnPtr(column->Des());
+ TInt colErr = aStmt.ColumnText(aIndex, columnPtr);
+
+ wstring temp(desToWstring(columnPtr));
+ aColValue = temp;
+ }
+}