diff -r f5050f1da672 -r 04becd199f91 javaruntimes/standalone/src/javastarterimpl.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/javaruntimes/standalone/src/javastarterimpl.cpp Tue Apr 27 16:30:29 2010 +0300 @@ -0,0 +1,596 @@ +/* +* 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 +#include +#include +#include + +#include "javacoreui.h" +#include "javacoreuiparams.h" +#include "runtimestarterutils.h" + +#include "dynamiclibloader.h" +#include "javacommonutils.h" +#include "javaoslayer.h" +#include "logger.h" + +#ifdef __SYMBIAN32__ +#include "javasymbianoslayer.h" +#else // __SYMBIAN32__ +#include + +#endif // __SYMBIAN32__ + +#include "runtimeexception.h" + +#include "javastarter.h" +#include "javastarterimpl.h" + + +using namespace java::runtime; +using namespace java::util; +using namespace java::ui; +using namespace java; + +const wchar_t* const NATIVE_RUNTIME_MAIN_CLASS = L"com.nokia.mj.impl.rt.midp.Main"; +const wchar_t* const MAIN_RUNTIME_MAIN_CLASS = L"com.nokia.mj.impl.rt.main.Main"; + +const wchar_t* const ARG_CONF = L"-conf="; +const wchar_t* const CONF_CDC = L"cdc"; +const wchar_t* const CONF_FOUNDATION = L"foun"; +const wchar_t* const CONF_CLDC = L"cldc"; + +const wchar_t* const ARG_PROFILE = L"-profile="; +const wchar_t* const PROFILE_MAIN = L"main"; +const wchar_t* const PROFILE_STANDALONE_MIDLET = L"standalonemidlet"; +const wchar_t* const ARG_STANDALONE = L"-standalone"; + +const wchar_t* const ARG_ORIENTATION = L"-Dcom.nokia.startup.arg.orientation="; +const wchar_t* const ORIENTATION_PORTRAIT = L"portrait"; +const wchar_t* const ORIENTATION_LANDSCAPE = L"landscape"; + +const wchar_t* const ARG_START_SCREEN = L"-Dcom.nokia.startup.arg.startscreen="; +const wchar_t* const START_SCREEN_DEFAULT = L"default"; +const wchar_t* const START_SCREEN_NO = L"no"; + +const wchar_t* const ARG_JAR = L"-jar"; +const wchar_t* const ARG_JAD = L"-jad"; +const wchar_t* const ARG_CP = L"-cp"; +const wchar_t* const ARG_CLASSPATH = L"-classpath"; +const wchar_t* const ARG_MAIN = L"-main"; +const wchar_t* const ARG_UID = L"-uid"; +const wchar_t* const ARG_ROOT_PATH = L"-rootpath"; +const wchar_t* const ARG_HANDLE = L"-handle"; +const wchar_t* const ARG_END = L"-interalArgEnd"; +const wchar_t* const ARG_EMPTY = L""; + + + +OS_EXPORT int java::start(int argc, const char** argv) +{ + JELOG2(EJavaRuntime); + LOG(EJavaRuntime, EInfo, "java::start(1)"); + int result = -1; + try + { + int i = 0; + if (argc > 0 && argv[0][0] != '-') + { + // Check if the first argument is the name of the exe. If so, skip it. + std::string firstArg(argv[0]); + std::transform(firstArg.begin(), firstArg.end(), + firstArg.begin(), tolower); + size_t pos = firstArg.rfind(".exe"); + bool endsWithExe = (pos != std::string::npos) && + (pos == (firstArg.length() - 4)); + if (endsWithExe) + { + // It did end with .exe so ignoring the first argument. + i = 1; + } + + } + + std::list args; + for (; i < argc; ++i) + { + args.push_back(JavaCommonUtils::utf8ToWstring(argv[i])); + } + + std::auto_ptr javaStarter(new JavaStarterImpl(args)); + result = javaStarter->start(); + } + catch (RuntimeException& e) + { + ELOG1(EJavaRuntime, "java::start RuntimeException catched: %s ", + e.toString().c_str()); + } + + catch (ExceptionBase& e) + { + ELOG1(EJavaRuntime, "java::start ExceptionBase catched: %s ", + e.toString().c_str()); + } + + catch (std::exception& e) + { + ELOG1(EJavaRuntime, "java::start Exception %s catched", e.what()); + } + + LOG1(EJavaRuntime, EInfo, "java::start with status %d", result); + return result; +} + +OS_EXPORT int java::start(const char* fileName) +{ + JELOG2(EJavaRuntime); + LOG(EJavaRuntime, EInfo, "java::start(2)"); + int result = -1; + try + { + std::list args; + JavaStarterImpl::getArgsFromFile(fileName, args); + std::auto_ptr javaStarter(new JavaStarterImpl(args)); + result = javaStarter->start(); + } + catch (RuntimeException& e) + { + ELOG1(EJavaRuntime, "java::start(2) RuntimeException catched: %s ", + e.toString().c_str()); + } + + catch (ExceptionBase& e) + { + ELOG1(EJavaRuntime, "java::start(2) ExceptionBase catched: %s ", + e.toString().c_str()); + } + + catch (std::exception& e) + { + ELOG1(EJavaRuntime, "java::start(2) Exception %s catched", e.what()); + } + + LOG1(EJavaRuntime, EInfo, "java::start(2) exited with status %d", result); + + return result; +} + +JavaStarterImpl::JavaStarterImpl(const std::list& args): + mJvmStarter(0), + mRuntimeStarterUtils(0), + mOriginalArgs(args), + mShudownOk(false), + mIsMainApp(true), + mConfiguration(JvmStarter::UNDEFINED) + +{ + JELOG2(EJavaRuntime); + mRuntimeStarterUtils = new RuntimeStarterUtils(); +} + +JavaStarterImpl::~JavaStarterImpl() +{ + JELOG2(EJavaRuntime); + delete mJvmStarter; + mJvmStarter = 0; + + delete mRuntimeStarterUtils; + mRuntimeStarterUtils = 0; +} + +int JavaStarterImpl::start() +{ + JELOG2(EJavaRuntime); + + // Start the thread supervisor for noticing crashes. + mRuntimeStarterUtils = new RuntimeStarterUtils(); // codescanner::nonleavenew + mRuntimeStarterUtils->startThreadSupervisor(); + + // Parse args that starts with '-'. + parseFlags(); + + // Create JVM starter for selected runtime. + createJvmStarter(); + + // Solves the UID of the application and sets the root path. + setUidAndRootPath(); + + // Create the start screen and start it if needed. + std::auto_ptr coreUiLoader; + CoreUi& coreUi = CoreUi::getUiInstance(coreUiLoader); + if (mUiParams.getScreenMode() != NO_START_SCREEN) + { + LOG(EJavaRuntime, EInfo, "StartUI"); + coreUi.start(mAppUid, &mUiParams); + LOG(EJavaRuntime, EInfo, "StartUI ok"); + } + + // Sets the -jar, -jad, -cp (or -classpath) args if were provided. + // Also a main class is set if needed. + handleJadJarCpArgs(); + + // Adds a handle to this object in order to enable the callbacks + // from runtime. + addHandle(); + + // Add the application arguments if provided. + addApplicationArgs(); + +#ifndef RD_JAVA_UI_QT + // In Java 2.x we are using legacy UI. + mJvmStarter->appendSystemProperty(L"-Dcom.nokia.legacy.support=symbian"); +#endif //RD_JAVA_HYBRID + + int result = mJvmStarter->startJvm(); + CoreUi::releaseUi(coreUiLoader); + if (mMonitor.get()) + { + mShudownOk = true; + LOG(EJavaRuntime, EInfo, "Notifying."); + mMonitor->notify(); + } + + LOG1(EJavaRuntime, EInfo, "Native exited with status %d", result); + + return result; + +} + +void JavaStarterImpl::parseFlags() +{ + JELOG2(EJavaRuntime); + for (mOriginalArgsIter = mOriginalArgs.begin(); + (mOriginalArgsIter != mOriginalArgs.end() && mOriginalArgsIter->at(0) == '-'); + ++mOriginalArgsIter) + { + LOG1(EJavaRuntime, EInfo, "Handling flags %S", mOriginalArgsIter->c_str()); + if (*mOriginalArgsIter == ARG_JAR) + { + storeNextArgument(mJarFile); + LOG1(EJavaRuntime, EInfo, "Jar file is %S", mJarFile.c_str()); + } + else if (*mOriginalArgsIter == ARG_JAD) + { + storeNextArgument(mJadFile); + LOG1(EJavaRuntime, EInfo, "Jad file is %S", mJadFile.c_str()); + } + else if (*mOriginalArgsIter == ARG_CP || *mOriginalArgsIter == ARG_CLASSPATH) + { + storeNextArgument(mClassPath); + LOG1(EJavaRuntime, EInfo, "Classpath is %S", mClassPath.c_str()); + } + else if (mOriginalArgsIter->find(ARG_CONF) == 0) + { + setConfigration(getArgValue(*mOriginalArgsIter)); + } + else if (mOriginalArgsIter->find(ARG_PROFILE) == 0) + { + setProfile(getArgValue(*mOriginalArgsIter)); + } + else if (mOriginalArgsIter->find(ARG_ORIENTATION) == 0) + { + setOrientation(getArgValue(*mOriginalArgsIter)); + } + else if (mOriginalArgsIter->find(ARG_START_SCREEN) == 0) + { + setStartScreen(getArgValue(*mOriginalArgsIter)); + } + else + { + mFlagArgs.push_back(*mOriginalArgsIter); + } + } +} + +void JavaStarterImpl::setConfigration(const std::wstring& conf) +{ + JELOG2(EJavaRuntime); + + if (conf == CONF_CLDC) + { + LOG(EJavaRuntime, EInfo, "Setting conf to CLDC"); + mConfiguration = JvmStarter::CLDC; + } + else if (conf == CONF_CDC) + { + LOG(EJavaRuntime, EInfo, "Setting conf to CDC"); + mConfiguration = JvmStarter::CDC; + } + else if (conf == CONF_FOUNDATION) + { + LOG(EJavaRuntime, EInfo, "Setting conf to FOUNDATION"); + mConfiguration = JvmStarter::FOUNDATION; + } + else + { + ELOG1(EJavaRuntime, "Unknown conf %S", conf.c_str()); + } +} + +void JavaStarterImpl::setProfile(const std::wstring& profile) +{ + JELOG2(EJavaRuntime); + + if (profile == PROFILE_STANDALONE_MIDLET) + { + LOG(EJavaRuntime, EInfo, "Setting profile to be standalone MIDlet"); + mIsMainApp = false; + } + else if (profile == PROFILE_MAIN) + { + LOG(EJavaRuntime, EInfo, "Setting profile to be main"); + mIsMainApp = true; + } + else + { + ELOG1(EJavaRuntime, "Unknown profile %S", profile.c_str()); + } +} + +void JavaStarterImpl::setOrientation(const std::wstring& orientation) +{ + JELOG2(EJavaRuntime); + + if (orientation == ORIENTATION_PORTRAIT) + { + LOG(EJavaRuntime, EInfo, "Setting orientation to portrait"); + mUiParams.setOrientation(PORTRAIT); + } + else if (orientation == ORIENTATION_LANDSCAPE) + { + LOG(EJavaRuntime, EInfo, "Setting orientation to landscape"); + mUiParams.setOrientation(LANDSCAPE); + } + else + { + ELOG1(EJavaRuntime, "Unknown orientation %S", orientation.c_str()); + } +} + +void JavaStarterImpl::setStartScreen(const std::wstring& startscreen) +{ + JELOG2(EJavaRuntime); + + if (startscreen == START_SCREEN_DEFAULT) + { + LOG(EJavaRuntime, EInfo, "Setting default start screen"); + mUiParams.setScreenMode(DEFAULT_START_SCREEN); + } + else if (startscreen == START_SCREEN_NO) + { + LOG(EJavaRuntime, EInfo, "Setting default start screen"); + mUiParams.setScreenMode(NO_START_SCREEN); + } + else + { + mUiParams.setScreenMode(USER_DEFINED_SCREEN); + mUiParams.setImagePath(startscreen); + LOG1(EJavaRuntime, EInfo, "Setting start screen from file %S", startscreen.c_str()); + } +} + +void JavaStarterImpl::createJvmStarter() +{ + JELOG2(EJavaRuntime); + if (mIsMainApp) + { + // We are starting main app. + if (mConfiguration == JvmStarter::UNDEFINED) + { + // If the user has not explicitely set the conf, CDC is default. + mConfiguration = JvmStarter::CDC; + } + mJvmStarter = JvmStarter::getJvmStarterInstance(mConfiguration, + PROFILE_MAIN); + mJvmStarter->appendSystemProperty(L"-Dcom.nokia.rt.port=main"); + mJvmStarter->setMainClass(MAIN_RUNTIME_MAIN_CLASS); + } + else + { + // We are starting standalone MIDlet. + if (mConfiguration == JvmStarter::UNDEFINED) + { + // If the user has not explicitely set the conf, CLDC is default. + mConfiguration = JvmStarter::CLDC; + } + mJvmStarter = JvmStarter::getJvmStarterInstance(mConfiguration, + PROFILE_STANDALONE_MIDLET); + mJvmStarter->appendSystemProperty(L"-Dcom.nokia.rt.port=midp"); + mJvmStarter->setMainClass(NATIVE_RUNTIME_MAIN_CLASS); + mJvmStarter->appendApplicationArgument(ARG_STANDALONE); + mJvmStarter->appendApplicationArgument(ARG_EMPTY); + } +} + +void JavaStarterImpl::handleJadJarCpArgs() +{ + JELOG2(EJavaRuntime); + if (mJarFile.length() > 0) + { + // The -jar argument was provided. Appending it to classpath and + // passing that as an argument to the runtime. + mJvmStarter->appendClassPath(mJarFile); + mJvmStarter->appendApplicationArgument(ARG_JAR); + mJvmStarter->appendApplicationArgument(mJarFile); + } + else + { + // The -jar argument was not provided. We assume that the next argument + // is the main class of the application in case of main app. + // passing that as an argument to the runtime. + if (mIsMainApp && mOriginalArgsIter != mOriginalArgs.end()) + { + mJvmStarter->appendApplicationArgument(ARG_MAIN); + mJvmStarter->appendApplicationArgument(*mOriginalArgsIter); + ++mOriginalArgsIter; + } + } + + if (mJadFile.length() > 0) + { + mJvmStarter->appendApplicationArgument(ARG_JAD); + mJvmStarter->appendApplicationArgument(mJadFile); + } + + if (mClassPath.length() > 0) + { + mJvmStarter->appendClassPath(mClassPath); + } +} + + +void JavaStarterImpl::setUidAndRootPath() +{ + JELOG2(EJavaRuntime); +#ifdef __SYMBIAN32__ + TUidToUid(RProcess().Type()[2], mAppUid); + LOG1(EJavaRuntime, EInfo, "PROCESS UID %S", mAppUid.toString().c_str()); + +// TUid tuid = uidType[1]; + TUid tuid(TUid::Uid(0x10005902)); +// TUidToUid(tuid, mAppUid); +// LOG1(EJavaRuntime, EInfo, "TEMP UID %S", mAppUid.toString().c_str()); +#else // __SYMBIAN32__ +// mAppUid = Uid(L"java_standalone"); + +#endif // __SYMBIAN32__ + + mJvmStarter->appendApplicationArgument(ARG_UID); + mJvmStarter->appendApplicationArgument(mAppUid.toString()); + + std::wstring rooPath; +#ifdef __SYMBIAN32__ + Uid uid; + TUidToUid(RProcess().SecureId(), uid); + rooPath += L"c:\\private\\"; + rooPath += uid.toString().substr(1,8); + rooPath += L"\\"; +#else // __SYMBIAN32__ + rooPath += L"./"; +#endif // __SYMBIAN32__ + mJvmStarter->appendApplicationArgument(ARG_ROOT_PATH); + mJvmStarter->appendApplicationArgument(rooPath); +} + +void JavaStarterImpl::addHandle() +{ + JELOG2(EJavaRuntime); + // Provide access to this object by Java peer via delivering a pointer + // to this object. + mJvmStarter->appendApplicationArgument(ARG_HANDLE); + MidpStarterInternalSupport* internalSupport = this; + int handle = reinterpret_cast(internalSupport); + mJvmStarter->appendApplicationArgument(JavaCommonUtils::intToWstring(handle)); +} + +void JavaStarterImpl::addApplicationArgs() +{ + JELOG2(EJavaRuntime); + // Adding end mark of the runtime arguments. + mJvmStarter->appendApplicationArgument(ARG_END); + + // What is left in the argument list is considered to be application arguments. + + for (; mOriginalArgsIter != mOriginalArgs.end(); ++mOriginalArgsIter) + { + LOG1(EJavaRuntime, EInfo, "Adding APP args %S", mOriginalArgsIter->c_str()); + mJvmStarter->appendApplicationArgument(*mOriginalArgsIter); + } +} + +void JavaStarterImpl::storeNextArgument(std::wstring& arg) +{ + ++mOriginalArgsIter; + if (mOriginalArgsIter != mOriginalArgs.end()) + { + arg = *mOriginalArgsIter; + } +} + +std::wstring JavaStarterImpl::getArgValue(const std::wstring& arg) +{ + JELOG2(EJavaRuntime); + return arg.substr(arg.find(L"=") + 1); +} + + +void JavaStarterImpl::getArgsFromFile(const char* file, std::list& args) +{ + std::ifstream argsFile; + try + { + argsFile.open(file, std::ifstream::in); + + std::string line; + + while (std::getline(argsFile, line)) + { + size_t endln = line.find_last_not_of("\r\n"); + if (endln != std::string::npos) + { + line.erase(endln+1); + } + args.push_back(JavaCommonUtils::utf8ToWstring(line.c_str())); + } + } + catch (std::exception& e) + { + LOG2(EJavaRuntime, EInfo, "Not able to read from file %s. Error %s", + file, e.what()); + } + argsFile.close(); +} + +void* JavaStarterImpl::ensureExit(void* ptr) +{ + JELOG2(EUtils); +#ifdef __SYMBIAN32__ + RThread().SetPriority(EPriorityMore); +#endif // __SYMBIAN32__ + JavaStarterImpl* starter = reinterpret_cast(ptr); + LOG(EJavaRuntime, EInfo, "Starting to wait for the shutdown."); + starter->mMonitor->wait(1200); // 1,2 seconds + LOG(EJavaRuntime, EInfo, "woke up from monitor."); + if (!starter->mShudownOk) + { + LOG(EJavaRuntime, EInfo, "Killing process."); +#ifdef __SYMBIAN32__ + RProcess().Kill(0); +#else + kill(getpid(), SIGTERM); +#endif // __SYMBIAN32__ + } + LOG(EJavaRuntime, EInfo, "Not killing process."); + return 0; +} + +void JavaStarterImpl::closeRuntimeInd() +{ + JELOG2(EJavaRuntime); + LOG(EJavaRuntime, EInfo, "Starter got close indication from JVM"); + pthread_t tid; + mMonitor.reset(Monitor::createMonitor()); + pthread_create(&tid, 0, ensureExit, this); +} + +void JavaStarterImpl::setUids(const java::util::Uid& /*uid*/, + const java::util::Uid& /*suiteUid*/) +{ + JELOG2(EJavaRuntime); + // Not applicable in this case. +}