1 /* 2 * Copyright (c) 2014, 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 set env variable (TODO) or pass "/Debug" option on command line. 64 - TODO: default directory is set to user's Documents and Settings. 65 - Application folder is added to the library path (so LoadLibrary()) works. 66 67 Limitations and future work: 68 - Running Java code in primordial thread may cause problems 69 (example: can not use custom stack size). 70 Solution used by java launcher is to create a new thread to invoke JVM. 71 See CR 6316197 for more information. 72 */ 73 74 extern "C" { 75 76 #ifdef WINDOWS 77 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { 78 return true; 79 } 80 81 __declspec(dllexport) 82 #endif //WINDOWS 83 84 bool start_launcher(int argc, TCHAR* argv[]) { 85 bool result = false; 86 bool parentProcess = true; 87 88 // Platform must be initialize first. 89 Platform& platform = Platform::GetInstance(); 90 91 try { 92 platform.SetAppCDSState(cdsOn); 93 94 for (int index = 0; index < argc; index++) { 95 TString argument = argv[index]; 96 97 if (argument == _T("-Xappcds:generatecache")) { 98 platform.SetAppCDSState(cdsGenCache); 99 } 100 else if (argument == _T("-Xappcds:off")) { 101 platform.SetAppCDSState(cdsNone); 102 } 103 else if (argument == _T("-Xapp:child")) { 104 parentProcess = false; 105 } 106 #ifdef DEBUG 107 //TODO There appears to be a compiler bug on Mac overloading ShowResponseMessage. Investigate. 108 else if (argument == _T("-nativedebug")) { 109 if (platform.ShowResponseMessage(_T("Test"), 110 TString(_T("Would you like to debug?\n\nProcessID: ")) + 111 PlatformString(platform.GetProcessID()).toString()) == mrOK) { 112 while (platform.IsNativeDebuggerPresent() == false) { 113 } 114 } 115 } 116 #endif //DEBUG 117 } 118 119 // Package must be initialized after Platform is fully initialized. 120 Package& package = Package::GetInstance(); 121 Macros::Initialize(); 122 package.SetCommandLineArguments(argc, argv); 123 platform.SetCurrentDirectory(package.GetPackageAppDirectory()); 124 125 switch (platform.GetAppCDSState()) { 126 case cdsGenCache: { 127 TString cacheDirectory = package.GetAppCDSCacheDirectory(); 128 129 if (FilePath::DirectoryExists(cacheDirectory) == false) { 130 FilePath::CreateDirectory(cacheDirectory, true); 131 } 132 else { 133 TString cacheFileName = package.GetAppCDSCacheFileName(); 134 135 if (FilePath::FileExists(cacheFileName) == true) { 136 FilePath::DeleteFile(cacheFileName); 137 } 138 } 139 140 141 break; 142 } 143 144 case cdsAuto: { 145 TString cacheFileName = package.GetAppCDSCacheFileName(); 146 147 if (parentProcess == true && FilePath::FileExists(cacheFileName) == false) { 148 AutoFreePtr<Process> process = platform.CreateProcess(); 149 std::vector<TString> args; 150 args.push_back(_T("-Xappcds:generatecache")); 151 args.push_back(_T("-Xapp:child")); 152 process->Execute(platform.GetModuleFileName(), args, true); 153 154 if (FilePath::FileExists(cacheFileName) == false) { 155 // Cache does not exist after trying to generate it, 156 // so run without cache. 157 platform.SetAppCDSState(cdsNone); 158 package.Clear(); 159 package.Initialize(); 160 } 161 } 162 163 break; 164 } 165 166 case cdsNone: 167 case cdsOn: { 168 break; 169 } 170 } 171 172 // Validation 173 AutoFreePtr<ISectionalPropertyContainer> config = platform.GetConfigFile(platform.GetConfigFileName()); 174 if (config->ContainsSection("AppCDSJVMOptions")) { 175 switch (platform.GetAppCDSState()) { 176 case cdsOn: 177 case cdsAuto: { 178 TString cacheFileName = package.GetAppCDSCacheFileName(); 179 180 if (FilePath::FileExists(cacheFileName) == false) { 181 Messages& messages = Messages::GetInstance(); 182 TString message = PlatformString::Format(messages.GetMessage(APPCDS_CACHE_FILE_NOT_FOUND), cacheFileName.data()); 183 throw FileNotFoundException(message); 184 } 185 break; 186 } 187 } 188 } 189 190 TString logFileName = FilePath::IncludeTrailingSeparater(platform.GetAppDataDirectory().data()) + _T("log.txt"); 191 192 // Run App 193 result = RunVM(); 194 } 195 catch (FileNotFoundException &e) { 196 platform.ShowMessage(e.GetMessage()); 197 } 198 199 return result; 200 } 201 202 void stop_launcher() { 203 } 204 }