diff -r f5050f1da672 -r 04becd199f91 javacommons/javastorage/src/client/messagedispatcher.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javacommons/javastorage/src/client/messagedispatcher.cpp Tue Apr 27 16:30:29 2010 +0300 @@ -0,0 +1,487 @@ +/* +* 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: MessageDispatcher +* +*/ + + +#include "commsmessage.h" +#include "javacommonutils.h" +#include "javadataaccess.h" +#include "javastorageexception.h" +#include "logger.h" +#include "messagedispatcher.h" +#include "statementutils.h" + +using namespace java::comms; +using namespace java::storage; +using namespace java::util; +using namespace std; + +MessageDispatcher::MessageDispatcher() +{ + JELOG2(EJavaStorage); + mDataAccess.reset(JavaDataAccess::createInstance()); + mUtils.reset(new StatementUtils()); +} + +MessageDispatcher::~MessageDispatcher() +{ +} + +std::string MessageDispatcher::createAndSendMessage( + JavaStorageMessage::MessageIdentifier aMsgId, + const string& aHeaders, + const string& aDatabaseName) +{ + JELOG2(EJavaStorage); + + string sessionID = ""; + CommsMessage receivedMessage; + int statusCode = -1; + + string headers = aHeaders; + createHeader(aMsgId, headers); + + switch (aMsgId) + { + case JavaStorageMessage::EOpen: + { + mDataAccess->open(headers, aDatabaseName, receivedMessage); + + receivedMessage>>statusCode; + + if (statusCode >= 0) + { + receivedMessage>>sessionID; + LOG1(EJavaStorage, EInfo, "Received sessionID: %s", + sessionID.c_str()); + } + break; + } + case JavaStorageMessage::EClose: + { + mDataAccess->close(headers, receivedMessage); + receivedMessage>>statusCode; + break; + } + case JavaStorageMessage::EStartTransaction: + { + mDataAccess->execute(headers, L"BEGIN;", receivedMessage); + receivedMessage>>statusCode; + break; + } + case JavaStorageMessage::ECommit: + { + mDataAccess->execute(headers, L"COMMIT;", receivedMessage); + receivedMessage>>statusCode; + break; + } + case JavaStorageMessage::ERollback: + { + mDataAccess->execute(headers, L"ROLLBACK;", receivedMessage); + receivedMessage>>statusCode; + break; + } + default: + { + ELOG1(EJavaStorage, "Unknown command: %d", aMsgId); + throw JavaStorageException(aMsgId, "Unknown message", + __FILE__, __FUNCTION__, __LINE__); + } + } + + if (statusCode < 0) + { + string errorMessage = ""; + readErrorMessage(receivedMessage, errorMessage); + throw JavaStorageException(statusCode, errorMessage.c_str(), + __FILE__, __FUNCTION__, __LINE__); + } + + return sessionID; +} + +int MessageDispatcher::createAndSendMessage( + JavaStorageMessage::MessageIdentifier aMsgId, + const string& aHeaders, + const string& identifier, + const JavaStorageApplicationEntry_t& aEntry) +{ + JELOG2(EJavaStorage); + + CommsMessage receivedMessage; + int statusCode = -1; + int retVal = -1; + + string headers = aHeaders; + createHeader(aMsgId, headers); + + wstring insertion(L", "); + + switch (aMsgId) + { + case JavaStorageMessage::EWrite: + { + wstring sqlStatement = L""; + mUtils->createWriteStatement( + aEntry, identifier, insertion, sqlStatement); + mDataAccess->execute(headers, sqlStatement, receivedMessage); + + receivedMessage>>statusCode; + break; + } + case JavaStorageMessage::ERead: + { + // Contains only one entry. It is already checked. + JavaStorageApplicationEntry_t::const_iterator iter = aEntry.begin(); + + wstring sqlStatement = L"SELECT * FROM "; + sqlStatement.append( + JavaCommonUtils::utf8ToWstring(identifier.c_str())); + sqlStatement.append(L" WHERE ID = '") + .append((*iter).entryValue()).append(L"';"); + + mDataAccess->execute(headers, sqlStatement, receivedMessage); + + receivedMessage>>statusCode; + + if (statusCode >= 0) + { + // Const cast required. This prevent need to create yet another + // createAndSend subroutine. + JavaStorageApplicationEntry_t& temp = + const_cast(aEntry); + + // Value was added by the API so remove that it does not exists + // in the response twice. + temp.clear(); + populateEntry(receivedMessage, temp); + } + break; + } + case JavaStorageMessage::ERemove: + { + wstring sqlStatement = L"DELETE FROM "; + + sqlStatement.append( + JavaCommonUtils::utf8ToWstring(identifier.c_str())); + + if (aEntry.size() > 0) + { + mUtils->createWhereStatement(aEntry, sqlStatement); + } + else // Delete whole table contents. + { + sqlStatement.append(L";"); + } + mDataAccess->execute(headers, sqlStatement, receivedMessage); + + receivedMessage>>statusCode; + + if (statusCode >= 0) + { + wstring temp = L""; + receivedMessage>>temp; + // How many entries removed i.e. rows removed. + retVal = JavaCommonUtils::wstringToInt(temp); + } + break; + } + case JavaStorageMessage::ECreateTable: + { + wstring sqlStatement = L""; + mUtils->createTableStatement( + aEntry, identifier, insertion, sqlStatement); + mDataAccess->execute(headers, sqlStatement, receivedMessage); + receivedMessage>>statusCode; + break; + } + case JavaStorageMessage::EAppendTable: + { + // NOTE: SQLite supports adding only one column at the time. + // For this reason several calls need to be executed. + + wstring prefix = L"ALTER TABLE "; + + prefix.append( + JavaCommonUtils::utf8ToWstring(identifier.c_str())); + + // Define added columns + // ID will always be primary key + prefix.append(L" ADD "); + + JavaStorageApplicationEntry_t::const_iterator colIter; + + for (colIter = aEntry.begin(); colIter != aEntry.end(); colIter++) + { + if ((*colIter).entryName() == L"") + { + throw JavaStorageException(EInvalidDataStructure, + "Column name not defined", + __FILE__, __FUNCTION__, __LINE__); + } + + wstring sqlStatement = prefix; + sqlStatement.append((*colIter).entryName()); + + if (JavaStorageEntry::STRING == (*colIter).entryType()) + { + sqlStatement.append(L" varchar"); + } + else if (JavaStorageEntry::INT == (*colIter).entryType()) + { + sqlStatement.append(L" int"); + } + else + { + ELOG(EJavaStorage, "Unknown column type"); + throw JavaStorageException(EInvalidDataStructure, + "Unknown column type", + __FILE__, __FUNCTION__, __LINE__); + } + sqlStatement.append(L";"); + + mDataAccess->execute(headers, sqlStatement, receivedMessage); + + receivedMessage>>statusCode; + + if (statusCode < 0) + { + break; // stop execution on first error. + } + else + { + // Reset for next round + receivedMessage.reset(); + } + } + break; + } + default: + { + ELOG1(EJavaStorage, "Unknown command: %d", aMsgId); + throw JavaStorageException(aMsgId, "Unknown message", + __FILE__, __FUNCTION__, __LINE__); + } + } + + if (statusCode < 0) + { + string errorMessage = ""; + readErrorMessage(receivedMessage, errorMessage); + throw JavaStorageException(statusCode, errorMessage.c_str(), + __FILE__, __FUNCTION__, __LINE__); + } + return retVal; +} + +void MessageDispatcher::handleSearch( + JavaStorageMessage::MessageIdentifier aMsgId, + const string& aHeaders, + const string& aTableName, + const JavaStorageApplicationEntry_t& aEntry, + JavaStorageApplicationList_t& aAppList +) +{ + int statusCode = -1; + CommsMessage receivedMessage; + + string headers = aHeaders; + createHeader(aMsgId, headers); + + wstring sqlStatement = L""; + mUtils->createSearchStatement(aEntry, aTableName, sqlStatement); + mDataAccess->execute(headers, sqlStatement, receivedMessage); + + receivedMessage>>statusCode; + + if (statusCode >= 0) + { + populateEntry(receivedMessage, aAppList); + } + else + { + string errorMessage = ""; + readErrorMessage(receivedMessage, errorMessage); + throw JavaStorageException(statusCode, errorMessage.c_str(), + __FILE__, __FUNCTION__, __LINE__); + } +} + +void MessageDispatcher::handleUpdate( + JavaStorageMessage::MessageIdentifier aMsgId, + const string& aHeaders, + const string& identifier, + const JavaStorageApplicationEntry_t& aUpdateEntry, + const JavaStorageApplicationEntry_t& aMatchEntry) +{ + int statusCode = -1; + CommsMessage receivedMessage; + string headers = aHeaders; + createHeader(aMsgId, headers); + + wstring sqlStatement = L""; + mUtils->createUpdateStatement( + aUpdateEntry, aMatchEntry, identifier, sqlStatement); + + mDataAccess->execute(headers, sqlStatement, receivedMessage); + receivedMessage>>statusCode; + + if (statusCode < 0) + { + string errorMessage = ""; + readErrorMessage(receivedMessage, errorMessage); + throw JavaStorageException(statusCode, errorMessage.c_str(), + __FILE__, __FUNCTION__, __LINE__); + } +} + +void MessageDispatcher::populateEntry(CommsMessage& aReceivedMessage, + JavaStorageApplicationEntry_t& aEntry) +{ + JELOG2(EJavaStorage); + + wstring data; + aReceivedMessage>>data; + + wstring::size_type startIdx = 0; + wstring::size_type endIdx = 0; + wstring appDelim = L";#\n;"; + wstring attrDelim = L";\n;"; + + // Skipp app delimiter + if (data.find(appDelim) == 0) + { + startIdx = appDelim.size(); + endIdx = startIdx; + } + + // This method reads only one storage row. If multiple ones are given + // they are ignored. + if ((endIdx = data.find(appDelim, startIdx)) != string::npos) + { + WLOG(EJavaStorage, "Removing multiple app occurrences"); + data = data.substr(0, endIdx); + } + + // Reset counter + endIdx = startIdx; + + wstring nameDelim = L"="; + + while (string::npos != startIdx || string::npos != endIdx) + { + // Read name + endIdx = data.find(nameDelim, startIdx); + if (endIdx == string::npos) break; // Not found + + wstring name = data.substr(startIdx, (endIdx - startIdx)); + + // Read value. Skip name and delimiter + startIdx = endIdx + 1; + endIdx = data.find(attrDelim, startIdx); + if (endIdx == string::npos) break; // Not found + + wstring value = L""; + + if (endIdx != startIdx) + { + value = data.substr(startIdx, (endIdx - startIdx)); + } + // else empty value. + + JavaStorageEntry entry; + entry.setEntry(name, value); + aEntry.insert(entry); + + // Skip value and delimiter + startIdx = endIdx + attrDelim.size(); + if (startIdx == string::npos) break; // Not found + } +} + +void MessageDispatcher::populateEntry(CommsMessage& aReceivedMessage, + JavaStorageApplicationList_t& aAppList) +{ + JELOG2(EJavaStorage); + + wstring data; + aReceivedMessage>>data; + + // ################# TEMP ################################################# + // LOG1WSTR(EJavaStorage, EInfo, "Response: %s", data); + // ################# END OF TEMP ########################################## + + wstring appDelim = L";#\n;"; + + if (data.size() <= appDelim.size()) + { + LOG(EJavaStorage, EInfo, "No entries to populate"); + return; + } + + wstring::size_type startIdx = appDelim.size(); + wstring::size_type endIdx = startIdx; + + // This does two if else less within while loop as its known string + // terminates always despite of column amount. + data.append(appDelim); + + JavaStorageApplicationEntry_t appEntry; + + do + { + endIdx = data.find(appDelim, startIdx); + + if (endIdx == string::npos) break; // No token found + + wstring appString = data.substr(startIdx, (endIdx - startIdx)); + + CommsMessage oneApp; + oneApp<>wideErrorMsg; + + char* errorMsg = JavaCommonUtils::wstringToUtf8(wideErrorMsg); + string errorMessage(errorMsg); + delete[] errorMsg; + aErrMsg = errorMessage; + ELOG1(EJavaStorage, "Error message %s", aErrMsg.c_str()); +}