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 platform.SetCurrentDirectory(package.GetPackageAppDirectory()); 91 92 switch (platform.GetAppCDSState()) { 93 case cdsDisabled: 94 case cdsUninitialized: 95 case cdsEnabled: { 96 break; 97 } 98 99 case cdsGenCache: { 100 TString cacheDirectory = package.GetAppCDSCacheDirectory(); 101 102 if (FilePath::DirectoryExists(cacheDirectory) == false) { 103 FilePath::CreateDirectory(cacheDirectory, true); 104 } else { 105 TString cacheFileName = 106 package.GetAppCDSCacheFileName(); 107 if (FilePath::FileExists(cacheFileName) == true) { 108 FilePath::DeleteFile(cacheFileName); 109 } 110 } 111 112 break; 113 } 114 115 case cdsAuto: { 116 TString cacheFileName = package.GetAppCDSCacheFileName(); 117 118 if (parentProcess == true && 119 FilePath::FileExists(cacheFileName) == false) { 120 AutoFreePtr<Process> process = platform.CreateProcess(); 121 std::vector<TString> args; 122 args.push_back(_T("-Xappcds:generatecache")); 123 args.push_back(_T("-Xapp:child")); 124 process->Execute( 125 platform.GetModuleFileName(), args, true); 126 127 if (FilePath::FileExists(cacheFileName) == false) { 128 // Cache does not exist after trying to generate it, 129 // so run without cache. 130 platform.SetAppCDSState(cdsDisabled); 131 package.Clear(); 132 package.Initialize(); 133 } 134 } 135 136 break; 137 } 138 } 139 140 // Validation 141 switch (platform.GetAppCDSState()) { 142 case cdsDisabled: 143 case cdsGenCache: { 144 // Do nothing. 145 break; 146 } 147 148 case cdsEnabled: 149 case cdsAuto: { 150 TString cacheFileName = 151 package.GetAppCDSCacheFileName(); 152 153 if (FilePath::FileExists(cacheFileName) == false) { 154 Messages& messages = Messages::GetInstance(); 155 TString message = PlatformString::Format( 156 messages.GetMessage( 157 APPCDS_CACHE_FILE_NOT_FOUND), 158 cacheFileName.data()); 159 throw Exception(message); 160 } 161 break; 162 } 163 164 case cdsUninitialized: { 165 platform.ShowMessage(_T("Internal Error")); 166 break; 167 } 168 } 169 170 // Run App 171 result = RunVM(); 172 } catch (Exception &e) { 173 platform.ShowMessage(e.GetMessage()); 174 } 175 176 return result; 177 } 178 179 JNIEXPORT void stop_launcher() { 180 } 181 }