javacommons/javastorage/src.s60/client/javadataaccessimpl.cpp
changeset 21 2a9601315dfc
child 78 71ad690e91f5
equal deleted inserted replaced
18:e8e63152f320 21:2a9601315dfc
       
     1 /*
       
     2 * Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  JavaDataAccessImpl
       
    15 *
       
    16 */
       
    17 
       
    18 #include <memory>
       
    19 
       
    20 #include "commsmessage.h"
       
    21 #include "javacommonutils.h"
       
    22 #include "javadataaccessimpl.h"
       
    23 #include "javastorageexception.h"
       
    24 #include "javastoragemessage.h"
       
    25 #include "javastoragenames.h"
       
    26 #include "javastoragetables.h"
       
    27 #include "javasymbianoslayer.h"
       
    28 #include "javauids.h"
       
    29 #include "logger.h"
       
    30 
       
    31 using namespace java::comms;
       
    32 using namespace java::storage;
       
    33 using namespace java::util;
       
    34 using namespace std;
       
    35 
       
    36 const int OK = 0;
       
    37 _LIT8(KJavaDbTimeoutOption, "QSQLITE_BUSY_TIMEOUT==10000;");
       
    38 
       
    39 JavaDataAccessImpl::JavaDataAccessImpl()
       
    40         : mConnOpen(false), mHavingTransaction(false)
       
    41 {
       
    42 }
       
    43 
       
    44 OS_EXPORT JavaDataAccessImpl::~JavaDataAccessImpl()
       
    45 {
       
    46     JELOG2(EJavaStorage);
       
    47 
       
    48     if (mHavingTransaction)
       
    49     {
       
    50         WLOG(EJavaStorage,
       
    51              "Active transaction while deleting. Rollback.");
       
    52 
       
    53         _LIT(KRollbackStatement, "ROLLBACK;");
       
    54         TInt err = mDatabase.Exec(KRollbackStatement);
       
    55     }
       
    56 
       
    57     if (mConnOpen)
       
    58     {
       
    59         mDatabase.Close();
       
    60     }
       
    61 }
       
    62 
       
    63 OS_EXPORT void JavaDataAccessImpl::open(
       
    64     const string& /*aHeaders*/,
       
    65     const string& aStorageName,
       
    66     CommsMessage& aReceivedMessage) throw(JavaStorageException)
       
    67 {
       
    68     JELOG2(EJavaStorage);
       
    69 
       
    70     int status = OK;
       
    71 
       
    72     if (!mConnOpen)
       
    73     {
       
    74         try
       
    75         {
       
    76             openDatabase(aStorageName);
       
    77         }
       
    78         catch (JavaStorageException& aJse)
       
    79         {
       
    80             status = aJse.mStatus;
       
    81         }
       
    82     }
       
    83     else
       
    84     {
       
    85         WLOG(EJavaStorage, "Connection already open");
       
    86     }
       
    87 
       
    88     // SessionID is not needed in this platform context.
       
    89     mSessionId = "N/A";
       
    90 
       
    91     aReceivedMessage<<status;
       
    92     aReceivedMessage<<mSessionId;
       
    93 }
       
    94 
       
    95 bool JavaDataAccessImpl::isDBInitialized(const string& aStorageName)
       
    96 {
       
    97     JELOG2(EJavaStorage);
       
    98     bool result = false;
       
    99     string sqlStatement = "SELECT ";
       
   100 
       
   101     if (JAVA_DATABASE_NAME == aStorageName)
       
   102     {
       
   103         sqlStatement.append("NAME FROM ");
       
   104         sqlStatement.append(PREINSTALL_TABLE);
       
   105     }
       
   106     else if (JAVA_OTA_DATABASE_NAME == aStorageName)
       
   107     {
       
   108         sqlStatement.append("ID FROM ");
       
   109         sqlStatement.append(OTA_STATUS_TABLE);
       
   110     }
       
   111     else
       
   112     {
       
   113         // External DB initialisation is not supported.
       
   114         // returning true skips other checks.
       
   115         return true;
       
   116     }
       
   117 
       
   118     sqlStatement.append(";");
       
   119 
       
   120     auto_ptr<HBufC> sqlDes(stringToDes(sqlStatement.c_str()));
       
   121 
       
   122     TInt err = mDatabase.Exec(sqlDes->Des());
       
   123 
       
   124     if (err >= 0)
       
   125     {
       
   126         result = true;
       
   127     }
       
   128     else
       
   129     {
       
   130         WLOG1(EJavaStorage, "Database is not initialized: %d", err);
       
   131     }
       
   132 
       
   133     return result;
       
   134 }
       
   135 
       
   136 void JavaDataAccessImpl::initializeDatabase(const string& aStorageName)
       
   137 throw(JavaStorageException)
       
   138 {
       
   139     JELOG2(EJavaStorage);
       
   140 
       
   141     if (JAVA_DATABASE_NAME == aStorageName
       
   142             && !isDBInitialized(aStorageName))
       
   143     {
       
   144         auto_ptr<HBufC> sqlDes(stringToDes(APPLICATION_PACKAGE));
       
   145         LOG(EJavaStorage, EInfo, "Creating APPLICATION PACKAGE");
       
   146         createTable(sqlDes->Des());
       
   147 
       
   148         sqlDes.reset(stringToDes(APPLICATION));
       
   149         LOG(EJavaStorage, EInfo, "Creating APPLICATION");
       
   150         createTable(sqlDes->Des());
       
   151 
       
   152         sqlDes.reset(stringToDes(APPLICATION_PACKAGE_ATTRIBUTES));
       
   153         LOG(EJavaStorage, EInfo, "Creating APPLICATION_PACKAGE_ATTRIBUTES");
       
   154         createTable(sqlDes->Des());
       
   155 
       
   156         sqlDes.reset(stringToDes(MIDP_PACKAGE));
       
   157         LOG(EJavaStorage, EInfo, "Creating MIDP_PACKAGE");
       
   158         createTable(sqlDes->Des());
       
   159 
       
   160         sqlDes.reset(stringToDes(MIDP_PERMISSIONS));
       
   161         LOG(EJavaStorage, EInfo, "Creating MIDP_PERMISSIONS");
       
   162         createTable(sqlDes->Des());
       
   163 
       
   164         sqlDes.reset(stringToDes(MIDP_FUNC_GRP_SETTINGS));
       
   165         LOG(EJavaStorage, EInfo, "Creating MIDP_FUNC_GRP_SETTINGS");
       
   166         createTable(sqlDes->Des());
       
   167 
       
   168         sqlDes.reset(stringToDes(PUSH_REGISTRATIONS));
       
   169         LOG(EJavaStorage, EInfo, "Creating PUSH_REGISTRATIONS");
       
   170         createTable(sqlDes->Des());
       
   171 
       
   172         sqlDes.reset(stringToDes(ALARM_REGISTRATIONS));
       
   173         LOG(EJavaStorage, EInfo, "Creating ALARM_REGISTRATIONS");
       
   174         createTable(sqlDes->Des());
       
   175 
       
   176         sqlDes.reset(stringToDes(RUNTIME_SETTINGS));
       
   177         LOG(EJavaStorage, EInfo, "Creating RUNTIME_SETTINGS");
       
   178         createTable(sqlDes->Des());
       
   179 
       
   180         sqlDes.reset(stringToDes(PREINSTALL));
       
   181         LOG(EJavaStorage, EInfo, "Creating PREINSTALL");
       
   182         createTable(sqlDes->Des());
       
   183     }
       
   184     else if (JAVA_OTA_DATABASE_NAME == aStorageName
       
   185              && !isDBInitialized(aStorageName))
       
   186     {
       
   187         auto_ptr<HBufC> sqlDes(stringToDes(OTA_STATUS));
       
   188         LOG(EJavaStorage, EInfo, "Creating OTA_STATUS");
       
   189         createTable(sqlDes->Des());
       
   190     }
       
   191 }
       
   192 
       
   193 OS_EXPORT void JavaDataAccessImpl::close(const string& /*aHeaders*/,
       
   194         CommsMessage& aReceivedMessage)
       
   195 throw(JavaStorageException)
       
   196 {
       
   197     JELOG2(EJavaStorage);
       
   198     int status = OK;
       
   199 
       
   200     // If active transaction while closing connection. Rollback is tried.
       
   201     if (mHavingTransaction)
       
   202     {
       
   203         WLOG(EJavaStorage,
       
   204              "Active transaction while closing connection. Rollback.");
       
   205 
       
   206         _LIT(KRollbackStatement, "ROLLBACK;");
       
   207         TInt err = mDatabase.Exec(KRollbackStatement);
       
   208     }
       
   209 
       
   210     mDatabase.Close();
       
   211     mConnOpen = false;
       
   212     mHavingTransaction = false;
       
   213 
       
   214     aReceivedMessage<<status;
       
   215     aReceivedMessage<<mSessionId;
       
   216 }
       
   217 
       
   218 OS_EXPORT void JavaDataAccessImpl::execute(const string& aHeaders,
       
   219         const wstring& aSqlStatement,
       
   220         CommsMessage& aReceivedMessage)
       
   221 throw(JavaStorageException)
       
   222 {
       
   223     JELOG2(EJavaStorage);
       
   224 
       
   225     int status = OK;
       
   226     wstring resultData;
       
   227 
       
   228     // First char contains msgId len
       
   229     int msgIdLen = JavaCommonUtils::stringToInt(aHeaders.substr(0, 1));
       
   230     // Next chars contain msgId
       
   231     int msgId = JavaCommonUtils::stringToInt(aHeaders.substr(1, msgIdLen));
       
   232 
       
   233     auto_ptr<HBufC> sqlStatement(HBufC16::New(aSqlStatement.size() + 1));
       
   234 
       
   235     if (!sqlStatement.get())
       
   236     {
       
   237         throw JavaStorageException(KErrNoMemory,
       
   238                                    "Cannot allocate statement Buffer",
       
   239                                    __FILE__, __FUNCTION__, __LINE__);
       
   240     }
       
   241 
       
   242     TPtr16 statementPtr(sqlStatement->Des());
       
   243     statementPtr = (const TUint16*)aSqlStatement.c_str();
       
   244 
       
   245     // ###################### TEMP ############################################
       
   246     // LOG1WSTR(EJavaStorage, EInfo, "Sql statement: %s", aSqlStatement);
       
   247     // ####################### END OF TEMP ####################################
       
   248 
       
   249     switch (msgId)
       
   250     {
       
   251     case JavaStorageMessage::EStartTransaction:
       
   252     {
       
   253         TInt err = mDatabase.Exec(sqlStatement->Des());
       
   254         status = err;
       
   255         resultData = L"OK";
       
   256 
       
   257         if (status < 0)
       
   258         {
       
   259             mHavingTransaction = false;
       
   260         }
       
   261         else
       
   262         {
       
   263             mHavingTransaction = true;
       
   264         }
       
   265         break;
       
   266     }
       
   267     case JavaStorageMessage::ECommit:
       
   268     case JavaStorageMessage::ERollback:
       
   269     {
       
   270         TInt err = mDatabase.Exec(sqlStatement->Des());
       
   271         status = err;
       
   272         resultData = L"OK";
       
   273 
       
   274         if (status >= 0)
       
   275         {
       
   276             mHavingTransaction = false;
       
   277         }
       
   278         break;
       
   279     }
       
   280     case JavaStorageMessage::EWrite:
       
   281     case JavaStorageMessage::ECreateTable:
       
   282     case JavaStorageMessage::EUpdate:
       
   283     case JavaStorageMessage::EAppendTable:
       
   284     {
       
   285         TInt err = mDatabase.Exec(sqlStatement->Des());
       
   286         status = err;
       
   287         resultData = L"OK";
       
   288         break;
       
   289     }
       
   290     case JavaStorageMessage::ERemove:
       
   291     {
       
   292         TInt err = mDatabase.Exec(sqlStatement->Des());
       
   293         status = err;
       
   294 
       
   295         if (0 <= status)
       
   296         {
       
   297             // Add affected row amount
       
   298             resultData = JavaCommonUtils::intToWstring(status);
       
   299         }
       
   300         break;
       
   301     }
       
   302     case JavaStorageMessage::ERead:
       
   303     case JavaStorageMessage::ESearch:
       
   304     {
       
   305         RSqlStatement statement;
       
   306         TInt err = statement.Prepare(mDatabase, sqlStatement->Des());
       
   307 
       
   308         if (err < 0)
       
   309         {
       
   310             ELOG1(EJavaStorage, "Prepare error: %d", err);
       
   311             status = err;
       
   312             statement.Close();
       
   313             break;
       
   314         }
       
   315 
       
   316         while ((err = statement.Next()) == KSqlAtRow)
       
   317         {
       
   318             resultData.append(L";#\n;");
       
   319 
       
   320             for (int i = 0; i < statement.ColumnCount(); i++)
       
   321             {
       
   322                 TSqlColumnType colType = statement.ColumnType(i);
       
   323 
       
   324                 if (colType != ESqlNull)
       
   325                 {
       
   326                     wstring colValue = L"";
       
   327                     columnValue(i, statement, colType, colValue);
       
   328 
       
   329                     wstring colName = L"";
       
   330                     columnName(i, statement, colName);
       
   331                     resultData.append(colName).append(L"=")
       
   332                     .append(colValue).append(L";\n;");
       
   333                 }
       
   334             }
       
   335         }
       
   336 
       
   337         if (err != KSqlAtEnd)
       
   338         {
       
   339             ELOG1(EJavaStorage,
       
   340                   "Error during statement execution: %d", err);
       
   341         }
       
   342 
       
   343         status = err;
       
   344 
       
   345         if (resultData.size() == 0)
       
   346         {
       
   347             resultData = L"OK"; // Indicate no match found.
       
   348         }
       
   349 
       
   350         statement.Close();
       
   351         break;
       
   352     }
       
   353     default:
       
   354     {
       
   355         LOG1(EJavaStorage, EInfo, "Unknown command: %d", msgId);
       
   356         break;
       
   357     }
       
   358     }
       
   359 
       
   360     if (status < 0)
       
   361     {
       
   362         ELOG1WSTR(EJavaStorage, "ErrorStmt: %s", aSqlStatement);
       
   363         TPtrC errMsg = mDatabase.LastErrorMessage();
       
   364         auto_ptr<HBufC16> tempBuf(HBufC16::New(errMsg.Size() + 1));
       
   365 
       
   366         if (!tempBuf.get())
       
   367         {
       
   368             throw JavaStorageException(
       
   369                 KErrNoMemory, "Cannot allocate errorMsg buffer",
       
   370                 __FILE__, __FUNCTION__, __LINE__);
       
   371         }
       
   372 
       
   373         TPtr16 tempBufPtr(tempBuf->Des());
       
   374         tempBufPtr.Append(errMsg);
       
   375         wstring tempStr(desToWstring(tempBufPtr));
       
   376         resultData = tempStr;
       
   377 
       
   378         if (resultData.size() == 0)
       
   379         {
       
   380             resultData = L"No error description available";
       
   381         }
       
   382         ELOG1WSTR(EJavaStorage, "EMsg: %s", resultData);
       
   383     }
       
   384 
       
   385     aReceivedMessage<<status;
       
   386     aReceivedMessage<<resultData;
       
   387 }
       
   388 
       
   389 void JavaDataAccessImpl::openDatabase(const string& aStorageName)
       
   390 throw(JavaStorageException)
       
   391 {
       
   392     JELOG2(EJavaStorage);
       
   393 
       
   394     auto_ptr<HBufC> dbName(0);
       
   395     bool isDefaultDB = false;
       
   396 
       
   397     if (JAVA_DATABASE_NAME == aStorageName
       
   398             || JAVA_OTA_DATABASE_NAME == aStorageName)
       
   399     {
       
   400         TUid tempUid = TUid::Uid(KJavaCaptainUid);
       
   401         java::util::Uid uid;
       
   402         TUidToUid(tempUid, uid);
       
   403         const char* tempStr = JavaCommonUtils::wstringToUtf8(uid.toString());
       
   404         string uidStr(tempStr);
       
   405         delete [] tempStr;
       
   406         string tempName = "c:" + uidStr + aStorageName + ".db";
       
   407 
       
   408         dbName.reset(stringToDes(tempName.c_str()));
       
   409         isDefaultDB = true;
       
   410     }
       
   411     else
       
   412     {
       
   413         dbName.reset(stringToDes(aStorageName.c_str()));
       
   414     }
       
   415 
       
   416     if (KErrNone != mDatabase.Open(dbName->Des(), &KJavaDbTimeoutOption))
       
   417     {
       
   418         createDatabase(dbName->Des(), isDefaultDB);
       
   419         initializeDatabase(aStorageName);
       
   420     }
       
   421 
       
   422     LOG1(EJavaStorage, EInfo, "Database '%s' opened", aStorageName.c_str());
       
   423     mConnOpen = true;
       
   424 }
       
   425 
       
   426 void JavaDataAccessImpl::createDatabase(const TDesC& aDbName, bool aIsDefault)
       
   427 throw(JavaStorageException)
       
   428 {
       
   429     JELOG2(EJavaStorage);
       
   430     mDatabase.Close();
       
   431 
       
   432     TInt err = KErrNone;
       
   433 
       
   434     if (aIsDefault)
       
   435     {
       
   436         TSecurityPolicy defaultPolicy;
       
   437         RSqlSecurityPolicy securityPolicy;
       
   438 
       
   439         securityPolicy.Create(defaultPolicy);
       
   440 
       
   441         // Create similar security policy to all Java platform system databases.
       
   442 
       
   443 #ifdef RD_JAVA_S60_RELEASE_9_2_ONWARDS
       
   444         TSecurityPolicy schemaPolicy(ECapabilityTrustedUI);
       
   445         TSecurityPolicy writePolicy(ECapabilityTrustedUI);
       
   446 #else  // RD_JAVA_S60_RELEASE_9_2_ONWARDS
       
   447         // Beta release must be run with lower capability set as
       
   448         // SBE engine capability set cannot anymore be modified.
       
   449         TSecurityPolicy schemaPolicy(ECapabilityWriteDeviceData);
       
   450         TSecurityPolicy writePolicy(ECapabilityWriteDeviceData);
       
   451 #endif  // RD_JAVA_S60_RELEASE_9_2_ONWARDS
       
   452 
       
   453         TSecurityPolicy readPolicy(TSecurityPolicy::EAlwaysPass);
       
   454 
       
   455         securityPolicy.SetDbPolicy(RSqlSecurityPolicy::ESchemaPolicy,
       
   456                                    schemaPolicy);
       
   457         securityPolicy.SetDbPolicy(RSqlSecurityPolicy::EWritePolicy,
       
   458                                    writePolicy);
       
   459         securityPolicy.SetDbPolicy(RSqlSecurityPolicy::EReadPolicy, readPolicy);
       
   460         err = mDatabase.Create(aDbName, securityPolicy);
       
   461         securityPolicy.Close();
       
   462     }
       
   463     else
       
   464     {
       
   465         err = mDatabase.Create(aDbName);
       
   466     }
       
   467 
       
   468     if (KErrNone != err)
       
   469     {
       
   470         ELOG1(EJavaStorage, "Cannot create database: %d", err);
       
   471 
       
   472         // LastErrorMessage cannot be called as create or open
       
   473         // didn't succeeded.
       
   474         mSessionId = "Database creation error";
       
   475         mConnOpen = false;
       
   476 
       
   477         throw JavaStorageException(err, mSessionId.c_str(),
       
   478                                    __FILE__, __FUNCTION__, __LINE__);
       
   479     }
       
   480     mConnOpen = true;
       
   481 }
       
   482 
       
   483 void JavaDataAccessImpl::createTable(const TDesC& aStatement)
       
   484 throw(JavaStorageException)
       
   485 {
       
   486     TInt err = mDatabase.Exec(aStatement);
       
   487 
       
   488     if (err < 0)
       
   489     {
       
   490         ELOG1(EJavaStorage, "Table create failed: %d", err);
       
   491         throw JavaStorageException(
       
   492             EInvalidDataStructure,
       
   493             "Table creation failed",
       
   494             __FILE__,
       
   495             __FUNCTION__,
       
   496             __LINE__);
       
   497     }
       
   498 }
       
   499 
       
   500 void JavaDataAccessImpl::columnName(int aIndex,
       
   501                                     RSqlStatement& aStmt,
       
   502                                     wstring& aColName)
       
   503 {
       
   504     TPtrC16 columnNamePtr;
       
   505     TInt err = aStmt.ColumnName(aIndex, columnNamePtr);
       
   506 
       
   507     if (KErrNone != err)
       
   508     {
       
   509         WLOG1(EJavaStorage, "Get ColumnName: %d", err);
       
   510     }
       
   511 
       
   512     // Deep copy needed.
       
   513     auto_ptr<HBufC16> colName(HBufC16::New(columnNamePtr.Length() + 1));
       
   514 
       
   515     if (!colName.get())
       
   516     {
       
   517         throw JavaStorageException(KErrNoMemory,
       
   518                                    "Cannot allocate column name buffer",
       
   519                                    __FILE__, __FUNCTION__, __LINE__);
       
   520     }
       
   521 
       
   522     TPtr16 colName2Ptr(colName->Des());
       
   523     colName2Ptr.Append(columnNamePtr);
       
   524     wstring temp(desToWstring(colName2Ptr));
       
   525     aColName = temp;
       
   526 }
       
   527 
       
   528 void JavaDataAccessImpl::columnValue(const int aIndex,
       
   529                                      RSqlStatement& aStmt,
       
   530                                      const TSqlColumnType aColumnType,
       
   531                                      wstring& aColValue)
       
   532 {
       
   533     // Only INT and STRING currently supported
       
   534     if (ESqlInt == aColumnType)
       
   535     {
       
   536         TInt value = aStmt.ColumnInt(aIndex);
       
   537         aColValue = JavaCommonUtils::intToWstring(value);
       
   538     }
       
   539     else
       
   540     {
       
   541         // Deep copy needed.
       
   542         auto_ptr<HBufC16> column(HBufC16::New(aStmt.ColumnSize(aIndex) + 1));
       
   543 
       
   544         if (!column.get())
       
   545         {
       
   546             throw JavaStorageException(KErrNoMemory,
       
   547                                        "Cannot allocate column value buffer",
       
   548                                        __FILE__, __FUNCTION__, __LINE__);
       
   549         }
       
   550 
       
   551         TPtr16 columnPtr(column->Des());
       
   552         TInt colErr = aStmt.ColumnText(aIndex, columnPtr);
       
   553 
       
   554         wstring temp(desToWstring(columnPtr));
       
   555         aColValue = temp;
       
   556     }
       
   557 }