javaruntimes/installer/starterdll/src/main.cpp
branchRCL_3
changeset 19 04becd199f91
child 23 98ccebc37403
equal deleted inserted replaced
16:f5050f1da672 19:04becd199f91
       
     1 /*
       
     2 * Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Main program for the JavaInstaller process
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 #include <unistd.h>
       
    20 #include <string.h>
       
    21 // next three includes are for semaphores
       
    22 #include <sys/sem.h>
       
    23 #include <sys/stat.h>
       
    24 #include <errno.h>
       
    25 
       
    26 #ifdef __SYMBIAN32__
       
    27 #include "javauids.h"
       
    28 #endif
       
    29 #include "comms.h"
       
    30 #include "commsclientendpoint.h"
       
    31 #include "exceptionbase.h"
       
    32 #include "javacommonutils.h"
       
    33 #include "javaoslayer.h"
       
    34 #include "jvmstarter.h"
       
    35 #include "logger.h"
       
    36 #include "runtimeexception.h"
       
    37 #include "runtimestarterutils.h"
       
    38 
       
    39 using namespace java::comms;
       
    40 using namespace java::runtime;
       
    41 using namespace java::util;
       
    42 
       
    43 const wchar_t* const INSTALLER_MAIN_CLASS =
       
    44     L"com.nokia.mj.impl.installer.Installer";
       
    45 
       
    46 int startJvm(int argc, char *argv[]);
       
    47 
       
    48 #ifdef __WINS__
       
    49 #include <e32ldr.h>
       
    50 #endif //__WINS__
       
    51 
       
    52 // random small int value
       
    53 #define SEM_KEY 1823 // codescanner::magicnumbers
       
    54 // same as Symbian KErrAlreadyExists
       
    55 #define INSTALLER_ALREADY_RUNNING -11 // codescanner::magicnumbers
       
    56 // semaphore operation error, same as Symbian KErrLocked
       
    57 #define SEMAPHORE_ERROR -22 // codescanner::magicnumbers
       
    58 // Ubuntu semaphore headers do not define these contants
       
    59 #ifndef SEM_R
       
    60 #define SEM_R S_IRUSR
       
    61 #endif
       
    62 #ifndef SEM_A
       
    63 #define SEM_A S_IWUSR
       
    64 #endif
       
    65 
       
    66 #ifndef __SYMBIAN32__
       
    67 extern "C"
       
    68 #endif //__SYMBIAN32__
       
    69 
       
    70 int dllMain(int argc, char *argv[])
       
    71 {
       
    72     JELOG(EJavaRuntime, "INSTALLER main()");
       
    73     JavaOsLayer::startUpTrace("INSTALLER main() start", -1, -1);
       
    74 
       
    75 #ifdef __SYMBIAN32__
       
    76 
       
    77     // Only processes with TrustedUI capability are allowed to start
       
    78     // Java Installer in S60 device (e.g. TCK runner, preinstaller,
       
    79     // appconverter, javacleaner, AppInstUI,javainstaller,
       
    80     // javapostupdater and SDK Debug Agent)
       
    81 
       
    82     TSecureId creatorSecId(User::CreatorSecureId());
       
    83     if (!User::CreatorHasCapability(ECapabilityTrustedUI))
       
    84     {
       
    85         ELOG1(EJavaRuntime,
       
    86               "INSTALLER main: Process %x is not allowed to launch Java Installer, since it is missing TrustedUI capability.",
       
    87               creatorSecId.iId);
       
    88         return KErrPermissionDenied;
       
    89     }
       
    90 
       
    91 #endif
       
    92 
       
    93 #ifdef __SYMBIAN32__
       
    94     _LIT(KJavaInstallerProcessName, "JavaInstaller");
       
    95     _LIT(KJavaInstallerThreadName, "JavaInstallerMainThread");
       
    96     // Rename installer process and main thread.
       
    97     TInt err = User::RenameProcess(KJavaInstallerProcessName);
       
    98     if (KErrNone != err)
       
    99     {
       
   100         ELOG1(EJavaRuntime,
       
   101               "INSTALLER main: cannot change process name to JavaInstaller, err %d", err);
       
   102     }
       
   103     err = User::RenameThread(KJavaInstallerThreadName);
       
   104     if (KErrNone != err)
       
   105     {
       
   106         ELOG1(EJavaRuntime,
       
   107               "INSTALLER main: cannot change main thread name to "
       
   108               "JavaInstallerMainThread, err %d", err);
       
   109     }
       
   110 #endif //__SYMBIAN32__
       
   111 
       
   112     // Allow running only one instance of this process at same time.
       
   113 
       
   114     // Because of S60 semop implementation (semop waits even if
       
   115     // IPC_NOWAIT has been specified) -> use semaphore access control
       
   116     // to limit number of instances to one.
       
   117 
       
   118 #ifdef __SYMBIAN32__
       
   119     int perm = 0x1FF; // all permissions to every process
       
   120 #else
       
   121     // Create one System V / XSI semaphore accessible only by this process
       
   122     int perm = (SEM_R | SEM_A);
       
   123 #endif //__SYMBIAN32__
       
   124     int semid = semget(SEM_KEY, 1, IPC_CREAT | perm);
       
   125 
       
   126     // Increase process instance count by one.
       
   127     // This increase is automatically undone when this process exits.
       
   128     sembuf st = {0, 1, SEM_UNDO | IPC_NOWAIT};
       
   129     int ret = semop(semid, &st, 1);
       
   130     if (-1 == ret)
       
   131     {
       
   132         ELOG(EJavaRuntime, "INSTALLER main: semop failed");
       
   133         JavaOsLayer::startUpTrace("INSTALLER main() end", -1, -1);
       
   134         return SEMAPHORE_ERROR;
       
   135     }
       
   136 
       
   137     // Get the current instance count
       
   138     ret = semctl(semid, 0, GETVAL);
       
   139     if (-1 == ret)
       
   140     {
       
   141         ELOG(EJavaRuntime, "INSTALLER main: semctl failed");
       
   142         JavaOsLayer::startUpTrace("INSTALLER main() end", -1, -1);
       
   143         return SEMAPHORE_ERROR;
       
   144     }
       
   145     else if (ret > 1)
       
   146     {
       
   147         WLOG(EJavaRuntime, "Installer already running. Exiting.");
       
   148         JavaOsLayer::startUpTrace("INSTALLER main() end", -1, -1);
       
   149         return INSTALLER_ALREADY_RUNNING;
       
   150     }
       
   151 
       
   152     int result = -1;
       
   153     try
       
   154     {
       
   155         // Start the VM.
       
   156         result = startJvm(argc, argv);
       
   157     }
       
   158     catch (RuntimeException& e)
       
   159     {
       
   160         ELOG1(EJavaRuntime, "INSTALLER main() RuntimeException caught: %s ",
       
   161               e.toString().c_str());
       
   162     }
       
   163     catch (ExceptionBase& e)
       
   164     {
       
   165         ELOG1(EJavaRuntime, "INSTALLER main() ExceptionBase caught: %s ",
       
   166               e.toString().c_str());
       
   167     }
       
   168     catch (std::exception& e)
       
   169     {
       
   170         ELOG1(EJavaRuntime, "INSTALLER main() Exception %s caught", e.what());
       
   171     }
       
   172 
       
   173     // Try to remove the semaphore, ignore possible error
       
   174     ret = semctl(semid, 0, IPC_RMID);
       
   175     if (-1 == ret)
       
   176     {
       
   177         ELOG1(EJavaRuntime, "INSTALLER main() Remove semaphore failed, err %d",
       
   178               errno);
       
   179     }
       
   180 
       
   181     LOG1(EJavaRuntime, EInfo, "INSTALLER main() exit = %d", result);
       
   182     JavaOsLayer::startUpTrace("INSTALLER main() end", -1, -1);
       
   183     return result;
       
   184 }
       
   185 
       
   186 #ifdef __SYMBIAN32__
       
   187 /**
       
   188  *  Start Java Captain process
       
   189  */
       
   190 TInt startJavaCaptain()
       
   191 {
       
   192     // Start 'systemams.exe' in S60 5.0 (it will start javacaptain) and
       
   193     // 'javacaptain.exe' in 9.2 and later
       
   194 
       
   195 #ifdef RD_JAVA_S60_RELEASE_5_0_IAD
       
   196     _LIT(KJavaCaptainExe, "systemams.exe");
       
   197 #else
       
   198     _LIT(KJavaCaptainExe, "javacaptain.exe");
       
   199 #endif
       
   200     _LIT(KJavaCaptainArg, "");
       
   201     RProcess proc;
       
   202     int err = proc.Create(KJavaCaptainExe, KJavaCaptainArg);
       
   203     if (err == KErrNone)
       
   204     {
       
   205         proc.Resume();
       
   206 #ifdef RD_JAVA_S60_RELEASE_5_0_IAD
       
   207         LOG(EJavaRuntime, EInfo,
       
   208             "InstallerStarter: startJavaCaptain systemams.exe was started ok");
       
   209 #else
       
   210         LOG(EJavaRuntime, EInfo,
       
   211             "InstallerStarter: startJavaCaptain javacaptain.exe was started ok");
       
   212 #endif
       
   213 
       
   214         // Wait 3 seconds so that Java Captain has time to start
       
   215         User::After(3000000);
       
   216     }
       
   217     else
       
   218     {
       
   219 #ifdef RD_JAVA_S60_RELEASE_5_0_IAD
       
   220         ELOG1(EJavaRuntime,
       
   221               "InstallerStarter: startJavaCaptain start systemams.exe failed: %d", err);
       
   222 #else
       
   223         ELOG1(EJavaRuntime,
       
   224               "InstallerStarter: startJavaCaptain start javacaptain.exe failed: %d", err);
       
   225 #endif
       
   226     }
       
   227 
       
   228     proc.Close();
       
   229     return err;
       
   230 }
       
   231 #endif
       
   232 
       
   233 int startJvm(int argc, char *argv[])
       
   234 {
       
   235     // Create instance of RuntimeStarterUtils for thread supervisioning.
       
   236     std::auto_ptr<RuntimeStarterUtils> starterUtils(new RuntimeStarterUtils()); // codescanner::nonleavenew
       
   237     starterUtils->startThreadSupervisor();
       
   238 
       
   239     // Create Comms endpoint for JavaCaptain.
       
   240     std::auto_ptr<CommsClientEndpoint> comms(
       
   241         new CommsClientEndpoint(L"InstallerJavaCaptain"));
       
   242     int result = comms->connect(IPC_ADDRESS_JAVA_CAPTAIN_C);
       
   243 
       
   244 #ifdef __SYMBIAN32__
       
   245     if (KErrNotFound == result)
       
   246     {
       
   247         ELOG(EJavaRuntime,
       
   248              "InstallerStarter: Java Captain was not running. Trying to restart it.");
       
   249 
       
   250         // Java Captain is not running, try to start it
       
   251         result = startJavaCaptain();
       
   252         if (KErrNone == result)
       
   253         {
       
   254             result = comms->connect(IPC_ADDRESS_JAVA_CAPTAIN_C);
       
   255         }
       
   256     }
       
   257 #endif
       
   258 
       
   259     if (result != 0)
       
   260     {
       
   261         ELOG1(EJavaRuntime,
       
   262               "InstallerStarter: Connection to JavaCaptain failed: Reason = %d",
       
   263               result);
       
   264     }
       
   265 
       
   266     // Another Comms Endpoint for TCK Runner or preinstaller
       
   267     std::auto_ptr<CommsClientEndpoint> commsPoll;
       
   268 
       
   269     // If installer is started in 'poll' mode, connect also to TCK Runner,
       
   270     // preinstaller or javaappconverter. Command line is
       
   271     // 'javainstaller poll -address=(tck|preinstall|convert) [options]'
       
   272     const int minArgCount = 3;
       
   273     if (argc >= minArgCount)
       
   274     {
       
   275         if (!strcmp(argv[1], "poll")) // codescanner::accessArrayElementWithoutCheck2
       
   276         {
       
   277             int connected = 0;
       
   278             // next argument must be -address=(tck|preinstaller|convert)
       
   279             char* val = strpbrk(argv[2], "="); // codescanner::accessArrayElementWithoutCheck2
       
   280             if (val != 0)
       
   281             {
       
   282                 val++;
       
   283                 int commsAddress = 0;
       
   284                 if (!strcmp(val, "tck"))
       
   285                 {
       
   286                     commsAddress = IPC_ADDRESS_JAVA_TCK_RUNNER_C;
       
   287                 }
       
   288                 else if (!strcmp(val, "preinstall"))
       
   289                 {
       
   290                     commsAddress = IPC_ADDRESS_JAVA_PREINSTALLER_C;
       
   291                 }
       
   292                 else if (!strcmp(val, "convert"))
       
   293                 {
       
   294                     commsAddress = IPC_ADDRESS_JAVA_APPCONVERTER_C;
       
   295                 }
       
   296                 else if (!strcmp(val, "debugapi"))
       
   297                 {
       
   298                     commsAddress = IPC_ADDRESS_JAVA_DEBUGAPI_C;
       
   299                 }
       
   300                 else
       
   301                 {
       
   302                     ELOG1(EJavaRuntime, "InstallerStarter: unknown comms "
       
   303                           "poll address %s", val);
       
   304                 }
       
   305 
       
   306                 if (0 != commsAddress)
       
   307                 {
       
   308                     commsPoll.reset(new CommsClientEndpoint(L"InstallerCommsPoll")); // codescanner::nonleavenew
       
   309                     result = commsPoll->connect(commsAddress);
       
   310                     if (0 != result)
       
   311                     {
       
   312                         ELOG3(EJavaRuntime,
       
   313                               "InstallerStarter: Connection to %s (address %d) failed: Reason = %d",
       
   314                               val, commsAddress, result);
       
   315                     }
       
   316                     else
       
   317                     {
       
   318                         connected = 1;
       
   319                     }
       
   320                 }
       
   321             }
       
   322             else
       
   323             {
       
   324                 ELOG1(EJavaRuntime, "InstallerStarter: No valid -address argument. Arg is %s",
       
   325                       argv[2]); // codescanner::accessArrayElementWithoutCheck2
       
   326             }
       
   327 
       
   328             // Installer cannot be started in 'poll' mode unless connection is ok
       
   329             if (!connected)
       
   330             {
       
   331                 ELOG(EJavaRuntime,
       
   332                      "InstallerStarter: Installer cannot be started in poll mode because connection to initiator fails.");
       
   333                 std::string errorStr("Installer cannot start in poll mode");
       
   334                 throw RuntimeException(errorStr, __FILE__, __FUNCTION__, __LINE__);
       
   335             }
       
   336         }
       
   337     }
       
   338 
       
   339     // Create starter for starting the JVM
       
   340     std::auto_ptr<JvmStarter>
       
   341     jvm(JvmStarter::getJvmStarterInstance(JvmStarter::CDC,
       
   342                                           L"Installer"));
       
   343 
       
   344     // Set the debugging features available provided by the captain.
       
   345     starterUtils->enableDevelopmentFeatures(*jvm.get());
       
   346 
       
   347     // Set the old heap size to 512K
       
   348     const int oldHeapSize = 512;
       
   349     jvm->overrideOldHeapSize(oldHeapSize);
       
   350 
       
   351     jvm->enableThreadDumping();
       
   352 
       
   353     jvm->setMainClass(INSTALLER_MAIN_CLASS);
       
   354 
       
   355     jvm->appendSystemProperty(L"-Dcom.nokia.rt.port=installer");
       
   356 
       
   357     for (int i = 1; i < argc; ++i)
       
   358     {
       
   359         jvm->appendApplicationArgument(
       
   360             JavaCommonUtils::utf8ToWstring(argv[i])); // codescanner::accessArrayElementWithoutCheck2
       
   361     }
       
   362 
       
   363 #ifdef RD_JAVA_INSTALLERUI_ENABLED
       
   364     jvm->appendSystemProperty(
       
   365         L"-Dcom.nokia.mj.impl.installer.ui="
       
   366         L"com.nokia.mj.impl.installer.ui.eswt.InstallerUiEswt");
       
   367 #endif
       
   368 
       
   369     std::wstring extendedBootClassPath;
       
   370     // This call is platform dependent.
       
   371     starterUtils->getExtBootClassPath(extendedBootClassPath);
       
   372     if (extendedBootClassPath.length() > 0)
       
   373     {
       
   374         // Provide the bootclasspath also as a system propery
       
   375         // to be used for security extensions.
       
   376         std::wstring addOnList(L"-Dcom.nokia.mj.addon.list=");
       
   377         addOnList += extendedBootClassPath;
       
   378         jvm->appendSystemProperty(addOnList);
       
   379     }
       
   380 
       
   381     // Start the JVM.
       
   382     return jvm->startJvm();
       
   383 }
       
   384 
       
   385 #ifdef __SYMBIAN32__
       
   386 #include "javasymbianoslayer.h"
       
   387 
       
   388 EXPORT_C FuncPtr findDllMethod(const char* funcName)
       
   389 {
       
   390     FuncPtr ptr = 0;
       
   391     if (strcmp(funcName, "dllMain") == 0)
       
   392     {
       
   393         ptr = (FuncPtr)dllMain;
       
   394     }
       
   395     return ptr;
       
   396 }
       
   397 #endif //__SYMBIAN32__