javaruntimes/midp/runtimestarter/src/midpruntimestarter.cpp
branchRCL_3
changeset 19 04becd199f91
child 23 98ccebc37403
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/javaruntimes/midp/runtimestarter/src/midpruntimestarter.cpp	Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,846 @@
+/*
+* Copyright (c) 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:  This class provides container for message.
+*
+*/
+
+
+#include <string>
+#include <string.h>
+#include <algorithm>
+#include <iostream>
+#include <fstream>
+#include <unistd.h>
+
+#include "midpruntimestarter.h"
+#include "applicationinfosetter.h"
+#include "runtimeexception.h"
+#include "runtimestarterutils.h"
+#include "midpruntimearguments.h"
+
+#include "dynamiclibloader.h"
+#include "javainifileutils.h"
+#include "javacommonutils.h"
+#include "javaoslayer.h"
+#include "logger.h"
+
+#include "commsmessage.h"
+#include "rtcmessages.h"
+
+#include "pushcontrollerstarter.h"
+
+#include "javastoragenames.h"
+
+#include "javacoreui.h"
+#include "javacoreuiparams.h"
+
+#include "com_nokia_mj_impl_rt_midp_MemoryLogger.h"
+
+using namespace java::runtime;
+using namespace java::util;
+using namespace java::push;
+using namespace java::storage;
+using namespace java::captain;
+using namespace java::ui;
+
+const wchar_t* const RUNTIME_MAIN_CLASS = L"com.nokia.mj.impl.rt.midp.Main";
+const wchar_t* const TRUE_WSTR          = L"true";
+
+
+MidpRuntimeStarter::MidpRuntimeStarter(): mMidletInfo(new MidletInfo()), // codescanner::nonleavenew
+        mRuntimeState(Constructed)
+{
+    JELOG2(EJavaRuntime);
+}
+
+MidpRuntimeStarter::~MidpRuntimeStarter()
+{
+    JELOG2(EJavaRuntime);
+    if (mPushLib.get())
+    {
+        mPushLib->closeLib();
+    }
+}
+
+int MidpRuntimeStarter::start(int argc, char *argv[])
+{
+    JELOG2(EJavaRuntime);
+
+    // Create instance of RuntimeStarterUtils for thread supervisioning.
+    std::auto_ptr<RuntimeStarterUtils> starterUtils(new RuntimeStarterUtils()); // codescanner::nonleavenew
+    starterUtils->startThreadSupervisor();
+
+    // Parse the args received from Captain.
+    parseArgs(argc, argv);
+
+    initComms();
+
+    // Some push plugins needs to get the UID of the MIDlet and the root
+    // path. Setting MidpRuntimeStarter as a service provider.
+    setApplicationInfoProvider(*this);
+
+    // Check if push command was receieved.
+    if (mMidletInfo->mPushStart)
+    {
+        // In order ot serve ApplicationInfo we need to solve the
+        // MIDlet suite UID.
+        std::auto_ptr<JavaStorage> storage(JavaStorage::createInstance());
+        storage->open();
+        getMIDletSuiteUidFromStorage(*storage.get());
+        storage->close();
+        storage.reset(0);
+
+        handlePushStart();
+        // Handle case where during the push listening we receive a close cmd.
+        if (mRuntimeState == Closing)
+        {
+            closePush();
+            return 0;
+        }
+    }
+    // Load the core UI
+    std::auto_ptr<java::util::DynamicLibLoader> coreUiLoader;
+    startCoreUi(coreUiLoader);
+
+    // Create starter for starting the JVM
+    std::auto_ptr<JvmStarter>
+    jvm(JvmStarter::getJvmStarterInstance(JvmStarter::CLDC,
+                                          L"Midp"));
+
+    // Don't know the class path in pre-warm state.
+    if (!mMidletInfo->mPreWarmStart)
+    {
+        jvm->appendClassPath(mMidletInfo->mClassPath);
+        jvm->appendApplicationArgument(L"-uid");
+        jvm->appendApplicationArgument(mMidletInfo->mMIDletUid.toString());
+
+        // Get the heap size recorded from the previous runs.
+        int heapSize = getHeapSize();
+        if (heapSize > com_nokia_mj_impl_rt_midp_MemoryLogger_MAX_OLD_SPACE)
+        {
+            heapSize = com_nokia_mj_impl_rt_midp_MemoryLogger_MAX_OLD_SPACE;
+        }
+
+        if (heapSize > com_nokia_mj_impl_rt_midp_MemoryLogger_DEFAULT_OLD_SPACE)
+        {
+            jvm->overrideOldHeapSize(heapSize / 1024);
+        }
+    }
+
+    jvm->setMainClass(RUNTIME_MAIN_CLASS);
+    jvm->enableThreadDumping();
+    jvm->appendSystemProperty(L"-Dcom.nokia.rt.port=midp");
+#ifndef RD_JAVA_UI_QT
+    jvm->appendSystemProperty(L"-Dcom.nokia.legacy.support=LegacySymbian");
+#endif // RD_JAVA_UI_QT
+
+    // Provide access to this object by Java peer via delivering a pointer
+    // to this object.
+    jvm->appendApplicationArgument(L"-handle");
+    MidpStarterInternalSupport* internalSupport = this;
+    int handle = reinterpret_cast<int>(internalSupport);
+    jvm->appendApplicationArgument(JavaCommonUtils::intToWstring(handle));
+
+    // If the intention is to go to prewarmed state pass the info to Java peer.
+    if (mMidletInfo->mPreWarmStart)
+    {
+        jvm->appendApplicationArgument(L"-prewarm");
+        // Captain needs a pid in order to identify the prewarmed runtime.
+        jvm->appendApplicationArgument(JavaCommonUtils::intToWstring(getpid()));
+
+        // Starting with lower old space in pre warm case.
+        jvm->overrideOldHeapSize(36);
+    }
+
+    // If the requested to go to back ground, pass the info to Java peer.
+    if (mMidletInfo->mBackGroundRequested)
+    {
+        jvm->appendApplicationArgument(L"-background");
+        jvm->appendApplicationArgument(TRUE_WSTR);
+    }
+
+    // If the autoinvocation happened pass the info to Java peer.
+    if (mMidletInfo->mAutoInvocationRequested)
+    {
+        jvm->appendApplicationArgument(L"-autoinvocation");
+        jvm->appendApplicationArgument(TRUE_WSTR);
+        jvm->appendApplicationArgument(L"-autoInvocationAdditional");
+        jvm->appendApplicationArgument(mPushAdditionalInfo);
+    }
+
+    // Enable thread dumping. If the captain informed about debug mode
+    // or arguments for MIDlet set the arguments provided by the captain.
+    std::wstring midletArgs;
+    starterUtils->enableDevelopmentFeatures(*jvm.get(),
+                                            mMidletInfo->mDebugRequested || mMidletInfo->mMIDletHasArgs,
+                                            &midletArgs);
+
+    if (midletArgs.length() == 0)
+    {
+        // If MIDlet was waiting for push or was pre-warmed,
+        // the arguments can be already in midlet info
+        midletArgs = mMidletInfo->mMIDletArgs;
+    }
+
+    if (midletArgs.length() > 0)
+    {
+        // Pass the arguments to 'Java side' in encoded form.
+        // Encoding is done to prevent security risks.
+        std::wstring encodedArgs = L"-Dcom.nokia.mid.cmdline=";
+
+        encodedArgs.append(encodeArgs(midletArgs));
+
+        jvm->appendSystemProperty(encodedArgs);
+        // remember the args
+        mMidletInfo->mMIDletArgs = encodedArgs;
+    }
+
+    // When starting this property has always value "1"
+    jvm->appendSystemProperty(L"-Dcom.nokia.mid.cmdline.instance=1");
+
+    // There might be extensions available. Solving if those exist.
+    std::wstring extendedBootClassPath;
+    // This call is platform dependent.
+    starterUtils->getExtBootClassPath(extendedBootClassPath);
+    if (extendedBootClassPath.length() > 0)
+    {
+        // Append the extensions to bootclasspath.
+        jvm->appendBootClassPath(extendedBootClassPath);
+
+        // Provide the bootclasspath also as a system propery
+        // for solving the protected and restricted packages.
+        std::wstring addOnList(L"-Dcom.nokia.mj.addon.list=");
+        addOnList += extendedBootClassPath;
+        jvm->appendSystemProperty(addOnList);
+    }
+
+    mRuntimeState = Active;
+
+    // Start the JVM.
+    int status = jvm->startJvm();
+
+    if (mComms.get())
+    {
+        mComms->disconnect();
+    }
+    CoreUi::releaseUi(coreUiLoader);
+
+    return status;
+}
+
+
+void MidpRuntimeStarter::parseArgs(int argc, char* argv[])
+{
+    JELOG2(EJavaRuntime);
+
+    bool appUidFound = false;
+
+    // Loop through the arguments. First one can be skipped, because it
+    // contains the name of the executable.
+    for (int index = 1 ; index < argc; index++)
+    {
+        const char* key = argv[index];
+        const char* value = 0;
+
+        // Checking if there is value available.
+        if (index+1 < argc)
+        {
+            value = argv[index+1];
+        }
+        LOG2(EJavaRuntime, EInfo,"MidpRuntimeStarter::parseArgs(). "
+             "Handling key %s with value %s",
+             key,
+             value==0?"<No Value>":value);
+
+        if (strcmp(key, APP_UID_ARGUMENT) == 0)
+        {
+            if (value)
+            {
+                mMidletInfo->mMIDletUid =
+                    Uid(java::util::JavaCommonUtils::utf8ToWstring(value));
+
+                appUidFound = true;
+                index++;
+            }
+        }
+
+        else if (strcmp(key, PREWARM_ARGUMENT) == 0)
+        {
+            mMidletInfo->mPreWarmStart = true;
+            LOG1(EJavaRuntime, EInfo,"PREWARM_ARGUMENT = %d ",  mMidletInfo->mPreWarmStart);
+        }
+
+        else if (strcmp(key, PUSH_ARGUMENT) == 0)
+        {
+            mMidletInfo->mPushStart = true;
+            LOG1(EJavaRuntime, EInfo,"PUSH_ARGUMENT = %d ",  mMidletInfo->mPushStart);
+        }
+
+        else if (strcmp(key, AUTO_INVOCATION_ARGUMENT) == 0)
+        {
+            mMidletInfo->mAutoInvocationRequested = true;
+            LOG1(EJavaRuntime, EInfo,"AUTO_INVOCATION_ARGUMENT = %d ",  mMidletInfo->mAutoInvocationRequested);
+        }
+
+        else if (strcmp(key, DEBUG_ARGUMENT) == 0)
+        {
+            mMidletInfo->mDebugRequested = true;
+            LOG1(EJavaRuntime, EInfo,"DEBUG_ARGUMENT = %d ",  mMidletInfo->mDebugRequested);
+        }
+
+        else if (strcmp(key, EXTRA_ARGUMENTS) == 0)
+        {
+            mMidletInfo->mMIDletHasArgs = true;
+            LOG1(EJavaRuntime, EInfo,"EXTRA_ARGUMENTS = %d ",  mMidletInfo->mMIDletHasArgs);
+        }
+
+        else if (strcmp(key, BG_START_ARGUMENT) == 0)
+        {
+            mMidletInfo->mBackGroundRequested = true;
+            LOG1(EJavaRuntime, EInfo,"BG_START_ARGUMENT = %d ",  mMidletInfo->mBackGroundRequested);
+        }
+
+        else
+        {
+            std::string errorStr("Unknown argument received: ");
+            errorStr.append(key);
+            throw RuntimeException(errorStr, __FILE__, __FUNCTION__, __LINE__);
+        }
+    }
+
+    if (appUidFound == false && mMidletInfo->mPreWarmStart == false)
+    {
+        std::string errorStr("Argument ");
+        errorStr.append(APP_UID_ARGUMENT);
+        errorStr.append(" not defined!");
+        throw RuntimeException(errorStr, __FILE__, __FUNCTION__, __LINE__);
+    }
+}
+
+void MidpRuntimeStarter::startCoreUi(std::auto_ptr<java::util::DynamicLibLoader>& coreUiLoader)
+{
+    CoreUi& coreUi = CoreUi::getUiInstance(coreUiLoader);
+
+    // Create the default UI only if not going into pre-warmed state.
+    if (!mMidletInfo->mPreWarmStart)
+    {
+
+        // Open a session to JavaStorage.
+        std::auto_ptr<JavaStorage> javaStorage(JavaStorage::createInstance());
+        javaStorage->open();
+
+        CoreUiParams uiParams;
+
+        // Get the MIDlet suite UID from storage.
+        if (mMidletInfo->mMIDletSuiteUid.toString() == L"")
+        {
+            getMIDletSuiteUidFromStorage(*javaStorage.get());
+        }
+
+        // Check if the MIDlet has defined the Nokia-MIDlet-App-Orientation
+        // JAD attribute.
+        std::auto_ptr<std::wstring> appOrientation
+        (getMidletAttributeFromStorage(*javaStorage.get(),
+                                       L"Nokia-MIDlet-App-Orientation"));
+        if (appOrientation.get() != 0)
+        {
+
+            std::transform(appOrientation->begin(), appOrientation->end(),
+                           appOrientation->begin(), tolower);
+            if (*appOrientation == L"portrait")
+            {
+                uiParams.setOrientation(PORTRAIT);
+            }
+            else if (*appOrientation == L"landscape")
+            {
+                uiParams.setOrientation(LANDSCAPE);
+            }
+            else
+            {
+                WLOG1(EJavaRuntime, "appOrientation contained unknown value: %S",
+                      appOrientation->c_str());
+            }
+        }
+        else
+        {
+            LOG(EJavaRuntime, EInfo, "Nokia-MIDlet-App-Orientation not defined");
+        }
+
+        // Check if the MIDlet has defined the MIDlet-Splash-Screen-Image
+        // JAD attribute.
+        std::auto_ptr<std::wstring> splashScreen
+        (getMidletAttributeFromStorage(*javaStorage.get(),
+                                       L"MIDlet-Splash-Screen-Image"));
+        if (splashScreen.get() != 0)
+        {
+            std::transform(splashScreen->begin(), splashScreen->end(),
+                           splashScreen->begin(), tolower);
+            if (*splashScreen == L"suppress")
+            {
+                // If MIDlet-Splash-Screen-Image JAD attribute is suppress then
+                // we start the UI into background.
+                LOG(EJavaRuntime, EInfo, "MIDlet-Splash-Screen-Image is suppress");
+                uiParams.setScreenMode(NO_START_SCREEN);
+                uiParams.setBackgroundStart(true);
+            }
+            else
+            {
+                // If MIDlet-Splash-Screen-Image JAD attribute is not suppress then
+                // we need to solve the root path of the MIDlet and provide that
+                // to the coreUI.
+                uiParams.setScreenMode(MIDLET_DEFINED_SCREEN);
+                LOG1(EJavaRuntime, EInfo, "MIDlet-Splash-Screen-Image, setPath to %S",
+                     mMidletInfo->mMIDletRootPath.c_str());
+            }
+        }
+        else
+        {
+            LOG(EJavaRuntime, EInfo, "MIDlet-Splash-Screen-Image not defined");
+            uiParams.setScreenMode(DEFAULT_START_SCREEN);
+        }
+
+        getRootPath();
+        uiParams.setImagePath(mMidletInfo->mMIDletRootPath);
+
+        // If there was a background start requst pass the info to coreUi.
+        // Also the autoinvocation start puts the screen into BG.
+        if (mMidletInfo->mBackGroundRequested || mMidletInfo->mAutoInvocationRequested)
+        {
+            uiParams.setBackgroundStart(true);
+        }
+
+        // Start the coreUI.
+        JavaOsLayer::startUpTrace("Starting CoreUI", -1, -1);
+        coreUi.start(mMidletInfo->mMIDletUid, &uiParams);
+        JavaOsLayer::startUpTrace("CoreUI started", -1, -1);
+
+        getMIDletSuiteInfoFromStorage(javaStorage.get(), JAR_PATH,
+                                      mMidletInfo->mClassPath);
+    }
+
+}
+
+void MidpRuntimeStarter::
+ApplicationStateChangeRequest(ApplicationState state)
+{
+    JELOG2(EJavaRuntime);
+    LOG1(EJavaRuntime, EInfo, "ApplicationStateChangeRequest: %d", state);
+    switch (state)
+    {
+    case START_APPLICATION:
+    case CONTINUE_APPLICATION_STARTUP:
+        doStateChange(Start);
+        break;
+
+    case CLOSE_APPLICATION:
+        doStateChange(Stop);
+        break;
+
+    default:
+        std::string errorStr("Illegal state ");
+        errorStr.append(JavaCommonUtils::intToString(state));
+        throw RuntimeException(errorStr, __FILE__, __FUNCTION__, __LINE__);
+    }
+}
+
+void MidpRuntimeStarter::doStateChange(StateChangeRequest request)
+{
+    JELOG2(EJavaRuntime);
+    LOG2(EJavaRuntime, EInfo, "MidpRuntimeStarter::doStateChange. Request: %d,"
+         " current state: %d", request, mRuntimeState);
+    ScopedLock lock(mProcessesMutex); // Making the method thread safe
+    switch (request)
+    {
+    case Start:
+        // Check if we are still waiting start command.
+        if (mRuntimeState == PushListen)
+        {
+            mRuntimeState = Active;
+            //Allow application startUp.
+            mMonitor->notify();
+        }
+        break;
+
+    case Stop:
+        // Check if we are still waiting start command.
+        if (mRuntimeState == PushListen)
+        {
+            //Allow application to close.
+            mRuntimeState = Closing;
+            mMonitor->notify();
+        }
+        break;
+
+    default:
+        std::string errorStr("Illegal request ");
+        errorStr.append(JavaCommonUtils::intToString(request));
+        throw RuntimeException(errorStr, __FILE__, __FUNCTION__, __LINE__);
+    }
+
+}
+void MidpRuntimeStarter::closeRuntimeInd()
+{
+    JELOG2(EJavaRuntime);
+    LOG(EJavaRuntime, EInfo, "Starter got close indication from JVM");
+    if (mMidletInfo->mPushStart)
+    {
+        closePush();
+    }
+}
+
+void MidpRuntimeStarter::setUids(const Uid& midletUid, const Uid& midletSuiteUid)
+{
+    JELOG2(EJavaRuntime);
+    mMidletInfo->mMIDletUid = midletUid;
+    mMidletInfo->mMIDletSuiteUid = midletSuiteUid;
+    LOG2(EJavaRuntime, EInfo, "Setting UID set during pre-warm start: m=%S, s=%S",
+         mMidletInfo->mMIDletUid.toString().c_str(),
+         mMidletInfo->mMIDletSuiteUid.toString().c_str());
+}
+
+int MidpRuntimeStarter::getHeapSize() const
+{
+    JELOG2(EJavaRuntime);
+    // No need to do charcter conversion in here.
+    std::string root(mMidletInfo->mClassPath.begin(),
+                     mMidletInfo->mClassPath.end());
+    int heapSize = -1;
+
+    // The file is stored into same location where the jar file is put.
+    // replace the 'xxx.jar' with 'heap' and open the file.
+
+    size_t pos = root.find_last_of("/\\");
+    if (pos != std::string::npos)
+    {
+        root.erase(pos+1);
+        root += "heap";
+        LOG1(EJavaRuntime, EInfo, "Heap size from file %s.", root.c_str());
+        try
+        {
+            std::ifstream heapFile;
+            heapFile.open(root.c_str(), std::ifstream::in);
+            heapFile >> heapSize;
+            heapFile.close();
+            LOG1(EJavaRuntime, EInfo, "  heap: %d.", heapSize);
+        }
+        catch (std::exception& e)
+        {
+            LOG2(EJavaRuntime, EInfo, "Not able to read from file %s. Error %s",
+                 root.c_str(), e.what());
+        }
+    }
+    return heapSize;
+}
+
+std::wstring MidpRuntimeStarter::encodeArgs(const std::wstring& str)
+{
+    // Modify the places where the following characters are used to prevent
+    // possible security problems when this string is passed as an command line
+    // system property parameter to JVM
+    const std::wstring specials(L"= -%");
+
+    std::string::size_type idx = str.find_first_of(specials);
+    std::string::size_type cur = 0;
+
+    std::wstring res;
+    std::string convBuf;
+
+    while (idx != std::string::npos)
+    {
+        // Add all characters up to and including the current special char to
+        // final result string
+        if (idx >= cur)
+        {
+            res.append(str.substr(cur, (idx - cur) + 1));
+        }
+
+        // Encode all special characters 'X' in same way.
+        // "X" -> "X%"
+        res.append(L"%");
+
+        cur = idx + 1;
+        idx = str.find_first_of(specials, cur);
+    }
+
+    // Add characters after last special character if any
+    res.append(str.substr(cur, str.length() - cur));
+
+    return res;
+}
+
+void MidpRuntimeStarter::getMIDletSuiteUidFromStorage(java::storage::JavaStorage& storage)
+{
+    JELOG2(EJavaRuntime);
+
+    // Get the MIDlet suite UID.
+    JavaStorageApplicationEntry_t midletEntries;
+
+    // Reading the MIDlet specific attributes from APPLICATION_TABLE.
+    // MIDlet UID is a key.
+    storage.read(APPLICATION_TABLE, mMidletInfo->mMIDletUid,
+                 midletEntries);
+    // Storing UID of the MIDlet suite.
+    mMidletInfo->mMIDletSuiteUid = Uid(getDbValue(midletEntries, PACKAGE_ID));
+}
+
+void MidpRuntimeStarter::getMIDletSuiteInfoFromStorage(JavaStorage* storageConnection,
+        const std::wstring& key,
+        std::wstring& value) const
+{
+    JELOG2(EJavaRuntime);
+
+    // If the JavaStorage connection is created temporarily in this method, auto_ptr is used to
+    // ensure closing and destroyng the JavaStorage connection. Don't use javaStorage ptr to any
+    // other purposes - instead use storageConnection.
+    std::auto_ptr<JavaStorage> javaStorage;
+    if (storageConnection == 0)
+    {
+        javaStorage.reset(JavaStorage::createInstance());
+        storageConnection = javaStorage.get();
+        javaStorage->open();
+    }
+
+    JavaStorageApplicationEntry_t midletSuiteEntries;
+
+    // Reading the MIDlet suite specific attributes from
+    // APPLICATION_PACKAGE_TABLE. MIDlet suite UID is a key.
+    storageConnection->read(APPLICATION_PACKAGE_TABLE,
+                            mMidletInfo->mMIDletSuiteUid,
+                            midletSuiteEntries);
+    value = getDbValue(midletSuiteEntries, key);
+}
+
+std::wstring*
+MidpRuntimeStarter::getMidletAttributeFromStorage(JavaStorage& storage,
+        const std::wstring& searchKey)
+const
+{
+    JELOG2(EJavaRuntime);
+
+    JavaStorageEntry findPattern;
+    JavaStorageApplicationEntry_t findPatterns;
+    JavaStorageApplicationList_t foundEntries;
+
+    findPattern.setEntry(ID, mMidletInfo->mMIDletSuiteUid.toString(),
+                         JavaStorageEntry::STRING);
+    findPatterns.insert(findPattern);
+
+    findPattern.setEntry(NAME, searchKey, JavaStorageEntry::STRING);
+    findPatterns.insert(findPattern);
+
+    findPattern.setEntry(VALUE,L"");
+    findPatterns.insert(findPattern);
+
+    storage.search(APPLICATION_PACKAGE_ATTRIBUTES_TABLE, findPatterns, foundEntries);
+
+    JavaStorageApplicationList_t::iterator iter = foundEntries.begin();
+
+    if (iter != foundEntries.end())
+    {
+        JavaStorageEntry findPatternForValue;
+        findPatternForValue.setEntry(VALUE, L"");
+        JavaStorageApplicationEntry_t::iterator valueIter = iter->find(findPatternForValue);
+        if (valueIter != iter->end())
+        {
+            return new std::wstring(valueIter->entryValue()); // codescanner::nonleavenew
+        }
+        else
+        {
+            std::string errorStr("MIDLET with UID: ");
+            std::wstring uid = mMidletInfo->mMIDletUid.toString();
+            errorStr += std::string(uid.begin(), uid.end());
+            errorStr += ". Error reading from storage: ";
+            errorStr += std::string(searchKey.begin(), searchKey.end());
+            throw RuntimeException(errorStr, __FILE__, __FUNCTION__, __LINE__);
+        }
+    }
+    return 0;
+}
+
+
+
+std::wstring MidpRuntimeStarter::getDbValue(
+    const java::storage::JavaStorageApplicationEntry_t& entry,
+    const std::wstring& key) const
+{
+    JELOG2(EJavaRuntime);
+    JavaStorageEntry findPattern;
+    std::wstring empty;
+
+    findPattern.setEntry(key, empty);
+
+    // Get attribute from read attributes.
+    JavaStorageApplicationEntry_t::const_iterator findIterator =
+        entry.find(findPattern);
+
+    if (findIterator != entry.end())
+    {
+        return findIterator->entryValue();
+    }
+    else
+    {
+        std::string errorStr("MIDLET with UID: ");
+        std::wstring uid = mMidletInfo->mMIDletUid.toString();
+        errorStr += std::string(uid.begin(), uid.end());
+        errorStr += ". Not able to find attribute ";
+        errorStr += std::string(key.begin(), key.end());
+        throw RuntimeException(errorStr, __FILE__, __FUNCTION__, __LINE__);
+    }
+}
+
+void MidpRuntimeStarter::handlePushStart()
+{
+    JELOG2(EJavaRuntime);
+    mMonitor.reset(Monitor::createMonitor());
+    mRuntimeState = PushListen;
+    PushControllerStarter::getPushControllerStarter(mPushLib).
+    startListen(mMidletInfo->mMIDletUid, this);
+    mMonitor->wait();
+}
+
+void MidpRuntimeStarter::closePush()
+{
+    // Received a close message from Java peer.
+    PushControllerStarter::getPushControllerStarter(mPushLib).close();
+}
+
+void MidpRuntimeStarter::
+startMidletRequestFromPush(const std::wstring& pushAdditionalInfo)
+{
+    JELOG2(EJavaRuntime);
+    mPushAdditionalInfo = pushAdditionalInfo;
+
+    // This can be considered to be auto invocation. Setting flag on
+    // to be delivered to Java runtime.
+    mMidletInfo->mAutoInvocationRequested = true;
+
+    doStateChange(Start);
+}
+
+void MidpRuntimeStarter::closeRuntimeRequestFromPush()
+{
+    JELOG2(EJavaRuntime);
+    doStateChange(Stop);
+}
+
+void MidpRuntimeStarter::initComms()
+{
+    JELOG2(EJavaRuntime);
+    mComms.reset(new CommsClientEndpoint(L"javacaptain")); // codescanner::nonleavenew
+    mComms->registerDefaultListener(this);
+    int result = mComms->connect(IPC_ADDRESS_JAVA_CAPTAIN_C);
+    if (result != 0)
+    {
+        std::string errorStr("Connection to JavaCaptain failed: Reason = ");
+        errorStr.append(JavaCommonUtils::intToString(result));
+        throw RuntimeException(errorStr, __FILE__, __FUNCTION__, __LINE__);
+    }
+    CommsMessage msg;
+    msg.setModuleId(PLUGIN_ID_RTC_C);
+    setApplicationRunningIndParams(msg, mMidletInfo->mMIDletUid, 0);
+    mComms->send(msg);
+}
+
+void MidpRuntimeStarter::processMessage(java::comms::CommsMessage& message)
+{
+    JELOG2(EJavaRuntime);
+    int messageId = message.getMessageId();
+
+    // RTC_MSG_ID_LAUNCH_APPLICATION_REQ and
+    // RTC_MSG_ID_TERMINATE_APPLICATION_REQ are received from the Java Captain
+    // when we are listening push connection and the VM is not started.
+    // When the MIDlet is running normally, these two messages are handled
+    // by Java peer.
+    // RTC_MSG_ID_ADD_PUSH_CONNECTION_IND is always handled here.
+
+    switch (messageId)
+    {
+    case RTC_MSG_ID_LAUNCH_APPLICATION_REQ:
+    {
+        LOG(EJavaRuntime, EInfo, "RTC_MSG_ID_LAUNCH_APPLICATION_REQ");
+        // Start the push MIDlet that is pre started to listen mode.
+
+        Uid          uid;
+        int          type;
+        int          options;
+        std::string  rtc;
+        std::wstring midletArgs;
+        std::wstring runtimeArguments;
+
+        getLaunchApplicationReqParams(message, uid, type, options, rtc,
+                                      midletArgs,
+                                      runtimeArguments);
+        if (type == RTC_LAUNCH_TYPE_AUTO_INVOCATION_C)
+        {
+            mMidletInfo->mAutoInvocationRequested = true;
+        }
+
+        // The arguments will be passed to midlet when JVM is started
+        mMidletInfo->mMIDletArgs = midletArgs;
+
+        ApplicationStateChangeRequest(START_APPLICATION);
+    }
+    break;
+
+    case RTC_MSG_ID_TERMINATE_APPLICATION_REQ:
+        LOG(EJavaRuntime, EInfo, "RTC_MSG_ID_TERMINATE_APPLICATION_REQ");
+
+        // Stop the push MIDlet that is pre started to listen mode.
+        ApplicationStateChangeRequest(CLOSE_APPLICATION);
+        break;
+
+    case RTC_MSG_ID_ADD_PUSH_CONNECTION_IND:
+    {
+        LOG(EJavaRuntime, EInfo, "RTC_MSG_ID_ADD_PUSH_CONNECTION_IND");
+        Uid uidFromMessage;
+        getUpdatePushReqParams(message, uidFromMessage);
+        if (uidFromMessage == mMidletInfo->mMIDletUid)
+        {
+
+            PushControllerStarter::getPushControllerStarter(mPushLib).
+            updatePushRegs(mMidletInfo->mMIDletUid, this);
+        }
+        else
+        {
+            ELOG2(EJavaRuntime, "getUpdatePushReqParams: wrong UID!: "
+                  "%S should be %S",
+                  uidFromMessage.toString().c_str(),
+                  mMidletInfo->mMIDletUid.toString().c_str());
+        }
+    }
+    break;
+
+    default:
+        ELOG1(EJavaRuntime, "Unknown message sent to Runtime %d",
+              messageId);
+        break;
+    }
+}
+
+const std::wstring& MidpRuntimeStarter::getRootPath() const
+{
+    JELOG2(EJavaRuntime);
+    // If the root path is not yet cached, read it from storage.
+    if (mMidletInfo->mMIDletRootPath.length() == 0)
+    {
+        getMIDletSuiteInfoFromStorage(0, ROOT_PATH,
+                                      mMidletInfo->mMIDletRootPath);
+    }
+    return mMidletInfo->mMIDletRootPath;
+}
+
+const java::util::Uid& MidpRuntimeStarter::getUid() const
+{
+    return mMidletInfo->mMIDletUid;
+}