javamanager/javacaptain/src/rtc.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Thu, 19 Aug 2010 09:48:13 +0300
branchRCL_3
changeset 24 6c158198356e
parent 18 9ac0a0a7da70
permissions -rw-r--r--
Revision: v2.2.9 Kit: 201033

/*
* Copyright (c) 2008 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:  Rtc
*
*/

#include <string>
#include <memory>
#include <exception>

#include "commsendpoint.h"
#include "commsmessage.h"
#include "logger.h"
#include "javacommonutils.h"
#include "libraryloaderexception.h"
#include "javaoslayer.h"

#include "rtc.h"
#include "coreinterface.h"
#include "rtcmessages.h"
#include "pmcmessages.h"
#include "applicationruntimeeventsinterface.h"
#include "booteventprovidermessages.h"
#include "javastorageentry.h"
#include "javastorage.h"
#include "javastoragenames.h"

#include "settingschangeeventsprovidermessages.h"

#include "midprtcplugin.h"
#ifdef RD_JAVA_CAPTAIN_TESTRUNTIME
#include "testrtcplugin.h"
#endif

namespace java
{
namespace captain
{

Rtc::Rtc() : mCore(0), mRuntimeEventsDispatcher(0), mSupportPreWarming(false)
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);
#if defined(RD_JAVA_PREWARM) && !defined (__WINS__)
    ILOG(EJavaCaptain, "Rtc::Rtc() - Prewarm support turned on");
    mSupportPreWarming = true;
#endif // RD_JAVA_PREWARM
}

Rtc::~Rtc()
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);
}

bool Rtc::start(CoreInterface* aCore,
                ApplicationRuntimeEventsInterface* aRuntimeEventsDispatcher)
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);

    mCore = aCore;
    mCore->getComms()->registerListener(PLUGIN_ID_RTC_C, this);
    mCore->getComms()->registerListener(PLUGIN_ID_PMC_C, this);
    mRuntimeEventsDispatcher = aRuntimeEventsDispatcher;
    initialiseRuntimePlugins();
    return true;
}

bool Rtc::stop()
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);

    if (mCore)
    {
        mCore->getComms()->unregisterListener(PLUGIN_ID_RTC_C, this);
        mCore->getComms()->unregisterListener(PLUGIN_ID_PMC_C, this);
    }

    terminateRtcRuntimes();
    clearDisabledList();
    clearRuntimePlugins();

    return true;
}

void Rtc::terminateRtcRuntimes()
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);

    // Delete the objects
    for (runtimes_t::iterator iter = mRuntimes.begin() ;
            iter != mRuntimes.end(); ++iter)
    {
        delete iter->second;
    }
    // Delete the pairs from map
    mRuntimes.clear();
}

void Rtc::stopPrewarm()
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);

    mSupportPreWarming = false;
    // Try to find prewarmed instance
    runtimes_t::iterator iter = mRuntimes.find(PREWARM_UID);
    if (iter != mRuntimes.end())
    {
        ILOG(EJavaCaptain, "Rtc::stopPrewarm() - prewarm instance found, deleting...");
        delete iter->second;
        mRuntimes.erase(iter);
    }
}

void Rtc::clearDisabledList()
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);
    mDisabledUIDs.clear();
}

// RtcInterface methods
bool Rtc::launch(const rtcLaunchInfo& aLaunchInfo)
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);
    if (mSupportPreWarming &&
            aLaunchInfo.mLaunchType == RTC_LAUNCH_TYPE_PREWARM_C &&
            mRuntimes.find(PREWARM_UID) != mRuntimes.end())
    {
        ILOG(EJavaCaptain, "Rtc::launch() - Prewarmed instance found, not creating new");
        return true;
    }
    int options = RTC_LAUNCH_OPTIONS_NONE_C;
    CommsMessage dummy;
    return launch(aLaunchInfo, options, dummy);
}

bool Rtc::terminate(const rtcTerminateInfo& aTerminateInfo)
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);
    int options = RTC_TERMINATE_OPTIONS_NONE_C;
    CommsMessage dummy;
    return terminate(aTerminateInfo, options, dummy);
}

bool Rtc::launch(const rtcLaunchInfo& aLaunchInfo, const int& aOptions, CommsMessage& aRequester)
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);

    LOG1WSTR(EJavaCaptain, EInfo, "Rtc::launch(uid=%s)", aLaunchInfo.mUID.toString());
    LOG3(EJavaCaptain, EInfo, "Rtc::launch(runtime=%s, type=%d, options=%d)",
         aLaunchInfo.mRtcType.c_str(), aLaunchInfo.mLaunchType, aOptions);

    bool launchSuccess = false;

    if (aOptions & RTC_LAUNCH_OPTIONS_RUNNING_IND_REQ_C)
    {
        mLaunchers.insert(std::make_pair(aLaunchInfo.mUID, aRequester));
    }
    if (aOptions & RTC_LAUNCH_OPTIONS_TERMINATE_IND_REQ_C)
    {
        mTerminators.insert(std::make_pair(aLaunchInfo.mUID, aRequester));
    }

    if (mDisabledUIDs.find(aLaunchInfo.mUID) != mDisabledUIDs.end())
    {
        notifyLaunchers(aLaunchInfo.mUID, -1, 0);
        notifyTerminators(aLaunchInfo.mUID, -1);
        launchSuccess = false;
    }
    else
    {
        rtcLaunchInfo finalLaunchInfo(aLaunchInfo.mUID,
                                      aLaunchInfo.mLaunchType, aLaunchInfo.mRtcType,
                                      (!aLaunchInfo.mApplicationArguments.empty() ? aLaunchInfo.mApplicationArguments
                                       : getGlobalApplicationArguments()),
                                      (!aLaunchInfo.mRuntimeArguments.empty() ? aLaunchInfo.mRuntimeArguments
                                       : getGlobalRuntimeArguments()));

        RtcRuntimeInterface* runtime = getOrCreateRtcRuntime(finalLaunchInfo);

        if ((0 == runtime) || (false == runtime->launch(finalLaunchInfo)))
        {
            deleteRuntime(finalLaunchInfo.mUID);
            notifyLaunchers(finalLaunchInfo.mUID, -1, 0);
            notifyTerminators(finalLaunchInfo.mUID, -1);
            launchSuccess = false;
        }
        else
        {
            if (runtime->isRunning())
            {
                notifyLaunchers(finalLaunchInfo.mUID, 0, runtime->pid());
            }
            launchSuccess = true;
        }
    }

    return launchSuccess;
}

bool Rtc::terminate(const rtcTerminateInfo& aTerminateInfo, const int& aOptions, CommsMessage& aRequester)
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);

    LOG1WSTR(EJavaCaptain, EInfo, "Rtc::terminate(uid=%s)", aTerminateInfo.mUID.toString());
    LOG1(EJavaCaptain, EInfo, "Rtc::terminate(options=%d)", aOptions);

    bool terminateSuccess = false;

    if (aOptions & RTC_TERMINATE_OPTIONS_TERMINATE_IND_REQ_C)
    {
        mTerminators.insert(std::make_pair(aTerminateInfo.mUID, aRequester));
    }

    RtcRuntimeInterface* runtime = getRtcRuntime(aTerminateInfo.mUID);

    if (0 == runtime ||
            true == runtime->terminate(aTerminateInfo))
    {
        notifyTerminators(aTerminateInfo.mUID, 0);
        mRuntimeEventsDispatcher->arTerminated(aTerminateInfo.mUID, 0);
        terminateSuccess = true;
    }

    return terminateSuccess;
}

void Rtc::notifyLaunchers(const Uid& aUid, const int& aStatus, const int& aPid)
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);

    requesters_t::iterator iter = mLaunchers.find(aUid);

    if (iter != mLaunchers.end())
    {
        CommsMessage msg;
        setApplicationRunningIndParams(msg, aUid, aStatus, aPid);
        CommsEndpoint* comms = mCore->getComms();
        while (comms && iter != mLaunchers.end())
        {
            msg.setModuleId(iter->second.getModuleId());
            msg.setReceiver(iter->second.getSender());
            msg.setMessageRef(iter->second.getMessageRef());
            LOG1(EJavaCaptain, EInfo, "informing launcher %d", msg.getReceiver());
            comms->send(msg);
            mLaunchers.erase(iter);
            iter = mLaunchers.find(aUid);
        }
    }
}

void Rtc::notifyTerminators(const Uid& aUid, const int& aStatus)
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);

    requesters_t::iterator iter = mTerminators.find(aUid);

    if (iter != mTerminators.end())
    {
        CommsMessage msg;
        setApplicationTerminatedIndParams(msg, aUid, aStatus);
        CommsEndpoint* comms = mCore->getComms();
        while (comms && iter != mTerminators.end())
        {
            msg.setModuleId(iter->second.getModuleId());
            msg.setReceiver(iter->second.getSender());
            msg.setMessageRef(iter->second.getMessageRef());
            LOG1(EJavaCaptain, EInfo, "informing terminator %d", msg.getReceiver());
            comms->send(msg);
            mTerminators.erase(iter);
            iter = mTerminators.find(aUid);
        }
    }
}

bool Rtc::enable(const Uid& aUID)
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);
    LOG1WSTR(EJavaCaptain, EInfo, "enable(%s)", aUID.toString());

    mDisabledUIDs.erase(aUID);

    return true;
}

bool Rtc::disable(const Uid& aUID)
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);
    LOG1WSTR(EJavaCaptain, EInfo, "disable(%s)", aUID.toString());

    mDisabledUIDs.insert(aUID);

    return true;
}

void Rtc::setGlobalRuntimeArguments(const std::wstring& aArguments)
{
    mGlobalRuntimeArguments = aArguments;
}

std::wstring Rtc::getGlobalRuntimeArguments()
{
    return mGlobalRuntimeArguments;
}

void Rtc::setGlobalApplicationArguments(const std::wstring& aArguments)
{
    mGlobalApplicationArguments = aArguments;
}

std::wstring Rtc::getGlobalApplicationArguments()
{
    return mGlobalApplicationArguments;
}

void Rtc::pmcTerminated(const int& pid, const int& exitCode)
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);

    for (runtimes_t::iterator iter = mRuntimes.begin() ;
            iter != mRuntimes.end(); ++iter)
    {
        if (iter->second->pid() == pid)
        {
            iter->second->pmcTerminated(pid, exitCode);

            Uid uid = iter->second->uid();
            // iter value might not be valid anymore after the following callbacks!
            mRuntimeEventsDispatcher->arTerminated(uid, exitCode);
            notifyLaunchers(uid, -1, pid);
            notifyTerminators(uid, 0);
            break;
        }
    }
}

void Rtc::processMessage(CommsMessage& aMessage)
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);

    try
    {
        switch (aMessage.getMessageId())
        {
        case RTC_MSG_ID_LAUNCH_APPLICATION_REQ:
        {
            java::util::JavaOsLayer::startUpTrace("CAPTAIN: Launch req", -1, -1);
            Uid uid;
            int type = 0;
            int options = 0;
            std::string rtc;
            std::wstring applicationArguments, runtimeArguments;
            getLaunchApplicationReqParams(aMessage, uid, type, options, rtc,
                                          applicationArguments, runtimeArguments);

            if (runtimeArguments.length() != 0 &&
                    !aMessage.hasPermission(LAUNCH_APPLICATION))
            {
                WLOG(EJavaCaptain, "LAUNCH_APP failed: not allowed to modify runtime arguments");
                sendOperationFailed(aMessage, uid, options);
            }
            else
            {
                launch(rtcLaunchInfo(uid, type, rtc, applicationArguments, runtimeArguments),
                       options, aMessage);
            }
        }
        break;

        case RTC_MSG_ID_TERMINATE_APPLICATION_REQ:
        {
            Uid uid;
            int options = 0;
            getTerminateApplicationReqParams(aMessage, uid, options);

            if (aMessage.hasPermission(STOP_APPLICATION))
            {
                terminate(uid, options, aMessage);
            }
            else
            {
                WLOG(EJavaCaptain, "STOP_APP failed: not allowed");
                sendOperationFailed(aMessage, uid, options);
            }
        }
        break;

        case RTC_MSG_ID_APPLICATION_RUNNING_IND:
        {
            Uid uid;
            int status = 0;
            getApplicationRunningIndParams(aMessage, uid, status);
            runtimes_t::iterator rtIter = mRuntimes.find(uid);

            if (rtIter != mRuntimes.end())
            {
                const int senderAddress = aMessage.getSender();
                rtIter->second->runningInd(senderAddress, status);
                mRuntimeEventsDispatcher->arLaunched(uid, senderAddress);
                notifyLaunchers(uid, 0, rtIter->second->pid());
            }
        }
        break;

        case RTC_MSG_ID_APPLICATION_TERMINATED_IND:
        {
            Uid uid;
            int status = 0;
            getApplicationTerminatedIndParams(aMessage, uid, status);
            runtimes_t::iterator rtIter = mRuntimes.find(uid);

            if (rtIter != mRuntimes.end())
            {
                rtIter->second->terminatedInd(status);
            }
        }
        break;

        case RTC_MSG_ID_SET_EXTRA_ARGUMENTS:
            if (aMessage.hasPermission(LAUNCH_APPLICATION))
            {
                getSetExtraArguments(aMessage, mGlobalRuntimeArguments,
                                     mGlobalApplicationArguments);
            }
            else
            {
                WLOG(EJavaCaptain, "SET_EXTRA_ARGUMENTS failed: not allowed");
            }
            break;

        case RTC_MSG_ID_GET_EXTRA_ARGUMENTS:
            if (!routeMessage(aMessage, aMessage.getSender()))
            {
                LOG(EJavaCaptain, EWarning,
                    "Rtc::ProcessMessage: Get extra args msg is not from one of the runtimes");

                // handler was not one of the runtimes then reply directly:
                CommsMessage message;
                message.replyTo(aMessage);
                setGetExtraArgumentsAck(message, mGlobalRuntimeArguments, mGlobalApplicationArguments);
                mCore->getComms()->send(message);
            }
            break;

        case PMC_MSG_ID_PROCESS_INITIALISED_IND:
        {
            int pid = 0;
            getProcessInitialisedIndParams(aMessage, pid);

            for (runtimes_t::iterator iter = mRuntimes.begin();
                    iter != mRuntimes.end(); ++iter)
            {
                if (iter->second->pid() == pid)
                {
                    iter->second->runningInd(aMessage.getSender(), 0);
                    break;
                }
            }
        }
        break;

        default:
            LOG1(EJavaCaptain, EInfo, "Rtc::ProcessMessage, unknown messageId = %d",
                 aMessage.getMessageId());
            break;
        }
    }

    catch (std::exception& e)
    {
        LOG(EJavaCaptain, EInfo, "Rtc::ProcessMessage: unhandled exception");
    }
}


bool Rtc::routeMessage(CommsMessage& aMessage, const int& aRuntimeAddress)
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);

    for (runtimes_t::iterator iter = mRuntimes.begin();
            iter != mRuntimes.end(); ++iter)
    {
        if (iter->second->runtimeAddress() == aRuntimeAddress)
        {
            iter->second->processMessage(aMessage);
            return true; // handler found
        }
    }

    return false; // handler not found
}

void Rtc::event(const std::string& eventProvider,
                java::comms::CommsMessage& aMsg )
{
    ILOG(EJavaCaptain, "+Rtc::event()");
    if (BOOT_EVENT_PROVIDER == eventProvider)
    {
        if (mSupportPreWarming && isThereInstalledMidlets())
        {
            ILOG(EJavaCaptain, "Rtc::event() - Boot event received, Starting "
                 "prewarm VM since found Installed MIDlets");
            launchPrewarm(); //New prewarm VM instance is will be created only
                                      //if it did not exist already
        }
    } else if ( SETTINGS_CHANGE_EVENT_PROVIDER == eventProvider )
    {
        int changeEventType = 0;
        getSettingsChangeEventMessageParams(aMsg, changeEventType);
        if ( MIDP_CLASS_PATH_CHANGE == changeEventType &&
             (mRuntimes.find(PREWARM_UID) != mRuntimes.end()) )
        {
            // Java libraries have been modified in the system.
            //Prewarm instance must be restarted
            ILOG(EJavaCaptain, "Rtc::event() - Restarting prewarm VM instance "
                 "since MIDP classpath has changed");
            stopPrewarm();
            launchPrewarm();
        }
    }
}

// ApplicationManagementEventsInterface methods
void Rtc::amAdded(const uids_t& /* aUids */)
{
    ILOG(EJavaCaptain, "+Rtc::amAdded()");
    // we know there is now installed MIDlets
    if (mSupportPreWarming)
    {
        ILOG(EJavaCaptain, "Rtc::amAdded() - MIDlets installed and prewarm is on -> try to start prewarm VM if not already running");
        launchPrewarm(); //New prewarm VM instance is will be created only if it did not exist already
    }
}

void Rtc::amUpdated(const uids_t& /* aUids */)
{
    ILOG(EJavaCaptain, "+Rtc::amUpdated()");
    // we know there is now installed MIDlets
    if (mSupportPreWarming)
    {
        ILOG(EJavaCaptain, "Rtc::amUpdated() - MIDlet updated and prewarm is on -> try to start prewarm VM if not already running ");
        launchPrewarm(); //New prewarm VM instance is will be created only if it did not exist already
    }
}

void Rtc::amDeleted(const uids_t& /* aUids */)
{
    ILOG(EJavaCaptain, "+Rtc::amDeleted()");
    // Check if prewarm can be turned off
    if (mSupportPreWarming && (!isThereInstalledMidlets()))
    {
        ILOG(EJavaCaptain,  "Rtc::amDeleted() - No MIDlets installed -> Stopping prewarm VM...");
        stopPrewarm();
    }
}

void Rtc::routeMessageToAll(CommsMessage& message)
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);

    for (runtimes_t::iterator iter = mRuntimes.begin();
            iter != mRuntimes.end(); ++iter)
    {
        iter->second->processMessage(message);
    }
}

void Rtc::sendOperationFailed(CommsMessage& aRequester, const Uid& aUid, const int& aOptions)
{
    if (aOptions != 0)
    {
        CommsMessage reply;
        reply.replyTo(aRequester);
        setApplicationTerminatedIndParams(reply, aUid, -1);
        mCore->getComms()->send(reply);
    }
}

void Rtc::initialiseRuntimePlugins()
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);

    mPlugins.insert(std::make_pair("midp", new rtcPluginData(getMidpRtcPlugin())));

#ifdef RD_JAVA_CAPTAIN_TESTRUNTIME
    mPlugins.insert(std::make_pair("test", new rtcPluginData(getTestRtcPlugin())));
#endif
}

void Rtc::clearRuntimePlugins()
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);

    // Delete the objects
    for (plugins_t::iterator iter = mPlugins.begin() ;
            iter != mPlugins.end(); ++iter)
    {
        delete iter->second;
    }
    // Delete the pairs from map
    mPlugins.clear();
}

RtcRuntimeInterface* Rtc::getRtcRuntime(const Uid& aUid)
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);

    RtcRuntimeInterface* runtime = 0;
    runtimes_t::iterator rtIter = mRuntimes.find(aUid);

    if (rtIter != mRuntimes.end())
    {
        runtime = rtIter->second;
    }

    return runtime;
}

RtcRuntimeInterface* Rtc::getOrCreateRtcRuntime(const rtcLaunchInfo& aLaunchInfo)
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);

    RtcRuntimeInterface* runtime = 0;
    runtimes_t::iterator rtIter = mRuntimes.find(aLaunchInfo.mUID);

    if (rtIter != mRuntimes.end() &&
            -1 == rtIter->second->pid())
    {
        delete rtIter->second;
        mRuntimes.erase(rtIter);
        rtIter = mRuntimes.end();
    }

    if (rtIter == mRuntimes.end())
    {
        runtime = getPrewarmedRtcRuntime(aLaunchInfo);
        if (runtime == 0)
        {
            RtcPluginInterface* rtcInterface = 0;
            plugins_t::iterator pluginIter = mPlugins.find(aLaunchInfo.mRtcType);

            if (pluginIter != mPlugins.end())
            {
                rtcInterface = pluginIter->second->mInterface;
            }
            else
            {
                try
                {
                    std::string pluginName = "javacaptain_rtc_" + aLaunchInfo.mRtcType;

                    std::auto_ptr<java::util::DynamicLibLoader>
                    loader(new java::util::DynamicLibLoader(pluginName.c_str()));

                    java::captain::RtcPluginInterface*(*getRtcPluginFunc)() =
                        (java::captain::RtcPluginInterface*(*)())
                        loader->getFunction("getRtcPlugin");

                    if (getRtcPluginFunc)
                    {
                        rtcInterface = getRtcPluginFunc();
                        if (rtcInterface)
                        {
                            mPlugins.insert(std::make_pair(aLaunchInfo.mRtcType,
                                                           new rtcPluginData(rtcInterface, loader)));
                        }
                    }
                }
                catch (java::util::LibraryLoaderException& ex)
                {
                    LOG2(EJavaCaptain, EError, "Rtc::getRtcPlugin(%s) failed due: %s",
                         aLaunchInfo.mRtcType.c_str(), ex.toString().c_str());
                }
            }

            if (rtcInterface)
            {
                runtime = rtcInterface->createNewRuntimeInstance(aLaunchInfo.mUID, mCore);
                if (runtime)
                {
                    mRuntimes.insert(std::make_pair(aLaunchInfo.mUID, runtime));
                }
            }
        }
    }
    else
    {
        runtime = rtIter->second;
    }

    return runtime;
}

RtcRuntimeInterface* Rtc::getPrewarmedRtcRuntime(const rtcLaunchInfo& aLaunchInfo)
{
    JELOG2(EJavaCaptain);
    RtcRuntimeInterface* runtime = 0;

    if (mSupportPreWarming &&
            aLaunchInfo.mRtcType == "midp" &&
            aLaunchInfo.mLaunchType == RTC_LAUNCH_TYPE_NORMAL_C)
    {
        // Use prewarming only for normal launches and leave out push,
        // debug, auto invocation etc.
        bool createNewPrewarmProcess = false;

        // Then check if there exists prewarmed instance.
        runtimes_t::iterator rtIter = mRuntimes.find(PREWARM_UID);
        if (rtIter != mRuntimes.end())
        {
            if (rtIter->second->isRunning())
            {
                // Prewarmed instance found, using it
                ILOG(EJavaCaptain,  "Rtc::getPrewarmedRtcRuntime() -Prewarmed instance found, launching within");
                runtime = rtIter->second;

                // Removed/add runtime instance with a correct UID to collection
                mRuntimes.erase(rtIter);
                mRuntimes.insert(std::make_pair(aLaunchInfo.mUID, runtime));
                ILOG(EJavaCaptain, "Rtc::getPrewarmedRtcRuntime() - Asking for new prewarm instance - previous was taken into use");
                createNewPrewarmProcess = true;
            }
            else
            {
                if (-1 == rtIter->second->pid())
                {
                    ILOG(EJavaCaptain, "Rtc::getPrewarmedRtcRuntime() - Prewarmed instance found but it has been deleted.");
                    // Remove the previous instance.
                    delete rtIter->second;
                    mRuntimes.erase(rtIter);
                    createNewPrewarmProcess = true;
                }
                else
                {
                    ILOG(EJavaCaptain, "Rtc::getPrewarmedRtcRuntime() - Prewarmed instance found but it is not ready yet");
                }
            }
        }
        else
        {
            ILOG(EJavaCaptain, "Rtc::getPrewarmedRtcRuntime() - New prewarm instance - didn't exist at all!");
            createNewPrewarmProcess = true;
        }
        if (createNewPrewarmProcess)
        {
            // Create new Prewarmed process.
            launchPrewarm();
        }
    }
    return runtime;
}

void Rtc::launchPrewarm()
{
    mSupportPreWarming = true;
    launch(rtcLaunchInfo(PREWARM_UID, RTC_LAUNCH_TYPE_PREWARM_C,
                         RTC_LAUNCH_RUNTIME_MIDP_C));
}

bool Rtc::isPrewarmSupported()
{
    return mSupportPreWarming;
}

void Rtc::deleteRuntime(const Uid& aUid)
{
    JELOG4(EJavaCaptain, EInfoHeavyLoad);

    runtimes_t::iterator rtIter = mRuntimes.find(aUid);
    if (rtIter != mRuntimes.end())
    {
        delete rtIter->second;
        mRuntimes.erase(rtIter);
    }
}

// Checks from Javastorage if there are installed MIDlets
bool Rtc::isThereInstalledMidlets() const
{
    bool result = false;
    using namespace java::storage;

    JavaStorageEntry idAttribute;
    idAttribute.setEntry(ID, L"");

    JavaStorageApplicationEntry_t findSuiteQuery;
    findSuiteQuery.insert(idAttribute);

    JavaStorageApplicationList_t foundMidletSuites;
    std::auto_ptr<JavaStorage> jsAptr(JavaStorage::createInstance());

    try
    {
        ILOG(EJavaCaptain, "Rtc::isThereInstalledMidlets() - searching for installed suites");
        jsAptr->open(JAVA_DATABASE_NAME);
        jsAptr->search(APPLICATION_PACKAGE_TABLE, findSuiteQuery, foundMidletSuites);
    }
    catch (JavaStorageException& jse)
    {
        ELOG1(EJavaCaptain, "Rtc::isThereInstalledMidlets() - Failed to search from JavaStorage: %s ",
              jse.toString().c_str());
    }
    findSuiteQuery.clear();

    if (foundMidletSuites.size() > 0)
    {
        ILOG(EJavaCaptain, "Rtc::isThereInstalledMidlets() - found installed suites");
        result = true;
    }
    foundMidletSuites.clear();

    // Close connection
    try
    {
        jsAptr->close();
    }
    catch (JavaStorageException& jse)
    {
        ELOG1(EJavaCaptain, "Rtc::isThereInstalledMidlets() - JavaStorage close failed: %s ",
              jse.toString().c_str());
    }

    return result;
}


} // namespace captain
} // namespace java