src/jdk.jpackager/share/native/library/common/main.cpp
branchJDK-8200758-branch
changeset 57017 1b08af362a30
parent 56982 e094d5483bd6
child 57028 51cc1a1f91f3
equal deleted inserted replaced
57016:f63f13da91c0 57017:1b08af362a30
       
     1 /*
       
     2  * Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved.
       
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
       
     4  *
       
     5  * This code is free software; you can redistribute it and/or modify it
       
     6  * under the terms of the GNU General Public License version 2 only, as
       
     7  * published by the Free Software Foundation.  Oracle designates this
       
     8  * particular file as subject to the "Classpath" exception as provided
       
     9  * by Oracle in the LICENSE file that accompanied this code.
       
    10  *
       
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
       
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
       
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       
    14  * version 2 for more details (a copy is included in the LICENSE file that
       
    15  * accompanied this code).
       
    16  *
       
    17  * You should have received a copy of the GNU General Public License version
       
    18  * 2 along with this work; if not, write to the Free Software Foundation,
       
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
       
    20  *
       
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
       
    22  * or visit www.oracle.com if you need additional information or have any
       
    23  * questions.
       
    24  */
       
    25 
       
    26 #include "Platform.h"
       
    27 #include "PlatformString.h"
       
    28 #include "FilePath.h"
       
    29 #include "PropertyFile.h"
       
    30 #include "JavaVirtualMachine.h"
       
    31 #include "Package.h"
       
    32 #include "PlatformThread.h"
       
    33 #include "Macros.h"
       
    34 #include "Messages.h"
       
    35 
       
    36 
       
    37 #ifdef WINDOWS
       
    38 #include <Shellapi.h>
       
    39 #endif
       
    40 
       
    41 
       
    42 #include <stdio.h>
       
    43 #include <signal.h>
       
    44 #include <stdlib.h>
       
    45 
       
    46 /*
       
    47 This is the launcher program for application packaging on Windows, Mac,
       
    48     and Linux.
       
    49 
       
    50 Basic approach:
       
    51   - Launcher executable loads jpackager.dll/libjpackager.dylib/libjpackager.so
       
    52     and calls start_launcher below.
       
    53   - Reads app/package.cfg or Info.plist or app/<appname>.cfg for application
       
    54     launch configuration (package.cfg is property file).
       
    55   - Load JVM with requested JVM settings (bundled client JVM if availble,
       
    56     server or installed JVM otherwise).
       
    57   - Wait for JVM to exit and then exit from Main
       
    58   - To debug application by passing command line argument.
       
    59   - Application folder is added to the library path (so LoadLibrary()) works.
       
    60 
       
    61 Limitations and future work:
       
    62   - Running Java code in primordial thread may cause problems
       
    63     (example: can not use custom stack size).
       
    64     Solution used by java launcher is to create a new thread to invoke JVM.
       
    65     See CR 6316197 for more information.
       
    66 */
       
    67 
       
    68 extern "C" {
       
    69 
       
    70 #ifdef WINDOWS
       
    71     BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason,
       
    72             LPVOID lpvReserved) {
       
    73         return true;
       
    74     }
       
    75 #endif //WINDOWS
       
    76 
       
    77     JNIEXPORT bool start_launcher(int argc, TCHAR* argv[]) {
       
    78         bool result = false;
       
    79         bool parentProcess = true;
       
    80 
       
    81         // Platform must be initialize first.
       
    82         Platform& platform = Platform::GetInstance();
       
    83 
       
    84         try {
       
    85             for (int index = 0; index < argc; index++) {
       
    86                 TString argument = argv[index];
       
    87 
       
    88                 if (argument == _T("-Xappcds:generatecache")) {
       
    89                     platform.SetAppCDSState(cdsGenCache);
       
    90                 }
       
    91                 else if (argument == _T("-Xappcds:off")) {
       
    92                     platform.SetAppCDSState(cdsDisabled);
       
    93                 }
       
    94                 else if (argument == _T("-Xapp:child")) {
       
    95                     parentProcess = false;
       
    96                 }
       
    97 #ifdef DEBUG
       
    98                 // There is a compiler bug on Mac when overloading
       
    99                 // ShowResponseMessage.
       
   100                 else if (argument == _T("-nativedebug")) {
       
   101                     if (platform.ShowResponseMessage(_T("Test"),
       
   102                         TString(_T("Would you like to debug?\n\nProcessID: "))
       
   103                         + PlatformString(platform.GetProcessID()).toString())
       
   104                          == mrOK) {
       
   105                         while (platform.IsNativeDebuggerPresent() == false) {
       
   106                         }
       
   107                     }
       
   108                 }
       
   109 #endif //DEBUG
       
   110             }
       
   111 
       
   112             // Package must be initialized after Platform is fully initialized.
       
   113             Package& package = Package::GetInstance();
       
   114             Macros::Initialize();
       
   115             package.SetCommandLineArguments(argc, argv);
       
   116             platform.SetCurrentDirectory(package.GetPackageAppDirectory());
       
   117 
       
   118             if (package.CheckForSingleInstance()) {
       
   119                 // reactivate the first instance if the process Id is valid
       
   120                 platform.reactivateAnotherInstance();
       
   121                 if (package.GetArgs().size() > 0 &&
       
   122                         platform.GetSingleInstanceProcessId() != 0) {
       
   123                     // if user specified args, pass them to the first instance
       
   124                     return RunVM(SINGLE_INSTANCE_NOTIFICATION_LAUNCH);
       
   125                 }
       
   126                 return true;
       
   127             }
       
   128 
       
   129             switch (platform.GetAppCDSState()) {
       
   130                 case cdsDisabled:
       
   131                 case cdsUninitialized:
       
   132                 case cdsEnabled: {
       
   133                     break;
       
   134                 }
       
   135 
       
   136                 case cdsGenCache: {
       
   137                     TString cacheDirectory = package.GetAppCDSCacheDirectory();
       
   138 
       
   139                     if (FilePath::DirectoryExists(cacheDirectory) == false) {
       
   140                         FilePath::CreateDirectory(cacheDirectory, true);
       
   141                     } else {
       
   142                         TString cacheFileName =
       
   143                                 package.GetAppCDSCacheFileName();
       
   144                         if (FilePath::FileExists(cacheFileName) == true) {
       
   145                             FilePath::DeleteFile(cacheFileName);
       
   146                         }
       
   147                     }
       
   148 
       
   149                     break;
       
   150                 }
       
   151 
       
   152                 case cdsAuto: {
       
   153                     TString cacheFileName = package.GetAppCDSCacheFileName();
       
   154 
       
   155                     if (parentProcess == true &&
       
   156                             FilePath::FileExists(cacheFileName) == false) {
       
   157                         AutoFreePtr<Process> process = platform.CreateProcess();
       
   158                         std::vector<TString> args;
       
   159                         args.push_back(_T("-Xappcds:generatecache"));
       
   160                         args.push_back(_T("-Xapp:child"));
       
   161                         process->Execute(
       
   162                                 platform.GetModuleFileName(), args, true);
       
   163 
       
   164                         if (FilePath::FileExists(cacheFileName) == false) {
       
   165                             // Cache does not exist after trying to generate it,
       
   166                             // so run without cache.
       
   167                             platform.SetAppCDSState(cdsDisabled);
       
   168                             package.Clear();
       
   169                             package.Initialize();
       
   170                         }
       
   171                     }
       
   172 
       
   173                     break;
       
   174                 }
       
   175             }
       
   176 
       
   177             // Validation
       
   178             switch (platform.GetAppCDSState()) {
       
   179                 case cdsDisabled:
       
   180                 case cdsGenCache: {
       
   181                     // Do nothing.
       
   182                     break;
       
   183                 }
       
   184 
       
   185                 case cdsEnabled:
       
   186                 case cdsAuto: {
       
   187                     TString cacheFileName =
       
   188                             package.GetAppCDSCacheFileName();
       
   189 
       
   190                     if (FilePath::FileExists(cacheFileName) == false) {
       
   191                         Messages& messages = Messages::GetInstance();
       
   192                         TString message = PlatformString::Format(
       
   193                                 messages.GetMessage(
       
   194                                 APPCDS_CACHE_FILE_NOT_FOUND),
       
   195                                 cacheFileName.data());
       
   196                         throw FileNotFoundException(message);
       
   197                     }
       
   198                     break;
       
   199                 }
       
   200 
       
   201                 case cdsUninitialized: {
       
   202                     platform.ShowMessage(_T("Internal Error"));
       
   203                     break;
       
   204                 }
       
   205             }
       
   206 
       
   207             // Run App
       
   208             result = RunVM(USER_APP_LAUNCH);
       
   209         } catch (FileNotFoundException &e) {
       
   210             platform.ShowMessage(e.GetMessage());
       
   211         }
       
   212 
       
   213         return result;
       
   214     }
       
   215 
       
   216     JNIEXPORT void stop_launcher() {
       
   217     }
       
   218 }