diff -r e8e63152f320 -r 2a9601315dfc javacommons/javastorage/src.s60/client/javadataaccessimpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javacommons/javastorage/src.s60/client/javadataaccessimpl.cpp Mon May 03 12:27:20 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 + +#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< 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 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 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< 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 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< 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 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 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; + } +}