1 /* 2 * Copyright (c) 2014, 2019, 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 "Macros.h" 33 #include "Messages.h" 34 35 #include <stdio.h> 36 #include <signal.h> 37 #include <stdlib.h> 38 39 /* 40 This is the app launcher program for application packaging on Windows, Mac, 41 and Linux. 42 43 Basic approach: 44 - Launcher (jpackageapplauncher) is executable that loads 45 applauncher.dll/libapplauncher.dylib/libapplauncher.so 46 and calls start_launcher below. 47 - Reads app/package.cfg or Info.plist or app/<appname>.cfg for application 48 launch configuration (package.cfg is property file). 49 - Load Java with requested Java settings (bundled client Java if availble, 50 server or installed Java otherwise). 51 - Wait for Java to exit and then exit from Main 52 - To debug application by passing command line argument. 53 - Application folder is added to the library path (so LoadLibrary()) works. 54 55 Limitations and future work: 56 - Running Java code in primordial thread may cause problems 57 (example: can not use custom stack size). 58 Solution used by java launcher is to create a new thread to invoke Java. 59 See CR 6316197 for more information. 60 */ 61 62 extern "C" { 63 64 JNIEXPORT bool start_launcher(int argc, TCHAR* argv[]) { 65 bool result = false; 66 bool parentProcess = true; 67 68 // Platform must be initialize first. 69 Platform& platform = Platform::GetInstance(); 70 71 try { 72 for (int index = 0; index < argc; index++) { 73 TString argument = argv[index]; 74 75 if (argument == _T("-Xappcds:generatecache")) { 76 platform.SetAppCDSState(cdsGenCache); 77 } 78 else if (argument == _T("-Xappcds:off")) { 79 platform.SetAppCDSState(cdsDisabled); 80 } 81 else if (argument == _T("-Xapp:child")) { 82 parentProcess = false; 83 } 84 } 85 86 // Package must be initialized after Platform is fully initialized. 87 Package& package = Package::GetInstance(); 88 Macros::Initialize(); 89 package.SetCommandLineArguments(argc, argv); 90 91 switch (platform.GetAppCDSState()) { 92 case cdsDisabled: 93 case cdsUninitialized: 94 case cdsEnabled: { 95 break; 96 } 97 98 case cdsGenCache: { 99 TString cacheDirectory = package.GetAppCDSCacheDirectory(); 100 101 if (FilePath::DirectoryExists(cacheDirectory) == false) { 102 FilePath::CreateDirectory(cacheDirectory, true); 103 } else { 104 TString cacheFileName = 105 package.GetAppCDSCacheFileName(); 106 if (FilePath::FileExists(cacheFileName) == true) { 107 FilePath::DeleteFile(cacheFileName); 108 } 109 } 110 111 break; 112 } 113 114 case cdsAuto: { 115 TString cacheFileName = package.GetAppCDSCacheFileName(); 116 117 if (parentProcess == true && 118 FilePath::FileExists(cacheFileName) == false) { 119 AutoFreePtr<Process> process = platform.CreateProcess(); 120 std::vector<TString> args; 121 args.push_back(_T("-Xappcds:generatecache")); 122 args.push_back(_T("-Xapp:child")); 123 process->Execute( 124 platform.GetModuleFileName(), args, true); 125 126 if (FilePath::FileExists(cacheFileName) == false) { 127 // Cache does not exist after trying to generate it, 128 // so run without cache. 129 platform.SetAppCDSState(cdsDisabled); 130 package.Clear(); 131 package.Initialize(); 132 } 133 } 134 135 break; 136 } 137 } 138 139 // Validation 140 switch (platform.GetAppCDSState()) { 141 case cdsDisabled: 142 case cdsGenCache: { 143 // Do nothing. 144 break; 145 } 146 147 case cdsEnabled: 148 case cdsAuto: { 149 TString cacheFileName = 150 package.GetAppCDSCacheFileName(); 151 152 if (FilePath::FileExists(cacheFileName) == false) { 153 Messages& messages = Messages::GetInstance(); 154 TString message = PlatformString::Format( 155 messages.GetMessage( 156 APPCDS_CACHE_FILE_NOT_FOUND), 157 cacheFileName.data()); 158 throw Exception(message); 159 } 160 break; 161 } 162 163 case cdsUninitialized: { 164 platform.ShowMessage(_T("Internal Error")); 165 break; 166 } 167 } 168 169 // Run App 170 result = RunVM(); 171 } catch (Exception &e) { 172 platform.ShowMessage(e.GetMessage()); 173 } 174 175 return result; 176 } 177 178 JNIEXPORT void stop_launcher() { 179 } 180 }