1 /* 2 * Copyright (c) 2014, 2015, Oracle and/or its affiliates. 3 * All rights reserved. Use is subject to license terms. 4 * 5 * This file is available and licensed under the following license: 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * - Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * - Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the distribution. 16 * - Neither the name of Oracle Corporation nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 31 */ 32 33 34 #include "Platform.h" 35 #include "PlatformString.h" 36 #include "FilePath.h" 37 #include "PropertyFile.h" 38 #include "JavaVirtualMachine.h" 39 #include "Package.h" 40 #include "PlatformThread.h" 41 #include "Macros.h" 42 #include "Messages.h" 43 44 45 #ifdef WINDOWS 46 #include <Shellapi.h> 47 #endif 48 49 50 #include <stdio.h> 51 #include <signal.h> 52 #include <stdlib.h> 53 54 /* 55 This is the launcher program for application packaging on Windows, Mac and Linux. 56 57 Basic approach: 58 - Launcher executable loads packager.dll/libpackager.dylib/libpackager.so and calls start_launcher below. 59 - Reads app/package.cfg or Info.plist or app/<appname>.cfg for application launch configuration 60 (package.cfg is property file). 61 - Load JVM with requested JVM settings (bundled client JVM if availble, server or installed JVM otherwise). 62 - Wait for JVM to exit and then exit from Main 63 - To debug application by passing command line argument. 64 - Application folder is added to the library path (so LoadLibrary()) works. 65 66 Limitations and future work: 67 - Running Java code in primordial thread may cause problems 68 (example: can not use custom stack size). 69 Solution used by java launcher is to create a new thread to invoke JVM. 70 See CR 6316197 for more information. 71 */ 72 73 extern "C" { 74 75 #ifdef WINDOWS 76 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { 77 return true; 78 } 79 80 __declspec(dllexport) 81 #endif //WINDOWS 82 83 bool start_launcher(int argc, TCHAR* argv[]) { 84 bool result = false; 85 bool parentProcess = true; 86 87 // Platform must be initialize first. 88 Platform& platform = Platform::GetInstance(); 89 90 try { 91 for (int index = 0; index < argc; index++) { 92 TString argument = argv[index]; 93 94 if (argument == _T("-Xappcds:generatecache")) { 95 platform.SetAppCDSState(cdsGenCache); 96 } 97 else if (argument == _T("-Xappcds:off")) { 98 platform.SetAppCDSState(cdsDisabled); 99 } 100 else if (argument == _T("-Xapp:child")) { 101 parentProcess = false; 102 } 103 #ifdef DEBUG 104 // There is a compiler bug on Mac when overloading ShowResponseMessage. 105 else if (argument == _T("-nativedebug")) { 106 if (platform.ShowResponseMessage(_T("Test"), 107 TString(_T("Would you like to debug?\n\nProcessID: ")) + 108 PlatformString(platform.GetProcessID()).toString()) == mrOK) { 109 while (platform.IsNativeDebuggerPresent() == false) { 110 } 111 } 112 } 113 #endif //DEBUG 114 } 115 116 // Package must be initialized after Platform is fully initialized. 117 Package& package = Package::GetInstance(); 118 Macros::Initialize(); 119 package.SetCommandLineArguments(argc, argv); 120 platform.SetCurrentDirectory(package.GetPackageAppDirectory()); 121 122 switch (platform.GetAppCDSState()) { 123 case cdsDisabled: 124 case cdsUninitialized: 125 case cdsEnabled: { 126 break; 127 } 128 129 case cdsGenCache: { 130 TString cacheDirectory = package.GetAppCDSCacheDirectory(); 131 132 if (FilePath::DirectoryExists(cacheDirectory) == false) { 133 FilePath::CreateDirectory(cacheDirectory, true); 134 } 135 else { 136 TString cacheFileName = package.GetAppCDSCacheFileName(); 137 138 if (FilePath::FileExists(cacheFileName) == true) { 139 FilePath::DeleteFile(cacheFileName); 140 } 141 } 142 143 break; 144 } 145 146 case cdsAuto: { 147 TString cacheFileName = package.GetAppCDSCacheFileName(); 148 149 if (parentProcess == true && FilePath::FileExists(cacheFileName) == false) { 150 AutoFreePtr<Process> process = platform.CreateProcess(); 151 std::vector<TString> args; 152 args.push_back(_T("-Xappcds:generatecache")); 153 args.push_back(_T("-Xapp:child")); 154 process->Execute(platform.GetModuleFileName(), args, true); 155 156 if (FilePath::FileExists(cacheFileName) == false) { 157 // Cache does not exist after trying to generate it, 158 // so run without cache. 159 platform.SetAppCDSState(cdsDisabled); 160 package.Clear(); 161 package.Initialize(); 162 } 163 } 164 165 break; 166 } 167 } 168 169 // Validation 170 { 171 switch (platform.GetAppCDSState()) { 172 case cdsDisabled: 173 case cdsGenCache: { 174 // Do nothing. 175 break; 176 } 177 178 case cdsEnabled: 179 case cdsAuto: { 180 TString cacheFileName = package.GetAppCDSCacheFileName(); 181 182 if (FilePath::FileExists(cacheFileName) == false) { 183 Messages& messages = Messages::GetInstance(); 184 TString message = PlatformString::Format(messages.GetMessage(APPCDS_CACHE_FILE_NOT_FOUND), cacheFileName.data()); 185 throw FileNotFoundException(message); 186 } 187 break; 188 } 189 190 case cdsUninitialized: { 191 throw Exception(_T("Internal Error")); 192 } 193 } 194 } 195 196 // Run App 197 result = RunVM(); 198 } 199 catch (FileNotFoundException &e) { 200 platform.ShowMessage(e.GetMessage()); 201 } 202 203 return result; 204 } 205 206 #ifdef WINDOWS 207 __declspec(dllexport) 208 #endif //WINDOWS 209 210 void stop_launcher() { 211 } 212 }