--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/javaruntimes/installer/starterdll/src/main.cpp Tue Apr 27 16:30:29 2010 +0300
@@ -0,0 +1,397 @@
+/*
+* Copyright (c) 2008-2010 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: Main program for the JavaInstaller process
+*
+*/
+
+
+#include <unistd.h>
+#include <string.h>
+// next three includes are for semaphores
+#include <sys/sem.h>
+#include <sys/stat.h>
+#include <errno.h>
+
+#ifdef __SYMBIAN32__
+#include "javauids.h"
+#endif
+#include "comms.h"
+#include "commsclientendpoint.h"
+#include "exceptionbase.h"
+#include "javacommonutils.h"
+#include "javaoslayer.h"
+#include "jvmstarter.h"
+#include "logger.h"
+#include "runtimeexception.h"
+#include "runtimestarterutils.h"
+
+using namespace java::comms;
+using namespace java::runtime;
+using namespace java::util;
+
+const wchar_t* const INSTALLER_MAIN_CLASS =
+ L"com.nokia.mj.impl.installer.Installer";
+
+int startJvm(int argc, char *argv[]);
+
+#ifdef __WINS__
+#include <e32ldr.h>
+#endif //__WINS__
+
+// random small int value
+#define SEM_KEY 1823 // codescanner::magicnumbers
+// same as Symbian KErrAlreadyExists
+#define INSTALLER_ALREADY_RUNNING -11 // codescanner::magicnumbers
+// semaphore operation error, same as Symbian KErrLocked
+#define SEMAPHORE_ERROR -22 // codescanner::magicnumbers
+// Ubuntu semaphore headers do not define these contants
+#ifndef SEM_R
+#define SEM_R S_IRUSR
+#endif
+#ifndef SEM_A
+#define SEM_A S_IWUSR
+#endif
+
+#ifndef __SYMBIAN32__
+extern "C"
+#endif //__SYMBIAN32__
+
+int dllMain(int argc, char *argv[])
+{
+ JELOG(EJavaRuntime, "INSTALLER main()");
+ JavaOsLayer::startUpTrace("INSTALLER main() start", -1, -1);
+
+#ifdef __SYMBIAN32__
+
+ // Only processes with TrustedUI capability are allowed to start
+ // Java Installer in S60 device (e.g. TCK runner, preinstaller,
+ // appconverter, javacleaner, AppInstUI,javainstaller,
+ // javapostupdater and SDK Debug Agent)
+
+ TSecureId creatorSecId(User::CreatorSecureId());
+ if (!User::CreatorHasCapability(ECapabilityTrustedUI))
+ {
+ ELOG1(EJavaRuntime,
+ "INSTALLER main: Process %x is not allowed to launch Java Installer, since it is missing TrustedUI capability.",
+ creatorSecId.iId);
+ return KErrPermissionDenied;
+ }
+
+#endif
+
+#ifdef __SYMBIAN32__
+ _LIT(KJavaInstallerProcessName, "JavaInstaller");
+ _LIT(KJavaInstallerThreadName, "JavaInstallerMainThread");
+ // Rename installer process and main thread.
+ TInt err = User::RenameProcess(KJavaInstallerProcessName);
+ if (KErrNone != err)
+ {
+ ELOG1(EJavaRuntime,
+ "INSTALLER main: cannot change process name to JavaInstaller, err %d", err);
+ }
+ err = User::RenameThread(KJavaInstallerThreadName);
+ if (KErrNone != err)
+ {
+ ELOG1(EJavaRuntime,
+ "INSTALLER main: cannot change main thread name to "
+ "JavaInstallerMainThread, err %d", err);
+ }
+#endif //__SYMBIAN32__
+
+ // Allow running only one instance of this process at same time.
+
+ // Because of S60 semop implementation (semop waits even if
+ // IPC_NOWAIT has been specified) -> use semaphore access control
+ // to limit number of instances to one.
+
+#ifdef __SYMBIAN32__
+ int perm = 0x1FF; // all permissions to every process
+#else
+ // Create one System V / XSI semaphore accessible only by this process
+ int perm = (SEM_R | SEM_A);
+#endif //__SYMBIAN32__
+ int semid = semget(SEM_KEY, 1, IPC_CREAT | perm);
+
+ // Increase process instance count by one.
+ // This increase is automatically undone when this process exits.
+ sembuf st = {0, 1, SEM_UNDO | IPC_NOWAIT};
+ int ret = semop(semid, &st, 1);
+ if (-1 == ret)
+ {
+ ELOG(EJavaRuntime, "INSTALLER main: semop failed");
+ JavaOsLayer::startUpTrace("INSTALLER main() end", -1, -1);
+ return SEMAPHORE_ERROR;
+ }
+
+ // Get the current instance count
+ ret = semctl(semid, 0, GETVAL);
+ if (-1 == ret)
+ {
+ ELOG(EJavaRuntime, "INSTALLER main: semctl failed");
+ JavaOsLayer::startUpTrace("INSTALLER main() end", -1, -1);
+ return SEMAPHORE_ERROR;
+ }
+ else if (ret > 1)
+ {
+ WLOG(EJavaRuntime, "Installer already running. Exiting.");
+ JavaOsLayer::startUpTrace("INSTALLER main() end", -1, -1);
+ return INSTALLER_ALREADY_RUNNING;
+ }
+
+ int result = -1;
+ try
+ {
+ // Start the VM.
+ result = startJvm(argc, argv);
+ }
+ catch (RuntimeException& e)
+ {
+ ELOG1(EJavaRuntime, "INSTALLER main() RuntimeException caught: %s ",
+ e.toString().c_str());
+ }
+ catch (ExceptionBase& e)
+ {
+ ELOG1(EJavaRuntime, "INSTALLER main() ExceptionBase caught: %s ",
+ e.toString().c_str());
+ }
+ catch (std::exception& e)
+ {
+ ELOG1(EJavaRuntime, "INSTALLER main() Exception %s caught", e.what());
+ }
+
+ // Try to remove the semaphore, ignore possible error
+ ret = semctl(semid, 0, IPC_RMID);
+ if (-1 == ret)
+ {
+ ELOG1(EJavaRuntime, "INSTALLER main() Remove semaphore failed, err %d",
+ errno);
+ }
+
+ LOG1(EJavaRuntime, EInfo, "INSTALLER main() exit = %d", result);
+ JavaOsLayer::startUpTrace("INSTALLER main() end", -1, -1);
+ return result;
+}
+
+#ifdef __SYMBIAN32__
+/**
+ * Start Java Captain process
+ */
+TInt startJavaCaptain()
+{
+ // Start 'systemams.exe' in S60 5.0 (it will start javacaptain) and
+ // 'javacaptain.exe' in 9.2 and later
+
+#ifdef RD_JAVA_S60_RELEASE_5_0_IAD
+ _LIT(KJavaCaptainExe, "systemams.exe");
+#else
+ _LIT(KJavaCaptainExe, "javacaptain.exe");
+#endif
+ _LIT(KJavaCaptainArg, "");
+ RProcess proc;
+ int err = proc.Create(KJavaCaptainExe, KJavaCaptainArg);
+ if (err == KErrNone)
+ {
+ proc.Resume();
+#ifdef RD_JAVA_S60_RELEASE_5_0_IAD
+ LOG(EJavaRuntime, EInfo,
+ "InstallerStarter: startJavaCaptain systemams.exe was started ok");
+#else
+ LOG(EJavaRuntime, EInfo,
+ "InstallerStarter: startJavaCaptain javacaptain.exe was started ok");
+#endif
+
+ // Wait 3 seconds so that Java Captain has time to start
+ User::After(3000000);
+ }
+ else
+ {
+#ifdef RD_JAVA_S60_RELEASE_5_0_IAD
+ ELOG1(EJavaRuntime,
+ "InstallerStarter: startJavaCaptain start systemams.exe failed: %d", err);
+#else
+ ELOG1(EJavaRuntime,
+ "InstallerStarter: startJavaCaptain start javacaptain.exe failed: %d", err);
+#endif
+ }
+
+ proc.Close();
+ return err;
+}
+#endif
+
+int startJvm(int argc, char *argv[])
+{
+ // Create instance of RuntimeStarterUtils for thread supervisioning.
+ std::auto_ptr<RuntimeStarterUtils> starterUtils(new RuntimeStarterUtils()); // codescanner::nonleavenew
+ starterUtils->startThreadSupervisor();
+
+ // Create Comms endpoint for JavaCaptain.
+ std::auto_ptr<CommsClientEndpoint> comms(
+ new CommsClientEndpoint(L"InstallerJavaCaptain"));
+ int result = comms->connect(IPC_ADDRESS_JAVA_CAPTAIN_C);
+
+#ifdef __SYMBIAN32__
+ if (KErrNotFound == result)
+ {
+ ELOG(EJavaRuntime,
+ "InstallerStarter: Java Captain was not running. Trying to restart it.");
+
+ // Java Captain is not running, try to start it
+ result = startJavaCaptain();
+ if (KErrNone == result)
+ {
+ result = comms->connect(IPC_ADDRESS_JAVA_CAPTAIN_C);
+ }
+ }
+#endif
+
+ if (result != 0)
+ {
+ ELOG1(EJavaRuntime,
+ "InstallerStarter: Connection to JavaCaptain failed: Reason = %d",
+ result);
+ }
+
+ // Another Comms Endpoint for TCK Runner or preinstaller
+ std::auto_ptr<CommsClientEndpoint> commsPoll;
+
+ // If installer is started in 'poll' mode, connect also to TCK Runner,
+ // preinstaller or javaappconverter. Command line is
+ // 'javainstaller poll -address=(tck|preinstall|convert) [options]'
+ const int minArgCount = 3;
+ if (argc >= minArgCount)
+ {
+ if (!strcmp(argv[1], "poll")) // codescanner::accessArrayElementWithoutCheck2
+ {
+ int connected = 0;
+ // next argument must be -address=(tck|preinstaller|convert)
+ char* val = strpbrk(argv[2], "="); // codescanner::accessArrayElementWithoutCheck2
+ if (val != 0)
+ {
+ val++;
+ int commsAddress = 0;
+ if (!strcmp(val, "tck"))
+ {
+ commsAddress = IPC_ADDRESS_JAVA_TCK_RUNNER_C;
+ }
+ else if (!strcmp(val, "preinstall"))
+ {
+ commsAddress = IPC_ADDRESS_JAVA_PREINSTALLER_C;
+ }
+ else if (!strcmp(val, "convert"))
+ {
+ commsAddress = IPC_ADDRESS_JAVA_APPCONVERTER_C;
+ }
+ else if (!strcmp(val, "debugapi"))
+ {
+ commsAddress = IPC_ADDRESS_JAVA_DEBUGAPI_C;
+ }
+ else
+ {
+ ELOG1(EJavaRuntime, "InstallerStarter: unknown comms "
+ "poll address %s", val);
+ }
+
+ if (0 != commsAddress)
+ {
+ commsPoll.reset(new CommsClientEndpoint(L"InstallerCommsPoll")); // codescanner::nonleavenew
+ result = commsPoll->connect(commsAddress);
+ if (0 != result)
+ {
+ ELOG3(EJavaRuntime,
+ "InstallerStarter: Connection to %s (address %d) failed: Reason = %d",
+ val, commsAddress, result);
+ }
+ else
+ {
+ connected = 1;
+ }
+ }
+ }
+ else
+ {
+ ELOG1(EJavaRuntime, "InstallerStarter: No valid -address argument. Arg is %s",
+ argv[2]); // codescanner::accessArrayElementWithoutCheck2
+ }
+
+ // Installer cannot be started in 'poll' mode unless connection is ok
+ if (!connected)
+ {
+ ELOG(EJavaRuntime,
+ "InstallerStarter: Installer cannot be started in poll mode because connection to initiator fails.");
+ std::string errorStr("Installer cannot start in poll mode");
+ throw RuntimeException(errorStr, __FILE__, __FUNCTION__, __LINE__);
+ }
+ }
+ }
+
+ // Create starter for starting the JVM
+ std::auto_ptr<JvmStarter>
+ jvm(JvmStarter::getJvmStarterInstance(JvmStarter::CDC,
+ L"Installer"));
+
+ // Set the debugging features available provided by the captain.
+ starterUtils->enableDevelopmentFeatures(*jvm.get());
+
+ // Set the old heap size to 512K
+ const int oldHeapSize = 512;
+ jvm->overrideOldHeapSize(oldHeapSize);
+
+ jvm->enableThreadDumping();
+
+ jvm->setMainClass(INSTALLER_MAIN_CLASS);
+
+ jvm->appendSystemProperty(L"-Dcom.nokia.rt.port=installer");
+
+ for (int i = 1; i < argc; ++i)
+ {
+ jvm->appendApplicationArgument(
+ JavaCommonUtils::utf8ToWstring(argv[i])); // codescanner::accessArrayElementWithoutCheck2
+ }
+
+#ifdef RD_JAVA_INSTALLERUI_ENABLED
+ jvm->appendSystemProperty(
+ L"-Dcom.nokia.mj.impl.installer.ui="
+ L"com.nokia.mj.impl.installer.ui.eswt.InstallerUiEswt");
+#endif
+
+ std::wstring extendedBootClassPath;
+ // This call is platform dependent.
+ starterUtils->getExtBootClassPath(extendedBootClassPath);
+ if (extendedBootClassPath.length() > 0)
+ {
+ // Provide the bootclasspath also as a system propery
+ // to be used for security extensions.
+ std::wstring addOnList(L"-Dcom.nokia.mj.addon.list=");
+ addOnList += extendedBootClassPath;
+ jvm->appendSystemProperty(addOnList);
+ }
+
+ // Start the JVM.
+ return jvm->startJvm();
+}
+
+#ifdef __SYMBIAN32__
+#include "javasymbianoslayer.h"
+
+EXPORT_C FuncPtr findDllMethod(const char* funcName)
+{
+ FuncPtr ptr = 0;
+ if (strcmp(funcName, "dllMain") == 0)
+ {
+ ptr = (FuncPtr)dllMain;
+ }
+ return ptr;
+}
+#endif //__SYMBIAN32__